Portal Hell PT2
https://git.do.srb2.org/STJr/SRB2/-/merge_requests/1774/diffs\?commit_id\=f6638c0f90a35cc13d97b985389bc058e1d57c3e
This commit is contained in:
parent
a739573ca1
commit
0b1854ed3d
12 changed files with 161 additions and 177 deletions
|
|
@ -33,8 +33,6 @@ typedef struct
|
|||
GLMipmap_t *current_texture = NULL;
|
||||
GLMipmap_t *current_brightmap = NULL;
|
||||
|
||||
//boolean currently_batching = false;
|
||||
|
||||
// Dynamic arrays for:
|
||||
// - unsorted draw calls
|
||||
// - unsorted vertices
|
||||
|
|
@ -55,7 +53,7 @@ typedef struct
|
|||
#define STATE_STACK_SIZE 2
|
||||
BatchingState stateStack[STATE_STACK_SIZE] = {0};
|
||||
int stateStackLevel = 0; // currently used level in state stack
|
||||
BatchingState *curState = &stateStack[0];
|
||||
BatchingState *cst = &stateStack[0];
|
||||
|
||||
// Dynamic arrays for:
|
||||
// - sorted order of draw calls
|
||||
|
|
@ -64,20 +62,10 @@ BatchingState *curState = &stateStack[0];
|
|||
// These are only used during HWR_RenderBatches so they don't need
|
||||
// to be in the state stac
|
||||
|
||||
// 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;
|
||||
|
|
@ -92,36 +80,36 @@ int finalIndicesSize = 0;
|
|||
// Call HWR_RenderBatches to render all the collected geometry.
|
||||
void HWR_StartBatching(void)
|
||||
{
|
||||
if (curState->currently_batching)
|
||||
if (cst->currently_batching)
|
||||
I_Error("Repeat call to HWR_StartBatching without HWR_RenderBatches");
|
||||
|
||||
// init arrays if that has not been done yet
|
||||
if (!curState->drawCalls)
|
||||
if (!cst->drawCalls)
|
||||
{
|
||||
curState->drawCallsCapacity = curState->unsortedVerticesCapacity = 65536;
|
||||
curState->drawCalls = malloc(
|
||||
curState->drawCallsCapacity * sizeof(DrawCallInfo));
|
||||
curState->unsortedVertices = malloc(
|
||||
curState->unsortedVerticesCapacity * sizeof(FOutVector));
|
||||
cst->drawCallsCapacity = cst->unsortedVerticesCapacity = 65536;
|
||||
cst->drawCalls = malloc(
|
||||
cst->drawCallsCapacity * sizeof(DrawCallInfo));
|
||||
cst->unsortedVertices = malloc(
|
||||
cst->unsortedVerticesCapacity * sizeof(FOutVector));
|
||||
}
|
||||
if (!finalVertices)
|
||||
{
|
||||
finalVertices = malloc(finalVerticesCapacity * sizeof(FOutVector));
|
||||
finalIndices = malloc(finalVerticesCapacity * 3 * sizeof(UINT32));
|
||||
drawCallOrder = malloc(curState->drawCallsCapacity * sizeof(UINT32));
|
||||
drawCallOrder = malloc(cst->drawCallsCapacity * sizeof(UINT32));
|
||||
}
|
||||
|
||||
curState->currently_batching = true;
|
||||
cst->currently_batching = true;
|
||||
}
|
||||
|
||||
// Disable batching while keeping collected draw calls.
|
||||
// Call HWR_StartBatching again to resume.
|
||||
void HWR_PauseBatching(void)
|
||||
{
|
||||
if (!curState->currently_batching)
|
||||
if (!cst->currently_batching)
|
||||
I_Error("HWR_PauseBatching: batching not started");
|
||||
|
||||
curState->currently_batching = false;
|
||||
cst->currently_batching = false;
|
||||
}
|
||||
|
||||
// This replaces the direct calls to pfnSetTexture in cases where batching is available.
|
||||
|
|
@ -129,7 +117,7 @@ void HWR_PauseBatching(void)
|
|||
// Doing this was easier than getting a texture pointer to HWR_ProcessPolygon.
|
||||
void HWR_SetCurrentTexture(GLMipmap_t *texture)
|
||||
{
|
||||
if (curState->currently_batching)
|
||||
if (cst->currently_batching)
|
||||
{
|
||||
if (texture != NULL)
|
||||
{
|
||||
|
|
@ -151,48 +139,48 @@ void HWR_SetCurrentTexture(GLMipmap_t *texture)
|
|||
static void HWR_CollectDrawCallInfo(FSurfaceInfo *pSurf, FUINT iNumPts, FBITFIELD PolyFlags, int shader_target, boolean horizonSpecial)
|
||||
{
|
||||
// make sure dynamic array has capacity
|
||||
if (curState->drawCallsSize == curState->drawCallsCapacity)
|
||||
if (cst->drawCallsSize == cst->drawCallsCapacity)
|
||||
{
|
||||
DrawCallInfo* new_array;
|
||||
// ran out of space, make new array double the size
|
||||
curState->drawCallsCapacity *= 2;
|
||||
new_array = malloc(curState->drawCallsCapacity * sizeof(DrawCallInfo));
|
||||
memcpy(new_array, curState->drawCalls, curState->drawCallsSize * sizeof(DrawCallInfo));
|
||||
free(curState->drawCalls);
|
||||
curState->drawCalls = new_array;
|
||||
cst->drawCallsCapacity *= 2;
|
||||
new_array = malloc(cst->drawCallsCapacity * sizeof(DrawCallInfo));
|
||||
memcpy(new_array, cst->drawCalls, cst->drawCallsSize * sizeof(DrawCallInfo));
|
||||
free(cst->drawCalls);
|
||||
cst->drawCalls = new_array;
|
||||
// also need to redo the index array, dont need to copy it though
|
||||
free(drawCallOrder);
|
||||
drawCallOrder = malloc(curState->drawCallsCapacity * sizeof(UINT32));
|
||||
drawCallOrder = malloc(cst->drawCallsCapacity * sizeof(UINT32));
|
||||
}
|
||||
// add entry to array
|
||||
curState->drawCalls[curState->drawCallsSize].surf = *pSurf;
|
||||
curState->drawCalls[curState->drawCallsSize].vertsIndex = curState->unsortedVerticesSize;
|
||||
curState->drawCalls[curState->drawCallsSize].numVerts = iNumPts;
|
||||
curState->drawCalls[curState->drawCallsSize].polyFlags = PolyFlags;
|
||||
curState->drawCalls[curState->drawCallsSize].texture = current_texture;
|
||||
curState->drawCalls[curState->drawCallsSize].brightmap = current_brightmap;
|
||||
curState->drawCalls[curState->drawCallsSize].shader = (shader_target != -1) ? HWR_GetShaderFromTarget(shader_target) : shader_target;
|
||||
curState->drawCalls[curState->drawCallsSize].horizonSpecial = horizonSpecial;
|
||||
curState->drawCallsSize++;
|
||||
cst->drawCalls[cst->drawCallsSize].surf = *pSurf;
|
||||
cst->drawCalls[cst->drawCallsSize].vertsIndex = cst->unsortedVerticesSize;
|
||||
cst->drawCalls[cst->drawCallsSize].numVerts = iNumPts;
|
||||
cst->drawCalls[cst->drawCallsSize].polyFlags = PolyFlags;
|
||||
cst->drawCalls[cst->drawCallsSize].texture = current_texture;
|
||||
cst->drawCalls[cst->drawCallsSize].brightmap = current_brightmap;
|
||||
cst->drawCalls[cst->drawCallsSize].shader = (shader_target != -1) ? HWR_GetShaderFromTarget(shader_target) : shader_target;
|
||||
cst->drawCalls[cst->drawCallsSize].horizonSpecial = horizonSpecial;
|
||||
cst->drawCallsSize++;
|
||||
}
|
||||
|
||||
static void HWR_CollectDrawCallVertices(FOutVector *pOutVerts, FUINT iNumPts)
|
||||
{
|
||||
// make sure dynamic array has capacity
|
||||
while (curState->unsortedVerticesSize + (int)iNumPts >
|
||||
curState->unsortedVerticesCapacity)
|
||||
while (cst->unsortedVerticesSize + (int)iNumPts >
|
||||
cst->unsortedVerticesCapacity)
|
||||
{
|
||||
FOutVector* new_array;
|
||||
// need more space for vertices in unsortedVertices
|
||||
curState->unsortedVerticesCapacity *= 2;
|
||||
new_array = malloc(curState->unsortedVerticesCapacity * sizeof(FOutVector));
|
||||
memcpy(new_array, curState->unsortedVertices, curState->unsortedVerticesSize * sizeof(FOutVector));
|
||||
free(curState->unsortedVertices);
|
||||
curState->unsortedVertices = new_array;
|
||||
cst->unsortedVerticesCapacity *= 2;
|
||||
new_array = malloc(cst->unsortedVerticesCapacity * sizeof(FOutVector));
|
||||
memcpy(new_array, cst->unsortedVertices, cst->unsortedVerticesSize * sizeof(FOutVector));
|
||||
free(cst->unsortedVertices);
|
||||
cst->unsortedVertices = new_array;
|
||||
}
|
||||
// add vertices to array
|
||||
memcpy(&curState->unsortedVertices[curState->unsortedVerticesSize], pOutVerts, iNumPts * sizeof(FOutVector));
|
||||
curState->unsortedVerticesSize += iNumPts;
|
||||
memcpy(&cst->unsortedVertices[cst->unsortedVerticesSize], pOutVerts, iNumPts * sizeof(FOutVector));
|
||||
cst->unsortedVerticesSize += iNumPts;
|
||||
}
|
||||
|
||||
// If batching is enabled, this function collects the polygon data and the chosen texture
|
||||
|
|
@ -200,7 +188,7 @@ static void HWR_CollectDrawCallVertices(FOutVector *pOutVerts, FUINT iNumPts)
|
|||
// render the polygon immediately.
|
||||
void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader_target, boolean horizonSpecial)
|
||||
{
|
||||
if (curState->currently_batching)
|
||||
if (cst->currently_batching)
|
||||
{
|
||||
if (!pSurf)
|
||||
{
|
||||
|
|
@ -218,33 +206,30 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
|
|||
}
|
||||
}
|
||||
|
||||
// TODO could alternatively save drawCalls and unsortedVertices variables here
|
||||
// instead of having "curState->" everywhere
|
||||
void HWR_PushBatchingState(void)
|
||||
{
|
||||
if (stateStackLevel == STATE_STACK_SIZE - 1)
|
||||
I_Error("HWR_PushBatchingState: State stack overflow");
|
||||
|
||||
stateStackLevel++;
|
||||
curState++;
|
||||
cst++;
|
||||
}
|
||||
|
||||
// TODO as above
|
||||
void HWR_PopBatchingState(void)
|
||||
{
|
||||
if (stateStackLevel == 0)
|
||||
I_Error("HWR_PopBatchingState: State stack underflow");
|
||||
|
||||
stateStackLevel--;
|
||||
curState--;
|
||||
cst--;
|
||||
}
|
||||
|
||||
static int compareDrawCalls(const void *p1, const void *p2)
|
||||
{
|
||||
UINT32 index1 = *(const UINT32*)p1;
|
||||
UINT32 index2 = *(const UINT32*)p2;
|
||||
DrawCallInfo* poly1 = &curState->drawCalls[index1];
|
||||
DrawCallInfo* poly2 = &curState->drawCalls[index2];
|
||||
DrawCallInfo* poly1 = &cst->drawCalls[index1];
|
||||
DrawCallInfo* poly2 = &cst->drawCalls[index2];
|
||||
int diff;
|
||||
INT64 diff64;
|
||||
UINT32 downloaded1 = 0;
|
||||
|
|
@ -306,8 +291,8 @@ static int compareDrawCallsNoShaders(const void *p1, const void *p2)
|
|||
{
|
||||
unsigned int index1 = *(const unsigned int*)p1;
|
||||
unsigned int index2 = *(const unsigned int*)p2;
|
||||
DrawCallInfo* poly1 = &curState->drawCalls[index1];
|
||||
DrawCallInfo* poly2 = &curState->drawCalls[index2];
|
||||
DrawCallInfo* poly1 = &cst->drawCalls[index1];
|
||||
DrawCallInfo* poly2 = &cst->drawCalls[index2];
|
||||
int diff;
|
||||
INT64 diff64;
|
||||
|
||||
|
|
@ -363,7 +348,7 @@ static void HWR_CollectVerticesIntoBatch(DrawCallInfo *drawCall)
|
|||
finalIndices = new_index_array;
|
||||
}
|
||||
// write the vertices of the polygon
|
||||
memcpy(&finalVertices[finalVerticesSize], &curState->unsortedVertices[drawCall->vertsIndex],
|
||||
memcpy(&finalVertices[finalVerticesSize], &cst->unsortedVertices[drawCall->vertsIndex],
|
||||
numVerts * sizeof(FOutVector));
|
||||
// write the indexes, pointing to the fan vertexes but in triangles format
|
||||
firstVIndex = finalVerticesSize;
|
||||
|
|
@ -461,7 +446,7 @@ static void HWR_ExecuteStateChanges(unsigned int stateChanges, DrawCallInfo *dc)
|
|||
|
||||
static void HWR_InitBatchingStats(void)
|
||||
{
|
||||
ps_hw_numpolys = curState->drawCallsSize;
|
||||
ps_hw_numpolys = cst->drawCallsSize;
|
||||
ps_hw_numcalls = ps_hw_numverts
|
||||
= ps_hw_numshaders = ps_hw_numtextures
|
||||
= ps_hw_numpolyflags = ps_hw_numcolors = 0;
|
||||
|
|
@ -474,26 +459,26 @@ void HWR_RenderBatches(void)
|
|||
int drawCallReadPos = 0; // position in drawCallOrder
|
||||
int i;
|
||||
|
||||
if (!curState->currently_batching)
|
||||
if (!cst->currently_batching)
|
||||
I_Error("HWR_RenderBatches called without starting batching");
|
||||
|
||||
curState->currently_batching = false; // no longer collecting batches
|
||||
cst->currently_batching = false; // no longer collecting batches
|
||||
|
||||
HWR_InitBatchingStats();
|
||||
|
||||
if (!curState->drawCallsSize)
|
||||
if (!cst->drawCallsSize)
|
||||
return; // nothing to draw
|
||||
|
||||
// init drawCallOrder
|
||||
for (i = 0; i < curState->drawCallsSize; i++)
|
||||
for (i = 0; i < cst->drawCallsSize; i++)
|
||||
drawCallOrder[i] = i;
|
||||
|
||||
// sort the draw calls
|
||||
ps_hw_batchsorttime = I_GetPreciseTime();
|
||||
if (cv_glshaders.value && gl_shadersavailable)
|
||||
qs22j(drawCallOrder, curState->drawCallsSize, sizeof(UINT32), compareDrawCalls);
|
||||
qs22j(drawCallOrder, cst->drawCallsSize, sizeof(UINT32), compareDrawCalls);
|
||||
else
|
||||
qs22j(drawCallOrder, curState->drawCallsSize, sizeof(UINT32), compareDrawCallsNoShaders);
|
||||
qs22j(drawCallOrder, cst->drawCallsSize, sizeof(UINT32), compareDrawCallsNoShaders);
|
||||
ps_hw_batchsorttime = I_GetPreciseTime() - ps_hw_batchsorttime;
|
||||
// sort grouping order
|
||||
// 1. shader
|
||||
|
|
@ -506,7 +491,7 @@ void HWR_RenderBatches(void)
|
|||
ps_hw_batchdrawtime = I_GetPreciseTime();
|
||||
|
||||
// set state for first batch
|
||||
HWR_ExecuteStateChanges(0xFFFF, &curState->drawCalls[drawCallOrder[0]]);
|
||||
HWR_ExecuteStateChanges(0xFFFF, &cst->drawCalls[drawCallOrder[0]]);
|
||||
|
||||
// - iterate through draw calls
|
||||
// - accumulate converted vertices and indices into finalVertices and finalIndices
|
||||
|
|
@ -527,18 +512,18 @@ void HWR_RenderBatches(void)
|
|||
// repeat loop
|
||||
|
||||
unsigned int stateChanges = 0; // flags defined above HWR_MarkStateChanges
|
||||
DrawCallInfo *currentDrawCall = &curState->drawCalls[drawCallOrder[drawCallReadPos++]];
|
||||
DrawCallInfo *currentDrawCall = &cst->drawCalls[drawCallOrder[drawCallReadPos++]];
|
||||
DrawCallInfo *nextDrawCall = NULL;
|
||||
|
||||
HWR_CollectVerticesIntoBatch(currentDrawCall);
|
||||
|
||||
if (drawCallReadPos >= curState->drawCallsSize) // was that the last draw call?
|
||||
if (drawCallReadPos >= cst->drawCallsSize) // was that the last draw call?
|
||||
{
|
||||
stopFlag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextDrawCall = &curState->drawCalls[drawCallOrder[drawCallReadPos]];
|
||||
nextDrawCall = &cst->drawCalls[drawCallOrder[drawCallReadPos]];
|
||||
stateChanges = HWR_MarkStateChanges(currentDrawCall, nextDrawCall);
|
||||
}
|
||||
|
||||
|
|
@ -564,8 +549,8 @@ void HWR_RenderBatches(void)
|
|||
HWR_ExecuteStateChanges(stateChanges, nextDrawCall);
|
||||
}
|
||||
// reset the arrays (set sizes to 0)
|
||||
curState->drawCallsSize = 0;
|
||||
curState->unsortedVerticesSize = 0;
|
||||
cst->drawCallsSize = 0;
|
||||
cst->unsortedVerticesSize = 0;
|
||||
|
||||
ps_hw_batchdrawtime = I_GetPreciseTime() - ps_hw_batchdrawtime;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ static boolean HWR_PortalCheckPointSide(fixed_t x, fixed_t y)
|
|||
P_ClosestPointOnLine(x, y, gl_portalclipline, &closest_point);
|
||||
if (closest_point.x != x || closest_point.y != y)
|
||||
{
|
||||
if (P_PointOnLineSide(x, y, gl_portalclipline) != gl_portalviewside)
|
||||
if (P_PointOnLineSide(x, y, gl_portalclipline) != 1)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -309,9 +309,7 @@ enum hwdsetspecialstate
|
|||
HWD_SET_SHADERS,
|
||||
HWD_SET_TEXTUREFILTERMODE,
|
||||
HWD_SET_TEXTUREANISOTROPICMODE,
|
||||
HWD_SET_STENCIL_MODE,
|
||||
HWD_SET_STENCIL_LEVEL, // must set mode afterwards for level to come into effect
|
||||
HWD_NUMSTATE // (TODO could create separate stencil function in r_opengl.c to avoid hacky behaviour like this)
|
||||
HWD_NUMSTATE
|
||||
};
|
||||
typedef enum hwdsetspecialstate hwdspecialstate_t;
|
||||
|
||||
|
|
@ -323,8 +321,8 @@ enum hwdshaderstage
|
|||
|
||||
typedef enum hwdshaderstage hwdshaderstage_t;
|
||||
|
||||
// stencil modes
|
||||
enum
|
||||
// Modes for SetStencilMode
|
||||
enum hwdstencilmode
|
||||
{
|
||||
HWD_STENCIL_INACTIVE,
|
||||
HWD_STENCIL_PORTAL_BEGIN,
|
||||
|
|
@ -332,6 +330,8 @@ enum
|
|||
HWD_STENCIL_PORTAL_FINISH
|
||||
};
|
||||
|
||||
typedef enum hwdstencilmode hwdstencilmode_t;
|
||||
|
||||
// Lactozilla: Shader info
|
||||
// Generally set at the start of the frame.
|
||||
enum hwdshaderinfo
|
||||
|
|
|
|||
|
|
@ -82,9 +82,6 @@ typedef struct
|
|||
|
||||
// initial size of drawnode array
|
||||
#define DRAWNODES_INIT_SIZE 64
|
||||
/*gl_drawnode_t *drawnodes = NULL;
|
||||
INT32 numdrawnodes = 0;
|
||||
INT32 alloceddrawnodes = 0;*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
|
@ -93,10 +90,9 @@ typedef struct
|
|||
INT32 alloceddrawnodes;
|
||||
} gl_drawnode_state_t;
|
||||
|
||||
// todo magic number 16
|
||||
// portal rendering will push and pop this stack
|
||||
// to keep multiple drawnode lists around until they're needed
|
||||
static gl_drawnode_state_t state_stack[16] = {0};
|
||||
static gl_drawnode_state_t state_stack[MAXPORTALS_CAP+1] = {0};
|
||||
static int stack_level = 0;
|
||||
static gl_drawnode_state_t *cst = &state_stack[0]; // current state
|
||||
|
||||
|
|
@ -183,8 +179,7 @@ void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polyse
|
|||
// pushes all drawnode rendering state to stack
|
||||
void HWR_PushDrawNodeState(void)
|
||||
{
|
||||
// todo magic number 16
|
||||
if (stack_level == 15)
|
||||
if (stack_level == MAXPORTALS_CAP)
|
||||
I_Error("HWR_PushDrawNodeState: State stack overflow");
|
||||
|
||||
stack_level++;
|
||||
|
|
@ -208,7 +203,6 @@ static int CompareDrawNodePlanes(const void *p1, const void *p2)
|
|||
return ABS(cst->drawnodes[n2].u.plane.fixedheight - viewz) - ABS(cst->drawnodes[n1].u.plane.fixedheight - viewz);
|
||||
}
|
||||
|
||||
// HWR_RenderDrawNodes
|
||||
// Sorts and renders the list of drawnodes for the scene being rendered.
|
||||
void HWR_RenderDrawNodes(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ void GL_GClipRect(INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip
|
|||
void GL_ClearMipMapCache(void);
|
||||
|
||||
void GL_SetSpecialState(hwdspecialstate_t IdState, INT32 Value);
|
||||
void GL_SetStencilMode(hwdstencilmode_t mode, INT32 ref);
|
||||
|
||||
// Hurdler: added for new development
|
||||
void GL_DrawModel(model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface);
|
||||
|
|
|
|||
|
|
@ -157,14 +157,13 @@ typedef struct
|
|||
} gl_portal_array_t;
|
||||
|
||||
// TODO magic number 16
|
||||
gl_portal_array_t gl_portal_arrays[16] = {0};
|
||||
gl_portal_array_t gl_portal_arrays[MAXPORTALS_CAP+1] = {0};
|
||||
|
||||
INT32 gl_portal_level = 0; // portal recursion level
|
||||
|
||||
boolean gl_drawing_stencil = false; // used when drawing segs to stencil buffer
|
||||
sector_t *gl_portalcullsector = NULL;
|
||||
line_t *gl_portalclipline = NULL;
|
||||
INT32 gl_portalviewside = 0;
|
||||
|
||||
// debug tools
|
||||
boolean gl_printportals = false; // print info about portals on this frame
|
||||
|
|
@ -186,9 +185,6 @@ static void HWR_PortalFrame(gl_portal_t *portal, boolean set_culling)
|
|||
{
|
||||
gl_portalcullsector = portal->clipline->frontsector;
|
||||
gl_portalclipline = portal->clipline;
|
||||
gl_portalviewside = P_PointOnLineSide(viewx, viewy, gl_portalclipline);
|
||||
// TODO check is gl_portalviewside always the same value?
|
||||
// if it is then it's not needed to have this variable
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -201,6 +197,38 @@ static gl_portal_array_t *HWR_GetPortalArray(void)
|
|||
return &gl_portal_arrays[level];
|
||||
}
|
||||
|
||||
// TODO move to r_main.c next to fixed point functions?
|
||||
|
||||
// More precise version of R_PointToAngle2 using floats and atan2.
|
||||
static angle_t R_PointToAngle2Precise(fixed_t pviewx, fixed_t pviewy, fixed_t x, fixed_t y)
|
||||
{
|
||||
fixed_t dx = x - pviewx;
|
||||
fixed_t dy = y - pviewy;
|
||||
float radians;
|
||||
|
||||
if (!dx && !dy)
|
||||
return 0;
|
||||
|
||||
// no need for correct scale with FIXED_TO_FLOAT here
|
||||
// since we're just calculating the angle
|
||||
radians = atan2(dy, dx);
|
||||
|
||||
return (angle_t)(radians / M_PI * ANGLE_180);
|
||||
}
|
||||
|
||||
// More precise version of R_PointToDist2 using floats and sqrt.
|
||||
static fixed_t R_PointToDist2Precise(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1)
|
||||
{
|
||||
// float-fixed conversions can be omitted here
|
||||
// because they cancel each other out in this case
|
||||
|
||||
float dx = px1 - px2;
|
||||
float dy = py1 - py2;
|
||||
double result = sqrt(dx*dx + dy*dy);
|
||||
|
||||
return (fixed_t)result;
|
||||
}
|
||||
|
||||
boolean HWR_AddPortal(line_t *start, line_t *dest, seg_t *seg)
|
||||
{
|
||||
gl_portal_array_t *array;
|
||||
|
|
@ -212,8 +240,8 @@ boolean HWR_AddPortal(line_t *start, line_t *dest, seg_t *seg)
|
|||
vertex_t dest_c, start_c;
|
||||
|
||||
if ((gl_portal_level + gl_rendering_skybox) >= cv_maxportals.value ||
|
||||
(gl_debugportal &&
|
||||
(gl_debugportal != (start-lines) || gl_portal_level)))
|
||||
(gl_debugportal &&
|
||||
(gl_debugportal != (start-lines) || gl_portal_level)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -227,45 +255,51 @@ boolean HWR_AddPortal(line_t *start, line_t *dest, seg_t *seg)
|
|||
{
|
||||
array->capacity = INIT_PORTAL_ARRAY_SIZE;
|
||||
array->portals = Z_Malloc(sizeof(gl_portal_t) * array->capacity, PU_LEVEL,
|
||||
&array->portals);
|
||||
&array->portals);
|
||||
}
|
||||
else if (array->size == array->capacity)
|
||||
{
|
||||
array->capacity *= 2;
|
||||
array->portals = Z_Realloc(array->portals, sizeof(gl_portal_t) * array->capacity,
|
||||
PU_LEVEL, &array->portals);
|
||||
PU_LEVEL, &array->portals);
|
||||
}
|
||||
|
||||
portal = &array->portals[array->size++];
|
||||
|
||||
dangle = R_PointToAngle2(0,0,dest->dx,dest->dy) - R_PointToAngle2(start->dx,start->dy,0,0);
|
||||
|
||||
// using this order of operations change fixes ante station island portal
|
||||
// Most fixed-point calculations and trigonometric function tables are replaced by
|
||||
// floats and cmath library calls in this part to improve the precision of the
|
||||
// location and angle of the new viewpoint.
|
||||
//
|
||||
// This reduces artefacts on the edges of portals, showing thin lines/pixels
|
||||
// of the underlying graphics. (for example the sky texture) It's not 100%
|
||||
// perfectly aligned and artefact-free, but looks noticeably
|
||||
// better than the original code. I'm not even sure if it's this
|
||||
// code or the nodebuilder or hw_map or something else causing the remaining issues..
|
||||
//#define R_PointToAngle2Precise R_PointToAngle2
|
||||
//#define R_PointToDist2Precise R_PointToDist2
|
||||
dangle = R_PointToAngle2Precise(0,0,dest->dx,dest->dy) - R_PointToAngle2Precise(start->dx,start->dy,0,0);
|
||||
|
||||
// looking glass center
|
||||
//start_c.x = (start->v1->x + start->v2->x) / 2;
|
||||
//start_c.y = (start->v1->y + start->v2->y) / 2;
|
||||
start_c.x = start->v1->x/2 + start->v2->x/2;
|
||||
start_c.y = start->v1->y/2 + start->v2->y/2;
|
||||
|
||||
// other side center
|
||||
//dest_c.x = (dest->v1->x + dest->v2->x) / 2;
|
||||
//dest_c.y = (dest->v1->y + dest->v2->y) / 2;
|
||||
dest_c.x = dest->v1->x/2 + dest->v2->x/2;
|
||||
dest_c.y = dest->v1->y/2 + dest->v2->y/2;
|
||||
|
||||
disttopoint = R_PointToDist2(start_c.x, start_c.y, viewx, viewy);
|
||||
angtopoint = R_PointToAngle2(start_c.x, start_c.y, viewx, viewy);
|
||||
disttopoint = R_PointToDist2Precise(start_c.x, start_c.y, viewx, viewy);
|
||||
angtopoint = R_PointToAngle2Precise(start_c.x, start_c.y, viewx, viewy);
|
||||
angtopoint += dangle;
|
||||
|
||||
// could using float or double here help with the slight impreciseness of
|
||||
// the view coordinates?
|
||||
//float fang = ((float)angtopoint / 4294967296.0f) * 2.0f * M_PI;
|
||||
float fang = ((float)angtopoint / 4294967296.0f) * 2.0f * M_PI;
|
||||
|
||||
portal->viewx = dest_c.x + FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
|
||||
portal->viewy = dest_c.y + FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
|
||||
//portal->viewx = dest_c.x + FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
|
||||
//portal->viewy = dest_c.y + FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
|
||||
//portal->viewx = dest_c.x + FixedMul(FLOAT_TO_FIXED(cos(fang)), disttopoint);
|
||||
//portal->viewy = dest_c.y + FixedMul(FLOAT_TO_FIXED(sin(fang)), disttopoint);
|
||||
// cos and sin are just scaling disttopoint so no need for float-fixed conversions
|
||||
portal->viewx = dest_c.x + (fixed_t)(cos(fang) * disttopoint);
|
||||
portal->viewy = dest_c.y + (fixed_t)(sin(fang) * disttopoint);
|
||||
portal->viewz = viewz + dest->frontsector->floorheight - start->frontsector->floorheight;
|
||||
portal->viewangle = viewangle + dangle;
|
||||
portal->seg = seg;
|
||||
|
|
@ -437,7 +471,7 @@ UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap) // Let's see if
|
|||
|
||||
realcolor.rgba = (colormap != NULL) ? colormap->rgba : GL_DEFAULTMIX;
|
||||
|
||||
if (cv_glshaders.value && gl_shadersavailable)
|
||||
if (HWR_UseShader())
|
||||
{
|
||||
surfcolor.s.alpha = (255 - light);
|
||||
}
|
||||
|
|
@ -565,20 +599,6 @@ boolean HWR_BlendMidtextureSurface(FSurfaceInfo *pSurf)
|
|||
return true;
|
||||
}
|
||||
|
||||
// -----------------+
|
||||
// HWR_ClearView : clear the viewwindow, with maximum z value
|
||||
// -----------------+
|
||||
/*static inline void HWR_ClearView(void)
|
||||
{
|
||||
GL_GClipRect((INT32)gl_viewwindowx,
|
||||
(INT32)gl_viewwindowy,
|
||||
(INT32)(gl_viewwindowx + gl_viewwidth),
|
||||
(INT32)(gl_viewwindowy + gl_viewheight),
|
||||
ZCLIP_PLANE);
|
||||
GL_ClearBuffer(false, true, true, 0)
|
||||
}*/
|
||||
|
||||
|
||||
// -----------------+
|
||||
// HWR_SetViewSize : set projection and scaling values
|
||||
// -----------------+
|
||||
|
|
@ -680,6 +700,7 @@ static void HWR_PortalClipping(gl_portal_t *portal)
|
|||
gld_clipper_SafeAddClipRange(portal->angle1, portal->angle2);
|
||||
}
|
||||
|
||||
// Tells the backend are shaders being used for 3d rendering.
|
||||
static void HWR_SetShaderState(void)
|
||||
{
|
||||
GL_SetSpecialState(HWD_SET_SHADERS, (INT32)HWR_UseShader());
|
||||
|
|
@ -741,9 +762,6 @@ static void HWR_EnterSkyboxState(void)
|
|||
HWR_PushBatchingState();
|
||||
HWR_PushSpriteState();
|
||||
HWR_PushDrawNodeState();
|
||||
// need to use the next level in the portal arrays
|
||||
// so skybox doesn't interfere with previously collected portals
|
||||
//gl_portal_level++;
|
||||
gl_rendering_skybox = true;
|
||||
}
|
||||
|
||||
|
|
@ -752,8 +770,6 @@ static void HWR_LeaveSkyboxState(void)
|
|||
HWR_PopBatchingState();
|
||||
HWR_PopSpriteState();
|
||||
HWR_PopDrawNodeState();
|
||||
// see above comment
|
||||
//gl_portal_level--;
|
||||
gl_rendering_skybox = false;
|
||||
}
|
||||
|
||||
|
|
@ -767,16 +783,12 @@ static void HWR_RenderPortalSeg(seg_t *seg)
|
|||
gl_drawing_stencil = false;
|
||||
// need to work around the r_opengl PF_Invisible bug with this call
|
||||
// similarly as in the linkdraw hack in HWR_DrawSprites
|
||||
// TODO not completely sure if this is needed, check it? (try without)
|
||||
GL_SetBlend(PF_Translucent|PF_Occlude|PF_Masked);
|
||||
}
|
||||
|
||||
static void HWR_SetStencilState(INT32 state)
|
||||
{
|
||||
// this order of calls must be used for the stencil
|
||||
// level to take effect correctly
|
||||
GL_SetSpecialState(HWD_SET_STENCIL_LEVEL, gl_portal_level);
|
||||
GL_SetSpecialState(HWD_SET_STENCIL_MODE, state);
|
||||
GL_SetStencilMode(state, gl_portal_level);
|
||||
}
|
||||
|
||||
// clear the depth buffer from the stenciled area so portal
|
||||
|
|
@ -784,7 +796,7 @@ static void HWR_SetStencilState(INT32 state)
|
|||
// (glClear ignores the stencil buffer so can't be used for this purpose)
|
||||
static void HWR_RenderDepthEraser(boolean visible)
|
||||
{
|
||||
FOutVector verts[4] = {0}; // TODO not sure if PF_NoAlphaTest is needed?
|
||||
FOutVector verts[4] = {0};
|
||||
FBITFIELD blendflags = PF_Occlude|PF_NoDepthTest|PF_NoTexture|PF_NoAlphaTest;
|
||||
if (!visible)
|
||||
blendflags |= PF_Invisible;
|
||||
|
|
@ -897,7 +909,6 @@ static void HWR_RenderViewpoint(player_t *player, boolean drawSkyTexture, boolea
|
|||
{
|
||||
//if (gl_printportals)
|
||||
// CONS_Printf("drawing a skybox\n");
|
||||
// TODO NOTE this probably wont set correct position under portals?
|
||||
R_SkyboxFrame(viewssnum);
|
||||
// render skybox while keeping batches, sprites and drawnodes
|
||||
// from the regular viewpoint stashed in the state stacks
|
||||
|
|
@ -1250,6 +1261,9 @@ void CV_glpalettedepth_OnChange(void);
|
|||
consvar_t cv_glpaletterendering = CVAR_INIT ("gr_paletteshader", "Off", CV_CALL|CV_SAVE, CV_OnOff, CV_glpaletterendering_OnChange);
|
||||
consvar_t cv_glpalettedepth = CVAR_INIT ("gr_palettedepth", "16 bits", CV_SAVE|CV_CALL, glpalettedepth_cons_t, CV_glpalettedepth_OnChange);
|
||||
|
||||
// Isolates rendering to one of the top level portals.
|
||||
// (Stencil cutting of the portal is also disabled)
|
||||
// Use gr_printportals to find the number to use.
|
||||
consvar_t cv_gldebugportal = CVAR_INIT ("gr_debugportal", "0", 0, CV_Unsigned, NULL);
|
||||
|
||||
consvar_t cv_glskydebug = CVAR_INIT ("gr_skydebug", "0", 0, CV_Unsigned, NULL);
|
||||
|
|
|
|||
|
|
@ -177,7 +177,6 @@ extern INT32 gl_portal_level;
|
|||
extern boolean gl_drawing_stencil;
|
||||
extern sector_t *gl_portalcullsector;
|
||||
extern line_t *gl_portalclipline;
|
||||
extern INT32 gl_portalviewside;
|
||||
|
||||
extern boolean gl_printportals;
|
||||
extern INT32 gl_debugportal;
|
||||
|
|
|
|||
|
|
@ -479,9 +479,9 @@ static void HWR_ProcessTwoSidedSegMiddle(FOutVector *wallVerts, FSurfaceInfo *Su
|
|||
sector_t *front, *back;
|
||||
fixed_t h, l; // 2s middle textures
|
||||
fixed_t hS, lS;
|
||||
fixed_t popentop, popenbottom, polytop, polybottom, lowcut, highcut;
|
||||
fixed_t popentop, popenbottom, polytop, polybottom, lowcut, highcut;
|
||||
fixed_t popentopslope, popenbottomslope, polytopslope, polybottomslope, lowcutslope, highcutslope;
|
||||
fixed_t texturevpeg = 0;
|
||||
fixed_t texturevpeg = 0;
|
||||
INT32 repeats;
|
||||
fixed_t midtexheight = 0;
|
||||
fixed_t texturevpegslope = 0;
|
||||
|
|
|
|||
|
|
@ -28,9 +28,6 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing);
|
|||
// sprites are drawn after all wall and planes are rendered, so that
|
||||
// sprite translucency effects apply on the rendered view (instead of the background sky!!)
|
||||
|
||||
//UINT32 gl_visspritecount;
|
||||
//static gl_vissprite_t *gl_visspritechunks[MAXVISSPRITES >> VISSPRITECHUNKBITS] = {NULL};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FOutVector verts[4];
|
||||
|
|
@ -47,8 +44,7 @@ typedef struct
|
|||
|
||||
// TODO this array is ~3 megabytes because of linkdrawlist...
|
||||
// maybe turn that into a dynamic array
|
||||
// TODO magic number 16
|
||||
static gl_sprite_state_t state_stack[16] = {0};
|
||||
static gl_sprite_state_t state_stack[MAXPORTALS_CAP+1] = {0};
|
||||
static int stack_level = 0;
|
||||
static gl_sprite_state_t *cst = &state_stack[0]; // current state
|
||||
|
||||
|
|
@ -64,8 +60,7 @@ void HWR_ClearSprites(void)
|
|||
// pushes all sprite rendering state to stack
|
||||
void HWR_PushSpriteState(void)
|
||||
{
|
||||
// todo magic number 16
|
||||
if (stack_level == 15)
|
||||
if (stack_level == MAXPORTALS_CAP)
|
||||
I_Error("HWR_PushSpriteState: State stack overflow");
|
||||
|
||||
stack_level++;
|
||||
|
|
@ -111,11 +106,6 @@ static gl_vissprite_t *HWR_NewVisSprite(void)
|
|||
// NOTE: This will no longer be necessary once full translucent sorting is implemented, where
|
||||
// translucent sprites and surfaces are sorted together.
|
||||
|
||||
/*
|
||||
// this list is used to store data about linkdraw sprites
|
||||
zbuffersprite_t linkdrawlist[MAXVISSPRITES];
|
||||
UINT32 linkdrawcount = 0;*/
|
||||
|
||||
// add the necessary data to the list for delayed z-buffer drawing
|
||||
static void HWR_LinkDrawHackAdd(FOutVector *verts, gl_vissprite_t *spr)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -73,7 +73,6 @@ static GLuint tex_downloaded = 0;
|
|||
static GLuint lt_downloaded = 0; // currently bound lighttable texture
|
||||
static GLfloat fov = 90.0f;
|
||||
static FBITFIELD CurrentPolyFlags;
|
||||
static GLint gl_stencil_ref = 0;
|
||||
|
||||
// Linked list of all textures.
|
||||
static FTextureInfo *TexCacheTail = NULL;
|
||||
|
|
@ -2400,33 +2399,32 @@ void GL_SetSpecialState(hwdspecialstate_t IdState, INT32 Value)
|
|||
Flush(); //??? if we want to change filter mode by texture, remove this
|
||||
break;
|
||||
|
||||
case HWD_SET_STENCIL_MODE:
|
||||
switch (Value)
|
||||
{
|
||||
case HWD_STENCIL_INACTIVE:
|
||||
pglStencilFunc(GL_ALWAYS, gl_stencil_ref, 0xFF);
|
||||
pglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
break;
|
||||
case HWD_STENCIL_PORTAL_BEGIN:
|
||||
pglStencilFunc(GL_EQUAL, gl_stencil_ref, 0xFF);
|
||||
pglStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
|
||||
break;
|
||||
case HWD_STENCIL_PORTAL_INSIDE:
|
||||
pglStencilFunc(GL_EQUAL, gl_stencil_ref, 0xFF);
|
||||
pglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
break;
|
||||
case HWD_STENCIL_PORTAL_FINISH:
|
||||
pglStencilFunc(GL_EQUAL, gl_stencil_ref, 0xFF);
|
||||
pglStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case HWD_SET_STENCIL_LEVEL:
|
||||
gl_stencil_ref = Value;
|
||||
void GL_SetStencilMode(hwdstencilmode_t mode, INT32 ref)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case HWD_STENCIL_INACTIVE:
|
||||
pglStencilFunc(GL_ALWAYS, ref, 0xFF);
|
||||
pglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
break;
|
||||
|
||||
default:
|
||||
case HWD_STENCIL_PORTAL_BEGIN:
|
||||
pglStencilFunc(GL_EQUAL, ref, 0xFF);
|
||||
pglStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
|
||||
break;
|
||||
case HWD_STENCIL_PORTAL_INSIDE:
|
||||
pglStencilFunc(GL_EQUAL, ref, 0xFF);
|
||||
pglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
break;
|
||||
case HWD_STENCIL_PORTAL_FINISH:
|
||||
pglStencilFunc(GL_EQUAL, ref, 0xFF);
|
||||
pglStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ static CV_PossibleValue_t drawdist_precip_cons_t[] = {
|
|||
|
||||
static CV_PossibleValue_t fov_cons_t[] = {{60*FRACUNIT, "MIN"}, {179*FRACUNIT, "MAX"}, {0, NULL}};
|
||||
static CV_PossibleValue_t translucenthud_cons_t[] = {{0, "MIN"}, {10, "MAX"}, {0, NULL}};
|
||||
static CV_PossibleValue_t maxportals_cons_t[] = {{0, "MIN"}, {12, "MAX"}, {0, NULL}}; // lmao rendering 32 portals, you're a card
|
||||
static CV_PossibleValue_t maxportals_cons_t[] = {{0, "MIN"}, {MAXPORTALS_CAP, "MAX"}, {0, NULL}}; // lmao rendering 32 portals, you're a card
|
||||
static CV_PossibleValue_t homremoval_cons_t[] = {{0, "No"}, {1, "Yes"}, {2, "Flash"}, {0, NULL}};
|
||||
static CV_PossibleValue_t secbright_cons_t[] = {{0, "MIN"}, {255, "MAX"}, {0, NULL}};
|
||||
|
||||
|
|
|
|||
|
|
@ -108,6 +108,9 @@ extern player_t *viewplayer;
|
|||
extern mobj_t *r_viewmobj;
|
||||
|
||||
extern consvar_t cv_allowmlook;
|
||||
|
||||
// maximum value for maxportals cvar
|
||||
#define MAXPORTALS_CAP 12
|
||||
extern consvar_t cv_maxportals;
|
||||
|
||||
extern angle_t clipangle[MAXSPLITSCREENPLAYERS];
|
||||
|
|
|
|||
Loading…
Reference in a new issue