From e4a2461faffcf9d1f354dfef1751ad049ed9cfd6 Mon Sep 17 00:00:00 2001 From: "James R." Date: Sun, 10 Sep 2023 05:52:50 -0700 Subject: [PATCH 1/5] WIP - brightmaps in opengl, artifacts may occur, batching is super broken --- src/hardware/hw_cache.c | 49 ++++++++++++++++++++++++++++++-- src/hardware/hw_defs.h | 1 + src/hardware/r_opengl/r_opengl.c | 44 ++++++++++++++++++++++++---- 3 files changed, 86 insertions(+), 8 deletions(-) diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 0cb7da14b..bd04cbdcb 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -443,7 +443,7 @@ static UINT8 *MakeBlock(GLMipmap_t *grMipmap) // Create a composite texture from patches, adapt the texture size to a power of 2 // height and width for the hardware texture cache. // -static void HWR_GenerateTexture(INT32 texnum, INT32 basetexnum, GLMapTexture_t *grtex) +static void HWR_GenerateTexture(GLMapTexture_t *grtex, INT32 texnum, boolean noencoremap) { UINT8 *block; texture_t *texture; @@ -477,7 +477,7 @@ static void HWR_GenerateTexture(INT32 texnum, INT32 basetexnum, GLMapTexture_t * grtex->mipmap.height = (UINT16)texture->height; grtex->mipmap.format = textureformat; - if (encoremap && R_TextureCanRemap(basetexnum)) + if (!noencoremap && encoremap) colormap += COLORMAP_REMAPOFFSET; grtex->mipmap.colormap = Z_Calloc(sizeof(*grtex->mipmap.colormap), PU_HWRPATCHCOLMIPMAP, NULL); @@ -797,7 +797,7 @@ GLMapTexture_t *HWR_GetTexture(INT32 tex, INT32 basetex) // Generate texture if missing from the cache if (!grtex->mipmap.data && !grtex->mipmap.downloaded) - HWR_GenerateTexture(tex, basetex, grtex); + HWR_GenerateTexture(grtex, tex, !R_TextureCanRemap(basetex)); // If hardware does not have the texture, then call pfnSetTexture to upload it if (!grtex->mipmap.downloaded) @@ -807,6 +807,29 @@ GLMapTexture_t *HWR_GetTexture(INT32 tex, INT32 basetex) // The system-memory data can be purged now. Z_ChangeTag(grtex->mipmap.data, PU_HWRCACHE_UNLOCKED); + if (R_GetTextureBrightmap(tex)) + { + GLMapTexture_t *grtexbright; + + // Every texture in memory, stored in the + // hardware renderer's bit depth format. Wow! + grtexbright = &gl_textures[R_GetTextureBrightmap(tex)]; + + // Generate texture if missing from the cache + if (!grtexbright->mipmap.data && !grtexbright->mipmap.downloaded) + HWR_GenerateTexture(grtexbright, R_GetTextureBrightmap(tex), true); + + grtexbright->mipmap.flags |= TF_BRIGHTMAP; + + // If hardware does not have the texture, then call pfnSetTexture to upload it + if (!grtexbright->mipmap.downloaded) + HWD.pfnSetTexture(&grtexbright->mipmap); + HWR_SetCurrentTexture(&grtexbright->mipmap); + + // The system-memory data can be purged now. + Z_ChangeTag(grtexbright->mipmap.data, PU_HWRCACHE_UNLOCKED); + } + return grtex; } @@ -966,6 +989,26 @@ void HWR_GetLevelFlat(levelflat_t *levelflat, boolean noencoremap) // The system-memory data can be purged now. Z_ChangeTag(grtex->mipmap.data, PU_HWRCACHE_UNLOCKED); + + if ((texturenum = R_GetTextureBrightmap(texturenum))) + { + // Every texture in memory, stored as a 8-bit flat. Wow! + grtex = &gl_flats[texturenum]; + + // Generate flat if missing from the cache + if (!grtex->mipmap.data && !grtex->mipmap.downloaded) + HWR_CacheTextureAsFlat(&grtex->mipmap, texturenum, true); + + grtex->mipmap.flags |= TF_BRIGHTMAP; + + // If hardware does not have the texture, then call pfnSetTexture to upload it + if (!grtex->mipmap.downloaded) + HWD.pfnSetTexture(&grtex->mipmap); + HWR_SetCurrentTexture(&grtex->mipmap); + + // The system-memory data can be purged now. + Z_ChangeTag(grtex->mipmap.data, PU_HWRCACHE_UNLOCKED); + } } else if (levelflat->type == LEVELFLAT_PATCH) { diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 2738cc28f..e631604cb 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -258,6 +258,7 @@ enum ETextureFlags TF_WRAPXY = TF_WRAPY|TF_WRAPX, // very common so use alias is more easy TF_CHROMAKEYED = 0x00000010, TF_TRANSPARENT = 0x00000040, // texture with some alpha == 0 + TF_BRIGHTMAP = 0x00000080, }; struct FTextureInfo diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index ab7d14c06..29a4556cd 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -580,6 +580,10 @@ static PFNglGetUniformLocation pglGetUniformLocation; // 13062019 typedef enum { + // textures + gluniform_tex, + gluniform_brightmap, + // lighting gluniform_poly_color, gluniform_tint_color, @@ -703,7 +707,7 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "}\n" #define GLSL_SOFTWARE_FADE_EQUATION \ - "float darkness = R_DoomLightingEquation(lighting);\n" \ + "float darkness = R_DoomLightingEquation(lighting + light_gain);\n" \ "if (fade_start != 0.0 || fade_end != 31.0) {\n" \ "float fs = fade_start / 31.0;\n" \ "float fe = fade_end / 31.0;\n" \ @@ -746,6 +750,7 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; #define GLSL_SOFTWARE_FRAGMENT_SHADER \ "uniform sampler2D tex;\n" \ + "uniform sampler2D brightmap;\n" \ "uniform vec4 poly_color;\n" \ "uniform vec4 tint_color;\n" \ "uniform vec4 fade_color;\n" \ @@ -758,6 +763,7 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ "vec4 base_color = texel * poly_color;\n" \ "vec4 final_color = base_color;\n" \ + "float light_gain = (255.0 - lighting) * floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \ GLSL_SOFTWARE_TINT_EQUATION \ GLSL_SOFTWARE_FADE_EQUATION \ "final_color.a = texel.a * poly_color.a;\n" \ @@ -768,6 +774,7 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; // accompanying vertex shader (stored in gl_Color) #define GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER \ "uniform sampler2D tex;\n" \ + "uniform sampler2D brightmap;\n" \ "uniform vec4 poly_color;\n" \ "uniform vec4 tint_color;\n" \ "uniform vec4 fade_color;\n" \ @@ -780,6 +787,7 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ "vec4 base_color = texel * poly_color;\n" \ "vec4 final_color = base_color;\n" \ + "float light_gain = (255.0 - lighting) * floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \ GLSL_SOFTWARE_TINT_EQUATION \ GLSL_SOFTWARE_FADE_EQUATION \ "final_color *= gl_Color;\n" \ @@ -796,6 +804,7 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; #define GLSL_WATER_FRAGMENT_SHADER \ "uniform sampler2D tex;\n" \ + "uniform sampler2D brightmap;\n" \ "uniform vec4 poly_color;\n" \ "uniform vec4 tint_color;\n" \ "uniform vec4 fade_color;\n" \ @@ -817,6 +826,7 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "vec4 texel = texture2D(tex, vec2(gl_TexCoord[0].s - sdistort, gl_TexCoord[0].t - cdistort));\n" \ "vec4 base_color = texel * poly_color;\n" \ "vec4 final_color = base_color;\n" \ + "float light_gain = (255.0 - lighting) * floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \ GLSL_SOFTWARE_TINT_EQUATION \ GLSL_SOFTWARE_FADE_EQUATION \ "final_color.a = texel.a * poly_color.a;\n" \ @@ -840,6 +850,7 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "void main(void) {\n" \ "vec4 base_color = gl_Color;\n" \ "vec4 final_color = base_color;\n" \ + "float light_gain = 0.0;\n" \ GLSL_SOFTWARE_TINT_EQUATION \ GLSL_SOFTWARE_FADE_EQUATION \ "gl_FragColor = final_color;\n" \ @@ -1154,14 +1165,16 @@ EXPORT void HWRAPI(CleanShaders) (void) // -----------------+ // SetNoTexture : Disable texture // -----------------+ -static void SetNoTexture(void) +static void SetNoTexture(GLenum texture) { // Disable texture. if (tex_downloaded != NOTEXTURE_NUM) { if (NOTEXTURE_NUM == 0) pglGenTextures(1, &NOTEXTURE_NUM); + pglActiveTexture(texture); pglBindTexture(GL_TEXTURE_2D, NOTEXTURE_NUM); + pglActiveTexture(GL_TEXTURE0); tex_downloaded = NOTEXTURE_NUM; } } @@ -1307,7 +1320,7 @@ void SetStates(void) SetBlend(0); tex_downloaded = 0; - SetNoTexture(); + SetNoTexture(GL_TEXTURE0); pglPolygonOffset(-1.0f, -1.0f); @@ -1782,7 +1795,7 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) } if (PolyFlags & PF_NoTexture) { - SetNoTexture(); + SetNoTexture(GL_TEXTURE0); } } CurrentPolyFlags = PolyFlags; @@ -1906,6 +1919,12 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) else GL_MSG_Warning("UpdateTexture: bad format %d\n", pTexInfo->format); + if (!(pTexInfo->flags & TF_BRIGHTMAP)) + { + SetNoTexture(GL_TEXTURE1); // will be assigned later, if needed + } + + pglActiveTexture(pTexInfo->flags & TF_BRIGHTMAP ? GL_TEXTURE1 : GL_TEXTURE0); pglBindTexture(GL_TEXTURE_2D, num); tex_downloaded = num; @@ -1996,6 +2015,8 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) if (maximumAnisotropy) pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropic_filter); + + pglActiveTexture(GL_TEXTURE0); } // -----------------+ @@ -2005,14 +2026,21 @@ EXPORT void HWRAPI(SetTexture) (GLMipmap_t *pTexInfo) { if (!pTexInfo) { - SetNoTexture(); + SetNoTexture(GL_TEXTURE0); return; } else if (pTexInfo->downloaded) { if (pTexInfo->downloaded != tex_downloaded) { + if (!(pTexInfo->flags & TF_BRIGHTMAP)) + { + SetNoTexture(GL_TEXTURE1); // will be assigned later, if needed + } + + pglActiveTexture(pTexInfo->flags & TF_BRIGHTMAP ? GL_TEXTURE1 : GL_TEXTURE0); pglBindTexture(GL_TEXTURE_2D, pTexInfo->downloaded); + pglActiveTexture(GL_TEXTURE0); tex_downloaded = pTexInfo->downloaded; } } @@ -2084,6 +2112,8 @@ static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAF function (uniform, a, b, c, d); // polygon + UNIFORM_1(shader->uniforms[gluniform_tex], 0, pglUniform1i); + UNIFORM_1(shader->uniforms[gluniform_brightmap], 1, pglUniform1i); UNIFORM_4(shader->uniforms[gluniform_poly_color], poly->red, poly->green, poly->blue, poly->alpha, pglUniform4f); UNIFORM_4(shader->uniforms[gluniform_tint_color], tint->red, tint->green, tint->blue, tint->alpha, pglUniform4f); UNIFORM_4(shader->uniforms[gluniform_fade_color], fade->red, fade->green, fade->blue, fade->alpha, pglUniform4f); @@ -2183,6 +2213,10 @@ static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i, const GLchar // 13062019 #define GETUNI(uniform) pglGetUniformLocation(shader->program, uniform); + // textures + shader->uniforms[gluniform_tex] = GETUNI("tex"); + shader->uniforms[gluniform_brightmap] = GETUNI("brightmap"); + // lighting shader->uniforms[gluniform_poly_color] = GETUNI("poly_color"); shader->uniforms[gluniform_tint_color] = GETUNI("tint_color"); From d03eb9e9cdcf531895f8955115990f9bf212dd69 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 18 Sep 2023 01:05:36 -0400 Subject: [PATCH 2/5] Add batching support to OGL brightmaps --- src/hardware/hw_batching.c | 101 ++++++++++++++++++++++++++----------- src/hardware/hw_batching.h | 1 + 2 files changed, 72 insertions(+), 30 deletions(-) diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c index b13ad03ea..ad363cefe 100644 --- a/src/hardware/hw_batching.c +++ b/src/hardware/hw_batching.c @@ -17,6 +17,7 @@ // The texture for the next polygon given to HWR_ProcessPolygon. // Set with HWR_SetCurrentTexture. GLMipmap_t *current_texture = NULL; +GLMipmap_t *current_brightmap = NULL; boolean currently_batching = false; @@ -42,10 +43,10 @@ int unsortedVertexArrayAllocSize = 65536; // Call HWR_RenderBatches to render all the collected geometry. void HWR_StartBatching(void) { - if (currently_batching) - I_Error("Repeat call to HWR_StartBatching without HWR_RenderBatches"); + if (currently_batching) + I_Error("Repeat call to HWR_StartBatching without HWR_RenderBatches"); - // init arrays if that has not been done yet + // init arrays if that has not been done yet if (!finalVertexArray) { finalVertexArray = malloc(finalVertexArrayAllocSize * sizeof(FOutVector)); @@ -55,7 +56,7 @@ void HWR_StartBatching(void) unsortedVertexArray = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector)); } - currently_batching = true; + currently_batching = true; } // This replaces the direct calls to pfnSetTexture in cases where batching is available. @@ -63,14 +64,29 @@ void HWR_StartBatching(void) // Doing this was easier than getting a texture pointer to HWR_ProcessPolygon. void HWR_SetCurrentTexture(GLMipmap_t *texture) { - if (currently_batching) - { - current_texture = texture; - } - else - { - HWD.pfnSetTexture(texture); - } + if (currently_batching) + { + if (texture != NULL) + { + if (texture->flags & TF_BRIGHTMAP) + { + current_brightmap = texture; + } + else + { + current_texture = texture; + current_brightmap = NULL; + } + } + else + { + current_texture = current_brightmap = NULL; + } + } + else + { + HWD.pfnSetTexture(texture); + } } // If batching is enabled, this function collects the polygon data and the chosen texture @@ -78,7 +94,7 @@ void HWR_SetCurrentTexture(GLMipmap_t *texture) // render the polygon immediately. void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial) { - if (currently_batching) + if (currently_batching) { if (!pSurf) I_Error("Got a null FSurfaceInfo in batching");// nulls should not come in the stuff that batching currently applies to @@ -114,6 +130,7 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt polygonArray[polygonArraySize].numVerts = iNumPts; polygonArray[polygonArraySize].polyFlags = PolyFlags; polygonArray[polygonArraySize].texture = current_texture; + polygonArray[polygonArraySize].brightmap = current_brightmap; polygonArray[polygonArraySize].shader = shader; polygonArray[polygonArraySize].horizonSpecial = horizonSpecial; polygonArraySize++; @@ -123,10 +140,10 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt } else { - if (shader) - HWD.pfnSetShader(shader); - HWD.pfnDrawPolygon(pSurf, pOutVerts, iNumPts, PolyFlags); - } + if (shader) + HWD.pfnSetShader(shader); + HWD.pfnDrawPolygon(pSurf, pOutVerts, iNumPts, PolyFlags); + } } static int comparePolygons(const void *p1, const void *p2) @@ -161,6 +178,15 @@ static int comparePolygons(const void *p1, const void *p2) diff64 = downloaded1 - downloaded2; if (diff64 != 0) return diff64; + downloaded1 = 0; + downloaded2 = 0; + if (poly1->brightmap) + downloaded1 = poly1->brightmap->downloaded; // there should be a opengl texture name here, usable for comparisons + if (poly2->brightmap) + downloaded2 = poly2->brightmap->downloaded; + diff64 = downloaded1 - downloaded2; + if (diff64 != 0) return diff64; + diff = poly1->polyFlags - poly2->polyFlags; if (diff != 0) return diff; @@ -219,15 +245,17 @@ static int comparePolygonsNoShaders(const void *p1, const void *p2) // the rendering backend to draw them. void HWR_RenderBatches(void) { - int finalVertexWritePos = 0;// position in finalVertexArray + int finalVertexWritePos = 0;// position in finalVertexArray int finalIndexWritePos = 0;// position in finalVertexIndexArray int polygonReadPos = 0;// position in polygonIndexArray int currentShader; int nextShader = 0; - GLMipmap_t *currentTexture; + GLMipmap_t *currentTexture = NULL; GLMipmap_t *nextTexture = NULL; + GLMipmap_t *currentBrightmap = NULL; + GLMipmap_t *nextBrightmap = NULL; FBITFIELD currentPolyFlags = 0; FBITFIELD nextPolyFlags = 0; FSurfaceInfo currentSurfaceInfo; @@ -235,7 +263,7 @@ void HWR_RenderBatches(void) int i; - if (!currently_batching) + if (!currently_batching) I_Error("HWR_RenderBatches called without starting batching"); nextSurfaceInfo.LightInfo.fade_end = 0; @@ -268,14 +296,16 @@ void HWR_RenderBatches(void) // sort order // 1. shader // 2. texture - // 3. polyflags - // 4. colors + light level + // 3. brightmap + // 4. polyflags + // 5. colors + light level // not sure about what order of the last 2 should be, or if it even matters ps_hw_batchdrawtime = I_GetPreciseTime(); currentShader = polygonArray[polygonIndexArray[0]].shader; currentTexture = polygonArray[polygonIndexArray[0]].texture; + currentBrightmap = polygonArray[polygonIndexArray[0]].brightmap; currentPolyFlags = polygonArray[polygonIndexArray[0]].polyFlags; currentSurfaceInfo = polygonArray[polygonIndexArray[0]].surf; // For now, will sort and track the colors. Vertex attributes could be used instead of uniforms @@ -289,9 +319,15 @@ void HWR_RenderBatches(void) } if (currentPolyFlags & PF_NoTexture) - currentTexture = NULL; - else - HWD.pfnSetTexture(currentTexture); + { + currentTexture = currentBrightmap = NULL; + } + else + { + HWD.pfnSetTexture(currentTexture); + if (currentBrightmap) + HWD.pfnSetTexture(currentBrightmap); + } while (1)// note: remember handling notexture polyflag as having texture number 0 (also in comparePolygons) { @@ -361,16 +397,17 @@ void HWR_RenderBatches(void) int nextIndex = polygonIndexArray[polygonReadPos]; nextShader = polygonArray[nextIndex].shader; nextTexture = polygonArray[nextIndex].texture; + nextBrightmap = polygonArray[nextIndex].brightmap; nextPolyFlags = polygonArray[nextIndex].polyFlags; nextSurfaceInfo = polygonArray[nextIndex].surf; if (nextPolyFlags & PF_NoTexture) - nextTexture = 0; + nextTexture = nextBrightmap = 0; if (currentShader != nextShader && cv_glshaders.value && gl_shadersavailable) { changeState = true; changeShader = true; } - if (currentTexture != nextTexture) + if (currentTexture != nextTexture || currentBrightmap != nextBrightmap) { changeState = true; changeTexture = true; @@ -406,7 +443,7 @@ void HWR_RenderBatches(void) if (changeState || stopFlag) { // execute draw call - HWD.pfnDrawIndexedTriangles(¤tSurfaceInfo, finalVertexArray, finalIndexWritePos, currentPolyFlags, finalVertexIndexArray); + HWD.pfnDrawIndexedTriangles(¤tSurfaceInfo, finalVertexArray, finalIndexWritePos, currentPolyFlags, finalVertexIndexArray); // update stats ps_hw_numcalls++; ps_hw_numverts += finalIndexWritePos; @@ -431,10 +468,14 @@ void HWR_RenderBatches(void) if (changeTexture) { // texture should be already ready for use from calls to SetTexture during batch collection - HWD.pfnSetTexture(nextTexture); + HWD.pfnSetTexture(nextTexture); currentTexture = nextTexture; - changeTexture = false; + if (nextBrightmap) + HWD.pfnSetTexture(nextBrightmap); + currentBrightmap = nextBrightmap; + + changeTexture = false; ps_hw_numtextures++; } if (changePolyFlags) diff --git a/src/hardware/hw_batching.h b/src/hardware/hw_batching.h index b7a80d9ce..18bea3ee3 100644 --- a/src/hardware/hw_batching.h +++ b/src/hardware/hw_batching.h @@ -27,6 +27,7 @@ typedef struct FUINT numVerts; FBITFIELD polyFlags; GLMipmap_t *texture; + GLMipmap_t *brightmap; int shader; // this tells batching that the plane belongs to a horizon line and must be drawn in correct order with the skywalls boolean horizonSpecial; From 83e3401806d1232818534871f420096bec309ea5 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 18 Sep 2023 01:26:17 -0400 Subject: [PATCH 3/5] Don't use colormap tint on OGL brightmap --- src/hardware/r_opengl/r_opengl.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 29a4556cd..b6c767043 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -698,9 +698,9 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "}\n" #define GLSL_SOFTWARE_TINT_EQUATION \ - "if (tint_color.a > 0.0) {\n" \ + "if (mix(tint_color.a, 0.0, brightmap_mix) > 0.0) {\n" \ "float color_bright = sqrt((base_color.r * base_color.r) + (base_color.g * base_color.g) + (base_color.b * base_color.b));\n" \ - "float strength = sqrt(9.0 * tint_color.a);\n" \ + "float strength = sqrt(9.0 * mix(tint_color.a, 0.0, brightmap_mix));\n" \ "final_color.r = clamp((color_bright * (tint_color.r * strength)) + (base_color.r * (1.0 - strength)), 0.0, 1.0);\n" \ "final_color.g = clamp((color_bright * (tint_color.g * strength)) + (base_color.g * (1.0 - strength)), 0.0, 1.0);\n" \ "final_color.b = clamp((color_bright * (tint_color.b * strength)) + (base_color.b * (1.0 - strength)), 0.0, 1.0);\n" \ @@ -708,7 +708,7 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; #define GLSL_SOFTWARE_FADE_EQUATION \ "float darkness = R_DoomLightingEquation(lighting + light_gain);\n" \ - "if (fade_start != 0.0 || fade_end != 31.0) {\n" \ + "if (fade_start > 0.0 || fade_end < 31.0) {\n" \ "float fs = fade_start / 31.0;\n" \ "float fe = fade_end / 31.0;\n" \ "float fd = fe - fs;\n" \ @@ -763,7 +763,8 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ "vec4 base_color = texel * poly_color;\n" \ "vec4 final_color = base_color;\n" \ - "float light_gain = (255.0 - lighting) * floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \ + "float brightmap_mix = floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \ + "float light_gain = (255.0 - lighting) * brightmap_mix;\n" \ GLSL_SOFTWARE_TINT_EQUATION \ GLSL_SOFTWARE_FADE_EQUATION \ "final_color.a = texel.a * poly_color.a;\n" \ @@ -787,7 +788,8 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ "vec4 base_color = texel * poly_color;\n" \ "vec4 final_color = base_color;\n" \ - "float light_gain = (255.0 - lighting) * floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \ + "float brightmap_mix = floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \ + "float light_gain = (255.0 - lighting) * brightmap_mix;\n" \ GLSL_SOFTWARE_TINT_EQUATION \ GLSL_SOFTWARE_FADE_EQUATION \ "final_color *= gl_Color;\n" \ @@ -826,7 +828,8 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "vec4 texel = texture2D(tex, vec2(gl_TexCoord[0].s - sdistort, gl_TexCoord[0].t - cdistort));\n" \ "vec4 base_color = texel * poly_color;\n" \ "vec4 final_color = base_color;\n" \ - "float light_gain = (255.0 - lighting) * floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \ + "float brightmap_mix = floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \ + "float light_gain = (255.0 - lighting) * brightmap_mix;\n" \ GLSL_SOFTWARE_TINT_EQUATION \ GLSL_SOFTWARE_FADE_EQUATION \ "final_color.a = texel.a * poly_color.a;\n" \ @@ -850,6 +853,7 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "void main(void) {\n" \ "vec4 base_color = gl_Color;\n" \ "vec4 final_color = base_color;\n" \ + "float brightmap_mix = 0.0;\n" \ "float light_gain = 0.0;\n" \ GLSL_SOFTWARE_TINT_EQUATION \ GLSL_SOFTWARE_FADE_EQUATION \ From 938203133757145f9c94afe6c74e817867d2674e Mon Sep 17 00:00:00 2001 From: Sal Date: Wed, 4 Oct 2023 03:51:43 +0000 Subject: [PATCH 4/5] OpenGL sprite+model directional light --- src/hardware/hw_batching.c | 8 +- src/hardware/hw_defs.h | 6 ++ src/hardware/hw_glob.h | 2 + src/hardware/hw_main.c | 112 +++++++++++++++---- src/hardware/hw_main.h | 2 +- src/hardware/hw_md2.c | 6 +- src/hardware/r_opengl/r_opengl.c | 180 ++++++++++++++++++++----------- src/p_setup.cpp | 31 +++--- src/r_things.cpp | 2 +- src/r_things.h | 1 + 10 files changed, 246 insertions(+), 104 deletions(-) diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c index ad363cefe..32a697a2b 100644 --- a/src/hardware/hw_batching.c +++ b/src/hardware/hw_batching.c @@ -202,6 +202,10 @@ static int comparePolygons(const void *p1, const void *p2) diff = poly1->surf.LightInfo.fade_start - poly2->surf.LightInfo.fade_start; if (diff != 0) return diff; diff = poly1->surf.LightInfo.fade_end - poly2->surf.LightInfo.fade_end; + + diff = poly1->surf.LightInfo.directional - poly2->surf.LightInfo.directional; + if (diff != 0) return diff; + return diff; } @@ -269,6 +273,7 @@ void HWR_RenderBatches(void) nextSurfaceInfo.LightInfo.fade_end = 0; nextSurfaceInfo.LightInfo.fade_start = 0; nextSurfaceInfo.LightInfo.light_level = 0; + nextSurfaceInfo.LightInfo.directional = false; currently_batching = false;// no longer collecting batches if (!polygonArraySize) @@ -424,7 +429,8 @@ void HWR_RenderBatches(void) currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba || currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level || currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start || - currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end) + currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end || + currentSurfaceInfo.LightInfo.directional != nextSurfaceInfo.LightInfo.directional) { changeState = true; changeSurfaceInfo = true; diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index e631604cb..621cb9015 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -277,6 +277,7 @@ struct FLightInfo FUINT light_level; FUINT fade_start; FUINT fade_end; + boolean directional; }; typedef struct FLightInfo FLightInfo; @@ -321,6 +322,11 @@ typedef enum hwdshaderoption hwdshaderoption_t; enum hwdshaderinfo { HWD_SHADERINFO_LEVELTIME = 1, + HWD_SHADERINFO_LIGHT_X, + HWD_SHADERINFO_LIGHT_Y, + HWD_SHADERINFO_LIGHT_Z, + HWD_SHADERINFO_LIGHT_CONTRAST, + HWD_SHADERINFO_LIGHT_BACKLIGHT, }; typedef enum hwdshaderinfo hwdshaderinfo_t; diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 1c2b96a69..17b8ca800 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -100,6 +100,8 @@ typedef struct gl_vissprite_s mobj_t *mobj; // NOTE: This is a precipmobj_t if precip is true !!! Watch out. } gl_vissprite_t; +void HWR_ObjectLightLevelPost(gl_vissprite_t *spr, const sector_t *sector, INT32 *lightlevel, boolean model); + // -------- // hw_bsp.c // -------- diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 3595d7138..271076b05 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -199,13 +199,68 @@ boolean HWR_OverrideObjectLightLevel(mobj_t *thing, INT32 *lightlevel) *lightlevel = 255; else if (R_ThingIsFullDark(thing)) *lightlevel = 0; + else if (thing->renderflags & RF_ABSOLUTELIGHTLEVEL) + *lightlevel = R_ThingLightLevel(thing); else return false; return true; } -void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap) +void HWR_ObjectLightLevelPost(gl_vissprite_t *spr, const sector_t *sector, INT32 *lightlevel, boolean model) +{ + const boolean semibright = R_ThingIsSemiBright(spr->mobj); + const boolean papersprite = R_ThingIsPaperSprite(spr->mobj); + + *lightlevel += R_ThingLightLevel(spr->mobj); + + if (maplighting.directional == true && P_SectorUsesDirectionalLighting(sector)) + { + if (model == false) // this is implemented by shader + { + fixed_t extralight = R_GetSpriteDirectionalLighting( + papersprite + ? spr->angle + (spr->flip ? -ANGLE_90 : ANGLE_90) + : R_PointToAngle(spr->mobj->x, spr->mobj->y) // fixme + ); + + // Less change in contrast in dark sectors + extralight = FixedMul(extralight, min(max(0, *lightlevel), 255) * FRACUNIT / 255); + + if (papersprite) + { + // Papersprite contrast should match walls + *lightlevel += FixedFloor(extralight + (FRACUNIT / 2)) / FRACUNIT; + } + else + { + // simple OGL approximation + fixed_t tr = R_PointToDist(spr->mobj->x, spr->mobj->y); + fixed_t xscale = FixedDiv((vid.width / 2) << FRACBITS, tr); + + // Less change in contrast at further distances, to counteract DOOM diminished light + fixed_t n = FixedDiv(FixedMul(xscale, LIGHTRESOLUTIONFIX), ((MAXLIGHTSCALE-1) << LIGHTSCALESHIFT)); + extralight = FixedMul(extralight, min(n, FRACUNIT)); + + // Contrast is stronger for normal sprites, stronger than wall lighting is at the same distance + *lightlevel += FixedFloor((extralight * 2) + (FRACUNIT / 2)) / FRACUNIT; + } + } + + // Semibright objects will be made slightly brighter to compensate contrast + if (semibright) + { + *lightlevel += 16; + } + } + + if (semibright) + { + *lightlevel = 192 + (*lightlevel >> 1); + } +} + +void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap, const boolean directional) { RGBA_t poly_color, tint_color, fade_color; @@ -256,9 +311,12 @@ void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *col Surface->PolyColor.rgba = poly_color.rgba; Surface->TintColor.rgba = tint_color.rgba; Surface->FadeColor.rgba = fade_color.rgba; + Surface->LightInfo.light_level = light_level; Surface->LightInfo.fade_start = (colormap != NULL) ? colormap->fadestart : 0; Surface->LightInfo.fade_end = (colormap != NULL) ? colormap->fadeend : 31; + + Surface->LightInfo.directional = (maplighting.directional == true && directional == true); } UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap) // Let's see if this can work @@ -306,13 +364,13 @@ static FUINT HWR_CalcWallLight(FUINT lightnum, seg_t *seg) return (FUINT)finallight; } -static FUINT HWR_CalcSlopeLight(FUINT lightnum, pslope_t *slope, const sector_t *sector) +static FUINT HWR_CalcSlopeLight(FUINT lightnum, pslope_t *slope, const sector_t *sector, const boolean fof) { INT16 finallight = lightnum; if (slope != NULL && sector != NULL && P_ApplyLightOffsetFine(lightnum, sector)) { - finallight += slope->hwLightOffset; + finallight += (fof ? -slope->hwLightOffset : slope->hwLightOffset); if (finallight > 255) finallight = 255; if (finallight < 0) finallight = 0; @@ -504,8 +562,8 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool for (i = 0, v3d = planeVerts; i < nrPlaneVerts; i++,v3d++,pv++) SETUP3DVERT(v3d, pv->x, pv->y); - lightlevel = HWR_CalcSlopeLight(lightlevel, slope, gl_frontsector); - HWR_Lighting(&Surf, lightlevel, planecolormap); + lightlevel = HWR_CalcSlopeLight(lightlevel, slope, gl_frontsector, (FOFsector != NULL)); + HWR_Lighting(&Surf, lightlevel, planecolormap, P_SectorUsesDirectionalLighting(gl_frontsector)); if (PolyFlags & PF_EnvironmentTrans) { @@ -744,7 +802,7 @@ static void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIEL { INT32 shader = SHADER_DEFAULT; - HWR_Lighting(pSurf, lightlevel, wallcolormap); + HWR_Lighting(pSurf, lightlevel, wallcolormap, P_SectorUsesDirectionalLighting(gl_frontsector)); if (HWR_UseShader()) { @@ -2267,7 +2325,7 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, v3d->z = FIXED_TO_FLOAT(polysector->vertices[i]->y); } - HWR_Lighting(&Surf, lightlevel, planecolormap); + HWR_Lighting(&Surf, lightlevel, planecolormap, P_SectorUsesDirectionalLighting((FOFsector != NULL) ? FOFsector : gl_frontsector)); if (blendmode & PF_Translucent) { @@ -3151,7 +3209,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) colormap = thing->subsector->sector->extra_colormap; } - HWR_Lighting(&sSurf, 255, colormap); + HWR_Lighting(&sSurf, 255, colormap, P_SectorUsesDirectionalLighting(thing->subsector->sector)); sSurf.PolyColor.s.alpha = 255; if (thing->whiteshadow == true) @@ -3394,8 +3452,8 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) } } - if (R_ThingIsSemiBright(spr->mobj)) - lightlevel = 192 + (lightlevel>>1); + if (!lightset) + HWR_ObjectLightLevelPost(spr, sector, &lightlevel, false); for (i = 0; i < sector->numlights; i++) { @@ -3408,9 +3466,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) if (!lightset) { lightlevel = *list[i].lightlevel > 255 ? 255 : *list[i].lightlevel; - - if (R_ThingIsSemiBright(spr->mobj)) - lightlevel = 192 + (lightlevel>>1); + HWR_ObjectLightLevelPost(spr, sector, &lightlevel, false); } if (!R_ThingIsFullBright(spr->mobj) && !(spr->mobj->renderflags & RF_NOCOLORMAPS)) @@ -3477,7 +3533,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) wallVerts[1].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult; } - HWR_Lighting(&Surf, lightlevel, colormap); + HWR_Lighting(&Surf, lightlevel, colormap, P_SectorUsesDirectionalLighting(sector) && !R_ThingIsFullBright(spr->mobj)); Surf.PolyColor.s.alpha = alpha; @@ -3506,7 +3562,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) wallVerts[0].y = bot; wallVerts[1].y = endbot; - HWR_Lighting(&Surf, lightlevel, colormap); + HWR_Lighting(&Surf, lightlevel, colormap, P_SectorUsesDirectionalLighting(sector)); Surf.PolyColor.s.alpha = alpha; @@ -3582,7 +3638,9 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) if (!spr->mobj->subsector) return; - if (spr->mobj->subsector->sector->numlights && !splat) + if (spr->mobj->subsector->sector->numlights + && (spr->mobj->renderflags & RF_ABSOLUTELIGHTLEVEL) == 0 + && !splat) { HWR_SplitSprite(spr); return; @@ -3796,10 +3854,10 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) else if (!lightset) lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel; - if (R_ThingIsSemiBright(spr->mobj)) - lightlevel = 128 + (lightlevel>>1); + if (!lightset) + HWR_ObjectLightLevelPost(spr, sector, &lightlevel, false); - HWR_Lighting(&Surf, lightlevel, colormap); + HWR_Lighting(&Surf, lightlevel, colormap, P_SectorUsesDirectionalLighting(sector) && !R_ThingIsFullBright(spr->mobj)); } { @@ -3946,7 +4004,7 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr) //lightlevel = 128 + (lightlevel>>1); - HWR_Lighting(&Surf, lightlevel, colormap); + HWR_Lighting(&Surf, lightlevel, colormap, P_SectorUsesDirectionalLighting(sector)); } // Determine the blendmode and translucency value @@ -4410,7 +4468,7 @@ static void HWR_DrawSprites(void) #ifdef BAD_MODEL_OPTIONS HWD.pfnSetSpecialState(HWD_SET_MODEL_LIGHTING, cv_glmodellighting.value); #else - HWD.pfnSetSpecialState(HWD_SET_MODEL_LIGHTING, false); + HWD.pfnSetSpecialState(HWD_SET_MODEL_LIGHTING, 1); #endif for (i = 0; i < gl_visspritecount; i++) @@ -5867,8 +5925,18 @@ void HWR_RenderPlayerView(void) ClearColor.alpha = 1.0f; if (cv_glshaders.value) + { HWD.pfnSetShaderInfo(HWD_SHADERINFO_LEVELTIME, (INT32)leveltime); // The water surface shader needs the leveltime. + const angle_t light_angle = maplighting.angle - viewangle + ANGLE_90; // I fucking hate OGL's coordinate system + HWD.pfnSetShaderInfo(HWD_SHADERINFO_LIGHT_X, FINECOSINE(light_angle >> ANGLETOFINESHIFT)); + HWD.pfnSetShaderInfo(HWD_SHADERINFO_LIGHT_Y, 0); + HWD.pfnSetShaderInfo(HWD_SHADERINFO_LIGHT_Z, -FINESINE(light_angle >> ANGLETOFINESHIFT)); + + HWD.pfnSetShaderInfo(HWD_SHADERINFO_LIGHT_CONTRAST, maplighting.contrast); + HWD.pfnSetShaderInfo(HWD_SHADERINFO_LIGHT_BACKLIGHT, maplighting.backlight); + } + if (viewssnum == 0) // Only do it if it's the first screen being rendered HWD.pfnClearBuffer(true, false, &ClearColor); // Clear the Color Buffer, stops HOMs. Also seems to fix the skybox issue on Intel GPUs. @@ -6072,7 +6140,7 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, INT32 shader = SHADER_DEFAULT; // Lighting is done here instead so that fog isn't drawn incorrectly on transparent walls after sorting - HWR_Lighting(pSurf, lightlevel, wallcolormap); + HWR_Lighting(pSurf, lightlevel, wallcolormap, P_SectorUsesDirectionalLighting(gl_frontsector)); pSurf->PolyColor.s.alpha = alpha; // put the alpha back after lighting diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 010d83327..0c5239d6f 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -72,7 +72,7 @@ void HWR_DrawScreenFinalTexture(int width, int height); // This stuff is put here so models can use them boolean HWR_OverrideObjectLightLevel(mobj_t *thing, INT32 *lightlevel); -void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap); +void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap, const boolean directional); UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap); // Let's see if this can work UINT8 HWR_GetTranstableAlpha(INT32 transtablenum); diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 5720223a9..acddebc9c 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1355,10 +1355,10 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) colormap = sector->extra_colormap; } - if (R_ThingIsSemiBright(spr->mobj)) - lightlevel = 128 + (lightlevel>>1); + if (!lightset) + HWR_ObjectLightLevelPost(spr, sector, &lightlevel, true); - HWR_Lighting(&Surf, lightlevel, colormap); + HWR_Lighting(&Surf, lightlevel, colormap, P_SectorUsesDirectionalLighting(sector) && !R_ThingIsFullBright(spr->mobj)); } else Surf.PolyColor.rgba = 0xFFFFFFFF; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index b6c767043..d5366bf4d 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -591,6 +591,9 @@ typedef enum gluniform_lighting, gluniform_fade_start, gluniform_fade_end, + gluniform_light_dir, + gluniform_light_contrast, + gluniform_light_backlight, // misc. (custom shaders) gluniform_leveltime, @@ -621,6 +624,11 @@ static gl_shaderstate_t gl_shaderstate; // Shader info static INT32 shader_leveltime = 0; +static float shader_light_x = 0.0f; +static float shader_light_y = 0.0f; +static float shader_light_z = 0.0f; +static INT32 shader_light_contrast = 0; +static INT32 shader_light_backlight = 0; // Lactozilla: Shader functions static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i, const GLchar *vert_shader, const GLchar *frag_shader); @@ -629,56 +637,6 @@ static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAF static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; -// ================ -// Vertex shaders -// ================ - -// -// Generic vertex shader -// - -#define GLSL_DEFAULT_VERTEX_SHADER \ - "void main()\n" \ - "{\n" \ - "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ - "gl_FrontColor = gl_Color;\n" \ - "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ - "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ - "}\0" - -// replicates the way fixed function lighting is used by the model lighting option, -// stores the lighting result to gl_Color -// (ambient lighting of 0.75 and diffuse lighting from above) -#define GLSL_MODEL_LIGHTING_VERTEX_SHADER \ - "void main()\n" \ - "{\n" \ - "float nDotVP = dot(gl_Normal, vec3(0, 1, 0));\n" \ - "float light = 0.75 + max(nDotVP, 0.0);\n" \ - "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ - "gl_FrontColor = vec4(light, light, light, 1.0);\n" \ - "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ - "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ - "}\0" - -// ================== -// Fragment shaders -// ================== - -// -// Generic fragment shader -// - -#define GLSL_DEFAULT_FRAGMENT_SHADER \ - "uniform sampler2D tex;\n" \ - "uniform vec4 poly_color;\n" \ - "void main(void) {\n" \ - "gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \ - "}\0" - -// -// Software fragment shader -// - #define GLSL_DOOM_COLORMAP \ "float R_DoomColormap(float light, float z)\n" \ "{\n" \ @@ -707,7 +665,7 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "}\n" #define GLSL_SOFTWARE_FADE_EQUATION \ - "float darkness = R_DoomLightingEquation(lighting + light_gain);\n" \ + "float darkness = R_DoomLightingEquation(final_lighting);\n" \ "if (fade_start > 0.0 || fade_end < 31.0) {\n" \ "float fs = fade_start / 31.0;\n" \ "float fe = fade_end / 31.0;\n" \ @@ -746,7 +704,68 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "final_color.b += colorIntensity;\n" \ "} else {\n" \ "final_color.b -= colorIntensity;\n" \ - "}\n" \ + "}\n" + +// ================ +// Vertex shaders +// ================ + +// +// Generic vertex shader +// + +#define GLSL_DEFAULT_VERTEX_SHADER \ + "void main()\n" \ + "{\n" \ + "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ + "gl_FrontColor = gl_Color;\n" \ + "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ + "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ + "}\0" + +// reinterpretation of sprite lighting for models +// it's a combination of how it works for normal sprites & papersprites +#define GLSL_MODEL_LIGHTING_VERTEX_SHADER \ + "uniform float lighting;\n" \ + "uniform vec3 light_dir;\n" \ + "uniform float light_contrast;\n" \ + "uniform float light_backlight;\n" \ + "void main()\n" \ + "{\n" \ + "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ + "float light = lighting;\n" \ + "if (length(light_dir) > 0.000001) {\n" \ + "mat4 m4 = gl_ProjectionMatrix * gl_ModelViewMatrix;\n" \ + "mat3 m3 = mat3( m4[0].xyz, m4[1].xyz, m4[2].xyz );\n" \ + "float extralight = -dot(normalize(gl_Normal * m3), normalize(light_dir));\n" \ + "extralight *= light_contrast - light_backlight;\n" \ + "extralight *= lighting / 255.0;\n" \ + "light += extralight * 2.5;\n" \ + "}\n" \ + "light = clamp(light / 255.0, 0.0, 1.0);\n" \ + "gl_FrontColor = vec4(light, light, light, 1.0);\n" \ + "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ + "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ + "}\0" + +// ================== +// Fragment shaders +// ================== + +// +// Generic fragment shader +// + +#define GLSL_DEFAULT_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform vec4 poly_color;\n" \ + "void main(void) {\n" \ + "gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \ + "}\0" + +// +// Software fragment shader +// #define GLSL_SOFTWARE_FRAGMENT_SHADER \ "uniform sampler2D tex;\n" \ @@ -765,6 +784,7 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "vec4 final_color = base_color;\n" \ "float brightmap_mix = floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \ "float light_gain = (255.0 - lighting) * brightmap_mix;\n" \ + "float final_lighting = lighting + light_gain;\n" \ GLSL_SOFTWARE_TINT_EQUATION \ GLSL_SOFTWARE_FADE_EQUATION \ "final_color.a = texel.a * poly_color.a;\n" \ @@ -779,7 +799,6 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "uniform vec4 poly_color;\n" \ "uniform vec4 tint_color;\n" \ "uniform vec4 fade_color;\n" \ - "uniform float lighting;\n" \ "uniform float fade_start;\n" \ "uniform float fade_end;\n" \ GLSL_DOOM_COLORMAP \ @@ -788,11 +807,12 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ "vec4 base_color = texel * poly_color;\n" \ "vec4 final_color = base_color;\n" \ + "float final_lighting = gl_Color.r * 255.0;\n" \ "float brightmap_mix = floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \ - "float light_gain = (255.0 - lighting) * brightmap_mix;\n" \ + "float light_gain = (255.0 - final_lighting) * brightmap_mix;\n" \ + "final_lighting += light_gain;\n" \ GLSL_SOFTWARE_TINT_EQUATION \ GLSL_SOFTWARE_FADE_EQUATION \ - "final_color *= gl_Color;\n" \ "final_color.a = texel.a * poly_color.a;\n" \ "gl_FragColor = final_color;\n" \ "}\0" @@ -830,6 +850,7 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "vec4 final_color = base_color;\n" \ "float brightmap_mix = floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \ "float light_gain = (255.0 - lighting) * brightmap_mix;\n" \ + "float final_lighting = lighting + light_gain;\n" \ GLSL_SOFTWARE_TINT_EQUATION \ GLSL_SOFTWARE_FADE_EQUATION \ "final_color.a = texel.a * poly_color.a;\n" \ @@ -855,6 +876,7 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "vec4 final_color = base_color;\n" \ "float brightmap_mix = 0.0;\n" \ "float light_gain = 0.0;\n" \ + "float final_lighting = lighting + light_gain;\n" \ GLSL_SOFTWARE_TINT_EQUATION \ GLSL_SOFTWARE_FADE_EQUATION \ "gl_FragColor = final_color;\n" \ @@ -1036,6 +1058,21 @@ EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value) case HWD_SHADERINFO_LEVELTIME: shader_leveltime = value; break; + case HWD_SHADERINFO_LIGHT_X: + shader_light_x = FixedToFloat(value); + break; + case HWD_SHADERINFO_LIGHT_Y: + shader_light_y = FixedToFloat(value); + break; + case HWD_SHADERINFO_LIGHT_Z: + shader_light_z = FixedToFloat(value); + break; + case HWD_SHADERINFO_LIGHT_CONTRAST: + shader_light_contrast = value; + break; + case HWD_SHADERINFO_LIGHT_BACKLIGHT: + shader_light_backlight = value; + break; default: break; } @@ -2121,12 +2158,35 @@ static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAF UNIFORM_4(shader->uniforms[gluniform_poly_color], poly->red, poly->green, poly->blue, poly->alpha, pglUniform4f); UNIFORM_4(shader->uniforms[gluniform_tint_color], tint->red, tint->green, tint->blue, tint->alpha, pglUniform4f); UNIFORM_4(shader->uniforms[gluniform_fade_color], fade->red, fade->green, fade->blue, fade->alpha, pglUniform4f); + + boolean directional = false; if (Surface != NULL) { UNIFORM_1(shader->uniforms[gluniform_lighting], Surface->LightInfo.light_level, pglUniform1f); UNIFORM_1(shader->uniforms[gluniform_fade_start], Surface->LightInfo.fade_start, pglUniform1f); UNIFORM_1(shader->uniforms[gluniform_fade_end], Surface->LightInfo.fade_end, pglUniform1f); + directional = Surface->LightInfo.directional; } + else + { + UNIFORM_1(shader->uniforms[gluniform_lighting], 255, pglUniform1f); + UNIFORM_1(shader->uniforms[gluniform_fade_start], 0, pglUniform1f); + UNIFORM_1(shader->uniforms[gluniform_fade_end], 31, pglUniform1f); + } + + if (directional) + { + UNIFORM_3(shader->uniforms[gluniform_light_dir], shader_light_x, shader_light_y, shader_light_z, pglUniform3f); + UNIFORM_1(shader->uniforms[gluniform_light_contrast], shader_light_contrast, pglUniform1f); + UNIFORM_1(shader->uniforms[gluniform_light_backlight], shader_light_backlight, pglUniform1f); + } + else + { + UNIFORM_3(shader->uniforms[gluniform_light_dir], 0, 0, 0, pglUniform3f); + UNIFORM_1(shader->uniforms[gluniform_light_contrast], 0, pglUniform1f); + UNIFORM_1(shader->uniforms[gluniform_light_backlight], 0, pglUniform1f); + } + UNIFORM_1(shader->uniforms[gluniform_leveltime], ((float)shader_leveltime) / TICRATE, pglUniform1f); #undef UNIFORM_1 @@ -2228,6 +2288,9 @@ static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i, const GLchar shader->uniforms[gluniform_lighting] = GETUNI("lighting"); shader->uniforms[gluniform_fade_start] = GETUNI("fade_start"); shader->uniforms[gluniform_fade_end] = GETUNI("fade_end"); + shader->uniforms[gluniform_light_dir] = GETUNI("light_dir"); + shader->uniforms[gluniform_light_contrast] = GETUNI("light_contrast"); + shader->uniforms[gluniform_light_backlight] = GETUNI("light_backlight"); // misc. (custom shaders) shader->uniforms[gluniform_leveltime] = GETUNI("leveltime"); @@ -2820,13 +2883,6 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float diffuse[2] = poly.blue; diffuse[3] = poly.alpha; - if (ambient[0] > 0.75f) - ambient[0] = 0.75f; - if (ambient[1] > 0.75f) - ambient[1] = 0.75f; - if (ambient[2] > 0.75f) - ambient[2] = 0.75f; - pglLightfv(GL_LIGHT0, GL_POSITION, LightPos); pglEnable(GL_LIGHTING); diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 414fd210b..55529928a 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -3658,23 +3658,26 @@ void P_UpdateSegLightOffset(seg_t *li) boolean P_SectorUsesDirectionalLighting(const sector_t *sector) { - // explicitly turned on - if (sector->flags & MSF_DIRECTIONLIGHTING) + if (sector != NULL) { - return true; - } + // explicitly turned on + if (sector->flags & MSF_DIRECTIONLIGHTING) + { + return true; + } - // explicitly turned off - if (sector->flags & MSF_FLATLIGHTING) - { - return false; - } + // explicitly turned off + if (sector->flags & MSF_FLATLIGHTING) + { + return false; + } - // automatically turned on - if (sector->ceilingpic == skyflatnum) - { - // sky is visible - return true; + // automatically turned on + if (sector->ceilingpic == skyflatnum) + { + // sky is visible + return true; + } } // default is off, for indoors diff --git a/src/r_things.cpp b/src/r_things.cpp index 6afe405b1..8dcd89df6 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1679,7 +1679,7 @@ static void R_ProjectBoundingBox(mobj_t *thing, vissprite_t *vis) box->x2test = 0; } -static fixed_t R_GetSpriteDirectionalLighting(angle_t angle) +fixed_t R_GetSpriteDirectionalLighting(angle_t angle) { // Copied from P_UpdateSegLightOffset const UINT8 contrast = std::min(std::max(0, maplighting.contrast - maplighting.backlight), UINT8_MAX); diff --git a/src/r_things.h b/src/r_things.h index 5ad5687e1..7148caacc 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -64,6 +64,7 @@ extern INT16 negonearray[MAXVIDWIDTH]; extern INT16 screenheightarray[MAXVIDWIDTH]; fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope); +fixed_t R_GetSpriteDirectionalLighting(angle_t angle); //SoM: 6/5/2000: Light sprites correctly! void R_AddSprites(sector_t *sec, INT32 lightlevel); From 014cbdb3bb0aa652cab7e97955f0c6fcae3cdcab Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 17 Jan 2024 18:21:38 -0800 Subject: [PATCH 5/5] OpenGL: fix BRIGHTMAP sneaking into textures where it doesn't belong and creating artifacts --- src/hardware/r_opengl/r_opengl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index d5366bf4d..d79be21ef 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1962,6 +1962,7 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) if (!(pTexInfo->flags & TF_BRIGHTMAP)) { + tex_downloaded = 0; // force update SetNoTexture(GL_TEXTURE1); // will be assigned later, if needed } @@ -2076,6 +2077,7 @@ EXPORT void HWRAPI(SetTexture) (GLMipmap_t *pTexInfo) { if (!(pTexInfo->flags & TF_BRIGHTMAP)) { + tex_downloaded = 0; // force update SetNoTexture(GL_TEXTURE1); // will be assigned later, if needed }