mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-28 23:11:58 +00:00
- moved all methods that would involve command buffer manipulation in Vulkan to FRenderState, because that's the object that would serve as command buffer builder.
This commit is contained in:
parent
2ee2766812
commit
9f9d747a6b
21 changed files with 314 additions and 311 deletions
|
@ -440,7 +440,7 @@ void FGLRenderer::Draw2D(F2DDrawer *drawer)
|
|||
FDrawInfo di; // For access to the virtual interface. This should be placed elsewhere...
|
||||
const auto &mScreenViewport = screen->mScreenViewport;
|
||||
glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
|
||||
screen->mViewpoints->Set2D(&di, screen->GetWidth(), screen->GetHeight());
|
||||
screen->mViewpoints->Set2D(gl_RenderState, screen->GetWidth(), screen->GetHeight());
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
|
|
|
@ -39,6 +39,8 @@
|
|||
#include "gl/renderer/gl_renderbuffers.h"
|
||||
#include "gl/textures/gl_hwtexture.h"
|
||||
#include "gl/system/gl_buffers.h"
|
||||
#include "hwrenderer/utility/hw_clock.h"
|
||||
#include "hwrenderer/data/hw_viewpointbuffer.h"
|
||||
|
||||
FGLRenderState gl_RenderState;
|
||||
|
||||
|
@ -375,3 +377,144 @@ void FGLRenderState::ApplyBlendMode()
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// API dependent draw calls
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static int dt2gl[] = { GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_FAN, GL_TRIANGLE_STRIP };
|
||||
|
||||
void FGLRenderState::Draw(int dt, int index, int count, bool apply)
|
||||
{
|
||||
assert(this == &gl_RenderState);
|
||||
if (apply)
|
||||
{
|
||||
gl_RenderState.Apply();
|
||||
}
|
||||
drawcalls.Clock();
|
||||
glDrawArrays(dt2gl[dt], index, count);
|
||||
drawcalls.Unclock();
|
||||
}
|
||||
|
||||
void FGLRenderState::DrawIndexed(int dt, int index, int count, bool apply)
|
||||
{
|
||||
assert(this == &gl_RenderState);
|
||||
if (apply)
|
||||
{
|
||||
gl_RenderState.Apply();
|
||||
}
|
||||
drawcalls.Clock();
|
||||
glDrawElements(dt2gl[dt], count, GL_UNSIGNED_INT, (void*)(intptr_t)(index * sizeof(uint32_t)));
|
||||
drawcalls.Unclock();
|
||||
}
|
||||
|
||||
void FGLRenderState::SetDepthMask(bool on)
|
||||
{
|
||||
glDepthMask(on);
|
||||
}
|
||||
|
||||
void FGLRenderState::SetDepthFunc(int func)
|
||||
{
|
||||
static int df2gl[] = { GL_LESS, GL_LEQUAL, GL_ALWAYS };
|
||||
glDepthFunc(df2gl[func]);
|
||||
}
|
||||
|
||||
void FGLRenderState::SetDepthRange(float min, float max)
|
||||
{
|
||||
glDepthRange(min, max);
|
||||
}
|
||||
|
||||
void FGLRenderState::EnableDrawBufferAttachments(bool on)
|
||||
{
|
||||
EnableDrawBuffers(on ? gl_RenderState.GetPassDrawBufferCount() : 1);
|
||||
}
|
||||
|
||||
void FGLRenderState::SetStencil(int offs, int op, int flags)
|
||||
{
|
||||
static int op2gl[] = { GL_KEEP, GL_INCR, GL_DECR };
|
||||
|
||||
glStencilFunc(GL_EQUAL, screen->stencilValue + offs, ~0); // draw sky into stencil
|
||||
glStencilOp(GL_KEEP, GL_KEEP, op2gl[op]); // this stage doesn't modify the stencil
|
||||
|
||||
bool cmon = !(flags & SF_ColorMaskOff);
|
||||
glColorMask(cmon, cmon, cmon, cmon); // don't write to the graphics buffer
|
||||
glDepthMask(!(flags & SF_DepthMaskOff));
|
||||
if (flags & SF_DepthTestOff)
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
else
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
if (flags & SF_DepthClear)
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void FGLRenderState::SetCulling(int mode)
|
||||
{
|
||||
if (mode != Cull_None)
|
||||
{
|
||||
glEnable(GL_CULL_FACE);
|
||||
glFrontFace(mode == Cull_CCW ? GL_CCW : GL_CW);
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable(GL_CULL_FACE);
|
||||
}
|
||||
}
|
||||
|
||||
void FGLRenderState::EnableClipDistance(int num, bool state)
|
||||
{
|
||||
// Update the viewpoint-related clip plane setting.
|
||||
if (!(gl.flags & RFL_NO_CLIP_PLANES))
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
glEnable(GL_CLIP_DISTANCE0 + num);
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable(GL_CLIP_DISTANCE0 + num);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
void FGLRenderState::ClearScreen()
|
||||
{
|
||||
bool multi = !!glIsEnabled(GL_MULTISAMPLE);
|
||||
|
||||
screen->mViewpoints->Set2D(*this, SCREENWIDTH, SCREENHEIGHT);
|
||||
SetColor(0, 0, 0);
|
||||
Apply();
|
||||
|
||||
glDisable(GL_MULTISAMPLE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, FFlatVertexBuffer::FULLSCREEN_INDEX, 4);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
if (multi) glEnable(GL_MULTISAMPLE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Below are less frequently altrered state settings which do not get
|
||||
// buffered by the state object, but set directly instead.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FGLRenderState::SetDepthClamp(bool on)
|
||||
{
|
||||
bool res = mLastDepthClamp;
|
||||
if (!on) glDisable(GL_DEPTH_CLAMP);
|
||||
else glEnable(GL_DEPTH_CLAMP);
|
||||
mLastDepthClamp = on;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -115,16 +115,6 @@ public:
|
|||
mSpecularLevel = specularLevel;
|
||||
}
|
||||
|
||||
// This wraps the depth clamp setting because we frequently need to read it which OpenGL is not particularly performant at...
|
||||
bool SetDepthClamp(bool on)
|
||||
{
|
||||
bool res = mLastDepthClamp;
|
||||
if (!on) glDisable(GL_DEPTH_CLAMP);
|
||||
else glEnable(GL_DEPTH_CLAMP);
|
||||
mLastDepthClamp = on;
|
||||
return res;
|
||||
}
|
||||
|
||||
void SetPassType(EPassType passType)
|
||||
{
|
||||
mPassType = passType;
|
||||
|
@ -151,6 +141,20 @@ public:
|
|||
return mPassType == GBUFFER_PASS ? 3 : 1;
|
||||
}
|
||||
|
||||
void ClearScreen() override;
|
||||
void Draw(int dt, int index, int count, bool apply = true) override;
|
||||
void DrawIndexed(int dt, int index, int count, bool apply = true) override;
|
||||
|
||||
bool SetDepthClamp(bool on) override;
|
||||
void SetDepthMask(bool on) override;
|
||||
void SetDepthFunc(int func) override;
|
||||
void SetDepthRange(float min, float max) override;
|
||||
void EnableDrawBufferAttachments(bool on) override;
|
||||
void SetStencil(int offs, int op, int flags) override;
|
||||
void SetCulling(int mode) override;
|
||||
void EnableClipDistance(int num, bool state) override;
|
||||
|
||||
|
||||
};
|
||||
|
||||
extern FGLRenderState gl_RenderState;
|
||||
|
|
|
@ -19,13 +19,6 @@
|
|||
//
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
/*
|
||||
** gl_drawinfo.cpp
|
||||
** Implements the draw info structure which contains most of the
|
||||
** data in a scene and the draw lists - including a very thorough BSP
|
||||
** style sorting algorithm for translucent objects.
|
||||
**
|
||||
*/
|
||||
|
||||
#include "gl_load/gl_system.h"
|
||||
#include "r_sky.h"
|
||||
|
@ -35,7 +28,6 @@
|
|||
#include "tarray.h"
|
||||
#include "hwrenderer/scene/hw_drawstructs.h"
|
||||
#include "hwrenderer/data/flatvertices.h"
|
||||
#include "hwrenderer/utility/hw_clock.h"
|
||||
|
||||
#include "gl/scene/gl_drawinfo.h"
|
||||
#include "hwrenderer/scene/hw_clipper.h"
|
||||
|
@ -45,43 +37,6 @@
|
|||
#include "hwrenderer/dynlights/hw_lightbuffer.h"
|
||||
#include "hwrenderer/models/hw_models.h"
|
||||
|
||||
bool FDrawInfo::SetDepthClamp(bool on)
|
||||
{
|
||||
return gl_RenderState.SetDepthClamp(on);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static int dt2gl[] = { GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_FAN, GL_TRIANGLE_STRIP };
|
||||
|
||||
void FDrawInfo::Draw(EDrawType dt, FRenderState &state, int index, int count, bool apply)
|
||||
{
|
||||
assert(&state == &gl_RenderState);
|
||||
if (apply)
|
||||
{
|
||||
gl_RenderState.Apply();
|
||||
}
|
||||
drawcalls.Clock();
|
||||
glDrawArrays(dt2gl[dt], index, count);
|
||||
drawcalls.Unclock();
|
||||
}
|
||||
|
||||
void FDrawInfo::DrawIndexed(EDrawType dt, FRenderState &state, int index, int count, bool apply)
|
||||
{
|
||||
assert(&state == &gl_RenderState);
|
||||
if (apply)
|
||||
{
|
||||
gl_RenderState.Apply();
|
||||
}
|
||||
drawcalls.Clock();
|
||||
glDrawElements(dt2gl[dt], count, GL_UNSIGNED_INT, (void*)(intptr_t)(index * sizeof(uint32_t)));
|
||||
drawcalls.Unclock();
|
||||
}
|
||||
|
||||
void FDrawInfo::RenderPortal(HWPortal *p, bool usestencil)
|
||||
{
|
||||
auto gp = static_cast<HWPortal *>(p);
|
||||
|
@ -92,99 +47,8 @@ void FDrawInfo::RenderPortal(HWPortal *p, bool usestencil)
|
|||
gp->DrawContents(new_di, gl_RenderState);
|
||||
new_di->EndDrawInfo();
|
||||
screen->mVertexData->Bind(gl_RenderState);
|
||||
screen->mViewpoints->Bind(this, vpIndex);
|
||||
screen->mViewpoints->Bind(gl_RenderState, vpIndex);
|
||||
gp->RemoveStencil(this, gl_RenderState, usestencil);
|
||||
|
||||
}
|
||||
|
||||
void FDrawInfo::SetDepthMask(bool on)
|
||||
{
|
||||
glDepthMask(on);
|
||||
}
|
||||
|
||||
void FDrawInfo::SetDepthFunc(int func)
|
||||
{
|
||||
static int df2gl[] = { GL_LESS, GL_LEQUAL, GL_ALWAYS };
|
||||
glDepthFunc(df2gl[func]);
|
||||
}
|
||||
|
||||
void FDrawInfo::SetDepthRange(float min, float max)
|
||||
{
|
||||
glDepthRange(min, max);
|
||||
}
|
||||
|
||||
void FDrawInfo::EnableDrawBufferAttachments(bool on)
|
||||
{
|
||||
gl_RenderState.EnableDrawBuffers(on? gl_RenderState.GetPassDrawBufferCount() : 1);
|
||||
}
|
||||
|
||||
void FDrawInfo::SetStencil(int offs, int op, int flags)
|
||||
{
|
||||
static int op2gl[] = { GL_KEEP, GL_INCR, GL_DECR };
|
||||
|
||||
glStencilFunc(GL_EQUAL, screen->stencilValue + offs, ~0); // draw sky into stencil
|
||||
glStencilOp(GL_KEEP, GL_KEEP, op2gl[op]); // this stage doesn't modify the stencil
|
||||
|
||||
bool cmon = !(flags & SF_ColorMaskOff);
|
||||
glColorMask(cmon, cmon, cmon, cmon); // don't write to the graphics buffer
|
||||
glDepthMask(!(flags & SF_DepthMaskOff));
|
||||
if (flags & SF_DepthTestOff)
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
else
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
if (flags & SF_DepthClear)
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void FDrawInfo::SetCulling(int mode)
|
||||
{
|
||||
if (mode != Cull_None)
|
||||
{
|
||||
glEnable(GL_CULL_FACE);
|
||||
glFrontFace(mode == Cull_CCW ? GL_CCW : GL_CW);
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable(GL_CULL_FACE);
|
||||
}
|
||||
}
|
||||
|
||||
void FDrawInfo::EnableClipDistance(int num, bool state)
|
||||
{
|
||||
// Update the viewpoint-related clip plane setting.
|
||||
if (!(gl.flags & RFL_NO_CLIP_PLANES))
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
glEnable(GL_CLIP_DISTANCE0+num);
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable(GL_CLIP_DISTANCE0+num);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
void FDrawInfo::ClearScreen()
|
||||
{
|
||||
bool multi = !!glIsEnabled(GL_MULTISAMPLE);
|
||||
|
||||
screen->mViewpoints->Set2D(this, SCREENWIDTH, SCREENHEIGHT);
|
||||
gl_RenderState.SetColor(0, 0, 0);
|
||||
gl_RenderState.Apply();
|
||||
|
||||
glDisable(GL_MULTISAMPLE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, FFlatVertexBuffer::FULLSCREEN_INDEX, 4);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
if (multi) glEnable(GL_MULTISAMPLE);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -13,19 +13,8 @@
|
|||
|
||||
struct FDrawInfo : public HWDrawInfo
|
||||
{
|
||||
|
||||
void Draw(EDrawType dt, FRenderState &state, int index, int count, bool apply = true) override;
|
||||
void DrawIndexed(EDrawType dt, FRenderState &state, int index, int count, bool apply = true) override;
|
||||
void RenderPortal(HWPortal *p, bool stencil) override;
|
||||
|
||||
void SetDepthMask(bool on) override;
|
||||
void SetDepthFunc(int func) override;
|
||||
void SetDepthRange(float min, float max) override;
|
||||
void EnableDrawBufferAttachments(bool on) override;
|
||||
void SetStencil(int offs, int op, int flags) override;
|
||||
void SetCulling(int mode) override;
|
||||
void EnableClipDistance(int num, bool state) override;
|
||||
|
||||
void CreateScene();
|
||||
void RenderScene(int recursion);
|
||||
void RenderTranslucent();
|
||||
|
@ -33,7 +22,5 @@ struct FDrawInfo : public HWDrawInfo
|
|||
void ProcessScene(bool toscreen = false);
|
||||
void EndDrawScene(sector_t * viewsector);
|
||||
void DrawEndScene2D(sector_t * viewsector);
|
||||
bool SetDepthClamp(bool on) override;
|
||||
void ClearScreen() override;
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -275,7 +275,7 @@ void FDrawInfo::DrawScene(int drawmode)
|
|||
GLRenderer->mBuffers->BindSceneFB(true);
|
||||
gl_RenderState.EnableDrawBuffers(gl_RenderState.GetPassDrawBufferCount());
|
||||
gl_RenderState.Apply();
|
||||
screen->mViewpoints->Bind(this, vpIndex);
|
||||
screen->mViewpoints->Bind(gl_RenderState, vpIndex);
|
||||
}
|
||||
|
||||
// Handle all portals after rendering the opaque objects but before
|
||||
|
@ -324,7 +324,7 @@ void FDrawInfo::DrawEndScene2D(sector_t * viewsector)
|
|||
HWViewpointUniforms vp = VPUniforms;
|
||||
vp.mViewMatrix.loadIdentity();
|
||||
vp.mProjectionMatrix = vrmode->GetHUDSpriteProjection();
|
||||
screen->mViewpoints->SetViewpoint(this, &vp);
|
||||
screen->mViewpoints->SetViewpoint(gl_RenderState, &vp);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_MULTISAMPLE);
|
||||
|
||||
|
@ -426,7 +426,7 @@ sector_t * FGLRenderer::RenderViewpoint (FRenderViewpoint &mainvp, AActor * came
|
|||
di->VPUniforms.mProjectionMatrix = eye.GetProjection(fov, ratio, fovratio);
|
||||
// Stereo mode specific viewpoint adjustment
|
||||
vp.Pos += eye.GetViewShift(vp.HWAngles.Yaw.Degrees);
|
||||
di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, false, false);
|
||||
di->SetupView(gl_RenderState, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, false, false);
|
||||
|
||||
di->ProcessScene(toscreen);
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "hwrenderer/data/shaderuniforms.h"
|
||||
#include "hwrenderer/scene/hw_viewpointuniforms.h"
|
||||
#include "hwrenderer/scene/hw_drawinfo.h"
|
||||
#include "hwrenderer/scene/hw_renderstate.h"
|
||||
#include "hw_viewpointbuffer.h"
|
||||
|
||||
static const int INITIAL_BUFFER_SIZE = 100; // 100 viewpoints per frame should nearly always be enough
|
||||
|
@ -60,18 +61,18 @@ void GLViewpointBuffer::CheckSize()
|
|||
}
|
||||
}
|
||||
|
||||
int GLViewpointBuffer::Bind(HWDrawInfo *di, unsigned int index)
|
||||
int GLViewpointBuffer::Bind(FRenderState &di, unsigned int index)
|
||||
{
|
||||
if (index != mLastMappedIndex)
|
||||
{
|
||||
mLastMappedIndex = index;
|
||||
mBuffer->BindRange(index * mBlockAlign, mBlockAlign);
|
||||
di->EnableClipDistance(0, mClipPlaneInfo[index]);
|
||||
di.EnableClipDistance(0, mClipPlaneInfo[index]);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
void GLViewpointBuffer::Set2D(HWDrawInfo *di, int width, int height)
|
||||
void GLViewpointBuffer::Set2D(FRenderState &di, int width, int height)
|
||||
{
|
||||
if (width != m2DWidth || height != m2DHeight)
|
||||
{
|
||||
|
@ -89,7 +90,7 @@ void GLViewpointBuffer::Set2D(HWDrawInfo *di, int width, int height)
|
|||
Bind(di, 0);
|
||||
}
|
||||
|
||||
int GLViewpointBuffer::SetViewpoint(HWDrawInfo *di, HWViewpointUniforms *vp)
|
||||
int GLViewpointBuffer::SetViewpoint(FRenderState &di, HWViewpointUniforms *vp)
|
||||
{
|
||||
CheckSize();
|
||||
mBuffer->Map();
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "hwrenderer/data/buffers.h"
|
||||
|
||||
struct HWViewpointUniforms;
|
||||
struct HWDrawInfo;
|
||||
class FRenderState;
|
||||
|
||||
class GLViewpointBuffer
|
||||
{
|
||||
|
@ -27,9 +27,9 @@ public:
|
|||
GLViewpointBuffer();
|
||||
~GLViewpointBuffer();
|
||||
void Clear();
|
||||
int Bind(HWDrawInfo *di, unsigned int index);
|
||||
void Set2D(HWDrawInfo *di, int width, int height);
|
||||
int SetViewpoint(HWDrawInfo *di, HWViewpointUniforms *vp);
|
||||
int Bind(FRenderState &di, unsigned int index);
|
||||
void Set2D(FRenderState &di, int width, int height);
|
||||
int SetViewpoint(FRenderState &di, HWViewpointUniforms *vp);
|
||||
unsigned int GetBlockSize() const { return mBlockSize; }
|
||||
};
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ VSMatrix FGLModelRenderer::GetViewToWorldMatrix()
|
|||
|
||||
void FGLModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix, bool mirrored)
|
||||
{
|
||||
di->SetDepthFunc(DF_LEqual);
|
||||
state.SetDepthFunc(DF_LEqual);
|
||||
state.EnableTexture(true);
|
||||
// [BB] In case the model should be rendered translucent, do back face culling.
|
||||
// This solves a few of the problems caused by the lack of depth sorting.
|
||||
|
@ -62,7 +62,7 @@ void FGLModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, con
|
|||
// TO-DO: Implement proper depth sorting.
|
||||
if (!(actor->RenderStyle == DefaultRenderStyle()) && !(smf->flags & MDL_DONTCULLBACKFACES))
|
||||
{
|
||||
di->SetCulling((mirrored ^ screen->mPortalState->isMirrored()) ? Cull_CCW : Cull_CW);
|
||||
state.SetCulling((mirrored ^ screen->mPortalState->isMirrored()) ? Cull_CCW : Cull_CW);
|
||||
}
|
||||
|
||||
state.mModelMatrix = objectToWorldMatrix;
|
||||
|
@ -72,21 +72,21 @@ void FGLModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, con
|
|||
void FGLModelRenderer::EndDrawModel(AActor *actor, FSpriteModelFrame *smf)
|
||||
{
|
||||
state.EnableModelMatrix(false);
|
||||
di->SetDepthFunc(DF_Less);
|
||||
state.SetDepthFunc(DF_Less);
|
||||
if (!(actor->RenderStyle == DefaultRenderStyle()) && !(smf->flags & MDL_DONTCULLBACKFACES))
|
||||
di->SetCulling(Cull_None);
|
||||
state.SetCulling(Cull_None);
|
||||
}
|
||||
|
||||
void FGLModelRenderer::BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix, bool mirrored)
|
||||
{
|
||||
di->SetDepthFunc(DF_LEqual);
|
||||
state.SetDepthFunc(DF_LEqual);
|
||||
|
||||
// [BB] In case the model should be rendered translucent, do back face culling.
|
||||
// This solves a few of the problems caused by the lack of depth sorting.
|
||||
// TO-DO: Implement proper depth sorting.
|
||||
if (!(actor->RenderStyle == DefaultRenderStyle()))
|
||||
{
|
||||
di->SetCulling((mirrored ^ screen->mPortalState->isMirrored()) ? Cull_CW : Cull_CCW);
|
||||
state.SetCulling((mirrored ^ screen->mPortalState->isMirrored()) ? Cull_CW : Cull_CCW);
|
||||
}
|
||||
|
||||
state.mModelMatrix = objectToWorldMatrix;
|
||||
|
@ -97,9 +97,9 @@ void FGLModelRenderer::EndDrawHUDModel(AActor *actor)
|
|||
{
|
||||
state.EnableModelMatrix(false);
|
||||
|
||||
di->SetDepthFunc(DF_Less);
|
||||
state.SetDepthFunc(DF_Less);
|
||||
if (!(actor->RenderStyle == DefaultRenderStyle()))
|
||||
di->SetCulling(Cull_None);
|
||||
state.SetCulling(Cull_None);
|
||||
}
|
||||
|
||||
IModelVertexBuffer *FGLModelRenderer::CreateVertexBuffer(bool needindex, bool singleframe)
|
||||
|
@ -121,12 +121,12 @@ void FGLModelRenderer::SetMaterial(FTexture *skin, bool clampNoFilter, int trans
|
|||
|
||||
void FGLModelRenderer::DrawArrays(int start, int count)
|
||||
{
|
||||
di->Draw(DT_Triangles, state, start, count);
|
||||
state.Draw(DT_Triangles, start, count);
|
||||
}
|
||||
|
||||
void FGLModelRenderer::DrawElements(int numIndices, size_t offset)
|
||||
{
|
||||
di->DrawIndexed(DT_Triangles, state, int(offset / sizeof(unsigned int)), numIndices);
|
||||
state.DrawIndexed(DT_Triangles, int(offset / sizeof(unsigned int)), numIndices);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
|
|
@ -87,7 +87,7 @@ void GLDecal::DrawDecal(HWDrawInfo *di, FRenderState &state)
|
|||
|
||||
if (lightlist == nullptr)
|
||||
{
|
||||
di->Draw(DT_TriangleFan, state, vertindex, 4);
|
||||
state.Draw(DT_TriangleFan, vertindex, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -111,7 +111,7 @@ void GLDecal::DrawDecal(HWDrawInfo *di, FRenderState &state)
|
|||
state.SetFog(thisll, rellight, di->isFullbrightScene(), &thiscm, false);
|
||||
state.SetSplitPlanes(lightlist[k].plane, lowplane);
|
||||
|
||||
di->Draw(DT_TriangleFan, state, vertindex, 4);
|
||||
state.Draw(DT_TriangleFan, vertindex, 4);
|
||||
}
|
||||
if (low1 <= dv[0].z && low2 <= dv[3].z) break;
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ void GLDecal::DrawDecal(HWDrawInfo *di, FRenderState &state)
|
|||
void HWDrawInfo::DrawDecals(FRenderState &state, TArray<GLDecal *> &decals)
|
||||
{
|
||||
side_t *wall = nullptr;
|
||||
SetDepthMask(false);
|
||||
state.SetDepthMask(false);
|
||||
state.SetDepthBias(-1, -128);
|
||||
state.SetLightIndex(-1);
|
||||
for (auto gldecal : decals)
|
||||
|
@ -155,7 +155,7 @@ void HWDrawInfo::DrawDecals(FRenderState &state, TArray<GLDecal *> &decals)
|
|||
state.EnableSplit(false);
|
||||
state.ClearDepthBias();
|
||||
state.SetTextureMode(TM_NORMAL);
|
||||
SetDepthMask(true);
|
||||
state.SetDepthMask(true);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -166,7 +166,7 @@ void HWDrawInfo::DrawDecals(FRenderState &state, TArray<GLDecal *> &decals)
|
|||
|
||||
void GLWall::DrawDecalsForMirror(HWDrawInfo *di, FRenderState &state, TArray<GLDecal *> &decals)
|
||||
{
|
||||
di->SetDepthMask(false);
|
||||
state.SetDepthMask(false);
|
||||
state.SetDepthBias(-1, -128);
|
||||
state.SetLightIndex(-1);
|
||||
state.SetFog(lightlevel, rellight + getExtraLight(), di->isFullbrightScene(), &Colormap, false);
|
||||
|
@ -179,7 +179,7 @@ void GLWall::DrawDecalsForMirror(HWDrawInfo *di, FRenderState &state, TArray<GLD
|
|||
}
|
||||
state.ClearDepthBias();
|
||||
state.SetTextureMode(TM_NORMAL);
|
||||
di->SetDepthMask(true);
|
||||
state.SetDepthMask(true);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -364,14 +364,14 @@ void HWDrawInfo::SetViewMatrix(const FRotator &angles, float vx, float vy, float
|
|||
// Setup the view rotation matrix for the given viewpoint
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void HWDrawInfo::SetupView(float vx, float vy, float vz, bool mirror, bool planemirror)
|
||||
void HWDrawInfo::SetupView(FRenderState &state, float vx, float vy, float vz, bool mirror, bool planemirror)
|
||||
{
|
||||
auto &vp = Viewpoint;
|
||||
vp.SetViewAngle(r_viewwindow);
|
||||
SetViewMatrix(vp.HWAngles, vx, vy, vz, mirror, planemirror);
|
||||
SetCameraPos(vp.Pos);
|
||||
VPUniforms.CalcDependencies();
|
||||
vpIndex = screen->mViewpoints->SetViewpoint(this, &VPUniforms);
|
||||
vpIndex = screen->mViewpoints->SetViewpoint(state, &VPUniforms);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -345,7 +345,7 @@ public:
|
|||
|
||||
void UpdateCurrentMapSection();
|
||||
void SetViewMatrix(const FRotator &angles, float vx, float vy, float vz, bool mirror, bool planemirror);
|
||||
void SetupView(float vx, float vy, float vz, bool mirror, bool planemirror);
|
||||
void SetupView(FRenderState &state, float vx, float vy, float vz, bool mirror, bool planemirror);
|
||||
angle_t FrustumAngle();
|
||||
|
||||
void DrawDecals(FRenderState &state, TArray<GLDecal *> &decals);
|
||||
|
@ -359,26 +359,10 @@ public:
|
|||
void AddFlat(GLFlat *flat, bool fog);
|
||||
void AddSprite(GLSprite *sprite, bool translucent);
|
||||
|
||||
virtual bool SetDepthClamp(bool on) = 0;
|
||||
|
||||
GLDecal *AddDecal(bool onmirror);
|
||||
|
||||
virtual void ClearScreen() = 0;
|
||||
virtual void Draw(EDrawType dt, FRenderState &state, int index, int count, bool apply = true) = 0;
|
||||
virtual void DrawIndexed(EDrawType dt, FRenderState &state, int index, int count, bool apply = true) = 0;
|
||||
virtual void RenderPortal(HWPortal *p, bool usestencil) = 0;
|
||||
virtual void DrawScene(int drawmode) = 0;
|
||||
|
||||
|
||||
// Immediate render state change commands. These only change infrequently and should not clutter the render state.
|
||||
virtual void SetDepthMask(bool on) = 0;
|
||||
virtual void SetDepthFunc(int func) = 0;
|
||||
virtual void SetDepthRange(float min, float max) = 0;
|
||||
virtual void EnableDrawBufferAttachments(bool on) = 0;
|
||||
virtual void SetStencil(int offs, int op, int flags) = 0;
|
||||
virtual void SetCulling(int mode) = 0;
|
||||
virtual void EnableClipDistance(int num, bool state) = 0;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -926,11 +926,11 @@ void HWDrawList::DrawSorted(HWDrawInfo *di, FRenderState &state)
|
|||
screen->mVertexData->Unmap();
|
||||
}
|
||||
state.ClearClipSplit();
|
||||
di->EnableClipDistance(1, true);
|
||||
di->EnableClipDistance(2, true);
|
||||
state.EnableClipDistance(1, true);
|
||||
state.EnableClipDistance(2, true);
|
||||
DrawSorted(di, state, sorted);
|
||||
di->EnableClipDistance(1, false);
|
||||
di->EnableClipDistance(2, false);
|
||||
state.EnableClipDistance(1, false);
|
||||
state.EnableClipDistance(2, false);
|
||||
state.ClearClipSplit();
|
||||
}
|
||||
|
||||
|
|
|
@ -191,7 +191,7 @@ void GLFlat::DrawSubsectors(HWDrawInfo *di, FRenderState &state)
|
|||
state.SetLightIndex(dynlightindex);
|
||||
if (vcount > 0 && !di->ClipLineShouldBeActive())
|
||||
{
|
||||
di->DrawIndexed(DT_Triangles, state, iboindex, vcount);
|
||||
state.DrawIndexed(DT_Triangles, iboindex, vcount);
|
||||
flatvertices += vcount;
|
||||
flatprimitives++;
|
||||
}
|
||||
|
@ -205,7 +205,7 @@ void GLFlat::DrawSubsectors(HWDrawInfo *di, FRenderState &state)
|
|||
|
||||
if (di->ss_renderflags[sub->Index()] & renderflags)
|
||||
{
|
||||
di->DrawIndexed(DT_Triangles, state, index, (sub->numlines - 2) * 3, false);
|
||||
state.DrawIndexed(DT_Triangles, index, (sub->numlines - 2) * 3, false);
|
||||
flatvertices += sub->numlines;
|
||||
flatprimitives++;
|
||||
}
|
||||
|
@ -226,7 +226,7 @@ void GLFlat::DrawSubsectors(HWDrawInfo *di, FRenderState &state)
|
|||
auto num = node->sub->numlines;
|
||||
flatvertices += num;
|
||||
flatprimitives++;
|
||||
di->Draw(DT_TriangleFan, state, node->vertexindex, num);
|
||||
state.Draw(DT_TriangleFan,node->vertexindex, num);
|
||||
node = node->next;
|
||||
}
|
||||
// Flood gaps with the back side's ceiling/floor texture
|
||||
|
@ -249,26 +249,26 @@ void GLFlat::DrawSubsectors(HWDrawInfo *di, FRenderState &state)
|
|||
// Create stencil
|
||||
state.SetEffect(EFF_STENCIL);
|
||||
state.EnableTexture(false);
|
||||
di->SetStencil(0, SOP_Increment, SF_ColorMaskOff);
|
||||
di->Draw(DT_TriangleFan, state, fnode->vertexindex, 4);
|
||||
state.SetStencil(0, SOP_Increment, SF_ColorMaskOff);
|
||||
state.Draw(DT_TriangleFan,fnode->vertexindex, 4);
|
||||
|
||||
// Draw projected plane into stencil
|
||||
state.EnableTexture(true);
|
||||
state.SetEffect(EFF_NONE);
|
||||
di->SetStencil(1, SOP_Keep, SF_DepthMaskOff | SF_DepthTestOff);
|
||||
di->Draw(DT_TriangleFan, state, fnode->vertexindex + 4, 4);
|
||||
state.SetStencil(1, SOP_Keep, SF_DepthMaskOff | SF_DepthTestOff);
|
||||
state.Draw(DT_TriangleFan,fnode->vertexindex + 4, 4);
|
||||
|
||||
// clear stencil
|
||||
state.SetEffect(EFF_STENCIL);
|
||||
state.EnableTexture(false);
|
||||
di->SetStencil(1, SOP_Decrement, SF_ColorMaskOff | SF_DepthMaskOff | SF_DepthTestOff);
|
||||
di->Draw(DT_TriangleFan, state, fnode->vertexindex, 4);
|
||||
state.SetStencil(1, SOP_Decrement, SF_ColorMaskOff | SF_DepthMaskOff | SF_DepthTestOff);
|
||||
state.Draw(DT_TriangleFan,fnode->vertexindex, 4);
|
||||
|
||||
// restore old stencil op.
|
||||
state.EnableTexture(true);
|
||||
state.SetEffect(EFF_NONE);
|
||||
state.SetDepthBias(0, 0);
|
||||
di->SetStencil(0, SOP_Keep, SF_AllOn);
|
||||
state.SetStencil(0, SOP_Keep, SF_AllOn);
|
||||
|
||||
fnode = fnode->next;
|
||||
}
|
||||
|
@ -305,7 +305,7 @@ void GLFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent)
|
|||
{
|
||||
state.SetMaterial(gltexture, CLAMP_XY, 0, -1);
|
||||
state.SetLightIndex(dynlightindex);
|
||||
di->Draw(DT_TriangleFan, state, iboindex, 4);
|
||||
state.Draw(DT_TriangleFan,iboindex, 4);
|
||||
flatvertices += 4;
|
||||
flatprimitives++;
|
||||
}
|
||||
|
|
|
@ -167,7 +167,7 @@ void FPortalSceneState::RenderPortal(HWPortal *p, bool usestencil, HWDrawInfo *o
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void HWPortal::DrawPortalStencil(HWDrawInfo *di, FRenderState &state, int pass)
|
||||
void HWPortal::DrawPortalStencil(FRenderState &state, int pass)
|
||||
{
|
||||
if (mPrimIndices.Size() == 0)
|
||||
{
|
||||
|
@ -181,15 +181,15 @@ void HWPortal::DrawPortalStencil(HWDrawInfo *di, FRenderState &state, int pass)
|
|||
}
|
||||
for (unsigned int i = 0; i < mPrimIndices.Size(); i += 2)
|
||||
{
|
||||
di->Draw(DT_TriangleFan, state, mPrimIndices[i], mPrimIndices[i + 1], i == 0);
|
||||
state.Draw(DT_TriangleFan, mPrimIndices[i], mPrimIndices[i + 1], i == 0);
|
||||
}
|
||||
if (NeedCap() && lines.Size() > 1)
|
||||
{
|
||||
// The cap's depth handling needs special treatment so that it won't block further portal caps.
|
||||
if (pass == STP_DepthRestore) di->SetDepthRange(1, 1);
|
||||
di->Draw(DT_TriangleFan, state, FFlatVertexBuffer::STENCILTOP_INDEX, 4);
|
||||
di->Draw(DT_TriangleFan, state, FFlatVertexBuffer::STENCILBOTTOM_INDEX, 4);
|
||||
if (pass == STP_DepthRestore) di->SetDepthRange(0, 1);
|
||||
if (pass == STP_DepthRestore) state.SetDepthRange(1, 1);
|
||||
state.Draw(DT_TriangleFan, FFlatVertexBuffer::STENCILTOP_INDEX, 4);
|
||||
state.Draw(DT_TriangleFan, FFlatVertexBuffer::STENCILBOTTOM_INDEX, 4);
|
||||
if (pass == STP_DepthRestore) state.SetDepthRange(0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,32 +213,32 @@ void HWPortal::SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil
|
|||
|
||||
if (NeedDepthBuffer())
|
||||
{
|
||||
di->SetStencil(0, SOP_Increment, SF_ColorMaskOff | SF_DepthMaskOff);
|
||||
di->SetDepthFunc(DF_Less);
|
||||
DrawPortalStencil(di, state, STP_Stencil);
|
||||
state.SetStencil(0, SOP_Increment, SF_ColorMaskOff | SF_DepthMaskOff);
|
||||
state.SetDepthFunc(DF_Less);
|
||||
DrawPortalStencil(state, STP_Stencil);
|
||||
|
||||
// Clear Z-buffer
|
||||
di->SetStencil(1, SOP_Keep, SF_ColorMaskOff);
|
||||
di->SetDepthRange(1, 1);
|
||||
di->SetDepthFunc(DF_Always);
|
||||
DrawPortalStencil(di, state, STP_DepthClear);
|
||||
state.SetStencil(1, SOP_Keep, SF_ColorMaskOff);
|
||||
state.SetDepthRange(1, 1);
|
||||
state.SetDepthFunc(DF_Always);
|
||||
DrawPortalStencil(state, STP_DepthClear);
|
||||
|
||||
// set normal drawing mode
|
||||
state.EnableTexture(true);
|
||||
di->SetStencil(1, SOP_Keep, SF_AllOn);
|
||||
di->SetDepthRange(0, 1);
|
||||
di->SetDepthFunc(DF_Less);
|
||||
state.SetStencil(1, SOP_Keep, SF_AllOn);
|
||||
state.SetDepthRange(0, 1);
|
||||
state.SetDepthFunc(DF_Less);
|
||||
state.SetEffect(EFF_NONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No z-buffer is needed therefore we can skip all the complicated stuff that is involved
|
||||
// Note: We must draw the stencil with z-write enabled here because there is no second pass!
|
||||
di->SetStencil(0, SOP_Increment, SF_ColorMaskOff);
|
||||
di->SetDepthFunc(DF_Less);
|
||||
DrawPortalStencil(di, state, STP_AllInOne);
|
||||
state.SetStencil(0, SOP_Increment, SF_ColorMaskOff);
|
||||
state.SetDepthFunc(DF_Less);
|
||||
DrawPortalStencil(state, STP_AllInOne);
|
||||
|
||||
di->SetStencil(1, SOP_Keep, SF_DepthTestOff | SF_DepthMaskOff);
|
||||
state.SetStencil(1, SOP_Keep, SF_DepthTestOff | SF_DepthMaskOff);
|
||||
state.EnableTexture(true);
|
||||
state.SetEffect(EFF_NONE);
|
||||
}
|
||||
|
@ -249,7 +249,7 @@ void HWPortal::SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil
|
|||
{
|
||||
if (!NeedDepthBuffer())
|
||||
{
|
||||
di->SetStencil(0, SOP_Keep, SF_DepthTestOff | SF_DepthMaskOff);
|
||||
state.SetStencil(0, SOP_Keep, SF_DepthTestOff | SF_DepthMaskOff);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -275,17 +275,17 @@ void HWPortal::RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestenci
|
|||
if (needdepth)
|
||||
{
|
||||
// first step: reset the depth buffer to max. depth
|
||||
di->SetStencil(0, SOP_Keep, SF_ColorMaskOff);
|
||||
di->SetDepthRange(1, 1); // always
|
||||
di->SetDepthFunc(DF_Always); // write the farthest depth value
|
||||
DrawPortalStencil(di, state, STP_DepthClear);
|
||||
state.SetStencil(0, SOP_Keep, SF_ColorMaskOff);
|
||||
state.SetDepthRange(1, 1); // always
|
||||
state.SetDepthFunc(DF_Always); // write the farthest depth value
|
||||
DrawPortalStencil(state, STP_DepthClear);
|
||||
}
|
||||
|
||||
// second step: restore the depth buffer to the previous values and reset the stencil
|
||||
di->SetStencil(0, SOP_Decrement, SF_ColorMaskOff);
|
||||
di->SetDepthRange(0, 1);
|
||||
di->SetDepthFunc(DF_LEqual);
|
||||
DrawPortalStencil(di, state, STP_DepthRestore);
|
||||
state.SetStencil(0, SOP_Decrement, SF_ColorMaskOff);
|
||||
state.SetDepthRange(0, 1);
|
||||
state.SetDepthFunc(DF_LEqual);
|
||||
DrawPortalStencil(state, STP_DepthRestore);
|
||||
|
||||
state.EnableTexture(true);
|
||||
state.SetEffect(EFF_NONE);
|
||||
|
@ -298,15 +298,15 @@ void HWPortal::RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestenci
|
|||
state.EnableTexture(false);
|
||||
state.SetRenderStyle(STYLE_Source);
|
||||
|
||||
di->SetStencil(0, SOP_Keep, needdepth ? SF_ColorMaskOff | SF_DepthClear : SF_ColorMaskOff);
|
||||
di->SetDepthRange(0, 1);
|
||||
di->SetDepthFunc(DF_LEqual);
|
||||
DrawPortalStencil(di, state, STP_DepthRestore);
|
||||
state.SetStencil(0, SOP_Keep, needdepth ? SF_ColorMaskOff | SF_DepthClear : SF_ColorMaskOff);
|
||||
state.SetDepthRange(0, 1);
|
||||
state.SetDepthFunc(DF_LEqual);
|
||||
DrawPortalStencil(state, STP_DepthRestore);
|
||||
|
||||
state.SetEffect(EFF_NONE);
|
||||
state.EnableTexture(true);
|
||||
}
|
||||
di->SetStencil(0, SOP_Keep, SF_AllOn);
|
||||
state.SetStencil(0, SOP_Keep, SF_AllOn);
|
||||
}
|
||||
|
||||
|
||||
|
@ -403,7 +403,7 @@ int HWLinePortal::ClipPoint(const DVector2 &pos)
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool HWMirrorPortal::Setup(HWDrawInfo *di, Clipper *clipper)
|
||||
bool HWMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper)
|
||||
{
|
||||
auto state = mOwner->mState;
|
||||
if (state->renderdepth > r_mirror_recursions)
|
||||
|
@ -473,7 +473,7 @@ bool HWMirrorPortal::Setup(HWDrawInfo *di, Clipper *clipper)
|
|||
|
||||
state->MirrorFlag++;
|
||||
di->SetClipLine(linedef);
|
||||
di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1));
|
||||
di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1));
|
||||
|
||||
clipper->Clear();
|
||||
|
||||
|
@ -484,7 +484,7 @@ bool HWMirrorPortal::Setup(HWDrawInfo *di, Clipper *clipper)
|
|||
return true;
|
||||
}
|
||||
|
||||
void HWMirrorPortal::Shutdown(HWDrawInfo *di)
|
||||
void HWMirrorPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate)
|
||||
{
|
||||
mOwner->mState->MirrorFlag--;
|
||||
}
|
||||
|
@ -506,7 +506,7 @@ const char *HWMirrorPortal::GetName() { return "Mirror"; }
|
|||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
bool HWLineToLinePortal::Setup(HWDrawInfo *di, Clipper *clipper)
|
||||
bool HWLineToLinePortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper)
|
||||
{
|
||||
// TODO: Handle recursion more intelligently
|
||||
auto &state = mOwner->mState;
|
||||
|
@ -553,7 +553,7 @@ bool HWLineToLinePortal::Setup(HWDrawInfo *di, Clipper *clipper)
|
|||
|
||||
vp.ViewActor = nullptr;
|
||||
di->SetClipLine(glport->lines[0]->mDestination);
|
||||
di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1));
|
||||
di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1));
|
||||
|
||||
ClearClipper(di, clipper);
|
||||
return true;
|
||||
|
@ -583,7 +583,7 @@ const char *HWLineToLinePortal::GetName() { return "LineToLine"; }
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool HWSkyboxPortal::Setup(HWDrawInfo *di, Clipper *clipper)
|
||||
bool HWSkyboxPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper)
|
||||
{
|
||||
auto state = mOwner->mState;
|
||||
old_pm = state->PlaneMirrorMode;
|
||||
|
@ -602,8 +602,7 @@ bool HWSkyboxPortal::Setup(HWDrawInfo *di, Clipper *clipper)
|
|||
portal->mFlags |= PORTSF_INSKYBOX;
|
||||
vp.extralight = 0;
|
||||
|
||||
|
||||
oldclamp = di->SetDepthClamp(false);
|
||||
oldclamp = rstate.SetDepthClamp(false);
|
||||
vp.Pos = origin->InterpolatedPosition(vp.TicFrac);
|
||||
vp.ActorPos = origin->Pos();
|
||||
vp.Angles.Yaw += (origin->PrevAngles.Yaw + deltaangle(origin->PrevAngles.Yaw, origin->Angles.Yaw) * vp.TicFrac);
|
||||
|
@ -616,7 +615,7 @@ bool HWSkyboxPortal::Setup(HWDrawInfo *di, Clipper *clipper)
|
|||
|
||||
vp.ViewActor = origin;
|
||||
|
||||
di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1));
|
||||
di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1));
|
||||
di->SetViewArea();
|
||||
ClearClipper(di, clipper);
|
||||
di->UpdateCurrentMapSection();
|
||||
|
@ -624,11 +623,12 @@ bool HWSkyboxPortal::Setup(HWDrawInfo *di, Clipper *clipper)
|
|||
}
|
||||
|
||||
|
||||
void HWSkyboxPortal::Shutdown(HWDrawInfo *di)
|
||||
void HWSkyboxPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate)
|
||||
{
|
||||
rstate.SetDepthClamp(oldclamp);
|
||||
|
||||
auto state = mOwner->mState;
|
||||
portal->mFlags &= ~PORTSF_INSKYBOX;
|
||||
di->SetDepthClamp(oldclamp);
|
||||
state->inskybox = false;
|
||||
state->skyboxrecursion--;
|
||||
state->PlaneMirrorMode = old_pm;
|
||||
|
@ -693,7 +693,7 @@ void HWSectorStackPortal::SetupCoverage(HWDrawInfo *di)
|
|||
// GLSectorStackPortal::DrawContents
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
bool HWSectorStackPortal::Setup(HWDrawInfo *di, Clipper *clipper)
|
||||
bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper)
|
||||
{
|
||||
auto state = mOwner->mState;
|
||||
FSectorPortalGroup *portal = origin;
|
||||
|
@ -706,7 +706,7 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, Clipper *clipper)
|
|||
// avoid recursions!
|
||||
if (origin->plane != -1) screen->instack[origin->plane]++;
|
||||
|
||||
di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1));
|
||||
di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1));
|
||||
SetupCoverage(di);
|
||||
ClearClipper(di, clipper);
|
||||
|
||||
|
@ -722,7 +722,7 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, Clipper *clipper)
|
|||
}
|
||||
|
||||
|
||||
void HWSectorStackPortal::Shutdown(HWDrawInfo *di)
|
||||
void HWSectorStackPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate)
|
||||
{
|
||||
if (origin->plane != -1) screen->instack[origin->plane]--;
|
||||
}
|
||||
|
@ -745,7 +745,7 @@ const char *HWSectorStackPortal::GetName() { return "Sectorstack"; }
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool HWPlaneMirrorPortal::Setup(HWDrawInfo *di, Clipper *clipper)
|
||||
bool HWPlaneMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper)
|
||||
{
|
||||
auto state = mOwner->mState;
|
||||
if (state->renderdepth > r_mirror_recursions)
|
||||
|
@ -768,14 +768,14 @@ bool HWPlaneMirrorPortal::Setup(HWDrawInfo *di, Clipper *clipper)
|
|||
|
||||
state->PlaneMirrorFlag++;
|
||||
di->SetClipHeight(planez, state->PlaneMirrorMode < 0 ? -1.f : 1.f);
|
||||
di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1));
|
||||
di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1));
|
||||
ClearClipper(di, clipper);
|
||||
|
||||
di->UpdateCurrentMapSection();
|
||||
return true;
|
||||
}
|
||||
|
||||
void HWPlaneMirrorPortal::Shutdown(HWDrawInfo *di)
|
||||
void HWPlaneMirrorPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate)
|
||||
{
|
||||
auto state = mOwner->mState;
|
||||
state->PlaneMirrorFlag--;
|
||||
|
@ -876,7 +876,7 @@ void HWHorizonPortal::DrawContents(HWDrawInfo *di, FRenderState &state)
|
|||
gltexture = FMaterial::ValidateTexture(sp->texture, false, true);
|
||||
if (!gltexture)
|
||||
{
|
||||
di->ClearScreen();
|
||||
state.ClearScreen();
|
||||
return;
|
||||
}
|
||||
di->SetCameraPos(vp.Pos);
|
||||
|
@ -905,9 +905,9 @@ void HWHorizonPortal::DrawContents(HWDrawInfo *di, FRenderState &state)
|
|||
|
||||
for (unsigned i = 0; i < vcount; i += 4)
|
||||
{
|
||||
di->Draw(DT_TriangleStrip, state, voffset + i, 4, true);// i == 0);
|
||||
state.Draw(DT_TriangleStrip, voffset + i, 4, true);// i == 0);
|
||||
}
|
||||
di->Draw(DT_TriangleStrip, state, voffset + vcount, 10, false);
|
||||
state.Draw(DT_TriangleStrip, voffset + vcount, 10, false);
|
||||
|
||||
state.EnableTextureMatrix(false);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "hw_drawinfo.h"
|
||||
#include "hw_drawstructs.h"
|
||||
#include "hwrenderer/textures/hw_material.h"
|
||||
#include "hwrenderer/scene/hw_renderstate.h"
|
||||
|
||||
class FSkyVertexBuffer;
|
||||
|
||||
|
@ -55,7 +56,7 @@ class HWPortal
|
|||
ActorRenderFlags savedvisibility;
|
||||
TArray<unsigned int> mPrimIndices;
|
||||
|
||||
void DrawPortalStencil(HWDrawInfo *di, FRenderState &state, int pass);
|
||||
void DrawPortalStencil(FRenderState &state, int pass);
|
||||
|
||||
public:
|
||||
FPortalSceneState * mState;
|
||||
|
@ -142,8 +143,8 @@ public:
|
|||
virtual void * GetSource() const = 0; // GetSource MUST be implemented!
|
||||
virtual const char *GetName() = 0;
|
||||
|
||||
virtual bool Setup(HWDrawInfo *di, Clipper *clipper) = 0;
|
||||
virtual void Shutdown(HWDrawInfo *di) {}
|
||||
virtual bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) = 0;
|
||||
virtual void Shutdown(HWDrawInfo *di, FRenderState &rstate) {}
|
||||
virtual void RenderAttached(HWDrawInfo *di) {}
|
||||
|
||||
};
|
||||
|
@ -204,8 +205,8 @@ struct HWMirrorPortal : public HWLinePortal
|
|||
line_t * linedef;
|
||||
|
||||
protected:
|
||||
bool Setup(HWDrawInfo *di, Clipper *clipper) override;
|
||||
void Shutdown(HWDrawInfo *di) override;
|
||||
bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override;
|
||||
void Shutdown(HWDrawInfo *di, FRenderState &rstate) override;
|
||||
void * GetSource() const override { return linedef; }
|
||||
const char *GetName() override;
|
||||
|
||||
|
@ -223,7 +224,7 @@ struct HWLineToLinePortal : public HWLinePortal
|
|||
{
|
||||
FLinePortalSpan *glport;
|
||||
protected:
|
||||
bool Setup(HWDrawInfo *di, Clipper *clipper) override;
|
||||
bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override;
|
||||
virtual void * GetSource() const override { return glport; }
|
||||
virtual const char *GetName() override;
|
||||
virtual line_t *ClipLine() override { return line(); }
|
||||
|
@ -246,8 +247,8 @@ struct HWSkyboxPortal : public HWScenePortalBase
|
|||
FSectorPortal * portal;
|
||||
|
||||
protected:
|
||||
bool Setup(HWDrawInfo *di, Clipper *clipper) override;
|
||||
void Shutdown(HWDrawInfo *di) override;
|
||||
bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override;
|
||||
void Shutdown(HWDrawInfo *di, FRenderState &rstate) override;
|
||||
virtual void * GetSource() const { return portal; }
|
||||
virtual bool IsSky() { return true; }
|
||||
virtual const char *GetName();
|
||||
|
@ -267,8 +268,8 @@ struct HWSectorStackPortal : public HWScenePortalBase
|
|||
{
|
||||
TArray<subsector_t *> subsectors;
|
||||
protected:
|
||||
bool Setup(HWDrawInfo *di, Clipper *clipper) override;
|
||||
void Shutdown(HWDrawInfo *di) override;
|
||||
bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override;
|
||||
void Shutdown(HWDrawInfo *di, FRenderState &rstate) override;
|
||||
virtual void * GetSource() const { return origin; }
|
||||
virtual bool IsSky() { return true; } // although this isn't a real sky it can be handled as one.
|
||||
virtual const char *GetName();
|
||||
|
@ -292,8 +293,8 @@ struct HWPlaneMirrorPortal : public HWScenePortalBase
|
|||
{
|
||||
int old_pm;
|
||||
protected:
|
||||
bool Setup(HWDrawInfo *di, Clipper *clipper) override;
|
||||
void Shutdown(HWDrawInfo *di) override;
|
||||
bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override;
|
||||
void Shutdown(HWDrawInfo *di, FRenderState &rstate) override;
|
||||
virtual void * GetSource() const { return origin; }
|
||||
virtual const char *GetName();
|
||||
secplane_t * origin;
|
||||
|
@ -325,12 +326,12 @@ public:
|
|||
virtual bool NeedDepthBuffer() { return true; }
|
||||
virtual void DrawContents(HWDrawInfo *di, FRenderState &state)
|
||||
{
|
||||
if (mScene->Setup(di, di->mClipper))
|
||||
if (mScene->Setup(di, state, di->mClipper))
|
||||
{
|
||||
di->DrawScene(DM_PORTAL);
|
||||
mScene->Shutdown(di);
|
||||
mScene->Shutdown(di, state);
|
||||
}
|
||||
else di->ClearScreen();
|
||||
else state.ClearScreen();
|
||||
}
|
||||
virtual void RenderAttached(HWDrawInfo *di) { return mScene->RenderAttached(di); }
|
||||
};
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "vectors.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "hw_drawstructs.h"
|
||||
#include "hw_drawlist.h"
|
||||
#include "r_data/matrix.h"
|
||||
#include "hwrenderer/textures/hw_material.h"
|
||||
|
||||
|
@ -422,5 +423,23 @@ public:
|
|||
|
||||
void SetColor(int sectorlightlevel, int rellight, bool fullbright, const FColormap &cm, float alpha, bool weapon = false);
|
||||
void SetFog(int lightlevel, int rellight, bool fullbright, const FColormap *cmap, bool isadditive);
|
||||
|
||||
// API-dependent render interface
|
||||
|
||||
// Draw commands
|
||||
virtual void ClearScreen() = 0;
|
||||
virtual void Draw(int dt, int index, int count, bool apply = true) = 0;
|
||||
virtual void DrawIndexed(int dt, int index, int count, bool apply = true) = 0;
|
||||
|
||||
// Immediate render state change commands. These only change infrequently and should not clutter the render state.
|
||||
virtual bool SetDepthClamp(bool on) = 0;
|
||||
virtual void SetDepthMask(bool on) = 0;
|
||||
virtual void SetDepthFunc(int func) = 0;
|
||||
virtual void SetDepthRange(float min, float max) = 0;
|
||||
virtual void EnableDrawBufferAttachments(bool on) = 0;
|
||||
virtual void SetStencil(int offs, int op, int flags) = 0;
|
||||
virtual void SetCulling(int mode) = 0;
|
||||
virtual void EnableClipDistance(int num, bool state) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
void HWSkyPortal::RenderRow(HWDrawInfo *di, FRenderState &state, EDrawType prim, int row, bool apply)
|
||||
{
|
||||
di->Draw(prim, state, vertexBuffer->mPrimStart[row], vertexBuffer->mPrimStart[row + 1] - vertexBuffer->mPrimStart[row]);
|
||||
state.Draw(prim, vertexBuffer->mPrimStart[row], vertexBuffer->mPrimStart[row + 1] - vertexBuffer->mPrimStart[row]);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -115,40 +115,40 @@ void HWSkyPortal::RenderBox(HWDrawInfo *di, FRenderState &state, FTextureID texn
|
|||
// north
|
||||
tex = FMaterial::ValidateTexture(sb->faces[0], false);
|
||||
state.SetMaterial(tex, CLAMP_XY, 0, -1);
|
||||
di->Draw(DT_TriangleStrip, state, vertexBuffer->FaceStart(0), 4);
|
||||
state.Draw(DT_TriangleStrip, vertexBuffer->FaceStart(0), 4);
|
||||
|
||||
// east
|
||||
tex = FMaterial::ValidateTexture(sb->faces[1], false);
|
||||
state.SetMaterial(tex, CLAMP_XY, 0, -1);
|
||||
di->Draw(DT_TriangleStrip, state, vertexBuffer->FaceStart(1), 4);
|
||||
state.Draw(DT_TriangleStrip, vertexBuffer->FaceStart(1), 4);
|
||||
|
||||
// south
|
||||
tex = FMaterial::ValidateTexture(sb->faces[2], false);
|
||||
state.SetMaterial(tex, CLAMP_XY, 0, -1);
|
||||
di->Draw(DT_TriangleStrip, state, vertexBuffer->FaceStart(2), 4);
|
||||
state.Draw(DT_TriangleStrip, vertexBuffer->FaceStart(2), 4);
|
||||
|
||||
// west
|
||||
tex = FMaterial::ValidateTexture(sb->faces[3], false);
|
||||
state.SetMaterial(tex, CLAMP_XY, 0, -1);
|
||||
di->Draw(DT_TriangleStrip, state, vertexBuffer->FaceStart(3), 4);
|
||||
state.Draw(DT_TriangleStrip, vertexBuffer->FaceStart(3), 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
faces=1;
|
||||
tex = FMaterial::ValidateTexture(sb->faces[0], false);
|
||||
state.SetMaterial(tex, CLAMP_XY, 0, -1);
|
||||
di->Draw(DT_TriangleStrip, state, vertexBuffer->FaceStart(-1), 10);
|
||||
state.Draw(DT_TriangleStrip, vertexBuffer->FaceStart(-1), 10);
|
||||
}
|
||||
|
||||
// top
|
||||
tex = FMaterial::ValidateTexture(sb->faces[faces], false);
|
||||
state.SetMaterial(tex, CLAMP_XY, 0, -1);
|
||||
di->Draw(DT_TriangleStrip, state, vertexBuffer->FaceStart(sb->fliptop ? 6 : 5), 4);
|
||||
state.Draw(DT_TriangleStrip, vertexBuffer->FaceStart(sb->fliptop ? 6 : 5), 4);
|
||||
|
||||
// bottom
|
||||
tex = FMaterial::ValidateTexture(sb->faces[faces+1], false);
|
||||
state.SetMaterial(tex, CLAMP_XY, 0, -1);
|
||||
di->Draw(DT_TriangleStrip, state, vertexBuffer->FaceStart(4), 4);
|
||||
state.Draw(DT_TriangleStrip, vertexBuffer->FaceStart(4), 4);
|
||||
|
||||
state.EnableModelMatrix(false);
|
||||
}
|
||||
|
@ -176,9 +176,9 @@ void HWSkyPortal::DrawContents(HWDrawInfo *di, FRenderState &state)
|
|||
state.EnableFog(false);
|
||||
state.AlphaFunc(Alpha_GEqual, 0.f);
|
||||
state.SetRenderStyle(STYLE_Translucent);
|
||||
bool oldClamp = di->SetDepthClamp(true);
|
||||
bool oldClamp = state.SetDepthClamp(true);
|
||||
|
||||
di->SetupView(0, 0, 0, !!(mState->MirrorFlag & 1), !!(mState->PlaneMirrorFlag & 1));
|
||||
di->SetupView(state, 0, 0, 0, !!(mState->MirrorFlag & 1), !!(mState->PlaneMirrorFlag & 1));
|
||||
|
||||
vertexBuffer->Bind(state);
|
||||
if (origin->texture[0] && origin->texture[0]->tex->bSkybox)
|
||||
|
@ -210,13 +210,13 @@ void HWSkyPortal::DrawContents(HWDrawInfo *di, FRenderState &state)
|
|||
|
||||
state.EnableTexture(false);
|
||||
state.SetObjectColor(FadeColor);
|
||||
di->Draw(DT_Triangles, state, 0, 12);
|
||||
state.Draw(DT_Triangles, 0, 12);
|
||||
state.EnableTexture(true);
|
||||
state.SetObjectColor(0xffffffff);
|
||||
}
|
||||
}
|
||||
::level.lightmode = oldlightmode;
|
||||
di->SetDepthClamp(oldClamp);
|
||||
state.SetDepthClamp(oldClamp);
|
||||
}
|
||||
|
||||
const char *HWSkyPortal::GetName() { return "Sky"; }
|
||||
|
|
|
@ -255,7 +255,7 @@ void GLSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent)
|
|||
state.SetDepthBias(-1, -128);
|
||||
}
|
||||
state.SetLightIndex(-1);
|
||||
di->Draw(DT_TriangleStrip, state, vertexindex, 4);
|
||||
state.Draw(DT_TriangleStrip, vertexindex, 4);
|
||||
|
||||
if (foglayer)
|
||||
{
|
||||
|
@ -263,7 +263,7 @@ void GLSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent)
|
|||
state.SetFog(foglevel, rel, false, &Colormap, additivefog);
|
||||
state.SetTextureMode(TM_FOGLAYER);
|
||||
state.SetRenderStyle(STYLE_Translucent);
|
||||
di->Draw(DT_TriangleStrip, state, vertexindex, 4);
|
||||
state.Draw(DT_TriangleStrip, vertexindex, 4);
|
||||
state.SetTextureMode(TM_NORMAL);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ void GLWall::RenderWall(HWDrawInfo *di, FRenderState &state, int textured)
|
|||
{
|
||||
assert(vertcount > 0);
|
||||
state.SetLightIndex(dynlightindex);
|
||||
di->Draw(DT_TriangleFan, state, vertindex, vertcount);
|
||||
state.Draw(DT_TriangleFan, vertindex, vertcount);
|
||||
vertexcount += vertcount;
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ void GLWall::RenderFogBoundary(HWDrawInfo *di, FRenderState &state)
|
|||
if (gl_fogmode && !di->isFullbrightScene())
|
||||
{
|
||||
int rel = rellight + getExtraLight();
|
||||
di->EnableDrawBufferAttachments(false);
|
||||
state.EnableDrawBufferAttachments(false);
|
||||
state.SetFog(lightlevel, rel, false, &Colormap, false);
|
||||
state.SetEffect(EFF_FOGBOUNDARY);
|
||||
state.AlphaFunc(Alpha_GEqual, 0.f);
|
||||
|
@ -76,7 +76,7 @@ void GLWall::RenderFogBoundary(HWDrawInfo *di, FRenderState &state)
|
|||
RenderWall(di, state, GLWall::RWF_BLANK);
|
||||
state.ClearDepthBias();
|
||||
state.SetEffect(EFF_NONE);
|
||||
di->EnableDrawBufferAttachments(true);
|
||||
state.EnableDrawBufferAttachments(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,7 +90,7 @@ void GLWall::RenderMirrorSurface(HWDrawInfo *di, FRenderState &state)
|
|||
{
|
||||
if (!TexMan.mirrorTexture.isValid()) return;
|
||||
|
||||
di->SetDepthFunc(DF_LEqual);
|
||||
state.SetDepthFunc(DF_LEqual);
|
||||
|
||||
// we use texture coordinates and texture matrix to pass the normal stuff to the shader so that the default vertex buffer format can be used as is.
|
||||
state.EnableTextureMatrix(true);
|
||||
|
@ -112,7 +112,7 @@ void GLWall::RenderMirrorSurface(HWDrawInfo *di, FRenderState &state)
|
|||
state.SetEffect(EFF_NONE);
|
||||
state.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold);
|
||||
|
||||
di->SetDepthFunc(DF_Less);
|
||||
state.SetDepthFunc(DF_Less);
|
||||
|
||||
// This is drawn in the translucent pass which is done after the decal pass
|
||||
// As a result the decals have to be drawn here, right after the wall they are on,
|
||||
|
|
|
@ -88,7 +88,7 @@ void HWDrawInfo::DrawPSprite(HUDSprite *huds, FRenderState &state)
|
|||
float thresh = (huds->tex->tex->GetTranslucency() || huds->OverrideShader != -1) ? 0.f : gl_mask_sprite_threshold;
|
||||
state.AlphaFunc(Alpha_GEqual, thresh);
|
||||
state.SetMaterial(huds->tex, CLAMP_XY_NOMIP, 0, huds->OverrideShader);
|
||||
Draw(DT_TriangleStrip, state, huds->mx, 4);
|
||||
state.Draw(DT_TriangleStrip, huds->mx, 4);
|
||||
}
|
||||
|
||||
state.SetTextureMode(TM_NORMAL);
|
||||
|
|
Loading…
Reference in a new issue