From d5fdd60fed7fd2ef5d2b8b0b3805a304b7f665fd Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 15 Jan 2024 13:35:17 +0100 Subject: [PATCH 01/24] replace karts batching with srb2s batching currently palette renderer does not work may need to try it with the reworked --- src/Makefile | 2 +- src/hardware/hw_batching.c | 488 +++++++++++++++++++++++ src/hardware/hw_batching.h | 39 ++ src/hardware/hw_cache.c | 26 +- src/hardware/hw_draw.c | 22 +- src/hardware/hw_drv.h | 10 +- src/hardware/hw_main.c | 97 +++-- src/hardware/hw_main.h | 2 + src/hardware/r_opengl/r_opengl.c | 656 +++---------------------------- src/sdl/hwsym_sdl.c | 6 +- src/sdl/i_video.c | 4 +- 11 files changed, 677 insertions(+), 675 deletions(-) create mode 100644 src/hardware/hw_batching.c create mode 100644 src/hardware/hw_batching.h diff --git a/src/Makefile b/src/Makefile index 06567753a..8af668744 100644 --- a/src/Makefile +++ b/src/Makefile @@ -275,7 +275,7 @@ else OPTS+=-DHWRENDER OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \ $(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o \ - $(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o + $(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o $(OBJDIR)/hw_batching.o endif OPTS += -DCOMPVERSION diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c new file mode 100644 index 000000000..b56278c7d --- /dev/null +++ b/src/hardware/hw_batching.c @@ -0,0 +1,488 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2020-2023 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file hw_batching.c +/// \brief Draw call batching and related things. + +#ifdef HWRENDER +#include "hw_glob.h" +#include "hw_batching.h" +#include "hw_main.h" +#include "../i_system.h" + +// The texture for the next polygon given to HWR_ProcessPolygon. +// Set with HWR_SetCurrentTexture. +GLMipmap_t *current_texture = NULL; + +boolean currently_batching = false; + +FOutVector* finalVertexArray = NULL;// contains subset of sorted vertices and texture coordinates to be sent to gpu +UINT32* finalVertexIndexArray = NULL;// contains indexes for glDrawElements, taking into account fan->triangles conversion +// NOTE have this alloced as 3x finalVertexArray size +int finalVertexArrayAllocSize = 65536; +//GLubyte* colorArray = NULL;// contains color data to be sent to gpu, if needed +//int colorArrayAllocSize = 65536; +// not gonna use this for now, just sort by color and change state when it changes +// later maybe when using vertex attributes if it's needed + +PolygonArrayEntry* polygonArray = NULL;// contains the polygon data from DrawPolygon, waiting to be processed +int polygonArraySize = 0; +UINT32* polygonIndexArray = NULL;// contains sorting pointers for polygonArray +int polygonArrayAllocSize = 65536; + +FOutVector* unsortedVertexArray = NULL;// contains unsorted vertices and texture coordinates from DrawPolygon +int unsortedVertexArraySize = 0; +int unsortedVertexArrayAllocSize = 65536; + +// Enables batching mode. HWR_ProcessPolygon will collect polygons instead of passing them directly to the rendering backend. +// 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"); + + // init arrays if that has not been done yet + if (!finalVertexArray) + { + finalVertexArray = malloc(finalVertexArrayAllocSize * sizeof(FOutVector)); + finalVertexIndexArray = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32)); + polygonArray = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry)); + polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(UINT32)); + unsortedVertexArray = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector)); + } + + currently_batching = true; +} + +// This replaces the direct calls to pfnSetTexture in cases where batching is available. +// The texture selection is saved for the next HWR_ProcessPolygon call. +// 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 batching is enabled, this function collects the polygon data and the chosen texture +// for later use in HWR_RenderBatches. Otherwise the rendering backend is used to +// render the polygon immediately. +void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial) +{ + 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 + if (polygonArraySize == polygonArrayAllocSize) + { + PolygonArrayEntry* new_array; + // ran out of space, make new array double the size + polygonArrayAllocSize *= 2; + new_array = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry)); + memcpy(new_array, polygonArray, polygonArraySize * sizeof(PolygonArrayEntry)); + free(polygonArray); + polygonArray = new_array; + // also need to redo the index array, dont need to copy it though + free(polygonIndexArray); + polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(UINT32)); + } + + while (unsortedVertexArraySize + (int)iNumPts > unsortedVertexArrayAllocSize) + { + FOutVector* new_array; + // need more space for vertices in unsortedVertexArray + unsortedVertexArrayAllocSize *= 2; + new_array = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector)); + memcpy(new_array, unsortedVertexArray, unsortedVertexArraySize * sizeof(FOutVector)); + free(unsortedVertexArray); + unsortedVertexArray = new_array; + } + + // add the polygon data to the arrays + + polygonArray[polygonArraySize].surf = *pSurf; + polygonArray[polygonArraySize].vertsIndex = unsortedVertexArraySize; + polygonArray[polygonArraySize].numVerts = iNumPts; + polygonArray[polygonArraySize].polyFlags = PolyFlags; + polygonArray[polygonArraySize].texture = current_texture; + polygonArray[polygonArraySize].shader = shader; + polygonArray[polygonArraySize].horizonSpecial = horizonSpecial; + polygonArraySize++; + + memcpy(&unsortedVertexArray[unsortedVertexArraySize], pOutVerts, iNumPts * sizeof(FOutVector)); + unsortedVertexArraySize += iNumPts; + } + else + { + if (shader) + HWD.pfnSetShader(shader); + HWD.pfnDrawPolygon(pSurf, pOutVerts, iNumPts, PolyFlags); + } +} + +static int comparePolygons(const void *p1, const void *p2) +{ + unsigned int index1 = *(const unsigned int*)p1; + unsigned int index2 = *(const unsigned int*)p2; + PolygonArrayEntry* poly1 = &polygonArray[index1]; + PolygonArrayEntry* poly2 = &polygonArray[index2]; + int diff; + INT64 diff64; + UINT32 downloaded1 = 0; + UINT32 downloaded2 = 0; + + int shader1 = poly1->shader; + int shader2 = poly2->shader; + // make skywalls and horizon lines first in order + if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial) + shader1 = -1; + if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial) + shader2 = -1; + diff = shader1 - shader2; + if (diff != 0) return diff; + + // skywalls and horizon lines must retain their order for horizon lines to work + if (shader1 == -1 && shader2 == -1) + return index1 - index2; + + if (poly1->texture) + downloaded1 = poly1->texture->downloaded; // there should be a opengl texture name here, usable for comparisons + if (poly2->texture) + downloaded2 = poly2->texture->downloaded; + diff64 = downloaded1 - downloaded2; + if (diff64 != 0) return diff64; + + if (HWR_ShouldUsePaletteRendering()) + { + diff = poly1->surf.LightTableId - poly2->surf.LightTableId; + if (diff != 0) return diff; + } + + diff = poly1->polyFlags - poly2->polyFlags; + if (diff != 0) return diff; + + diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba; + if (diff64 < 0) return -1; else if (diff64 > 0) return 1; + diff64 = poly1->surf.TintColor.rgba - poly2->surf.TintColor.rgba; + if (diff64 < 0) return -1; else if (diff64 > 0) return 1; + diff64 = poly1->surf.FadeColor.rgba - poly2->surf.FadeColor.rgba; + if (diff64 < 0) return -1; else if (diff64 > 0) return 1; + + diff = poly1->surf.LightInfo.light_level - poly2->surf.LightInfo.light_level; + if (diff != 0) return diff; + 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; + return diff; +} + +static int comparePolygonsNoShaders(const void *p1, const void *p2) +{ + unsigned int index1 = *(const unsigned int*)p1; + unsigned int index2 = *(const unsigned int*)p2; + PolygonArrayEntry* poly1 = &polygonArray[index1]; + PolygonArrayEntry* poly2 = &polygonArray[index2]; + int diff; + INT64 diff64; + + GLMipmap_t *texture1 = poly1->texture; + GLMipmap_t *texture2 = poly2->texture; + UINT32 downloaded1 = 0; + UINT32 downloaded2 = 0; + if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial) + texture1 = NULL; + if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial) + texture2 = NULL; + if (texture1) + downloaded1 = texture1->downloaded; // there should be a opengl texture name here, usable for comparisons + if (texture2) + downloaded2 = texture2->downloaded; + // skywalls and horizon lines must retain their order for horizon lines to work + if (!texture1 && !texture2) + return index1 - index2; + diff64 = downloaded1 - downloaded2; + if (diff64 != 0) return diff64; + + diff = poly1->polyFlags - poly2->polyFlags; + if (diff != 0) return diff; + + diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba; + if (diff64 < 0) return -1; else if (diff64 > 0) return 1; + + return 0; +} + +// This function organizes the geometry collected by HWR_ProcessPolygon calls into batches and uses +// the rendering backend to draw them. +void HWR_RenderBatches(void) +{ + 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 *nextTexture = NULL; + FBITFIELD currentPolyFlags = 0; + FBITFIELD nextPolyFlags = 0; + FSurfaceInfo currentSurfaceInfo; + FSurfaceInfo nextSurfaceInfo; + + int i; + + if (!currently_batching) + I_Error("HWR_RenderBatches called without starting batching"); + + nextSurfaceInfo.LightInfo.fade_end = 0; + nextSurfaceInfo.LightInfo.fade_start = 0; + nextSurfaceInfo.LightInfo.light_level = 0; + + currently_batching = false;// no longer collecting batches + if (!polygonArraySize) + { + ps_hw_numpolys.value.i = ps_hw_numcalls.value.i = ps_hw_numshaders.value.i + = ps_hw_numtextures.value.i = ps_hw_numpolyflags.value.i + = ps_hw_numcolors.value.i = 0; + return;// nothing to draw + } + // init stats vars + ps_hw_numpolys.value.i = polygonArraySize; + ps_hw_numcalls.value.i = ps_hw_numverts.value.i = 0; + ps_hw_numshaders.value.i = ps_hw_numtextures.value.i + = ps_hw_numpolyflags.value.i = ps_hw_numcolors.value.i = 1; + // init polygonIndexArray + for (i = 0; i < polygonArraySize; i++) + { + polygonIndexArray[i] = i; + } + + // sort polygons + PS_START_TIMING(ps_hw_batchsorttime); + if (cv_grshaders.value && gr_shadersavailable) + qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons); + else + qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders); + PS_STOP_TIMING(ps_hw_batchsorttime); + // sort order + // 1. shader + // 2. texture + // 3. polyflags + // 4. colors + light level + // not sure about what order of the last 2 should be, or if it even matters + + PS_START_TIMING(ps_hw_batchdrawtime); + + currentShader = polygonArray[polygonIndexArray[0]].shader; + currentTexture = polygonArray[polygonIndexArray[0]].texture; + 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 + // and a color array could replace the color calls. + + // set state for first batch + + if (cv_grshaders.value && gr_shadersavailable) + { + HWD.pfnSetShader(currentShader); + } + + if (currentPolyFlags & PF_NoTexture) + currentTexture = NULL; + else + HWD.pfnSetTexture(currentTexture); + + while (1)// note: remember handling notexture polyflag as having texture number 0 (also in comparePolygons) + { + int firstIndex; + int lastIndex; + + boolean stopFlag = false; + boolean changeState = false; + boolean changeShader = false; + boolean changeTexture = false; + boolean changePolyFlags = false; + boolean changeSurfaceInfo = false; + + // steps: + // write vertices + // check for changes or end, otherwise go back to writing + // changes will affect the next vars and the change bools + // end could set flag for stopping + // execute draw call + // could check ending flag here + // change states according to next vars and change bools, updating the current vars and reseting the bools + // reset write pos + // repeat loop + + int index = polygonIndexArray[polygonReadPos++]; + int numVerts = polygonArray[index].numVerts; + // before writing, check if there is enough room + // using 'while' instead of 'if' here makes sure that there will *always* be enough room. + // probably never will this loop run more than once though + while (finalVertexWritePos + numVerts > finalVertexArrayAllocSize) + { + FOutVector* new_array; + unsigned int* new_index_array; + finalVertexArrayAllocSize *= 2; + new_array = malloc(finalVertexArrayAllocSize * sizeof(FOutVector)); + memcpy(new_array, finalVertexArray, finalVertexWritePos * sizeof(FOutVector)); + free(finalVertexArray); + finalVertexArray = new_array; + // also increase size of index array, 3x of vertex array since + // going from fans to triangles increases vertex count to 3x + new_index_array = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32)); + memcpy(new_index_array, finalVertexIndexArray, finalIndexWritePos * sizeof(UINT32)); + free(finalVertexIndexArray); + finalVertexIndexArray = new_index_array; + } + // write the vertices of the polygon + memcpy(&finalVertexArray[finalVertexWritePos], &unsortedVertexArray[polygonArray[index].vertsIndex], + numVerts * sizeof(FOutVector)); + // write the indexes, pointing to the fan vertexes but in triangles format + firstIndex = finalVertexWritePos; + lastIndex = finalVertexWritePos + numVerts; + finalVertexWritePos += 2; + while (finalVertexWritePos < lastIndex) + { + finalVertexIndexArray[finalIndexWritePos++] = firstIndex; + finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos - 1; + finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos++; + } + + if (polygonReadPos >= polygonArraySize) + { + stopFlag = true; + } + else + { + // check if a state change is required, set the change bools and next vars + int nextIndex = polygonIndexArray[polygonReadPos]; + nextShader = polygonArray[nextIndex].shader; + nextTexture = polygonArray[nextIndex].texture; + nextPolyFlags = polygonArray[nextIndex].polyFlags; + nextSurfaceInfo = polygonArray[nextIndex].surf; + if (nextPolyFlags & PF_NoTexture) + nextTexture = 0; + if (currentShader != nextShader && cv_grshaders.value && gr_shadersavailable) + { + changeState = true; + changeShader = true; + } + if (currentTexture != nextTexture) + { + changeState = true; + changeTexture = true; + } + if (currentPolyFlags != nextPolyFlags) + { + changeState = true; + changePolyFlags = true; + } + if ((cv_grshaders.value && gr_shadersavailable) && (HWR_ShouldUsePaletteRendering())) + { + if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba || + currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba || + 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.LightTableId != nextSurfaceInfo.LightTableId) + { + changeState = true; + changeSurfaceInfo = true; + } + } + else if (cv_grshaders.value && gr_shadersavailable) + { + if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba || + currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba || + 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) + { + changeState = true; + changeSurfaceInfo = true; + } + } + else + { + if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba) + { + changeState = true; + changeSurfaceInfo = true; + } + } + } + + if (changeState || stopFlag) + { + // execute draw call + HWD.pfnDrawIndexedTriangles(¤tSurfaceInfo, finalVertexArray, finalIndexWritePos, currentPolyFlags, finalVertexIndexArray); + // update stats + ps_hw_numcalls.value.i++; + ps_hw_numverts.value.i += finalIndexWritePos; + // reset write positions + finalVertexWritePos = 0; + finalIndexWritePos = 0; + } + else continue; + + // if we're here then either its time to stop or time to change state + if (stopFlag) break; + + // change state according to change bools and next vars, update current vars and reset bools + if (changeShader) + { + HWD.pfnSetShader(nextShader); + currentShader = nextShader; + changeShader = false; + + ps_hw_numshaders.value.i++; + } + if (changeTexture) + { + // texture should be already ready for use from calls to SetTexture during batch collection + HWD.pfnSetTexture(nextTexture); + currentTexture = nextTexture; + changeTexture = false; + + ps_hw_numtextures.value.i++; + } + if (changePolyFlags) + { + currentPolyFlags = nextPolyFlags; + changePolyFlags = false; + + ps_hw_numpolyflags.value.i++; + } + if (changeSurfaceInfo) + { + currentSurfaceInfo = nextSurfaceInfo; + changeSurfaceInfo = false; + + ps_hw_numcolors.value.i++; + } + // and that should be it? + } + // reset the arrays (set sizes to 0) + polygonArraySize = 0; + unsortedVertexArraySize = 0; + + PS_STOP_TIMING(ps_hw_batchdrawtime); +} + + +#endif // HWRENDER diff --git a/src/hardware/hw_batching.h b/src/hardware/hw_batching.h new file mode 100644 index 000000000..bf0b7fc94 --- /dev/null +++ b/src/hardware/hw_batching.h @@ -0,0 +1,39 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file hw_batching.h +/// \brief Draw call batching and related things. + +#ifndef __HWR_BATCHING_H__ +#define __HWR_BATCHING_H__ + +#include "hw_defs.h" +#include "hw_data.h" +#include "hw_drv.h" + +typedef struct +{ + FSurfaceInfo surf;// surf also has its own polyflags for some reason, but it seems unused + unsigned int vertsIndex;// location of verts in unsortedVertexArray + FUINT numVerts; + FBITFIELD polyFlags; + GLMipmap_t *texture; + 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; +} PolygonArrayEntry; + +void HWR_StartBatching(void); +void HWR_SetCurrentTexture(GLMipmap_t *texture); +void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial); +void HWR_RenderBatches(void); + +extern boolean currently_batching; + +#endif diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 4255475bb..bdcdea1a6 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -17,6 +17,7 @@ #include "hw_main.h" #include "hw_glob.h" #include "hw_drv.h" +#include "hw_batching.h" #include "../doomstat.h" //gamemode #include "../i_video.h" //rendermode @@ -591,7 +592,11 @@ GLTexture_t *HWR_GetTexture(INT32 tex) if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded) HWR_GenerateTexture(tex, grtex); - HWD.pfnSetTexture(&grtex->mipmap); + // 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.grInfo.data, PU_HWRCACHE_UNLOCKED); @@ -675,7 +680,11 @@ void HWR_GetFlat(lumpnum_t flatlumpnum, boolean noencoremap) if (!grmip->downloaded && !grmip->grInfo.data) HWR_CacheFlat(grmip, flatlumpnum); - HWD.pfnSetTexture(grmip); + // If hardware does not have the texture, then call pfnSetTexture to upload it + if (!grmip->downloaded) + HWD.pfnSetTexture(grmip); + + HWR_SetCurrentTexture(grmip); // The system-memory data can be purged now. Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED); @@ -701,8 +710,11 @@ static void HWR_LoadMappedPatch(GLMipmap_t *grmip, GLPatch_t *gpatch) Z_Free(patch); } - - HWD.pfnSetTexture(grmip); + // If hardware does not have the texture, then call pfnSetTexture to upload it + if (!grmip->downloaded) + HWD.pfnSetTexture(grmip); + + HWR_SetCurrentTexture(grmip); // The system-memory data can be purged now. Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED); @@ -732,7 +744,11 @@ void HWR_GetPatch(GLPatch_t *gpatch) Z_Free(ptr); } - HWD.pfnSetTexture(gpatch->mipmap); + // If hardware does not have the texture, then call pfnSetTexture to upload it + if (!gpatch->mipmap->downloaded) + HWD.pfnSetTexture(gpatch->mipmap); + + HWR_SetCurrentTexture(gpatch->mipmap); // The system-memory patch data can be purged now. Z_ChangeTag(gpatch->mipmap->grInfo.data, PU_HWRCACHE_UNLOCKED); diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 8feb7c050..8c309f020 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -122,7 +122,7 @@ void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option) flags |= PF_ForceWrapY; // clip it since it is used for bunny scroll in doom I - HWD.pfnDrawPolygon(NULL, v, 4, flags, false); + HWD.pfnDrawPolygon(NULL, v, 4, flags); } void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap) @@ -300,10 +300,10 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[hudtrans]; else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; flags |= PF_Modulated; - HWD.pfnDrawPolygon(&Surf, v, 4, flags, false); + HWD.pfnDrawPolygon(&Surf, v, 4, flags); } else - HWD.pfnDrawPolygon(NULL, v, 4, flags, false); + HWD.pfnDrawPolygon(NULL, v, 4, flags); } void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h) @@ -454,10 +454,10 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[cv_translucenthud.value]; else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; flags |= PF_Modulated; - HWD.pfnDrawPolygon(&Surf, v, 4, flags, false); + HWD.pfnDrawPolygon(&Surf, v, 4, flags); } else - HWD.pfnDrawPolygon(NULL, v, 4, flags, false); + HWD.pfnDrawPolygon(NULL, v, 4, flags); } // ========================================================================== @@ -533,7 +533,7 @@ void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum // BTW, I see we put 0 for PFs, and If I'm right, that // means we take the previous PFs as default // how can we be sure they are ok? - HWD.pfnDrawPolygon(NULL, v, 4, PF_NoDepthTest, false); //PF_Translucent); + HWD.pfnDrawPolygon(NULL, v, 4, PF_NoDepthTest); //PF_Translucent); } @@ -575,7 +575,7 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength) Surf.PolyColor.s.alpha = (UINT8)(strength*25.5f); } - HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest, false); + HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } // Draw the console background with translucency support @@ -602,7 +602,7 @@ void HWR_DrawConsoleBack(UINT32 color, INT32 height) Surf.PolyColor.rgba = UINT2RGBA(color); Surf.PolyColor.s.alpha = 0x80; - HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest, false); + HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } @@ -851,7 +851,7 @@ void HWR_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 color) Surf.PolyColor = V_GetColor(color); HWD.pfnDrawPolygon(&Surf, v, 4, - PF_Modulated|PF_NoTexture|PF_NoDepthTest, false); + PF_Modulated|PF_NoTexture|PF_NoDepthTest); } // -------------------+ @@ -959,7 +959,7 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32 Surf.PolyColor.rgba = UINT2RGBA(color); Surf.PolyColor.s.alpha = 0x80; - HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest, false); + HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } // -----------------+ @@ -1076,7 +1076,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; } - HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest, false); + HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } #ifdef HAVE_PNG diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index b231e76c4..f7441204f 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -36,7 +36,8 @@ EXPORT void HWRAPI(SetPalette) (RGBA_t *ppal, RGBA_t *pgamma); #endif EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl); EXPORT void HWRAPI(Draw2DLine) (F2DCoord *v1, F2DCoord *v2, RGBA_t Color); -EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, boolean horizonSpecial); +EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags); +EXPORT void HWRAPI(DrawIndexedTriangles) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, unsigned int *IndexArray); EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags); EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FBOOLEAN StencilMask, FRGBAFloat *ClearColor); EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo); @@ -81,9 +82,6 @@ EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value); EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boolean fragment); EXPORT boolean HWRAPI(InitCustomShaders) (void); -EXPORT void HWRAPI(StartBatching) (void); -EXPORT void HWRAPI(RenderBatches) (precise_t *sSortTime, precise_t *sDrawTime, int *sNumPolys, int *sNumVerts, int *sNumCalls, int *sNumShaders, int *sNumTextures, int *sNumPolyFlags, int *sNumColors); - EXPORT void HWRAPI(InitPalette) (int flashnum, boolean skiplut); EXPORT UINT32 HWRAPI(AddLightTable) (UINT8 *lighttable); EXPORT void HWRAPI(ClearLightTableCache) (void); @@ -102,6 +100,7 @@ struct hwdriver_s FinishUpdate pfnFinishUpdate; Draw2DLine pfnDraw2DLine; DrawPolygon pfnDrawPolygon; + DrawIndexedTriangles pfnDrawIndexedTriangles; SetBlend pfnSetBlend; ClearBuffer pfnClearBuffer; SetTexture pfnSetTexture; @@ -136,9 +135,6 @@ struct hwdriver_s LoadCustomShader pfnLoadCustomShader; InitCustomShaders pfnInitCustomShaders; - StartBatching pfnStartBatching; - RenderBatches pfnRenderBatches; - InitPalette pfnInitPalette; AddLightTable pfnAddLightTable; ClearLightTableCache pfnClearLightTableCache; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index b2a4bdde8..bf733b637 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -19,6 +19,7 @@ #include "hw_main.h" #include "hw_glob.h" #include "hw_drv.h" +#include "hw_batching.h" #include "hw_md2.h" #include "hw_clip.h" #include "hw_light.h" @@ -682,6 +683,8 @@ void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isc static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; + + INT32 shader = 0; // no convex poly were generated for this subsector if (!xsub->planepoly) @@ -859,16 +862,16 @@ void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isc if (HWR_UseShader()) { if (PolyFlags & PF_Fog) - HWD.pfnSetShader(6); // fog shader + shader = 6; // fog shader else if (PolyFlags & PF_Ripple) - HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 11 : 5); // water shader + shader = (HWR_ShouldUsePaletteRendering() ? 11 : 5); // water shader else - HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 9 : 1); // floor shader + shader = (HWR_ShouldUsePaletteRendering() ? 9 : 1); // floor shader PolyFlags |= PF_ColorMapped; } - HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags, false); + HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags, shader, false); if (subsector) { @@ -953,7 +956,7 @@ void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isc horizonpts[4].y = gr_viewz; // Draw - HWD.pfnDrawPolygon(&Surf, horizonpts, 6, PolyFlags, true); + HWR_ProcessPolygon(&Surf, horizonpts, 6, PolyFlags, shader, true); } } } @@ -969,6 +972,8 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf) fixed_t i; // seg bbox fixed_t segbbox[4]; + + INT32 shader = 0; M_ClearBox(segbbox); M_AddToBox(segbbox, @@ -1022,10 +1027,10 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf) if (HWR_UseShader()) { - HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader + shader = (HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader } - HWD.pfnDrawPolygon(&pSurf, wallVerts, 4, i|PF_Modulated|PF_Decal, false); + HWD.HWR_ProcessPolygon(&pSurf, wallVerts, 4, i|PF_Modulated|PF_Decal, shader, false); } } #endif @@ -1056,11 +1061,13 @@ FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf) // void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blendmode, INT32 lightlevel, extracolormap_t *wallcolormap) { + INT32 shader = 0; + HWR_Lighting(pSurf, lightlevel, wallcolormap); if (HWR_UseShader()) { - HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader + shader = (HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader blendmode |= PF_ColorMapped; } @@ -1071,7 +1078,7 @@ void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend blendmode &= ~PF_Masked; } - HWD.pfnDrawPolygon(pSurf, wallVerts, 4, blendmode|PF_Modulated|PF_Occlude, false); + HWR_ProcessPolygon(pSurf, wallVerts, 4, blendmode|PF_Modulated|PF_Occlude, shader, false); // wall shader #ifdef WALLSPLATS if (gr_curline->linedef->splats && cv_splats.value) @@ -1427,11 +1434,11 @@ static void HWR_DrawSkyWallList(void) surf.PolyColor.rgba = 0xFFFFFFFF; - HWD.pfnSetTexture(NULL); + HWR_SetCurrentTexture(NULL); HWD.pfnUnSetShader(); for (i = 0; i < skyWallVertexArraySize; i++) { - HWD.pfnDrawPolygon(&surf, skyWallVertexArray + i * 4, 4, PF_Occlude|PF_Invisible|PF_NoTexture, false); + HWD.pfnDrawPolygon(&surf, skyWallVertexArray + i * 4, 4, PF_Occlude|PF_Invisible|PF_NoTexture); } } @@ -1452,7 +1459,7 @@ void HWR_DrawSkyWall(FOutVector *wallVerts, FSurfaceInfo *Surf) } else { - HWD.pfnSetTexture(NULL); + HWR_SetCurrentTexture(NULL); HWR_ProjectWall(wallVerts, Surf, PF_Invisible|PF_NoTexture, 255, NULL); } // PF_Invisible so it's not drawn into the colour buffer @@ -3147,6 +3154,8 @@ void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; + + INT32 shader = 0; nrPlaneVerts = polysector->numVertices; @@ -3292,11 +3301,11 @@ void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t if (HWR_UseShader()) { - HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 9 : 1); // floor shader + shader = (HWR_ShouldUsePaletteRendering() ? 9 : 1); // floor shader blendmode |= PF_ColorMapped; } - HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode, false); + HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode, shader, false); // floor shader } void HWR_AddPolyObjectPlanes(void) @@ -3952,6 +3961,8 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t fixed_t slopez; float offset = 0; + INT32 shader = 0; + R_GetShadowZ(spr->mobj, &floorslope); mobjfloor = HWR_OpaqueFloorAtPos( @@ -4101,10 +4112,10 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t if (HWR_UseShader()) { - HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 9 : 1); // floor shader + shader = (HWR_ShouldUsePaletteRendering() ? 9 : 1); // floor shader } - - HWD.pfnDrawPolygon(&sSurf, swallVerts, 4, PF_Translucent|PF_Modulated, false); + + HWR_ProcessPolygon(&sSurf, swallVerts, 4, PF_Translucent|PF_Modulated, shader, false); } } @@ -4200,6 +4211,8 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) fixed_t v1x, v1y, v2x, v2y; #endif + INT32 shader = 0; + this_scale = FIXED_TO_FLOAT(spr->mobj->scale); if (hires) @@ -4473,11 +4486,11 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) if (HWR_UseShader()) { - HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader + shader = (HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader blend |= PF_ColorMapped; } - HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, false); + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, shader, false); // sprite shader top = bot; #ifdef ESLOPE @@ -4518,11 +4531,11 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) if (HWR_UseShader()) { - HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader + shader = (HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader blend |= PF_ColorMapped; } - HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, false); + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, shader, false); // sprite shader } // -----------------+ @@ -4536,6 +4549,9 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) FOutVector wallVerts[4]; GLPatch_t *gpatch; // sprite patch converted to hardware FSurfaceInfo Surf; + + INT32 shader = 0; + const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)( (spr->mobj->localskin) ? spr->mobj->localskin : spr->mobj->skin ))->flags & SF_HIRES); if (spr->mobj) this_scale = FIXED_TO_FLOAT(spr->mobj->scale); @@ -4676,11 +4692,11 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) if (HWR_UseShader()) { - HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader + shader = (HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader blend |= PF_ColorMapped; } - HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, false); + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, shader, false); } } @@ -4691,6 +4707,8 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) FOutVector wallVerts[4]; GLPatch_t *gpatch; // sprite patch converted to hardware FSurfaceInfo Surf; + + INT32 shader = 0; if (!spr->mobj) return; @@ -4775,11 +4793,11 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) if (HWR_UseShader()) { - HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader + shader = (HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader blend |= PF_ColorMapped; } - HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, false); + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, shader, false); } // -------------------------------------------------------------------------- @@ -5945,8 +5963,8 @@ static void HWR_PortalClipping(gl_portal_t *portal) line_t *line = &lines[portal->clipline]; - angle1 = R_PointToAngleEx64(viewx, viewy, line->v1->x, line->v1->y); - angle2 = R_PointToAngleEx64(viewx, viewy, line->v2->x, line->v2->y); + angle1 = R_PointToAngleEx(viewx, viewy, line->v1->x, line->v1->y); + angle2 = R_PointToAngleEx(viewx, viewy, line->v2->x, line->v2->y); // clip things that are not inside the portal window from our viewpoint gld_clipper_SafeAddClipRange(angle2, angle1); @@ -6076,8 +6094,9 @@ static void HWR_RenderViewpoint(gl_portal_t *rootportal, const float fpov, playe } //drawcount = 0; validcount++; + if (cv_grbatching.value) - HWD.pfnStartBatching(); + HWR_StartBatching(); ps_numbspcalls.value.i = 0; ps_numpolyobjects.value.i = 0; @@ -6098,14 +6117,10 @@ static void HWR_RenderViewpoint(gl_portal_t *rootportal, const float fpov, playe gr_portal = oldgl_portal_state; PS_STOP_TIMING(ps_bsptime); - + if (cv_grbatching.value) - { - HWD.pfnRenderBatches(&ps_hw_batchsorttime.value.p, &ps_hw_batchdrawtime.value.p, - &ps_hw_numpolys.value.i, &ps_hw_numverts.value.i, &ps_hw_numcalls.value.i, - &ps_hw_numshaders.value.i, &ps_hw_numtextures.value.i, &ps_hw_numpolyflags.value.i, - &ps_hw_numcolors.value.i); - } + HWR_RenderBatches(); + if (skyWallVertexArraySize)// if there are skywalls to draw using the alternate method { HWR_SetStencilState(HWR_STENCIL_SKY, -1); @@ -6353,7 +6368,7 @@ void HWR_AddCommands(void) CV_RegisterVar(&cv_granisotropicmode); CV_RegisterVar(&cv_grcorrecttricks); CV_RegisterVar(&cv_grsolvetjoin); - + CV_RegisterVar(&cv_grbatching); CV_RegisterVar(&cv_grfofcut); CV_RegisterVar(&cv_fofzfightfix); @@ -6444,6 +6459,8 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, { FBITFIELD blendmode = blend; UINT8 alpha = pSurf->PolyColor.s.alpha; // retain the alpha + + INT32 shader = 0; // Lighting is done here instead so that fog isn't drawn incorrectly on transparent walls after sorting HWR_Lighting(pSurf, lightlevel, wallcolormap); @@ -6456,7 +6473,7 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, if (fogwall) { blendmode |= PF_Fog; - HWD.pfnSetShader(6); // fog shader + shader = 6; // fog shader } blendmode |= PF_Modulated; // No PF_Occlude means overlapping (incorrect) transparency @@ -6465,12 +6482,12 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, { if (HWR_UseShader()) { - HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader + shader = (HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader blendmode |= PF_ColorMapped; } } - HWD.pfnDrawPolygon(pSurf, wallVerts, 4, blendmode, false); + HWR_ProcessPolygon(pSurf, wallVerts, 4, blendmode, shader, false); #ifdef WALLSPLATS if (gr_curline->linedef->splats && cv_splats.value) @@ -6521,7 +6538,7 @@ void HWR_DoPostProcessor(player_t *player) Surf.PolyColor.s.alpha = 0xc0; // match software mode - HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated|PF_Translucent|PF_NoTexture|PF_NoDepthTest, false); + HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated|PF_Translucent|PF_NoTexture|PF_NoDepthTest); } if (!cv_grscreentextures.value) // screen textures are needed for the rest of the effects diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 6a62295f8..23d93e8ce 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -64,6 +64,8 @@ extern ps_metric_t ps_hw_numcolors; extern ps_metric_t ps_hw_batchsorttime; extern ps_metric_t ps_hw_batchdrawtime; +extern boolean gr_shadersavailable; + // hw_draw.c void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option); void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap); diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 2fbd9071e..681c42005 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -34,6 +34,7 @@ #include "../../i_system.h" // for I_GetPreciseTime (batching time measurements) #include "../hw_main.h" +#include "../hw_batching.h" // Eeeeh not sure is this right way, but it works < sry :c extern consvar_t cv_grusecustomshaders; @@ -638,8 +639,6 @@ static boolean gl_shadersenabled = false; static GLuint gl_currentshaderprogram = 0; static boolean gl_shaderprogramchanged = true; -static boolean gl_batching = false;// are we currently collecting batches? - static GLint gl_palette[768]; boolean gl_palette_initialized = false; static boolean gl_palshader = false; @@ -1464,7 +1463,7 @@ EXPORT void HWRAPI(InitPalette) (int flashnum, boolean skiplut) static void SetNoTexture(void) { // Disable texture. - if (tex_downloaded != NOTEXTURE_NUM && !gl_batching) + if (tex_downloaded != NOTEXTURE_NUM) { pglBindTexture(GL_TEXTURE_2D, NOTEXTURE_NUM); tex_downloaded = NOTEXTURE_NUM; @@ -1685,7 +1684,7 @@ EXPORT UINT32 HWRAPI(AddLightTable) (UINT8 *lighttable) pglTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 256, 32, 0, GL_RED, GL_UNSIGNED_BYTE, lighttable); // restore previously bound texture - if (!gl_batching) + if (!cv_grbatching.value) pglBindTexture(GL_TEXTURE_2D, tex_downloaded); return ltcachetail->id; @@ -2362,628 +2361,77 @@ static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAF #endif } - -// unfinished draw call batching - -// Note: could use realloc in the array reallocation code - -typedef struct +// code that is common between DrawPolygon and DrawIndexedTriangles +// the corona thing is there too, i have no idea if that stuff works with DrawIndexedTriangles and batching +static void PreparePolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FBITFIELD PolyFlags) { - FSurfaceInfo surf;// surf also has its own polyflags for some reason, but it seems unused - unsigned int vertsIndex;// location of verts in unsortedVertexArray - FUINT numVerts; - FBITFIELD polyFlags; - GLuint texNum; - GLuint shader; - // this tells batching that the plane belongs to a horizon line and must be drawn in correct order with the skywalls - boolean horizonSpecial; -} PolygonArrayEntry; + static GLRGBAFloat poly = {0,0,0,0}; + static GLRGBAFloat tint = {0,0,0,0}; + static GLRGBAFloat fade = {0,0,0,0}; -FOutVector* finalVertexArray = NULL;// contains subset of sorted vertices and texture coordinates to be sent to gpu -UINT32* finalVertexIndexArray = NULL;// contains indexes for glDrawElements, taking into account fan->triangles conversion -// NOTE have this alloced as 3x finalVertexArray size -int finalVertexArrayAllocSize = 65536; -//GLubyte* colorArray = NULL;// contains color data to be sent to gpu, if needed -//int colorArrayAllocSize = 65536; -// not gonna use this for now, just sort by color and change state when it changes -// later maybe when using vertex attributes if it's needed + SetBlend(PolyFlags); //TODO: inline (#pragma..) -PolygonArrayEntry* polygonArray = NULL;// contains the polygon data from DrawPolygon, waiting to be processed -int polygonArraySize = 0; -UINT32* polygonIndexArray = NULL;// contains sorting pointers for polygonArray -int polygonArrayAllocSize = 65536; - -FOutVector* unsortedVertexArray = NULL;// contains unsorted vertices and texture coordinates from DrawPolygon -int unsortedVertexArraySize = 0; -int unsortedVertexArrayAllocSize = 65536; - -EXPORT void HWRAPI(StartBatching) (void) -{ - //CONS_Printf("StartBatching begin\n"); - // init arrays if that has not been done yet - if (!finalVertexArray) + // PolyColor + if (pSurf) { - finalVertexArray = malloc(finalVertexArrayAllocSize * sizeof(FOutVector)); - finalVertexIndexArray = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32)); - polygonArray = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry)); - polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(UINT32)); - unsortedVertexArray = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector)); - } - // drawing functions will now collect the drawing data instead of passing it to opengl - gl_batching = true; - //CONS_Printf("StartBatching end\n"); -} + // If Modulated, mix the surface colour to the texture + if (CurrentPolyFlags & PF_Modulated) + { + // Poly color + poly.red = byte2float[pSurf->PolyColor.s.red]; + poly.green = byte2float[pSurf->PolyColor.s.green]; + poly.blue = byte2float[pSurf->PolyColor.s.blue]; + poly.alpha = byte2float[pSurf->PolyColor.s.alpha]; -static int comparePolygons(const void *p1, const void *p2) -{ - unsigned int index1 = *(const unsigned int*)p1; - unsigned int index2 = *(const unsigned int*)p2; - PolygonArrayEntry* poly1 = &polygonArray[index1]; - PolygonArrayEntry* poly2 = &polygonArray[index2]; - int diff; - INT64 diff64; + pglColor4ubv((GLubyte*)&pSurf->PolyColor.s); + } - int shader1 = poly1->shader; - int shader2 = poly2->shader; - // make skywalls and horizon lines first in order - if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial) - shader1 = -1; - if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial) - shader2 = -1; - diff = shader1 - shader2; - if (diff != 0) return diff; + // Tint color + tint.red = byte2float[pSurf->TintColor.s.red]; + tint.green = byte2float[pSurf->TintColor.s.green]; + tint.blue = byte2float[pSurf->TintColor.s.blue]; + tint.alpha = byte2float[pSurf->TintColor.s.alpha]; - // skywalls and horizon lines must retain their order for horizon lines to work - if (shader1 == -1 && shader2 == -1) - return index1 - index2; - - diff = poly1->texNum - poly2->texNum; - if (diff != 0) return diff; - - if (gl_palshader) - { - diff = poly1->surf.LightTableId - poly2->surf.LightTableId; - if (diff != 0) return diff; + // Fade color + fade.red = byte2float[pSurf->FadeColor.s.red]; + fade.green = byte2float[pSurf->FadeColor.s.green]; + fade.blue = byte2float[pSurf->FadeColor.s.blue]; + fade.alpha = byte2float[pSurf->FadeColor.s.alpha]; } - diff = poly1->polyFlags - poly2->polyFlags; - if (diff != 0) return diff; - - diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba; - if (diff64 < 0) return -1; else if (diff64 > 0) return 1; - diff64 = poly1->surf.TintColor.rgba - poly2->surf.TintColor.rgba; - if (diff64 < 0) return -1; else if (diff64 > 0) return 1; - diff64 = poly1->surf.FadeColor.rgba - poly2->surf.FadeColor.rgba; - if (diff64 < 0) return -1; else if (diff64 > 0) return 1; - - diff = poly1->surf.LightInfo.light_level - poly2->surf.LightInfo.light_level; - if (diff != 0) return diff; - 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; - return diff; -} - -static int comparePolygonsNoShaders(const void *p1, const void *p2) -{ - unsigned int index1 = *(const unsigned int*)p1; - unsigned int index2 = *(const unsigned int*)p2; - PolygonArrayEntry* poly1 = &polygonArray[index1]; - PolygonArrayEntry* poly2 = &polygonArray[index2]; - int diff; - INT64 diff64; - - GLuint texNum1 = poly1->texNum; - GLuint texNum2 = poly2->texNum; - if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial) - texNum1 = 0; - if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial) - texNum2 = 0; - diff = texNum1 - texNum2; - if (diff != 0) return diff; - - // skywalls and horizon lines must retain their order for horizon lines to work - if (texNum1 == 0 && texNum2 == 0) - return index1 - index2; - - diff = poly1->polyFlags - poly2->polyFlags; - if (diff != 0) return diff; - - diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba; - if (diff64 < 0) return -1; else if (diff64 > 0) return 1; - - return 0; -} - -// the parameters for this functions (numPolys etc.) are used to return rendering stats -EXPORT void HWRAPI(RenderBatches) (precise_t *sSortTime, precise_t *sDrawTime, int *sNumPolys, int *sNumVerts, int *sNumCalls, int *sNumShaders, int *sNumTextures, int *sNumPolyFlags, int *sNumColors) -{ - int finalVertexWritePos = 0;// position in finalVertexArray - int finalIndexWritePos = 0;// position in finalVertexIndexArray - - int polygonReadPos = 0;// position in polygonIndexArray - - GLuint currentShader; - GLuint currentTexture; - FBITFIELD currentPolyFlags; - FSurfaceInfo currentSurfaceInfo; - - GLRGBAFloat firstPoly = {0,0,0,0}; // may be misleading but this means first PolyColor - GLRGBAFloat firstTint = {0,0,0,0}; - GLRGBAFloat firstFade = {0,0,0,0}; - - boolean needRebind = false; - - int i; - - //CONS_Printf("RenderBatches\n"); - gl_batching = false;// no longer collecting batches - if (!polygonArraySize) - { - *sSortTime = *sDrawTime = *sNumPolys = *sNumCalls = *sNumShaders = *sNumTextures = *sNumPolyFlags = *sNumColors = 0; - return;// nothing to draw - } - // init stats vars - *sNumPolys = polygonArraySize; - *sNumCalls = *sNumVerts = 0; - *sNumShaders = *sNumTextures = *sNumPolyFlags = *sNumColors = 1; - // init polygonIndexArray - for (i = 0; i < polygonArraySize; i++) - { - polygonIndexArray[i] = i; - } - - // sort polygons - //CONS_Printf("qsort polys\n"); - *sSortTime = I_GetPreciseTime(); - if (gl_allowshaders) - qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons); - else - qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders); - *sSortTime = I_GetPreciseTime() - *sSortTime; - //CONS_Printf("sort done\n"); - // sort order - // 1. shader - // 2. texture - // 3. polyflags - // 4. colors + light level - // not sure about order of last 2, or if it even matters - - *sDrawTime = I_GetPreciseTime(); - - currentShader = polygonArray[polygonIndexArray[0]].shader; - currentTexture = polygonArray[polygonIndexArray[0]].texNum; - 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 - // and a color array could replace the color calls. - - // set state for first batch - //CONS_Printf("set first state\n"); - gl_currentshaderprogram = currentShader; - gl_shaderprogramchanged = true; - if (currentPolyFlags & PF_Modulated) - { - // Poly color - firstPoly.red = byte2float[currentSurfaceInfo.PolyColor.s.red]; - firstPoly.green = byte2float[currentSurfaceInfo.PolyColor.s.green]; - firstPoly.blue = byte2float[currentSurfaceInfo.PolyColor.s.blue]; - firstPoly.alpha = byte2float[currentSurfaceInfo.PolyColor.s.alpha]; - pglColor4ubv((GLubyte*)¤tSurfaceInfo.PolyColor.s); - } - // Tint color - firstTint.red = byte2float[currentSurfaceInfo.TintColor.s.red]; - firstTint.green = byte2float[currentSurfaceInfo.TintColor.s.green]; - firstTint.blue = byte2float[currentSurfaceInfo.TintColor.s.blue]; - firstTint.alpha = byte2float[currentSurfaceInfo.TintColor.s.alpha]; - // Fade color - firstFade.red = byte2float[currentSurfaceInfo.FadeColor.s.red]; - firstFade.green = byte2float[currentSurfaceInfo.FadeColor.s.green]; - firstFade.blue = byte2float[currentSurfaceInfo.FadeColor.s.blue]; - firstFade.alpha = byte2float[currentSurfaceInfo.FadeColor.s.alpha]; - - if (gl_allowshaders) - { - Shader_Load(¤tSurfaceInfo, &firstPoly, &firstTint, &firstFade); - if (gl_palshader) - { - pglActiveTexture(GL_TEXTURE2);// this stuff could be done better but gonna do it quick like this for now - pglBindTexture(GL_TEXTURE_2D, currentSurfaceInfo.LightTableId); - pglActiveTexture(GL_TEXTURE0); - } - } - - if (currentPolyFlags & PF_NoTexture) - currentTexture = 0; - pglBindTexture(GL_TEXTURE_2D, currentTexture); - tex_downloaded = currentTexture; - - SetBlend(currentPolyFlags); - - //CONS_Printf("first pointers to ogl\n"); - pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &finalVertexArray[0].x); - pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &finalVertexArray[0].s); - - while (1)// note: remember handling notexture polyflag as having texture number 0 (also in comparePolygons) - { - int firstIndex; - int lastIndex; - - boolean stopFlag = false; - boolean changeState = false; - boolean changeShader = false; - GLuint nextShader = 0U; - boolean changeTexture = false; - GLuint nextTexture = 0U; - boolean changePolyFlags = false; - FBITFIELD nextPolyFlags = 0U; - boolean changeSurfaceInfo = false; - FSurfaceInfo nextSurfaceInfo; - - //CONS_Printf("loop iter start\n"); - // new try: - // write vertices - // check for changes or end, otherwise go back to writing - // changes will affect the next vars and the change bools - // end could set flag for stopping - // execute draw call - // could check ending flag here - // change states according to next vars and change bools, updating the current vars and reseting the bools - // reset write pos - // repeat loop - - int index = polygonIndexArray[polygonReadPos++]; - int numVerts = polygonArray[index].numVerts; - // before writing, check if there is enough room - // using 'while' instead of 'if' here makes sure that there will *always* be enough room. - // probably never will this loop run more than once though - while (finalVertexWritePos + numVerts > finalVertexArrayAllocSize) - { - FOutVector* new_array; - unsigned int* new_index_array; - //CONS_Printf("final vert realloc\n"); - finalVertexArrayAllocSize *= 2; - new_array = malloc(finalVertexArrayAllocSize * sizeof(FOutVector)); - memcpy(new_array, finalVertexArray, finalVertexWritePos * sizeof(FOutVector)); - free(finalVertexArray); - finalVertexArray = new_array; - // also increase size of index array, 3x of vertex array since - // going from fans to triangles increases vertex count to 3x - new_index_array = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32)); - memcpy(new_index_array, finalVertexIndexArray, finalIndexWritePos * sizeof(UINT32)); - free(finalVertexIndexArray); - finalVertexIndexArray = new_index_array; - // if vertex buffers are reallocated then opengl needs to know too - needRebind = true; - } - //CONS_Printf("write verts to final\n"); - // write the vertices of the polygon - memcpy(&finalVertexArray[finalVertexWritePos], &unsortedVertexArray[polygonArray[index].vertsIndex], - numVerts * sizeof(FOutVector)); - // write the indexes, pointing to the fan vertexes but in triangles format - firstIndex = finalVertexWritePos; - lastIndex = finalVertexWritePos + numVerts; - finalVertexWritePos += 2; - //CONS_Printf("write final vert indices\n"); - while (finalVertexWritePos < lastIndex) - { - finalVertexIndexArray[finalIndexWritePos++] = firstIndex; - finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos - 1; - finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos++; - } - - if (polygonReadPos >= polygonArraySize) - { - stopFlag = true; - } - else - { - //CONS_Printf("state change check\n"); - // check if a state change is required, set the change bools and next vars - int nextIndex = polygonIndexArray[polygonReadPos]; - nextShader = polygonArray[nextIndex].shader; - nextTexture = polygonArray[nextIndex].texNum; - nextPolyFlags = polygonArray[nextIndex].polyFlags; - nextSurfaceInfo = polygonArray[nextIndex].surf; - if (nextPolyFlags & PF_NoTexture) - nextTexture = 0; - if (currentShader != nextShader) - { - changeState = true; - changeShader = true; - } - if (currentTexture != nextTexture) - { - changeState = true; - changeTexture = true; - } - if (currentPolyFlags != nextPolyFlags) - { - changeState = true; - changePolyFlags = true; - } - if (gl_allowshaders && gl_palshader) - { - if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba || - currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba || - 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.LightTableId != nextSurfaceInfo.LightTableId) - { - changeState = true; - changeSurfaceInfo = true; - } - } - else if ((gl_allowshaders) && (!gl_palshader)) - { - if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba || - currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba || - 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) - { - changeState = true; - changeSurfaceInfo = true; - } - } - else - { - if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba) - { - changeState = true; - changeSurfaceInfo = true; - } - } - } - - if (changeState || stopFlag) - { - if (needRebind) - { - //CONS_Printf("rebind\n"); - pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &finalVertexArray[0].x); - pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &finalVertexArray[0].s); - needRebind = false; - } - //CONS_Printf("exec draw call\n"); - // execute draw call - pglDrawElements(GL_TRIANGLES, finalIndexWritePos, GL_UNSIGNED_INT, finalVertexIndexArray); - //CONS_Printf("draw call done\n"); - // update stats - (*sNumCalls)++; - *sNumVerts += finalIndexWritePos; - // reset write positions - finalVertexWritePos = 0; - finalIndexWritePos = 0; - } - else continue; - - // if we're here then either its time to stop or time to change state - if (stopFlag) break; - - //CONS_Printf("state change\n"); - - // change state according to change bools and next vars, update current vars and reset bools - if (changeShader) - { - GLRGBAFloat poly = {0,0,0,0}; - GLRGBAFloat tint = {0,0,0,0}; - GLRGBAFloat fade = {0,0,0,0}; - gl_currentshaderprogram = nextShader; - gl_shaderprogramchanged = true; - if (nextPolyFlags & PF_Modulated) - { - // Poly color - poly.red = byte2float[nextSurfaceInfo.PolyColor.s.red]; - poly.green = byte2float[nextSurfaceInfo.PolyColor.s.green]; - poly.blue = byte2float[nextSurfaceInfo.PolyColor.s.blue]; - poly.alpha = byte2float[nextSurfaceInfo.PolyColor.s.alpha]; - } - // Tint color - tint.red = byte2float[nextSurfaceInfo.TintColor.s.red]; - tint.green = byte2float[nextSurfaceInfo.TintColor.s.green]; - tint.blue = byte2float[nextSurfaceInfo.TintColor.s.blue]; - tint.alpha = byte2float[nextSurfaceInfo.TintColor.s.alpha]; - // Fade color - fade.red = byte2float[nextSurfaceInfo.FadeColor.s.red]; - fade.green = byte2float[nextSurfaceInfo.FadeColor.s.green]; - fade.blue = byte2float[nextSurfaceInfo.FadeColor.s.blue]; - fade.alpha = byte2float[nextSurfaceInfo.FadeColor.s.alpha]; - - Shader_Load(&nextSurfaceInfo, &poly, &tint, &fade); - currentShader = nextShader; - changeShader = false; - - (*sNumShaders)++; - } - if (changeTexture) - { - // texture should be already ready for use from calls to SetTexture during batch collection - pglBindTexture(GL_TEXTURE_2D, nextTexture); - tex_downloaded = nextTexture; - currentTexture = nextTexture; - changeTexture = false; - - (*sNumTextures)++; - } - if (changePolyFlags) - { - SetBlend(nextPolyFlags); - currentPolyFlags = nextPolyFlags; - changePolyFlags = false; - - (*sNumPolyFlags)++; - } - if (changeSurfaceInfo) - { - GLRGBAFloat poly = {0,0,0,0}; - GLRGBAFloat tint = {0,0,0,0}; - GLRGBAFloat fade = {0,0,0,0}; - gl_shaderprogramchanged = false; - if (nextPolyFlags & PF_Modulated) - { - // Poly color - poly.red = byte2float[nextSurfaceInfo.PolyColor.s.red]; - poly.green = byte2float[nextSurfaceInfo.PolyColor.s.green]; - poly.blue = byte2float[nextSurfaceInfo.PolyColor.s.blue]; - poly.alpha = byte2float[nextSurfaceInfo.PolyColor.s.alpha]; - pglColor4ubv((GLubyte*)&nextSurfaceInfo.PolyColor.s); - } - if (gl_allowshaders) - { - // Tint color - tint.red = byte2float[nextSurfaceInfo.TintColor.s.red]; - tint.green = byte2float[nextSurfaceInfo.TintColor.s.green]; - tint.blue = byte2float[nextSurfaceInfo.TintColor.s.blue]; - tint.alpha = byte2float[nextSurfaceInfo.TintColor.s.alpha]; - // Fade color - fade.red = byte2float[nextSurfaceInfo.FadeColor.s.red]; - fade.green = byte2float[nextSurfaceInfo.FadeColor.s.green]; - fade.blue = byte2float[nextSurfaceInfo.FadeColor.s.blue]; - fade.alpha = byte2float[nextSurfaceInfo.FadeColor.s.alpha]; - - Shader_Load(&nextSurfaceInfo, &poly, &tint, &fade); - - if (gl_palshader) - { - pglActiveTexture(GL_TEXTURE2);// this stuff could be done better but gonna do it quick like this for now - pglBindTexture(GL_TEXTURE_2D, nextSurfaceInfo.LightTableId); - pglActiveTexture(GL_TEXTURE0); - } - } - - currentSurfaceInfo = nextSurfaceInfo; - changeSurfaceInfo = false; - - (*sNumColors)++; - } - // and that should be it? - } - // reset the arrays (set sizes to 0) - polygonArraySize = 0; - unsortedVertexArraySize = 0; - - *sDrawTime = I_GetPreciseTime() - *sDrawTime; + Shader_Load(pSurf, &poly, &tint, &fade); } // -----------------+ // DrawPolygon : Render a polygon, set the texture, set render mode // -----------------+ -EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, boolean horizonSpecial) +EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags) { - if (gl_batching) - { - //CONS_Printf("Batched DrawPolygon\n"); - if (!pSurf) - I_Error("Got a null FSurfaceInfo in batching");// nulls should only come in sky background pic drawing - if (polygonArraySize == polygonArrayAllocSize) - { - PolygonArrayEntry* new_array; - // ran out of space, make new array double the size - polygonArrayAllocSize *= 2; - new_array = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry)); - memcpy(new_array, polygonArray, polygonArraySize * sizeof(PolygonArrayEntry)); - free(polygonArray); - polygonArray = new_array; - // also need to redo the index array, dont need to copy it though - free(polygonIndexArray); - polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(unsigned int)); - } + PreparePolygon(pSurf, pOutVerts, PolyFlags); - while (unsortedVertexArraySize + (int)iNumPts > unsortedVertexArrayAllocSize) - { - FOutVector* new_array; - // need more space for vertices in unsortedVertexArray - unsortedVertexArrayAllocSize *= 2; - new_array = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector)); - memcpy(new_array, unsortedVertexArray, unsortedVertexArraySize * sizeof(FOutVector)); - free(unsortedVertexArray); - unsortedVertexArray = new_array; - } + pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x); + pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].s); + pglDrawArrays(GL_TRIANGLE_FAN, 0, iNumPts); - // add the polygon data to the arrays + if (PolyFlags & PF_RemoveYWrap) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - polygonArray[polygonArraySize].surf = *pSurf; - polygonArray[polygonArraySize].vertsIndex = unsortedVertexArraySize; - polygonArray[polygonArraySize].numVerts = iNumPts; - polygonArray[polygonArraySize].polyFlags = PolyFlags; - polygonArray[polygonArraySize].texNum = tex_downloaded; - polygonArray[polygonArraySize].shader = gl_currentshaderprogram; - polygonArray[polygonArraySize].horizonSpecial = horizonSpecial; - polygonArraySize++; + if (PolyFlags & PF_ForceWrapX) + Clamp2D(GL_TEXTURE_WRAP_S); - memcpy(&unsortedVertexArray[unsortedVertexArraySize], pOutVerts, iNumPts * sizeof(FOutVector)); - unsortedVertexArraySize += iNumPts; - } - else - { - static GLRGBAFloat poly = {0,0,0,0}; - static GLRGBAFloat tint = {0,0,0,0}; - static GLRGBAFloat fade = {0,0,0,0}; + if (PolyFlags & PF_ForceWrapY) + Clamp2D(GL_TEXTURE_WRAP_T); +} - SetBlend(PolyFlags); //TODO: inline (#pragma..) +EXPORT void HWRAPI(DrawIndexedTriangles) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, unsigned int *IndexArray) +{ + PreparePolygon(pSurf, pOutVerts, PolyFlags); - if (gl_portal_mode == HWD_PORTAL_NORMAL) - { - // PolyColor - if (pSurf) - { - // If modulated, mix the surface colour to the texture - if (CurrentPolyFlags & PF_Modulated) - pglColor4ubv((GLubyte*)&pSurf->PolyColor.s); + pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x); + pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].s); + pglDrawElements(GL_TRIANGLES, iNumPts, GL_UNSIGNED_INT, IndexArray); - // If the surface is either modulated or colormapped, or both - if (CurrentPolyFlags & (PF_Modulated | PF_ColorMapped)) - { - poly.red = byte2float[pSurf->PolyColor.s.red]; - poly.green = byte2float[pSurf->PolyColor.s.green]; - poly.blue = byte2float[pSurf->PolyColor.s.blue]; - poly.alpha = byte2float[pSurf->PolyColor.s.alpha]; - } - - // Only if the surface is colormapped - if (CurrentPolyFlags & PF_ColorMapped) - { - tint.red = byte2float[pSurf->TintColor.s.red]; - tint.green = byte2float[pSurf->TintColor.s.green]; - tint.blue = byte2float[pSurf->TintColor.s.blue]; - tint.alpha = byte2float[pSurf->TintColor.s.alpha]; - - fade.red = byte2float[pSurf->FadeColor.s.red]; - fade.green = byte2float[pSurf->FadeColor.s.green]; - fade.blue = byte2float[pSurf->FadeColor.s.blue]; - fade.alpha = byte2float[pSurf->FadeColor.s.alpha]; - } - - if (gl_palshader && gl_allowshaders) - { - pglActiveTexture(GL_TEXTURE2); - pglBindTexture(GL_TEXTURE_2D, pSurf->LightTableId); - pglActiveTexture(GL_TEXTURE0); - } - } - - Shader_Load(pSurf, &poly, &tint, &fade); - } - else - UnSetShader(); - - pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x); - pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].s); - pglDrawArrays(GL_TRIANGLE_FAN, 0, iNumPts); - - if (PolyFlags & PF_RemoveYWrap) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - - if (PolyFlags & PF_ForceWrapX) - Clamp2D(GL_TEXTURE_WRAP_S); - - if (PolyFlags & PF_ForceWrapY) - Clamp2D(GL_TEXTURE_WRAP_T); - } + // the DrawPolygon variant of this has some code about polyflags and wrapping here but havent noticed any problems from omitting it? } // Sky dome code, taken/backported from SRB2 diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index 96b7b0679..181866443 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -81,6 +81,7 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(SetupGLInfo); GETFUNC(Draw2DLine); GETFUNC(DrawPolygon); + GETFUNC(DrawIndexedTriangles); GETFUNC(SetBlend); GETFUNC(ClearBuffer); GETFUNC(SetTexture); @@ -114,10 +115,7 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(SetShaderInfo); GETFUNC(LoadCustomShader); GETFUNC(InitCustomShaders); - - GETFUNC(StartBatching); - GETFUNC(RenderBatches); - + GETFUNC(InitPalette); GETFUNC(AddLightTable); GETFUNC(ClearLightTableCache); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index dd2953716..9011c333d 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -2113,6 +2113,7 @@ void I_StartupGraphics(void) HWD.pfnFinishUpdate = NULL; HWD.pfnDraw2DLine = hwSym("Draw2DLine",NULL); HWD.pfnDrawPolygon = hwSym("DrawPolygon",NULL); + HWD.pfnDrawIndexedTriangles = hwSym("DrawIndexedTriangles",NULL); HWD.pfnSetBlend = hwSym("SetBlend",NULL); HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL); HWD.pfnSetTexture = hwSym("SetTexture",NULL); @@ -2148,9 +2149,6 @@ void I_StartupGraphics(void) HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL); HWD.pfnInitCustomShaders = hwSym("InitCustomShaders",NULL); - HWD.pfnStartBatching = hwSym("StartBatching",NULL); - HWD.pfnRenderBatches = hwSym("RenderBatches",NULL); - HWD.pfnInitPalette = hwSym("InitPalette",NULL); HWD.pfnAddLightTable = hwSym("AddLightTable",NULL); HWD.pfnClearLightTableCache = hwSym("ClearLightTableCache",NULL); -- 2.54.0 From 08e5b4844e00590e5718ef4770c02ce821baeca3 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 15 Jan 2024 13:59:43 +0100 Subject: [PATCH 02/24] fix palshader --- src/hardware/r_opengl/r_opengl.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 681c42005..5a3ea3360 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -2397,6 +2397,13 @@ static void PreparePolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FBITFIELD fade.green = byte2float[pSurf->FadeColor.s.green]; fade.blue = byte2float[pSurf->FadeColor.s.blue]; fade.alpha = byte2float[pSurf->FadeColor.s.alpha]; + + if (HWR_ShouldUsePaletteRendering && gl_allowshaders) + { + pglActiveTexture(GL_TEXTURE2); + pglBindTexture(GL_TEXTURE_2D, pSurf->LightTableId); + pglActiveTexture(GL_TEXTURE0); + } } Shader_Load(pSurf, &poly, &tint, &fade); -- 2.54.0 From 35e8d54fc4ba74c7e4b3440e6afb16fd04e479cc Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 15 Jan 2024 14:21:38 +0100 Subject: [PATCH 03/24] oopsie --- src/hardware/r_opengl/r_opengl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 5a3ea3360..418967bf3 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -2398,7 +2398,7 @@ static void PreparePolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FBITFIELD fade.blue = byte2float[pSurf->FadeColor.s.blue]; fade.alpha = byte2float[pSurf->FadeColor.s.alpha]; - if (HWR_ShouldUsePaletteRendering && gl_allowshaders) + if (HWR_ShouldUsePaletteRendering() && gl_allowshaders) { pglActiveTexture(GL_TEXTURE2); pglBindTexture(GL_TEXTURE_2D, pSurf->LightTableId); -- 2.54.0 From 5e0fe497f516808fe4e928f0263db56ba3e6faba Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 15 Jan 2024 14:27:01 +0100 Subject: [PATCH 04/24] add stuff here too --- src/CMakeLists.txt | 2 ++ src/sdl/Srb2SDL-vc10.vcxproj | 2 ++ src/sdl/Srb2SDL-vc10.vcxproj.filters | 6 ++++++ 3 files changed, 10 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8f6a56235..d2985dc21 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -452,6 +452,7 @@ endif() if(${SRB2_CONFIG_HWRENDER}) add_definitions(-DHWRENDER) set(SRB2_HWRENDER_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_batching.c ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_bsp.c ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_cache.c ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.c @@ -467,6 +468,7 @@ if(${SRB2_CONFIG_HWRENDER}) ) set (SRB2_HWRENDER_HEADERS + ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_batching.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_data.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_defs.h diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj index 813e31a98..e51799314 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj +++ b/src/sdl/Srb2SDL-vc10.vcxproj @@ -218,6 +218,7 @@ + @@ -364,6 +365,7 @@ + diff --git a/src/sdl/Srb2SDL-vc10.vcxproj.filters b/src/sdl/Srb2SDL-vc10.vcxproj.filters index f197a394b..2234d7620 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj.filters +++ b/src/sdl/Srb2SDL-vc10.vcxproj.filters @@ -215,6 +215,9 @@ Hw_Hardware + + + Hw_Hardware Hw_Hardware @@ -617,6 +620,9 @@ Hw_Hardware + + + Hw_Hardware Hw_Hardware -- 2.54.0 From 3eb8886890076baad71917f1b6d3dd3299abe3de Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 15 Jan 2024 15:10:02 +0100 Subject: [PATCH 05/24] remove Shader_Load as Shader_SetUniforms literally did the same thing --- src/hardware/r_opengl/r_opengl.c | 59 ++++++++++++++------------------ 1 file changed, 25 insertions(+), 34 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 418967bf3..5f03a2995 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -128,9 +128,10 @@ static GLuint endScreenWipe = 0; static GLuint finalScreenTexture = 0; // Lactozilla: Set shader programs and uniforms -static void *Shader_Load(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade); static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade); +static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; + // shortcut for ((float)1/i) static const GLfloat byte2float[256] = { 0.000000f, 0.003922f, 0.007843f, 0.011765f, 0.015686f, 0.019608f, 0.023529f, 0.027451f, @@ -2282,43 +2283,33 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) } } - -static void *Shader_Load(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade) -{ -#ifdef GL_SHADERS - if (gl_shadersenabled && pglUseProgram) - { - gl_shaderprogram_t *shader = &gl_shaderprograms[gl_currentshaderprogram]; - if (shader->program) - { - if (gl_shaderprogramchanged) - { - pglUseProgram(gl_shaderprograms[gl_currentshaderprogram].program); - gl_shaderprogramchanged = false; - } - Shader_SetUniforms(Surface, poly, tint, fade); - return shader; - } - else - pglUseProgram(0); - } -#else - (void)Surface; - (void)poly; - (void)tint; - (void)fade; -#endif - return NULL; -} - static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade) { + gl_shaderprogram_t *shader = &gl_shaderprograms[gl_currentshaderprogram]; + #ifdef GL_SHADERS - if (gl_shadersenabled) + if (gl_shadersenabled && (shader != NULL) && pglUseProgram) { - gl_shaderprogram_t *shader = &gl_shaderprograms[gl_currentshaderprogram]; + if (!shader->program) + { + pglUseProgram(0); return; + } + + if (gl_shaderprogramchanged) + { + pglUseProgram(gl_shaderprograms[gl_currentshaderprogram].program); + gl_shaderprogramchanged = false; + } + + // Color uniforms can be left NULL and will be set to white (1.0f, 1.0f, 1.0f, 1.0f) + if (poly == NULL) + poly = &shader_defaultcolor; + if (tint == NULL) + tint = &shader_defaultcolor; + if (fade == NULL) + fade = &shader_defaultcolor; #define UNIFORM_1(uniform, a, function) \ if (uniform != -1) \ @@ -2406,7 +2397,7 @@ static void PreparePolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FBITFIELD } } - Shader_Load(pSurf, &poly, &tint, &fade); + Shader_SetUniforms(pSurf, &poly, &tint, &fade); } // -----------------+ @@ -3182,7 +3173,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float fade.blue = byte2float[Surface->FadeColor.s.blue]; fade.alpha = byte2float[Surface->FadeColor.s.alpha]; - Shader_Load(Surface, &poly, &tint, &fade); + Shader_SetUniforms(Surface, &poly, &tint, &fade); pglEnable(GL_CULL_FACE); pglEnable(GL_NORMALIZE); -- 2.54.0 From d071f52707bc1194fa7a611194e0f72b6aa33218 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 17 Jan 2024 18:15:54 +0100 Subject: [PATCH 06/24] fix typo --- src/hardware/hw_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index bf733b637..56b72eae7 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1030,7 +1030,7 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf) shader = (HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader } - HWD.HWR_ProcessPolygon(&pSurf, wallVerts, 4, i|PF_Modulated|PF_Decal, shader, false); + HWR_ProcessPolygon(&pSurf, wallVerts, 4, i|PF_Modulated|PF_Decal, shader, false); } } #endif -- 2.54.0 From 3dcf4f6f6472b76fe8cd124c52ee5c35c3bac8e4 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 17 Jan 2024 18:31:36 +0100 Subject: [PATCH 07/24] Refactor Batching code from Hannu Hanhi https://git.do.srb2.org/STJr/SRB2/-/commit/707687beea50a2bfcc14638e923ac516195351b1?merge_request_iid=1774 --- src/hardware/hw_batching.c | 569 ++++++++++++++++++------------------- src/hardware/hw_batching.h | 12 - 2 files changed, 275 insertions(+), 306 deletions(-) diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c index b56278c7d..bbb228367 100644 --- a/src/hardware/hw_batching.c +++ b/src/hardware/hw_batching.c @@ -15,29 +15,54 @@ #include "hw_main.h" #include "../i_system.h" +typedef struct +{ + FSurfaceInfo surf; // surf also has its own polyflags for some reason, but it seems unused + unsigned int vertsIndex; // location of verts in unsortedVertices + FUINT numVerts; + FBITFIELD polyFlags; + GLMipmap_t *texture; + 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; +} DrawCallInfo; + // The texture for the next polygon given to HWR_ProcessPolygon. // Set with HWR_SetCurrentTexture. GLMipmap_t *current_texture = NULL; boolean currently_batching = false; -FOutVector* finalVertexArray = NULL;// contains subset of sorted vertices and texture coordinates to be sent to gpu -UINT32* finalVertexIndexArray = NULL;// contains indexes for glDrawElements, taking into account fan->triangles conversion -// NOTE have this alloced as 3x finalVertexArray size -int finalVertexArrayAllocSize = 65536; -//GLubyte* colorArray = NULL;// contains color data to be sent to gpu, if needed -//int colorArrayAllocSize = 65536; -// not gonna use this for now, just sort by color and change state when it changes -// later maybe when using vertex attributes if it's needed +// Dynamic arrays for: +// - unsorted draw calls +// - sorted order of draw calls +// - unsorted vertices +// - final (sorted) vertices +// - vertex indices for sorted vertices -PolygonArrayEntry* polygonArray = NULL;// contains the polygon data from DrawPolygon, waiting to be processed -int polygonArraySize = 0; -UINT32* polygonIndexArray = NULL;// contains sorting pointers for polygonArray -int polygonArrayAllocSize = 65536; +// contains the draw calls from DrawPolygon, waiting to be processed +DrawCallInfo* drawCalls = NULL; +int drawCallsSize = 0; +int drawCallsCapacity = 65536; -FOutVector* unsortedVertexArray = NULL;// contains unsorted vertices and texture coordinates from DrawPolygon -int unsortedVertexArraySize = 0; -int unsortedVertexArrayAllocSize = 65536; +// contains sorted order (array indices) for drawCalls +// (therefore size and capacity shared with it) +UINT32* drawCallOrder = NULL; + +// contains unsorted vertices and texture coordinates from DrawPolygon +FOutVector* unsortedVertices = NULL; +int unsortedVerticesSize = 0; +int unsortedVerticesCapacity = 65536; + +// contains subset of sorted vertices and texture coordinates to be sent to gpu +FOutVector* finalVertices = NULL; +int finalVerticesSize = 0; +int finalVerticesCapacity = 65536; + +// contains vertex indices into finalVertices for glDrawElements, +// taking into account fan->triangles conversion +UINT32* finalIndices = NULL; // this is alloced with 3x finalVertices size +int finalIndicesSize = 0; // Enables batching mode. HWR_ProcessPolygon will collect polygons instead of passing them directly to the rendering backend. // Call HWR_RenderBatches to render all the collected geometry. @@ -47,13 +72,13 @@ void HWR_StartBatching(void) I_Error("Repeat call to HWR_StartBatching without HWR_RenderBatches"); // init arrays if that has not been done yet - if (!finalVertexArray) + if (!finalVertices) { - finalVertexArray = malloc(finalVertexArrayAllocSize * sizeof(FOutVector)); - finalVertexIndexArray = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32)); - polygonArray = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry)); - polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(UINT32)); - unsortedVertexArray = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector)); + finalVertices = malloc(finalVerticesCapacity * sizeof(FOutVector)); + finalIndices = malloc(finalVerticesCapacity * 3 * sizeof(UINT32)); + drawCalls = malloc(drawCallsCapacity * sizeof(DrawCallInfo)); + drawCallOrder = malloc(drawCallsCapacity * sizeof(UINT32)); + unsortedVertices = malloc(unsortedVerticesCapacity * sizeof(FOutVector)); } currently_batching = true; @@ -64,14 +89,55 @@ 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) + current_texture = texture; + else + HWD.pfnSetTexture(texture); +} + +static void HWR_CollectDrawCallInfo(FSurfaceInfo *pSurf, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial) +{ + // make sure dynamic array has capacity + if (drawCallsSize == drawCallsCapacity) + { + DrawCallInfo* new_array; + // ran out of space, make new array double the size + drawCallsCapacity *= 2; + new_array = malloc(drawCallsCapacity * sizeof(DrawCallInfo)); + memcpy(new_array, drawCalls, drawCallsSize * sizeof(DrawCallInfo)); + free(drawCalls); + drawCalls = new_array; + // also need to redo the index array, dont need to copy it though + free(drawCallOrder); + drawCallOrder = malloc(drawCallsCapacity * sizeof(UINT32)); + } + // add entry to array + drawCalls[drawCallsSize].surf = *pSurf; + drawCalls[drawCallsSize].vertsIndex = unsortedVerticesSize; + drawCalls[drawCallsSize].numVerts = iNumPts; + drawCalls[drawCallsSize].polyFlags = PolyFlags; + drawCalls[drawCallsSize].texture = current_texture; + drawCalls[drawCallsSize].shader = shader; + drawCalls[drawCallsSize].horizonSpecial = horizonSpecial; + drawCallsSize++; +} + +static void HWR_CollectDrawCallVertices(FOutVector *pOutVerts, FUINT iNumPts) +{ + // make sure dynamic array has capacity + while (unsortedVerticesSize + (int)iNumPts > unsortedVerticesCapacity) + { + FOutVector* new_array; + // need more space for vertices in unsortedVertices + unsortedVerticesCapacity *= 2; + new_array = malloc(unsortedVerticesCapacity * sizeof(FOutVector)); + memcpy(new_array, unsortedVertices, unsortedVerticesSize * sizeof(FOutVector)); + free(unsortedVertices); + unsortedVertices = new_array; + } + // add vertices to array + memcpy(&unsortedVertices[unsortedVerticesSize], pOutVerts, iNumPts * sizeof(FOutVector)); + unsortedVerticesSize += iNumPts; } // If batching is enabled, this function collects the polygon data and the chosen texture @@ -79,48 +145,16 @@ 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 - if (polygonArraySize == polygonArrayAllocSize) { - PolygonArrayEntry* new_array; - // ran out of space, make new array double the size - polygonArrayAllocSize *= 2; - new_array = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry)); - memcpy(new_array, polygonArray, polygonArraySize * sizeof(PolygonArrayEntry)); - free(polygonArray); - polygonArray = new_array; - // also need to redo the index array, dont need to copy it though - free(polygonIndexArray); - polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(UINT32)); + // handling null FSurfaceInfo is not implemented + I_Error("Got a null FSurfaceInfo in batching"); } - while (unsortedVertexArraySize + (int)iNumPts > unsortedVertexArrayAllocSize) - { - FOutVector* new_array; - // need more space for vertices in unsortedVertexArray - unsortedVertexArrayAllocSize *= 2; - new_array = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector)); - memcpy(new_array, unsortedVertexArray, unsortedVertexArraySize * sizeof(FOutVector)); - free(unsortedVertexArray); - unsortedVertexArray = new_array; - } - - // add the polygon data to the arrays - - polygonArray[polygonArraySize].surf = *pSurf; - polygonArray[polygonArraySize].vertsIndex = unsortedVertexArraySize; - polygonArray[polygonArraySize].numVerts = iNumPts; - polygonArray[polygonArraySize].polyFlags = PolyFlags; - polygonArray[polygonArraySize].texture = current_texture; - polygonArray[polygonArraySize].shader = shader; - polygonArray[polygonArraySize].horizonSpecial = horizonSpecial; - polygonArraySize++; - - memcpy(&unsortedVertexArray[unsortedVertexArraySize], pOutVerts, iNumPts * sizeof(FOutVector)); - unsortedVertexArraySize += iNumPts; + HWR_CollectDrawCallInfo(pSurf, iNumPts, PolyFlags, shader, horizonSpecial); + HWR_CollectDrawCallVertices(pOutVerts, iNumPts); } else { @@ -130,12 +164,12 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt } } -static int comparePolygons(const void *p1, const void *p2) +static int compareDrawCalls(const void *p1, const void *p2) { - unsigned int index1 = *(const unsigned int*)p1; - unsigned int index2 = *(const unsigned int*)p2; - PolygonArrayEntry* poly1 = &polygonArray[index1]; - PolygonArrayEntry* poly2 = &polygonArray[index2]; + UINT32 index1 = *(const UINT32*)p1; + UINT32 index2 = *(const UINT32*)p2; + DrawCallInfo* poly1 = &drawCalls[index1]; + DrawCallInfo* poly2 = &drawCalls[index2]; int diff; INT64 diff64; UINT32 downloaded1 = 0; @@ -186,12 +220,12 @@ static int comparePolygons(const void *p1, const void *p2) return diff; } -static int comparePolygonsNoShaders(const void *p1, const void *p2) +static int compareDrawCallsNoShaders(const void *p1, const void *p2) { - unsigned int index1 = *(const unsigned int*)p1; - unsigned int index2 = *(const unsigned int*)p2; - PolygonArrayEntry* poly1 = &polygonArray[index1]; - PolygonArrayEntry* poly2 = &polygonArray[index2]; + UINT32 index1 = *(const UINT32*)p1; + UINT32 index2 = *(const UINT32*)p2; + DrawCallInfo* poly1 = &drawCalls[index1]; + DrawCallInfo* poly2 = &drawCalls[index2]; int diff; INT64 diff64; @@ -222,60 +256,155 @@ static int comparePolygonsNoShaders(const void *p1, const void *p2) return 0; } -// This function organizes the geometry collected by HWR_ProcessPolygon calls into batches and uses -// the rendering backend to draw them. +static void HWR_CollectVerticesIntoBatch(DrawCallInfo *drawCall) +{ + int firstVIndex; + int lastVIndex; + int numVerts = drawCall->numVerts; + // before writing, check if there is enough room + // using 'while' instead of 'if' here makes sure that there will *always* be enough room. + // probably never will this loop run more than once though + while (finalVerticesSize + numVerts > finalVerticesCapacity) + { + FOutVector* new_array; + UINT32* new_index_array; + finalVerticesCapacity *= 2; + new_array = malloc(finalVerticesCapacity * sizeof(FOutVector)); + memcpy(new_array, finalVertices, finalVerticesSize * sizeof(FOutVector)); + free(finalVertices); + finalVertices = new_array; + // also increase size of index array, 3x of vertex array since + // going from fans to triangles increases vertex count to 3x + new_index_array = malloc(finalVerticesCapacity * 3 * sizeof(UINT32)); + memcpy(new_index_array, finalIndices, finalIndicesSize * sizeof(UINT32)); + free(finalIndices); + finalIndices = new_index_array; + } + // write the vertices of the polygon + memcpy(&finalVertices[finalVerticesSize], &unsortedVertices[drawCall->vertsIndex], + numVerts * sizeof(FOutVector)); + // write the indexes, pointing to the fan vertexes but in triangles format + firstVIndex = finalVerticesSize; + lastVIndex = finalVerticesSize + numVerts; + finalVerticesSize += 2; + while (finalVerticesSize < lastVIndex) + { + finalIndices[finalIndicesSize++] = firstVIndex; + finalIndices[finalIndicesSize++] = finalVerticesSize - 1; + finalIndices[finalIndicesSize++] = finalVerticesSize++; + } +} + +static GLMipmap_t *HWR_GetDrawCallTexture(DrawCallInfo *dc) +{ + return (dc->polyFlags & PF_NoTexture) ? NULL : dc->texture; +} + +// flags returned by HWR_MarkStateChanges +#define SHADER_CHANGED 1 +#define TEXTURE_CHANGED 2 +#define POLYFLAGS_CHANGED 4 +#define SURFACEINFO_CHANGED 8 + +static unsigned int HWR_MarkStateChanges(DrawCallInfo *current, DrawCallInfo *next) +{ + unsigned int stateChanges = 0; + FSurfaceInfo *currentSI = ¤t->surf; + FSurfaceInfo *nextSI = &next->surf; + + // check if a state change is required and flag it to stateChanges + + if (current->shader != next->shader && cv_grshaders.value && gr_shadersavailable) + stateChanges |= SHADER_CHANGED; + if (HWR_GetDrawCallTexture(current) != HWR_GetDrawCallTexture(next)) + stateChanges |= TEXTURE_CHANGED; + if (current->polyFlags != next->polyFlags) + stateChanges |= POLYFLAGS_CHANGED; + if (cv_grshaders.value && gr_shadersavailable) + { + if (currentSI->PolyColor.rgba != nextSI->PolyColor.rgba || + currentSI->TintColor.rgba != nextSI->TintColor.rgba || + currentSI->FadeColor.rgba != nextSI->FadeColor.rgba || + currentSI->LightInfo.light_level != nextSI->LightInfo.light_level || + currentSI->LightInfo.fade_start != nextSI->LightInfo.fade_start || + currentSI->LightInfo.fade_end != nextSI->LightInfo.fade_end) + { + stateChanges |= SURFACEINFO_CHANGED; + } + } + else + { + if (currentSI->PolyColor.rgba != nextSI->PolyColor.rgba) + stateChanges |= SURFACEINFO_CHANGED; + } + + return stateChanges; +} + +static void HWR_ExecuteStateChanges(unsigned int stateChanges, DrawCallInfo *dc) +{ + if ((stateChanges & SHADER_CHANGED) && cv_grshaders.value && gr_shadersavailable) + { + HWD.pfnSetShader(dc->shader); + ps_hw_numshaders.value.i++; + } + if (stateChanges & TEXTURE_CHANGED) + { + // for PF_NoTexture the texture is set in DrawIndexedTriangles + if (!(dc->polyFlags & PF_NoTexture)) + { + // texture should be already ready for use from calls to + // SetTexture during batch collection + HWD.pfnSetTexture(dc->texture); + } + ps_hw_numtextures.value.i++; + } + // these two are just parameters to DrawIndexedTriangles + // (changes to polyflags states are tracked in r_opengl.c though) + if (stateChanges & POLYFLAGS_CHANGED) + ps_hw_numpolyflags.value.i++; + if (stateChanges & SURFACEINFO_CHANGED) + ps_hw_numcolors.value.i++; +} + + +static void HWR_InitBatchingStats(void) +{ + ps_hw_numpolys.value.i = drawCallsSize; + ps_hw_numcalls.value.i = ps_hw_numverts.value.i + = ps_hw_numshaders.value.i = ps_hw_numtextures.value.i + = ps_hw_numpolyflags.value.i = ps_hw_numcolors.value.i = 0; +} + +// This function organizes the geometry and draw calls collected by HWR_ProcessPolygon +// calls into batches and uses the rendering backend to draw them. void HWR_RenderBatches(void) { - 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 *nextTexture = NULL; - FBITFIELD currentPolyFlags = 0; - FBITFIELD nextPolyFlags = 0; - FSurfaceInfo currentSurfaceInfo; - FSurfaceInfo nextSurfaceInfo; - + int drawCallReadPos = 0; // position in drawCallOrder int i; - if (!currently_batching) + if (!currently_batching) I_Error("HWR_RenderBatches called without starting batching"); - nextSurfaceInfo.LightInfo.fade_end = 0; - nextSurfaceInfo.LightInfo.fade_start = 0; - nextSurfaceInfo.LightInfo.light_level = 0; + currently_batching = false; // no longer collecting batches - currently_batching = false;// no longer collecting batches - if (!polygonArraySize) - { - ps_hw_numpolys.value.i = ps_hw_numcalls.value.i = ps_hw_numshaders.value.i - = ps_hw_numtextures.value.i = ps_hw_numpolyflags.value.i - = ps_hw_numcolors.value.i = 0; - return;// nothing to draw - } - // init stats vars - ps_hw_numpolys.value.i = polygonArraySize; - ps_hw_numcalls.value.i = ps_hw_numverts.value.i = 0; - ps_hw_numshaders.value.i = ps_hw_numtextures.value.i - = ps_hw_numpolyflags.value.i = ps_hw_numcolors.value.i = 1; - // init polygonIndexArray - for (i = 0; i < polygonArraySize; i++) - { - polygonIndexArray[i] = i; - } + HWR_InitBatchingStats(); - // sort polygons + if (!drawCallsSize) + return; // nothing to draw + + // init drawCallOrder + for (i = 0; i < drawCallsSize; i++) + drawCallOrder[i] = i; + + // sort the draw calls PS_START_TIMING(ps_hw_batchsorttime); if (cv_grshaders.value && gr_shadersavailable) - qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons); + qsort(drawCallOrder, drawCallsSize, sizeof(UINT32), compareDrawCalls); else - qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders); + qsort(drawCallOrder, drawCallsSize, sizeof(UINT32), compareDrawCallsNoShaders); PS_STOP_TIMING(ps_hw_batchsorttime); - // sort order + // sort grouping order // 1. shader // 2. texture // 3. polyflags @@ -284,205 +413,57 @@ void HWR_RenderBatches(void) PS_START_TIMING(ps_hw_batchdrawtime); - currentShader = polygonArray[polygonIndexArray[0]].shader; - currentTexture = polygonArray[polygonIndexArray[0]].texture; - 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 - // and a color array could replace the color calls. - // set state for first batch + HWR_ExecuteStateChanges(0xFFFF, &drawCalls[drawCallOrder[0]]); - if (cv_grshaders.value && gr_shadersavailable) + // - iterate through draw calls + // - accumulate converted vertices and indices into finalVertices and finalIndices + // and send them as a combined draw call when a state change occurs + while (1) { - HWD.pfnSetShader(currentShader); - } - - if (currentPolyFlags & PF_NoTexture) - currentTexture = NULL; - else - HWD.pfnSetTexture(currentTexture); - - while (1)// note: remember handling notexture polyflag as having texture number 0 (also in comparePolygons) - { - int firstIndex; - int lastIndex; - boolean stopFlag = false; - boolean changeState = false; - boolean changeShader = false; - boolean changeTexture = false; - boolean changePolyFlags = false; - boolean changeSurfaceInfo = false; + unsigned int stateChanges = 0; // flags defined above HWR_MarkStateChanges + DrawCallInfo *currentDrawCall = &drawCalls[drawCallOrder[drawCallReadPos++]]; + DrawCallInfo *nextDrawCall = NULL; - // steps: - // write vertices - // check for changes or end, otherwise go back to writing - // changes will affect the next vars and the change bools - // end could set flag for stopping - // execute draw call - // could check ending flag here - // change states according to next vars and change bools, updating the current vars and reseting the bools - // reset write pos - // repeat loop + HWR_CollectVerticesIntoBatch(currentDrawCall); - int index = polygonIndexArray[polygonReadPos++]; - int numVerts = polygonArray[index].numVerts; - // before writing, check if there is enough room - // using 'while' instead of 'if' here makes sure that there will *always* be enough room. - // probably never will this loop run more than once though - while (finalVertexWritePos + numVerts > finalVertexArrayAllocSize) - { - FOutVector* new_array; - unsigned int* new_index_array; - finalVertexArrayAllocSize *= 2; - new_array = malloc(finalVertexArrayAllocSize * sizeof(FOutVector)); - memcpy(new_array, finalVertexArray, finalVertexWritePos * sizeof(FOutVector)); - free(finalVertexArray); - finalVertexArray = new_array; - // also increase size of index array, 3x of vertex array since - // going from fans to triangles increases vertex count to 3x - new_index_array = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32)); - memcpy(new_index_array, finalVertexIndexArray, finalIndexWritePos * sizeof(UINT32)); - free(finalVertexIndexArray); - finalVertexIndexArray = new_index_array; - } - // write the vertices of the polygon - memcpy(&finalVertexArray[finalVertexWritePos], &unsortedVertexArray[polygonArray[index].vertsIndex], - numVerts * sizeof(FOutVector)); - // write the indexes, pointing to the fan vertexes but in triangles format - firstIndex = finalVertexWritePos; - lastIndex = finalVertexWritePos + numVerts; - finalVertexWritePos += 2; - while (finalVertexWritePos < lastIndex) - { - finalVertexIndexArray[finalIndexWritePos++] = firstIndex; - finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos - 1; - finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos++; - } - - if (polygonReadPos >= polygonArraySize) + if (drawCallReadPos >= drawCallsSize) // was that the last draw call? { stopFlag = true; } else { - // check if a state change is required, set the change bools and next vars - int nextIndex = polygonIndexArray[polygonReadPos]; - nextShader = polygonArray[nextIndex].shader; - nextTexture = polygonArray[nextIndex].texture; - nextPolyFlags = polygonArray[nextIndex].polyFlags; - nextSurfaceInfo = polygonArray[nextIndex].surf; - if (nextPolyFlags & PF_NoTexture) - nextTexture = 0; - if (currentShader != nextShader && cv_grshaders.value && gr_shadersavailable) - { - changeState = true; - changeShader = true; - } - if (currentTexture != nextTexture) - { - changeState = true; - changeTexture = true; - } - if (currentPolyFlags != nextPolyFlags) - { - changeState = true; - changePolyFlags = true; - } - if ((cv_grshaders.value && gr_shadersavailable) && (HWR_ShouldUsePaletteRendering())) - { - if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba || - currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba || - 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.LightTableId != nextSurfaceInfo.LightTableId) - { - changeState = true; - changeSurfaceInfo = true; - } - } - else if (cv_grshaders.value && gr_shadersavailable) - { - if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba || - currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba || - 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) - { - changeState = true; - changeSurfaceInfo = true; - } - } - else - { - if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba) - { - changeState = true; - changeSurfaceInfo = true; - } - } + nextDrawCall = &drawCalls[drawCallOrder[drawCallReadPos]]; + stateChanges = HWR_MarkStateChanges(currentDrawCall, nextDrawCall); } - if (changeState || stopFlag) + if (stateChanges || stopFlag) { - // execute draw call - HWD.pfnDrawIndexedTriangles(¤tSurfaceInfo, finalVertexArray, finalIndexWritePos, currentPolyFlags, finalVertexIndexArray); + // execute combined draw call + HWD.pfnDrawIndexedTriangles(¤tDrawCall->surf, finalVertices, + finalIndicesSize, currentDrawCall->polyFlags, finalIndices); // update stats ps_hw_numcalls.value.i++; - ps_hw_numverts.value.i += finalIndexWritePos; - // reset write positions - finalVertexWritePos = 0; - finalIndexWritePos = 0; + ps_hw_numverts.value.i += finalIndicesSize; + // reset final geometry collection arrays + finalVerticesSize = 0; + finalIndicesSize = 0; } - else continue; + else + continue; // if we're here then either its time to stop or time to change state - if (stopFlag) break; - - // change state according to change bools and next vars, update current vars and reset bools - if (changeShader) - { - HWD.pfnSetShader(nextShader); - currentShader = nextShader; - changeShader = false; - - ps_hw_numshaders.value.i++; - } - if (changeTexture) - { - // texture should be already ready for use from calls to SetTexture during batch collection - HWD.pfnSetTexture(nextTexture); - currentTexture = nextTexture; - changeTexture = false; - - ps_hw_numtextures.value.i++; - } - if (changePolyFlags) - { - currentPolyFlags = nextPolyFlags; - changePolyFlags = false; - - ps_hw_numpolyflags.value.i++; - } - if (changeSurfaceInfo) - { - currentSurfaceInfo = nextSurfaceInfo; - changeSurfaceInfo = false; - - ps_hw_numcolors.value.i++; - } - // and that should be it? + if (stopFlag) + break; + else + HWR_ExecuteStateChanges(stateChanges, nextDrawCall); } // reset the arrays (set sizes to 0) - polygonArraySize = 0; - unsortedVertexArraySize = 0; + drawCallsSize = 0; + unsortedVerticesSize = 0; PS_STOP_TIMING(ps_hw_batchdrawtime); } - #endif // HWRENDER diff --git a/src/hardware/hw_batching.h b/src/hardware/hw_batching.h index bf0b7fc94..b4e4bd9e3 100644 --- a/src/hardware/hw_batching.h +++ b/src/hardware/hw_batching.h @@ -17,18 +17,6 @@ #include "hw_data.h" #include "hw_drv.h" -typedef struct -{ - FSurfaceInfo surf;// surf also has its own polyflags for some reason, but it seems unused - unsigned int vertsIndex;// location of verts in unsortedVertexArray - FUINT numVerts; - FBITFIELD polyFlags; - GLMipmap_t *texture; - 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; -} PolygonArrayEntry; - void HWR_StartBatching(void); void HWR_SetCurrentTexture(GLMipmap_t *texture); void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial); -- 2.54.0 From 5cec34e8d9c4fadea4ee4be1c1fb5dd8bde3d324 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 18 Jan 2024 16:56:59 +0100 Subject: [PATCH 08/24] fix lighttable batching for new batching and palshader code --- src/hardware/hw_batching.c | 6 ------ src/hardware/r_opengl/r_opengl.c | 20 ++++++++++++-------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c index bbb228367..e3d02c4b4 100644 --- a/src/hardware/hw_batching.c +++ b/src/hardware/hw_batching.c @@ -195,12 +195,6 @@ static int compareDrawCalls(const void *p1, const void *p2) downloaded2 = poly2->texture->downloaded; diff64 = downloaded1 - downloaded2; if (diff64 != 0) return diff64; - - if (HWR_ShouldUsePaletteRendering()) - { - diff = poly1->surf.LightTableId - poly2->surf.LightTableId; - if (diff != 0) return diff; - } diff = poly1->polyFlags - poly2->polyFlags; if (diff != 0) return diff; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 68619d4e0..581fa8625 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -79,10 +79,7 @@ static float NEAR_CLIPPING_PLANE = NZCLIP_PLANE; // ************************************************************************** static GLuint tex_downloaded = 0; -// these didnt work with karts batching system, hope this is not an issue -//static GLuint lt_downloaded = 0; // currently bound lighttable texture - currentSurfaceInfo -//static GLuint lt_downloaded2 = 0; // currently bound lighttable texture - nextSurfaceInfo -//static GLuint lt_downloaded3 = 0; // currently bound lighttable texture - pSurf +static GLuint lt_downloaded = 0; // currently bound lighttable texture static GLfloat fov = 90.0f; static FBITFIELD CurrentPolyFlags; @@ -2211,11 +2208,12 @@ static void PreparePolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FBITFIELD fade.blue = byte2float[pSurf->FadeColor.s.blue]; fade.alpha = byte2float[pSurf->FadeColor.s.alpha]; - if (HWR_ShouldUsePaletteRendering() && gl_allowshaders) + if (pSurf->LightTableId && pSurf->LightTableId != lt_downloaded) { pglActiveTexture(GL_TEXTURE2); pglBindTexture(GL_TEXTURE_2D, pSurf->LightTableId); pglActiveTexture(GL_TEXTURE0); + lt_downloaded = pSurf->LightTableId; } } @@ -2990,6 +2988,14 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float fade.green = byte2float[Surface->FadeColor.s.green]; fade.blue = byte2float[Surface->FadeColor.s.blue]; fade.alpha = byte2float[Surface->FadeColor.s.alpha]; + + if (Surface->LightTableId && Surface->LightTableId != lt_downloaded) + { + pglActiveTexture(GL_TEXTURE2); + pglBindTexture(GL_TEXTURE_2D, Surface->LightTableId); + pglActiveTexture(GL_TEXTURE0); + lt_downloaded = Surface->LightTableId; + } Shader_SetUniforms(Surface, &poly, &tint, &fade); @@ -3856,9 +3862,7 @@ EXPORT void HWRAPI(ClearLightTables)(void) LightTablesTail = NULL; // we no longer have a bound light table (if we had one), we just deleted it! - //lt_downloaded = 0; - //lt_downloaded2 = 0; - //lt_downloaded3 = 0; + lt_downloaded = 0; } // This palette is used for the palette rendering postprocessing step. -- 2.54.0 From 2a0e2f76f1ed35623f5ada872e45561e97165aef Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 15 Jan 2024 16:17:17 +0100 Subject: [PATCH 09/24] paletterenderer screentex stuff again this didnt really work like it shouldve so ill keep it here for now --- src/hardware/hw_defs.h | 12 ++ src/hardware/hw_draw.c | 6 +- src/hardware/hw_drv.h | 23 +-- src/hardware/hw_main.c | 22 ++- src/hardware/hw_main.h | 1 + src/hardware/r_opengl/r_opengl.c | 280 +++++++++++-------------------- src/m_menu.c | 23 ++- src/sdl/hwsym_sdl.c | 7 +- src/sdl/i_video.c | 22 +-- src/sdl/ogl_sdl.c | 4 +- 10 files changed, 161 insertions(+), 239 deletions(-) diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 1313d80aa..2625a0ea6 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -288,4 +288,16 @@ enum hwdfiltermode HWD_SET_TEXTUREFILTER_MIXED3, }; +// Screen texture slots +enum hwdscreentexture +{ + HWD_SCREENTEXTURE_WIPE_START, // source image for the wipe/fade effect + HWD_SCREENTEXTURE_WIPE_END, // destination image for the wipe/fade effect + HWD_SCREENTEXTURE_GENERIC1, // underwater/heat effect, intermission background + HWD_SCREENTEXTURE_GENERIC2, // screen before palette rendering's postprocessing + HWD_SCREENTEXTURE_GENERIC3, // screen after palette rendering's postprocessing + NUMSCREENTEXTURES, // (generic3 is unused if palette rendering is disabled) +}; +typedef enum hwdscreentexture hwdscreentexture_t; + #endif //_HWR_DEFS_ diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index f35ee6fde..28f12c5c6 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -1158,6 +1158,7 @@ static inline boolean saveTGA(const char *file_name, void *buffer, UINT8 *HWR_GetScreenshot(void) { static UINT8 *buf = NULL; + int tex = ((HWR_ShouldUsePaletteRendering() && !cv_groldpal.value) ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2); buf = realloc(buf, vid.width * vid.height * 3); @@ -1165,7 +1166,7 @@ UINT8 *HWR_GetScreenshot(void) return NULL; // returns 24bit 888 RGB - HWD.pfnReadRect(0, 0, vid.width, vid.height, vid.width * 3, (void *)buf); + HWD.pfnReadScreenTexture(tex, (void *)buf); return buf; } @@ -1173,6 +1174,7 @@ boolean HWR_Screenshot(const char *pathname) { boolean ret; UINT8 *buf = malloc(vid.width * vid.height * 3 * sizeof (*buf)); + int tex = ((HWR_ShouldUsePaletteRendering() && !cv_groldpal.value) ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2); if (!buf) { @@ -1181,7 +1183,7 @@ boolean HWR_Screenshot(const char *pathname) } // returns 24bit 888 RGB - HWD.pfnReadRect(0, 0, vid.width, vid.height, vid.width * 3, (void *)buf); + HWD.pfnReadScreenTexture(tex, (void *)buf); #ifdef USE_PNG ret = M_SavePNG(pathname, buf, vid.width, vid.height, NULL); diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index 66ddf3a33..b022afe01 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -38,7 +38,7 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags); EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FBOOLEAN StencilMask, FRGBAFloat *ClearColor); EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo); EXPORT void HWRAPI(UpdateTexture) (FTextureInfo *TexInfo); -EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data); +EXPORT void HWRAPI(ReadScreenTexture) (int tex, UINT16 *dst_data); EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip, float farclip); EXPORT void HWRAPI(ClearMipMapCache) (void); @@ -56,14 +56,12 @@ EXPORT INT32 HWRAPI(GetTextureUsed) (void); EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture_height, FTransform transform); EXPORT void HWRAPI(FlushScreenTextures) (void); -EXPORT void HWRAPI(StartScreenWipe) (void); -EXPORT void HWRAPI(EndScreenWipe) (void); -EXPORT void HWRAPI(DoScreenWipe) (void); -EXPORT void HWRAPI(DrawIntermissionBG) (void); -EXPORT void HWRAPI(MakeScreenTexture) (void); +EXPORT void HWRAPI(DoScreenWipe) (int wipeStart, int wipeEnd); +EXPORT void HWRAPI(DrawScreenTexture) (int tex); +EXPORT void HWRAPI(MakeScreenTexture) (int tex); +EXPORT void HWRAPI(DrawScreenFinalTexture) (int tex, int width, int height); + EXPORT void HWRAPI(RenderVhsEffect) (fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT8 downdistort, UINT8 barsize); -EXPORT void HWRAPI(MakeScreenFinalTexture) (void); -EXPORT void HWRAPI(DrawScreenFinalTexture) (int width, int height); #define SCREENVERTS 10 EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]); @@ -102,7 +100,7 @@ struct hwdriver_s ClearBuffer pfnClearBuffer; SetTexture pfnSetTexture; UpdateTexture pfnUpdateTexture; - ReadRect pfnReadRect; + ReadScreenTexture pfnReadScreenTexture; GClipRect pfnGClipRect; ClearMipMapCache pfnClearMipMapCache; SetSpecialState pfnSetSpecialState; @@ -112,13 +110,10 @@ struct hwdriver_s GetTextureUsed pfnGetTextureUsed; PostImgRedraw pfnPostImgRedraw; FlushScreenTextures pfnFlushScreenTextures; - StartScreenWipe pfnStartScreenWipe; - EndScreenWipe pfnEndScreenWipe; DoScreenWipe pfnDoScreenWipe; - DrawIntermissionBG pfnDrawIntermissionBG; + DrawScreenTexture pfnDrawScreenTexture; MakeScreenTexture pfnMakeScreenTexture; - RenderVhsEffect pfnRenderVhsEffect; - MakeScreenFinalTexture pfnMakeScreenFinalTexture; + RenderVhsEffect pfnRenderVhsEffect; DrawScreenFinalTexture pfnDrawScreenFinalTexture; RenderSkyDome pfnRenderSkyDome; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index a7fca8729..849744cf5 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -152,6 +152,7 @@ static CV_PossibleValue_t glpalettedepth_cons_t[] = {{16, "16 bits"}, {24, "24 b consvar_t cv_grpalettedepth = {"gr_palettedepth", "16 bits", CV_SAVE|CV_CALL, glpalettedepth_cons_t, CV_grpalettedepth_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grflashpal = {"gr_flashpal", "On", CV_CALL|CV_SAVE, CV_OnOff, CV_grshaders_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_groldpal = {"gr_oldpal", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grmdls = {"gr_mdls", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grfallbackplayermodel = {"gr_fallbackplayermodel", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -6412,7 +6413,8 @@ void HWR_AddCommands(void) CV_RegisterVar(&cv_grpaletterendering); CV_RegisterVar(&cv_grpalettedepth); - CV_RegisterVar(&cv_grflashpal); + CV_RegisterVar(&cv_grflashpal); + CV_RegisterVar(&cv_groldpal); } // -------------------------------------------------------------------------- @@ -6554,7 +6556,7 @@ void HWR_DoPostProcessor(player_t *player) // Capture the screen for intermission and screen waving if(gamestate != GS_INTERMISSION) - HWD.pfnMakeScreenTexture(); + HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_GENERIC1); if (splitscreen) // Not supported in splitscreen - someone want to add support? return; @@ -6598,24 +6600,24 @@ void HWR_DoPostProcessor(player_t *player) // Capture the screen again for screen waving on the intermission if(gamestate != GS_INTERMISSION) - HWD.pfnMakeScreenTexture(); + HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_GENERIC1); } // Flipping of the screen isn't done here anymore } void HWR_StartScreenWipe(void) { - HWD.pfnStartScreenWipe(); + HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_WIPE_START); } void HWR_EndScreenWipe(void) { - HWD.pfnEndScreenWipe(); + HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_WIPE_END); } void HWR_DrawIntermissionBG(void) { - HWD.pfnDrawIntermissionBG(); + HWD.pfnDrawScreenTexture(HWD_SCREENTEXTURE_GENERIC1); } void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum) @@ -6643,7 +6645,7 @@ void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum) } HWR_GetFadeMask(lumpnum); - HWD.pfnDoScreenWipe(); + HWD.pfnDoScreenWipe(HWD_SCREENTEXTURE_WIPE_START, HWD_SCREENTEXTURE_WIPE_END); } void HWR_RenderVhsEffect(fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT8 downdistort, UINT8 barsize) @@ -6653,12 +6655,14 @@ void HWR_RenderVhsEffect(fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT void HWR_MakeScreenFinalTexture(void) { - HWD.pfnMakeScreenFinalTexture(); + int tex = ((HWR_ShouldUsePaletteRendering() && !cv_groldpal.value) ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2); + HWD.pfnMakeScreenTexture(tex); } void HWR_DrawScreenFinalTexture(int width, int height) { - HWD.pfnDrawScreenFinalTexture(width, height); + int tex = ((HWR_ShouldUsePaletteRendering() && !cv_groldpal.value) ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2); + HWD.pfnDrawScreenFinalTexture(tex, width, height); } // jimita 18032019 diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index dbcb93bb1..a4edf3496 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -192,6 +192,7 @@ extern consvar_t cv_grrenderdistance; extern consvar_t cv_grusecustomshaders; extern consvar_t cv_grpaletterendering; extern consvar_t cv_grpalettedepth; +extern consvar_t cv_groldpal; extern consvar_t cv_grflashpal; extern consvar_t cv_grscreentextures; extern consvar_t cv_grportals; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 581fa8625..df1138755 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -124,10 +124,7 @@ static GLint viewport[4]; // flush all of the stored textures, leaving them unavailable at times such as between levels // These need to start at 0 and be set to their number, and be reset to 0 when deleted so that Intel GPUs // can know when the textures aren't there, as textures are always considered resident in their virtual memory -static GLuint screentexture = 0; -static GLuint startScreenWipe = 0; -static GLuint endScreenWipe = 0; -static GLuint finalScreenTexture = 0; +static GLuint screenTextures[NUMSCREENTEXTURES] = {0}; // Lactozilla: Set shader programs and uniforms static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade); @@ -568,7 +565,7 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglTexParameteri, glTexParameteri) GETOPENGLFUNC(pglTexImage1D, glTexImage1D) GETOPENGLFUNC(pglTexImage2D, glTexImage2D) - GETOPENGLFUNC(pglTexSubImage2D , glTexSubImage2D) + GETOPENGLFUNC(pglTexSubImage2D, glTexSubImage2D) GETOPENGLFUNC(pglGenTextures, glGenTextures) GETOPENGLFUNC(pglDeleteTextures, glDeleteTextures) @@ -1324,14 +1321,19 @@ EXPORT void HWRAPI(SetShader) (int shader) EXPORT void HWRAPI(UnSetShader) (void) { #ifdef GL_SHADERS - gl_shadersenabled = false; - gl_currentshaderprogram = 0; - gl_shaderprogramchanged = true;// not sure if this is needed - if (!pglUseProgram) return; - pglUseProgram(0); + if (gl_shadersenabled) // don't repeatedly call glUseProgram if not needed + { + gl_shadersenabled = false; + gl_currentshaderprogram = 0; + gl_shaderprogramchanged = true;// not sure if this is needed + if (!pglUseProgram) return; + pglUseProgram(0); + } #endif + gl_shadersenabled = false; } + EXPORT void HWRAPI(KillShaders) (void) { // unused......................... @@ -1524,58 +1526,40 @@ EXPORT void HWRAPI(ClearMipMapCache) (void) Flush(); } -// -----------------+ -// ReadRect : Read a rectangle region of the truecolor framebuffer -// : store pixels as 16bit 565 RGB -// Returns : 16bit 565 RGB pixel array stored in dst_data -// -----------------+ -EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, - INT32 dst_stride, UINT16 * dst_data) +// Writes screen texture tex into dst_data. +// Pixel format is 24-bit RGB. Row order is top to bottom. +// Dimensions are screen_width * screen_height. +EXPORT void HWRAPI(ReadScreenTexture) (int tex, UINT16 *dst_data) { INT32 i; - //GL_DBG_Printf("ReadRect()\n"); - if (dst_stride == width*3) + int dst_stride = screen_width * 3; // stride between rows of image data + GLubyte*top = (GLvoid*)dst_data, *bottom = top + dst_stride * (screen_height - 1); + GLubyte *row; + row = malloc(dst_stride); + if (!row) return; + // at the time this function is called, generic2 can be found drawn on the framebuffer + // if some other screen texture is needed, draw it to the framebuffer + // and draw generic2 back after reading the framebuffer. + // this hack is for some reason **much** faster than the simple solution of using glGetTexImage. + if (tex != HWD_SCREENTEXTURE_GENERIC2) + DrawScreenTexture(tex); + pglPixelStorei(GL_PACK_ALIGNMENT, 1); + pglReadPixels(0, 0, screen_width, screen_height, GL_RGB, GL_UNSIGNED_BYTE, dst_data); + if (tex != HWD_SCREENTEXTURE_GENERIC2) + DrawScreenTexture(HWD_SCREENTEXTURE_GENERIC2); + // Flip image upside down. + // In other words, convert OpenGL's "bottom->top" row order into "top->bottom". + for(i = 0; i < screen_height/2; i++) { - GLubyte*top = (GLvoid*)dst_data, *bottom = top + dst_stride * (height - 1); - GLubyte *row = malloc(dst_stride); - if (!row) return; - pglPixelStorei(GL_PACK_ALIGNMENT, 1); - pglReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, dst_data); - pglPixelStorei(GL_UNPACK_ALIGNMENT, 1); - for(i = 0; i < height/2; i++) - { - memcpy(row, top, dst_stride); - memcpy(top, bottom, dst_stride); - memcpy(bottom, row, dst_stride); - top += dst_stride; - bottom -= dst_stride; - } - free(row); - } - else - { - INT32 j; - GLubyte *image = malloc(width*height*3*sizeof (*image)); - if (!image) return; - pglPixelStorei(GL_PACK_ALIGNMENT, 1); - pglReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, image); - pglPixelStorei(GL_UNPACK_ALIGNMENT, 1); - for (i = height-1; i >= 0; i--) - { - for (j = 0; j < width; j++) - { - dst_data[(height-1-i)*width+j] = - (UINT16)( - ((image[(i*width+j)*3]>>3)<<11) | - ((image[(i*width+j)*3+1]>>2)<<5) | - ((image[(i*width+j)*3+2]>>3))); - } - } - free(image); + memcpy(row, top, dst_stride); + memcpy(top, bottom, dst_stride); + memcpy(bottom, row, dst_stride); + top += dst_stride; + bottom -= dst_stride; } + free(row); } - // -----------------+ // GClipRect : Defines the 2D hardware clipping window // -----------------+ @@ -3282,7 +3266,7 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) 16.0f, 16.0f, 6.0f, 16.0f, -16.0f, 6.0f }; - + if (!gl_enable_screen_textures) return; // look for power of two that is large enough for the screen @@ -3357,77 +3341,13 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) // a new size EXPORT void HWRAPI(FlushScreenTextures) (void) { - pglDeleteTextures(1, &screentexture); - pglDeleteTextures(1, &startScreenWipe); - pglDeleteTextures(1, &endScreenWipe); - pglDeleteTextures(1, &finalScreenTexture); - - screentexture = 0; - startScreenWipe = 0; - endScreenWipe = 0; - finalScreenTexture = 0; + int i; + pglDeleteTextures(NUMSCREENTEXTURES, screenTextures); + for (i = 0; i < NUMSCREENTEXTURES; i++) + screenTextures[i] = 0; } -// Create Screen to fade from -EXPORT void HWRAPI(StartScreenWipe) (void) -{ - INT32 texsize = 512; - boolean firstTime = (startScreenWipe == 0); - - // look for power of two that is large enough for the screen - while (texsize < screen_width || texsize < screen_height) - texsize <<= 1; - - // Create screen texture - if (firstTime) - pglGenTextures(1, &startScreenWipe); - pglBindTexture(GL_TEXTURE_2D, startScreenWipe); - - if (firstTime) - { - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - Clamp2D(GL_TEXTURE_WRAP_S); - Clamp2D(GL_TEXTURE_WRAP_T); - pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0); - } - else - pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize); - - tex_downloaded = startScreenWipe; -} - -// Create Screen to fade to -EXPORT void HWRAPI(EndScreenWipe)(void) -{ - INT32 texsize = 512; - boolean firstTime = (endScreenWipe == 0); - - // look for power of two that is large enough for the screen - while (texsize < screen_width || texsize < screen_height) - texsize <<= 1; - - // Create screen texture - if (firstTime) - pglGenTextures(1, &endScreenWipe); - pglBindTexture(GL_TEXTURE_2D, endScreenWipe); - - if (firstTime) - { - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - Clamp2D(GL_TEXTURE_WRAP_S); - Clamp2D(GL_TEXTURE_WRAP_T); - pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0); - } - else - pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize); - - tex_downloaded = endScreenWipe; -} - -// Draw the last scene under the intermission -EXPORT void HWRAPI(DrawIntermissionBG)(void) +EXPORT void HWRAPI(DrawScreenTexture)(int tex) { float xfix, yfix; INT32 texsize = 512; @@ -3441,6 +3361,8 @@ EXPORT void HWRAPI(DrawIntermissionBG)(void) }; float fix[8]; + + if (!gl_enable_screen_textures) return; // look for power of two that is large enough for the screen while (texsize < screen_width || texsize < screen_height) @@ -3449,6 +3371,9 @@ EXPORT void HWRAPI(DrawIntermissionBG)(void) xfix = 1/((float)(texsize)/((float)((screen_width)))); yfix = 1/((float)(texsize)/((float)((screen_height)))); + // const float screenVerts[12] + + // float fix[8]; fix[0] = 0.0f; fix[1] = 0.0f; fix[2] = 0.0f; @@ -3459,17 +3384,27 @@ EXPORT void HWRAPI(DrawIntermissionBG)(void) fix[7] = 0.0f; pglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - pglBindTexture(GL_TEXTURE_2D, screentexture); + + pglBindTexture(GL_TEXTURE_2D, screenTextures[tex]); + + if (((HWR_ShouldUsePaletteRendering()) && (tex == HWD_SCREENTEXTURE_GENERIC2)) && !cv_groldpal.value) + pglUseProgram(gl_shaderprograms[8].program); // palette postprocess shader + pglColor4ubv(white); + pglTexCoordPointer(2, GL_FLOAT, 0, fix); pglVertexPointer(3, GL_FLOAT, 0, screenVerts); pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + if (((HWR_ShouldUsePaletteRendering()) && (tex == HWD_SCREENTEXTURE_GENERIC2)) && !cv_groldpal.value) + pglUseProgram(0); - tex_downloaded = screentexture; + tex_downloaded = screenTextures[tex]; } + // Do screen fades! -EXPORT void HWRAPI(DoScreenWipe)(void) +EXPORT void HWRAPI(DoScreenWipe)(int wipeStart, int wipeEnd) { INT32 texsize = 512; float xfix, yfix; @@ -3501,6 +3436,9 @@ EXPORT void HWRAPI(DoScreenWipe)(void) xfix = 1/((float)(texsize)/((float)((screen_width)))); yfix = 1/((float)(texsize)/((float)((screen_height)))); + // const float screenVerts[12] + + // float fix[8]; fix[0] = 0.0f; fix[1] = 0.0f; fix[2] = 0.0f; @@ -3516,7 +3454,7 @@ EXPORT void HWRAPI(DoScreenWipe)(void) pglEnable(GL_TEXTURE_2D); // Draw the original screen - pglBindTexture(GL_TEXTURE_2D, startScreenWipe); + pglBindTexture(GL_TEXTURE_2D, screenTextures[wipeStart]); pglColor4ubv(white); pglTexCoordPointer(2, GL_FLOAT, 0, fix); pglVertexPointer(3, GL_FLOAT, 0, screenVerts); @@ -3527,7 +3465,7 @@ EXPORT void HWRAPI(DoScreenWipe)(void) // Draw the end screen that fades in pglActiveTexture(GL_TEXTURE0); pglEnable(GL_TEXTURE_2D); - pglBindTexture(GL_TEXTURE_2D, endScreenWipe); + pglBindTexture(GL_TEXTURE_2D, screenTextures[wipeEnd]); pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); pglActiveTexture(GL_TEXTURE1); @@ -3536,6 +3474,8 @@ EXPORT void HWRAPI(DoScreenWipe)(void) pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + // const float defaultST[8] + pglClientActiveTexture(GL_TEXTURE0); pglTexCoordPointer(2, GL_FLOAT, 0, fix); pglVertexPointer(3, GL_FLOAT, 0, screenVerts); @@ -3549,38 +3489,7 @@ EXPORT void HWRAPI(DoScreenWipe)(void) pglActiveTexture(GL_TEXTURE0); pglClientActiveTexture(GL_TEXTURE0); - tex_downloaded = endScreenWipe; -} - -// Create a texture from the screen. -EXPORT void HWRAPI(MakeScreenTexture) (void) -{ - INT32 texsize = 512; - boolean firstTime = (screentexture == 0); - - if (!gl_enable_screen_textures) return; - - // look for power of two that is large enough for the screen - while (texsize < screen_width || texsize < screen_height) - texsize <<= 1; - - // Create screen texture - if (firstTime) - pglGenTextures(1, &screentexture); - pglBindTexture(GL_TEXTURE_2D, screentexture); - - if (firstTime) - { - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - Clamp2D(GL_TEXTURE_WRAP_S); - Clamp2D(GL_TEXTURE_WRAP_T); - pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0); - } - else - pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize); - - tex_downloaded = screentexture; + tex_downloaded = screenTextures[wipeEnd]; } EXPORT void HWRAPI(RenderVhsEffect) (fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT8 downdistort, UINT8 barsize) @@ -3607,9 +3516,9 @@ EXPORT void HWRAPI(RenderVhsEffect) (fixed_t upbary, fixed_t downbary, UINT8 upd yfix = 1/((float)(texsize)/((float)((screen_height)))); // Slight fuzziness - MakeScreenTexture(); + MakeScreenTexture(HWD_SCREENTEXTURE_GENERIC1); SetBlend(PF_Modulated|PF_Translucent|PF_NoDepthTest); - pglBindTexture(GL_TEXTURE_2D, screentexture); + //pglBindTexture(GL_TEXTURE_2D, screentexture); for (i = 0; i < 1; i += 2.f/vid.height) { @@ -3631,8 +3540,8 @@ EXPORT void HWRAPI(RenderVhsEffect) (fixed_t upbary, fixed_t downbary, UINT8 upd } // Upward bar - MakeScreenTexture(); - pglBindTexture(GL_TEXTURE_2D, screentexture); + MakeScreenTexture(HWD_SCREENTEXTURE_GENERIC1); + //pglBindTexture(GL_TEXTURE_2D, screentexture); color[0] = color[1] = color[2] = 190; color[3] = 250; pglColor4ubv(color); @@ -3659,8 +3568,8 @@ EXPORT void HWRAPI(RenderVhsEffect) (fixed_t upbary, fixed_t downbary, UINT8 upd pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); // Downward bar - MakeScreenTexture(); - pglBindTexture(GL_TEXTURE_2D, screentexture); + MakeScreenTexture(HWD_SCREENTEXTURE_GENERIC1); + //pglBindTexture(GL_TEXTURE_2D, screentexture); fix[0] = 0.0f; fix[6] = xfix; @@ -3684,11 +3593,12 @@ EXPORT void HWRAPI(RenderVhsEffect) (fixed_t upbary, fixed_t downbary, UINT8 upd pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); } -EXPORT void HWRAPI(MakeScreenFinalTexture) (void) +// Create a texture from the screen. +EXPORT void HWRAPI(MakeScreenTexture) (int tex) { INT32 texsize = 512; - boolean firstTime = (finalScreenTexture == 0); - + boolean firstTime = (screenTextures[tex] == 0); + if (!gl_enable_screen_textures) return; // look for power of two that is large enough for the screen @@ -3697,8 +3607,8 @@ EXPORT void HWRAPI(MakeScreenFinalTexture) (void) // Create screen texture if (firstTime) - pglGenTextures(1, &finalScreenTexture); - pglBindTexture(GL_TEXTURE_2D, finalScreenTexture); + pglGenTextures(1, &screenTextures[tex]); + pglBindTexture(GL_TEXTURE_2D, screenTextures[tex]); if (firstTime) { @@ -3711,10 +3621,10 @@ EXPORT void HWRAPI(MakeScreenFinalTexture) (void) else pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize); - tex_downloaded = finalScreenTexture; + tex_downloaded = screenTextures[tex]; } -EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height) +EXPORT void HWRAPI(DrawScreenFinalTexture)(int tex, int width, int height) { float xfix, yfix; float origaspect, newaspect; @@ -3724,7 +3634,7 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height) float off[12]; float fix[8]; - + if (!gl_enable_screen_textures) return; // look for power of two that is large enough for the screen @@ -3747,6 +3657,7 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height) yoff = newaspect / origaspect; } + // float off[12]; off[0] = -xoff; off[1] = -yoff; off[2] = 1.0f; @@ -3760,6 +3671,7 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height) off[10] = -yoff; off[11] = 1.0f; + // float fix[8]; fix[0] = 0.0f; fix[1] = 0.0f; fix[2] = 0.0f; @@ -3778,23 +3690,23 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height) if (HWR_ShouldUsePaletteRendering()) SetBlend(PF_NoDepthTest); - pglBindTexture(GL_TEXTURE_2D, finalScreenTexture); - - if (HWR_ShouldUsePaletteRendering()) // still quite hacky, but the replacement code in i_video didnt work and killed performance instead. somehow need to figure out whats up with that. + pglBindTexture(GL_TEXTURE_2D, screenTextures[tex]); + + if ((HWR_ShouldUsePaletteRendering()) && cv_groldpal.value) pglUseProgram(gl_shaderprograms[8].program); // palette postprocess shader pglColor4ubv(white); + pglTexCoordPointer(2, GL_FLOAT, 0, fix); pglVertexPointer(3, GL_FLOAT, 0, off); pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - tex_downloaded = finalScreenTexture; - if (HWR_ShouldUsePaletteRendering()) + if ((HWR_ShouldUsePaletteRendering()) && cv_groldpal.value) pglUseProgram(0); -} + tex_downloaded = screenTextures[tex]; +} EXPORT void HWRAPI(SetPaletteLookup)(UINT8 *lut) { diff --git a/src/m_menu.c b/src/m_menu.c index 9dae711ad..1d9dc17af 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1484,20 +1484,23 @@ static menuitem_t OP_ColorOptionsMenu[] = static menuitem_t OP_ExpOptionsMenu[] = { {IT_HEADER, NULL, "Experimental Options", NULL, 10}, - {IT_STRING | IT_CVAR, NULL, "Weather Interpolation", &cv_precipinterp, 35}, - {IT_STRING | IT_CVAR, NULL, "Less Weather Effects", &cv_lessprecip, 45}, + {IT_STRING | IT_CVAR, NULL, "Weather Interpolation", &cv_precipinterp, 25}, + {IT_STRING | IT_CVAR, NULL, "Less Weather Effects", &cv_lessprecip, 35}, - {IT_STRING | IT_CVAR, NULL, "VHS effect", &cv_vhseffect, 65}, + {IT_STRING | IT_CVAR, NULL, "VHS effect", &cv_vhseffect, 55}, - {IT_STRING | IT_CVAR, NULL, "FFloorclip", &cv_ffloorclip, 85}, - {IT_STRING | IT_CVAR, NULL, "Spriteclip", &cv_spriteclip, 95}, + {IT_STRING | IT_CVAR, NULL, "FFloorclip", &cv_ffloorclip, 75}, + {IT_STRING | IT_CVAR, NULL, "Spriteclip", &cv_spriteclip, 85}, #ifdef HWRENDER {IT_STRING | IT_CVAR, NULL, "Screen Textures", &cv_grscreentextures, 75}, - {IT_STRING | IT_CVAR, NULL, "Splitwall/Slope texture fix", &cv_splitwallfix, 95}, - {IT_STRING | IT_CVAR, NULL, "Slope midtexture peg fix", &cv_slopepegfix, 105}, - {IT_STRING | IT_CVAR, NULL, "ZFighting fix for fofs", &cv_fofzfightfix, 115}, - {IT_STRING | IT_CVAR, NULL, "FOF wall cutoff for slopes", &cv_grfofcut, 125}, + {IT_STRING | IT_CVAR, NULL, "Palette Depth", &cv_grpalettedepth, 75}, + {IT_STRING | IT_CVAR, NULL, "Old Palshader", &cv_groldpal, 85}, + + {IT_STRING | IT_CVAR, NULL, "Splitwall/Slope texture fix", &cv_splitwallfix, 105}, + {IT_STRING | IT_CVAR, NULL, "Slope midtexture peg fix", &cv_slopepegfix, 115}, + {IT_STRING | IT_CVAR, NULL, "ZFighting fix for fofs", &cv_fofzfightfix, 125}, + {IT_STRING | IT_CVAR, NULL, "FOF wall cutoff for slopes", &cv_grfofcut, 135}, #endif }; @@ -1512,6 +1515,8 @@ static const char* OP_ExpTooltips[] = #ifdef HWRENDER "Should the game do Screen Textures? Provides a good boost to frames\nat the cost of some visual effects not working when disabled.", "Fixes issues that resulted in Textures sticking from the\nground sometimes.\nThis may be CPU heavy and result in worse performance in some cases.", + "Changes back to old Palette renderer screentexture behaviour\nthis makes performance better and keeps the old visuals\nat the cost of accuracy.", + "Fixes issues that resulted in Textures sticking from the ground sometimes.\n This may be CPU heavy and result in worse performance in some cases.", "Fixes issues that resulted in Textures not being properly skewed\n example: Fences on slopes that didnt show proper.\n This may be CPU heavy and result in worse performance in some cases.", "Fixes issues that resulted in Textures on Floor over Floors\nZFighting heavily.", "Toggle for FOF wall cutoff with slopes.", diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index 1ea07f3d4..da12b0e7c 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -86,7 +86,7 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(ClearBuffer); GETFUNC(SetTexture); GETFUNC(UpdateTexture); - GETFUNC(ReadRect); + GETFUNC(ReadScreenTexture); GETFUNC(GClipRect); GETFUNC(ClearMipMapCache); GETFUNC(SetSpecialState); @@ -96,13 +96,10 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(SetTransform); GETFUNC(PostImgRedraw); GETFUNC(FlushScreenTextures); - GETFUNC(StartScreenWipe); - GETFUNC(EndScreenWipe); GETFUNC(DoScreenWipe); - GETFUNC(DrawIntermissionBG); + GETFUNC(DrawScreenTexture); GETFUNC(MakeScreenTexture); GETFUNC(RenderVhsEffect); - GETFUNC(MakeScreenFinalTexture); GETFUNC(DrawScreenFinalTexture); GETFUNC(RenderSkyDome); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 4e9a98433..9aa2ed49d 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1483,17 +1483,12 @@ void I_FinishUpdate(void) #ifdef HWRENDER else if (rendermode == render_opengl) { - /*// Final postprocess step of palette rendering, after everything else has been drawn. - if (HWR_ShouldUsePaletteRendering()) + // Final postprocess step of palette rendering, after everything else has been drawn. + if (HWR_ShouldUsePaletteRendering() && !cv_groldpal.value) { - // not using the function for its original named purpose but can be used like this too - HWR_MakeScreenFinalTexture(); - HWD.pfnSetSpecialState(HWD_SET_SHADERS, 1); - HWD.pfnSetShader(8); - HWR_DrawScreenFinalTexture(vid.width, vid.height); - HWD.pfnUnSetShader(); - HWD.pfnSetSpecialState(HWD_SET_SHADERS, 0); - }*/ //for some reason this does not work here,so ill keep it in DrawScreenFinalTexture itself for now + HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_GENERIC2); + HWD.pfnDrawScreenTexture(HWD_SCREENTEXTURE_GENERIC2); + } OglSdlFinishUpdate(cv_vidwait.value); } @@ -2130,7 +2125,7 @@ void I_StartupGraphics(void) HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL); HWD.pfnSetTexture = hwSym("SetTexture",NULL); HWD.pfnUpdateTexture = hwSym("UpdateTexture",NULL); - HWD.pfnReadRect = hwSym("ReadRect",NULL); + HWD.pfnReadScreenTexture= hwSym("ReadScreenTexture",NULL); HWD.pfnGClipRect = hwSym("GClipRect",NULL); HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL); HWD.pfnSetSpecialState = hwSym("SetSpecialState",NULL); @@ -2141,13 +2136,10 @@ void I_StartupGraphics(void) HWD.pfnSetTransform = hwSym("SetTransform",NULL); HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL); HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL); - HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL); - HWD.pfnEndScreenWipe = hwSym("EndScreenWipe",NULL); HWD.pfnDoScreenWipe = hwSym("DoScreenWipe",NULL); - HWD.pfnDrawIntermissionBG=hwSym("DrawIntermissionBG",NULL); + HWD.pfnDrawScreenTexture= hwSym("DrawScreenTexture",NULL); HWD.pfnMakeScreenTexture= hwSym("MakeScreenTexture",NULL); HWD.pfnRenderVhsEffect = hwSym("RenderVhsEffect",NULL); - HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL); HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL); HWD.pfnRenderSkyDome = hwSym("RenderSkyDome",NULL); diff --git a/src/sdl/ogl_sdl.c b/src/sdl/ogl_sdl.c index dc831fce0..aa53df384 100644 --- a/src/sdl/ogl_sdl.c +++ b/src/sdl/ogl_sdl.c @@ -233,7 +233,9 @@ void OglSdlFinishUpdate(boolean waitvbl) // Sryder: We need to draw the final screen texture again into the other buffer in the original position so that // effects that want to take the old screen can do so after this - HWR_DrawScreenFinalTexture(realwidth, realheight); + // Generic2 has the screen image without palette rendering brightness adjustments. + // Using that here will prevent brightness adjustments being applied twice. + DrawScreenTexture(HWD_SCREENTEXTURE_GENERIC2); } EXPORT void HWRAPI(OglSdlSetPalette) (RGBA_t *palette) -- 2.54.0 From cc317cb28ec699cf5405ac34b6ae75de3472cb98 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 15 Jan 2024 16:23:19 +0100 Subject: [PATCH 10/24] remove gr_oldpal for now --- src/hardware/hw_main.c | 6 ++---- src/hardware/hw_main.h | 1 - src/hardware/r_opengl/r_opengl.c | 14 +++++--------- src/m_menu.c | 5 ++--- src/sdl/i_video.c | 7 +++++-- 5 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 849744cf5..f3196a5db 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -152,7 +152,6 @@ static CV_PossibleValue_t glpalettedepth_cons_t[] = {{16, "16 bits"}, {24, "24 b consvar_t cv_grpalettedepth = {"gr_palettedepth", "16 bits", CV_SAVE|CV_CALL, glpalettedepth_cons_t, CV_grpalettedepth_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grflashpal = {"gr_flashpal", "On", CV_CALL|CV_SAVE, CV_OnOff, CV_grshaders_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_groldpal = {"gr_oldpal", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grmdls = {"gr_mdls", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grfallbackplayermodel = {"gr_fallbackplayermodel", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -6414,7 +6413,6 @@ void HWR_AddCommands(void) CV_RegisterVar(&cv_grpaletterendering); CV_RegisterVar(&cv_grpalettedepth); CV_RegisterVar(&cv_grflashpal); - CV_RegisterVar(&cv_groldpal); } // -------------------------------------------------------------------------- @@ -6655,13 +6653,13 @@ void HWR_RenderVhsEffect(fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT void HWR_MakeScreenFinalTexture(void) { - int tex = ((HWR_ShouldUsePaletteRendering() && !cv_groldpal.value) ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2); + int tex = (HWR_ShouldUsePaletteRendering() ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2); HWD.pfnMakeScreenTexture(tex); } void HWR_DrawScreenFinalTexture(int width, int height) { - int tex = ((HWR_ShouldUsePaletteRendering() && !cv_groldpal.value) ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2); + int tex = (HWR_ShouldUsePaletteRendering() ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2); HWD.pfnDrawScreenFinalTexture(tex, width, height); } diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index a4edf3496..dbcb93bb1 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -192,7 +192,6 @@ extern consvar_t cv_grrenderdistance; extern consvar_t cv_grusecustomshaders; extern consvar_t cv_grpaletterendering; extern consvar_t cv_grpalettedepth; -extern consvar_t cv_groldpal; extern consvar_t cv_grflashpal; extern consvar_t cv_grscreentextures; extern consvar_t cv_grportals; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index df1138755..ebdfe06f5 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -3387,17 +3387,13 @@ EXPORT void HWRAPI(DrawScreenTexture)(int tex) pglBindTexture(GL_TEXTURE_2D, screenTextures[tex]); - if (((HWR_ShouldUsePaletteRendering()) && (tex == HWD_SCREENTEXTURE_GENERIC2)) && !cv_groldpal.value) - pglUseProgram(gl_shaderprograms[8].program); // palette postprocess shader + Shader_SetUniforms(NULL, NULL, NULL, NULL); // prepare shader, if it is enabled pglColor4ubv(white); pglTexCoordPointer(2, GL_FLOAT, 0, fix); pglVertexPointer(3, GL_FLOAT, 0, screenVerts); pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - if (((HWR_ShouldUsePaletteRendering()) && (tex == HWD_SCREENTEXTURE_GENERIC2)) && !cv_groldpal.value) - pglUseProgram(0); tex_downloaded = screenTextures[tex]; } @@ -3692,8 +3688,8 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int tex, int width, int height) pglBindTexture(GL_TEXTURE_2D, screenTextures[tex]); - if ((HWR_ShouldUsePaletteRendering()) && cv_groldpal.value) - pglUseProgram(gl_shaderprograms[8].program); // palette postprocess shader + //if ((HWR_ShouldUsePaletteRendering()) && cv_groldpal.value) + //pglUseProgram(gl_shaderprograms[8].program); // palette postprocess shader pglColor4ubv(white); @@ -3702,8 +3698,8 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int tex, int width, int height) pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); - if ((HWR_ShouldUsePaletteRendering()) && cv_groldpal.value) - pglUseProgram(0); + //if ((HWR_ShouldUsePaletteRendering()) && cv_groldpal.value) + //pglUseProgram(0); tex_downloaded = screenTextures[tex]; } diff --git a/src/m_menu.c b/src/m_menu.c index 1d9dc17af..8ece67fe5 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1494,8 +1494,7 @@ static menuitem_t OP_ExpOptionsMenu[] = #ifdef HWRENDER {IT_STRING | IT_CVAR, NULL, "Screen Textures", &cv_grscreentextures, 75}, - {IT_STRING | IT_CVAR, NULL, "Palette Depth", &cv_grpalettedepth, 75}, - {IT_STRING | IT_CVAR, NULL, "Old Palshader", &cv_groldpal, 85}, + {IT_STRING | IT_CVAR, NULL, "Palette Depth", &cv_grpalettedepth, 85}, {IT_STRING | IT_CVAR, NULL, "Splitwall/Slope texture fix", &cv_splitwallfix, 105}, {IT_STRING | IT_CVAR, NULL, "Slope midtexture peg fix", &cv_slopepegfix, 115}, @@ -1515,7 +1514,7 @@ static const char* OP_ExpTooltips[] = #ifdef HWRENDER "Should the game do Screen Textures? Provides a good boost to frames\nat the cost of some visual effects not working when disabled.", "Fixes issues that resulted in Textures sticking from the\nground sometimes.\nThis may be CPU heavy and result in worse performance in some cases.", - "Changes back to old Palette renderer screentexture behaviour\nthis makes performance better and keeps the old visuals\nat the cost of accuracy.", + "Change the depth of the palette in palette rendering mode.", "Fixes issues that resulted in Textures sticking from the ground sometimes.\n This may be CPU heavy and result in worse performance in some cases.", "Fixes issues that resulted in Textures not being properly skewed\n example: Fences on slopes that didnt show proper.\n This may be CPU heavy and result in worse performance in some cases.", "Fixes issues that resulted in Textures on Floor over Floors\nZFighting heavily.", diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 9aa2ed49d..fadce02f7 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1484,12 +1484,15 @@ void I_FinishUpdate(void) else if (rendermode == render_opengl) { // Final postprocess step of palette rendering, after everything else has been drawn. - if (HWR_ShouldUsePaletteRendering() && !cv_groldpal.value) + if (HWR_ShouldUsePaletteRendering()) { HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_GENERIC2); + HWD.pfnSetSpecialState(HWD_SET_SHADERS, 1); + HWD.pfnSetShader(8); HWD.pfnDrawScreenTexture(HWD_SCREENTEXTURE_GENERIC2); + HWD.pfnUnSetShader(); + HWD.pfnSetSpecialState(HWD_SET_SHADERS, 0); } - OglSdlFinishUpdate(cv_vidwait.value); } #endif -- 2.54.0 From d7fe3272e2e86096611bc7c233f576f9bc482b96 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 15 Jan 2024 16:29:01 +0100 Subject: [PATCH 11/24] Light table support for HWR_FadeScreenMenuBack --- src/hardware/hw_defs.h | 2 +- src/hardware/hw_draw.c | 18 +++++++++++++++-- src/hardware/hw_drv.h | 2 +- src/hardware/hw_main.c | 2 +- src/hardware/r_opengl/r_opengl.c | 34 +++++++++++++++++++++++++------- src/sdl/i_video.c | 2 +- src/sdl/ogl_sdl.c | 2 +- 7 files changed, 48 insertions(+), 14 deletions(-) diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 2625a0ea6..09d7b89a1 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -294,7 +294,7 @@ enum hwdscreentexture HWD_SCREENTEXTURE_WIPE_START, // source image for the wipe/fade effect HWD_SCREENTEXTURE_WIPE_END, // destination image for the wipe/fade effect HWD_SCREENTEXTURE_GENERIC1, // underwater/heat effect, intermission background - HWD_SCREENTEXTURE_GENERIC2, // screen before palette rendering's postprocessing + HWD_SCREENTEXTURE_GENERIC2, // palette-based colormap fade, screen before palette rendering's postprocessing HWD_SCREENTEXTURE_GENERIC3, // screen after palette rendering's postprocessing NUMSCREENTEXTURES, // (generic3 is unused if palette rendering is disabled) }; diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 28f12c5c6..2f0c13773 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -562,6 +562,20 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength) if (color & 0xFF00) // Do COLORMAP fade. { + if (HWR_ShouldUsePaletteRendering()) + { + const hwdscreentexture_t scr_tex = HWD_SCREENTEXTURE_GENERIC2; + + Surf.LightTableId = HWR_GetLightTableID(NULL); + Surf.LightInfo.light_level = strength; + HWD.pfnMakeScreenTexture(scr_tex); + HWD.pfnSetShader(12); + HWD.pfnDrawScreenTexture(scr_tex, &Surf, PF_ColorMapped|PF_NoDepthTest); + HWD.pfnUnSetShader(); + + return; + } + Surf.PolyColor.rgba = UINT2RGBA(0x01010160); Surf.PolyColor.s.alpha = (strength*8); } @@ -1158,7 +1172,7 @@ static inline boolean saveTGA(const char *file_name, void *buffer, UINT8 *HWR_GetScreenshot(void) { static UINT8 *buf = NULL; - int tex = ((HWR_ShouldUsePaletteRendering() && !cv_groldpal.value) ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2); + int tex = (HWR_ShouldUsePaletteRendering() ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2); buf = realloc(buf, vid.width * vid.height * 3); @@ -1174,7 +1188,7 @@ boolean HWR_Screenshot(const char *pathname) { boolean ret; UINT8 *buf = malloc(vid.width * vid.height * 3 * sizeof (*buf)); - int tex = ((HWR_ShouldUsePaletteRendering() && !cv_groldpal.value) ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2); + int tex = (HWR_ShouldUsePaletteRendering() ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2); if (!buf) { diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index b022afe01..a8d588e7c 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -57,7 +57,7 @@ EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture EXPORT void HWRAPI(FlushScreenTextures) (void); EXPORT void HWRAPI(DoScreenWipe) (int wipeStart, int wipeEnd); -EXPORT void HWRAPI(DrawScreenTexture) (int tex); +EXPORT void HWRAPI(DrawScreenTexture) (int tex, FSurfaceInfo *surf, FBITFIELD polyflags); EXPORT void HWRAPI(MakeScreenTexture) (int tex); EXPORT void HWRAPI(DrawScreenFinalTexture) (int tex, int width, int height); diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index f3196a5db..5bbc07d94 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -6615,7 +6615,7 @@ void HWR_EndScreenWipe(void) void HWR_DrawIntermissionBG(void) { - HWD.pfnDrawScreenTexture(HWD_SCREENTEXTURE_GENERIC1); + HWD.pfnDrawScreenTexture(HWD_SCREENTEXTURE_GENERIC1, NULL, 0); } void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index ebdfe06f5..702b3ca77 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -921,6 +921,19 @@ static float shader_leveltime = 0; "vec4 final_color = texture1D(palette_tex, palette_coord);\n" \ "gl_FragColor = final_color;\n" \ "}\0" + + +#define GLSL_UI_COLORMAP_FADE_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform float lighting;\n" \ + "uniform sampler3D palette_lookup_tex;\n" \ + "uniform sampler2D lighttable_tex;\n" \ + "void main(void) {\n" \ + "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ + "float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \ + "vec2 lighttable_coord = vec2((tex_pal_idx + 0.5) / 256.0, (lighting + 0.5) / 32.0);\n" \ + "gl_FragColor = texture2D(lighttable_tex, lighttable_coord);\n" \ + "}\0" \ // // Sky fragment shader @@ -969,6 +982,9 @@ static const char *fragment_shaders[] = { // Palette water shader GLSL_PALETTE_WATER_FRAGMENT_SHADER, + + // UI colormap fade shader + GLSL_UI_COLORMAP_FADE_SHADER, NULL, }; @@ -1026,6 +1042,9 @@ static const char *vertex_shaders[] = { // Palette water vertex shader GLSL_DEFAULT_VERTEX_SHADER, + + // UI colormap fade shader + GLSL_DEFAULT_VERTEX_SHADER, NULL, }; @@ -1542,11 +1561,11 @@ EXPORT void HWRAPI(ReadScreenTexture) (int tex, UINT16 *dst_data) // and draw generic2 back after reading the framebuffer. // this hack is for some reason **much** faster than the simple solution of using glGetTexImage. if (tex != HWD_SCREENTEXTURE_GENERIC2) - DrawScreenTexture(tex); + DrawScreenTexture(tex, NULL, 0); pglPixelStorei(GL_PACK_ALIGNMENT, 1); pglReadPixels(0, 0, screen_width, screen_height, GL_RGB, GL_UNSIGNED_BYTE, dst_data); if (tex != HWD_SCREENTEXTURE_GENERIC2) - DrawScreenTexture(HWD_SCREENTEXTURE_GENERIC2); + DrawScreenTexture(HWD_SCREENTEXTURE_GENERIC2, NULL, 0); // Flip image upside down. // In other words, convert OpenGL's "bottom->top" row order into "top->bottom". for(i = 0; i < screen_height/2; i++) @@ -2156,6 +2175,7 @@ static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAF } // code that is common between DrawPolygon and DrawIndexedTriangles +// DrawScreenTexture also can use this function for fancier screen texture drawing // the corona thing is there too, i have no idea if that stuff works with DrawIndexedTriangles and batching static void PreparePolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FBITFIELD PolyFlags) { @@ -3347,7 +3367,7 @@ EXPORT void HWRAPI(FlushScreenTextures) (void) screenTextures[i] = 0; } -EXPORT void HWRAPI(DrawScreenTexture)(int tex) +EXPORT void HWRAPI(DrawScreenTexture)(int tex, FSurfaceInfo *surf, FBITFIELD polyflags) { float xfix, yfix; INT32 texsize = 512; @@ -3387,7 +3407,10 @@ EXPORT void HWRAPI(DrawScreenTexture)(int tex) pglBindTexture(GL_TEXTURE_2D, screenTextures[tex]); - Shader_SetUniforms(NULL, NULL, NULL, NULL); // prepare shader, if it is enabled + if (surf) + PreparePolygon(surf, NULL, polyflags); + else + Shader_SetUniforms(NULL, NULL, NULL, NULL); // prepare shader, if it is enabled pglColor4ubv(white); @@ -3683,9 +3706,6 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int tex, int width, int height) clearColour.alpha = 1; ClearBuffer(true, false, false, &clearColour); - if (HWR_ShouldUsePaletteRendering()) - SetBlend(PF_NoDepthTest); - pglBindTexture(GL_TEXTURE_2D, screenTextures[tex]); //if ((HWR_ShouldUsePaletteRendering()) && cv_groldpal.value) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index fadce02f7..0a427be58 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1489,7 +1489,7 @@ void I_FinishUpdate(void) HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_GENERIC2); HWD.pfnSetSpecialState(HWD_SET_SHADERS, 1); HWD.pfnSetShader(8); - HWD.pfnDrawScreenTexture(HWD_SCREENTEXTURE_GENERIC2); + HWD.pfnDrawScreenTexture(HWD_SCREENTEXTURE_GENERIC2, NULL, 0); HWD.pfnUnSetShader(); HWD.pfnSetSpecialState(HWD_SET_SHADERS, 0); } diff --git a/src/sdl/ogl_sdl.c b/src/sdl/ogl_sdl.c index aa53df384..25d21bff5 100644 --- a/src/sdl/ogl_sdl.c +++ b/src/sdl/ogl_sdl.c @@ -235,7 +235,7 @@ void OglSdlFinishUpdate(boolean waitvbl) // effects that want to take the old screen can do so after this // Generic2 has the screen image without palette rendering brightness adjustments. // Using that here will prevent brightness adjustments being applied twice. - DrawScreenTexture(HWD_SCREENTEXTURE_GENERIC2); + DrawScreenTexture(HWD_SCREENTEXTURE_GENERIC2, NULL, 0); } EXPORT void HWRAPI(OglSdlSetPalette) (RGBA_t *palette) -- 2.54.0 From 241108abc25bd73f2c2810f9db27f9acd2ea956a Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 15 Jan 2024 16:50:20 +0100 Subject: [PATCH 12/24] ensure consistent shader state --- src/hardware/hw_main.c | 18 +++++++++++++++++- src/hardware/hw_main.h | 2 ++ src/hardware/r_opengl/r_opengl.c | 8 ++++---- src/sdl/i_video.c | 2 -- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 5bbc07d94..c57b5664f 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -182,6 +182,9 @@ static void CV_screentextures_ONChange(void) static void CV_grshaders_OnChange(void) { + if (rendermode == render_opengl) + HWR_SetShaderState(); + if ((rendermode == render_opengl) && (cv_grpaletterendering.value)) { // can't do palette rendering without shaders, so update the state if needed @@ -212,6 +215,17 @@ static void CV_grpalettedepth_OnChange(void) HWR_SetPalette(pLocalPalette); } +// +// Sets the shader state. +// +void HWR_SetShaderState(void) +{ + INT32 state = cv_grshaders.value; + + HWD.pfnSetSpecialState(HWD_SET_SHADERS, (INT32)state); + HWD.pfnSetShader(0); +} + // ========================================================================== // Globals // ========================================================================== @@ -6440,7 +6454,9 @@ void HWR_Startup(void) HWD.pfnKillShaders(); if (!HWD.pfnLoadShaders()) gr_shadersavailable = false; - + + HWR_SetShaderState(); + HWR_TogglePaletteRendering(); if (msaa) diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index dbcb93bb1..0b9437f5d 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -167,6 +167,8 @@ RGBA_t *HWR_GetTexturePalette(void); // hw_trick.c void HWR_CorrectSWTricks(void); +void HWR_SetShaderState(void); + // Console variables extern consvar_t cv_grshaders; extern consvar_t cv_grfofcut; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 702b3ca77..4b257d626 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -3407,10 +3407,9 @@ EXPORT void HWRAPI(DrawScreenTexture)(int tex, FSurfaceInfo *surf, FBITFIELD pol pglBindTexture(GL_TEXTURE_2D, screenTextures[tex]); - if (surf) - PreparePolygon(surf, NULL, polyflags); - else - Shader_SetUniforms(NULL, NULL, NULL, NULL); // prepare shader, if it is enabled + PreparePolygon(surf, NULL, surf ? polyflags : (PF_NoDepthTest)); + if (!surf) + pglColor4ubv(white); pglColor4ubv(white); @@ -3705,6 +3704,7 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int tex, int width, int height) clearColour.red = clearColour.green = clearColour.blue = 0; clearColour.alpha = 1; ClearBuffer(true, false, false, &clearColour); + SetBlend(PF_NoDepthTest); pglBindTexture(GL_TEXTURE_2D, screenTextures[tex]); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 0a427be58..6d2f56a08 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1487,11 +1487,9 @@ void I_FinishUpdate(void) if (HWR_ShouldUsePaletteRendering()) { HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_GENERIC2); - HWD.pfnSetSpecialState(HWD_SET_SHADERS, 1); HWD.pfnSetShader(8); HWD.pfnDrawScreenTexture(HWD_SCREENTEXTURE_GENERIC2, NULL, 0); HWD.pfnUnSetShader(); - HWD.pfnSetSpecialState(HWD_SET_SHADERS, 0); } OglSdlFinishUpdate(cv_vidwait.value); } -- 2.54.0 From d370b59777d98bb593e71177a1994fe485ebac56 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 15 Jan 2024 17:44:07 +0100 Subject: [PATCH 13/24] do this a little better --- src/hardware/hw_draw.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 2f0c13773..9006bca3b 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -548,6 +548,7 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength) { FOutVector v[4]; FSurfaceInfo Surf; + FBITFIELD poly_flags = PF_NoTexture|PF_Modulated|PF_NoDepthTest; v[0].x = v[3].x = -1.0f; v[2].x = v[1].x = 1.0f; @@ -575,9 +576,12 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength) return; } - - Surf.PolyColor.rgba = UINT2RGBA(0x01010160); - Surf.PolyColor.s.alpha = (strength*8); + else + { + Surf.PolyColor.rgba = UINT2RGBA(0x01010160); + Surf.PolyColor.s.alpha = (strength*8); + poly_flags |= PF_Translucent; + } } else // Do TRANSMAP** fade. { @@ -588,9 +592,11 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength) Surf.PolyColor.s.alpha = softwaretranstogl[strength]; else Surf.PolyColor.s.alpha = (UINT8)(strength*25.5f); + + poly_flags |= PF_Translucent; } - HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); + HWD.pfnDrawPolygon(&Surf, v, 4, poly_flags); } // Draw the console background with translucency support -- 2.54.0 From e77a4d4690a421d665626bfe59ecdb739d401c47 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 15 Jan 2024 19:36:37 +0100 Subject: [PATCH 14/24] readd oldpal for performance reasons its better --- src/hardware/hw_draw.c | 6 +++--- src/hardware/hw_main.c | 28 ++++++++++++++-------------- src/hardware/hw_main.h | 1 + src/hardware/r_opengl/r_opengl.c | 8 ++++---- src/m_menu.c | 5 +++-- src/sdl/i_video.c | 2 +- 6 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 9006bca3b..b9c4e9fd4 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -563,7 +563,7 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength) if (color & 0xFF00) // Do COLORMAP fade. { - if (HWR_ShouldUsePaletteRendering()) + if (HWR_ShouldUsePaletteRendering() && !cv_groldpal.value) { const hwdscreentexture_t scr_tex = HWD_SCREENTEXTURE_GENERIC2; @@ -1178,7 +1178,7 @@ static inline boolean saveTGA(const char *file_name, void *buffer, UINT8 *HWR_GetScreenshot(void) { static UINT8 *buf = NULL; - int tex = (HWR_ShouldUsePaletteRendering() ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2); + int tex = ((HWR_ShouldUsePaletteRendering() && !cv_groldpal.value) ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2); buf = realloc(buf, vid.width * vid.height * 3); @@ -1194,7 +1194,7 @@ boolean HWR_Screenshot(const char *pathname) { boolean ret; UINT8 *buf = malloc(vid.width * vid.height * 3 * sizeof (*buf)); - int tex = (HWR_ShouldUsePaletteRendering() ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2); + int tex = ((HWR_ShouldUsePaletteRendering() && !cv_groldpal.value) ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2); if (!buf) { diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index c57b5664f..1793b8250 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -71,7 +71,7 @@ static boolean gr_palette_rendering_state = false; static void CV_filtermode_ONChange(void); static void CV_anisotropic_ONChange(void); static void CV_screentextures_ONChange(void); -static void CV_useCustomShaders_ONChange(void); +static void CV_useCustomShaders_ONChange(void); static void CV_grshaders_OnChange(void); static void CV_grpaletterendering_OnChange(void); static void CV_grpalettedepth_OnChange(void); @@ -90,10 +90,10 @@ consvar_t cv_grrounddown = {"gr_rounddown", "Off", 0, CV_OnOff, NULL, 0, NULL, N consvar_t cv_grfiltermode = {"gr_filtermode", "Nearest", CV_CALL|CV_SAVE, grfiltermode_cons_t, CV_filtermode_ONChange, 0, NULL, NULL, 0, 0, NULL}; - + consvar_t cv_granisotropicmode = {"gr_anisotropicmode", "1", CV_CALL|CV_SAVE, granisotropicmode_cons_t, CV_anisotropic_ONChange, 0, NULL, NULL, 0, 0, NULL}; - + consvar_t cv_grcorrecttricks = {"gr_correcttricks", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grsolvetjoin = {"gr_solvetjoin", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -112,7 +112,7 @@ static CV_PossibleValue_t grrenderdistance_cons_t[] = { {6, "12288"}, {7, "16384"}, {0, NULL}}; consvar_t cv_grrenderdistance = {"gr_renderdistance", "Max", CV_SAVE, grrenderdistance_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; - + consvar_t cv_grportals = {"gr_portals", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_nostencil = {"nostencil", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_portalline = {"portalline", "0", 0, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -121,10 +121,10 @@ CV_PossibleValue_t secbright_cons_t[] = {{0, "MIN"}, {255, "MAX"}, {0, NULL}}; consvar_t cv_secbright = {"secbright", "0", CV_SAVE, secbright_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; - + consvar_t cv_grfovchange = {"gr_fovchange", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; - + // values for the far clipping plane static float clipping_distances[] = {1024.0f, 2048.0f, 4096.0f, 6144.0f, 8192.0f, 12288.0f, 16384.0f}; // values for bsp culling @@ -142,7 +142,7 @@ static INT32 current_bsp_culling_distance = 0; // - full screen scaling (use native resolution or windowed mode to avoid this) consvar_t cv_grscreentextures = {"gr_screentextures", "On", CV_CALL|CV_SAVE, CV_OnOff, CV_screentextures_ONChange, 0, NULL, NULL, 0, 0, NULL}; - + consvar_t cv_grshaders = {"gr_shaders", "On", CV_CALL|CV_SAVE, CV_OnOff, CV_grshaders_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grusecustomshaders = {"gr_usecustomshaders", "Yes", CV_CALL|CV_SAVE, CV_OnOff, CV_useCustomShaders_ONChange, 0, NULL, NULL, 0, 0, NULL}; @@ -152,6 +152,7 @@ static CV_PossibleValue_t glpalettedepth_cons_t[] = {{16, "16 bits"}, {24, "24 b consvar_t cv_grpalettedepth = {"gr_palettedepth", "16 bits", CV_SAVE|CV_CALL, glpalettedepth_cons_t, CV_grpalettedepth_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grflashpal = {"gr_flashpal", "On", CV_CALL|CV_SAVE, CV_OnOff, CV_grshaders_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_groldpal = {"gr_oldpal", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grmdls = {"gr_mdls", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grfallbackplayermodel = {"gr_fallbackplayermodel", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -165,19 +166,19 @@ consvar_t cv_grslopecontrast = {"gr_slopecontrast", "Off", CV_SAVE, CV_OnOff, NU static void CV_filtermode_ONChange(void) { if (rendermode == render_opengl) - HWD.pfnSetSpecialState(HWD_SET_TEXTUREFILTERMODE, cv_grfiltermode.value); + HWD.pfnSetSpecialState(HWD_SET_TEXTUREFILTERMODE, cv_grfiltermode.value); } static void CV_anisotropic_ONChange(void) { if (rendermode == render_opengl) - HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_granisotropicmode.value); + HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_granisotropicmode.value); } static void CV_screentextures_ONChange(void) { if (rendermode == render_opengl) - HWD.pfnSetSpecialState(HWD_SET_SCREEN_TEXTURES, cv_grscreentextures.value); + HWD.pfnSetSpecialState(HWD_SET_SCREEN_TEXTURES, cv_grscreentextures.value); } static void CV_grshaders_OnChange(void) @@ -204,9 +205,7 @@ static void CV_useCustomShaders_ONChange(void) // should we do a call to HWR_Tog static void CV_grpaletterendering_OnChange(void) { if ((rendermode == render_opengl) && (gr_shadersavailable)) - { HWR_TogglePaletteRendering(); - } } static void CV_grpalettedepth_OnChange(void) @@ -6427,6 +6426,7 @@ void HWR_AddCommands(void) CV_RegisterVar(&cv_grpaletterendering); CV_RegisterVar(&cv_grpalettedepth); CV_RegisterVar(&cv_grflashpal); + CV_RegisterVar(&cv_groldpal); } // -------------------------------------------------------------------------- @@ -6669,13 +6669,13 @@ void HWR_RenderVhsEffect(fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT void HWR_MakeScreenFinalTexture(void) { - int tex = (HWR_ShouldUsePaletteRendering() ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2); + int tex = ((HWR_ShouldUsePaletteRendering() && !cv_groldpal.value) ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2); HWD.pfnMakeScreenTexture(tex); } void HWR_DrawScreenFinalTexture(int width, int height) { - int tex = (HWR_ShouldUsePaletteRendering() ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2); + int tex = ((HWR_ShouldUsePaletteRendering() && !cv_groldpal.value) ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2); HWD.pfnDrawScreenFinalTexture(tex, width, height); } diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 0b9437f5d..6fba8d78e 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -195,6 +195,7 @@ extern consvar_t cv_grusecustomshaders; extern consvar_t cv_grpaletterendering; extern consvar_t cv_grpalettedepth; extern consvar_t cv_grflashpal; +extern consvar_t cv_groldpal; extern consvar_t cv_grscreentextures; extern consvar_t cv_grportals; extern consvar_t cv_nostencil; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 4b257d626..fb8292ba7 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -3708,8 +3708,8 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int tex, int width, int height) pglBindTexture(GL_TEXTURE_2D, screenTextures[tex]); - //if ((HWR_ShouldUsePaletteRendering()) && cv_groldpal.value) - //pglUseProgram(gl_shaderprograms[8].program); // palette postprocess shader + if ((HWR_ShouldUsePaletteRendering()) && cv_groldpal.value) + pglUseProgram(gl_shaderprograms[8].program); // palette postprocess shader pglColor4ubv(white); @@ -3718,8 +3718,8 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int tex, int width, int height) pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); - //if ((HWR_ShouldUsePaletteRendering()) && cv_groldpal.value) - //pglUseProgram(0); + if ((HWR_ShouldUsePaletteRendering()) && cv_groldpal.value) + pglUseProgram(0); tex_downloaded = screenTextures[tex]; } diff --git a/src/m_menu.c b/src/m_menu.c index 8ece67fe5..28d3b0a93 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1493,8 +1493,9 @@ static menuitem_t OP_ExpOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Spriteclip", &cv_spriteclip, 85}, #ifdef HWRENDER {IT_STRING | IT_CVAR, NULL, "Screen Textures", &cv_grscreentextures, 75}, - + {IT_STRING | IT_CVAR, NULL, "Palette Depth", &cv_grpalettedepth, 85}, + {IT_STRING | IT_CVAR, NULL, "Old Palshader Screentexture", &cv_groldpal, 95}, {IT_STRING | IT_CVAR, NULL, "Splitwall/Slope texture fix", &cv_splitwallfix, 105}, {IT_STRING | IT_CVAR, NULL, "Slope midtexture peg fix", &cv_slopepegfix, 115}, @@ -1514,7 +1515,7 @@ static const char* OP_ExpTooltips[] = #ifdef HWRENDER "Should the game do Screen Textures? Provides a good boost to frames\nat the cost of some visual effects not working when disabled.", "Fixes issues that resulted in Textures sticking from the\nground sometimes.\nThis may be CPU heavy and result in worse performance in some cases.", - "Change the depth of the palette in palette rendering mode.", + "Changes back to old Palette renderer screentexture behaviour\nthis makes performance better and keeps the old visuals\nat the cost of accuracy.", "Fixes issues that resulted in Textures sticking from the ground sometimes.\n This may be CPU heavy and result in worse performance in some cases.", "Fixes issues that resulted in Textures not being properly skewed\n example: Fences on slopes that didnt show proper.\n This may be CPU heavy and result in worse performance in some cases.", "Fixes issues that resulted in Textures on Floor over Floors\nZFighting heavily.", diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 6d2f56a08..7d3313f0e 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1484,7 +1484,7 @@ void I_FinishUpdate(void) else if (rendermode == render_opengl) { // Final postprocess step of palette rendering, after everything else has been drawn. - if (HWR_ShouldUsePaletteRendering()) + if (HWR_ShouldUsePaletteRendering() && !cv_groldpal.value) { HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_GENERIC2); HWD.pfnSetShader(8); -- 2.54.0 From 00dbd08641cf3e5466f8a9da489816c738a2d327 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 15 Jan 2024 20:12:35 +0100 Subject: [PATCH 15/24] remove the extra screentex and apply palshader directly to finaltex theres basically barely any difference, even in the fades theres very little, and it just cost so freaking much performance however, ill keep the revamped screentex setup as this it allows us to keep the better fadescreen background for menus --- src/hardware/hw_defs.h | 3 +-- src/hardware/hw_draw.c | 8 +++----- src/hardware/hw_main.c | 10 +++------- src/hardware/hw_main.h | 1 - src/hardware/r_opengl/r_opengl.c | 4 ++-- src/m_menu.c | 4 +--- src/sdl/i_video.c | 8 -------- src/sdl/ogl_sdl.c | 4 +--- 8 files changed, 11 insertions(+), 31 deletions(-) diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 09d7b89a1..dd293c000 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -294,8 +294,7 @@ enum hwdscreentexture HWD_SCREENTEXTURE_WIPE_START, // source image for the wipe/fade effect HWD_SCREENTEXTURE_WIPE_END, // destination image for the wipe/fade effect HWD_SCREENTEXTURE_GENERIC1, // underwater/heat effect, intermission background - HWD_SCREENTEXTURE_GENERIC2, // palette-based colormap fade, screen before palette rendering's postprocessing - HWD_SCREENTEXTURE_GENERIC3, // screen after palette rendering's postprocessing + HWD_SCREENTEXTURE_GENERIC2, // palette-based colormap fade, final screen texture NUMSCREENTEXTURES, // (generic3 is unused if palette rendering is disabled) }; typedef enum hwdscreentexture hwdscreentexture_t; diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index b9c4e9fd4..d5c18a129 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -563,7 +563,7 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength) if (color & 0xFF00) // Do COLORMAP fade. { - if (HWR_ShouldUsePaletteRendering() && !cv_groldpal.value) + if (HWR_ShouldUsePaletteRendering() && cv_grscreentextures.value) { const hwdscreentexture_t scr_tex = HWD_SCREENTEXTURE_GENERIC2; @@ -1178,7 +1178,6 @@ static inline boolean saveTGA(const char *file_name, void *buffer, UINT8 *HWR_GetScreenshot(void) { static UINT8 *buf = NULL; - int tex = ((HWR_ShouldUsePaletteRendering() && !cv_groldpal.value) ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2); buf = realloc(buf, vid.width * vid.height * 3); @@ -1186,7 +1185,7 @@ UINT8 *HWR_GetScreenshot(void) return NULL; // returns 24bit 888 RGB - HWD.pfnReadScreenTexture(tex, (void *)buf); + HWD.pfnReadScreenTexture(HWD_SCREENTEXTURE_GENERIC2, (void *)buf); return buf; } @@ -1194,7 +1193,6 @@ boolean HWR_Screenshot(const char *pathname) { boolean ret; UINT8 *buf = malloc(vid.width * vid.height * 3 * sizeof (*buf)); - int tex = ((HWR_ShouldUsePaletteRendering() && !cv_groldpal.value) ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2); if (!buf) { @@ -1203,7 +1201,7 @@ boolean HWR_Screenshot(const char *pathname) } // returns 24bit 888 RGB - HWD.pfnReadScreenTexture(tex, (void *)buf); + HWD.pfnReadScreenTexture(HWD_SCREENTEXTURE_GENERIC2, (void *)buf); #ifdef USE_PNG ret = M_SavePNG(pathname, buf, vid.width, vid.height, NULL); diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 1793b8250..a54de5f31 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -124,7 +124,7 @@ consvar_t cv_secbright = {"secbright", "0", CV_SAVE, secbright_cons_t, consvar_t cv_grfovchange = {"gr_fovchange", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; - + // values for the far clipping plane static float clipping_distances[] = {1024.0f, 2048.0f, 4096.0f, 6144.0f, 8192.0f, 12288.0f, 16384.0f}; // values for bsp culling @@ -152,7 +152,6 @@ static CV_PossibleValue_t glpalettedepth_cons_t[] = {{16, "16 bits"}, {24, "24 b consvar_t cv_grpalettedepth = {"gr_palettedepth", "16 bits", CV_SAVE|CV_CALL, glpalettedepth_cons_t, CV_grpalettedepth_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grflashpal = {"gr_flashpal", "On", CV_CALL|CV_SAVE, CV_OnOff, CV_grshaders_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_groldpal = {"gr_oldpal", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grmdls = {"gr_mdls", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grfallbackplayermodel = {"gr_fallbackplayermodel", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -6426,7 +6425,6 @@ void HWR_AddCommands(void) CV_RegisterVar(&cv_grpaletterendering); CV_RegisterVar(&cv_grpalettedepth); CV_RegisterVar(&cv_grflashpal); - CV_RegisterVar(&cv_groldpal); } // -------------------------------------------------------------------------- @@ -6669,14 +6667,12 @@ void HWR_RenderVhsEffect(fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT void HWR_MakeScreenFinalTexture(void) { - int tex = ((HWR_ShouldUsePaletteRendering() && !cv_groldpal.value) ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2); - HWD.pfnMakeScreenTexture(tex); + HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_GENERIC2); } void HWR_DrawScreenFinalTexture(int width, int height) { - int tex = ((HWR_ShouldUsePaletteRendering() && !cv_groldpal.value) ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2); - HWD.pfnDrawScreenFinalTexture(tex, width, height); + HWD.pfnDrawScreenFinalTexture(HWD_SCREENTEXTURE_GENERIC2, width, height); } // jimita 18032019 diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 6fba8d78e..0b9437f5d 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -195,7 +195,6 @@ extern consvar_t cv_grusecustomshaders; extern consvar_t cv_grpaletterendering; extern consvar_t cv_grpalettedepth; extern consvar_t cv_grflashpal; -extern consvar_t cv_groldpal; extern consvar_t cv_grscreentextures; extern consvar_t cv_grportals; extern consvar_t cv_nostencil; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index fb8292ba7..bb5f3396a 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -3708,7 +3708,7 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int tex, int width, int height) pglBindTexture(GL_TEXTURE_2D, screenTextures[tex]); - if ((HWR_ShouldUsePaletteRendering()) && cv_groldpal.value) + if (HWR_ShouldUsePaletteRendering()) pglUseProgram(gl_shaderprograms[8].program); // palette postprocess shader pglColor4ubv(white); @@ -3718,7 +3718,7 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int tex, int width, int height) pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); - if ((HWR_ShouldUsePaletteRendering()) && cv_groldpal.value) + if (HWR_ShouldUsePaletteRendering()) pglUseProgram(0); tex_downloaded = screenTextures[tex]; diff --git a/src/m_menu.c b/src/m_menu.c index 28d3b0a93..2d7a49972 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1495,7 +1495,6 @@ static menuitem_t OP_ExpOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Screen Textures", &cv_grscreentextures, 75}, {IT_STRING | IT_CVAR, NULL, "Palette Depth", &cv_grpalettedepth, 85}, - {IT_STRING | IT_CVAR, NULL, "Old Palshader Screentexture", &cv_groldpal, 95}, {IT_STRING | IT_CVAR, NULL, "Splitwall/Slope texture fix", &cv_splitwallfix, 105}, {IT_STRING | IT_CVAR, NULL, "Slope midtexture peg fix", &cv_slopepegfix, 115}, @@ -1514,8 +1513,7 @@ static const char* OP_ExpTooltips[] = "Hides Sprites which are not visible\npotentially resulting in a performance boost.", #ifdef HWRENDER "Should the game do Screen Textures? Provides a good boost to frames\nat the cost of some visual effects not working when disabled.", - "Fixes issues that resulted in Textures sticking from the\nground sometimes.\nThis may be CPU heavy and result in worse performance in some cases.", - "Changes back to old Palette renderer screentexture behaviour\nthis makes performance better and keeps the old visuals\nat the cost of accuracy.", + "Change the depth of the Palette in Palette rendering mod\n 16 bits is like software looks ingame\nwhile 24 bits is how software looks in screenshots.", "Fixes issues that resulted in Textures sticking from the ground sometimes.\n This may be CPU heavy and result in worse performance in some cases.", "Fixes issues that resulted in Textures not being properly skewed\n example: Fences on slopes that didnt show proper.\n This may be CPU heavy and result in worse performance in some cases.", "Fixes issues that resulted in Textures on Floor over Floors\nZFighting heavily.", diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 7d3313f0e..c070b3826 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1483,14 +1483,6 @@ void I_FinishUpdate(void) #ifdef HWRENDER else if (rendermode == render_opengl) { - // Final postprocess step of palette rendering, after everything else has been drawn. - if (HWR_ShouldUsePaletteRendering() && !cv_groldpal.value) - { - HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_GENERIC2); - HWD.pfnSetShader(8); - HWD.pfnDrawScreenTexture(HWD_SCREENTEXTURE_GENERIC2, NULL, 0); - HWD.pfnUnSetShader(); - } OglSdlFinishUpdate(cv_vidwait.value); } #endif diff --git a/src/sdl/ogl_sdl.c b/src/sdl/ogl_sdl.c index 25d21bff5..dc831fce0 100644 --- a/src/sdl/ogl_sdl.c +++ b/src/sdl/ogl_sdl.c @@ -233,9 +233,7 @@ void OglSdlFinishUpdate(boolean waitvbl) // Sryder: We need to draw the final screen texture again into the other buffer in the original position so that // effects that want to take the old screen can do so after this - // Generic2 has the screen image without palette rendering brightness adjustments. - // Using that here will prevent brightness adjustments being applied twice. - DrawScreenTexture(HWD_SCREENTEXTURE_GENERIC2, NULL, 0); + HWR_DrawScreenFinalTexture(realwidth, realheight); } EXPORT void HWRAPI(OglSdlSetPalette) (RGBA_t *palette) -- 2.54.0 From fc2a0846cb96e947e93fee76ede30a81c2c30c5b Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 18 Jan 2024 20:53:59 +0100 Subject: [PATCH 16/24] Add toggle for horizonlines --- src/hardware/hw_main.c | 5 ++++- src/hardware/hw_main.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index a54de5f31..cfb8c7aa4 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -161,6 +161,8 @@ consvar_t cv_grspritebillboarding = {"gr_spritebillboarding", "On", CV_SAVE, CV_ consvar_t cv_grfakecontrast = {"gr_fakecontrast", "Standard", CV_SAVE, grfakecontrast_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grslopecontrast = {"gr_slopecontrast", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_grhorizonlines = {"gr_horizonlines", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; + static void CV_filtermode_ONChange(void) { @@ -852,7 +854,7 @@ void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isc HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags, shader, false); - if (subsector) + if (subsector && cv_grhorizonlines.value) { // Horizon lines FOutVector horizonpts[6]; @@ -6402,6 +6404,7 @@ void HWR_AddCommands(void) CV_RegisterVar(&cv_grfakecontrast); CV_RegisterVar(&cv_grslopecontrast); + CV_RegisterVar(&cv_grhorizonlines); CV_RegisterVar(&cv_grfovchange); diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 0b9437f5d..b98bc0893 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -188,6 +188,7 @@ extern consvar_t cv_grsolvetjoin; extern consvar_t cv_grspritebillboarding; extern consvar_t cv_grfakecontrast; extern consvar_t cv_grslopecontrast; +extern consvar_t cv_grhorizonlines; extern consvar_t cv_grfallbackplayermodel; extern consvar_t cv_grbatching; extern consvar_t cv_grrenderdistance; -- 2.54.0 From 9725a9d9a595cb490f7528a37cffd3e26c03d186 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 19 Jan 2024 19:23:49 +0100 Subject: [PATCH 17/24] Fix blackscreen on start + some other changes move a few things around in HWR_Startup so they only get called on startup --- src/d_main.c | 2 - src/hardware/hw_main.c | 77 +++++++++++++++----------------- src/hardware/r_opengl/r_opengl.c | 2 - src/screen.h | 7 +++ src/sdl/i_video.c | 16 ++++--- 5 files changed, 52 insertions(+), 52 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 3850243b8..a56c69436 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1521,9 +1521,7 @@ void D_SRB2Main(void) // Has to be done before the configuration file loads, // but after the OpenGL library loads. HWR_AddCommands(); -#endif -#ifdef HWRENDER if (rendermode == render_opengl) { for (i = 0; i < numwadfiles; i++) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index cfb8c7aa4..4cf8b04a3 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -163,31 +163,31 @@ consvar_t cv_grslopecontrast = {"gr_slopecontrast", "Off", CV_SAVE, CV_OnOff, NU consvar_t cv_grhorizonlines = {"gr_horizonlines", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +#define ONLY_IF_GL_LOADED if (vid.glstate != VID_GL_LIBRARY_LOADED) return; static void CV_filtermode_ONChange(void) { - if (rendermode == render_opengl) - HWD.pfnSetSpecialState(HWD_SET_TEXTUREFILTERMODE, cv_grfiltermode.value); + ONLY_IF_GL_LOADED + HWD.pfnSetSpecialState(HWD_SET_TEXTUREFILTERMODE, cv_grfiltermode.value); } static void CV_anisotropic_ONChange(void) { - if (rendermode == render_opengl) - HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_granisotropicmode.value); + ONLY_IF_GL_LOADED + HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_granisotropicmode.value); } static void CV_screentextures_ONChange(void) { - if (rendermode == render_opengl) - HWD.pfnSetSpecialState(HWD_SET_SCREEN_TEXTURES, cv_grscreentextures.value); + ONLY_IF_GL_LOADED + HWD.pfnSetSpecialState(HWD_SET_SCREEN_TEXTURES, cv_grscreentextures.value); } static void CV_grshaders_OnChange(void) { - if (rendermode == render_opengl) - HWR_SetShaderState(); - - if ((rendermode == render_opengl) && (cv_grpaletterendering.value)) + ONLY_IF_GL_LOADED + HWR_SetShaderState(); + if ((cv_grpaletterendering.value)) { // can't do palette rendering without shaders, so update the state if needed HWR_TogglePaletteRendering(); @@ -196,22 +196,22 @@ static void CV_grshaders_OnChange(void) static void CV_useCustomShaders_ONChange(void) // should we do a call to HWR_TogglePaletteRendering here aswell in pal rendering mode? { - if (rendermode == render_opengl) - { - if (HWR_UseShader()) - HWD.pfnInitCustomShaders(); - } + ONLY_IF_GL_LOADED + if (HWR_UseShader()) + HWD.pfnInitCustomShaders(); } static void CV_grpaletterendering_OnChange(void) { - if ((rendermode == render_opengl) && (gr_shadersavailable)) + ONLY_IF_GL_LOADED + if (gr_shadersavailable) HWR_TogglePaletteRendering(); } static void CV_grpalettedepth_OnChange(void) { - if ((rendermode == render_opengl) && (HWR_ShouldUsePaletteRendering())) + ONLY_IF_GL_LOADED + if (HWR_ShouldUsePaletteRendering()) HWR_SetPalette(pLocalPalette); } @@ -220,10 +220,7 @@ static void CV_grpalettedepth_OnChange(void) // void HWR_SetShaderState(void) { - INT32 state = cv_grshaders.value; - - HWD.pfnSetSpecialState(HWD_SET_SHADERS, (INT32)state); - HWD.pfnSetShader(0); + HWD.pfnSetSpecialState(HWD_SET_SHADERS, HWR_UseShader()); } // ========================================================================== @@ -6273,8 +6270,8 @@ void HWR_RenderFrame(INT32 viewnumber, player_t *player, boolean skybox) HWR_ClearClipper(); // Reset the shader state. - HWD.pfnSetSpecialState(HWD_SET_SHADERS, cv_grshaders.value); - HWD.pfnSetShader(0); + //HWD.pfnSetSpecialState(HWD_SET_SHADERS, cv_grshaders.value); + //HWD.pfnSetShader(0); validcount++; @@ -6447,26 +6444,24 @@ void HWR_Startup(void) HWR_InitMD2(); HWD.pfnSetupGLInfo(); - } + + // jimita + HWD.pfnKillShaders(); + if (!HWD.pfnLoadShaders()) + gr_shadersavailable = false; + HWR_SetShaderState(); + HWR_TogglePaletteRendering(); + + if (msaa) + { + if (a2c) + HWD.pfnSetSpecialState(HWD_SET_MSAA, 2); + else + HWD.pfnSetSpecialState(HWD_SET_MSAA, 1); + } + } startupdone = true; - - // jimita - HWD.pfnKillShaders(); - if (!HWD.pfnLoadShaders()) - gr_shadersavailable = false; - - HWR_SetShaderState(); - - HWR_TogglePaletteRendering(); - - if (msaa) - { - if (a2c) - HWD.pfnSetSpecialState(HWD_SET_MSAA, 2); - else - HWD.pfnSetSpecialState(HWD_SET_MSAA, 1); - } } // -------------------------------------------------------------------------- diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index bb5f3396a..26073bbeb 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -3411,8 +3411,6 @@ EXPORT void HWRAPI(DrawScreenTexture)(int tex, FSurfaceInfo *surf, FBITFIELD pol if (!surf) pglColor4ubv(white); - pglColor4ubv(white); - pglTexCoordPointer(2, GL_FLOAT, 0, fix); pglVertexPointer(3, GL_FLOAT, 0, screenVerts); pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); diff --git a/src/screen.h b/src/screen.h index 64c04dc15..478890c49 100644 --- a/src/screen.h +++ b/src/screen.h @@ -72,11 +72,18 @@ typedef struct viddef_s #ifdef HWRENDER INT32/*fixed_t*/ fsmalldupx, fsmalldupy; INT32/*fixed_t*/ fmeddupx, fmeddupy; + INT32 glstate; #endif } viddef_t; #define VIDWIDTH vid.width #define VIDHEIGHT vid.height +enum +{ + VID_GL_LIBRARY_LOADED = 1, + VID_GL_LIBRARY_ERROR = -1, +}; + // internal additional info for vesa modes only typedef struct { diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index c070b3826..8ce2b4710 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1787,10 +1787,8 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen) flags |= SDL_WINDOW_BORDERLESS; #ifdef HWRENDER - if (rendermode == render_opengl) - { + if (vid.glstate == VID_GL_LIBRARY_LOADED) flags |= SDL_WINDOW_OPENGL; - } if (msaa) { @@ -1802,12 +1800,12 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen) // Some GPU drivers may give us a 16-bit depth buffer since the // default value for SDL_GL_DEPTH_SIZE is 16. SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); -#endif - + // request stencil buffer. If there are problems on weaker hw the bit count could be reduced // If only something like 1-bit or 2-bit stencil is available on some gpus then should implement limit for maxportals based on that. // 4 bits would be enough for current limit in maxportals (12) SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 4); +#endif // Create a window window = SDL_CreateWindow("SRB2Kart "VERSIONSTRING, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, @@ -1821,7 +1819,8 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen) // Renderer-specific stuff #ifdef HWRENDER - if (rendermode == render_opengl) + if ((rendermode == render_opengl) + && (vid.glstate != VID_GL_LIBRARY_ERROR)) { sdlglcontext = SDL_GL_CreateContext(window); if (sdlglcontext == NULL) @@ -2151,8 +2150,11 @@ void I_StartupGraphics(void) HWD.pfnClearLightTables = hwSym("ClearLightTables",NULL); HWD.pfnSetScreenPalette = hwSym("SetScreenPalette",NULL); - if (!HWD.pfnInit()) // load the OpenGL library + vid.glstate = HWD.pfnInit() ? VID_GL_LIBRARY_LOADED : VID_GL_LIBRARY_ERROR; // let load the OpenGL library + if (vid.glstate == VID_GL_LIBRARY_ERROR) + { rendermode = render_soft; + } } #endif -- 2.54.0 From 27c8f3a8b4f71e7e55d4907a77414ff6549a0486 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 19 Jan 2024 19:37:00 +0100 Subject: [PATCH 18/24] change gr_shadersavailible hopefully a little safer + remove killshader call since that function is empty and does nothing --- src/hardware/hw_main.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 4cf8b04a3..eb00e9834 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -58,8 +58,8 @@ // ========================================================================== struct hwdriver_s hwdriver; - -boolean gr_shadersavailable = true; +// false if shaders have not been initialized yet, or if shaders are not available +boolean gr_shadersavailable = false; // Whether the internal state is set to palette rendering or not. static boolean gr_palette_rendering_state = false; @@ -6444,11 +6444,8 @@ void HWR_Startup(void) HWR_InitMD2(); HWD.pfnSetupGLInfo(); - - // jimita - HWD.pfnKillShaders(); - if (!HWD.pfnLoadShaders()) - gr_shadersavailable = false; + + gr_shadersavailable = HWD.pfnLoadShaders(); HWR_SetShaderState(); HWR_TogglePaletteRendering(); -- 2.54.0 From 32d4d288bc31050450cae4585421efbf8bb86cd9 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 25 Jan 2024 15:05:42 +0100 Subject: [PATCH 19/24] OpenGL shader code rearrangement and shader pre-preprocessor https://git.do.srb2.org/STJr/SRB2/-/commit/de37df1be04e9d1dfb11083a9585eb6ac1761633?merge_request_iid=1516 wew --- src/Makefile | 2 +- src/d_main.c | 6 - src/hardware/hw_batching.c | 12 +- src/hardware/hw_defs.h | 40 ++ src/hardware/hw_draw.c | 2 +- src/hardware/hw_drv.h | 16 +- src/hardware/hw_glob.h | 14 + src/hardware/hw_main.c | 235 ++------ src/hardware/hw_main.h | 3 +- src/hardware/hw_md2.c | 2 +- src/hardware/hw_shaders.c | 884 +++++++++++++++++++++++++++++++ src/hardware/r_opengl/r_opengl.c | 865 ++++++++++-------------------- src/hardware/r_opengl/r_opengl.h | 1 + src/sdl/hwsym_sdl.c | 7 +- src/sdl/i_video.c | 11 +- src/w_wad.c | 15 +- 16 files changed, 1276 insertions(+), 839 deletions(-) create mode 100644 src/hardware/hw_shaders.c diff --git a/src/Makefile b/src/Makefile index 8af668744..cf1cfb006 100644 --- a/src/Makefile +++ b/src/Makefile @@ -275,7 +275,7 @@ else OPTS+=-DHWRENDER OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \ $(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o \ - $(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o $(OBJDIR)/hw_batching.o + $(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o $(OBJDIR)/hw_batching.o $(OBJDIR)/hw_shaders.o endif OPTS += -DCOMPVERSION diff --git a/src/d_main.c b/src/d_main.c index a56c69436..9f3ad8ac9 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1521,12 +1521,6 @@ void D_SRB2Main(void) // Has to be done before the configuration file loads, // but after the OpenGL library loads. HWR_AddCommands(); - - if (rendermode == render_opengl) - { - for (i = 0; i < numwadfiles; i++) - HWR_LoadShaders(i, (wadfiles[i]->type == RET_PK3)); - } #endif //--------------------------------------------------------- CONSOLE diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c index e3d02c4b4..e58b2ba7f 100644 --- a/src/hardware/hw_batching.c +++ b/src/hardware/hw_batching.c @@ -95,7 +95,7 @@ void HWR_SetCurrentTexture(GLMipmap_t *texture) HWD.pfnSetTexture(texture); } -static void HWR_CollectDrawCallInfo(FSurfaceInfo *pSurf, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial) +static void HWR_CollectDrawCallInfo(FSurfaceInfo *pSurf, FUINT iNumPts, FBITFIELD PolyFlags, int shader_target, boolean horizonSpecial) { // make sure dynamic array has capacity if (drawCallsSize == drawCallsCapacity) @@ -117,7 +117,7 @@ static void HWR_CollectDrawCallInfo(FSurfaceInfo *pSurf, FUINT iNumPts, FBITFIEL drawCalls[drawCallsSize].numVerts = iNumPts; drawCalls[drawCallsSize].polyFlags = PolyFlags; drawCalls[drawCallsSize].texture = current_texture; - drawCalls[drawCallsSize].shader = shader; + drawCalls[drawCallsSize].shader = (shader_target != -1) ? HWR_GetShaderFromTarget(shader_target) : shader_target; drawCalls[drawCallsSize].horizonSpecial = horizonSpecial; drawCallsSize++; } @@ -143,7 +143,7 @@ static void HWR_CollectDrawCallVertices(FOutVector *pOutVerts, FUINT iNumPts) // If batching is enabled, this function collects the polygon data and the chosen texture // for later use in HWR_RenderBatches. Otherwise the rendering backend is used to // render the polygon immediately. -void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial) +void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader_target, boolean horizonSpecial) { if (currently_batching) { @@ -153,13 +153,13 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt I_Error("Got a null FSurfaceInfo in batching"); } - HWR_CollectDrawCallInfo(pSurf, iNumPts, PolyFlags, shader, horizonSpecial); + HWR_CollectDrawCallInfo(pSurf, iNumPts, PolyFlags, shader_target, horizonSpecial); HWR_CollectDrawCallVertices(pOutVerts, iNumPts); } else { - if (shader) - HWD.pfnSetShader(shader); + if (shader_target != -1) + HWD.pfnSetShader(HWR_GetShaderFromTarget(shader_target)); HWD.pfnDrawPolygon(pSurf, pOutVerts, iNumPts, PolyFlags); } } diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index dd293c000..cbcbef5ac 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -165,6 +165,46 @@ typedef struct FLOAT s,t; } FOutVector; +#ifdef GL_SHADERS +// Shader targets used to render specific types of geometry. +// A shader target is resolved to an actual shader with HWR_GetShaderFromTarget. +// The shader returned may be a base shader or a custom shader. +enum +{ + SHADER_NONE = -1, + SHADER_FLOOR = 0, + SHADER_WALL, + SHADER_MODEL, + SHADER_SPRITE, + SHADER_WATER, + SHADER_FOG, + SHADER_SKY, + SHADER_PALETTE_POSTPROCESS, + SHADER_UI_COLORMAP_FADE, + + NUMSHADERTARGETS +}; + +// Must be at least NUMSHADERTARGETS*2 to fit base and custom shaders for each shader target. +#define HWR_MAXSHADERS NUMSHADERTARGETS*2 + +// Custom shader reference table +typedef struct +{ + const char *type; + INT32 id; +} customshaderxlat_t; + +enum hwdshaderstage +{ + HWD_SHADERSTAGE_VERTEX, + HWD_SHADERSTAGE_FRAGMENT, +}; + +typedef enum hwdshaderstage hwdshaderstage_t; + +#endif + // ========================================================================== // RENDER MODES // ========================================================================== diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index d5c18a129..bd09b69d2 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -570,7 +570,7 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength) Surf.LightTableId = HWR_GetLightTableID(NULL); Surf.LightInfo.light_level = strength; HWD.pfnMakeScreenTexture(scr_tex); - HWD.pfnSetShader(12); + HWD.pfnSetShader(HWR_GetShaderFromTarget(SHADER_UI_COLORMAP_FADE)); HWD.pfnDrawScreenTexture(scr_tex, &Surf, PF_ColorMapped|PF_NoDepthTest); HWD.pfnUnSetShader(); diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index a8d588e7c..df4d431f9 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -67,14 +67,13 @@ EXPORT void HWRAPI(RenderVhsEffect) (fixed_t upbary, fixed_t downbary, UINT8 upd EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]); // jimita -EXPORT boolean HWRAPI(LoadShaders) (void); -EXPORT void HWRAPI(KillShaders) (void); -EXPORT void HWRAPI(SetShader) (int shader); +EXPORT boolean HWRAPI(InitShaders) (void); +EXPORT void HWRAPI(LoadShader) (int slot, char *code, hwdshaderstage_t stage); +EXPORT boolean HWRAPI(CompileShader) (int slot); +EXPORT void HWRAPI(SetShader) (int slot); EXPORT void HWRAPI(UnSetShader) (void); EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value); -EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boolean fragment); -EXPORT boolean HWRAPI(InitCustomShaders) (void); EXPORT void HWRAPI(SetPaletteLookup)(UINT8 *lut); EXPORT UINT32 HWRAPI(CreateLightTable)(RGBA_t *hw_lighttable); @@ -118,14 +117,13 @@ struct hwdriver_s RenderSkyDome pfnRenderSkyDome; - LoadShaders pfnLoadShaders; - KillShaders pfnKillShaders; + InitShaders pfnInitShaders; + LoadShader pfnLoadShader; + CompileShader pfnCompileShader; SetShader pfnSetShader; UnSetShader pfnUnSetShader; SetShaderInfo pfnSetShaderInfo; - LoadCustomShader pfnLoadCustomShader; - InitCustomShaders pfnInitCustomShaders; SetPaletteLookup pfnSetPaletteLookup; CreateLightTable pfnCreateLightTable; diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 082a6a78c..9e565a8aa 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -95,4 +95,18 @@ void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, void HWR_RenderDrawNodes(void); +// -------- +// hw_shaders.c +// -------- +boolean HWR_InitShaders(void); +void HWR_CompileShaders(void); + +int HWR_GetShaderFromTarget(int shader_target); + +void HWR_LoadAllCustomShaders(void); +void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3); +const char *HWR_GetShaderName(INT32 shader); + +extern customshaderxlat_t shaderxlat[]; + #endif //_HW_GLOB_ \ No newline at end of file diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 38fa024b0..9ff5d563b 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -71,7 +71,7 @@ static boolean gr_palette_rendering_state = false; static void CV_filtermode_ONChange(void); static void CV_anisotropic_ONChange(void); static void CV_screentextures_ONChange(void); -static void CV_useCustomShaders_ONChange(void); +//static void CV_useCustomShaders_ONChange(void); static void CV_grshaders_OnChange(void); static void CV_grpaletterendering_OnChange(void); static void CV_grpalettedepth_OnChange(void); @@ -144,7 +144,7 @@ consvar_t cv_grscreentextures = {"gr_screentextures", "On", CV_CALL|CV_SAVE, CV_ CV_screentextures_ONChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grshaders = {"gr_shaders", "On", CV_CALL|CV_SAVE, CV_OnOff, CV_grshaders_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grusecustomshaders = {"gr_usecustomshaders", "Yes", CV_CALL|CV_SAVE, CV_OnOff, CV_useCustomShaders_ONChange, 0, NULL, NULL, 0, 0, NULL}; +//consvar_t cv_grusecustomshaders = {"gr_usecustomshaders", "Yes", CV_CALL|CV_SAVE, CV_OnOff, CV_useCustomShaders_ONChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grpaletterendering = {"gr_paletteshader", "Off", CV_CALL|CV_SAVE, CV_OnOff, CV_grpaletterendering_OnChange, 0, NULL, NULL, 0, 0, NULL}; @@ -195,18 +195,26 @@ static void CV_grshaders_OnChange(void) } } -static void CV_useCustomShaders_ONChange(void) // should we do a call to HWR_TogglePaletteRendering here aswell in pal rendering mode? +/*static void CV_useCustomShaders_ONChange(void) // should we do a call to HWR_TogglePaletteRendering here aswell in pal rendering mode? { ONLY_IF_GL_LOADED - if (HWR_UseShader()) - HWD.pfnInitCustomShaders(); -} + if (HWR_UseShader() && cv_grusecustomshaders.value) + { + HWR_LoadAllCustomShaders(); + HWR_CompileShaders(); + } + else if (HWR_UseShader() && !cv_grusecustomshaders.value) + HWR_CompileShaders(); +}*/ static void CV_grpaletterendering_OnChange(void) { ONLY_IF_GL_LOADED if (gr_shadersavailable) + { + HWR_CompileShaders(); HWR_TogglePaletteRendering(); + } } static void CV_grpalettedepth_OnChange(void) @@ -662,7 +670,7 @@ void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isc static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; - INT32 shader = 0; + INT32 shader = SHADER_NONE; // no convex poly were generated for this subsector if (!xsub->planepoly) @@ -840,11 +848,11 @@ void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isc if (HWR_UseShader()) { if (PolyFlags & PF_Fog) - shader = 6; // fog shader + shader = SHADER_FOG; // fog shader else if (PolyFlags & PF_Ripple) - shader = (HWR_ShouldUsePaletteRendering() ? 11 : 5); // water shader + shader = SHADER_WATER; // water shader else - shader = (HWR_ShouldUsePaletteRendering() ? 9 : 1); // floor shader + shader = SHADER_FLOOR; // floor shader PolyFlags |= PF_ColorMapped; } @@ -951,7 +959,7 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf) // seg bbox fixed_t segbbox[4]; - INT32 shader = 0; + INT32 shader = SHADER_NONE; M_ClearBox(segbbox); M_AddToBox(segbbox, @@ -1004,9 +1012,7 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf) } if (HWR_UseShader()) - { - shader = (HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader - } + shader = SHADER_WALL; // wall shader HWR_ProcessPolygon(&pSurf, wallVerts, 4, i|PF_Modulated|PF_Decal, shader, false); } @@ -1039,13 +1045,13 @@ FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf) // void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blendmode, INT32 lightlevel, extracolormap_t *wallcolormap) { - INT32 shader = 0; + INT32 shader = SHADER_NONE; HWR_Lighting(pSurf, lightlevel, wallcolormap); if (HWR_UseShader()) { - shader = (HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader + shader = SHADER_WALL; // wall shader blendmode |= PF_ColorMapped; } @@ -3133,7 +3139,7 @@ void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; - INT32 shader = 0; + INT32 shader = SHADER_NONE; nrPlaneVerts = polysector->numVertices; @@ -3279,7 +3285,7 @@ void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t if (HWR_UseShader()) { - shader = (HWR_ShouldUsePaletteRendering() ? 9 : 1); // floor shader + shader = SHADER_FLOOR; // floor shader blendmode |= PF_ColorMapped; } @@ -3939,7 +3945,7 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t fixed_t slopez; float offset = 0; - INT32 shader = 0; + INT32 shader = SHADER_NONE; R_GetShadowZ(spr->mobj, &floorslope); @@ -4090,7 +4096,7 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t if (HWR_UseShader()) { - shader = (HWR_ShouldUsePaletteRendering() ? 9 : 1); // floor shader + shader = SHADER_FLOOR; // floor shader } HWR_ProcessPolygon(&sSurf, swallVerts, 4, PF_Translucent|PF_Modulated, shader, false); @@ -4189,7 +4195,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) fixed_t v1x, v1y, v2x, v2y; #endif - INT32 shader = 0; + INT32 shader = SHADER_NONE; this_scale = FIXED_TO_FLOAT(spr->mobj->scale); @@ -4464,7 +4470,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) if (HWR_UseShader()) { - shader = (HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader + shader = SHADER_SPRITE; // sprite shader blend |= PF_ColorMapped; } @@ -4509,7 +4515,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) if (HWR_UseShader()) { - shader = (HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader + shader = SHADER_SPRITE; // sprite shader blend |= PF_ColorMapped; } @@ -4528,7 +4534,7 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) GLPatch_t *gpatch; // sprite patch converted to hardware FSurfaceInfo Surf; - INT32 shader = 0; + INT32 shader = SHADER_NONE; const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)( (spr->mobj->localskin) ? spr->mobj->localskin : spr->mobj->skin ))->flags & SF_HIRES); if (spr->mobj) @@ -4670,7 +4676,7 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) if (HWR_UseShader()) { - shader = (HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader + shader = SHADER_SPRITE; // sprite shader blend |= PF_ColorMapped; } @@ -4686,7 +4692,7 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) GLPatch_t *gpatch; // sprite patch converted to hardware FSurfaceInfo Surf; - INT32 shader = 0; + INT32 shader = SHADER_NONE; if (!spr->mobj) return; @@ -4771,7 +4777,7 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) if (HWR_UseShader()) { - shader = (HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader + shader = SHADER_SPRITE; // sprite shader blend |= PF_ColorMapped; } @@ -5802,9 +5808,9 @@ void HWR_DrawSkyBackground(float fpov) dometransform.splitscreen = splitscreen; HWR_GetTexture(texturetranslation[skytexture]); - HWD.pfnSetShader(7); // sky shader + if (HWR_UseShader()) + HWD.pfnSetShader(HWR_GetShaderFromTarget(SHADER_SKY));// sky shader HWD.pfnRenderSkyDome(skytexture, textures[skytexture]->width, textures[skytexture]->height, dometransform); - HWD.pfnSetShader(0); } @@ -6413,7 +6419,7 @@ void HWR_AddCommands(void) CV_RegisterVar(&cv_grshearing); CV_RegisterVar(&cv_grshaders); - CV_RegisterVar(&cv_grusecustomshaders); + //CV_RegisterVar(&cv_grusecustomshaders); CV_RegisterVar(&cv_grportals); CV_RegisterVar(&cv_nostencil); @@ -6445,7 +6451,10 @@ void HWR_Startup(void) HWD.pfnSetupGLInfo(); - gr_shadersavailable = HWD.pfnLoadShaders(); + gr_shadersavailable = HWR_InitShaders(); + + //if (cv_grusecustomshaders.value) + HWR_LoadAllCustomShaders(); HWR_SetShaderState(); HWR_TogglePaletteRendering(); @@ -6477,7 +6486,7 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, FBITFIELD blendmode = blend; UINT8 alpha = pSurf->PolyColor.s.alpha; // retain the alpha - INT32 shader = 0; + INT32 shader = SHADER_NONE; // Lighting is done here instead so that fog isn't drawn incorrectly on transparent walls after sorting HWR_Lighting(pSurf, lightlevel, wallcolormap); @@ -6490,7 +6499,7 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, if (fogwall) { blendmode |= PF_Fog; - shader = 6; // fog shader + shader = SHADER_FOG; // fog shader } blendmode |= PF_Modulated; // No PF_Occlude means overlapping (incorrect) transparency @@ -6499,7 +6508,7 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, { if (HWR_UseShader()) { - shader = (HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader + shader = SHADER_WALL; // wall shader blendmode |= PF_ColorMapped; } } @@ -6669,162 +6678,4 @@ void HWR_DrawScreenFinalTexture(int width, int height) { HWD.pfnDrawScreenFinalTexture(HWD_SCREENTEXTURE_GENERIC2, width, height); } - -// jimita 18032019 -typedef struct -{ - char type[16]; - INT32 id; -} shaderxlat_t; - -static inline UINT16 HWR_CheckShader(UINT16 wadnum) -{ - UINT16 i; - lumpinfo_t *lump_p; - - lump_p = wadfiles[wadnum]->lumpinfo; - for (i = 0; i < wadfiles[wadnum]->numlumps; i++, lump_p++) - if (memcmp(lump_p->name, "SHADERS", 7) == 0) - return i; - - return INT16_MAX; -} - -void HWR_LoadShaders(UINT16 wadnum, boolean PK3) -{ - UINT16 lump; - char *shaderdef, *line; - char *stoken; - char *value; - size_t size; - int linenum = 1; - int shadertype = 0; - int i; - - #define SHADER_TYPES 7 - shaderxlat_t shaderxlat[SHADER_TYPES] = - { - {"Flat", 1}, - {"WallTexture", 2}, - {"Sprite", 3}, - {"Model", 4}, - {"WaterRipple", 5}, - {"Fog", 6}, - {"Sky", 7}, - }; - - lump = HWR_CheckShader(wadnum); - if (lump == INT16_MAX) - return; - - shaderdef = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE); - size = W_LumpLengthPwad(wadnum, lump); - - line = Z_Malloc(size+1, PU_STATIC, NULL); - if (!line) - I_Error("HWR_LoadShaders: No more free memory\n"); - - M_Memcpy(line, shaderdef, size); - line[size] = '\0'; - - stoken = strtok(line, "\r\n "); - while (stoken) - { - if ((stoken[0] == '/' && stoken[1] == '/') - || (stoken[0] == '#'))// skip comments - { - stoken = strtok(NULL, "\r\n"); - goto skip_field; - } - - if (!stricmp(stoken, "GLSL")) - { - value = strtok(NULL, "\r\n "); - if (!value) - { - CONS_Alert(CONS_WARNING, "HWR_LoadShaders: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); - stoken = strtok(NULL, "\r\n"); // skip end of line - goto skip_lump; - } - - if (!stricmp(value, "VERTEX")) - shadertype = 1; - else if (!stricmp(value, "FRAGMENT")) - shadertype = 2; - -skip_lump: - stoken = strtok(NULL, "\r\n "); - linenum++; - } - else - { - value = strtok(NULL, "\r\n= "); - if (!value) - { - CONS_Alert(CONS_WARNING, "HWR_LoadShaders: Missing shader target (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); - stoken = strtok(NULL, "\r\n"); // skip end of line - goto skip_field; - } - - if (!shadertype) - { - CONS_Alert(CONS_ERROR, "HWR_LoadShaders: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); - Z_Free(line); - return; - } - - for (i = 0; i < SHADER_TYPES; i++) - { - if (!stricmp(shaderxlat[i].type, stoken)) - { - size_t shader_size; - char *shader_source; - char *shader_lumpname; - UINT16 shader_lumpnum; - - if (PK3) - { - shader_lumpname = Z_Malloc(strlen(value) + 12, PU_STATIC, NULL); - strcpy(shader_lumpname, "Shaders/sh_"); - strcat(shader_lumpname, value); - shader_lumpnum = W_CheckNumForFullNamePK3(shader_lumpname, wadnum, 0); - } - else - { - shader_lumpname = Z_Malloc(strlen(value) + 4, PU_STATIC, NULL); - strcpy(shader_lumpname, "SH_"); - strcat(shader_lumpname, value); - shader_lumpnum = W_CheckNumForNamePwad(shader_lumpname, wadnum, 0); - } - - if (shader_lumpnum == INT16_MAX) - { - CONS_Alert(CONS_ERROR, "HWR_LoadShaders: Missing shader source %s (file %s, line %d)\n", shader_lumpname, wadfiles[wadnum]->filename, linenum); - Z_Free(shader_lumpname); - continue; - } - - shader_size = W_LumpLengthPwad(wadnum, shader_lumpnum); - shader_source = Z_Malloc(shader_size, PU_STATIC, NULL); - W_ReadLumpPwad(wadnum, shader_lumpnum, shader_source); - - HWD.pfnLoadCustomShader(shaderxlat[i].id, shader_source, shader_size, (shadertype == 2)); - - Z_Free(shader_source); - Z_Free(shader_lumpname); - } - } - -skip_field: - stoken = strtok(NULL, "\r\n= "); - linenum++; - } - } - - HWD.pfnInitCustomShaders(); - - Z_Free(line); - return; -} - #endif // HWRENDER diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index b98bc0893..cf77942fc 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -85,7 +85,6 @@ boolean HWR_Screenshot(const char *lbmname); // hw_main.c void HWR_RenderFrame(INT32 viewnumber, player_t *player, boolean skybox); void HWR_RenderPlayerView(INT32 viewnumber, player_t *player); -void HWR_LoadShaders(UINT16 wadnum, boolean PK3); void HWR_SetViewSize(void); void HWR_AddCommands(void); void HWR_SetTransform(float fpov, player_t *player); @@ -192,7 +191,7 @@ extern consvar_t cv_grhorizonlines; extern consvar_t cv_grfallbackplayermodel; extern consvar_t cv_grbatching; extern consvar_t cv_grrenderdistance; -extern consvar_t cv_grusecustomshaders; +//extern consvar_t cv_grusecustomshaders; extern consvar_t cv_grpaletterendering; extern consvar_t cv_grpalettedepth; extern consvar_t cv_grflashpal; diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 2a581b489..c64d77639 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1458,7 +1458,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) p.mirror = atransform.mirror; // from Kart #endif - HWD.pfnSetShader(4); // model shader + HWD.pfnSetShader(SHADER_MODEL); // model shader { SINT8 flipfactor = flip ? -1 : 1; diff --git a/src/hardware/hw_shaders.c b/src/hardware/hw_shaders.c new file mode 100644 index 000000000..5840e8cd1 --- /dev/null +++ b/src/hardware/hw_shaders.c @@ -0,0 +1,884 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2021 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file hw_shaders.h +/// \brief Handles the shaders used by the game. + +#ifdef HWRENDER + +#include "hw_main.h" +#include "hw_glob.h" +#include "hw_drv.h" +#include "../z_zone.h" + +// ================ +// 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" + +// ================== +// 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 +// + +// Include GLSL_FLOOR_FUDGES or GLSL_WALL_FUDGES or define the fudges in shaders that use this macro. +#define GLSL_DOOM_COLORMAP \ + "float R_DoomColormap(float light, float z)\n" \ + "{\n" \ + "float lightnum = clamp(light / 17.0, 0.0, 15.0);\n" \ + "float lightz = clamp(z / 16.0, 0.0, 127.0);\n" \ + "float startmap = (15.0 - lightnum) * 4.0;\n" \ + "float scale = 160.0 / (lightz + 1.0);\n" \ + "float cap = (155.0 - light) * 0.26;\n" \ + "return max(startmap * STARTMAP_FUDGE - scale * 0.5 * SCALE_FUDGE, cap);\n" \ + "}\n" +// lighting cap adjustment: +// first num (155.0), increase to make it start to go dark sooner +// second num (0.26), increase to make it go dark faster + +#define GLSL_DOOM_LIGHT_EQUATION \ + "float R_DoomLightingEquation(float light)\n" \ + "{\n" \ + "float z = gl_FragCoord.z / gl_FragCoord.w;\n" \ + "float colormap = floor(R_DoomColormap(light, z)) + 0.5;\n" \ + "return clamp(colormap, 0.0, 31.0) / 32.0;\n" \ + "}\n" + +#define GLSL_SOFTWARE_TINT_EQUATION \ + "if (tint_color.a > 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" \ + "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" \ + "}\n" + +#define GLSL_SOFTWARE_FADE_EQUATION \ + "float darkness = R_DoomLightingEquation(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" \ + "float fd = fe - fs;\n" \ + "darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \ + "}\n" \ + "final_color = mix(final_color, fade_color, darkness);\n" + +#define GLSL_PALETTE_RENDERING \ + "float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \ + "float z = gl_FragCoord.z / gl_FragCoord.w;\n" \ + "float light_y = clamp(floor(R_DoomColormap(lighting, z)), 0.0, 31.0);\n" \ + "vec2 lighttable_coord = vec2((tex_pal_idx + 0.5) / 256.0, (light_y + 0.5) / 32.0);\n" \ + "vec4 final_color = texture2D(lighttable_tex, lighttable_coord);\n" \ + "final_color.a = texel.a * poly_color.a;\n" \ + "gl_FragColor = final_color;\n" \ + +#define GLSL_SOFTWARE_FRAGMENT_SHADER \ + "#ifdef SRB2_PALETTE_RENDERING\n" \ + "uniform sampler2D tex;\n" \ + "uniform sampler3D palette_lookup_tex;\n" \ + "uniform sampler2D lighttable_tex;\n" \ + "uniform vec4 poly_color;\n" \ + "uniform float lighting;\n" \ + GLSL_DOOM_COLORMAP \ + "void main(void) {\n" \ + "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ + GLSL_PALETTE_RENDERING \ + "}\n" \ + "#else\n" \ + "uniform sampler2D tex;\n" \ + "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 \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ + "vec4 base_color = texel * poly_color;\n" \ + "vec4 final_color = base_color;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "final_color.a = texel.a * poly_color.a;\n" \ + "gl_FragColor = final_color;\n" \ + "}\n" \ + "#endif\0" + +// hand tuned adjustments for light level calculation +#define GLSL_FLOOR_FUDGES \ + "#define STARTMAP_FUDGE 1.06\n" \ + "#define SCALE_FUDGE 1.15\n" + +#define GLSL_WALL_FUDGES \ + "#define STARTMAP_FUDGE 1.05\n" \ + "#define SCALE_FUDGE 2.2\n" + +#define GLSL_FLOOR_FRAGMENT_SHADER \ + GLSL_FLOOR_FUDGES \ + GLSL_SOFTWARE_FRAGMENT_SHADER + +#define GLSL_WALL_FRAGMENT_SHADER \ + GLSL_WALL_FUDGES \ + GLSL_SOFTWARE_FRAGMENT_SHADER + +// +// Water surface shader +// +// Mostly guesstimated, rather than the rest being built off Software science. +// Still needs to distort things underneath/around the water... +// + +#define GLSL_WATER_TEXEL \ + "float water_z = (gl_FragCoord.z / gl_FragCoord.w) / 2.0;\n" \ + "float a = -pi * (water_z * freq) + (leveltime * speed);\n" \ + "float sdistort = sin(a) * amp;\n" \ + "float cdistort = cos(a) * amp;\n" \ + "vec4 texel = texture2D(tex, vec2(gl_TexCoord[0].s - sdistort, gl_TexCoord[0].t - cdistort));\n" + +#define GLSL_WATER_FRAGMENT_SHADER \ + GLSL_FLOOR_FUDGES \ + "const float freq = 0.025;\n" \ + "const float amp = 0.025;\n" \ + "const float speed = 2.0;\n" \ + "const float pi = 3.14159;\n" \ + "#ifdef SRB2_PALETTE_RENDERING\n" \ + "uniform sampler2D tex;\n" \ + "uniform sampler3D palette_lookup_tex;\n" \ + "uniform sampler2D lighttable_tex;\n" \ + "uniform vec4 poly_color;\n" \ + "uniform float lighting;\n" \ + "uniform float leveltime;\n" \ + GLSL_DOOM_COLORMAP \ + "void main(void) {\n" \ + GLSL_WATER_TEXEL \ + GLSL_PALETTE_RENDERING \ + "}\n" \ + "#else\n" \ + "uniform sampler2D tex;\n" \ + "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" \ + "uniform float leveltime;\n" \ + GLSL_DOOM_COLORMAP \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + GLSL_WATER_TEXEL \ + "vec4 base_color = texel * poly_color;\n" \ + "vec4 final_color = base_color;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "final_color.a = texel.a * poly_color.a;\n" \ + "gl_FragColor = final_color;\n" \ + "}\n" \ + "#endif\0" + +// +// Fog block shader +// +// Alpha of the planes themselves are still slightly off -- see HWR_FogBlockAlpha +// + +// The floor fudges are used, but should the wall fudges be used instead? or something inbetween? +// or separate values for floors and walls? (need to change more than this shader for that) +#define GLSL_FOG_FRAGMENT_SHADER \ + GLSL_FLOOR_FUDGES \ + "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 \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + "vec4 base_color = gl_Color;\n" \ + "vec4 final_color = base_color;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "gl_FragColor = final_color;\n" \ + "}\0" + +// +// Sky fragment shader +// Modulates poly_color with gl_Color +// +#define GLSL_SKY_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform vec4 poly_color;\n" \ + "void main(void) {\n" \ + "gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * gl_Color * poly_color;\n" \ + "}\0" + +// Shader for the palette rendering postprocess step +#define GLSL_PALETTE_POSTPROCESS_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform sampler3D palette_lookup_tex;\n" \ + "uniform sampler1D palette_tex;\n" \ + "void main(void) {\n" \ + "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ + "float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \ + "float palette_coord = (tex_pal_idx + 0.5) / 256.0;\n" \ + "vec4 final_color = texture1D(palette_tex, palette_coord);\n" \ + "gl_FragColor = final_color;\n" \ + "}\0" + +#define GLSL_UI_COLORMAP_FADE_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform float lighting;\n" \ + "uniform sampler3D palette_lookup_tex;\n" \ + "uniform sampler2D lighttable_tex;\n" \ + "void main(void) {\n" \ + "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ + "float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \ + "vec2 lighttable_coord = vec2((tex_pal_idx + 0.5) / 256.0, (lighting + 0.5) / 32.0);\n" \ + "gl_FragColor = texture2D(lighttable_tex, lighttable_coord);\n" \ + "}\0" \ + +// ================ +// Shader sources +// ================ + +static struct { + const char *vertex; + const char *fragment; +} const gl_shadersources[] = { + + // Floor shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_FLOOR_FRAGMENT_SHADER}, + + // Wall shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_WALL_FRAGMENT_SHADER}, + + // Sprite shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_WALL_FRAGMENT_SHADER}, + + // Model shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_WALL_FRAGMENT_SHADER}, + + // Water shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_WATER_FRAGMENT_SHADER}, + + // Fog shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_FOG_FRAGMENT_SHADER}, + + // Sky shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SKY_FRAGMENT_SHADER}, + + // Palette postprocess shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_PALETTE_POSTPROCESS_FRAGMENT_SHADER}, + + // UI colormap fade shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_UI_COLORMAP_FADE_FRAGMENT_SHADER}, + + {NULL, NULL}, +}; + +typedef struct +{ + int base_shader; // index of base shader_t + int custom_shader; // index of custom shader_t +} shadertarget_t; + +typedef struct +{ + char *vertex; + char *fragment; + boolean compiled; +} shader_t; // these are in an array and accessed by indices + +// the array has NUMSHADERTARGETS entries for base shaders and for custom shaders +// the array could be expanded in the future to fit "dynamic" custom shaders that +// aren't fixed to shader targets +static shader_t gl_shaders[NUMSHADERTARGETS*2]; + +static shadertarget_t gl_shadertargets[NUMSHADERTARGETS]; + +#define WHITESPACE_CHARS " \t" + +#define PALETTE_RENDERING_DEFINE "#define SRB2_PALETTE_RENDERING" + +// Initialize shader variables and the backend's shader system. Load the base shaders. +// Returns false if shaders cannot be used. +boolean HWR_InitShaders(void) +{ + int i; + + if (!HWD.pfnInitShaders()) + return false; + + for (i = 0; i < NUMSHADERTARGETS; i++) + { + // set up string pointers for base shaders + gl_shaders[i].vertex = Z_StrDup(gl_shadersources[i].vertex); + gl_shaders[i].fragment = Z_StrDup(gl_shadersources[i].fragment); + // set shader target indices to correct values + gl_shadertargets[i].base_shader = i; + gl_shadertargets[i].custom_shader = -1; + } + + HWR_CompileShaders(); + + return true; +} + +// helper function: strstr but returns an int with the substring position +// returns INT32_MAX if not found +static INT32 strstr_int(const char *str1, const char *str2) +{ + char *location = strstr(str1, str2); + if (location) + return location - str1; + else + return INT32_MAX; +} + +// Creates a preprocessed copy of the shader according to the current graphics settings +// Returns a pointer to the results on success and NULL on failure. +// Remember memory management of the returned string. +static char *HWR_PreprocessShader(char *original) +{ + const char *line_ending = "\n"; + int line_ending_len; + char *read_pos = original; + int original_len = strlen(original); + int distance_to_end = original_len; + int new_len; + char *new_shader; + char *write_pos; + char shader_glsl_version[3]; + int version_pos = -1; + int version_len = 0; + + if (strstr(original, "\r\n")) + { + line_ending = "\r\n"; + // check if all line endings are same + while ((read_pos = strchr(read_pos, '\n'))) + { + read_pos--; + if (*read_pos != '\r') + { + // this file contains mixed CRLF and LF line endings. + // treating it as a LF file during parsing should keep + // the results sane enough as long as the gpu driver is fine + // with these kinds of weirdly formatted shader sources. + line_ending = "\n"; + break; + } + read_pos += 2; + } + read_pos = original; + } + + line_ending_len = strlen(line_ending); + + // Find the #version directive, if it exists. Also don't get fooled if it's + // inside a comment. Copy the version digits so they can be used in the preamble. + // Time for some string parsing :D + +#define STARTSWITH(str, with_what) !strncmp(str, with_what, sizeof(with_what)-1) +#define ADVANCE(amount) read_pos += (amount); distance_to_end -= (amount); + while (true) + { + // we're at the start of a line or at the end of a block comment. + // first get any possible whitespace out of the way + int whitespace_len = strspn(read_pos, WHITESPACE_CHARS); + if (whitespace_len == distance_to_end) + break; // we got to the end + ADVANCE(whitespace_len) + + if (STARTSWITH(read_pos, "#version")) + { + // found a version directive (and it's not inside a comment) + // now locate, verify and read the version number + int version_number_len; + version_pos = read_pos - original; + ADVANCE(sizeof("#version") - 1) + whitespace_len = strspn(read_pos, WHITESPACE_CHARS); + if (!whitespace_len) + { + CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Syntax error in #version. Expected space after #version, but got other text.\n"); + return NULL; + } + else if (whitespace_len == distance_to_end) + { + CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Syntax error in #version. Expected version number, but got end of file.\n"); + return NULL; + } + ADVANCE(whitespace_len) + version_number_len = strspn(read_pos, "0123456789"); + if (!version_number_len) + { + CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Syntax error in #version. Expected version number, but got other text.\n"); + return NULL; + } + else if (version_number_len != 3) + { + CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Syntax error in #version. Expected version with 3 digits, but got %d digits.\n", version_number_len); + return NULL; + } + M_Memcpy(shader_glsl_version, read_pos, 3); + ADVANCE(version_number_len) + version_len = (read_pos - original) - version_pos; + whitespace_len = strspn(read_pos, WHITESPACE_CHARS); + ADVANCE(whitespace_len) + if (STARTSWITH(read_pos, "es")) + { + CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Support for ES shaders is not implemented.\n"); + return NULL; + } + break; + } + else + { + // go to next newline or end of next block comment if it starts before the newline + // and is not inside a line comment + INT32 newline_pos = strstr_int(read_pos, line_ending); + INT32 line_comment_pos; + INT32 block_comment_pos; + // optimization: temporarily put a null at the line ending, so strstr does not needlessly + // look past it since we're only interested in the current line + if (newline_pos != INT32_MAX) + read_pos[newline_pos] = '\0'; + line_comment_pos = strstr_int(read_pos, "//"); + block_comment_pos = strstr_int(read_pos, "/*"); + // restore the line ending, remove the null we just put there + if (newline_pos != INT32_MAX) + read_pos[newline_pos] = line_ending[0]; + if (line_comment_pos < block_comment_pos) + { + // line comment found, skip rest of the line + if (newline_pos != INT32_MAX) + { + ADVANCE(newline_pos + line_ending_len) + } + else + { + // we got to the end + break; + } + } + else if (block_comment_pos < line_comment_pos) + { + // block comment found, skip past it + INT32 block_comment_end; + ADVANCE(block_comment_pos + 2) + block_comment_end = strstr_int(read_pos, "*/"); + if (block_comment_end == INT32_MAX) + { + // could also leave insertion_pos at 0 and let the GLSL compiler + // output an error message for this broken comment + CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Encountered unclosed block comment in shader.\n"); + return NULL; + } + ADVANCE(block_comment_end + 2) + } + else if (newline_pos == INT32_MAX) + { + // we got to the end + break; + } + else + { + // nothing special on this line, move to the next one + ADVANCE(newline_pos + line_ending_len) + } + } + } +#undef STARTSWITH +#undef ADVANCE + +#define ADD_TO_LEN(def) new_len += sizeof(def) - 1 + line_ending_len; + + // Calculate length of modified shader. + new_len = original_len; + + if (cv_grpaletterendering.value) + ADD_TO_LEN(PALETTE_RENDERING_DEFINE) + +#undef ADD_TO_LEN + +#define VERSION_PART "#version " + + if (new_len != original_len) + { + if (version_pos != -1) + new_len += sizeof(VERSION_PART) - 1 + 3 + line_ending_len; + new_len += sizeof("#line 0") - 1 + line_ending_len; + } + + // Allocate memory for modified shader. + new_shader = Z_Malloc(new_len + 1, PU_STATIC, NULL); + + read_pos = original; + write_pos = new_shader; + + if (new_len != original_len && version_pos != -1) + { + strcpy(write_pos, VERSION_PART); + write_pos += sizeof(VERSION_PART) - 1; + M_Memcpy(write_pos, shader_glsl_version, 3); + write_pos += 3; + strcpy(write_pos, line_ending); + write_pos += line_ending_len; + } + +#undef VERSION_PART + +#define WRITE_DEFINE(define) \ + { \ + strcpy(write_pos, define); \ + write_pos += sizeof(define) - 1; \ + strcpy(write_pos, line_ending); \ + write_pos += line_ending_len; \ + } + + // Write the defines. + if (cv_grpaletterendering.value) + WRITE_DEFINE(PALETTE_RENDERING_DEFINE) + +#undef WRITE_DEFINE + + // Write a #line directive, so compiler errors will report line numbers from the + // original shader without our preamble lines. + if (new_len != original_len) + { + // line numbering in the #line directive is different for versions 110-150 + if (version_pos == -1 || shader_glsl_version[0] == '1') + strcpy(write_pos, "#line 0"); + else + strcpy(write_pos, "#line 1"); + write_pos += sizeof("#line 0") - 1; + strcpy(write_pos, line_ending); + write_pos += line_ending_len; + } + + // Copy the original shader. + M_Memcpy(write_pos, read_pos, original_len); + + // Erase the original #version directive, if it exists and was copied. + if (new_len != original_len && version_pos != -1) + memset(write_pos + version_pos, ' ', version_len); + + // Terminate the new string. + new_shader[new_len] = '\0'; + + return new_shader; +} + +// preprocess and compile shader at gl_shaders[index] +static void HWR_CompileShader(int index) +{ + char *vertex_source = gl_shaders[index].vertex; + char *fragment_source = gl_shaders[index].fragment; + + if (vertex_source) + { + char *preprocessed = HWR_PreprocessShader(vertex_source); + if (!preprocessed) return; + HWD.pfnLoadShader(index, preprocessed, HWD_SHADERSTAGE_VERTEX); + } + if (fragment_source) + { + char *preprocessed = HWR_PreprocessShader(fragment_source); + if (!preprocessed) return; + HWD.pfnLoadShader(index, preprocessed, HWD_SHADERSTAGE_FRAGMENT); + } + + gl_shaders[index].compiled = HWD.pfnCompileShader(index); +} + +// compile or recompile shaders +void HWR_CompileShaders(void) +{ + int i; + + for (i = 0; i < NUMSHADERTARGETS; i++) + { + int custom_index = gl_shadertargets[i].custom_shader; + HWR_CompileShader(i); + if (!gl_shaders[i].compiled) + CONS_Alert(CONS_ERROR, "HWR_CompileShaders: Compilation failed for base %s shader!\n", shaderxlat[i].type); + if (custom_index != -1) + { + HWR_CompileShader(custom_index); + if (!gl_shaders[custom_index].compiled) + CONS_Alert(CONS_ERROR, "HWR_CompileShaders: Recompilation failed for the custom %s shader! See the console messages above for more information.\n", shaderxlat[i].type); + } + } +} + +int HWR_GetShaderFromTarget(int shader_target) +{ + int custom_shader = gl_shadertargets[shader_target].custom_shader; + // use custom shader if following are true + // - custom shader exists + // - custom shader has been compiled successfully + // - custom shaders are enabled + // - custom shaders are allowed by the server + if (custom_shader != -1 && gl_shaders[custom_shader].compiled && + cv_grshaders.value) + return custom_shader; + else + return gl_shadertargets[shader_target].base_shader; +} + +static inline UINT16 HWR_FindShaderDefs(UINT16 wadnum) +{ + UINT16 i; + lumpinfo_t *lump_p; + + lump_p = wadfiles[wadnum]->lumpinfo; + for (i = 0; i < wadfiles[wadnum]->numlumps; i++, lump_p++) + if (memcmp(lump_p->name, "SHADERS", 7) == 0) + return i; + + return INT16_MAX; +} + +customshaderxlat_t shaderxlat[] = +{ + {"Flat", SHADER_FLOOR}, + {"WallTexture", SHADER_WALL}, + {"Sprite", SHADER_SPRITE}, + {"Model", SHADER_MODEL}, + {"WaterRipple", SHADER_WATER}, + {"Fog", SHADER_FOG}, + {"Sky", SHADER_SKY}, + {"PalettePostprocess", SHADER_PALETTE_POSTPROCESS}, + {"UIColormapFade", SHADER_UI_COLORMAP_FADE}, + {NULL, 0}, +}; + +void HWR_LoadAllCustomShaders(void) +{ + INT32 i; + + // read every custom shader + for (i = 0; i < numwadfiles; i++) + HWR_LoadCustomShadersFromFile(i, (wadfiles[i]->type == RET_PK3)); +} + +void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3) +{ + UINT16 lump; + char *shaderdef, *line; + char *stoken; + char *value; + size_t size; + int linenum = 1; + int shadertype = 0; + int i; + boolean modified_shaders[NUMSHADERTARGETS] = {0}; + + if (!HWR_UseShader()) + return; + + //if (!cv_grusecustomshaders.value) + //return; + + lump = HWR_FindShaderDefs(wadnum); + if (lump == INT16_MAX) + return; + + shaderdef = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE); + size = W_LumpLengthPwad(wadnum, lump); + + line = Z_Malloc(size+1, PU_STATIC, NULL); + M_Memcpy(line, shaderdef, size); + line[size] = '\0'; + + stoken = strtok(line, "\r\n "); + while (stoken) + { + if ((stoken[0] == '/' && stoken[1] == '/') + || (stoken[0] == '#'))// skip comments + { + stoken = strtok(NULL, "\r\n"); + goto skip_field; + } + + if (!stricmp(stoken, "GLSL")) + { + value = strtok(NULL, "\r\n "); + if (!value) + { + CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); + stoken = strtok(NULL, "\r\n"); // skip end of line + goto skip_lump; + } + + if (!stricmp(value, "VERTEX")) + shadertype = 1; + else if (!stricmp(value, "FRAGMENT")) + shadertype = 2; + +skip_lump: + stoken = strtok(NULL, "\r\n "); + linenum++; + } + else + { + value = strtok(NULL, "\r\n= "); + if (!value) + { + CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: Missing shader target (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); + stoken = strtok(NULL, "\r\n"); // skip end of line + goto skip_field; + } + + if (!shadertype) + { + CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); + Z_Free(line); + return; + } + + for (i = 0; shaderxlat[i].type; i++) + { + if (!stricmp(shaderxlat[i].type, stoken)) + { + size_t shader_string_length; + char *shader_source; + char *shader_lumpname; + UINT16 shader_lumpnum; + int shader_index; // index in gl_shaders + + if (PK3) + { + shader_lumpname = Z_Malloc(strlen(value) + 12, PU_STATIC, NULL); + strcpy(shader_lumpname, "Shaders/sh_"); + strcat(shader_lumpname, value); + shader_lumpnum = W_CheckNumForFullNamePK3(shader_lumpname, wadnum, 0); + } + else + { + shader_lumpname = Z_Malloc(strlen(value) + 4, PU_STATIC, NULL); + strcpy(shader_lumpname, "SH_"); + strcat(shader_lumpname, value); + shader_lumpnum = W_CheckNumForNamePwad(shader_lumpname, wadnum, 0); + } + + if (shader_lumpnum == INT16_MAX) + { + CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: Missing shader source %s (file %s, line %d)\n", shader_lumpname, wadfiles[wadnum]->filename, linenum); + Z_Free(shader_lumpname); + continue; + } + + shader_string_length = W_LumpLengthPwad(wadnum, shader_lumpnum) + 1; + shader_source = Z_Malloc(shader_string_length, PU_STATIC, NULL); + W_ReadLumpPwad(wadnum, shader_lumpnum, shader_source); + shader_source[shader_string_length-1] = '\0'; + + shader_index = shaderxlat[i].id + NUMSHADERTARGETS; + if (!modified_shaders[shaderxlat[i].id]) + { + // this will clear any old custom shaders from previously loaded files + // Z_Free checks if the pointer is NULL! + Z_Free(gl_shaders[shader_index].vertex); + gl_shaders[shader_index].vertex = NULL; + Z_Free(gl_shaders[shader_index].fragment); + gl_shaders[shader_index].fragment = NULL; + } + modified_shaders[shaderxlat[i].id] = true; + + if (shadertype == 1) + { + if (gl_shaders[shader_index].vertex) + { + CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: %s is overwriting another %s vertex shader from the same addon! (file %s, line %d)\n", shader_lumpname, shaderxlat[i].type, wadfiles[wadnum]->filename, linenum); + Z_Free(gl_shaders[shader_index].vertex); + } + gl_shaders[shader_index].vertex = shader_source; + } + else + { + if (gl_shaders[shader_index].fragment) + { + CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: %s is overwriting another %s fragment shader from the same addon! (file %s, line %d)\n", shader_lumpname, shaderxlat[i].type, wadfiles[wadnum]->filename, linenum); + Z_Free(gl_shaders[shader_index].fragment); + } + gl_shaders[shader_index].fragment = shader_source; + } + + Z_Free(shader_lumpname); + } + } + +skip_field: + stoken = strtok(NULL, "\r\n= "); + linenum++; + } + } + + for (i = 0; i < NUMSHADERTARGETS; i++) + { + if (modified_shaders[i]) + { + int shader_index = i + NUMSHADERTARGETS; // index to gl_shaders + gl_shadertargets[i].custom_shader = shader_index; + // if only one stage (vertex/fragment) is defined, the other one + // is copied from the base shaders. + if (!gl_shaders[shader_index].fragment) + gl_shaders[shader_index].fragment = Z_StrDup(gl_shadersources[i].fragment); + if (!gl_shaders[shader_index].vertex) + gl_shaders[shader_index].vertex = Z_StrDup(gl_shadersources[i].vertex); + HWR_CompileShader(shader_index); + if (!gl_shaders[shader_index].compiled) + CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: A compilation error occured for the %s shader in file %s. See the console messages above for more information.\n", shaderxlat[i].type, wadfiles[wadnum]->filename); + } + } + + Z_Free(line); + return; +} + +const char *HWR_GetShaderName(INT32 shader) +{ + INT32 i; + + for (i = 0; shaderxlat[i].type; i++) + { + if (shaderxlat[i].id == shader) + return shaderxlat[i].type; + } + + return "Unknown"; +} + +#endif // HWRENDER diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 26073bbeb..8637dcf09 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -126,11 +126,6 @@ static GLint viewport[4]; // can know when the textures aren't there, as textures are always considered resident in their virtual memory static GLuint screenTextures[NUMSCREENTEXTURES] = {0}; -// Lactozilla: Set shader programs and uniforms -static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade); - -static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; - // shortcut for ((float)1/i) static const GLfloat byte2float[256] = { 0.000000f, 0.003922f, 0.007843f, 0.011765f, 0.015686f, 0.019608f, 0.023529f, 0.027451f, @@ -593,6 +588,7 @@ typedef void (APIENTRY *PFNglGetShaderiv) (GLuint, GLenum, GLint*); typedef void (APIENTRY *PFNglGetShaderInfoLog) (GLuint, GLsizei, GLsizei*, GLchar*); typedef void (APIENTRY *PFNglDeleteShader) (GLuint); typedef GLuint (APIENTRY *PFNglCreateProgram) (void); +typedef void (APIENTRY *PFNglDeleteProgram) (GLuint); typedef void (APIENTRY *PFNglAttachShader) (GLuint, GLuint); typedef void (APIENTRY *PFNglLinkProgram) (GLuint); typedef void (APIENTRY *PFNglGetProgramiv) (GLuint, GLenum, GLint*); @@ -614,6 +610,7 @@ static PFNglGetShaderiv pglGetShaderiv; static PFNglGetShaderInfoLog pglGetShaderInfoLog; static PFNglDeleteShader pglDeleteShader; static PFNglCreateProgram pglCreateProgram; +static PFNglDeleteProgram pglDeleteProgram; static PFNglAttachShader pglAttachShader; static PFNglLinkProgram pglLinkProgram; static PFNglGetProgramiv pglGetProgramiv; @@ -628,19 +625,9 @@ static PFNglUniform2fv pglUniform2fv; static PFNglUniform3fv pglUniform3fv; static PFNglGetUniformLocation pglGetUniformLocation; -#define MAXSHADERS 16 -#define MAXSHADERPROGRAMS 16 - // 18032019 -static char *gl_customvertexshaders[MAXSHADERS]; -static char *gl_customfragmentshaders[MAXSHADERS]; - -static boolean gl_allowshaders = false; static boolean gl_shadersenabled = false; -static GLuint gl_currentshaderprogram = 0; -static boolean gl_shaderprogramchanged = true; - -static boolean gl_batching = false;// are we currently collecting batches? +static INT32 gl_allowshaders = 0; static INT32 gl_enable_screen_textures = 1; @@ -670,334 +657,41 @@ typedef enum gluniform_max, } gluniform_t; -typedef struct gl_shaderprogram_s +typedef struct gl_shader_s { + char *vertex_shader; + char *fragment_shader; GLuint program; - boolean custom; GLint uniforms[gluniform_max+1]; -} gl_shaderprogram_t; -static gl_shaderprogram_t gl_shaderprograms[MAXSHADERPROGRAMS]; +} gl_shader_t; + +static gl_shader_t gl_shaders[HWR_MAXSHADERS]; +static gl_shader_t gl_fallback_shader; + +// 09102020 +typedef struct gl_shaderstate_s +{ + gl_shader_t *current; + GLuint type; + GLuint program; + boolean changed; +} gl_shaderstate_t; +static gl_shaderstate_t gl_shaderstate; // Shader info static float shader_leveltime = 0; -// ======================== -// Fragment shader macros -// ======================== +// Lactozilla: Shader functions +static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i); +static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade); + +static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; // -// GLSL generic fragment shader +// Generic vertex 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" - -// -// GLSL Software fragment shader -// - -#define GLSL_DOOM_COLORMAP \ - "float R_DoomColormap(float light, float z)\n" \ - "{\n" \ - "float lightnum = clamp(light / 17.0, 0.0, 15.0);\n" \ - "float lightz = clamp(z / 16.0, 0.0, 127.0);\n" \ - "float startmap = (15.0 - lightnum) * 4.0;\n" \ - "float scale = 160.0 / (lightz + 1.0);\n" \ - "float cap = (155.0 - light) * 0.26;\n" \ - "return max(startmap * STARTMAP_FUDGE - scale * 0.5 * SCALE_FUDGE, cap);\n" \ - "}\n" - -#define GLSL_DOOM_LIGHT_EQUATION \ - "float R_DoomLightingEquation(float light)\n" \ - "{\n" \ - "float z = gl_FragCoord.z / gl_FragCoord.w;\n" \ - "float colormap = floor(R_DoomColormap(light, z)) + 0.5;\n" \ - "return clamp(colormap, 0.0, 31.0) / 32.0;\n" \ - "}\n" - -#define GLSL_SOFTWARE_TINT_EQUATION \ - "if (tint_color.a > 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" \ - "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" \ - "}\n" - -#define GLSL_SOFTWARE_FADE_EQUATION \ - "float darkness = R_DoomLightingEquation(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" \ - "float fd = fe - fs;\n" \ - "darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \ - "}\n" \ - "final_color = mix(final_color, fade_color, darkness);\n" - -#define GLSL_SOFTWARE_UNIFORMS \ - "uniform sampler2D tex;\n" \ - "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" - -#define GLSL_SOFTWARE_MAIN \ - "void main(void) {\n" \ - "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ - "vec4 base_color = texel * poly_color;\n" \ - "vec4 final_color = base_color;\n" \ - GLSL_SOFTWARE_TINT_EQUATION \ - GLSL_SOFTWARE_FADE_EQUATION \ - "final_color.a = texel.a * poly_color.a;\n" \ - "gl_FragColor = final_color;\n" \ - "}\n" - -// hand tuned adjustments for light level calculation -// do those even work correctly without the preprocessor? -#define GLSL_FLOOR_FUDGES \ - "#define STARTMAP_FUDGE 1.06\n" \ - "#define SCALE_FUDGE 1.15\n" - -#define GLSL_WALL_FUDGES \ - "#define STARTMAP_FUDGE 1.05\n" \ - "#define SCALE_FUDGE 2.2\n" - -#define GLSL_SOFTWARE_FRAGMENT_SHADER_FLOORS \ - GLSL_SOFTWARE_UNIFORMS \ - GLSL_FLOOR_FUDGES \ - GLSL_DOOM_COLORMAP \ - GLSL_DOOM_LIGHT_EQUATION \ - GLSL_SOFTWARE_MAIN \ - "\0" - -#define GLSL_SOFTWARE_FRAGMENT_SHADER_WALLS \ - GLSL_SOFTWARE_UNIFORMS \ - GLSL_WALL_FUDGES \ - GLSL_DOOM_COLORMAP \ - GLSL_DOOM_LIGHT_EQUATION \ - GLSL_SOFTWARE_MAIN \ - "\0" - -#define GLSL_SOFTWARE_PAL_UNIFORMS \ - "uniform sampler2D tex;\n" \ - "uniform sampler3D palette_lookup_tex;\n" \ - "uniform sampler2D lighttable_tex;\n" \ - "uniform vec4 poly_color;\n" \ - "uniform float lighting;\n" \ - -#define GLSL_SOFTWARE_PAL_MAIN \ - "void main(void) {\n" \ - "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ - "float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \ - "float z = gl_FragCoord.z / gl_FragCoord.w;\n" \ - "float light_y = clamp(floor(R_DoomColormap(lighting, z)), 0.0, 31.0);\n" \ - "vec2 lighttable_coord = vec2((tex_pal_idx + 0.5) / 256.0, (light_y + 0.5) / 32.0);\n" \ - "vec4 final_color = texture2D(lighttable_tex, lighttable_coord);\n" \ - "final_color.a = texel.a * poly_color.a;\n" \ - "gl_FragColor = final_color;\n" \ - "}\n" - -#define GLSL_SOFTWARE_PAL_FRAGMENT_SHADER_FLOORS \ - GLSL_SOFTWARE_PAL_UNIFORMS \ - GLSL_FLOOR_FUDGES \ - GLSL_DOOM_COLORMAP \ - GLSL_SOFTWARE_PAL_MAIN \ - "\0" - -#define GLSL_SOFTWARE_PAL_FRAGMENT_SHADER_WALLS \ - GLSL_SOFTWARE_PAL_UNIFORMS \ - GLSL_WALL_FUDGES \ - GLSL_DOOM_COLORMAP \ - GLSL_SOFTWARE_PAL_MAIN \ - "\0" - -// -// Water surface shader -// -// Mostly guesstimated, rather than the rest being built off Software science. -// Still needs to distort things underneath/around the water... -// - -#define GLSL_WATER_FRAGMENT_SHADER \ - GLSL_FLOOR_FUDGES \ - "uniform sampler2D tex;\n" \ - "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" \ - "uniform float leveltime;\n" \ - "const float freq = 0.025;\n" \ - "const float amp = 0.025;\n" \ - "const float speed = 2.0;\n" \ - "const float pi = 3.14159;\n" \ - GLSL_DOOM_COLORMAP \ - GLSL_DOOM_LIGHT_EQUATION \ - "void main(void) {\n" \ - "float z = (gl_FragCoord.z / gl_FragCoord.w) / 2.0;\n" \ - "float a = -pi * (z * freq) + (leveltime * speed);\n" \ - "float sdistort = sin(a) * amp;\n" \ - "float cdistort = cos(a) * amp;\n" \ - "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" \ - GLSL_SOFTWARE_TINT_EQUATION \ - GLSL_SOFTWARE_FADE_EQUATION \ - "final_color.a = texel.a * poly_color.a;\n" \ - "gl_FragColor = final_color;\n" \ - "}\0" - -//TODO: make this not a hacky copy of two shaders mixed together -#define GLSL_PALETTE_WATER_FRAGMENT_SHADER \ - GLSL_FLOOR_FUDGES \ - "const float freq = 0.025;\n" \ - "const float amp = 0.025;\n" \ - "const float speed = 2.0;\n" \ - "const float pi = 3.14159;\n" \ - "uniform sampler2D tex;\n" \ - "uniform sampler3D palette_lookup_tex;\n" \ - "uniform sampler2D lighttable_tex;\n" \ - "uniform vec4 poly_color;\n" \ - "uniform float lighting;\n" \ - "uniform float leveltime;\n" \ - GLSL_DOOM_COLORMAP \ - "void main(void) {\n" \ - "float water_z = (gl_FragCoord.z / gl_FragCoord.w) / 2.0;\n" \ - "float a = -pi * (water_z * freq) + (leveltime * speed);\n" \ - "float sdistort = sin(a) * amp;\n" \ - "float cdistort = cos(a) * amp;\n" \ - "vec4 texel = texture2D(tex, vec2(gl_TexCoord[0].s - sdistort, gl_TexCoord[0].t - cdistort));\n" \ - "float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \ - "float z = gl_FragCoord.z / gl_FragCoord.w;\n" \ - "float light_y = clamp(floor(R_DoomColormap(lighting, z)), 0.0, 31.0);\n" \ - "vec2 lighttable_coord = vec2((tex_pal_idx + 0.5) / 256.0, (light_y + 0.5) / 32.0);\n" \ - "vec4 final_color = texture2D(lighttable_tex, lighttable_coord);\n" \ - "final_color.a = texel.a * poly_color.a;\n" \ - "gl_FragColor = final_color;\n" \ - "}\0" - -// -// Fog block shader -// -// Alpha of the planes themselves are still slightly off -- see HWR_FogBlockAlpha -// - -#define GLSL_FOG_FRAGMENT_SHADER \ - GLSL_FLOOR_FUDGES \ - "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 \ - GLSL_DOOM_LIGHT_EQUATION \ - "void main(void) {\n" \ - "vec4 base_color = gl_Color;\n" \ - "vec4 final_color = base_color;\n" \ - GLSL_SOFTWARE_TINT_EQUATION \ - GLSL_SOFTWARE_FADE_EQUATION \ - "gl_FragColor = final_color;\n" \ - "}\0" - -// -// Palette color quantization shader -// - -#define GLSL_PALETTE_FRAGMENT_SHADER \ - "uniform sampler2D tex;\n" \ - "uniform sampler3D palette_lookup_tex;\n" \ - "uniform sampler1D palette_tex;\n" \ - "void main(void) {\n" \ - "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ - "float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \ - "float palette_coord = (tex_pal_idx + 0.5) / 256.0;\n" \ - "vec4 final_color = texture1D(palette_tex, palette_coord);\n" \ - "gl_FragColor = final_color;\n" \ - "}\0" - - -#define GLSL_UI_COLORMAP_FADE_SHADER \ - "uniform sampler2D tex;\n" \ - "uniform float lighting;\n" \ - "uniform sampler3D palette_lookup_tex;\n" \ - "uniform sampler2D lighttable_tex;\n" \ - "void main(void) {\n" \ - "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ - "float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \ - "vec2 lighttable_coord = vec2((tex_pal_idx + 0.5) / 256.0, (lighting + 0.5) / 32.0);\n" \ - "gl_FragColor = texture2D(lighttable_tex, lighttable_coord);\n" \ - "}\0" \ - -// -// Sky fragment shader -// Modulates poly_color with gl_Color -// -#define GLSL_SKY_FRAGMENT_SHADER \ - "uniform sampler2D tex;\n" \ - "uniform vec4 poly_color;\n" \ - "void main(void) {\n" \ - "gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * gl_Color * poly_color;\n" \ - "}\0" - -static const char *fragment_shaders[] = { - // Default fragment shader - GLSL_DEFAULT_FRAGMENT_SHADER, - - // Floor fragment shader - GLSL_SOFTWARE_FRAGMENT_SHADER_FLOORS, - - // Wall fragment shader - GLSL_SOFTWARE_FRAGMENT_SHADER_WALLS, - - // Sprite fragment shader - GLSL_SOFTWARE_FRAGMENT_SHADER_WALLS, - - // Model fragment shader - GLSL_SOFTWARE_FRAGMENT_SHADER_WALLS, - - // Water fragment shader - GLSL_WATER_FRAGMENT_SHADER, - - // Fog fragment shader - GLSL_FOG_FRAGMENT_SHADER, - - // Sky fragment shader - GLSL_SKY_FRAGMENT_SHADER, - - // Palette fragment shader - GLSL_PALETTE_FRAGMENT_SHADER, - - // Palette floor fudge shader - GLSL_SOFTWARE_PAL_FRAGMENT_SHADER_FLOORS, - - // Palette wall fudge shader - GLSL_SOFTWARE_PAL_FRAGMENT_SHADER_WALLS, - - // Palette water shader - GLSL_PALETTE_WATER_FRAGMENT_SHADER, - - // UI colormap fade shader - GLSL_UI_COLORMAP_FADE_SHADER, - - NULL, -}; - -// ====================== -// Vertex shader macros -// ====================== - -// -// GLSL generic vertex shader -// - -#define GLSL_DEFAULT_VERTEX_SHADER \ +#define GLSL_FALLBACK_VERTEX_SHADER \ "void main()\n" \ "{\n" \ "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ @@ -1006,48 +700,16 @@ static const char *fragment_shaders[] = { "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ "}\0" -static const char *vertex_shaders[] = { - // Default vertex shader - GLSL_DEFAULT_VERTEX_SHADER, +// +// Generic fragment shader +// - // Floor vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // Wall vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // Sprite vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // Model vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // Water vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // Fog vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // Sky vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // Palette vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // Palette floor vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // Palette wall vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // Palette water vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // UI colormap fade shader - GLSL_DEFAULT_VERTEX_SHADER, - - NULL, -}; +#define GLSL_FALLBACK_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" #endif // GL_SHADERS @@ -1077,6 +739,7 @@ void SetupGLFunc4(void) pglGetShaderInfoLog = GetGLFunc("glGetShaderInfoLog"); pglDeleteShader = GetGLFunc("glDeleteShader"); pglCreateProgram = GetGLFunc("glCreateProgram"); + pglDeleteProgram = GetGLFunc("glDeleteProgram"); pglAttachShader = GetGLFunc("glAttachShader"); pglLinkProgram = GetGLFunc("glLinkProgram"); pglGetProgramiv = GetGLFunc("glGetProgramiv"); @@ -1100,160 +763,78 @@ void SetupGLFunc4(void) #endif } -// jimita -EXPORT boolean HWRAPI(LoadShaders) (void) +EXPORT boolean HWRAPI(InitShaders) (void) { #ifdef GL_SHADERS - GLuint gl_vertShader, gl_fragShader; - GLint i, result; + if (!pglUseProgram) + return false; - if (!pglUseProgram) return false; + gl_fallback_shader.vertex_shader = Z_StrDup(GLSL_FALLBACK_VERTEX_SHADER); + gl_fallback_shader.fragment_shader = Z_StrDup(GLSL_FALLBACK_FRAGMENT_SHADER); - gl_customvertexshaders[0] = NULL; - gl_customfragmentshaders[0] = NULL; - - for (i = 0; vertex_shaders[i] && fragment_shaders[i]; i++) + if (!Shader_CompileProgram(&gl_fallback_shader, -1)) { - gl_shaderprogram_t *shader; - const GLchar* vert_shader = vertex_shaders[i]; - const GLchar* frag_shader = fragment_shaders[i]; - boolean custom = cv_grusecustomshaders.value && ((gl_customvertexshaders[i] || gl_customfragmentshaders[i]) && (i > 0)); - - // 18032019 - if (cv_grusecustomshaders.value && gl_customvertexshaders[i]) - vert_shader = gl_customvertexshaders[i]; - if (cv_grusecustomshaders.value && gl_customfragmentshaders[i]) - frag_shader = gl_customfragmentshaders[i]; - - - if (i >= MAXSHADERS) - break; - if (i >= MAXSHADERPROGRAMS) - break; - - // - // Load and compile vertex shader - // - gl_vertShader = pglCreateShader(GL_VERTEX_SHADER); - if (!gl_vertShader) - { - GL_MSG_Error("LoadShaders: Error creating vertex shader %d\n", i); - continue; - } - - pglShaderSource(gl_vertShader, 1, &vert_shader, NULL); - pglCompileShader(gl_vertShader); - - // check for compile errors - pglGetShaderiv(gl_vertShader, GL_COMPILE_STATUS, &result); - if (result == GL_FALSE) - { - GLchar* infoLog; - GLint logLength; - - pglGetShaderiv(gl_vertShader, GL_INFO_LOG_LENGTH, &logLength); - - infoLog = malloc(logLength); - pglGetShaderInfoLog(gl_vertShader, logLength, NULL, infoLog); - - GL_MSG_Error("LoadShaders: Error compiling vertex shader %d\n%s", i, infoLog); - continue; - } - - // - // Load and compile fragment shader - // - gl_fragShader = pglCreateShader(GL_FRAGMENT_SHADER); - if (!gl_fragShader) - { - GL_MSG_Error("LoadShaders: Error creating fragment shader %d\n", i); - continue; - } - - pglShaderSource(gl_fragShader, 1, &frag_shader, NULL); - pglCompileShader(gl_fragShader); - - // check for compile errors - pglGetShaderiv(gl_fragShader, GL_COMPILE_STATUS, &result); - if (result == GL_FALSE) - { - GLchar* infoLog; - GLint logLength; - - pglGetShaderiv(gl_fragShader, GL_INFO_LOG_LENGTH, &logLength); - - infoLog = malloc(logLength); - pglGetShaderInfoLog(gl_fragShader, logLength, NULL, infoLog); - - GL_MSG_Error("LoadShaders: Error compiling fragment shader %d\n%s", i, infoLog); - continue; - } - - shader = &gl_shaderprograms[i]; - shader->program = pglCreateProgram(); - shader->custom = custom; - pglAttachShader(shader->program, gl_vertShader); - pglAttachShader(shader->program, gl_fragShader); - pglLinkProgram(shader->program); - - // check link status - pglGetProgramiv(shader->program, GL_LINK_STATUS, &result); - - // delete the shader objects - pglDeleteShader(gl_vertShader); - pglDeleteShader(gl_fragShader); - - // couldn't link? - if (result != GL_TRUE) - { - shader->program = 0; - shader->custom = false; - GL_MSG_Error("LoadShaders: Error linking shader program %d\n", i); - continue; - } - - // 13062019 -#define GETUNI(uniform) pglGetUniformLocation(shader->program, uniform); - - // lighting - shader->uniforms[gluniform_poly_color] = GETUNI("poly_color"); - shader->uniforms[gluniform_tint_color] = GETUNI("tint_color"); - shader->uniforms[gluniform_fade_color] = GETUNI("fade_color"); - shader->uniforms[gluniform_lighting] = GETUNI("lighting"); - shader->uniforms[gluniform_fade_start] = GETUNI("fade_start"); - shader->uniforms[gluniform_fade_end] = GETUNI("fade_end"); - - // palette rendering - shader->uniforms[gluniform_palette_tex] = GETUNI("palette_tex"); - shader->uniforms[gluniform_palette_lookup_tex] = GETUNI("palette_lookup_tex"); - shader->uniforms[gluniform_lighttable_tex] = GETUNI("lighttable_tex"); - - // misc. - shader->uniforms[gluniform_leveltime] = GETUNI("leveltime"); -#undef GETUNI - -// set permanent uniform values -#define UNIFORM_1(uniform, a, function) \ - if (uniform != -1) \ - function (uniform, a); - - pglUseProgram(shader->program); - - // texture unit numbers for the samplers used for palette rendering - UNIFORM_1(shader->uniforms[gluniform_palette_tex], 2, pglUniform1i); - UNIFORM_1(shader->uniforms[gluniform_palette_lookup_tex], 1, pglUniform1i); - UNIFORM_1(shader->uniforms[gluniform_lighttable_tex], 2, pglUniform1i); - - // restore gl shader state - //pglUseProgram(gl_shaderstate.program); - pglUseProgram(gl_currentshaderprogram); - //pglUseProgram(0); // dont remember why this was here in the first place, but seems fine? -#undef UNIFORM_1 + GL_MSG_Error("Failed to compile the fallback shader program!\n"); + return false; } -#endif + return true; +#else + return false; +#endif } +EXPORT void HWRAPI(LoadShader) (int slot, char *code, hwdshaderstage_t stage) +{ +#ifdef GL_SHADERS + gl_shader_t *shader; + + if (slot < 0 || slot >= HWR_MAXSHADERS) + I_Error("LoadShader: Invalid slot %d", slot); + + shader = &gl_shaders[slot]; + +#define LOADSHADER(source) { \ + if (shader->source) \ + Z_Free(shader->source); \ + shader->source = code; \ + } + + if (stage == HWD_SHADERSTAGE_VERTEX) + LOADSHADER(vertex_shader) + else if (stage == HWD_SHADERSTAGE_FRAGMENT) + LOADSHADER(fragment_shader) + else + I_Error("LoadShader: invalid shader stage"); + +#undef LOADSHADER +#else + (void)slot; + (void)code; + (void)stage; +#endif +} + +EXPORT boolean HWRAPI(CompileShader) (int slot) +{ +#ifdef GL_SHADERS + if (slot < 0 || slot >= HWR_MAXSHADERS) + I_Error("CompileShader: Invalid slot %d", slot); + + if (Shader_CompileProgram(&gl_shaders[slot], slot)) + { + return true; + } + else + { + gl_shaders[slot].program = 0; + return false; + } +#else + (void)slot; + return false; +#endif +} // // Shader info @@ -1266,7 +847,7 @@ EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value) switch (info) { case HWD_SHADERINFO_LEVELTIME: - shader_leveltime = (((float)(value-1)) + FIXED_TO_FLOAT(rendertimefrac)) / TICRATE; + shader_leveltime = value; break; default: break; @@ -1277,62 +858,31 @@ EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value) #endif } -// -// Custom shader loading -// -EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boolean fragment) -{ -#ifdef GL_SHADERS - if (!pglUseProgram) - return; - - if (number < 1 || number > MAXSHADERS) - I_Error("LoadCustomShader(): cannot load shader %d (max %d)", number, MAXSHADERS); - - if (fragment) - { - gl_customfragmentshaders[number] = malloc(size+1); - strncpy(gl_customfragmentshaders[number], shader, size); - gl_customfragmentshaders[number][size] = 0; - } - else - { - gl_customvertexshaders[number] = malloc(size+1); - strncpy(gl_customvertexshaders[number], shader, size); - gl_customvertexshaders[number][size] = 0; - } -#else - (void)number; - (void)shader; - (void)size; - (void)fragment; -#endif -} - -EXPORT boolean HWRAPI(InitCustomShaders) (void) -{ -#ifdef GL_SHADERS - KillShaders(); - return LoadShaders(); -#endif -} - - -EXPORT void HWRAPI(SetShader) (int shader) +EXPORT void HWRAPI(SetShader) (int slot) { #ifdef GL_SHADERS if (gl_allowshaders) { - if ((GLuint)shader != gl_currentshaderprogram) + gl_shader_t *next_shader = &gl_shaders[slot]; // the gl_shader_t we are going to switch to + + if (!next_shader->program) + next_shader = &gl_fallback_shader; // unusable shader, use fallback instead + + // update gl_shaderstate if an actual shader switch is needed + if (gl_shaderstate.current != next_shader) { - gl_currentshaderprogram = shader; - gl_shaderprogramchanged = true; + gl_shaderstate.current = next_shader; + gl_shaderstate.program = next_shader->program; + gl_shaderstate.type = slot; + gl_shaderstate.changed = true; } + gl_shadersenabled = true; + return; } #else - (void)shader; + (void)slot; #endif gl_shadersenabled = false; } @@ -1340,24 +890,17 @@ EXPORT void HWRAPI(SetShader) (int shader) EXPORT void HWRAPI(UnSetShader) (void) { #ifdef GL_SHADERS - if (gl_shadersenabled) // don't repeatedly call glUseProgram if not needed - { - gl_shadersenabled = false; - gl_currentshaderprogram = 0; - gl_shaderprogramchanged = true;// not sure if this is needed - if (!pglUseProgram) return; + gl_shaderstate.current = NULL; + gl_shaderstate.type = 0; + gl_shaderstate.program = 0; + + if (pglUseProgram) pglUseProgram(0); - } #endif + gl_shadersenabled = false; } - -EXPORT void HWRAPI(KillShaders) (void) -{ - // unused......................... -} - // -----------------+ // SetNoTexture : Disable texture // -----------------+ @@ -2107,24 +1650,23 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade) { - gl_shaderprogram_t *shader = &gl_shaderprograms[gl_currentshaderprogram]; - #ifdef GL_SHADERS + gl_shader_t *shader = gl_shaderstate.current; + if (gl_shadersenabled && (shader != NULL) && pglUseProgram) { - if (!shader->program) { pglUseProgram(0); return; } - if (gl_shaderprogramchanged) + if (gl_shaderstate.changed) { - pglUseProgram(gl_shaderprograms[gl_currentshaderprogram].program); - gl_shaderprogramchanged = false; + pglUseProgram(shader->program); + gl_shaderstate.changed = false; } - + // Color uniforms can be left NULL and will be set to white (1.0f, 1.0f, 1.0f, 1.0f) if (poly == NULL) poly = &shader_defaultcolor; @@ -2153,13 +1695,15 @@ 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); + 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); } - UNIFORM_1(shader->uniforms[gluniform_leveltime], shader_leveltime, pglUniform1f); + + UNIFORM_1(shader->uniforms[gluniform_leveltime], ((float)shader_leveltime) / TICRATE, pglUniform1f); #undef UNIFORM_1 #undef UNIFORM_2 @@ -2174,6 +1718,139 @@ static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAF #endif } +static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i) +{ + GLuint gl_vertShader = 0; + GLuint gl_fragShader = 0; + GLint result; + const GLchar *vert_shader = shader->vertex_shader; + const GLchar *frag_shader = shader->fragment_shader; + + if (shader->program) + pglDeleteProgram(shader->program); + + if (!vert_shader && !frag_shader) + { + GL_MSG_Error("Shader_CompileProgram: Missing shaders for shader program %s\n", HWR_GetShaderName(i)); + return false; + } + + if (vert_shader) + { + // + // Load and compile vertex shader + // + gl_vertShader = pglCreateShader(GL_VERTEX_SHADER); + if (!gl_vertShader) + { + GL_MSG_Error("Shader_CompileProgram: Error creating vertex shader %s\n", HWR_GetShaderName(i)); + return false; + } + + pglShaderSource(gl_vertShader, 1, &vert_shader, NULL); + pglCompileShader(gl_vertShader); + + // check for compile errors + pglGetShaderiv(gl_vertShader, GL_COMPILE_STATUS, &result); + if (result == GL_FALSE) + { + GL_MSG_Error("Error compiling vertex shader", gl_vertShader, i); + pglDeleteShader(gl_vertShader); + return false; + } + } + + if (frag_shader) + { + // + // Load and compile fragment shader + // + gl_fragShader = pglCreateShader(GL_FRAGMENT_SHADER); + if (!gl_fragShader) + { + GL_MSG_Error("Shader_CompileProgram: Error creating fragment shader %s\n", HWR_GetShaderName(i)); + pglDeleteShader(gl_vertShader); + pglDeleteShader(gl_fragShader); + return false; + } + + pglShaderSource(gl_fragShader, 1, &frag_shader, NULL); + pglCompileShader(gl_fragShader); + + // check for compile errors + pglGetShaderiv(gl_fragShader, GL_COMPILE_STATUS, &result); + if (result == GL_FALSE) + { + GL_MSG_Error("Error compiling fragment shader", gl_fragShader, i); + pglDeleteShader(gl_vertShader); + pglDeleteShader(gl_fragShader); + return false; + } + } + + shader->program = pglCreateProgram(); + if (vert_shader) + pglAttachShader(shader->program, gl_vertShader); + if (frag_shader) + pglAttachShader(shader->program, gl_fragShader); + pglLinkProgram(shader->program); + + // check link status + pglGetProgramiv(shader->program, GL_LINK_STATUS, &result); + + // delete the shader objects + if (vert_shader) + pglDeleteShader(gl_vertShader); + if (frag_shader) + pglDeleteShader(gl_fragShader); + + // couldn't link? + if (result != GL_TRUE) + { + GL_MSG_Error("Shader_CompileProgram: Error linking shader program %s\n", HWR_GetShaderName(i)); + pglDeleteProgram(shader->program); + return false; + } + + // 13062019 +#define GETUNI(uniform) pglGetUniformLocation(shader->program, uniform); + + // lighting + shader->uniforms[gluniform_poly_color] = GETUNI("poly_color"); + shader->uniforms[gluniform_tint_color] = GETUNI("tint_color"); + shader->uniforms[gluniform_fade_color] = GETUNI("fade_color"); + shader->uniforms[gluniform_lighting] = GETUNI("lighting"); + shader->uniforms[gluniform_fade_start] = GETUNI("fade_start"); + shader->uniforms[gluniform_fade_end] = GETUNI("fade_end"); + + // palette rendering + shader->uniforms[gluniform_palette_tex] = GETUNI("palette_tex"); + shader->uniforms[gluniform_palette_lookup_tex] = GETUNI("palette_lookup_tex"); + shader->uniforms[gluniform_lighttable_tex] = GETUNI("lighttable_tex"); + + // misc. + shader->uniforms[gluniform_leveltime] = GETUNI("leveltime"); +#undef GETUNI + + // set permanent uniform values +#define UNIFORM_1(uniform, a, function) \ + if (uniform != -1) \ + function (uniform, a); + + pglUseProgram(shader->program); + + // texture unit numbers for the samplers used for palette rendering + UNIFORM_1(shader->uniforms[gluniform_palette_tex], 2, pglUniform1i); + UNIFORM_1(shader->uniforms[gluniform_palette_lookup_tex], 1, pglUniform1i); + UNIFORM_1(shader->uniforms[gluniform_lighttable_tex], 2, pglUniform1i); + + // restore gl shader state + pglUseProgram(gl_shaderstate.program); +#undef UNIFORM_1 + + return true; +} + // code that is common between DrawPolygon and DrawIndexedTriangles // DrawScreenTexture also can use this function for fancier screen texture drawing // the corona thing is there too, i have no idea if that stuff works with DrawIndexedTriangles and batching @@ -2566,15 +2243,7 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value) switch (IdState) { case HWD_SET_SHADERS: - switch (Value) - { - case 1: - gl_allowshaders = true; - break; - default: - gl_allowshaders = false; - break; - } + gl_allowshaders = Value; break; case HWD_SET_TEXTUREFILTERMODE: @@ -3707,7 +3376,7 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int tex, int width, int height) pglBindTexture(GL_TEXTURE_2D, screenTextures[tex]); if (HWR_ShouldUsePaletteRendering()) - pglUseProgram(gl_shaderprograms[8].program); // palette postprocess shader + pglUseProgram(gl_shaders[SHADER_PALETTE_POSTPROCESS].program); // palette postprocess shader pglColor4ubv(white); @@ -3717,7 +3386,7 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int tex, int width, int height) pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); if (HWR_ShouldUsePaletteRendering()) - pglUseProgram(0); + UnSetShader(); tex_downloaded = screenTextures[tex]; } diff --git a/src/hardware/r_opengl/r_opengl.h b/src/hardware/r_opengl/r_opengl.h index 6d11bf4e3..7991e19d2 100644 --- a/src/hardware/r_opengl/r_opengl.h +++ b/src/hardware/r_opengl/r_opengl.h @@ -46,6 +46,7 @@ #define _CREATE_DLL_ // necessary for Unix AND Windows #include "../../doomdef.h" #include "../hw_drv.h" +#include "../../z_zone.h" // ========================================================================== // DEFINITIONS diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index da12b0e7c..64f9b7da9 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -104,14 +104,13 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(RenderSkyDome); - GETFUNC(LoadShaders); - GETFUNC(KillShaders); + GETFUNC(InitShaders); + GETFUNC(LoadShader); + GETFUNC(CompileShader); GETFUNC(SetShader); GETFUNC(UnSetShader); GETFUNC(SetShaderInfo); - GETFUNC(LoadCustomShader); - GETFUNC(InitCustomShaders); GETFUNC(SetPaletteLookup); GETFUNC(CreateLightTable); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 8ce2b4710..cbe0fac05 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -2136,14 +2136,13 @@ void I_StartupGraphics(void) HWD.pfnRenderSkyDome = hwSym("RenderSkyDome",NULL); - HWD.pfnLoadShaders = hwSym("LoadShaders",NULL); - HWD.pfnKillShaders = hwSym("KillShaders",NULL); - HWD.pfnSetShader = hwSym("SetShader",NULL); - HWD.pfnUnSetShader = hwSym("UnSetShader",NULL); + HWD.pfnInitShaders = hwSym("InitShaders",NULL); + HWD.pfnLoadShader = hwSym("LoadShader",NULL); + HWD.pfnCompileShader = hwSym("CompileShader",NULL); + HWD.pfnSetShader = hwSym("SetShader",NULL); + HWD.pfnUnSetShader = hwSym("UnSetShader",NULL); HWD.pfnSetShaderInfo = hwSym("SetShaderInfo",NULL); - HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL); - HWD.pfnInitCustomShaders = hwSym("InitCustomShaders",NULL); HWD.pfnSetPaletteLookup = hwSym("SetPaletteLookup",NULL); HWD.pfnCreateLightTable = hwSym("CreateLightTable",NULL); diff --git a/src/w_wad.c b/src/w_wad.c index 4989f497b..76c622999 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -693,18 +693,6 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp) return lumpinfo; } -static void W_ReadFileShaders(wadfile_t *wadfile) -{ -#ifdef HWRENDER - if (rendermode == render_opengl) - { - HWR_LoadShaders(numwadfiles - 1, W_FileHasFolders(wadfile)); - } -#else - (void)wadfile; -#endif -} - // Allocate a wadfile, setup the lumpinfo (directory) and // lumpcache, add the wadfile to the current active wadfiles // @@ -838,7 +826,8 @@ UINT16 W_InitFile(const char *filename, const char *lumpname, UINT16 *wadnump, b numwadfiles++; // must come BEFORE W_LoadDehackedLumps, so any addfile called by COM_BufInsertText called by Lua doesn't overwrite what we just loaded // Read shaders from file - W_ReadFileShaders(wadfile); + if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED)) + HWR_LoadCustomShadersFromFile(numwadfiles - 1, (type == RET_PK3)); // TODO: HACK ALERT - Load Lua & SOC stuff right here. I feel like this should be out of this place, but... Let's stick with this for now. switch (wadfile->type) -- 2.54.0 From 51699bfdb5b93fef5bfec4c8786233eedc6625be Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 22 Jan 2024 18:14:14 +0100 Subject: [PATCH 20/24] split hw_shader files --- src/hardware/hw_shaders.c | 255 +------------------------------- src/hardware/hw_shaders.h | 298 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 300 insertions(+), 253 deletions(-) create mode 100644 src/hardware/hw_shaders.h diff --git a/src/hardware/hw_shaders.c b/src/hardware/hw_shaders.c index 5840e8cd1..7cf10fbe5 100644 --- a/src/hardware/hw_shaders.c +++ b/src/hardware/hw_shaders.c @@ -6,7 +6,7 @@ // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file hw_shaders.h +/// \file hw_shaders.c /// \brief Handles the shaders used by the game. #ifdef HWRENDER @@ -14,260 +14,9 @@ #include "hw_main.h" #include "hw_glob.h" #include "hw_drv.h" +#include "hw_shaders.h" #include "../z_zone.h" -// ================ -// 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" - -// ================== -// 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 -// - -// Include GLSL_FLOOR_FUDGES or GLSL_WALL_FUDGES or define the fudges in shaders that use this macro. -#define GLSL_DOOM_COLORMAP \ - "float R_DoomColormap(float light, float z)\n" \ - "{\n" \ - "float lightnum = clamp(light / 17.0, 0.0, 15.0);\n" \ - "float lightz = clamp(z / 16.0, 0.0, 127.0);\n" \ - "float startmap = (15.0 - lightnum) * 4.0;\n" \ - "float scale = 160.0 / (lightz + 1.0);\n" \ - "float cap = (155.0 - light) * 0.26;\n" \ - "return max(startmap * STARTMAP_FUDGE - scale * 0.5 * SCALE_FUDGE, cap);\n" \ - "}\n" -// lighting cap adjustment: -// first num (155.0), increase to make it start to go dark sooner -// second num (0.26), increase to make it go dark faster - -#define GLSL_DOOM_LIGHT_EQUATION \ - "float R_DoomLightingEquation(float light)\n" \ - "{\n" \ - "float z = gl_FragCoord.z / gl_FragCoord.w;\n" \ - "float colormap = floor(R_DoomColormap(light, z)) + 0.5;\n" \ - "return clamp(colormap, 0.0, 31.0) / 32.0;\n" \ - "}\n" - -#define GLSL_SOFTWARE_TINT_EQUATION \ - "if (tint_color.a > 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" \ - "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" \ - "}\n" - -#define GLSL_SOFTWARE_FADE_EQUATION \ - "float darkness = R_DoomLightingEquation(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" \ - "float fd = fe - fs;\n" \ - "darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \ - "}\n" \ - "final_color = mix(final_color, fade_color, darkness);\n" - -#define GLSL_PALETTE_RENDERING \ - "float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \ - "float z = gl_FragCoord.z / gl_FragCoord.w;\n" \ - "float light_y = clamp(floor(R_DoomColormap(lighting, z)), 0.0, 31.0);\n" \ - "vec2 lighttable_coord = vec2((tex_pal_idx + 0.5) / 256.0, (light_y + 0.5) / 32.0);\n" \ - "vec4 final_color = texture2D(lighttable_tex, lighttable_coord);\n" \ - "final_color.a = texel.a * poly_color.a;\n" \ - "gl_FragColor = final_color;\n" \ - -#define GLSL_SOFTWARE_FRAGMENT_SHADER \ - "#ifdef SRB2_PALETTE_RENDERING\n" \ - "uniform sampler2D tex;\n" \ - "uniform sampler3D palette_lookup_tex;\n" \ - "uniform sampler2D lighttable_tex;\n" \ - "uniform vec4 poly_color;\n" \ - "uniform float lighting;\n" \ - GLSL_DOOM_COLORMAP \ - "void main(void) {\n" \ - "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ - GLSL_PALETTE_RENDERING \ - "}\n" \ - "#else\n" \ - "uniform sampler2D tex;\n" \ - "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 \ - GLSL_DOOM_LIGHT_EQUATION \ - "void main(void) {\n" \ - "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ - "vec4 base_color = texel * poly_color;\n" \ - "vec4 final_color = base_color;\n" \ - GLSL_SOFTWARE_TINT_EQUATION \ - GLSL_SOFTWARE_FADE_EQUATION \ - "final_color.a = texel.a * poly_color.a;\n" \ - "gl_FragColor = final_color;\n" \ - "}\n" \ - "#endif\0" - -// hand tuned adjustments for light level calculation -#define GLSL_FLOOR_FUDGES \ - "#define STARTMAP_FUDGE 1.06\n" \ - "#define SCALE_FUDGE 1.15\n" - -#define GLSL_WALL_FUDGES \ - "#define STARTMAP_FUDGE 1.05\n" \ - "#define SCALE_FUDGE 2.2\n" - -#define GLSL_FLOOR_FRAGMENT_SHADER \ - GLSL_FLOOR_FUDGES \ - GLSL_SOFTWARE_FRAGMENT_SHADER - -#define GLSL_WALL_FRAGMENT_SHADER \ - GLSL_WALL_FUDGES \ - GLSL_SOFTWARE_FRAGMENT_SHADER - -// -// Water surface shader -// -// Mostly guesstimated, rather than the rest being built off Software science. -// Still needs to distort things underneath/around the water... -// - -#define GLSL_WATER_TEXEL \ - "float water_z = (gl_FragCoord.z / gl_FragCoord.w) / 2.0;\n" \ - "float a = -pi * (water_z * freq) + (leveltime * speed);\n" \ - "float sdistort = sin(a) * amp;\n" \ - "float cdistort = cos(a) * amp;\n" \ - "vec4 texel = texture2D(tex, vec2(gl_TexCoord[0].s - sdistort, gl_TexCoord[0].t - cdistort));\n" - -#define GLSL_WATER_FRAGMENT_SHADER \ - GLSL_FLOOR_FUDGES \ - "const float freq = 0.025;\n" \ - "const float amp = 0.025;\n" \ - "const float speed = 2.0;\n" \ - "const float pi = 3.14159;\n" \ - "#ifdef SRB2_PALETTE_RENDERING\n" \ - "uniform sampler2D tex;\n" \ - "uniform sampler3D palette_lookup_tex;\n" \ - "uniform sampler2D lighttable_tex;\n" \ - "uniform vec4 poly_color;\n" \ - "uniform float lighting;\n" \ - "uniform float leveltime;\n" \ - GLSL_DOOM_COLORMAP \ - "void main(void) {\n" \ - GLSL_WATER_TEXEL \ - GLSL_PALETTE_RENDERING \ - "}\n" \ - "#else\n" \ - "uniform sampler2D tex;\n" \ - "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" \ - "uniform float leveltime;\n" \ - GLSL_DOOM_COLORMAP \ - GLSL_DOOM_LIGHT_EQUATION \ - "void main(void) {\n" \ - GLSL_WATER_TEXEL \ - "vec4 base_color = texel * poly_color;\n" \ - "vec4 final_color = base_color;\n" \ - GLSL_SOFTWARE_TINT_EQUATION \ - GLSL_SOFTWARE_FADE_EQUATION \ - "final_color.a = texel.a * poly_color.a;\n" \ - "gl_FragColor = final_color;\n" \ - "}\n" \ - "#endif\0" - -// -// Fog block shader -// -// Alpha of the planes themselves are still slightly off -- see HWR_FogBlockAlpha -// - -// The floor fudges are used, but should the wall fudges be used instead? or something inbetween? -// or separate values for floors and walls? (need to change more than this shader for that) -#define GLSL_FOG_FRAGMENT_SHADER \ - GLSL_FLOOR_FUDGES \ - "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 \ - GLSL_DOOM_LIGHT_EQUATION \ - "void main(void) {\n" \ - "vec4 base_color = gl_Color;\n" \ - "vec4 final_color = base_color;\n" \ - GLSL_SOFTWARE_TINT_EQUATION \ - GLSL_SOFTWARE_FADE_EQUATION \ - "gl_FragColor = final_color;\n" \ - "}\0" - -// -// Sky fragment shader -// Modulates poly_color with gl_Color -// -#define GLSL_SKY_FRAGMENT_SHADER \ - "uniform sampler2D tex;\n" \ - "uniform vec4 poly_color;\n" \ - "void main(void) {\n" \ - "gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * gl_Color * poly_color;\n" \ - "}\0" - -// Shader for the palette rendering postprocess step -#define GLSL_PALETTE_POSTPROCESS_FRAGMENT_SHADER \ - "uniform sampler2D tex;\n" \ - "uniform sampler3D palette_lookup_tex;\n" \ - "uniform sampler1D palette_tex;\n" \ - "void main(void) {\n" \ - "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ - "float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \ - "float palette_coord = (tex_pal_idx + 0.5) / 256.0;\n" \ - "vec4 final_color = texture1D(palette_tex, palette_coord);\n" \ - "gl_FragColor = final_color;\n" \ - "}\0" - -#define GLSL_UI_COLORMAP_FADE_FRAGMENT_SHADER \ - "uniform sampler2D tex;\n" \ - "uniform float lighting;\n" \ - "uniform sampler3D palette_lookup_tex;\n" \ - "uniform sampler2D lighttable_tex;\n" \ - "void main(void) {\n" \ - "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ - "float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \ - "vec2 lighttable_coord = vec2((tex_pal_idx + 0.5) / 256.0, (lighting + 0.5) / 32.0);\n" \ - "gl_FragColor = texture2D(lighttable_tex, lighttable_coord);\n" \ - "}\0" \ - // ================ // Shader sources // ================ diff --git a/src/hardware/hw_shaders.h b/src/hardware/hw_shaders.h new file mode 100644 index 000000000..eb705c34c --- /dev/null +++ b/src/hardware/hw_shaders.h @@ -0,0 +1,298 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2021 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file hw_shaders.h +/// \brief Handles the shaders used by the game. + +#ifndef _HW_SHADERS_H_ +#define _HW_SHADERS_H_ + +#include "../doomtype.h" + +// ================ +// 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" + +// ================== +// 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 +// + +// Include GLSL_FLOOR_FUDGES or GLSL_WALL_FUDGES or define the fudges in shaders that use this macro. +#define GLSL_DOOM_COLORMAP \ + "float R_DoomColormap(float light, float z)\n" \ + "{\n" \ + "float lightnum = clamp(light / 17.0, 0.0, 15.0);\n" \ + "float lightz = clamp(z / 16.0, 0.0, 127.0);\n" \ + "float startmap = (15.0 - lightnum) * 4.0;\n" \ + "float scale = 160.0 / (lightz + 1.0);\n" \ + "float cap = (155.0 - light) * 0.26;\n" \ + "return max(startmap * STARTMAP_FUDGE - scale * 0.5 * SCALE_FUDGE, cap);\n" \ + "}\n" +// lighting cap adjustment: +// first num (155.0), increase to make it start to go dark sooner +// second num (0.26), increase to make it go dark faster + +#define GLSL_DOOM_LIGHT_EQUATION \ + "float R_DoomLightingEquation(float light)\n" \ + "{\n" \ + "float z = gl_FragCoord.z / gl_FragCoord.w;\n" \ + "float colormap = floor(R_DoomColormap(light, z)) + 0.5;\n" \ + "return clamp(colormap, 0.0, 31.0) / 32.0;\n" \ + "}\n" + +#define GLSL_SOFTWARE_TINT_EQUATION \ + "if (tint_color.a > 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" \ + "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" \ + "}\n" + +#define GLSL_SOFTWARE_FADE_EQUATION \ + "float darkness = R_DoomLightingEquation(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" \ + "float fd = fe - fs;\n" \ + "darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \ + "}\n" \ + "final_color = mix(final_color, fade_color, darkness);\n" + +#define GLSL_PALETTE_RENDERING \ + "float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \ + "float z = gl_FragCoord.z / gl_FragCoord.w;\n" \ + "float light_y = clamp(floor(R_DoomColormap(lighting, z)), 0.0, 31.0);\n" \ + "vec2 lighttable_coord = vec2((tex_pal_idx + 0.5) / 256.0, (light_y + 0.5) / 32.0);\n" \ + "vec4 final_color = texture2D(lighttable_tex, lighttable_coord);\n" \ + "final_color.a = texel.a * poly_color.a;\n" \ + "gl_FragColor = final_color;\n" \ + +#define GLSL_SOFTWARE_FRAGMENT_SHADER \ + "#ifdef SRB2_PALETTE_RENDERING\n" \ + "uniform sampler2D tex;\n" \ + "uniform sampler3D palette_lookup_tex;\n" \ + "uniform sampler2D lighttable_tex;\n" \ + "uniform vec4 poly_color;\n" \ + "uniform float lighting;\n" \ + GLSL_DOOM_COLORMAP \ + "void main(void) {\n" \ + "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ + GLSL_PALETTE_RENDERING \ + "}\n" \ + "#else\n" \ + "uniform sampler2D tex;\n" \ + "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 \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ + "vec4 base_color = texel * poly_color;\n" \ + "vec4 final_color = base_color;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "final_color.a = texel.a * poly_color.a;\n" \ + "gl_FragColor = final_color;\n" \ + "}\n" \ + "#endif\0" + +// hand tuned adjustments for light level calculation +#define GLSL_FLOOR_FUDGES \ + "#define STARTMAP_FUDGE 1.06\n" \ + "#define SCALE_FUDGE 1.15\n" + +#define GLSL_WALL_FUDGES \ + "#define STARTMAP_FUDGE 1.05\n" \ + "#define SCALE_FUDGE 2.2\n" + +#define GLSL_FLOOR_FRAGMENT_SHADER \ + GLSL_FLOOR_FUDGES \ + GLSL_SOFTWARE_FRAGMENT_SHADER + +#define GLSL_WALL_FRAGMENT_SHADER \ + GLSL_WALL_FUDGES \ + GLSL_SOFTWARE_FRAGMENT_SHADER + +// +// Water surface shader +// +// Mostly guesstimated, rather than the rest being built off Software science. +// Still needs to distort things underneath/around the water... +// + +#define GLSL_WATER_TEXEL \ + "float water_z = (gl_FragCoord.z / gl_FragCoord.w) / 2.0;\n" \ + "float a = -pi * (water_z * freq) + (leveltime * speed);\n" \ + "float sdistort = sin(a) * amp;\n" \ + "float cdistort = cos(a) * amp;\n" \ + "vec4 texel = texture2D(tex, vec2(gl_TexCoord[0].s - sdistort, gl_TexCoord[0].t - cdistort));\n" + +#define GLSL_WATER_FRAGMENT_SHADER \ + GLSL_FLOOR_FUDGES \ + "const float freq = 0.025;\n" \ + "const float amp = 0.025;\n" \ + "const float speed = 2.0;\n" \ + "const float pi = 3.14159;\n" \ + "#ifdef SRB2_PALETTE_RENDERING\n" \ + "uniform sampler2D tex;\n" \ + "uniform sampler3D palette_lookup_tex;\n" \ + "uniform sampler2D lighttable_tex;\n" \ + "uniform vec4 poly_color;\n" \ + "uniform float lighting;\n" \ + "uniform float leveltime;\n" \ + GLSL_DOOM_COLORMAP \ + "void main(void) {\n" \ + GLSL_WATER_TEXEL \ + GLSL_PALETTE_RENDERING \ + "}\n" \ + "#else\n" \ + "uniform sampler2D tex;\n" \ + "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" \ + "uniform float leveltime;\n" \ + GLSL_DOOM_COLORMAP \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + GLSL_WATER_TEXEL \ + "vec4 base_color = texel * poly_color;\n" \ + "vec4 final_color = base_color;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "final_color.a = texel.a * poly_color.a;\n" \ + "gl_FragColor = final_color;\n" \ + "}\n" \ + "#endif\0" + +// +// Fog block shader +// +// Alpha of the planes themselves are still slightly off -- see HWR_FogBlockAlpha +// + +// The floor fudges are used, but should the wall fudges be used instead? or something inbetween? +// or separate values for floors and walls? (need to change more than this shader for that) +#define GLSL_FOG_FRAGMENT_SHADER \ + GLSL_FLOOR_FUDGES \ + "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 \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + "vec4 base_color = gl_Color;\n" \ + "vec4 final_color = base_color;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "gl_FragColor = final_color;\n" \ + "}\0" + +// +// Sky fragment shader +// Modulates poly_color with gl_Color +// +#define GLSL_SKY_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform vec4 poly_color;\n" \ + "void main(void) {\n" \ + "gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * gl_Color * poly_color;\n" \ + "}\0" + +// Shader for the palette rendering postprocess step +#define GLSL_PALETTE_POSTPROCESS_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform sampler3D palette_lookup_tex;\n" \ + "uniform sampler1D palette_tex;\n" \ + "void main(void) {\n" \ + "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ + "float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \ + "float palette_coord = (tex_pal_idx + 0.5) / 256.0;\n" \ + "vec4 final_color = texture1D(palette_tex, palette_coord);\n" \ + "gl_FragColor = final_color;\n" \ + "}\0" + +// Applies a palettized colormap fade to tex +#define GLSL_UI_COLORMAP_FADE_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform float lighting;\n" \ + "uniform sampler3D palette_lookup_tex;\n" \ + "uniform sampler2D lighttable_tex;\n" \ + "void main(void) {\n" \ + "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ + "float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \ + "vec2 lighttable_coord = vec2((tex_pal_idx + 0.5) / 256.0, (lighting + 0.5) / 32.0);\n" \ + "gl_FragColor = texture2D(lighttable_tex, lighttable_coord);\n" \ + "}\0" \ + +// ================ +// Fallback shaders +// ================ + +// +// Generic vertex shader +// + +#define GLSL_FALLBACK_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" + +// +// Generic fragment shader +// + +#define GLSL_FALLBACK_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" + +#endif -- 2.54.0 From ce13d4f818feb75fff5b9da0292d95349bc086b7 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 22 Jan 2024 18:15:53 +0100 Subject: [PATCH 21/24] shaderstate should be set here --- src/hardware/hw_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 9ff5d563b..97dda6346 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -6452,11 +6452,11 @@ void HWR_Startup(void) HWD.pfnSetupGLInfo(); gr_shadersavailable = HWR_InitShaders(); + HWR_SetShaderState(); //if (cv_grusecustomshaders.value) HWR_LoadAllCustomShaders(); - HWR_SetShaderState(); HWR_TogglePaletteRendering(); if (msaa) -- 2.54.0 From 79b0b160cbc6f409f7f1d59526d3df5f838e8c7d Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 22 Jan 2024 18:25:51 +0100 Subject: [PATCH 22/24] add toggle for custom shaders it seems better like this, atleast thats how hannu set it up --- src/hardware/hw_main.c | 24 ++++-------------------- src/hardware/hw_main.h | 1 - src/hardware/hw_shaders.c | 5 +---- src/hardware/r_opengl/r_opengl.c | 3 +-- 4 files changed, 6 insertions(+), 27 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 97dda6346..21aafa6f1 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -71,7 +71,6 @@ static boolean gr_palette_rendering_state = false; static void CV_filtermode_ONChange(void); static void CV_anisotropic_ONChange(void); static void CV_screentextures_ONChange(void); -//static void CV_useCustomShaders_ONChange(void); static void CV_grshaders_OnChange(void); static void CV_grpaletterendering_OnChange(void); static void CV_grpalettedepth_OnChange(void); @@ -142,9 +141,9 @@ static INT32 current_bsp_culling_distance = 0; // - full screen scaling (use native resolution or windowed mode to avoid this) consvar_t cv_grscreentextures = {"gr_screentextures", "On", CV_CALL|CV_SAVE, CV_OnOff, CV_screentextures_ONChange, 0, NULL, NULL, 0, 0, NULL}; - -consvar_t cv_grshaders = {"gr_shaders", "On", CV_CALL|CV_SAVE, CV_OnOff, CV_grshaders_OnChange, 0, NULL, NULL, 0, 0, NULL}; -//consvar_t cv_grusecustomshaders = {"gr_usecustomshaders", "Yes", CV_CALL|CV_SAVE, CV_OnOff, CV_useCustomShaders_ONChange, 0, NULL, NULL, 0, 0, NULL}; + +static CV_PossibleValue_t grshaders_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Ignore custom shaders"}, {0, NULL}}; +consvar_t cv_grshaders = {"gr_shaders", "On", CV_CALL|CV_SAVE, grshaders_cons_t, CV_grshaders_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grpaletterendering = {"gr_paletteshader", "Off", CV_CALL|CV_SAVE, CV_OnOff, CV_grpaletterendering_OnChange, 0, NULL, NULL, 0, 0, NULL}; @@ -195,18 +194,6 @@ static void CV_grshaders_OnChange(void) } } -/*static void CV_useCustomShaders_ONChange(void) // should we do a call to HWR_TogglePaletteRendering here aswell in pal rendering mode? -{ - ONLY_IF_GL_LOADED - if (HWR_UseShader() && cv_grusecustomshaders.value) - { - HWR_LoadAllCustomShaders(); - HWR_CompileShaders(); - } - else if (HWR_UseShader() && !cv_grusecustomshaders.value) - HWR_CompileShaders(); -}*/ - static void CV_grpaletterendering_OnChange(void) { ONLY_IF_GL_LOADED @@ -6419,7 +6406,6 @@ void HWR_AddCommands(void) CV_RegisterVar(&cv_grshearing); CV_RegisterVar(&cv_grshaders); - //CV_RegisterVar(&cv_grusecustomshaders); CV_RegisterVar(&cv_grportals); CV_RegisterVar(&cv_nostencil); @@ -6453,9 +6439,7 @@ void HWR_Startup(void) gr_shadersavailable = HWR_InitShaders(); HWR_SetShaderState(); - - //if (cv_grusecustomshaders.value) - HWR_LoadAllCustomShaders(); + HWR_LoadAllCustomShaders(); HWR_TogglePaletteRendering(); diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index cf77942fc..0d63732e3 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -191,7 +191,6 @@ extern consvar_t cv_grhorizonlines; extern consvar_t cv_grfallbackplayermodel; extern consvar_t cv_grbatching; extern consvar_t cv_grrenderdistance; -//extern consvar_t cv_grusecustomshaders; extern consvar_t cv_grpaletterendering; extern consvar_t cv_grpalettedepth; extern consvar_t cv_grflashpal; diff --git a/src/hardware/hw_shaders.c b/src/hardware/hw_shaders.c index 7cf10fbe5..f9c755b0d 100644 --- a/src/hardware/hw_shaders.c +++ b/src/hardware/hw_shaders.c @@ -400,7 +400,7 @@ int HWR_GetShaderFromTarget(int shader_target) // - custom shaders are enabled // - custom shaders are allowed by the server if (custom_shader != -1 && gl_shaders[custom_shader].compiled && - cv_grshaders.value) + cv_grshaders.value == 1) return custom_shader; else return gl_shadertargets[shader_target].base_shader; @@ -456,9 +456,6 @@ void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3) if (!HWR_UseShader()) return; - - //if (!cv_grusecustomshaders.value) - //return; lump = HWR_FindShaderDefs(wadnum); if (lump == INT16_MAX) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 8637dcf09..ae3ba5c49 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -33,8 +33,7 @@ #include "../hw_main.h" #include "../hw_batching.h" -// Eeeeh not sure is this right way, but it works < sry :c -extern consvar_t cv_grusecustomshaders; +// Eeeeh not sure is this right way, but it works < sry :c < sry again it had to go :c extern fixed_t fovtan; // also extremely bad, I'm just too lazy!!! -- 2.54.0 From 0588442ae2fd01d815508562d0a44a2d3a04daf1 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 22 Jan 2024 18:32:13 +0100 Subject: [PATCH 23/24] change this --- src/hardware/hw_batching.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c index e58b2ba7f..388bb2023 100644 --- a/src/hardware/hw_batching.c +++ b/src/hardware/hw_batching.c @@ -158,10 +158,9 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt } else { - if (shader_target != -1) - HWD.pfnSetShader(HWR_GetShaderFromTarget(shader_target)); - HWD.pfnDrawPolygon(pSurf, pOutVerts, iNumPts, PolyFlags); - } + HWD.pfnSetShader((shader_target != SHADER_NONE) ? HWR_GetShaderFromTarget(shader_target) : shader_target); + HWD.pfnDrawPolygon(pSurf, pOutVerts, iNumPts, PolyFlags); + } } static int compareDrawCalls(const void *p1, const void *p2) -- 2.54.0 From c63142c8133a7c81c546c9953e2c4c1b3a16955f Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 22 Jan 2024 18:41:00 +0100 Subject: [PATCH 24/24] add hw_shaders to cmakelist --- src/CMakeLists.txt | 2 ++ src/hardware/hw_main.c | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d2985dc21..d4d684313 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -453,6 +453,7 @@ if(${SRB2_CONFIG_HWRENDER}) add_definitions(-DHWRENDER) set(SRB2_HWRENDER_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_batching.c + ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_shaders.c ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_bsp.c ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_cache.c ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.c @@ -469,6 +470,7 @@ if(${SRB2_CONFIG_HWRENDER}) set (SRB2_HWRENDER_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_batching.h + ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_shaders.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_data.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_defs.h diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 21aafa6f1..b0ed574ab 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -216,7 +216,7 @@ static void CV_grpalettedepth_OnChange(void) // void HWR_SetShaderState(void) { - HWD.pfnSetSpecialState(HWD_SET_SHADERS, HWR_UseShader()); + HWD.pfnSetSpecialState(HWD_SET_SHADERS, (INT32)HWR_UseShader()); } // ========================================================================== @@ -6263,8 +6263,7 @@ void HWR_RenderFrame(INT32 viewnumber, player_t *player, boolean skybox) HWR_ClearClipper(); // Reset the shader state. - //HWD.pfnSetSpecialState(HWD_SET_SHADERS, cv_grshaders.value); - //HWD.pfnSetShader(0); + //HWR_SetShaderState(); validcount++; -- 2.54.0