From fabdca42b48cc4acf214c06adda9814e5cce8577 Mon Sep 17 00:00:00 2001 From: havoc Date: Wed, 16 Oct 2002 21:48:14 +0000 Subject: [PATCH] fixed some dynamic lighting bugs related to glowing self rmeshstate_t now has alphascale now clears stencil from shadows differently (draws shadow volume over again to clear) R_LightModel now does GL_Color or GL_UseColorArray depending on whether the model has any shading model->DrawBaseLighting function is gone, now just a few special cases in the normal Draw function removed R_NotCulledBox added PVS_CullBox, R_CullSphere, and PVS_CullSphere visiblevolume flag is gone from shadow rendering code (visible volumes are now automatic depending on what stage the shadow system is in) R_DrawShadowVolumes is gone (now just a special option to R_ShadowVolumeLighting) cubemap textures now upload correctly doubled the bumpyness of surfaces to make bumpmapping noticable (still less than tenebrae) fixed crash when loading external map textures now supports _luma as an alternate name for _glow map textures (tenebrae compatibility) can now override _bump, _gloss, and _glow/_luma textures that were generated from the map bumpmapping works on the map now (that was a stupid typo...) now uses alpha buffering for multi-pass lighting effects r_shadows 3 now works on Geforce2 (2tex no3D 3 pass per layer) and Radeon (2tex 3D 2 pass per layer - Radeon has 3 texture units but the lighting code is most efficient with 2 units, and 3D textures use up 2 texture units on Radeon... lame...) gloss isn't working yet r_shadows 3 mode supports up to 64x overbright lighting now (by rendering light multiple times) fixed palettes (this fixes oddities like seeing sky behind fullbrights) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@2531 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_main.c | 2 +- gl_backend.c | 23 ++- gl_backend.h | 1 + gl_models.c | 81 +-------- gl_rmain.c | 474 ++++++++++++++++++++----------------------------- gl_rsurf.c | 176 +++--------------- gl_textures.c | 39 ++-- image.c | 2 +- model_alias.c | 9 +- model_brush.c | 66 ++++--- model_brush.h | 3 +- model_shared.h | 4 +- model_sprite.c | 1 - palette.c | 34 ++-- r_light.c | 184 ++++++++++--------- r_shadow.c | 316 +++++++++++++++++++++------------ r_shadow.h | 5 +- render.h | 8 +- vid_glx.c | 2 + vid_wgl.c | 9 +- 20 files changed, 641 insertions(+), 798 deletions(-) diff --git a/cl_main.c b/cl_main.c index 1e04c31e..819dae89 100644 --- a/cl_main.c +++ b/cl_main.c @@ -717,7 +717,7 @@ static void CL_RelinkNetworkEntities() { VectorCopy(neworg, v); // hack to make glowing player light shine on their gun - if (i == cl.viewentity && !chase_active.integer) + if (i == cl.viewentity/* && !chase_active.integer*/) v[2] += 30; CL_AllocDlight (&ent->render, v, 1, dlightcolor[0], dlightcolor[1], dlightcolor[2], 0, 0); } diff --git a/gl_backend.c b/gl_backend.c index c9d9ec8a..c8ab4bef 100644 --- a/gl_backend.c +++ b/gl_backend.c @@ -291,7 +291,7 @@ typedef struct gltextureunit_s { unsigned int t1d, t2d, t3d, tcubemap; unsigned int arrayenabled; - float rgbscale; + float rgbscale, alphascale; int combinergb, combinealpha; // FIXME: add more combine stuff } @@ -327,6 +327,7 @@ void GL_SetupTextureState(void) unit->t3d = 0; unit->tcubemap = 0; unit->rgbscale = 1; + unit->alphascale = 1; unit->combinergb = GL_MODULATE; unit->combinealpha = GL_MODULATE; unit->arrayenabled = false; @@ -562,6 +563,7 @@ void R_Mesh_Finish(void) if (gl_combine.integer) { qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1);CHECKGLERROR + qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1);CHECKGLERROR } } qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR @@ -637,7 +639,7 @@ void R_Mesh_MainState(const rmeshstate_t *m) void R_Mesh_TextureState(const rmeshstate_t *m) { int i, combinergb, combinealpha; - float rgbscale; + float scale; gltextureunit_t *unit; BACKENDACTIVECHECK @@ -764,14 +766,23 @@ void R_Mesh_TextureState(const rmeshstate_t *m) qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, (unit->tcubemap = m->texcubemap[i]));CHECKGLERROR } } - rgbscale = max(m->texrgbscale[i], 1); - if (gl_state.units[i].rgbscale != rgbscale) + scale = max(m->texrgbscale[i], 1); + if (gl_state.units[i].rgbscale != scale) + { + if (gl_state.unit != i) + { + qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR + } + qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (gl_state.units[i].rgbscale = scale));CHECKGLERROR + } + scale = max(m->texalphascale[i], 1); + if (gl_state.units[i].alphascale != scale) { if (gl_state.unit != i) { qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR } - qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (gl_state.units[i].rgbscale = rgbscale));CHECKGLERROR + qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, (gl_state.units[i].alphascale = scale));CHECKGLERROR } } } @@ -823,7 +834,7 @@ void R_ClearScreen(void) // clear to black qglClearColor(0,0,0,0);CHECKGLERROR // clear the screen - qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);CHECKGLERROR + qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | (gl_stencil ? GL_STENCIL_BUFFER_BIT : 0));CHECKGLERROR // set dithering mode if (gl_dither.integer) { diff --git a/gl_backend.h b/gl_backend.h index 58757545..40bb6cee 100644 --- a/gl_backend.h +++ b/gl_backend.h @@ -35,6 +35,7 @@ typedef struct int tex3d[MAX_TEXTUREUNITS]; int texcubemap[MAX_TEXTUREUNITS]; int texrgbscale[MAX_TEXTUREUNITS]; // used only if COMBINE is present + int texalphascale[MAX_TEXTUREUNITS]; // used only if COMBINE is present int texcombinergb[MAX_TEXTUREUNITS]; // works with or without combine for some operations int texcombinealpha[MAX_TEXTUREUNITS]; // does nothing without combine } diff --git a/gl_models.c b/gl_models.c index 4126c63a..f77d722e 100644 --- a/gl_models.c +++ b/gl_models.c @@ -289,7 +289,6 @@ void R_DrawQ1Q2AliasModelCallback (const void *calldata1, int calldata2) varray_texcoord[0][i + 1] *= 8.0f; } R_LightModel(ent, model->numverts, varray_vertex, aliasvert_normals, varray_color, colorscale, colorscale, colorscale, false); - GL_UseColorArray(); R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices); return; } @@ -330,10 +329,7 @@ void R_DrawQ1Q2AliasModelCallback (const void *calldata1, int calldata2) if (fullbright) GL_Color(colorscale * ifog, colorscale * ifog, colorscale * ifog, ent->alpha); else - { - GL_UseColorArray(); R_LightModel(ent, model->numverts, varray_vertex, aliasvert_normals, varray_color, colorscale * ifog, colorscale * ifog, colorscale * ifog, false); - } R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices); c_alias_polys += model->numtris; blendfunc1 = GL_SRC_ALPHA; @@ -361,10 +357,7 @@ void R_DrawQ1Q2AliasModelCallback (const void *calldata1, int calldata2) if (pantsfullbright) GL_Color(pantscolor[0] * colorscale * ifog, pantscolor[1] * colorscale * ifog, pantscolor[2] * colorscale * ifog, ent->alpha); else - { - GL_UseColorArray(); R_LightModel(ent, model->numverts, varray_vertex, aliasvert_normals, varray_color, pantscolor[0] * colorscale * ifog, pantscolor[1] * colorscale * ifog, pantscolor[2] * colorscale * ifog, false); - } R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices); c_alias_polys += model->numtris; blendfunc1 = GL_SRC_ALPHA; @@ -390,10 +383,7 @@ void R_DrawQ1Q2AliasModelCallback (const void *calldata1, int calldata2) if (shirtfullbright) GL_Color(shirtcolor[0] * colorscale * ifog, shirtcolor[1] * colorscale * ifog, shirtcolor[2] * colorscale * ifog, ent->alpha); else - { - GL_UseColorArray(); R_LightModel(ent, model->numverts, varray_vertex, aliasvert_normals, varray_color, shirtcolor[0] * colorscale * ifog, shirtcolor[1] * colorscale * ifog, shirtcolor[2] * colorscale * ifog, false); - } R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices); c_alias_polys += model->numtris; blendfunc1 = GL_SRC_ALPHA; @@ -454,64 +444,6 @@ void R_Model_Alias_DrawFakeShadow (entity_render_t *ent) model_t *model; float *v, planenormal[3], planedist, dist, projection[3], floororigin[3], surfnormal[3], lightdirection[3], v2[3]; - /* - if (r_shadows.integer > 1) - { - float f, lightscale, lightcolor[3]; - vec3_t temp; - mlight_t *sl; - rdlight_t *rd; - memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_ONE; - m.blendfunc2 = GL_ONE; - R_Mesh_State(&m); - R_Mesh_Matrix(&ent->matrix); - for (i = 0, sl = cl.worldmodel->lights;i < cl.worldmodel->numlights;i++, sl++) - { - if (d_lightstylevalue[sl->style] > 0) - { - VectorSubtract(ent->origin, sl->origin, temp); - f = DotProduct(temp,temp); - if (f < (ent->model->radius2 + sl->cullradius2)) - { - model = ent->model; - R_Mesh_ResizeCheck(model->numverts * 2); - R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvert_normals); - Matrix4x4_Transform(&ent->inversematrix, sl->origin, temp); - GL_Color(0.1 * r_colorscale, 0.025 * r_colorscale, 0.0125 * r_colorscale, 1); - R_Shadow_Volume(model->numverts, model->numtris, varray_vertex, model->mdlmd2data_indices, model->mdlmd2data_triangleneighbors, temp, sl->cullradius + model->radius - sqrt(f), true); - GL_UseColorArray(); - lightscale = d_lightstylevalue[sl->style] * (1.0f / 65536.0f); - VectorScale(sl->light, lightscale, lightcolor); - R_Shadow_VertexLight(model->numverts, varray_vertex, aliasvert_normals, temp, sl->cullradius2, sl->distbias, sl->subtract, lightcolor); - R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices); - } - } - } - for (i = 0, rd = r_dlight;i < r_numdlights;i++, rd++) - { - if (ent != rd->ent) - { - VectorSubtract(ent->origin, rd->origin, temp); - f = DotProduct(temp,temp); - if (f < (ent->model->radius2 + rd->cullradius2)) - { - model = ent->model; - R_Mesh_ResizeCheck(model->numverts * 2); - R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvert_normals); - Matrix4x4_Transform(&ent->inversematrix, rd->origin, temp); - GL_Color(0.1 * r_colorscale, 0.025 * r_colorscale, 0.0125 * r_colorscale, 1); - R_Shadow_Volume(model->numverts, model->numtris, varray_vertex, model->mdlmd2data_indices, model->mdlmd2data_triangleneighbors, temp, rd->cullradius + model->radius - sqrt(f), true); - GL_UseColorArray(); - R_Shadow_VertexLight(model->numverts, varray_vertex, aliasvert_normals, temp, rd->cullradius2, LIGHTOFFSET, rd->subtract, rd->light); - R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices); - } - } - } - return; - } - */ - lightdirection[0] = 0.5; lightdirection[1] = 0.2; lightdirection[2] = -1; @@ -559,16 +491,7 @@ void R_Model_Alias_DrawFakeShadow (entity_render_t *ent) R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices); } -void R_Model_Alias_DrawBaseLighting(entity_render_t *ent) -{ - R_Mesh_Matrix(&ent->matrix); - GL_Color(0, 0, 0, 1); - R_Mesh_ResizeCheck(ent->model->numverts); - R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvert_normals); - R_Mesh_Draw(ent->model->numverts, ent->model->numtris, ent->model->mdlmd2data_indices); -} - -void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume) +void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius) { float projectdistance; projectdistance = lightradius + ent->model->radius - sqrt(DotProduct(relativelightorigin, relativelightorigin)); @@ -577,7 +500,7 @@ void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightor R_Mesh_Matrix(&ent->matrix); R_Mesh_ResizeCheck(ent->model->numverts * 2); R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvert_normals); - R_Shadow_Volume(ent->model->numverts, ent->model->numtris, varray_vertex, ent->model->mdlmd2data_indices, ent->model->mdlmd2data_triangleneighbors, relativelightorigin, lightradius, projectdistance, visiblevolume); + R_Shadow_Volume(ent->model->numverts, ent->model->numtris, varray_vertex, ent->model->mdlmd2data_indices, ent->model->mdlmd2data_triangleneighbors, relativelightorigin, lightradius, projectdistance); } } diff --git a/gl_rmain.c b/gl_rmain.c index 4a8d46f5..6e24c183 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -330,7 +330,7 @@ void GL_Init (void) Con_Printf ("\nengine extensions: %s\n", ENGINE_EXTENSIONS); } -int R_CullBox(const vec3_t emins, const vec3_t emaxs) +int R_CullBox(const vec3_t mins, const vec3_t maxs) { int i; mplane_t *p; @@ -341,35 +341,35 @@ int R_CullBox(const vec3_t emins, const vec3_t emaxs) { default: case 0: - if (p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2] < p->dist) + if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist) return true; break; case 1: - if (p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2] < p->dist) + if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist) return true; break; case 2: - if (p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2] < p->dist) + if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist) return true; break; case 3: - if (p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2] < p->dist) + if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist) return true; break; case 4: - if (p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2] < p->dist) + if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist) return true; break; case 5: - if (p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2] < p->dist) + if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist) return true; break; case 6: - if (p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2] < p->dist) + if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist) return true; break; case 7: - if (p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2] < p->dist) + if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist) return true; break; } @@ -377,48 +377,62 @@ int R_CullBox(const vec3_t emins, const vec3_t emaxs) return false; } -int R_NotCulledBox(const vec3_t emins, const vec3_t emaxs) +int PVS_CullBox(const vec3_t mins, const vec3_t maxs) { - int i; - mplane_t *p; - for (i = 0;i < 4;i++) + int stackpos, sides; + mnode_t *node, *stack[4096]; + stackpos = 0; + stack[stackpos++] = cl.worldmodel->nodes; + while (stackpos) { - p = frustum + i; - switch(p->signbits) + node = stack[--stackpos]; + if (node->contents < 0) { - default: - case 0: - if (p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2] < p->dist) - return false; - break; - case 1: - if (p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2] < p->dist) + if (((mleaf_t *)node)->pvsframe == cl.worldmodel->pvsframecount) return false; - break; - case 2: - if (p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2] < p->dist) - return false; - break; - case 3: - if (p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2] < p->dist) - return false; - break; - case 4: - if (p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2] < p->dist) - return false; - break; - case 5: - if (p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2] < p->dist) - return false; - break; - case 6: - if (p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2] < p->dist) - return false; - break; - case 7: - if (p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2] < p->dist) + } + else + { + sides = BoxOnPlaneSide(mins, maxs, node->plane); + if (sides & 2 && stackpos < 4096) + stack[stackpos++] = node->children[1]; + if (sides & 1 && stackpos < 4096) + stack[stackpos++] = node->children[0]; + } + } + return true; +} + +int R_CullSphere(const vec3_t origin, vec_t radius) +{ + return (DotProduct(frustum[0].normal, origin) + radius < frustum[0].dist + || DotProduct(frustum[1].normal, origin) + radius < frustum[1].dist + || DotProduct(frustum[2].normal, origin) + radius < frustum[2].dist + || DotProduct(frustum[3].normal, origin) + radius < frustum[3].dist); +} + +int PVS_CullSphere(const vec3_t origin, vec_t radius) +{ + int stackpos; + mnode_t *node, *stack[4096]; + float dist; + stackpos = 0; + stack[stackpos++] = cl.worldmodel->nodes; + while (stackpos) + { + node = stack[--stackpos]; + if (node->contents < 0) + { + if (((mleaf_t *)node)->pvsframe == cl.worldmodel->pvsframecount) return false; - break; + } + else + { + dist = PlaneDiff(origin, node->plane); + if (dist <= radius) + stack[stackpos++] = node->children[1]; + if (dist >= -radius) + stack[stackpos++] = node->children[0]; } } return true; @@ -469,7 +483,10 @@ static void R_MarkEntities (void) Matrix4x4_Invert_Simple(&ent->inversematrix, &ent->matrix); R_LerpAnimation(ent); R_UpdateEntLights(ent); - if (R_NotCulledBox(ent->mins, ent->maxs)) + if (!R_CullSphere(ent->origin, ent->model->radius * ent->scale) + && !PVS_CullSphere(ent->origin, ent->model->radius * ent->scale) + && !R_CullBox(ent->mins, ent->maxs) + && !PVS_CullBox(ent->mins, ent->maxs)) { ent->visframe = r_framecount; R_FarClip_Box(ent->mins, ent->maxs); @@ -522,7 +539,7 @@ void R_DrawViewModel (void) } void R_DrawNoModel(entity_render_t *ent); -void R_DrawModels (int baselighting) +void R_DrawModels () { int i; entity_render_t *ent; @@ -536,16 +553,8 @@ void R_DrawModels (int baselighting) ent = r_refdef.entities[i]; if (ent->visframe == r_framecount) { - if (ent->model) - { - if (baselighting && ent->model->DrawBaseLighting != NULL) - { - if (ent->model->DrawBaseLighting) - ent->model->DrawBaseLighting(ent); - } - else if (ent->model->Draw) - ent->model->Draw(ent); - } + if (ent->model && ent->model->Draw != NULL) + ent->model->Draw(ent); else R_DrawNoModel(ent); } @@ -573,7 +582,7 @@ void R_DrawFakeShadows (void) #include "r_shadow.h" -void R_TestAndDrawShadowVolume(entity_render_t *ent, vec3_t lightorigin, float lightradius, int visiblevolume) +void R_TestAndDrawShadowVolume(entity_render_t *ent, vec3_t lightorigin, float lightradius) { int i; vec3_t p, p2, temp, relativelightorigin; @@ -631,144 +640,25 @@ void R_TestAndDrawShadowVolume(entity_render_t *ent, vec3_t lightorigin, float l if (mins[1] > p2[1]) mins[1] = p2[1];if (maxs[1] < p2[1]) maxs[1] = p2[1]; if (mins[2] > p2[2]) mins[2] = p2[2];if (maxs[2] < p2[2]) maxs[2] = p2[2]; } - if (R_NotCulledBox(mins, maxs)) + if (!R_CullBox(mins, maxs)) #endif { Matrix4x4_Transform(&ent->inversematrix, lightorigin, relativelightorigin); - ent->model->DrawShadowVolume (ent, relativelightorigin, lightradius, visiblevolume); + ent->model->DrawShadowVolume (ent, relativelightorigin, lightradius); } } } } } -void R_DrawWorldLightShadowVolume(mlight_t *sl, int visiblevolume) +void R_DrawWorldLightShadowVolume(mlight_t *sl) { shadowmesh_t *mesh; R_Mesh_Matrix(&cl_entities[0].render.matrix); for (mesh = sl->shadowvolume;mesh;mesh = mesh->next) { memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4])); - R_Shadow_RenderVolume(mesh->numverts, mesh->numtriangles, mesh->elements, visiblevolume); - } -} - -void R_DrawShadowVolumes (void) -{ - int i, lnum; - entity_render_t *ent; - vec3_t mins, maxs;//, relativelightorigin; - mlight_t *sl; - rdlight_t *rd; - rmeshstate_t m; - - for (lnum = 0, sl = cl.worldmodel->lights;lnum < cl.worldmodel->numlights;lnum++, sl++) - { - if (d_lightstylevalue[sl->style] <= 0) - continue; - if (r_light_debuglight.integer >= 0 && lnum != r_light_debuglight.integer) - continue; - /* - mins[0] = sl->origin[0] - sl->cullradius; - maxs[0] = sl->origin[0] + sl->cullradius; - mins[1] = sl->origin[1] - sl->cullradius; - maxs[1] = sl->origin[1] + sl->cullradius; - mins[2] = sl->origin[2] - sl->cullradius; - maxs[2] = sl->origin[2] + sl->cullradius; - if (R_CullBox(mins, maxs)) - continue; - */ - if (R_CullBox(sl->mins, sl->maxs)) - continue; - memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_ONE; - m.blendfunc2 = GL_ONE; - R_Mesh_State(&m); - GL_Color(0.0 * r_colorscale, 0.0125 * r_colorscale, 0.1 * r_colorscale, 1); - if (sl->shadowvolume && r_staticworldlights.integer) - R_DrawWorldLightShadowVolume(sl, true); - else - { - ent = &cl_entities[0].render; - R_TestAndDrawShadowVolume(ent, sl->origin, sl->cullradius, true); - } - /* - ent = &cl_entities[0].render; - if (ent->model && ent->model->DrawShadowVolume && ent->maxs[0] >= mins[0] && ent->mins[0] <= maxs[0] && ent->maxs[1] >= mins[1] && ent->mins[1] <= maxs[1] && ent->maxs[2] >= mins[2] && ent->mins[2] <= maxs[2]) - { - Matrix4x4_Transform(&ent->inversematrix, sl->origin, relativelightorigin); - ent->model->DrawShadowVolume (ent, relativelightorigin, sl->cullradius, true); - } - */ - if (r_drawentities.integer) - { - for (i = 0;i < r_refdef.numentities;i++) - { - ent = r_refdef.entities[i]; - /* - if (ent->mins[0] <= sl->maxs[0] - && ent->maxs[0] >= sl->mins[0] - && ent->mins[1] <= sl->maxs[1] - && ent->maxs[1] >= sl->mins[1] - && ent->mins[2] <= sl->maxs[2] - && ent->maxs[2] >= sl->mins[2]) - */ - R_TestAndDrawShadowVolume(ent, sl->origin, sl->cullradius, true); - /* - ent = r_refdef.entities[i]; - if (ent->model && ent->model->DrawShadowVolume && ent->maxs[0] >= mins[0] && ent->mins[0] <= maxs[0] && ent->maxs[1] >= mins[1] && ent->mins[1] <= maxs[1] && ent->maxs[2] >= mins[2] && ent->mins[2] <= maxs[2]) - { - Matrix4x4_Transform(&ent->inversematrix, sl->origin, relativelightorigin); - ent->model->DrawShadowVolume (ent, relativelightorigin, sl->cullradius, true); - } - */ - } - } - } - - for (lnum = 0, rd = r_dlight;lnum < r_numdlights;lnum++, rd++) - { - mins[0] = rd->origin[0] - rd->cullradius; - maxs[0] = rd->origin[0] + rd->cullradius; - mins[1] = rd->origin[1] - rd->cullradius; - maxs[1] = rd->origin[1] + rd->cullradius; - mins[2] = rd->origin[2] - rd->cullradius; - maxs[2] = rd->origin[2] + rd->cullradius; - if (R_CullBox(mins, maxs)) - continue; - memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_ONE; - m.blendfunc2 = GL_ONE; - R_Mesh_State(&m); - GL_Color(0.1 * r_colorscale, 0.0125 * r_colorscale, 0.0 * r_colorscale, 1); - ent = &cl_entities[0].render; - if (ent != rd->ent) - R_TestAndDrawShadowVolume(ent, rd->origin, rd->cullradius, true); - /* - ent = &cl_entities[0].render; - if (ent != rd->ent && ent->model && ent->model->DrawShadowVolume && ent->maxs[0] >= mins[0] && ent->mins[0] <= maxs[0] && ent->maxs[1] >= mins[1] && ent->mins[1] <= maxs[1] && ent->maxs[2] >= mins[2] && ent->mins[2] <= maxs[2]) - { - Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin); - ent->model->DrawShadowVolume (ent, relativelightorigin, rd->cullradius, true); - } - */ - if (r_drawentities.integer) - { - for (i = 0;i < r_refdef.numentities;i++) - { - ent = r_refdef.entities[i]; - if (ent != rd->ent) - R_TestAndDrawShadowVolume(ent, rd->origin, rd->cullradius, true); - /* - ent = r_refdef.entities[i]; - if (ent != rd->ent && ent->model && ent->model->DrawShadowVolume && ent->maxs[0] >= mins[0] && ent->mins[0] <= maxs[0] && ent->maxs[1] >= mins[1] && ent->mins[1] <= maxs[1] && ent->maxs[2] >= mins[2] && ent->mins[2] <= maxs[2]) - { - Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin); - ent->model->DrawShadowVolume (ent, relativelightorigin, rd->cullradius, true); - } - */ - } - } + R_Shadow_RenderVolume(mesh->numverts, mesh->numtriangles, mesh->elements); } } @@ -804,24 +694,13 @@ void R_CreateShadowSphere(void) VectorScale(&verts[6], 1.0f, &verts[6]); VectorScale(&verts[9], 1.0f, &verts[9]); Mod_ShadowMesh_AddPolygon(zonemempool, shadowsphere, 4, verts); - /* - AngleVectorsFLU(angles, verts, NULL, NULL); - AngleVectorsFLU(angles2, verts + 3, NULL, NULL); - AngleVectorsFLU(angles3, verts + 6, NULL, NULL); - AngleVectorsFLU(angles4, verts + 9, NULL, NULL); - VectorScale(&verts[0], -4.0f, &verts[0]); - VectorScale(&verts[3], -4.0f, &verts[3]); - VectorScale(&verts[6], -4.0f, &verts[6]); - VectorScale(&verts[9], -4.0f, &verts[9]); - Mod_ShadowMesh_AddPolygon(zonemempool, shadowsphere, 4, verts); - */ } } shadowsphere = Mod_ShadowMesh_Finish(zonemempool, shadowsphere); } -void R_DrawShadowSphere(vec3_t origin, float cullradius, float lightradius, int visiblevolume) +void R_DrawShadowSphere(vec3_t origin, float cullradius, float lightradius) { shadowmesh_t *mesh; matrix4x4_t matrix; @@ -833,7 +712,7 @@ void R_DrawShadowSphere(vec3_t origin, float cullradius, float lightradius, int for (mesh = shadowsphere;mesh;mesh = mesh->next) { memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4])); - R_Shadow_RenderVolume(mesh->numverts, mesh->numtriangles, mesh->elements, visiblevolume); + R_Shadow_RenderVolume(mesh->numverts, mesh->numtriangles, mesh->elements); } Matrix4x4_CreateScale(&matrix, -cullradius); Matrix4x4_ConcatTranslate(&matrix, origin[0], origin[1], origin[2]); @@ -841,148 +720,172 @@ void R_DrawShadowSphere(vec3_t origin, float cullradius, float lightradius, int for (mesh = shadowsphere;mesh;mesh = mesh->next) { memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4])); - R_Shadow_RenderVolume(mesh->numverts, mesh->numtriangles, mesh->elements, visiblevolume); + R_Shadow_RenderVolume(mesh->numverts, mesh->numtriangles, mesh->elements); } } -void R_ShadowVolumeLighting (void) +void R_ShadowVolumeLighting (int visiblevolumes) { int i; entity_render_t *ent; int lnum; - float f; - vec3_t mins, maxs, relativelightorigin, relativeeyeorigin, lightcolor; + float f, lightradius, cullradius; + vec3_t relativelightorigin, relativeeyeorigin, lightcolor; mlight_t *sl; rdlight_t *rd; + rmeshstate_t m; - R_Shadow_Stage_Begin(); + if (visiblevolumes) + { + memset(&m, 0, sizeof(m)); + m.blendfunc1 = GL_ONE; + m.blendfunc2 = GL_ONE; + R_Mesh_State(&m); + GL_Color(0.0 * r_colorscale, 0.0125 * r_colorscale, 0.1 * r_colorscale, 1); + } + else + R_Shadow_Stage_Begin(); for (lnum = 0, sl = cl.worldmodel->lights;lnum < cl.worldmodel->numlights;lnum++, sl++) { if (d_lightstylevalue[sl->style] <= 0) continue; if (r_light_debuglight.integer >= 0 && lnum != r_light_debuglight.integer) continue; - VectorCopy(sl->mins, mins); - VectorCopy(sl->maxs, maxs); - if (R_CullBox(mins, maxs)) + cullradius = sl->cullradius; + lightradius = sl->lightradius; + if (R_CullBox(sl->mins, sl->maxs) || PVS_CullBox(sl->mins, sl->maxs) || R_CullSphere(sl->origin, cullradius) || PVS_CullSphere(sl->origin, cullradius)) continue; f = d_lightstylevalue[sl->style] * (1.0f / 32768.0f); VectorScale(sl->light, f, lightcolor); - R_Shadow_Stage_ShadowVolumes(); - R_DrawShadowSphere(sl->origin, sl->cullradius, sl->lightradius * 2, false); + if (!visiblevolumes) + R_Shadow_Stage_ShadowVolumes(); + R_DrawShadowSphere(sl->origin, cullradius, lightradius * 2); if (sl->shadowvolume && r_staticworldlights.integer) - R_DrawWorldLightShadowVolume(sl, false); + R_DrawWorldLightShadowVolume(sl); else - R_TestAndDrawShadowVolume(&cl_entities[0].render, sl->origin, sl->cullradius, false); + R_TestAndDrawShadowVolume(&cl_entities[0].render, sl->origin, cullradius); if (r_drawentities.integer) { for (i = 0;i < r_refdef.numentities;i++) { ent = r_refdef.entities[i]; - /* - if (ent->maxs[0] >= mins[0] - && ent->mins[0] <= maxs[0] - && ent->maxs[1] >= mins[1] - && ent->mins[1] <= maxs[1] - && ent->maxs[2] >= mins[2] - && ent->mins[2] <= maxs[2]) - */ - R_TestAndDrawShadowVolume(r_refdef.entities[i], sl->origin, sl->cullradius, false); + if (ent->maxs[0] >= sl->mins[0] && ent->mins[0] <= sl->maxs[0] + && ent->maxs[1] >= sl->mins[1] && ent->mins[1] <= sl->maxs[1] + && ent->maxs[2] >= sl->mins[2] && ent->mins[2] <= sl->maxs[2]) + R_TestAndDrawShadowVolume(r_refdef.entities[i], sl->origin, cullradius); } } - R_Shadow_Stage_Light(); - ent = &cl_entities[0].render; - if (ent->model && ent->model->DrawLight) - { - Matrix4x4_Transform(&ent->inversematrix, sl->origin, relativelightorigin); - Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin); - ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, sl->lightradius, sl->distbias, sl->subtract, lightcolor); - } - if (r_drawentities.integer) + if (!visiblevolumes) { - for (i = 0;i < r_refdef.numentities;i++) + R_Shadow_Stage_Light(); + ent = &cl_entities[0].render; + if (ent->model && ent->model->DrawLight) { - ent = r_refdef.entities[i]; - if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight - /* - && ent->maxs[0] >= mins[0] - && ent->mins[0] <= maxs[0] - && ent->maxs[1] >= mins[1] - && ent->mins[1] <= maxs[1] - && ent->maxs[2] >= mins[2] - && ent->mins[2] <= maxs[2]*/) + Matrix4x4_Transform(&ent->inversematrix, sl->origin, relativelightorigin); + Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin); + ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius, sl->distbias, sl->subtract, lightcolor); + } + if (r_drawentities.integer) + { + for (i = 0;i < r_refdef.numentities;i++) + { + ent = r_refdef.entities[i]; + if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight + && ent->maxs[0] >= sl->mins[0] && ent->mins[0] <= sl->maxs[0] + && ent->maxs[1] >= sl->mins[1] && ent->mins[1] <= sl->maxs[1] + && ent->maxs[2] >= sl->mins[2] && ent->mins[2] <= sl->maxs[2]) + { + Matrix4x4_Transform(&ent->inversematrix, sl->origin, relativelightorigin); + Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin); + ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius, sl->distbias, sl->subtract, lightcolor); + } + } + } + + R_Shadow_Stage_EraseShadowVolumes(); + R_DrawShadowSphere(sl->origin, cullradius, lightradius * 2); + if (sl->shadowvolume && r_staticworldlights.integer) + R_DrawWorldLightShadowVolume(sl); + else + R_TestAndDrawShadowVolume(&cl_entities[0].render, sl->origin, cullradius); + if (r_drawentities.integer) + { + for (i = 0;i < r_refdef.numentities;i++) { - Matrix4x4_Transform(&ent->inversematrix, sl->origin, relativelightorigin); - Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin); - ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, sl->lightradius, sl->distbias, sl->subtract, lightcolor); + ent = r_refdef.entities[i]; + if (ent->maxs[0] >= sl->mins[0] && ent->mins[0] <= sl->maxs[0] + && ent->maxs[1] >= sl->mins[1] && ent->mins[1] <= sl->maxs[1] + && ent->maxs[2] >= sl->mins[2] && ent->mins[2] <= sl->maxs[2]) + R_TestAndDrawShadowVolume(r_refdef.entities[i], sl->origin, cullradius); } } } } for (lnum = 0, rd = r_dlight;lnum < r_numdlights;lnum++, rd++) { - mins[0] = rd->origin[0] - rd->cullradius; - maxs[0] = rd->origin[0] + rd->cullradius; - mins[1] = rd->origin[1] - rd->cullradius; - maxs[1] = rd->origin[1] + rd->cullradius; - mins[2] = rd->origin[2] - rd->cullradius; - maxs[2] = rd->origin[2] + rd->cullradius; - if (R_CullBox(mins, maxs)) + cullradius = rd->cullradius; + lightradius = rd->cullradius; + if (R_CullSphere(rd->origin, cullradius) || PVS_CullSphere(rd->origin, cullradius)) continue; - R_Shadow_Stage_ShadowVolumes(); - R_TestAndDrawShadowVolume(&cl_entities[0].render, rd->origin, rd->cullradius, false); + VectorScale(rd->light, 4.0f, lightcolor); + + if (!visiblevolumes) + R_Shadow_Stage_ShadowVolumes(); + R_TestAndDrawShadowVolume(&cl_entities[0].render, rd->origin, cullradius); if (r_drawentities.integer) { for (i = 0;i < r_refdef.numentities;i++) { ent = r_refdef.entities[i]; - /* - if (ent->maxs[0] >= mins[0] - && ent->mins[0] <= maxs[0] - && ent->maxs[1] >= mins[1] - && ent->mins[1] <= maxs[1] - && ent->maxs[2] >= mins[2] - && ent->mins[2] <= maxs[2]) - */ - R_TestAndDrawShadowVolume(ent, rd->origin, rd->cullradius, false); + if (ent != rd->ent) + R_TestAndDrawShadowVolume(ent, rd->origin, cullradius); } } - R_Shadow_Stage_Light(); - ent = &cl_entities[0].render; - if (ent->model && ent->model->DrawLight) - { - Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin); - Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin); - ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, rd->cullradius, LIGHTOFFSET, rd->subtract, rd->light); - } - if (r_drawentities.integer) + if (!visiblevolumes) { - for (i = 0;i < r_refdef.numentities;i++) + R_Shadow_Stage_Light(); + ent = &cl_entities[0].render; + if (ent->model && ent->model->DrawLight) { - ent = r_refdef.entities[i]; - if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight - /* - && ent->maxs[0] >= mins[0] - && ent->mins[0] <= maxs[0] - && ent->maxs[1] >= mins[1] - && ent->mins[1] <= maxs[1] - && ent->maxs[2] >= mins[2] - && ent->mins[2] <= maxs[2]*/) + Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin); + Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin); + ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, cullradius, LIGHTOFFSET, rd->subtract, lightcolor); + } + if (r_drawentities.integer) + { + for (i = 0;i < r_refdef.numentities;i++) { - Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin); - Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin); - ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, rd->cullradius, LIGHTOFFSET, rd->subtract, rd->light); + ent = r_refdef.entities[i]; + if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight) + { + Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin); + Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin); + ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, cullradius, LIGHTOFFSET, rd->subtract, lightcolor); + } + } + } + + R_Shadow_Stage_EraseShadowVolumes(); + R_TestAndDrawShadowVolume(&cl_entities[0].render, rd->origin, cullradius); + if (r_drawentities.integer) + { + for (i = 0;i < r_refdef.numentities;i++) + { + ent = r_refdef.entities[i]; + if (ent != rd->ent) + R_TestAndDrawShadowVolume(ent, rd->origin, cullradius); } } } } - R_Shadow_Stage_End(); + if (!visiblevolumes) + R_Shadow_Stage_End(); } static void R_SetFrustum (void) @@ -1135,7 +1038,7 @@ void R_RenderView (void) R_TimeReport("bmodelsky"); // must occur early because it can draw sky - R_DrawWorld(world, r_shadows.integer == 3); + R_DrawWorld(world); R_TimeReport("world"); // don't let sound skip if going slow @@ -1148,11 +1051,14 @@ void R_RenderView (void) if (r_shadows.integer == 1) { R_DrawFakeShadows(); - R_TimeReport("fakeshadows"); + R_TimeReport("fakeshadow"); } if (r_shadows.integer == 3) - R_ShadowVolumeLighting(); + { + R_ShadowVolumeLighting(false); + R_TimeReport("dynlight"); + } R_DrawParticles(); R_TimeReport("particles"); @@ -1176,8 +1082,8 @@ void R_RenderView (void) R_MeshQueue_EndScene(); if (r_shadows.integer == 2) { - R_DrawShadowVolumes(); - R_TimeReport("shadowvolumes"); + R_ShadowVolumeLighting(true); + R_TimeReport("shadowvolume"); } R_Mesh_Finish(); R_TimeReport("meshfinish"); diff --git a/gl_rsurf.c b/gl_rsurf.c index a587d658..1ca92021 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -1304,6 +1304,7 @@ static void RSurfShader_Wall_Vertex_Callback(const void *calldata1, int calldata RSurfShader_Wall_Pass_Fog(ent, surf); } +extern cvar_t r_shadows; static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf) { const msurface_t *surf; @@ -1320,6 +1321,13 @@ static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const texture_ } } } + else if (r_shadows.integer == 3 && cl.worldmodel->numlights) + { + // opaque base lighting + RSurfShader_OpaqueWall_Pass_OpaqueGlow(ent, texture, firstsurf); + if (fogenabled) + RSurfShader_OpaqueWall_Pass_Fog(ent, texture, firstsurf); + } else if (r_vertexsurfaces.integer) { // opaque vertex shaded from lightmap @@ -1365,53 +1373,9 @@ static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const texture_ } } -static void RSurfShader_Wall_Lightmap_BaseLighting(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf) -{ - const msurface_t *surf; - if (cl.worldmodel->numlights) - RSurfShader_OpaqueWall_Pass_OpaqueGlow(ent, texture, firstsurf); - else if (r_vertexsurfaces.integer) - { - // opaque vertex shaded from lightmap - for (surf = firstsurf;surf;surf = surf->texturechain) - if (surf->visframe == r_framecount) - RSurfShader_Wall_Pass_BaseVertex(ent, surf); - if (texture->glowtexture) - for (surf = firstsurf;surf;surf = surf->texturechain) - if (surf->visframe == r_framecount) - RSurfShader_Wall_Pass_Glow(ent, surf); - } - else - { - // opaque lightmapped - if (r_textureunits.integer >= 2) - { - if (r_textureunits.integer >= 3 && gl_combine.integer && r_detailtextures.integer) - RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(ent, texture, firstsurf); - else - { - RSurfShader_OpaqueWall_Pass_BaseDoubleTex(ent, texture, firstsurf); - if (r_detailtextures.integer) - RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, firstsurf); - } - } - else - { - RSurfShader_OpaqueWall_Pass_BaseTexture(ent, texture, firstsurf); - RSurfShader_OpaqueWall_Pass_BaseLightmap(ent, texture, firstsurf); - if (r_detailtextures.integer) - RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, firstsurf); - } - if (!r_dlightmap.integer && !(ent->effects & EF_FULLBRIGHT)) - RSurfShader_OpaqueWall_Pass_Light(ent, texture, firstsurf); - if (texture->glowtexture) - RSurfShader_OpaqueWall_Pass_Glow(ent, texture, firstsurf); - } -} - -Cshader_t Cshader_wall_lightmap = {{NULL, RSurfShader_Wall_Lightmap, RSurfShader_Wall_Lightmap_BaseLighting}, SHADERFLAGS_NEEDLIGHTMAP}; -Cshader_t Cshader_water = {{NULL, RSurfShader_Water, NULL}, 0}; -Cshader_t Cshader_sky = {{RSurfShader_Sky, NULL, NULL}, 0}; +Cshader_t Cshader_wall_lightmap = {{NULL, RSurfShader_Wall_Lightmap}, SHADERFLAGS_NEEDLIGHTMAP}; +Cshader_t Cshader_water = {{NULL, RSurfShader_Water}, 0}; +Cshader_t Cshader_sky = {{RSurfShader_Sky, NULL}, 0}; int Cshader_count = 3; Cshader_t *Cshaders[3] = @@ -1421,6 +1385,7 @@ Cshader_t *Cshaders[3] = &Cshader_sky }; +extern cvar_t r_shadows; void R_PrepareSurfaces(entity_render_t *ent) { int i, texframe, numsurfaces, *surfacevisframes; @@ -1455,7 +1420,7 @@ void R_PrepareSurfaces(entity_render_t *ent) } } - if (r_dynamic.integer) + if (r_dynamic.integer && r_shadows.integer != 3) R_MarkLights(ent); for (i = 0, surf = surfaces;i < numsurfaces;i++, surf++) @@ -1636,16 +1601,16 @@ void R_SurfaceWorldNode (entity_render_t *ent) #if WORLDNODECULLBACKFACES if (PlaneDist(modelorg, surf->plane) < surf->plane->dist) { - if ((surf->flags & SURF_PLANEBACK) && R_NotCulledBox (surf->poly_mins, surf->poly_maxs)) + if ((surf->flags & SURF_PLANEBACK) && !R_CullBox (surf->poly_mins, surf->poly_maxs)) surfacevisframes[i] = r_framecount; } else { - if (!(surf->flags & SURF_PLANEBACK) && R_NotCulledBox (surf->poly_mins, surf->poly_maxs)) + if (!(surf->flags & SURF_PLANEBACK) && !R_CullBox (surf->poly_mins, surf->poly_maxs)) surfacevisframes[i] = r_framecount; } #else - if (R_NotCulledBox (surf->poly_mins, surf->poly_maxs)) + if (!R_CullBox (surf->poly_mins, surf->poly_maxs)) surfacevisframes[i] = r_framecount; #endif } @@ -1697,8 +1662,8 @@ loc0: if (leaf->worldnodeframe != r_framecount) { leaf->worldnodeframe = r_framecount; - // FIXME: R_NotCulledBox is absolute, should be done relative - if (leaf->pvsframe == ent->model->pvsframecount && R_NotCulledBox(leaf->mins, leaf->maxs)) + // FIXME: R_CullBox is absolute, should be done relative + if (leaf->pvsframe == ent->model->pvsframecount && !R_CullBox(leaf->mins, leaf->maxs)) { p->visframe = r_framecount; pstack[portalstack++] = p; @@ -1775,8 +1740,8 @@ static void R_PortalWorldNode(entity_render_t *ent, mleaf_t *viewleaf) if (leaf->worldnodeframe != r_framecount) { leaf->worldnodeframe = r_framecount; - // FIXME: R_NotCulledBox is absolute, should be done relative - if (leaf->pvsframe == ent->model->pvsframecount && R_NotCulledBox(leaf->mins, leaf->maxs)) + // FIXME: R_CullBox is absolute, should be done relative + if (leaf->pvsframe == ent->model->pvsframecount && !R_CullBox(leaf->mins, leaf->maxs)) leafstack[leafstackpos++] = leaf; } } @@ -1833,7 +1798,7 @@ void R_PVSUpdate (entity_render_t *ent, mleaf_t *viewleaf) R_DrawWorld ============= */ -void R_DrawWorld (entity_render_t *ent, int baselighting) +void R_DrawWorld (entity_render_t *ent) { vec3_t modelorg; mleaf_t *viewleaf; @@ -1851,10 +1816,7 @@ void R_DrawWorld (entity_render_t *ent, int baselighting) R_PortalWorldNode (ent, viewleaf); R_PrepareSurfaces(ent); R_DrawSurfaces(ent, SHADERSTAGE_SKY); - if (baselighting) - R_DrawSurfaces(ent, SHADERSTAGE_BASELIGHTING); - else - R_DrawSurfaces(ent, SHADERSTAGE_NORMAL); + R_DrawSurfaces(ent, SHADERSTAGE_NORMAL); } void R_Model_Brush_DrawSky (entity_render_t *ent) @@ -1872,28 +1834,7 @@ void R_Model_Brush_Draw (entity_render_t *ent) R_DrawSurfaces(ent, SHADERSTAGE_NORMAL); } -void R_Model_Brush_DrawBaseLighting (entity_render_t *ent) -{ - c_bmodels++; - if (ent != &cl_entities[0].render) - R_PrepareBrushModel(ent); - R_DrawSurfaces(ent, SHADERSTAGE_BASELIGHTING); - /* - shadowmesh_t *mesh; - if (!cl.worldmodel->numlights) - GL_Color(0.3, 0.3, 0.3, 1); - for (mesh = ent->model->shadowmesh;mesh;mesh = mesh->next) - { - R_Mesh_ResizeCheck(mesh->numverts); - memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4])); - R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->elements); - } - if (!cl.worldmodel->numlights) - GL_Color(0, 0, 0, 1); - */ -} - -void R_Model_Brush_DrawShadowVolume (entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume) +void R_Model_Brush_DrawShadowVolume (entity_render_t *ent, vec3_t relativelightorigin, float lightradius) { #if 1 float projectdistance, temp[3]; @@ -1907,7 +1848,7 @@ void R_Model_Brush_DrawShadowVolume (entity_render_t *ent, vec3_t relativelighto { R_Mesh_ResizeCheck(mesh->numverts * 2); memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4])); - R_Shadow_Volume(mesh->numverts, mesh->numtriangles, varray_vertex, mesh->elements, mesh->neighbors, relativelightorigin, lightradius, projectdistance, visiblevolume); + R_Shadow_Volume(mesh->numverts, mesh->numtriangles, varray_vertex, mesh->elements, mesh->neighbors, relativelightorigin, lightradius, projectdistance); } } #else @@ -1935,7 +1876,7 @@ void R_Model_Brush_DrawShadowVolume (entity_render_t *ent, vec3_t relativelighto { R_Mesh_ResizeCheck(mesh->numverts * 2); memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4])); - R_Shadow_Volume(mesh->numverts, mesh->numtriangles, varray_vertex, mesh->index, mesh->triangleneighbors, relativelightorigin, lightradius, projectdistance, visiblevolume); + R_Shadow_Volume(mesh->numverts, mesh->numtriangles, varray_vertex, mesh->index, mesh->triangleneighbors, relativelightorigin, lightradius, projectdistance); } } } @@ -1983,73 +1924,6 @@ void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, v } } -/* -extern cvar_t r_shadows; -void R_DrawBrushModelFakeShadow (entity_render_t *ent) -{ - int i; - vec3_t relativelightorigin; - rmeshstate_t m; - mlight_t *sl; - rdlight_t *rd; - svbspmesh_t *mesh; - - if (r_shadows.integer < 2) - return; - - memset(&m, 0, sizeof(m)); - m.blendfunc1 = GL_ONE; - m.blendfunc2 = GL_ONE; - R_Mesh_State(&m); - R_Mesh_Matrix(&ent->matrix); - GL_Color(0.0125 * r_colorscale, 0.025 * r_colorscale, 0.1 * r_colorscale, 1); - if (0)//ent->model == cl.worldmodel) - { - for (i = 0, sl = cl.worldmodel->lights;i < cl.worldmodel->numlights;i++, sl++) - { - if (d_lightstylevalue[sl->style] > 0 && R_NotCulledBox(sl->shadowvolumemins, sl->shadowvolumemaxs)) - { - for (mesh = sl->shadowvolume;mesh;mesh = mesh->next) - { - memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4])); - R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->elements); - } - } - } - } - else - { - for (i = 0, sl = cl.worldmodel->lights;i < cl.worldmodel->numlights;i++, sl++) - { - if (d_lightstylevalue[sl->style] > 0 - && ent->maxs[0] >= sl->origin[0] - sl->cullradius - && ent->mins[0] <= sl->origin[0] + sl->cullradius - && ent->maxs[1] >= sl->origin[1] - sl->cullradius - && ent->mins[1] <= sl->origin[1] + sl->cullradius - && ent->maxs[2] >= sl->origin[2] - sl->cullradius - && ent->mins[2] <= sl->origin[2] + sl->cullradius) - { - Matrix4x4_Transform(&ent->inversematrix, sl->origin, relativelightorigin); - R_DrawBrushModelShadowVolume (ent, relativelightorigin, sl->cullradius, true); - } - } - } - for (i = 0, rd = r_dlight;i < r_numdlights;i++, rd++) - { - if (ent->maxs[0] >= rd->origin[0] - rd->cullradius - && ent->mins[0] <= rd->origin[0] + rd->cullradius - && ent->maxs[1] >= rd->origin[1] - rd->cullradius - && ent->mins[1] <= rd->origin[1] + rd->cullradius - && ent->maxs[2] >= rd->origin[2] - rd->cullradius - && ent->mins[2] <= rd->origin[2] + rd->cullradius) - { - Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin); - R_DrawBrushModelShadowVolume (ent, relativelightorigin, rd->cullradius, true); - } - } -} -*/ - static void gl_surf_start(void) { } diff --git a/gl_textures.c b/gl_textures.c index a502f81a..558b1f59 100644 --- a/gl_textures.c +++ b/gl_textures.c @@ -554,8 +554,7 @@ static void GL_SetupTextureParameters(int flags, int texturetype) CHECKGLERROR qglTexParameteri(textureenum, GL_TEXTURE_WRAP_S, wrapmode); - if (gltexturetypedimensions[texturetype] >= 2) - qglTexParameteri(textureenum, GL_TEXTURE_WRAP_T, wrapmode); + qglTexParameteri(textureenum, GL_TEXTURE_WRAP_T, wrapmode); if (gltexturetypedimensions[texturetype] >= 3) qglTexParameteri(textureenum, GL_TEXTURE_WRAP_R, wrapmode); @@ -621,7 +620,7 @@ static void R_Upload(gltexture_t *glt, qbyte *data) { // promote paletted to RGBA, so we only have to worry about RGB and // RGBA in the rest of this code - R_MakeResizeBufferBigger(glt->image->width * glt->image->height * glt->image->depth * glt->image->bytesperpixel); + R_MakeResizeBufferBigger(glt->image->width * glt->image->height * glt->image->depth * glt->image->sides * glt->image->bytesperpixel); Image_Copy8bitRGBA(prevbuffer, colorconvertbuffer, glt->width * glt->height * glt->depth, glt->palette); prevbuffer = colorconvertbuffer; } @@ -655,7 +654,7 @@ static void R_Upload(gltexture_t *glt, qbyte *data) for (height = 1;height < glt->height;height <<= 1); for (depth = 1;depth < glt->depth ;depth <<= 1); - R_MakeResizeBufferBigger(width * height * depth * glt->image->bytesperpixel); + R_MakeResizeBufferBigger(width * height * depth * glt->image->sides * glt->image->bytesperpixel); if (prevbuffer == NULL) { @@ -671,29 +670,31 @@ static void R_Upload(gltexture_t *glt, qbyte *data) { // promote paletted to RGBA, so we only have to worry about RGB and // RGBA in the rest of this code - Image_Copy8bitRGBA(prevbuffer, colorconvertbuffer, glt->width * glt->height * glt->depth, glt->palette); + Image_Copy8bitRGBA(prevbuffer, colorconvertbuffer, glt->width * glt->height * glt->depth * glt->image->sides, glt->palette); prevbuffer = colorconvertbuffer; } + } + // 3 and 4 are converted by the driver to it's preferred format for the current display mode + internalformat = 3; + if (glt->flags & TEXF_ALPHA) + internalformat = 4; + + // cubemaps contain multiple images and thus get processed a bit differently + if (glt->image->texturetype != GLTEXTURETYPE_CUBEMAP) + { if (glt->width != width || glt->height != height || glt->depth != depth) { Image_Resample(prevbuffer, glt->width, glt->height, glt->depth, resizebuffer, width, height, depth, glt->image->bytesperpixel, r_lerpimages.integer); prevbuffer = resizebuffer; } - - // apply picmip/max_size limitations + // picmip/max_size while (width > glt->image->width || height > glt->image->height || depth > glt->image->depth) { Image_MipReduce(prevbuffer, resizebuffer, &width, &height, &depth, glt->image->width, glt->image->height, glt->image->depth, glt->image->bytesperpixel); prevbuffer = resizebuffer; } } - - // 3 and 4 are converted by the driver to it's preferred format for the current display mode - internalformat = 3; - if (glt->flags & TEXF_ALPHA) - internalformat = 4; - mip = 0; switch(glt->image->texturetype) { @@ -747,6 +748,18 @@ static void R_Upload(gltexture_t *glt, qbyte *data) { prevbuffer = texturebuffer; texturebuffer += width * height * depth * glt->textype->inputbytesperpixel; + if (glt->width != width || glt->height != height || glt->depth != depth) + { + Image_Resample(prevbuffer, glt->width, glt->height, glt->depth, resizebuffer, width, height, depth, glt->image->bytesperpixel, r_lerpimages.integer); + prevbuffer = resizebuffer; + } + // picmip/max_size + while (width > glt->image->width || height > glt->image->height || depth > glt->image->depth) + { + Image_MipReduce(prevbuffer, resizebuffer, &width, &height, &depth, glt->image->width, glt->image->height, glt->image->depth, glt->image->bytesperpixel); + prevbuffer = resizebuffer; + } + mip = 0; qglTexImage2D(cubemapside[i], mip++, internalformat, width, height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer); CHECKGLERROR if (glt->flags & TEXF_MIPMAP) diff --git a/image.c b/image.c index dce3b365..0ce0886a 100644 --- a/image.c +++ b/image.c @@ -1296,7 +1296,7 @@ void Image_HeightmapToNormalmap(const unsigned char *inpixels, unsigned char *ou float iwidth, iheight, ibumpscale, n[3]; iwidth = 1.0f / width; iheight = 1.0f / height; - ibumpscale = (255.0f * 3.0f) / (bumpscale * 16.0f); + ibumpscale = (255.0f * 3.0f) / (bumpscale * 8.0f); out = outpixels; for (y = 0;y < height;y++) { diff --git a/model_alias.c b/model_alias.c index 112df181..9adc1b77 100644 --- a/model_alias.c +++ b/model_alias.c @@ -211,8 +211,7 @@ static int Mod_LoadInternalSkin (char *basename, qbyte *skindata, int width, int #define BOUNDF(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%f exceeds %f - %f)\n", loadmodel->name, VALUE, MIN, MAX); extern void R_Model_Alias_Draw(entity_render_t *ent); extern void R_Model_Alias_DrawFakeShadow(entity_render_t *ent); -extern void R_Model_Alias_DrawBaseLighting(entity_render_t *ent); -extern void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume); +extern void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius); extern void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor); void Mod_LoadAliasModel (model_t *mod, void *buffer) { @@ -248,7 +247,6 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) loadmodel->DrawSky = NULL; loadmodel->Draw = R_Model_Alias_Draw; loadmodel->DrawFakeShadow = R_Model_Alias_DrawFakeShadow; - loadmodel->DrawBaseLighting = R_Model_Alias_DrawBaseLighting; loadmodel->DrawShadowVolume = R_Model_Alias_DrawShadowVolume; loadmodel->DrawLight = R_Model_Alias_DrawLight; @@ -572,7 +570,6 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) loadmodel->DrawSky = NULL; loadmodel->Draw = R_Model_Alias_Draw; loadmodel->DrawFakeShadow = R_Model_Alias_DrawFakeShadow; - loadmodel->DrawBaseLighting = R_Model_Alias_DrawBaseLighting; loadmodel->DrawShadowVolume = R_Model_Alias_DrawShadowVolume; loadmodel->DrawLight = R_Model_Alias_DrawLight; @@ -766,8 +763,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) extern void R_Model_Zymotic_DrawSky(entity_render_t *ent); extern void R_Model_Zymotic_Draw(entity_render_t *ent); extern void R_Model_Zymotic_DrawFakeShadow(entity_render_t *ent); -extern void R_Model_Zymotic_DrawBaseLighting(entity_render_t *ent); -extern void R_Model_Zymotic_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume); +extern void R_Model_Zymotic_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius); extern void R_Model_Zymotic_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor); void Mod_LoadZymoticModel(model_t *mod, void *buffer) { @@ -786,7 +782,6 @@ void Mod_LoadZymoticModel(model_t *mod, void *buffer) loadmodel->DrawSky = NULL; loadmodel->Draw = R_Model_Zymotic_Draw; loadmodel->DrawFakeShadow = NULL;//R_Model_Zymotic_DrawFakeShadow; - loadmodel->DrawBaseLighting = NULL;//R_Model_Zymotic_DrawBaseLighting; loadmodel->DrawShadowVolume = NULL;//R_Model_Zymotic_DrawShadowVolume; loadmodel->DrawLight = NULL;//R_Model_Zymotic_DrawLight; diff --git a/model_brush.c b/model_brush.c index 665483c2..c91368de 100644 --- a/model_brush.c +++ b/model_brush.c @@ -296,12 +296,12 @@ static void Mod_LoadTextures (lump_t *l) Con_Printf("warning: unnamed texture in %s, renaming to %s\n", loadmodel->name, tx->name); } - basepixels = NULL; - bumppixels = NULL; - nmappixels = NULL; - glosspixels = NULL; - glowpixels = NULL; - maskpixels = NULL; + basepixels = NULL;basepixels_width = 0;basepixels_height = 0; + bumppixels = NULL;bumppixels_width = 0;bumppixels_height = 0; + nmappixels = NULL;nmappixels_width = 0;nmappixels_height = 0; + glosspixels = NULL;glosspixels_width = 0;glosspixels_height = 0; + glowpixels = NULL;glowpixels_width = 0;glowpixels_height = 0; + maskpixels = NULL;maskpixels_width = 0;maskpixels_height = 0; detailtexture = NULL; // LordHavoc: HL sky textures are entirely different than quake @@ -331,14 +331,30 @@ static void Mod_LoadTextures (lump_t *l) } else { - basepixels = loadimagepixels(tx->name, false, 0, 0); - if (basepixels) + if ((basepixels = loadimagepixels(tx->name, false, 0, 0)) != NULL) { - strcpy(name, tx->name); - strcat(name, "_glow"); - glowpixels = loadimagepixels(name, false, 0, 0); + basepixels_width = image_width; + basepixels_height = image_height; } - else + // _luma is supported for tenebrae compatibility + // (I think it's a very stupid name, but oh well) + if ((glowpixels = loadimagepixels(va("%s_glow", tx->name), false, 0, 0)) != NULL + || (glowpixels = loadimagepixels(va("%s_luma", tx->name), false, 0, 0)) != NULL) + { + glowpixels_width = image_width; + glowpixels_height = image_height; + } + if ((bumppixels = loadimagepixels(va("%s_bump", tx->name), false, 0, 0)) != NULL) + { + bumppixels_width = image_width; + bumppixels_height = image_height; + } + if ((glosspixels = loadimagepixels(va("%s_gloss", tx->name), false, 0, 0)) != NULL) + { + glosspixels_width = image_width; + glosspixels_height = image_height; + } + if (!basepixels) { if (loadmodel->ishlbsp) { @@ -365,15 +381,18 @@ static void Mod_LoadTextures (lump_t *l) basepixels_height = tx->height; basepixels = Mem_Alloc(loadmodel->mempool, basepixels_width * basepixels_height * 4); Image_Copy8bitRGBA(mtdata, basepixels, basepixels_width * basepixels_height, palette_nofullbrights); - for (j = 0;j < tx->width*tx->height;j++) - if (((qbyte *)&palette_onlyfullbrights[mtdata[j]])[3] > 0) // fullbright - break; - if (j < tx->width * tx->height) + if (!glowpixels) { - glowpixels_width = tx->width; - glowpixels_height = tx->height; - glowpixels = Mem_Alloc(loadmodel->mempool, glowpixels_width * glowpixels_height * 4); - Image_Copy8bitRGBA(mtdata, glowpixels, glowpixels_width * glowpixels_height, palette_onlyfullbrights); + for (j = 0;j < tx->width*tx->height;j++) + if (((qbyte *)&palette_onlyfullbrights[mtdata[j]])[3] > 0) // fullbright + break; + if (j < tx->width * tx->height) + { + glowpixels_width = tx->width; + glowpixels_height = tx->height; + glowpixels = Mem_Alloc(loadmodel->mempool, glowpixels_width * glowpixels_height * 4); + Image_Copy8bitRGBA(mtdata, glowpixels, glowpixels_width * glowpixels_height, palette_onlyfullbrights); + } } } else @@ -431,7 +450,7 @@ static void Mod_LoadTextures (lump_t *l) { tx->texture = R_LoadTexture2D (loadmodel->texturepool, tx->name, basepixels_width, basepixels_height, basepixels, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL); if (nmappixels) - tx->nmaptexture = R_LoadTexture2D (loadmodel->texturepool, va("%s_nmap", tx->name), basepixels_width, basepixels_height, basepixels, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL); + tx->nmaptexture = R_LoadTexture2D (loadmodel->texturepool, va("%s_nmap", tx->name), basepixels_width, basepixels_height, nmappixels, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL); if (glosspixels) tx->glosstexture = R_LoadTexture2D (loadmodel->texturepool, va("%s_gloss", tx->name), glosspixels_width, glosspixels_height, glosspixels, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL); if (glowpixels) @@ -3511,9 +3530,7 @@ Mod_LoadBrushModel */ extern void R_Model_Brush_DrawSky(entity_render_t *ent); extern void R_Model_Brush_Draw(entity_render_t *ent); -//extern void R_Model_Brush_DrawFakeShadow(entity_render_t *ent); -extern void R_Model_Brush_DrawBaseLighting(entity_render_t *ent); -extern void R_Model_Brush_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume); +extern void R_Model_Brush_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius); extern void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor); void Mod_LoadBrushModel (model_t *mod, void *buffer) { @@ -3607,7 +3624,6 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) mod->DrawSky = NULL; mod->Draw = R_Model_Brush_Draw; mod->DrawFakeShadow = NULL; - mod->DrawBaseLighting = R_Model_Brush_DrawBaseLighting; mod->DrawShadowVolume = R_Model_Brush_DrawShadowVolume; mod->DrawLight = R_Model_Brush_DrawLight; mod->texturesurfacechains = Mem_Alloc(originalloadmodel->mempool, mod->numtextures * sizeof(msurface_t *)); diff --git a/model_brush.h b/model_brush.h index 3d031e73..2998a106 100644 --- a/model_brush.h +++ b/model_brush.h @@ -57,8 +57,7 @@ mplane_t; #define SHADERSTAGE_SKY 0 #define SHADERSTAGE_NORMAL 1 -#define SHADERSTAGE_BASELIGHTING 2 -#define SHADERSTAGE_COUNT 3 +#define SHADERSTAGE_COUNT 2 #define SHADERFLAGS_NEEDLIGHTMAP 1 diff --git a/model_shared.h b/model_shared.h index f013bb28..776b1af5 100644 --- a/model_shared.h +++ b/model_shared.h @@ -245,10 +245,8 @@ typedef struct model_s void(*DrawFakeShadow)(struct entity_render_s *ent); // functions used only in shadow volume rendering mode - // draw the base lighting for the model (glowing areas, etc) - void(*DrawBaseLighting)(struct entity_render_s *ent); // draw a shadow volume for the model based on light source - void(*DrawShadowVolume)(struct entity_render_s *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume); + void(*DrawShadowVolume)(struct entity_render_s *ent, vec3_t relativelightorigin, float lightradius); // draw the lighting on a model (through stencil) void(*DrawLight)(struct entity_render_s *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float lightdistbias, float lightsubtract, float *lightcolor); diff --git a/model_sprite.c b/model_sprite.c index 732b8c63..edcec466 100644 --- a/model_sprite.c +++ b/model_sprite.c @@ -249,7 +249,6 @@ void Mod_LoadSpriteModel (model_t *mod, void *buffer) loadmodel->DrawSky = NULL; loadmodel->Draw = R_Model_Sprite_Draw; loadmodel->DrawFakeShadow = NULL; - loadmodel->DrawBaseLighting = NULL; loadmodel->DrawShadowVolume = NULL; loadmodel->DrawLight = NULL; diff --git a/palette.c b/palette.c index 7dbc82f0..1978eefe 100644 --- a/palette.c +++ b/palette.c @@ -55,48 +55,56 @@ void Palette_Setup8to24(void) reversed_start = 128; reversed_end = 224; - memset(palette_nofullbrights, 0, sizeof(palette_nofullbrights)); for (i = 0;i < fullbright_start;i++) palette_nofullbrights[i] = palette_complete[i]; + for (i = fullbright_start;i < 255;i++) + palette_nofullbrights[i] = palette_complete[0]; + palette_nofullbrights[255] = 0; - memset(palette_onlyfullbrights, 0, sizeof(palette_onlyfullbrights)); + for (i = 0;i < 256;i++) + palette_onlyfullbrights[i] = palette_complete[0]; for (i = fullbright_start;i < fullbright_end;i++) palette_onlyfullbrights[i] = palette_complete[i]; + palette_onlyfullbrights[255] = 0; for (i = 0;i < 256;i++) palette_nocolormapnofullbrights[i] = palette_complete[i]; for (i = pants_start;i < pants_end;i++) - palette_nocolormapnofullbrights[i] = 0; + palette_nocolormapnofullbrights[i] = palette_complete[0]; for (i = shirt_start;i < shirt_end;i++) - palette_nocolormapnofullbrights[i] = 0; + palette_nocolormapnofullbrights[i] = palette_complete[0]; for (i = fullbright_start;i < fullbright_end;i++) - palette_nocolormapnofullbrights[i] = 0; + palette_nocolormapnofullbrights[i] = palette_complete[0]; + palette_nocolormapnofullbrights[255] = 0; - memset(palette_pantsaswhite, 0, sizeof(palette_pantsaswhite)); + for (i = 0;i < 256;i++) + palette_pantsaswhite[i] = palette_complete[0]; for (i = pants_start;i < pants_end;i++) { if (i >= reversed_start && i < reversed_end) - palette_pantsaswhite[i] = 15 - (i - pants_start); + palette_pantsaswhite[i] = palette_complete[15 - (i - pants_start)]; else - palette_pantsaswhite[i] = i - pants_start; + palette_pantsaswhite[i] = palette_complete[i - pants_start]; } - memset(palette_shirtaswhite, 0, sizeof(palette_shirtaswhite)); + for (i = 0;i < 256;i++) + palette_shirtaswhite[i] = palette_complete[0]; for (i = shirt_start;i < shirt_end;i++) { if (i >= reversed_start && i < reversed_end) - palette_shirtaswhite[i] = 15 - (i - shirt_start); + palette_shirtaswhite[i] = palette_complete[15 - (i - shirt_start)]; else - palette_shirtaswhite[i] = i - shirt_start; + palette_shirtaswhite[i] = palette_complete[i - shirt_start]; } - memset(palette_alpha, 0, sizeof(palette_alpha)); for (i = 0;i < 255;i++) palette_alpha[i] = 0xFFFFFFFF; + palette_alpha[255] = 0; - memset(palette_font, 0, sizeof(palette_font)); + palette_font[0] = 0; for (i = 1;i < 255;i++) palette_font[i] = palette_complete[i]; + palette_font[255] = 0; } diff --git a/r_light.c b/r_light.c index e233ff7e..1c46419d 100644 --- a/r_light.c +++ b/r_light.c @@ -662,6 +662,7 @@ void R_ModelLightPoint (const entity_render_t *ent, vec3_t color, const vec3_t p RecursiveLightPoint (color, cl.worldmodel->nodes, p[0], p[1], p[2], p[2] - 65536); } +extern cvar_t r_shadows; void R_LightModel(const entity_render_t *ent, int numverts, float *vertices, float *normals, float *colors, float colorr, float colorg, float colorb, int worldcoords) { int i, j, nearlights = 0, maxnearlights = r_modellights.integer; @@ -690,72 +691,16 @@ void R_LightModel(const entity_render_t *ent, int numverts, float *vertices, flo { R_ModelLightPoint(ent, basecolor, ent->origin); - nl = &nearlight[0]; - for (i = 0;i < ent->numentlights;i++) + if (r_shadows.integer != 3) { - sl = cl.worldmodel->lights + ent->entlights[i]; - stylescale = d_lightstylevalue[sl->style] * (1.0f / 65536.0f); - VectorSubtract (ent->origin, sl->origin, v); - f = ((1.0f / (DotProduct(v, v) * sl->falloff + sl->distbias)) - sl->subtract) * stylescale; - VectorScale(sl->light, f, ambientcolor); - intensity = DotProduct(ambientcolor, ambientcolor); - if (f < 0) - intensity *= -1.0f; - if (nearlights < maxnearlights) - j = nearlights++; - else + nl = &nearlight[0]; + for (i = 0;i < ent->numentlights;i++) { - for (j = 0;j < maxnearlights;j++) - { - if (nearlight[j].intensity < intensity) - { - if (nearlight[j].intensity > 0) - VectorAdd(basecolor, nearlight[j].ambientlight, basecolor); - break; - } - } - } - if (j >= maxnearlights) - { - // this light is less significant than all others, - // add it to ambient - if (intensity > 0) - VectorAdd(basecolor, ambientcolor, basecolor); - } - else - { - nl = nearlight + j; - nl->intensity = intensity; - // transform the light into the model's coordinate system - if (worldcoords) - VectorCopy(sl->origin, nl->origin); - else - Matrix4x4_Transform(&ent->inversematrix, sl->origin, nl->origin); - // integrate mscale into falloff, for maximum speed - nl->falloff = sl->falloff * mscale; - VectorCopy(ambientcolor, nl->ambientlight); - nl->light[0] = sl->light[0] * stylescale * colorr * 4.0f; - nl->light[1] = sl->light[1] * stylescale * colorg * 4.0f; - nl->light[2] = sl->light[2] * stylescale * colorb * 4.0f; - nl->subtract = sl->subtract; - nl->offset = sl->distbias; - } - } - for (i = 0;i < r_numdlights;i++) - { - rd = r_dlight + i; - VectorCopy(rd->origin, v); - if (v[0] < ent->mins[0]) v[0] = ent->mins[0];if (v[0] > ent->maxs[0]) v[0] = ent->maxs[0]; - if (v[1] < ent->mins[1]) v[1] = ent->mins[1];if (v[1] > ent->maxs[1]) v[1] = ent->maxs[1]; - if (v[2] < ent->mins[2]) v[2] = ent->mins[2];if (v[2] > ent->maxs[2]) v[2] = ent->maxs[2]; - VectorSubtract (v, rd->origin, v); - if (DotProduct(v, v) < rd->cullradius2) - { - if (CL_TraceLine(ent->origin, rd->origin, NULL, NULL, 0, false, NULL) != 1) - continue; - VectorSubtract (ent->origin, rd->origin, v); - f = ((1.0f / (DotProduct(v, v) + LIGHTOFFSET)) - rd->subtract); - VectorScale(rd->light, f, ambientcolor); + sl = cl.worldmodel->lights + ent->entlights[i]; + stylescale = d_lightstylevalue[sl->style] * (1.0f / 65536.0f); + VectorSubtract (ent->origin, sl->origin, v); + f = ((1.0f / (DotProduct(v, v) * sl->falloff + sl->distbias)) - sl->subtract) * stylescale; + VectorScale(sl->light, f, ambientcolor); intensity = DotProduct(ambientcolor, ambientcolor); if (f < 0) intensity *= -1.0f; @@ -786,43 +731,101 @@ void R_LightModel(const entity_render_t *ent, int numverts, float *vertices, flo nl->intensity = intensity; // transform the light into the model's coordinate system if (worldcoords) - VectorCopy(rd->origin, nl->origin); + VectorCopy(sl->origin, nl->origin); else - { - Matrix4x4_Transform(&ent->inversematrix, rd->origin, nl->origin); - /* - Con_Printf("%i %s : %f %f %f : %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n" - , rd - r_dlight, ent->model->name - , rd->origin[0], rd->origin[1], rd->origin[2] - , nl->origin[0], nl->origin[1], nl->origin[2] - , ent->inversematrix.m[0][0], ent->inversematrix.m[0][1], ent->inversematrix.m[0][2], ent->inversematrix.m[0][3] - , ent->inversematrix.m[1][0], ent->inversematrix.m[1][1], ent->inversematrix.m[1][2], ent->inversematrix.m[1][3] - , ent->inversematrix.m[2][0], ent->inversematrix.m[2][1], ent->inversematrix.m[2][2], ent->inversematrix.m[2][3] - , ent->inversematrix.m[3][0], ent->inversematrix.m[3][1], ent->inversematrix.m[3][2], ent->inversematrix.m[3][3]); - */ - } + Matrix4x4_Transform(&ent->inversematrix, sl->origin, nl->origin); // integrate mscale into falloff, for maximum speed - nl->falloff = mscale; + nl->falloff = sl->falloff * mscale; VectorCopy(ambientcolor, nl->ambientlight); - nl->light[0] = rd->light[0] * colorr * 4.0f; - nl->light[1] = rd->light[1] * colorg * 4.0f; - nl->light[2] = rd->light[2] * colorb * 4.0f; - nl->subtract = rd->subtract; - nl->offset = LIGHTOFFSET; + nl->light[0] = sl->light[0] * stylescale * colorr * 4.0f; + nl->light[1] = sl->light[1] * stylescale * colorg * 4.0f; + nl->light[2] = sl->light[2] * stylescale * colorb * 4.0f; + nl->subtract = sl->subtract; + nl->offset = sl->distbias; + } + } + for (i = 0;i < r_numdlights;i++) + { + rd = r_dlight + i; + VectorCopy(rd->origin, v); + if (v[0] < ent->mins[0]) v[0] = ent->mins[0];if (v[0] > ent->maxs[0]) v[0] = ent->maxs[0]; + if (v[1] < ent->mins[1]) v[1] = ent->mins[1];if (v[1] > ent->maxs[1]) v[1] = ent->maxs[1]; + if (v[2] < ent->mins[2]) v[2] = ent->mins[2];if (v[2] > ent->maxs[2]) v[2] = ent->maxs[2]; + VectorSubtract (v, rd->origin, v); + if (DotProduct(v, v) < rd->cullradius2) + { + if (CL_TraceLine(ent->origin, rd->origin, NULL, NULL, 0, false, NULL) != 1) + continue; + VectorSubtract (ent->origin, rd->origin, v); + f = ((1.0f / (DotProduct(v, v) + LIGHTOFFSET)) - rd->subtract); + VectorScale(rd->light, f, ambientcolor); + intensity = DotProduct(ambientcolor, ambientcolor); + if (f < 0) + intensity *= -1.0f; + if (nearlights < maxnearlights) + j = nearlights++; + else + { + for (j = 0;j < maxnearlights;j++) + { + if (nearlight[j].intensity < intensity) + { + if (nearlight[j].intensity > 0) + VectorAdd(basecolor, nearlight[j].ambientlight, basecolor); + break; + } + } + } + if (j >= maxnearlights) + { + // this light is less significant than all others, + // add it to ambient + if (intensity > 0) + VectorAdd(basecolor, ambientcolor, basecolor); + } + else + { + nl = nearlight + j; + nl->intensity = intensity; + // transform the light into the model's coordinate system + if (worldcoords) + VectorCopy(rd->origin, nl->origin); + else + { + Matrix4x4_Transform(&ent->inversematrix, rd->origin, nl->origin); + /* + Con_Printf("%i %s : %f %f %f : %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n" + , rd - r_dlight, ent->model->name + , rd->origin[0], rd->origin[1], rd->origin[2] + , nl->origin[0], nl->origin[1], nl->origin[2] + , ent->inversematrix.m[0][0], ent->inversematrix.m[0][1], ent->inversematrix.m[0][2], ent->inversematrix.m[0][3] + , ent->inversematrix.m[1][0], ent->inversematrix.m[1][1], ent->inversematrix.m[1][2], ent->inversematrix.m[1][3] + , ent->inversematrix.m[2][0], ent->inversematrix.m[2][1], ent->inversematrix.m[2][2], ent->inversematrix.m[2][3] + , ent->inversematrix.m[3][0], ent->inversematrix.m[3][1], ent->inversematrix.m[3][2], ent->inversematrix.m[3][3]); + */ + } + // integrate mscale into falloff, for maximum speed + nl->falloff = mscale; + VectorCopy(ambientcolor, nl->ambientlight); + nl->light[0] = rd->light[0] * colorr * 4.0f; + nl->light[1] = rd->light[1] * colorg * 4.0f; + nl->light[2] = rd->light[2] * colorb * 4.0f; + nl->subtract = rd->subtract; + nl->offset = LIGHTOFFSET; + } } } } } else - { R_CompleteLightPoint (basecolor, ent->origin, true, NULL); - } basecolor[0] *= colorr; basecolor[1] *= colorg; basecolor[2] *= colorb; avc = colors; if (nearlights) { + GL_UseColorArray(); av = vertices; avn = normals; for (i = 0;i < numverts;i++) @@ -870,14 +873,7 @@ void R_LightModel(const entity_render_t *ent, int numverts, float *vertices, flo } } else - { - for (i = 0;i < numverts;i++) - { - VectorCopy(basecolor, avc); - avc[3] = a; - avc += 4; - } - } + GL_Color(basecolor[0], basecolor[1], basecolor[2], a); } void R_UpdateEntLights(entity_render_t *ent) diff --git a/r_shadow.c b/r_shadow.c index f648a5e5..5e3cfde4 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -2,6 +2,13 @@ #include "quakedef.h" #include "r_shadow.h" +#define SHADOWSTAGE_NONE 0 +#define SHADOWSTAGE_STENCIL 1 +#define SHADOWSTAGE_LIGHT 2 +#define SHADOWSTAGE_ERASESTENCIL 3 + +int r_shadowstage = SHADOWSTAGE_NONE; + mempool_t *r_shadow_mempool; int maxshadowelements; @@ -15,12 +22,12 @@ rtexture_t *r_shadow_normalscubetexture; rtexture_t *r_shadow_attenuation2dtexture; rtexture_t *r_shadow_blankbumptexture; -cvar_t r_shadow1 = {0, "r_shadow1", "16"}; -cvar_t r_shadow2 = {0, "r_shadow2", "2"}; -cvar_t r_shadow3 = {0, "r_shadow3", "65536"}; -cvar_t r_shadow4 = {0, "r_shadow4", "1"}; +cvar_t r_shadow1 = {0, "r_shadow1", "2"}; +cvar_t r_shadow2 = {0, "r_shadow2", "0"}; +cvar_t r_shadow3 = {0, "r_shadow3", "32768"}; +cvar_t r_shadow4 = {0, "r_shadow4", "0"}; cvar_t r_shadow5 = {0, "r_shadow5", "0"}; -cvar_t r_shadow6 = {0, "r_shadow6", "1"}; +cvar_t r_shadow6 = {0, "r_shadow6", "0"}; cvar_t r_light_realtime = {0, "r_light_realtime", "0"}; cvar_t r_light_quality = {0, "r_light_quality", "1"}; cvar_t r_light_gloss = {0, "r_light_gloss", "0"}; @@ -74,7 +81,7 @@ void R_Shadow_Init(void) R_RegisterModule("R_Shadow", r_shadow_start, r_shadow_shutdown, r_shadow_newmap); } -void R_Shadow_Volume(int numverts, int numtris, float *vertex, int *elements, int *neighbors, vec3_t relativelightorigin, float lightradius, float projectdistance, int visiblevolume) +void R_Shadow_Volume(int numverts, int numtris, float *vertex, int *elements, int *neighbors, vec3_t relativelightorigin, float lightradius, float projectdistance) { int i, *e, *n, *out, tris; float *v0, *v1, *v2, temp[3], f; @@ -262,19 +269,15 @@ void R_Shadow_Volume(int numverts, int numtris, float *vertex, int *elements, in } } } - R_Shadow_RenderVolume(numverts * 2, tris, shadowelements, visiblevolume); + R_Shadow_RenderVolume(numverts * 2, tris, shadowelements); } -void R_Shadow_RenderVolume(int numverts, int numtris, int *elements, int visiblevolume) +void R_Shadow_RenderVolume(int numverts, int numtris, int *elements) { + if (!numverts || !numtris) + return; // draw the volume - if (visiblevolume) - { - //qglDisable(GL_CULL_FACE); - R_Mesh_Draw(numverts, numtris, elements); - //qglEnable(GL_CULL_FACE); - } - else + if (r_shadowstage == SHADOWSTAGE_STENCIL) { // increment stencil if backface is behind depthbuffer qglCullFace(GL_BACK); // quake is backwards, this culls front faces @@ -285,6 +288,8 @@ void R_Shadow_RenderVolume(int numverts, int numtris, int *elements, int visible qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP); R_Mesh_Draw(numverts, numtris, elements); } + else + R_Mesh_Draw(numverts, numtris, elements); } float r_shadow_atten1, r_shadow_atten2, r_shadow_atten5; @@ -305,12 +310,10 @@ static void R_Shadow_Make3DTextures(void) v[0] = (x + 0.5f) * (2.0f / (float) ATTEN3DSIZE) - 1.0f; v[1] = (y + 0.5f) * (2.0f / (float) ATTEN3DSIZE) - 1.0f; v[2] = (z + 0.5f) * (2.0f / (float) ATTEN3DSIZE) - 1.0f; - length = sqrt(DotProduct(v, v)); - if (DotProduct(v, v) < 1) - intensity = (((r_shadow_atten1 / (length*length + r_shadow_atten5)) - (r_shadow_atten1 * r_shadow_atten2))) / 256.0f; - else - intensity = 0; - ilen = 127.0f * bound(0, intensity, 1) / length; + intensity = 1.0f - sqrt(DotProduct(v, v)); + if (intensity > 0) + intensity *= intensity; + ilen = 127.0f * bound(0, intensity * r_shadow_atten1, 1) / sqrt(DotProduct(v, v)); data[z][y][x][0] = 128.0f + ilen * v[0]; data[z][y][x][1] = 128.0f + ilen * v[1]; data[z][y][x][2] = 128.0f + ilen * v[2]; @@ -404,18 +407,18 @@ static void R_Shadow_MakeTextures(void) v[0] = (x + 0.5f) * (2.0f / 128.0f) - 1.0f; v[1] = (y + 0.5f) * (2.0f / 128.0f) - 1.0f; v[2] = 0; - if (DotProduct(v, v) < 1) - intensity = (((r_shadow_atten1 / (DotProduct(v, v)+r_shadow_atten5)) - (r_shadow_atten1 * r_shadow_atten2))) / 256.0f; - else - intensity = 0; - d = bound(0, intensity, 255) / sqrt(DotProduct(v, v)); + intensity = 1.0f - sqrt(DotProduct(v, v)); + if (intensity > 0) + intensity *= intensity; + intensity = bound(0, intensity * r_shadow_atten1 * 256.0f, 255.0f); + d = bound(0, intensity, 255); data[0][y][x][0] = d; data[0][y][x][1] = d; data[0][y][x][2] = d; - data[0][y][x][3] = 255; + data[0][y][x][3] = d; } } - r_shadow_attenuation2dtexture = R_LoadTexture2D(r_shadow_texturepool, "attenuation2d", 128, 128, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL); + r_shadow_attenuation2dtexture = R_LoadTexture2D(r_shadow_texturepool, "attenuation2d", 128, 128, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_ALPHA | TEXF_MIPMAP, NULL); R_Shadow_Make3DTextures(); } @@ -441,6 +444,7 @@ void R_Shadow_Stage_Begin(void) m.blendfunc2 = GL_ZERO; R_Mesh_State(&m); GL_Color(0, 0, 0, 1); + r_shadowstage = SHADOWSTAGE_NONE; } void R_Shadow_Stage_ShadowVolumes(void) @@ -458,6 +462,9 @@ void R_Shadow_Stage_ShadowVolumes(void) qglEnable(GL_STENCIL_TEST); qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); qglStencilFunc(GL_ALWAYS, 0, 0xFF); + qglEnable(GL_CULL_FACE); + qglEnable(GL_DEPTH_TEST); + r_shadowstage = SHADOWSTAGE_STENCIL; } void R_Shadow_Stage_Light(void) @@ -478,11 +485,33 @@ void R_Shadow_Stage_Light(void) // only draw light where this geometry was already rendered AND the // stencil is 0 (non-zero means shadow) qglStencilFunc(GL_EQUAL, 0, 0xFF); + qglEnable(GL_CULL_FACE); + qglEnable(GL_DEPTH_TEST); + r_shadowstage = SHADOWSTAGE_LIGHT; } -void R_Shadow_Stage_End(void) +void R_Shadow_Stage_EraseShadowVolumes(void) { rmeshstate_t m; + memset(&m, 0, sizeof(m)); + R_Mesh_TextureState(&m); + GL_Color(1, 1, 1, 1); + qglColorMask(0, 0, 0, 0); + qglDisable(GL_BLEND); + qglDepthMask(0); + qglDepthFunc(GL_LESS); + qglClearStencil(0); + qglClear(GL_STENCIL_BUFFER_BIT); + qglEnable(GL_STENCIL_TEST); + qglStencilOp(GL_ZERO, GL_KEEP, GL_KEEP); + qglStencilFunc(GL_NOTEQUAL, 0, 0xFF); + qglDisable(GL_CULL_FACE); + qglDisable(GL_DEPTH_TEST); + r_shadowstage = SHADOWSTAGE_ERASESTENCIL; +} + +void R_Shadow_Stage_End(void) +{ // attempt to restore state to what Mesh_State thinks it is qglDisable(GL_BLEND); qglBlendFunc(GL_ONE, GL_ZERO); @@ -494,31 +523,25 @@ void R_Shadow_Stage_End(void) qglDisable(GL_STENCIL_TEST); qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); qglStencilFunc(GL_ALWAYS, 0, 0xFF); + qglEnable(GL_CULL_FACE); + qglEnable(GL_DEPTH_TEST); + r_shadowstage = SHADOWSTAGE_NONE; } -void R_Shadow_GenTexCoords_Attenuation2D(float *out, int numverts, const float *vertex, const float *svectors, const float *tvectors, const vec3_t relativelightorigin, float lightradius) +void R_Shadow_GenTexCoords_Attenuation2D1D(float *out2d, float *out1d, int numverts, const float *vertex, const float *svectors, const float *tvectors, const float *normals, const vec3_t relativelightorigin, float lightradius) { int i; float lightvec[3], iradius; iradius = 0.5f / lightradius; - for (i = 0;i < numverts;i++, vertex += 4, svectors += 4, tvectors += 4, out += 4) + for (i = 0;i < numverts;i++, vertex += 4, svectors += 4, tvectors += 4, normals += 4, out2d += 4, out1d += 4) { VectorSubtract(vertex, relativelightorigin, lightvec); - out[0] = 0.5f + DotProduct(svectors, lightvec) * iradius; - out[1] = 0.5f + DotProduct(tvectors, lightvec) * iradius; - } -} - -void R_Shadow_GenTexCoords_Attenuation1D(float *out, int numverts, const float *vertex, const float *normals, const vec3_t relativelightorigin, float lightradius) -{ - int i; - float lightvec[3], iradius; - iradius = 0.5f / lightradius; - for (i = 0;i < numverts;i++, vertex += 4, normals += 4, out += 4) - { - VectorSubtract(vertex, relativelightorigin, lightvec); - out[0] = 0.5f + DotProduct(normals, lightvec) * iradius; - out[1] = 0.5f; + out2d[0] = 0.5f + DotProduct(svectors, lightvec) * iradius; + out2d[1] = 0.5f + DotProduct(tvectors, lightvec) * iradius; + out2d[2] = 0; + out1d[0] = 0.5f + DotProduct(normals, lightvec) * iradius; + out1d[1] = 0.5f; + out1d[2] = 0; } } @@ -530,40 +553,16 @@ void R_Shadow_GenTexCoords_Diffuse_Attenuation3D(float *out, int numverts, const for (i = 0;i < numverts;i++, vertex += 4, svectors += 4, tvectors += 4, normals += 4, out += 4) { VectorSubtract(vertex, relativelightorigin, lightvec); - if (r_shadow6.integer != 0) - { - VectorClear(lightvec); - if (r_shadow6.integer > 0) - lightvec[(r_shadow6.integer - 1) % 3] = 64; - else - lightvec[((-r_shadow6.integer) - 1) % 3] = -64; - } - if (r_shadow4.integer & 8) - lightvec[0] = -lightvec[0]; - if (r_shadow4.integer & 16) - lightvec[1] = -lightvec[1]; - if (r_shadow4.integer & 32) - lightvec[2] = -lightvec[2]; - if (r_shadow4.integer & 1) - out[0] = 0.5f - DotProduct(svectors, lightvec) * iradius; - else - out[0] = 0.5f + DotProduct(svectors, lightvec) * iradius; - if (r_shadow4.integer & 2) - out[1] = 0.5f - DotProduct(tvectors, lightvec) * iradius; - else - out[2] = 0.5f + DotProduct(tvectors, lightvec) * iradius; - if (r_shadow4.integer & 4) - out[2] = 0.5f - DotProduct(normals, lightvec) * iradius; - else - out[2] = 0.5f + DotProduct(normals, lightvec) * iradius; + out[0] = 0.5f + DotProduct(svectors, lightvec) * iradius; + out[1] = 0.5f + DotProduct(tvectors, lightvec) * iradius; + out[2] = 0.5f + DotProduct(normals, lightvec) * iradius; } } -void R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(float *out, int numverts, const float *vertex, const float *svectors, const float *tvectors, const float *normals, const vec3_t relativelightorigin, float lightradius) +void R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(float *out, int numverts, const float *vertex, const float *svectors, const float *tvectors, const float *normals, const vec3_t relativelightorigin) { int i; float lightdir[3], iradius; - iradius = 0.5f / lightradius; for (i = 0;i < numverts;i++, vertex += 4, svectors += 4, tvectors += 4, normals += 4, out += 4) { VectorSubtract(vertex, relativelightorigin, lightdir); @@ -595,11 +594,10 @@ void R_Shadow_GenTexCoords_Specular_Attenuation3D(float *out, int numverts, cons } } -void R_Shadow_GenTexCoords_Specular_NormalCubeMap(float *out, int numverts, const float *vertex, const float *svectors, const float *tvectors, const float *normals, const vec3_t relativelightorigin, const vec3_t relativeeyeorigin, float lightradius) +void R_Shadow_GenTexCoords_Specular_NormalCubeMap(float *out, int numverts, const float *vertex, const float *svectors, const float *tvectors, const float *normals, const vec3_t relativelightorigin, const vec3_t relativeeyeorigin) { int i; float lightdir[3], eyedir[3], halfdir[3], lightdirlen, ilen, iradius; - iradius = 0.5f / lightradius; for (i = 0;i < numverts;i++, vertex += 4, svectors += 4, tvectors += 4, normals += 4, out += 4) { VectorSubtract(vertex, relativelightorigin, lightdir); @@ -617,61 +615,155 @@ void R_Shadow_GenTexCoords_Specular_NormalCubeMap(float *out, int numverts, cons void R_Shadow_GenTexCoords_LightCubeMap(float *out, int numverts, const float *vertex, const vec3_t relativelightorigin) { int i; + // FIXME: this needs to be written + // this code assumes the vertices are in worldspace (a false assumption) for (i = 0;i < numverts;i++, vertex += 4, out += 4) VectorSubtract(vertex, relativelightorigin, out); } void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements, const float *svectors, const float *tvectors, const float *normals, const float *texcoords, const float *relativelightorigin, const float *relativeeyeorigin, float lightradius, const float *lightcolor, rtexture_t *basetexture, rtexture_t *glosstexture, rtexture_t *bumptexture, rtexture_t *lightcubemap) { - float f; + int mult; + float scale, colorscale; rmeshstate_t m; memset(&m, 0, sizeof(m)); if (!bumptexture) bumptexture = r_shadow_blankbumptexture; - f = 1.0f / r_shadow3.value; + // colorscale accounts for how much we multiply the brightness during combine if (r_light_quality.integer == 1) { - // 4 texture 3D path, two pass - GL_Color(1,1,1,1); - //lightcolor[0] * f, lightcolor[1] * f, lightcolor[2] * f, 1); - memcpy(varray_texcoord[0], texcoords, numverts * sizeof(float[4])); - memcpy(varray_texcoord[2], texcoords, numverts * sizeof(float[4])); - if (r_light_gloss.integer != 2) + if (r_textureunits.integer >= 4) + colorscale = r_colorscale * 0.125f / r_shadow3.value; + else + colorscale = r_colorscale * 0.5f / r_shadow3.value; + } + else + colorscale = r_colorscale * 0.5f / r_shadow3.value; + // limit mult to 64 for sanity sake + for (mult = 1, scale = ixtable[mult];mult < 64 && (lightcolor[0] * scale * colorscale > 1 || lightcolor[1] * scale * colorscale > 1 || lightcolor[2] * scale * colorscale > 1);mult++, scale = ixtable[mult]); + colorscale *= scale; + for (;mult > 0;mult--) + { + if (r_light_quality.integer == 1) { - m.tex[0] = R_GetTexture(bumptexture); - m.tex3d[1] = R_GetTexture(r_shadow_normalsattenuationtexture); - m.tex[2] = R_GetTexture(basetexture); - m.texcubemap[3] = R_GetTexture(lightcubemap); - m.texcombinergb[0] = GL_REPLACE; - m.texcombinergb[1] = GL_DOT3_RGB_ARB; - m.texcombinergb[2] = GL_MODULATE; - m.texcombinergb[3] = GL_MODULATE; - m.texrgbscale[2] = 2; - R_Mesh_TextureState(&m); - R_Shadow_GenTexCoords_Diffuse_Attenuation3D(varray_texcoord[1], numverts, varray_vertex, svectors, tvectors, normals, relativelightorigin, lightradius); - if (m.texcubemap[3]) - R_Shadow_GenTexCoords_LightCubeMap(varray_texcoord[3], numverts, varray_vertex, relativelightorigin); - R_Mesh_Draw(numverts, numtriangles, elements); + if (r_textureunits.integer >= 4) + { + // 4 texture 3D path, two pass + m.tex[0] = R_GetTexture(bumptexture); + m.tex3d[1] = R_GetTexture(r_shadow_normalsattenuationtexture); + m.tex[2] = R_GetTexture(basetexture); + m.texcubemap[3] = R_GetTexture(lightcubemap); + m.tex[3] = R_GetTexture(r_notexture); + m.texcombinergb[0] = GL_REPLACE; + m.texcombinergb[1] = GL_DOT3_RGB_ARB; + m.texcombinergb[2] = GL_MODULATE; + m.texcombinergb[3] = GL_MODULATE; + m.texrgbscale[1] = 2; + m.texrgbscale[3] = 4; + R_Mesh_TextureState(&m); + GL_Color(lightcolor[0] * colorscale, lightcolor[1] * colorscale, lightcolor[2] * colorscale, 1); + memcpy(varray_texcoord[0], texcoords, numverts * sizeof(float[4])); + memcpy(varray_texcoord[2], texcoords, numverts * sizeof(float[4])); + if (lightcubemap) + R_Shadow_GenTexCoords_LightCubeMap(varray_texcoord[3], numverts, varray_vertex, relativelightorigin); + else + { + qglActiveTexture(GL_TEXTURE3_ARB); + qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB); + } + R_Shadow_GenTexCoords_Diffuse_Attenuation3D(varray_texcoord[1], numverts, varray_vertex, svectors, tvectors, normals, relativelightorigin, lightradius); + R_Mesh_Draw(numverts, numtriangles, elements); + if (!lightcubemap) + { + qglActiveTexture(GL_TEXTURE3_ARB); + qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); + } + if (r_light_gloss.integer && glosstexture) + { + m.tex[2] = R_GetTexture(glosstexture); + R_Mesh_TextureState(&m); + R_Shadow_GenTexCoords_Specular_Attenuation3D(varray_texcoord[1], numverts, varray_vertex, svectors, tvectors, normals, relativelightorigin, relativeeyeorigin, lightradius); + if (!lightcubemap) + { + qglActiveTexture(GL_TEXTURE3_ARB); + qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB); + } + R_Mesh_Draw(numverts, numtriangles, elements); + if (!lightcubemap) + { + qglActiveTexture(GL_TEXTURE3_ARB); + qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); + } + } + } + else + { + // 2 texture 3D path, four pass + m.tex[0] = R_GetTexture(bumptexture); + m.tex3d[1] = R_GetTexture(r_shadow_normalsattenuationtexture); + m.texcombinergb[1] = GL_DOT3_RGBA_ARB; + m.texalphascale[1] = 2; + R_Mesh_TextureState(&m); + qglColorMask(0,0,0,1); + qglDisable(GL_BLEND); + GL_Color(1,1,1,1); + memcpy(varray_texcoord[0], texcoords, numverts * sizeof(float[4])); + R_Shadow_GenTexCoords_Diffuse_Attenuation3D(varray_texcoord[1], numverts, varray_vertex, svectors, tvectors, normals, relativelightorigin, lightradius); + R_Mesh_Draw(numverts, numtriangles, elements); + + m.tex[0] = R_GetTexture(basetexture); + m.tex3d[1] = 0; + m.texcubemap[1] = R_GetTexture(lightcubemap); + m.texcombinergb[1] = GL_MODULATE; + m.texrgbscale[1] = 1; + m.texalphascale[1] = 1; + R_Mesh_TextureState(&m); + qglColorMask(1,1,1,1); + qglBlendFunc(GL_DST_ALPHA, GL_ONE); + qglEnable(GL_BLEND); + GL_Color(lightcolor[0] * colorscale, lightcolor[1] * colorscale, lightcolor[2] * colorscale, 1); + if (lightcubemap) + R_Shadow_GenTexCoords_LightCubeMap(varray_texcoord[1], numverts, varray_vertex, relativelightorigin); + R_Mesh_Draw(numverts, numtriangles, elements); + } } - if (r_light_gloss.integer && glosstexture) + else { + // 2 texture no3D path, six pass + m.tex[0] = R_GetTexture(r_shadow_attenuation2dtexture); + m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture); + R_Mesh_TextureState(&m); + qglColorMask(0,0,0,1); + qglDisable(GL_BLEND); + GL_Color(1,1,1,1); + R_Shadow_GenTexCoords_Attenuation2D1D(varray_texcoord[0], varray_texcoord[1], numverts, varray_vertex, svectors, tvectors, normals, relativelightorigin, lightradius); + R_Mesh_Draw(numverts, numtriangles, elements); + m.tex[0] = R_GetTexture(bumptexture); - m.tex3d[1] = R_GetTexture(r_shadow_normalsattenuationtexture); - m.tex[2] = R_GetTexture(glosstexture); - m.texcubemap[3] = R_GetTexture(lightcubemap); - m.texcombinergb[0] = GL_REPLACE; - m.texcombinergb[1] = GL_DOT3_RGB_ARB; - m.texcombinergb[2] = GL_MODULATE; - m.texcombinergb[3] = GL_MODULATE; - m.texrgbscale[2] = 2; + m.tex[1] = 0; + m.texcubemap[1] = R_GetTexture(r_shadow_normalscubetexture); + m.texcombinergb[1] = GL_DOT3_RGBA_ARB; + m.texalphascale[1] = 2; R_Mesh_TextureState(&m); - R_Shadow_GenTexCoords_Specular_Attenuation3D(varray_texcoord[1], numverts, varray_vertex, svectors, tvectors, normals, relativelightorigin, relativeeyeorigin, lightradius); + qglBlendFunc(GL_DST_ALPHA, GL_ZERO); + qglEnable(GL_BLEND); + memcpy(varray_texcoord[0], texcoords, numverts * sizeof(float[4])); + R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord[1], numverts, varray_vertex, svectors, tvectors, normals, relativelightorigin); + R_Mesh_Draw(numverts, numtriangles, elements); + + m.tex[0] = R_GetTexture(basetexture); + m.texcubemap[1] = R_GetTexture(lightcubemap); + m.texcombinergb[1] = GL_MODULATE; + m.texrgbscale[1] = 1; + m.texalphascale[1] = 1; + R_Mesh_TextureState(&m); + qglColorMask(1,1,1,1); + qglBlendFunc(GL_DST_ALPHA, GL_ONE); + GL_Color(lightcolor[0] * colorscale, lightcolor[1] * colorscale, lightcolor[2] * colorscale, 1); + if (lightcubemap) + R_Shadow_GenTexCoords_LightCubeMap(varray_texcoord[1], numverts, varray_vertex, relativelightorigin); R_Mesh_Draw(numverts, numtriangles, elements); } } - else - { - //R_Mesh_TextureState(&m); - } } diff --git a/r_shadow.h b/r_shadow.h index e2dedad6..01ae581c 100644 --- a/r_shadow.h +++ b/r_shadow.h @@ -8,14 +8,15 @@ extern cvar_t r_light_gloss; extern cvar_t r_light_debuglight; void R_Shadow_Init(void); -void R_Shadow_Volume(int numverts, int numtris, float *vertex, int *elements, int *neighbors, vec3_t relativelightorigin, float lightradius, float projectdistance, int visiblevolume); +void R_Shadow_Volume(int numverts, int numtris, float *vertex, int *elements, int *neighbors, vec3_t relativelightorigin, float lightradius, float projectdistance); void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements, const float *svectors, const float *tvectors, const float *normals, const float *texcoords, const float *relativelightorigin, const float *relativeeyeorigin, float lightradius, const float *lightcolor, rtexture_t *basetexture, rtexture_t *glosstexture, rtexture_t *bumptexture, rtexture_t *lightcubemap); void R_Shadow_ClearStencil(void); -void R_Shadow_RenderVolume(int numverts, int numtris, int *elements, int visiblevolume); +void R_Shadow_RenderVolume(int numverts, int numtris, int *elements); void R_Shadow_Stage_Begin(void); void R_Shadow_Stage_ShadowVolumes(void); void R_Shadow_Stage_Light(void); +void R_Shadow_Stage_EraseShadowVolumes(void); void R_Shadow_Stage_End(void); #endif diff --git a/render.h b/render.h index 7ca8cfc7..5b2c7126 100644 --- a/render.h +++ b/render.h @@ -108,7 +108,7 @@ void R_InitSky (qbyte *src, int bytesperpixel); // called at level load void R_NewMap (void); -void R_DrawWorld(entity_render_t *ent, int baselighting); +void R_DrawWorld(entity_render_t *ent); void R_DrawParticles(void); void R_DrawExplosions(void); @@ -120,8 +120,10 @@ void R_DrawExplosions(void); //#define PARANOID 1 -int R_CullBox(const vec3_t emins, const vec3_t emaxs); -int R_NotCulledBox(const vec3_t emins, const vec3_t emaxs); +int R_CullBox(const vec3_t mins, const vec3_t maxs); +int PVS_CullBox(const vec3_t mins, const vec3_t maxs); +int R_CullSphere(const vec3_t origin, vec_t radius); +int PVS_CullSphere(const vec3_t origin, vec_t radius); extern qboolean fogenabled; extern vec3_t fogcolor; diff --git a/vid_glx.c b/vid_glx.c index 542690a6..22075cb4 100644 --- a/vid_glx.c +++ b/vid_glx.c @@ -654,9 +654,11 @@ void VID_BuildGLXAttrib(int *attrib, int stencil, int gamma) *attrib++ = GLX_BLUE_SIZE;*attrib++ = 1; *attrib++ = GLX_DOUBLEBUFFER; *attrib++ = GLX_DEPTH_SIZE;*attrib++ = 1; + // if stencil is enabled, ask for alpha too if (stencil) { *attrib++ = GLX_STENCIL_SIZE;*attrib++ = 8; + *attrib++ = GLX_ALPHA_SIZE;*attrib++ = 1; } if (gamma) { diff --git a/vid_wgl.c b/vid_wgl.c index bdc0076f..969cfcc0 100644 --- a/vid_wgl.c +++ b/vid_wgl.c @@ -809,14 +809,21 @@ int VID_InitMode (int fullscreen, int width, int height, int bpp, int stencil) HGLRC baseRC; int CenterX, CenterY; const char *gldrivername; - + if (vid_initialized) Sys_Error("VID_InitMode called when video is already initialised\n"); + // if stencil is enabled, ask for alpha too if (stencil) + { pfd.cStencilBits = 8; + pfd.cAlphaBits = 8; + } else + { pfd.cStencilBits = 0; + pfd.cAlphaBits = 0; + } gldrivername = "opengl32.dll"; i = COM_CheckParm("-gl_driver"); -- 2.39.2