Replace Karts Batching with SRB2´s #90
No files matched your search
@@ -452,6 +452,7 @@ endif()
|
||||
if(${SRB2_CONFIG_HWRENDER})
|
||||
add_definitions(-DHWRENDER)
|
||||
set(SRB2_HWRENDER_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_batching.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_bsp.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_cache.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.c
|
||||
@@ -467,6 +468,7 @@ if(${SRB2_CONFIG_HWRENDER})
|
||||
)
|
||||
|
||||
set (SRB2_HWRENDER_HEADERS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_batching.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_data.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_defs.h
|
||||
|
||||
+1
-1
@@ -275,7 +275,7 @@ else
|
||||
OPTS+=-DHWRENDER
|
||||
OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \
|
||||
$(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o \
|
||||
$(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o
|
||||
$(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o $(OBJDIR)/hw_batching.o
|
||||
endif
|
||||
|
||||
OPTS += -DCOMPVERSION
|
||||
|
||||
@@ -0,0 +1,463 @@
|
||||
// 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, boolean horizonSpecial)
|
||||
{
|
||||
// make sure dynamic array has capacity
|
||||
if (drawCallsSize == drawCallsCapacity)
|
||||
{
|
||||
DrawCallInfo* new_array;
|
||||
// ran out of space, make new array double the size
|
||||
drawCallsCapacity *= 2;
|
||||
new_array = malloc(drawCallsCapacity * sizeof(DrawCallInfo));
|
||||
memcpy(new_array, drawCalls, drawCallsSize * sizeof(DrawCallInfo));
|
||||
free(drawCalls);
|
||||
drawCalls = new_array;
|
||||
// also need to redo the index array, dont need to copy it though
|
||||
free(drawCallOrder);
|
||||
drawCallOrder = malloc(drawCallsCapacity * sizeof(UINT32));
|
||||
}
|
||||
// add entry to array
|
||||
drawCalls[drawCallsSize].surf = *pSurf;
|
||||
drawCalls[drawCallsSize].vertsIndex = unsortedVerticesSize;
|
||||
drawCalls[drawCallsSize].numVerts = iNumPts;
|
||||
drawCalls[drawCallsSize].polyFlags = PolyFlags;
|
||||
drawCalls[drawCallsSize].texture = current_texture;
|
||||
drawCalls[drawCallsSize].shader = shader;
|
||||
drawCalls[drawCallsSize].horizonSpecial = horizonSpecial;
|
||||
drawCallsSize++;
|
||||
}
|
||||
|
||||
static void HWR_CollectDrawCallVertices(FOutVector *pOutVerts, FUINT iNumPts)
|
||||
{
|
||||
// make sure dynamic array has capacity
|
||||
while (unsortedVerticesSize + (int)iNumPts > unsortedVerticesCapacity)
|
||||
{
|
||||
FOutVector* new_array;
|
||||
// need more space for vertices in unsortedVertices
|
||||
unsortedVerticesCapacity *= 2;
|
||||
new_array = malloc(unsortedVerticesCapacity * sizeof(FOutVector));
|
||||
memcpy(new_array, unsortedVertices, unsortedVerticesSize * sizeof(FOutVector));
|
||||
free(unsortedVertices);
|
||||
unsortedVertices = new_array;
|
||||
}
|
||||
// add vertices to array
|
||||
memcpy(&unsortedVertices[unsortedVerticesSize], pOutVerts, iNumPts * sizeof(FOutVector));
|
||||
unsortedVerticesSize += iNumPts;
|
||||
}
|
||||
|
||||
// If batching is enabled, this function collects the polygon data and the chosen texture
|
||||
// for later use in HWR_RenderBatches. Otherwise the rendering backend is used to
|
||||
// render the polygon immediately.
|
||||
void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial)
|
||||
{
|
||||
if (currently_batching)
|
||||
{
|
||||
if (!pSurf)
|
||||
{
|
||||
// handling null FSurfaceInfo is not implemented
|
||||
I_Error("Got a null FSurfaceInfo in batching");
|
||||
}
|
||||
|
||||
HWR_CollectDrawCallInfo(pSurf, iNumPts, PolyFlags, shader, horizonSpecial);
|
||||
HWR_CollectDrawCallVertices(pOutVerts, iNumPts);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (shader)
|
||||
HWD.pfnSetShader(shader);
|
||||
HWD.pfnDrawPolygon(pSurf, pOutVerts, iNumPts, PolyFlags);
|
||||
}
|
||||
}
|
||||
|
||||
static int compareDrawCalls(const void *p1, const void *p2)
|
||||
{
|
||||
UINT32 index1 = *(const UINT32*)p1;
|
||||
UINT32 index2 = *(const UINT32*)p2;
|
||||
DrawCallInfo* poly1 = &drawCalls[index1];
|
||||
DrawCallInfo* poly2 = &drawCalls[index2];
|
||||
int diff;
|
||||
INT64 diff64;
|
||||
UINT32 downloaded1 = 0;
|
||||
UINT32 downloaded2 = 0;
|
||||
|
||||
int shader1 = poly1->shader;
|
||||
int shader2 = poly2->shader;
|
||||
// make skywalls and horizon lines first in order
|
||||
if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial)
|
||||
shader1 = -1;
|
||||
if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial)
|
||||
shader2 = -1;
|
||||
diff = shader1 - shader2;
|
||||
if (diff != 0) return diff;
|
||||
|
||||
// skywalls and horizon lines must retain their order for horizon lines to work
|
||||
if (shader1 == -1 && shader2 == -1)
|
||||
return index1 - index2;
|
||||
|
||||
if (poly1->texture)
|
||||
downloaded1 = poly1->texture->downloaded; // there should be a opengl texture name here, usable for comparisons
|
||||
if (poly2->texture)
|
||||
downloaded2 = poly2->texture->downloaded;
|
||||
diff64 = downloaded1 - downloaded2;
|
||||
if (diff64 != 0) return diff64;
|
||||
|
||||
diff = poly1->polyFlags - poly2->polyFlags;
|
||||
if (diff != 0) return diff;
|
||||
|
||||
diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba;
|
||||
if (diff64 < 0) return -1; else if (diff64 > 0) return 1;
|
||||
diff64 = poly1->surf.TintColor.rgba - poly2->surf.TintColor.rgba;
|
||||
if (diff64 < 0) return -1; else if (diff64 > 0) return 1;
|
||||
diff64 = poly1->surf.FadeColor.rgba - poly2->surf.FadeColor.rgba;
|
||||
if (diff64 < 0) return -1; else if (diff64 > 0) return 1;
|
||||
|
||||
diff = poly1->surf.LightInfo.light_level - poly2->surf.LightInfo.light_level;
|
||||
if (diff != 0) return diff;
|
||||
diff = poly1->surf.LightInfo.fade_start - poly2->surf.LightInfo.fade_start;
|
||||
if (diff != 0) return diff;
|
||||
diff = poly1->surf.LightInfo.fade_end - poly2->surf.LightInfo.fade_end;
|
||||
return diff;
|
||||
}
|
||||
|
||||
static int compareDrawCallsNoShaders(const void *p1, const void *p2)
|
||||
{
|
||||
UINT32 index1 = *(const UINT32*)p1;
|
||||
UINT32 index2 = *(const UINT32*)p2;
|
||||
DrawCallInfo* poly1 = &drawCalls[index1];
|
||||
DrawCallInfo* poly2 = &drawCalls[index2];
|
||||
int diff;
|
||||
INT64 diff64;
|
||||
|
||||
GLMipmap_t *texture1 = poly1->texture;
|
||||
GLMipmap_t *texture2 = poly2->texture;
|
||||
UINT32 downloaded1 = 0;
|
||||
UINT32 downloaded2 = 0;
|
||||
if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial)
|
||||
texture1 = NULL;
|
||||
if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial)
|
||||
texture2 = NULL;
|
||||
if (texture1)
|
||||
downloaded1 = texture1->downloaded; // there should be a opengl texture name here, usable for comparisons
|
||||
if (texture2)
|
||||
downloaded2 = texture2->downloaded;
|
||||
// skywalls and horizon lines must retain their order for horizon lines to work
|
||||
if (!texture1 && !texture2)
|
||||
return index1 - index2;
|
||||
diff64 = downloaded1 - downloaded2;
|
||||
if (diff64 != 0) return diff64;
|
||||
|
||||
diff = poly1->polyFlags - poly2->polyFlags;
|
||||
if (diff != 0) return diff;
|
||||
|
||||
diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba;
|
||||
if (diff64 < 0) return -1; else if (diff64 > 0) return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void HWR_CollectVerticesIntoBatch(DrawCallInfo *drawCall)
|
||||
{
|
||||
int firstVIndex;
|
||||
int lastVIndex;
|
||||
int numVerts = drawCall->numVerts;
|
||||
// before writing, check if there is enough room
|
||||
// using 'while' instead of 'if' here makes sure that there will *always* be enough room.
|
||||
// probably never will this loop run more than once though
|
||||
while (finalVerticesSize + numVerts > finalVerticesCapacity)
|
||||
{
|
||||
FOutVector* new_array;
|
||||
UINT32* new_index_array;
|
||||
finalVerticesCapacity *= 2;
|
||||
new_array = malloc(finalVerticesCapacity * sizeof(FOutVector));
|
||||
memcpy(new_array, finalVertices, finalVerticesSize * sizeof(FOutVector));
|
||||
free(finalVertices);
|
||||
finalVertices = new_array;
|
||||
// also increase size of index array, 3x of vertex array since
|
||||
// going from fans to triangles increases vertex count to 3x
|
||||
new_index_array = malloc(finalVerticesCapacity * 3 * sizeof(UINT32));
|
||||
memcpy(new_index_array, finalIndices, finalIndicesSize * sizeof(UINT32));
|
||||
free(finalIndices);
|
||||
finalIndices = new_index_array;
|
||||
}
|
||||
// write the vertices of the polygon
|
||||
memcpy(&finalVertices[finalVerticesSize], &unsortedVertices[drawCall->vertsIndex],
|
||||
numVerts * sizeof(FOutVector));
|
||||
// write the indexes, pointing to the fan vertexes but in triangles format
|
||||
firstVIndex = finalVerticesSize;
|
||||
lastVIndex = finalVerticesSize + numVerts;
|
||||
finalVerticesSize += 2;
|
||||
while (finalVerticesSize < lastVIndex)
|
||||
{
|
||||
finalIndices[finalIndicesSize++] = firstVIndex;
|
||||
finalIndices[finalIndicesSize++] = finalVerticesSize - 1;
|
||||
finalIndices[finalIndicesSize++] = finalVerticesSize++;
|
||||
}
|
||||
}
|
||||
|
||||
static GLMipmap_t *HWR_GetDrawCallTexture(DrawCallInfo *dc)
|
||||
{
|
||||
return (dc->polyFlags & PF_NoTexture) ? NULL : dc->texture;
|
||||
}
|
||||
|
||||
// flags returned by HWR_MarkStateChanges
|
||||
#define SHADER_CHANGED 1
|
||||
#define TEXTURE_CHANGED 2
|
||||
#define POLYFLAGS_CHANGED 4
|
||||
#define SURFACEINFO_CHANGED 8
|
||||
|
||||
static unsigned int HWR_MarkStateChanges(DrawCallInfo *current, DrawCallInfo *next)
|
||||
{
|
||||
unsigned int stateChanges = 0;
|
||||
FSurfaceInfo *currentSI = ¤t->surf;
|
||||
FSurfaceInfo *nextSI = &next->surf;
|
||||
|
||||
// check if a state change is required and flag it to stateChanges
|
||||
|
||||
if (current->shader != next->shader && cv_grshaders.value && gr_shadersavailable)
|
||||
stateChanges |= SHADER_CHANGED;
|
||||
if (HWR_GetDrawCallTexture(current) != HWR_GetDrawCallTexture(next))
|
||||
stateChanges |= TEXTURE_CHANGED;
|
||||
if (current->polyFlags != next->polyFlags)
|
||||
stateChanges |= POLYFLAGS_CHANGED;
|
||||
if (cv_grshaders.value && gr_shadersavailable)
|
||||
{
|
||||
if (currentSI->PolyColor.rgba != nextSI->PolyColor.rgba ||
|
||||
currentSI->TintColor.rgba != nextSI->TintColor.rgba ||
|
||||
currentSI->FadeColor.rgba != nextSI->FadeColor.rgba ||
|
||||
currentSI->LightInfo.light_level != nextSI->LightInfo.light_level ||
|
||||
currentSI->LightInfo.fade_start != nextSI->LightInfo.fade_start ||
|
||||
currentSI->LightInfo.fade_end != nextSI->LightInfo.fade_end)
|
||||
{
|
||||
stateChanges |= SURFACEINFO_CHANGED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentSI->PolyColor.rgba != nextSI->PolyColor.rgba)
|
||||
stateChanges |= SURFACEINFO_CHANGED;
|
||||
}
|
||||
|
||||
return stateChanges;
|
||||
}
|
||||
|
||||
static void HWR_ExecuteStateChanges(unsigned int stateChanges, DrawCallInfo *dc)
|
||||
{
|
||||
if ((stateChanges & SHADER_CHANGED) && cv_grshaders.value && gr_shadersavailable)
|
||||
{
|
||||
HWD.pfnSetShader(dc->shader);
|
||||
ps_hw_numshaders.value.i++;
|
||||
}
|
||||
if (stateChanges & TEXTURE_CHANGED)
|
||||
{
|
||||
// for PF_NoTexture the texture is set in DrawIndexedTriangles
|
||||
if (!(dc->polyFlags & PF_NoTexture))
|
||||
{
|
||||
// texture should be already ready for use from calls to
|
||||
// SetTexture during batch collection
|
||||
HWD.pfnSetTexture(dc->texture);
|
||||
}
|
||||
ps_hw_numtextures.value.i++;
|
||||
}
|
||||
// these two are just parameters to DrawIndexedTriangles
|
||||
// (changes to polyflags states are tracked in r_opengl.c though)
|
||||
if (stateChanges & POLYFLAGS_CHANGED)
|
||||
ps_hw_numpolyflags.value.i++;
|
||||
if (stateChanges & SURFACEINFO_CHANGED)
|
||||
ps_hw_numcolors.value.i++;
|
||||
}
|
||||
|
||||
|
||||
static void HWR_InitBatchingStats(void)
|
||||
{
|
||||
ps_hw_numpolys.value.i = drawCallsSize;
|
||||
ps_hw_numcalls.value.i = ps_hw_numverts.value.i
|
||||
= ps_hw_numshaders.value.i = ps_hw_numtextures.value.i
|
||||
= ps_hw_numpolyflags.value.i = ps_hw_numcolors.value.i = 0;
|
||||
}
|
||||
|
||||
// This function organizes the geometry and draw calls collected by HWR_ProcessPolygon
|
||||
// calls into batches and uses the rendering backend to draw them.
|
||||
void HWR_RenderBatches(void)
|
||||
{
|
||||
int drawCallReadPos = 0; // position in drawCallOrder
|
||||
int i;
|
||||
|
||||
if (!currently_batching)
|
||||
I_Error("HWR_RenderBatches called without starting batching");
|
||||
|
||||
currently_batching = false; // no longer collecting batches
|
||||
|
||||
HWR_InitBatchingStats();
|
||||
|
||||
if (!drawCallsSize)
|
||||
return; // nothing to draw
|
||||
|
||||
// init drawCallOrder
|
||||
for (i = 0; i < drawCallsSize; i++)
|
||||
drawCallOrder[i] = i;
|
||||
|
||||
// sort the draw calls
|
||||
PS_START_TIMING(ps_hw_batchsorttime);
|
||||
if (cv_grshaders.value && gr_shadersavailable)
|
||||
qsort(drawCallOrder, drawCallsSize, sizeof(UINT32), compareDrawCalls);
|
||||
else
|
||||
qsort(drawCallOrder, drawCallsSize, sizeof(UINT32), compareDrawCallsNoShaders);
|
||||
PS_STOP_TIMING(ps_hw_batchsorttime);
|
||||
// sort grouping order
|
||||
// 1. shader
|
||||
// 2. texture
|
||||
// 3. polyflags
|
||||
// 4. colors + light level
|
||||
// not sure about what order of the last 2 should be, or if it even matters
|
||||
|
||||
PS_START_TIMING(ps_hw_batchdrawtime);
|
||||
|
||||
// set state for first batch
|
||||
HWR_ExecuteStateChanges(0xFFFF, &drawCalls[drawCallOrder[0]]);
|
||||
|
||||
// - iterate through draw calls
|
||||
// - accumulate converted vertices and indices into finalVertices and finalIndices
|
||||
// and send them as a combined draw call when a state change occurs
|
||||
while (1)
|
||||
{
|
||||
boolean stopFlag = false;
|
||||
unsigned int stateChanges = 0; // flags defined above HWR_MarkStateChanges
|
||||
DrawCallInfo *currentDrawCall = &drawCalls[drawCallOrder[drawCallReadPos++]];
|
||||
DrawCallInfo *nextDrawCall = NULL;
|
||||
|
||||
HWR_CollectVerticesIntoBatch(currentDrawCall);
|
||||
|
||||
if (drawCallReadPos >= drawCallsSize) // was that the last draw call?
|
||||
{
|
||||
stopFlag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextDrawCall = &drawCalls[drawCallOrder[drawCallReadPos]];
|
||||
stateChanges = HWR_MarkStateChanges(currentDrawCall, nextDrawCall);
|
||||
}
|
||||
|
||||
if (stateChanges || stopFlag)
|
||||
{
|
||||
// execute combined draw call
|
||||
HWD.pfnDrawIndexedTriangles(¤tDrawCall->surf, finalVertices,
|
||||
finalIndicesSize, currentDrawCall->polyFlags, finalIndices);
|
||||
// update stats
|
||||
ps_hw_numcalls.value.i++;
|
||||
ps_hw_numverts.value.i += finalIndicesSize;
|
||||
// reset final geometry collection arrays
|
||||
finalVerticesSize = 0;
|
||||
finalIndicesSize = 0;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
// if we're here then either its time to stop or time to change state
|
||||
if (stopFlag)
|
||||
break;
|
||||
else
|
||||
HWR_ExecuteStateChanges(stateChanges, nextDrawCall);
|
||||
}
|
||||
// reset the arrays (set sizes to 0)
|
||||
drawCallsSize = 0;
|
||||
unsortedVerticesSize = 0;
|
||||
|
||||
PS_STOP_TIMING(ps_hw_batchdrawtime);
|
||||
}
|
||||
|
||||
#endif // HWRENDER
|
||||
@@ -0,0 +1,27 @@
|
||||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2020 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file hw_batching.h
|
||||
/// \brief Draw call batching and related things.
|
||||
|
||||
#ifndef __HWR_BATCHING_H__
|
||||
#define __HWR_BATCHING_H__
|
||||
|
||||
#include "hw_defs.h"
|
||||
#include "hw_data.h"
|
||||
#include "hw_drv.h"
|
||||
|
||||
void HWR_StartBatching(void);
|
||||
void HWR_SetCurrentTexture(GLMipmap_t *texture);
|
||||
void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial);
|
||||
void HWR_RenderBatches(void);
|
||||
|
||||
extern boolean currently_batching;
|
||||
|
||||
#endif
|
||||
+21
-5
@@ -17,6 +17,7 @@
|
||||
#include "hw_main.h"
|
||||
#include "hw_glob.h"
|
||||
#include "hw_drv.h"
|
||||
#include "hw_batching.h"
|
||||
|
||||
#include "../doomstat.h" //gamemode
|
||||
#include "../i_video.h" //rendermode
|
||||
@@ -592,7 +593,11 @@ GLTexture_t *HWR_GetTexture(INT32 tex)
|
||||
if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded)
|
||||
HWR_GenerateTexture(tex, grtex);
|
||||
|
||||
HWD.pfnSetTexture(&grtex->mipmap);
|
||||
// If hardware does not have the texture, then call pfnSetTexture to upload it
|
||||
if (!grtex->mipmap.downloaded)
|
||||
HWD.pfnSetTexture(&grtex->mipmap);
|
||||
|
||||
HWR_SetCurrentTexture(&grtex->mipmap);
|
||||
|
||||
// The system-memory data can be purged now.
|
||||
Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED);
|
||||
@@ -676,7 +681,11 @@ void HWR_GetFlat(lumpnum_t flatlumpnum, boolean noencoremap)
|
||||
if (!grmip->downloaded && !grmip->grInfo.data)
|
||||
HWR_CacheFlat(grmip, flatlumpnum);
|
||||
|
||||
HWD.pfnSetTexture(grmip);
|
||||
// If hardware does not have the texture, then call pfnSetTexture to upload it
|
||||
if (!grmip->downloaded)
|
||||
HWD.pfnSetTexture(grmip);
|
||||
|
||||
HWR_SetCurrentTexture(grmip);
|
||||
|
||||
// The system-memory data can be purged now.
|
||||
Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED);
|
||||
@@ -702,8 +711,11 @@ static void HWR_LoadMappedPatch(GLMipmap_t *grmip, GLPatch_t *gpatch)
|
||||
Z_Free(patch);
|
||||
}
|
||||
|
||||
|
||||
HWD.pfnSetTexture(grmip);
|
||||
// If hardware does not have the texture, then call pfnSetTexture to upload it
|
||||
if (!grmip->downloaded)
|
||||
HWD.pfnSetTexture(grmip);
|
||||
|
||||
HWR_SetCurrentTexture(grmip);
|
||||
|
||||
// The system-memory data can be purged now.
|
||||
Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED);
|
||||
@@ -733,7 +745,11 @@ void HWR_GetPatch(GLPatch_t *gpatch)
|
||||
Z_Free(ptr);
|
||||
}
|
||||
|
||||
HWD.pfnSetTexture(gpatch->mipmap);
|
||||
// If hardware does not have the texture, then call pfnSetTexture to upload it
|
||||
if (!gpatch->mipmap->downloaded)
|
||||
HWD.pfnSetTexture(gpatch->mipmap);
|
||||
|
||||
HWR_SetCurrentTexture(gpatch->mipmap);
|
||||
|
||||
// The system-memory patch data can be purged now.
|
||||
Z_ChangeTag(gpatch->mipmap->grInfo.data, PU_HWRCACHE_UNLOCKED);
|
||||
|
||||
+11
-11
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -576,7 +576,7 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength)
|
||||
Surf.PolyColor.s.alpha = (UINT8)(strength*25.5f);
|
||||
}
|
||||
|
||||
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest, false);
|
||||
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
|
||||
}
|
||||
|
||||
// Draw the console background with translucency support
|
||||
@@ -603,7 +603,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 +854,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 +963,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 +1081,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
|
||||
|
||||
@@ -32,7 +32,8 @@ 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);
|
||||
@@ -77,9 +78,6 @@ EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value);
|
||||
EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boolean fragment);
|
||||
EXPORT boolean HWRAPI(InitCustomShaders) (void);
|
||||
|
||||
EXPORT void HWRAPI(StartBatching) (void);
|
||||
EXPORT void HWRAPI(RenderBatches) (precise_t *sSortTime, precise_t *sDrawTime, int *sNumPolys, int *sNumVerts, int *sNumCalls, int *sNumShaders, int *sNumTextures, int *sNumPolyFlags, int *sNumColors);
|
||||
|
||||
EXPORT void HWRAPI(SetPaletteLookup)(UINT8 *lut);
|
||||
EXPORT UINT32 HWRAPI(CreateLightTable)(RGBA_t *hw_lighttable);
|
||||
EXPORT void HWRAPI(ClearLightTables)(void);
|
||||
@@ -99,6 +97,7 @@ struct hwdriver_s
|
||||
FinishUpdate pfnFinishUpdate;
|
||||
Draw2DLine pfnDraw2DLine;
|
||||
DrawPolygon pfnDrawPolygon;
|
||||
DrawIndexedTriangles pfnDrawIndexedTriangles;
|
||||
SetBlend pfnSetBlend;
|
||||
ClearBuffer pfnClearBuffer;
|
||||
SetTexture pfnSetTexture;
|
||||
@@ -133,9 +132,6 @@ struct hwdriver_s
|
||||
LoadCustomShader pfnLoadCustomShader;
|
||||
InitCustomShaders pfnInitCustomShaders;
|
||||
|
||||
StartBatching pfnStartBatching;
|
||||
RenderBatches pfnRenderBatches;
|
||||
|
||||
SetPaletteLookup pfnSetPaletteLookup;
|
||||
CreateLightTable pfnCreateLightTable;
|
||||
ClearLightTables pfnClearLightTables;
|
||||
|
||||
+55
-38
@@ -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"
|
||||
@@ -649,6 +650,8 @@ void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isc
|
||||
|
||||
static FOutVector *planeVerts = NULL;
|
||||
static UINT16 numAllocedPlaneVerts = 0;
|
||||
|
||||
INT32 shader = 0;
|
||||
|
||||
// no convex poly were generated for this subsector
|
||||
if (!xsub->planepoly)
|
||||
@@ -826,16 +829,16 @@ void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isc
|
||||
if (HWR_UseShader())
|
||||
{
|
||||
if (PolyFlags & PF_Fog)
|
||||
HWD.pfnSetShader(6); // fog shader
|
||||
shader = 6; // fog shader
|
||||
else if (PolyFlags & PF_Ripple)
|
||||
HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 11 : 5); // water shader
|
||||
shader = (HWR_ShouldUsePaletteRendering() ? 11 : 5); // water shader
|
||||
else
|
||||
HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 9 : 1); // floor shader
|
||||
shader = (HWR_ShouldUsePaletteRendering() ? 9 : 1); // floor shader
|
||||
|
||||
PolyFlags |= PF_ColorMapped;
|
||||
}
|
||||
|
||||
HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags, false);
|
||||
HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags, shader, false);
|
||||
|
||||
if (subsector)
|
||||
{
|
||||
@@ -920,7 +923,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -936,6 +939,8 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf)
|
||||
fixed_t i;
|
||||
// seg bbox
|
||||
fixed_t segbbox[4];
|
||||
|
||||
INT32 shader = 0;
|
||||
|
||||
M_ClearBox(segbbox);
|
||||
M_AddToBox(segbbox,
|
||||
@@ -989,10 +994,10 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf)
|
||||
|
||||
if (HWR_UseShader())
|
||||
{
|
||||
HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader
|
||||
shader = (HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader
|
||||
}
|
||||
|
||||
HWD.pfnDrawPolygon(&pSurf, wallVerts, 4, i|PF_Modulated|PF_Decal, false);
|
||||
HWR_ProcessPolygon(&pSurf, wallVerts, 4, i|PF_Modulated|PF_Decal, shader, false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1023,11 +1028,13 @@ FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf)
|
||||
//
|
||||
void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blendmode, INT32 lightlevel, extracolormap_t *wallcolormap)
|
||||
{
|
||||
INT32 shader = 0;
|
||||
|
||||
HWR_Lighting(pSurf, lightlevel, wallcolormap);
|
||||
|
||||
if (HWR_UseShader())
|
||||
{
|
||||
HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader
|
||||
shader = (HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader
|
||||
blendmode |= PF_ColorMapped;
|
||||
}
|
||||
|
||||
@@ -1038,7 +1045,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)
|
||||
@@ -1394,11 +1401,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1419,7 +1426,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
|
||||
@@ -3114,6 +3121,8 @@ void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t
|
||||
|
||||
static FOutVector *planeVerts = NULL;
|
||||
static UINT16 numAllocedPlaneVerts = 0;
|
||||
|
||||
INT32 shader = 0;
|
||||
|
||||
nrPlaneVerts = polysector->numVertices;
|
||||
|
||||
@@ -3259,11 +3268,11 @@ void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t
|
||||
|
||||
if (HWR_UseShader())
|
||||
{
|
||||
HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 9 : 1); // floor shader
|
||||
shader = (HWR_ShouldUsePaletteRendering() ? 9 : 1); // floor shader
|
||||
blendmode |= PF_ColorMapped;
|
||||
}
|
||||
|
||||
HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode, false);
|
||||
HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode, shader, false); // floor shader
|
||||
}
|
||||
|
||||
void HWR_AddPolyObjectPlanes(void)
|
||||
@@ -3919,6 +3928,8 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t
|
||||
fixed_t slopez;
|
||||
float offset = 0;
|
||||
|
||||
INT32 shader = 0;
|
||||
|
||||
R_GetShadowZ(spr->mobj, &floorslope);
|
||||
|
||||
mobjfloor = HWR_OpaqueFloorAtPos(
|
||||
@@ -4068,10 +4079,10 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t
|
||||
|
||||
if (HWR_UseShader())
|
||||
{
|
||||
HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 9 : 1); // floor shader
|
||||
shader = (HWR_ShouldUsePaletteRendering() ? 9 : 1); // floor shader
|
||||
}
|
||||
|
||||
HWD.pfnDrawPolygon(&sSurf, swallVerts, 4, PF_Translucent|PF_Modulated, false);
|
||||
|
||||
HWR_ProcessPolygon(&sSurf, swallVerts, 4, PF_Translucent|PF_Modulated, shader, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4167,6 +4178,8 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
|
||||
fixed_t v1x, v1y, v2x, v2y;
|
||||
#endif
|
||||
|
||||
INT32 shader = 0;
|
||||
|
||||
this_scale = FIXED_TO_FLOAT(spr->mobj->scale);
|
||||
|
||||
if (hires)
|
||||
@@ -4440,11 +4453,11 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
|
||||
|
||||
if (HWR_UseShader())
|
||||
{
|
||||
HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader
|
||||
shader = (HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader
|
||||
blend |= PF_ColorMapped;
|
||||
}
|
||||
|
||||
HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, false);
|
||||
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, shader, false); // sprite shader
|
||||
|
||||
top = bot;
|
||||
#ifdef ESLOPE
|
||||
@@ -4485,11 +4498,11 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
|
||||
|
||||
if (HWR_UseShader())
|
||||
{
|
||||
HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader
|
||||
shader = (HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader
|
||||
blend |= PF_ColorMapped;
|
||||
}
|
||||
|
||||
HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, false);
|
||||
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, shader, false); // sprite shader
|
||||
}
|
||||
|
||||
// -----------------+
|
||||
@@ -4503,6 +4516,9 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
|
||||
FOutVector wallVerts[4];
|
||||
GLPatch_t *gpatch; // sprite patch converted to hardware
|
||||
FSurfaceInfo Surf;
|
||||
|
||||
INT32 shader = 0;
|
||||
|
||||
const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)( (spr->mobj->localskin) ? spr->mobj->localskin : spr->mobj->skin ))->flags & SF_HIRES);
|
||||
if (spr->mobj)
|
||||
this_scale = FIXED_TO_FLOAT(spr->mobj->scale);
|
||||
@@ -4643,11 +4659,11 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
|
||||
|
||||
if (HWR_UseShader())
|
||||
{
|
||||
HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader
|
||||
shader = (HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader
|
||||
blend |= PF_ColorMapped;
|
||||
}
|
||||
|
||||
HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, false);
|
||||
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, shader, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4658,6 +4674,8 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr)
|
||||
FOutVector wallVerts[4];
|
||||
GLPatch_t *gpatch; // sprite patch converted to hardware
|
||||
FSurfaceInfo Surf;
|
||||
|
||||
INT32 shader = 0;
|
||||
|
||||
if (!spr->mobj)
|
||||
return;
|
||||
@@ -4742,11 +4760,11 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr)
|
||||
|
||||
if (HWR_UseShader())
|
||||
{
|
||||
HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader
|
||||
shader = (HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader
|
||||
blend |= PF_ColorMapped;
|
||||
}
|
||||
|
||||
HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, false);
|
||||
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, shader, false);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -6043,8 +6061,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;
|
||||
@@ -6065,14 +6084,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);
|
||||
@@ -6362,7 +6377,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);
|
||||
@@ -6452,6 +6467,8 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend,
|
||||
{
|
||||
FBITFIELD blendmode = blend;
|
||||
UINT8 alpha = pSurf->PolyColor.s.alpha; // retain the alpha
|
||||
|
||||
INT32 shader = 0;
|
||||
|
||||
// Lighting is done here instead so that fog isn't drawn incorrectly on transparent walls after sorting
|
||||
HWR_Lighting(pSurf, lightlevel, wallcolormap);
|
||||
@@ -6464,7 +6481,7 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend,
|
||||
if (fogwall)
|
||||
{
|
||||
blendmode |= PF_Fog;
|
||||
HWD.pfnSetShader(6); // fog shader
|
||||
shader = 6; // fog shader
|
||||
}
|
||||
|
||||
blendmode |= PF_Modulated; // No PF_Occlude means overlapping (incorrect) transparency
|
||||
@@ -6473,12 +6490,12 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend,
|
||||
{
|
||||
if (HWR_UseShader())
|
||||
{
|
||||
HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader
|
||||
shader = (HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader
|
||||
blendmode |= PF_ColorMapped;
|
||||
}
|
||||
}
|
||||
|
||||
HWD.pfnDrawPolygon(pSurf, wallVerts, 4, blendmode, false);
|
||||
HWR_ProcessPolygon(pSurf, wallVerts, 4, blendmode, shader, false);
|
||||
|
||||
#ifdef WALLSPLATS
|
||||
if (gr_curline->linedef->splats && cv_splats.value)
|
||||
@@ -6529,7 +6546,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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "../../i_system.h" // for I_GetPreciseTime (batching time measurements)
|
||||
|
||||
#include "../hw_main.h"
|
||||
#include "../hw_batching.h"
|
||||
|
||||
// Eeeeh not sure is this right way, but it works < sry :c
|
||||
extern consvar_t cv_grusecustomshaders;
|
||||
@@ -78,10 +79,7 @@ static float NEAR_CLIPPING_PLANE = NZCLIP_PLANE;
|
||||
// **************************************************************************
|
||||
|
||||
static GLuint tex_downloaded = 0;
|
||||
// these didnt work with karts batching system, hope this is not an issue
|
||||
//static GLuint lt_downloaded = 0; // currently bound lighttable texture - currentSurfaceInfo
|
||||
//static GLuint lt_downloaded2 = 0; // currently bound lighttable texture - nextSurfaceInfo
|
||||
//static GLuint lt_downloaded3 = 0; // currently bound lighttable texture - pSurf
|
||||
static GLuint lt_downloaded = 0; // currently bound lighttable texture
|
||||
static GLfloat fov = 90.0f;
|
||||
static FBITFIELD CurrentPolyFlags;
|
||||
|
||||
@@ -132,9 +130,10 @@ static GLuint endScreenWipe = 0;
|
||||
static GLuint finalScreenTexture = 0;
|
||||
|
||||
// Lactozilla: Set shader programs and uniforms
|
||||
static void *Shader_Load(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade);
|
||||
static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade);
|
||||
|
||||
static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
|
||||
// shortcut for ((float)1/i)
|
||||
static const GLfloat byte2float[256] = {
|
||||
0.000000f, 0.003922f, 0.007843f, 0.011765f, 0.015686f, 0.019608f, 0.023529f, 0.027451f,
|
||||
@@ -1344,7 +1343,7 @@ EXPORT void HWRAPI(KillShaders) (void)
|
||||
static void SetNoTexture(void)
|
||||
{
|
||||
// Disable texture.
|
||||
if (tex_downloaded != NOTEXTURE_NUM && !gl_batching)
|
||||
if (tex_downloaded != NOTEXTURE_NUM)
|
||||
{
|
||||
pglBindTexture(GL_TEXTURE_2D, NOTEXTURE_NUM);
|
||||
tex_downloaded = NOTEXTURE_NUM;
|
||||
@@ -2103,43 +2102,33 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void *Shader_Load(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade)
|
||||
{
|
||||
#ifdef GL_SHADERS
|
||||
if (gl_shadersenabled && pglUseProgram)
|
||||
{
|
||||
gl_shaderprogram_t *shader = &gl_shaderprograms[gl_currentshaderprogram];
|
||||
if (shader->program)
|
||||
{
|
||||
if (gl_shaderprogramchanged)
|
||||
{
|
||||
pglUseProgram(gl_shaderprograms[gl_currentshaderprogram].program);
|
||||
gl_shaderprogramchanged = false;
|
||||
}
|
||||
Shader_SetUniforms(Surface, poly, tint, fade);
|
||||
return shader;
|
||||
}
|
||||
else
|
||||
pglUseProgram(0);
|
||||
}
|
||||
#else
|
||||
(void)Surface;
|
||||
(void)poly;
|
||||
(void)tint;
|
||||
(void)fade;
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade)
|
||||
{
|
||||
gl_shaderprogram_t *shader = &gl_shaderprograms[gl_currentshaderprogram];
|
||||
|
||||
#ifdef GL_SHADERS
|
||||
if (gl_shadersenabled)
|
||||
if (gl_shadersenabled && (shader != NULL) && pglUseProgram)
|
||||
{
|
||||
gl_shaderprogram_t *shader = &gl_shaderprograms[gl_currentshaderprogram];
|
||||
|
||||
if (!shader->program)
|
||||
{
|
||||
pglUseProgram(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gl_shaderprogramchanged)
|
||||
{
|
||||
pglUseProgram(gl_shaderprograms[gl_currentshaderprogram].program);
|
||||
gl_shaderprogramchanged = false;
|
||||
}
|
||||
|
||||
// Color uniforms can be left NULL and will be set to white (1.0f, 1.0f, 1.0f, 1.0f)
|
||||
if (poly == NULL)
|
||||
poly = &shader_defaultcolor;
|
||||
if (tint == NULL)
|
||||
tint = &shader_defaultcolor;
|
||||
if (fade == NULL)
|
||||
fade = &shader_defaultcolor;
|
||||
|
||||
#define UNIFORM_1(uniform, a, function) \
|
||||
if (uniform != -1) \
|
||||
@@ -2182,636 +2171,85 @@ static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAF
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// unfinished draw call batching
|
||||
|
||||
// Note: could use realloc in the array reallocation code
|
||||
|
||||
typedef struct
|
||||
// code that is common between DrawPolygon and DrawIndexedTriangles
|
||||
// the corona thing is there too, i have no idea if that stuff works with DrawIndexedTriangles and batching
|
||||
static void PreparePolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FBITFIELD PolyFlags)
|
||||
{
|
||||
FSurfaceInfo surf;// surf also has its own polyflags for some reason, but it seems unused
|
||||
unsigned int vertsIndex;// location of verts in unsortedVertexArray
|
||||
FUINT numVerts;
|
||||
FBITFIELD polyFlags;
|
||||
GLuint texNum;
|
||||
GLuint shader;
|
||||
// this tells batching that the plane belongs to a horizon line and must be drawn in correct order with the skywalls
|
||||
boolean horizonSpecial;
|
||||
} PolygonArrayEntry;
|
||||
static GLRGBAFloat poly = {0,0,0,0};
|
||||
static GLRGBAFloat tint = {0,0,0,0};
|
||||
static GLRGBAFloat fade = {0,0,0,0};
|
||||
|
||||
FOutVector* finalVertexArray = NULL;// contains subset of sorted vertices and texture coordinates to be sent to gpu
|
||||
UINT32* finalVertexIndexArray = NULL;// contains indexes for glDrawElements, taking into account fan->triangles conversion
|
||||
// NOTE have this alloced as 3x finalVertexArray size
|
||||
int finalVertexArrayAllocSize = 65536;
|
||||
//GLubyte* colorArray = NULL;// contains color data to be sent to gpu, if needed
|
||||
//int colorArrayAllocSize = 65536;
|
||||
// not gonna use this for now, just sort by color and change state when it changes
|
||||
// later maybe when using vertex attributes if it's needed
|
||||
SetBlend(PolyFlags); //TODO: inline (#pragma..)
|
||||
|
||||
PolygonArrayEntry* polygonArray = NULL;// contains the polygon data from DrawPolygon, waiting to be processed
|
||||
int polygonArraySize = 0;
|
||||
UINT32* polygonIndexArray = NULL;// contains sorting pointers for polygonArray
|
||||
int polygonArrayAllocSize = 65536;
|
||||
|
||||
FOutVector* unsortedVertexArray = NULL;// contains unsorted vertices and texture coordinates from DrawPolygon
|
||||
int unsortedVertexArraySize = 0;
|
||||
int unsortedVertexArrayAllocSize = 65536;
|
||||
|
||||
EXPORT void HWRAPI(StartBatching) (void)
|
||||
{
|
||||
//CONS_Printf("StartBatching begin\n");
|
||||
// init arrays if that has not been done yet
|
||||
if (!finalVertexArray)
|
||||
// PolyColor
|
||||
if (pSurf)
|
||||
{
|
||||
finalVertexArray = malloc(finalVertexArrayAllocSize * sizeof(FOutVector));
|
||||
finalVertexIndexArray = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32));
|
||||
polygonArray = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry));
|
||||
polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(UINT32));
|
||||
unsortedVertexArray = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector));
|
||||
}
|
||||
// drawing functions will now collect the drawing data instead of passing it to opengl
|
||||
gl_batching = true;
|
||||
//CONS_Printf("StartBatching end\n");
|
||||
}
|
||||
// If Modulated, mix the surface colour to the texture
|
||||
if (CurrentPolyFlags & PF_Modulated)
|
||||
{
|
||||
// Poly color
|
||||
poly.red = byte2float[pSurf->PolyColor.s.red];
|
||||
poly.green = byte2float[pSurf->PolyColor.s.green];
|
||||
poly.blue = byte2float[pSurf->PolyColor.s.blue];
|
||||
poly.alpha = byte2float[pSurf->PolyColor.s.alpha];
|
||||
|
||||
static int comparePolygons(const void *p1, const void *p2)
|
||||
{
|
||||
unsigned int index1 = *(const unsigned int*)p1;
|
||||
unsigned int index2 = *(const unsigned int*)p2;
|
||||
PolygonArrayEntry* poly1 = &polygonArray[index1];
|
||||
PolygonArrayEntry* poly2 = &polygonArray[index2];
|
||||
int diff;
|
||||
INT64 diff64;
|
||||
pglColor4ubv((GLubyte*)&pSurf->PolyColor.s);
|
||||
}
|
||||
|
||||
int shader1 = poly1->shader;
|
||||
int shader2 = poly2->shader;
|
||||
// make skywalls and horizon lines first in order
|
||||
if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial)
|
||||
shader1 = -1;
|
||||
if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial)
|
||||
shader2 = -1;
|
||||
diff = shader1 - shader2;
|
||||
if (diff != 0) return diff;
|
||||
// Tint color
|
||||
tint.red = byte2float[pSurf->TintColor.s.red];
|
||||
tint.green = byte2float[pSurf->TintColor.s.green];
|
||||
tint.blue = byte2float[pSurf->TintColor.s.blue];
|
||||
tint.alpha = byte2float[pSurf->TintColor.s.alpha];
|
||||
|
||||
// skywalls and horizon lines must retain their order for horizon lines to work
|
||||
if (shader1 == -1 && shader2 == -1)
|
||||
return index1 - index2;
|
||||
|
||||
diff = poly1->texNum - poly2->texNum;
|
||||
if (diff != 0) return diff;
|
||||
|
||||
if (HWR_ShouldUsePaletteRendering())
|
||||
{
|
||||
diff = poly1->surf.LightTableId - poly2->surf.LightTableId;
|
||||
if (diff != 0) return diff;
|
||||
}
|
||||
|
||||
diff = poly1->polyFlags - poly2->polyFlags;
|
||||
if (diff != 0) return diff;
|
||||
|
||||
diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba;
|
||||
if (diff64 < 0) return -1; else if (diff64 > 0) return 1;
|
||||
diff64 = poly1->surf.TintColor.rgba - poly2->surf.TintColor.rgba;
|
||||
if (diff64 < 0) return -1; else if (diff64 > 0) return 1;
|
||||
diff64 = poly1->surf.FadeColor.rgba - poly2->surf.FadeColor.rgba;
|
||||
if (diff64 < 0) return -1; else if (diff64 > 0) return 1;
|
||||
|
||||
diff = poly1->surf.LightInfo.light_level - poly2->surf.LightInfo.light_level;
|
||||
if (diff != 0) return diff;
|
||||
diff = poly1->surf.LightInfo.fade_start - poly2->surf.LightInfo.fade_start;
|
||||
if (diff != 0) return diff;
|
||||
diff = poly1->surf.LightInfo.fade_end - poly2->surf.LightInfo.fade_end;
|
||||
return diff;
|
||||
}
|
||||
|
||||
static int comparePolygonsNoShaders(const void *p1, const void *p2)
|
||||
{
|
||||
unsigned int index1 = *(const unsigned int*)p1;
|
||||
unsigned int index2 = *(const unsigned int*)p2;
|
||||
PolygonArrayEntry* poly1 = &polygonArray[index1];
|
||||
PolygonArrayEntry* poly2 = &polygonArray[index2];
|
||||
int diff;
|
||||
INT64 diff64;
|
||||
|
||||
GLuint texNum1 = poly1->texNum;
|
||||
GLuint texNum2 = poly2->texNum;
|
||||
if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial)
|
||||
texNum1 = 0;
|
||||
if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial)
|
||||
texNum2 = 0;
|
||||
diff = texNum1 - texNum2;
|
||||
if (diff != 0) return diff;
|
||||
|
||||
// skywalls and horizon lines must retain their order for horizon lines to work
|
||||
if (texNum1 == 0 && texNum2 == 0)
|
||||
return index1 - index2;
|
||||
|
||||
diff = poly1->polyFlags - poly2->polyFlags;
|
||||
if (diff != 0) return diff;
|
||||
|
||||
diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba;
|
||||
if (diff64 < 0) return -1; else if (diff64 > 0) return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// the parameters for this functions (numPolys etc.) are used to return rendering stats
|
||||
EXPORT void HWRAPI(RenderBatches) (precise_t *sSortTime, precise_t *sDrawTime, int *sNumPolys, int *sNumVerts, int *sNumCalls, int *sNumShaders, int *sNumTextures, int *sNumPolyFlags, int *sNumColors)
|
||||
{
|
||||
int finalVertexWritePos = 0;// position in finalVertexArray
|
||||
int finalIndexWritePos = 0;// position in finalVertexIndexArray
|
||||
|
||||
int polygonReadPos = 0;// position in polygonIndexArray
|
||||
|
||||
GLuint currentShader;
|
||||
GLuint currentTexture;
|
||||
FBITFIELD currentPolyFlags;
|
||||
FSurfaceInfo currentSurfaceInfo;
|
||||
|
||||
GLRGBAFloat firstPoly = {0,0,0,0}; // may be misleading but this means first PolyColor
|
||||
GLRGBAFloat firstTint = {0,0,0,0};
|
||||
GLRGBAFloat firstFade = {0,0,0,0};
|
||||
|
||||
boolean needRebind = false;
|
||||
|
||||
int i;
|
||||
|
||||
//CONS_Printf("RenderBatches\n");
|
||||
gl_batching = false;// no longer collecting batches
|
||||
if (!polygonArraySize)
|
||||
{
|
||||
*sSortTime = *sDrawTime = *sNumPolys = *sNumCalls = *sNumShaders = *sNumTextures = *sNumPolyFlags = *sNumColors = 0;
|
||||
return;// nothing to draw
|
||||
}
|
||||
// init stats vars
|
||||
*sNumPolys = polygonArraySize;
|
||||
*sNumCalls = *sNumVerts = 0;
|
||||
*sNumShaders = *sNumTextures = *sNumPolyFlags = *sNumColors = 1;
|
||||
// init polygonIndexArray
|
||||
for (i = 0; i < polygonArraySize; i++)
|
||||
{
|
||||
polygonIndexArray[i] = i;
|
||||
}
|
||||
|
||||
// sort polygons
|
||||
//CONS_Printf("qsort polys\n");
|
||||
*sSortTime = I_GetPreciseTime();
|
||||
if (gl_allowshaders)
|
||||
qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons);
|
||||
else
|
||||
qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders);
|
||||
*sSortTime = I_GetPreciseTime() - *sSortTime;
|
||||
//CONS_Printf("sort done\n");
|
||||
// sort order
|
||||
// 1. shader
|
||||
// 2. texture
|
||||
// 3. polyflags
|
||||
// 4. colors + light level
|
||||
// not sure about order of last 2, or if it even matters
|
||||
|
||||
*sDrawTime = I_GetPreciseTime();
|
||||
|
||||
currentShader = polygonArray[polygonIndexArray[0]].shader;
|
||||
currentTexture = polygonArray[polygonIndexArray[0]].texNum;
|
||||
currentPolyFlags = polygonArray[polygonIndexArray[0]].polyFlags;
|
||||
currentSurfaceInfo = polygonArray[polygonIndexArray[0]].surf;
|
||||
// For now, will sort and track the colors. Vertex attributes could be used instead of uniforms
|
||||
// and a color array could replace the color calls.
|
||||
|
||||
// set state for first batch
|
||||
//CONS_Printf("set first state\n");
|
||||
gl_currentshaderprogram = currentShader;
|
||||
gl_shaderprogramchanged = true;
|
||||
if (currentPolyFlags & PF_Modulated)
|
||||
{
|
||||
// Poly color
|
||||
firstPoly.red = byte2float[currentSurfaceInfo.PolyColor.s.red];
|
||||
firstPoly.green = byte2float[currentSurfaceInfo.PolyColor.s.green];
|
||||
firstPoly.blue = byte2float[currentSurfaceInfo.PolyColor.s.blue];
|
||||
firstPoly.alpha = byte2float[currentSurfaceInfo.PolyColor.s.alpha];
|
||||
pglColor4ubv((GLubyte*)¤tSurfaceInfo.PolyColor.s);
|
||||
}
|
||||
// Tint color
|
||||
firstTint.red = byte2float[currentSurfaceInfo.TintColor.s.red];
|
||||
firstTint.green = byte2float[currentSurfaceInfo.TintColor.s.green];
|
||||
firstTint.blue = byte2float[currentSurfaceInfo.TintColor.s.blue];
|
||||
firstTint.alpha = byte2float[currentSurfaceInfo.TintColor.s.alpha];
|
||||
// Fade color
|
||||
firstFade.red = byte2float[currentSurfaceInfo.FadeColor.s.red];
|
||||
firstFade.green = byte2float[currentSurfaceInfo.FadeColor.s.green];
|
||||
firstFade.blue = byte2float[currentSurfaceInfo.FadeColor.s.blue];
|
||||
firstFade.alpha = byte2float[currentSurfaceInfo.FadeColor.s.alpha];
|
||||
|
||||
if (gl_allowshaders)
|
||||
{
|
||||
Shader_Load(¤tSurfaceInfo, &firstPoly, &firstTint, &firstFade);
|
||||
// Fade color
|
||||
fade.red = byte2float[pSurf->FadeColor.s.red];
|
||||
fade.green = byte2float[pSurf->FadeColor.s.green];
|
||||
fade.blue = byte2float[pSurf->FadeColor.s.blue];
|
||||
fade.alpha = byte2float[pSurf->FadeColor.s.alpha];
|
||||
|
||||
//if (currentSurfaceInfo.LightTableId && currentSurfaceInfo.LightTableId != lt_downloaded)
|
||||
if (HWR_ShouldUsePaletteRendering())
|
||||
if (pSurf->LightTableId && pSurf->LightTableId != lt_downloaded)
|
||||
{
|
||||
pglActiveTexture(GL_TEXTURE2);
|
||||
pglBindTexture(GL_TEXTURE_2D, currentSurfaceInfo.LightTableId);
|
||||
pglBindTexture(GL_TEXTURE_2D, pSurf->LightTableId);
|
||||
pglActiveTexture(GL_TEXTURE0);
|
||||
//lt_downloaded = currentSurfaceInfo.LightTableId;
|
||||
lt_downloaded = pSurf->LightTableId;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentPolyFlags & PF_NoTexture)
|
||||
currentTexture = 0;
|
||||
pglBindTexture(GL_TEXTURE_2D, currentTexture);
|
||||
tex_downloaded = currentTexture;
|
||||
|
||||
SetBlend(currentPolyFlags);
|
||||
|
||||
//CONS_Printf("first pointers to ogl\n");
|
||||
pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &finalVertexArray[0].x);
|
||||
pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &finalVertexArray[0].s);
|
||||
|
||||
while (1)// note: remember handling notexture polyflag as having texture number 0 (also in comparePolygons)
|
||||
{
|
||||
int firstIndex;
|
||||
int lastIndex;
|
||||
|
||||
boolean stopFlag = false;
|
||||
boolean changeState = false;
|
||||
boolean changeShader = false;
|
||||
GLuint nextShader = 0U;
|
||||
boolean changeTexture = false;
|
||||
GLuint nextTexture = 0U;
|
||||
boolean changePolyFlags = false;
|
||||
FBITFIELD nextPolyFlags = 0U;
|
||||
boolean changeSurfaceInfo = false;
|
||||
FSurfaceInfo nextSurfaceInfo;
|
||||
|
||||
//CONS_Printf("loop iter start\n");
|
||||
// new try:
|
||||
// write vertices
|
||||
// check for changes or end, otherwise go back to writing
|
||||
// changes will affect the next vars and the change bools
|
||||
// end could set flag for stopping
|
||||
// execute draw call
|
||||
// could check ending flag here
|
||||
// change states according to next vars and change bools, updating the current vars and reseting the bools
|
||||
// reset write pos
|
||||
// repeat loop
|
||||
|
||||
int index = polygonIndexArray[polygonReadPos++];
|
||||
int numVerts = polygonArray[index].numVerts;
|
||||
// before writing, check if there is enough room
|
||||
// using 'while' instead of 'if' here makes sure that there will *always* be enough room.
|
||||
// probably never will this loop run more than once though
|
||||
while (finalVertexWritePos + numVerts > finalVertexArrayAllocSize)
|
||||
{
|
||||
FOutVector* new_array;
|
||||
unsigned int* new_index_array;
|
||||
//CONS_Printf("final vert realloc\n");
|
||||
finalVertexArrayAllocSize *= 2;
|
||||
new_array = malloc(finalVertexArrayAllocSize * sizeof(FOutVector));
|
||||
memcpy(new_array, finalVertexArray, finalVertexWritePos * sizeof(FOutVector));
|
||||
free(finalVertexArray);
|
||||
finalVertexArray = new_array;
|
||||
// also increase size of index array, 3x of vertex array since
|
||||
// going from fans to triangles increases vertex count to 3x
|
||||
new_index_array = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32));
|
||||
memcpy(new_index_array, finalVertexIndexArray, finalIndexWritePos * sizeof(UINT32));
|
||||
free(finalVertexIndexArray);
|
||||
finalVertexIndexArray = new_index_array;
|
||||
// if vertex buffers are reallocated then opengl needs to know too
|
||||
needRebind = true;
|
||||
}
|
||||
//CONS_Printf("write verts to final\n");
|
||||
// write the vertices of the polygon
|
||||
memcpy(&finalVertexArray[finalVertexWritePos], &unsortedVertexArray[polygonArray[index].vertsIndex],
|
||||
numVerts * sizeof(FOutVector));
|
||||
// write the indexes, pointing to the fan vertexes but in triangles format
|
||||
firstIndex = finalVertexWritePos;
|
||||
lastIndex = finalVertexWritePos + numVerts;
|
||||
finalVertexWritePos += 2;
|
||||
//CONS_Printf("write final vert indices\n");
|
||||
while (finalVertexWritePos < lastIndex)
|
||||
{
|
||||
finalVertexIndexArray[finalIndexWritePos++] = firstIndex;
|
||||
finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos - 1;
|
||||
finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos++;
|
||||
}
|
||||
|
||||
if (polygonReadPos >= polygonArraySize)
|
||||
{
|
||||
stopFlag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//CONS_Printf("state change check\n");
|
||||
// check if a state change is required, set the change bools and next vars
|
||||
int nextIndex = polygonIndexArray[polygonReadPos];
|
||||
nextShader = polygonArray[nextIndex].shader;
|
||||
nextTexture = polygonArray[nextIndex].texNum;
|
||||
nextPolyFlags = polygonArray[nextIndex].polyFlags;
|
||||
nextSurfaceInfo = polygonArray[nextIndex].surf;
|
||||
if (nextPolyFlags & PF_NoTexture)
|
||||
nextTexture = 0;
|
||||
if (currentShader != nextShader)
|
||||
{
|
||||
changeState = true;
|
||||
changeShader = true;
|
||||
}
|
||||
if (currentTexture != nextTexture)
|
||||
{
|
||||
changeState = true;
|
||||
changeTexture = true;
|
||||
}
|
||||
if (currentPolyFlags != nextPolyFlags)
|
||||
{
|
||||
changeState = true;
|
||||
changePolyFlags = true;
|
||||
}
|
||||
if (gl_allowshaders && HWR_ShouldUsePaletteRendering())
|
||||
{
|
||||
if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba ||
|
||||
currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba ||
|
||||
currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba ||
|
||||
currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level ||
|
||||
currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start ||
|
||||
currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end ||
|
||||
currentSurfaceInfo.LightTableId != nextSurfaceInfo.LightTableId)
|
||||
{
|
||||
changeState = true;
|
||||
changeSurfaceInfo = true;
|
||||
}
|
||||
}
|
||||
else if ((gl_allowshaders) && (!HWR_ShouldUsePaletteRendering()))
|
||||
{
|
||||
if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba ||
|
||||
currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba ||
|
||||
currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba ||
|
||||
currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level ||
|
||||
currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start ||
|
||||
currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end)
|
||||
{
|
||||
changeState = true;
|
||||
changeSurfaceInfo = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba)
|
||||
{
|
||||
changeState = true;
|
||||
changeSurfaceInfo = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (changeState || stopFlag)
|
||||
{
|
||||
if (needRebind)
|
||||
{
|
||||
//CONS_Printf("rebind\n");
|
||||
pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &finalVertexArray[0].x);
|
||||
pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &finalVertexArray[0].s);
|
||||
needRebind = false;
|
||||
}
|
||||
//CONS_Printf("exec draw call\n");
|
||||
// execute draw call
|
||||
pglDrawElements(GL_TRIANGLES, finalIndexWritePos, GL_UNSIGNED_INT, finalVertexIndexArray);
|
||||
//CONS_Printf("draw call done\n");
|
||||
// update stats
|
||||
(*sNumCalls)++;
|
||||
*sNumVerts += finalIndexWritePos;
|
||||
// reset write positions
|
||||
finalVertexWritePos = 0;
|
||||
finalIndexWritePos = 0;
|
||||
}
|
||||
else continue;
|
||||
|
||||
// if we're here then either its time to stop or time to change state
|
||||
if (stopFlag) break;
|
||||
|
||||
//CONS_Printf("state change\n");
|
||||
|
||||
// change state according to change bools and next vars, update current vars and reset bools
|
||||
if (changeShader)
|
||||
{
|
||||
GLRGBAFloat poly = {0,0,0,0};
|
||||
GLRGBAFloat tint = {0,0,0,0};
|
||||
GLRGBAFloat fade = {0,0,0,0};
|
||||
gl_currentshaderprogram = nextShader;
|
||||
gl_shaderprogramchanged = true;
|
||||
if (nextPolyFlags & PF_Modulated)
|
||||
{
|
||||
// Poly color
|
||||
poly.red = byte2float[nextSurfaceInfo.PolyColor.s.red];
|
||||
poly.green = byte2float[nextSurfaceInfo.PolyColor.s.green];
|
||||
poly.blue = byte2float[nextSurfaceInfo.PolyColor.s.blue];
|
||||
poly.alpha = byte2float[nextSurfaceInfo.PolyColor.s.alpha];
|
||||
}
|
||||
// Tint color
|
||||
tint.red = byte2float[nextSurfaceInfo.TintColor.s.red];
|
||||
tint.green = byte2float[nextSurfaceInfo.TintColor.s.green];
|
||||
tint.blue = byte2float[nextSurfaceInfo.TintColor.s.blue];
|
||||
tint.alpha = byte2float[nextSurfaceInfo.TintColor.s.alpha];
|
||||
// Fade color
|
||||
fade.red = byte2float[nextSurfaceInfo.FadeColor.s.red];
|
||||
fade.green = byte2float[nextSurfaceInfo.FadeColor.s.green];
|
||||
fade.blue = byte2float[nextSurfaceInfo.FadeColor.s.blue];
|
||||
fade.alpha = byte2float[nextSurfaceInfo.FadeColor.s.alpha];
|
||||
|
||||
Shader_Load(&nextSurfaceInfo, &poly, &tint, &fade);
|
||||
|
||||
currentShader = nextShader;
|
||||
changeShader = false;
|
||||
|
||||
(*sNumShaders)++;
|
||||
}
|
||||
if (changeTexture)
|
||||
{
|
||||
// texture should be already ready for use from calls to SetTexture during batch collection
|
||||
pglBindTexture(GL_TEXTURE_2D, nextTexture);
|
||||
tex_downloaded = nextTexture;
|
||||
currentTexture = nextTexture;
|
||||
changeTexture = false;
|
||||
|
||||
(*sNumTextures)++;
|
||||
}
|
||||
if (changePolyFlags)
|
||||
{
|
||||
SetBlend(nextPolyFlags);
|
||||
currentPolyFlags = nextPolyFlags;
|
||||
changePolyFlags = false;
|
||||
|
||||
(*sNumPolyFlags)++;
|
||||
}
|
||||
if (changeSurfaceInfo)
|
||||
{
|
||||
GLRGBAFloat poly = {0,0,0,0};
|
||||
GLRGBAFloat tint = {0,0,0,0};
|
||||
GLRGBAFloat fade = {0,0,0,0};
|
||||
gl_shaderprogramchanged = false;
|
||||
if (nextPolyFlags & PF_Modulated)
|
||||
{
|
||||
// Poly color
|
||||
poly.red = byte2float[nextSurfaceInfo.PolyColor.s.red];
|
||||
poly.green = byte2float[nextSurfaceInfo.PolyColor.s.green];
|
||||
poly.blue = byte2float[nextSurfaceInfo.PolyColor.s.blue];
|
||||
poly.alpha = byte2float[nextSurfaceInfo.PolyColor.s.alpha];
|
||||
pglColor4ubv((GLubyte*)&nextSurfaceInfo.PolyColor.s);
|
||||
}
|
||||
if (gl_allowshaders)
|
||||
{
|
||||
// Tint color
|
||||
tint.red = byte2float[nextSurfaceInfo.TintColor.s.red];
|
||||
tint.green = byte2float[nextSurfaceInfo.TintColor.s.green];
|
||||
tint.blue = byte2float[nextSurfaceInfo.TintColor.s.blue];
|
||||
tint.alpha = byte2float[nextSurfaceInfo.TintColor.s.alpha];
|
||||
// Fade color
|
||||
fade.red = byte2float[nextSurfaceInfo.FadeColor.s.red];
|
||||
fade.green = byte2float[nextSurfaceInfo.FadeColor.s.green];
|
||||
fade.blue = byte2float[nextSurfaceInfo.FadeColor.s.blue];
|
||||
fade.alpha = byte2float[nextSurfaceInfo.FadeColor.s.alpha];
|
||||
|
||||
Shader_Load(&nextSurfaceInfo, &poly, &tint, &fade);
|
||||
|
||||
//if (nextSurfaceInfo.LightTableId && nextSurfaceInfo.LightTableId != lt_downloaded2)
|
||||
if (HWR_ShouldUsePaletteRendering())
|
||||
{
|
||||
pglActiveTexture(GL_TEXTURE2);
|
||||
pglBindTexture(GL_TEXTURE_2D, nextSurfaceInfo.LightTableId);
|
||||
pglActiveTexture(GL_TEXTURE0);
|
||||
//lt_downloaded2 = nextSurfaceInfo.LightTableId;
|
||||
}
|
||||
}
|
||||
|
||||
currentSurfaceInfo = nextSurfaceInfo;
|
||||
changeSurfaceInfo = false;
|
||||
|
||||
(*sNumColors)++;
|
||||
}
|
||||
// and that should be it?
|
||||
}
|
||||
// reset the arrays (set sizes to 0)
|
||||
polygonArraySize = 0;
|
||||
unsortedVertexArraySize = 0;
|
||||
|
||||
*sDrawTime = I_GetPreciseTime() - *sDrawTime;
|
||||
Shader_SetUniforms(pSurf, &poly, &tint, &fade);
|
||||
}
|
||||
|
||||
// -----------------+
|
||||
// DrawPolygon : Render a polygon, set the texture, set render mode
|
||||
// -----------------+
|
||||
EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, boolean horizonSpecial)
|
||||
EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags)
|
||||
{
|
||||
if (gl_batching)
|
||||
{
|
||||
//CONS_Printf("Batched DrawPolygon\n");
|
||||
if (!pSurf)
|
||||
I_Error("Got a null FSurfaceInfo in batching");// nulls should only come in sky background pic drawing
|
||||
if (polygonArraySize == polygonArrayAllocSize)
|
||||
{
|
||||
PolygonArrayEntry* new_array;
|
||||
// ran out of space, make new array double the size
|
||||
polygonArrayAllocSize *= 2;
|
||||
new_array = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry));
|
||||
memcpy(new_array, polygonArray, polygonArraySize * sizeof(PolygonArrayEntry));
|
||||
free(polygonArray);
|
||||
polygonArray = new_array;
|
||||
// also need to redo the index array, dont need to copy it though
|
||||
free(polygonIndexArray);
|
||||
polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(unsigned int));
|
||||
}
|
||||
PreparePolygon(pSurf, pOutVerts, PolyFlags);
|
||||
|
||||
while (unsortedVertexArraySize + (int)iNumPts > unsortedVertexArrayAllocSize)
|
||||
{
|
||||
FOutVector* new_array;
|
||||
// need more space for vertices in unsortedVertexArray
|
||||
unsortedVertexArrayAllocSize *= 2;
|
||||
new_array = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector));
|
||||
memcpy(new_array, unsortedVertexArray, unsortedVertexArraySize * sizeof(FOutVector));
|
||||
free(unsortedVertexArray);
|
||||
unsortedVertexArray = new_array;
|
||||
}
|
||||
pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x);
|
||||
pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].s);
|
||||
pglDrawArrays(GL_TRIANGLE_FAN, 0, iNumPts);
|
||||
|
||||
// add the polygon data to the arrays
|
||||
if (PolyFlags & PF_RemoveYWrap)
|
||||
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
polygonArray[polygonArraySize].surf = *pSurf;
|
||||
polygonArray[polygonArraySize].vertsIndex = unsortedVertexArraySize;
|
||||
polygonArray[polygonArraySize].numVerts = iNumPts;
|
||||
polygonArray[polygonArraySize].polyFlags = PolyFlags;
|
||||
polygonArray[polygonArraySize].texNum = tex_downloaded;
|
||||
polygonArray[polygonArraySize].shader = gl_currentshaderprogram;
|
||||
polygonArray[polygonArraySize].horizonSpecial = horizonSpecial;
|
||||
polygonArraySize++;
|
||||
if (PolyFlags & PF_ForceWrapX)
|
||||
Clamp2D(GL_TEXTURE_WRAP_S);
|
||||
|
||||
memcpy(&unsortedVertexArray[unsortedVertexArraySize], pOutVerts, iNumPts * sizeof(FOutVector));
|
||||
unsortedVertexArraySize += iNumPts;
|
||||
}
|
||||
else
|
||||
{
|
||||
static GLRGBAFloat poly = {0,0,0,0};
|
||||
static GLRGBAFloat tint = {0,0,0,0};
|
||||
static GLRGBAFloat fade = {0,0,0,0};
|
||||
if (PolyFlags & PF_ForceWrapY)
|
||||
Clamp2D(GL_TEXTURE_WRAP_T);
|
||||
}
|
||||
|
||||
SetBlend(PolyFlags); //TODO: inline (#pragma..)
|
||||
EXPORT void HWRAPI(DrawIndexedTriangles) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, unsigned int *IndexArray)
|
||||
{
|
||||
PreparePolygon(pSurf, pOutVerts, PolyFlags);
|
||||
|
||||
if (gl_portal_mode == HWD_PORTAL_NORMAL)
|
||||
{
|
||||
// PolyColor
|
||||
if (pSurf)
|
||||
{
|
||||
// If modulated, mix the surface colour to the texture
|
||||
if (CurrentPolyFlags & PF_Modulated)
|
||||
pglColor4ubv((GLubyte*)&pSurf->PolyColor.s);
|
||||
pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x);
|
||||
pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].s);
|
||||
pglDrawElements(GL_TRIANGLES, iNumPts, GL_UNSIGNED_INT, IndexArray);
|
||||
|
||||
// If the surface is either modulated or colormapped, or both
|
||||
if (CurrentPolyFlags & (PF_Modulated | PF_ColorMapped))
|
||||
{
|
||||
poly.red = byte2float[pSurf->PolyColor.s.red];
|
||||
poly.green = byte2float[pSurf->PolyColor.s.green];
|
||||
poly.blue = byte2float[pSurf->PolyColor.s.blue];
|
||||
poly.alpha = byte2float[pSurf->PolyColor.s.alpha];
|
||||
}
|
||||
|
||||
// Only if the surface is colormapped
|
||||
if (CurrentPolyFlags & PF_ColorMapped)
|
||||
{
|
||||
tint.red = byte2float[pSurf->TintColor.s.red];
|
||||
tint.green = byte2float[pSurf->TintColor.s.green];
|
||||
tint.blue = byte2float[pSurf->TintColor.s.blue];
|
||||
tint.alpha = byte2float[pSurf->TintColor.s.alpha];
|
||||
|
||||
fade.red = byte2float[pSurf->FadeColor.s.red];
|
||||
fade.green = byte2float[pSurf->FadeColor.s.green];
|
||||
fade.blue = byte2float[pSurf->FadeColor.s.blue];
|
||||
fade.alpha = byte2float[pSurf->FadeColor.s.alpha];
|
||||
|
||||
//if (pSurf->LightTableId && pSurf->LightTableId != lt_downloaded3)
|
||||
if (HWR_ShouldUsePaletteRendering())
|
||||
{
|
||||
pglActiveTexture(GL_TEXTURE2);
|
||||
pglBindTexture(GL_TEXTURE_2D, pSurf->LightTableId);
|
||||
pglActiveTexture(GL_TEXTURE0);
|
||||
//lt_downloaded3 = pSurf->LightTableId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Shader_Load(pSurf, &poly, &tint, &fade);
|
||||
}
|
||||
else
|
||||
UnSetShader();
|
||||
|
||||
pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x);
|
||||
pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].s);
|
||||
pglDrawArrays(GL_TRIANGLE_FAN, 0, iNumPts);
|
||||
|
||||
if (PolyFlags & PF_RemoveYWrap)
|
||||
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
if (PolyFlags & PF_ForceWrapX)
|
||||
Clamp2D(GL_TEXTURE_WRAP_S);
|
||||
|
||||
if (PolyFlags & PF_ForceWrapY)
|
||||
Clamp2D(GL_TEXTURE_WRAP_T);
|
||||
}
|
||||
// the DrawPolygon variant of this has some code about polyflags and wrapping here but havent noticed any problems from omitting it?
|
||||
}
|
||||
|
||||
// Sky dome code, taken/backported from SRB2
|
||||
@@ -3550,8 +2988,16 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float
|
||||
fade.green = byte2float[Surface->FadeColor.s.green];
|
||||
fade.blue = byte2float[Surface->FadeColor.s.blue];
|
||||
fade.alpha = byte2float[Surface->FadeColor.s.alpha];
|
||||
|
||||
if (Surface->LightTableId && Surface->LightTableId != lt_downloaded)
|
||||
{
|
||||
pglActiveTexture(GL_TEXTURE2);
|
||||
pglBindTexture(GL_TEXTURE_2D, Surface->LightTableId);
|
||||
pglActiveTexture(GL_TEXTURE0);
|
||||
lt_downloaded = Surface->LightTableId;
|
||||
}
|
||||
|
||||
Shader_Load(Surface, &poly, &tint, &fade);
|
||||
Shader_SetUniforms(Surface, &poly, &tint, &fade);
|
||||
|
||||
pglEnable(GL_CULL_FACE);
|
||||
pglEnable(GL_NORMALIZE);
|
||||
@@ -4416,9 +3862,7 @@ EXPORT void HWRAPI(ClearLightTables)(void)
|
||||
LightTablesTail = NULL;
|
||||
|
||||
// we no longer have a bound light table (if we had one), we just deleted it!
|
||||
//lt_downloaded = 0;
|
||||
//lt_downloaded2 = 0;
|
||||
//lt_downloaded3 = 0;
|
||||
lt_downloaded = 0;
|
||||
}
|
||||
|
||||
// This palette is used for the palette rendering postprocessing step.
|
||||
|
||||
@@ -218,6 +218,7 @@
|
||||
<ClInclude Include="..\hardware\hw3dsdrv.h" />
|
||||
<ClInclude Include="..\hardware\hw3sound.h" />
|
||||
<ClInclude Include="..\hardware\hws_data.h" />
|
||||
<ClInclude Include="..\hardware\hw_batching.h" />
|
||||
<ClInclude Include="..\hardware\hw_clip.h" />
|
||||
<ClInclude Include="..\hardware\hw_data.h" />
|
||||
<ClInclude Include="..\hardware\hw_defs.h" />
|
||||
@@ -364,6 +365,7 @@
|
||||
<ClCompile Include="..\g_game.c" />
|
||||
<ClCompile Include="..\g_input.c" />
|
||||
<ClCompile Include="..\hardware\hw3sound.c" />
|
||||
<ClCompile Include="..\hardware\hw_batching.c" />
|
||||
<ClCompile Include="..\hardware\hw_bsp.c" />
|
||||
<ClCompile Include="..\hardware\hw_cache.c" />
|
||||
<ClCompile Include="..\hardware\hw_clip.c" />
|
||||
|
||||
@@ -215,6 +215,9 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\hardware\hws_data.h">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\hardware\hw_batching.h">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\hardware\hw_clip.h">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
@@ -617,6 +620,9 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\hardware\hw3sound.c">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\hardware\hw_batching.c">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\hardware\hw_bsp.c">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
|
||||
+1
-3
@@ -81,6 +81,7 @@ void *hwSym(const char *funcName,void *handle)
|
||||
GETFUNC(SetupGLInfo);
|
||||
GETFUNC(Draw2DLine);
|
||||
GETFUNC(DrawPolygon);
|
||||
GETFUNC(DrawIndexedTriangles);
|
||||
GETFUNC(SetBlend);
|
||||
GETFUNC(ClearBuffer);
|
||||
GETFUNC(SetTexture);
|
||||
@@ -115,9 +116,6 @@ void *hwSym(const char *funcName,void *handle)
|
||||
GETFUNC(LoadCustomShader);
|
||||
GETFUNC(InitCustomShaders);
|
||||
|
||||
GETFUNC(StartBatching);
|
||||
GETFUNC(RenderBatches);
|
||||
|
||||
GETFUNC(SetPaletteLookup);
|
||||
GETFUNC(CreateLightTable);
|
||||
GETFUNC(ClearLightTables);
|
||||
|
||||
+1
-3
@@ -2125,6 +2125,7 @@ void I_StartupGraphics(void)
|
||||
HWD.pfnFinishUpdate = NULL;
|
||||
HWD.pfnDraw2DLine = hwSym("Draw2DLine",NULL);
|
||||
HWD.pfnDrawPolygon = hwSym("DrawPolygon",NULL);
|
||||
HWD.pfnDrawIndexedTriangles = hwSym("DrawIndexedTriangles",NULL);
|
||||
HWD.pfnSetBlend = hwSym("SetBlend",NULL);
|
||||
HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL);
|
||||
HWD.pfnSetTexture = hwSym("SetTexture",NULL);
|
||||
@@ -2160,9 +2161,6 @@ void I_StartupGraphics(void)
|
||||
HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL);
|
||||
HWD.pfnInitCustomShaders = hwSym("InitCustomShaders",NULL);
|
||||
|
||||
HWD.pfnStartBatching = hwSym("StartBatching",NULL);
|
||||
HWD.pfnRenderBatches = hwSym("RenderBatches",NULL);
|
||||
|
||||
HWD.pfnSetPaletteLookup = hwSym("SetPaletteLookup",NULL);
|
||||
HWD.pfnCreateLightTable = hwSym("CreateLightTable",NULL);
|
||||
HWD.pfnClearLightTables = hwSym("ClearLightTables",NULL);
|
||||
|
||||
Reference in new issue
Block a user