X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;ds=sidebyside;f=gl_rmain.c;h=1a8a4999e737b4534602db2671382da3278e4174;hb=e865bb5de13259629b64de5e9df153cbd3fbc84d;hp=577e6fb457167d04c012101ded47aa9b87a71ff2;hpb=a8ebe2e6a3993a953d3b9114d604c8278c3ceef3;p=xonotic%2Fdarkplaces.git diff --git a/gl_rmain.c b/gl_rmain.c index 577e6fb4..1a8a4999 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // r_main.c #include "quakedef.h" +#include "cl_dyntexture.h" #include "r_shadow.h" #include "polygon.h" #include "image.h" @@ -89,6 +90,7 @@ cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "h cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"}; cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"}; +cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"}; cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"}; cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"}; @@ -245,43 +247,49 @@ void FOG_clear(void) Cvar_Set("gl_fogblue", "0.3"); } r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f; + r_refdef.fog_start = 0; + r_refdef.fog_end = 1000000000; } -float FogPoint_World(const vec3_t p) +float FogForDistance(vec_t dist) { - int fogmasktableindex = (int)(VectorDistance((p), r_view.origin) * r_refdef.fogmasktabledistmultiplier); + unsigned int fogmasktableindex = (unsigned int)(bound(0, dist - r_refdef.fog_start, r_refdef.fog_end - r_refdef.fog_start) * r_refdef.fogmasktabledistmultiplier); return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)]; } +float FogPoint_World(const vec3_t p) +{ + return FogForDistance(VectorDistance((p), r_view.origin)); +} + float FogPoint_Model(const vec3_t p) { - int fogmasktableindex = (int)(VectorDistance((p), rsurface.modelorg) * r_refdef.fogmasktabledistmultiplier); - return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)]; + return FogForDistance(VectorDistance((p), rsurface.modelorg)); } static void R_BuildBlankTextures(void) { unsigned char data[4]; - data[0] = 128; // normal X + data[2] = 128; // normal X data[1] = 128; // normal Y - data[2] = 255; // normal Z + data[0] = 255; // normal Z data[3] = 128; // height - r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL); + r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL); data[0] = 255; data[1] = 255; data[2] = 255; data[3] = 255; - r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL); + r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL); data[0] = 128; data[1] = 128; data[2] = 128; data[3] = 255; - r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL); + r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL); data[0] = 0; data[1] = 0; data[2] = 0; data[3] = 255; - r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL); + r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL); } static void R_BuildNoTexture(void) @@ -309,19 +317,14 @@ static void R_BuildNoTexture(void) } } } - r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL); + r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL); } static void R_BuildWhiteCube(void) { unsigned char data[6*1*1*4]; - data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255; - data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255; - data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255; - data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255; - data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255; - data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255; - r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL); + memset(data, 255, sizeof(data)); + r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL); } static void R_BuildNormalizationCube(void) @@ -374,20 +377,20 @@ static void R_BuildNormalizationCube(void) break; } intensity = 127.0f / sqrt(DotProduct(v, v)); - data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]); + data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]); data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]); - data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]); + data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]); data[side][y][x][3] = 255; } } } - r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL); + r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL); } static void R_BuildFogTexture(void) { int x, b; -#define FOGWIDTH 64 +#define FOGWIDTH 256 unsigned char data1[FOGWIDTH][4]; //unsigned char data2[FOGWIDTH][4]; for (x = 0;x < FOGWIDTH;x++) @@ -402,8 +405,8 @@ static void R_BuildFogTexture(void) //data2[x][2] = 255 - b; //data2[x][3] = 255; } - r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL); - //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL); + r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL); + //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL); } static const char *builtinshaderstring = @@ -607,6 +610,8 @@ static const char *builtinshaderstring = "uniform float OffsetMapping_Scale;\n" "uniform float OffsetMapping_Bias;\n" "uniform float FogRangeRecip;\n" +"uniform float FogStart;\n" +"uniform float FogLength;\n" "\n" "uniform myhalf AmbientScale;\n" "uniform myhalf DiffuseScale;\n" @@ -796,7 +801,8 @@ static const char *builtinshaderstring = "# endif\n" "\n" " // apply lightmap color\n" -" color.rgb = myhvec4(tempcolor,1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n" +" color.rgb = color.rgb * AmbientScale + tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec3(gl_Color);\n" +" color.a *= myhalf(gl_Color.a);\n" "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n" "\n" "\n" @@ -817,7 +823,8 @@ static const char *builtinshaderstring = "# endif\n" "\n" " // apply lightmap color\n" -" color = myhvec4(tempcolor, 1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n" +" color.rgb = color.rgb * AmbientScale + tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec3(gl_Color);\n" +" color.a *= myhalf(gl_Color.a);\n" "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n" "\n" "\n" @@ -848,17 +855,18 @@ static const char *builtinshaderstring = "# endif\n" "#endif\n" "\n" -"#ifdef USEFOG\n" -" // apply fog\n" -" color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n" -"#endif\n" -"\n" "#ifdef USECONTRASTBOOST\n" " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhvec3(1, 1, 1));\n" "#endif\n" "\n" " color.rgb *= SceneBrightness;\n" "\n" +"#ifdef USEFOG\n" +" // apply fog\n" +" color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(max(0.0, min(length(EyeVectorModelSpace) - FogStart, FogLength))*FogRangeRecip, 0.0))));\n" +//" color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n" +"#endif\n" +"\n" " gl_FragColor = vec4(color);\n" "}\n" "#endif // MODE_REFRACTION\n" @@ -951,6 +959,8 @@ typedef struct r_glsl_permutation_s int loc_Color_Pants; int loc_Color_Shirt; int loc_FogRangeRecip; + int loc_FogStart; + int loc_FogLength; int loc_AmbientScale; int loc_DiffuseScale; int loc_SpecularScale; @@ -1082,6 +1092,8 @@ static void R_GLSL_CompilePermutation(const char *filename, int permutation, int p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants"); p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt"); p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip"); + p->loc_FogStart = qglGetUniformLocationARB(p->program, "FogStart"); + p->loc_FogLength = qglGetUniformLocationARB(p->program, "FogLength"); p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale"); p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale"); p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower"); @@ -1357,11 +1369,11 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl else if (mode == SHADERMODE_LIGHTDIRECTION) { if (r_glsl_permutation->loc_AmbientColor >= 0) - qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface.modellight_ambient[0] * ambientscale, rsurface.modellight_ambient[1] * ambientscale, rsurface.modellight_ambient[2] * ambientscale); + qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface.modellight_ambient[0] * ambientscale * r_refdef.lightmapintensity, rsurface.modellight_ambient[1] * ambientscale * r_refdef.lightmapintensity, rsurface.modellight_ambient[2] * ambientscale * r_refdef.lightmapintensity); if (r_glsl_permutation->loc_DiffuseColor >= 0) - qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface.modellight_diffuse[0] * diffusescale, rsurface.modellight_diffuse[1] * diffusescale, rsurface.modellight_diffuse[2] * diffusescale); + qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface.modellight_diffuse[0] * diffusescale * r_refdef.lightmapintensity, rsurface.modellight_diffuse[1] * diffusescale * r_refdef.lightmapintensity, rsurface.modellight_diffuse[2] * diffusescale * r_refdef.lightmapintensity); if (r_glsl_permutation->loc_SpecularColor >= 0) - qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale, rsurface.modellight_diffuse[1] * specularscale, rsurface.modellight_diffuse[2] * specularscale); + qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale * r_refdef.lightmapintensity, rsurface.modellight_diffuse[1] * specularscale * r_refdef.lightmapintensity, rsurface.modellight_diffuse[2] * specularscale * r_refdef.lightmapintensity); 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]); } @@ -1394,21 +1406,6 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)) qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0); else - /* - { - vec3_t fogvec; - // color.rgb *= SceneBrightness; - VectorScale(r_refdef.fogcolor, r_view.colorscale, fogvec); - if(r_glsl_permutation->loc_ContrastBoostCoeff >= 0) // need to support contrast boost - { - // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1); - fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1); - fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1); - fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1); - } - qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogvec[0], fogvec[1], fogvec[2]); - } - */ qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]); } if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]); @@ -1427,6 +1424,8 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0); } if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip); + if (r_glsl_permutation->loc_FogStart >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogStart, r_refdef.fog_start); + if (r_glsl_permutation->loc_FogLength >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogLength, r_refdef.fog_end - r_refdef.fog_start); if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower); if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value); 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); @@ -1476,50 +1475,86 @@ void R_SkinFrame_Purge(void) { if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence) { - if (s->base == r_texture_notexture) s->base = NULL; - if (s->nmap == r_texture_blanknormalmap)s->nmap = NULL; - if (s->merged == s->base) s->merged = NULL; - if (s->stain ) R_FreeTexture(s->stain );s->stain = NULL; - if (s->merged) R_FreeTexture(s->merged);s->merged = NULL; - if (s->base ) R_FreeTexture(s->base );s->base = NULL; - if (s->pants ) R_FreeTexture(s->pants );s->pants = NULL; - if (s->shirt ) R_FreeTexture(s->shirt );s->shirt = NULL; - if (s->nmap ) R_FreeTexture(s->nmap );s->nmap = NULL; - if (s->gloss ) R_FreeTexture(s->gloss );s->gloss = NULL; - if (s->glow ) R_FreeTexture(s->glow );s->glow = NULL; - if (s->fog ) R_FreeTexture(s->fog );s->fog = NULL; + if (s->merged == s->base) + s->merged = NULL; + // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black] + R_PurgeTexture(s->stain );s->stain = NULL; + R_PurgeTexture(s->merged);s->merged = NULL; + R_PurgeTexture(s->base );s->base = NULL; + R_PurgeTexture(s->pants );s->pants = NULL; + R_PurgeTexture(s->shirt );s->shirt = NULL; + R_PurgeTexture(s->nmap );s->nmap = NULL; + R_PurgeTexture(s->gloss );s->gloss = NULL; + R_PurgeTexture(s->glow );s->glow = NULL; + R_PurgeTexture(s->fog );s->fog = NULL; s->loadsequence = 0; } } } } +skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) { + skinframe_t *item; + char basename[MAX_QPATH]; + + Image_StripImageExtension(name, basename, sizeof(basename)); + + if( last == NULL ) { + int hashindex; + hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1); + item = r_skinframe.hash[hashindex]; + } else { + item = last->next; + } + + // linearly search through the hash bucket + for( ; item ; item = item->next ) { + if( !strcmp( item->basename, basename ) ) { + return item; + } + } + return NULL; +} + skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add) { skinframe_t *item; int hashindex; char basename[MAX_QPATH]; - + Image_StripImageExtension(name, basename, sizeof(basename)); hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1); for (item = r_skinframe.hash[hashindex];item;item = item->next) if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc) break; - if (!item) - { - if (!add) + + if (!item) { + rtexture_t *dyntexture; + // check whether its a dynamic texture + dyntexture = CL_GetDynTexture( basename ); + if (!add && !dyntexture) return NULL; item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array); memset(item, 0, sizeof(*item)); strlcpy(item->basename, basename, sizeof(item->basename)); + item->base = dyntexture; // either NULL or dyntexture handle item->textureflags = textureflags; item->comparewidth = comparewidth; item->compareheight = compareheight; item->comparecrc = comparecrc; - item->next = r_skinframe.hash[hashindex]; + item->next = r_skinframe.hash[hashindex]; r_skinframe.hash[hashindex] = item; } + else if( item->base == NULL ) + { + rtexture_t *dyntexture; + // check whether its a dynamic texture + // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black] + dyntexture = CL_GetDynTexture( basename ); + item->base = dyntexture; // either NULL or dyntexture handle + } + R_SkinFrame_MarkUsed(item); return item; } @@ -1551,7 +1586,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole if (skinframe && skinframe->base) return skinframe; - basepixels = loadimagepixels(name, complain, 0, 0, true); + basepixels = loadimagepixelsbgra(name, complain, true); if (basepixels == NULL) return NULL; @@ -1570,7 +1605,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole basepixels_width = image_width; basepixels_height = image_height; - skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL); + 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), NULL); if (textureflags & TEXF_ALPHA) { @@ -1588,7 +1623,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole 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_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL); + 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), NULL); Mem_Free(pixels); } } @@ -1596,35 +1631,35 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole // _norm is the name used by tenebrae and has been adopted as standard if (loadnormalmap) { - if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0, false)) != NULL) + if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL) { - skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL); + skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL); Mem_Free(pixels); pixels = NULL; } - else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0, false)) != NULL) + else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL) { pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4); - Image_HeightmapToNormalmap(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_RGBA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL); + Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value); + skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL); Mem_Free(pixels); Mem_Free(bumppixels); } else if (r_shadow_bumpscale_basetexture.value > 0) { pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4); - Image_HeightmapToNormalmap(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_RGBA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL); + Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value); + skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL); Mem_Free(pixels); } } // _luma is supported for tenebrae compatibility // (I think it's a very stupid name, but oh well) // _glow is the preferred name - if (loadglow && ((pixels = loadimagepixels(va("%s_glow", skinframe->basename), false, 0, 0, false)) != NULL || (pixels = loadimagepixels(va("%s_luma", skinframe->basename), false, 0, 0, false)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;} - if (loadgloss && (pixels = loadimagepixels(va("%s_gloss", skinframe->basename), false, 0, 0, false)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;} - if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_pants", skinframe->basename), false, 0, 0, false)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;} - if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_shirt", skinframe->basename), false, 0, 0, false)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;} + if (loadglow && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) != NULL || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false)) != NULL)) {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), NULL);Mem_Free(pixels);pixels = NULL;} + if (loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)) != NULL) {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), NULL);Mem_Free(pixels);pixels = NULL;} + if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)) != NULL) {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), NULL);Mem_Free(pixels);pixels = NULL;} + if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)) != NULL) {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), NULL);Mem_Free(pixels);pixels = NULL;} if (basepixels) Mem_Free(basepixels); @@ -1646,7 +1681,8 @@ static rtexture_t *R_SkinFrame_TextureForSkinLayer(const unsigned char *in, int return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette); } -skinframe_t *R_SkinFrame_LoadInternal(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height, int bitsperpixel, const unsigned int *palette, const unsigned int *alphapalette) +// this is only used by .spr32 sprites, HL .spr files, HL .bsp files +skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height) { int i; unsigned char *temp1, *temp2; @@ -1656,7 +1692,7 @@ skinframe_t *R_SkinFrame_LoadInternal(const char *name, int textureflags, int lo return NULL; // if already loaded just return it, otherwise make a new skinframe - skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true); + skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true); if (skinframe && skinframe->base) return skinframe; @@ -1674,77 +1710,95 @@ skinframe_t *R_SkinFrame_LoadInternal(const char *name, int textureflags, int lo if (!skindata) return NULL; - if (bitsperpixel == 32) + if (r_shadow_bumpscale_basetexture.value > 0) { - if (r_shadow_bumpscale_basetexture.value > 0) - { - temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8); - temp2 = temp1 + width * height * 4; - Image_HeightmapToNormalmap(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_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL); - Mem_Free(temp1); - } - skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, skinframe->textureflags, NULL); - if (textureflags & TEXF_ALPHA) - { - for (i = 3;i < width * height * 4;i += 4) - if (skindata[i] < 255) - break; - if (i < width * height * 4) - { - unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 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_RGBA, skinframe->textureflags, NULL); - Mem_Free(fogpixels); - } - } + 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, NULL); + Mem_Free(temp1); } - else if (bitsperpixel == 8) + skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL); + if (textureflags & TEXF_ALPHA) { - if (r_shadow_bumpscale_basetexture.value > 0) - { - temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8); - temp2 = temp1 + width * height * 4; - if (bitsperpixel == 32) - Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value); - else - { - // use either a custom palette or the quake palette - Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete); - Image_HeightmapToNormalmap(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_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL); - Mem_Free(temp1); - } - // use either a custom palette, or the quake palette - skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette ? palette : (loadglowtexture ? palette_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_transparent : palette_complete)), skinframe->textureflags, true); // all - if (!palette && loadglowtexture) - skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, skinframe->textureflags, false); // glow - if (!palette && loadpantsandshirt) - { - skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, skinframe->textureflags, false); // pants - skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, skinframe->textureflags, false); // shirt - } - if (skinframe->pants || skinframe->shirt) - skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, skinframe->textureflags, false); // no special colors - if (textureflags & TEXF_ALPHA) + for (i = 3;i < width * height * 4;i += 4) + if (skindata[i] < 255) + break; + if (i < width * height * 4) { - // if not using a custom alphapalette, use the quake one - if (!alphapalette) - alphapalette = palette_alpha; - for (i = 0;i < width * height;i++) - if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255) - break; - if (i < width * height) - skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, skinframe->textureflags, true); // fog mask + unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 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, NULL); + Mem_Free(fogpixels); } } return skinframe; } +skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height) +{ + int i; + unsigned char *temp1, *temp2; + skinframe_t *skinframe; + + if (cls.state == ca_dedicated) + return NULL; + + // if already loaded just return it, otherwise make a new skinframe + skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true); + if (skinframe && skinframe->base) + return skinframe; + + skinframe->stain = NULL; + skinframe->merged = NULL; + skinframe->base = r_texture_notexture; + skinframe->pants = NULL; + skinframe->shirt = NULL; + skinframe->nmap = r_texture_blanknormalmap; + skinframe->gloss = NULL; + skinframe->glow = NULL; + skinframe->fog = NULL; + + // if no data was provided, then clearly the caller wanted to get a blank skinframe + if (!skindata) + return NULL; + + if (r_shadow_bumpscale_basetexture.value > 0) + { + temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8); + temp2 = temp1 + width * height * 4; + // 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, NULL); + Mem_Free(temp1); + } + // use either a custom palette, or the quake palette + skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete)), skinframe->textureflags, true); // all + if (loadglowtexture) + skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow + if (loadpantsandshirt) + { + skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants + skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt + } + if (skinframe->pants || skinframe->shirt) + skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename), loadglowtexture ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap, skinframe->textureflags, false); // no special colors + if (textureflags & TEXF_ALPHA) + { + for (i = 0;i < width * height;i++) + if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255) + break; + if (i < width * height) + skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask + } + + return skinframe; +} + skinframe_t *R_SkinFrame_LoadMissing(void) { skinframe_t *skinframe; @@ -1771,10 +1825,10 @@ void gl_main_start(void) int x; double r, alpha; - r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH); + r = -16.0 / (1.0 * FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH); for (x = 0;x < FOGMASKTABLEWIDTH;x++) { - alpha = 1 - exp(r / ((double)x*(double)x)); + alpha = exp(r * ((double)x*(double)x)); if (x == FOGMASKTABLEWIDTH - 1) alpha = 0; r_refdef.fogmasktable[x] = bound(0, alpha, 1); @@ -1911,6 +1965,7 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_water_reflectdistort); Cvar_RegisterVariable(&r_lerpsprites); Cvar_RegisterVariable(&r_lerpmodels); + Cvar_RegisterVariable(&r_lerplightstyles); Cvar_RegisterVariable(&r_waterscroll); Cvar_RegisterVariable(&r_bloom); Cvar_RegisterVariable(&r_bloom_colorscale); @@ -1945,7 +2000,6 @@ extern void GL_Main_Init(void); extern void R_Shadow_Init(void); extern void R_Sky_Init(void); extern void GL_Surf_Init(void); -extern void R_Light_Init(void); extern void R_Particles_Init(void); extern void R_Explosion_Init(void); extern void gl_backend_init(void); @@ -1963,7 +2017,6 @@ void Render_Init(void) R_Sky_Init(); GL_Surf_Init(); Sbar_Init(); - R_Light_Init(); R_Particles_Init(); R_Explosion_Init(); R_LightningBeams_Init(); @@ -2088,43 +2141,6 @@ int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, c //================================================================================== -static void R_UpdateEntityLighting(entity_render_t *ent) -{ - vec3_t tempdiffusenormal; - - // fetch the lighting from the worldmodel data - VectorSet(ent->modellight_ambient, r_ambient.value * (2.0f / 128.0f), r_ambient.value * (2.0f / 128.0f), r_ambient.value * (2.0f / 128.0f)); - VectorClear(ent->modellight_diffuse); - VectorClear(tempdiffusenormal); - if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint) - { - vec3_t org; - Matrix4x4_OriginFromMatrix(&ent->matrix, org); - r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal); - } - else // highly rare - VectorSet(ent->modellight_ambient, 1, 1, 1); - - // move the light direction into modelspace coordinates for lighting code - Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir); - if(VectorLength2(ent->modellight_lightdir) > 0) - { - VectorNormalize(ent->modellight_lightdir); - } - else - { - VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here - } - - // scale ambient and directional light contributions according to rendering variables - ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity; - ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity; - ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity; - ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity; - ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity; - ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity; -} - static void R_View_UpdateEntityVisible (void) { int i, renderimask; @@ -2140,7 +2156,7 @@ static void R_View_UpdateEntityVisible (void) for (i = 0;i < r_refdef.numentities;i++) { ent = r_refdef.entities[i]; - r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs)) && ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_viewcache.world_leafvisible, ent->mins, ent->maxs)); + r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs)) && ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_viewcache.world_leafvisible, ent->mins, ent->maxs)); } if(r_cullentities_trace.integer) @@ -2164,13 +2180,9 @@ static void R_View_UpdateEntityVisible (void) for (i = 0;i < r_refdef.numentities;i++) { ent = r_refdef.entities[i]; - r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs)); + r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs)); } } - - // update entity lighting (even on hidden entities for r_shadows) - for (i = 0;i < r_refdef.numentities;i++) - R_UpdateEntityLighting(r_refdef.entities[i]); } // only used if skyrendermasked, and normally returns false @@ -2650,14 +2662,12 @@ static void R_Water_AddWaterPlane(msurface_t *surface) { int triangleindex, planeindex; const int *e; - vec_t f; vec3_t vert[3]; vec3_t normal; vec3_t center; r_waterstate_waterplane_t *p; // just use the first triangle with a valid normal for any decisions VectorClear(normal); - VectorClear(center); for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3) { Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]); @@ -2667,14 +2677,6 @@ static void R_Water_AddWaterPlane(msurface_t *surface) if (VectorLength2(normal) >= 0.001) break; } - // now find the center of this surface - for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles*3;triangleindex++, e++) - { - Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]); - VectorAdd(center, vert[0], center); - } - f = 1.0 / surface->num_triangles*3; - VectorScale(center, f, center); // find a matching plane if there is one for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++) @@ -2706,9 +2708,11 @@ static void R_Water_AddWaterPlane(msurface_t *surface) // merge this surface's materialflags into the waterplane p->materialflags |= surface->texture->currentframe->currentmaterialflags; // merge this surface's PVS into the waterplane - if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.worldmodel && r_refdef.worldmodel->brush.FatPVS) + VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center); + if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.worldmodel && r_refdef.worldmodel->brush.FatPVS + && r_refdef.worldmodel->brush.PointInLeaf && r_refdef.worldmodel->brush.PointInLeaf(r_refdef.worldmodel, center)->clusterindex >= 0) { - r_refdef.worldmodel->brush.FatPVS(r_refdef.worldmodel, r_view.origin, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid); + r_refdef.worldmodel->brush.FatPVS(r_refdef.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid); p->pvsvalid = true; } } @@ -2727,7 +2731,7 @@ static void R_Water_ProcessPlanes(void) if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) { if (!p->texture_refraction) - p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL); + p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL); if (!p->texture_refraction) goto error; } @@ -2735,7 +2739,7 @@ static void R_Water_ProcessPlanes(void) if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) { if (!p->texture_reflection) - p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL); + p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL); if (!p->texture_reflection) goto error; } @@ -2879,7 +2883,7 @@ void R_Bloom_StartFrame(void) r_bloomstate.screentexturewidth = screentexturewidth; r_bloomstate.screentextureheight = screentextureheight; if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight) - r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL); + r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL); } if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight) { @@ -2889,7 +2893,7 @@ void R_Bloom_StartFrame(void) r_bloomstate.bloomtexturewidth = bloomtexturewidth; r_bloomstate.bloomtextureheight = bloomtextureheight; if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight) - r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL); + r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL); } // set up a texcoord array for the full resolution screen image @@ -3066,6 +3070,8 @@ void R_Bloom_MakeTexture(void) } } +static void R_UpdateFogColor(void); // needs to be called before HDR subrender too, as that changes colorscale! + void R_HDR_RenderBloomTexture(void) { int oldwidth, oldheight; @@ -3083,6 +3089,9 @@ void R_HDR_RenderBloomTexture(void) r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value; if (r_hdr.integer) r_view.colorscale /= r_hdr_range.value; + + R_UpdateFogColor(); + r_waterstate.numwaterplanes = 0; R_RenderScene(r_waterstate.enabled); r_view.showdebug = true; @@ -3171,6 +3180,32 @@ void R_RenderScene(qboolean addwaterplanes); matrix4x4_t r_waterscrollmatrix; +static void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale! +{ + if (r_refdef.fog_density) + { + r_refdef.fogcolor[0] = r_refdef.fog_red; + r_refdef.fogcolor[1] = r_refdef.fog_green; + r_refdef.fogcolor[2] = r_refdef.fog_blue; + + { + vec3_t fogvec; + // color.rgb *= SceneBrightness; + VectorScale(r_refdef.fogcolor, r_view.colorscale, fogvec); + if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost + { + // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1); + fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1); + fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1); + fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1); + } + r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f); + r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f); + r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f); + } + } +} + void R_UpdateVariables(void) { R_Textures_Frame(); @@ -3220,19 +3255,23 @@ void R_UpdateVariables(void) r_refdef.fog_blue = 0; } } - if (r_refdef.fog_density) + + if (r_refdef.fog_start >= r_refdef.fog_end || r_refdef.fog_start < 0) { - r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f); - r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f); - r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f); + r_refdef.fog_start = 0; + r_refdef.fog_end = 1000000000; + // TODO update fog cvars here too } + + R_UpdateFogColor(); + if (r_refdef.fog_density) { r_refdef.fogenabled = true; // this is the point where the fog reaches 0.9986 alpha, which we // consider a good enough cutoff point for the texture // (0.9986 * 256 == 255.6) - r_refdef.fogrange = 400 / r_refdef.fog_density; + r_refdef.fogrange = 16 / (r_refdef.fog_density * r_refdef.fog_density); r_refdef.fograngerecip = 1.0f / r_refdef.fogrange; r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip; // fog color was already set @@ -3781,7 +3820,7 @@ void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_ R_Mesh_TexBind(0, R_GetTexture(fogtexture)); GL_BlendFunc(blendfunc1, GL_ONE); fog = 1 - fog; - GL_Color(r_refdef.fogcolor[0] * fog * r_view.colorscale, r_refdef.fogcolor[1] * fog * r_view.colorscale, r_refdef.fogcolor[2] * fog * r_view.colorscale, ca); + GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca); R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); } } @@ -4023,7 +4062,12 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)) t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND; - for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++) + // make sure that the waterscroll matrix is used on water surfaces when + // there is no tcmod + if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0) + t->currenttexmatrix = r_waterscrollmatrix; + + for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++) { matrix4x4_t matrix; switch(tcmod->tcmod) @@ -4113,17 +4157,6 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) t->specularscale = 0; } - t->currentpolygonfactor = r_refdef.polygonfactor + t->basepolygonfactor; - t->currentpolygonoffset = r_refdef.polygonoffset + t->basepolygonoffset; - // submodels are biased to avoid z-fighting with world surfaces that they - // may be exactly overlapping (avoids z-fighting artifacts on certain - // doors and things in Quake maps) - if (ent->model->brush.submodel) - { - t->currentpolygonfactor += r_polygonoffset_submodel_factor.value; - t->currentpolygonoffset += r_polygonoffset_submodel_offset.value; - } - VectorClear(t->dlightcolor); t->currentnumlayers = 0; if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW)) @@ -4179,7 +4212,7 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) // applied to the color // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright) if (ent->model->type == mod_brushq3) - colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f); + colorscale *= r_refdef.rtlightstylevalue[0]; colorscale *= r_refdef.lightmapintensity; R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha); if (r_ambient.value >= (1.0f/64.0f)) @@ -4349,6 +4382,13 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q rsurface.frameblend[1] = ent->frameblend[1]; rsurface.frameblend[2] = ent->frameblend[2]; rsurface.frameblend[3] = ent->frameblend[3]; + rsurface.basepolygonfactor = r_refdef.polygonfactor; + rsurface.basepolygonoffset = r_refdef.polygonoffset; + if (ent->model->brush.submodel) + { + rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value; + rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value; + } if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0)) { if (wanttangents) @@ -5280,12 +5320,13 @@ static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t // TODO: optimize // model lighting VectorCopy(rsurface.modellight_lightdir, lightdir); - ambientcolor[0] = rsurface.modellight_ambient[0] * r * 0.5f; - ambientcolor[1] = rsurface.modellight_ambient[1] * g * 0.5f; - ambientcolor[2] = rsurface.modellight_ambient[2] * b * 0.5f; - diffusecolor[0] = rsurface.modellight_diffuse[0] * r * 0.5f; - diffusecolor[1] = rsurface.modellight_diffuse[1] * g * 0.5f; - diffusecolor[2] = rsurface.modellight_diffuse[2] * b * 0.5f; + f = 0.5f * r_refdef.lightmapintensity; + ambientcolor[0] = rsurface.modellight_ambient[0] * r * f; + ambientcolor[1] = rsurface.modellight_ambient[1] * g * f; + ambientcolor[2] = rsurface.modellight_ambient[2] * b * f; + diffusecolor[0] = rsurface.modellight_diffuse[0] * r * f; + diffusecolor[1] = rsurface.modellight_diffuse[1] * g * f; + diffusecolor[2] = rsurface.modellight_diffuse[2] * b * f; if (VectorLength2(diffusecolor) > 0) { // generate color arrays for the surfaces in this list @@ -5331,12 +5372,20 @@ static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); } -static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist) +void RSurf_SetupDepthAndCulling(void) { + // submodels are biased to avoid z-fighting with world surfaces that they + // may be exactly overlapping (avoids z-fighting artifacts on certain + // doors and things in Quake maps) GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1); - GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset); + GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset); GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST)); GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back); +} + +static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist) +{ + RSurf_SetupDepthAndCulling(); if (rsurface.mode != RSURFMODE_SHOWSURFACES) { rsurface.mode = RSURFMODE_SHOWSURFACES; @@ -5369,10 +5418,7 @@ static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **te // restore entity matrix R_Mesh_Matrix(&rsurface.matrix); } - GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1); - GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset); - GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST)); - GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back); + RSurf_SetupDepthAndCulling(); GL_DepthMask(true); // LordHavoc: HalfLife maps have freaky skypolys so don't use // skymasking on them, and Quake3 never did sky masking (unlike @@ -5812,9 +5858,7 @@ static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **textur GL_ColorMask(0,0,0,0); GL_Color(1,1,1,1); } - GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1); - GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset); - GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back); + RSurf_SetupDepthAndCulling(); GL_DepthTest(true); GL_BlendFunc(GL_ONE, GL_ZERO); GL_DepthMask(true); @@ -5836,10 +5880,8 @@ static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **textur { if (rsurface.mode != RSURFMODE_MULTIPASS) rsurface.mode = RSURFMODE_MULTIPASS; - GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1); - GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset); + RSurf_SetupDepthAndCulling(); GL_DepthTest(true); - GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back); GL_BlendFunc(GL_ONE, GL_ZERO); GL_DepthMask(writedepth); GL_Color(1,1,1,1); @@ -5883,10 +5925,7 @@ static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **textur // write depth for anything we skipped on the depth-only pass earlier if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) writedepth = true; - GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1); - GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset); - GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST)); - GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back); + RSurf_SetupDepthAndCulling(); GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED)); GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0); @@ -6161,35 +6200,38 @@ void R_DrawDebugModel(entity_render_t *ent) } if (r_shownormals.value > 0) { - GL_Color(r_view.colorscale, 0, 0, r_shownormals.value); qglBegin(GL_LINES); for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++) { VectorCopy(rsurface.vertex3f + l * 3, v); + GL_Color(r_view.colorscale, 0, 0, 1); qglVertex3f(v[0], v[1], v[2]); - VectorMA(v, 8, rsurface.svector3f + l * 3, v); + VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v); + GL_Color(r_view.colorscale, 1, 1, 1); qglVertex3f(v[0], v[1], v[2]); } qglEnd(); CHECKGLERROR - GL_Color(0, 0, r_view.colorscale, r_shownormals.value); qglBegin(GL_LINES); for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++) { VectorCopy(rsurface.vertex3f + l * 3, v); + GL_Color(0, r_view.colorscale, 0, 1); qglVertex3f(v[0], v[1], v[2]); - VectorMA(v, 8, rsurface.tvector3f + l * 3, v); + VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v); + GL_Color(r_view.colorscale, 1, 1, 1); qglVertex3f(v[0], v[1], v[2]); } qglEnd(); CHECKGLERROR - GL_Color(0, r_view.colorscale, 0, r_shownormals.value); qglBegin(GL_LINES); for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++) { VectorCopy(rsurface.vertex3f + l * 3, v); + GL_Color(0, 0, r_view.colorscale, 1); qglVertex3f(v[0], v[1], v[2]); - VectorMA(v, 8, rsurface.normal3f + l * 3, v); + VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v); + GL_Color(r_view.colorscale, 1, 1, 1); qglVertex3f(v[0], v[1], v[2]); } qglEnd(); @@ -6205,7 +6247,7 @@ extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface); void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug) { int i, j, endj, f, flagsmask; - msurface_t *surface, **surfacechain; + msurface_t *surface; texture_t *t; model_t *model = r_refdef.worldmodel; const int maxsurfacelist = 1024; @@ -6216,17 +6258,19 @@ void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean dep RSurf_ActiveWorldEntity(); - // update light styles - if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains) + // update light styles on this submodel + if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0) { - for (i = 0;i < model->brushq1.light_styles;i++) + model_brush_lightstyleinfo_t *style; + for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++) { - if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]]) + if (style->value != r_refdef.lightstylevalue[style->style]) { - model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]]; - if ((surfacechain = model->brushq1.light_styleupdatechains[i])) - for (;(surface = *surfacechain);surfacechain++) - surface->cached_dlight = true; + msurface_t *surfaces = model->data_surfaces; + int *list = style->surfacelist; + style->value = r_refdef.lightstylevalue[style->style]; + for (j = 0;j < style->numsurfaces;j++) + surfaces[list[j]].cached_dlight = true; } } } @@ -6283,8 +6327,8 @@ void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean dep void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug) { - int i, f, flagsmask; - msurface_t *surface, *endsurface, **surfacechain; + int i, j, f, flagsmask; + msurface_t *surface, *endsurface; texture_t *t; model_t *model = ent->model; const int maxsurfacelist = 1024; @@ -6304,16 +6348,18 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly); // update light styles - if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains) + if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0) { - for (i = 0;i < model->brushq1.light_styles;i++) + model_brush_lightstyleinfo_t *style; + for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++) { - if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]]) + if (style->value != r_refdef.lightstylevalue[style->style]) { - model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]]; - if ((surfacechain = model->brushq1.light_styleupdatechains[i])) - for (;(surface = *surfacechain);surfacechain++) - surface->cached_dlight = true; + msurface_t *surfaces = model->data_surfaces; + int *list = style->surfacelist; + style->value = r_refdef.lightstylevalue[style->style]; + for (j = 0;j < style->numsurfaces;j++) + surfaces[list[j]].cached_dlight = true; } } }