X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=gl_rmain.c;h=4fa5d8b3465aae6ce374b3ca5aaa28389292c86d;hb=254f265a4209363a017ef60c922e9872848bdd82;hp=b0c146c0b07d3fd95ccf79c4561832029c1f351b;hpb=ad37bc7de1dce1d858f74df2d70dc214983fb934;p=xonotic%2Fdarkplaces.git diff --git a/gl_rmain.c b/gl_rmain.c index b0c146c0..4fa5d8b3 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "csprogs.h" #include "cl_video.h" #include "dpsoftrast.h" +#include "cl_collision.h" #ifdef SUPPORTD3D #include @@ -76,10 +77,10 @@ cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"}; // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat? -cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"}; -cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"}; -cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"}; -cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"}; +cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light (DEPRECATED)"}; +cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio (DEPRECATED)"}; +cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression) (DEPRECATED)"}; +cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level (DEPRECATED)"}; cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"}; cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"}; @@ -93,6 +94,7 @@ cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbyne cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"}; cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"}; cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"}; +cvar_t r_showbboxes_client = { 0, "r_showbboxes_client", "0", "shows bounding boxes of clientside qc entities, value controls opacity scaling (1 = 10%, 10 = 100%)" }; cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"}; cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"}; cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"}; @@ -109,18 +111,26 @@ cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"}; cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"}; cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"}; cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"}; +cvar_t r_cullentities_trace_entityocclusion = { 0, "r_cullentities_trace_entityocclusion", "1", "check for occluding entities such as doors, not just world hull" }; cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"}; cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"}; cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"}; cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"}; +cvar_t r_cullentities_trace_eyejitter = {0, "r_cullentities_trace_eyejitter", "16", "randomly offset rays from the eye by this much to reduce the odds of flickering"}; cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"}; cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"}; cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"}; -cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"}; -cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"}; +cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps (DEPRECATED)"}; +cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier (DEPRECATED)"}; #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit)) +cvar_t r_fullbright_directed = {0, "r_fullbright_directed", "0", "render fullbright things (unlit worldmodel and EF_FULLBRIGHT entities, but not fullbright shaders) using a constant light direction instead to add more depth while keeping uniform brightness"}; +cvar_t r_fullbright_directed_ambient = {0, "r_fullbright_directed_ambient", "0.5", "ambient light multiplier for directed fullbright"}; +cvar_t r_fullbright_directed_diffuse = {0, "r_fullbright_directed_diffuse", "0.75", "diffuse light multiplier for directed fullbright"}; +cvar_t r_fullbright_directed_pitch = {0, "r_fullbright_directed_pitch", "20", "constant pitch direction ('height') of the fake light source to use for fullbright"}; +cvar_t r_fullbright_directed_pitch_relative = {0, "r_fullbright_directed_pitch_relative", "0", "whether r_fullbright_directed_pitch is interpreted as absolute (0) or relative (1) pitch"}; + cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"}; cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"}; cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"}; @@ -637,9 +647,6 @@ const char *builtinhlslshaderstrings[] = 0 }; -char *glslshaderstring = NULL; -char *hlslshaderstring = NULL; - //======================================================================================================================================================= typedef struct shaderpermutationinfo_s @@ -651,9 +658,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; @@ -695,46 +707,48 @@ shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] = }; // 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; @@ -743,7 +757,7 @@ typedef struct r_glsl_permutation_s /// hash lookup data struct r_glsl_permutation_s *hashnext; unsigned int mode; - unsigned int permutation; + dpuint64 permutation; /// indicates if we have tried compiling this permutation already qboolean compiled; @@ -954,7 +968,7 @@ qboolean R_CompileShader_CheckStaticParms(void) shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \ else \ shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n" -static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation) +static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation) { shaderstaticparms_count = 0; @@ -982,7 +996,7 @@ r_glsl_permutation_t *r_glsl_permutation; /// storage for permutations linked in the hash table memexpandablearray_t r_glsl_permutationarray; -static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation) +static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation) { //unsigned int hashdepth = 0; unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1); @@ -1028,63 +1042,50 @@ 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) +static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation) { 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; @@ -1100,7 +1101,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)); @@ -1124,6 +1125,27 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode geomstrings_list[geomstrings_count++] = "#define GLSL130\n"; fragstrings_list[fragstrings_count++] = "#define GLSL130\n"; } + // if we can do #version 120, we should (this adds the invariant keyword) + else if(vid.support.glshaderversion >= 120) + { + vertstrings_list[vertstrings_count++] = "#version 120\n"; + geomstrings_list[geomstrings_count++] = "#version 120\n"; + fragstrings_list[fragstrings_count++] = "#version 120\n"; + vertstrings_list[vertstrings_count++] = "#define GLSL120\n"; + geomstrings_list[geomstrings_count++] = "#define GLSL120\n"; + fragstrings_list[fragstrings_count++] = "#define GLSL120\n"; + } + // GLES also adds several things from GLSL120 + switch(vid.renderpath) + { + case RENDERPATH_GLES2: + vertstrings_list[vertstrings_count++] = "#define GLES\n"; + geomstrings_list[geomstrings_count++] = "#define GLES\n"; + fragstrings_list[fragstrings_count++] = "#define GLES\n"; + break; + default: + break; + } // the first pretext is which type of shader to compile as // (later these will all be bound together as a program object) @@ -1140,7 +1162,7 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode // now add all the permutation pretexts for (i = 0;i < SHADERPERMUTATION_COUNT;i++) { - if (permutation & (1<filename, true, false); + sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false); strlcat(permutationname, modeinfo->filename, sizeof(permutationname)); strlcat(cachename, "hlsl/", sizeof(cachename)); @@ -1755,7 +1777,7 @@ static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode // now add all the permutation pretexts for (i = 0;i < SHADERPERMUTATION_COUNT;i++) { - if (permutation & (1<= 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); @@ -1998,14 +2014,13 @@ static void R_GLSL_DumpShader_f(void) } else Con_Printf("failed to write to %s\n", modeinfo[mode].filename); - Mem_Free(text); } } } void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha) { - unsigned int permutation = 0; + dpuint64 permutation = 0; if (r_trippy.integer && !notrippy) permutation |= SHADERPERMUTATION_TRIPPY; permutation |= SHADERPERMUTATION_VIEWTINT; @@ -2086,7 +2101,7 @@ void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy) void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal) { - unsigned int permutation = 0; + dpuint64 permutation = 0; if (r_trippy.integer && !notrippy) permutation |= SHADERPERMUTATION_TRIPPY; if (depthrgb) @@ -2136,8 +2151,10 @@ 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; @@ -2202,7 +2219,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, // combination of texture, entity, light source, and fogging, only use the // minimum features necessary to avoid wasting rendering time in the // fragment shader on features that are not being used - unsigned int permutation = 0; + dpuint64 permutation = 0; unsigned int mode = 0; int blendfuncflags; static float dummy_colormod[3] = {1, 1, 1}; @@ -2673,8 +2690,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]); @@ -2836,8 +2861,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)); @@ -2982,8 +3015,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)); @@ -3066,7 +3107,7 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight) // combination of texture, entity, light source, and fogging, only use the // minimum features necessary to avoid wasting rendering time in the // fragment shader on features that are not being used - unsigned int permutation = 0; + dpuint64 permutation = 0; unsigned int mode = 0; const float *lightcolorbase = rtlight->currentcolor; float ambientscale = rtlight->ambientscale; @@ -3111,8 +3152,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); @@ -3138,8 +3179,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); @@ -3161,8 +3202,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); @@ -4125,13 +4166,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)); @@ -4227,13 +4266,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) @@ -4266,6 +4303,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"); @@ -4309,6 +4347,7 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_transparent_useplanardistance); Cvar_RegisterVariable(&r_showoverdraw); Cvar_RegisterVariable(&r_showbboxes); + Cvar_RegisterVariable(&r_showbboxes_client); Cvar_RegisterVariable(&r_showsurfaces); Cvar_RegisterVariable(&r_showtris); Cvar_RegisterVariable(&r_shownormals); @@ -4323,10 +4362,12 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_draw2d); Cvar_RegisterVariable(&r_drawworld); Cvar_RegisterVariable(&r_cullentities_trace); + Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion); Cvar_RegisterVariable(&r_cullentities_trace_samples); Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples); Cvar_RegisterVariable(&r_cullentities_trace_enlarge); Cvar_RegisterVariable(&r_cullentities_trace_delay); + Cvar_RegisterVariable(&r_cullentities_trace_eyejitter); Cvar_RegisterVariable(&r_sortentities); Cvar_RegisterVariable(&r_drawviewmodel); Cvar_RegisterVariable(&r_drawexteriormodel); @@ -4336,6 +4377,11 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_dynamic); Cvar_RegisterVariable(&r_fakelight); Cvar_RegisterVariable(&r_fakelight_intensity); + Cvar_RegisterVariable(&r_fullbright_directed); + Cvar_RegisterVariable(&r_fullbright_directed_ambient); + Cvar_RegisterVariable(&r_fullbright_directed_diffuse); + Cvar_RegisterVariable(&r_fullbright_directed_pitch); + Cvar_RegisterVariable(&r_fullbright_directed_pitch_relative); Cvar_RegisterVariable(&r_fullbright); Cvar_RegisterVariable(&r_shadows); Cvar_RegisterVariable(&r_shadows_darken); @@ -4682,7 +4728,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); @@ -5073,6 +5125,26 @@ void R_AnimCache_CacheVisibleEntities(void) extern cvar_t r_overheadsprites_pushback; +static void R_GetDirectedFullbright(vec3_t ambient, vec3_t diffuse, vec3_t worldspacenormal) +{ + vec3_t angles; + + VectorSet(ambient, r_fullbright_directed_ambient.value, r_fullbright_directed_ambient.value, r_fullbright_directed_ambient.value); + VectorSet(diffuse, r_fullbright_directed_diffuse.value, r_fullbright_directed_diffuse.value, r_fullbright_directed_diffuse.value); + + // Use cl.viewangles and not r_refdef.view.forward here so it is the + // same for all stereo views, and to better handle pitches outside + // [-90, 90] (in_pitch_* cvars allow that). + VectorCopy(cl.viewangles, angles); + if (r_fullbright_directed_pitch_relative.integer) { + angles[PITCH] += r_fullbright_directed_pitch.value; + } else { + angles[PITCH] = r_fullbright_directed_pitch.value; + } + AngleVectors(angles, worldspacenormal, NULL, NULL); + VectorNegate(worldspacenormal, worldspacenormal); +} + static void R_View_UpdateEntityLighting (void) { int i; @@ -5093,9 +5165,21 @@ static void R_View_UpdateEntityLighting (void) if (ent->model && ent->model == cl.worldmodel) { // TODO: use modellight for r_ambient settings on world? - VectorSet(ent->modellight_ambient, 0, 0, 0); - VectorSet(ent->modellight_diffuse, 0, 0, 0); - VectorSet(ent->modellight_lightdir, 0, 0, 1); + // The logic here currently matches RSurf_ActiveWorldEntity. + if (r_fullbright_directed.integer && (r_fullbright.integer || !ent->model || !ent->model->lit)) + { + R_GetDirectedFullbright(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal); + Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir); + if(VectorLength2(ent->modellight_lightdir) == 0) + VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here + VectorNormalize(ent->modellight_lightdir); + } + else + { + VectorSet(ent->modellight_ambient, 0, 0, 0); + VectorSet(ent->modellight_diffuse, 0, 0, 0); + VectorSet(ent->modellight_lightdir, 0, 0, 1); + } continue; } @@ -5124,8 +5208,18 @@ static void R_View_UpdateEntityLighting (void) org[2] = org[2] + r_overheadsprites_pushback.value; R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT); } - else + else if (!r_fullbright.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->lit && r_refdef.scene.worldmodel->brush.LightPoint) + { R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP); + } + else if (r_fullbright_directed.integer) + { + R_GetDirectedFullbright(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal); + } + else + { + VectorSet(ent->modellight_ambient, 1, 1, 1); + } if(ent->flags & RENDER_EQUALIZE) { @@ -5172,8 +5266,18 @@ static void R_View_UpdateEntityLighting (void) } } } - else // highly rare - VectorSet(ent->modellight_ambient, 1, 1, 1); + else + { + // EF_FULLBRIGHT entity. + if (r_fullbright_directed.integer) + { + R_GetDirectedFullbright(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal); + } + else + { + VectorSet(ent->modellight_ambient, 1, 1, 1); + } + } } // move the light direction into modelspace coordinates for lighting code @@ -5184,42 +5288,88 @@ static void R_View_UpdateEntityLighting (void) } } -#define MAX_LINEOFSIGHTTRACES 64 - -static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs) +qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs) { int i; + vec3_t eyemins, eyemaxs; vec3_t boxmins, boxmaxs; vec3_t start; vec3_t end; dp_model_t *model = r_refdef.scene.worldmodel; + static vec3_t positions[] = { + { 0.5f, 0.5f, 0.5f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 1.0f }, + { 0.0f, 1.0f, 0.0f }, + { 0.0f, 1.0f, 1.0f }, + { 1.0f, 0.0f, 0.0f }, + { 1.0f, 0.0f, 1.0f }, + { 1.0f, 1.0f, 0.0f }, + { 1.0f, 1.0f, 1.0f }, + }; + + // sample count can be set to -1 to skip this logic, for flicker-prone objects + if (numsamples < 0) + return true; + + // view origin is not used for culling in portal/reflection/refraction renders or isometric views + if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer) + return true; - if (!model || !model->brush.TraceLineOfSight) + if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight)) return true; + // expand the eye box a little + eyemins[0] = eye[0] - eyejitter; + eyemaxs[0] = eye[0] + eyejitter; + eyemins[1] = eye[1] - eyejitter; + eyemaxs[1] = eye[1] + eyejitter; + eyemins[2] = eye[2] - eyejitter; + eyemaxs[2] = eye[2] + eyejitter; // expand the box a little - boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0]; - boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0]; - boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1]; - boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1]; - boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2]; - boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2]; - - // return true if eye is inside enlarged box - if (BoxesOverlap(boxmins, boxmaxs, eye, eye)) + boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0]; + boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0]; + boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1]; + boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1]; + boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2]; + boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2]; + + // return true if eye overlaps enlarged box + if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs)) return true; - // try center - VectorCopy(eye, start); - VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end); - if (model->brush.TraceLineOfSight(model, start, end)) + // try specific positions in the box first - note that these can be cached + if (r_cullentities_trace_entityocclusion.integer) + { + for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++) + { + VectorCopy(eye, start); + end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0]; + end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1]; + end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2]; + //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true); + trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT); + // not picky - if the trace ended anywhere in the box we're good + if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs)) + return true; + } + } + else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs)) return true; // try various random positions - for (i = 0;i < numsamples;i++) + for (i = 0; i < numsamples; i++) { + VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2])); VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2])); - if (model->brush.TraceLineOfSight(model, start, end)) + if (r_cullentities_trace_entityocclusion.integer) + { + trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT); + // not picky - if the trace ended anywhere in the box we're good + if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs)) + return true; + } + else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs)) return true; } @@ -5268,22 +5418,19 @@ static void R_View_UpdateEntityVisible (void) r_refdef.viewcache.entityvisible[i] = true; } } - 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 + if (r_cullentities_trace.integer) { for (i = 0;i < r_refdef.scene.numentities;i++) { if (!r_refdef.viewcache.entityvisible[i]) continue; ent = r_refdef.scene.entities[i]; - if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*'))) + if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*'))) { - samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer; - if (samples < 0) - continue; // temp entities do pvs only - if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs)) + samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer; + if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs)) ent->last_trace_visibility = realtime; - if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value) + if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value) r_refdef.viewcache.entityvisible[i] = 0; } } @@ -6612,6 +6759,7 @@ static void R_Bloom_MakeTexture(void) r_fb.bloomindex = 0; R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL); R_SetViewport(&r_fb.bloomviewport); + GL_CullFace(GL_NONE); GL_DepthTest(false); GL_BlendFunc(GL_ONE, GL_ZERO); GL_Color(colorscale, colorscale, colorscale, 1); @@ -6735,7 +6883,7 @@ static void R_Bloom_MakeTexture(void) static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture) { - unsigned int permutation; + dpuint64 permutation; float uservecs[4][4]; R_EntityMatrix(&identitymatrix); @@ -7367,10 +7515,11 @@ void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortex extern cvar_t cl_locs_show; static void R_DrawLocs(void); -static void R_DrawEntityBBoxes(void); +static void R_DrawEntityBBoxes(prvm_prog_t *prog); 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; @@ -7422,18 +7571,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); @@ -7447,16 +7603,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); @@ -7479,7 +7625,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) @@ -7500,7 +7646,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) @@ -7529,10 +7675,6 @@ void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture) R_DrawExplosions(); if (r_timereport_active) R_TimeReport("explosions"); - - R_DrawLightningBeams(); - if (r_timereport_active) - R_TimeReport("lightning"); } if (cl.csqc_loaded) @@ -7554,11 +7696,17 @@ void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture) R_TimeReport("portals"); } + if (r_showbboxes_client.value > 0) + { + R_DrawEntityBBoxes(CLVM_prog); + if (r_timereport_active) + R_TimeReport("clbboxes"); + } if (r_showbboxes.value > 0) { - R_DrawEntityBBoxes(); + R_DrawEntityBBoxes(SVVM_prog); if (r_timereport_active) - R_TimeReport("bboxes"); + R_TimeReport("svbboxes"); } } @@ -7622,10 +7770,36 @@ static const unsigned short bboxelements[36] = 1, 0, 2, 1, 2, 3, }; +#define BBOXEDGES 13 +static const float bboxedges[BBOXEDGES][6] = +{ + // whole box + { 0, 0, 0, 1, 1, 1 }, + // bottom edges + { 0, 0, 0, 0, 1, 0 }, + { 0, 0, 0, 1, 0, 0 }, + { 0, 1, 0, 1, 1, 0 }, + { 1, 0, 0, 1, 1, 0 }, + // top edges + { 0, 0, 1, 0, 1, 1 }, + { 0, 0, 1, 1, 0, 1 }, + { 0, 1, 1, 1, 1, 1 }, + { 1, 0, 1, 1, 1, 1 }, + // vertical edges + { 0, 0, 0, 0, 0, 1 }, + { 1, 0, 0, 1, 0, 1 }, + { 0, 1, 0, 0, 1, 1 }, + { 1, 1, 0, 1, 1, 1 }, +}; + static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca) { - int i; - float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4]; + int numvertices = BBOXEDGES * 8; + float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4]; + int numtriangles = BBOXEDGES * 12; + unsigned short elements[BBOXEDGES * 36]; + int i, edge; + float *v, *c, f1, f2, edgemins[3], edgemaxs[3]; RSurf_ActiveWorldEntity(); @@ -7633,20 +7807,29 @@ static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float c GL_DepthMask(false); GL_DepthRange(0, 1); GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset); -// R_Mesh_ResetTextureState(); - vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; // - vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2]; - vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2]; - vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2]; - vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2]; - vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2]; - vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2]; - vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2]; - R_FillColors(color4f, 8, cr, cg, cb, ca); + for (edge = 0; edge < BBOXEDGES; edge++) + { + for (i = 0; i < 3; i++) + { + edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f; + edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f; + } + vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2]; + vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2]; + vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2]; + vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2]; + vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2]; + vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2]; + vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2]; + vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2]; + for (i = 0; i < 36; i++) + elements[edge * 36 + i] = edge * 8 + bboxelements[i]; + } + R_FillColors(color4f, numvertices, cr, cg, cb, ca); if (r_refdef.fogenabled) { - for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4) + for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4) { f1 = RSurf_FogVertex(v); f2 = 1 - f1; @@ -7655,23 +7838,20 @@ static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float c c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2; } } - R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL); + R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL); R_Mesh_ResetTextureState(); R_SetupShader_Generic_NoTexture(false, false); - R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0); + R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0); } static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) { - prvm_prog_t *prog = SVVM_prog; + // hacky overloading of the parameters + prvm_prog_t *prog = (prvm_prog_t *)rtlight; int i; float color[4]; prvm_edict_t *edict; - // this function draws bounding boxes of server entities - if (!sv.active) - return; - GL_CullFace(GL_NONE); R_SetupShader_Generic_NoTexture(false, false); @@ -7688,37 +7868,37 @@ static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtligh case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break; default: Vector4Set(color, 0, 0, 0, 0.50);break; } - color[3] *= r_showbboxes.value; + if (prog == CLVM_prog) + color[3] *= r_showbboxes_client.value; + else + color[3] *= r_showbboxes.value; color[3] = bound(0, color[3], 1); GL_DepthTest(!r_showdisabledepthtest.integer); - GL_CullFace(r_refdef.view.cullface_front); R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]); } } -static void R_DrawEntityBBoxes(void) +static void R_DrawEntityBBoxes(prvm_prog_t *prog) { int i; prvm_edict_t *edict; vec3_t center; - prvm_prog_t *prog = SVVM_prog; - // this function draws bounding boxes of server entities - if (!sv.active) + if (prog == NULL) return; - for (i = 0;i < prog->num_edicts;i++) + for (i = 0; i < prog->num_edicts; i++) { edict = PRVM_EDICT_NUM(i); if (edict->priv.server->free) continue; // exclude the following for now, as they don't live in world coordinate space and can't be solid: - if(PRVM_serveredictedict(edict, tag_entity) != 0) + if (PRVM_serveredictedict(edict, tag_entity) != 0) continue; - if(PRVM_serveredictedict(edict, viewmodelforclient) != 0) + if (PRVM_serveredictedict(edict, viewmodelforclient) != 0) continue; VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center); - R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL); + R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog); } } @@ -8203,13 +8383,13 @@ 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->basealpha; @@ -8244,7 +8424,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) { @@ -8273,10 +8453,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) @@ -8293,8 +8472,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; @@ -8483,9 +8664,17 @@ void RSurf_ActiveWorldEntity(void) rsurface.fogheightfade = r_refdef.fogheightfade; rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist; rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip; - VectorSet(rsurface.modellight_ambient, 0, 0, 0); - VectorSet(rsurface.modellight_diffuse, 0, 0, 0); - VectorSet(rsurface.modellight_lightdir, 0, 0, 1); + if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit)) + { + R_GetDirectedFullbright(rsurface.modellight_ambient, rsurface.modellight_diffuse, rsurface.modellight_lightdir); + rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT; + } + else + { + VectorSet(rsurface.modellight_ambient, 0, 0, 0); + VectorSet(rsurface.modellight_diffuse, 0, 0, 0); + VectorSet(rsurface.modellight_lightdir, 0, 0, 1); + } VectorSet(rsurface.colormap_pantscolor, 0, 0, 0); VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0); VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale); @@ -8600,6 +8789,10 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q rsurface.ent_skinnum = ent->skinnum; rsurface.ent_qwskin = (ent->entitynumber <= cl.maxclients && ent->entitynumber >= 1 && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[ent->entitynumber - 1].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) ? (ent->entitynumber - 1) : -1; rsurface.ent_flags = ent->flags; + if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit)) + { + rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT; + } rsurface.shadertime = r_refdef.scene.time - ent->shadertime; rsurface.matrix = ent->matrix; rsurface.inversematrix = ent->inversematrix; @@ -8608,7 +8801,7 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q R_EntityMatrix(&rsurface.matrix); Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin); Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane); - rsurface.fogplaneviewdist *= rsurface.inversematrixscale; + rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist * rsurface.inversematrixscale; rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale; rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale; rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip; @@ -9237,60 +9430,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))) @@ -10133,10 +10329,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: @@ -10154,8 +10350,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: @@ -10195,10 +10391,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;