From 2a1615321fd8f4a44b97d5b980bb15a4a2132292 Mon Sep 17 00:00:00 2001 From: havoc Date: Tue, 27 Dec 2005 10:10:55 +0000 Subject: [PATCH] reworked rtlighting code to handle transparent water lighting and transparent model lighting (doesn't properly handle alpha textures though) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@5871 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_particles.c | 8 +- client.h | 6 + gl_rmain.c | 50 +++--- gl_rsurf.c | 97 ++++++----- meshqueue.c | 38 +++-- meshqueue.h | 4 +- model_shared.h | 6 +- r_explosion.c | 7 +- r_lightning.c | 6 +- r_shadow.c | 446 ++++++++++++++++++++++++++++--------------------- r_shadow.h | 25 ++- r_sprites.c | 6 +- 12 files changed, 406 insertions(+), 293 deletions(-) diff --git a/cl_particles.c b/cl_particles.c index 7b56f914..d49affc9 100644 --- a/cl_particles.c +++ b/cl_particles.c @@ -2064,9 +2064,9 @@ float particle_vertex3f[12], particle_texcoord2f[8]; void R_DrawParticle(particle_t *p) { #else -void R_DrawParticleCallback(const void *calldata1, int calldata2) +void R_DrawParticle_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight) { - const particle_t *p = (particle_t *)calldata1; + const particle_t *p = particles + surfacenumber; rmeshstate_t m; #endif pblend_t blendmode; @@ -2257,9 +2257,9 @@ void R_DrawParticles (void) if (DotProduct(p->org, r_viewforward) >= minparticledist || p->type->orientation == PARTICLE_BEAM) { if (p->type == particletype + pt_decal) - R_DrawParticleCallback(p, 0); + R_DrawParticle_TransparentCallback(0, i, 0); else - R_MeshQueue_AddTransparent(p->org, R_DrawParticleCallback, p, 0); + R_MeshQueue_AddTransparent(p->org, R_DrawParticle_TransparentCallback, NULL, i, NULL); } } } diff --git a/client.h b/client.h index c52361e2..1f815d72 100644 --- a/client.h +++ b/client.h @@ -117,6 +117,12 @@ typedef struct rtlight_s // squared cullradius //vec_t cullradius2; + // rendering properties, updated each time a light is rendered + // this is rtlight->color * d_lightstylevalue + vec3_t currentcolor; + // this is R_Shadow_Cubemap(rtlight->cubemapname) + rtexture_t *currentcubemap; + // lightmap renderer stuff (remove someday!) // the size of the light vec_t lightmap_cullradius; diff --git a/gl_rmain.c b/gl_rmain.c index d1291faa..485b446d 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -1281,9 +1281,8 @@ float nomodelcolor4f[6*4] = 0.5f, 0.0f, 0.0f, 1.0f }; -void R_DrawNoModelCallback(const void *calldata1, int calldata2) +void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight) { - const entity_render_t *ent = (entity_render_t *)calldata1; int i; float f1, f2, *c; float color4f[6*4]; @@ -1339,7 +1338,7 @@ void R_DrawNoModelCallback(const void *calldata1, int calldata2) void R_DrawNoModel(entity_render_t *ent) { //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1)) - R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModelCallback, ent, 0); + R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight); //else // R_DrawNoModelCallback(ent, 0); } @@ -1507,7 +1506,6 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) { // FIXME: identify models using a better check than ent->model->brush.shadowmesh //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2; - float currentalpha; { texture_t *texture = t; @@ -1530,14 +1528,14 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) } t->currentmaterialflags = t->basematerialflags; - currentalpha = ent->alpha; + t->currentalpha = ent->alpha; if (t->basematerialflags & MATERIALFLAG_WATERALPHA) - currentalpha *= r_wateralpha.value; + t->currentalpha *= r_wateralpha.value; if (!(ent->flags & RENDER_LIGHT)) t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT; if (ent->effects & EF_ADDITIVE) t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT; - else if (currentalpha < 1) + else if (t->currentalpha < 1) t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT; if (ent->effects & EF_NODEPTHTEST) t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST; @@ -1586,11 +1584,12 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) currentbasetexture = (ent->colormap < 0 && t->skin.merged) ? t->skin.merged : t->skin.base; if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) { - R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], currentalpha); + // fullbright is not affected by r_lightmapintensity + R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha); if (ent->colormap >= 0 && t->skin.pants) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2], currentalpha); + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2], t->currentalpha); if (ent->colormap >= 0 && t->skin.shirt) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2], currentalpha); + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2], t->currentalpha); } else { @@ -1601,32 +1600,30 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) // applied to the color if (ent->model->type == mod_brushq3) colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f); - // transparent and fullbright are not affected by r_lightmapintensity - if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT)) - colorscale *= r_lightmapintensity; + colorscale *= r_lightmapintensity; if (r_textureunits.integer >= 2 && gl_combine.integer) - R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE_COMBINE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, currentalpha); + R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE_COMBINE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha); else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0) - R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale * 0.5f, ent->colormod[1] * colorscale * 0.5f, ent->colormod[2] * colorscale * 0.5f, currentalpha); + R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale * 0.5f, ent->colormod[1] * colorscale * 0.5f, ent->colormod[2] * colorscale * 0.5f, t->currentalpha); else - R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, currentalpha); + R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha); if (r_ambient.value >= (1.0f/64.0f)) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), currentalpha); + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha); if (ent->colormap >= 0 && t->skin.pants) { - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * colorscale, ent->colormap_pantscolor[1] * colorscale, ent->colormap_pantscolor[2] * colorscale, currentalpha); + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * colorscale, ent->colormap_pantscolor[1] * colorscale, ent->colormap_pantscolor[2] * colorscale, t->currentalpha); if (r_ambient.value >= (1.0f/64.0f)) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[2] * r_ambient.value * (1.0f / 64.0f), currentalpha); + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha); } if (ent->colormap >= 0 && t->skin.shirt) { - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * colorscale, ent->colormap_shirtcolor[1] * colorscale, ent->colormap_shirtcolor[2] * colorscale, currentalpha); + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * colorscale, ent->colormap_shirtcolor[1] * colorscale, ent->colormap_shirtcolor[2] * colorscale, t->currentalpha); if (r_ambient.value >= (1.0f/64.0f)) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[2] * r_ambient.value * (1.0f / 64.0f), currentalpha); + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha); } } if (t->skin.glow != NULL) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, currentalpha); + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha); if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD)) { // if this is opaque use alpha blend which will darken the earlier @@ -1640,7 +1637,7 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) // were darkened by fog already, and we should not add fog color // (because the background was not darkened, there is no fog color // that was lost behind it). - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->skin.fog, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], currentalpha); + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->skin.fog, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], t->currentalpha); } } } @@ -2181,10 +2178,9 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text qglEnable(GL_CULL_FACE); } -static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2) +static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight) { - const entity_render_t *ent = (entity_render_t *)calldata1; - const msurface_t *surface = ent->model->data_surfaces + calldata2; + const msurface_t *surface = ent->model->data_surfaces + surfacenumber; vec3_t modelorg; texture_t *texture; @@ -2215,7 +2211,7 @@ void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int tex tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f; tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f; Matrix4x4_Transform(&ent->matrix, tempcenter, center); - R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->data_surfaces); + R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight); } } } diff --git a/gl_rsurf.c b/gl_rsurf.c index 786e738b..1ebb0c88 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -294,12 +294,12 @@ void R_Stain (const vec3_t origin, float radius, int cr1, int cg1, int cb1, int ============================================================= */ -static void R_DrawPortal_Callback(const void *calldata1, int calldata2) +static void R_DrawPortal_Callback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight) { + const mportal_t *portal = (mportal_t *)ent; int i; float *v; rmeshstate_t m; - const mportal_t *portal = (mportal_t *)calldata1; GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GL_DepthMask(false); GL_DepthTest(true); @@ -309,7 +309,7 @@ static void R_DrawPortal_Callback(const void *calldata1, int calldata2) m.pointer_vertex = varray_vertex3f; R_Mesh_State(&m); - i = calldata2; + i = surfacenumber; GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f), ((i & 0x0038) >> 3) * (1.0f / 7.0f), ((i & 0x01C0) >> 6) * (1.0f / 7.0f), @@ -330,7 +330,7 @@ static void R_DrawPortal_Callback(const void *calldata1, int calldata2) // LordHavoc: this is just a nice debugging tool, very slow static void R_DrawPortals(void) { - int i, leafnum;//, portalnum; + int i, leafnum; mportal_t *portal; float center[3], f; model_t *model = r_refdef.worldmodel; @@ -351,8 +351,7 @@ static void R_DrawPortals(void) VectorAdd(center, portal->points[i].position, center); f = ixtable[portal->numpoints]; VectorScale(center, f, center); - //R_MeshQueue_AddTransparent(center, R_DrawPortal_Callback, portal, portalnum); - R_MeshQueue_AddTransparent(center, R_DrawPortal_Callback, portal, leafnum); + R_MeshQueue_AddTransparent(center, R_DrawPortal_Callback, (entity_render_t *)portal, leafnum, r_shadow_rtlight); } } } @@ -603,7 +602,6 @@ void R_Q1BSP_RecursiveGetLightInfo(r_q1bsp_getlightinfo_t *info, mnode_t *node) { msurface_t *surface = info->model->data_surfaces + surfaceindex; if (BoxesOverlap(info->lightmins, info->lightmaxs, surface->mins, surface->maxs)) - if ((surface->texture->currentmaterialflags & (MATERIALFLAG_WALL | MATERIALFLAG_NODRAW | MATERIALFLAG_TRANSPARENT)) == MATERIALFLAG_WALL) { int triangleindex, t; const int *e; @@ -768,9 +766,23 @@ void R_Q1BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, } } +static void R_Q1BSP_DrawLight_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight) +{ + msurface_t *surface = ent->model->data_surfaces + surfacenumber; + texture_t *texture = surface->texture; + R_UpdateTextureInfo(ent, texture); + texture = texture->currentframe; + R_Shadow_RenderMode_Begin(); + R_Shadow_RenderMode_ActiveLight((rtlight_t *)rtlight); + R_Shadow_RenderMode_Lighting(false, true); + R_Shadow_SetupEntityLight(ent); + R_Shadow_RenderSurfacesLighting(ent, texture, 1, &surface); + R_Shadow_RenderMode_End(); +} + #define RSURF_MAX_BATCHSURFACES 1024 -void R_Q1BSP_DrawLight(entity_render_t *ent, float *lightcolorbase, float *lightcolorpants, float *lightcolorshirt, int numsurfaces, const int *surfacelist) +void R_Q1BSP_DrawLight(entity_render_t *ent, int numsurfaces, const int *surfacelist) { model_t *model = ent->model; msurface_t *surface; @@ -779,14 +791,9 @@ void R_Q1BSP_DrawLight(entity_render_t *ent, float *lightcolorbase, float *light msurface_t *batchsurfacelist[RSURF_MAX_BATCHSURFACES]; vec3_t modelorg; texture_t *tex; - rtexture_t *basetexture = NULL; - rtexture_t *glosstexture = NULL; - float specularscale = 0; qboolean skip; if (r_drawcollisionbrushes.integer >= 2) return; - if (VectorLength2(lightcolorbase) + VectorLength2(lightcolorpants) + VectorLength2(lightcolorshirt) < 0.0001) - return; R_UpdateAllTextureInfo(ent); Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg); tex = NULL; @@ -803,46 +810,50 @@ void R_Q1BSP_DrawLight(entity_render_t *ent, float *lightcolorbase, float *light { if (batchnumsurfaces > 0) { - R_Shadow_RenderSurfacesLighting(ent, texture, batchnumsurfaces, batchsurfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, glosstexture, specularscale, modelorg); + if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT) + { + int batchsurfaceindex; + for (batchsurfaceindex = 0;batchsurfaceindex < batchnumsurfaces;batchsurfaceindex++) + { + msurface_t *batchsurface = batchsurfacelist[batchsurfaceindex]; + vec3_t tempcenter, center; + tempcenter[0] = (batchsurface->mins[0] + batchsurface->maxs[0]) * 0.5f; + tempcenter[1] = (batchsurface->mins[1] + batchsurface->maxs[1]) * 0.5f; + tempcenter[2] = (batchsurface->mins[2] + batchsurface->maxs[2]) * 0.5f; + Matrix4x4_Transform(&ent->matrix, tempcenter, center); + R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_Q1BSP_DrawLight_TransparentCallback, ent, batchsurface - ent->model->data_surfaces, r_shadow_rtlight); + } + } + else + R_Shadow_RenderSurfacesLighting(ent, texture, batchnumsurfaces, batchsurfacelist); batchnumsurfaces = 0; } tex = surface->texture; texture = surface->texture->currentframe; - // FIXME: transparent surfaces need to be lit later - skip = (texture->currentmaterialflags & (MATERIALFLAG_WALL | MATERIALFLAG_TRANSPARENT)) != MATERIALFLAG_WALL; + skip = (texture->currentmaterialflags & MATERIALFLAG_SKY) != 0; if (skip) continue; - if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) - qglDisable(GL_CULL_FACE); - else - qglEnable(GL_CULL_FACE); - glosstexture = r_texture_black; - specularscale = 0; - if (texture->skin.gloss) - { - if (r_shadow_gloss.integer >= 1 && r_shadow_glossintensity.value > 0 && r_shadow_rtlight->specularscale > 0) - { - glosstexture = texture->skin.gloss; - specularscale = r_shadow_rtlight->specularscale * r_shadow_glossintensity.value; - } - } - else - { - if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0 && r_shadow_glossintensity.value > 0 && r_shadow_rtlight->specularscale > 0) - { - glosstexture = r_texture_white; - specularscale = r_shadow_rtlight->specularscale * r_shadow_gloss2intensity.value; - } - } - basetexture = (ent->colormap < 0 && texture->skin.merged) ? texture->skin.merged : texture->skin.base; - if ((r_shadow_rtlight->ambientscale + r_shadow_rtlight->diffusescale) * (VectorLength2(lightcolorbase) + VectorLength2(lightcolorpants) + VectorLength2(lightcolorshirt)) + specularscale * VectorLength2(lightcolorbase) < (1.0f / 1048576.0f)) - skip = true; } if (!skip && surface->num_triangles) { if (batchnumsurfaces == RSURF_MAX_BATCHSURFACES) { - R_Shadow_RenderSurfacesLighting(ent, texture, batchnumsurfaces, batchsurfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, glosstexture, specularscale, modelorg); + if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT) + { + int batchsurfaceindex; + for (batchsurfaceindex = 0;batchsurfaceindex < batchnumsurfaces;batchsurfaceindex++) + { + msurface_t *batchsurface = batchsurfacelist[batchsurfaceindex]; + vec3_t tempcenter, center; + tempcenter[0] = (batchsurface->mins[0] + batchsurface->maxs[0]) * 0.5f; + tempcenter[1] = (batchsurface->mins[1] + batchsurface->maxs[1]) * 0.5f; + tempcenter[2] = (batchsurface->mins[2] + batchsurface->maxs[2]) * 0.5f; + Matrix4x4_Transform(&ent->matrix, tempcenter, center); + R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_Q1BSP_DrawLight_TransparentCallback, ent, batchsurface - ent->model->data_surfaces, r_shadow_rtlight); + } + } + else + R_Shadow_RenderSurfacesLighting(ent, texture, batchnumsurfaces, batchsurfacelist); batchnumsurfaces = 0; } batchsurfacelist[batchnumsurfaces++] = surface; @@ -850,7 +861,7 @@ void R_Q1BSP_DrawLight(entity_render_t *ent, float *lightcolorbase, float *light } if (batchnumsurfaces > 0) { - R_Shadow_RenderSurfacesLighting(ent, texture, batchnumsurfaces, batchsurfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, glosstexture, specularscale, modelorg); + R_Shadow_RenderSurfacesLighting(ent, texture, batchnumsurfaces, batchsurfacelist); batchnumsurfaces = 0; } qglEnable(GL_CULL_FACE); diff --git a/meshqueue.c b/meshqueue.c index b176bf4d..a9b7ac0b 100644 --- a/meshqueue.c +++ b/meshqueue.c @@ -9,9 +9,10 @@ cvar_t r_meshqueue_sort = {0, "r_meshqueue_sort", "0"}; typedef struct meshqueue_s { struct meshqueue_s *next; - void (*callback)(const void *data1, int data2); - const void *data1; - int data2; + void (*callback)(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight); + const entity_render_t *ent; + int surfacenumber; + const rtlight_t *rtlight; float dist; } meshqueue_t; @@ -40,7 +41,7 @@ void R_MeshQueue_Render(void) if (!mq_count) return; for (mq = mq_listhead;mq;mq = mq->next) - mq->callback(mq->data1, mq->data2); + mq->callback(mq->ent, mq->surfacenumber, mq->rtlight); mq_count = 0; mq_listhead = NULL; } @@ -58,20 +59,21 @@ static void R_MeshQueue_EnlargeTransparentArray(int newtotal) mqt_total = newtotal; } -void R_MeshQueue_Add(void (*callback)(const void *data1, int data2), const void *data1, int data2) +void R_MeshQueue_Add(void (*callback)(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight) { meshqueue_t *mq, **mqnext; if (r_meshqueue_immediaterender.integer) { - callback(data1, data2); + callback(ent, surfacenumber, rtlight); return; } if (mq_count >= mq_total) R_MeshQueue_Render(); mq = &mq_array[mq_count++]; mq->callback = callback; - mq->data1 = data1; - mq->data2 = data2; + mq->ent = ent; + mq->surfacenumber = surfacenumber; + mq->rtlight = rtlight; if (r_meshqueue_sort.integer) { @@ -80,12 +82,17 @@ void R_MeshQueue_Add(void (*callback)(const void *data1, int data2), const void { if (mq->callback == (*mqnext)->callback) { - if (mq->data1 == (*mqnext)->data1) + if (mq->ent == (*mqnext)->ent) { - if (mq->data2 <= (*mqnext)->data2) + if (mq->surfacenumber == (*mqnext)->surfacenumber) + { + if (mq->rtlight <= (*mqnext)->rtlight) + break; + } + else if (mq->surfacenumber < (*mqnext)->surfacenumber) break; } - else if (mq->data1 < (*mqnext)->data1) + else if (mq->ent < (*mqnext)->ent) break; } else if (mq->callback < (*mqnext)->callback) @@ -101,15 +108,16 @@ void R_MeshQueue_Add(void (*callback)(const void *data1, int data2), const void *mqnext = mq; } -void R_MeshQueue_AddTransparent(const vec3_t center, void (*callback)(const void *data1, int data2), const void *data1, int data2) +void R_MeshQueue_AddTransparent(const vec3_t center, void (*callback)(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight) { meshqueue_t *mq; if (mqt_count >= mqt_total) R_MeshQueue_EnlargeTransparentArray(mqt_total + 100); mq = &mqt_array[mqt_count++]; mq->callback = callback; - mq->data1 = data1; - mq->data2 = data2; + mq->ent = ent; + mq->surfacenumber = surfacenumber; + mq->rtlight = rtlight; mq->dist = DotProduct(center, r_viewforward) - mqt_viewplanedist; mq->next = NULL; mqt_viewmaxdist = max(mqt_viewmaxdist, mq->dist); @@ -143,7 +151,7 @@ void R_MeshQueue_RenderTransparent(void) for (i = 4095;i >= 0;i--) if (hash[i]) for (mqt = hash[i];mqt;mqt = mqt->next) - mqt->callback(mqt->data1, mqt->data2); + mqt->callback(mqt->ent, mqt->surfacenumber, mqt->rtlight); mqt_count = 0; } diff --git a/meshqueue.h b/meshqueue.h index ed587e14..fd6cce45 100644 --- a/meshqueue.h +++ b/meshqueue.h @@ -3,8 +3,8 @@ #define MESHQUEUE_H void R_MeshQueue_Init(void); -void R_MeshQueue_Add(void (*callback)(const void *data1, int data2), const void *data1, int data2); -void R_MeshQueue_AddTransparent(const vec3_t center, void (*callback)(const void *data1, int data2), const void *data1, int data2); +void R_MeshQueue_Add(void (*callback)(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight); +void R_MeshQueue_AddTransparent(const vec3_t center, void (*callback)(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight); void R_MeshQueue_BeginScene(void); void R_MeshQueue_Render(void); void R_MeshQueue_RenderTransparent(void); diff --git a/model_shared.h b/model_shared.h index 60c315fc..aa64aa20 100644 --- a/model_shared.h +++ b/model_shared.h @@ -203,6 +203,8 @@ typedef struct texture_s // (this is an optimization in the renderer) int animated; + // the current alpha of this texture (may be affected by r_wateralpha) + float currentalpha; // the current texture frame in animation struct texture_s *currentframe; // current texture transform matrix (used for water scrolling) @@ -555,7 +557,7 @@ typedef struct model_s // draw a shadow volume for the model based on light source void(*DrawShadowVolume)(struct entity_render_s *ent, vec3_t relativelightorigin, float lightradius, int numsurfaces, const int *surfacelist, const vec3_t lightmins, const vec3_t lightmaxs); // draw the lighting on a model (through stencil) - void(*DrawLight)(struct entity_render_s *ent, vec3_t lightcolorbase, vec3_t lightcolorpants, vec3_t lightcolorshirt, int numsurfaces, const int *surfacelist); + void(*DrawLight)(struct entity_render_s *ent, int numsurfaces, const int *surfacelist); // trace a box against this model void (*TraceBox)(struct model_s *model, int frame, struct trace_s *trace, const vec3_t boxstartmins, const vec3_t boxstartmaxs, const vec3_t boxendmins, const vec3_t boxendmaxs, int hitsupercontentsmask); // fields belonging to some types of model @@ -655,7 +657,7 @@ void R_Q1BSP_Draw(struct entity_render_s *ent); void R_Q1BSP_GetLightInfo(struct entity_render_s *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outleaflist, unsigned char *outleafpvs, int *outnumleafspointer, int *outsurfacelist, unsigned char *outsurfacepvs, int *outnumsurfacespointer); void R_Q1BSP_CompileShadowVolume(struct entity_render_s *ent, vec3_t relativelightorigin, float lightradius, int numsurfaces, const int *surfacelist); void R_Q1BSP_DrawShadowVolume(struct entity_render_s *ent, vec3_t relativelightorigin, float lightradius, int numsurfaces, const int *surfacelist, const vec3_t lightmins, const vec3_t lightmaxs); -void R_Q1BSP_DrawLight(struct entity_render_s *ent, vec3_t lightcolorbase, vec3_t lightcolorpants, vec3_t lightcolorshirt, int numsurfaces, const int *surfacelist); +void R_Q1BSP_DrawLight(struct entity_render_s *ent, int numsurfaces, const int *surfacelist); // alias models struct frameblend_s; diff --git a/r_explosion.c b/r_explosion.c index 7bf4e183..000fc692 100644 --- a/r_explosion.c +++ b/r_explosion.c @@ -180,13 +180,12 @@ void R_NewExplosion(vec3_t org) } } -static void R_DrawExplosionCallback(const void *calldata1, int calldata2) +static void R_DrawExplosion_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight) { + const explosion_t *e = explosion + surfacenumber; int numtriangles, numverts; float alpha; rmeshstate_t m; - const explosion_t *e; - e = (explosion_t *)calldata1; GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); GL_DepthMask(false); @@ -258,6 +257,6 @@ void R_DrawExplosions(void) return; for (i = 0;i < MAX_EXPLOSIONS;i++) if (r_refdef.time < explosion[i].endtime) - R_MeshQueue_AddTransparent(explosion[i].origin, R_DrawExplosionCallback, &explosion[i], 0); + R_MeshQueue_AddTransparent(explosion[i].origin, R_DrawExplosion_TransparentCallback, NULL, i, NULL); } diff --git a/r_lightning.c b/r_lightning.c index c11ad9fd..4309170f 100644 --- a/r_lightning.c +++ b/r_lightning.c @@ -229,9 +229,9 @@ void R_FogLightningBeam_Vertex3f_Color4f(const float *v, float *c, int numverts, float beamrepeatscale; -void R_DrawLightningBeamCallback(const void *calldata1, int calldata2) +void R_DrawLightningBeam_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight) { - const beam_t *b = (beam_t *)calldata1; + const beam_t *b = cl_beams + surfacenumber; rmeshstate_t m; vec3_t beamdir, right, up, offset; float length, t1, t2; @@ -343,7 +343,7 @@ void R_DrawLightningBeams(void) { VectorAdd(b->start, b->end, org); VectorScale(org, 0.5f, org); - R_MeshQueue_AddTransparent(org, R_DrawLightningBeamCallback, b, 0); + R_MeshQueue_AddTransparent(org, R_DrawLightningBeam_TransparentCallback, NULL, i, NULL); } } } diff --git a/r_shadow.c b/r_shadow.c index c1f71e14..1631a3ad 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -142,20 +142,22 @@ demonstrated by the game Doom3. extern void R_Shadow_EditLights_Init(void); -typedef enum r_shadowstage_e +typedef enum r_shadow_rendermode_e { - R_SHADOWSTAGE_NONE, - R_SHADOWSTAGE_STENCIL, - R_SHADOWSTAGE_STENCILTWOSIDE, - R_SHADOWSTAGE_LIGHT_VERTEX, - R_SHADOWSTAGE_LIGHT_DOT3, - R_SHADOWSTAGE_LIGHT_GLSL, - R_SHADOWSTAGE_VISIBLEVOLUMES, - R_SHADOWSTAGE_VISIBLELIGHTING, + R_SHADOW_RENDERMODE_NONE, + R_SHADOW_RENDERMODE_STENCIL, + R_SHADOW_RENDERMODE_STENCILTWOSIDE, + R_SHADOW_RENDERMODE_LIGHT_VERTEX, + R_SHADOW_RENDERMODE_LIGHT_DOT3, + R_SHADOW_RENDERMODE_LIGHT_GLSL, + R_SHADOW_RENDERMODE_VISIBLEVOLUMES, + R_SHADOW_RENDERMODE_VISIBLELIGHTING, } -r_shadowstage_t; +r_shadow_rendermode_t; -r_shadowstage_t r_shadowstage = R_SHADOWSTAGE_NONE; +r_shadow_rendermode_t r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE; +r_shadow_rendermode_t r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_NONE; +r_shadow_rendermode_t r_shadow_shadowingrendermode = R_SHADOW_RENDERMODE_NONE; mempool_t *r_shadow_mempool; @@ -991,7 +993,7 @@ void R_Shadow_RenderVolume(int numvertices, int numtriangles, const float *verte m.pointer_vertex = vertex3f; R_Mesh_State(&m); GL_LockArrays(0, numvertices); - if (r_shadowstage == R_SHADOWSTAGE_STENCIL) + if (r_shadow_rendermode == R_SHADOW_RENDERMODE_STENCIL) { // decrement stencil if backface is behind depthbuffer qglCullFace(GL_BACK); // quake is backwards, this culls front faces @@ -1072,32 +1074,24 @@ void R_Shadow_ValidateCvars(void) // light currently being rendered rtlight_t *r_shadow_rtlight; -// light filter cubemap being used by the light -static rtexture_t *r_shadow_lightcubemap; // this is the location of the eye in entity space -static vec3_t r_shadow_entityeyeorigin; +vec3_t r_shadow_entityeyeorigin; // this is the location of the light in entity space -static vec3_t r_shadow_entitylightorigin; +vec3_t r_shadow_entitylightorigin; // this transforms entity coordinates to light filter cubemap coordinates // (also often used for other purposes) -static matrix4x4_t r_shadow_entitytolight; +matrix4x4_t r_shadow_entitytolight; // based on entitytolight this transforms -1 to +1 to 0 to 1 for purposes // of attenuation texturing in full 3D (Z result often ignored) -static matrix4x4_t r_shadow_entitytoattenuationxyz; +matrix4x4_t r_shadow_entitytoattenuationxyz; // this transforms only the Z to S, and T is always 0.5 -static matrix4x4_t r_shadow_entitytoattenuationz; -// rtlight->color * r_refdef.lightstylevalue[rtlight->style] / 256 * r_shadow_lightintensityscale.value * ent->colormod * ent->alpha -static vec3_t r_shadow_entitylightcolorbase; -// rtlight->color * r_refdef.lightstylevalue[rtlight->style] / 256 * r_shadow_lightintensityscale.value * ent->colormap_pantscolor * ent->alpha -static vec3_t r_shadow_entitylightcolorpants; -// rtlight->color * r_refdef.lightstylevalue[rtlight->style] / 256 * r_shadow_lightintensityscale.value * ent->colormap_shirtcolor * ent->alpha -static vec3_t r_shadow_entitylightcolorshirt; +matrix4x4_t r_shadow_entitytoattenuationz; static int r_shadow_lightpermutation; static int r_shadow_lightprog; -void R_Shadow_Stage_Begin(void) +void R_Shadow_RenderMode_Begin(void) { rmeshstate_t m; @@ -1110,42 +1104,55 @@ void R_Shadow_Stage_Begin(void) R_Shadow_MakeTextures(); memset(&m, 0, sizeof(m)); + R_Mesh_State(&m); GL_BlendFunc(GL_ONE, GL_ZERO); GL_DepthMask(false); GL_DepthTest(true); - R_Mesh_State(&m); GL_Color(0, 0, 0, 1); qglCullFace(GL_FRONT); // quake is backwards, this culls back faces qglEnable(GL_CULL_FACE); GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height); - r_shadowstage = R_SHADOWSTAGE_NONE; + + r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE; + + if (gl_ext_stenciltwoside.integer) + r_shadow_shadowingrendermode = R_SHADOW_RENDERMODE_STENCILTWOSIDE; + else + r_shadow_shadowingrendermode = R_SHADOW_RENDERMODE_STENCIL; + + if (r_shadow_glsl.integer && r_shadow_program_light[0]) + r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_GLSL; + else if (gl_dot3arb && gl_texturecubemap && r_textureunits.integer >= 2 && gl_combine.integer && gl_stencil) + r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_DOT3; + else + r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX; } -void R_Shadow_Stage_ActiveLight(rtlight_t *rtlight) +void R_Shadow_RenderMode_ActiveLight(rtlight_t *rtlight) { r_shadow_rtlight = rtlight; } -void R_Shadow_Stage_Reset(void) +void R_Shadow_RenderMode_Reset(void) { rmeshstate_t m; - if (gl_support_stenciltwoside) - qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT); - if (r_shadowstage == R_SHADOWSTAGE_LIGHT_GLSL) + if (r_shadow_rendermode == R_SHADOW_RENDERMODE_LIGHT_GLSL) { qglUseProgramObjectARB(0); - // HACK HACK HACK: work around for stupid NVIDIA bug that causes GL_OUT_OF_MEMORY and/or software rendering in 6xxx drivers + // HACK HACK HACK: work around for bug in NVIDIAI 6xxx drivers that causes GL_OUT_OF_MEMORY and/or software rendering qglBegin(GL_TRIANGLES); qglEnd(); CHECKGLERROR } + else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_STENCILTWOSIDE) + qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT); memset(&m, 0, sizeof(m)); R_Mesh_State(&m); } -void R_Shadow_Stage_StencilShadowVolumes(void) +void R_Shadow_RenderMode_StencilShadowVolumes(void) { - R_Shadow_Stage_Reset(); + R_Shadow_RenderMode_Reset(); GL_Color(1, 1, 1, 1); GL_ColorMask(0, 0, 0, 0); GL_BlendFunc(GL_ONE, GL_ZERO); @@ -1163,9 +1170,9 @@ void R_Shadow_Stage_StencilShadowVolumes(void) qglCullFace(GL_FRONT); // quake is backwards, this culls back faces qglEnable(GL_STENCIL_TEST); qglStencilFunc(GL_ALWAYS, 128, ~0); - if (gl_ext_stenciltwoside.integer) + r_shadow_rendermode = r_shadow_shadowingrendermode; + if (r_shadow_rendermode == R_SHADOW_RENDERMODE_STENCILTWOSIDE) { - r_shadowstage = R_SHADOWSTAGE_STENCILTWOSIDE; qglDisable(GL_CULL_FACE); qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT); qglActiveStencilFaceEXT(GL_BACK); // quake is backwards, this is front faces @@ -1177,7 +1184,6 @@ void R_Shadow_Stage_StencilShadowVolumes(void) } else { - r_shadowstage = R_SHADOWSTAGE_STENCIL; qglEnable(GL_CULL_FACE); qglStencilMask(~0); // this is changed by every shadow render so its value here is unimportant @@ -1187,10 +1193,9 @@ void R_Shadow_Stage_StencilShadowVolumes(void) renderstats.lights_clears++; } -void R_Shadow_Stage_Lighting(int stenciltest) +void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent) { - rmeshstate_t m; - R_Shadow_Stage_Reset(); + R_Shadow_RenderMode_Reset(); GL_BlendFunc(GL_ONE, GL_ONE); GL_DepthMask(false); GL_DepthTest(true); @@ -1198,10 +1203,13 @@ void R_Shadow_Stage_Lighting(int stenciltest) //qglDisable(GL_POLYGON_OFFSET_FILL); GL_Color(1, 1, 1, 1); GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1); - qglDepthFunc(GL_EQUAL); + if (transparent) + qglDepthFunc(GL_LEQUAL); + else + qglDepthFunc(GL_EQUAL); qglCullFace(GL_FRONT); // quake is backwards, this culls back faces qglEnable(GL_CULL_FACE); - if (r_shadowstage == R_SHADOWSTAGE_STENCIL || r_shadowstage == R_SHADOWSTAGE_STENCILTWOSIDE) + if (stenciltest) qglEnable(GL_STENCIL_TEST); else qglDisable(GL_STENCIL_TEST); @@ -1210,22 +1218,21 @@ void R_Shadow_Stage_Lighting(int stenciltest) // only draw light where this geometry was already rendered AND the // stencil is 128 (values other than this mean shadow) qglStencilFunc(GL_EQUAL, 128, ~0); - if (r_shadow_glsl.integer && r_shadow_program_light[0]) + r_shadow_rendermode = r_shadow_lightingrendermode; + // do global setup needed for the chosen lighting mode + if (r_shadow_rendermode == R_SHADOW_RENDERMODE_LIGHT_GLSL) { - r_shadowstage = R_SHADOWSTAGE_LIGHT_GLSL; - memset(&m, 0, sizeof(m)); - m.pointer_vertex = varray_vertex3f; - m.pointer_texcoord[0] = varray_texcoord2f[0]; - m.pointer_texcoord3f[1] = varray_svector3f; - m.pointer_texcoord3f[2] = varray_tvector3f; - m.pointer_texcoord3f[3] = varray_normal3f; - m.tex[0] = R_GetTexture(r_texture_blanknormalmap); // normal - m.tex[1] = R_GetTexture(r_texture_white); // diffuse - m.tex[2] = R_GetTexture(r_texture_white); // gloss - m.texcubemap[3] = R_GetTexture(r_shadow_lightcubemap); // light filter - m.tex[4] = R_GetTexture(r_texture_fogattenuation); // fog - //m.texmatrix[3] = r_shadow_entitytolight; // light filter matrix - R_Mesh_State(&m); + R_Mesh_VertexPointer(varray_vertex3f); + R_Mesh_TexCoordPointer(0, 2, varray_texcoord2f[0]); + R_Mesh_TexCoordPointer(1, 3, varray_svector3f); + R_Mesh_TexCoordPointer(2, 3, varray_tvector3f); + R_Mesh_TexCoordPointer(3, 3, varray_normal3f); + R_Mesh_TexBind(0, R_GetTexture(r_texture_blanknormalmap)); // normal + R_Mesh_TexBind(1, R_GetTexture(r_texture_white)); // diffuse + R_Mesh_TexBind(2, R_GetTexture(r_texture_white)); // gloss + R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap)); // light filter + R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation)); // fog + //R_Mesh_TexMatrix(3, r_shadow_entitytolight); // light filter matrix GL_BlendFunc(GL_ONE, GL_ONE); GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 0); CHECKGLERROR @@ -1237,7 +1244,7 @@ void R_Shadow_Stage_Lighting(int stenciltest) r_shadow_lightpermutation |= SHADERPERMUTATION_FOG; if (r_shadow_rtlight->specularscale && r_shadow_gloss.integer >= 1 && r_shadow_program_light[r_shadow_lightpermutation | SHADERPERMUTATION_SPECULAR]) r_shadow_lightpermutation |= SHADERPERMUTATION_SPECULAR; - if (r_shadow_lightcubemap != r_texture_whitecube && r_shadow_program_light[r_shadow_lightpermutation | SHADERPERMUTATION_CUBEFILTER]) + if (r_shadow_rtlight->currentcubemap != r_texture_whitecube && r_shadow_program_light[r_shadow_lightpermutation | SHADERPERMUTATION_CUBEFILTER]) r_shadow_lightpermutation |= SHADERPERMUTATION_CUBEFILTER; if (r_shadow_glsl_offsetmapping.integer && r_shadow_program_light[r_shadow_lightpermutation | SHADERPERMUTATION_OFFSETMAPPING]) r_shadow_lightpermutation |= SHADERPERMUTATION_OFFSETMAPPING; @@ -1259,7 +1266,7 @@ void R_Shadow_Stage_Lighting(int stenciltest) qglUniform1fARB(qglGetUniformLocationARB(r_shadow_lightprog, "SpecularPower"), 8);CHECKGLERROR qglUniform1fARB(qglGetUniformLocationARB(r_shadow_lightprog, "SpecularScale"), r_shadow_rtlight->specularscale);CHECKGLERROR } - //qglUniform3fARB(qglGetUniformLocationARB(r_shadow_lightprog, "LightColor"), lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKGLERROR + //qglUniform3fARB(qglGetUniformLocationARB(r_shadow_lightprog, "LightColor"), r_shadow_entitylightcolorbase[0], r_shadow_entitylightcolorbase[1], r_shadow_entitylightcolorbase[2]);CHECKGLERROR //qglUniform3fARB(qglGetUniformLocationARB(r_shadow_lightprog, "LightPosition"), relativelightorigin[0], relativelightorigin[1], relativelightorigin[2]);CHECKGLERROR //if (r_shadow_lightpermutation & (SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_FOG | SHADERPERMUTATION_OFFSETMAPPING)) //{ @@ -1271,15 +1278,11 @@ void R_Shadow_Stage_Lighting(int stenciltest) qglUniform1fARB(qglGetUniformLocationARB(r_shadow_lightprog, "OffsetMapping_Bias"), r_shadow_glsl_offsetmapping_bias.value);CHECKGLERROR } } - else if (gl_dot3arb && gl_texturecubemap && r_textureunits.integer >= 2 && gl_combine.integer && gl_stencil) - r_shadowstage = R_SHADOWSTAGE_LIGHT_DOT3; - else - r_shadowstage = R_SHADOWSTAGE_LIGHT_VERTEX; } -void R_Shadow_Stage_VisibleShadowVolumes(void) +void R_Shadow_RenderMode_VisibleShadowVolumes(void) { - R_Shadow_Stage_Reset(); + R_Shadow_RenderMode_Reset(); GL_BlendFunc(GL_ONE, GL_ONE); GL_DepthMask(false); GL_DepthTest(r_shadow_visiblevolumes.integer < 2); @@ -1290,32 +1293,35 @@ void R_Shadow_Stage_VisibleShadowVolumes(void) qglCullFace(GL_FRONT); // this culls back qglDisable(GL_CULL_FACE); qglDisable(GL_STENCIL_TEST); - r_shadowstage = R_SHADOWSTAGE_VISIBLEVOLUMES; + r_shadow_rendermode = R_SHADOW_RENDERMODE_VISIBLEVOLUMES; } -void R_Shadow_Stage_VisibleLighting(int stenciltest) +void R_Shadow_RenderMode_VisibleLighting(qboolean stenciltest, qboolean transparent) { - R_Shadow_Stage_Reset(); + R_Shadow_RenderMode_Reset(); GL_BlendFunc(GL_ONE, GL_ONE); GL_DepthMask(false); GL_DepthTest(r_shadow_visiblelighting.integer < 2); qglPolygonOffset(0, 0); GL_Color(0.1, 0.0125, 0, 1); GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1); - qglDepthFunc(GL_EQUAL); + if (transparent) + qglDepthFunc(GL_LEQUAL); + else + qglDepthFunc(GL_EQUAL); qglCullFace(GL_FRONT); // this culls back qglEnable(GL_CULL_FACE); if (stenciltest) qglEnable(GL_STENCIL_TEST); else qglDisable(GL_STENCIL_TEST); - r_shadowstage = R_SHADOWSTAGE_VISIBLELIGHTING; + r_shadow_rendermode = R_SHADOW_RENDERMODE_VISIBLELIGHTING; } -void R_Shadow_Stage_End(void) +void R_Shadow_RenderMode_End(void) { - R_Shadow_Stage_Reset(); - R_Shadow_Stage_ActiveLight(NULL); + R_Shadow_RenderMode_Reset(); + R_Shadow_RenderMode_ActiveLight(NULL); GL_BlendFunc(GL_ONE, GL_ZERO); GL_DepthMask(true); GL_DepthTest(true); @@ -1326,13 +1332,14 @@ void R_Shadow_Stage_End(void) GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height); qglDepthFunc(GL_LEQUAL); qglCullFace(GL_FRONT); // quake is backwards, this culls back faces + qglEnable(GL_CULL_FACE); qglDisable(GL_STENCIL_TEST); qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); if (gl_support_stenciltwoside) qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT); qglStencilMask(~0); qglStencilFunc(GL_ALWAYS, 128, ~0); - r_shadowstage = R_SHADOWSTAGE_NONE; + r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE; } qboolean R_Shadow_ScissorForBBox(const float *mins, const float *maxs) @@ -1431,7 +1438,7 @@ extern float *rsurface_tvector3f; extern float *rsurface_normal3f; extern void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg); -static void R_Shadow_RenderSurfacesLighting_Light_Vertex_Shading(const msurface_t *surface, const float *diffusecolor, const float *ambientcolor, float reduce, const vec3_t modelorg) +static void R_Shadow_RenderSurfacesLighting_Light_Vertex_Shading(const msurface_t *surface, const float *diffusecolor, const float *ambientcolor, float reduce) { int numverts = surface->num_vertices; float *vertex3f = rsurface_vertex3f + 3 * surface->num_firstvertex; @@ -1452,7 +1459,7 @@ static void R_Shadow_RenderSurfacesLighting_Light_Vertex_Shading(const msurface_ color4f[2] = (ambientcolor[2] + shadeintensity * diffusecolor[2]) - reduce; if (fogenabled) { - float f = VERTEXFOGTABLE(VectorDistance(v, modelorg)); + float f = VERTEXFOGTABLE(VectorDistance(v, r_shadow_entityeyeorigin)); VectorScale(color4f, f, color4f); } } @@ -1485,7 +1492,7 @@ static void R_Shadow_RenderSurfacesLighting_Light_Vertex_Shading(const msurface_ } if (fogenabled) { - float f = VERTEXFOGTABLE(VectorDistance(v, modelorg)); + float f = VERTEXFOGTABLE(VectorDistance(v, r_shadow_entityeyeorigin)); VectorScale(color4f, f, color4f); } } @@ -1519,7 +1526,7 @@ static void R_Shadow_RenderSurfacesLighting_Light_Vertex_Shading(const msurface_ } if (fogenabled) { - float f = VERTEXFOGTABLE(VectorDistance(v, modelorg)); + float f = VERTEXFOGTABLE(VectorDistance(v, r_shadow_entityeyeorigin)); VectorScale(color4f, f, color4f); } } @@ -1594,7 +1601,7 @@ static void R_Shadow_GenTexCoords_Specular_NormalCubeMap(float *out3f, int numve } } -static void R_Shadow_RenderSurfacesLighting_VisibleLighting(const entity_render_t *ent, const texture_t *texture, int numsurfaces, msurface_t **surfacelist, const vec3_t lightcolorbase, const vec3_t lightcolorpants, const vec3_t lightcolorshirt, rtexture_t *basetexture, rtexture_t *pantstexture, rtexture_t *shirttexture, rtexture_t *normalmaptexture, rtexture_t *glosstexture, float specularscale, const vec3_t modelorg) +static void R_Shadow_RenderSurfacesLighting_VisibleLighting(const entity_render_t *ent, const texture_t *texture, int numsurfaces, msurface_t **surfacelist, const vec3_t lightcolorbase, const vec3_t lightcolorpants, const vec3_t lightcolorshirt, rtexture_t *basetexture, rtexture_t *pantstexture, rtexture_t *shirttexture, rtexture_t *normalmaptexture, rtexture_t *glosstexture, float specularscale) { // used to display how many times a surface is lit for level design purposes int surfacelistindex; @@ -1614,14 +1621,14 @@ static void R_Shadow_RenderSurfacesLighting_VisibleLighting(const entity_render_ for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++) { const msurface_t *surface = surfacelist[surfacelistindex]; - RSurf_SetVertexPointer(ent, texture, surface, modelorg); + RSurf_SetVertexPointer(ent, texture, surface, r_shadow_entityeyeorigin); GL_LockArrays(surface->num_firstvertex, surface->num_vertices); R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle); GL_LockArrays(0, 0); } } -static void R_Shadow_RenderSurfacesLighting_Light_GLSL(const entity_render_t *ent, const texture_t *texture, int numsurfaces, msurface_t **surfacelist, const vec3_t lightcolorbase, const vec3_t lightcolorpants, const vec3_t lightcolorshirt, rtexture_t *basetexture, rtexture_t *pantstexture, rtexture_t *shirttexture, rtexture_t *normalmaptexture, rtexture_t *glosstexture, float specularscale, const vec3_t modelorg) +static void R_Shadow_RenderSurfacesLighting_Light_GLSL(const entity_render_t *ent, const texture_t *texture, int numsurfaces, msurface_t **surfacelist, const vec3_t lightcolorbase, const vec3_t lightcolorpants, const vec3_t lightcolorshirt, rtexture_t *basetexture, rtexture_t *pantstexture, rtexture_t *shirttexture, rtexture_t *normalmaptexture, rtexture_t *glosstexture, float specularscale) { // ARB2 GLSL shader path (GFFX5200, Radeon 9500) int surfacelistindex; @@ -1631,9 +1638,9 @@ static void R_Shadow_RenderSurfacesLighting_Light_GLSL(const entity_render_t *en qboolean dospecular = specularscale * VectorLength2(lightcolorbase) > 0.00001 && glosstexture != r_texture_black; // TODO: add direct pants/shirt rendering if (dopants) - R_Shadow_RenderSurfacesLighting_Light_GLSL(ent, texture, numsurfaces, surfacelist, lightcolorpants, vec3_origin, vec3_origin, pantstexture, r_texture_black, r_texture_black, normalmaptexture, r_texture_black, 0, modelorg); + R_Shadow_RenderSurfacesLighting_Light_GLSL(ent, texture, numsurfaces, surfacelist, lightcolorpants, vec3_origin, vec3_origin, pantstexture, r_texture_black, r_texture_black, normalmaptexture, r_texture_black, 0); if (doshirt) - R_Shadow_RenderSurfacesLighting_Light_GLSL(ent, texture, numsurfaces, surfacelist, lightcolorshirt, vec3_origin, vec3_origin, shirttexture, r_texture_black, r_texture_black, normalmaptexture, r_texture_black, 0, modelorg); + R_Shadow_RenderSurfacesLighting_Light_GLSL(ent, texture, numsurfaces, surfacelist, lightcolorshirt, vec3_origin, vec3_origin, shirttexture, r_texture_black, r_texture_black, normalmaptexture, r_texture_black, 0); if (!dobase && !dospecular) return; R_Mesh_TexMatrix(0, &texture->currenttexmatrix); @@ -1649,7 +1656,7 @@ static void R_Shadow_RenderSurfacesLighting_Light_GLSL(const entity_render_t *en { const msurface_t *surface = surfacelist[surfacelistindex]; const int *elements = surface->groupmesh->data_element3i + surface->num_firsttriangle * 3; - RSurf_SetVertexPointer(ent, texture, surface, modelorg); + RSurf_SetVertexPointer(ent, texture, surface, r_shadow_entityeyeorigin); if (!rsurface_svector3f) { rsurface_svector3f = varray_svector3f; @@ -1667,7 +1674,7 @@ static void R_Shadow_RenderSurfacesLighting_Light_GLSL(const entity_render_t *en } } -static void R_Shadow_RenderSurfacesLighting_Light_Dot3(const entity_render_t *ent, const texture_t *texture, int numsurfaces, msurface_t **surfacelist, const vec3_t lightcolorbase, const vec3_t lightcolorpants, const vec3_t lightcolorshirt, rtexture_t *basetexture, rtexture_t *pantstexture, rtexture_t *shirttexture, rtexture_t *normalmaptexture, rtexture_t *glosstexture, float specularscale, const vec3_t modelorg) +static void R_Shadow_RenderSurfacesLighting_Light_Dot3(const entity_render_t *ent, const texture_t *texture, int numsurfaces, msurface_t **surfacelist, const vec3_t lightcolorbase, const vec3_t lightcolorpants, const vec3_t lightcolorshirt, rtexture_t *basetexture, rtexture_t *pantstexture, rtexture_t *shirttexture, rtexture_t *normalmaptexture, rtexture_t *glosstexture, float specularscale) { // ARB path (any Geforce, any Radeon) int surfacelistindex; @@ -1683,16 +1690,16 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3(const entity_render_t *en qboolean dospecular = specularscale * VectorLength2(lightcolorbase) > 0.00001 && glosstexture != r_texture_black; // TODO: add direct pants/shirt rendering if (doambientpants || dodiffusepants) - R_Shadow_RenderSurfacesLighting_Light_Dot3(ent, texture, numsurfaces, surfacelist, lightcolorpants, vec3_origin, vec3_origin, pantstexture, r_texture_black, r_texture_black, normalmaptexture, r_texture_black, 0, modelorg); + R_Shadow_RenderSurfacesLighting_Light_Dot3(ent, texture, numsurfaces, surfacelist, lightcolorpants, vec3_origin, vec3_origin, pantstexture, r_texture_black, r_texture_black, normalmaptexture, r_texture_black, 0); if (doambientshirt || dodiffuseshirt) - R_Shadow_RenderSurfacesLighting_Light_Dot3(ent, texture, numsurfaces, surfacelist, lightcolorshirt, vec3_origin, vec3_origin, shirttexture, r_texture_black, r_texture_black, normalmaptexture, r_texture_black, 0, modelorg); + R_Shadow_RenderSurfacesLighting_Light_Dot3(ent, texture, numsurfaces, surfacelist, lightcolorshirt, vec3_origin, vec3_origin, shirttexture, r_texture_black, r_texture_black, normalmaptexture, r_texture_black, 0); if (!doambientbase && !dodiffusebase && !dospecular) return; for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++) { const msurface_t *surface = surfacelist[surfacelistindex]; const int *elements = surface->groupmesh->data_element3i + surface->num_firsttriangle * 3; - RSurf_SetVertexPointer(ent, texture, surface, modelorg); + RSurf_SetVertexPointer(ent, texture, surface, r_shadow_entityeyeorigin); if (!rsurface_svector3f) { rsurface_svector3f = varray_svector3f; @@ -1711,7 +1718,7 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3(const entity_render_t *en // performed to get more brightness than otherwise possible. // // Limit mult to 64 for sanity sake. - if (r_shadow_texture3d.integer && r_shadow_lightcubemap != r_texture_whitecube && r_textureunits.integer >= 4) + if (r_shadow_texture3d.integer && r_shadow_rtlight->currentcubemap != r_texture_whitecube && r_textureunits.integer >= 4) { // 3 3D combine path (Geforce3, Radeon 8500) memset(&m, 0, sizeof(m)); @@ -1727,7 +1734,7 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3(const entity_render_t *en m.tex[1] = R_GetTexture(basetexture); m.pointer_texcoord[1] = surface->groupmesh->data_texcoordtexture2f; m.texmatrix[1] = texture->currenttexmatrix; - m.texcubemap[2] = R_GetTexture(r_shadow_lightcubemap); + m.texcubemap[2] = R_GetTexture(r_shadow_rtlight->currentcubemap); #ifdef USETEXMATRIX m.pointer_texcoord3f[2] = rsurface_vertex3f; m.texmatrix[2] = r_shadow_entitytolight; @@ -1737,7 +1744,7 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3(const entity_render_t *en #endif GL_BlendFunc(GL_ONE, GL_ONE); } - else if (r_shadow_texture3d.integer && r_shadow_lightcubemap == r_texture_whitecube && r_textureunits.integer >= 2) + else if (r_shadow_texture3d.integer && r_shadow_rtlight->currentcubemap == r_texture_whitecube && r_textureunits.integer >= 2) { // 2 3D combine path (Geforce3, original Radeon) memset(&m, 0, sizeof(m)); @@ -1755,7 +1762,7 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3(const entity_render_t *en m.texmatrix[1] = texture->currenttexmatrix; GL_BlendFunc(GL_ONE, GL_ONE); } - else if (r_textureunits.integer >= 4 && r_shadow_lightcubemap != r_texture_whitecube) + else if (r_textureunits.integer >= 4 && r_shadow_rtlight->currentcubemap != r_texture_whitecube) { // 4 2D combine path (Geforce3, Radeon 8500) memset(&m, 0, sizeof(m)); @@ -1779,9 +1786,9 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3(const entity_render_t *en m.tex[2] = R_GetTexture(basetexture); m.pointer_texcoord[2] = surface->groupmesh->data_texcoordtexture2f; m.texmatrix[2] = texture->currenttexmatrix; - if (r_shadow_lightcubemap != r_texture_whitecube) + if (r_shadow_rtlight->currentcubemap != r_texture_whitecube) { - m.texcubemap[3] = R_GetTexture(r_shadow_lightcubemap); + m.texcubemap[3] = R_GetTexture(r_shadow_rtlight->currentcubemap); #ifdef USETEXMATRIX m.pointer_texcoord3f[3] = rsurface_vertex3f; m.texmatrix[3] = r_shadow_entitytolight; @@ -1792,7 +1799,7 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3(const entity_render_t *en } GL_BlendFunc(GL_ONE, GL_ONE); } - else if (r_textureunits.integer >= 3 && r_shadow_lightcubemap == r_texture_whitecube) + else if (r_textureunits.integer >= 3 && r_shadow_rtlight->currentcubemap == r_texture_whitecube) { // 3 2D combine path (Geforce3, original Radeon) memset(&m, 0, sizeof(m)); @@ -1851,9 +1858,9 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3(const entity_render_t *en m.tex[0] = R_GetTexture(basetexture); m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f; m.texmatrix[0] = texture->currenttexmatrix; - if (r_shadow_lightcubemap != r_texture_whitecube) + if (r_shadow_rtlight->currentcubemap != r_texture_whitecube) { - m.texcubemap[1] = R_GetTexture(r_shadow_lightcubemap); + m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap); #ifdef USETEXMATRIX m.pointer_texcoord3f[1] = rsurface_vertex3f; m.texmatrix[1] = r_shadow_entitytolight; @@ -1920,9 +1927,9 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3(const entity_render_t *en m.tex[0] = R_GetTexture(basetexture); m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f; m.texmatrix[0] = texture->currenttexmatrix; - if (r_shadow_lightcubemap != r_texture_whitecube) + if (r_shadow_rtlight->currentcubemap != r_texture_whitecube) { - m.texcubemap[1] = R_GetTexture(r_shadow_lightcubemap); + m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap); #ifdef USETEXMATRIX m.pointer_texcoord3f[1] = rsurface_vertex3f; m.texmatrix[1] = r_shadow_entitytolight; @@ -1933,7 +1940,7 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3(const entity_render_t *en } GL_BlendFunc(GL_DST_ALPHA, GL_ONE); } - else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && r_shadow_lightcubemap != r_texture_whitecube) + else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && r_shadow_rtlight->currentcubemap != r_texture_whitecube) { // 1/2/2 3D combine path (original Radeon) memset(&m, 0, sizeof(m)); @@ -1974,9 +1981,9 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3(const entity_render_t *en m.tex[0] = R_GetTexture(basetexture); m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f; m.texmatrix[0] = texture->currenttexmatrix; - if (r_shadow_lightcubemap != r_texture_whitecube) + if (r_shadow_rtlight->currentcubemap != r_texture_whitecube) { - m.texcubemap[1] = R_GetTexture(r_shadow_lightcubemap); + m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap); #ifdef USETEXMATRIX m.pointer_texcoord3f[1] = rsurface_vertex3f; m.texmatrix[1] = r_shadow_entitytolight; @@ -1987,7 +1994,7 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3(const entity_render_t *en } GL_BlendFunc(GL_DST_ALPHA, GL_ONE); } - else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && r_shadow_lightcubemap == r_texture_whitecube) + else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && r_shadow_rtlight->currentcubemap == r_texture_whitecube) { // 2/2 3D combine path (original Radeon) memset(&m, 0, sizeof(m)); @@ -2063,9 +2070,9 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3(const entity_render_t *en m.tex[0] = R_GetTexture(basetexture); m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f; m.texmatrix[0] = texture->currenttexmatrix; - if (r_shadow_lightcubemap != r_texture_whitecube) + if (r_shadow_rtlight->currentcubemap != r_texture_whitecube) { - m.texcubemap[1] = R_GetTexture(r_shadow_lightcubemap); + m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap); #ifdef USETEXMATRIX m.pointer_texcoord3f[1] = rsurface_vertex3f; m.texmatrix[1] = r_shadow_entitytolight; @@ -2125,9 +2132,9 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3(const entity_render_t *en m.tex[0] = R_GetTexture(basetexture); m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f; m.texmatrix[0] = texture->currenttexmatrix; - if (r_shadow_lightcubemap != r_texture_whitecube) + if (r_shadow_rtlight->currentcubemap != r_texture_whitecube) { - m.texcubemap[1] = R_GetTexture(r_shadow_lightcubemap); + m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap); #ifdef USETEXMATRIX m.pointer_texcoord3f[1] = rsurface_vertex3f; m.texmatrix[1] = r_shadow_entitytolight; @@ -2157,7 +2164,7 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3(const entity_render_t *en { colorscale = specularscale; GL_Color(1,1,1,1); - if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && r_shadow_lightcubemap != r_texture_whitecube /* && gl_support_blendsquare*/) // FIXME: detect blendsquare! + if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && r_shadow_rtlight->currentcubemap != r_texture_whitecube /* && gl_support_blendsquare*/) // FIXME: detect blendsquare! { // 2/0/0/1/2 3D combine blendsquare path memset(&m, 0, sizeof(m)); @@ -2212,9 +2219,9 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3(const entity_render_t *en m.tex[0] = R_GetTexture(glosstexture); m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f; m.texmatrix[0] = texture->currenttexmatrix; - if (r_shadow_lightcubemap != r_texture_whitecube) + if (r_shadow_rtlight->currentcubemap != r_texture_whitecube) { - m.texcubemap[1] = R_GetTexture(r_shadow_lightcubemap); + m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap); #ifdef USETEXMATRIX m.pointer_texcoord3f[1] = rsurface_vertex3f; m.texmatrix[1] = r_shadow_entitytolight; @@ -2225,7 +2232,7 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3(const entity_render_t *en } GL_BlendFunc(GL_DST_ALPHA, GL_ONE); } - else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && r_shadow_lightcubemap == r_texture_whitecube /* && gl_support_blendsquare*/) // FIXME: detect blendsquare! + else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && r_shadow_rtlight->currentcubemap == r_texture_whitecube /* && gl_support_blendsquare*/) // FIXME: detect blendsquare! { // 2/0/0/2 3D combine blendsquare path memset(&m, 0, sizeof(m)); @@ -2337,9 +2344,9 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3(const entity_render_t *en m.tex[0] = R_GetTexture(glosstexture); m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f; m.texmatrix[0] = texture->currenttexmatrix; - if (r_shadow_lightcubemap != r_texture_whitecube) + if (r_shadow_rtlight->currentcubemap != r_texture_whitecube) { - m.texcubemap[1] = R_GetTexture(r_shadow_lightcubemap); + m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap); #ifdef USETEXMATRIX m.pointer_texcoord3f[1] = rsurface_vertex3f; m.texmatrix[1] = r_shadow_entitytolight; @@ -2365,7 +2372,7 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3(const entity_render_t *en } } -static void R_Shadow_RenderSurfacesLighting_Light_Vertex(const entity_render_t *ent, const texture_t *texture, int numsurfaces, msurface_t **surfacelist, const vec3_t lightcolorbase, const vec3_t lightcolorpants, const vec3_t lightcolorshirt, rtexture_t *basetexture, rtexture_t *pantstexture, rtexture_t *shirttexture, rtexture_t *normalmaptexture, rtexture_t *glosstexture, float specularscale, const vec3_t modelorg) +static void R_Shadow_RenderSurfacesLighting_Light_Vertex(const entity_render_t *ent, const texture_t *texture, int numsurfaces, msurface_t **surfacelist, const vec3_t lightcolorbase, const vec3_t lightcolorpants, const vec3_t lightcolorshirt, rtexture_t *basetexture, rtexture_t *pantstexture, rtexture_t *shirttexture, rtexture_t *normalmaptexture, rtexture_t *glosstexture, float specularscale) { int surfacelistindex; int renders; @@ -2380,9 +2387,9 @@ static void R_Shadow_RenderSurfacesLighting_Light_Vertex(const entity_render_t * //qboolean dospecular = specularscale * VectorLength2(lightcolorbase) > 0.00001 && glosstexture != r_texture_black; // TODO: add direct pants/shirt rendering if (doambientpants || dodiffusepants) - R_Shadow_RenderSurfacesLighting_Light_Vertex(ent, texture, numsurfaces, surfacelist, lightcolorpants, vec3_origin, vec3_origin, pantstexture, r_texture_black, r_texture_black, normalmaptexture, r_texture_black, 0, modelorg); + R_Shadow_RenderSurfacesLighting_Light_Vertex(ent, texture, numsurfaces, surfacelist, lightcolorpants, vec3_origin, vec3_origin, pantstexture, r_texture_black, r_texture_black, normalmaptexture, r_texture_black, 0); if (doambientshirt || dodiffuseshirt) - R_Shadow_RenderSurfacesLighting_Light_Vertex(ent, texture, numsurfaces, surfacelist, lightcolorshirt, vec3_origin, vec3_origin, shirttexture, r_texture_black, r_texture_black, normalmaptexture, r_texture_black, 0, modelorg); + R_Shadow_RenderSurfacesLighting_Light_Vertex(ent, texture, numsurfaces, surfacelist, lightcolorshirt, vec3_origin, vec3_origin, shirttexture, r_texture_black, r_texture_black, normalmaptexture, r_texture_black, 0); if (!doambientbase && !dodiffusebase) return; VectorScale(lightcolorbase, r_shadow_rtlight->ambientscale, ambientcolor2); @@ -2418,7 +2425,7 @@ static void R_Shadow_RenderSurfacesLighting_Light_Vertex(const entity_render_t * { const msurface_t *surface = surfacelist[surfacelistindex]; const int *elements = surface->groupmesh->data_element3i + surface->num_firsttriangle * 3; - RSurf_SetVertexPointer(ent, texture, surface, modelorg); + RSurf_SetVertexPointer(ent, texture, surface, r_shadow_entityeyeorigin); if (!rsurface_svector3f) { rsurface_svector3f = varray_svector3f; @@ -2447,7 +2454,7 @@ static void R_Shadow_RenderSurfacesLighting_Light_Vertex(const entity_render_t * #endif } } - R_Shadow_RenderSurfacesLighting_Light_Vertex_Shading(surface, diffusecolor2, ambientcolor2, 0, modelorg); + R_Shadow_RenderSurfacesLighting_Light_Vertex_Shading(surface, diffusecolor2, ambientcolor2, 0); for (renders = 0;renders < 64 && (ambientcolor2[0] > renders || ambientcolor2[1] > renders || ambientcolor2[2] > renders || diffusecolor2[0] > renders || diffusecolor2[1] > renders || diffusecolor2[2] > renders);renders++) { int i; @@ -2514,25 +2521,76 @@ goodpass: } } -void R_Shadow_RenderSurfacesLighting(const entity_render_t *ent, const texture_t *texture, int numsurfaces, msurface_t **surfacelist, const vec3_t lightcolorbase, const vec3_t lightcolorpants, const vec3_t lightcolorshirt, rtexture_t *basetexture, rtexture_t *pantstexture, rtexture_t *shirttexture, rtexture_t *normalmaptexture, rtexture_t *glosstexture, float specularscale, const vec3_t modelorg) +void R_Shadow_RenderSurfacesLighting(const entity_render_t *ent, const texture_t *texture, int numsurfaces, msurface_t **surfacelist) { // FIXME: support MATERIALFLAG_NODEPTHTEST - switch (r_shadowstage) + vec3_t lightcolorbase, lightcolorpants, lightcolorshirt; + rtexture_t *basetexture; + rtexture_t *glosstexture; + float specularscale; + if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) + qglDisable(GL_CULL_FACE); + else + qglEnable(GL_CULL_FACE); + glosstexture = r_texture_black; + specularscale = 0; + if (r_shadow_gloss.integer > 0) + { + if (texture->skin.gloss) + { + if (r_shadow_glossintensity.value > 0 && r_shadow_rtlight->specularscale > 0) + { + glosstexture = texture->skin.gloss; + specularscale = r_shadow_rtlight->specularscale * r_shadow_glossintensity.value; + } + } + else + { + if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0 && r_shadow_glossintensity.value > 0 && r_shadow_rtlight->specularscale > 0) + { + glosstexture = r_texture_white; + specularscale = r_shadow_rtlight->specularscale * r_shadow_gloss2intensity.value; + } + } + } + // calculate colors to render this texture with + lightcolorbase[0] = r_shadow_rtlight->currentcolor[0] * ent->colormod[0] * texture->currentalpha; + lightcolorbase[1] = r_shadow_rtlight->currentcolor[1] * ent->colormod[1] * texture->currentalpha; + lightcolorbase[2] = r_shadow_rtlight->currentcolor[2] * ent->colormod[2] * texture->currentalpha; + lightcolorpants[0] = r_shadow_rtlight->currentcolor[0] * ent->colormap_pantscolor[0] * texture->currentalpha; + lightcolorpants[1] = r_shadow_rtlight->currentcolor[1] * ent->colormap_pantscolor[1] * texture->currentalpha; + lightcolorpants[2] = r_shadow_rtlight->currentcolor[2] * ent->colormap_pantscolor[2] * texture->currentalpha; + lightcolorshirt[0] = r_shadow_rtlight->currentcolor[0] * ent->colormap_shirtcolor[0] * texture->currentalpha; + lightcolorshirt[1] = r_shadow_rtlight->currentcolor[1] * ent->colormap_shirtcolor[1] * texture->currentalpha; + lightcolorshirt[2] = r_shadow_rtlight->currentcolor[2] * ent->colormap_shirtcolor[2] * texture->currentalpha; + if (ent->colormap >= 0) + { + basetexture = texture->skin.base; + if ((r_shadow_rtlight->ambientscale + r_shadow_rtlight->diffusescale) * (VectorLength2(lightcolorbase) + VectorLength2(lightcolorpants) + VectorLength2(lightcolorshirt)) + specularscale * VectorLength2(lightcolorbase) < (1.0f / 1048576.0f)) + return; + } + else + { + basetexture = texture->skin.merged ? texture->skin.merged : texture->skin.base; + if ((r_shadow_rtlight->ambientscale + r_shadow_rtlight->diffusescale) * VectorLength2(lightcolorbase) + specularscale * VectorLength2(lightcolorbase) < (1.0f / 1048576.0f)) + return; + } + switch (r_shadow_rendermode) { - case R_SHADOWSTAGE_VISIBLELIGHTING: - R_Shadow_RenderSurfacesLighting_VisibleLighting(ent, texture, numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, glosstexture, specularscale, modelorg); + case R_SHADOW_RENDERMODE_VISIBLELIGHTING: + R_Shadow_RenderSurfacesLighting_VisibleLighting(ent, texture, numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, glosstexture, specularscale); break; - case R_SHADOWSTAGE_LIGHT_GLSL: - R_Shadow_RenderSurfacesLighting_Light_GLSL(ent, texture, numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, glosstexture, specularscale, modelorg); + case R_SHADOW_RENDERMODE_LIGHT_GLSL: + R_Shadow_RenderSurfacesLighting_Light_GLSL(ent, texture, numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, glosstexture, specularscale); break; - case R_SHADOWSTAGE_LIGHT_DOT3: - R_Shadow_RenderSurfacesLighting_Light_Dot3(ent, texture, numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, glosstexture, specularscale, modelorg); + case R_SHADOW_RENDERMODE_LIGHT_DOT3: + R_Shadow_RenderSurfacesLighting_Light_Dot3(ent, texture, numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, glosstexture, specularscale); break; - case R_SHADOWSTAGE_LIGHT_VERTEX: - R_Shadow_RenderSurfacesLighting_Light_Vertex(ent, texture, numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, glosstexture, specularscale, modelorg); + case R_SHADOW_RENDERMODE_LIGHT_VERTEX: + R_Shadow_RenderSurfacesLighting_Light_Vertex(ent, texture, numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, glosstexture, specularscale); break; default: - Con_Printf("R_Shadow_RenderLighting: unknown r_shadowstage %i\n", r_shadowstage); + Con_Printf("R_Shadow_RenderSurfacesLighting: unknown r_shadow_rendermode %i\n", r_shadow_rendermode); break; } } @@ -2681,22 +2739,22 @@ void R_Shadow_UncompileWorldLights(void) R_RTLight_Uncompile(&light->rtlight); } -void R_Shadow_DrawEntityShadow(entity_render_t *ent, rtlight_t *rtlight, int numsurfaces, int *surfacelist) +void R_Shadow_DrawEntityShadow(entity_render_t *ent, int numsurfaces, int *surfacelist) { vec3_t relativeshadoworigin, relativeshadowmins, relativeshadowmaxs; vec_t relativeshadowradius; if (ent == r_refdef.worldentity) { - if (rtlight->compiled && r_shadow_realtime_world_compile.integer && r_shadow_realtime_world_compileshadow.integer) + if (r_shadow_rtlight->compiled && r_shadow_realtime_world_compile.integer && r_shadow_realtime_world_compileshadow.integer) { shadowmesh_t *mesh; R_Mesh_Matrix(&ent->matrix); - for (mesh = rtlight->static_meshchain_shadow;mesh;mesh = mesh->next) + for (mesh = r_shadow_rtlight->static_meshchain_shadow;mesh;mesh = mesh->next) { renderstats.lights_shadowtriangles += mesh->numtriangles; R_Mesh_VertexPointer(mesh->vertex3f); GL_LockArrays(0, mesh->numverts); - if (r_shadowstage == R_SHADOWSTAGE_STENCIL) + if (r_shadow_rendermode == R_SHADOW_RENDERMODE_STENCIL) { // decrement stencil if backface is behind depthbuffer qglCullFace(GL_BACK); // quake is backwards, this culls front faces @@ -2713,13 +2771,13 @@ void R_Shadow_DrawEntityShadow(entity_render_t *ent, rtlight_t *rtlight, int num else if (numsurfaces) { R_Mesh_Matrix(&ent->matrix); - ent->model->DrawShadowVolume(ent, rtlight->shadoworigin, rtlight->radius, numsurfaces, surfacelist, rtlight->cullmins, rtlight->cullmaxs); + ent->model->DrawShadowVolume(ent, r_shadow_rtlight->shadoworigin, r_shadow_rtlight->radius, numsurfaces, surfacelist, r_shadow_rtlight->cullmins, r_shadow_rtlight->cullmaxs); } } else { - Matrix4x4_Transform(&ent->inversematrix, rtlight->shadoworigin, relativeshadoworigin); - relativeshadowradius = rtlight->radius / ent->scale; + Matrix4x4_Transform(&ent->inversematrix, r_shadow_rtlight->shadoworigin, relativeshadoworigin); + relativeshadowradius = r_shadow_rtlight->radius / ent->scale; relativeshadowmins[0] = relativeshadoworigin[0] - relativeshadowradius; relativeshadowmins[1] = relativeshadoworigin[1] - relativeshadowradius; relativeshadowmins[2] = relativeshadoworigin[2] - relativeshadowradius; @@ -2731,27 +2789,17 @@ void R_Shadow_DrawEntityShadow(entity_render_t *ent, rtlight_t *rtlight, int num } } -void R_Shadow_DrawEntityLight(entity_render_t *ent, rtlight_t *rtlight, vec3_t lightcolor, int numsurfaces, int *surfacelist) +void R_Shadow_SetupEntityLight(const entity_render_t *ent) { // set up properties for rendering light onto this entity - r_shadow_entitylightcolorbase[0] = lightcolor[0] * ent->colormod[0] * ent->alpha; - r_shadow_entitylightcolorbase[1] = lightcolor[1] * ent->colormod[1] * ent->alpha; - r_shadow_entitylightcolorbase[2] = lightcolor[2] * ent->colormod[2] * ent->alpha; - r_shadow_entitylightcolorpants[0] = lightcolor[0] * ent->colormap_pantscolor[0] * ent->alpha; - r_shadow_entitylightcolorpants[1] = lightcolor[1] * ent->colormap_pantscolor[1] * ent->alpha; - r_shadow_entitylightcolorpants[2] = lightcolor[2] * ent->colormap_pantscolor[2] * ent->alpha; - r_shadow_entitylightcolorshirt[0] = lightcolor[0] * ent->colormap_shirtcolor[0] * ent->alpha; - r_shadow_entitylightcolorshirt[1] = lightcolor[1] * ent->colormap_shirtcolor[1] * ent->alpha; - r_shadow_entitylightcolorshirt[2] = lightcolor[2] * ent->colormap_shirtcolor[2] * ent->alpha; - Matrix4x4_Concat(&r_shadow_entitytolight, &rtlight->matrix_worldtolight, &ent->matrix); + Matrix4x4_Concat(&r_shadow_entitytolight, &r_shadow_rtlight->matrix_worldtolight, &ent->matrix); Matrix4x4_Concat(&r_shadow_entitytoattenuationxyz, &matrix_attenuationxyz, &r_shadow_entitytolight); Matrix4x4_Concat(&r_shadow_entitytoattenuationz, &matrix_attenuationz, &r_shadow_entitytolight); - Matrix4x4_Transform(&ent->inversematrix, rtlight->shadoworigin, r_shadow_entitylightorigin); + Matrix4x4_Transform(&ent->inversematrix, r_shadow_rtlight->shadoworigin, r_shadow_entitylightorigin); Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, r_shadow_entityeyeorigin); R_Mesh_Matrix(&ent->matrix); - if (r_shadowstage == R_SHADOWSTAGE_LIGHT_GLSL) + if (r_shadow_rendermode == R_SHADOW_RENDERMODE_LIGHT_GLSL) { - R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_lightcubemap)); R_Mesh_TexMatrix(3, &r_shadow_entitytolight); qglUniform3fARB(qglGetUniformLocationARB(r_shadow_lightprog, "LightPosition"), r_shadow_entitylightorigin[0], r_shadow_entitylightorigin[1], r_shadow_entitylightorigin[2]);CHECKGLERROR if (r_shadow_lightpermutation & (SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_FOG | SHADERPERMUTATION_OFFSETMAPPING)) @@ -2759,17 +2807,21 @@ void R_Shadow_DrawEntityLight(entity_render_t *ent, rtlight_t *rtlight, vec3_t l qglUniform3fARB(qglGetUniformLocationARB(r_shadow_lightprog, "EyePosition"), r_shadow_entityeyeorigin[0], r_shadow_entityeyeorigin[1], r_shadow_entityeyeorigin[2]);CHECKGLERROR } } +} + +void R_Shadow_DrawEntityLight(entity_render_t *ent, int numsurfaces, int *surfacelist) +{ + R_Shadow_SetupEntityLight(ent); if (ent == r_refdef.worldentity) - ent->model->DrawLight(ent, r_shadow_entitylightcolorbase, r_shadow_entitylightcolorpants, r_shadow_entitylightcolorshirt, numsurfaces, surfacelist); + ent->model->DrawLight(ent, numsurfaces, surfacelist); else - ent->model->DrawLight(ent, r_shadow_entitylightcolorbase, r_shadow_entitylightcolorpants, r_shadow_entitylightcolorshirt, ent->model->nummodelsurfaces, ent->model->surfacelist); + ent->model->DrawLight(ent, ent->model->nummodelsurfaces, ent->model->surfacelist); } void R_DrawRTLight(rtlight_t *rtlight, qboolean visible) { int i, usestencil; float f; - vec3_t lightcolor; int numleafs, numsurfaces; int *leaflist, *surfacelist; unsigned char *leafpvs; @@ -2778,30 +2830,34 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible) entity_render_t *lightentities[MAX_EDICTS]; entity_render_t *shadowentities[MAX_EDICTS]; - // skip lights that don't light (corona only lights) - if (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale < (1.0f / 32768.0f)) + // skip lights that don't light because of ambientscale+diffusescale+specularscale being 0 (corona only lights) + // skip lights that are basically invisible (color 0 0 0) + if (VectorLength2(rtlight->color) * (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale) < (1.0f / 1048576.0f)) return; + // loading is done before visibility checks because loading should happen + // all at once at the start of a level, not when it stalls gameplay. + // (especially important to benchmarks) + // compile light + if (rtlight->isstatic && !rtlight->compiled && r_shadow_realtime_world_compile.integer) + R_RTLight_Compile(rtlight); + // load cubemap + rtlight->currentcubemap = rtlight->cubemapname[0] ? R_Shadow_Cubemap(rtlight->cubemapname) : r_texture_whitecube; + + // look up the light style value at this time f = (rtlight->style >= 0 ? r_refdef.lightstylevalue[rtlight->style] : 128) * (1.0f / 256.0f) * r_shadow_lightintensityscale.value; - VectorScale(rtlight->color, f, lightcolor); - if (VectorLength2(lightcolor) < (1.0f / 32768.0f)) - return; + VectorScale(rtlight->color, f, rtlight->currentcolor); /* if (rtlight->selected) { f = 2 + sin(realtime * M_PI * 4.0); - VectorScale(lightcolor, f, lightcolor); + VectorScale(rtlight->currentcolor, f, rtlight->currentcolor); } */ - // loading is done before visibility checks because loading should happen - // all at once at the start of a level, not when it stalls gameplay. - // (especially important to benchmarks) - // compile light - if (rtlight->isstatic && !rtlight->compiled && r_shadow_realtime_world_compile.integer) - R_RTLight_Compile(rtlight); - // load cubemap - r_shadow_lightcubemap = rtlight->cubemapname[0] ? R_Shadow_Cubemap(rtlight->cubemapname) : r_texture_whitecube; + // if lightstyle is currently off, don't draw the light + if (VectorLength2(rtlight->currentcolor) < (1.0f / 1048576.0f)) + return; // if the light box is offscreen, skip it if (R_CullBox(rtlight->cullmins, rtlight->cullmaxs)) @@ -2852,12 +2908,16 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible) if (R_Shadow_ScissorForBBox(rtlight->cullmins, rtlight->cullmaxs)) return; + // make a list of lit entities and shadow casting entities numlightentities = 0; - if (numsurfaces) - lightentities[numlightentities++] = r_refdef.worldentity; numshadowentities = 0; + // don't count the world unless some surfaces are actually lit if (numsurfaces) + { + lightentities[numlightentities++] = r_refdef.worldentity; shadowentities[numshadowentities++] = r_refdef.worldentity; + } + // add dynamic entities that are lit by the light if (r_drawentities.integer) { for (i = 0;i < r_refdef.numentities;i++) @@ -2881,37 +2941,46 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible) if (!numlightentities) return; - R_Shadow_Stage_ActiveLight(rtlight); + // make this the active rtlight for rendering purposes + R_Shadow_RenderMode_ActiveLight(rtlight); + // count this light in the r_speeds renderstats.lights++; + // draw stencil shadow volumes to mask off pixels that are in shadow + // so that they won't receive lighting usestencil = false; if (numshadowentities && (!visible || r_shadow_visiblelighting.integer == 1) && gl_stencil && rtlight->shadow && (rtlight->isstatic ? r_rtworldshadows : r_rtdlightshadows)) { usestencil = true; - R_Shadow_Stage_StencilShadowVolumes(); + R_Shadow_RenderMode_StencilShadowVolumes(); for (i = 0;i < numshadowentities;i++) - R_Shadow_DrawEntityShadow(shadowentities[i], rtlight, numsurfaces, surfacelist); + R_Shadow_DrawEntityShadow(shadowentities[i], numsurfaces, surfacelist); } + // draw lighting in the unmasked areas if (numlightentities && !visible) { - R_Shadow_Stage_Lighting(usestencil); + R_Shadow_RenderMode_Lighting(usestencil, false); for (i = 0;i < numlightentities;i++) - R_Shadow_DrawEntityLight(lightentities[i], rtlight, lightcolor, numsurfaces, surfacelist); + R_Shadow_DrawEntityLight(lightentities[i], numsurfaces, surfacelist); } + // optionally draw visible shape of the shadow volumes + // for performance analysis by level designers if (numshadowentities && visible && r_shadow_visiblevolumes.integer > 0 && rtlight->shadow && (rtlight->isstatic ? r_rtworldshadows : r_rtdlightshadows)) { - R_Shadow_Stage_VisibleShadowVolumes(); + R_Shadow_RenderMode_VisibleShadowVolumes(); for (i = 0;i < numshadowentities;i++) - R_Shadow_DrawEntityShadow(shadowentities[i], rtlight, numsurfaces, surfacelist); + R_Shadow_DrawEntityShadow(shadowentities[i], numsurfaces, surfacelist); } + // optionally draw the illuminated areas + // for performance analysis by level designers if (numlightentities && visible && r_shadow_visiblelighting.integer > 0) { - R_Shadow_Stage_VisibleLighting(usestencil); + R_Shadow_RenderMode_VisibleLighting(usestencil, false); for (i = 0;i < numlightentities;i++) - R_Shadow_DrawEntityLight(lightentities[i], rtlight, lightcolor, numsurfaces, surfacelist); + R_Shadow_DrawEntityLight(lightentities[i], numsurfaces, surfacelist); } } @@ -2923,7 +2992,7 @@ void R_ShadowVolumeLighting(qboolean visible) if (r_refdef.worldmodel && strncmp(r_refdef.worldmodel->name, r_shadow_mapname, sizeof(r_shadow_mapname))) R_Shadow_EditLights_Reload_f(); - R_Shadow_Stage_Begin(); + R_Shadow_RenderMode_Begin(); flag = r_rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE; if (r_shadow_debuglight.integer >= 0) @@ -2940,7 +3009,7 @@ void R_ShadowVolumeLighting(qboolean visible) for (lnum = 0;lnum < r_refdef.numlights;lnum++) R_DrawRTLight(&r_refdef.lights[lnum]->rtlight, visible); - R_Shadow_Stage_End(); + R_Shadow_RenderMode_End(); } //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"}; @@ -3131,23 +3200,22 @@ void R_Shadow_SelectLight(dlight_t *light) r_shadow_selectedlight->selected = true; } -void R_Shadow_DrawCursorCallback(const void *calldata1, int calldata2) +void R_Shadow_DrawCursor_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight) { float scale = r_editlights_cursorgrid.value * 0.5f; R_DrawSprite(GL_SRC_ALPHA, GL_ONE, lighttextures[0], NULL, false, r_editlights_cursorlocation, r_viewright, r_viewup, scale, -scale, -scale, scale, 1, 1, 1, 0.5f); } -void R_Shadow_DrawLightSpriteCallback(const void *calldata1, int calldata2) +void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight) { float intensity; - const dlight_t *light; - light = (dlight_t *)calldata1; + const dlight_t *light = (dlight_t *)ent; intensity = 0.5; if (light->selected) intensity = 0.75 + 0.25 * sin(realtime * M_PI * 4.0); if (!light->shadow) intensity *= 0.5f; - R_DrawSprite(GL_SRC_ALPHA, GL_ONE, lighttextures[calldata2], NULL, false, light->origin, r_viewright, r_viewup, 8, -8, -8, 8, intensity, intensity, intensity, 0.5); + R_DrawSprite(GL_SRC_ALPHA, GL_ONE, lighttextures[surfacenumber], NULL, false, light->origin, r_viewright, r_viewup, 8, -8, -8, 8, intensity, intensity, intensity, 0.5); } void R_Shadow_DrawLightSprites(void) @@ -3164,8 +3232,8 @@ void R_Shadow_DrawLightSprites(void) } for (i = 0, light = r_shadow_worldlightchain;light;i++, light = light->next) - R_MeshQueue_AddTransparent(light->origin, R_Shadow_DrawLightSpriteCallback, light, i % 5); - R_MeshQueue_AddTransparent(r_editlights_cursorlocation, R_Shadow_DrawCursorCallback, NULL, 0); + R_MeshQueue_AddTransparent(light->origin, R_Shadow_DrawLightSprite_TransparentCallback, (entity_render_t *)light, i % 5, &light->rtlight); + R_MeshQueue_AddTransparent(r_editlights_cursorlocation, R_Shadow_DrawCursor_TransparentCallback, NULL, 0, NULL); } void R_Shadow_SelectLightInView(void) diff --git a/r_shadow.h b/r_shadow.h index 84078ac5..52fa087a 100644 --- a/r_shadow.h +++ b/r_shadow.h @@ -36,10 +36,33 @@ extern mempool_t *r_shadow_mempool; void R_Shadow_Init(void); void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f, const int *elements, const int *neighbors, const vec3_t projectorigin, float projectdistance, int nummarktris, const int *marktris); void R_Shadow_MarkVolumeFromBox(int firsttriangle, int numtris, const float *invertex3f, const int *elements, const vec3_t projectorigin, const vec3_t lightmins, const vec3_t lightmaxs, const vec3_t surfacemins, const vec3_t surfacemaxs); -void R_Shadow_RenderSurfacesLighting(const entity_render_t *ent, const texture_t *texture, int numsurfaces, msurface_t **surfacelist, const vec3_t lightcolorbase, const vec3_t lightcolorpants, const vec3_t lightcolorshirt, rtexture_t *basetexture, rtexture_t *pantstexture, rtexture_t *shirttexture, rtexture_t *normalmaptexture, rtexture_t *glosstexture, float specularscale, const vec3_t modelorg); +void R_Shadow_RenderSurfacesLighting(const entity_render_t *ent, const texture_t *texture, int numsurfaces, msurface_t **surfacelist); +void R_Shadow_RenderMode_Begin(void); +void R_Shadow_RenderMode_ActiveLight(rtlight_t *rtlight); +void R_Shadow_RenderMode_Reset(void); +void R_Shadow_RenderMode_StencilShadowVolumes(void); +void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent); +void R_Shadow_RenderMode_VisibleShadowVolumes(void); +void R_Shadow_RenderMode_VisibleLighting(qboolean stenciltest, qboolean transparent); +void R_Shadow_RenderMode_End(void); +void R_Shadow_SetupEntityLight(const entity_render_t *ent); + // light currently being rendered extern rtlight_t *r_shadow_rtlight; +// this is the location of the eye in entity space +extern vec3_t r_shadow_entityeyeorigin; +// this is the location of the light in entity space +extern vec3_t r_shadow_entitylightorigin; +// this transforms entity coordinates to light filter cubemap coordinates +// (also often used for other purposes) +extern matrix4x4_t r_shadow_entitytolight; +// based on entitytolight this transforms -1 to +1 to 0 to 1 for purposes +// of attenuation texturing in full 3D (Z result often ignored) +extern matrix4x4_t r_shadow_entitytoattenuationxyz; +// this transforms only the Z to S, and T is always 0.5 +extern matrix4x4_t r_shadow_entitytoattenuationz; + void R_Shadow_RenderVolume(int numvertices, int numtriangles, const float *vertex3f, const int *element3i); qboolean R_Shadow_ScissorForBBox(const float *mins, const float *maxs); diff --git a/r_sprites.c b/r_sprites.c index bd7d0213..70169e12 100644 --- a/r_sprites.c +++ b/r_sprites.c @@ -1,9 +1,9 @@ #include "quakedef.h" +#include "r_shadow.h" -void R_DrawSpriteModelCallback(const void *calldata1, int calldata2) +void R_Model_Sprite_Draw_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight) { - const entity_render_t *ent = (entity_render_t *)calldata1; int i; vec3_t left, up, org, color, diffusecolor, diffusenormal; mspriteframe_t *frame; @@ -103,6 +103,6 @@ void R_Model_Sprite_Draw(entity_render_t *ent) if (ent->frameblend[0].frame < 0) return; - R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawSpriteModelCallback, ent, 0); + R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_Model_Sprite_Draw_TransparentCallback, ent, 0, r_shadow_rtlight); } -- 2.39.2