cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
+cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
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)"};
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"};
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)"};
}
else
{
- r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, -1, NULL);
- //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
+ r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
+ //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
}
}
"#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"
"#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"
" 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"
"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"
" //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"
" 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"
"\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"
"#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"
"#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) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
-" gl_FragColor.rgb = lerp(float3(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"
" 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"
" 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"
"\n"
"\n"
"\n"
+"#ifdef MODE_FAKELIGHT\n"
+"#define SHADING\n"
+"half3 lightnormal = half3(normalize(EyeVector));\n"
+"half3 lightcolor = half3(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)) * Color_Diffuse);\n"
"#endif // MODE_LIGHTMAP\n"
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_SHADOWMAPRECT = 1<<18, ///< (lightsource) use shadowmap rectangle texture as light filter
- SHADERPERMUTATION_SHADOWMAPCUBE = 1<<19, ///< (lightsource) use shadowmap cubemap texture as light filter
- SHADERPERMUTATION_SHADOWMAP2D = 1<<20, ///< (lightsource) use shadowmap rectangle texture as light filter
- SHADERPERMUTATION_SHADOWMAPPCF = 1<<21, ///< (lightsource) use percentage closer filtering on shadowmap test results
- SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<22, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
- SHADERPERMUTATION_SHADOWSAMPLER = 1<<23, ///< (lightsource) use hardware shadowmap test
- SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<24, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
- SHADERPERMUTATION_SHADOWMAPORTHO = 1<<25, //< (lightsource) use orthographic shadowmap projection
- SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<26, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
- SHADERPERMUTATION_ALPHAKILL = 1<<27, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
- SHADERPERMUTATION_REFLECTCUBE = 1<<28, ///< 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_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
+ SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
+ SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
+ SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
+ SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
+ SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
+ SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
+ SHADERPERMUTATION_SHADOWMAPORTHO = 1<<24, //< (lightsource) use orthographic shadowmap projection
+ SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<25, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
+ SHADERPERMUTATION_ALPHAKILL = 1<<26, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
+ SHADERPERMUTATION_REFLECTCUBE = 1<<27, ///< fake reflections using global cubemap (not HDRI light probe)
+ SHADERPERMUTATION_NORMALMAPSCROLLBLEND = 1<<28, // (water) counter-direction normalmaps scrolling
SHADERPERMUTATION_LIMIT = 1<<29, ///< size of permutations array
SHADERPERMUTATION_COUNT = 29 ///< size of shaderpermutationinfo array
}
{"#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"},
{"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
{"#define USEALPHAKILL\n", " alphakill"},
{"#define USEREFLECTCUBE\n", " reflectcube"},
+ {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
};
/// this enum is multiplied by SHADERPERMUTATION_MODEBASE
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)
{"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"},
{"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"},
int loc_PixelToScreenTexCoord;
int loc_ModelToReflectCube;
int loc_ShadowMapMatrix;
+ 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
{
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;
}
}
+ // 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;
+
// now append the shader text itself
vertstrings_list[vertstrings_count++] = vertexstring;
geomstrings_list[geomstrings_count++] = geometrystring;
p->loc_PixelToScreenTexCoord = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
p->loc_ModelToReflectCube = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
p->loc_ShadowMapMatrix = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
+ 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);
CGparameter fp_ViewToLight;
CGparameter fp_PixelToScreenTexCoord;
CGparameter fp_ModelToReflectCube;
+ CGparameter fp_NormalmapScrollBlend;
}
r_cg_permutation_t;
{
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;
}
}
+ // 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] == ' ')
p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
p->fp_ModelToReflectCube = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
+ p->fp_NormalmapScrollBlend = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
CHECKCGERROR
}
switch (vid.renderpath)
{
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, (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_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
if (r_glsl_permutation->loc_Texture_Second) 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, (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
extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
extern rtexture_t *r_shadow_prepasslightingspeculartexture;
+static qboolean R_BlendFuncAllowsColormod(int src, int dst)
+{
+ // a blendfunc allows colormod if:
+ // a) it can never keep the destination pixel invariant, or
+ // b) it can keep the destination pixel invariant, and still can do so if colormodded
+ // this is to prevent unintended side effects from colormod
+
+ // in formulas:
+ // IF there is a (s, sa) for which for all (d, da),
+ // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
+ // THEN, for this (s, sa) and all (colormod, d, da):
+ // s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
+ // OBVIOUSLY, this means that
+ // s*colormod * src(s*colormod, d, sa, da) = 0
+ // dst(s*colormod, d, sa, da) = 1
+
+ // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
+
+ // main condition to leave dst color invariant:
+ // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
+ // src == GL_ZERO:
+ // s * 0 + d * dst(s, d, sa, da) == d
+ // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
+ // => colormod is a problem for GL_SRC_COLOR only
+ // src == GL_ONE:
+ // s + d * dst(s, d, sa, da) == d
+ // => s == 0
+ // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
+ // => colormod is never problematic for these
+ // src == GL_SRC_COLOR:
+ // s*s + d * dst(s, d, sa, da) == d
+ // => s == 0
+ // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
+ // => colormod is never problematic for these
+ // src == GL_ONE_MINUS_SRC_COLOR:
+ // s*(1-s) + d * dst(s, d, sa, da) == d
+ // => s == 0 or s == 1
+ // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
+ // => colormod is a problem for GL_SRC_COLOR only
+ // src == GL_DST_COLOR
+ // s*d + d * dst(s, d, sa, da) == d
+ // => s == 1
+ // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
+ // => colormod is always a problem
+ // or
+ // => s == 0
+ // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
+ // => colormod is never problematic for these
+ // => BUT, we do not know s! We must assume it is problematic
+ // then... except in GL_ONE case, where we know all invariant
+ // cases are fine
+ // src == GL_ONE_MINUS_DST_COLOR
+ // s*(1-d) + d * dst(s, d, sa, da) == d
+ // => s == 0 (1-d is impossible to handle for our desired result)
+ // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
+ // => colormod is never problematic for these
+ // src == GL_SRC_ALPHA
+ // s*sa + d * dst(s, d, sa, da) == d
+ // => s == 0, or sa == 0
+ // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
+ // => colormod breaks in the case GL_SRC_COLOR only
+ // src == GL_ONE_MINUS_SRC_ALPHA
+ // s*(1-sa) + d * dst(s, d, sa, da) == d
+ // => s == 0, or sa == 1
+ // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
+ // => colormod breaks in the case GL_SRC_COLOR only
+ // src == GL_DST_ALPHA
+ // s*da + d * dst(s, d, sa, da) == d
+ // => s == 0
+ // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
+ // => colormod is never problematic for these
+
+ switch(src)
+ {
+ case GL_ZERO:
+ case GL_ONE_MINUS_SRC_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ if(dst == GL_SRC_COLOR)
+ return false;
+ return true;
+ case GL_ONE:
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ return true;
+ case GL_DST_COLOR:
+ if(dst == GL_ONE)
+ return true;
+ return false;
+ default:
+ return false;
+ }
+}
void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
{
// select a permutation of the lighting shader appropriate to this
// fragment shader on features that are not being used
unsigned int permutation = 0;
unsigned int mode = 0;
+ qboolean allow_colormod;
+ static float dummy_colormod[3] = {1, 1, 1};
+ float *colormod = rsurface.colormod;
float m16f[16];
if (rsurfacepass == RSURFPASS_BACKGROUND)
{
// 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);
}
R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
R_Mesh_ColorPointer(NULL, 0, 0);
GL_AlphaTest(false);
- GL_BlendFunc(GL_ONE, GL_ZERO);
}
else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
{
R_Mesh_ColorPointer(NULL, 0, 0);
GL_AlphaTest(false);
GL_BlendFunc(GL_ONE, GL_ZERO);
+ allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
}
else if (rsurfacepass == RSURFPASS_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_refdef.fogenabled)
permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
if (rsurface.texture->colormapping)
R_Mesh_ColorPointer(NULL, 0, 0);
GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+ allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
}
else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
{
R_Mesh_ColorPointer(NULL, 0, 0);
GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+ allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
}
else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
{
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)
R_Mesh_ColorPointer(NULL, 0, 0);
GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+ allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
}
else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
{
R_Mesh_ColorPointer(NULL, 0, 0);
GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+ allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
}
else
{
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;
+ if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
+ R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
+ else
+ R_Mesh_ColorPointer(NULL, 0, 0);
+ }
+ 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)
mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
permutation |= SHADERPERMUTATION_DIFFUSE;
if (specularscale > 0)
- {
permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
- if (r_shadow_glossexact.integer)
- permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
- }
R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
else
R_Mesh_ColorPointer(NULL, 0, 0);
}
- 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;
- }
R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
}
GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+ allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
}
+ if(!allow_colormod)
+ colormod = dummy_colormod;
switch(vid.renderpath)
{
case RENDERPATH_GL20:
if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
- if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);
- if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);
+ if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
+ if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
// 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
{
if (mode == SHADERMODE_FLATCOLOR)
{
- if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
+ if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
}
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) * rsurface.colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * rsurface.colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * rsurface.colormod[2]);
- if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.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, rsurface.colormod[0] * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * r_shadow_deferred_8bitrange.value);
+ 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
{
- if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * rsurface.colormod[0], r_refdef.scene.ambient * rsurface.colormod[1], r_refdef.scene.ambient * rsurface.colormod[2]);
+ if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[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, rsurface.colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
+ if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * 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);
}
// additive passes are only darkened by fog, not tinted
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);}
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)
{
{
if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
- if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);CHECKCGERROR
- if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);CHECKCGERROR
+ if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
+ if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);CHECKCGERROR
// 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
{
if (mode == SHADERMODE_FLATCOLOR)
{
- if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
+ if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
}
else if (mode == SHADERMODE_LIGHTDIRECTION)
{
- if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * rsurface.colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * rsurface.colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * rsurface.colormod[2]);CHECKCGERROR
- if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);CHECKCGERROR
+ if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_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]);CHECKCGERROR
+ if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);CHECKCGERROR
if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_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);CHECKCGERROR
- if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, rsurface.colormod[0] * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
+ if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);CHECKCGERROR
if (r_cg_permutation->fp_LightDir) cgGLSetParameter3f(r_cg_permutation->fp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
}
else
{
- if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * rsurface.colormod[0], r_refdef.scene.ambient * rsurface.colormod[1], r_refdef.scene.ambient * rsurface.colormod[2]);CHECKCGERROR
+ if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);CHECKCGERROR
if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);CHECKCGERROR
if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_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);CHECKCGERROR
- if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, rsurface.colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
+ if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
}
// additive passes are only darkened by fog, not tinted
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)
{
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_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
{
if (r_shadow_usingshadowmaprect)
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);
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
{
basepixels_width = image_width;
basepixels_height = image_height;
- skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
+ skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
if (textureflags & TEXF_ALPHA)
{
for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
pixels[j+2] = 255;
pixels[j+3] = basepixels[j+3];
}
- skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
+ skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
Mem_Free(pixels);
}
}
R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
//Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
- R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
+ R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
- R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
+ R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
}
if (r_loaddds)
{
mymiplevel = savemiplevel;
if (r_loadnormalmap)
- skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, mymiplevel);
+ skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
if (r_loadgloss)
skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
mymiplevel = savemiplevel;
if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
{
- skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+ skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
Mem_Free(pixels);
pixels = NULL;
}
{
pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
- skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+ skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
Mem_Free(pixels);
Mem_Free(bumppixels);
}
{
pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
- skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+ skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
Mem_Free(pixels);
}
if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
- R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
+ R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
}
// _luma is supported only for tenebrae compatibility
mymiplevel = savemiplevel;
if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel))))
{
- skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+ skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
- R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
+ R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
Mem_Free(pixels);pixels = NULL;
}
mymiplevel = savemiplevel;
if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)))
{
- skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+ skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
- R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
+ R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
Mem_Free(pixels);
pixels = NULL;
}
mymiplevel = savemiplevel;
if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)))
{
- skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+ skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
- R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
+ R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
Mem_Free(pixels);
pixels = NULL;
}
mymiplevel = savemiplevel;
if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)))
{
- skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+ skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
- R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
+ R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
Mem_Free(pixels);
pixels = NULL;
}
mymiplevel = savemiplevel;
if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)))
{
- skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+ skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
- R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true);
+ R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
Mem_Free(pixels);
pixels = NULL;
}
temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
temp2 = temp1 + width * height * 4;
Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
- skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, -1, NULL);
+ skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
Mem_Free(temp1);
}
- skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, -1, NULL);
+ skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
if (textureflags & TEXF_ALPHA)
{
for (i = 3;i < width * height * 4;i += 4)
memcpy(fogpixels, skindata, width * height * 4);
for (i = 0;i < width * height * 4;i += 4)
fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
- skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, -1, NULL);
+ skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
Mem_Free(fogpixels);
}
}
// use either a custom palette or the quake palette
Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
- skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, -1, NULL);
+ skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
Mem_Free(temp1);
}
if (developer_loading.integer)
Con_Printf("loading embedded 8bit image \"%s\"\n", name);
- skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette);
+ skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
if (textureflags & TEXF_ALPHA)
{
for (i = 0;i < width * height;i++)
}
}
if (r_loadfog && skinframe->hasalpha)
- skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, alphapalette);
+ skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
}
R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
Cvar_RegisterVariable(&r_showdisabledepthtest);
Cvar_RegisterVariable(&r_drawportals);
Cvar_RegisterVariable(&r_drawentities);
+ Cvar_RegisterVariable(&r_draw2d);
Cvar_RegisterVariable(&r_drawworld);
Cvar_RegisterVariable(&r_cullentities_trace);
Cvar_RegisterVariable(&r_cullentities_trace_samples);
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);
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);
Cvar_RegisterVariable(&r_test);
Cvar_RegisterVariable(&r_batchmode);
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);
- R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
+ R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
Cvar_RegisterVariable(&r_track_sprites);
Cvar_RegisterVariable(&r_track_sprites_flags);
{
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, true, true);
+ }
+ 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...
{
ent = r_refdef.scene.entities[i];
if (!(ent->flags & renderimask))
- if (!R_CullBox(ent->mins, ent->maxs) || (ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
+ if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
r_refdef.viewcache.entityvisible[i] = true;
}
}
}
-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);
+
+ // 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);
+ }
// we can't trust r_refdef.view.forward and friends in reflected scenes
Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
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
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);
//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();
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;
static void R_Water_ProcessPlanes(void)
{
+ int myscissor[4];
r_refdef_view_t originalview;
r_refdef_view_t myview;
int planeindex;
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;
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);
// (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);
r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
R_RenderView_UpdateViewVectors();
- r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
+ if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
+ {
+ r_refdef.view.usecustompvs = true;
+ r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
+ }
}
PlaneClassify(&r_refdef.view.clipplane);
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);
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;
// also reverse the view matrix
Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, 1, -1); // this serves to invert texcoords in the result, as the copied texture is mapped the wrong way round
R_RenderView_UpdateViewVectors();
- if(p->camera_entity)
+ if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
+ {
+ r_refdef.view.usecustompvs = true;
r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
+ }
// camera needs no clipplane
r_refdef.view.useclipplane = false;
#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();
R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && 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;
}
else
{
- r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, -1, NULL);
+ r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
}
}
}
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;
GL_Scissor(0, 0, vid.width, vid.height);
GL_ScissorTest(false);
+
CHECKGLERROR
}
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 ();
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
blendfunc1 = GL_ONE;
blendfunc2 = GL_ZERO;
}
+ // don't colormod evilblend textures
+ if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
+ VectorSet(t->lightmapcolor, 1, 1, 1);
depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
{
RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
}
+static void RSurf_DrawBatch_GL11_ApplyFakeLight(int texturenumsurfaces, const msurface_t **texturesurfacelist)
+{
+ int texturesurfaceindex;
+ int i;
+ float f;
+ const float *v;
+ const float *n;
+ float *c;
+ //vec3_t eyedir;
+
+ // fake shading
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
+ int numverts = surface->num_vertices;
+ v = rsurface.vertex3f + 3 * surface->num_firstvertex;
+ n = rsurface.normal3f + 3 * surface->num_firstvertex;
+ c = rsurface.array_color4f + 4 * surface->num_firstvertex;
+ for (i = 0;i < numverts;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.lightmapcolor4f = rsurface.array_color4f;
+ rsurface.lightmapcolor4f_bufferobject = 0;
+ rsurface.lightmapcolor4f_bufferoffset = 0;
+}
+
+static void RSurf_DrawBatch_GL11_FakeLight(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
+{
+ RSurf_DrawBatch_GL11_ApplyFakeLight(texturenumsurfaces, texturesurfacelist);
+ if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
+ if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
+ R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
+ GL_Color(r, g, b, a);
+ RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+}
+
static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
{
int texturesurfaceindex;
R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
+ else if (FAKELIGHT_ENABLED)
+ RSurf_DrawBatch_GL11_FakeLight(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
else if (rsurface.uselightmaptexture)
RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
else
R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
+ else if (FAKELIGHT_ENABLED)
+ RSurf_DrawBatch_GL11_FakeLight(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
else if (rsurface.uselightmaptexture)
RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
else
GL_DepthMask(writedepth);
}
- rsurface.lightmapcolor4f = NULL;
-
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
{
RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
}
+ else if (FAKELIGHT_ENABLED)
+ {
+ RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
+
+ r_refdef.lightmapintensity = r_fakelight_intensity.value;
+ RSurf_DrawBatch_GL11_ApplyFakeLight(texturenumsurfaces, texturesurfacelist);
+ r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
+ }
else
{
RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
surface = rsurface.modelsurfaces + surfacelist[i];
texture = surface->texture;
rsurface.texture = R_GetCurrentTexture(texture);
- rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
// scan ahead until we find a different texture
endsurface = min(i + 1024, numsurfaces);
texturenumsurfaces = 0;
texturesurfacelist[texturenumsurfaces++] = surface;
- for (;j < endsurface;j++)
+ if(FAKELIGHT_ENABLED)
{
- surface = rsurface.modelsurfaces + surfacelist[j];
- if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
- break;
- texturesurfacelist[texturenumsurfaces++] = surface;
+ rsurface.uselightmaptexture = false;
+ for (;j < endsurface;j++)
+ {
+ surface = rsurface.modelsurfaces + surfacelist[j];
+ if (texture != surface->texture)
+ break;
+ texturesurfacelist[texturenumsurfaces++] = surface;
+ }
+ }
+ else
+ {
+ rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
+ for (;j < endsurface;j++)
+ {
+ surface = rsurface.modelsurfaces + surfacelist[j];
+ if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
+ break;
+ texturesurfacelist[texturenumsurfaces++] = surface;
+ }
}
if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
continue;
surface = rsurface.modelsurfaces + surfacelist[i];
texture = surface->texture;
rsurface.texture = R_GetCurrentTexture(texture);
- 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.uselightmaptexture != (surface->lightmaptexture != NULL))
- break;
- texturesurfacelist[texturenumsurfaces++] = surface;
+ rsurface.uselightmaptexture = false;
+ for (;j < endsurface;j++)
+ {
+ surface = rsurface.modelsurfaces + surfacelist[j];
+ if (texture != surface->texture)
+ break;
+ texturesurfacelist[texturenumsurfaces++] = surface;
+ }
+ }
+ else
+ {
+ rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
+ for (;j < endsurface;j++)
+ {
+ surface = rsurface.modelsurfaces + surfacelist[j];
+ if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
+ break;
+ texturesurfacelist[texturenumsurfaces++] = surface;
+ }
}
// render the range of surfaces
if (ent == r_refdef.scene.worldentity)
// use skin 1 instead)
texture = surfacelist[i]->texture;
rsurface.texture = R_GetCurrentTexture(texture);
- 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
;
continue;
}
- // simply scan ahead until we find a different texture or lightmap state
- for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
- ;
+ if(FAKELIGHT_ENABLED || depthonly || prepass)
+ {
+ 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.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.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
+ ;
+ }
// render the range of surfaces
R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
}
// use skin 1 instead)
texture = surfacelist[i]->texture;
rsurface.texture = R_GetCurrentTexture(texture);
- 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
;
continue;
}
- // simply scan ahead until we find a different texture or lightmap state
- for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
- ;
+ if(FAKELIGHT_ENABLED || depthonly || prepass)
+ {
+ 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.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.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
+ ;
+ }
// render the range of surfaces
R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
}
extern cvar_t cl_decals_bias;
extern cvar_t cl_decals_models;
extern cvar_t cl_decals_newsystem_intensitymultiplier;
+// baseparms, parms, temps
+static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
+{
+ int cornerindex;
+ int index;
+ float v[9][3];
+ const float *vertex3f;
+ int numpoints;
+ float points[2][9][3];
+ float temp[3];
+ float tc[9][2];
+ float f;
+ float c[9][4];
+ const int *e;
+
+ e = rsurface.modelelement3i + 3*triangleindex;
+
+ vertex3f = rsurface.modelvertex3f;
+
+ for (cornerindex = 0;cornerindex < 3;cornerindex++)
+ {
+ index = 3*e[cornerindex];
+ VectorCopy(vertex3f + index, v[cornerindex]);
+ }
+ // cull backfaces
+ //TriangleNormal(v[0], v[1], v[2], normal);
+ //if (DotProduct(normal, localnormal) < 0.0f)
+ // continue;
+ // clip by each of the box planes formed from the projection matrix
+ // if anything survives, we emit the decal
+ numpoints = PolygonF_Clip(3 , v[0] , planes[0][0], planes[0][1], planes[0][2], planes[0][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
+ if (numpoints < 3)
+ return;
+ numpoints = PolygonF_Clip(numpoints, points[1][0], planes[1][0], planes[1][1], planes[1][2], planes[1][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
+ if (numpoints < 3)
+ return;
+ numpoints = PolygonF_Clip(numpoints, points[0][0], planes[2][0], planes[2][1], planes[2][2], planes[2][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
+ if (numpoints < 3)
+ return;
+ numpoints = PolygonF_Clip(numpoints, points[1][0], planes[3][0], planes[3][1], planes[3][2], planes[3][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
+ if (numpoints < 3)
+ return;
+ numpoints = PolygonF_Clip(numpoints, points[0][0], planes[4][0], planes[4][1], planes[4][2], planes[4][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
+ if (numpoints < 3)
+ return;
+ numpoints = PolygonF_Clip(numpoints, points[1][0], planes[5][0], planes[5][1], planes[5][2], planes[5][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), v[0]);
+ if (numpoints < 3)
+ return;
+ // some part of the triangle survived, so we have to accept it...
+ if (dynamic)
+ {
+ // dynamic always uses the original triangle
+ numpoints = 3;
+ for (cornerindex = 0;cornerindex < 3;cornerindex++)
+ {
+ index = 3*e[cornerindex];
+ VectorCopy(vertex3f + index, v[cornerindex]);
+ }
+ }
+ for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
+ {
+ // convert vertex positions to texcoords
+ Matrix4x4_Transform(projection, v[cornerindex], temp);
+ tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
+ tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
+ // calculate distance fade from the projection origin
+ f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
+ f = bound(0.0f, f, 1.0f);
+ c[cornerindex][0] = r * f;
+ c[cornerindex][1] = g * f;
+ c[cornerindex][2] = b * f;
+ c[cornerindex][3] = 1.0f;
+ //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
+ }
+ if (dynamic)
+ R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex, surfaceindex, decalsequence);
+ else
+ for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
+ R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[cornerindex+1], v[cornerindex+2], tc[0], tc[cornerindex+1], tc[cornerindex+2], c[0], c[cornerindex+1], c[cornerindex+2], -1, surfaceindex, decalsequence);
+}
static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
{
matrix4x4_t projection;
decalsystem_t *decalsystem;
qboolean dynamic;
dp_model_t *model;
- const float *vertex3f;
const msurface_t *surface;
const msurface_t *surfaces;
const int *surfacelist;
int surfacelistindex;
int surfaceindex;
int triangleindex;
- int cornerindex;
- int index;
- int numpoints;
- const int *e;
float localorigin[3];
float localnormal[3];
float localmins[3];
float localmaxs[3];
float localsize;
- float v[9][3];
- float tc[9][2];
- float c[9][4];
//float normal[3];
float planes[6][4];
- float f;
- float points[2][9][3];
float angles[3];
- float temp[3];
+ bih_t *bih;
+ int bih_triangles_count;
+ int bih_triangles[256];
+ int bih_surfaces[256];
decalsystem = &ent->decalsystem;
model = ent->model;
#endif
dynamic = model->surfmesh.isanimated;
- vertex3f = rsurface.modelvertex3f;
numsurfacelist = model->nummodelsurfaces;
surfacelist = model->sortedmodelsurfaces;
surfaces = model->data_surfaces;
- for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
+
+ bih = NULL;
+ bih_triangles_count = -1;
+ if(!dynamic)
{
- surfaceindex = surfacelist[surfacelistindex];
- surface = surfaces + surfaceindex;
- // check cull box first because it rejects more than any other check
- if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
- continue;
- // skip transparent surfaces
- texture = surface->texture;
- if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
- continue;
- if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
- continue;
- numtriangles = surface->num_triangles;
- for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
+ if(model->render_bih.numleafs)
+ bih = &model->render_bih;
+ else if(model->collision_bih.numleafs)
+ bih = &model->collision_bih;
+ }
+ if(bih)
+ bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
+ if(bih_triangles_count == 0)
+ return;
+ if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
+ return;
+ if(bih_triangles_count > 0)
+ {
+ for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
{
- for (cornerindex = 0;cornerindex < 3;cornerindex++)
- {
- index = 3*e[cornerindex];
- VectorCopy(vertex3f + index, v[cornerindex]);
- }
- // cull backfaces
- //TriangleNormal(v[0], v[1], v[2], normal);
- //if (DotProduct(normal, localnormal) < 0.0f)
- // continue;
- // clip by each of the box planes formed from the projection matrix
- // if anything survives, we emit the decal
- numpoints = PolygonF_Clip(3 , v[0] , planes[0][0], planes[0][1], planes[0][2], planes[0][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
- if (numpoints < 3)
- continue;
- numpoints = PolygonF_Clip(numpoints, points[1][0], planes[1][0], planes[1][1], planes[1][2], planes[1][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
- if (numpoints < 3)
+ surfaceindex = bih_surfaces[triangleindex];
+ surface = surfaces + surfaceindex;
+ texture = surface->texture;
+ if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
continue;
- numpoints = PolygonF_Clip(numpoints, points[0][0], planes[2][0], planes[2][1], planes[2][2], planes[2][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
- if (numpoints < 3)
+ if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
continue;
- numpoints = PolygonF_Clip(numpoints, points[1][0], planes[3][0], planes[3][1], planes[3][2], planes[3][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
- if (numpoints < 3)
+ R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
+ }
+ }
+ else
+ {
+ for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
+ {
+ surfaceindex = surfacelist[surfacelistindex];
+ surface = surfaces + surfaceindex;
+ // check cull box first because it rejects more than any other check
+ if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
continue;
- numpoints = PolygonF_Clip(numpoints, points[0][0], planes[4][0], planes[4][1], planes[4][2], planes[4][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
- if (numpoints < 3)
+ // skip transparent surfaces
+ texture = surface->texture;
+ if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
continue;
- numpoints = PolygonF_Clip(numpoints, points[1][0], planes[5][0], planes[5][1], planes[5][2], planes[5][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), v[0]);
- if (numpoints < 3)
+ if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
continue;
- // some part of the triangle survived, so we have to accept it...
- if (dynamic)
- {
- // dynamic always uses the original triangle
- numpoints = 3;
- for (cornerindex = 0;cornerindex < 3;cornerindex++)
- {
- index = 3*e[cornerindex];
- VectorCopy(vertex3f + index, v[cornerindex]);
- }
- }
- for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
- {
- // convert vertex positions to texcoords
- Matrix4x4_Transform(&projection, v[cornerindex], temp);
- tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
- tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
- // calculate distance fade from the projection origin
- f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
- f = bound(0.0f, f, 1.0f);
- c[cornerindex][0] = r * f;
- c[cornerindex][1] = g * f;
- c[cornerindex][2] = b * f;
- c[cornerindex][3] = 1.0f;
- //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
- }
- if (dynamic)
- R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex+surface->num_firsttriangle, surfaceindex, decalsequence);
- else
- for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
- R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[cornerindex+1], v[cornerindex+2], tc[0], tc[cornerindex+1], tc[cornerindex+2], c[0], c[cornerindex+1], c[cornerindex+2], -1, surfaceindex, decalsequence);
+ numtriangles = surface->num_triangles;
+ for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
+ R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
}
}
}
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;