From: havoc Date: Fri, 9 Aug 2002 21:14:12 +0000 (+0000) Subject: rewrote most of the RSurfShader_ functions to use R_Mesh_Draw_GetBuffer instead of... X-Git-Tag: RELEASE_0_2_0_RC1~358 X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=commitdiff_plain;h=9085903141b6ca8abcf0f518908d770e0107d378;hp=69a003b5def5ea2ece7310d3b35b62bf023c29b1 rewrote most of the RSurfShader_ functions to use R_Mesh_Draw_GetBuffer instead of R_Mesh_Draw r_modellights replaced r_lightmodels, r_modellights sets limit on how many directional lights will be shaded onto the model (only the brightest are chosen) cleaned up lighting code a lot, it is now consistent between static and dynamic light sources, and the light radius has been reduced unfortunately this commit seems to have slowed down the engine a bit, and I don't know why, it should be a speed gain git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@2223 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/gl_rsurf.c b/gl_rsurf.c index a9a6cb55..8851704d 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -104,7 +104,7 @@ static int R_IntAddDynamicLights (msurface_t *surf) red = r_dlight[lnum].light[0]; green = r_dlight[lnum].light[1]; blue = r_dlight[lnum].light[2]; - subtract = (int) (r_dlight[lnum].lightsubtract * 4194304.0f); + subtract = (int) (r_dlight[lnum].subtract * 4194304.0f); bl = intblocklights; i = impactt; @@ -122,9 +122,9 @@ static int R_IntAddDynamicLights (msurface_t *surf) k = dlightdivtable[(sdtable[s] + td) >> 7] - subtract; if (k > 0) { - bl[0] += (red * k) >> 8; - bl[1] += (green * k) >> 8; - bl[2] += (blue * k) >> 8; + bl[0] += (red * k) >> 7; + bl[1] += (green * k) >> 7; + bl[2] += (blue * k) >> 7; lit = true; } } @@ -197,7 +197,7 @@ static int R_FloatAddDynamicLights (msurface_t *surf) red = r_dlight[lnum].light[0]; green = r_dlight[lnum].light[1]; blue = r_dlight[lnum].light[2]; - subtract = r_dlight[lnum].lightsubtract * 16384.0f; + subtract = r_dlight[lnum].subtract * 32768.0f; bl = floatblocklights; td1 = impactt; @@ -212,7 +212,7 @@ static int R_FloatAddDynamicLights (msurface_t *surf) { if (sdtable[s] < maxdist2) { - k = (16384.0f / (sdtable[s] + td)) - subtract; + k = (32768.0f / (sdtable[s] + td)) - subtract; bl[0] += red * k; bl[1] += green * k; bl[2] += blue * k; @@ -816,11 +816,11 @@ static void RSurfShader_Sky(msurface_t *firstsurf) static int RSurf_Light(int *dlightbits, int numverts) { - float f; - int i, l, lit = false; - rdlight_t *rd; - vec3_t lightorigin; - surfvert_t *sv; + float f; + int i, l, lit = false; + rdlight_t *rd; + vec3_t lightorigin; + surfvert_t *sv; for (l = 0;l < r_numdlights;l++) { if (dlightbits[l >> 5] & (1 << (l & 31))) @@ -830,10 +830,10 @@ static int RSurf_Light(int *dlightbits, int numverts) VectorCopy(rd->origin, lightorigin); for (i = 0, sv = svert;i < numverts;i++, sv++) { - f = VectorDistance2(sv->v, lightorigin) + LIGHTOFFSET; + f = VectorDistance2(sv->v, lightorigin); if (f < rd->cullradius2) { - f = (1.0f / f) - rd->lightsubtract; + f = (1.0f / f) - rd->subtract; sv->c[0] += rd->light[0] * f; sv->c[1] += rd->light[1] * f; sv->c[2] += rd->light[2] * f; @@ -845,8 +845,215 @@ static int RSurf_Light(int *dlightbits, int numverts) return lit; } +static int RSurf_LightSeparate(int *dlightbits, int numverts, float *vert, float *color) +{ + float f, *v, *c; + int i, l, lit = false; + rdlight_t *rd; + vec3_t lightorigin; + for (l = 0;l < r_numdlights;l++) + { + if (dlightbits[l >> 5] & (1 << (l & 31))) + { + rd = &r_dlight[l]; + // FIXME: support softwareuntransform here and make bmodels use hardware transform? + VectorCopy(rd->origin, lightorigin); + for (i = 0, v = vert, c = color;i < numverts;i++, v += 4, c += 4) + { + f = VectorDistance2(v, lightorigin) + LIGHTOFFSET; + if (f < rd->cullradius2) + { + f = (1.0f / f) - rd->subtract; + VectorMA(c, f, rd->light, c); + lit = true; + } + } + } + } + return lit; +} + +// note: this untransforms lights to do the checking, +// and takes surf->mesh->vertex data +static int RSurf_LightCheck(int *dlightbits, surfmesh_t *mesh) +{ + int i, l; + rdlight_t *rd; + vec3_t lightorigin; + surfvertex_t *sv; + for (l = 0;l < r_numdlights;l++) + { + if (dlightbits[l >> 5] & (1 << (l & 31))) + { + rd = &r_dlight[l]; + softwareuntransform(rd->origin, lightorigin); + for (i = 0, sv = mesh->vertex;i < mesh->numverts;i++, sv++) + if (VectorDistance2(sv->v, lightorigin) < rd->cullradius2) + return true; + } + } + return false; +} + static void RSurfShader_Water_Pass_Base(msurface_t *surf) { +#if 0 + int i, size3; + surfvertex_t *v; + float *outv, *outc, *outst, *outuv, cl, ca, diff[3]; + float base[3], scale, f; + qbyte *lm; + surfmesh_t *mesh; + rmeshbufferinfo_t m; + memset(&m, 0, sizeof(m)); + if (currentrenderentity->effects & EF_ADDITIVE) + { + m.transparent = true; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE; + } + else if (surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1) + { + m.transparent = true; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + } + else + { + m.transparent = false; + m.blendfunc1 = GL_ONE; + m.blendfunc2 = GL_ZERO; + } + m.depthwrite = false; + m.depthdisable = false; + m.tex[0] = R_GetTexture(surf->currenttexture->texture); + + size3 = ((surf->extents[0]>>4)+1)*((surf->extents[1]>>4)+1)*3; + + base[0] = base[1] = base[2] = currentrenderentity->effects & EF_FULLBRIGHT ? 2.0f : r_ambient.value * (1.0f / 64.0f) + surf->flags & SURF_LIGHTMAP ? 0 : ; + + ca = currentrenderentity->alpha; + for (mesh = surf->mesh;mesh;mesh = mesh->chain) + { + m.numtriangles = mesh->numtriangles; + m.numverts = mesh->numverts; + + if (R_Mesh_Draw_GetBuffer(&m)) + { + cl = m.colorscale; + memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3])); + + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2) + { + softwaretransform(v->v, outv); + outv[3] = 1; + VectorCopy(base, outc); + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; + } + + if (surf->dlightframe == r_framecount) + RSurf_LightSeparate(surf->dlightbits, m.numverts, m.vertex, m.color); + + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color;i < m.numverts;i++, v++, outv += 4, outc += 4) + { + if (surf->flags & SURF_LIGHTMAP) + if (surf->styles[0] != 255) + { + lm = surf->samples + v->lightmapoffset; + scale = d_lightstylevalue[surf->styles[0]] * (1.0f / 32768.0f); + VectorMA(outc, scale, lm, outc); + if (surf->styles[1] != 255) + { + lm += size3; + scale = d_lightstylevalue[surf->styles[1]] * (1.0f / 32768.0f); + VectorMA(outc, scale, lm, outc); + if (surf->styles[2] != 255) + { + lm += size3; + scale = d_lightstylevalue[surf->styles[2]] * (1.0f / 32768.0f); + VectorMA(outc, scale, lm, outc); + if (surf->styles[3] != 255) + { + lm += size3; + scale = d_lightstylevalue[surf->styles[3]] * (1.0f / 32768.0f); + VectorMA(outc, scale, lm, outc); + } + } + } + } + if (fogenabled) + { + VectorSubtract(outv, r_origin, diff); + f = cl * (1 - exp(fogdensity/DotProduct(diff, diff))); + VectorScale(outc, f, outc); + } + else + VectorScale(outc, cl, outc); + } + } + } + int i; + surfvertex_t *v; + float *outv, *outc, *outst, *outuv, cl, ca, diff[3]; + surfmesh_t *mesh; + rmeshbufferinfo_t m; + memset(&m, 0, sizeof(m)); + if (currentrenderentity->effects & EF_ADDITIVE) + { + m.transparent = true; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE; + } + else if (surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1) + { + m.transparent = true; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + } + else + { + m.transparent = false; + m.blendfunc1 = GL_ONE; + m.blendfunc2 = GL_ZERO; + } + m.depthwrite = false; + m.depthdisable = false; + m.tex[0] = R_GetTexture(surf->currenttexture->texture); + m.tex[1] = R_GetTexture(surf->lightmaptexture); + ca = currentrenderentity->alpha; + for (mesh = surf->mesh;mesh;mesh = mesh->chain) + { + m.numtriangles = mesh->numtriangles; + m.numverts = mesh->numverts; + + if (R_Mesh_Draw_GetBuffer(&m)) + { + cl = (float) (1 << lightscalebit) * m.colorscale; + memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3])); + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2) + { + softwaretransform(v->v, outv); + if (r_waterripple.value) + outv[2] += r_waterripple.value * (1.0f / 64.0f) * turbsin[(int)((v->v[0]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255] * turbsin[(int)((v->v[1]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255]; + outv[3] = 1; + if (fogenabled) + { + VectorSubtract(outv, r_origin, diff); + outc[0] = outc[1] = outc[2] = cl * (1 - exp(fogdensity/DotProduct(diff, diff))); + } + else + outc[0] = outc[1] = outc[2] = cl; + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; + outuv[0] = v->uv[0]; + outuv[1] = v->uv[1]; + } + } + } +#else int i; float diff[3], alpha, ifog; surfvertex_t *v; @@ -917,72 +1124,13 @@ static void RSurfShader_Water_Pass_Base(msurface_t *surf) } R_Mesh_Draw(&m); } -} - -static void RSurfShader_Water_Pass_Glow(msurface_t *surf) -{ - int i; - float diff[3], alpha, ifog; - surfvertex_t *v; - surfvert_t *sv; - surfmesh_t *mesh; - rmeshinfo_t m; - alpha = currentrenderentity->alpha * (surf->flags & SURF_DRAWNOALPHA ? 1 : r_wateralpha.value); - - memset(&m, 0, sizeof(m)); - m.transparent = alpha != 1 || surf->currenttexture->fogtexture != NULL; - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE; - m.vertex = &svert[0].v[0]; - m.vertexstep = sizeof(surfvert_t); - m.cr = 1; - m.cg = 1; - m.cb = 1; - m.ca = alpha; - m.tex[0] = R_GetTexture(surf->currenttexture->glowtexture); - m.texcoords[0] = &svert[0].st[0]; - m.texcoordstep[0] = sizeof(surfvert_t); - for (mesh = surf->mesh;mesh;mesh = mesh->chain) - { - m.numtriangles = mesh->numtriangles; - m.numverts = mesh->numverts; - m.index = mesh->index; - if (fogenabled) - { - m.color = &svert[0].c[0]; - m.colorstep = sizeof(surfvert_t); - for (i = 0, sv = svert, v = mesh->vertex;i < m.numverts;i++, sv++, v++) - { - softwaretransform(v->v, sv->v); - if (r_waterripple.value) - sv->v[2] += r_waterripple.value * (1.0f / 64.0f) * turbsin[(int)((v->v[0]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255] * turbsin[(int)((v->v[1]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255]; - sv->st[0] = (v->st[0] + turbsin[(int)((v->st[1]*0.125f+cl.time) * TURBSCALE) & 255]) * (1.0f / 64.0f); - sv->st[1] = (v->st[1] + turbsin[(int)((v->st[0]*0.125f+cl.time) * TURBSCALE) & 255]) * (1.0f / 64.0f); - VectorSubtract(sv->v, r_origin, diff); - ifog = 1 - exp(fogdensity/DotProduct(diff, diff)); - sv->c[0] = m.cr * ifog; - sv->c[1] = m.cg * ifog; - sv->c[2] = m.cb * ifog; - sv->c[3] = m.ca; - } - } - else - { - for (i = 0, sv = svert, v = mesh->vertex;i < m.numverts;i++, sv++, v++) - { - softwaretransform(v->v, sv->v); - if (r_waterripple.value) - sv->v[2] += r_waterripple.value * (1.0f / 64.0f) * turbsin[(int)((v->v[0]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255] * turbsin[(int)((v->v[1]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255]; - sv->st[0] = (v->st[0] + turbsin[(int)((v->st[1]*0.125f+cl.time) * TURBSCALE) & 255]) * (1.0f / 64.0f); - sv->st[1] = (v->st[1] + turbsin[(int)((v->st[0]*0.125f+cl.time) * TURBSCALE) & 255]) * (1.0f / 64.0f); - } - } - R_Mesh_Draw(&m); - } +#endif } static void RSurfShader_Water_Pass_Fog(msurface_t *surf) { +#if 0 +#else int i; float alpha; surfvertex_t *v; @@ -1027,6 +1175,7 @@ static void RSurfShader_Water_Pass_Fog(msurface_t *surf) } R_Mesh_Draw(&m); } +#endif } static void RSurfShader_Water(msurface_t *firstsurf) @@ -1034,9 +1183,6 @@ static void RSurfShader_Water(msurface_t *firstsurf) msurface_t *surf; for (surf = firstsurf;surf;surf = surf->chain) RSurfShader_Water_Pass_Base(surf); - for (surf = firstsurf;surf;surf = surf->chain) - if (surf->currenttexture->glowtexture) - RSurfShader_Water_Pass_Glow(surf); if (fogenabled) for (surf = firstsurf;surf;surf = surf->chain) RSurfShader_Water_Pass_Fog(surf); @@ -1044,6 +1190,112 @@ static void RSurfShader_Water(msurface_t *firstsurf) static void RSurfShader_Wall_Pass_BaseMTex(msurface_t *surf) { +#if 1 + int i; + surfvertex_t *v; + float *outv, *outc, *outst, *outuv, cl, ca, diff[3]; + surfmesh_t *mesh; + rmeshbufferinfo_t m; + memset(&m, 0, sizeof(m)); + if (currentrenderentity->effects & EF_ADDITIVE) + { + m.transparent = true; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE; + } + else if (surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1) + { + m.transparent = true; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + } + else + { + m.transparent = false; + m.blendfunc1 = GL_ONE; + m.blendfunc2 = GL_ZERO; + } + m.depthwrite = false; + m.depthdisable = false; + m.tex[0] = R_GetTexture(surf->currenttexture->texture); + m.tex[1] = R_GetTexture(surf->lightmaptexture); + ca = currentrenderentity->alpha; + for (mesh = surf->mesh;mesh;mesh = mesh->chain) + { + m.numtriangles = mesh->numtriangles; + m.numverts = mesh->numverts; + + if (R_Mesh_Draw_GetBuffer(&m)) + { + cl = (float) (1 << lightscalebit) * m.colorscale; + memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3])); + if (fogenabled) + { + if (softwaretransform_complexity) + { + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2) + { + softwaretransform(v->v, outv); + outv[3] = 1; + VectorSubtract(outv, r_origin, diff); + outc[0] = outc[1] = outc[2] = cl * (1 - exp(fogdensity/DotProduct(diff, diff))); + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; + outuv[0] = v->uv[0]; + outuv[1] = v->uv[1]; + } + } + else + { + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2) + { + VectorCopy(v->v, outv); + outv[3] = 1; + VectorSubtract(outv, r_origin, diff); + outc[0] = outc[1] = outc[2] = cl * (1 - exp(fogdensity/DotProduct(diff, diff))); + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; + outuv[0] = v->uv[0]; + outuv[1] = v->uv[1]; + } + } + } + else + { + if (softwaretransform_complexity) + { + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2) + { + softwaretransform(v->v, outv); + outv[3] = 1; + outc[0] = outc[1] = outc[2] = cl; + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; + outuv[0] = v->uv[0]; + outuv[1] = v->uv[1]; + } + } + else + { + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2) + { + VectorCopy(v->v, outv); + outv[3] = 1; + outc[0] = outc[1] = outc[2] = cl; + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; + outuv[0] = v->uv[0]; + outuv[1] = v->uv[1]; + } + } + } + } + } +#else int i; float diff[3], ifog; surfvertex_t *v; @@ -1134,10 +1386,61 @@ static void RSurfShader_Wall_Pass_BaseMTex(msurface_t *surf) } R_Mesh_Draw(&m); } +#endif } static void RSurfShader_Wall_Pass_BaseTexture(msurface_t *surf) { +#if 1 + int i; + surfvertex_t *v; + float *outv, *outc, *outst, cl, ca; + surfmesh_t *mesh; + rmeshbufferinfo_t m; + memset(&m, 0, sizeof(m)); + m.transparent = false; + m.blendfunc1 = GL_ONE; + m.blendfunc2 = GL_ZERO; + m.depthwrite = false; + m.depthdisable = false; + m.tex[0] = R_GetTexture(surf->currenttexture->texture); + ca = currentrenderentity->alpha; + for (mesh = surf->mesh;mesh;mesh = mesh->chain) + { + m.numtriangles = mesh->numtriangles; + m.numverts = mesh->numverts; + + if (R_Mesh_Draw_GetBuffer(&m)) + { + cl = (float) (1 << lightscalebit) * m.colorscale; + memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3])); + if (softwaretransform_complexity) + { + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) + { + softwaretransform(v->v, outv); + outv[3] = 1; + outc[0] = outc[1] = outc[2] = cl; + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; + } + } + else + { + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) + { + VectorCopy(v->v, outv); + outv[3] = 1; + outc[0] = outc[1] = outc[2] = cl; + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; + } + } + } + } +#else int i; surfvertex_t *v; surfvert_t *sv; @@ -1170,12 +1473,95 @@ static void RSurfShader_Wall_Pass_BaseTexture(msurface_t *surf) m.vertex = &mesh->vertex->v[0]; m.vertexstep = sizeof(surfvertex_t); } - R_Mesh_Draw(&m); + R_Mesh_Draw(&m); + } +#endif +} + +static void RSurfShader_Wall_Pass_BaseLightmap(msurface_t *surf) +{ +#if 1 + int i; + surfvertex_t *v; + float *outv, *outc, *outuv, cl, ca, diff[3]; + surfmesh_t *mesh; + rmeshbufferinfo_t m; + memset(&m, 0, sizeof(m)); + m.transparent = false; + m.blendfunc1 = GL_ZERO; + m.blendfunc2 = GL_SRC_COLOR; + m.depthwrite = false; + m.depthdisable = false; + m.tex[0] = R_GetTexture(surf->lightmaptexture); + ca = currentrenderentity->alpha; + for (mesh = surf->mesh;mesh;mesh = mesh->chain) + { + m.numtriangles = mesh->numtriangles; + m.numverts = mesh->numverts; + + if (R_Mesh_Draw_GetBuffer(&m)) + { + cl = (float) (1 << lightscalebit) * m.colorscale; + memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3])); + if (fogenabled) + { + if (softwaretransform_complexity) + { + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outuv = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outuv += 2) + { + softwaretransform(v->v, outv); + outv[3] = 1; + VectorSubtract(outv, r_origin, diff); + outc[0] = outc[1] = outc[2] = cl * (1 - exp(fogdensity/DotProduct(diff, diff))); + outc[3] = ca; + outuv[0] = v->uv[0]; + outuv[1] = v->uv[1]; + } + } + else + { + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outuv = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outuv += 2) + { + VectorCopy(v->v, outv); + outv[3] = 1; + VectorSubtract(outv, r_origin, diff); + outc[0] = outc[1] = outc[2] = cl * (1 - exp(fogdensity/DotProduct(diff, diff))); + outc[3] = ca; + outuv[0] = v->uv[0]; + outuv[1] = v->uv[1]; + } + } + } + else + { + if (softwaretransform_complexity) + { + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outuv = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outuv += 2) + { + softwaretransform(v->v, outv); + outv[3] = 1; + outc[0] = outc[1] = outc[2] = cl; + outc[3] = ca; + outuv[0] = v->uv[0]; + outuv[1] = v->uv[1]; + } + } + else + { + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outuv = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outuv += 2) + { + VectorCopy(v->v, outv); + outv[3] = 1; + outc[0] = outc[1] = outc[2] = cl; + outc[3] = ca; + outuv[0] = v->uv[0]; + outuv[1] = v->uv[1]; + } + } + } + } } -} - -static void RSurfShader_Wall_Pass_BaseLightmap(msurface_t *surf) -{ +#else int i; float diff[3], ifog; surfvertex_t *v; @@ -1248,10 +1634,155 @@ static void RSurfShader_Wall_Pass_BaseLightmap(msurface_t *surf) } R_Mesh_Draw(&m); } +#endif } static void RSurfShader_Wall_Pass_BaseVertex(msurface_t *surf) { +#if 1 + int i, size3; + surfvertex_t *v; + float *outv, *outc, *outst, *outuv, cl, ca, diff[3]; + float base[3], scale, f; + qbyte *lm; + surfmesh_t *mesh; + rmeshbufferinfo_t m; + memset(&m, 0, sizeof(m)); + if (currentrenderentity->effects & EF_ADDITIVE) + { + m.transparent = true; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE; + } + else if (surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1) + { + m.transparent = true; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + } + else + { + m.transparent = false; + m.blendfunc1 = GL_ONE; + m.blendfunc2 = GL_ZERO; + } + m.depthwrite = false; + m.depthdisable = false; + m.tex[0] = R_GetTexture(surf->currenttexture->texture); + + size3 = ((surf->extents[0]>>4)+1)*((surf->extents[1]>>4)+1)*3; + + base[0] = base[1] = base[2] = currentrenderentity->effects & EF_FULLBRIGHT ? 2.0f : r_ambient.value * (1.0f / 64.0f); + + ca = currentrenderentity->alpha; + for (mesh = surf->mesh;mesh;mesh = mesh->chain) + { + m.numtriangles = mesh->numtriangles; + m.numverts = mesh->numverts; + + if (R_Mesh_Draw_GetBuffer(&m)) + { + cl = m.colorscale; + memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3])); + + if (currentrenderentity->effects & EF_FULLBRIGHT) + { + if (softwaretransform_complexity) + { + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2) + { + softwaretransform(v->v, outv); + outv[3] = 1; + VectorSubtract(outv, r_origin, diff); + outc[0] = outc[1] = outc[2] = 2.0f * cl * (1 - exp(fogdensity/DotProduct(diff, diff))); + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; + } + } + else + { + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2) + { + VectorCopy(v->v, outv); + outv[3] = 1; + VectorSubtract(outv, r_origin, diff); + outc[0] = outc[1] = outc[2] = 2.0f * cl * (1 - exp(fogdensity/DotProduct(diff, diff))); + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; + } + } + } + else + { + if (softwaretransform_complexity) + { + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2) + { + softwaretransform(v->v, outv); + outv[3] = 1; + VectorCopy(base, outc); + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; + } + } + else + { + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2) + { + VectorCopy(v->v, outv); + outv[3] = 1; + VectorCopy(base, outc); + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; + } + } + + if (surf->dlightframe == r_framecount) + RSurf_LightSeparate(surf->dlightbits, m.numverts, m.vertex, m.color); + + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color;i < m.numverts;i++, v++, outv += 4, outc += 4) + { + if (surf->styles[0] != 255) + { + lm = surf->samples + v->lightmapoffset; + scale = d_lightstylevalue[surf->styles[0]] * (1.0f / 32768.0f); + VectorMA(outc, scale, lm, outc); + if (surf->styles[1] != 255) + { + lm += size3; + scale = d_lightstylevalue[surf->styles[1]] * (1.0f / 32768.0f); + VectorMA(outc, scale, lm, outc); + if (surf->styles[2] != 255) + { + lm += size3; + scale = d_lightstylevalue[surf->styles[2]] * (1.0f / 32768.0f); + VectorMA(outc, scale, lm, outc); + if (surf->styles[3] != 255) + { + lm += size3; + scale = d_lightstylevalue[surf->styles[3]] * (1.0f / 32768.0f); + VectorMA(outc, scale, lm, outc); + } + } + } + } + if (fogenabled) + { + VectorSubtract(outv, r_origin, diff); + f = cl * (1 - exp(fogdensity/DotProduct(diff, diff))); + VectorScale(outc, f, outc); + } + else + VectorScale(outc, cl, outc); + } + } + } + } +#else int i, size3; float c[3], base[3], scale, diff[3], ifog; surfvertex_t *v; @@ -1262,7 +1793,7 @@ static void RSurfShader_Wall_Pass_BaseVertex(msurface_t *surf) size3 = ((surf->extents[0]>>4)+1)*((surf->extents[1]>>4)+1)*3; - base[0] = base[1] = base[2] = r_ambient.value * (1.0f / 128.0f); + base[0] = base[1] = base[2] = currentrenderentity->effects & EF_FULLBRIGHT ? 2.0f : r_ambient.value * (1.0f / 128.0f); memset(&m, 0, sizeof(m)); if (currentrenderentity->effects & EF_ADDITIVE) @@ -1343,10 +1874,108 @@ static void RSurfShader_Wall_Pass_BaseVertex(msurface_t *surf) } R_Mesh_Draw(&m); } +#endif } static void RSurfShader_Wall_Pass_BaseFullbright(msurface_t *surf) { +#if 1 + int i; + surfvertex_t *v; + float *outv, *outc, *outst, cl, ca, diff[3]; + surfmesh_t *mesh; + rmeshbufferinfo_t m; + memset(&m, 0, sizeof(m)); + if (currentrenderentity->effects & EF_ADDITIVE) + { + m.transparent = true; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE; + } + else if (surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1) + { + m.transparent = true; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + } + else + { + m.transparent = false; + m.blendfunc1 = GL_ONE; + m.blendfunc2 = GL_ZERO; + } + m.depthwrite = false; + m.depthdisable = false; + m.tex[0] = R_GetTexture(surf->currenttexture->texture); + ca = currentrenderentity->alpha; + for (mesh = surf->mesh;mesh;mesh = mesh->chain) + { + m.numtriangles = mesh->numtriangles; + m.numverts = mesh->numverts; + + if (R_Mesh_Draw_GetBuffer(&m)) + { + cl = m.colorscale; + memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3])); + if (fogenabled) + { + if (softwaretransform_complexity) + { + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) + { + softwaretransform(v->v, outv); + outv[3] = 1; + VectorSubtract(outv, r_origin, diff); + outc[0] = outc[1] = outc[2] = cl * (1 - exp(fogdensity/DotProduct(diff, diff))); + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; + } + } + else + { + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) + { + VectorCopy(v->v, outv); + outv[3] = 1; + VectorSubtract(outv, r_origin, diff); + outc[0] = outc[1] = outc[2] = cl * (1 - exp(fogdensity/DotProduct(diff, diff))); + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; + } + } + } + else + { + if (softwaretransform_complexity) + { + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) + { + softwaretransform(v->v, outv); + outv[3] = 1; + outc[0] = outc[1] = outc[2] = cl; + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; + } + } + else + { + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) + { + VectorCopy(v->v, outv); + outv[3] = 1; + outc[0] = outc[1] = outc[2] = cl; + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; + } + } + } + } + } +#else int i; float diff[3], ifog; surfvertex_t *v; @@ -1407,10 +2036,83 @@ static void RSurfShader_Wall_Pass_BaseFullbright(msurface_t *surf) } R_Mesh_Draw(&m); } +#endif } static void RSurfShader_Wall_Pass_Light(msurface_t *surf) { +#if 1 + int i; + surfvertex_t *v; + float *outv, *outc, *outst, *outuv, cl, ca, diff[3], f; + surfmesh_t *mesh; + rmeshbufferinfo_t m; + + if (surf->dlightframe != r_framecount) + return; + if (currentrenderentity->effects & EF_FULLBRIGHT) + return; + + memset(&m, 0, sizeof(m)); + if (currentrenderentity->effects & EF_ADDITIVE) + { + m.transparent = true; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE; + } + else if (surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1) + { + m.transparent = true; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + } + else + { + m.transparent = false; + m.blendfunc1 = GL_ONE; + m.blendfunc2 = GL_ZERO; + } + m.depthwrite = false; + m.depthdisable = false; + m.tex[0] = R_GetTexture(surf->currenttexture->texture); + ca = currentrenderentity->alpha; + for (mesh = surf->mesh;mesh;mesh = mesh->chain) + { + if (RSurf_LightCheck(surf->dlightbits, mesh)) + { + m.numtriangles = mesh->numtriangles; + m.numverts = mesh->numverts; + + if (R_Mesh_Draw_GetBuffer(&m)) + { + cl = m.colorscale; + memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3])); + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2) + { + softwaretransform(v->v, outv); + outv[3] = 1; + VectorClear(outc); + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; + } + RSurf_LightSeparate(surf->dlightbits, m.numverts, m.vertex, m.color); + if (fogenabled) + { + for (i = 0, outv = m.vertex, outc = m.color;i < m.numverts;i++, outv += 4, outc += 4) + { + VectorSubtract(outv, r_origin, diff); + f = cl * (1 - exp(fogdensity/DotProduct(diff, diff))); + VectorScale(outc, f, outc); + } + } + else if (cl != 1) + for (i = 0, outc = m.color;i < m.numverts;i++, outc += 4) + VectorScale(outc, cl, outc); + } + } + } +#else int i; float diff[3], ifog; surfvertex_t *v; @@ -1463,10 +2165,60 @@ static void RSurfShader_Wall_Pass_Light(msurface_t *surf) R_Mesh_Draw(&m); } } +#endif } static void RSurfShader_Wall_Pass_Glow(msurface_t *surf) { +#if 1 + int i; + surfvertex_t *v; + float *outv, *outc, *outst, cl, ca, diff[3]; + surfmesh_t *mesh; + rmeshbufferinfo_t m; + memset(&m, 0, sizeof(m)); + m.transparent = currentrenderentity->effects & EF_ADDITIVE || surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE; + m.tex[0] = R_GetTexture(surf->currenttexture->glowtexture); + ca = currentrenderentity->alpha; + for (mesh = surf->mesh;mesh;mesh = mesh->chain) + { + m.numtriangles = mesh->numtriangles; + m.numverts = mesh->numverts; + + if (R_Mesh_Draw_GetBuffer(&m)) + { + cl = m.colorscale; + memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3])); + if (fogenabled) + { + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) + { + softwaretransform(v->v, outv); + outv[3] = 1; + VectorSubtract(outv, r_origin, diff); + outc[0] = outc[1] = outc[2] = cl * (1 - exp(fogdensity/DotProduct(diff, diff))); + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; + } + } + else + { + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) + { + softwaretransform(v->v, outv); + outv[3] = 1; + outc[0] = outc[1] = outc[2] = cl; + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; + } + } + } + } +#else int i; float diff[3], ifog; surfvertex_t *v; @@ -1475,12 +2227,7 @@ static void RSurfShader_Wall_Pass_Glow(msurface_t *surf) rmeshinfo_t m; memset(&m, 0, sizeof(m)); - if (currentrenderentity->effects & EF_ADDITIVE) - m.transparent = true; - else if (surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1) - m.transparent = true; - else - m.transparent = false; + m.transparent = currentrenderentity->effects & EF_ADDITIVE || surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1; m.blendfunc1 = GL_SRC_ALPHA; m.blendfunc2 = GL_ONE; m.cr = 1; @@ -1546,10 +2293,63 @@ static void RSurfShader_Wall_Pass_Glow(msurface_t *surf) } R_Mesh_Draw(&m); } +#endif } static void RSurfShader_Wall_Pass_Fog(msurface_t *surf) { +#if 1 + int i; + surfvertex_t *v; + float *outv, *outc, *outst, cl, ca, diff[3], f; + surfmesh_t *mesh; + rmeshbufferinfo_t m; + memset(&m, 0, sizeof(m)); + m.transparent = currentrenderentity->effects & EF_ADDITIVE || surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE; + ca = currentrenderentity->alpha; + for (mesh = surf->mesh;mesh;mesh = mesh->chain) + { + m.numtriangles = mesh->numtriangles; + m.numverts = mesh->numverts; + + if (R_Mesh_Draw_GetBuffer(&m)) + { + cl = m.colorscale; + memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3])); + if (softwaretransform_complexity) + { + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) + { + softwaretransform(v->v, outv); + outv[3] = 1; + VectorSubtract(outv, r_origin, diff); + f = cl * exp(fogdensity/DotProduct(diff, diff)); + VectorScale(fogcolor, f, outc); + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; + } + } + else + { + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) + { + VectorCopy(v->v, outv); + outv[3] = 1; + VectorSubtract(outv, r_origin, diff); + VectorSubtract(outv, r_origin, diff); + f = cl * exp(fogdensity/DotProduct(diff, diff)); + VectorScale(fogcolor, f, outc); + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; + } + } + } + } +#else int i; surfvertex_t *v; surfvert_t *sv; @@ -1558,12 +2358,7 @@ static void RSurfShader_Wall_Pass_Fog(msurface_t *surf) vec3_t diff; memset(&m, 0, sizeof(m)); - if (currentrenderentity->effects & EF_ADDITIVE) - m.transparent = true; - else if (surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1) - m.transparent = true; - else - m.transparent = false; + m.transparent = currentrenderentity->effects & EF_ADDITIVE || surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1; m.blendfunc1 = GL_SRC_ALPHA; m.blendfunc2 = GL_ONE; m.color = &svert[0].c[0]; @@ -1605,6 +2400,7 @@ static void RSurfShader_Wall_Pass_Fog(msurface_t *surf) } R_Mesh_Draw(&m); } +#endif } static void RSurfShader_Wall_Fullbright(msurface_t *firstsurf) diff --git a/menu.c b/menu.c index 8e367d22..f1f76853 100644 --- a/menu.c +++ b/menu.c @@ -1467,7 +1467,7 @@ void M_Menu_Options_Effects_f (void) extern cvar_t cl_particles; extern cvar_t cl_explosions; extern cvar_t cl_stainmaps; -extern cvar_t r_lightmodels; +extern cvar_t r_modellights; extern cvar_t cl_particles_bulletimpacts; extern cvar_t cl_particles_smoke; extern cvar_t cl_particles_sparks; @@ -1483,7 +1483,7 @@ void M_Menu_Options_Effects_AdjustSliders (int dir) switch (options_effects_cursor) { case 0: - Cvar_SetValueQuick (&r_lightmodels, !r_lightmodels.integer); + Cvar_SetValueQuick (&r_modellights, bound(0, r_modellights.value + dir, 8)); break; case 1: Cvar_SetValueQuick (&cl_particles, !cl_particles.integer); @@ -1528,7 +1528,7 @@ void M_Options_Effects_Draw (void) M_DrawPic((320-p->width)/2, 4, "gfx/p_option.lmp"); y = 32; - M_Print(16, y, " Model Lighting");M_DrawCheckbox(220, y, r_lightmodels.integer);y += 8; + M_Print(16, y, " Lights Per Model");M_DrawSlider(220, y, r_modellights.value / 8);y += 8; M_Print(16, y, " Particles");M_DrawCheckbox(220, y, cl_particles.integer);y += 8; M_Print(16, y, " Explosions");M_DrawCheckbox(220, y, cl_explosions.integer);y += 8; M_Print(16, y, " Stainmaps");M_DrawCheckbox(220, y, cl_stainmaps.integer);y += 8; diff --git a/r_light.c b/r_light.c index fd18b086..5f9ef7f8 100644 --- a/r_light.c +++ b/r_light.c @@ -25,7 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. rdlight_t r_dlight[MAX_DLIGHTS]; int r_numdlights = 0; -cvar_t r_lightmodels = {CVAR_SAVE, "r_lightmodels", "1"}; +cvar_t r_modellights = {CVAR_SAVE, "r_modellights", "4"}; cvar_t r_vismarklights = {0, "r_vismarklights", "1"}; static rtexture_t *lightcorona; @@ -66,7 +66,7 @@ void r_light_newmap(void) void R_Light_Init(void) { - Cvar_RegisterVariable(&r_lightmodels); + Cvar_RegisterVariable(&r_modellights); Cvar_RegisterVariable(&r_vismarklights); R_RegisterModule("R_Light", r_light_start, r_light_shutdown, r_light_newmap); } @@ -101,9 +101,9 @@ void R_AnimateLight (void) void R_BuildLightList(void) { - int i; - dlight_t *cd; - rdlight_t *rd; + int i; + dlight_t *cd; + rdlight_t *rd; r_numdlights = 0; c_dlights = 0; @@ -118,13 +118,13 @@ void R_BuildLightList(void) continue; rd = &r_dlight[r_numdlights++]; VectorCopy(cd->origin, rd->origin); - VectorScale(cd->color, cd->radius * 128.0f, rd->light); - rd->cullradius = (1.0f / 128.0f) * sqrt(DotProduct(rd->light, rd->light)); + VectorScale(cd->color, cd->radius * 64.0f, rd->light); + rd->cullradius2 = DotProduct(rd->light, rd->light) * (0.25f / (64.0f * 64.0f)) + 4096.0f; // clamp radius to avoid overflowing division table in lightmap code - if (rd->cullradius > 2048.0f) - rd->cullradius = 2048.0f; - rd->cullradius2 = rd->cullradius * rd->cullradius; - rd->lightsubtract = 1.0f / rd->cullradius2; + if (rd->cullradius2 > (2048.0f * 2048.0f)) + rd->cullradius2 = (2048.0f * 2048.0f); + rd->cullradius = sqrt(rd->cullradius2); + rd->subtract = 1.0f / rd->cullradius2; //rd->ent = cd->ent; r_numdlights++; c_dlights++; // count every dlight in use @@ -215,10 +215,10 @@ R_MarkLights */ static void R_OldMarkLights (vec3_t lightorigin, rdlight_t *rd, int bit, int bitindex, mnode_t *node) { - float ndist, maxdist; - msurface_t *surf; - mleaf_t *leaf; - int i; + float ndist, maxdist; + msurface_t *surf; + mleaf_t *leaf; + int i; if (!r_dynamic.integer) return; @@ -336,12 +336,12 @@ static void R_VisMarkLights (rdlight_t *rd, int bit, int bitindex) mleaf_t *pvsleaf; vec3_t lightorigin; model_t *model; - int i, k, m, c, leafnum; + int i, k, m, c, leafnum; msurface_t *surf, **mark; mleaf_t *leaf; - qbyte *in; - int row; - float low[3], high[3], dist, maxdist; + qbyte *in; + int row; + float low[3], high[3], dist, maxdist; if (!r_dynamic.integer) return; @@ -494,9 +494,9 @@ LIGHT SAMPLING static int RecursiveLightPoint (vec3_t color, mnode_t *node, float x, float y, float startz, float endz) { - int side, distz = endz - startz; - float front, back; - float mid; + int side, distz = endz - startz; + float front, back; + float mid; loc0: if (node->contents < 0) @@ -634,8 +634,8 @@ middle sample (the one which was requested) void R_CompleteLightPoint (vec3_t color, vec3_t p, int dynamic, mleaf_t *leaf) { - int i, *dlightbits; - vec3_t dist; + int i, *dlightbits; + vec3_t v; float f; rdlight_t *rd; mlight_t *sl; @@ -662,19 +662,14 @@ void R_CompleteLightPoint (vec3_t color, vec3_t p, int dynamic, mleaf_t *leaf) sl = cl.worldmodel->lights + i; if (d_lightstylevalue[sl->style] > 0) { - VectorSubtract (p, sl->origin, dist); - f = DotProduct(dist, dist) + sl->distbias; - f = (1.0f / f) - sl->subtract; - if (f > 0) + VectorSubtract (p, sl->origin, v); + f = ((1.0f / (DotProduct(v, v) * sl->falloff + sl->distbias)) - sl->subtract); + if (f > 0 && CL_TraceLine(p, sl->origin, NULL, NULL, 0, false) == 1) { - if (CL_TraceLine(p, sl->origin, NULL, NULL, 0, false) == 1) - { - f *= d_lightstylevalue[sl->style] * (1.0f / 16384.0f); - VectorMA(color, f, sl->light, color); - } + f *= d_lightstylevalue[sl->style] * (1.0f / 65536.0f); + VectorMA(color, f, sl->light, color); } } - } } else @@ -688,13 +683,12 @@ void R_CompleteLightPoint (vec3_t color, vec3_t p, int dynamic, mleaf_t *leaf) if (!(dlightbits[i >> 5] & (1 << (i & 31)))) continue; rd = r_dlight + i; - VectorSubtract (p, rd->origin, dist); - f = DotProduct(dist, dist) + LIGHTOFFSET; + VectorSubtract (p, rd->origin, v); + f = DotProduct(v, v); if (f < rd->cullradius2) { - f = (1.0f / f) - rd->lightsubtract; - if (f > 0) - VectorMA(color, f, rd->light, color); + f = (1.0f / (f + LIGHTOFFSET)) - rd->subtract; + VectorMA(color, f, rd->light, color); } } } @@ -711,7 +705,7 @@ void R_ModelLightPoint (vec3_t color, vec3_t p, int *dlightbits) return; } - if (r_fullbright.integer || !cl.worldmodel->lightdata) + if (r_fullbright.integer || !cl.worldmodel->lightdata || currentrenderentity->effects & EF_FULLBRIGHT) { color[0] = color[1] = color[2] = 2; dlightbits[0] = dlightbits[1] = dlightbits[2] = dlightbits[3] = dlightbits[4] = dlightbits[5] = dlightbits[6] = dlightbits[7] = 0; @@ -739,128 +733,149 @@ void R_ModelLightPoint (vec3_t color, vec3_t p, int *dlightbits) void R_LightModel(int numverts, float colorr, float colorg, float colorb, int worldcoords) { - int i, j, nearlights = 0; - float color[3], basecolor[3], v[3], t, *av, *avn, *avc, a, f, dist2, mscale, dot; + int i, j, nearlights = 0, maxnearlights = r_modellights.integer; + float color[3], basecolor[3], v[3], t, *av, *avn, *avc, a, f, dist2, mscale, dot, stylescale, intensity, ambientcolor[3]; struct { vec3_t origin; //vec_t cullradius2; vec3_t light; - vec_t lightsubtract; + // how much this light would contribute to ambient if replaced + vec3_t ambientlight; + vec_t subtract; vec_t falloff; vec_t offset; + // used for choosing only the brightest lights + vec_t intensity; } nearlight[MAX_DLIGHTS], *nl; int modeldlightbits[8]; mlight_t *sl; + rdlight_t *rd; a = currentrenderentity->alpha; // scale of the model's coordinate space, to alter light attenuation to match // make the mscale squared so it can scale the squared distance results mscale = currentrenderentity->scale * currentrenderentity->scale; - if (r_fullbright.integer || r_ambient.value > 128.0f || currentrenderentity->effects & EF_FULLBRIGHT) + if ((maxnearlights != 0) && !r_fullbright.integer && !(currentrenderentity->effects & EF_FULLBRIGHT)) { - basecolor[0] = colorr * 2.0f; - basecolor[1] = colorg * 2.0f; - basecolor[2] = colorb * 2.0f; - } - else - { - if (r_lightmodels.integer) - { - R_ModelLightPoint(basecolor, currentrenderentity->origin, modeldlightbits); + R_ModelLightPoint(basecolor, currentrenderentity->origin, modeldlightbits); - nl = &nearlight[0]; - VectorSubtract(currentrenderentity->origin, currentrenderentity->entlightsorigin, v); - if ((realtime > currentrenderentity->entlightstime && DotProduct(v,v) >= 1.0f) || currentrenderentity->numentlights >= MAXENTLIGHTS) + nl = &nearlight[0]; + VectorSubtract(currentrenderentity->origin, currentrenderentity->entlightsorigin, v); + if ((realtime > currentrenderentity->entlightstime && DotProduct(v,v) >= 1.0f)) + { + currentrenderentity->numentlights = 0; + currentrenderentity->entlightstime = realtime + 0.2; + VectorCopy(currentrenderentity->origin, currentrenderentity->entlightsorigin); + for (i = 0, sl = cl.worldmodel->lights;i < cl.worldmodel->numlights && currentrenderentity->numentlights < MAXENTLIGHTS;i++, sl++) + if (CL_TraceLine(currentrenderentity->origin, sl->origin, NULL, NULL, 0, false) == 1) + currentrenderentity->entlights[currentrenderentity->numentlights++] = i; + } + for (i = 0;i < currentrenderentity->numentlights;i++) + { + sl = cl.worldmodel->lights + currentrenderentity->entlights[i]; + stylescale = d_lightstylevalue[sl->style] * (1.0f / 65536.0f); + VectorSubtract (currentrenderentity->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 { - currentrenderentity->numentlights = 0; - currentrenderentity->entlightstime = realtime + 0.2; - VectorCopy(currentrenderentity->origin, currentrenderentity->entlightsorigin); - for (i = 0, sl = cl.worldmodel->lights;i < cl.worldmodel->numlights && nearlights < MAX_DLIGHTS;i++, sl++) + for (j = 0;j < maxnearlights;j++) { - if (CL_TraceLine(currentrenderentity->origin, sl->origin, NULL, NULL, 0, false) == 1) + if (nearlight[j].intensity < intensity) { - if (currentrenderentity->numentlights < MAXENTLIGHTS) - currentrenderentity->entlights[currentrenderentity->numentlights++] = i; - - // integrate mscale into falloff, for maximum speed - nl->falloff = mscale * sl->falloff; - // transform the light into the model's coordinate system - if (worldcoords) - VectorCopy(sl->origin, nl->origin); - else - softwareuntransform(sl->origin, nl->origin); - f = d_lightstylevalue[sl->style] * (1.0f / 65536.0f); - nl->light[0] = sl->light[0] * f * colorr; - nl->light[1] = sl->light[1] * f * colorg; - nl->light[2] = sl->light[2] * f * colorb; - //nl->cullradius2 = 99999999; - nl->lightsubtract = sl->subtract; - nl->offset = sl->distbias; - nl++; - nearlights++; + 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 { - for (i = 0;i < currentrenderentity->numentlights && nearlights < MAX_DLIGHTS;i++) - { - sl = cl.worldmodel->lights + currentrenderentity->entlights[i]; - - // integrate mscale into falloff, for maximum speed - nl->falloff = mscale * sl->falloff; - // transform the light into the model's coordinate system - if (worldcoords) - VectorCopy(sl->origin, nl->origin); - else - softwareuntransform(sl->origin, nl->origin); - f = d_lightstylevalue[sl->style] * (1.0f / 65536.0f); - nl->light[0] = sl->light[0] * f * colorr; - nl->light[1] = sl->light[1] * f * colorg; - nl->light[2] = sl->light[2] * f * colorb; - //nl->cullradius2 = 99999999; - nl->lightsubtract = sl->subtract; - nl->offset = sl->distbias; - nl++; - nearlights++; - } + nl = nearlight + j; + nl->intensity = intensity; + // transform the light into the model's coordinate system + if (worldcoords) + VectorCopy(sl->origin, nl->origin); + else + softwareuntransform(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 && nearlights < MAX_DLIGHTS;i++) + } + for (i = 0;i < r_numdlights;i++) + { + if (!(modeldlightbits[i >> 5] & (1 << (i & 31)))) + continue; + rd = r_dlight + i; + VectorSubtract (currentrenderentity->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 { - if (!(modeldlightbits[i >> 5] & (1 << (i & 31)))) - continue; - /* - if (currentrenderentity == r_dlight[i].ent) + for (j = 0;j < maxnearlights;j++) { - f = (1.0f / LIGHTOFFSET) - nl->lightsubtract; - if (f > 0) - VectorMA(basecolor, f, r_dlight[i].light, basecolor); + 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 - { - */ - // transform the light into the model's coordinate system - if (worldcoords) - VectorCopy(r_dlight[i].origin, nl->origin); - else - softwareuntransform(r_dlight[i].origin, nl->origin); - // integrate mscale into falloff, for maximum speed - nl->falloff = mscale; - // scale the cullradius so culling by distance is done before mscale is applied - //nl->cullradius2 = r_dlight[i].cullradius2 * currentrenderentity->scale * currentrenderentity->scale; - nl->light[0] = r_dlight[i].light[0] * colorr; - nl->light[1] = r_dlight[i].light[1] * colorg; - nl->light[2] = r_dlight[i].light[2] * colorb; - nl->lightsubtract = r_dlight[i].lightsubtract; - nl->offset = LIGHTOFFSET; - nl++; - nearlights++; - //} + softwareuntransform(rd->origin, nl->origin); + // 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, currentrenderentity->origin, true, NULL); + } + else + { + R_CompleteLightPoint (basecolor, currentrenderentity->origin, true, NULL); } basecolor[0] *= colorr; basecolor[1] *= colorg; @@ -884,7 +899,7 @@ void R_LightModel(int numverts, float colorr, float colorg, float colorb, int wo // do the distance attenuation dist2 = DotProduct(v,v); - f = (1.0f / (dist2 * nl->falloff + nl->offset)) - nl->lightsubtract; + f = (1.0f / (dist2 * nl->falloff + nl->offset)) - nl->subtract; if (f > 0) { #if SLOWMATH @@ -901,7 +916,7 @@ void R_LightModel(int numverts, float colorr, float colorg, float colorb, int wo // the hardness variables are for backlighting/shinyness // these have been hardwired at * 0.5 + 0.5 to match // the quake map lighting utility's equations - f *= dot * t * 0.5f + 0.5f;// * hardness + hardnessoffset; + f *= dot * t;// * 0.5f + 0.5f;// * hardness + hardnessoffset; VectorMA(color, f, nl->light, color); } } diff --git a/r_light.h b/r_light.h index 1c28cb7f..cc63e8bb 100644 --- a/r_light.h +++ b/r_light.h @@ -8,7 +8,7 @@ typedef struct vec_t cullradius2; // only for culling comparisons, squared version vec3_t light; // the brightness of the light vec_t cullradius; // only for culling comparisons - vec_t lightsubtract; // to avoid sudden brightness change at cullradius, subtract this + vec_t subtract; // to avoid sudden brightness change at cullradius, subtract this // entity_render_t *ent; // owner of this light } rdlight_t;