X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=gl_rmain.c;h=8bf14a8afd42673e1fa13b42bc2deb6f3dcad96b;hb=360452cf7e3c6d203c3aed9ddf3f3f1993f46be4;hp=1ebe76c788c9bf66384b804262d6edcdc8a2a8bd;hpb=52c7f899aabced8885deb6bbb38a696c707afcd3;p=xonotic%2Fdarkplaces.git diff --git a/gl_rmain.c b/gl_rmain.c index 1ebe76c7..8bf14a8a 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -34,6 +34,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern LPDIRECT3DDEVICE9 vid_d3d9dev; #endif +#ifdef WIN32 +// Enable NVIDIA High Performance Graphics while using Integrated Graphics. +#ifdef __cplusplus +extern "C" { +#endif +__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; +#ifdef __cplusplus +} +#endif +#endif + mempool_t *r_main_mempool; rtexturepool_t *r_main_texturepool; @@ -184,6 +195,7 @@ cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_user cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"}; cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"}; +cvar_t r_water_cameraentitiesonly = {CVAR_SAVE, "r_water_cameraentitiesonly", "0", "whether to only show QC-defined reflections/refractions (typically used for camera- or portal-like effects)"}; cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"}; cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"}; cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"}; @@ -625,9 +637,6 @@ const char *builtinhlslshaderstrings[] = 0 }; -char *glslshaderstring = NULL; -char *hlslshaderstring = NULL; - //======================================================================================================================================================= typedef struct shaderpermutationinfo_s @@ -639,9 +648,14 @@ shaderpermutationinfo_t; typedef struct shadermodeinfo_s { - const char *filename; + const char *sourcebasename; + const char *extension; + const char **builtinshaderstrings; const char *pretext; const char *name; + char *filename; + char *builtinstring; + int builtincrc; } shadermodeinfo_t; @@ -678,50 +692,53 @@ shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] = {"#define USETRIPPY\n", " trippy"}, {"#define USEDEPTHRGB\n", " depthrgb"}, {"#define USEALPHAGENVERTEX\n", " alphagenvertex"}, - {"#define USESKELETAL\n", " skeletal"} + {"#define USESKELETAL\n", " skeletal"}, + {"#define USEOCCLUDE\n", " occlude"} }; // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS! -shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] = -{ - {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"}, - {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"}, - {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"}, - {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"}, - {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"}, - {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"}, - {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"}, - {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"}, - {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"}, - {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"}, - {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"}, - {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"}, - {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"}, - {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"}, - {"glsl/default.glsl", "#define MODE_WATER\n", " water"}, - {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"}, - {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"}, -}; - -shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] = -{ - {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"}, - {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"}, - {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"}, - {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"}, - {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"}, - {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"}, - {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"}, - {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"}, - {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"}, - {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"}, - {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"}, - {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"}, - {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"}, - {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"}, - {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"}, - {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"}, - {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"}, +shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] = +{ + // SHADERLANGUAGE_GLSL + { + {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"}, + {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"}, + {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"}, + {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"}, + {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"}, + {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"}, + {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"}, + {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"}, + {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"}, + {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"}, + {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"}, + {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"}, + {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"}, + {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"}, + {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"}, + {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"}, + {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"}, + }, + // SHADERLANGUAGE_HLSL + { + {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"}, + {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"}, + {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"}, + {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"}, + {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"}, + {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"}, + {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"}, + {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"}, + {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"}, + {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"}, + {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"}, + {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"}, + {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"}, + {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"}, + {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"}, + {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"}, + {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"}, + }, }; struct r_glsl_permutation_s; @@ -895,7 +912,7 @@ extern qboolean r_shadow_shadowmapsampler; extern int r_shadow_shadowmappcf; qboolean R_CompileShader_CheckStaticParms(void) { - static int r_compileshader_staticparms_save[1]; + static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5]; memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms)); memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms)); @@ -1015,55 +1032,42 @@ static char *R_ShaderStrCat(const char **strings) return string; } -static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly) +static char *R_ShaderStrCat(const char **strings); +static void R_InitShaderModeInfo(void) { - char *shaderstring; - if (!filename || !filename[0]) - return NULL; - // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat - if (!strcmp(filename, "glsl/default.glsl")) - { - if (builtinonly) - return R_ShaderStrCat(builtinshaderstrings); - if (!glslshaderstring) - { - glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL); - if (glslshaderstring) - Con_DPrintf("Loading shaders from file %s...\n", filename); - else - glslshaderstring = R_ShaderStrCat(builtinshaderstrings); - } - shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1); - memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1); - return shaderstring; - } - if (!strcmp(filename, "hlsl/default.hlsl")) + int i, language; + shadermodeinfo_t *modeinfo; + // we have a bunch of things to compute that weren't calculated at engine compile time - all filenames should have a crc of the builtin strings to prevent accidental overrides (any customization must be updated to match engine) + for (language = 0; language < SHADERLANGUAGE_COUNT; language++) { - if (builtinonly) - return R_ShaderStrCat(builtinhlslshaderstrings); - if (!hlslshaderstring) + for (i = 0; i < SHADERMODE_COUNT; i++) { - hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL); - if (hlslshaderstring) - Con_DPrintf("Loading shaders from file %s...\n", filename); - else - hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings); + char filename[MAX_QPATH]; + modeinfo = &shadermodeinfo[language][i]; + modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings); + modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring)); + dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension); + modeinfo->filename = Mem_strdup(r_main_mempool, filename); } - shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1); - memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1); - return shaderstring; } - // we don't have builtin strings for any other files - if (builtinonly) - return NULL; - shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL); +} + +static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly) +{ + char *shaderstring; + // if the mode has no filename we have to return the builtin string + if (builtinonly || !modeinfo->filename) + return Mem_strdup(r_main_mempool, modeinfo->builtinstring); + // note that FS_LoadFile appends a 0 byte to make it a valid string + shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL); if (shaderstring) { if (printfromdisknotice) - Con_DPrintf("from disk %s... ", filename); + Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename); return shaderstring; } - return shaderstring; + // fall back to builtinstring + return Mem_strdup(r_main_mempool, modeinfo->builtinstring); } static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation) @@ -1071,7 +1075,7 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode int i; int ubibind; int sampler; - shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode; + shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode]; char *sourcestring; char permutationname[256]; int vertstrings_count = 0; @@ -1087,7 +1091,7 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode p->program = 0; permutationname[0] = 0; - sourcestring = R_GetShaderText(modeinfo->filename, true, false); + sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false); strlcat(permutationname, modeinfo->filename, sizeof(permutationname)); @@ -1629,7 +1633,7 @@ static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, c vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable); } else - vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable); + vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable); if (vsbuffer) { vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer); @@ -1652,7 +1656,7 @@ static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, c psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable); } else - psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable); + psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable); if (psbuffer) { psbinsize = ID3DXBuffer_GetBufferSize(psbuffer); @@ -1689,7 +1693,7 @@ static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, c static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation) { int i; - shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode; + shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode]; int vertstring_length = 0; int geomstring_length = 0; int fragstring_length = 0; @@ -1713,7 +1717,7 @@ static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode permutationname[0] = 0; cachename[0] = 0; - sourcestring = R_GetShaderText(modeinfo->filename, true, false); + sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false); strlcat(permutationname, modeinfo->filename, sizeof(permutationname)); strlcat(cachename, "hlsl/", sizeof(cachename)); @@ -1780,23 +1784,23 @@ static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode vertstring_length = 0; for (i = 0;i < vertstrings_count;i++) - vertstring_length += strlen(vertstrings_list[i]); + vertstring_length += (int)strlen(vertstrings_list[i]); vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1); - for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++) + for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++) memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i])); geomstring_length = 0; for (i = 0;i < geomstrings_count;i++) - geomstring_length += strlen(geomstrings_list[i]); + geomstring_length += (int)strlen(geomstrings_list[i]); geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1); - for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++) + for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++) memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i])); fragstring_length = 0; for (i = 0;i < fragstrings_count;i++) - fragstring_length += strlen(fragstrings_list[i]); + fragstring_length += (int)strlen(fragstrings_list[i]); fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1); - for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++) + for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++) memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i])); // try to load the cached shader, or generate one @@ -1887,12 +1891,6 @@ static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int per void R_GLSL_Restart_f(void) { unsigned int i, limit; - if (glslshaderstring) - Mem_Free(glslshaderstring); - glslshaderstring = NULL; - if (hlslshaderstring) - Mem_Free(hlslshaderstring); - hlslshaderstring = NULL; switch(vid.renderpath) { case RENDERPATH_D3D9: @@ -1900,7 +1898,7 @@ void R_GLSL_Restart_f(void) { r_hlsl_permutation_t *p; r_hlsl_permutation = NULL; - limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray); + limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray); for (i = 0;i < limit;i++) { if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i))) @@ -1927,7 +1925,7 @@ void R_GLSL_Restart_f(void) { r_glsl_permutation_t *p; r_glsl_permutation = NULL; - limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray); + limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray); for (i = 0;i < limit;i++) { if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i))) @@ -1955,9 +1953,9 @@ static void R_GLSL_DumpShader_f(void) shadermodeinfo_t *modeinfo; qfile_t *file; - for (language = 0;language < 2;language++) + for (language = 0;language < SHADERLANGUAGE_COUNT;language++) { - modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo); + modeinfo = shadermodeinfo[language]; for (mode = 0;mode < SHADERMODE_COUNT;mode++) { // don't dump the same file multiple times (most or all shaders come from the same file) @@ -1966,7 +1964,7 @@ static void R_GLSL_DumpShader_f(void) break; if (dupe >= 0) continue; - text = R_GetShaderText(modeinfo[mode].filename, false, true); + text = modeinfo[mode].builtinstring; if (!text) continue; file = FS_OpenRealFile(modeinfo[mode].filename, "w", false); @@ -1985,7 +1983,6 @@ static void R_GLSL_DumpShader_f(void) } else Con_Printf("failed to write to %s\n", modeinfo[mode].filename); - Mem_Free(text); } } } @@ -2123,14 +2120,15 @@ extern rtexture_t *r_shadow_attenuation2dtexture; extern rtexture_t *r_shadow_attenuation3dtexture; extern qboolean r_shadow_usingshadowmap2d; extern qboolean r_shadow_usingshadowmaportho; -extern float r_shadow_shadowmap_texturescale[2]; -extern float r_shadow_shadowmap_parameters[4]; +extern float r_shadow_modelshadowmap_texturescale[4]; +extern float r_shadow_modelshadowmap_parameters[4]; +extern float r_shadow_lightshadowmap_texturescale[4]; +extern float r_shadow_lightshadowmap_parameters[4]; extern qboolean r_shadow_shadowmapvsdct; extern rtexture_t *r_shadow_shadowmap2ddepthbuffer; extern rtexture_t *r_shadow_shadowmap2ddepthtexture; extern rtexture_t *r_shadow_shadowmapvsdcttexture; extern matrix4x4_t r_shadow_shadowmapmatrix; -extern int r_shadow_shadowmaplod; // changes for each light based on distance extern int r_shadow_prepass_width; extern int r_shadow_prepass_height; extern rtexture_t *r_shadow_prepassgeometrydepthbuffer; @@ -2202,6 +2200,8 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, permutation |= SHADERPERMUTATION_TRIPPY; if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) permutation |= SHADERPERMUTATION_ALPHAKILL; + if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE) + permutation |= SHADERPERMUTATION_OCCLUDE; if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1]) permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic if (rsurfacepass == RSURFPASS_BACKGROUND) @@ -2400,10 +2400,10 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP; if (rsurface.texture->reflectmasktexture) permutation |= SHADERPERMUTATION_REFLECTCUBE; - if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld) + if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld) { permutation |= SHADERPERMUTATION_BOUNCEGRID; - if (r_shadow_bouncegriddirectional) + if (r_shadow_bouncegrid_state.directional) permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL; } GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); @@ -2458,10 +2458,10 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP; if (rsurface.texture->reflectmasktexture) permutation |= SHADERPERMUTATION_REFLECTCUBE; - if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld) + if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld) { permutation |= SHADERPERMUTATION_BOUNCEGRID; - if (r_shadow_bouncegriddirectional) + if (r_shadow_bouncegrid_state.directional) permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL; } GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); @@ -2555,10 +2555,10 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, // ordinary vertex coloring (q3bsp) mode = SHADERMODE_VERTEXCOLOR; } - if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld) + if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld) { permutation |= SHADERPERMUTATION_BOUNCEGRID; - if (r_shadow_bouncegriddirectional) + if (r_shadow_bouncegrid_state.directional) permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL; } GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); @@ -2659,8 +2659,16 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, if (mode == SHADERMODE_WATER) hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]); } - hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]); - hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]); + if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO) + { + hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]); + hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]); + } + else + { + hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]); + hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]); + } hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]); hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1)); hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]); @@ -2822,8 +2830,16 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);} if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);} if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);} - if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]); - if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]); + if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO) + { + if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]); + if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]); + } + else + { + if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]); + if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]); + } if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]); if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1)); @@ -2856,8 +2872,8 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias); if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]); if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height); - if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);} - if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale); + if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegrid_state.matrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);} + if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale); if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white ); if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white ); @@ -2901,7 +2917,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture ); } } - if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture); + if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture); CHECKGLERROR break; case RENDERPATH_GL11: @@ -2968,8 +2984,16 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);} {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);} {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);} - DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]); - DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]); + if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO) + { + DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]); + DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]); + } + else + { + DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]); + DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]); + } DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]); DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1)); @@ -3085,7 +3109,7 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight) GL_AlphaToCoverage(false); Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin); Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld); - Matrix4x4_Invert_Simple(&viewtolight, &lighttoview); + Matrix4x4_Invert_Full(&viewtolight, &lighttoview); Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f); switch(vid.renderpath) { @@ -3097,8 +3121,8 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight) hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale ); hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale ); hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale); - hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]); - hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]); + hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]); + hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]); hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f); hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]); hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height); @@ -3124,8 +3148,8 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight) if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale ); if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale ); if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale); - if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f( r_glsl_permutation->loc_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]); - if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f( r_glsl_permutation->loc_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]); + if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4f( r_glsl_permutation->loc_ShadowMap_TextureScale , r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]); + if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f( r_glsl_permutation->loc_ShadowMap_Parameters , r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]); if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f( r_glsl_permutation->loc_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f); if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f( r_glsl_permutation->loc_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]); if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height); @@ -3147,8 +3171,8 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight) DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale ); DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale ); DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale); - DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]); - DPSOFTRAST_Uniform4f( DPSOFTRAST_UNIFORM_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]); + DPSOFTRAST_Uniform4f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]); + DPSOFTRAST_Uniform4f( DPSOFTRAST_UNIFORM_ShadowMap_Parameters , r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]); DPSOFTRAST_Uniform1f( DPSOFTRAST_UNIFORM_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f); DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]); DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height); @@ -3166,7 +3190,7 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight) typedef struct { - int loadsequence; // incremented each level change + unsigned int loadsequence; // incremented each level change memexpandablearray_t array; skinframe_t *hash[SKINFRAME_HASH]; } @@ -3400,6 +3424,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole skinframe->fog = NULL; skinframe->reflect = NULL; skinframe->hasalpha = false; + // we could store the q2animname here too if (ddsbase) { @@ -3565,7 +3590,6 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB) { int i; - unsigned char *temp1, *temp2; skinframe_t *skinframe; char vabuf[1024]; @@ -3599,11 +3623,11 @@ skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, co if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0) { - 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(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL); - Mem_Free(temp1); + unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8); + unsigned char *b = a + width * height * 4; + Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value); + skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, b, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL); + Mem_Free(a); } skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL); if (textureflags & TEXF_ALPHA) @@ -3678,6 +3702,9 @@ skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, i featuresmask |= palette_featureflags[skindata[i]]; skinframe->hasalpha = false; + // fence textures + if (name[0] == '{') + skinframe->hasalpha = true; skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT)); skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0; skinframe->qgeneratemerged = true; @@ -3720,21 +3747,24 @@ static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboo if (skinframe->qgeneratenmap) { - unsigned char *temp1, *temp2; + unsigned char *a, *b; skinframe->qgeneratenmap = false; - temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8); - temp2 = temp1 + width * height * 4; + a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8); + b = a + 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(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL); - Mem_Free(temp1); + Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete); + Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value); + skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, b, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL); + Mem_Free(a); } if (skinframe->qgenerateglow) { skinframe->qgenerateglow = false; - skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow + if (skinframe->hasalpha) // fence textures + skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags | TEXF_ALPHA, -1, palette_bgra_onlyfullbrights_transparent); // glow + else + skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow } if (colormapped) @@ -3747,7 +3777,10 @@ static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboo else { skinframe->qgeneratemerged = false; - skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete); + if (skinframe->hasalpha) // fence textures + skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags | TEXF_ALPHA, -1, skinframe->glow ? palette_bgra_nofullbrights_transparent : palette_bgra_transparent); + else + skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete); } if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase) @@ -4102,13 +4135,11 @@ static void gl_main_start(void) r_glsl_permutation = NULL; memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash)); Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256); - glslshaderstring = NULL; #ifdef SUPPORTD3D r_hlsl_permutation = NULL; memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash)); Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256); #endif - hlslshaderstring = NULL; memset(&r_svbsp, 0, sizeof (r_svbsp)); memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps)); @@ -4204,13 +4235,11 @@ static void gl_main_shutdown(void) r_glsl_permutation = NULL; memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash)); Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray); - glslshaderstring = NULL; #ifdef SUPPORTD3D r_hlsl_permutation = NULL; memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash)); Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray); #endif - hlslshaderstring = NULL; } static void gl_main_newmap(void) @@ -4243,6 +4272,7 @@ void GL_Main_Init(void) { int i; r_main_mempool = Mem_AllocPool("Renderer", 0, NULL); + R_InitShaderModeInfo(); Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed"); Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl"); @@ -4371,6 +4401,7 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_celoutlines); Cvar_RegisterVariable(&r_water); + Cvar_RegisterVariable(&r_water_cameraentitiesonly); Cvar_RegisterVariable(&r_water_resolutionmultiplier); Cvar_RegisterVariable(&r_water_clippingplanebias); Cvar_RegisterVariable(&r_water_refractdistort); @@ -4493,9 +4524,6 @@ int R_CullBox(const vec3_t mins, const vec3_t maxs) return false; for (i = 0;i < r_refdef.view.numfrustumplanes;i++) { - // skip nearclip plane, it often culls portals when you are very close, and is almost never useful - if (i == 4) - continue; p = r_refdef.view.frustum + i; switch(p->signbits) { @@ -4661,7 +4689,13 @@ void *R_FrameData_Alloc(size_t size) while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size) { // emergency - we ran out of space, allocate more memory - newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f); + // note: this has no upper-bound, we'll fail to allocate memory eventually and just die + newvalue = r_framedatasize.value * 2.0f; + // upper bound based on architecture - if we try to allocate more than this we could overflow, better to loop until we error out on allocation failure + if (sizeof(size_t) >= 8) + newvalue = bound(0.25f, newvalue, (float)(1ll << 42)); + else + newvalue = bound(0.25f, newvalue, (float)(1 << 10)); // this might not be a growing it, but we'll allocate another buffer every time Cvar_SetValueQuick(&r_framedatasize, newvalue); R_FrameData_Resize(true); @@ -4835,7 +4869,7 @@ r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferda Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n"); mem = r_bufferdata_buffer[r_bufferdata_cycle][type]; - offset = mem->current; + offset = (int)mem->current; mem->current += padsize; // upload the data to the buffer at the chosen offset @@ -5213,18 +5247,20 @@ static void R_View_UpdateEntityVisible (void) int samples; entity_render_t *ent; - renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) - : r_fb.water.hideplayer ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) - : (chase_active.integer || r_fb.water.renderingscene) ? RENDER_VIEWMODEL - : RENDER_EXTERIORMODEL; + if (r_refdef.envmap || r_fb.water.hideplayer) + renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL; + else if (chase_active.integer || r_fb.water.renderingscene) + renderimask = RENDER_VIEWMODEL; + else + renderimask = RENDER_EXTERIORMODEL; if (!r_drawviewmodel.integer) renderimask |= RENDER_VIEWMODEL; if (!r_drawexteriormodel.integer) renderimask |= RENDER_EXTERIORMODEL; + memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities); if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs) { // worldmodel can check visibility - memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities); for (i = 0;i < r_refdef.scene.numentities;i++) { ent = r_refdef.scene.entities[i]; @@ -5240,10 +5276,12 @@ static void R_View_UpdateEntityVisible (void) for (i = 0;i < r_refdef.scene.numentities;i++) { ent = r_refdef.scene.entities[i]; - r_refdef.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)); + if (!(ent->flags & renderimask)) + if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE))) + r_refdef.viewcache.entityvisible[i] = true; } } - if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer) + if(r_cullentities_trace.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer) // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling { for (i = 0;i < r_refdef.scene.numentities;i++) @@ -5822,7 +5860,7 @@ void R_RenderView_UpdateViewVectors(void) Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin); VectorNegate(r_refdef.view.left, r_refdef.view.right); // make an inverted copy of the view matrix for tracking sprites - Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix); + Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix); } void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture); @@ -5996,25 +6034,33 @@ void R_Water_AddWaterPlane(msurface_t *surface, int entno) } } planeindex = bestplaneindex; - p = r_fb.water.waterplanes + planeindex; // if this surface does not fit any known plane rendered this frame, add one - if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes) + if (planeindex < 0 || bestplanescore > 0.001f) { - // store the new plane - planeindex = r_fb.water.numwaterplanes++; - p = r_fb.water.waterplanes + planeindex; - p->plane = plane; - // clear materialflags and pvs - p->materialflags = 0; - p->pvsvalid = false; - p->camera_entity = t->camera_entity; - VectorCopy(mins, p->mins); - VectorCopy(maxs, p->maxs); + if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes) + { + // store the new plane + planeindex = r_fb.water.numwaterplanes++; + p = r_fb.water.waterplanes + planeindex; + p->plane = plane; + // clear materialflags and pvs + p->materialflags = 0; + p->pvsvalid = false; + p->camera_entity = t->camera_entity; + VectorCopy(mins, p->mins); + VectorCopy(maxs, p->maxs); + } + else + { + // We're totally screwed. + return; + } } else { // merge mins/maxs when we're adding this surface to the plane + p = r_fb.water.waterplanes + planeindex; p->mins[0] = min(p->mins[0], mins[0]); p->mins[1] = min(p->mins[1], mins[1]); p->mins[2] = min(p->mins[2], mins[2]); @@ -6027,7 +6073,7 @@ void R_Water_AddWaterPlane(msurface_t *surface, int entno) if(!(p->materialflags & MATERIALFLAG_CAMERA)) { // merge this surface's PVS into the waterplane - if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS + if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0) { r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid); @@ -6079,6 +6125,8 @@ static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t // make sure enough textures are allocated for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++) { + if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity) + continue; if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) { if (!p->texture_refraction) @@ -6134,6 +6182,8 @@ static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t r_fb.water.renderingscene = true; for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++) { + if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity) + continue; if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) { r_refdef.view = myview; @@ -6411,7 +6461,7 @@ static void R_Bloom_StartFrame(void) Cvar_SetValueQuick(&r_damageblur, 0); } - if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) + if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) && !r_bloom.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)) && !useviewfbo @@ -7334,6 +7384,7 @@ static void R_DrawEntityBBoxes(void); static void R_DrawModelDecals(void); extern cvar_t cl_decals_newsystem; extern qboolean r_shadow_usingdeferredprepass; +extern int r_shadow_shadowmapatlas_modelshadows_size; void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture) { qboolean shadowmapping = false; @@ -7385,18 +7436,25 @@ void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture) } } + R_Shadow_PrepareModelShadows(); R_Shadow_PrepareLights(fbo, depthtexture, colortexture); - if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0) - R_Shadow_PrepareModelShadows(); if (r_timereport_active) R_TimeReport("preparelights"); - if (R_Shadow_ShadowMappingEnabled()) - shadowmapping = true; + // render all the shadowmaps that will be used for this view + shadowmapping = R_Shadow_ShadowMappingEnabled(); + if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size) + { + R_Shadow_DrawShadowMaps(); + if (r_timereport_active) + R_TimeReport("shadowmaps"); + } + // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass if (r_shadow_usingdeferredprepass) R_Shadow_DrawPrepass(); + // now we begin the forward pass of the view render if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth) { r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity); @@ -7410,16 +7468,6 @@ void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture) R_TimeReport("modeldepth"); } - if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0) - { - R_ResetViewRendering3D(fbo, depthtexture, colortexture); - R_DrawModelShadowMaps(fbo, depthtexture, colortexture); - R_ResetViewRendering3D(fbo, depthtexture, colortexture); - // don't let sound skip if going slow - if (r_refdef.scene.extraupdate) - S_ExtraUpdate (); - } - if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw) { r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity); @@ -7442,7 +7490,7 @@ void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture) if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0) { R_ResetViewRendering3D(fbo, depthtexture, colortexture); - R_DrawModelShadows(fbo, depthtexture, colortexture); + R_Shadow_DrawModelShadows(); R_ResetViewRendering3D(fbo, depthtexture, colortexture); // don't let sound skip if going slow if (r_refdef.scene.extraupdate) @@ -7463,7 +7511,7 @@ void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture) if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0) { R_ResetViewRendering3D(fbo, depthtexture, colortexture); - R_DrawModelShadows(fbo, depthtexture, colortexture); + R_Shadow_DrawModelShadows(); R_ResetViewRendering3D(fbo, depthtexture, colortexture); // don't let sound skip if going slow if (r_refdef.scene.extraupdate) @@ -8142,7 +8190,9 @@ texture_t *R_GetCurrentTexture(texture_t *t) { // use an alternate animation if the entity's frame is not 0, // and only if the texture has an alternate animation - if (rsurface.ent_alttextures && t->anim_total[1]) + if (t->animated == 2) // q2bsp + t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]]; + else if (rsurface.ent_alttextures && t->anim_total[1]) t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0]; else t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0]; @@ -8164,16 +8214,16 @@ texture_t *R_GetCurrentTexture(texture_t *t) if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin)) R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin); t->currentskinframe = r_qwskincache[i].skinframe; - if (t->currentskinframe == NULL) - t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)]; + if (t->materialshaderpass && t->currentskinframe == NULL) + t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)]; } - else if (t->numskinframes >= 2) - t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)]; - if (t->backgroundnumskinframes >= 2) - t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)]; + else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2) + t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)]; + if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2) + t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)]; t->currentmaterialflags = t->basematerialflags; - t->currentalpha = rsurface.colormod[3]; + t->currentalpha = rsurface.colormod[3] * t->basealpha; if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer)) t->currentalpha *= r_wateralpha.value; if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) @@ -8205,7 +8255,7 @@ texture_t *R_GetCurrentTexture(texture_t *t) t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE; if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE; - if (t->backgroundnumskinframes) + if (t->backgroundshaderpass) t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND; if (t->currentmaterialflags & MATERIALFLAG_BLENDED) { @@ -8234,10 +8284,9 @@ texture_t *R_GetCurrentTexture(texture_t *t) Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix); } - for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++) - R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags); - for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++) - R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags); + if (t->materialshaderpass) + for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++) + R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags); t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f); if (t->currentskinframe->qpixels) @@ -8254,8 +8303,10 @@ texture_t *R_GetCurrentTexture(texture_t *t) t->glowtexture = t->currentskinframe->glow; t->fogtexture = t->currentskinframe->fog; t->reflectmasktexture = t->currentskinframe->reflect; - if (t->backgroundnumskinframes) + if (t->backgroundshaderpass) { + for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++) + R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags); t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base; t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap; t->backgroundglosstexture = r_texture_black; @@ -8416,7 +8467,7 @@ texture_t *R_GetCurrentTexture(texture_t *t) } } - return t->currentframe; + return t; } rsurfacestate_t rsurface; @@ -9025,7 +9076,6 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const qboolean dynamicvertex; float amplitude; float animpos; - float scale; float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3]; float waveparms[4]; unsigned char *ub; @@ -9199,60 +9249,63 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const break; } } - switch(rsurface.texture->tcgen.tcgen) + if (rsurface.texture->materialshaderpass) { - default: - case Q3TCGEN_TEXTURE: - break; - case Q3TCGEN_LIGHTMAP: - if (!dynamicvertex) + switch (rsurface.texture->materialshaderpass->tcgen.tcgen) { - r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1; - r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces; - r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices; - r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles; - } - dynamicvertex = true; - batchneed |= BATCHNEED_ARRAY_LIGHTMAP; - needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP; - break; - case Q3TCGEN_VECTOR: - if (!dynamicvertex) - { - r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1; - r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces; - r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices; - r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles; - } - dynamicvertex = true; - batchneed |= BATCHNEED_ARRAY_VERTEX; - needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD; - break; - case Q3TCGEN_ENVIRONMENT: - if (!dynamicvertex) - { - r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1; - r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces; - r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices; - r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles; + default: + case Q3TCGEN_TEXTURE: + break; + case Q3TCGEN_LIGHTMAP: + if (!dynamicvertex) + { + r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1; + r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces; + r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices; + r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles; + } + dynamicvertex = true; + batchneed |= BATCHNEED_ARRAY_LIGHTMAP; + needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP; + break; + case Q3TCGEN_VECTOR: + if (!dynamicvertex) + { + r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1; + r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces; + r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices; + r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles; + } + dynamicvertex = true; + batchneed |= BATCHNEED_ARRAY_VERTEX; + needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD; + break; + case Q3TCGEN_ENVIRONMENT: + if (!dynamicvertex) + { + r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1; + r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces; + r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices; + r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles; + } + dynamicvertex = true; + batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL; + needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD; + break; } - dynamicvertex = true; - batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL; - needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD; - break; - } - if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT) - { - if (!dynamicvertex) + if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT) { - r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1; - r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces; - r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices; - r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles; + if (!dynamicvertex) + { + r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1; + r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces; + r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices; + r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles; + } + dynamicvertex = true; + batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD; + needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD; } - dynamicvertex = true; - batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD; - needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD; } if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))) @@ -9823,6 +9876,7 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const // in place for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++) { + float scale; switch (deform->deform) { default: @@ -10094,10 +10148,10 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const } } - if (rsurface.batchtexcoordtexture2f) + if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass) { // generate texcoords based on the chosen texcoord source - switch(rsurface.texture->tcgen.tcgen) + switch(rsurface.texture->materialshaderpass->tcgen.tcgen) { default: case Q3TCGEN_TEXTURE: @@ -10115,8 +10169,8 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const // rsurface.batchtexcoordtexture2f_bufferoffset = 0; for (j = 0;j < batchnumvertices;j++) { - rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms); - rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3); + rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms); + rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3); } break; case Q3TCGEN_ENVIRONMENT: @@ -10156,10 +10210,10 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const // and we only support that as the first one // (handling a mixture of turbulent and other tcmods would be problematic // without punting it entirely to a software path) - if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT) + if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT) { - amplitude = rsurface.texture->tcmods[0].parms[1]; - animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3]; + amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1]; + animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3]; // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2])); // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL; // rsurface.batchtexcoordtexture2f_bufferoffset = 0; @@ -10657,7 +10711,7 @@ static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_ // in Quake3 maps as it causes problems with q3map2 sky tricks, // and skymasking also looks very bad when noclipping outside the // level, so don't use it then either. - if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer) + if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer) { R_Mesh_ResetTextureState(); if (skyrendermasked) @@ -11098,9 +11152,9 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices); for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++) { - unsigned char c = (vi << 3) * (1.0f / 256.0f); + unsigned char d = (vi << 3) * (1.0f / 256.0f); VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f); - Vector4Set(batchvertex[vi].color4f, c, c, c, 1); + Vector4Set(batchvertex[vi].color4f, d, d, d, 1); } R_Mesh_PrepareVertices_Generic_Unlock(); RSurf_DrawBatch(); @@ -11112,13 +11166,13 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles); for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3) { - unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f); + unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f); VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f); VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f); VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f); - Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1); - Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1); - Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1); + Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1); + Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1); + Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1); } R_Mesh_PrepareVertices_Generic_Unlock(); R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0); @@ -11619,7 +11673,7 @@ void R_DecalSystem_Reset(decalsystem_t *decalsystem) memset(decalsystem, 0, sizeof(*decalsystem)); } -static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float *v0, const float *v1, const float *v2, const float *t0, const float *t1, const float *t2, const float *c0, const float *c1, const float *c2, int triangleindex, int surfaceindex, int decalsequence) +static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float *v0, const float *v1, const float *v2, const float *t0, const float *t1, const float *t2, const float *c0, const float *c1, const float *c2, int triangleindex, int surfaceindex, unsigned int decalsequence) { tridecal_t *decal; tridecal_t *decals; @@ -11699,7 +11753,7 @@ extern cvar_t cl_decals_bias; extern cvar_t cl_decals_models; extern cvar_t cl_decals_newsystem_intensitymultiplier; // baseparms, parms, temps -static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex) +static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, unsigned int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex) { int cornerindex; int index; @@ -11792,7 +11846,7 @@ static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, flo for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++) R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[cornerindex+1], v[cornerindex+2], tc[0], tc[cornerindex+1], tc[cornerindex+2], c[0], c[cornerindex+1], c[cornerindex+2], -1, surfaceindex, decalsequence); } -static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence) +static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, unsigned int decalsequence) { matrix4x4_t projection; decalsystem_t *decalsystem; @@ -11953,7 +12007,7 @@ static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldor } // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead -static void R_DecalSystem_ApplySplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence) +static void R_DecalSystem_ApplySplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, unsigned int decalsequence) { int renderentityindex; float worldmins[3]; @@ -11989,7 +12043,7 @@ typedef struct r_decalsystem_splatqueue_s float color[4]; float tcrange[4]; float worldsize; - int decalsequence; + unsigned int decalsequence; } r_decalsystem_splatqueue_t; @@ -12028,7 +12082,7 @@ static void R_DrawModelDecals_FadeEntity(entity_render_t *ent) int i; decalsystem_t *decalsystem = &ent->decalsystem; int numdecals; - int killsequence; + unsigned int killsequence; tridecal_t *decal; float frametime; float lifetime; @@ -12045,7 +12099,7 @@ static void R_DrawModelDecals_FadeEntity(entity_render_t *ent) return; } - killsequence = cl.decalsequence - max(1, cl_decals_max.integer); + killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence); lifetime = cl_decals_time.value + cl_decals_fadetime.value; if (decalsystem->lastupdatetime) @@ -12060,7 +12114,7 @@ static void R_DrawModelDecals_FadeEntity(entity_render_t *ent) if (decal->color4f[0][3]) { decal->lived += frametime; - if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime) + if (killsequence > decal->decalsequence || decal->lived >= lifetime) { memset(decal, 0, sizeof(*decal)); if (decalsystem->freedecal > i) @@ -12720,6 +12774,7 @@ void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, i texture.update_lastrenderframe = -1; // regenerate this texture texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL; + texture.basealpha = 1.0f; texture.currentskinframe = skinframe; texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE texture.offsetmapping = OFFSETMAPPING_OFF;