More Palette Rendering things #96

Merged
alufolie91 merged 26 commits from morenewpalshader into Saturn-Next 2024-02-01 00:57:31 +01:00
24 changed files with 2147 additions and 1760 deletions

No files matched your search

+4
View File
@@ -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
View File
@@ -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
-8
View File
@@ -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();
+462
View File
@@ -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 = &current->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(&currentDrawCall->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
+27
View File
@@ -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
View File
@@ -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);
+51
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+14
View File
@@ -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
View File
@@ -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
+4 -2
View File
@@ -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;
+1 -1
View File
@@ -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;
+630
View File
@@ -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
+298
View File
@@ -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
File diff suppressed because it is too large. Load diff
+1
View File
@@ -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
View File
@@ -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.",
+7
View File
@@ -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
{
+2
View File
@@ -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" />
+6
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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)