#include "csprogs.h"
#include "cl_video.h"
#include "dpsoftrast.h"
+#include "cl_collision.h"
#ifdef SUPPORTD3D
#include <d3d9.h>
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;
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"};
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_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"};
cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer, requires mod_q3shader_force_terrain_alphaflag on."};
cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
-cvar_t r_bufferdatasize[R_BUFFERDATA_COUNT] =
+cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
{
- {CVAR_SAVE, "r_bufferdatasize_vertex", "4", "vertex buffer size for one frame"},
- {CVAR_SAVE, "r_bufferdatasize_index16", "1", "index buffer size for one frame (16bit indices)"},
- {CVAR_SAVE, "r_bufferdatasize_index32", "1", "index buffer size for one frame (32bit indices)"},
- {CVAR_SAVE, "r_bufferdatasize_uniform", "0.25", "uniform buffer size for one frame"},
+ {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
+ {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
+ {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
+ {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
};
extern cvar_t v_glslgamma;
0
};
-char *glslshaderstring = NULL;
-char *hlslshaderstring = NULL;
-
//=======================================================================================================================================================
typedef struct shaderpermutationinfo_s
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;
{"#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;
/// 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;
SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
+ SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
};
-#define SHADERSTATICPARMS_COUNT 13
+#define SHADERSTATICPARMS_COUNT 14
static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
static int shaderstaticparms_count = 0;
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));
if (r_glsl_postprocess_uservec4_enable.integer)
R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
}
+ if (r_fxaa.integer)
+ R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
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;
R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
+ R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
}
/// information about each possible shader 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);
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;
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));
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)
// now add all the permutation pretexts
for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
{
- if (permutation & (1<<i))
+ if (permutation & (1ll<<i))
{
vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
// look up all the uniform variable names we care about, so we don't
// have to look them up every time we set them
+#if 0
+ // debugging aid
+ {
+ GLint activeuniformindex = 0;
+ GLint numactiveuniforms = 0;
+ char uniformname[128];
+ GLsizei uniformnamelength = 0;
+ GLint uniformsize = 0;
+ GLenum uniformtype = 0;
+ memset(uniformname, 0, sizeof(uniformname));
+ qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
+ Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
+ for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
+ {
+ qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
+ Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
+ }
+ }
+#endif
+
p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
// get the uniform block indices so we can bind them
+#ifndef USE_GLES2 /* FIXME: GLES3 only */
if (vid.support.arb_uniform_buffer_object)
p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
else
+#endif
p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
// clear the uniform block bindings
p->ubibind_Skeletal_Transform12_UniformBlock = -1;
// bind the uniform blocks in use
ubibind = 0;
+#ifndef USE_GLES2 /* FIXME: GLES3 only */
if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
+#endif
// we're done compiling and setting up the shader, at least until it is used
CHECKGLERROR
Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
Mem_Free(sourcestring);
}
-static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
+static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
{
r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
if (r_glsl_permutation != perm)
if (!r_glsl_permutation->program)
{
if (!r_glsl_permutation->compiled)
+ {
+ Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
R_GLSL_CompilePermutation(perm, mode, permutation);
+ }
if (!r_glsl_permutation->program)
{
// remove features until we find a valid permutation
for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
{
// reduce i more quickly whenever it would not remove any bits
- int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
+ dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
if (!(permutation & j))
continue;
permutation -= j;
if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
+ CHECKGLERROR
}
#ifdef SUPPORTD3D
/// hash lookup data
struct r_hlsl_permutation_s *hashnext;
unsigned int mode;
- unsigned int permutation;
+ dpuint64 permutation;
/// indicates if we have tried compiling this permutation already
qboolean compiled;
/// storage for permutations linked in the hash table
memexpandablearray_t r_hlsl_permutationarray;
-static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
+static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
{
//unsigned int hashdepth = 0;
unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
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);
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);
psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
}
-static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
+static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, dpuint64 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;
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));
// now add all the permutation pretexts
for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
{
- if (permutation & (1<<i))
+ if (permutation & (1ll<<i))
{
vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
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
static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
-void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
+void R_SetupShader_SetPermutationHLSL(unsigned int mode, dpuint64 permutation)
{
r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
if (r_hlsl_permutation != perm)
for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
{
// reduce i more quickly whenever it would not remove any bits
- int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
+ dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
if (!(permutation & j))
continue;
permutation -= j;
}
#endif
-static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
+static void R_SetupShader_SetPermutationSoft(unsigned int mode, dpuint64 permutation)
{
DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
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:
{
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)))
{
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)))
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)
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);
}
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;
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)
case RENDERPATH_GL20:
case RENDERPATH_GLES2:
R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
+#ifndef USE_GLES2 /* FIXME: GLES3 only */
if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
+#endif
break;
case RENDERPATH_GL13:
case RENDERPATH_GLES1:
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;
// 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};
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)
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);
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);
// 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);
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]);
if (rsurface.batchskeletaltransform3x4buffer)
permutation |= SHADERPERMUTATION_SKELETAL;
R_SetupShader_SetPermutationGLSL(mode, permutation);
+#ifndef USE_GLES2 /* FIXME: GLES3 only */
if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
+#endif
if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
if (mode == SHADERMODE_LIGHTSOURCE)
{
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));
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 );
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:
{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));
// 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;
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)
{
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);
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);
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);
typedef struct
{
- int loadsequence; // incremented each level change
+ unsigned int loadsequence; // incremented each level change
memexpandablearray_t array;
skinframe_t *hash[SKINFRAME_HASH];
}
skinframe->fog = NULL;
skinframe->reflect = NULL;
skinframe->hasalpha = false;
+ // we could store the q2animname here too
if (ddsbase)
{
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];
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)
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;
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)
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)
r_loadnormalmap = true;
r_loadgloss = true;
r_loadfog = false;
+#ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
if (vid.support.arb_uniform_buffer_object)
qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
- break;
+#endif
+ break;
case RENDERPATH_GL13:
case RENDERPATH_GLES1:
Cvar_SetValueQuick(&r_textureunits, vid.texunits);
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));
r_texture_numcubemaps = 0;
r_refdef.fogmasktable_density = 0;
+
+#ifdef __ANDROID__
+ // For Steelstorm Android
+ // FIXME CACHE the program and reload
+ // FIXME see possible combinations for SS:BR android
+ Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
+ R_SetupShader_SetPermutationGLSL(0, 12);
+ R_SetupShader_SetPermutationGLSL(0, 13);
+ R_SetupShader_SetPermutationGLSL(0, 8388621);
+ R_SetupShader_SetPermutationGLSL(3, 0);
+ R_SetupShader_SetPermutationGLSL(3, 2048);
+ R_SetupShader_SetPermutationGLSL(5, 0);
+ R_SetupShader_SetPermutationGLSL(5, 2);
+ R_SetupShader_SetPermutationGLSL(5, 2048);
+ R_SetupShader_SetPermutationGLSL(5, 8388608);
+ R_SetupShader_SetPermutationGLSL(11, 1);
+ R_SetupShader_SetPermutationGLSL(11, 2049);
+ R_SetupShader_SetPermutationGLSL(11, 8193);
+ R_SetupShader_SetPermutationGLSL(11, 10241);
+ Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
+#endif
}
static void gl_main_shutdown(void)
case RENDERPATH_GL20:
case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
-#ifdef GL_SAMPLES_PASSED_ARB
+#if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
if (r_maxqueries)
qglDeleteQueriesARB(r_maxqueries, r_queries);
#endif
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)
{
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");
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);
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);
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);
Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
Cvar_RegisterVariable(&r_framedatasize);
for (i = 0;i < R_BUFFERDATA_COUNT;i++)
- Cvar_RegisterVariable(&r_bufferdatasize[i]);
+ Cvar_RegisterVariable(&r_buffermegs[i]);
Cvar_RegisterVariable(&r_batch_dynamicbuffer);
if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
Cvar_SetValue("r_fullbrights", 0);
+#ifdef DP_MOBILETOUCH
+ // GLES devices have terrible depth precision in general, so...
+ Cvar_SetValueQuick(&r_nearclip, 4);
+ Cvar_SetValueQuick(&r_farclip_base, 4096);
+ Cvar_SetValueQuick(&r_farclip_world, 0);
+ Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
+#endif
R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
}
VID_CheckExtensions();
// LordHavoc: report supported extensions
+#ifdef CONFIG_MENU
Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
+#else
+ Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
+#endif
// clear to black (loading plaque will be seen over this)
GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
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)
{
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);
//==================================================================================
-// avoid reusing the same buffer objects on consecutive buffers
-#define R_BUFFERDATA_CYCLE 2
+// avoid reusing the same buffer objects on consecutive frames
+#define R_BUFFERDATA_CYCLE 3
typedef struct r_bufferdata_buffer_s
{
for (type = 0;type < R_BUFFERDATA_COUNT;type++)
{
// free all buffers
- p = &r_bufferdata_buffer[r_bufferdata_cycle][type];
+ p = &r_bufferdata_buffer[cycle][type];
while (*p)
{
mem = *p;
}
// resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
-static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow)
+static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
{
r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
size_t size;
- size = (size_t)(r_bufferdatasize[type].value * 1024*1024);
- size = bound(65536, size, 512*1024*1024);
+ float newvalue = r_buffermegs[type].value;
+
+ // increase the cvar if we have to (but only if we already have a mem)
+ if (mustgrow && mem)
+ newvalue *= 2.0f;
+ newvalue = bound(0.25f, newvalue, 256.0f);
+ while (newvalue * 1024*1024 < minsize)
+ newvalue *= 2.0f;
+
+ // clamp the cvar to valid range
+ newvalue = bound(0.25f, newvalue, 256.0f);
+ if (r_buffermegs[type].value != newvalue)
+ Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
+
+ // calculate size in bytes
+ size = (size_t)(newvalue * 1024*1024);
+ size = bound(131072, size, 256*1024*1024);
+
+ // allocate a new buffer if the size is different (purge old one later)
+ // or if we were told we must grow the buffer
if (!mem || mem->size != size || mustgrow)
{
mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
{
if (r_bufferdata_buffer[r_bufferdata_cycle][type])
{
- R_BufferData_Resize((r_bufferdata_type_t)type, false);
+ R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
// free all but the head buffer, this is how we recycle obsolete
// buffers after they are no longer in use
p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
}
}
-r_meshbuffer_t *R_BufferData_Store(size_t datasize, void *data, r_bufferdata_type_t type, int *returnbufferoffset, qboolean allowfail)
+r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
{
r_bufferdata_buffer_t *mem;
int offset = 0;
int padsize;
- float newvalue;
*returnbufferoffset = 0;
else
padsize = (datasize + 15) & ~15;
- while (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
- {
- // emergency - we ran out of space, allocate more memory
- newvalue = bound(0.25f, r_bufferdatasize[type].value * 2.0f, 256.0f);
- // if we're already at the limit, just fail (if allowfail is false we might run out of video ram)
- if (newvalue == r_bufferdatasize[type].value && allowfail)
- return NULL;
- Cvar_SetValueQuick(&r_bufferdatasize[type], newvalue);
- R_BufferData_Resize(type, true);
- }
+ // if we ran out of space in this buffer we must allocate a new one
+ if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
+ R_BufferData_Resize(type, true, padsize);
+
+ // if the resize did not give us enough memory, fail
+ if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
+ 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
Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
// note: this can fail if the buffer is at the grow limit
ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
- ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset, true);
+ ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
}
else if (ent->animcache_vertex3f)
{
}
}
-#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;
- if (!model || !model->brush.TraceLineOfSight)
+ // 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 (!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;
}
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];
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)
- // 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;
}
}
case RENDERPATH_GL11:
case RENDERPATH_GL13:
case RENDERPATH_GLES1:
+#ifndef USE_GLES2
qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
+#endif
break;
case RENDERPATH_SOFT:
DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
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);
}
else
{
- for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
- for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
- for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
- for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
+ for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
+ for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
+ for (camerawidth = 1;camerawidth * 2 <= waterwidth ;camerawidth *= 2);
+ for (cameraheight = 1;cameraheight * 2 <= waterheight;cameraheight *= 2);
}
// allocate textures as needed
}
}
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]);
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);
// 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)
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;
memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
}
- r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
+ r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
R_ClearScreen(r_refdef.fogenabled);
if(r_water_scissormode.integer & 2)
continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
}
- r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
+ r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
r_refdef.view.clipplane = p->plane;
VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
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
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);
static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
{
- unsigned int permutation;
+ dpuint64 permutation;
float uservecs[4][4];
R_EntityMatrix(&identitymatrix);
R_SortEntities();
R_AnimCache_ClearCache();
- R_FrameData_NewFrame();
- R_BufferData_NewFrame();
/* adjust for stereo display */
if(R_Stereo_Active())
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;
}
}
+ 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);
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);
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)
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)
R_DrawExplosions();
if (r_timereport_active)
R_TimeReport("explosions");
-
- R_DrawLightningBeams();
- if (r_timereport_active)
- R_TimeReport("lightning");
}
if (cl.csqc_loaded)
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");
}
}
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();
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;
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);
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);
}
}
static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
{
int w, h, idx;
- double f;
- double offsetd[2];
+ float shadertime;
+ float f;
+ float offsetd[2];
float tcmat[12];
matrix4x4_t matrix, temp;
+ // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
+ // it's better to have one huge fixup every 9 hours than gradual
+ // degradation over time which looks consistently bad after many hours.
+ //
+ // tcmod scroll in particular suffers from this degradation which can't be
+ // effectively worked around even with floor() tricks because we don't
+ // know if tcmod scroll is the last tcmod being applied, and for clampmap
+ // a workaround involving floor() would be incorrect anyway...
+ shadertime = rsurface.shadertime;
+ if (shadertime >= 32768.0f)
+ shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
switch(tcmod->tcmod)
{
case Q3TCMOD_COUNT:
Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
break;
case Q3TCMOD_ROTATE:
- f = tcmod->parms[0] * rsurface.shadertime;
Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
- Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
+ Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
break;
case Q3TCMOD_SCALE:
Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
break;
case Q3TCMOD_SCROLL:
- // extra care is needed because of precision breakdown with large values of time
+ // this particular tcmod is a "bug for bug" compatible one with regards to
+ // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
+ // specifically did the wrapping and so we must mimic that...
offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
{
// 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];
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)
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)
{
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)
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;
}
}
- return t->currentframe;
+ return t;
}
rsurfacestate_t rsurface;
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;
break;
}
}
- switch(rsurface.texture->tcgen.tcgen)
+ if (rsurface.texture->materialshaderpass)
{
- 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)
+ switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
{
- 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)))
rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
}
// upload buffer data for the copytriangles batch
- if (vid.forcevbo || (r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object))
+ if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
{
if (rsurface.batchelement3s)
- rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset, !vid.forcevbo);
+ rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
else if (rsurface.batchelement3i)
- rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset, !vid.forcevbo);
+ rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
}
}
else
// in place
for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
{
+ float scale;
switch (deform->deform)
{
default:
}
}
- // generate texcoords based on the chosen texcoord source
- switch(rsurface.texture->tcgen.tcgen)
+ if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
{
- default:
- case Q3TCGEN_TEXTURE:
- break;
- case Q3TCGEN_LIGHTMAP:
-// rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
-// rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
-// rsurface.batchtexcoordtexture2f_bufferoffset = 0;
- if (rsurface.batchtexcoordlightmap2f)
- memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
- break;
- case Q3TCGEN_VECTOR:
-// rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
-// rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
-// 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);
- }
- break;
- case Q3TCGEN_ENVIRONMENT:
- // make environment reflections using a spheremap
- rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
- rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
- rsurface.batchtexcoordtexture2f_bufferoffset = 0;
- for (j = 0;j < batchnumvertices;j++)
+ // generate texcoords based on the chosen texcoord source
+ switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
{
- // identical to Q3A's method, but executed in worldspace so
- // carried models can be shiny too
+ default:
+ case Q3TCGEN_TEXTURE:
+ break;
+ case Q3TCGEN_LIGHTMAP:
+ // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
+ // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
+ if (rsurface.batchtexcoordlightmap2f)
+ memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
+ break;
+ case Q3TCGEN_VECTOR:
+ // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
+ // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
+ for (j = 0;j < batchnumvertices;j++)
+ {
+ 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:
+ // make environment reflections using a spheremap
+ rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
+ rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordtexture2f_bufferoffset = 0;
+ for (j = 0;j < batchnumvertices;j++)
+ {
+ // identical to Q3A's method, but executed in worldspace so
+ // carried models can be shiny too
- float viewer[3], d, reflected[3], worldreflected[3];
+ float viewer[3], d, reflected[3], worldreflected[3];
- VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
- // VectorNormalize(viewer);
+ VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
+ // VectorNormalize(viewer);
- d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
+ d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
- reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
- reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
- reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
- // note: this is proportinal to viewer, so we can normalize later
+ reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
+ reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
+ reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
+ // note: this is proportinal to viewer, so we can normalize later
- Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
- VectorNormalize(worldreflected);
+ Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
+ VectorNormalize(worldreflected);
- // note: this sphere map only uses world x and z!
- // so positive and negative y will LOOK THE SAME.
- rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
- rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
+ // note: this sphere map only uses world x and z!
+ // so positive and negative y will LOOK THE SAME.
+ rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
+ rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
+ }
+ break;
}
- break;
- }
- // the only tcmod that needs software vertex processing is turbulent, so
- // check for it here and apply the changes if needed
- // 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)
- {
- amplitude = rsurface.texture->tcmods[0].parms[1];
- animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
-// rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
-// rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
-// rsurface.batchtexcoordtexture2f_bufferoffset = 0;
- for (j = 0;j < batchnumvertices;j++)
- {
- rsurface.batchtexcoordtexture2f[j*2+0] += amplitude * sin(((rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
- rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
+ // the only tcmod that needs software vertex processing is turbulent, so
+ // check for it here and apply the changes if needed
+ // 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->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
+ {
+ 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;
+ for (j = 0;j < batchnumvertices;j++)
+ {
+ rsurface.batchtexcoordtexture2f[j*2+0] += amplitude * sin(((rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
+ rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
+ }
}
}
}
// upload buffer data for the dynamic batch
- if (vid.forcevbo || (r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object))
+ if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
{
if (rsurface.batchvertexmesh)
- rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset, !vid.forcevbo);
+ rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
else
{
if (rsurface.batchvertex3f)
- rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset, !vid.forcevbo);
+ rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
if (rsurface.batchsvector3f)
- rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset, !vid.forcevbo);
+ rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
if (rsurface.batchtvector3f)
- rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset, !vid.forcevbo);
+ rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
if (rsurface.batchnormal3f)
- rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset, !vid.forcevbo);
- if (rsurface.batchlightmapcolor4f && r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object)
- rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset, !vid.forcevbo);
- if (rsurface.batchtexcoordtexture2f && r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object)
- rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset, !vid.forcevbo);
- if (rsurface.batchtexcoordlightmap2f && r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object)
- rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset, !vid.forcevbo);
+ rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
+ if (rsurface.batchlightmapcolor4f)
+ rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
+ if (rsurface.batchtexcoordtexture2f)
+ rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
+ if (rsurface.batchtexcoordlightmap2f)
+ rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
if (rsurface.batchskeletalindex4ub)
- rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset, !vid.forcevbo);
+ rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
if (rsurface.batchskeletalweight4ub)
- rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset, !vid.forcevbo);
+ rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
}
if (rsurface.batchelement3s)
- rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset, !vid.forcevbo);
+ rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
else if (rsurface.batchelement3i)
- rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset, !vid.forcevbo);
+ rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
}
}
// 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)
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();
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);
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;
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;
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;
}
// 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];
float color[4];
float tcrange[4];
float worldsize;
- int decalsequence;
+ unsigned int decalsequence;
}
r_decalsystem_splatqueue_t;
int i;
decalsystem_t *decalsystem = &ent->decalsystem;
int numdecals;
- int killsequence;
+ unsigned int killsequence;
tridecal_t *decal;
float frametime;
float lifetime;
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)
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)
static void R_DrawDebugModel(void)
{
entity_render_t *ent = rsurface.entity;
- int i, j, k, l, flagsmask;
+ int i, j, flagsmask;
const msurface_t *surface;
dp_model_t *model = ent->model;
- vec3_t v;
if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
return;
if (r_shownormals.value != 0 && qglBegin)
{
+ int l, k;
+ vec3_t v;
if (r_showdisabledepthtest.integer)
{
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
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;