More Palette Rendering things #96
No files matched your search
@@ -452,6 +452,8 @@ 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_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
|
||||
@@ -467,6 +469,8 @@ 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
|
||||
|
||||
+1
-1
@@ -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 $(OBJDIR)/hw_shaders.o
|
||||
endif
|
||||
|
||||
OPTS += -DCOMPVERSION
|
||||
|
||||
@@ -1523,14 +1523,6 @@ void D_SRB2Main(void)
|
||||
HWR_AddCommands();
|
||||
#endif
|
||||
|
||||
#ifdef HWRENDER
|
||||
if (rendermode == render_opengl)
|
||||
{
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
HWR_LoadShaders(i, (wadfiles[i]->type == RET_PK3));
|
||||
}
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------- CONSOLE
|
||||
// setup loading screen
|
||||
SCR_Startup();
|
||||
|
||||
@@ -0,0 +1,462 @@
|
||||
// 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"
|
||||
|
||||
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;
|
||||
|
||||
// Dynamic arrays for:
|
||||
// - unsorted draw calls
|
||||
// - sorted order of draw calls
|
||||
// - unsorted vertices
|
||||
// - final (sorted) vertices
|
||||
// - vertex indices for sorted vertices
|
||||
|
||||
// contains the draw calls from DrawPolygon, waiting to be processed
|
||||
DrawCallInfo* drawCalls = NULL;
|
||||
int drawCallsSize = 0;
|
||||
int drawCallsCapacity = 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.
|
||||
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 (!finalVertices)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
static void HWR_CollectDrawCallInfo(FSurfaceInfo *pSurf, FUINT iNumPts, FBITFIELD PolyFlags, int shader_target, 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_target != -1) ? HWR_GetShaderFromTarget(shader_target) : shader_target;
|
||||
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
|
||||
// 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_target, boolean horizonSpecial)
|
||||
{
|
||||
if (currently_batching)
|
||||
{
|
||||
if (!pSurf)
|
||||
{
|
||||
// handling null FSurfaceInfo is not implemented
|
||||
I_Error("Got a null FSurfaceInfo in batching");
|
||||
}
|
||||
|
||||
HWR_CollectDrawCallInfo(pSurf, iNumPts, PolyFlags, shader_target, horizonSpecial);
|
||||
HWR_CollectDrawCallVertices(pOutVerts, iNumPts);
|
||||
}
|
||||
else
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
|
||||
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 compareDrawCallsNoShaders(const void *p1, const void *p2)
|
||||
{
|
||||
UINT32 index1 = *(const UINT32*)p1;
|
||||
UINT32 index2 = *(const UINT32*)p2;
|
||||
DrawCallInfo* poly1 = &drawCalls[index1];
|
||||
DrawCallInfo* poly2 = &drawCalls[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;
|
||||
}
|
||||
|
||||
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 drawCallReadPos = 0; // position in drawCallOrder
|
||||
int i;
|
||||
|
||||
if (!currently_batching)
|
||||
I_Error("HWR_RenderBatches called without starting batching");
|
||||
|
||||
currently_batching = false; // no longer collecting batches
|
||||
|
||||
HWR_InitBatchingStats();
|
||||
|
||||
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(drawCallOrder, drawCallsSize, sizeof(UINT32), compareDrawCalls);
|
||||
else
|
||||
qsort(drawCallOrder, drawCallsSize, sizeof(UINT32), compareDrawCallsNoShaders);
|
||||
PS_STOP_TIMING(ps_hw_batchsorttime);
|
||||
// sort grouping 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);
|
||||
|
||||
// set state for first batch
|
||||
HWR_ExecuteStateChanges(0xFFFF, &drawCalls[drawCallOrder[0]]);
|
||||
|
||||
// - 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)
|
||||
{
|
||||
boolean stopFlag = false;
|
||||
unsigned int stateChanges = 0; // flags defined above HWR_MarkStateChanges
|
||||
DrawCallInfo *currentDrawCall = &drawCalls[drawCallOrder[drawCallReadPos++]];
|
||||
DrawCallInfo *nextDrawCall = NULL;
|
||||
|
||||
HWR_CollectVerticesIntoBatch(currentDrawCall);
|
||||
|
||||
if (drawCallReadPos >= drawCallsSize) // was that the last draw call?
|
||||
{
|
||||
stopFlag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextDrawCall = &drawCalls[drawCallOrder[drawCallReadPos]];
|
||||
stateChanges = HWR_MarkStateChanges(currentDrawCall, nextDrawCall);
|
||||
}
|
||||
|
||||
if (stateChanges || stopFlag)
|
||||
{
|
||||
// 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 += finalIndicesSize;
|
||||
// reset final geometry collection arrays
|
||||
finalVerticesSize = 0;
|
||||
finalIndicesSize = 0;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
// if we're here then either its time to stop or time to change state
|
||||
if (stopFlag)
|
||||
break;
|
||||
else
|
||||
HWR_ExecuteStateChanges(stateChanges, nextDrawCall);
|
||||
}
|
||||
// reset the arrays (set sizes to 0)
|
||||
drawCallsSize = 0;
|
||||
unsortedVerticesSize = 0;
|
||||
|
||||
PS_STOP_TIMING(ps_hw_batchdrawtime);
|
||||
}
|
||||
|
||||
#endif // HWRENDER
|
||||
@@ -0,0 +1,27 @@
|
||||
// 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"
|
||||
|
||||
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
|
||||
+21
-5
@@ -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
|
||||
@@ -592,7 +593,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);
|
||||
@@ -676,7 +681,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);
|
||||
@@ -702,8 +711,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);
|
||||
@@ -733,7 +745,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);
|
||||
|
||||
@@ -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
|
||||
// ==========================================================================
|
||||
@@ -288,4 +328,15 @@ 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, // palette-based colormap fade, final screen texture
|
||||
NUMSCREENTEXTURES, // (generic3 is unused if palette rendering is disabled)
|
||||
};
|
||||
typedef enum hwdscreentexture hwdscreentexture_t;
|
||||
|
||||
#endif //_HWR_DEFS_
|
||||
+35
-15
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -562,8 +563,25 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength)
|
||||
|
||||
if (color & 0xFF00) // Do COLORMAP fade.
|
||||
{
|
||||
Surf.PolyColor.rgba = UINT2RGBA(0x01010160);
|
||||
Surf.PolyColor.s.alpha = (strength*8);
|
||||
if (HWR_ShouldUsePaletteRendering() && cv_grscreentextures.value)
|
||||
{
|
||||
const hwdscreentexture_t scr_tex = HWD_SCREENTEXTURE_GENERIC2;
|
||||
|
||||
Surf.LightTableId = HWR_GetLightTableID(NULL);
|
||||
Surf.LightInfo.light_level = strength;
|
||||
HWD.pfnMakeScreenTexture(scr_tex);
|
||||
HWD.pfnSetShader(HWR_GetShaderFromTarget(SHADER_UI_COLORMAP_FADE));
|
||||
HWD.pfnDrawScreenTexture(scr_tex, &Surf, PF_ColorMapped|PF_NoDepthTest);
|
||||
HWD.pfnUnSetShader();
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Surf.PolyColor.rgba = UINT2RGBA(0x01010160);
|
||||
Surf.PolyColor.s.alpha = (strength*8);
|
||||
poly_flags |= PF_Translucent;
|
||||
}
|
||||
}
|
||||
else // Do TRANSMAP** fade.
|
||||
{
|
||||
@@ -574,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, false);
|
||||
HWD.pfnDrawPolygon(&Surf, v, 4, poly_flags);
|
||||
}
|
||||
|
||||
// Draw the console background with translucency support
|
||||
@@ -603,7 +623,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -854,7 +874,7 @@ void HWR_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 color)
|
||||
Surf.PolyColor = palette[color&0xFF];
|
||||
|
||||
HWD.pfnDrawPolygon(&Surf, v, 4,
|
||||
PF_Modulated|PF_NoTexture|PF_NoDepthTest, false);
|
||||
PF_Modulated|PF_NoTexture|PF_NoDepthTest);
|
||||
}
|
||||
|
||||
// -------------------+
|
||||
@@ -963,7 +983,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);
|
||||
}
|
||||
|
||||
// -----------------+
|
||||
@@ -1081,7 +1101,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
|
||||
@@ -1165,7 +1185,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(HWD_SCREENTEXTURE_GENERIC2, (void *)buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
@@ -1181,7 +1201,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(HWD_SCREENTEXTURE_GENERIC2, (void *)buf);
|
||||
|
||||
#ifdef USE_PNG
|
||||
ret = M_SavePNG(pathname, buf, vid.width, vid.height, NULL);
|
||||
|
||||
+19
-30
@@ -32,12 +32,13 @@ EXPORT void HWRAPI(SetupGLInfo) (void);
|
||||
EXPORT void HWRAPI(SetTexturePalette) (RGBA_t *ppal);
|
||||
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);
|
||||
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);
|
||||
|
||||
@@ -55,30 +56,24 @@ 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, FSurfaceInfo *surf, FBITFIELD polyflags);
|
||||
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]);
|
||||
|
||||
// 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(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(SetPaletteLookup)(UINT8 *lut);
|
||||
EXPORT UINT32 HWRAPI(CreateLightTable)(RGBA_t *hw_lighttable);
|
||||
@@ -99,11 +94,12 @@ struct hwdriver_s
|
||||
FinishUpdate pfnFinishUpdate;
|
||||
Draw2DLine pfnDraw2DLine;
|
||||
DrawPolygon pfnDrawPolygon;
|
||||
DrawIndexedTriangles pfnDrawIndexedTriangles;
|
||||
SetBlend pfnSetBlend;
|
||||
ClearBuffer pfnClearBuffer;
|
||||
SetTexture pfnSetTexture;
|
||||
UpdateTexture pfnUpdateTexture;
|
||||
ReadRect pfnReadRect;
|
||||
ReadScreenTexture pfnReadScreenTexture;
|
||||
GClipRect pfnGClipRect;
|
||||
ClearMipMapCache pfnClearMipMapCache;
|
||||
SetSpecialState pfnSetSpecialState;
|
||||
@@ -113,29 +109,22 @@ 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;
|
||||
|
||||
LoadShaders pfnLoadShaders;
|
||||
KillShaders pfnKillShaders;
|
||||
InitShaders pfnInitShaders;
|
||||
LoadShader pfnLoadShader;
|
||||
CompileShader pfnCompileShader;
|
||||
SetShader pfnSetShader;
|
||||
UnSetShader pfnUnSetShader;
|
||||
|
||||
SetShaderInfo pfnSetShaderInfo;
|
||||
LoadCustomShader pfnLoadCustomShader;
|
||||
InitCustomShaders pfnInitCustomShaders;
|
||||
|
||||
StartBatching pfnStartBatching;
|
||||
RenderBatches pfnRenderBatches;
|
||||
|
||||
SetPaletteLookup pfnSetPaletteLookup;
|
||||
CreateLightTable pfnCreateLightTable;
|
||||
ClearLightTables pfnClearLightTables;
|
||||
|
||||
@@ -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_
|
||||
+111
-253
@@ -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"
|
||||
@@ -57,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;
|
||||
@@ -70,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);
|
||||
@@ -89,10 +89,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};
|
||||
|
||||
@@ -111,7 +111,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};
|
||||
@@ -120,10 +120,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,8 +142,8 @@ static INT32 current_bsp_culling_distance = 0;
|
||||
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};
|
||||
|
||||
@@ -162,57 +162,63 @@ 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)
|
||||
ONLY_IF_GL_LOADED
|
||||
HWD.pfnSetSpecialState(HWD_SET_TEXTUREFILTERMODE, cv_grfiltermode.value);
|
||||
}
|
||||
|
||||
static void CV_anisotropic_ONChange(void)
|
||||
{
|
||||
if (rendermode == render_opengl)
|
||||
ONLY_IF_GL_LOADED
|
||||
HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_granisotropicmode.value);
|
||||
}
|
||||
|
||||
static void CV_screentextures_ONChange(void)
|
||||
{
|
||||
if (rendermode == render_opengl)
|
||||
ONLY_IF_GL_LOADED
|
||||
HWD.pfnSetSpecialState(HWD_SET_SCREEN_TEXTURES, cv_grscreentextures.value);
|
||||
}
|
||||
|
||||
static void CV_grshaders_OnChange(void)
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
static void CV_grpaletterendering_OnChange(void)
|
||||
{
|
||||
if ((rendermode == render_opengl) && (gr_shadersavailable))
|
||||
ONLY_IF_GL_LOADED
|
||||
if (gr_shadersavailable)
|
||||
{
|
||||
HWR_CompileShaders();
|
||||
HWR_TogglePaletteRendering();
|
||||
}
|
||||
}
|
||||
|
||||
static void CV_grpalettedepth_OnChange(void)
|
||||
{
|
||||
if ((rendermode == render_opengl) && (HWR_ShouldUsePaletteRendering()))
|
||||
ONLY_IF_GL_LOADED
|
||||
if (HWR_ShouldUsePaletteRendering())
|
||||
HWR_SetPalette(pLocalPalette);
|
||||
}
|
||||
|
||||
//
|
||||
// Sets the shader state.
|
||||
//
|
||||
void HWR_SetShaderState(void)
|
||||
{
|
||||
HWD.pfnSetSpecialState(HWD_SET_SHADERS, (INT32)HWR_UseShader());
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// Globals
|
||||
// ==========================================================================
|
||||
@@ -650,6 +656,8 @@ void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isc
|
||||
|
||||
static FOutVector *planeVerts = NULL;
|
||||
static UINT16 numAllocedPlaneVerts = 0;
|
||||
|
||||
INT32 shader = SHADER_NONE;
|
||||
|
||||
// no convex poly were generated for this subsector
|
||||
if (!xsub->planepoly)
|
||||
@@ -827,16 +835,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 = SHADER_FOG; // fog shader
|
||||
else if (PolyFlags & PF_Ripple)
|
||||
HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 11 : 5); // water shader
|
||||
shader = SHADER_WATER; // water shader
|
||||
else
|
||||
HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 9 : 1); // floor shader
|
||||
shader = SHADER_FLOOR; // floor shader
|
||||
|
||||
PolyFlags |= PF_ColorMapped;
|
||||
}
|
||||
|
||||
HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags, false);
|
||||
HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags, shader, false);
|
||||
|
||||
if (subsector && cv_grhorizonlines.value)
|
||||
{
|
||||
@@ -921,7 +929,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -937,6 +945,8 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf)
|
||||
fixed_t i;
|
||||
// seg bbox
|
||||
fixed_t segbbox[4];
|
||||
|
||||
INT32 shader = SHADER_NONE;
|
||||
|
||||
M_ClearBox(segbbox);
|
||||
M_AddToBox(segbbox,
|
||||
@@ -989,11 +999,9 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf)
|
||||
}
|
||||
|
||||
if (HWR_UseShader())
|
||||
{
|
||||
HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader
|
||||
}
|
||||
shader = SHADER_WALL; // wall shader
|
||||
|
||||
HWD.pfnDrawPolygon(&pSurf, wallVerts, 4, i|PF_Modulated|PF_Decal, false);
|
||||
HWR_ProcessPolygon(&pSurf, wallVerts, 4, i|PF_Modulated|PF_Decal, shader, false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1024,11 +1032,13 @@ FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf)
|
||||
//
|
||||
void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blendmode, INT32 lightlevel, extracolormap_t *wallcolormap)
|
||||
{
|
||||
INT32 shader = SHADER_NONE;
|
||||
|
||||
HWR_Lighting(pSurf, lightlevel, wallcolormap);
|
||||
|
||||
if (HWR_UseShader())
|
||||
{
|
||||
HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader
|
||||
shader = SHADER_WALL; // wall shader
|
||||
blendmode |= PF_ColorMapped;
|
||||
}
|
||||
|
||||
@@ -1039,7 +1049,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)
|
||||
@@ -1395,11 +1405,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1420,7 +1430,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
|
||||
@@ -3115,6 +3125,8 @@ void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t
|
||||
|
||||
static FOutVector *planeVerts = NULL;
|
||||
static UINT16 numAllocedPlaneVerts = 0;
|
||||
|
||||
INT32 shader = SHADER_NONE;
|
||||
|
||||
nrPlaneVerts = polysector->numVertices;
|
||||
|
||||
@@ -3260,11 +3272,11 @@ void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t
|
||||
|
||||
if (HWR_UseShader())
|
||||
{
|
||||
HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 9 : 1); // floor shader
|
||||
shader = SHADER_FLOOR; // 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)
|
||||
@@ -3920,6 +3932,8 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t
|
||||
fixed_t slopez;
|
||||
float offset = 0;
|
||||
|
||||
INT32 shader = SHADER_NONE;
|
||||
|
||||
R_GetShadowZ(spr->mobj, &floorslope);
|
||||
|
||||
mobjfloor = HWR_OpaqueFloorAtPos(
|
||||
@@ -4069,10 +4083,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 = SHADER_FLOOR; // floor shader
|
||||
}
|
||||
|
||||
HWD.pfnDrawPolygon(&sSurf, swallVerts, 4, PF_Translucent|PF_Modulated, false);
|
||||
|
||||
HWR_ProcessPolygon(&sSurf, swallVerts, 4, PF_Translucent|PF_Modulated, shader, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4168,6 +4182,8 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
|
||||
fixed_t v1x, v1y, v2x, v2y;
|
||||
#endif
|
||||
|
||||
INT32 shader = SHADER_NONE;
|
||||
|
||||
this_scale = FIXED_TO_FLOAT(spr->mobj->scale);
|
||||
|
||||
if (hires)
|
||||
@@ -4441,11 +4457,11 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
|
||||
|
||||
if (HWR_UseShader())
|
||||
{
|
||||
HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader
|
||||
shader = SHADER_SPRITE; // 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
|
||||
@@ -4486,11 +4502,11 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
|
||||
|
||||
if (HWR_UseShader())
|
||||
{
|
||||
HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader
|
||||
shader = SHADER_SPRITE; // 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
|
||||
}
|
||||
|
||||
// -----------------+
|
||||
@@ -4504,6 +4520,9 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
|
||||
FOutVector wallVerts[4];
|
||||
GLPatch_t *gpatch; // sprite patch converted to hardware
|
||||
FSurfaceInfo Surf;
|
||||
|
||||
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)
|
||||
this_scale = FIXED_TO_FLOAT(spr->mobj->scale);
|
||||
@@ -4644,11 +4663,11 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
|
||||
|
||||
if (HWR_UseShader())
|
||||
{
|
||||
HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader
|
||||
shader = SHADER_SPRITE; // sprite shader
|
||||
blend |= PF_ColorMapped;
|
||||
}
|
||||
|
||||
HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, false);
|
||||
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, shader, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4659,6 +4678,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 = SHADER_NONE;
|
||||
|
||||
if (!spr->mobj)
|
||||
return;
|
||||
@@ -4743,11 +4764,11 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr)
|
||||
|
||||
if (HWR_UseShader())
|
||||
{
|
||||
HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader
|
||||
shader = SHADER_SPRITE; // sprite shader
|
||||
blend |= PF_ColorMapped;
|
||||
}
|
||||
|
||||
HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, false);
|
||||
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, shader, false);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -5774,9 +5795,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -6044,8 +6065,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;
|
||||
@@ -6066,14 +6088,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);
|
||||
@@ -6245,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++;
|
||||
|
||||
@@ -6363,7 +6380,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);
|
||||
@@ -6388,7 +6405,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);
|
||||
@@ -6399,7 +6415,7 @@ void HWR_AddCommands(void)
|
||||
|
||||
CV_RegisterVar(&cv_grpaletterendering);
|
||||
CV_RegisterVar(&cv_grpalettedepth);
|
||||
CV_RegisterVar(&cv_grflashpal);
|
||||
CV_RegisterVar(&cv_grflashpal);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -6419,24 +6435,22 @@ void HWR_Startup(void)
|
||||
HWR_InitMD2();
|
||||
|
||||
HWD.pfnSetupGLInfo();
|
||||
}
|
||||
|
||||
gr_shadersavailable = HWR_InitShaders();
|
||||
HWR_SetShaderState();
|
||||
HWR_LoadAllCustomShaders();
|
||||
|
||||
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_TogglePaletteRendering();
|
||||
|
||||
if (msaa)
|
||||
{
|
||||
if (a2c)
|
||||
HWD.pfnSetSpecialState(HWD_SET_MSAA, 2);
|
||||
else
|
||||
HWD.pfnSetSpecialState(HWD_SET_MSAA, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -6454,6 +6468,8 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend,
|
||||
{
|
||||
FBITFIELD blendmode = blend;
|
||||
UINT8 alpha = pSurf->PolyColor.s.alpha; // retain the alpha
|
||||
|
||||
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);
|
||||
@@ -6466,7 +6482,7 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend,
|
||||
if (fogwall)
|
||||
{
|
||||
blendmode |= PF_Fog;
|
||||
HWD.pfnSetShader(6); // fog shader
|
||||
shader = SHADER_FOG; // fog shader
|
||||
}
|
||||
|
||||
blendmode |= PF_Modulated; // No PF_Occlude means overlapping (incorrect) transparency
|
||||
@@ -6475,12 +6491,12 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend,
|
||||
{
|
||||
if (HWR_UseShader())
|
||||
{
|
||||
HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader
|
||||
shader = SHADER_WALL; // 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)
|
||||
@@ -6531,7 +6547,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
|
||||
@@ -6539,7 +6555,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;
|
||||
@@ -6583,24 +6599,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, NULL, 0);
|
||||
}
|
||||
|
||||
void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum)
|
||||
@@ -6628,7 +6644,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)
|
||||
@@ -6638,169 +6654,11 @@ void HWR_RenderVhsEffect(fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT
|
||||
|
||||
void HWR_MakeScreenFinalTexture(void)
|
||||
{
|
||||
HWD.pfnMakeScreenFinalTexture();
|
||||
HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_GENERIC2);
|
||||
}
|
||||
|
||||
void HWR_DrawScreenFinalTexture(int width, int height)
|
||||
{
|
||||
HWD.pfnDrawScreenFinalTexture(width, 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
|
||||
@@ -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);
|
||||
@@ -83,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);
|
||||
@@ -165,6 +166,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;
|
||||
@@ -188,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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -0,0 +1,630 @@
|
||||
// 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.c
|
||||
/// \brief Handles the shaders used by the game.
|
||||
|
||||
#ifdef HWRENDER
|
||||
|
||||
#include "hw_main.h"
|
||||
#include "hw_glob.h"
|
||||
#include "hw_drv.h"
|
||||
#include "hw_shaders.h"
|
||||
#include "../z_zone.h"
|
||||
|
||||
// ================
|
||||
// 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 == 1)
|
||||
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;
|
||||
|
||||
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
|
||||
@@ -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
|
||||
+415
-1377
File diff suppressed because it is too large.
Load diff
@@ -46,6 +46,7 @@
|
||||
#define _CREATE_DLL_ // necessary for Unix AND Windows
|
||||
#include "../../doomdef.h"
|
||||
#include "../hw_drv.h"
|
||||
#include "../../z_zone.h"
|
||||
|
||||
// ==========================================================================
|
||||
// DEFINITIONS
|
||||
|
||||
+13
-10
@@ -1484,20 +1484,22 @@ 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, "Palette Depth", &cv_grpalettedepth, 85},
|
||||
|
||||
{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, "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
|
||||
};
|
||||
|
||||
@@ -1511,7 +1513,8 @@ 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.",
|
||||
"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.",
|
||||
"Toggle for FOF wall cutoff with slopes.",
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -218,6 +218,7 @@
|
||||
<ClInclude Include="..\hardware\hw3dsdrv.h" />
|
||||
<ClInclude Include="..\hardware\hw3sound.h" />
|
||||
<ClInclude Include="..\hardware\hws_data.h" />
|
||||
<ClInclude Include="..\hardware\hw_batching.h" />
|
||||
<ClInclude Include="..\hardware\hw_clip.h" />
|
||||
<ClInclude Include="..\hardware\hw_data.h" />
|
||||
<ClInclude Include="..\hardware\hw_defs.h" />
|
||||
@@ -364,6 +365,7 @@
|
||||
<ClCompile Include="..\g_game.c" />
|
||||
<ClCompile Include="..\g_input.c" />
|
||||
<ClCompile Include="..\hardware\hw3sound.c" />
|
||||
<ClCompile Include="..\hardware\hw_batching.c" />
|
||||
<ClCompile Include="..\hardware\hw_bsp.c" />
|
||||
<ClCompile Include="..\hardware\hw_cache.c" />
|
||||
<ClCompile Include="..\hardware\hw_clip.c" />
|
||||
|
||||
@@ -215,6 +215,9 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\hardware\hws_data.h">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\hardware\hw_batching.h">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\hardware\hw_clip.h">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
@@ -617,6 +620,9 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\hardware\hw3sound.c">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\hardware\hw_batching.c">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\hardware\hw_bsp.c">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
|
||||
+6
-12
@@ -81,11 +81,12 @@ void *hwSym(const char *funcName,void *handle)
|
||||
GETFUNC(SetupGLInfo);
|
||||
GETFUNC(Draw2DLine);
|
||||
GETFUNC(DrawPolygon);
|
||||
GETFUNC(DrawIndexedTriangles);
|
||||
GETFUNC(SetBlend);
|
||||
GETFUNC(ClearBuffer);
|
||||
GETFUNC(SetTexture);
|
||||
GETFUNC(UpdateTexture);
|
||||
GETFUNC(ReadRect);
|
||||
GETFUNC(ReadScreenTexture);
|
||||
GETFUNC(GClipRect);
|
||||
GETFUNC(ClearMipMapCache);
|
||||
GETFUNC(SetSpecialState);
|
||||
@@ -95,28 +96,21 @@ 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);
|
||||
|
||||
GETFUNC(LoadShaders);
|
||||
GETFUNC(KillShaders);
|
||||
GETFUNC(InitShaders);
|
||||
GETFUNC(LoadShader);
|
||||
GETFUNC(CompileShader);
|
||||
GETFUNC(SetShader);
|
||||
GETFUNC(UnSetShader);
|
||||
|
||||
GETFUNC(SetShaderInfo);
|
||||
GETFUNC(LoadCustomShader);
|
||||
GETFUNC(InitCustomShaders);
|
||||
|
||||
GETFUNC(StartBatching);
|
||||
GETFUNC(RenderBatches);
|
||||
|
||||
GETFUNC(SetPaletteLookup);
|
||||
GETFUNC(CreateLightTable);
|
||||
|
||||
+17
-33
@@ -1483,18 +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())
|
||||
{
|
||||
// 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
|
||||
|
||||
OglSdlFinishUpdate(cv_vidwait.value);
|
||||
}
|
||||
#endif
|
||||
@@ -1799,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)
|
||||
{
|
||||
@@ -1814,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,
|
||||
@@ -1833,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)
|
||||
@@ -2125,11 +2112,12 @@ 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);
|
||||
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);
|
||||
@@ -2140,36 +2128,32 @@ 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);
|
||||
|
||||
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.pfnStartBatching = hwSym("StartBatching",NULL);
|
||||
HWD.pfnRenderBatches = hwSym("RenderBatches",NULL);
|
||||
|
||||
HWD.pfnSetPaletteLookup = hwSym("SetPaletteLookup",NULL);
|
||||
HWD.pfnCreateLightTable = hwSym("CreateLightTable",NULL);
|
||||
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
-13
@@ -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)
|
||||
|
||||
Reference in new issue
Block a user