//
r_refdef_t r_refdef;
-cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended"};
-cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"};
+cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
+cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
+cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
+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_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_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
+cvar_t r_shadows_shadowmapbias = {CVAR_SAVE, "r_shadows_shadowmapbias", "-1", "sets shadowmap bias for fake shadows. -1 sets the value of r_shadow_shadowmapping_bias. Needs shadowmapping ON."};
cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
+cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading (OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
+cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred; OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
-cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "0", "use depth texture instead of depth renderbuffer where possible, may not be slower on some hardware"};
+cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"};
cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
+cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
-cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
+cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
-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."};
+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)"};
{"#define USEOFFSETMAPPING\n", " offsetmapping"},
{"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
{"#define USESHADOWMAP2D\n", " shadowmap2d"},
- {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"}, // TODO make this a static parm
- {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"}, // TODO make this a static parm
- {"#define USESHADOWSAMPLER\n", " shadowsampler"}, // TODO make this a static parm
{"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
{"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
{"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
{"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
{"#define USETRIPPY\n", " trippy"},
{"#define USEDEPTHRGB\n", " depthrgb"},
+ {"#define USEALPHAGENVERTEX\n", "alphagenvertex"}
};
// NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
+ SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
+ SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
+ SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
+ SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
+ SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
};
-#define SHADERSTATICPARMS_COUNT 8
+#define SHADERSTATICPARMS_COUNT 13
static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
static int shaderstaticparms_count = 0;
static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
#define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
-static qboolean R_CompileShader_CheckStaticParms(void)
+
+extern qboolean r_shadow_shadowmapsampler;
+extern int r_shadow_shadowmappcf;
+qboolean R_CompileShader_CheckStaticParms(void)
{
static int r_compileshader_staticparms_save[1];
memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
}
if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
+
+ if (r_shadow_shadowmapsampler)
+ R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
+ if (r_shadow_shadowmappcf > 1)
+ R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
+ else if (r_shadow_shadowmappcf)
+ R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
+ if (r_celshading.integer)
+ R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
+ if (r_celoutlines.integer)
+ R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
+
return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
}
R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
+ R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
+ R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
+ R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
+ R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
+ R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
}
/// information about each possible shader permutation
{
if (debugshader)
{
-// vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
-// FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
}
vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
if (vsbuffer)
{
- vsbinsize = vsbuffer->GetBufferSize();
+ vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
- memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
- vsbuffer->Release();
+ memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
+ ID3DXBuffer_Release(vsbuffer);
}
if (vslog)
{
- strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
+ strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
- vslog->Release();
+ ID3DXBuffer_Release(vslog);
}
}
if (fragstring && fragstring[0])
{
if (debugshader)
{
-// psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
-// FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
}
psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
if (psbuffer)
{
- psbinsize = psbuffer->GetBufferSize();
+ psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
- memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
- psbuffer->Release();
+ memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
+ ID3DXBuffer_Release(psbuffer);
}
if (pslog)
{
- strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
+ strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
- pslog->Release();
+ ID3DXBuffer_Release(pslog);
}
}
Sys_UnloadLibrary(&d3dx9_dll);
DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
}
-static void R_GLSL_Restart_f(void)
+void R_GLSL_Restart_f(void)
{
unsigned int i, limit;
if (glslshaderstring && glslshaderstring != builtinshaderstring)
extern float r_shadow_shadowmap_texturescale[2];
extern float r_shadow_shadowmap_parameters[4];
extern qboolean r_shadow_shadowmapvsdct;
-extern qboolean r_shadow_shadowmapsampler;
-extern int r_shadow_shadowmappcf;
extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
extern rtexture_t *r_shadow_shadowmapvsdcttexture;
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
{
mode = SHADERMODE_WATER;
+ if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
+ permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
{
// this is the right thing to do for wateralpha
else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
{
mode = SHADERMODE_REFRACTION;
+ if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
+ permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else
{
mode = SHADERMODE_GENERIC;
- permutation |= SHADERPERMUTATION_DIFFUSE;
- GL_BlendFunc(GL_ONE, GL_ZERO);
- blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
+ permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
if (vid.allowalphatocoverage)
GL_AlphaToCoverage(false);
}
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
+ if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
+ permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
// light source
mode = SHADERMODE_LIGHTSOURCE;
if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
if(r_shadow_shadowmapvsdct)
permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
- if (r_shadow_shadowmapsampler)
- permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
- if (r_shadow_shadowmappcf > 1)
- permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
- else if (r_shadow_shadowmappcf)
- permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
if (r_shadow_shadowmap2ddepthbuffer)
permutation |= SHADERPERMUTATION_DEPTHRGB;
}
}
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
+ if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
+ permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
// unshaded geometry (fullbright or ambient model lighting)
mode = SHADERMODE_FLATCOLOR;
ambientscale = diffusescale = specularscale = 0;
- if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
+ if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
permutation |= SHADERPERMUTATION_GLOW;
if (r_refdef.fogenabled)
permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
permutation |= SHADERPERMUTATION_SHADOWMAP2D;
- if (r_shadow_shadowmapsampler)
- permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
- if (r_shadow_shadowmappcf > 1)
- permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
- else if (r_shadow_shadowmappcf)
- permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
if (r_shadow_shadowmap2ddepthbuffer)
permutation |= SHADERPERMUTATION_DEPTHRGB;
}
}
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
+ if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
+ permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
// directional model lighting
mode = SHADERMODE_LIGHTDIRECTION;
- if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
+ if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
permutation |= SHADERPERMUTATION_GLOW;
permutation |= SHADERPERMUTATION_DIFFUSE;
if (specularscale > 0)
permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
permutation |= SHADERPERMUTATION_SHADOWMAP2D;
- if (r_shadow_shadowmapsampler)
- permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
- if (r_shadow_shadowmappcf > 1)
- permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
- else if (r_shadow_shadowmappcf)
- permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
if (r_shadow_shadowmap2ddepthbuffer)
permutation |= SHADERPERMUTATION_DEPTHRGB;
}
}
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
+ if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
+ permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
// ambient model lighting
mode = SHADERMODE_LIGHTDIRECTION;
- if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
+ if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
permutation |= SHADERPERMUTATION_GLOW;
if (r_refdef.fogenabled)
permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
permutation |= SHADERPERMUTATION_SHADOWMAP2D;
- if (r_shadow_shadowmapsampler)
- permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
- if (r_shadow_shadowmappcf > 1)
- permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
- else if (r_shadow_shadowmappcf)
- permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
if (r_shadow_shadowmap2ddepthbuffer)
permutation |= SHADERPERMUTATION_DEPTHRGB;
}
}
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
+ if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
+ permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
// lightmapped wall
- if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
+ if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
permutation |= SHADERPERMUTATION_GLOW;
if (r_refdef.fogenabled)
permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
permutation |= SHADERPERMUTATION_SHADOWMAP2D;
- if (r_shadow_shadowmapsampler)
- permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
- if (r_shadow_shadowmappcf > 1)
- permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
- else if (r_shadow_shadowmappcf)
- permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
if (r_shadow_shadowmap2ddepthbuffer)
permutation |= SHADERPERMUTATION_DEPTHRGB;
}
1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
);
- hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
+ hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
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);
1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
);
- if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
+ if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
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);
1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
);
- DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
+ DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
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);
if (r_shadow_shadowmapvsdct)
permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
- if (r_shadow_shadowmapsampler)
- permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
- if (r_shadow_shadowmappcf > 1)
- permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
- else if (r_shadow_shadowmappcf)
- permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
if (r_shadow_shadowmap2ddepthbuffer)
permutation |= SHADERPERMUTATION_DEPTHRGB;
}
Image_StripImageExtension(name, basename, sizeof(basename));
// check for DDS texture file first
- if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
+ if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
{
basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
if (basepixels == NULL)
skinframe->hasalpha = ddshasalpha;
VectorCopy(ddsavgcolor, skinframe->avgcolor);
if (r_loadfog && skinframe->hasalpha)
- skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
+ skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel, true);
//Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
}
else
{
mymiplevel = savemiplevel;
if (r_loadnormalmap)
- skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
- skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
+ skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel, true);
+ skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
if (r_loadgloss)
- skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
- skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
- skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
- skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
+ skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
+ skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
+ skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
+ skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
}
// _norm is the name used by tenebrae and has been adopted as standard
// if already loaded just return it, otherwise make a new skinframe
skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
- if (skinframe && skinframe->base)
+ if (skinframe->base)
return skinframe;
textureflags &= ~TEXF_FORCE_RELOAD;
// if already loaded just return it, otherwise make a new skinframe
skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
- if (skinframe && skinframe->base)
+ if (skinframe->base)
return skinframe;
- textureflags &= ~TEXF_FORCE_RELOAD;
+ //textureflags &= ~TEXF_FORCE_RELOAD;
skinframe->stain = NULL;
skinframe->merged = NULL;
// if already loaded just return it, otherwise make a new skinframe
skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
- if (skinframe && skinframe->base)
+ if (skinframe->base)
return skinframe;
textureflags &= ~TEXF_FORCE_RELOAD;
Cvar_RegisterVariable(&r_deformvertexes);
Cvar_RegisterVariable(&r_transparent);
Cvar_RegisterVariable(&r_transparent_alphatocoverage);
+ Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
+ Cvar_RegisterVariable(&r_transparent_useplanardistance);
Cvar_RegisterVariable(&r_showoverdraw);
Cvar_RegisterVariable(&r_showbboxes);
Cvar_RegisterVariable(&r_showsurfaces);
Cvar_RegisterVariable(&r_shadows_throwdirection);
Cvar_RegisterVariable(&r_shadows_focus);
Cvar_RegisterVariable(&r_shadows_shadowmapscale);
+ Cvar_RegisterVariable(&r_shadows_shadowmapbias);
Cvar_RegisterVariable(&r_q1bsp_skymasking);
Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
+ Cvar_RegisterVariable(&r_celshading);
+ Cvar_RegisterVariable(&r_celoutlines);
Cvar_RegisterVariable(&r_water);
Cvar_RegisterVariable(&r_water_resolutionmultiplier);
Cvar_RegisterVariable(&r_bloom_resolution);
Cvar_RegisterVariable(&r_bloom_colorexponent);
Cvar_RegisterVariable(&r_bloom_colorsubtract);
+ Cvar_RegisterVariable(&r_bloom_scenebrightness);
Cvar_RegisterVariable(&r_hdr_scenebrightness);
Cvar_RegisterVariable(&r_hdr_glowintensity);
Cvar_RegisterVariable(&r_hdr_irisadaptation);
{
ent = r_refdef.scene.entities[i];
- // skip unseen models and models that updated by CSQC
- if ((!r_refdef.viewcache.entityvisible[i] && skipunseen) || ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
+ // skip unseen models
+ if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
continue;
// skip bsp models
- if (ent->model && ent->model->brush.num_leafs)
+ if (ent->model && ent->model == cl.worldmodel)
{
// TODO: use modellight for r_ambient settings on world?
VectorSet(ent->modellight_ambient, 0, 0, 0);
VectorSet(ent->modellight_lightdir, 0, 0, 1);
continue;
}
-
- // fetch the lighting from the worldmodel data
- VectorClear(ent->modellight_ambient);
- VectorClear(ent->modellight_diffuse);
- VectorClear(tempdiffusenormal);
- if (ent->flags & RENDER_LIGHT)
+
+ if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
{
- vec3_t org;
- Matrix4x4_OriginFromMatrix(&ent->matrix, org);
-
- // complete lightning for lit sprites
- // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
- if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
+ // aleady updated by CSQC
+ // TODO: force modellight on BSP models in this case?
+ VectorCopy(ent->modellight_lightdir, tempdiffusenormal);
+ }
+ else
+ {
+ // fetch the lighting from the worldmodel data
+ VectorClear(ent->modellight_ambient);
+ VectorClear(ent->modellight_diffuse);
+ VectorClear(tempdiffusenormal);
+ if (ent->flags & RENDER_LIGHT)
{
- if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
- org[2] = org[2] + r_overheadsprites_pushback.value;
- R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
- }
- else
- R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
+ vec3_t org;
+ Matrix4x4_OriginFromMatrix(&ent->matrix, org);
- if(ent->flags & RENDER_EQUALIZE)
- {
- // first fix up ambient lighting...
- if(r_equalize_entities_minambient.value > 0)
+ // complete lightning for lit sprites
+ // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
+ if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
+ {
+ if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
+ org[2] = org[2] + r_overheadsprites_pushback.value;
+ R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
+ }
+ else
+ R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
+
+ if(ent->flags & RENDER_EQUALIZE)
{
- fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
- if(fd > 0)
+ // first fix up ambient lighting...
+ if(r_equalize_entities_minambient.value > 0)
{
- fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
- if(fa < r_equalize_entities_minambient.value * fd)
+ fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
+ if(fd > 0)
{
- // solve:
- // fa'/fd' = minambient
- // fa'+0.25*fd' = fa+0.25*fd
- // ...
- // fa' = fd' * minambient
- // fd'*(0.25+minambient) = fa+0.25*fd
- // ...
- // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
- // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
- // ...
- fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
- f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
- VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
- VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
+ fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
+ if(fa < r_equalize_entities_minambient.value * fd)
+ {
+ // solve:
+ // fa'/fd' = minambient
+ // fa'+0.25*fd' = fa+0.25*fd
+ // ...
+ // fa' = fd' * minambient
+ // fd'*(0.25+minambient) = fa+0.25*fd
+ // ...
+ // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
+ // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
+ // ...
+ fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
+ f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
+ VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
+ VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
+ }
}
}
- }
- if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
- {
- fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
- fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
- f = fa + 0.25 * fd;
- if(f > 0)
+ if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
{
- // adjust brightness and saturation to target
- avg[0] = avg[1] = avg[2] = fa / f;
- VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
- avg[0] = avg[1] = avg[2] = fd / f;
- VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
+ fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
+ fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
+ f = fa + 0.25 * fd;
+ if(f > 0)
+ {
+ // adjust brightness and saturation to target
+ avg[0] = avg[1] = avg[2] = fa / f;
+ VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
+ avg[0] = avg[1] = avg[2] = fd / f;
+ VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
+ }
}
}
}
+ else // highly rare
+ VectorSet(ent->modellight_ambient, 1, 1, 1);
}
- else // highly rare
- VectorSet(ent->modellight_ambient, 1, 1, 1);
// move the light direction into modelspace coordinates for lighting code
Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
R_View_WorldVisibility(r_refdef.view.useclipplane);
R_View_UpdateEntityVisible();
R_View_UpdateEntityLighting();
- R_AnimCache_CacheVisibleEntities();
}
static void R_View_Update(void)
R_View_WorldVisibility(r_refdef.view.useclipplane);
R_View_UpdateEntityVisible();
R_View_UpdateEntityLighting();
- R_AnimCache_CacheVisibleEntities();
}
float viewscalefpsadjusted = 1.0f;
}
}
-void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
+void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
{
r_viewport_t viewport;
- DrawQ_Finish();
+
+ CHECKGLERROR
// GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
- R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
+ R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, x2, y2, -10, 100, NULL);
R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
R_SetViewport(&viewport);
GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
break;
}
GL_CullFace(GL_NONE);
+
+ CHECKGLERROR
+}
+
+void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
+{
+ DrawQ_Finish();
+
+ R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
}
void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
R_RenderView_UpdateViewVectors
================
*/
-static void R_RenderView_UpdateViewVectors(void)
+void R_RenderView_UpdateViewVectors(void)
{
// break apart the view matrix into vectors for various purposes
// it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
int i;
int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
r_waterstate_waterplane_t *p;
- qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
+ qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
return;
int planeindex, qualityreduction = 0, old_r_dynamic = 0, old_r_shadows = 0, old_r_worldrtlight = 0, old_r_dlight = 0, old_r_particles = 0, old_r_decals = 0;
r_waterstate_waterplane_t *p;
vec3_t visorigin;
- qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
+ qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
char vabuf[1024];
originalview = r_refdef.view;
R_View_UpdateWithScissor(myscissor);
else
R_View_Update();
+ R_AnimCache_CacheVisibleEntities();
if(r_water_scissormode.integer & 1)
GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
R_View_UpdateWithScissor(myscissor);
else
R_View_Update();
+ R_AnimCache_CacheVisibleEntities();
if(r_water_scissormode.integer & 1)
GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
R_ClearScreen(r_refdef.fogenabled);
R_View_Update();
+ R_AnimCache_CacheVisibleEntities();
R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
if (!p->fbo_camera)
if (!r_fb.water.depthtexture)
R_ClearScreen(r_refdef.fogenabled);
R_View_Update();
+ R_AnimCache_CacheVisibleEntities();
goto finish;
error:
r_refdef.view = originalview;
int i;
int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
int viewwidth, viewheight;
- qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.samples < 2;
+ qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
textype_t textype = TEXTYPE_COLORBUFFER;
switch (vid.renderpath)
{
case RENDERPATH_GL20:
r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
- if (vid.support.ext_framebuffer_object)
+ if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
{
if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
// set bloomwidth and bloomheight to the bloom resolution that will be
// used (often less than the screen resolution for faster rendering)
- r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
+ r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
}
// bloom texture is a different resolution
- r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
+ r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
r_fb.screentexcoord2f[6] = 0;
r_fb.screentexcoord2f[7] = 0;
+ if(r_fb.fbo)
+ {
+ for (i = 1;i < 8;i += 2)
+ {
+ r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
+ }
+ }
+
// set up a texcoord array for the reduced resolution bloom image
// (which will be additive blended over the screen image)
r_fb.bloomtexcoord2f[0] = 0;
case RENDERPATH_D3D9:
case RENDERPATH_D3D10:
case RENDERPATH_D3D11:
+ for (i = 0;i < 4;i++)
{
- int i;
- for (i = 0;i < 4;i++)
- {
- r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
- r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
- r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
- r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
- }
+ r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
+ r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
+ r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
+ r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
}
break;
}
- R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, r_refdef.view.x, (r_fb.bloomfbo[0] ? r_fb.bloomtextureheight : vid.height) - r_fb.bloomheight - r_refdef.view.y, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
+ R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
if (r_fb.fbo)
r_refdef.view.clear = true;
float colorscale = r_bloom_colorscale.value;
r_refdef.stats.bloom++;
-
+
+#if 0
+ // this copy is unnecessary since it happens in R_BlendView already
if (!r_fb.fbo)
{
R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
}
+#endif
// scale down screen texture to the bloom texture size
CHECKGLERROR
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_DepthTest(false);
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_Color(colorscale, colorscale, colorscale, 1);
// D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
r_fb.bloomindex ^= 1;
R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
x *= 2;
- r = bound(0, r_bloom_colorexponent.value / x, 1);
- GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
- GL_Color(r,r,r,1);
+ r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
+ if (!r_fb.bloomfbo[r_fb.bloomindex])
+ {
+ GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
+ GL_Color(r,r,r,1); // apply fix factor
+ }
+ else
+ {
+ if(x <= 2)
+ GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
+ GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
+ GL_Color(1,1,1,1); // no fix factor supported here
+ }
R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
xoffset /= (float)r_fb.bloomtexturewidth;
yoffset /= (float)r_fb.bloomtextureheight;
// compute a texcoord array with the specified x and y offset
- r_fb.offsettexcoord2f[0] = xoffset+0;
- r_fb.offsettexcoord2f[1] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
- r_fb.offsettexcoord2f[2] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
- r_fb.offsettexcoord2f[3] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
- r_fb.offsettexcoord2f[4] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
- r_fb.offsettexcoord2f[5] = yoffset+0;
- r_fb.offsettexcoord2f[6] = xoffset+0;
- r_fb.offsettexcoord2f[7] = yoffset+0;
+ r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
+ r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
+ r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
+ r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
+ r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
+ r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
+ r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
+ r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
// this r value looks like a 'dot' particle, fading sharply to
// black at the edges
// (probably not realistic but looks good enough)
unsigned int permutation;
float uservecs[4][4];
+ R_EntityMatrix(&identitymatrix);
+
switch (vid.renderpath)
{
case RENDERPATH_GL20:
{
r_refdef.lightmapintensity *= r_fakelight_intensity.value;
}
+ else if (r_refdef.scene.worldmodel)
+ {
+ r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
+ }
if (r_showsurfaces.integer)
{
r_refdef.scene.rtworld = false;
r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
+ if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
+ // in sRGB fallback, behave similar to true sRGB: convert this
+ // value from linear to sRGB
+ r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
+
R_RenderView_UpdateViewVectors();
R_Shadow_UpdateWorldLightSelection();
R_Bloom_StartFrame();
+
+ // apply bloom brightness offset
+ if(r_fb.bloomtexture[0])
+ r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
+
R_Water_StartFrame();
// now we probably have an fbo to render into
if (r_timereport_active)
R_TimeReport("visibility");
+ R_AnimCache_CacheVisibleEntities();
+ if (r_timereport_active)
+ R_TimeReport("animcache");
+
R_Shadow_UpdateBounceGridTexture();
if (r_timereport_active && r_shadow_bouncegrid.integer)
R_TimeReport("bouncegrid");
case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
+ 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(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
continue;
VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
- R_MeshQueue_AddTransparent(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 *)NULL);
}
}
vec3_t org;
Matrix4x4_OriginFromMatrix(&ent->matrix, org);
if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
- R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
+ R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
else
R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
}
-void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
+void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
{
vec3_t right1, right2, diff, normal;
{
int i;
const entity_render_t *ent = rsurface.entity;
- dp_model_t *model = ent->model;
+ dp_model_t *model = ent->model; // when calling this, ent must not be NULL
q3shaderinfo_layer_tcmod_t *tcmod;
- if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
+ if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
return t->currentframe;
t->update_lastrenderframe = r_textureframe;
t->update_lastrenderentity = (void *)ent;
- if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
+ if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
t->camera_entity = ent->entitynumber;
else
t->camera_entity = 0;
{
// no modellight if using fakelight for the map
}
- else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
+ else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
{
// pick a model lighting mode
if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
if (!t->backgroundnmaptexture)
t->backgroundnmaptexture = r_texture_blanknormalmap;
+ // make sure that if glow is going to be used, both textures are not NULL
+ if (!t->backgroundglowtexture && t->glowtexture)
+ t->backgroundglowtexture = r_texture_black;
+ if (!t->glowtexture && t->backgroundglowtexture)
+ t->glowtexture = r_texture_black;
}
else
{
t->basetexture = r_texture_grey128;
t->pantstexture = r_texture_black;
t->shirttexture = r_texture_black;
- t->nmaptexture = r_texture_blanknormalmap;
+ if (gl_lightmaps.integer < 2)
+ t->nmaptexture = r_texture_blanknormalmap;
t->glosstexture = r_texture_black;
t->glowtexture = NULL;
t->fogtexture = NULL;
t->reflectmasktexture = NULL;
t->backgroundbasetexture = NULL;
- t->backgroundnmaptexture = r_texture_blanknormalmap;
+ if (gl_lightmaps.integer < 2)
+ t->backgroundnmaptexture = r_texture_blanknormalmap;
t->backgroundglosstexture = r_texture_black;
t->backgroundglowtexture = NULL;
t->specularscale = 0;
blendfunc2 = GL_ZERO;
}
// don't colormod evilblend textures
- if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
+ if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
VectorSet(t->lightmapcolor, 1, 1, 1);
depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
rsurface.passcolor4f = NULL;
rsurface.passcolor4f_vertexbuffer = NULL;
rsurface.passcolor4f_bufferoffset = 0;
+ rsurface.forcecurrenttextureupdate = false;
}
void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
rsurface.passcolor4f = NULL;
rsurface.passcolor4f_vertexbuffer = NULL;
rsurface.passcolor4f_bufferoffset = 0;
+ rsurface.forcecurrenttextureupdate = false;
}
void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, int entflags, double shadertime, float r, float g, float b, float a, int numvertices, const float *vertex3f, const float *texcoord2f, const float *normal3f, const float *svector3f, const float *tvector3f, const float *color4f, int numtriangles, const int *element3i, const unsigned short *element3s, qboolean wantnormals, qboolean wanttangents)
rsurface.passcolor4f = NULL;
rsurface.passcolor4f_vertexbuffer = NULL;
rsurface.passcolor4f_bufferoffset = 0;
+ rsurface.forcecurrenttextureupdate = true;
if (rsurface.modelnumvertices && rsurface.modelelement3i)
{
rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
rsurface.passcolor4f_vertexbuffer = 0;
rsurface.passcolor4f_bufferoffset = 0;
- for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
+ for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
{
f = RSurf_FogVertex(v);
c2[0] = c[0] * f;
R_Mesh_TexBind(1, 0);
R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
// generate a color array for the fog pass
- R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
RSurf_DrawBatch();
break;
default:
switch (layer->type)
{
case TEXTURELAYERTYPE_LITTEXTURE:
- if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
+ if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
{
// two-pass lit texture with 2x rgbscale
// first the lightmap pass
R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
RSurf_DrawBatch_GL11_VertexShade(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
+ else if (FAKELIGHT_ENABLED)
+ RSurf_DrawBatch_GL11_FakeLight(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
else
RSurf_DrawBatch_GL11_VertexColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
}
R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
}
// generate a color array for the fog pass
- R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
RSurf_DrawBatch();
break;
default:
rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
}
-static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
+static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
{
// transparent surfaces get pushed off into the transparent queue
int surfacelistindex;
for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
{
surface = texturesurfacelist[surfacelistindex];
- tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
- tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
- tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
+ if (r_transparent_sortsurfacesbynearest.integer)
+ {
+ tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
+ tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
+ tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
+ }
+ else
+ {
+ tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
+ tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
+ tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
+ }
Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
- if (queueentity->transparent_offset) // transparent offset
+ if (rsurface.entity->transparent_offset) // transparent offset
{
- center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
- center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
- center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
+ center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
+ center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
+ center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
}
- R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
+ R_MeshQueue_AddTransparent((rsurface.entity->flags & RENDER_WORLDOBJECT) ? TRANSPARENTSORT_SKY : (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? TRANSPARENTSORT_HUD : rsurface.texture->transparentsort, center, R_DrawSurface_TransparentCallback, rsurface.entity, surface - rsurface.modelsurfaces, rsurface.rtlight);
}
}
static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
{
- const entity_render_t *queueentity = r_refdef.scene.worldentity;
CHECKGLERROR
if (depthonly)
R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
if (!rsurface.texture->currentnumlayers)
return;
if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
- R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
+ R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
else
R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
}
R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
else if (!rsurface.texture->currentnumlayers)
return;
- else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
+ else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
{
// in the deferred case, transparent surfaces were queued during prepass
if (!r_shadow_usingdeferredprepass)
- R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
+ R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
}
else
{
R_FrameData_ReturnToMark();
}
-static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
+static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
{
CHECKGLERROR
if (depthonly)
if (!rsurface.texture->currentnumlayers)
return;
if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
- R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
+ R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
else
R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
}
R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
else if (!rsurface.texture->currentnumlayers)
return;
- else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
+ else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
{
// in the deferred case, transparent surfaces were queued during prepass
if (!r_shadow_usingdeferredprepass)
- R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
+ R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
}
else
{
;
}
// render the range of surfaces
- R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
+ R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
}
R_FrameData_ReturnToMark();
}
for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
{
VectorLerp(loc->mins, 0.5f, loc->maxs, center);
- R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
}
}
else
frametime = 0;
decalsystem->lastupdatetime = r_refdef.scene.time;
- decal = decalsystem->decals;
numdecals = decalsystem->numdecals;
for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
RSurf_ActiveModelEntity(ent, false, false, false);
decalsystem->lastupdatetime = r_refdef.scene.time;
- decal = decalsystem->decals;
faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
{
int triangleindex;
int bihleafindex;
- qboolean cullbox = ent == r_refdef.scene.worldentity;
+ qboolean cullbox = false;
const q3mbrush_t *brush;
const bih_t *bih = &model->collision_bih;
const bih_leaf_t *bihleaf;
float vertex3f[3][3];
GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
- cullbox = false;
for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
{
if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
}
}
}
- if (update)
- for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
- if (update[j])
- R_BuildLightMap(ent, surfaces + j);
+
R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
// add to stats if desired
texture.offsetscale = 1;
texture.specularscalemod = 1;
texture.specularpowermod = 1;
+ texture.transparentsort = TRANSPARENTSORT_DISTANCE;
+ // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
+ // JUST GREP FOR "specularscalemod = 1".
surface.texture = &texture;
surface.num_triangles = numtriangles;