X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=gl_rsurf.c;h=af6060e0539585dd2683106f5483cbb17094b975;hb=b4b9ae3ea1a4d1252055e9a9969f4048ea3c3182;hp=cabf4bbf5d8f6e606b6839d03772a5465edb0749;hpb=b2a1ec8cb2a845e6440d0dbc5a9a84464f3deecc;p=xonotic%2Fdarkplaces.git diff --git a/gl_rsurf.c b/gl_rsurf.c index cabf4bbf..af6060e0 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -782,33 +782,37 @@ static void RSurfShader_Water_Callback(const void *calldata1, int calldata2) const entity_render_t *ent = calldata1; const msurface_t *surf = ent->model->brushq1.surfaces + calldata2; rmeshstate_t m; - float alpha; + float currentalpha; float modelorg[3]; texture_t *texture; float args[4] = {0.05f,0,0,0.04f}; + int rendertype; R_Mesh_Matrix(&ent->matrix); Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg); texture = surf->texinfo->texture->currentframe; - alpha = texture->currentalpha; - if (texture->rendertype == SURFRENDER_ADD) + currentalpha = texture->currentalpha; + if (ent->effects & EF_ADDITIVE) { + rendertype = SURFRENDER_ADD; GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); GL_DepthMask(false); } - else if (texture->rendertype == SURFRENDER_ALPHA) + else if (currentalpha < 1 || texture->skin.fog != NULL) { + rendertype = SURFRENDER_ALPHA; GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GL_DepthMask(false); } else { + rendertype = SURFRENDER_OPAQUE; GL_BlendFunc(GL_ONE, GL_ZERO); GL_DepthMask(true); } GL_DepthTest(true); - GL_Color(1, 1, 1, alpha); + GL_Color(1, 1, 1, currentalpha); memset(&m, 0, sizeof(m)); m.pointer_vertex = surf->mesh.data_vertex3f; if (gl_textureshader && r_watershader.value && !fogenabled) @@ -841,12 +845,8 @@ static void RSurfShader_Water_Callback(const void *calldata1, int calldata2) } else { - if (fogenabled) - { - R_FillColors(varray_color4f, surf->mesh.num_vertices, 1, 1, 1, alpha); - RSurf_FogColors_Vertex3f_Color4f(surf->mesh.data_vertex3f, varray_color4f, 1, surf->mesh.num_vertices, modelorg); - m.pointer_color = varray_color4f; - } + RSurf_FoggedColors_Vertex3f_Color4f(surf->mesh.data_vertex3f, varray_color4f, 1, 1, 1, currentalpha, 1, surf->mesh.num_vertices, modelorg); + m.pointer_color = varray_color4f; m.tex[0] = R_GetTexture(texture->skin.base); m.pointer_texcoord[0] = surf->mesh.data_texcoordtexture2f; if (r_waterscroll.value) @@ -855,16 +855,14 @@ static void RSurfShader_Water_Callback(const void *calldata1, int calldata2) Matrix4x4_CreateTranslate(&m.texmatrix[0], sin(cl.time) * 0.025 * r_waterscroll.value, sin(cl.time * 0.8f) * 0.025 * r_waterscroll.value, 0); } R_Mesh_State(&m); - GL_LockArrays(0, surf->mesh.num_vertices); R_Mesh_Draw(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_element3i); GL_LockArrays(0, 0); - - if (fogenabled && texture->rendertype != SURFRENDER_ADD) + if (fogenabled && rendertype != SURFRENDER_ADD) { GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); GL_DepthMask(false); - RSurf_FogPassColors_Vertex3f_Color4f(surf->mesh.data_vertex3f, varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], alpha, 1, surf->mesh.num_vertices, modelorg); + RSurf_FogPassColors_Vertex3f_Color4f(surf->mesh.data_vertex3f, varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], currentalpha, 1, surf->mesh.num_vertices, modelorg); m.tex[0] = R_GetTexture(texture->skin.fog); R_Mesh_State(&m); GL_LockArrays(0, surf->mesh.num_vertices); @@ -874,120 +872,103 @@ static void RSurfShader_Water_Callback(const void *calldata1, int calldata2) } } -static void RSurfShader_Water(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain) -{ - const msurface_t *surf; - msurface_t **chain; - vec3_t center; - if (texture->rendertype != SURFRENDER_OPAQUE) - { - for (chain = surfchain;(surf = *chain) != NULL;chain++) - { - if (surf->visframe == r_framecount) - { - Matrix4x4_Transform(&ent->matrix, surf->poly_center, center); - R_MeshQueue_AddTransparent(center, RSurfShader_Water_Callback, ent, surf - ent->model->brushq1.surfaces); - } - } - } - else - for (chain = surfchain;(surf = *chain) != NULL;chain++) - if (surf->visframe == r_framecount) - RSurfShader_Water_Callback(ent, surf - ent->model->brushq1.surfaces); -} - -static void RSurfShader_Wall_Pass_BaseVertex(const entity_render_t *ent, const msurface_t *surf, const texture_t *texture, int rendertype, float currentalpha) +static void RSurfShader_Wall_Vertex_Callback(const void *calldata1, int calldata2) { + const entity_render_t *ent = calldata1; + const msurface_t *surf = ent->model->brushq1.surfaces + calldata2; + int rendertype; + float currentalpha; + texture_t *texture; float base, colorscale; rmeshstate_t m; - float modelorg[3]; + vec3_t modelorg; Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg); - memset(&m, 0, sizeof(m)); - if (rendertype == SURFRENDER_ADD) + R_Mesh_Matrix(&ent->matrix); + + texture = surf->texinfo->texture; + if (texture->animated) + texture = texture->anim_frames[ent->frame != 0][(texture->anim_total[ent->frame != 0] >= 2) ? ((int) (cl.time * 5.0f) % texture->anim_total[ent->frame != 0]) : 0]; + + currentalpha = ent->alpha; + base = ent->effects & EF_FULLBRIGHT ? 2.0f : r_ambient.value * (1.0f / 64.0f); + GL_DepthTest(true); + if (ent->effects & EF_ADDITIVE) { + rendertype = SURFRENDER_ADD; GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); GL_DepthMask(false); } - else if (rendertype == SURFRENDER_ALPHA) + else if (currentalpha < 1 || texture->skin.fog != NULL) { + rendertype = SURFRENDER_ALPHA; GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GL_DepthMask(false); } else { + rendertype = SURFRENDER_OPAQUE; GL_BlendFunc(GL_ONE, GL_ZERO); GL_DepthMask(true); } - m.tex[0] = R_GetTexture(texture->skin.base); - colorscale = 1; - if (gl_combine.integer) + { - m.texrgbscale[0] = 4; - colorscale *= 0.25f; + memset(&m, 0, sizeof(m)); + m.tex[0] = R_GetTexture(texture->skin.base); + colorscale = 1; + if (gl_combine.integer) + { + m.texrgbscale[0] = 4; + colorscale *= 0.25f; + } + m.pointer_color = varray_color4f; + m.pointer_vertex = surf->mesh.data_vertex3f; + m.pointer_texcoord[0] = surf->mesh.data_texcoordtexture2f; + R_Mesh_State(&m); + R_FillColors(varray_color4f, surf->mesh.num_vertices, base, base, base, currentalpha); + if (!(ent->effects & EF_FULLBRIGHT)) + { + if (surf->dlightframe == r_framecount) + RSurf_LightSeparate_Vertex3f_Color4f(&ent->inversematrix, surf->dlightbits, surf->mesh.num_vertices, surf->mesh.data_vertex3f, varray_color4f, 1); + if (surf->flags & SURF_LIGHTMAP) + RSurf_AddLightmapToVertexColors_Color4f(surf->mesh.data_lightmapoffsets, varray_color4f,surf->mesh.num_vertices, surf->samples, ((surf->extents[0]>>4)+1)*((surf->extents[1]>>4)+1)*3, surf->styles); + } + RSurf_FogColors_Vertex3f_Color4f(surf->mesh.data_vertex3f, varray_color4f, colorscale, surf->mesh.num_vertices, modelorg); + GL_LockArrays(0, surf->mesh.num_vertices); + R_Mesh_Draw(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_element3i); + GL_LockArrays(0, 0); } - base = ent->effects & EF_FULLBRIGHT ? 2.0f : r_ambient.value * (1.0f / 64.0f); - GL_DepthTest(true); - - m.pointer_color = varray_color4f; - m.pointer_vertex = surf->mesh.data_vertex3f; - m.pointer_texcoord[0] = surf->mesh.data_texcoordtexture2f; - R_Mesh_State(&m); - R_FillColors(varray_color4f, surf->mesh.num_vertices, base, base, base, currentalpha); - if (!(ent->effects & EF_FULLBRIGHT)) + if (texture->skin.glow) { - if (surf->dlightframe == r_framecount) - RSurf_LightSeparate_Vertex3f_Color4f(&ent->inversematrix, surf->dlightbits, surf->mesh.num_vertices, surf->mesh.data_vertex3f, varray_color4f, 1); - if (surf->flags & SURF_LIGHTMAP) - RSurf_AddLightmapToVertexColors_Color4f(surf->mesh.data_lightmapoffsets, varray_color4f,surf->mesh.num_vertices, surf->samples, ((surf->extents[0]>>4)+1)*((surf->extents[1]>>4)+1)*3, surf->styles); + memset(&m, 0, sizeof(m)); + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + GL_DepthMask(false); + m.pointer_color = varray_color4f; + m.tex[0] = R_GetTexture(texture->skin.glow); + m.pointer_vertex = surf->mesh.data_vertex3f; + if (m.tex[0]) + m.pointer_texcoord[0] = surf->mesh.data_texcoordtexture2f; + R_Mesh_State(&m); + RSurf_FoggedColors_Vertex3f_Color4f(surf->mesh.data_vertex3f, varray_color4f, 1, 1, 1, currentalpha, 1, surf->mesh.num_vertices, modelorg); + GL_LockArrays(0, surf->mesh.num_vertices); + R_Mesh_Draw(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_element3i); + GL_LockArrays(0, 0); + } + if (fogenabled && rendertype != SURFRENDER_ADD) + { + memset(&m, 0, sizeof(m)); + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + GL_DepthMask(false); + m.pointer_color = varray_color4f; + m.tex[0] = R_GetTexture(texture->skin.fog); + m.pointer_vertex = surf->mesh.data_vertex3f; + if (m.tex[0]) + m.pointer_texcoord[0] = surf->mesh.data_texcoordtexture2f; + R_Mesh_State(&m); + RSurf_FogPassColors_Vertex3f_Color4f(surf->mesh.data_vertex3f, varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], currentalpha, 1, surf->mesh.num_vertices, modelorg); + GL_LockArrays(0, surf->mesh.num_vertices); + R_Mesh_Draw(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_element3i); + GL_LockArrays(0, 0); } - RSurf_FogColors_Vertex3f_Color4f(surf->mesh.data_vertex3f, varray_color4f, colorscale, surf->mesh.num_vertices, modelorg); - GL_LockArrays(0, surf->mesh.num_vertices); - R_Mesh_Draw(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_element3i); - GL_LockArrays(0, 0); -} - -static void RSurfShader_Wall_Pass_Glow(const entity_render_t *ent, const msurface_t *surf, const texture_t *texture, int rendertype, float currentalpha) -{ - rmeshstate_t m; - float modelorg[3]; - Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg); - memset(&m, 0, sizeof(m)); - GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); - GL_DepthMask(false); - GL_DepthTest(true); - m.pointer_color = varray_color4f; - m.tex[0] = R_GetTexture(texture->skin.glow); - - m.pointer_vertex = surf->mesh.data_vertex3f; - if (m.tex[0]) - m.pointer_texcoord[0] = surf->mesh.data_texcoordtexture2f; - R_Mesh_State(&m); - RSurf_FoggedColors_Vertex3f_Color4f(surf->mesh.data_vertex3f, varray_color4f, 1, 1, 1, currentalpha, 1, surf->mesh.num_vertices, modelorg); - GL_LockArrays(0, surf->mesh.num_vertices); - R_Mesh_Draw(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_element3i); - GL_LockArrays(0, 0); -} - -static void RSurfShader_Wall_Pass_Fog(const entity_render_t *ent, const msurface_t *surf, const texture_t *texture, int rendertype, float currentalpha) -{ - rmeshstate_t m; - float modelorg[3]; - Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg); - memset(&m, 0, sizeof(m)); - GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); - GL_DepthMask(false); - GL_DepthTest(true); - m.pointer_color = varray_color4f; - m.tex[0] = R_GetTexture(texture->skin.fog); - - m.pointer_vertex = surf->mesh.data_vertex3f; - if (m.tex[0]) - m.pointer_texcoord[0] = surf->mesh.data_texcoordtexture2f; - R_Mesh_State(&m); - RSurf_FogPassColors_Vertex3f_Color4f(surf->mesh.data_vertex3f, varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], currentalpha, 1, surf->mesh.num_vertices, modelorg); - GL_LockArrays(0, surf->mesh.num_vertices); - R_Mesh_Draw(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_element3i); - GL_LockArrays(0, 0); } static void RSurfShader_OpaqueWall_Pass_BaseCombine_TextureLightmapDetailGlow(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain) @@ -1290,130 +1271,97 @@ static void RSurfShader_OpaqueWall_Pass_BaseLightmapOnly(const entity_render_t * } } -static void RSurfShader_Wall_Vertex_Callback(const void *calldata1, int calldata2) -{ - const entity_render_t *ent = calldata1; - const msurface_t *surf = ent->model->brushq1.surfaces + calldata2; - int rendertype; - float currentalpha; - texture_t *texture; - R_Mesh_Matrix(&ent->matrix); - - texture = surf->texinfo->texture; - if (texture->animated) - texture = texture->anim_frames[ent->frame != 0][(texture->anim_total[ent->frame != 0] >= 2) ? ((int) (cl.time * 5.0f) % texture->anim_total[ent->frame != 0]) : 0]; - - currentalpha = ent->alpha; - if (ent->effects & EF_ADDITIVE) - rendertype = SURFRENDER_ADD; - else if (currentalpha < 1 || texture->skin.fog != NULL) - rendertype = SURFRENDER_ALPHA; - else - rendertype = SURFRENDER_OPAQUE; - - RSurfShader_Wall_Pass_BaseVertex(ent, surf, texture, rendertype, currentalpha); - if (texture->skin.glow) - RSurfShader_Wall_Pass_Glow(ent, surf, texture, rendertype, currentalpha); - if (fogenabled) - RSurfShader_Wall_Pass_Fog(ent, surf, texture, rendertype, currentalpha); -} - -static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain) +static void R_DrawSurfaceChain(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain) { const msurface_t *surf; msurface_t **chain; vec3_t center; - if (texture->rendertype != SURFRENDER_OPAQUE) + if (texture->flags & SURF_LIGHTMAP) { - // transparent vertex shaded from lightmap - for (chain = surfchain;(surf = *chain) != NULL;chain++) + if (gl_lightmaps.integer) { - if (surf->visframe == r_framecount) + RSurfShader_OpaqueWall_Pass_BaseLightmapOnly(ent, texture, surfchain); + if (fogenabled) + RSurfShader_OpaqueWall_Pass_Fog(ent, texture, surfchain); + } + else if (texture->rendertype != SURFRENDER_OPAQUE) + { + // transparent vertex shaded from lightmap + for (chain = surfchain;(surf = *chain) != NULL;chain++) { - Matrix4x4_Transform(&ent->matrix, surf->poly_center, center); - R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Vertex_Callback, ent, surf - ent->model->brushq1.surfaces); + if (surf->visframe == r_framecount) + { + Matrix4x4_Transform(&ent->matrix, surf->poly_center, center); + R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Vertex_Callback, ent, surf - ent->model->brushq1.surfaces); + } } } - } - else if (ent->effects & EF_FULLBRIGHT) - { - RSurfShader_OpaqueWall_Pass_BaseTexture(ent, texture, surfchain); - if (r_detailtextures.integer) - RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, surfchain); - if (texture->skin.glow) - RSurfShader_OpaqueWall_Pass_Glow(ent, texture, surfchain); - if (fogenabled) - RSurfShader_OpaqueWall_Pass_Fog(ent, texture, surfchain); - } - /* - // opaque base lighting - else if (r_shadow_realtime_world.integer && r_shadow_realtime_world_lightmaps.value <= 0) - { - if (r_ambient.value > 0) + else if (ent->effects & EF_FULLBRIGHT || r_fullbright.integer) + { + RSurfShader_OpaqueWall_Pass_BaseTexture(ent, texture, surfchain); + if (r_detailtextures.integer) + RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, surfchain); + if (texture->skin.glow) + RSurfShader_OpaqueWall_Pass_Glow(ent, texture, surfchain); + if (fogenabled) + RSurfShader_OpaqueWall_Pass_Fog(ent, texture, surfchain); + } + else if (r_textureunits.integer >= 4 && gl_combine.integer && r_detailtextures.integer) + { + RSurfShader_OpaqueWall_Pass_BaseCombine_TextureLightmapDetailGlow(ent, texture, surfchain); + if (fogenabled) + RSurfShader_OpaqueWall_Pass_Fog(ent, texture, surfchain); + } + else if (r_textureunits.integer >= 3 && gl_combine.integer && r_detailtextures.integer) + { + RSurfShader_OpaqueWall_Pass_BaseCombine_TextureLightmapDetail(ent, texture, surfchain); + if (texture->skin.glow) + RSurfShader_OpaqueWall_Pass_Glow(ent, texture, surfchain); + if (fogenabled) + RSurfShader_OpaqueWall_Pass_Fog(ent, texture, surfchain); + } + else if (r_textureunits.integer >= 2 && gl_combine.integer) { + RSurfShader_OpaqueWall_Pass_BaseCombine_TextureLightmap(ent, texture, surfchain); + if (r_detailtextures.integer) + RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, surfchain); + if (texture->skin.glow) + RSurfShader_OpaqueWall_Pass_Glow(ent, texture, surfchain); + if (fogenabled) + RSurfShader_OpaqueWall_Pass_Fog(ent, texture, surfchain); } else - RSurfShader_OpaqueWall_Pass_OpaqueGlow(ent, texture, surfchain); - if (fogenabled) - RSurfShader_OpaqueWall_Pass_Fog(ent, texture, surfchain); - } - */ - // opaque lightmapped - else if (r_textureunits.integer >= 4 && gl_combine.integer && r_detailtextures.integer && !gl_lightmaps.integer) - { - RSurfShader_OpaqueWall_Pass_BaseCombine_TextureLightmapDetailGlow(ent, texture, surfchain); - if (fogenabled) - RSurfShader_OpaqueWall_Pass_Fog(ent, texture, surfchain); - } - else if (r_textureunits.integer >= 3 && gl_combine.integer && r_detailtextures.integer && !gl_lightmaps.integer) - { - RSurfShader_OpaqueWall_Pass_BaseCombine_TextureLightmapDetail(ent, texture, surfchain); - if (texture->skin.glow) - RSurfShader_OpaqueWall_Pass_Glow(ent, texture, surfchain); - if (fogenabled) - RSurfShader_OpaqueWall_Pass_Fog(ent, texture, surfchain); - } - else if (r_textureunits.integer >= 2 && gl_combine.integer && !gl_lightmaps.integer) - { - RSurfShader_OpaqueWall_Pass_BaseCombine_TextureLightmap(ent, texture, surfchain); - if (r_detailtextures.integer) - RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, surfchain); - if (texture->skin.glow) - RSurfShader_OpaqueWall_Pass_Glow(ent, texture, surfchain); - if (fogenabled) - RSurfShader_OpaqueWall_Pass_Fog(ent, texture, surfchain); - } - else if (!gl_lightmaps.integer) - { - RSurfShader_OpaqueWall_Pass_BaseTexture(ent, texture, surfchain); - RSurfShader_OpaqueWall_Pass_BaseLightmap(ent, texture, surfchain); - if (r_detailtextures.integer) - RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, surfchain); - if (texture->skin.glow) - RSurfShader_OpaqueWall_Pass_Glow(ent, texture, surfchain); - if (fogenabled) - RSurfShader_OpaqueWall_Pass_Fog(ent, texture, surfchain); + { + RSurfShader_OpaqueWall_Pass_BaseTexture(ent, texture, surfchain); + RSurfShader_OpaqueWall_Pass_BaseLightmap(ent, texture, surfchain); + if (r_detailtextures.integer) + RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, surfchain); + if (texture->skin.glow) + RSurfShader_OpaqueWall_Pass_Glow(ent, texture, surfchain); + if (fogenabled) + RSurfShader_OpaqueWall_Pass_Fog(ent, texture, surfchain); + } } - else + else if (texture->flags & SURF_DRAWTURB) { - RSurfShader_OpaqueWall_Pass_BaseLightmapOnly(ent, texture, surfchain); - if (fogenabled) - RSurfShader_OpaqueWall_Pass_Fog(ent, texture, surfchain); + for (chain = surfchain;(surf = *chain) != NULL;chain++) + { + if (surf->visframe == r_framecount) + { + if (texture->rendertype == SURFRENDER_OPAQUE) + RSurfShader_Water_Callback(ent, surf - ent->model->brushq1.surfaces); + else + { + Matrix4x4_Transform(&ent->matrix, surf->poly_center, center); + R_MeshQueue_AddTransparent(center, RSurfShader_Water_Callback, ent, surf - ent->model->brushq1.surfaces); + } + } + } } + else if (texture->flags & SURF_DRAWSKY) + RSurfShader_Sky(ent, texture, surfchain); } -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] = -{ - &Cshader_wall_lightmap, - &Cshader_water, - &Cshader_sky -}; - void R_UpdateTextureInfo(entity_render_t *ent) { int i, texframe, alttextures; @@ -1511,16 +1459,20 @@ void R_PrepareSurfaces(entity_render_t *ent) } } -void R_DrawSurfaces(entity_render_t *ent, int type, msurface_t ***chains) +void R_DrawSurfaces(entity_render_t *ent, int flagsmask) { - int i; + int i, f; texture_t *t; - if (ent->model == NULL) + model_t *model = ent->model; + if (model == NULL) return; R_Mesh_Matrix(&ent->matrix); - for (i = 0, t = ent->model->brushq1.textures;i < ent->model->brushq1.numtextures;i++, t++) - if (t->shader->shaderfunc[type] && t->currentframe && chains[i] != NULL) - t->shader->shaderfunc[type](ent, t->currentframe, chains[i]); + for (i = 0, t = model->brushq1.textures;i < model->brushq1.numtextures;i++, t++) + { + f = t->flags & flagsmask; + if (f && t->currentframe && model->brushq1.pvstexturechains[i] != NULL) + R_DrawSurfaceChain(ent, t->currentframe, model->brushq1.pvstexturechains[i]); + } } static void R_DrawPortal_Callback(const void *calldata1, int calldata2) @@ -1807,8 +1759,8 @@ void R_DrawWorld(entity_render_t *ent) else { R_PrepareSurfaces(ent); - R_DrawSurfaces(ent, SHADERSTAGE_SKY, ent->model->brushq1.pvstexturechains); - R_DrawSurfaces(ent, SHADERSTAGE_NORMAL, ent->model->brushq1.pvstexturechains); + R_DrawSurfaces(ent, SURF_DRAWSKY); + R_DrawSurfaces(ent, SURF_DRAWTURB | SURF_LIGHTMAP); if (r_drawportals.integer) R_DrawPortals(ent); } @@ -1820,7 +1772,7 @@ void R_Model_Brush_DrawSky(entity_render_t *ent) return; if (ent != &cl_entities[0].render) R_PrepareBrushModel(ent); - R_DrawSurfaces(ent, SHADERSTAGE_SKY, ent->model->brushq1.pvstexturechains); + R_DrawSurfaces(ent, SURF_DRAWSKY); } void R_Model_Brush_Draw(entity_render_t *ent) @@ -1830,108 +1782,75 @@ void R_Model_Brush_Draw(entity_render_t *ent) c_bmodels++; if (ent != &cl_entities[0].render) R_PrepareBrushModel(ent); - R_DrawSurfaces(ent, SHADERSTAGE_NORMAL, ent->model->brushq1.pvstexturechains); + R_DrawSurfaces(ent, SURF_DRAWTURB | SURF_LIGHTMAP); } -void R_Model_Brush_DrawShadowVolume (entity_render_t *ent, vec3_t relativelightorigin, float lightradius) +void R_Model_Brush_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outclusterlist, qbyte *outclusterpvs, int *outnumclusterspointer, int *outsurfacelist, qbyte *outsurfacepvs, int *outnumsurfacespointer) { -#if 0 - int i; - msurface_t *surf; - float projectdistance, f, temp[3], lightradius2; - if (ent->model == NULL) - return; - R_Mesh_Matrix(&ent->matrix); - lightradius2 = lightradius * lightradius; - R_UpdateTextureInfo(ent); - projectdistance = lightradius + ent->model->radius;//projectdistance = 1000000000.0f;//lightradius + ent->model->radius; - //projectdistance = 1000000000.0f;//lightradius + ent->model->radius; - for (i = 0, surf = ent->model->brushq1.surfaces + ent->model->brushq1.firstmodelsurface;i < ent->model->brushq1.nummodelsurfaces;i++, surf++) - { - if (surf->texinfo->texture->rendertype == SURFRENDER_OPAQUE && surf->flags & SURF_SHADOWCAST) - { - f = PlaneDiff(relativelightorigin, surf->plane); - if (surf->flags & SURF_PLANEBACK) - f = -f; - // draw shadows only for frontfaces and only if they are close - if (f >= 0.1 && f < lightradius) - { - temp[0] = bound(surf->poly_mins[0], relativelightorigin[0], surf->poly_maxs[0]) - relativelightorigin[0]; - temp[1] = bound(surf->poly_mins[1], relativelightorigin[1], surf->poly_maxs[1]) - relativelightorigin[1]; - temp[2] = bound(surf->poly_mins[2], relativelightorigin[2], surf->poly_maxs[2]) - relativelightorigin[2]; - if (DotProduct(temp, temp) < lightradius2) - R_Shadow_VolumeFromSphere(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_vertex3f, surf->mesh.data_element3i, surf->mesh.data_neighbor3i, relativelightorigin, projectdistance, lightradius); - } - } - } -#else - int t, leafnum, marksurfnum, trianglenum; + model_t *model = ent->model; + vec3_t lightmins, lightmaxs; + int t, leafindex, marksurfaceindex, surfaceindex, triangleindex, outnumclusters = 0, outnumsurfaces = 0; const int *e; - msurface_t *surf; + const float *v[3]; + msurface_t *surface; mleaf_t *leaf; const qbyte *pvs; - float projectdistance; - const float *v[3]; - vec3_t lightmins, lightmaxs; - if (ent->model == NULL) - return; - R_Mesh_Matrix(&ent->matrix); - R_UpdateTextureInfo(ent); - projectdistance = lightradius + ent->model->radius;//projectdistance = 1000000000.0f;//lightradius + ent->model->radius; lightmins[0] = relativelightorigin[0] - lightradius; lightmins[1] = relativelightorigin[1] - lightradius; lightmins[2] = relativelightorigin[2] - lightradius; lightmaxs[0] = relativelightorigin[0] + lightradius; lightmaxs[1] = relativelightorigin[1] + lightradius; lightmaxs[2] = relativelightorigin[2] + lightradius; - /* - R_Shadow_PrepareShadowMark(ent->model->brush.shadowmesh->numtriangles); - maxmarksurfaces = sizeof(surfacelist) / sizeof(surfacelist[0]); - ent->model->brushq1.GetVisible(ent->model, relativelightorigin, lightmins, lightmaxs, 0, NULL, NULL, maxmarkleafs, markleaf, &nummarkleafs); - for (marksurfacenum = 0;marksurfacenum < nummarksurfaces;marksurfacenum++) + *outnumclusterspointer = 0; + *outnumsurfacespointer = 0; + memset(outclusterpvs, 0, model->brush.num_pvsclusterbytes); + memset(outsurfacepvs, 0, (model->numsurfaces + 7) >> 3); + if (model == NULL) { - surf = marksurface[marksurfacenum]; - if (surf->shadowmark != shadowmarkcount) - { - surf->shadowmark = shadowmarkcount; - if (BoxesOverlap(lightmins, lightmaxs, surf->poly_mins, surf->poly_maxs) && surf->texinfo->texture->rendertype == SURFRENDER_OPAQUE && (surf->flags & SURF_SHADOWCAST)) + VectorCopy(lightmins, outmins); + VectorCopy(lightmaxs, outmaxs); + return; + } + VectorCopy(relativelightorigin, outmins); + VectorCopy(relativelightorigin, outmaxs); + if (model->brush.GetPVS) + pvs = model->brush.GetPVS(model, relativelightorigin); + else + pvs = NULL; + // FIXME: use BSP recursion as lights are often small + for (leafindex = 0, leaf = model->brushq1.data_leafs;leafindex < model->brushq1.num_leafs;leafindex++, leaf++) + { + if (BoxesOverlap(lightmins, lightmaxs, leaf->mins, leaf->maxs) && (pvs == NULL || CHECKPVSBIT(pvs, leaf->clusterindex))) + { + outmins[0] = min(outmins[0], leaf->mins[0]); + outmins[1] = min(outmins[1], leaf->mins[1]); + outmins[2] = min(outmins[2], leaf->mins[2]); + outmaxs[0] = max(outmaxs[0], leaf->maxs[0]); + outmaxs[1] = max(outmaxs[1], leaf->maxs[1]); + outmaxs[2] = max(outmaxs[2], leaf->maxs[2]); + if (!CHECKPVSBIT(outclusterpvs, leaf->clusterindex)) { - for (trianglenum = 0, t = surf->num_firstshadowmeshtriangle, e = ent->model->brush.shadowmesh->element3i + t * 3;trianglenum < surf->mesh.num_triangles;trianglenum++, t++, e += 3) - { - v[0] = ent->model->brush.shadowmesh->vertex3f + e[0] * 3; - v[1] = ent->model->brush.shadowmesh->vertex3f + e[1] * 3; - v[2] = ent->model->brush.shadowmesh->vertex3f + e[2] * 3; - if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2]))) - shadowmarklist[numshadowmark++] = t; - } + SETPVSBIT(outclusterpvs, leaf->clusterindex); + outclusterlist[outnumclusters++] = leaf->clusterindex; } - } - } - */ - R_Shadow_PrepareShadowMark(ent->model->brush.shadowmesh->numtriangles); - if (ent->model->brush.GetPVS && (pvs = ent->model->brush.GetPVS(ent->model, relativelightorigin))) - { - pvs = ent->model->brush.GetPVS(ent->model, relativelightorigin); - // FIXME: use BSP recursion in q1bsp as dlights are often small - for (leafnum = 0, leaf = ent->model->brushq1.data_leafs;leafnum < ent->model->brushq1.num_leafs;leafnum++, leaf++) - { - if (BoxesOverlap(lightmins, lightmaxs, leaf->mins, leaf->maxs) && CHECKPVSBIT(pvs, leaf->clusterindex)) + for (marksurfaceindex = 0;marksurfaceindex < leaf->nummarksurfaces;marksurfaceindex++) { - for (marksurfnum = 0;marksurfnum < leaf->nummarksurfaces;marksurfnum++) + surfaceindex = leaf->firstmarksurface[marksurfaceindex]; + if (!CHECKPVSBIT(outsurfacepvs, surfaceindex)) { - surf = ent->model->brushq1.surfaces + leaf->firstmarksurface[marksurfnum]; - if (surf->shadowmark != shadowmarkcount) + surface = model->brushq1.surfaces + surfaceindex; + if (BoxesOverlap(lightmins, lightmaxs, surface->poly_mins, surface->poly_maxs) && (surface->flags & SURF_LIGHTMAP) && !surface->texinfo->texture->skin.fog) { - surf->shadowmark = shadowmarkcount; - if (BoxesOverlap(lightmins, lightmaxs, surf->poly_mins, surf->poly_maxs) && surf->texinfo->texture->rendertype == SURFRENDER_OPAQUE && (surf->flags & SURF_SHADOWCAST)) + for (triangleindex = 0, t = surface->num_firstshadowmeshtriangle, e = model->brush.shadowmesh->element3i + t * 3;triangleindex < surface->mesh.num_triangles;triangleindex++, t++, e += 3) { - for (trianglenum = 0, t = surf->num_firstshadowmeshtriangle, e = ent->model->brush.shadowmesh->element3i + t * 3;trianglenum < surf->mesh.num_triangles;trianglenum++, t++, e += 3) + v[0] = model->brush.shadowmesh->vertex3f + e[0] * 3; + v[1] = model->brush.shadowmesh->vertex3f + e[1] * 3; + v[2] = model->brush.shadowmesh->vertex3f + e[2] * 3; + if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2]))) { - v[0] = ent->model->brush.shadowmesh->vertex3f + e[0] * 3; - v[1] = ent->model->brush.shadowmesh->vertex3f + e[1] * 3; - v[2] = ent->model->brush.shadowmesh->vertex3f + e[2] * 3; - if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2]))) - shadowmarklist[numshadowmark++] = t; + SETPVSBIT(outsurfacepvs, surfaceindex); + outsurfacelist[outnumsurfaces++] = surfaceindex; + break; } } } @@ -1939,85 +1858,85 @@ void R_Model_Brush_DrawShadowVolume (entity_render_t *ent, vec3_t relativelighto } } } - else + + // limit combined leaf box to light boundaries + outmins[0] = max(outmins[0], lightmins[0]); + outmins[1] = max(outmins[1], lightmins[1]); + outmins[2] = max(outmins[2], lightmins[2]); + outmaxs[0] = min(outmaxs[0], lightmaxs[0]); + outmaxs[1] = min(outmaxs[1], lightmaxs[1]); + outmaxs[2] = min(outmaxs[2], lightmaxs[2]); + + *outnumclusterspointer = outnumclusters; + *outnumsurfacespointer = outnumsurfaces; +} + +void R_Model_Brush_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int numsurfaces, const int *surfacelist) +{ + model_t *model = ent->model; + vec3_t lightmins, lightmaxs; + msurface_t *surface; + int surfacelistindex, j, t; + const int *e; + const float *v[3]; + if (r_drawcollisionbrushes.integer < 2) { - for (marksurfnum = 0, surf = ent->model->brushq1.surfaces + ent->model->brushq1.firstmodelsurface;marksurfnum < ent->model->brushq1.nummodelsurfaces;marksurfnum++, surf++) + lightmins[0] = relativelightorigin[0] - lightradius; + lightmins[1] = relativelightorigin[1] - lightradius; + lightmins[2] = relativelightorigin[2] - lightradius; + lightmaxs[0] = relativelightorigin[0] + lightradius; + lightmaxs[1] = relativelightorigin[1] + lightradius; + lightmaxs[2] = relativelightorigin[2] + lightradius; + R_Mesh_Matrix(&ent->matrix); + R_Shadow_PrepareShadowMark(model->brush.shadowmesh->numtriangles); + for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++) { - if (BoxesOverlap(lightmins, lightmaxs, surf->poly_mins, surf->poly_maxs) && surf->texinfo->texture->rendertype == SURFRENDER_OPAQUE && (surf->flags & SURF_SHADOWCAST)) + surface = model->brushq1.surfaces + surfacelist[surfacelistindex]; + for (j = 0, t = surface->num_firstshadowmeshtriangle, e = model->brush.shadowmesh->element3i + t * 3;j < surface->mesh.num_triangles;j++, t++, e += 3) { - for (trianglenum = 0, t = surf->num_firstshadowmeshtriangle, e = ent->model->brush.shadowmesh->element3i + t * 3;trianglenum < surf->mesh.num_triangles;trianglenum++, t++, e += 3) - { - v[0] = ent->model->brush.shadowmesh->vertex3f + e[0] * 3; - v[1] = ent->model->brush.shadowmesh->vertex3f + e[1] * 3; - v[2] = ent->model->brush.shadowmesh->vertex3f + e[2] * 3; - if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2]))) - shadowmarklist[numshadowmark++] = t; - } + v[0] = model->brush.shadowmesh->vertex3f + e[0] * 3; + v[1] = model->brush.shadowmesh->vertex3f + e[1] * 3; + v[2] = model->brush.shadowmesh->vertex3f + e[2] * 3; + if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2]))) + shadowmarklist[numshadowmark++] = t; } } + R_Shadow_VolumeFromList(model->brush.shadowmesh->numverts, model->brush.shadowmesh->numtriangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, model->brush.shadowmesh->neighbor3i, relativelightorigin, lightradius + model->radius + r_shadow_projectdistance.value, numshadowmark, shadowmarklist); } - R_Shadow_VolumeFromList(ent->model->brush.shadowmesh->numverts, ent->model->brush.shadowmesh->numtriangles, ent->model->brush.shadowmesh->vertex3f, ent->model->brush.shadowmesh->element3i, ent->model->brush.shadowmesh->neighbor3i, relativelightorigin, projectdistance, numshadowmark, shadowmarklist); -#endif } -void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap) +void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap, int numsurfaces, const int *surfacelist) { - int leafnum, marksurfnum; - msurface_t *surf; - mleaf_t *leaf; - const qbyte *pvs; + model_t *model = ent->model; + vec3_t lightmins, lightmaxs, modelorg; + msurface_t *surface; texture_t *t; - float lightmins[3], lightmaxs[3]; - if (ent->model == NULL) - return; - R_Mesh_Matrix(&ent->matrix); - lightmins[0] = relativelightorigin[0] - lightradius; - lightmins[1] = relativelightorigin[1] - lightradius; - lightmins[2] = relativelightorigin[2] - lightradius; - lightmaxs[0] = relativelightorigin[0] + lightradius; - lightmaxs[1] = relativelightorigin[1] + lightradius; - lightmaxs[2] = relativelightorigin[2] + lightradius; - R_UpdateTextureInfo(ent); - shadowmarkcount++; - if (ent->model->brush.GetPVS && (pvs = ent->model->brush.GetPVS(ent->model, relativelightorigin))) + int surfacelistindex; + if (r_drawcollisionbrushes.integer < 2) { - pvs = ent->model->brush.GetPVS(ent->model, relativelightorigin); - for (leafnum = 0, leaf = ent->model->brushq1.data_leafs;leafnum < ent->model->brushq1.num_leafs;leafnum++, leaf++) + lightmins[0] = relativelightorigin[0] - lightradius; + lightmins[1] = relativelightorigin[1] - lightradius; + lightmins[2] = relativelightorigin[2] - lightradius; + lightmaxs[0] = relativelightorigin[0] + lightradius; + lightmaxs[1] = relativelightorigin[1] + lightradius; + lightmaxs[2] = relativelightorigin[2] + lightradius; + R_Mesh_Matrix(&ent->matrix); + Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg); + for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++) { - if (BoxesOverlap(lightmins, lightmaxs, leaf->mins, leaf->maxs) && CHECKPVSBIT(pvs, leaf->clusterindex)) + surface = model->brushq1.surfaces + surfacelist[surfacelistindex]; + if (r_shadow_compilingrtlight) { - for (marksurfnum = 0;marksurfnum < leaf->nummarksurfaces;marksurfnum++) - { - surf = ent->model->brushq1.surfaces + leaf->firstmarksurface[marksurfnum]; - if (surf->shadowmark != shadowmarkcount) - { - surf->shadowmark = shadowmarkcount; - if (BoxesOverlap(lightmins, lightmaxs, surf->poly_mins, surf->poly_maxs) && (ent != &cl_entities[0].render || surf->visframe == r_framecount)) - { - t = surf->texinfo->texture->currentframe; - if (t->rendertype == SURFRENDER_OPAQUE && t->flags & SURF_SHADOWLIGHT) - { - R_Shadow_DiffuseLighting(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_element3i, surf->mesh.data_vertex3f, surf->mesh.data_svector3f, surf->mesh.data_tvector3f, surf->mesh.data_normal3f, surf->mesh.data_texcoordtexture2f, relativelightorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.base, t->skin.nmap, lightcubemap); - R_Shadow_SpecularLighting(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_element3i, surf->mesh.data_vertex3f, surf->mesh.data_svector3f, surf->mesh.data_tvector3f, surf->mesh.data_normal3f, surf->mesh.data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.gloss, t->skin.nmap, lightcubemap); - } - } - } - } + // if compiling an rtlight, capture the mesh + t = surface->texinfo->texture; + if (t->flags & SURF_LIGHTMAP && t->skin.fog == NULL) + Mod_ShadowMesh_AddMesh(r_shadow_mempool, r_shadow_compilingrtlight->static_meshchain_light, surface->texinfo->texture->skin.base, surface->texinfo->texture->skin.gloss, surface->texinfo->texture->skin.nmap, surface->mesh.data_vertex3f, surface->mesh.data_svector3f, surface->mesh.data_tvector3f, surface->mesh.data_normal3f, surface->mesh.data_texcoordtexture2f, surface->mesh.num_triangles, surface->mesh.data_element3i); } - } - } - else - { - for (marksurfnum = 0, surf = ent->model->brushq1.surfaces + ent->model->brushq1.firstmodelsurface;marksurfnum < ent->model->brushq1.nummodelsurfaces;marksurfnum++, surf++) - { - if (BoxesOverlap(lightmins, lightmaxs, surf->poly_mins, surf->poly_maxs) && (ent != &cl_entities[0].render || surf->visframe == r_framecount)) + else if (ent != &cl_entities[0].render || surface->visframe == r_framecount) { - t = surf->texinfo->texture->currentframe; - if (t->rendertype == SURFRENDER_OPAQUE && t->flags & SURF_SHADOWLIGHT) - { - R_Shadow_DiffuseLighting(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_element3i, surf->mesh.data_vertex3f, surf->mesh.data_svector3f, surf->mesh.data_tvector3f, surf->mesh.data_normal3f, surf->mesh.data_texcoordtexture2f, relativelightorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.base, t->skin.nmap, lightcubemap); - R_Shadow_SpecularLighting(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_element3i, surf->mesh.data_vertex3f, surf->mesh.data_svector3f, surf->mesh.data_tvector3f, surf->mesh.data_normal3f, surf->mesh.data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.gloss, t->skin.nmap, lightcubemap); - } + t = surface->texinfo->texture->currentframe; + if (t->flags & SURF_LIGHTMAP && t->rendertype == SURFRENDER_OPAQUE) + R_Shadow_RenderLighting(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i, surface->mesh.data_vertex3f, surface->mesh.data_svector3f, surface->mesh.data_tvector3f, surface->mesh.data_normal3f, surface->mesh.data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.base, t->skin.nmap, t->skin.gloss, lightcubemap, LIGHTING_DIFFUSE | LIGHTING_SPECULAR); } } } @@ -2375,7 +2294,6 @@ void R_Q3BSP_DrawFace(entity_render_t *ent, q3mface_t *face) return; } c_faces++; - face->visframe = r_framecount; if ((face->texture->surfaceparms & Q3SURFACEPARM_TRANS) || ent->alpha < 1 || (ent->effects & EF_ADDITIVE)) { vec3_t facecenter, center; @@ -2477,13 +2395,12 @@ void R_Q3BSP_DrawSky(entity_render_t *ent) q3mface_t *face; vec3_t modelorg; model_t *model; - qbyte *pvs; R_Mesh_Matrix(&ent->matrix); model = ent->model; if (r_drawcollisionbrushes.integer < 2) { Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg); - if (ent == &cl_entities[0].render && model->brush.num_pvsclusters && !r_novis.integer && (pvs = model->brush.GetPVS(model, modelorg))) + if (ent == &cl_entities[0].render) { if (r_q3bsp_framecount != r_framecount) { @@ -2514,8 +2431,9 @@ void R_Q3BSP_Draw(entity_render_t *ent) if (r_drawcollisionbrushes.integer < 2) { Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg); - if (ent == &cl_entities[0].render && model->brush.num_pvsclusters && !r_novis.integer && (pvs = model->brush.GetPVS(model, modelorg))) + if (ent == &cl_entities[0].render) { + if (model->brush.num_pvsclusters && !r_novis.integer && (pvs = model->brush.GetPVS(model, modelorg))) if (r_q3bsp_framecount != r_framecount) { r_q3bsp_framecount = r_framecount; @@ -2546,132 +2464,156 @@ void R_Q3BSP_Draw(entity_render_t *ent) } } -void R_Q3BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius) +void R_Q3BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outclusterlist, qbyte *outclusterpvs, int *outnumclusterspointer, int *outsurfacelist, qbyte *outsurfacepvs, int *outnumsurfacespointer) { - int j, t, leafnum, marksurfnum; + model_t *model = ent->model; + vec3_t lightmins, lightmaxs; + int t, leafindex, marksurfaceindex, surfaceindex, triangleindex, outnumclusters = 0, outnumsurfaces = 0; const int *e; - const qbyte *pvs; const float *v[3]; - q3mface_t *face; + q3mface_t *surface; q3mleaf_t *leaf; - vec3_t modelorg, lightmins, lightmaxs; - model_t *model; - float projectdistance; - projectdistance = lightradius + ent->model->radius;//projectdistance = 1000000000.0f;//lightradius + ent->model->radius; - if (r_drawcollisionbrushes.integer < 2) + const qbyte *pvs; + lightmins[0] = relativelightorigin[0] - lightradius; + lightmins[1] = relativelightorigin[1] - lightradius; + lightmins[2] = relativelightorigin[2] - lightradius; + lightmaxs[0] = relativelightorigin[0] + lightradius; + lightmaxs[1] = relativelightorigin[1] + lightradius; + lightmaxs[2] = relativelightorigin[2] + lightradius; + *outnumclusterspointer = 0; + *outnumsurfacespointer = 0; + memset(outclusterpvs, 0, model->brush.num_pvsclusterbytes); + memset(outsurfacepvs, 0, (model->numsurfaces + 7) >> 3); + if (model == NULL) { - model = ent->model; - R_Mesh_Matrix(&ent->matrix); - Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg); - lightmins[0] = relativelightorigin[0] - lightradius; - lightmins[1] = relativelightorigin[1] - lightradius; - lightmins[2] = relativelightorigin[2] - lightradius; - lightmaxs[0] = relativelightorigin[0] + lightradius; - lightmaxs[1] = relativelightorigin[1] + lightradius; - lightmaxs[2] = relativelightorigin[2] + lightradius; - R_Shadow_PrepareShadowMark(model->brush.shadowmesh->numtriangles); - if (ent->model->brush.GetPVS && (pvs = ent->model->brush.GetPVS(ent->model, relativelightorigin))) - { - for (leafnum = 0, leaf = ent->model->brushq3.data_leafs;leafnum < ent->model->brushq3.num_leafs;leafnum++, leaf++) + VectorCopy(lightmins, outmins); + VectorCopy(lightmaxs, outmaxs); + return; + } + VectorCopy(relativelightorigin, outmins); + VectorCopy(relativelightorigin, outmaxs); + if (model->brush.GetPVS) + pvs = model->brush.GetPVS(model, relativelightorigin); + else + pvs = NULL; + // FIXME: use BSP recursion as lights are often small + for (leafindex = 0, leaf = model->brushq3.data_leafs;leafindex < model->brushq3.num_leafs;leafindex++, leaf++) + { + if (BoxesOverlap(lightmins, lightmaxs, leaf->mins, leaf->maxs) && (pvs == NULL || CHECKPVSBIT(pvs, leaf->clusterindex))) + { + outmins[0] = min(outmins[0], leaf->mins[0]); + outmins[1] = min(outmins[1], leaf->mins[1]); + outmins[2] = min(outmins[2], leaf->mins[2]); + outmaxs[0] = max(outmaxs[0], leaf->maxs[0]); + outmaxs[1] = max(outmaxs[1], leaf->maxs[1]); + outmaxs[2] = max(outmaxs[2], leaf->maxs[2]); + if (!CHECKPVSBIT(outclusterpvs, leaf->clusterindex)) { - if (BoxesOverlap(lightmins, lightmaxs, leaf->mins, leaf->maxs) && CHECKPVSBIT(pvs, leaf->clusterindex)) + SETPVSBIT(outclusterpvs, leaf->clusterindex); + outclusterlist[outnumclusters++] = leaf->clusterindex; + } + for (marksurfaceindex = 0;marksurfaceindex < leaf->numleaffaces;marksurfaceindex++) + { + surface = leaf->firstleafface[marksurfaceindex]; + surfaceindex = surface - model->brushq3.data_faces; + if (!CHECKPVSBIT(outsurfacepvs, surfaceindex)) { - for (marksurfnum = 0;marksurfnum < leaf->numleaffaces;marksurfnum++) + if (BoxesOverlap(lightmins, lightmaxs, surface->mins, surface->maxs) && !(surface->texture->surfaceparms & Q3SURFACEPARM_TRANS) && !(surface->texture->surfaceflags & (Q3SURFACEFLAG_SKY | Q3SURFACEFLAG_NODRAW))) { - face = leaf->firstleafface[marksurfnum]; - if (face->shadowmark != shadowmarkcount) + for (triangleindex = 0, t = surface->num_firstshadowmeshtriangle, e = model->brush.shadowmesh->element3i + t * 3;triangleindex < surface->num_triangles;triangleindex++, t++, e += 3) { - face->shadowmark = shadowmarkcount; - if (BoxesOverlap(lightmins, lightmaxs, face->mins, face->maxs)) + v[0] = model->brush.shadowmesh->vertex3f + e[0] * 3; + v[1] = model->brush.shadowmesh->vertex3f + e[1] * 3; + v[2] = model->brush.shadowmesh->vertex3f + e[2] * 3; + if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2]))) { - for (j = 0, t = face->num_firstshadowmeshtriangle, e = model->brush.shadowmesh->element3i + t * 3;j < face->num_triangles;j++, t++, e += 3) - { - v[0] = model->brush.shadowmesh->vertex3f + e[0] * 3; - v[1] = model->brush.shadowmesh->vertex3f + e[1] * 3; - v[2] = model->brush.shadowmesh->vertex3f + e[2] * 3; - if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2]))) - shadowmarklist[numshadowmark++] = t; - } + SETPVSBIT(outsurfacepvs, surfaceindex); + outsurfacelist[outnumsurfaces++] = surfaceindex; + break; } } } } } } - else + } + + // limit combined leaf box to light boundaries + outmins[0] = max(outmins[0], lightmins[0]); + outmins[1] = max(outmins[1], lightmins[1]); + outmins[2] = max(outmins[2], lightmins[2]); + outmaxs[0] = min(outmaxs[0], lightmaxs[0]); + outmaxs[1] = min(outmaxs[1], lightmaxs[1]); + outmaxs[2] = min(outmaxs[2], lightmaxs[2]); + + *outnumclusterspointer = outnumclusters; + *outnumsurfacespointer = outnumsurfaces; +} + +void R_Q3BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int numsurfaces, const int *surfacelist) +{ + model_t *model = ent->model; + vec3_t lightmins, lightmaxs; + q3mface_t *surface; + int surfacelistindex, j, t; + const int *e; + const float *v[3]; + if (r_drawcollisionbrushes.integer < 2) + { + lightmins[0] = relativelightorigin[0] - lightradius; + lightmins[1] = relativelightorigin[1] - lightradius; + lightmins[2] = relativelightorigin[2] - lightradius; + lightmaxs[0] = relativelightorigin[0] + lightradius; + lightmaxs[1] = relativelightorigin[1] + lightradius; + lightmaxs[2] = relativelightorigin[2] + lightradius; + R_Mesh_Matrix(&ent->matrix); + R_Shadow_PrepareShadowMark(model->brush.shadowmesh->numtriangles); + for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++) { - for (marksurfnum = 0, face = model->brushq3.data_thismodel->firstface;marksurfnum < model->brushq3.data_thismodel->numfaces;marksurfnum++, face++) + surface = model->brushq3.data_faces + surfacelist[surfacelistindex]; + // FIXME: check some manner of face->rendermode here? + if (!(surface->texture->surfaceflags & Q3SURFACEFLAG_NODRAW) && surface->num_triangles && !surface->texture->skin.fog) { - if (BoxesOverlap(lightmins, lightmaxs, face->mins, face->maxs)) + for (j = 0, t = surface->num_firstshadowmeshtriangle, e = model->brush.shadowmesh->element3i + t * 3;j < surface->num_triangles;j++, t++, e += 3) { - for (j = 0, t = face->num_firstshadowmeshtriangle, e = model->brush.shadowmesh->element3i + t * 3;j < face->num_triangles;j++, t++, e += 3) - { - v[0] = model->brush.shadowmesh->vertex3f + e[0] * 3; - v[1] = model->brush.shadowmesh->vertex3f + e[1] * 3; - v[2] = model->brush.shadowmesh->vertex3f + e[2] * 3; - if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2]))) - shadowmarklist[numshadowmark++] = t; - } + v[0] = model->brush.shadowmesh->vertex3f + e[0] * 3; + v[1] = model->brush.shadowmesh->vertex3f + e[1] * 3; + v[2] = model->brush.shadowmesh->vertex3f + e[2] * 3; + if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2]))) + shadowmarklist[numshadowmark++] = t; } } } - R_Shadow_VolumeFromList(model->brush.shadowmesh->numverts, model->brush.shadowmesh->numtriangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, model->brush.shadowmesh->neighbor3i, relativelightorigin, projectdistance, numshadowmark, shadowmarklist); + R_Shadow_VolumeFromList(model->brush.shadowmesh->numverts, model->brush.shadowmesh->numtriangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, model->brush.shadowmesh->neighbor3i, relativelightorigin, lightradius + model->radius + r_shadow_projectdistance.value, numshadowmark, shadowmarklist); } } -void R_Q3BSP_DrawFaceLight(entity_render_t *ent, q3mface_t *face, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap) +void R_Q3BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap, int numsurfaces, const int *surfacelist) { - if ((face->texture->surfaceflags & Q3SURFACEFLAG_NODRAW) || !face->num_triangles) - return; - R_Shadow_DiffuseLighting(face->num_vertices, face->num_triangles, face->data_element3i, face->data_vertex3f, face->data_svector3f, face->data_tvector3f, face->data_normal3f, face->data_texcoordtexture2f, relativelightorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, face->texture->skin.base, face->texture->skin.nmap, lightcubemap); - R_Shadow_SpecularLighting(face->num_vertices, face->num_triangles, face->data_element3i, face->data_vertex3f, face->data_svector3f, face->data_tvector3f, face->data_normal3f, face->data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, face->texture->skin.gloss, face->texture->skin.nmap, lightcubemap); -} - -void R_Q3BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap) -{ - int leafnum, marksurfnum; - const qbyte *pvs; - q3mface_t *face; - q3mleaf_t *leaf; - vec3_t modelorg, lightmins, lightmaxs; - model_t *model; + model_t *model = ent->model; + vec3_t lightmins, lightmaxs, modelorg; + q3mface_t *surface; + int surfacelistindex; if (r_drawcollisionbrushes.integer < 2) { - model = ent->model; - R_Mesh_Matrix(&ent->matrix); - Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg); lightmins[0] = relativelightorigin[0] - lightradius; lightmins[1] = relativelightorigin[1] - lightradius; lightmins[2] = relativelightorigin[2] - lightradius; lightmaxs[0] = relativelightorigin[0] + lightradius; lightmaxs[1] = relativelightorigin[1] + lightradius; lightmaxs[2] = relativelightorigin[2] + lightradius; - - if (ent->model->brush.GetPVS && (pvs = ent->model->brush.GetPVS(ent->model, relativelightorigin))) - { - pvs = ent->model->brush.GetPVS(ent->model, relativelightorigin); - for (leafnum = 0, leaf = ent->model->brushq3.data_leafs;leafnum < ent->model->brushq3.num_leafs;leafnum++, leaf++) + R_Mesh_Matrix(&ent->matrix); + Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg); + for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++) + { + surface = model->brushq3.data_faces + surfacelist[surfacelistindex]; + if (r_shadow_compilingrtlight) { - if (BoxesOverlap(lightmins, lightmaxs, leaf->mins, leaf->maxs) && CHECKPVSBIT(pvs, leaf->clusterindex)) - { - for (marksurfnum = 0;marksurfnum < leaf->numleaffaces;marksurfnum++) - { - face = leaf->firstleafface[marksurfnum]; - if (face->shadowmark != shadowmarkcount) - { - face->shadowmark = shadowmarkcount; - if (BoxesOverlap(lightmins, lightmaxs, face->mins, face->maxs) && (ent != &cl_entities[0].render || face->visframe == r_framecount)) - R_Q3BSP_DrawFaceLight(ent, face, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, lightcubemap); - } - } - } + // if compiling an rtlight, capture the mesh + Mod_ShadowMesh_AddMesh(r_shadow_mempool, r_shadow_compilingrtlight->static_meshchain_light, surface->texture->skin.base, surface->texture->skin.gloss, surface->texture->skin.nmap, surface->data_vertex3f, surface->data_svector3f, surface->data_tvector3f, surface->data_normal3f, surface->data_texcoordtexture2f, surface->num_triangles, surface->data_element3i); } - } - else - { - for (marksurfnum = 0, face = model->brushq3.data_thismodel->firstface;marksurfnum < model->brushq3.data_thismodel->numfaces;marksurfnum++, face++) - if (BoxesOverlap(lightmins, lightmaxs, face->mins, face->maxs) && (ent != &cl_entities[0].render || face->visframe == r_framecount)) - R_Q3BSP_DrawFaceLight(ent, face, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, lightcubemap); + else if ((ent != &cl_entities[0].render || surface->visframe == r_framecount) && !(surface->texture->surfaceflags & Q3SURFACEFLAG_NODRAW) && surface->num_triangles) + R_Shadow_RenderLighting(surface->num_vertices, surface->num_triangles, surface->data_element3i, surface->data_vertex3f, surface->data_svector3f, surface->data_tvector3f, surface->data_normal3f, surface->data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, surface->texture->skin.base, surface->texture->skin.nmap, surface->texture->skin.gloss, lightcubemap, LIGHTING_DIFFUSE | LIGHTING_SPECULAR); } } }