X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=r_shadow.c;h=20c95578f552bda8c248e6499e3921826feabb88;hp=e62ff1184b23caef41c057785597a9ead93aea29;hb=699c77ca2c9fd357fbe479f00e778486becfd840;hpb=97a90fe3eba97cf8de7163ddc018bdff04ace6cb diff --git a/r_shadow.c b/r_shadow.c index e62ff118..20c95578 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -162,30 +162,31 @@ rtexture_t *r_shadow_blankwhitetexture; // used only for light filters (cubemaps) rtexturepool_t *r_shadow_filters_texturepool; -cvar_t r_shadow_realtime_world_lightmaps = {0, "r_shadow_realtime_world_lightmaps", "0"}; +cvar_t r_shadow_bumpscale_basetexture = {0, "r_shadow_bumpscale_basetexture", "0"}; +cvar_t r_shadow_bumpscale_bumpmap = {0, "r_shadow_bumpscale_bumpmap", "4"}; +cvar_t r_shadow_cull = {0, "r_shadow_cull", "1"}; +cvar_t r_shadow_debuglight = {0, "r_shadow_debuglight", "-1"}; +cvar_t r_shadow_gloss = {0, "r_shadow_gloss", "1"}; +cvar_t r_shadow_gloss2intensity = {0, "r_shadow_gloss2intensity", "0.25"}; +cvar_t r_shadow_glossintensity = {0, "r_shadow_glossintensity", "1"}; cvar_t r_shadow_lightattenuationpower = {0, "r_shadow_lightattenuationpower", "0.5"}; cvar_t r_shadow_lightattenuationscale = {0, "r_shadow_lightattenuationscale", "1"}; cvar_t r_shadow_lightintensityscale = {0, "r_shadow_lightintensityscale", "1"}; -cvar_t r_shadow_realtime_world = {0, "r_shadow_realtime_world", "0"}; -cvar_t r_shadow_realtime_dlight = {0, "r_shadow_realtime_dlight", "0"}; -cvar_t r_shadow_visiblevolumes = {0, "r_shadow_visiblevolumes", "0"}; -cvar_t r_shadow_gloss = {0, "r_shadow_gloss", "1"}; -cvar_t r_shadow_glossintensity = {0, "r_shadow_glossintensity", "1"}; -cvar_t r_shadow_gloss2intensity = {0, "r_shadow_gloss2intensity", "0.25"}; -cvar_t r_shadow_debuglight = {0, "r_shadow_debuglight", "-1"}; -cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1"}; -cvar_t r_shadow_bumpscale_bumpmap = {0, "r_shadow_bumpscale_bumpmap", "4"}; -cvar_t r_shadow_bumpscale_basetexture = {0, "r_shadow_bumpscale_basetexture", "0"}; cvar_t r_shadow_polygonfactor = {0, "r_shadow_polygonfactor", "0"}; cvar_t r_shadow_polygonoffset = {0, "r_shadow_polygonoffset", "1"}; cvar_t r_shadow_portallight = {0, "r_shadow_portallight", "1"}; -cvar_t r_shadow_projectdistance = {0, "r_shadow_projectdistance", "10000"}; -cvar_t r_shadow_texture3d = {0, "r_shadow_texture3d", "1"}; +cvar_t r_shadow_projectdistance = {0, "r_shadow_projectdistance", "1000000"}; +cvar_t r_shadow_realtime_dlight = {0, "r_shadow_realtime_dlight", "1"}; +cvar_t r_shadow_realtime_dlight_shadows = {0, "r_shadow_realtime_dlight_shadows", "0"}; +cvar_t r_shadow_realtime_world = {0, "r_shadow_realtime_world", "0"}; +cvar_t r_shadow_realtime_world_dlightshadows = {0, "r_shadow_realtime_world_dlightshadows", "1"}; +cvar_t r_shadow_realtime_world_lightmaps = {0, "r_shadow_realtime_world_lightmaps", "0"}; +cvar_t r_shadow_realtime_world_shadows = {0, "r_shadow_realtime_world_shadows", "1"}; +cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1"}; cvar_t r_shadow_singlepassvolumegeneration = {0, "r_shadow_singlepassvolumegeneration", "1"}; -cvar_t r_shadow_worldshadows = {0, "r_shadow_worldshadows", "1"}; -cvar_t r_shadow_dlightshadows = {CVAR_SAVE, "r_shadow_dlightshadows", "1"}; cvar_t r_shadow_staticworldlights = {0, "r_shadow_staticworldlights", "1"}; -cvar_t r_shadow_cull = {0, "r_shadow_cull", "1"}; +cvar_t r_shadow_texture3d = {0, "r_shadow_texture3d", "1"}; +cvar_t r_shadow_visiblevolumes = {0, "r_shadow_visiblevolumes", "0"}; cvar_t gl_ext_stenciltwoside = {0, "gl_ext_stenciltwoside", "1"}; int c_rt_lights, c_rt_clears, c_rt_scissored; @@ -274,28 +275,29 @@ void R_Shadow_Help_f(void) Con_Printf( "Documentation on r_shadow system:\n" "Settings:\n" +"r_shadow_bumpscale_basetexture : base texture as bumpmap with this scale\n" +"r_shadow_bumpscale_bumpmap : depth scale for bumpmap conversion\n" +"r_shadow_debuglight : render only this light number (-1 = all)\n" +"r_shadow_gloss 0/1/2 : no gloss, gloss textures only, force gloss\n" +"r_shadow_gloss2intensity : brightness of forced gloss\n" +"r_shadow_glossintensity : brightness of textured gloss\n" "r_shadow_lightattenuationpower : used to generate attenuation texture\n" "r_shadow_lightattenuationscale : used to generate attenuation texture\n" "r_shadow_lightintensityscale : scale rendering brightness of all lights\n" -"r_shadow_realtime_world : use realtime world light rendering\n" -"r_shadow_realtime_dlight : use high quality dlight rendering\n" -"r_shadow_realtime_world_lightmaps : use lightmaps in addition to rtlights\n" -"r_shadow_visiblevolumes : useful for performance testing; bright = slow!\n" -"r_shadow_gloss 0/1/2 : no gloss, gloss textures only, force gloss\n" -"r_shadow_glossintensity : brightness of textured gloss\n" -"r_shadow_gloss2intensity : brightness of forced gloss\n" -"r_shadow_debuglight : render only this light number (-1 = all)\n" -"r_shadow_scissor : use scissor optimization\n" -"r_shadow_bumpscale_bumpmap : depth scale for bumpmap conversion\n" -"r_shadow_bumpscale_basetexture : base texture as bumpmap with this scale\n" "r_shadow_polygonfactor : nudge shadow volumes closer/further\n" "r_shadow_polygonoffset : nudge shadow volumes closer/further\n" "r_shadow_portallight : use portal visibility for static light precomputation\n" "r_shadow_projectdistance : shadow volume projection distance\n" -"r_shadow_texture3d : use 3d attenuation texture (if hardware supports)\n" +"r_shadow_realtime_dlight : use high quality dynamic lights in normal mode\n" +"r_shadow_realtime_dlight_shadows : cast shadows from dlights\n" +"r_shadow_realtime_world : use high quality world lighting mode\n" +"r_shadow_realtime_world_dlightshadows : cast shadows from dlights\n" +"r_shadow_realtime_world_lightmaps : use lightmaps in addition to lights\n" +"r_shadow_realtime_world_shadows : cast shadows from world lights\n" +"r_shadow_scissor : use scissor optimization\n" "r_shadow_singlepassvolumegeneration : selects shadow volume algorithm\n" -"r_shadow_worldshadows : enable world shadows\n" -"r_shadow_dlightshadows : enable dlight shadows\n" +"r_shadow_texture3d : use 3d attenuation texture (if hardware supports)\n" +"r_shadow_visiblevolumes : useful for performance testing; bright = slow!\n" "Commands:\n" "r_shadow_help : this help\n" ); @@ -303,30 +305,31 @@ void R_Shadow_Help_f(void) void R_Shadow_Init(void) { + Cvar_RegisterVariable(&r_shadow_bumpscale_basetexture); + Cvar_RegisterVariable(&r_shadow_bumpscale_bumpmap); + Cvar_RegisterVariable(&r_shadow_cull); + Cvar_RegisterVariable(&r_shadow_debuglight); + Cvar_RegisterVariable(&r_shadow_gloss); + Cvar_RegisterVariable(&r_shadow_gloss2intensity); + Cvar_RegisterVariable(&r_shadow_glossintensity); Cvar_RegisterVariable(&r_shadow_lightattenuationpower); Cvar_RegisterVariable(&r_shadow_lightattenuationscale); Cvar_RegisterVariable(&r_shadow_lightintensityscale); - Cvar_RegisterVariable(&r_shadow_realtime_world); - Cvar_RegisterVariable(&r_shadow_realtime_world_lightmaps); - Cvar_RegisterVariable(&r_shadow_realtime_dlight); - Cvar_RegisterVariable(&r_shadow_visiblevolumes); - Cvar_RegisterVariable(&r_shadow_gloss); - Cvar_RegisterVariable(&r_shadow_glossintensity); - Cvar_RegisterVariable(&r_shadow_gloss2intensity); - Cvar_RegisterVariable(&r_shadow_debuglight); - Cvar_RegisterVariable(&r_shadow_scissor); - Cvar_RegisterVariable(&r_shadow_bumpscale_bumpmap); - Cvar_RegisterVariable(&r_shadow_bumpscale_basetexture); Cvar_RegisterVariable(&r_shadow_polygonfactor); Cvar_RegisterVariable(&r_shadow_polygonoffset); Cvar_RegisterVariable(&r_shadow_portallight); Cvar_RegisterVariable(&r_shadow_projectdistance); - Cvar_RegisterVariable(&r_shadow_texture3d); + Cvar_RegisterVariable(&r_shadow_realtime_dlight); + Cvar_RegisterVariable(&r_shadow_realtime_dlight_shadows); + Cvar_RegisterVariable(&r_shadow_realtime_world); + Cvar_RegisterVariable(&r_shadow_realtime_world_dlightshadows); + Cvar_RegisterVariable(&r_shadow_realtime_world_lightmaps); + Cvar_RegisterVariable(&r_shadow_realtime_world_shadows); + Cvar_RegisterVariable(&r_shadow_scissor); Cvar_RegisterVariable(&r_shadow_singlepassvolumegeneration); - Cvar_RegisterVariable(&r_shadow_worldshadows); - Cvar_RegisterVariable(&r_shadow_dlightshadows); Cvar_RegisterVariable(&r_shadow_staticworldlights); - Cvar_RegisterVariable(&r_shadow_cull); + Cvar_RegisterVariable(&r_shadow_texture3d); + Cvar_RegisterVariable(&r_shadow_visiblevolumes); Cvar_RegisterVariable(&gl_ext_stenciltwoside); if (gamemode == GAME_TENEBRAE) { @@ -930,9 +933,7 @@ int R_Shadow_ScissorForBBox(const float *mins, const float *maxs) if (!r_shadow_scissor.integer) return false; // if view is inside the box, just say yes it's visible - // LordHavoc: for some odd reason scissor seems broken without stencil - // (?!? seems like a driver bug) so abort if gl_stencil is false - if (!gl_stencil || BoxesOverlap(r_vieworigin, r_vieworigin, mins, maxs)) + if (BoxesOverlap(r_vieworigin, r_vieworigin, mins, maxs)) { GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height); return false; @@ -1094,7 +1095,7 @@ int R_Shadow_ScissorForBBox(const float *mins, const float *maxs) return false; } -void R_Shadow_VertexLighting(int numverts, const float *vertex3f, const float *normal3f, const float *lightcolor, const matrix4x4_t *m) +static void R_Shadow_VertexShadingWithXYZAttenuation(int numverts, const float *vertex3f, const float *normal3f, const float *lightcolor, const matrix4x4_t *m) { float *color4f = varray_color4f; float dist, dot, intensity, v[3], n[3]; @@ -1107,7 +1108,8 @@ void R_Shadow_VertexLighting(int numverts, const float *vertex3f, const float *n if ((dot = DotProduct(n, v)) > 0) { dist = sqrt(dist); - intensity = pow(1 - dist, r_shadow_attenpower) * r_shadow_attenscale * dot / sqrt(DotProduct(n,n)); + intensity = dot / sqrt(VectorLength2(v) * VectorLength2(n)); + intensity *= pow(1 - dist, r_shadow_attenpower) * r_shadow_attenscale; VectorScale(lightcolor, intensity, color4f); color4f[3] = 1; } @@ -1125,7 +1127,7 @@ void R_Shadow_VertexLighting(int numverts, const float *vertex3f, const float *n } } -void R_Shadow_VertexLightingWithXYAttenuationTexture(int numverts, const float *vertex3f, const float *normal3f, const float *lightcolor, const matrix4x4_t *m) +static void R_Shadow_VertexShadingWithZAttenuation(int numverts, const float *vertex3f, const float *normal3f, const float *lightcolor, const matrix4x4_t *m) { float *color4f = varray_color4f; float dist, dot, intensity, v[3], n[3]; @@ -1137,7 +1139,8 @@ void R_Shadow_VertexLightingWithXYAttenuationTexture(int numverts, const float * Matrix4x4_Transform3x3(m, normal3f, n); if ((dot = DotProduct(n, v)) > 0) { - intensity = pow(1 - dist, r_shadow_attenpower) * r_shadow_attenscale * dot / sqrt(DotProduct(n,n)); + intensity = dot / sqrt(VectorLength2(v) * VectorLength2(n)); + intensity *= pow(1 - dist, r_shadow_attenpower) * r_shadow_attenscale; VectorScale(lightcolor, intensity, color4f); color4f[3] = 1; } @@ -1155,9 +1158,33 @@ void R_Shadow_VertexLightingWithXYAttenuationTexture(int numverts, const float * } } -// FIXME: this should be done in a vertex program when possible +static void R_Shadow_VertexShading(int numverts, const float *vertex3f, const float *normal3f, const float *lightcolor, const matrix4x4_t *m) +{ + float *color4f = varray_color4f; + float dot, intensity, v[3], n[3]; + for (;numverts > 0;numverts--, vertex3f += 3, normal3f += 3, color4f += 4) + { + Matrix4x4_Transform(m, vertex3f, v); + Matrix4x4_Transform3x3(m, normal3f, n); + if ((dot = DotProduct(n, v)) > 0) + { + intensity = dot / sqrt(VectorLength2(v) * VectorLength2(n)); + VectorScale(lightcolor, intensity, color4f); + color4f[3] = 1; + } + else + { + VectorClear(color4f); + color4f[3] = 1; + } + } +} + +#define USETEXMATRIX 1 +#ifndef USETEXMATRIX +// FIXME: this should be done in a texture matrix or vertex program when possible // FIXME: if vertex program not available, this would really benefit from 3DNow! or SSE -void R_Shadow_Transform_Vertex3f_TexCoord3f(float *tc3f, int numverts, const float *vertex3f, const matrix4x4_t *matrix) +static void R_Shadow_Transform_Vertex3f_TexCoord3f(float *tc3f, int numverts, const float *vertex3f, const matrix4x4_t *matrix) { do { @@ -1170,7 +1197,7 @@ void R_Shadow_Transform_Vertex3f_TexCoord3f(float *tc3f, int numverts, const flo while (--numverts); } -void R_Shadow_Transform_Vertex3f_TexCoord2f(float *tc2f, int numverts, const float *vertex3f, const matrix4x4_t *matrix) +static void R_Shadow_Transform_Vertex3f_TexCoord2f(float *tc2f, int numverts, const float *vertex3f, const matrix4x4_t *matrix) { do { @@ -1181,8 +1208,9 @@ void R_Shadow_Transform_Vertex3f_TexCoord2f(float *tc2f, int numverts, const flo } while (--numverts); } +#endif -void R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(float *out3f, int numverts, const float *vertex3f, const float *svector3f, const float *tvector3f, const float *normal3f, const vec3_t relativelightorigin) +static void R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(float *out3f, int numverts, const float *vertex3f, const float *svector3f, const float *tvector3f, const float *normal3f, const vec3_t relativelightorigin) { int i; float lightdir[3]; @@ -1196,7 +1224,7 @@ void R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(float *out3f, int numverts, con } } -void R_Shadow_GenTexCoords_Specular_NormalCubeMap(float *out3f, int numverts, const float *vertex3f, const float *svector3f, const float *tvector3f, const float *normal3f, const vec3_t relativelightorigin, const vec3_t relativeeyeorigin) +static void R_Shadow_GenTexCoords_Specular_NormalCubeMap(float *out3f, int numverts, const float *vertex3f, const float *svector3f, const float *tvector3f, const float *normal3f, const vec3_t relativelightorigin, const vec3_t relativeeyeorigin) { int i; float lightdir[3], eyedir[3], halfdir[3]; @@ -1230,28 +1258,37 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements if (lighting & LIGHTING_DIFFUSE) { GL_Color(1,1,1,1); - // colorscale accounts for how much we multiply the brightness during combine + colorscale = r_shadow_lightintensityscale.value; + // colorscale accounts for how much we multiply the brightness + // during combine. + // // mult is how many times the final pass of the lighting will be - // performed to get more brightness than otherwise possible - // limit mult to 64 for sanity sake + // performed to get more brightness than otherwise possible. + // + // Limit mult to 64 for sanity sake. if (r_shadow_texture3d.integer && r_textureunits.integer >= 4) { // 3/2 3D combine path (Geforce3, Radeon 8500) memset(&m, 0, sizeof(m)); m.pointer_vertex = vertex3f; m.tex[0] = R_GetTexture(bumptexture); - m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture); - m.tex3d[2] = R_GetTexture(r_shadow_attenuation3dtexture); m.texcombinergb[0] = GL_REPLACE; - m.texcombinergb[1] = GL_DOT3_RGBA_ARB; m.pointer_texcoord[0] = texcoord2f; - m.pointer_texcoord[1] = varray_texcoord3f[1]; - m.pointer_texcoord[2] = varray_texcoord3f[2]; + m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture); + m.texcombinergb[1] = GL_DOT3_RGBA_ARB; + m.pointer_texcoord3f[1] = varray_texcoord3f[1]; + R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin); + m.tex3d[2] = R_GetTexture(r_shadow_attenuation3dtexture); +#if USETEXMATRIX + m.pointer_texcoord3f[2] = vertex3f; + m.texmatrix[2] = *matrix_modeltoattenuationxyz; +#else + m.pointer_texcoord3f[2] = varray_texcoord3f[2]; + R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[2], numverts, vertex3f, matrix_modeltoattenuationxyz); +#endif R_Mesh_State(&m); GL_ColorMask(0,0,0,1); GL_BlendFunc(GL_ONE, GL_ZERO); - R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin); - R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[2], numverts, vertex3f, matrix_modeltoattenuationxyz); GL_LockArrays(0, numverts); R_Mesh_Draw(numverts, numtriangles, elements); GL_LockArrays(0, 0); @@ -1265,25 +1302,14 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements if (lightcubemap) { m.texcubemap[1] = R_GetTexture(lightcubemap); - m.pointer_texcoord[1] = varray_texcoord3f[1]; +#if USETEXMATRIX + m.pointer_texcoord3f[1] = vertex3f; + m.texmatrix[1] = *matrix_modeltolight; +#else + m.pointer_texcoord3f[1] = varray_texcoord3f[1]; R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltolight); +#endif } - R_Mesh_State(&m); - GL_LockArrays(0, numverts); - GL_ColorMask(1,1,1,0); - GL_BlendFunc(GL_DST_ALPHA, GL_ONE); - VectorScale(lightcolor, r_shadow_lightintensityscale.value, color2); - for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--) - { - color[0] = bound(0, color2[0], 1); - color[1] = bound(0, color2[1], 1); - color[2] = bound(0, color2[2], 1); - GL_Color(color[0], color[1], color[2], 1); - R_Mesh_Draw(numverts, numtriangles, elements); - c_rt_lightmeshes++; - c_rt_lighttris += numtriangles; - } - GL_LockArrays(0, 0); } else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && lightcubemap) { @@ -1291,11 +1317,16 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements memset(&m, 0, sizeof(m)); m.pointer_vertex = vertex3f; m.tex3d[0] = R_GetTexture(r_shadow_attenuation3dtexture); - m.pointer_texcoord[0] = varray_texcoord3f[0]; +#if USETEXMATRIX + m.pointer_texcoord3f[0] = vertex3f; + m.texmatrix[0] = *matrix_modeltoattenuationxyz; +#else + m.pointer_texcoord3f[0] = varray_texcoord3f[0]; + R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[0], numverts, vertex3f, matrix_modeltoattenuationxyz); +#endif R_Mesh_State(&m); GL_ColorMask(0,0,0,1); GL_BlendFunc(GL_ONE, GL_ZERO); - R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[0], numverts, vertex3f, matrix_modeltoattenuationxyz); GL_LockArrays(0, numverts); R_Mesh_Draw(numverts, numtriangles, elements); GL_LockArrays(0, 0); @@ -1305,14 +1336,14 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements memset(&m, 0, sizeof(m)); m.pointer_vertex = vertex3f; m.tex[0] = R_GetTexture(bumptexture); - m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture); m.texcombinergb[0] = GL_REPLACE; - m.texcombinergb[1] = GL_DOT3_RGBA_ARB; m.pointer_texcoord[0] = texcoord2f; - m.pointer_texcoord[1] = varray_texcoord3f[1]; + m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture); + m.texcombinergb[1] = GL_DOT3_RGBA_ARB; + m.pointer_texcoord3f[1] = varray_texcoord3f[1]; + R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin); R_Mesh_State(&m); GL_BlendFunc(GL_DST_ALPHA, GL_ZERO); - R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin); GL_LockArrays(0, numverts); R_Mesh_Draw(numverts, numtriangles, elements); GL_LockArrays(0, 0); @@ -1326,25 +1357,14 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements if (lightcubemap) { m.texcubemap[1] = R_GetTexture(lightcubemap); - m.pointer_texcoord[1] = varray_texcoord3f[1]; +#if USETEXMATRIX + m.pointer_texcoord3f[1] = vertex3f; + m.texmatrix[1] = *matrix_modeltolight; +#else + m.pointer_texcoord3f[1] = varray_texcoord3f[1]; R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltolight); +#endif } - R_Mesh_State(&m); - GL_LockArrays(0, numverts); - GL_ColorMask(1,1,1,0); - GL_BlendFunc(GL_DST_ALPHA, GL_ONE); - VectorScale(lightcolor, r_shadow_lightintensityscale.value, color2); - for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--) - { - color[0] = bound(0, color2[0], 1); - color[1] = bound(0, color2[1], 1); - color[2] = bound(0, color2[2], 1); - GL_Color(color[0], color[1], color[2], 1); - R_Mesh_Draw(numverts, numtriangles, elements); - c_rt_lightmeshes++; - c_rt_lighttris += numtriangles; - } - GL_LockArrays(0, 0); } else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && !lightcubemap) { @@ -1352,15 +1372,15 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements memset(&m, 0, sizeof(m)); m.pointer_vertex = vertex3f; m.tex[0] = R_GetTexture(bumptexture); - m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture); m.texcombinergb[0] = GL_REPLACE; - m.texcombinergb[1] = GL_DOT3_RGBA_ARB; m.pointer_texcoord[0] = texcoord2f; - m.pointer_texcoord[1] = varray_texcoord3f[1]; + m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture); + m.texcombinergb[1] = GL_DOT3_RGBA_ARB; + m.pointer_texcoord3f[1] = varray_texcoord3f[1]; + R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin); R_Mesh_State(&m); GL_ColorMask(0,0,0,1); GL_BlendFunc(GL_ONE, GL_ZERO); - R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin); GL_LockArrays(0, numverts); R_Mesh_Draw(numverts, numtriangles, elements); GL_LockArrays(0, 0); @@ -1370,26 +1390,15 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements memset(&m, 0, sizeof(m)); m.pointer_vertex = vertex3f; m.tex[0] = R_GetTexture(basetexture); - m.tex3d[1] = R_GetTexture(r_shadow_attenuation3dtexture); m.pointer_texcoord[0] = texcoord2f; - m.pointer_texcoord[1] = varray_texcoord3f[1]; - R_Mesh_State(&m); - GL_LockArrays(0, numverts); - GL_ColorMask(1,1,1,0); - GL_BlendFunc(GL_DST_ALPHA, GL_ONE); + m.tex3d[1] = R_GetTexture(r_shadow_attenuation3dtexture); +#if USETEXMATRIX + m.pointer_texcoord3f[1] = vertex3f; + m.texmatrix[1] = *matrix_modeltoattenuationxyz; +#else + m.pointer_texcoord3f[1] = varray_texcoord3f[1]; R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltoattenuationxyz); - VectorScale(lightcolor, r_shadow_lightintensityscale.value, color2); - for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--) - { - color[0] = bound(0, color2[0], 1); - color[1] = bound(0, color2[1], 1); - color[2] = bound(0, color2[2], 1); - GL_Color(color[0], color[1], color[2], 1); - R_Mesh_Draw(numverts, numtriangles, elements); - c_rt_lightmeshes++; - c_rt_lighttris += numtriangles; - } - GL_LockArrays(0, 0); +#endif } else if (r_textureunits.integer >= 4) { @@ -1397,21 +1406,31 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements memset(&m, 0, sizeof(m)); m.pointer_vertex = vertex3f; m.tex[0] = R_GetTexture(bumptexture); - m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture); m.texcombinergb[0] = GL_REPLACE; + m.pointer_texcoord[0] = texcoord2f; + m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture); m.texcombinergb[1] = GL_DOT3_RGBA_ARB; + m.pointer_texcoord3f[1] = varray_texcoord3f[1]; + R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin); m.tex[2] = R_GetTexture(r_shadow_attenuation2dtexture); - m.tex[3] = R_GetTexture(r_shadow_attenuation2dtexture); - m.pointer_texcoord[0] = texcoord2f; - m.pointer_texcoord[1] = varray_texcoord3f[1]; +#if USETEXMATRIX + m.pointer_texcoord3f[2] = vertex3f; + m.texmatrix[2] = *matrix_modeltoattenuationxyz; +#else m.pointer_texcoord[2] = varray_texcoord2f[2]; + R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[2], numverts, vertex3f, matrix_modeltoattenuationxyz); +#endif + m.tex[3] = R_GetTexture(r_shadow_attenuation2dtexture); +#if USETEXMATRIX + m.pointer_texcoord3f[3] = vertex3f; + m.texmatrix[3] = *matrix_modeltoattenuationz; +#else m.pointer_texcoord[3] = varray_texcoord2f[3]; + R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[3], numverts, vertex3f, matrix_modeltoattenuationz); +#endif R_Mesh_State(&m); GL_ColorMask(0,0,0,1); GL_BlendFunc(GL_ONE, GL_ZERO); - R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin); - R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[2], numverts, vertex3f, matrix_modeltoattenuationxyz); - R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[3], numverts, vertex3f, matrix_modeltoattenuationz); GL_LockArrays(0, numverts); R_Mesh_Draw(numverts, numtriangles, elements); GL_LockArrays(0, 0); @@ -1425,25 +1444,14 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements if (lightcubemap) { m.texcubemap[1] = R_GetTexture(lightcubemap); - m.pointer_texcoord[1] = varray_texcoord3f[1]; +#if USETEXMATRIX + m.pointer_texcoord3f[1] = vertex3f; + m.texmatrix[1] = *matrix_modeltolight; +#else + m.pointer_texcoord3f[1] = varray_texcoord3f[1]; R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltolight); +#endif } - R_Mesh_State(&m); - GL_LockArrays(0, numverts); - GL_ColorMask(1,1,1,0); - GL_BlendFunc(GL_DST_ALPHA, GL_ONE); - VectorScale(lightcolor, r_shadow_lightintensityscale.value, color2); - for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--) - { - color[0] = bound(0, color2[0], 1); - color[1] = bound(0, color2[1], 1); - color[2] = bound(0, color2[2], 1); - GL_Color(color[0], color[1], color[2], 1); - R_Mesh_Draw(numverts, numtriangles, elements); - c_rt_lightmeshes++; - c_rt_lighttris += numtriangles; - } - GL_LockArrays(0, 0); } else { @@ -1451,14 +1459,24 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements memset(&m, 0, sizeof(m)); m.pointer_vertex = vertex3f; m.tex[0] = R_GetTexture(r_shadow_attenuation2dtexture); - m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture); +#if USETEXMATRIX + m.pointer_texcoord3f[0] = vertex3f; + m.texmatrix[0] = *matrix_modeltoattenuationxyz; +#else m.pointer_texcoord[0] = varray_texcoord2f[0]; + R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[0], numverts, vertex3f, matrix_modeltoattenuationxyz); +#endif + m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture); +#if USETEXMATRIX + m.pointer_texcoord3f[1] = vertex3f; + m.texmatrix[1] = *matrix_modeltoattenuationz; +#else m.pointer_texcoord[1] = varray_texcoord2f[1]; + R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[1], numverts, vertex3f, matrix_modeltoattenuationz); +#endif R_Mesh_State(&m); GL_ColorMask(0,0,0,1); GL_BlendFunc(GL_ONE, GL_ZERO); - R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[0], numverts, vertex3f, matrix_modeltoattenuationxyz); - R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[1], numverts, vertex3f, matrix_modeltoattenuationz); GL_LockArrays(0, numverts); R_Mesh_Draw(numverts, numtriangles, elements); GL_LockArrays(0, 0); @@ -1468,14 +1486,14 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements memset(&m, 0, sizeof(m)); m.pointer_vertex = vertex3f; m.tex[0] = R_GetTexture(bumptexture); - m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture); m.texcombinergb[0] = GL_REPLACE; - m.texcombinergb[1] = GL_DOT3_RGBA_ARB; m.pointer_texcoord[0] = texcoord2f; - m.pointer_texcoord[1] = varray_texcoord3f[1]; + m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture); + m.texcombinergb[1] = GL_DOT3_RGBA_ARB; + m.pointer_texcoord3f[1] = varray_texcoord3f[1]; + R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin); R_Mesh_State(&m); GL_BlendFunc(GL_DST_ALPHA, GL_ZERO); - R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin); GL_LockArrays(0, numverts); R_Mesh_Draw(numverts, numtriangles, elements); GL_LockArrays(0, 0); @@ -1489,257 +1507,259 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements if (lightcubemap) { m.texcubemap[1] = R_GetTexture(lightcubemap); - m.pointer_texcoord[1] = varray_texcoord3f[1]; +#if USETEXMATRIX + m.pointer_texcoord3f[1] = vertex3f; + m.texmatrix[1] = *matrix_modeltolight; +#else + m.pointer_texcoord3f[1] = varray_texcoord3f[1]; R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltolight); +#endif } - R_Mesh_State(&m); - GL_LockArrays(0, numverts); - GL_ColorMask(1,1,1,0); - GL_BlendFunc(GL_DST_ALPHA, GL_ONE); - VectorScale(lightcolor, r_shadow_lightintensityscale.value, color2); - for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--) - { - color[0] = bound(0, color2[0], 1); - color[1] = bound(0, color2[1], 1); - color[2] = bound(0, color2[2], 1); - GL_Color(color[0], color[1], color[2], 1); - R_Mesh_Draw(numverts, numtriangles, elements); - c_rt_lightmeshes++; - c_rt_lighttris += numtriangles; - } - GL_LockArrays(0, 0); } - } - if ((lighting & LIGHTING_SPECULAR) && (r_shadow_gloss.integer >= 2 || (r_shadow_gloss.integer >= 1 && glosstexture != r_shadow_blankglosstexture))) - { - colorscale = r_shadow_glossintensity.value; - if (glosstexture == r_shadow_blankglosstexture) - colorscale *= r_shadow_gloss2intensity.value; - GL_Color(1,1,1,1); - if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && lightcubemap /*&& gl_support_blendsquare*/) // FIXME: detect blendsquare! + // this final code is shared + R_Mesh_State(&m); + GL_ColorMask(1,1,1,0); + GL_BlendFunc(GL_DST_ALPHA, GL_ONE); + VectorScale(lightcolor, colorscale, color2); + for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--) { - // 2/0/0/1/2 3D combine blendsquare path - memset(&m, 0, sizeof(m)); - m.pointer_vertex = vertex3f; - m.tex[0] = R_GetTexture(bumptexture); - m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture); - m.texcombinergb[1] = GL_DOT3_RGBA_ARB; - m.pointer_texcoord[0] = texcoord2f; - m.pointer_texcoord[1] = varray_texcoord3f[1]; - R_Mesh_State(&m); - GL_ColorMask(0,0,0,1); - // this squares the result - GL_BlendFunc(GL_SRC_ALPHA, GL_ZERO); - R_Shadow_GenTexCoords_Specular_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin, relativeeyeorigin); + GL_Color(bound(0, color2[0], 1), bound(0, color2[1], 1), bound(0, color2[2], 1), 1); GL_LockArrays(0, numverts); R_Mesh_Draw(numverts, numtriangles, elements); GL_LockArrays(0, 0); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; - - memset(&m, 0, sizeof(m)); - m.pointer_vertex = vertex3f; - R_Mesh_State(&m); - GL_LockArrays(0, numverts); - // square alpha in framebuffer a few times to make it shiny - GL_BlendFunc(GL_ZERO, GL_DST_ALPHA); - // these comments are a test run through this math for intensity 0.5 - // 0.5 * 0.5 = 0.25 (done by the BlendFunc earlier) - // 0.25 * 0.25 = 0.0625 (this is another pass) - // 0.0625 * 0.0625 = 0.00390625 (this is another pass) - R_Mesh_Draw(numverts, numtriangles, elements); - c_rt_lightmeshes++; - c_rt_lighttris += numtriangles; - R_Mesh_Draw(numverts, numtriangles, elements); - c_rt_lightmeshes++; - c_rt_lighttris += numtriangles; - GL_LockArrays(0, 0); - - memset(&m, 0, sizeof(m)); - m.pointer_vertex = vertex3f; - m.tex3d[0] = R_GetTexture(r_shadow_attenuation3dtexture); - m.pointer_texcoord[0] = varray_texcoord3f[0]; - R_Mesh_State(&m); - GL_BlendFunc(GL_DST_ALPHA, GL_ZERO); - R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[0], numverts, vertex3f, matrix_modeltoattenuationxyz); - GL_LockArrays(0, numverts); - R_Mesh_Draw(numverts, numtriangles, elements); - GL_LockArrays(0, 0); - c_rt_lightmeshes++; - c_rt_lighttris += numtriangles; - - memset(&m, 0, sizeof(m)); - m.pointer_vertex = vertex3f; - m.tex[0] = R_GetTexture(glosstexture); - if (lightcubemap) + } + } + if ((lighting & LIGHTING_SPECULAR) && (r_shadow_gloss.integer >= 2 || (r_shadow_gloss.integer >= 1 && glosstexture != r_shadow_blankglosstexture))) + { + // FIXME: detect blendsquare! + //if (gl_support_blendsquare) + { + colorscale = r_shadow_lightintensityscale.value * r_shadow_glossintensity.value; + if (glosstexture == r_shadow_blankglosstexture) + colorscale *= r_shadow_gloss2intensity.value; + GL_Color(1,1,1,1); + if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && lightcubemap /*&& gl_support_blendsquare*/) // FIXME: detect blendsquare! { - m.texcubemap[1] = R_GetTexture(lightcubemap); - m.pointer_texcoord[1] = varray_texcoord3f[1]; - R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltolight); + // 2/0/0/1/2 3D combine blendsquare path + memset(&m, 0, sizeof(m)); + m.pointer_vertex = vertex3f; + m.tex[0] = R_GetTexture(bumptexture); + m.pointer_texcoord[0] = texcoord2f; + m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture); + m.texcombinergb[1] = GL_DOT3_RGBA_ARB; + m.pointer_texcoord3f[1] = varray_texcoord3f[1]; + R_Shadow_GenTexCoords_Specular_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin, relativeeyeorigin); + R_Mesh_State(&m); + GL_ColorMask(0,0,0,1); + // this squares the result + GL_BlendFunc(GL_SRC_ALPHA, GL_ZERO); + GL_LockArrays(0, numverts); + R_Mesh_Draw(numverts, numtriangles, elements); + GL_LockArrays(0, 0); + c_rt_lightmeshes++; + c_rt_lighttris += numtriangles; + + memset(&m, 0, sizeof(m)); + m.pointer_vertex = vertex3f; + R_Mesh_State(&m); + GL_LockArrays(0, numverts); + // square alpha in framebuffer a few times to make it shiny + GL_BlendFunc(GL_ZERO, GL_DST_ALPHA); + // these comments are a test run through this math for intensity 0.5 + // 0.5 * 0.5 = 0.25 (done by the BlendFunc earlier) + // 0.25 * 0.25 = 0.0625 (this is another pass) + // 0.0625 * 0.0625 = 0.00390625 (this is another pass) + R_Mesh_Draw(numverts, numtriangles, elements); + c_rt_lightmeshes++; + c_rt_lighttris += numtriangles; + R_Mesh_Draw(numverts, numtriangles, elements); + c_rt_lightmeshes++; + c_rt_lighttris += numtriangles; + GL_LockArrays(0, 0); + + memset(&m, 0, sizeof(m)); + m.pointer_vertex = vertex3f; + m.tex3d[0] = R_GetTexture(r_shadow_attenuation3dtexture); +#if USETEXMATRIX + m.pointer_texcoord3f[0] = vertex3f; + m.texmatrix[0] = *matrix_modeltoattenuationxyz; +#else + m.pointer_texcoord3f[0] = varray_texcoord3f[0]; + R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[0], numverts, vertex3f, matrix_modeltoattenuationxyz); +#endif + R_Mesh_State(&m); + GL_BlendFunc(GL_DST_ALPHA, GL_ZERO); + GL_LockArrays(0, numverts); + R_Mesh_Draw(numverts, numtriangles, elements); + GL_LockArrays(0, 0); + c_rt_lightmeshes++; + c_rt_lighttris += numtriangles; + + memset(&m, 0, sizeof(m)); + m.pointer_vertex = vertex3f; + m.tex[0] = R_GetTexture(glosstexture); + m.pointer_texcoord[0] = texcoord2f; + if (lightcubemap) + { + m.texcubemap[1] = R_GetTexture(lightcubemap); +#if USETEXMATRIX + m.pointer_texcoord3f[1] = vertex3f; + m.texmatrix[1] = *matrix_modeltolight; +#else + m.pointer_texcoord3f[1] = varray_texcoord3f[1]; + R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltolight); +#endif + } } - m.pointer_texcoord[0] = texcoord2f; - R_Mesh_State(&m); - GL_LockArrays(0, numverts); - GL_ColorMask(1,1,1,0); - GL_BlendFunc(GL_DST_ALPHA, GL_ONE); - VectorScale(lightcolor, colorscale, color2); - for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--) + else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && !lightcubemap /*&& gl_support_blendsquare*/) // FIXME: detect blendsquare! { - color[0] = bound(0, color2[0], 1); - color[1] = bound(0, color2[1], 1); - color[2] = bound(0, color2[2], 1); - GL_Color(color[0], color[1], color[2], 1); + // 2/0/0/2 3D combine blendsquare path + memset(&m, 0, sizeof(m)); + m.pointer_vertex = vertex3f; + m.tex[0] = R_GetTexture(bumptexture); + m.pointer_texcoord[0] = texcoord2f; + m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture); + m.texcombinergb[1] = GL_DOT3_RGBA_ARB; + m.pointer_texcoord3f[1] = varray_texcoord3f[1]; + R_Shadow_GenTexCoords_Specular_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin, relativeeyeorigin); + R_Mesh_State(&m); + GL_ColorMask(0,0,0,1); + // this squares the result + GL_BlendFunc(GL_SRC_ALPHA, GL_ZERO); + GL_LockArrays(0, numverts); + R_Mesh_Draw(numverts, numtriangles, elements); + GL_LockArrays(0, 0); + c_rt_lightmeshes++; + c_rt_lighttris += numtriangles; + + memset(&m, 0, sizeof(m)); + m.pointer_vertex = vertex3f; + R_Mesh_State(&m); + GL_LockArrays(0, numverts); + // square alpha in framebuffer a few times to make it shiny + GL_BlendFunc(GL_ZERO, GL_DST_ALPHA); + // these comments are a test run through this math for intensity 0.5 + // 0.5 * 0.5 = 0.25 (done by the BlendFunc earlier) + // 0.25 * 0.25 = 0.0625 (this is another pass) + // 0.0625 * 0.0625 = 0.00390625 (this is another pass) R_Mesh_Draw(numverts, numtriangles, elements); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; + R_Mesh_Draw(numverts, numtriangles, elements); + c_rt_lightmeshes++; + c_rt_lighttris += numtriangles; + GL_LockArrays(0, 0); + + memset(&m, 0, sizeof(m)); + m.pointer_vertex = vertex3f; + m.tex[0] = R_GetTexture(glosstexture); + m.pointer_texcoord[0] = texcoord2f; + m.tex3d[1] = R_GetTexture(r_shadow_attenuation3dtexture); +#if USETEXMATRIX + m.pointer_texcoord3f[1] = vertex3f; + m.texmatrix[1] = *matrix_modeltoattenuationxyz; +#else + m.pointer_texcoord3f[1] = varray_texcoord3f[1]; + R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltoattenuationxyz); +#endif } - GL_LockArrays(0, 0); - } - else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && !lightcubemap /*&& gl_support_blendsquare*/) // FIXME: detect blendsquare! - { - // 2/0/0/2 3D combine blendsquare path - memset(&m, 0, sizeof(m)); - m.pointer_vertex = vertex3f; - m.tex[0] = R_GetTexture(bumptexture); - m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture); - m.texcombinergb[1] = GL_DOT3_RGBA_ARB; - m.pointer_texcoord[0] = texcoord2f; - m.pointer_texcoord[1] = varray_texcoord3f[1]; - R_Mesh_State(&m); - GL_ColorMask(0,0,0,1); - // this squares the result - GL_BlendFunc(GL_SRC_ALPHA, GL_ZERO); - R_Shadow_GenTexCoords_Specular_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin, relativeeyeorigin); - GL_LockArrays(0, numverts); - R_Mesh_Draw(numverts, numtriangles, elements); - GL_LockArrays(0, 0); - c_rt_lightmeshes++; - c_rt_lighttris += numtriangles; - - memset(&m, 0, sizeof(m)); - m.pointer_vertex = vertex3f; - R_Mesh_State(&m); - GL_LockArrays(0, numverts); - // square alpha in framebuffer a few times to make it shiny - GL_BlendFunc(GL_ZERO, GL_DST_ALPHA); - // these comments are a test run through this math for intensity 0.5 - // 0.5 * 0.5 = 0.25 (done by the BlendFunc earlier) - // 0.25 * 0.25 = 0.0625 (this is another pass) - // 0.0625 * 0.0625 = 0.00390625 (this is another pass) - R_Mesh_Draw(numverts, numtriangles, elements); - c_rt_lightmeshes++; - c_rt_lighttris += numtriangles; - R_Mesh_Draw(numverts, numtriangles, elements); - c_rt_lightmeshes++; - c_rt_lighttris += numtriangles; - GL_LockArrays(0, 0); - - memset(&m, 0, sizeof(m)); - m.pointer_vertex = vertex3f; - m.tex[0] = R_GetTexture(glosstexture); - m.tex3d[1] = R_GetTexture(r_shadow_attenuation3dtexture); - m.pointer_texcoord[0] = texcoord2f; - m.pointer_texcoord[1] = varray_texcoord3f[1]; - R_Mesh_State(&m); - GL_LockArrays(0, numverts); - GL_ColorMask(1,1,1,0); - GL_BlendFunc(GL_DST_ALPHA, GL_ONE); - R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltoattenuationxyz); - VectorScale(lightcolor, colorscale, color2); - for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--) + else { - color[0] = bound(0, color2[0], 1); - color[1] = bound(0, color2[1], 1); - color[2] = bound(0, color2[2], 1); - GL_Color(color[0], color[1], color[2], 1); + // 2/0/0/2/2 2D combine blendsquare path + memset(&m, 0, sizeof(m)); + m.pointer_vertex = vertex3f; + m.tex[0] = R_GetTexture(bumptexture); + m.pointer_texcoord[0] = texcoord2f; + m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture); + m.texcombinergb[1] = GL_DOT3_RGBA_ARB; + m.pointer_texcoord3f[1] = varray_texcoord3f[1]; + R_Shadow_GenTexCoords_Specular_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin, relativeeyeorigin); + R_Mesh_State(&m); + GL_ColorMask(0,0,0,1); + // this squares the result + GL_BlendFunc(GL_SRC_ALPHA, GL_ZERO); + GL_LockArrays(0, numverts); + R_Mesh_Draw(numverts, numtriangles, elements); + GL_LockArrays(0, 0); + c_rt_lightmeshes++; + c_rt_lighttris += numtriangles; + + memset(&m, 0, sizeof(m)); + m.pointer_vertex = vertex3f; + R_Mesh_State(&m); + GL_LockArrays(0, numverts); + // square alpha in framebuffer a few times to make it shiny + GL_BlendFunc(GL_ZERO, GL_DST_ALPHA); + // these comments are a test run through this math for intensity 0.5 + // 0.5 * 0.5 = 0.25 (done by the BlendFunc earlier) + // 0.25 * 0.25 = 0.0625 (this is another pass) + // 0.0625 * 0.0625 = 0.00390625 (this is another pass) + R_Mesh_Draw(numverts, numtriangles, elements); + c_rt_lightmeshes++; + c_rt_lighttris += numtriangles; + R_Mesh_Draw(numverts, numtriangles, elements); + c_rt_lightmeshes++; + c_rt_lighttris += numtriangles; + GL_LockArrays(0, 0); + + memset(&m, 0, sizeof(m)); + m.pointer_vertex = vertex3f; + m.tex[0] = R_GetTexture(r_shadow_attenuation2dtexture); +#if USETEXMATRIX + m.pointer_texcoord3f[0] = vertex3f; + m.texmatrix[0] = *matrix_modeltoattenuationxyz; +#else + m.pointer_texcoord[0] = varray_texcoord2f[0]; + R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[0], numverts, vertex3f, matrix_modeltoattenuationxyz); +#endif + m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture); +#if USETEXMATRIX + m.pointer_texcoord3f[1] = vertex3f; + m.texmatrix[1] = *matrix_modeltoattenuationz; +#else + m.pointer_texcoord[1] = varray_texcoord2f[1]; + R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[1], numverts, vertex3f, matrix_modeltoattenuationz); +#endif + R_Mesh_State(&m); + GL_BlendFunc(GL_DST_ALPHA, GL_ZERO); + GL_LockArrays(0, numverts); R_Mesh_Draw(numverts, numtriangles, elements); + GL_LockArrays(0, 0); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; + + memset(&m, 0, sizeof(m)); + m.pointer_vertex = vertex3f; + m.tex[0] = R_GetTexture(glosstexture); + m.pointer_texcoord[0] = texcoord2f; + if (lightcubemap) + { + m.texcubemap[1] = R_GetTexture(lightcubemap); +#if USETEXMATRIX + m.pointer_texcoord3f[1] = vertex3f; + m.texmatrix[1] = *matrix_modeltolight; +#else + m.pointer_texcoord3f[1] = varray_texcoord3f[1]; + R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltolight); +#endif + } } - GL_LockArrays(0, 0); } - else if (r_textureunits.integer >= 2 /*&& gl_support_blendsquare*/) // FIXME: detect blendsquare! + R_Mesh_State(&m); + GL_ColorMask(1,1,1,0); + GL_BlendFunc(GL_DST_ALPHA, GL_ONE); + VectorScale(lightcolor, colorscale, color2); + GL_LockArrays(0, numverts); + for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--) { - // 2/0/0/2/2 2D combine blendsquare path - memset(&m, 0, sizeof(m)); - m.pointer_vertex = vertex3f; - m.tex[0] = R_GetTexture(bumptexture); - m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture); - m.texcombinergb[1] = GL_DOT3_RGBA_ARB; - m.pointer_texcoord[0] = texcoord2f; - m.pointer_texcoord[1] = varray_texcoord3f[1]; - R_Mesh_State(&m); - GL_ColorMask(0,0,0,1); - // this squares the result - GL_BlendFunc(GL_SRC_ALPHA, GL_ZERO); - R_Shadow_GenTexCoords_Specular_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin, relativeeyeorigin); - GL_LockArrays(0, numverts); + GL_Color(bound(0, color2[0], 1), bound(0, color2[1], 1), bound(0, color2[2], 1), 1); R_Mesh_Draw(numverts, numtriangles, elements); - GL_LockArrays(0, 0); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; - - memset(&m, 0, sizeof(m)); - m.pointer_vertex = vertex3f; - R_Mesh_State(&m); - GL_LockArrays(0, numverts); - // square alpha in framebuffer a few times to make it shiny - GL_BlendFunc(GL_ZERO, GL_DST_ALPHA); - // these comments are a test run through this math for intensity 0.5 - // 0.5 * 0.5 = 0.25 (done by the BlendFunc earlier) - // 0.25 * 0.25 = 0.0625 (this is another pass) - // 0.0625 * 0.0625 = 0.00390625 (this is another pass) - R_Mesh_Draw(numverts, numtriangles, elements); - c_rt_lightmeshes++; - c_rt_lighttris += numtriangles; - R_Mesh_Draw(numverts, numtriangles, elements); - c_rt_lightmeshes++; - c_rt_lighttris += numtriangles; - GL_LockArrays(0, 0); - - memset(&m, 0, sizeof(m)); - m.pointer_vertex = vertex3f; - m.tex[0] = R_GetTexture(r_shadow_attenuation2dtexture); - m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture); - m.pointer_texcoord[0] = varray_texcoord2f[0]; - m.pointer_texcoord[1] = varray_texcoord2f[1]; - R_Mesh_State(&m); - GL_BlendFunc(GL_DST_ALPHA, GL_ZERO); - R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[0], numverts, vertex3f, matrix_modeltoattenuationxyz); - R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[1], numverts, vertex3f, matrix_modeltoattenuationz); - GL_LockArrays(0, numverts); - R_Mesh_Draw(numverts, numtriangles, elements); - GL_LockArrays(0, 0); - c_rt_lightmeshes++; - c_rt_lighttris += numtriangles; - - memset(&m, 0, sizeof(m)); - m.pointer_vertex = vertex3f; - m.tex[0] = R_GetTexture(glosstexture); - if (lightcubemap) - { - m.texcubemap[1] = R_GetTexture(lightcubemap); - m.pointer_texcoord[1] = varray_texcoord3f[1]; - R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltolight); - } - m.pointer_texcoord[0] = texcoord2f; - R_Mesh_State(&m); - GL_LockArrays(0, numverts); - GL_ColorMask(1,1,1,0); - GL_BlendFunc(GL_DST_ALPHA, GL_ONE); - VectorScale(lightcolor, colorscale, color2); - for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--) - { - color[0] = bound(0, color2[0], 1); - color[1] = bound(0, color2[1], 1); - color[2] = bound(0, color2[2], 1); - GL_Color(color[0], color[1], color[2], 1); - R_Mesh_Draw(numverts, numtriangles, elements); - c_rt_lightmeshes++; - c_rt_lighttris += numtriangles; - } - GL_LockArrays(0, 0); } + GL_LockArrays(0, 0); } } else @@ -1757,25 +1777,44 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements { // voodoo2 m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture); +#if USETEXMATRIX + m.pointer_texcoord3f[1] = vertex3f; + m.texmatrix[1] = *matrix_modeltoattenuationxyz; +#else m.pointer_texcoord[1] = varray_texcoord2f[1]; R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[1], numverts, vertex3f, matrix_modeltoattenuationxyz); +#endif + if (r_textureunits.integer >= 3) + { + // Geforce3/Radeon class but not using dot3 + m.tex[2] = R_GetTexture(r_shadow_attenuation2dtexture); +#if USETEXMATRIX + m.pointer_texcoord3f[2] = vertex3f; + m.texmatrix[2] = *matrix_modeltoattenuationz; +#else + m.pointer_texcoord[2] = varray_texcoord2f[2]; + R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[2], numverts, vertex3f, matrix_modeltoattenuationz); +#endif + } } R_Mesh_State(&m); - GL_LockArrays(0, numverts); for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--) { color[0] = bound(0, color2[0], 1); color[1] = bound(0, color2[1], 1); color[2] = bound(0, color2[2], 1); - if (r_textureunits.integer >= 2) - R_Shadow_VertexLightingWithXYAttenuationTexture(numverts, vertex3f, normal3f, color, matrix_modeltolight); + if (r_textureunits.integer >= 3) + R_Shadow_VertexShading(numverts, vertex3f, normal3f, color, matrix_modeltolight); + else if (r_textureunits.integer >= 2) + R_Shadow_VertexShadingWithZAttenuation(numverts, vertex3f, normal3f, color, matrix_modeltolight); else - R_Shadow_VertexLighting(numverts, vertex3f, normal3f, color, matrix_modeltolight); + R_Shadow_VertexShadingWithXYZAttenuation(numverts, vertex3f, normal3f, color, matrix_modeltolight); + GL_LockArrays(0, numverts); R_Mesh_Draw(numverts, numtriangles, elements); + GL_LockArrays(0, 0); c_rt_lightmeshes++; c_rt_lighttris += numtriangles; } - GL_LockArrays(0, 0); } } } @@ -1819,7 +1858,7 @@ void R_RTLight_UpdateFromDLight(rtlight_t *rtlight, const dlight_t *light, int i rtlight->lightmap_cullradius = bound(0, rtlight->radius, 2048.0f); rtlight->lightmap_cullradius2 = rtlight->lightmap_cullradius * rtlight->lightmap_cullradius; - VectorScale(rtlight->color, rtlight->radius * d_lightstylevalue[rtlight->style] * 0.25f, rtlight->lightmap_light); + VectorScale(rtlight->color, rtlight->radius * d_lightstylevalue[rtlight->style] * 0.125f, rtlight->lightmap_light); rtlight->lightmap_subtract = 1.0f / rtlight->lightmap_cullradius2; } @@ -1851,7 +1890,7 @@ void R_RTLight_Compile(rtlight_t *rtlight) // this variable directs the DrawShadowVolume and DrawLight code to capture into the mesh chain instead of rendering r_shadow_compilingrtlight = rtlight; R_Shadow_EnlargeClusterBuffer(model->brush.num_pvsclusters); - R_Shadow_EnlargeSurfaceBuffer(model->numsurfaces); + R_Shadow_EnlargeSurfaceBuffer(model->nummodelsurfaces); model->GetLightInfo(ent, rtlight->shadoworigin, rtlight->radius, rtlight->cullmins, rtlight->cullmaxs, r_shadow_buffer_clusterlist, r_shadow_buffer_clusterpvs, &numclusters, r_shadow_buffer_surfacelist, r_shadow_buffer_surfacepvs, &numsurfaces); if (numclusters) { @@ -1979,7 +2018,7 @@ void R_DrawRTLight(rtlight_t *rtlight, int visiblevolumes) else if (cl.worldmodel && cl.worldmodel->GetLightInfo) { R_Shadow_EnlargeClusterBuffer(cl.worldmodel->brush.num_pvsclusters); - R_Shadow_EnlargeSurfaceBuffer(cl.worldmodel->numsurfaces); + R_Shadow_EnlargeSurfaceBuffer(cl.worldmodel->nummodelsurfaces); cl.worldmodel->GetLightInfo(&cl_entities[0].render, rtlight->shadoworigin, rtlight->radius, cullmins, cullmaxs, r_shadow_buffer_clusterlist, r_shadow_buffer_clusterpvs, &numclusters, r_shadow_buffer_surfacelist, r_shadow_buffer_surfacepvs, &numsurfaces); clusterlist = r_shadow_buffer_clusterlist; clusterpvs = r_shadow_buffer_clusterpvs; @@ -2013,7 +2052,24 @@ void R_DrawRTLight(rtlight_t *rtlight, int visiblevolumes) else cubemaptexture = NULL; - shadow = rtlight->shadow && (rtlight->isstatic ? r_shadow_worldshadows.integer : r_shadow_dlightshadows.integer); +#if 1 + shadow = rtlight->shadow && (rtlight->isstatic ? r_shadow_realtime_world_shadows.integer : (r_shadow_realtime_world.integer ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer)); +#else + shadow = false; + if (rtlight->shadow) + { + if (rtlight->isstatic) + shadow = r_shadow_realtime_world_shadows.integer; + else + { + if (r_shadow_realtime_world.integer) + shadow = r_shadow_realtime_world_dlightshadows.integer; + else + shadow = r_shadow_realtime_dlight_shadows.integer; + } + } +#endif + if (shadow && (gl_stencil || visiblevolumes)) { if (!visiblevolumes) @@ -2067,7 +2123,10 @@ void R_DrawRTLight(rtlight_t *rtlight, int visiblevolumes) if (!(ent->flags & RENDER_SHADOW) || !ent->model || !ent->model->DrawShadowVolume) continue; Matrix4x4_Transform(&ent->inversematrix, rtlight->shadoworigin, relativelightorigin); - ent->model->DrawShadowVolume(ent, relativelightorigin, rtlight->radius, ent->model->numsurfaces, ent->model->surfacelist); + // light emitting entities should not cast their own shadow + if (VectorLength2(relativelightorigin) < 0.1) + continue; + ent->model->DrawShadowVolume(ent, relativelightorigin, rtlight->radius, ent->model->nummodelsurfaces, ent->model->surfacelist); } } } @@ -2108,7 +2167,7 @@ void R_DrawRTLight(rtlight_t *rtlight, int visiblevolumes) Matrix4x4_Concat(&matrix_modeltolight, &rtlight->matrix_worldtolight, &ent->matrix); Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &rtlight->matrix_worldtoattenuationxyz, &ent->matrix); Matrix4x4_Concat(&matrix_modeltoattenuationz, &rtlight->matrix_worldtoattenuationz, &ent->matrix); - ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, rtlight->radius, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, cubemaptexture, ent->model->numsurfaces, ent->model->surfacelist); + ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, rtlight->radius, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, cubemaptexture, ent->model->nummodelsurfaces, ent->model->surfacelist); } } } @@ -2188,11 +2247,19 @@ static cubemapinfo_t cubemaps[MAX_CUBEMAPS]; typedef struct suffixinfo_s { char *suffix; - int flipx, flipy, flipdiagonal; + qboolean flipx, flipy, flipdiagonal; } suffixinfo_t; static suffixinfo_t suffix[3][6] = { + { + {"px", false, false, false}, + {"nx", false, false, false}, + {"py", false, false, false}, + {"ny", false, false, false}, + {"pz", false, false, false}, + {"nz", false, false, false} + }, { {"posx", false, false, false}, {"negx", false, false, false}, @@ -2202,20 +2269,12 @@ static suffixinfo_t suffix[3][6] = {"negz", false, false, false} }, { - {"px", false, false, false}, - {"nx", false, false, false}, - {"py", false, false, false}, - {"ny", false, false, false}, - {"pz", false, false, false}, - {"nz", false, false, false} - }, - { - {"ft", true, false, true}, - {"bk", false, true, true}, - {"lf", true, true, false}, - {"rt", false, false, false}, - {"up", false, false, false}, - {"dn", false, false, false} + {"rt", true, false, true}, + {"lf", false, true, true}, + {"ft", true, true, false}, + {"bk", false, false, false}, + {"up", true, false, true}, + {"dn", true, false, true} } }; @@ -2231,30 +2290,39 @@ rtexture_t *R_Shadow_LoadCubemap(const char *basename) cubemapsize = 0; cubemappixels = NULL; cubemaptexture = NULL; + // keep trying different suffix groups (posx, px, rt) until one loads for (j = 0;j < 3 && !cubemappixels;j++) { + // load the 6 images in the suffix group for (i = 0;i < 6;i++) { + // generate an image name based on the base and and suffix snprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix); + // load it if ((image_rgba = loadimagepixels(name, false, cubemapsize, cubemapsize))) { + // an image loaded, make sure width and height are equal if (image_width == image_height) { + // if this is the first image to load successfully, allocate the cubemap memory if (!cubemappixels && image_width >= 1) { cubemapsize = image_width; - // note this clears to black, so unavailable sizes are black + // note this clears to black, so unavailable sides are black cubemappixels = Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4); } + // copy the image with any flipping needed by the suffix (px and posx types don't need flipping) if (cubemappixels) Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_rgba, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder); } else Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height); + // free the image Mem_Free(image_rgba); } } } + // if a cubemap loaded, upload it if (cubemappixels) { if (!r_shadow_filters_texturepool) @@ -2429,7 +2497,7 @@ void R_Shadow_LoadWorldLights(void) } FS_StripExtension (cl.worldmodel->name, name, sizeof (name)); strlcat (name, ".rtlights", sizeof (name)); - lightsstring = FS_LoadFile(name, false); + lightsstring = FS_LoadFile(name, tempmempool, false); if (lightsstring) { s = lightsstring; @@ -2547,7 +2615,7 @@ void R_Shadow_LoadLightsFile(void) } FS_StripExtension (cl.worldmodel->name, name, sizeof (name)); strlcat (name, ".lights", sizeof (name)); - lightsstring = FS_LoadFile(name, false); + lightsstring = FS_LoadFile(name, tempmempool, false); if (lightsstring) { s = lightsstring;