X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=gl_rmain.c;h=d1ee2700ec908d69961dc85d4749e9c4be1f8b24;hb=4eb6393c19467e2a1e45913397aaf11380d1cd83;hp=ad083b2dfa24c3b1e83274d098a809826d6e1947;hpb=bb84273fe855ec05959ae0c64b77b6d31d230e7f;p=xonotic%2Fdarkplaces.git diff --git a/gl_rmain.c b/gl_rmain.c index ad083b2d..d1ee2700 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -33,7 +33,8 @@ rtexturepool_t *r_main_texturepool; // r_refdef_t r_refdef; -cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "1", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"}; +cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"}; +cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"}; cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" }; cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"}; cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"}; @@ -63,6 +64,7 @@ cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"}; cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "2", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"}; cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"}; +cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"}; cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"}; cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"}; @@ -76,11 +78,16 @@ cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the re cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"}; cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"}; +cvar_t r_glsl_contrastboost = {CVAR_SAVE, "r_glsl_contrastboost", "1", "by how much to multiply the contrast in dark areas (1 is no change)"}; +cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"}; cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"}; cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"}; cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"}; -cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"}; -cvar_t r_glsl_contrastboost = {CVAR_SAVE, "r_glsl_contrastboost", "1", "by how much to multiply the contrast in dark areas (1 is no change)"}; +cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"}; +cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"}; +cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"}; +cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"}; +cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"}; cvar_t r_glsl_usegeneric = {CVAR_SAVE, "r_glsl_usegeneric", "1", "use shaders for rendering simple geometry (rather than conventional fixed-function rendering for this purpose)"}; cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"}; @@ -120,14 +127,9 @@ cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rot cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"}; cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"}; -extern qboolean v_flipped_state; +extern cvar_t v_glslgamma; -typedef struct r_glsl_bloomshader_s -{ - int program; - int loc_Texture_Bloom; -} -r_glsl_bloomshader_t; +extern qboolean v_flipped_state; static struct r_bloomstate_s { @@ -142,8 +144,6 @@ static struct r_bloomstate_s int bloomtexturewidth, bloomtextureheight; rtexture_t *texture_bloom; - r_glsl_bloomshader_t *shader; - // arrays for rendering the screen passes float screentexcoord2f[8]; float bloomtexcoord2f[8]; @@ -151,36 +151,7 @@ static struct r_bloomstate_s } r_bloomstate; -typedef struct r_waterstate_waterplane_s -{ - rtexture_t *texture_refraction; - rtexture_t *texture_reflection; - mplane_t plane; - int materialflags; // combined flags of all water surfaces on this plane - unsigned char pvsbits[(32768+7)>>3]; // FIXME: buffer overflow on huge maps - qboolean pvsvalid; -} -r_waterstate_waterplane_t; - -#define MAX_WATERPLANES 16 - -static struct r_waterstate_s -{ - qboolean enabled; - - qboolean renderingscene; // true while rendering a refraction or reflection texture, disables water surfaces - - int waterwidth, waterheight; - int texturewidth, textureheight; - - int maxwaterplanes; // same as MAX_WATERPLANES - int numwaterplanes; - r_waterstate_waterplane_t waterplanes[MAX_WATERPLANES]; - - float screenscale[2]; - float screencenter[2]; -} -r_waterstate; +r_waterstate_t r_waterstate; // shadow volume bsp struct with automatically growing nodes buffer svbsp_t r_svbsp; @@ -193,6 +164,8 @@ rtexture_t *r_texture_notexture; rtexture_t *r_texture_whitecube; rtexture_t *r_texture_normalizationcube; rtexture_t *r_texture_fogattenuation; +rtexture_t *r_texture_gammaramps; +unsigned int r_texture_gammaramps_serial; //rtexture_t *r_texture_fogintensity; char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH]; @@ -269,7 +242,7 @@ float FogPoint_World(const vec3_t p) float FogPoint_Model(const vec3_t p) { - return FogForDistance(VectorDistance((p), rsurface.modelorg)); + return FogForDistance(VectorDistance((p), rsurface.modelorg) * Matrix4x4_ScaleFromMatrix(&rsurface.matrix)); } static void R_BuildBlankTextures(void) @@ -476,8 +449,66 @@ static const char *builtinshaderstring = "# endif\n" "\n" "#else\n" -"#ifdef MODE_GENERIC\n" "\n" +"#ifdef MODE_POSTPROCESS\n" +"# ifdef VERTEX_SHADER\n" +"void main(void)\n" +"{\n" +" gl_FrontColor = gl_Color;\n" +" gl_Position = ftransform();\n" +" gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n" +"#ifdef USEGLOW\n" +" gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n" +"#endif\n" +"}\n" +"# endif\n" +"# ifdef FRAGMENT_SHADER\n" +"\n" +"uniform sampler2D Texture_First;\n" +"#ifdef USEGLOW\n" +"uniform sampler2D Texture_Second;\n" +"#endif\n" +"#ifdef USEGAMMARAMPS\n" +"uniform sampler2D Texture_GammaRamps;\n" +"#endif\n" +"#ifdef USEVERTEXTEXTUREBLEND\n" +"uniform vec4 TintColor;\n" +"#endif\n" +"#ifdef USECOLORMOD\n" +"uniform vec3 Gamma;\n" +"#endif\n" +"//uncomment these if you want to use them:\n" +"// uniform vec4 UserVec1;\n" +"// uniform vec4 UserVec2;\n" +"// uniform vec4 UserVec3;\n" +"// uniform vec4 UserVec4;\n" +"// uniform float ClientTime;\n" +"// uniform vec2 PixelSize;\n" +"void main(void)\n" +"{\n" +" gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n" +"#ifdef USEGLOW\n" +" gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n" +"#endif\n" +"#ifdef USEVERTEXTEXTUREBLEND\n" +" gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n" +"#endif\n" +"\n" +"#ifdef USEPOSTPROCESSING\n" +"// add your own postprocessing here or make your own ifdef for it\n" +"#endif\n" +"\n" +"#ifdef USEGAMMARAMPS\n" +" gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n" +" gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n" +" gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n" +"#endif\n" +"}\n" +"# endif\n" +"\n" +"\n" +"#else\n" +"#ifdef MODE_GENERIC\n" "# ifdef VERTEX_SHADER\n" "void main(void)\n" "{\n" @@ -517,7 +548,7 @@ static const char *builtinshaderstring = " gl_FragColor += tex2;\n" "# endif\n" "# ifdef USEVERTEXTEXTUREBLEND\n" -" gl_FragColor = mix(tex2, gl_FragColor, tex2.a);\n" +" gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n" "# endif\n" "}\n" "# endif\n" @@ -527,38 +558,35 @@ static const char *builtinshaderstring = "varying vec2 TexCoord;\n" "varying vec2 TexCoordLightmap;\n" "\n" -"//#ifdef MODE_LIGHTSOURCE\n" +"#ifdef MODE_LIGHTSOURCE\n" "varying vec3 CubeVector;\n" -"//#endif\n" +"#endif\n" "\n" -"//#ifdef MODE_LIGHTSOURCE\n" +"#ifdef MODE_LIGHTSOURCE\n" "varying vec3 LightVector;\n" -"//#else\n" -"//# ifdef MODE_LIGHTDIRECTION\n" -"//varying vec3 LightVector;\n" -"//# endif\n" -"//#endif\n" +"#endif\n" +"#ifdef MODE_LIGHTDIRECTION\n" +"varying vec3 LightVector;\n" +"#endif\n" "\n" "varying vec3 EyeVector;\n" -"//#ifdef USEFOG\n" +"#ifdef USEFOG\n" "varying vec3 EyeVectorModelSpace;\n" -"//#endif\n" +"#endif\n" "\n" "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n" "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n" "varying vec3 VectorR; // direction of R texcoord (surface normal)\n" "\n" -"//#ifdef MODE_WATER\n" +"#ifdef MODE_WATER\n" "varying vec4 ModelViewProjectionPosition;\n" -"//#else\n" -"//# ifdef MODE_REFRACTION\n" -"//varying vec4 ModelViewProjectionPosition;\n" -"//# else\n" -"//# ifdef USEREFLECTION\n" -"//varying vec4 ModelViewProjectionPosition;\n" -"//# endif\n" -"//# endif\n" -"//#endif\n" +"#endif\n" +"#ifdef MODE_REFRACTION\n" +"varying vec4 ModelViewProjectionPosition;\n" +"#endif\n" +"#ifdef USEREFLECTION\n" +"varying vec4 ModelViewProjectionPosition;\n" +"#endif\n" "\n" "\n" "\n" @@ -819,7 +847,8 @@ static const char *builtinshaderstring = " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n" " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n" " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n" -" color = mix(myhalf4(texture2D(Texture_SecondaryColor, TexCoord)), color, terrainblend);\n" +" color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord)), color.rgb, terrainblend);\n" +" color.a = 1.0;\n" " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n" "#endif\n" "\n" @@ -831,7 +860,7 @@ static const char *builtinshaderstring = " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n" "# endif\n" "# else\n" -" myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5));\n" +" myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n" "# ifdef USESPECULAR\n" " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n" "# endif\n" @@ -852,10 +881,16 @@ static const char *builtinshaderstring = " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n" "# endif\n" "# ifdef USESPECULAR\n" +"# ifndef USEEXACTSPECULARMATH\n" " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n" "\n" +"# endif\n" " // calculate directional shading\n" +"# ifdef USEEXACTSPECULARMATH\n" +" color.rgb = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower)) * glosscolor);\n" +"# else\n" " color.rgb = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower)) * glosscolor);\n" +"# endif\n" "# else\n" "# ifdef USEDIFFUSE\n" " // calculate directional shading\n" @@ -880,13 +915,17 @@ static const char *builtinshaderstring = " // directional model lighting\n" "# ifdef USEDIFFUSE\n" " // get the light normal\n" -" myhalf3 diffusenormal = myhalf3(LightVector);\n" +" myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n" "# endif\n" "# ifdef USESPECULAR\n" " // calculate directional shading\n" " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n" +"# ifdef USEEXACTSPECULARMATH\n" +" color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n" +"# else\n" " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n" " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n" +"# endif\n" "# else\n" "# ifdef USEDIFFUSE\n" "\n" @@ -905,13 +944,20 @@ static const char *builtinshaderstring = " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n" "\n" " // get the light normal\n" -" myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhalf3(0.5);\n" -" myhalf3 diffusenormal = normalize(myhalf3(dot(diffusenormal_modelspace, myhalf3(VectorS)), dot(diffusenormal_modelspace, myhalf3(VectorT)), dot(diffusenormal_modelspace, myhalf3(VectorR))));\n" -" // calculate directional shading\n" -" myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n" +" myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n" +" myhalf3 diffusenormal;\n" +" diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n" +" diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n" +" diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n" +" // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n" +" myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n" "# ifdef USESPECULAR\n" +"# ifdef USEEXACTSPECULARMATH\n" +" tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n" +"# else\n" " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n" " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n" +"# endif\n" "# endif\n" "\n" " // apply lightmap color\n" @@ -925,12 +971,16 @@ static const char *builtinshaderstring = " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n" "\n" " // get the light normal\n" -" myhalf3 diffusenormal = normalize(myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhalf3(0.5));\n" -" // calculate directional shading\n" -" myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n" +" myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n" +" // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n" +" myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n" "# ifdef USESPECULAR\n" +"# ifdef USEEXACTSPECULARMATH\n" +" tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n" +"# else\n" " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n" " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n" +"# endif\n" "# endif\n" "\n" " // apply lightmap color\n" @@ -998,6 +1048,7 @@ static const char *builtinshaderstring = "#endif // FRAGMENT_SHADER\n" "\n" "#endif // !MODE_GENERIC\n" +"#endif // !MODE_POSTPROCESS\n" "#endif // !MODE_DEPTH_OR_SHADOW\n" ; @@ -1028,11 +1079,14 @@ typedef enum shaderpermutation_e SHADERPERMUTATION_CUBEFILTER = 1<<5, // (lightsource) use cubemap light filter SHADERPERMUTATION_GLOW = 1<<6, // (lightmap) blend in an additive glow texture SHADERPERMUTATION_SPECULAR = 1<<7, // (lightsource or deluxemapping) render specular effects - SHADERPERMUTATION_REFLECTION = 1<<8, // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface - SHADERPERMUTATION_OFFSETMAPPING = 1<<9, // adjust texcoords to roughly simulate a displacement mapped surface - SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!) - SHADERPERMUTATION_LIMIT = 1<<11, // size of permutations array - SHADERPERMUTATION_COUNT = 11 // size of shaderpermutationinfo array + SHADERPERMUTATION_EXACTSPECULARMATH = 1<<8, // (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation + SHADERPERMUTATION_REFLECTION = 1<<9, // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface + SHADERPERMUTATION_OFFSETMAPPING = 1<<10, // adjust texcoords to roughly simulate a displacement mapped surface + SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<11, // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!) + SHADERPERMUTATION_GAMMARAMPS = 1<<12, // gamma (postprocessing only) + SHADERPERMUTATION_POSTPROCESSING = 1<<13, // user defined postprocessing + SHADERPERMUTATION_LIMIT = 1<<14, // size of permutations array + SHADERPERMUTATION_COUNT = 14 // size of shaderpermutationinfo array } shaderpermutation_t; @@ -1047,15 +1101,19 @@ shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] = {"#define USECUBEFILTER\n", " cubefilter"}, {"#define USEGLOW\n", " glow"}, {"#define USESPECULAR\n", " specular"}, + {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"}, {"#define USEREFLECTION\n", " reflection"}, {"#define USEOFFSETMAPPING\n", " offsetmapping"}, {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"}, + {"#define USEGAMMARAMPS\n", " gammaramps"}, + {"#define USEPOSTPROCESSING\n", " postprocessing"}, }; // this enum is multiplied by SHADERPERMUTATION_MODEBASE typedef enum shadermode_e { SHADERMODE_GENERIC, // (particles/HUD/etc) vertex color, optionally multiplied by one texture + SHADERMODE_POSTPROCESS, // postprocessing shader (r_glsl_postprocess) SHADERMODE_DEPTH_OR_SHADOW, // (depthfirst/shadows) vertex shader only SHADERMODE_FLATCOLOR, // (lightmap) modulate texture by uniform color (q1bsp, q3bsp) SHADERMODE_VERTEXCOLOR, // (lightmap) modulate texture by vertex colors (q3bsp) @@ -1074,6 +1132,7 @@ shadermode_t; shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] = { {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"}, + {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"}, {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"}, {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"}, {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"}, @@ -1095,6 +1154,7 @@ typedef struct r_glsl_permutation_s // locations of detected uniforms in program object, or -1 if not found int loc_Texture_First; int loc_Texture_Second; + int loc_Texture_GammaRamps; int loc_Texture_Normal; int loc_Texture_Color; int loc_Texture_Gloss; @@ -1131,6 +1191,7 @@ typedef struct r_glsl_permutation_s int loc_SpecularColor; int loc_LightDir; int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost + int loc_GammaCoeff; // 1 / gamma int loc_DistortScaleRefractReflect; int loc_ScreenScaleRefractReflect; int loc_ScreenCenterRefractReflect; @@ -1138,6 +1199,12 @@ typedef struct r_glsl_permutation_s int loc_ReflectColor; int loc_ReflectFactor; int loc_ReflectOffset; + int loc_UserVec1; + int loc_UserVec2; + int loc_UserVec3; + int loc_UserVec4; + int loc_ClientTime; + int loc_PixelSize; } r_glsl_permutation_t; @@ -1247,6 +1314,7 @@ static void R_GLSL_CompilePermutation(shadermode_t mode, shaderpermutation_t per // have to look them up every time we set them p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First"); p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second"); + p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps"); p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal"); p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color"); p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss"); @@ -1290,9 +1358,17 @@ static void R_GLSL_CompilePermutation(shadermode_t mode, shaderpermutation_t per p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor"); p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor"); p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset"); + p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff"); + p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1"); + p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2"); + p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3"); + p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4"); + p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime"); + p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize"); // initialize the samplers to refer to the texture units we use if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST); if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND); + if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS); if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL); if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR); if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS); @@ -1341,7 +1417,7 @@ void R_GLSL_DumpShader_f(void) { int i; - qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false); + qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false); if(!file) { Con_Printf("failed to write to glsl/default.glsl\n"); @@ -1421,7 +1497,7 @@ void R_SetupGenericTwoTextureShader(int texturemode) if (gl_support_fragment_shader) { if (r_glsl.integer && r_glsl_usegeneric.integer) - R_SetupShader_SetPermutation(SHADERMODE_GENERIC, SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)))); + R_SetupShader_SetPermutation(SHADERMODE_GENERIC, SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)))); else if (r_glsl_permutation) { r_glsl_permutation = NULL; @@ -1600,6 +1676,9 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) permutation |= SHADERPERMUTATION_REFLECTION; } + if(permutation & SHADERPERMUTATION_SPECULAR) + if(r_shadow_glossexact.integer) + permutation |= SHADERPERMUTATION_EXACTSPECULARMATH; R_SetupShader_SetPermutation(mode, permutation); if (mode == SHADERMODE_LIGHTSOURCE) { @@ -1634,7 +1713,7 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f } else { - if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 1.0f / 128.0f); + if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f); if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity); if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale); } @@ -1684,8 +1763,15 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f else qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0); } - if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip); - if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower); + if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix)); + if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH) + { + if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25); + } + else + { + if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower); + } if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value); CHECKGLERROR } @@ -1810,7 +1896,7 @@ skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewid return item; } -skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain) +skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha) { // FIXME: it should be possible to disable loading various layers using // cvars, to prevent wasted loading time and memory usage if the user does @@ -1827,6 +1913,8 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole int basepixels_height; skinframe_t *skinframe; + *has_alpha = false; + if (cls.state == ca_dedicated) return NULL; @@ -1841,6 +1929,9 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole if (basepixels == NULL) return NULL; + if (developer_loading.integer) + Con_Printf("loading skin \"%s\"\n", name); + // we've got some pixels to store, so really allocate this new texture now if (!skinframe) skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true); @@ -1866,6 +1957,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole if (j < basepixels_width * basepixels_height * 4) { // has transparent pixels + *has_alpha = true; pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4); for (j = 0;j < image_width * image_height * 4;j += 4) { @@ -1884,7 +1976,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole { if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL) { - skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL); + skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL); Mem_Free(pixels); pixels = NULL; } @@ -1892,7 +1984,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole { pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4); Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value); - skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL); + skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL); Mem_Free(pixels); Mem_Free(bumppixels); } @@ -1900,7 +1992,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole { pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4); Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value); - skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL); + skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL); Mem_Free(pixels); } } @@ -1918,6 +2010,12 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole return skinframe; } +skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain) +{ + qboolean has_alpha; + return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha); +} + static rtexture_t *R_SkinFrame_TextureForSkinLayer(const unsigned char *in, int width, int height, const char *name, const unsigned int *palette, int textureflags, qboolean force) { int i; @@ -1961,6 +2059,9 @@ skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, co if (!skindata) return NULL; + if (developer_loading.integer) + Con_Printf("loading 32bit skin \"%s\"\n", name); + if (r_shadow_bumpscale_basetexture.value > 0) { temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8); @@ -2017,6 +2118,9 @@ skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, i if (!skindata) return NULL; + if (developer_loading.integer) + Con_Printf("loading quake skin \"%s\"\n", name); + if (r_shadow_bumpscale_basetexture.value > 0) { temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8); @@ -2090,6 +2194,7 @@ void gl_main_start(void) R_BuildNormalizationCube(); } r_texture_fogattenuation = NULL; + r_texture_gammaramps = NULL; //r_texture_fogintensity = NULL; memset(&r_bloomstate, 0, sizeof(r_bloomstate)); memset(&r_waterstate, 0, sizeof(r_waterstate)); @@ -2119,6 +2224,7 @@ void gl_main_shutdown(void) r_texture_whitecube = NULL; r_texture_normalizationcube = NULL; r_texture_fogattenuation = NULL; + r_texture_gammaramps = NULL; //r_texture_fogintensity = NULL; memset(&r_bloomstate, 0, sizeof(r_bloomstate)); memset(&r_waterstate, 0, sizeof(r_waterstate)); @@ -2169,6 +2275,7 @@ void GL_Main_Init(void) Cvar_RegisterVariable (&gl_skyclip); } Cvar_RegisterVariable(&r_depthfirst); + Cvar_RegisterVariable(&r_useinfinitefarclip); Cvar_RegisterVariable(&r_nearclip); Cvar_RegisterVariable(&r_showbboxes); Cvar_RegisterVariable(&r_showsurfaces); @@ -2198,12 +2305,19 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_polygonoffset_submodel_factor); Cvar_RegisterVariable(&r_polygonoffset_submodel_offset); Cvar_RegisterVariable(&r_fog_exp2); + Cvar_RegisterVariable(&r_drawfog); Cvar_RegisterVariable(&r_textureunits); Cvar_RegisterVariable(&r_glsl); + Cvar_RegisterVariable(&r_glsl_contrastboost); + Cvar_RegisterVariable(&r_glsl_deluxemapping); Cvar_RegisterVariable(&r_glsl_offsetmapping); Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping); Cvar_RegisterVariable(&r_glsl_offsetmapping_scale); - Cvar_RegisterVariable(&r_glsl_deluxemapping); + Cvar_RegisterVariable(&r_glsl_postprocess); + Cvar_RegisterVariable(&r_glsl_postprocess_uservec1); + Cvar_RegisterVariable(&r_glsl_postprocess_uservec2); + Cvar_RegisterVariable(&r_glsl_postprocess_uservec3); + Cvar_RegisterVariable(&r_glsl_postprocess_uservec4); Cvar_RegisterVariable(&r_glsl_usegeneric); Cvar_RegisterVariable(&r_water); Cvar_RegisterVariable(&r_water_resolutionmultiplier); @@ -2223,7 +2337,6 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_bloom_colorsubtract); Cvar_RegisterVariable(&r_hdr); Cvar_RegisterVariable(&r_hdr_scenebrightness); - Cvar_RegisterVariable(&r_glsl_contrastboost); Cvar_RegisterVariable(&r_hdr_glowintensity); Cvar_RegisterVariable(&r_hdr_range); Cvar_RegisterVariable(&r_smoothnormals_areaweighting); @@ -2278,6 +2391,22 @@ GL_Init extern char *ENGINE_EXTENSIONS; void GL_Init (void) { + gl_renderer = (const char *)qglGetString(GL_RENDERER); + gl_vendor = (const char *)qglGetString(GL_VENDOR); + gl_version = (const char *)qglGetString(GL_VERSION); + gl_extensions = (const char *)qglGetString(GL_EXTENSIONS); + + if (!gl_extensions) + gl_extensions = ""; + if (!gl_platformextensions) + gl_platformextensions = ""; + + Con_Printf("GL_VENDOR: %s\n", gl_vendor); + Con_Printf("GL_RENDERER: %s\n", gl_renderer); + Con_Printf("GL_VERSION: %s\n", gl_version); + Con_Printf("GL_EXTENSIONS: %s\n", gl_extensions); + Con_Printf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions); + VID_CheckExtensions(); // LordHavoc: report supported extensions @@ -2400,11 +2529,14 @@ static void R_View_UpdateEntityVisible (void) if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs) { // worldmodel can check visibility + memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities); for (i = 0;i < r_refdef.scene.numentities;i++) { ent = r_refdef.scene.entities[i]; - r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs)) && ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs)); - + if (!(ent->flags & renderimask)) + if (!R_CullBox(ent->mins, ent->maxs) || (ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE))) + if ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs)) + r_refdef.viewcache.entityvisible[i] = true; } if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight) { @@ -2697,7 +2829,7 @@ void R_SetupView(qboolean allowwaterclippingplane) { if (!r_refdef.view.useperspective) GL_SetupView_Mode_Ortho(-r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip); - else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows) + else if (gl_stencil && r_useinfinitefarclip.integer) GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip); else GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip); @@ -2773,67 +2905,6 @@ void R_ResetViewRendering3D(void) R_SetupGenericShader(true); } -/* - R_Bloom_SetupShader( -"// bloom shader\n" -"// written by Forest 'LordHavoc' Hale\n" -"\n" -"// common definitions between vertex shader and fragment shader:\n" -"\n" -"#ifdef __GLSL_CG_DATA_TYPES\n" -"#define myhalf half\n" -"#define myhalf2 half2\n" -"#define myhalf3 half3\n" -"#define myhalf4 half4\n" -"#else\n" -"#define myhalf float\n" -"#define myhalf2 vec2\n" -"#define myhalf3 vec3\n" -"#define myhalf4 vec4\n" -"#endif\n" -"\n" -"varying vec2 ScreenTexCoord;\n" -"varying vec2 BloomTexCoord;\n" -"\n" -"\n" -"\n" -"\n" -"// vertex shader specific:\n" -"#ifdef VERTEX_SHADER\n" -"\n" -"void main(void)\n" -"{\n" -" ScreenTexCoord = vec2(gl_MultiTexCoord0);\n" -" BloomTexCoord = vec2(gl_MultiTexCoord1);\n" -" // transform vertex to camera space, using ftransform to match non-VS\n" -" // rendering\n" -" gl_Position = ftransform();\n" -"}\n" -"\n" -"#endif // VERTEX_SHADER\n" -"\n" -"\n" -"\n" -"\n" -"// fragment shader specific:\n" -"#ifdef FRAGMENT_SHADER\n" -"\n" -"void main(void)\n" -"{\n" -" int x, y; -" myhalf3 color = myhalf3(texture2D(Texture_Screen, ScreenTexCoord));\n" -" for (x = -BLUR_X;x <= BLUR_X;x++) -" color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n" -" color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n" -" color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n" -" color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n" - -" gl_FragColor = vec4(color);\n" -"}\n" -"\n" -"#endif // FRAGMENT_SHADER\n" -*/ - void R_RenderScene(qboolean addwaterplanes); static void R_Water_StartFrame(void) @@ -2904,6 +2975,7 @@ static void R_Water_AddWaterPlane(msurface_t *surface) vec3_t vert[3]; vec3_t normal; vec3_t center; + mplane_t plane; r_waterstate_waterplane_t *p; // just use the first triangle with a valid normal for any decisions VectorClear(normal); @@ -2917,6 +2989,21 @@ static void R_Water_AddWaterPlane(msurface_t *surface) break; } + VectorCopy(normal, plane.normal); + VectorNormalize(plane.normal); + plane.dist = DotProduct(vert[0], plane.normal); + PlaneClassify(&plane); + if (PlaneDiff(r_refdef.view.origin, &plane) < 0) + { + // skip backfaces (except if nocullface is set) + if (!(surface->texture->currentframe->currentmaterialflags & MATERIALFLAG_NOCULLFACE)) + return; + VectorNegate(plane.normal, plane.normal); + plane.dist *= -1; + PlaneClassify(&plane); + } + + // find a matching plane if there is one for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++) if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1) @@ -2929,17 +3016,7 @@ static void R_Water_AddWaterPlane(msurface_t *surface) { // store the new plane r_waterstate.numwaterplanes++; - VectorCopy(normal, p->plane.normal); - VectorNormalize(p->plane.normal); - p->plane.dist = DotProduct(vert[0], p->plane.normal); - PlaneClassify(&p->plane); - // flip the plane if it does not face the viewer - if (PlaneDiff(r_refdef.view.origin, &p->plane) < 0) - { - VectorNegate(p->plane.normal, p->plane.normal); - p->plane.dist *= -1; - PlaneClassify(&p->plane); - } + p->plane = plane; // clear materialflags and pvs p->materialflags = 0; p->pvsvalid = false; @@ -3070,6 +3147,8 @@ void R_Bloom_StartFrame(void) r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width); r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width; r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height); + r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size); + r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size); // calculate desired texture sizes if (gl_support_arb_texture_non_power_of_two) @@ -3087,33 +3166,16 @@ void R_Bloom_StartFrame(void) for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2); } - if (r_hdr.integer) - { - screentexturewidth = screentextureheight = 0; - } - else if (r_bloom.integer) + if ((r_hdr.integer || r_bloom.integer) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > gl_max_texture_size || r_refdef.view.height > gl_max_texture_size)) { + Cvar_SetValueQuick(&r_hdr, 0); + Cvar_SetValueQuick(&r_bloom, 0); } - else - { + + if (!(r_glsl.integer && (r_glsl_postprocess.integer || (v_glslgamma.integer && !vid_gammatables_trivial) || r_bloom.integer || r_hdr.integer)) && !r_bloom.integer) screentexturewidth = screentextureheight = 0; + if (!r_hdr.integer && !r_bloom.integer) bloomtexturewidth = bloomtextureheight = 0; - } - - if ((!bloomtexturewidth && !bloomtextureheight) || r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512 || screentexturewidth > gl_max_texture_size || screentextureheight > gl_max_texture_size || bloomtexturewidth > gl_max_texture_size || bloomtextureheight > gl_max_texture_size) - { - // can't use bloom if the parameters are too weird - // can't use bloom if the card does not support the texture size - if (r_bloomstate.texture_screen) - R_FreeTexture(r_bloomstate.texture_screen); - if (r_bloomstate.texture_bloom) - R_FreeTexture(r_bloomstate.texture_bloom); - memset(&r_bloomstate, 0, sizeof(r_bloomstate)); - return; - } - - r_bloomstate.enabled = true; - r_bloomstate.hdr = r_hdr.integer != 0; // allocate textures as needed if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight) @@ -3140,10 +3202,10 @@ void R_Bloom_StartFrame(void) // set up a texcoord array for the full resolution screen image // (we have to keep this around to copy back during final render) r_bloomstate.screentexcoord2f[0] = 0; - r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight; - r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth; - r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight; - r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth; + r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight; + r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth; + r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight; + r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth; r_bloomstate.screentexcoord2f[5] = 0; r_bloomstate.screentexcoord2f[6] = 0; r_bloomstate.screentexcoord2f[7] = 0; @@ -3152,38 +3214,34 @@ void R_Bloom_StartFrame(void) // (which will be additive blended over the screen image) r_bloomstate.bloomtexcoord2f[0] = 0; r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight; - r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth; + r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth; r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight; - r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth; + r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth; r_bloomstate.bloomtexcoord2f[5] = 0; r_bloomstate.bloomtexcoord2f[6] = 0; r_bloomstate.bloomtexcoord2f[7] = 0; + + if (r_hdr.integer || r_bloom.integer) + { + r_bloomstate.enabled = true; + r_bloomstate.hdr = r_hdr.integer != 0; + } } -void R_Bloom_CopyScreenTexture(float colorscale) +void R_Bloom_CopyBloomTexture(float colorscale) { r_refdef.stats.bloom++; - R_ResetViewRendering2D(); - R_Mesh_VertexPointer(r_screenvertex3f, 0, 0); - R_Mesh_ColorPointer(NULL, 0, 0); - R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0); - R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen)); - R_SetupGenericShader(true); - - // copy view into the screen texture - GL_ActiveTexture(0); - CHECKGLERROR - qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR - r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height; - - // now scale it down to the bloom texture size + // scale down screen texture to the bloom texture size CHECKGLERROR qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR GL_BlendFunc(GL_ONE, GL_ZERO); GL_Color(colorscale, colorscale, colorscale, 1); // TODO: optimize with multitexture or GLSL - R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); + R_SetupGenericShader(true); + R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0); + R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen)); + R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0); r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight; // we now have a bloom image in the framebuffer @@ -3228,7 +3286,7 @@ void R_Bloom_MakeTexture(void) GL_Color(r, r, r, 1); R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom)); R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0); - R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0); r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight; // copy the vertically blurred bloom view to a texture @@ -3272,7 +3330,7 @@ void R_Bloom_MakeTexture(void) //r = (dir ? 1.0f : brighten)/(range*2+1); r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range)); GL_Color(r, r, r, 1); - R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0); r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight; GL_BlendFunc(GL_ONE, GL_ONE); } @@ -3292,7 +3350,7 @@ void R_Bloom_MakeTexture(void) R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom)); R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0); GL_Color(1, 1, 1, 1); - R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0); r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight; GL_BlendFunc(GL_ONE, GL_ONE); @@ -3300,7 +3358,7 @@ void R_Bloom_MakeTexture(void) R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0); GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1); - R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0); r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight; qglBlendEquationEXT(GL_FUNC_ADD_EXT); @@ -3358,7 +3416,88 @@ void R_HDR_RenderBloomTexture(void) static void R_BlendView(void) { - if (r_bloomstate.enabled && r_bloomstate.hdr) + if (r_bloomstate.texture_screen) + { + // copy view into the screen texture + R_ResetViewRendering2D(); + R_Mesh_VertexPointer(r_screenvertex3f, 0, 0); + R_Mesh_ColorPointer(NULL, 0, 0); + R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen)); + GL_ActiveTexture(0);CHECKGLERROR + qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR + r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height; + } + + if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom)) + { + unsigned int permutation = + (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0) + | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0) + | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0) + | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0); + + if (r_bloomstate.texture_bloom && !r_bloomstate.hdr) + { + // render simple bloom effect + // copy the screen and shrink it and darken it for the bloom process + R_Bloom_CopyBloomTexture(r_bloom_colorscale.value); + // make the bloom texture + R_Bloom_MakeTexture(); + } + + R_ResetViewRendering2D(); + R_Mesh_VertexPointer(r_screenvertex3f, 0, 0); + R_Mesh_ColorPointer(NULL, 0, 0); + GL_Color(1, 1, 1, 1); + GL_BlendFunc(GL_ONE, GL_ZERO); + R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation); + R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen)); + R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0); + R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom)); + R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0); + if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) + R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps)); + if (r_glsl_permutation->loc_TintColor >= 0) + qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]); + if (r_glsl_permutation->loc_ClientTime >= 0) + qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time); + if (r_glsl_permutation->loc_PixelSize >= 0) + qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight); + if (r_glsl_permutation->loc_UserVec1 >= 0) + { + float a=0, b=0, c=0, d=0; +#if _MSC_VER >= 1400 +#define sscanf sscanf_s +#endif + sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d); + qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d); + } + if (r_glsl_permutation->loc_UserVec2 >= 0) + { + float a=0, b=0, c=0, d=0; + sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d); + qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d); + } + if (r_glsl_permutation->loc_UserVec3 >= 0) + { + float a=0, b=0, c=0, d=0; + sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d); + qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d); + } + if (r_glsl_permutation->loc_UserVec4 >= 0) + { + float a=0, b=0, c=0, d=0; + sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d); + qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d); + } + R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0); + r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height; + return; + } + + + + if (r_bloomstate.texture_bloom && r_bloomstate.hdr) { // render high dynamic range bloom effect // the bloom texture was made earlier this render, so we just need to @@ -3371,14 +3510,14 @@ static void R_BlendView(void) GL_BlendFunc(GL_ONE, GL_ONE); R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom)); R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0); - R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0); r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height; } - else if (r_bloomstate.enabled) + else if (r_bloomstate.texture_bloom) { // render simple bloom effect // copy the screen and shrink it and darken it for the bloom process - R_Bloom_CopyScreenTexture(r_bloom_colorscale.value); + R_Bloom_CopyBloomTexture(r_bloom_colorscale.value); // make the bloom texture R_Bloom_MakeTexture(); // put the original screen image back in place and blend the bloom @@ -3400,14 +3539,14 @@ static void R_BlendView(void) else { R_SetupGenericShader(true); - R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0); r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height; // now blend on the bloom texture GL_BlendFunc(GL_ONE, GL_ONE); R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen)); R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0); } - R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0); r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height; } if (r_refdef.viewblend[3] >= (1.0f / 256.0f)) @@ -3419,7 +3558,7 @@ static void R_BlendView(void) R_SetupGenericShader(false); GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]); - R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0); } } @@ -3458,9 +3597,11 @@ void R_UpdateVariables(void) { R_Textures_Frame(); + r_refdef.scene.ambient = r_ambient.value; + r_refdef.farclip = 4096; if (r_refdef.scene.worldmodel) - r_refdef.farclip += VectorDistance(r_refdef.scene.worldmodel->normalmins, r_refdef.scene.worldmodel->normalmaxs); + r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2; r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f); if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1) @@ -3470,17 +3611,17 @@ void R_UpdateVariables(void) r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1); r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1); - r_refdef.rtworld = r_shadow_realtime_world.integer; - r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil; - r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer; - r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil; - r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1; + r_refdef.scene.rtworld = r_shadow_realtime_world.integer; + r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil; + r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer; + r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil; + r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1; if (r_showsurfaces.integer) { - r_refdef.rtworld = false; - r_refdef.rtworldshadows = false; - r_refdef.rtdlight = false; - r_refdef.rtdlightshadows = false; + r_refdef.scene.rtworld = false; + r_refdef.scene.rtworldshadows = false; + r_refdef.scene.rtdlight = false; + r_refdef.scene.rtdlightshadows = false; r_refdef.lightmapintensity = 0; } @@ -3516,7 +3657,7 @@ void R_UpdateVariables(void) // R_UpdateFogColor(); // why? R_RenderScene does it anyway - if (r_refdef.fog_density) + if (r_refdef.fog_density && r_drawfog.integer) { r_refdef.fogenabled = true; // this is the point where the fog reaches 0.9986 alpha, which we @@ -3536,6 +3677,41 @@ void R_UpdateVariables(void) } else r_refdef.fogenabled = false; + + if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial) + { + if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial) + { + // build GLSL gamma texture +#define RAMPWIDTH 256 + unsigned short ramp[RAMPWIDTH * 3]; + unsigned char ramprgb[RAMPWIDTH][4]; + int i; + + r_texture_gammaramps_serial = vid_gammatables_serial; + + VID_BuildGammaTables(&ramp[0], RAMPWIDTH); + for(i = 0; i < RAMPWIDTH; ++i) + { + ramprgb[i][0] = ramp[i] >> 8; + ramprgb[i][1] = ramp[i + RAMPWIDTH] >> 8; + ramprgb[i][2] = ramp[i + 2 * RAMPWIDTH] >> 8; + ramprgb[i][3] = 0; + } + if (r_texture_gammaramps) + { + R_UpdateTexture(r_texture_gammaramps, &ramprgb[0][0], 0, 0, RAMPWIDTH, 1); + } + else + { + r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &ramprgb[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL); + } + } + } + else + { + // remove GLSL gamma texture + } } static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT; @@ -3577,7 +3753,24 @@ R_RenderView */ void R_RenderView(void) { - if (!r_refdef.scene.entities/* || !r_refdef.scene.worldmodel*/) + if (r_refdef.view.isoverlay) + { + // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas] + GL_Clear( GL_DEPTH_BUFFER_BIT ); + R_TimeReport("depthclear"); + + r_refdef.view.showdebug = false; + + r_waterstate.enabled = false; + r_waterstate.numwaterplanes = 0; + + R_RenderScene(false); + + CHECKGLERROR + return; + } + + if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/) return; //Host_Error ("R_RenderView: NULL worldmodel"); r_refdef.view.colorscale = r_hdr_scenebrightness.value; @@ -3830,7 +4023,7 @@ void R_RenderScene(qboolean addwaterplanes) R_ResetViewRendering2D(); } -static const int bboxelements[36] = +static const unsigned short bboxelements[36] = { 5, 1, 3, 5, 3, 7, 6, 2, 0, 6, 0, 4, @@ -3875,7 +4068,7 @@ void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, floa R_Mesh_ColorPointer(color4f, 0, 0); R_Mesh_ResetTextureState(); R_SetupGenericShader(false); - R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0); + R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0); } static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) @@ -3883,10 +4076,16 @@ static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtligh int i; float color[4]; prvm_edict_t *edict; + prvm_prog_t *prog_save = prog; + // this function draws bounding boxes of server entities if (!sv.active) return; + + GL_CullFace(GL_NONE); R_SetupGenericShader(false); + + prog = 0; SV_VM_Begin(); for (i = 0;i < numsurfaces;i++) { @@ -3907,6 +4106,7 @@ static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtligh R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]); } SV_VM_End(); + prog = prog_save; } static void R_DrawEntityBBoxes(void) @@ -3914,22 +4114,32 @@ static void R_DrawEntityBBoxes(void) int i; prvm_edict_t *edict; vec3_t center; + prvm_prog_t *prog_save = prog; + // this function draws bounding boxes of server entities if (!sv.active) return; + + prog = 0; SV_VM_Begin(); for (i = 0;i < prog->num_edicts;i++) { edict = PRVM_EDICT_NUM(i); if (edict->priv.server->free) continue; + // exclude the following for now, as they don't live in world coordinate space and can't be solid: + if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0) + continue; + if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0) + continue; VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center); R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL); } SV_VM_End(); + prog = prog_save; } -int nomodelelements[24] = +unsigned short nomodelelements[24] = { 5, 2, 0, 5, 1, 2, @@ -4017,7 +4227,7 @@ void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight else R_Mesh_ColorPointer(nomodelcolor4f, 0, 0); R_Mesh_ResetTextureState(); - R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0); + R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0); } void R_DrawNoModel(entity_render_t *ent) @@ -4109,7 +4319,7 @@ void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_ R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0); // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca); - R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0); if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA) { @@ -4117,7 +4327,7 @@ void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_ GL_BlendFunc(blendfunc1, GL_ONE); fog = 1 - fog; GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca); - R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0); } } @@ -4270,12 +4480,19 @@ static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms) void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) { + int w, h, idx; int i; - model_t *model = ent->model; + dp_model_t *model = ent->model; float f; float tcmat[12]; q3shaderinfo_layer_tcmod_t *tcmod; + if (t->basematerialflags & MATERIALFLAG_NODRAW) + { + t->currentmaterialflags = MATERIALFLAG_NODRAW; + return; + } + // switch to an alternate material if this is a q1bsp animated material { texture_t *texture = t; @@ -4304,12 +4521,13 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) } // update currentskinframe to be a qw skin or animation frame - if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients) + if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[i].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) { if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin)) { strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i])); - Con_DPrintf("loading skins/%s\n", r_qwskincache[i]); + if (developer_loading.integer) + Con_Printf("loading skins/%s\n", r_qwskincache[i]); r_qwskincache_skinframe[i] = R_SkinFrame_LoadExternal(va("skins/%s", r_qwskincache[i]), TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS, developer.integer > 0); } t->currentskinframe = r_qwskincache_skinframe[i]; @@ -4324,16 +4542,10 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) t->currentmaterialflags = t->basematerialflags; t->currentalpha = ent->alpha; if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer)) - { t->currentalpha *= r_wateralpha.value; - /* - * FIXME what is this supposed to do? - // if rendering refraction/reflection, disable transparency - if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA))) - t->currentmaterialflags |= MATERIALFLAG_WATERSHADER; - */ - } - if(!r_waterstate.enabled) + if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) + t->currentalpha *= t->r_water_wateralpha; + if(!r_waterstate.enabled || r_refdef.view.isoverlay) t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION); if (!(ent->flags & RENDER_LIGHT)) t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT; @@ -4366,7 +4578,7 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER); // there is no tcmod - if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0) + if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL) t->currenttexmatrix = r_waterscrollmatrix; for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++) @@ -4376,7 +4588,7 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) { case Q3TCMOD_COUNT: case Q3TCMOD_NONE: - if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0) + if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL) matrix = r_waterscrollmatrix; else matrix = identitymatrix; @@ -4397,6 +4609,14 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) case Q3TCMOD_SCROLL: Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0); break; + case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures) + w = tcmod->parms[0]; + h = tcmod->parms[1]; + f = r_refdef.scene.time / (tcmod->parms[2] * w * h); + f = f - floor(f); + idx = floor(f * w * h); + Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0); + break; case Q3TCMOD_STRETCH: f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms); Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f); @@ -4458,105 +4678,98 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) t->basetexture = r_texture_grey128; t->backgroundbasetexture = NULL; t->specularscale = 0; - t->currentmaterialflags &= ~(MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_WATERALPHA | MATERIALFLAG_WATER | MATERIALFLAG_SKY | MATERIALFLAG_ALPHATEST | MATERIALFLAG_BLENDED | MATERIALFLAG_CUSTOMBLEND | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION); - t->currentmaterialflags |= MATERIALFLAG_WALL; + t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE)); } Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha); VectorClear(t->dlightcolor); t->currentnumlayers = 0; - if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW)) + if (t->currentmaterialflags & MATERIALFLAG_WALL) { - if (!(t->currentmaterialflags & MATERIALFLAG_SKY)) + int layerflags = 0; + int blendfunc1, blendfunc2, depthmask; + if (t->currentmaterialflags & MATERIALFLAG_ADD) { - int blendfunc1, blendfunc2, depthmask; - if (t->currentmaterialflags & MATERIALFLAG_ADD) - { - blendfunc1 = GL_SRC_ALPHA; - blendfunc2 = GL_ONE; - } - else if (t->currentmaterialflags & MATERIALFLAG_ALPHA) - { - blendfunc1 = GL_SRC_ALPHA; - blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; - } - else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND) - { - blendfunc1 = t->customblendfunc[0]; - blendfunc2 = t->customblendfunc[1]; - } - else + blendfunc1 = GL_SRC_ALPHA; + blendfunc2 = GL_ONE; + } + else if (t->currentmaterialflags & MATERIALFLAG_ALPHA) + { + blendfunc1 = GL_SRC_ALPHA; + blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + } + else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND) + { + blendfunc1 = t->customblendfunc[0]; + blendfunc2 = t->customblendfunc[1]; + } + else + { + blendfunc1 = GL_ONE; + blendfunc2 = GL_ZERO; + } + depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED); + if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED)) + layerflags |= TEXTURELAYERFLAG_FOGDARKEN; + if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) + { + // fullbright is not affected by r_refdef.lightmapintensity + R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]); + if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]); + if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]); + } + else + { + vec3_t ambientcolor; + float colorscale; + // set the color tint used for lights affecting this surface + VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]); + colorscale = 2; + // q3bsp has no lightmap updates, so the lightstylevalue that + // would normally be baked into the lightmap must be + // applied to the color + // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright) + if (ent->model->type == mod_brushq3) + colorscale *= r_refdef.scene.rtlightstylevalue[0]; + colorscale *= r_refdef.lightmapintensity; + VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor); + VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor); + // basic lit geometry + R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]); + // add pants/shirt if needed + if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]); + if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]); + // now add ambient passes if needed + if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f)) { - blendfunc1 = GL_ONE; - blendfunc2 = GL_ZERO; - } - depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED); - if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL)) - { - int layerflags = 0; - if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED)) - layerflags |= TEXTURELAYERFLAG_FOGDARKEN; - if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) - { - // fullbright is not affected by r_refdef.lightmapintensity - R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]); - if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]); - if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]); - } - else - { - vec3_t ambientcolor; - float colorscale; - // set the color tint used for lights affecting this surface - VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]); - colorscale = 2; - // q3bsp has no lightmap updates, so the lightstylevalue that - // would normally be baked into the lightmap must be - // applied to the color - // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright) - if (ent->model->type == mod_brushq3) - colorscale *= r_refdef.scene.rtlightstylevalue[0]; - colorscale *= r_refdef.lightmapintensity; - VectorScale(t->lightmapcolor, r_ambient.value * (1.0f / 64.0f), ambientcolor); - VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor); - // basic lit geometry - R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]); - // add pants/shirt if needed - if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]); - if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]); - // now add ambient passes if needed - if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f)) - { - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]); - if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ambientcolor[0], ent->colormap_pantscolor[1] * ambientcolor[1], ent->colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]); - if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ambientcolor[0], ent->colormap_shirtcolor[1] * ambientcolor[1], ent->colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]); - } - } - if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->lightmapcolor[3]); - if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD)) - { - // if this is opaque use alpha blend which will darken the earlier - // passes cheaply. - // - // if this is an alpha blended material, all the earlier passes - // were darkened by fog already, so we only need to add the fog - // color ontop through the fog mask texture - // - // if this is an additive blended material, all the earlier passes - // were darkened by fog already, and we should not add fog color - // (because the background was not darkened, there is no fog color - // that was lost behind it). - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->currentskinframe->fog, &identitymatrix, r_refdef.fogcolor[0] / r_refdef.view.colorscale, r_refdef.fogcolor[1] / r_refdef.view.colorscale, r_refdef.fogcolor[2] / r_refdef.view.colorscale, t->lightmapcolor[3]); - } + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]); + if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ambientcolor[0], ent->colormap_pantscolor[1] * ambientcolor[1], ent->colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]); + if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ambientcolor[0], ent->colormap_shirtcolor[1] * ambientcolor[1], ent->colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]); } } + if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->lightmapcolor[3]); + if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD)) + { + // if this is opaque use alpha blend which will darken the earlier + // passes cheaply. + // + // if this is an alpha blended material, all the earlier passes + // were darkened by fog already, so we only need to add the fog + // color ontop through the fog mask texture + // + // if this is an additive blended material, all the earlier passes + // were darkened by fog already, and we should not add fog color + // (because the background was not darkened, there is no fog color + // that was lost behind it). + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->currentskinframe->fog, &identitymatrix, r_refdef.fogcolor[0] / r_refdef.view.colorscale, r_refdef.fogcolor[1] / r_refdef.view.colorscale, r_refdef.fogcolor[2] / r_refdef.view.colorscale, t->lightmapcolor[3]); + } } } @@ -4594,7 +4807,7 @@ void R_Mesh_ResizeArrays(int newvertices) void RSurf_ActiveWorldEntity(void) { - model_t *model = r_refdef.scene.worldmodel; + dp_model_t *model = r_refdef.scene.worldmodel; if (rsurface.array_size < model->surfmesh.num_vertices) R_Mesh_ResizeArrays(model->surfmesh.num_vertices); rsurface.matrix = identitymatrix; @@ -4638,7 +4851,9 @@ void RSurf_ActiveWorldEntity(void) rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo; rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f; rsurface.modelelement3i = model->surfmesh.data_element3i; - rsurface.modelelement3i_bufferobject = model->surfmesh.ebo; + rsurface.modelelement3s = model->surfmesh.data_element3s; + rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i; + rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s; rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets; rsurface.modelnum_vertices = model->surfmesh.num_vertices; rsurface.modelnum_triangles = model->surfmesh.num_triangles; @@ -4661,7 +4876,7 @@ void RSurf_ActiveWorldEntity(void) void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents) { - model_t *model = ent->model; + dp_model_t *model = ent->model; if (rsurface.array_size < model->surfmesh.num_vertices) R_Mesh_ResizeArrays(model->surfmesh.num_vertices); rsurface.matrix = ent->matrix; @@ -4689,7 +4904,7 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value; rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value; } - if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0)) + if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0)) { if (wanttangents) { @@ -4697,7 +4912,7 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q rsurface.modelsvector3f = rsurface.array_modelsvector3f; rsurface.modeltvector3f = rsurface.array_modeltvector3f; rsurface.modelnormal3f = rsurface.array_modelnormal3f; - Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f); + model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f); } else if (wantnormals) { @@ -4705,7 +4920,7 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q rsurface.modelsvector3f = NULL; rsurface.modeltvector3f = NULL; rsurface.modelnormal3f = rsurface.array_modelnormal3f; - Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL); + model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL); } else { @@ -4713,7 +4928,7 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q rsurface.modelsvector3f = NULL; rsurface.modeltvector3f = NULL; rsurface.modelnormal3f = NULL; - Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL); + model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL); } rsurface.modelvertex3f_bufferobject = 0; rsurface.modelvertex3f_bufferoffset = 0; @@ -4751,7 +4966,9 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo; rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f; rsurface.modelelement3i = model->surfmesh.data_element3i; - rsurface.modelelement3i_bufferobject = model->surfmesh.ebo; + rsurface.modelelement3s = model->surfmesh.data_element3s; + rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i; + rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s; rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets; rsurface.modelnum_vertices = model->surfmesh.num_vertices; rsurface.modelnum_triangles = model->surfmesh.num_triangles; @@ -5205,7 +5422,7 @@ void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacel if (texturenumsurfaces == 1) { GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle)); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject); } else if (r_batchmode.integer == 2) { @@ -5218,7 +5435,7 @@ void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacel j = i + 1; if (surface->num_triangles > MAXBATCHTRIANGLES) { - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle)); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject); continue; } memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3])); @@ -5237,7 +5454,7 @@ void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacel } surface2 = texturesurfacelist[j-1]; numvertices = endvertex - firstvertex; - R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0); + R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0); } } else if (r_batchmode.integer == 1) @@ -5252,7 +5469,7 @@ void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacel numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex; numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle; GL_LockArrays(surface->num_firstvertex, numvertices); - R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle)); + R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject); } } else @@ -5261,7 +5478,7 @@ void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacel { surface = texturesurfacelist[i]; GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle)); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject); } } } @@ -5315,7 +5532,7 @@ static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black)); } GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle)); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject); } } @@ -5336,7 +5553,7 @@ static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurfa if (deluxemaptexunit >= 0) R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture)); GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle)); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject); } else if (r_batchmode.integer == 2) { @@ -5352,7 +5569,7 @@ static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurfa j = i + 1; if (surface->num_triangles > MAXBATCHTRIANGLES) { - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle)); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject); continue; } memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3])); @@ -5371,7 +5588,7 @@ static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurfa } surface2 = texturesurfacelist[j-1]; numvertices = endvertex - firstvertex; - R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0); + R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0); } } else if (r_batchmode.integer == 1) @@ -5405,7 +5622,7 @@ static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurfa numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex; numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle; GL_LockArrays(surface->num_firstvertex, numvertices); - R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle)); + R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject); } #if 0 Con_Printf("\n"); @@ -5420,7 +5637,7 @@ static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurfa if (deluxemaptexunit >= 0) R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture)); GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle)); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject); } } } @@ -5438,7 +5655,7 @@ static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **te { float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale; GL_Color(f, f, f, 1); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, 1, (rsurface.modelelement3i + 3 * (j + surface->num_firsttriangle)), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * (j + surface->num_firsttriangle))); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject); } } } @@ -5450,7 +5667,7 @@ static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **te int k = (int)(((size_t)surface) / sizeof(msurface_t)); GL_Color((k & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 4) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 8) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, 1); GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle)); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject); } } } @@ -5553,7 +5770,7 @@ static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t int i; float *c; // TODO: optimize - if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples) + if (texturesurfacelist[0]->lightmapinfo) { // generate color arrays for the surfaces in this list for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) @@ -5753,8 +5970,11 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **t R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture)); R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow)); } - R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants)); - R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt)); + if(rsurface.texture->colormapping) + { + R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants)); + R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt)); + } R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation)); if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)) R_Mesh_ColorPointer(NULL, 0, 0); @@ -6250,7 +6470,7 @@ float locboxvertex3f[6*4*3] = 1,0,0, 0,0,0, 0,1,0, 1,1,0 }; -int locboxelement3i[6*2*3] = +unsigned short locboxelements[6*2*3] = { 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, @@ -6301,7 +6521,7 @@ void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, in for (j = 0;j < 3;j++, i++) vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i]; - R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0); + R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0); } void R_DrawLocs(void) @@ -6323,10 +6543,10 @@ void R_DrawDebugModel(entity_render_t *ent) const int *elements; q3mbrush_t *brush; msurface_t *surface; - model_t *model = ent->model; + dp_model_t *model = ent->model; vec3_t v; - flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL; + flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL; R_Mesh_ColorPointer(NULL, 0, 0); R_Mesh_ResetTextureState(); @@ -6345,7 +6565,7 @@ void R_DrawDebugModel(entity_render_t *ent) { R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0); GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value); - R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0); + R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0); } } for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++) @@ -6354,7 +6574,7 @@ void R_DrawDebugModel(entity_render_t *ent) { R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0); GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value); - R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0); + R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0); } } } @@ -6448,20 +6668,32 @@ void R_DrawDebugModel(entity_render_t *ent) } extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface); +int r_maxsurfacelist = 0; +msurface_t **r_surfacelist = NULL; void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug) { int i, j, endj, f, flagsmask; - msurface_t *surface; texture_t *t; - model_t *model = r_refdef.scene.worldmodel; - const int maxsurfacelist = 1024; + dp_model_t *model = r_refdef.scene.worldmodel; + msurface_t *surfaces; + unsigned char *update; int numsurfacelist = 0; - msurface_t *surfacelist[1024]; if (model == NULL) return; + if (r_maxsurfacelist < model->num_surfaces) + { + r_maxsurfacelist = model->num_surfaces; + if (r_surfacelist) + Mem_Free(r_surfacelist); + r_surfacelist = Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist)); + } + RSurf_ActiveWorldEntity(); + surfaces = model->data_surfaces; + update = model->brushq1.lightmapupdateflags; + // update light styles on this submodel if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0) { @@ -6470,17 +6702,16 @@ void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean dep { if (style->value != r_refdef.scene.lightstylevalue[style->style]) { - msurface_t *surfaces = model->data_surfaces; int *list = style->surfacelist; style->value = r_refdef.scene.lightstylevalue[style->style]; for (j = 0;j < style->numsurfaces;j++) - surfaces[list[j]].cached_dlight = true; + update[list[j]] = true; } } } R_UpdateAllTextureInfo(r_refdef.scene.worldentity); - flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL)); + flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL); if (debug) { @@ -6494,54 +6725,60 @@ void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean dep rsurface.texture = NULL; rsurface.rtlight = NULL; numsurfacelist = 0; + // add visible surfaces to draw list j = model->firstmodelsurface; endj = j + model->nummodelsurfaces; - while (j < endj) + if (update) { - // quickly skip over non-visible surfaces - for (;j < endj && !r_refdef.viewcache.world_surfacevisible[j];j++) - ; - // quickly iterate over visible surfaces - for (;j < endj && r_refdef.viewcache.world_surfacevisible[j];j++) + for (;j < endj;j++) { - // process this surface - surface = model->data_surfaces + j; - // if this surface fits the criteria, add it to the list - if (surface->num_triangles) + if (r_refdef.viewcache.world_surfacevisible[j]) { - // if lightmap parameters changed, rebuild lightmap texture - if (surface->cached_dlight) - R_BuildLightMap(r_refdef.scene.worldentity, surface); - // add face to draw list - surfacelist[numsurfacelist++] = surface; - r_refdef.stats.world_triangles += surface->num_triangles; - if (numsurfacelist >= maxsurfacelist) - { - r_refdef.stats.world_surfaces += numsurfacelist; - R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes); - numsurfacelist = 0; - } + r_surfacelist[numsurfacelist++] = surfaces + j; + // update lightmap if needed + if (update[j]) + R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j); } } } - r_refdef.stats.world_surfaces += numsurfacelist; - if (numsurfacelist) - R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes); + else + for (;j < endj;j++) + if (r_refdef.viewcache.world_surfacevisible[j]) + r_surfacelist[numsurfacelist++] = surfaces + j; + // don't do anything if there were no surfaces + if (!numsurfacelist) + return; + R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, addwaterplanes); GL_AlphaTest(false); + + // add to stats if desired + if (r_speeds.integer && !skysurfaces && !depthonly && !addwaterplanes) + { + r_refdef.stats.world_surfaces += numsurfacelist; + for (j = 0;j < numsurfacelist;j++) + r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles; + } } void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug) { - int i, j, f, flagsmask; - msurface_t *surface, *endsurface; + int i, j, endj, f, flagsmask; texture_t *t; - model_t *model = ent->model; - const int maxsurfacelist = 1024; + dp_model_t *model = ent->model; + msurface_t *surfaces; + unsigned char *update; int numsurfacelist = 0; - msurface_t *surfacelist[1024]; if (model == NULL) return; + if (r_maxsurfacelist < model->num_surfaces) + { + r_maxsurfacelist = model->num_surfaces; + if (r_surfacelist) + Mem_Free(r_surfacelist); + r_surfacelist = Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist)); + } + // if the model is static it doesn't matter what value we give for // wantnormals and wanttangents, so this logic uses only rules applicable // to a model, knowing that they are meaningless otherwise @@ -6552,6 +6789,9 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr else RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly); + surfaces = model->data_surfaces; + update = model->brushq1.lightmapupdateflags; + // update light styles if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0) { @@ -6560,17 +6800,16 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr { if (style->value != r_refdef.scene.lightstylevalue[style->style]) { - msurface_t *surfaces = model->data_surfaces; int *list = style->surfacelist; style->value = r_refdef.scene.lightstylevalue[style->style]; for (j = 0;j < style->numsurfaces;j++) - surfaces[list[j]].cached_dlight = true; + update[list[j]] = true; } } } R_UpdateAllTextureInfo(ent); - flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL)); + flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL); if (debug) { @@ -6584,29 +6823,28 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr rsurface.texture = NULL; rsurface.rtlight = NULL; numsurfacelist = 0; - surface = model->data_surfaces + model->firstmodelsurface; - endsurface = surface + model->nummodelsurfaces; - for (;surface < endsurface;surface++) + // add visible surfaces to draw list + j = model->firstmodelsurface; + endj = j + model->nummodelsurfaces; + for (;j < endj;j++) + r_surfacelist[numsurfacelist++] = surfaces + j; + // don't do anything if there were no surfaces + if (!numsurfacelist) + return; + // update lightmaps if needed + if (update) + for (j = model->firstmodelsurface;j < endj;j++) + if (update[j]) + R_BuildLightMap(ent, surfaces + j); + R_QueueSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, addwaterplanes); + GL_AlphaTest(false); + + // add to stats if desired + if (r_speeds.integer && !skysurfaces && !depthonly && !addwaterplanes) { - // if this surface fits the criteria, add it to the list - if (surface->num_triangles) - { - // if lightmap parameters changed, rebuild lightmap texture - if (surface->cached_dlight) - R_BuildLightMap(ent, surface); - // add face to draw list - surfacelist[numsurfacelist++] = surface; - r_refdef.stats.entities_triangles += surface->num_triangles; - if (numsurfacelist >= maxsurfacelist) - { - r_refdef.stats.entities_surfaces += numsurfacelist; - R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes); - numsurfacelist = 0; - } - } + r_refdef.stats.entities++; + r_refdef.stats.entities_surfaces += numsurfacelist; + for (j = 0;j < numsurfacelist;j++) + r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles; } - r_refdef.stats.entities_surfaces += numsurfacelist; - if (numsurfacelist) - R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes); - GL_AlphaTest(false); }