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)"};
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"};
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 11
+#define SHADERSTATICPARMS_COUNT 13
static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
static int shaderstaticparms_count = 0;
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_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
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);
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_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);
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;
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;
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");
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;
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)
{
if (rsurface.passcolor4f)
{
// generate color arrays
- c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
rsurface.passcolor4f_vertexbuffer = 0;
rsurface.passcolor4f_bufferoffset = 0;
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