X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=gl_rmain.c;h=d538305f90d653c111842c0bbb2f33e31b53a895;hb=cd5581199cb9c33255024144859164e36fcaa166;hp=64b031dc7eaddf4e150c7cc63e0c7cffe83d5214;hpb=5f0b5e693f0e50a14c417d16bf9ae8d929f0a0fa;p=xonotic%2Fdarkplaces.git diff --git a/gl_rmain.c b/gl_rmain.c index 64b031dc..d538305f 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -76,11 +76,17 @@ 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)"}; cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"}; @@ -119,14 +125,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 { @@ -141,8 +142,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]; @@ -150,36 +149,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; @@ -192,6 +162,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]; @@ -453,53 +425,166 @@ static const char *builtinshaderstring = "\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" +"//#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" +"#ifdef MODE_DEPTH_OR_SHADOW\n" +"\n" +"# ifdef VERTEX_SHADER\n" +"void main(void)\n" +"{\n" +" gl_Position = ftransform();\n" +"}\n" +"# endif\n" +"\n" +"#else\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" +" gl_FrontColor = gl_Color;\n" +"# ifdef USEDIFFUSE\n" +" gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n" +"# endif\n" +"# ifdef USESPECULAR\n" +" gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n" +"# endif\n" +" gl_Position = ftransform();\n" +"}\n" +"# endif\n" +"# ifdef FRAGMENT_SHADER\n" +"\n" +"# ifdef USEDIFFUSE\n" +"uniform sampler2D Texture_First;\n" +"# endif\n" +"# ifdef USESPECULAR\n" +"uniform sampler2D Texture_Second;\n" +"# endif\n" +"\n" +"void main(void)\n" +"{\n" +" gl_FragColor = gl_Color;\n" +"# ifdef USEDIFFUSE\n" +" gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n" +"# endif\n" +"\n" +"# ifdef USESPECULAR\n" +" vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n" +"# endif\n" +"# ifdef USECOLORMAPPING\n" +" gl_FragColor *= tex2;\n" +"# endif\n" +"# ifdef USEGLOW\n" +" gl_FragColor += tex2;\n" +"# endif\n" +"# ifdef USEVERTEXTEXTUREBLEND\n" +" gl_FragColor = mix(tex2, gl_FragColor, tex2.a);\n" +"# endif\n" +"}\n" +"# endif\n" +"\n" +"#else // !MODE_GENERIC\n" "\n" "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" @@ -512,7 +597,7 @@ static const char *builtinshaderstring = "uniform vec3 EyePosition;\n" "uniform vec3 LightDir;\n" "\n" -"// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n" +"// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n" "\n" "void main(void)\n" "{\n" @@ -720,11 +805,11 @@ static const char *builtinshaderstring = " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n" " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n" " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n" -" float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 5.0) * ReflectFactor + ReflectOffset;\n" +" float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n" " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n" "}\n" "\n" -"#else // MODE_WATER\n" +"#else // !MODE_WATER\n" "#ifdef MODE_REFRACTION\n" "\n" "// refraction pass\n" @@ -742,7 +827,7 @@ static const char *builtinshaderstring = " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n" "}\n" "\n" -"#else // MODE_REFRACTION\n" +"#else // !MODE_REFRACTION\n" "void main(void)\n" "{\n" "#ifdef USEOFFSETMAPPING\n" @@ -933,10 +1018,14 @@ static const char *builtinshaderstring = "\n" " gl_FragColor = vec4(color);\n" "}\n" -"#endif // MODE_REFRACTION\n" -"#endif // MODE_WATER\n" +"#endif // !MODE_REFRACTION\n" +"#endif // !MODE_WATER\n" "\n" "#endif // FRAGMENT_SHADER\n" +"\n" +"#endif // !MODE_GENERIC\n" +"#endif // !MODE_POSTPROCESS\n" +"#endif // !MODE_DEPTH_OR_SHADOW\n" ; typedef struct shaderpermutationinfo_s @@ -969,8 +1058,10 @@ typedef enum shaderpermutation_e 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_GAMMARAMPS = 1<<11, // gamma (postprocessing only) + SHADERPERMUTATION_POSTPROCESSING = 1<<12, // user defined postprocessing + SHADERPERMUTATION_LIMIT = 1<<13, // size of permutations array + SHADERPERMUTATION_COUNT = 13 // size of shaderpermutationinfo array } shaderpermutation_t; @@ -988,11 +1079,16 @@ shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] = {"#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) SHADERMODE_LIGHTMAP, // (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp) @@ -1009,6 +1105,9 @@ shadermode_t; // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS! 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"}, {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"}, @@ -1027,6 +1126,9 @@ typedef struct r_glsl_permutation_s // 0 if compilation failed int program; // 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; @@ -1063,6 +1165,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; @@ -1070,6 +1173,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; @@ -1177,6 +1286,9 @@ static void R_GLSL_CompilePermutation(shadermode_t mode, shaderpermutation_t per qglUseProgramObjectARB(p->program);CHECKGLERROR // look up all the uniform variable names we care about, so we don't // 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"); @@ -1220,7 +1332,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); @@ -1239,7 +1361,6 @@ static void R_GLSL_CompilePermutation(shadermode_t mode, shaderpermutation_t per if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION); if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION); CHECKGLERROR - qglUseProgramObjectARB(0);CHECKGLERROR if (developer.integer) Con_Printf("GLSL shader %s compiled.\n", permutationname); } @@ -1290,10 +1411,99 @@ void R_GLSL_DumpShader_f(void) Con_Printf("glsl/default.glsl written\n"); } +void R_SetupShader_SetPermutation(shadermode_t mode, unsigned int permutation) +{ + r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation]; + if (r_glsl_permutation != perm) + { + r_glsl_permutation = perm; + if (!r_glsl_permutation->program) + { + if (!r_glsl_permutation->compiled) + R_GLSL_CompilePermutation(mode, permutation); + if (!r_glsl_permutation->program) + { + // remove features until we find a valid permutation + int i; + for (i = 0;i < SHADERPERMUTATION_COUNT;i++) + { + // reduce i more quickly whenever it would not remove any bits + int j = 1<<(SHADERPERMUTATION_COUNT-1-i); + if (!(permutation & j)) + continue; + permutation -= j; + r_glsl_permutation = &r_glsl_permutations[mode][permutation]; + if (!r_glsl_permutation->compiled) + R_GLSL_CompilePermutation(mode, permutation); + if (r_glsl_permutation->program) + break; + } + if (i >= SHADERPERMUTATION_COUNT) + { + Con_Printf("OpenGL 2.0 shaders disabled - unable to find a working shader permutation fallback on this driver (set r_glsl 1 if you want to try again)\n"); + Cvar_SetValueQuick(&r_glsl, 0); + R_GLSL_Restart_f(); // unload shaders + return; // no bit left to clear + } + } + } + CHECKGLERROR + qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR + } +} + +void R_SetupGenericShader(qboolean usetexture) +{ + if (gl_support_fragment_shader) + { + if (r_glsl.integer && r_glsl_usegeneric.integer) + R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0); + else if (r_glsl_permutation) + { + r_glsl_permutation = NULL; + qglUseProgramObjectARB(0);CHECKGLERROR + } + } +} + +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)))); + else if (r_glsl_permutation) + { + r_glsl_permutation = NULL; + qglUseProgramObjectARB(0);CHECKGLERROR + } + } + if (!r_glsl_permutation) + { + if (texturemode == GL_DECAL && gl_combine.integer) + texturemode = GL_INTERPOLATE_ARB; + R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1); + } +} + +void R_SetupDepthOrShadowShader(void) +{ + if (gl_support_fragment_shader) + { + if (r_glsl.integer && r_glsl_usegeneric.integer) + R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0); + else if (r_glsl_permutation) + { + r_glsl_permutation = NULL; + qglUseProgramObjectARB(0);CHECKGLERROR + } + } +} + extern rtexture_t *r_shadow_attenuationgradienttexture; extern rtexture_t *r_shadow_attenuation2dtexture; extern rtexture_t *r_shadow_attenuation3dtexture; -int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass) +void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass) { // select a permutation of the lighting shader appropriate to this // combination of texture, entity, light source, and fogging, only use the @@ -1301,7 +1511,6 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl // fragment shader on features that are not being used unsigned int permutation = 0; shadermode_t mode = 0; - r_glsl_permutation = NULL; // TODO: implement geometry-shader based shadow volumes someday if (r_glsl_offsetmapping.integer) { @@ -1342,7 +1551,7 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl mode = SHADERMODE_FLATCOLOR; if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND; - if (rsurface.texture->currentskinframe->glow) + if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer) permutation |= SHADERPERMUTATION_GLOW; if (r_refdef.fogenabled) permutation |= SHADERPERMUTATION_FOG; @@ -1365,7 +1574,7 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl mode = SHADERMODE_LIGHTDIRECTION; if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND; - if (rsurface.texture->currentskinframe->glow) + if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer) permutation |= SHADERPERMUTATION_GLOW; permutation |= SHADERPERMUTATION_DIFFUSE; if (specularscale > 0) @@ -1385,7 +1594,7 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl mode = SHADERMODE_LIGHTDIRECTION; if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND; - if (rsurface.texture->currentskinframe->glow) + if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer) permutation |= SHADERPERMUTATION_GLOW; if (r_refdef.fogenabled) permutation |= SHADERPERMUTATION_FOG; @@ -1430,7 +1639,7 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl } if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND; - if (rsurface.texture->currentskinframe->glow) + if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer) permutation |= SHADERPERMUTATION_GLOW; if (r_refdef.fogenabled) permutation |= SHADERPERMUTATION_FOG; @@ -1441,38 +1650,7 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) permutation |= SHADERPERMUTATION_REFLECTION; } - r_glsl_permutation = &r_glsl_permutations[mode][permutation]; - if (!r_glsl_permutation->program) - { - if (!r_glsl_permutation->compiled) - R_GLSL_CompilePermutation(mode, permutation); - if (!r_glsl_permutation->program) - { - // remove features until we find a valid permutation - int i; - for (i = 0;i < SHADERPERMUTATION_COUNT;i++) - { - // reduce i more quickly whenever it would not remove any bits - int j = 1<<(SHADERPERMUTATION_COUNT-1-i); - if (!(permutation & j)) - continue; - permutation -= j; - r_glsl_permutation = &r_glsl_permutations[mode][permutation]; - if (!r_glsl_permutation->compiled) - R_GLSL_CompilePermutation(mode, permutation); - if (r_glsl_permutation->program) - break; - } - if (i >= SHADERPERMUTATION_COUNT) - { - Con_Printf("OpenGL 2.0 shaders disabled - unable to find a working shader permutation fallback on this driver (set r_glsl 1 if you want to try again)\n"); - Cvar_SetValueQuick(&r_glsl, 0); - return 0; // no bit left to clear - } - } - } - CHECKGLERROR - qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR + R_SetupShader_SetPermutation(mode, permutation); if (mode == SHADERMODE_LIGHTSOURCE) { if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]); @@ -1506,7 +1684,7 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl } 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); } @@ -1560,7 +1738,6 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl 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 - return permutation; } #define SKINFRAME_HASH 1024 @@ -1714,6 +1891,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); @@ -1834,6 +2014,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); @@ -1890,6 +2073,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); @@ -1963,6 +2149,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)); @@ -1992,6 +2179,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)); @@ -2073,10 +2261,17 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_fog_exp2); 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); Cvar_RegisterVariable(&r_water_clippingplanebias); @@ -2095,7 +2290,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); @@ -2407,10 +2601,10 @@ static void R_View_SetFrustum(void) { int i; double slopex, slopey; + vec3_t forward, left, up, origin; - // break apart the view matrix into vectors for various purposes - Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin); - VectorNegate(r_refdef.view.left, r_refdef.view.right); + // we can't trust r_refdef.view.forward and friends in reflected scenes + Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin); #if 0 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x; @@ -2478,11 +2672,11 @@ static void R_View_SetFrustum(void) { slopex = 1.0 / r_refdef.view.frustum_x; slopey = 1.0 / r_refdef.view.frustum_y; - VectorMA(r_refdef.view.forward, -slopex, r_refdef.view.left, r_refdef.view.frustum[0].normal); - VectorMA(r_refdef.view.forward, slopex, r_refdef.view.left, r_refdef.view.frustum[1].normal); - VectorMA(r_refdef.view.forward, -slopey, r_refdef.view.up , r_refdef.view.frustum[2].normal); - VectorMA(r_refdef.view.forward, slopey, r_refdef.view.up , r_refdef.view.frustum[3].normal); - VectorCopy(r_refdef.view.forward, r_refdef.view.frustum[4].normal); + VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal); + VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal); + VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal); + VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal); + VectorCopy(forward, r_refdef.view.frustum[4].normal); // Leaving those out was a mistake, those were in the old code, and they // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix @@ -2493,10 +2687,10 @@ static void R_View_SetFrustum(void) VectorNormalize(r_refdef.view.frustum[3].normal); // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling - VectorMAMAMAM(1, r_refdef.view.origin, 1024, r_refdef.view.forward, -1024 * slopex, r_refdef.view.left, -1024 * slopey, r_refdef.view.up, r_refdef.view.frustumcorner[0]); - VectorMAMAMAM(1, r_refdef.view.origin, 1024, r_refdef.view.forward, 1024 * slopex, r_refdef.view.left, -1024 * slopey, r_refdef.view.up, r_refdef.view.frustumcorner[1]); - VectorMAMAMAM(1, r_refdef.view.origin, 1024, r_refdef.view.forward, -1024 * slopex, r_refdef.view.left, 1024 * slopey, r_refdef.view.up, r_refdef.view.frustumcorner[2]); - VectorMAMAMAM(1, r_refdef.view.origin, 1024, r_refdef.view.forward, 1024 * slopex, r_refdef.view.left, 1024 * slopey, r_refdef.view.up, r_refdef.view.frustumcorner[3]); + VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]); + VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]); + VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[2]); + VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[3]); r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal); r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal); @@ -2506,11 +2700,11 @@ static void R_View_SetFrustum(void) } else { - VectorScale(r_refdef.view.left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal); - VectorScale(r_refdef.view.left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal); - VectorScale(r_refdef.view.up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal); - VectorScale(r_refdef.view.up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal); - VectorCopy(r_refdef.view.forward, r_refdef.view.frustum[4].normal); + VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal); + VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal); + VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal); + VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal); + VectorCopy(forward, r_refdef.view.frustum[4].normal); r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x; r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x; r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y; @@ -2533,27 +2727,27 @@ static void R_View_SetFrustum(void) // Quake2 has it disabled as well. // rotate R_VIEWFORWARD right by FOV_X/2 degrees - //RotatePointAroundVector( r_refdef.view.frustum[0].normal, r_refdef.view.up, r_refdef.view.forward, -(90 - r_refdef.fov_x / 2)); + //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2)); //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal); //PlaneClassify(&frustum[0]); // rotate R_VIEWFORWARD left by FOV_X/2 degrees - //RotatePointAroundVector( r_refdef.view.frustum[1].normal, r_refdef.view.up, r_refdef.view.forward, (90 - r_refdef.fov_x / 2)); + //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2)); //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal); //PlaneClassify(&frustum[1]); // rotate R_VIEWFORWARD up by FOV_X/2 degrees - //RotatePointAroundVector( r_refdef.view.frustum[2].normal, r_refdef.view.left, r_refdef.view.forward, -(90 - r_refdef.fov_y / 2)); + //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2)); //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal); //PlaneClassify(&frustum[2]); // rotate R_VIEWFORWARD down by FOV_X/2 degrees - //RotatePointAroundVector( r_refdef.view.frustum[3].normal, r_refdef.view.left, r_refdef.view.forward, (90 - r_refdef.fov_y / 2)); + //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2)); //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal); //PlaneClassify(&frustum[3]); // nearclip plane - //VectorCopy(r_refdef.view.forward, r_refdef.view.frustum[4].normal); + //VectorCopy(forward, r_refdef.view.frustum[4].normal); //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value; //PlaneClassify(&frustum[4]); } @@ -2565,18 +2759,18 @@ void R_View_Update(void) R_View_UpdateEntityVisible(); } -void R_SetupView(void) +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 (r_refdef.scene.rtworldshadows || r_refdef.scene.rtdlightshadows) 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); GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix); - if (r_refdef.view.useclipplane) + if (r_refdef.view.useclipplane && allowwaterclippingplane) { // LordHavoc: couldn't figure out how to make this approach the vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value; @@ -2589,11 +2783,6 @@ void R_SetupView(void) void R_ResetViewRendering2D(void) { - if (gl_support_fragment_shader) - { - qglUseProgramObjectARB(0);CHECKGLERROR - } - DrawQ_Finish(); // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom @@ -2618,20 +2807,16 @@ void R_ResetViewRendering2D(void) qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces + R_SetupGenericShader(true); } void R_ResetViewRendering3D(void) { - if (gl_support_fragment_shader) - { - qglUseProgramObjectARB(0);CHECKGLERROR - } - DrawQ_Finish(); // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR - R_SetupView(); + R_SetupView(true); GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height); GL_Color(1, 1, 1, 1); GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1); @@ -2651,69 +2836,9 @@ void R_ResetViewRendering3D(void) qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR GL_CullFace(r_refdef.view.cullface_back); + 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) @@ -2784,6 +2909,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); @@ -2797,6 +2923,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) @@ -2809,17 +2950,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; @@ -2895,6 +3026,8 @@ static void R_Water_ProcessPlanes(void) { // render reflected scene and copy into texture Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2); + // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems) + Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin); r_refdef.view.clipplane = p->plane; // reverse the cullface settings for this render r_refdef.view.cullface_front = GL_FRONT; @@ -2948,6 +3081,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) @@ -2965,33 +3100,16 @@ void R_Bloom_StartFrame(void) for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2); } - if (r_hdr.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)) { - screentexturewidth = screentextureheight = 0; + Cvar_SetValueQuick(&r_hdr, 0); + Cvar_SetValueQuick(&r_bloom, 0); } - else if (r_bloom.integer) - { - } - 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) @@ -3018,10 +3136,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; @@ -3030,36 +3148,33 @@ 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)); - - // 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_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, 2, polygonelements, 0, 0); r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight; @@ -3091,6 +3206,7 @@ void R_Bloom_MakeTexture(void) R_ResetViewRendering2D(); R_Mesh_VertexPointer(r_screenvertex3f, 0, 0); R_Mesh_ColorPointer(NULL, 0, 0); + R_SetupGenericShader(true); // we have a bloom image in the framebuffer CHECKGLERROR @@ -3234,7 +3350,85 @@ 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; + 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, 2, 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 @@ -3242,6 +3436,7 @@ static void R_BlendView(void) R_ResetViewRendering2D(); R_Mesh_VertexPointer(r_screenvertex3f, 0, 0); R_Mesh_ColorPointer(NULL, 0, 0); + R_SetupGenericShader(true); GL_Color(1, 1, 1, 1); GL_BlendFunc(GL_ONE, GL_ONE); R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom)); @@ -3249,11 +3444,11 @@ static void R_BlendView(void) R_Mesh_Draw(0, 4, 2, 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 @@ -3268,12 +3463,13 @@ static void R_BlendView(void) R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0); if (r_textureunits.integer >= 2 && gl_combine.integer) { - R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1); + R_SetupGenericTwoTextureShader(GL_ADD); R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen)); R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0); } else { + R_SetupGenericShader(true); R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height; // now blend on the bloom texture @@ -3290,6 +3486,7 @@ static void R_BlendView(void) R_ResetViewRendering2D(); R_Mesh_VertexPointer(r_screenvertex3f, 0, 0); R_Mesh_ColorPointer(NULL, 0, 0); + 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); @@ -3331,6 +3528,8 @@ 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); @@ -3343,17 +3542,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; } @@ -3387,28 +3586,95 @@ void R_UpdateVariables(void) r_refdef.fog_start = max(0, r_refdef.fog_start); r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end); - // R_UpdateFogColor(); // why? R_RenderScene does it anyway + // R_UpdateFogColor(); // why? R_RenderScene does it anyway + + if (r_refdef.fog_density) + { + r_refdef.fogenabled = true; + // this is the point where the fog reaches 0.9986 alpha, which we + // consider a good enough cutoff point for the texture + // (0.9986 * 256 == 255.6) + if (r_fog_exp2.integer) + r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start; + else + r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start; + r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end); + r_refdef.fograngerecip = 1.0f / r_refdef.fogrange; + r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip; + // fog color was already set + // update the fog texture + if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange) + R_BuildFogTexture(); + } + 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; +static r_refdef_scene_t r_scenes_store[ RST_COUNT ]; +/* +================ +R_SelectScene +================ +*/ +void R_SelectScene( r_refdef_scene_type_t scenetype ) { + if( scenetype != r_currentscenetype ) { + // store the old scenetype + r_scenes_store[ r_currentscenetype ] = r_refdef.scene; + r_currentscenetype = scenetype; + // move in the new scene + r_refdef.scene = r_scenes_store[ r_currentscenetype ]; + } +} - if (r_refdef.fog_density) - { - r_refdef.fogenabled = true; - // this is the point where the fog reaches 0.9986 alpha, which we - // consider a good enough cutoff point for the texture - // (0.9986 * 256 == 255.6) - if (r_fog_exp2.integer) - r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start; - else - r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start; - r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end); - r_refdef.fograngerecip = 1.0f / r_refdef.fogrange; - r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip; - // fog color was already set - // update the fog texture - if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange) - R_BuildFogTexture(); +/* +================ +R_GetScenePointer +================ +*/ +r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype ) +{ + // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function.. + if( scenetype == r_currentscenetype ) { + return &r_refdef.scene; + } else { + return &r_scenes_store[ scenetype ]; } - else - r_refdef.fogenabled = false; } /* @@ -3423,6 +3689,14 @@ void R_RenderView(void) r_refdef.view.colorscale = r_hdr_scenebrightness.value; + // break apart the view matrix into vectors for various purposes + // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong + // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc + Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin); + VectorNegate(r_refdef.view.left, r_refdef.view.right); + // make an inverted copy of the view matrix for tracking sprites + Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix); + R_Shadow_UpdateWorldLightSelection(); R_Bloom_StartFrame(); @@ -3439,6 +3713,10 @@ void R_RenderView(void) R_ClearScreen(r_refdef.fogenabled); if (r_timereport_active) R_TimeReport("viewclear"); + } else { + // 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.clear = true; @@ -3468,7 +3746,8 @@ static void R_DrawLocs(void); static void R_DrawEntityBBoxes(void); void R_RenderScene(qboolean addwaterplanes) { - Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix); + r_refdef.stats.renders++; + R_UpdateFogColor(); if (addwaterplanes) @@ -3602,10 +3881,7 @@ void R_RenderScene(qboolean addwaterplanes) R_TimeReport("explosions"); } - if (gl_support_fragment_shader) - { - qglUseProgramObjectARB(0);CHECKGLERROR - } + R_SetupGenericShader(true); VM_CL_AddPolygonsToMeshQueue(); if (r_refdef.view.showdebug) @@ -3632,18 +3908,12 @@ void R_RenderScene(qboolean addwaterplanes) } } - if (gl_support_fragment_shader) - { - qglUseProgramObjectARB(0);CHECKGLERROR - } + R_SetupGenericShader(true); R_MeshQueue_RenderTransparent(); if (r_timereport_active) R_TimeReport("drawtrans"); - if (gl_support_fragment_shader) - { - qglUseProgramObjectARB(0);CHECKGLERROR - } + R_SetupGenericShader(true); if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0)) { @@ -3655,10 +3925,7 @@ void R_RenderScene(qboolean addwaterplanes) R_TimeReport("modeldebug"); } - if (gl_support_fragment_shader) - { - qglUseProgramObjectARB(0);CHECKGLERROR - } + R_SetupGenericShader(true); if (cl.csqc_vidvars.drawworld) { @@ -3718,6 +3985,7 @@ void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, floa R_Mesh_VertexPointer(vertex3f, 0, 0); R_Mesh_ColorPointer(color4f, 0, 0); R_Mesh_ResetTextureState(); + R_SetupGenericShader(false); R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0); } @@ -3729,6 +3997,8 @@ static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtligh // this function draws bounding boxes of server entities if (!sv.active) return; + GL_CullFace(GL_NONE); + R_SetupGenericShader(false); SV_VM_Begin(); for (i = 0;i < numsurfaces;i++) { @@ -3831,6 +4101,7 @@ void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset); GL_DepthTest(!(ent->effects & EF_NODEPTHTEST)); GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back); + R_SetupGenericShader(false); R_Mesh_VertexPointer(nomodelvertex3f, 0, 0); if (r_refdef.fogenabled) { @@ -3922,6 +4193,7 @@ void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_ } else GL_CullFace(r_refdef.view.cullface_back); + GL_CullFace(GL_NONE); GL_DepthMask(false); GL_DepthRange(0, depthshort ? 0.0625 : 1); @@ -3944,6 +4216,7 @@ void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_ R_Mesh_VertexPointer(vertex3f, 0, 0); R_Mesh_ColorPointer(NULL, 0, 0); R_Mesh_ResetTextureState(); + R_SetupGenericShader(true); R_Mesh_TexBind(0, R_GetTexture(texture)); R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0); // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1 @@ -4115,6 +4388,12 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) 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; @@ -4148,7 +4427,8 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) 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]; @@ -4172,6 +4452,8 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) t->currentmaterialflags |= MATERIALFLAG_WATERSHADER; */ } + if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled) + t->currentalpha *= t->r_water_wateralpha; if(!r_waterstate.enabled) t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION); if (!(ent->flags & RENDER_LIGHT)) @@ -4194,21 +4476,18 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE; if (ent->flags & RENDER_VIEWMODEL) t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE; + if (t->backgroundnumskinframes) + t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND; if (t->currentmaterialflags & MATERIALFLAG_BLENDED) { if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER)) t->currentmaterialflags &= ~MATERIALFLAG_BLENDED; } else - { - if (t->backgroundnumskinframes) - t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND; t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER); - } - // make sure that the waterscroll matrix is used on water surfaces when // 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++) @@ -4218,7 +4497,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; @@ -4295,109 +4574,103 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) // lightmaps mode looks bad with dlights using actual texturing, so turn // off the colormap and glossmap, but leave the normalmap on as it still // accurately represents the shading involved - if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED)) + if (gl_lightmaps.integer) { - t->basetexture = r_texture_white; + t->basetexture = r_texture_grey128; + t->backgroundbasetexture = NULL; t->specularscale = 0; + 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_ONE; - blendfunc2 = GL_ZERO; - } - depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED); - if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL)) + 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)) { - rtexture_t *currentbasetexture; - int layerflags = 0; - if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED)) - layerflags |= TEXTURELAYERFLAG_FOGDARKEN; - currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base; - if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) - { - // fullbright is not affected by r_refdef.lightmapintensity - R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &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, currentbasetexture, &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, currentbasetexture, &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) - 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]); + } } } @@ -4433,23 +4706,9 @@ void R_Mesh_ResizeArrays(int newvertices) rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31; } -void RSurf_CleanUp(void) -{ - CHECKGLERROR - if (rsurface.mode == RSURFMODE_GLSL) - { - qglUseProgramObjectARB(0);CHECKGLERROR - } - GL_AlphaTest(false); - rsurface.mode = RSURFMODE_NONE; - rsurface.uselightmaptexture = false; - rsurface.texture = NULL; -} - void RSurf_ActiveWorldEntity(void) { model_t *model = r_refdef.scene.worldmodel; - RSurf_CleanUp(); if (rsurface.array_size < model->surfmesh.num_vertices) R_Mesh_ResizeArrays(model->surfmesh.num_vertices); rsurface.matrix = identitymatrix; @@ -4517,7 +4776,6 @@ void RSurf_ActiveWorldEntity(void) void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents) { model_t *model = ent->model; - RSurf_CleanUp(); if (rsurface.array_size < model->surfmesh.num_vertices) R_Mesh_ResizeArrays(model->surfmesh.num_vertices); rsurface.matrix = ent->matrix; @@ -4545,7 +4803,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) { @@ -4553,7 +4811,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) { @@ -4561,7 +4819,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 { @@ -4569,7 +4827,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; @@ -4786,7 +5044,7 @@ void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generateta v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]); v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]); #if 0 - Debug_PolygonBegin(NULL, 0, false, 0); + Debug_PolygonBegin(NULL, 0); Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1); Debug_PolygonVertex((v1[0] + v2[0]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, (v1[1] + v2[1]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1], (v1[2] + v2[2]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2], 0, 0, 1, 1, 0, 1); Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1); @@ -4813,7 +5071,7 @@ void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generateta VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start); VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end); #if 0 - Debug_PolygonBegin(NULL, 0, false, 0); + Debug_PolygonBegin(NULL, 0); Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1); Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 4, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 4, 0, 0, 0, 1, 0, 1); Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1); @@ -4834,14 +5092,14 @@ void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generateta CrossProduct(up, forward, newright); VectorNormalize(newright); #if 0 - Debug_PolygonBegin(NULL, 0, false, 0); + Debug_PolygonBegin(NULL, 0); Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 8, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 8, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 8, 0, 0, 1, 0, 0, 1); Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1); Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1); Debug_PolygonEnd(); #endif #if 0 - Debug_PolygonBegin(NULL, 0, false, 0); + Debug_PolygonBegin(NULL, 0); Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1); Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1); Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1); @@ -5539,38 +5797,19 @@ void RSurf_SetupDepthAndCulling(void) GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back); } -static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist) -{ - RSurf_SetupDepthAndCulling(); - if (rsurface.mode != RSURFMODE_SHOWSURFACES) - { - rsurface.mode = RSURFMODE_SHOWSURFACES; - GL_DepthMask(true); - GL_BlendFunc(GL_ONE, GL_ZERO); - R_Mesh_ColorPointer(NULL, 0, 0); - R_Mesh_ResetTextureState(); - } - RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist); - RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist); -} - static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist) { // transparent sky would be ridiculous if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) return; - if (rsurface.mode != RSURFMODE_SKY) - { - if (rsurface.mode == RSURFMODE_GLSL) - { - qglUseProgramObjectARB(0);CHECKGLERROR - } - rsurface.mode = RSURFMODE_SKY; - } + R_SetupGenericShader(false); if (skyrendernow) { skyrendernow = false; + // we have to force off the water clipping plane while rendering sky + R_SetupView(false); R_Sky(); + R_SetupView(true); // restore entity matrix R_Mesh_Matrix(&rsurface.matrix); } @@ -5589,6 +5828,7 @@ static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **te R_Mesh_ResetTextureState(); if (skyrendermasked) { + R_SetupDepthOrShadowShader(); // depth-only (masking) GL_ColorMask(0,0,0,0); // just to make sure that braindead drivers don't draw @@ -5597,6 +5837,7 @@ static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **te } else { + R_SetupGenericShader(false); // fog sky GL_BlendFunc(GL_ONE, GL_ZERO); } @@ -5605,20 +5846,15 @@ static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **te if (skyrendermasked) GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1); } + R_Mesh_ResetTextureState(); + GL_Color(1, 1, 1, 1); } -static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist) +static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth) { if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))) return; - if (rsurface.mode != RSURFMODE_GLSL) - { - rsurface.mode = RSURFMODE_GLSL; - R_Mesh_ResetTextureState(); - GL_Color(1, 1, 1, 1); - } - R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix); R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap)); R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture)); @@ -5631,8 +5867,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); @@ -5660,10 +5899,10 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **t R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset); RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1); } + GL_LockArrays(0, 0); GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); GL_DepthMask(false); - GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0); if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)) R_Mesh_ColorPointer(NULL, 0, 0); else @@ -5689,6 +5928,12 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **t GL_DepthMask(true); GL_AlphaTest(false); } + else + { + GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); + GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED)); + GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0); + } if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) { @@ -5704,9 +5949,10 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **t else RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); } + GL_LockArrays(0, 0); } -static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist) +static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth) { // OpenGL 1.3 path - anything not completely ancient int texturesurfaceindex; @@ -5715,8 +5961,6 @@ static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **t rmeshstate_t m; int layerindex; const texturelayer_t *layer; - if (rsurface.mode != RSURFMODE_MULTIPASS) - rsurface.mode = RSURFMODE_MULTIPASS; RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist); for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++) @@ -5733,7 +5977,7 @@ static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **t qglDepthFunc(GL_EQUAL);CHECKGLERROR } } - GL_DepthMask(layer->depthmask); + GL_DepthMask(layer->depthmask && writedepth); GL_BlendFunc(layer->blendfunc1, layer->blendfunc2); if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) { @@ -5830,7 +6074,7 @@ static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **t } } -static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist) +static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth) { // OpenGL 1.1 - crusty old voodoo path int texturesurfaceindex; @@ -5838,8 +6082,6 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **t rmeshstate_t m; int layerindex; const texturelayer_t *layer; - if (rsurface.mode != RSURFMODE_MULTIPASS) - rsurface.mode = RSURFMODE_MULTIPASS; RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist); for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++) @@ -5854,7 +6096,7 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **t qglDepthFunc(GL_EQUAL);CHECKGLERROR } } - GL_DepthMask(layer->depthmask); + GL_DepthMask(layer->depthmask && writedepth); GL_BlendFunc(layer->blendfunc1, layer->blendfunc2); R_Mesh_ColorPointer(NULL, 0, 0); applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0; @@ -5961,113 +6203,17 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **t } } -static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly) +static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth) { - if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW) - return; - rsurface.rtlight = NULL; CHECKGLERROR - if (depthonly) - { - if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST))) - return; - if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))) - return; - if (rsurface.mode != RSURFMODE_MULTIPASS) - rsurface.mode = RSURFMODE_MULTIPASS; - if (r_depthfirst.integer == 3) - { - int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces); - if (!r_refdef.view.showdebug) - GL_Color(0, 0, 0, 1); - else - GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1); - } - else - { - GL_ColorMask(0,0,0,0); - GL_Color(1,1,1,1); - } - RSurf_SetupDepthAndCulling(); - GL_DepthTest(true); - GL_BlendFunc(GL_ONE, GL_ZERO); - GL_DepthMask(true); - GL_AlphaTest(false); - R_Mesh_ColorPointer(NULL, 0, 0); - R_Mesh_ResetTextureState(); - RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist); - RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); - GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1); - } - else if (r_depthfirst.integer == 3) - return; - else if (!r_refdef.view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer)) - { - GL_Color(0, 0, 0, 1); - RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); - } - else if (r_showsurfaces.integer) - { - if (rsurface.mode != RSURFMODE_MULTIPASS) - rsurface.mode = RSURFMODE_MULTIPASS; - RSurf_SetupDepthAndCulling(); - GL_DepthTest(true); - GL_BlendFunc(GL_ONE, GL_ZERO); - GL_DepthMask(writedepth); - GL_Color(1,1,1,1); - GL_AlphaTest(false); - R_Mesh_ColorPointer(NULL, 0, 0); - R_Mesh_ResetTextureState(); - RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist); - R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist); - } - else if (gl_lightmaps.integer) - { - rmeshstate_t m; - if (rsurface.mode != RSURFMODE_MULTIPASS) - rsurface.mode = RSURFMODE_MULTIPASS; - GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1); - GL_DepthTest(true); - GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back); - GL_BlendFunc(GL_ONE, GL_ZERO); - GL_DepthMask(writedepth); - GL_Color(1,1,1,1); - GL_AlphaTest(false); - R_Mesh_ColorPointer(NULL, 0, 0); - memset(&m, 0, sizeof(m)); - m.tex[0] = R_GetTexture(r_texture_white); - m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f; - m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject; - m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset; - R_Mesh_TextureState(&m); - RSurf_PrepareVerticesForBatch(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, false, texturenumsurfaces, texturesurfacelist); - if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) - RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false); - else if (rsurface.uselightmaptexture) - RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false); - else - RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false); - } - else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) - R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist); - else if (rsurface.texture->currentnumlayers) - { - // write depth for anything we skipped on the depth-only pass earlier - if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) - writedepth = true; - RSurf_SetupDepthAndCulling(); - GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); - GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED)); - GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0); - if (r_glsl.integer && gl_support_fragment_shader) - R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist); - else if (gl_combine.integer && r_textureunits.integer >= 2) - R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist); - else - R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist); - } + RSurf_SetupDepthAndCulling(); + if (r_glsl.integer && gl_support_fragment_shader) + R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth); + else if (gl_combine.integer && r_textureunits.integer >= 2) + R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth); + else + R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth); CHECKGLERROR - GL_LockArrays(0, 0); } static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) @@ -6108,16 +6254,74 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const texturesurfacelist[texturenumsurfaces++] = surface; } // render the range of surfaces - R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false); + R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false); } + GL_AlphaTest(false); +} - RSurf_CleanUp(); +static void R_ProcessTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity) +{ + CHECKGLERROR + if (depthonly) + { + if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST))) + return; + if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))) + return; + RSurf_SetupDepthAndCulling(); + RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist); + RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); + } + else if (r_showsurfaces.integer) + { + RSurf_SetupDepthAndCulling(); + GL_DepthTest(true); + GL_BlendFunc(GL_ONE, GL_ZERO); + GL_DepthMask(true); + GL_AlphaTest(false); + R_Mesh_ColorPointer(NULL, 0, 0); + R_Mesh_ResetTextureState(); + R_SetupGenericShader(false); + RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist); + if (!r_refdef.view.showdebug) + { + GL_Color(0, 0, 0, 1); + RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); + } + else + RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist); + } + else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) + R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist); + else if (!rsurface.texture->currentnumlayers) + return; + else if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) && queueentity) + { + // transparent surfaces get pushed off into the transparent queue + int surfacelistindex; + const msurface_t *surface; + vec3_t tempcenter, center; + for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++) + { + surface = texturesurfacelist[surfacelistindex]; + tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f; + tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f; + tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f; + Matrix4x4_Transform(&rsurface.matrix, tempcenter, center); + R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight); + } + } + else + { + // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier + R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)); + } + CHECKGLERROR } void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes) { int i, j; - vec3_t tempcenter, center; texture_t *texture; // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one if (addwaterplanes) @@ -6138,33 +6342,18 @@ void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surf texture = surfacelist[i]->texture; rsurface.texture = texture->currentframe; rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL; - if (!(rsurface.texture->currentmaterialflags & flagsmask)) + if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)) { // if this texture is not the kind we want, skip ahead to the next one for (;j < numsurfaces && texture == surfacelist[j]->texture;j++) ; continue; } - if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) - { - // transparent surfaces get pushed off into the transparent queue - const msurface_t *surface = surfacelist[i]; - if (depthonly) - continue; - tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f; - tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f; - tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f; - Matrix4x4_Transform(&rsurface.matrix, tempcenter, center); - R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight); - } - else - { - // simply scan ahead until we find a different texture or lightmap state - for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++) - ; - // render the range of surfaces - R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly); - } + // simply scan ahead until we find a different texture or lightmap state + for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++) + ; + // render the range of surfaces + R_ProcessTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent); } } @@ -6206,6 +6395,7 @@ void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, in R_Mesh_VertexPointer(vertex3f, 0, 0); R_Mesh_ColorPointer(NULL, 0, 0); R_Mesh_ResetTextureState(); + R_SetupGenericShader(false); i = surfacelist[0]; GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale, @@ -6253,10 +6443,11 @@ void R_DrawDebugModel(entity_render_t *ent) 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(); + R_SetupGenericShader(false); GL_DepthRange(0, 1); GL_DepthTest(!r_showdisabledepthtest.integer); GL_DepthMask(false); @@ -6406,7 +6597,7 @@ void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean dep } 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) { @@ -6418,6 +6609,7 @@ void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean dep t = NULL; rsurface.uselightmaptexture = false; rsurface.texture = NULL; + rsurface.rtlight = NULL; numsurfacelist = 0; j = model->firstmodelsurface; endj = j + model->nummodelsurfaces; @@ -6452,7 +6644,7 @@ void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean dep r_refdef.stats.world_surfaces += numsurfacelist; if (numsurfacelist) R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes); - RSurf_CleanUp(); + GL_AlphaTest(false); } void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug) @@ -6495,7 +6687,7 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr } 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) { @@ -6507,6 +6699,7 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr t = NULL; rsurface.uselightmaptexture = false; rsurface.texture = NULL; + rsurface.rtlight = NULL; numsurfacelist = 0; surface = model->data_surfaces + model->firstmodelsurface; endsurface = surface + model->nummodelsurfaces; @@ -6532,5 +6725,5 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr r_refdef.stats.entities_surfaces += numsurfacelist; if (numsurfacelist) R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes); - RSurf_CleanUp(); + GL_AlphaTest(false); }