X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=gl_rmain.c;h=626762f51ddc91735eeaaecdf1e3ce03200cb73e;hp=4f3aeade523e7b6860a722af72163d3d3582c39d;hb=7ada10412116cc9625c5191a00fbda7f2c701b0c;hpb=88f0fcbd983dae9880e48b6bc457eabd9bd7017d diff --git a/gl_rmain.c b/gl_rmain.c index 4f3aeade..626762f5 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -92,6 +92,11 @@ cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", " cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"}; cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"}; cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"}; + +cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"}; +cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"}; +#define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit)) + cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"}; cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"}; cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"}; @@ -143,12 +148,17 @@ cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", 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_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"}; +cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"}; +cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"}; +cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"}; 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"}; cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"}; cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"}; cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"}; +cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"}; cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"}; cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"}; @@ -183,6 +193,7 @@ cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspectiv cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"}; cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"}; +cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"}; cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"}; @@ -583,7 +594,7 @@ static const char *builtinshaderstring = "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n" "#define USELIGHTMAP\n" "#endif\n" -"#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n" +"#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n" "#define USEEYEVECTOR\n" "#endif\n" "\n" @@ -743,8 +754,16 @@ static const char *builtinshaderstring = "#ifdef USESATURATION\n" " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n" " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n" -" //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n" -" gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n" +" // 'vampire sight' effect, wheres red is compensated\n" +" #ifdef SATURATION_REDCOMPENSATE\n" +" float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n" +" gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n" +" gl_FragColor.r += rboost;\n" +" #else\n" +" // normal desaturation\n" +" //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n" +" gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n" +" #endif\n" "#endif\n" "\n" "#ifdef USEGAMMARAMPS\n" @@ -790,7 +809,11 @@ static const char *builtinshaderstring = "\n" "void main(void)\n" "{\n" +"#ifdef USEVIEWTINT\n" " gl_FragColor = gl_Color;\n" +"#else\n" +" gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n" +"#endif\n" "#ifdef USEDIFFUSE\n" " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n" "#endif\n" @@ -887,7 +910,7 @@ static const char *builtinshaderstring = " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n" " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n" " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n" -" gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n" +" gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n" "}\n" "#endif\n" "#else // !MODE_REFRACTION\n" @@ -927,6 +950,10 @@ static const char *builtinshaderstring = "uniform vec4 ReflectColor;\n" "uniform float ReflectFactor;\n" "uniform float ReflectOffset;\n" +"uniform float ClientTime;\n" +"#ifdef USENORMALMAPSCROLLBLEND\n" +"uniform vec2 NormalmapScrollBlend;\n" +"#endif\n" "\n" "void main(void)\n" "{\n" @@ -934,24 +961,32 @@ static const char *builtinshaderstring = " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n" " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n" " //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n" -" vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n" +" // slight water animation via 2 layer scrolling (todo: tweak)\n" +" #ifdef USENORMALMAPSCROLLBLEND\n" +" vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n" +" normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n" +" vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n" +" #else\n" +" vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n" +" #endif\n" " // FIXME temporary hack to detect the case that the reflection\n" " // gets blackened at edges due to leaving the area that contains actual\n" " // content.\n" " // Remove this 'ack once we have a better way to stop this thing from\n" " // 'appening.\n" -" float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n" -" f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n" -" f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n" -" f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n" -" ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n" -" f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n" -" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n" -" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n" -" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n" +" float f1 = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n" +" f1 *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n" +" f1 *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n" +" f1 *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n" +" ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f1);\n" +" float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n" +" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n" +" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n" +" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n" " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\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" +" gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n" +" gl_FragColor.a = f1 + 0.5;\n" "}\n" "#endif\n" "#else // !MODE_WATER\n" @@ -1121,15 +1156,14 @@ static const char *builtinshaderstring = " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n" " return RT.xy;\n" "#else\n" -" // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n" +" // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n" " // this basically moves forward the full distance, and then backs up based\n" " // on height of samples\n" " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n" " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n" " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n" " TexCoord += OffsetVector;\n" -" OffsetVector *= 0.333;\n" -" TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n" +" OffsetVector *= 0.5;\n" " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n" " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n" " return TexCoord;\n" @@ -1643,6 +1677,7 @@ static const char *builtinshaderstring = " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n" " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n" " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n" +" lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n" " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n" " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n" " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n" @@ -1664,6 +1699,15 @@ static const char *builtinshaderstring = "\n" "\n" "\n" +"#ifdef MODE_FAKELIGHT\n" +"#define SHADING\n" +"myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n" +"myhalf3 lightcolor = myhalf3(1.0);\n" +"#endif // MODE_FAKELIGHT\n" +"\n" +"\n" +"\n" +"\n" "#ifdef MODE_LIGHTMAP\n" " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n" "#endif // MODE_LIGHTMAP\n" @@ -1796,7 +1840,7 @@ const char *builtincgshaderstring = "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n" "#define USELIGHTMAP\n" "#endif\n" -"#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n" +"#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n" "#define USEEYEVECTOR\n" "#endif\n" "\n" @@ -1832,7 +1876,7 @@ const char *builtincgshaderstring = "out float4 gl_FragColor : COLOR\n" ")\n" "{\n" -"// float3 temp = float3(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0));\n" +"// float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n" " float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n" " temp.yz -= floor(temp.yz);\n" " gl_FragColor = temp;\n" @@ -1976,8 +2020,16 @@ const char *builtincgshaderstring = "#ifdef USESATURATION\n" " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n" " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n" -" //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n" -" gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n" +" // 'vampire sight' effect, wheres red is compensated\n" +" #ifdef SATURATION_REDCOMPENSATE\n" +" float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n" +" gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n" +" gl_FragColor.r += r;\n" +" #else\n" +" // normal desaturation\n" +" //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n" +" gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n" +" #endif\n" "#endif\n" "\n" "#ifdef USEGAMMARAMPS\n" @@ -2042,7 +2094,11 @@ const char *builtincgshaderstring = "out float4 gl_FragColor : COLOR\n" ")\n" "{\n" +"#ifdef USEVIEWTINT\n" " gl_FragColor = gl_FrontColor;\n" +"#else\n" +" gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n" +"#endif\n" "#ifdef USEDIFFUSE\n" " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n" "#endif\n" @@ -2145,7 +2201,7 @@ const char *builtincgshaderstring = " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n" " //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n" " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n" -" float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.xy;\n" +" float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n" " // FIXME temporary hack to detect the case that the reflection\n" " // gets blackened at edges due to leaving the area that contains actual\n" " // content.\n" @@ -2156,7 +2212,7 @@ const char *builtincgshaderstring = " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n" " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n" " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n" -" gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n" +" gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n" "}\n" "#endif\n" "#else // !MODE_REFRACTION\n" @@ -2233,7 +2289,7 @@ const char *builtincgshaderstring = " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n" " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n" " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n" -" gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n" +" gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n" "}\n" "#endif\n" "#else // !MODE_WATER\n" @@ -3163,6 +3219,15 @@ const char *builtincgshaderstring = "\n" "\n" "\n" +"#ifdef MODE_FAKELIGHT\n" +"#define SHADING\n" +"half3 lightnormal = half3(normalize(EyeVector));\n" +"half3 lightcolor = half3(1.0,1.0,1.0);\n" +"#endif // MODE_FAKELIGHT\n" +"\n" +"\n" +"\n" +"\n" "#ifdef MODE_LIGHTMAP\n" " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n" "#endif // MODE_LIGHTMAP\n" @@ -3280,7 +3345,7 @@ typedef enum shaderpermutation_e { SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp) - SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only) + SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only), use vertex colors (generic only) SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only) SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode @@ -3292,19 +3357,19 @@ typedef enum shaderpermutation_e SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only) SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only) - SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation - SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface - SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface - SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!) - SHADERPERMUTATION_SHADOWMAP2D = 1<<18, ///< (lightsource) use shadowmap texture as light filter - SHADERPERMUTATION_SHADOWMAPPCF = 1<<19, ///< (lightsource) use percentage closer filtering on shadowmap test results - SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<20, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results - SHADERPERMUTATION_SHADOWSAMPLER = 1<<21, ///< (lightsource) use hardware shadowmap test - SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<22, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing - SHADERPERMUTATION_SHADOWMAPORTHO = 1<<23, //< (lightsource) use orthographic shadowmap projection - SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping - SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5 - SHADERPERMUTATION_REFLECTCUBE = 1<<26, ///< fake reflections using global cubemap (not HDRI light probe) + SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface + SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface + SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!) + SHADERPERMUTATION_SHADOWMAP2D = 1<<17, ///< (lightsource) use shadowmap texture as light filter + SHADERPERMUTATION_SHADOWMAPPCF = 1<<18, ///< (lightsource) use percentage closer filtering on shadowmap test results + SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<19, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results + SHADERPERMUTATION_SHADOWSAMPLER = 1<<20, ///< (lightsource) use hardware shadowmap test + SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<21, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing + SHADERPERMUTATION_SHADOWMAPORTHO = 1<<22, //< (lightsource) use orthographic shadowmap projection + SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<23, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping + SHADERPERMUTATION_ALPHAKILL = 1<<24, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5 + SHADERPERMUTATION_REFLECTCUBE = 1<<25, ///< fake reflections using global cubemap (not HDRI light probe) + SHADERPERMUTATION_NORMALMAPSCROLLBLEND = 1<<26, // (water) counter-direction normalmaps scrolling SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array } @@ -3327,7 +3392,6 @@ shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] = {"#define USEBLOOM\n", " bloom"}, {"#define USESPECULAR\n", " specular"}, {"#define USEPOSTPROCESSING\n", " postprocessing"}, - {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"}, {"#define USEREFLECTION\n", " reflection"}, {"#define USEOFFSETMAPPING\n", " offsetmapping"}, {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"}, @@ -3340,9 +3404,10 @@ shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] = {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"}, {"#define USEALPHAKILL\n", " alphakill"}, {"#define USEREFLECTCUBE\n", " reflectcube"}, + {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"}, }; -/// this enum is multiplied by SHADERPERMUTATION_MODEBASE +// this enum selects which of the glslshadermodeinfo entries should be used typedef enum shadermode_e { SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture @@ -3351,6 +3416,7 @@ typedef enum shadermode_e 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) + SHADERMODE_FAKELIGHT, ///< (fakelight) modulate texture by "fake" lighting (no lightmaps, no nothing) SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap) SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap) SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp) @@ -3373,6 +3439,7 @@ shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] = {"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"}, + {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"}, {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"}, {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"}, {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"}, @@ -3389,10 +3456,11 @@ shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] = { {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"}, {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"}, - {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth"}, + {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"}, {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"}, {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"}, {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"}, + {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"}, {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"}, {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"}, {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"}, @@ -3410,10 +3478,11 @@ shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] = { {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"}, {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"}, - {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth"}, + {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"}, {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"}, {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"}, {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"}, + {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"}, {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"}, {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"}, {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"}, @@ -3520,11 +3589,74 @@ typedef struct r_glsl_permutation_s int loc_ModelToReflectCube; int loc_ShadowMapMatrix; int loc_BloomColorSubtract; + int loc_NormalmapScrollBlend; } r_glsl_permutation_t; #define SHADERPERMUTATION_HASHSIZE 256 + +// non-degradable "lightweight" shader parameters to keep the permutations simpler +// these can NOT degrade! only use for simple stuff +enum +{ + SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation + SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation + SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled + SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled + SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled + SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5 ///< postprocess uservec4 is enabled +}; +#define SHADERSTATICPARMS_COUNT 6 + +static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT]; +static int shaderstaticparms_count = 0; + +static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0}; +#define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F)) +qboolean R_CompileShader_CheckStaticParms(void) +{ + static int r_compileshader_staticparms_save[1]; + memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms)); + memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms)); + + // detect all + if (r_glsl_saturation_redcompensate.integer) + R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE); + if (r_shadow_glossexact.integer) + R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH); + if (r_glsl_postprocess.integer) + { + if (r_glsl_postprocess_uservec1_enable.integer) + R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1); + if (r_glsl_postprocess_uservec2_enable.integer) + R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2); + if (r_glsl_postprocess_uservec3_enable.integer) + R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3); + if (r_glsl_postprocess_uservec4_enable.integer) + R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4); + } + return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0; +} + +#define R_COMPILESHADER_STATICPARM_EMIT(p, n) \ + if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \ + shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \ + else \ + shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n" +void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation) +{ + shaderstaticparms_count = 0; + + // emit all + R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE"); + R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH"); + R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1"); + R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2"); + R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3"); + R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4"); +} + /// information about each possible shader permutation r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE]; /// currently selected permutation @@ -3590,14 +3722,14 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode { int i; shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode; + char *vertexstring, *geometrystring, *fragmentstring; + char permutationname[256]; int vertstrings_count = 0; int geomstrings_count = 0; int fragstrings_count = 0; - char *vertexstring, *geometrystring, *fragmentstring; - const char *vertstrings_list[32+3]; - const char *geomstrings_list[32+3]; - const char *fragstrings_list[32+3]; - char permutationname[256]; + const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1]; + const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1]; + const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1]; if (p->compiled) return; @@ -3642,6 +3774,15 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode } } + // add static parms + R_CompileShader_AddStaticParms(mode, permutation); + memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count); + vertstrings_count += shaderstaticparms_count; + memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count); + geomstrings_count += shaderstaticparms_count; + memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count); + fragstrings_count += shaderstaticparms_count; + // now append the shader text itself vertstrings_list[vertstrings_count++] = vertexstring; geomstrings_list[geomstrings_count++] = geometrystring; @@ -3746,6 +3887,7 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode p->loc_ModelToReflectCube = qglGetUniformLocationARB(p->program, "ModelToReflectCube"); p->loc_ShadowMapMatrix = qglGetUniformLocationARB(p->program, "ShadowMapMatrix"); p->loc_BloomColorSubtract = qglGetUniformLocationARB(p->program, "BloomColorSubtract"); + p->loc_NormalmapScrollBlend = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend"); // 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); @@ -3937,6 +4079,7 @@ typedef struct r_cg_permutation_s CGparameter fp_PixelToScreenTexCoord; CGparameter fp_ModelToReflectCube; CGparameter fp_BloomColorSubtract; + CGparameter fp_NormalmapScrollBlend; } r_cg_permutation_t; @@ -4012,19 +4155,22 @@ static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, un { int i; shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode; - int vertstrings_count = 0, vertstring_length = 0; - int geomstrings_count = 0, geomstring_length = 0; - int fragstrings_count = 0, fragstring_length = 0; + int vertstring_length = 0; + int geomstring_length = 0; + int fragstring_length = 0; char *t; char *vertexstring, *geometrystring, *fragmentstring; char *vertstring, *geomstring, *fragstring; - const char *vertstrings_list[32+3]; - const char *geomstrings_list[32+3]; - const char *fragstrings_list[32+3]; char permutationname[256]; char cachename[256]; CGprofile vertexProfile; CGprofile fragmentProfile; + int vertstrings_count = 0; + int geomstrings_count = 0; + int fragstrings_count = 0; + const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1]; + const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1]; + const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1]; if (p->compiled) return; @@ -4074,6 +4220,15 @@ static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, un } } + // add static parms + R_CompileShader_AddStaticParms(mode, permutation); + memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count); + vertstrings_count += shaderstaticparms_count; + memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count); + geomstrings_count += shaderstaticparms_count; + memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count); + fragstrings_count += shaderstaticparms_count; + // replace spaces in the cachename with _ characters for (i = 0;cachename[i];i++) if (cachename[i] == ' ') @@ -4235,6 +4390,7 @@ static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, un p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord"); p->fp_ModelToReflectCube = cgGetNamedParameter(p->fprogram, "ModelToReflectCube"); p->fp_BloomColorSubtract = cgGetNamedParameter(p->fprogram, "BloomColorSubtract"); + p->fp_NormalmapScrollBlend = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend"); CHECKCGERROR } @@ -4420,7 +4576,8 @@ typedef enum D3DPSREGISTER_e D3DPSREGISTER_BloomColorSubtract = 43, D3DPSREGISTER_ViewToLight = 44, // float4x4 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4 - // next at 52 + D3DPSREGISTER_NormalmapScrollBlend = 52, + // next at 53 } D3DPSREGISTER_t; @@ -4632,17 +4789,20 @@ static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode { int i; shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode; - int vertstrings_count = 0, vertstring_length = 0; - int geomstrings_count = 0, geomstring_length = 0; - int fragstrings_count = 0, fragstring_length = 0; + int vertstring_length = 0; + int geomstring_length = 0; + int fragstring_length = 0; char *t; char *vertexstring, *geometrystring, *fragmentstring; char *vertstring, *geomstring, *fragstring; - const char *vertstrings_list[32+3]; - const char *geomstrings_list[32+3]; - const char *fragstrings_list[32+3]; char permutationname[256]; char cachename[256]; + int vertstrings_count = 0; + int geomstrings_count = 0; + int fragstrings_count = 0; + const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1]; + const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1]; + const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1]; if (p->compiled) return; @@ -4660,6 +4820,9 @@ static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode strlcat(cachename, "hlsl/", sizeof(cachename)); // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler + vertstrings_count = 0; + geomstrings_count = 0; + fragstrings_count = 0; vertstrings_list[vertstrings_count++] = "#define HLSL\n"; geomstrings_list[geomstrings_count++] = "#define HLSL\n"; fragstrings_list[fragstrings_count++] = "#define HLSL\n"; @@ -4697,6 +4860,15 @@ static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode } } + // add static parms + R_CompileShader_AddStaticParms(mode, permutation); + memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count); + vertstrings_count += shaderstaticparms_count; + memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count); + geomstrings_count += shaderstaticparms_count; + memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count); + fragstrings_count += shaderstaticparms_count; + // replace spaces in the cachename with _ characters for (i = 0;cachename[i];i++) if (cachename[i] == ' ') @@ -4978,7 +5150,7 @@ void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemod { case RENDERPATH_D3D9: #ifdef SUPPORTD3D - R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)))); + R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)))); R_Mesh_TexBind(GL20TU_FIRST , first ); R_Mesh_TexBind(GL20TU_SECOND, second); #endif @@ -4990,14 +5162,14 @@ void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemod Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); break; case RENDERPATH_GL20: - R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)))); + R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)))); R_Mesh_TexBind(GL20TU_FIRST , first ); R_Mesh_TexBind(GL20TU_SECOND, second); break; case RENDERPATH_CGGL: #ifdef SUPPORTCG CHECKCGERROR - R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)))); + R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)))); if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR #endif @@ -5215,17 +5387,27 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, { // distorted background if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER) + { mode = SHADERMODE_WATER; + if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1]) + permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION) + { mode = SHADERMODE_REFRACTION; + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } else { mode = SHADERMODE_GENERIC; permutation |= SHADERPERMUTATION_DIFFUSE; + GL_BlendFunc(GL_ONE, GL_ZERO); + allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO); } GL_AlphaTest(false); - GL_BlendFunc(GL_ONE, GL_ZERO); - allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO); } else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY) { @@ -5280,11 +5462,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, if (diffusescale > 0) permutation |= SHADERPERMUTATION_DIFFUSE; if (specularscale > 0) - { permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE; - if (r_shadow_glossexact.integer) - permutation |= SHADERPERMUTATION_EXACTSPECULARMATH; - } if (r_refdef.fogenabled) permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE); if (rsurface.texture->colormapping) @@ -5377,11 +5555,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, permutation |= SHADERPERMUTATION_GLOW; permutation |= SHADERPERMUTATION_DIFFUSE; if (specularscale > 0) - { permutation |= SHADERPERMUTATION_SPECULAR; - if (r_shadow_glossexact.integer) - permutation |= SHADERPERMUTATION_EXACTSPECULARMATH; - } if (r_refdef.fogenabled) permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE); if (rsurface.texture->colormapping) @@ -5497,7 +5671,15 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP; if (rsurface.texture->reflectmasktexture) permutation |= SHADERPERMUTATION_REFLECTCUBE; - if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping) + if (FAKELIGHT_ENABLED) + { + // fake lightmapping (q1bsp, q3bsp, fullbright map) + mode = SHADERMODE_FAKELIGHT; + permutation |= SHADERPERMUTATION_DIFFUSE; + if (specularscale > 0) + permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE; + } + else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping) { // deluxemapping (light direction texture) if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace) @@ -5506,23 +5688,15 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE; permutation |= SHADERPERMUTATION_DIFFUSE; if (specularscale > 0) - { permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE; - if (r_shadow_glossexact.integer) - permutation |= SHADERPERMUTATION_EXACTSPECULARMATH; - } } - else if (r_glsl_deluxemapping.integer >= 2) + else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture) { // fake deluxemapping (uniform light direction in tangentspace) mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE; permutation |= SHADERPERMUTATION_DIFFUSE; if (specularscale > 0) - { permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE; - if (r_shadow_glossexact.integer) - permutation |= SHADERPERMUTATION_EXACTSPECULARMATH; - } } else if (rsurface.uselightmaptexture) { @@ -5576,7 +5750,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, // additive passes are only darkened by fog, not tinted hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0); - hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f)); + hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f)); } else { @@ -5610,16 +5784,18 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor); hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]); hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]); - hlslPSSetParameter4fv(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f); - hlslPSSetParameter4fv(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f); + hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]); + hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]); hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin); hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin); - hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f)); + hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f)); + if (mode == SHADERMODE_WATER) + hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]); } hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]); hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]); hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]); - hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3]); + hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1)); hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]); if (rsurface.texture->pantstexture) hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]); @@ -5716,7 +5892,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, // additive passes are only darkened by fog, not tinted if (r_glsl_permutation->loc_FogColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0); - if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f)); + if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f)); } else { @@ -5726,12 +5902,12 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, } else if (mode == SHADERMODE_LIGHTDIRECTION) { - if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]); + if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]); if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]); if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale); if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value); if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value); - if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]); + if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]); if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]); } else @@ -5753,11 +5929,12 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor); if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]); if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]); - if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f); - if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f); + if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]); + if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]); if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin); if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin); - if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f)); + if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f)); + if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2fARB(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]); } if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);} if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);} @@ -5766,7 +5943,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]); if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]); - if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]); + if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1)); if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]); if (r_glsl_permutation->loc_Color_Pants >= 0) { @@ -5884,7 +6061,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, // additive passes are only darkened by fog, not tinted if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR - if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR + if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR } else { @@ -5922,16 +6099,17 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, if (r_cg_permutation->fp_DistortScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);CHECKCGERROR if (r_cg_permutation->fp_ScreenScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);CHECKCGERROR if (r_cg_permutation->fp_ScreenCenterRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);CHECKCGERROR - if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR - if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR + if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR + if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR - if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR + if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR + if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]); } if (r_cg_permutation->fp_ShadowMap_TextureScale) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR if (r_cg_permutation->fp_ShadowMap_Parameters) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR - if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR + if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));CHECKCGERROR if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR if (r_cg_permutation->fp_Color_Pants) { @@ -6036,11 +6214,7 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight) if (diffusescale > 0) permutation |= SHADERPERMUTATION_DIFFUSE; if (specularscale > 0) - { permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE; - if (r_shadow_glossexact.integer) - permutation |= SHADERPERMUTATION_EXACTSPECULARMATH; - } if (r_shadow_usingshadowmap2d) { permutation |= SHADERPERMUTATION_SHADOWMAP2D; @@ -6070,7 +6244,7 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight) hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range); hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]); hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]); - hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f)); + hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f)); hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]); hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height); @@ -6097,7 +6271,7 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight) if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3fARB( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range); if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB( r_glsl_permutation->loc_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]); if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4fARB( r_glsl_permutation->loc_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]); - if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB( r_glsl_permutation->loc_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f)); + if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB( r_glsl_permutation->loc_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f)); if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2fARB( r_glsl_permutation->loc_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]); if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height); @@ -6118,7 +6292,7 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight) if (r_cg_permutation->fp_DeferredColor_Specular ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);CHECKCGERROR if (r_cg_permutation->fp_ShadowMap_TextureScale ) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR if (r_cg_permutation->fp_ShadowMap_Parameters ) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR - if (r_cg_permutation->fp_SpecularPower ) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR + if (r_cg_permutation->fp_SpecularPower ) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR if (r_cg_permutation->fp_ScreenToDepth ) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR if (r_cg_permutation->fp_PixelToScreenTexCoord ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR @@ -7196,6 +7370,8 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_fullbrights); Cvar_RegisterVariable(&r_wateralpha); Cvar_RegisterVariable(&r_dynamic); + Cvar_RegisterVariable(&r_fakelight); + Cvar_RegisterVariable(&r_fakelight_intensity); Cvar_RegisterVariable(&r_fullbright); Cvar_RegisterVariable(&r_shadows); Cvar_RegisterVariable(&r_shadows_darken); @@ -7232,11 +7408,17 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_glsl_postprocess_uservec2); Cvar_RegisterVariable(&r_glsl_postprocess_uservec3); Cvar_RegisterVariable(&r_glsl_postprocess_uservec4); + Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable); + Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable); + Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable); + Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable); + Cvar_RegisterVariable(&r_water); Cvar_RegisterVariable(&r_water_resolutionmultiplier); Cvar_RegisterVariable(&r_water_clippingplanebias); Cvar_RegisterVariable(&r_water_refractdistort); Cvar_RegisterVariable(&r_water_reflectdistort); + Cvar_RegisterVariable(&r_water_scissormode); Cvar_RegisterVariable(&r_lerpsprites); Cvar_RegisterVariable(&r_lerpmodels); Cvar_RegisterVariable(&r_lerplightstyles); @@ -7257,6 +7439,7 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&gl_lightmaps); Cvar_RegisterVariable(&r_test); Cvar_RegisterVariable(&r_glsl_saturation); + Cvar_RegisterVariable(&r_glsl_saturation_redcompensate); Cvar_RegisterVariable(&r_framedatasize); if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE) Cvar_SetValue("r_fullbrights", 0); @@ -7720,7 +7903,18 @@ static void R_View_UpdateEntityLighting (void) { vec3_t org; Matrix4x4_OriginFromMatrix(&ent->matrix, org); - r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal); + + // complete lightning for lit sprites + // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)? + if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT)) + { + if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites + org[2] = org[2] + r_overheadsprites_pushback.value; + R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT); + } + else + r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal); + if(ent->flags & RENDER_EQUALIZE) { // first fix up ambient lighting... @@ -7958,11 +8152,38 @@ static void R_DrawModelsAddWaterPlanes(void) } } -static void R_View_SetFrustum(void) +static void R_View_SetFrustum(const int *scissor) { int i; - double slopex, slopey; - vec3_t forward, left, up, origin; + double fpx = +1, fnx = -1, fpy = +1, fny = -1; + vec3_t forward, left, up, origin, v; + + if(scissor) + { + // flipped x coordinates (because x points left here) + fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width); + fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width); + + // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one + switch(vid.renderpath) + { + case RENDERPATH_D3D9: + case RENDERPATH_D3D10: + case RENDERPATH_D3D11: + // non-flipped y coordinates + fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height); + fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height); + break; + case RENDERPATH_GL11: + case RENDERPATH_GL13: + case RENDERPATH_GL20: + case RENDERPATH_CGGL: + // non-flipped y coordinates + fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height); + fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height); + break; + } + } // we can't trust r_refdef.view.forward and friends in reflected scenes Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin); @@ -8031,13 +8252,29 @@ static void R_View_SetFrustum(void) if (r_refdef.view.useperspective) { - slopex = 1.0 / r_refdef.view.frustum_x; - slopey = 1.0 / r_refdef.view.frustum_y; - 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); + // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling + VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]); + VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]); + VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]); + VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]); + + // then the normals from the corners relative to origin + CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal); + CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal); + CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal); + CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal); + + // in a NORMAL view, forward cross left == up + // in a REFLECTED view, forward cross left == down + // so our cross products above need to be adjusted for a left handed coordinate system + CrossProduct(forward, left, v); + if(DotProduct(v, up) < 0) + { + VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal); + VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal); + VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal); + VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].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 @@ -8047,11 +8284,14 @@ static void R_View_SetFrustum(void) VectorNormalize(r_refdef.view.frustum[2].normal); 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, forward, -1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]); - VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]); - VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left, 1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]); - VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * r_refdef.view.frustum_x, left, 1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]); + // make the corners absolute + VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]); + VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]); + VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]); + VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]); + + // one more 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.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal); @@ -8113,10 +8353,19 @@ static void R_View_SetFrustum(void) //PlaneClassify(&frustum[4]); } +void R_View_UpdateWithScissor(const int *myscissor) +{ + R_Main_ResizeViewCache(); + R_View_SetFrustum(myscissor); + R_View_WorldVisibility(r_refdef.view.useclipplane); + R_View_UpdateEntityVisible(); + R_View_UpdateEntityLighting(); +} + void R_View_Update(void) { R_Main_ResizeViewCache(); - R_View_SetFrustum(); + R_View_SetFrustum(NULL); R_View_WorldVisibility(r_refdef.view.useclipplane); R_View_UpdateEntityVisible(); R_View_UpdateEntityLighting(); @@ -8431,6 +8680,18 @@ void R_Water_AddWaterPlane(msurface_t *surface, int entno) p->materialflags = 0; p->pvsvalid = false; p->camera_entity = t->camera_entity; + VectorCopy(surface->mins, p->mins); + VectorCopy(surface->maxs, p->maxs); + } + else + { + // merge mins/maxs + p->mins[0] = min(p->mins[0], surface->mins[0]); + p->mins[1] = min(p->mins[1], surface->mins[1]); + p->mins[2] = min(p->mins[2], surface->mins[2]); + p->maxs[0] = max(p->maxs[0], surface->maxs[0]); + p->maxs[1] = max(p->maxs[1], surface->maxs[1]); + p->maxs[2] = max(p->maxs[2], surface->maxs[2]); } // merge this surface's materialflags into the waterplane p->materialflags |= t->currentmaterialflags; @@ -8449,6 +8710,7 @@ void R_Water_AddWaterPlane(msurface_t *surface, int entno) static void R_Water_ProcessPlanes(void) { + int myscissor[4]; r_refdef_view_t originalview; r_refdef_view_t myview; int planeindex; @@ -8497,11 +8759,19 @@ static void R_Water_ProcessPlanes(void) if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) { r_refdef.view = myview; + if(r_water_scissormode.integer) + { + R_SetupView(true); + if(R_ScissorForBBox(p->mins, p->maxs, myscissor)) + continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible + } + // 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; r_refdef.view.cullface_back = GL_BACK; @@ -8516,7 +8786,12 @@ static void R_Water_ProcessPlanes(void) R_ResetViewRendering3D(); R_ClearScreen(r_refdef.fogenabled); - R_View_Update(); + if(r_water_scissormode.integer & 2) + R_View_UpdateWithScissor(myscissor); + else + R_View_Update(); + if(r_water_scissormode.integer & 1) + GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]); R_RenderScene(); R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height); @@ -8526,8 +8801,15 @@ static void R_Water_ProcessPlanes(void) // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted) if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) { - r_waterstate.renderingrefraction = true; r_refdef.view = myview; + if(r_water_scissormode.integer) + { + R_SetupView(true); + if(R_ScissorForBBox(p->mins, p->maxs, myscissor)) + continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible + } + + r_waterstate.renderingrefraction = true; r_refdef.view.clipplane = p->plane; VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal); @@ -8550,7 +8832,12 @@ static void R_Water_ProcessPlanes(void) R_ResetViewRendering3D(); R_ClearScreen(r_refdef.fogenabled); - R_View_Update(); + if(r_water_scissormode.integer & 2) + R_View_UpdateWithScissor(myscissor); + else + R_View_Update(); + if(r_water_scissormode.integer & 1) + GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]); R_RenderScene(); R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height); @@ -8575,6 +8862,9 @@ static void R_Water_ProcessPlanes(void) CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin); } + // note: all of the view is used for displaying... so + // there is no use in scissoring + // reverse the cullface settings for this render r_refdef.view.cullface_front = GL_FRONT; r_refdef.view.cullface_back = GL_BACK; @@ -8878,13 +9168,18 @@ void R_HDR_RenderBloomTexture(void) { int oldwidth, oldheight; float oldcolorscale; + int oldwaterstate; + oldwaterstate = r_waterstate.enabled; oldcolorscale = r_refdef.view.colorscale; oldwidth = r_refdef.view.width; oldheight = r_refdef.view.height; r_refdef.view.width = r_bloomstate.bloomwidth; r_refdef.view.height = r_bloomstate.bloomheight; + if(r_hdr.integer < 2) + r_waterstate.enabled = false; + // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance. // TODO: add exposure compensation features // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object) @@ -8904,7 +9199,7 @@ void R_HDR_RenderBloomTexture(void) // only do secondary renders with HDR if r_hdr is 2 or higher r_waterstate.numwaterplanes = 0; - if (r_waterstate.enabled && r_hdr.integer >= 2) + if (r_waterstate.enabled) R_RenderWaterPlanes(); r_refdef.view.showdebug = true; @@ -8917,6 +9212,7 @@ void R_HDR_RenderBloomTexture(void) R_Bloom_MakeTexture(); // restore the view settings + r_waterstate.enabled = oldwaterstate; r_refdef.view.width = oldwidth; r_refdef.view.height = oldheight; r_refdef.view.colorscale = oldcolorscale; @@ -9040,10 +9336,14 @@ static void R_BlendView(void) #define sscanf sscanf_s #endif memset(uservecs, 0, sizeof(uservecs)); - sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]); - sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]); - sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]); - sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]); + if (r_glsl_postprocess_uservec1_enable.integer) + sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]); + if (r_glsl_postprocess_uservec2_enable.integer) + sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]); + if (r_glsl_postprocess_uservec3_enable.integer) + sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]); + if (r_glsl_postprocess_uservec4_enable.integer) + sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]); R_ResetViewRendering2D(); GL_Color(1, 1, 1, 1); @@ -9179,9 +9479,13 @@ void R_UpdateVariables(void) r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0; r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil; - r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer; + r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer; r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil; r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1; + if (FAKELIGHT_ENABLED) + { + r_refdef.lightmapintensity *= r_fakelight_intensity.value; + } if (r_showsurfaces.integer) { r_refdef.scene.rtworld = false; @@ -9339,17 +9643,28 @@ R_RenderView */ void R_RenderView(void) { + matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix; if (r_timereport_active) R_TimeReport("start"); r_textureframe++; // used only by R_GetCurrentTexture rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity + if(R_CompileShader_CheckStaticParms()) + R_GLSL_Restart_f(); + if (!r_drawentities.integer) r_refdef.scene.numentities = 0; R_AnimCache_ClearCache(); R_FrameData_NewFrame(); + /* adjust for stereo display */ + if(R_Stereo_Active()) + { + Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_separation.value * (0.5f - r_stereo_side), 0, 0, r_stereo_angle.value * (0.5f - r_stereo_side), 0, 1); + Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix); + } + if (r_refdef.view.isoverlay) { // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas] @@ -9363,12 +9678,17 @@ void R_RenderView(void) R_RenderScene(); + r_refdef.view.matrix = originalmatrix; + CHECKGLERROR return; } if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/) + { + r_refdef.view.matrix = originalmatrix; return; //Host_Error ("R_RenderView: NULL worldmodel"); + } r_refdef.view.colorscale = r_hdr_scenebrightness.value; @@ -9420,6 +9740,9 @@ void R_RenderView(void) GL_Scissor(0, 0, vid.width, vid.height); GL_ScissorTest(false); + + r_refdef.view.matrix = originalmatrix; + CHECKGLERROR } @@ -9671,6 +9994,27 @@ void R_RenderScene(void) R_TimeReport("coronas"); } +#if 0 + { + GL_DepthTest(false); + qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + GL_Color(1, 1, 1, 1); + qglBegin(GL_POLYGON); + qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]); + qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]); + qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]); + qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]); + qglEnd(); + qglBegin(GL_POLYGON); + qglVertex3f(r_refdef.view.frustumcorner[0][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[0][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[0][2] + 1000 * r_refdef.view.forward[2]); + qglVertex3f(r_refdef.view.frustumcorner[1][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[1][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[1][2] + 1000 * r_refdef.view.forward[2]); + qglVertex3f(r_refdef.view.frustumcorner[3][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[3][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[3][2] + 1000 * r_refdef.view.forward[2]); + qglVertex3f(r_refdef.view.frustumcorner[2][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[2][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[2][2] + 1000 * r_refdef.view.forward[2]); + qglEnd(); + qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } +#endif + // don't let sound skip if going slow if (r_refdef.scene.extraupdate) S_ExtraUpdate (); @@ -9699,7 +10043,7 @@ void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, floa GL_DepthMask(false); GL_DepthRange(0, 1); GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset); - R_Mesh_ResetTextureState(); +// R_Mesh_ResetTextureState(); vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; // vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2]; @@ -9869,7 +10213,6 @@ void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset); GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST)); GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back); - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); memcpy(color4f, nomodelcolor4f, sizeof(float[6*4])); for (i = 0, c = color4f;i < 6;i++, c += 4) { @@ -9889,7 +10232,8 @@ void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2); } } - R_Mesh_ResetTextureState(); +// R_Mesh_ResetTextureState(); + R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL); R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0); } @@ -10255,23 +10599,27 @@ texture_t *R_GetCurrentTexture(texture_t *t) R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin); t->currentskinframe = r_qwskincache[i].skinframe; if (t->currentskinframe == NULL) - t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes]; + t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes]; } else if (t->numskinframes >= 2) - t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes]; + t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes]; if (t->backgroundnumskinframes >= 2) - t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes]; + t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes]; t->currentmaterialflags = t->basematerialflags; t->currentalpha = rsurface.colormod[3]; if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer)) t->currentalpha *= r_wateralpha.value; if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) - t->currentalpha *= t->r_water_wateralpha; + t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later if(!r_waterstate.enabled || r_refdef.view.isoverlay) t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA); if (!(rsurface.ent_flags & RENDER_LIGHT)) t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT; + else if (FAKELIGHT_ENABLED) + { + // no modellight if using fakelight for the map + } else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) { // pick a model lighting mode @@ -10542,6 +10890,7 @@ void R_Mesh_ResizeArrays(int newvertices) void RSurf_ActiveWorldEntity(void) { + int newvertices; dp_model_t *model = r_refdef.scene.worldmodel; //if (rsurface.entity == r_refdef.scene.worldentity) // return; @@ -10552,8 +10901,9 @@ void RSurf_ActiveWorldEntity(void) rsurface.ent_qwskin = -1; rsurface.ent_shadertime = 0; rsurface.ent_flags = r_refdef.scene.worldentity->flags; - if (rsurface.array_size < model->surfmesh.num_vertices) - R_Mesh_ResizeArrays(model->surfmesh.num_vertices); + newvertices = max(model->surfmesh.num_vertices, model->surfmesh.num_triangles); + if (rsurface.array_size < newvertices) + R_Mesh_ResizeArrays(newvertices); rsurface.matrix = identitymatrix; rsurface.inversematrix = identitymatrix; rsurface.matrixscale = 1; @@ -10657,6 +11007,7 @@ void RSurf_ActiveWorldEntity(void) void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass) { + int newvertices; dp_model_t *model = ent->model; //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents))) // return; @@ -10667,8 +11018,9 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q rsurface.ent_qwskin = (ent->entitynumber <= cl.maxclients && ent->entitynumber >= 1 && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[ent->entitynumber - 1].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) ? (ent->entitynumber - 1) : -1; rsurface.ent_shadertime = ent->shadertime; rsurface.ent_flags = ent->flags; - if (rsurface.array_size < model->surfmesh.num_vertices) - R_Mesh_ResizeArrays(model->surfmesh.num_vertices); + newvertices = max(model->surfmesh.num_vertices, model->surfmesh.num_triangles); + if (rsurface.array_size < newvertices) + R_Mesh_ResizeArrays(newvertices); rsurface.matrix = ent->matrix; rsurface.inversematrix = ent->inversematrix; rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix); @@ -10838,7 +11190,7 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, int entflags, double shadertime, float r, float g, float b, float a, int numvertices, const float *vertex3f, const float *texcoord2f, const float *normal3f, const float *svector3f, const float *tvector3f, const float *color4f, int numtriangles, const int *element3i, const unsigned short *element3s, qboolean wantnormals, qboolean wanttangents) { - int i; + int newvertices; rsurface.entity = r_refdef.scene.worldentity; rsurface.skeleton = NULL; @@ -10848,8 +11200,9 @@ void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inve rsurface.ent_flags = entflags; rsurface.modelnumvertices = numvertices; rsurface.modelnumtriangles = numtriangles; - if (rsurface.array_size < rsurface.modelnumvertices) - R_Mesh_ResizeArrays(rsurface.modelnumvertices); + newvertices = max(rsurface.modelnumvertices, rsurface.modelnumtriangles); + if (rsurface.array_size < newvertices) + R_Mesh_ResizeArrays(newvertices); rsurface.matrix = *matrix; rsurface.inversematrix = *inversematrix; rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix); @@ -10978,25 +11331,6 @@ void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inve rsurface.modeltvector3f = rsurface.array_modeltvector3f; } } - - // now convert arrays into vertexmesh structs - for (i = 0;i < numvertices;i++) - { - VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f); - VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f); - if (rsurface.modelsvector3f) - VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f); - if (rsurface.modeltvector3f) - VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f); - if (rsurface.modelnormal3f) - VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f); - if (rsurface.modellightmapcolor4f) - Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub); - if (rsurface.modeltexcoordtexture2f) - Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f); - if (rsurface.modeltexcoordlightmap2f) - Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f); - } } float RSurf_FogPoint(const float *v) @@ -11088,8 +11422,6 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const endvertex = surfaceendvertex; numtriangles += surfacenumtriangles; } - if (!numtriangles) - return; // we now know the vertex range used, and if there are any gaps in it rsurface.batchfirstvertex = firstvertex; @@ -11533,8 +11865,8 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const } } // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check - Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true); - Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true); + Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, r_smoothnormals_areaweighting.integer != 0); + Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, r_smoothnormals_areaweighting.integer != 0); rsurface.batchvertex3f = rsurface.array_batchvertex3f; rsurface.batchvertex3f_vertexbuffer = NULL; rsurface.batchvertex3f_bufferoffset = 0; @@ -11638,14 +11970,14 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const rsurface.batchvertex3f_bufferoffset = 0; if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL { - Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true); + Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, r_smoothnormals_areaweighting.integer != 0); rsurface.batchnormal3f = rsurface.array_batchnormal3f; rsurface.batchnormal3f_vertexbuffer = NULL; rsurface.batchnormal3f_bufferoffset = 0; } if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL { - Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true); + Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, r_smoothnormals_areaweighting.integer != 0); rsurface.batchsvector3f = rsurface.array_batchsvector3f; rsurface.batchsvector3f_vertexbuffer = NULL; rsurface.batchsvector3f_bufferoffset = 0; @@ -11671,7 +12003,7 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const rsurface.batchnormal3f_bufferoffset = 0; if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL { - Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true); + Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, r_smoothnormals_areaweighting.integer != 0); rsurface.batchsvector3f = rsurface.array_batchsvector3f; rsurface.batchsvector3f_vertexbuffer = NULL; rsurface.batchsvector3f_bufferoffset = 0; @@ -11702,7 +12034,7 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j); } // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check - Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true); + Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, r_smoothnormals_areaweighting.integer != 0); rsurface.batchvertex3f = rsurface.array_batchvertex3f; rsurface.batchvertex3f_vertexbuffer = NULL; rsurface.batchvertex3f_bufferoffset = 0; @@ -11711,7 +12043,7 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const rsurface.batchnormal3f_bufferoffset = 0; if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL { - Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true); + Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, r_smoothnormals_areaweighting.integer != 0); rsurface.batchsvector3f = rsurface.array_batchsvector3f; rsurface.batchsvector3f_vertexbuffer = NULL; rsurface.batchsvector3f_bufferoffset = 0; @@ -11728,7 +12060,7 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j); } // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check - Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true); + Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, r_smoothnormals_areaweighting.integer != 0); rsurface.batchvertex3f = rsurface.array_batchvertex3f; rsurface.batchvertex3f_vertexbuffer = NULL; rsurface.batchvertex3f_bufferoffset = 0; @@ -11737,7 +12069,7 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const rsurface.batchnormal3f_bufferoffset = 0; if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL { - Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true); + Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, r_smoothnormals_areaweighting.integer != 0); rsurface.batchsvector3f = rsurface.array_batchsvector3f; rsurface.batchsvector3f_vertexbuffer = NULL; rsurface.batchsvector3f_bufferoffset = 0; @@ -11880,6 +12212,36 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const void RSurf_DrawBatch(void) { + // sometimes a zero triangle surface (usually a degenerate patch) makes it + // through the pipeline, killing it earlier in the pipeline would have + // per-surface overhead rather than per-batch overhead, so it's best to + // reject it here, before it hits glDraw. + if (rsurface.batchnumtriangles == 0) + return; +#if 0 + // batch debugging code + if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f) + { + int i; + int j; + int c; + const int *e; + e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3; + for (i = 0;i < rsurface.batchnumtriangles*3;i++) + { + c = e[i]; + for (j = 0;j < rsurface.entity->model->num_surfaces;j++) + { + if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices)) + { + if (rsurface.modelsurfaces[j].texture != rsurface.texture) + Sys_Error("RSurf_DrawBatch: index %i uses different texture (%s) than surface %i which it belongs to (which uses %s)\n", c, rsurface.texture->name, j, rsurface.modelsurfaces[j].texture->name); + break; + } + } + } + } +#endif R_Mesh_Draw(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchfirsttriangle, rsurface.batchnumtriangles, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset); } @@ -11891,13 +12253,20 @@ static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface) vec3_t vert; const float *v; r_waterstate_waterplane_t *p; + qboolean prepared = false; bestd = 0; for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++) { if(p->camera_entity != rsurface.texture->camera_entity) continue; d = 0; - RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface); + if(!prepared) + { + RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface); + prepared = true; + if(rsurface.batchnumvertices == 0) + break; + } for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3) { Matrix4x4_Transform(&rsurface.matrix, v, vert); @@ -11910,6 +12279,10 @@ static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface) } } return bestplaneindex; + // NOTE: this MAY return a totally unrelated water plane; we can ignore + // this situation though, as it might be better to render single larger + // batches with useless stuff (backface culled for example) than to + // render multiple smaller batches } static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void) @@ -12074,6 +12447,40 @@ static void RSurf_DrawBatch_GL11_ClampColor(void) } } +static void RSurf_DrawBatch_GL11_ApplyFakeLight(void) +{ + int i; + float f; + const float *v; + const float *n; + float *c; + //vec3_t eyedir; + + // fake shading + for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4) + { + f = -DotProduct(r_refdef.view.forward, n); + f = max(0, f); + f = f * 0.85 + 0.15; // work around so stuff won't get black + f *= r_refdef.lightmapintensity; + Vector4Set(c, f, f, f, 1); + } + + rsurface.passcolor4f = rsurface.array_passcolor4f; + rsurface.passcolor4f_vertexbuffer = 0; + rsurface.passcolor4f_bufferoffset = 0; +} + +static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog) +{ + RSurf_DrawBatch_GL11_ApplyFakeLight(); + if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(); + if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a); + R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset); + GL_Color(r, g, b, a); + RSurf_DrawBatch(); +} + static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor) { int i; @@ -12228,16 +12635,23 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface // bind lightmap texture // water/refraction/reflection/camera surfaces have to be handled specially - if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene) + if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION))) { int start, end, startplaneindex; for (start = 0;start < texturenumsurfaces;start = end) { startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]); + if(startplaneindex < 0) + { + // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this. + // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags); + end = start + 1; + continue; + } for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++) ; // now that we have a batch using the same planeindex, render it - if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene) + if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA))) { // render water or distortion background GL_DepthMask(true); @@ -12248,7 +12662,7 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL); RSurf_DrawBatch(); } - else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene) + else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)) { // render surface with reflection texture as input GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED)); @@ -12324,6 +12738,8 @@ static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset); if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog); + else if (FAKELIGHT_ENABLED) + RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog); else if (rsurface.uselightmaptexture) RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog); else @@ -12409,6 +12825,8 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset); if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false); + else if (FAKELIGHT_ENABLED) + RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false); else if (rsurface.uselightmaptexture) RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false); else @@ -12480,7 +12898,7 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const float c[4]; GL_AlphaTest(false); - R_Mesh_ResetTextureState(); +// R_Mesh_ResetTextureState(); R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); if(rsurface.texture && rsurface.texture->currentskinframe) @@ -12560,6 +12978,14 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor); r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all } + else if (FAKELIGHT_ENABLED) + { + RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist); + + r_refdef.lightmapintensity = r_fakelight_intensity.value; + RSurf_DrawBatch_GL11_ApplyFakeLight(); + r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all + } else { RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist); @@ -12776,7 +13202,7 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const GL_BlendFunc(GL_ONE, GL_ZERO); GL_DepthMask(true); GL_AlphaTest(false); - R_Mesh_ResetTextureState(); +// R_Mesh_ResetTextureState(); R_SetupShader_DepthOrShadow(); } RSurf_SetupDepthAndCulling(); @@ -12794,19 +13220,35 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const surface = rsurface.modelsurfaces + surfacelist[i]; texture = surface->texture; rsurface.texture = R_GetCurrentTexture(texture); - rsurface.lightmaptexture = surface->lightmaptexture; - rsurface.deluxemaptexture = surface->deluxemaptexture; - rsurface.uselightmaptexture = surface->lightmaptexture != NULL; // scan ahead until we find a different texture endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces); texturenumsurfaces = 0; texturesurfacelist[texturenumsurfaces++] = surface; - for (;j < endsurface;j++) + if(FAKELIGHT_ENABLED) { - surface = rsurface.modelsurfaces + surfacelist[j]; - if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture) - break; - texturesurfacelist[texturenumsurfaces++] = surface; + rsurface.lightmaptexture = NULL; + rsurface.deluxemaptexture = NULL; + rsurface.uselightmaptexture = false; + for (;j < endsurface;j++) + { + surface = rsurface.modelsurfaces + surfacelist[j]; + if (texture != surface->texture) + break; + texturesurfacelist[texturenumsurfaces++] = surface; + } + } + else + { + rsurface.lightmaptexture = surface->lightmaptexture; + rsurface.deluxemaptexture = surface->deluxemaptexture; + rsurface.uselightmaptexture = surface->lightmaptexture != NULL; + for (;j < endsurface;j++) + { + surface = rsurface.modelsurfaces + surfacelist[j]; + if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture) + break; + texturesurfacelist[texturenumsurfaces++] = surface; + } } // render the range of surfaces if (ent == r_refdef.scene.worldentity) @@ -12900,9 +13342,6 @@ void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, in // use skin 1 instead) texture = surfacelist[i]->texture; rsurface.texture = R_GetCurrentTexture(texture); - rsurface.lightmaptexture = surfacelist[i]->lightmaptexture; - rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture; - rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass; 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 @@ -12910,9 +13349,24 @@ void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, in ; continue; } - // simply scan ahead until we find a different texture or lightmap state - for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++) - ; + if(FAKELIGHT_ENABLED || depthonly || prepass) + { + rsurface.lightmaptexture = NULL; + rsurface.deluxemaptexture = NULL; + rsurface.uselightmaptexture = false; + // simply scan ahead until we find a different texture or lightmap state + for (;j < numsurfaces && texture == surfacelist[j]->texture;j++) + ; + } + else + { + rsurface.lightmaptexture = surfacelist[i]->lightmaptexture; + rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture; + rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL; + // simply scan ahead until we find a different texture or lightmap state + for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++) + ; + } // render the range of surfaces R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass); } @@ -12964,9 +13418,6 @@ void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurfa // use skin 1 instead) texture = surfacelist[i]->texture; rsurface.texture = R_GetCurrentTexture(texture); - rsurface.lightmaptexture = surfacelist[i]->lightmaptexture; - rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture; - rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass; 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 @@ -12974,9 +13425,24 @@ void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurfa ; continue; } - // simply scan ahead until we find a different texture or lightmap state - for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++) - ; + if(FAKELIGHT_ENABLED || depthonly || prepass) + { + rsurface.lightmaptexture = NULL; + rsurface.deluxemaptexture = NULL; + rsurface.uselightmaptexture = false; + // simply scan ahead until we find a different texture or lightmap state + for (;j < numsurfaces && texture == surfacelist[j]->texture;j++) + ; + } + else + { + rsurface.lightmaptexture = surfacelist[i]->lightmaptexture; + rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture; + rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL; + // simply scan ahead until we find a different texture or lightmap state + for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++) + ; + } // render the range of surfaces R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass); } @@ -13017,7 +13483,7 @@ void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, in GL_CullFace(GL_NONE); R_EntityMatrix(&identitymatrix); - R_Mesh_ResetTextureState(); +// R_Mesh_ResetTextureState(); i = surfacelist[0]; GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale, @@ -13608,9 +14074,9 @@ static void R_DrawModelDecals_Entity(entity_render_t *ent) if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles) { e = rsurface.modelelement3i + 3*decal->triangleindex; - VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f); - VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3); - VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6); + VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f); + VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3); + VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6); } else { @@ -13642,7 +14108,7 @@ static void R_DrawModelDecals_Entity(entity_render_t *ent) // now render the decals all at once // (this assumes they all use one particle font texture!) RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, rsurface.ent_shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false); - R_Mesh_ResetTextureState(); +// R_Mesh_ResetTextureState(); R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f); GL_DepthMask(false); GL_DepthRange(0, 1); @@ -13720,7 +14186,7 @@ void R_DrawDebugModel(void) flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL; - R_Mesh_ResetTextureState(); +// R_Mesh_ResetTextureState(); R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); GL_DepthRange(0, 1); GL_DepthTest(!r_showdisabledepthtest.integer); @@ -14143,7 +14609,6 @@ void R_DrawCustomSurface_Texture(texture_t *texture, const matrix4x4_t *texmatri const msurface_t *surfacelist = &surface; // fake enough texture and surface state to render this geometry - surface.texture = texture; surface.num_triangles = numtriangles; surface.num_firsttriangle = firsttriangle;