Merge remote-tracking branch 'gzdoom/modern' into hw_postprocess
This commit is contained in:
commit
32d837cdf1
164 changed files with 23408 additions and 12966 deletions
|
|
@ -50,7 +50,7 @@ CVAR(Bool, gl_light_models, true, CVAR_ARCHIVE)
|
|||
VSMatrix FGLModelRenderer::GetViewToWorldMatrix()
|
||||
{
|
||||
VSMatrix objectToWorldMatrix;
|
||||
gl_RenderState.mViewMatrix.inverseMatrix(objectToWorldMatrix);
|
||||
di->VPUniforms.mViewMatrix.inverseMatrix(objectToWorldMatrix);
|
||||
return objectToWorldMatrix;
|
||||
}
|
||||
|
||||
|
|
@ -65,7 +65,7 @@ void FGLModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, con
|
|||
if (!(actor->RenderStyle == LegacyRenderStyles[STYLE_Normal]) && !(smf->flags & MDL_DONTCULLBACKFACES))
|
||||
{
|
||||
glEnable(GL_CULL_FACE);
|
||||
glFrontFace((mirrored ^ GLPortal::isMirrored()) ? GL_CCW : GL_CW);
|
||||
glFrontFace((mirrored ^ GLRenderer->mPortalState.isMirrored()) ? GL_CCW : GL_CW);
|
||||
}
|
||||
|
||||
gl_RenderState.mModelMatrix = objectToWorldMatrix;
|
||||
|
|
@ -91,7 +91,7 @@ void FGLModelRenderer::BeginDrawHUDModel(AActor *actor, const VSMatrix &objectTo
|
|||
if (!(actor->RenderStyle == LegacyRenderStyles[STYLE_Normal]))
|
||||
{
|
||||
glEnable(GL_CULL_FACE);
|
||||
glFrontFace((mirrored ^ GLPortal::isMirrored()) ? GL_CW : GL_CCW);
|
||||
glFrontFace((mirrored ^ GLRenderer->mPortalState.isMirrored()) ? GL_CW : GL_CCW);
|
||||
}
|
||||
|
||||
gl_RenderState.mModelMatrix = objectToWorldMatrix;
|
||||
|
|
@ -314,27 +314,3 @@ void FModelVertexBuffer::SetupFrame(FModelRenderer *renderer, unsigned int frame
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// gl_RenderModel
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void gl_RenderModel(GLSprite * spr, int mli)
|
||||
{
|
||||
FGLModelRenderer renderer(mli);
|
||||
renderer.RenderModel(spr->x, spr->y, spr->z, spr->modelframe, spr->actor);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// gl_RenderHUDModel
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void gl_RenderHUDModel(DPSprite *psp, float ofsX, float ofsY, int mli)
|
||||
{
|
||||
FGLModelRenderer renderer(mli);
|
||||
renderer.RenderHUDModel(psp, ofsX, ofsY);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,12 +29,14 @@
|
|||
#include "r_data/models/models.h"
|
||||
|
||||
class GLSprite;
|
||||
struct FDrawInfo;
|
||||
|
||||
class FGLModelRenderer : public FModelRenderer
|
||||
{
|
||||
int modellightindex = -1;
|
||||
FDrawInfo *di;
|
||||
public:
|
||||
FGLModelRenderer(int mli) : modellightindex(mli)
|
||||
FGLModelRenderer(FDrawInfo *d, int mli) : modellightindex(mli), di(d)
|
||||
{}
|
||||
ModelRendererType GetType() const override { return GLModelRendererType; }
|
||||
void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix, bool mirrored) override;
|
||||
|
|
@ -51,5 +53,3 @@ public:
|
|||
void DrawElements(int numIndices, size_t offset) override;
|
||||
};
|
||||
|
||||
void gl_RenderModel(GLSprite * spr, int mli);
|
||||
void gl_RenderHUDModel(DPSprite *psp, float ofsx, float ofsy, int mli);
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ void gl_SetFog(int lightlevel, int rellight, bool fullbright, const FColormap *c
|
|||
}
|
||||
|
||||
// Make fog a little denser when inside a skybox
|
||||
if (GLPortal::inskybox) fogdensity+=fogdensity/2;
|
||||
if (GLRenderer->mPortalState.inskybox) fogdensity+=fogdensity/2;
|
||||
|
||||
|
||||
// no fog in enhanced vision modes!
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#define __GL_LIGHTDATA
|
||||
|
||||
#include "v_palette.h"
|
||||
#include "p_3dfloors.h"
|
||||
#include "r_defs.h"
|
||||
#include "r_data/renderstyle.h"
|
||||
#include "hwrenderer/utility/hw_lighting.h"
|
||||
#include "r_data/colormaps.h"
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@
|
|||
#include "hwrenderer/postprocessing/hw_presentshader.h"
|
||||
#include "hwrenderer/postprocessing/hw_postprocess.h"
|
||||
#include "hwrenderer/postprocessing/hw_postprocess_cvars.h"
|
||||
#include "hwrenderer/utility/hw_vrmodes.h"
|
||||
#include "gl/shaders/gl_postprocessshaderinstance.h"
|
||||
#include "gl/stereo3d/gl_stereo3d.h"
|
||||
#include "gl/textures/gl_hwtexture.h"
|
||||
#include "r_videoscale.h"
|
||||
|
||||
|
|
@ -239,7 +239,7 @@ void FGLRenderBuffers::RenderEffect(const FString &name)
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FGLRenderer::AmbientOccludeScene()
|
||||
void FGLRenderer::AmbientOccludeScene(float m5)
|
||||
{
|
||||
FGLDebug::PushGroup("AmbientOccludeScene");
|
||||
|
||||
|
|
@ -252,7 +252,7 @@ void FGLRenderer::AmbientOccludeScene()
|
|||
float aoStrength = gl_ssao_strength;
|
||||
|
||||
//float tanHalfFovy = tan(fovy * (M_PI / 360.0f));
|
||||
float tanHalfFovy = 1.0f / gl_RenderState.mProjectionMatrix.get()[5];
|
||||
float tanHalfFovy = 1.0f / m5;
|
||||
float invFocalLenX = tanHalfFovy * (mBuffers->GetSceneWidth() / (float)mBuffers->GetSceneHeight());
|
||||
float invFocalLenY = tanHalfFovy;
|
||||
float nDotVBias = clamp(bias, 0.0f, 1.0f);
|
||||
|
|
@ -272,8 +272,8 @@ void FGLRenderer::AmbientOccludeScene()
|
|||
mBuffers->BindSceneColorTexture(1);
|
||||
mLinearDepthShader->Bind(NOQUEUE);
|
||||
if (gl_multisample > 1) mLinearDepthShader->Uniforms->SampleIndex = 0;
|
||||
mLinearDepthShader->Uniforms->LinearizeDepthA = 1.0f / GetZFar() - 1.0f / GetZNear();
|
||||
mLinearDepthShader->Uniforms->LinearizeDepthB = MAX(1.0f / GetZNear(), 1.e-8f);
|
||||
mLinearDepthShader->Uniforms->LinearizeDepthA = 1.0f / screen->GetZFar() - 1.0f / screen->GetZNear();
|
||||
mLinearDepthShader->Uniforms->LinearizeDepthB = MAX(1.0f / screen->GetZNear(), 1.e-8f);
|
||||
mLinearDepthShader->Uniforms->InverseDepthRangeA = 1.0f;
|
||||
mLinearDepthShader->Uniforms->InverseDepthRangeB = 0.0f;
|
||||
mLinearDepthShader->Uniforms->Scale = sceneScale;
|
||||
|
|
@ -424,18 +424,18 @@ void FGLRenderer::ApplyFXAA()
|
|||
|
||||
void FGLRenderer::Flush()
|
||||
{
|
||||
const s3d::Stereo3DMode& stereo3dMode = s3d::Stereo3DMode::getCurrentMode();
|
||||
auto vrmode = VRMode::GetVRMode(true);
|
||||
const auto &mSceneViewport = screen->mSceneViewport;
|
||||
const auto &mScreenViewport = screen->mScreenViewport;
|
||||
|
||||
if (stereo3dMode.IsMono())
|
||||
if (vrmode->mEyeCount == 1)
|
||||
{
|
||||
CopyToBackbuffer(nullptr, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Render 2D to eye textures
|
||||
for (int eye_ix = 0; eye_ix < stereo3dMode.eye_count(); ++eye_ix)
|
||||
for (int eye_ix = 0; eye_ix < vrmode->mEyeCount; ++eye_ix)
|
||||
{
|
||||
FGLDebug::PushGroup("Eye2D");
|
||||
mBuffers->BindEyeFB(eye_ix);
|
||||
|
|
@ -448,7 +448,9 @@ void FGLRenderer::Flush()
|
|||
|
||||
FGLPostProcessState savedState;
|
||||
FGLDebug::PushGroup("PresentEyes");
|
||||
stereo3dMode.Present();
|
||||
// Note: This here is the ONLY place in the entire engine where the OpenGL dependent parts of the Stereo3D code need to be dealt with.
|
||||
// There's absolutely no need to create a overly complex class hierarchy for just this.
|
||||
GLRenderer->PresentStereo();
|
||||
FGLDebug::PopGroup();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include "gl_load/gl_interface.h"
|
||||
#include "gl/system/gl_framebuffer.h"
|
||||
#include "hwrenderer/utility/hw_cvars.h"
|
||||
#include "gl/scene/gl_portal.h"
|
||||
#include "gl/system/gl_debug.h"
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/renderer/gl_lightdata.h"
|
||||
|
|
@ -49,13 +50,11 @@
|
|||
#include "gl/renderer/gl_renderbuffers.h"
|
||||
#include "gl/data/gl_vertexbuffer.h"
|
||||
#include "gl/scene/gl_drawinfo.h"
|
||||
#include "gl/scene/gl_scenedrawer.h"
|
||||
#include "hwrenderer/postprocessing/hw_ambientshader.h"
|
||||
#include "hwrenderer/postprocessing/hw_presentshader.h"
|
||||
#include "hwrenderer/postprocessing/hw_present3dRowshader.h"
|
||||
#include "hwrenderer/postprocessing/hw_shadowmapshader.h"
|
||||
#include "gl/shaders/gl_postprocessshaderinstance.h"
|
||||
#include "gl/stereo3d/gl_stereo3d.h"
|
||||
#include "gl/textures/gl_samplers.h"
|
||||
#include "gl/dynlights/gl_lightbuffer.h"
|
||||
#include "r_videoscale.h"
|
||||
|
|
@ -80,11 +79,8 @@ extern bool NoInterpolateView;
|
|||
FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
|
||||
{
|
||||
framebuffer = fb;
|
||||
mCurrentPortal = nullptr;
|
||||
mMirrorCount = 0;
|
||||
mPlaneMirrorCount = 0;
|
||||
mAngles = FRotator(0.f, 0.f, 0.f);
|
||||
mViewVector = FVector2(0,0);
|
||||
mVBO = nullptr;
|
||||
mSkyVBO = nullptr;
|
||||
mShaderManager = nullptr;
|
||||
|
|
@ -121,6 +117,8 @@ void FGLRenderer::Initialize(int width, int height)
|
|||
mCustomPostProcessShaders = new FCustomPostProcessShaders();
|
||||
|
||||
// needed for the core profile, because someone decided it was a good idea to remove the default VAO.
|
||||
glGenQueries(1, &PortalQueryObject);
|
||||
|
||||
glGenVertexArrays(1, &mVAOID);
|
||||
glBindVertexArray(mVAOID);
|
||||
FGLDebug::LabelObject(GL_VERTEX_ARRAY, mVAOID, "FGLRenderer.mVAOID");
|
||||
|
|
@ -135,14 +133,10 @@ void FGLRenderer::Initialize(int width, int height)
|
|||
SetupLevel();
|
||||
mShaderManager = new FShaderManager;
|
||||
mSamplerManager = new FSamplerManager;
|
||||
|
||||
GLPortal::Initialize();
|
||||
}
|
||||
|
||||
FGLRenderer::~FGLRenderer()
|
||||
{
|
||||
GLPortal::Shutdown();
|
||||
|
||||
FlushModels();
|
||||
AActor::DeleteAllAttachedLights();
|
||||
FMaterial::FlushAll();
|
||||
|
|
@ -157,6 +151,8 @@ FGLRenderer::~FGLRenderer()
|
|||
glBindVertexArray(0);
|
||||
glDeleteVertexArrays(1, &mVAOID);
|
||||
}
|
||||
if (PortalQueryObject != 0) glDeleteQueries(1, &PortalQueryObject);
|
||||
|
||||
if (swdrawer) delete swdrawer;
|
||||
if (mBuffers) delete mBuffers;
|
||||
if (mPresentShader) delete mPresentShader;
|
||||
|
|
@ -195,17 +191,6 @@ void FGLRenderer::SetupLevel()
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
void FGLRenderer::FlushTextures()
|
||||
{
|
||||
FMaterial::FlushAll();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool FGLRenderer::StartOffscreen()
|
||||
{
|
||||
bool firstBind = (mFBID == 0);
|
||||
|
|
@ -281,10 +266,8 @@ sector_t *FGLRenderer::RenderView(player_t* player)
|
|||
fovratio = ratio;
|
||||
}
|
||||
|
||||
GLSceneDrawer drawer;
|
||||
|
||||
mShadowMap.Update();
|
||||
retsec = drawer.RenderViewpoint(player->camera, NULL, r_viewpoint.FieldOfView.Degrees, ratio, fovratio, true, true);
|
||||
retsec = RenderViewpoint(r_viewpoint, player->camera, NULL, r_viewpoint.FieldOfView.Degrees, ratio, fovratio, true, true);
|
||||
}
|
||||
All.Unclock();
|
||||
return retsec;
|
||||
|
|
@ -311,27 +294,70 @@ void FGLRenderer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, doub
|
|||
bounds.width = FHardwareTexture::GetTexDimension(gltex->GetWidth());
|
||||
bounds.height = FHardwareTexture::GetTexDimension(gltex->GetHeight());
|
||||
|
||||
GLSceneDrawer drawer;
|
||||
drawer.RenderViewpoint(Viewpoint, &bounds, FOV, (float)width / height, (float)width / height, false, false);
|
||||
FRenderViewpoint texvp;
|
||||
RenderViewpoint(texvp, Viewpoint, &bounds, FOV, (float)width / height, (float)width / height, false, false);
|
||||
|
||||
EndOffscreen();
|
||||
|
||||
tex->SetUpdated();
|
||||
}
|
||||
|
||||
void FGLRenderer::WriteSavePic(player_t *player, FileWriter *file, int width, int height)
|
||||
//===========================================================================
|
||||
//
|
||||
// Render the view to a savegame picture
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FGLRenderer::WriteSavePic (player_t *player, FileWriter *file, int width, int height)
|
||||
{
|
||||
// Todo: This needs to call the software renderer and process the returned image, if so desired.
|
||||
// This also needs to take out parts of the scene drawer so they can be shared between renderers.
|
||||
GLSceneDrawer drawer;
|
||||
drawer.WriteSavePic(player, file, width, height);
|
||||
IntRect bounds;
|
||||
bounds.left = 0;
|
||||
bounds.top = 0;
|
||||
bounds.width = width;
|
||||
bounds.height = height;
|
||||
|
||||
// if mVBO is persistently mapped we must be sure the GPU finished reading from it before we fill it with new data.
|
||||
glFinish();
|
||||
|
||||
// Switch to render buffers dimensioned for the savepic
|
||||
mBuffers = mSaveBuffers;
|
||||
|
||||
P_FindParticleSubsectors(); // make sure that all recently spawned particles have a valid subsector.
|
||||
gl_RenderState.SetVertexBuffer(mVBO);
|
||||
mVBO->Reset();
|
||||
mLights->Clear();
|
||||
|
||||
// This shouldn't overwrite the global viewpoint even for a short time.
|
||||
FRenderViewpoint savevp;
|
||||
sector_t *viewsector = RenderViewpoint(savevp, players[consoleplayer].camera, &bounds, r_viewpoint.FieldOfView.Degrees, 1.6f, 1.6f, true, false);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
gl_RenderState.SetSoftLightLevel(-1);
|
||||
CopyToBackbuffer(&bounds, false);
|
||||
|
||||
// strictly speaking not needed as the glReadPixels should block until the scene is rendered, but this is to safeguard against shitty drivers
|
||||
glFinish();
|
||||
|
||||
uint8_t * scr = (uint8_t *)M_Malloc(width * height * 3);
|
||||
glReadPixels(0,0,width, height,GL_RGB,GL_UNSIGNED_BYTE,scr);
|
||||
M_CreatePNG (file, scr + ((height-1) * width * 3), NULL, SS_RGB, width, height, -width * 3, Gamma);
|
||||
M_Free(scr);
|
||||
|
||||
// Switch back the screen render buffers
|
||||
screen->SetViewportRects(nullptr);
|
||||
mBuffers = mScreenBuffers;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FGLRenderer::BeginFrame()
|
||||
{
|
||||
buffersActive = GLRenderer->mScreenBuffers->Setup(screen->mScreenViewport.width, screen->mScreenViewport.height, screen->mSceneViewport.width, screen->mSceneViewport.height);
|
||||
buffersActive = mScreenBuffers->Setup(screen->mScreenViewport.width, screen->mScreenViewport.height, screen->mSceneViewport.width, screen->mSceneViewport.height);
|
||||
if (buffersActive)
|
||||
buffersActive = GLRenderer->mSaveBuffers->Setup(SAVEPICWIDTH, SAVEPICHEIGHT, SAVEPICWIDTH, SAVEPICHEIGHT);
|
||||
buffersActive = mSaveBuffers->Setup(SAVEPICWIDTH, SAVEPICHEIGHT, SAVEPICWIDTH, SAVEPICHEIGHT);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
|
@ -396,9 +422,11 @@ void FGLRenderer::Draw2D(F2DDrawer *drawer)
|
|||
const auto &mScreenViewport = screen->mScreenViewport;
|
||||
glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
|
||||
|
||||
gl_RenderState.mViewMatrix.loadIdentity();
|
||||
gl_RenderState.mProjectionMatrix.ortho(0, screen->GetWidth(), screen->GetHeight(), 0, -1.0f, 1.0f);
|
||||
gl_RenderState.ApplyMatrices();
|
||||
HWViewpointUniforms matrices;
|
||||
matrices.SetDefaults();
|
||||
matrices.mProjectionMatrix.ortho(0, screen->GetWidth(), screen->GetHeight(), 0, -1.0f, 1.0f);
|
||||
matrices.CalcDependencies();
|
||||
GLRenderer->mShaderManager->ApplyMatrices(&matrices, NORMAL_PASS);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
|
|
@ -524,7 +552,7 @@ void FGLRenderer::Draw2D(F2DDrawer *drawer)
|
|||
}
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
gl_RenderState.SetVertexBuffer(GLRenderer->mVBO);
|
||||
gl_RenderState.SetVertexBuffer(mVBO);
|
||||
gl_RenderState.EnableTexture(true);
|
||||
gl_RenderState.EnableBrightmap(true);
|
||||
gl_RenderState.SetTextureMode(TM_MODULATE);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "vectors.h"
|
||||
#include "r_renderer.h"
|
||||
#include "r_data/matrix.h"
|
||||
#include "hwrenderer/scene/hw_portal.h"
|
||||
#include "gl/dynlights/gl_shadowmap.h"
|
||||
#include <functional>
|
||||
|
||||
|
|
@ -37,8 +38,8 @@ class FGL2DDrawer;
|
|||
class FHardwareTexture;
|
||||
class FShadowMapShader;
|
||||
class FCustomPostProcessShaders;
|
||||
class GLSceneDrawer;
|
||||
class SWSceneDrawer;
|
||||
struct FRenderViewpoint;
|
||||
#define NOQUEUE nullptr // just some token to be used as a placeholder
|
||||
|
||||
enum
|
||||
|
|
@ -54,16 +55,14 @@ class FGLRenderer
|
|||
public:
|
||||
|
||||
OpenGLFrameBuffer *framebuffer;
|
||||
//GLPortal *mClipPortal;
|
||||
GLPortal *mCurrentPortal;
|
||||
int mMirrorCount;
|
||||
int mPlaneMirrorCount;
|
||||
float mCurrentFoV;
|
||||
AActor *mViewActor;
|
||||
FShaderManager *mShaderManager;
|
||||
FSamplerManager *mSamplerManager;
|
||||
unsigned int mFBID;
|
||||
unsigned int mVAOID;
|
||||
unsigned int PortalQueryObject;
|
||||
|
||||
int mOldFBID;
|
||||
|
||||
FGLRenderBuffers *mBuffers;
|
||||
|
|
@ -82,21 +81,19 @@ public:
|
|||
|
||||
FShadowMap mShadowMap;
|
||||
|
||||
FRotator mAngles;
|
||||
FVector2 mViewVector;
|
||||
//FRotator mAngles;
|
||||
|
||||
FFlatVertexBuffer *mVBO;
|
||||
FSkyVertexBuffer *mSkyVBO;
|
||||
FLightBuffer *mLights;
|
||||
SWSceneDrawer *swdrawer = nullptr;
|
||||
|
||||
bool mDrawingScene2D = false;
|
||||
FPortalSceneState mPortalState;
|
||||
|
||||
bool buffersActive = false;
|
||||
|
||||
float mSceneClearColor[3];
|
||||
|
||||
float mGlobVis = 0.0f;
|
||||
|
||||
FGLRenderer(OpenGLFrameBuffer *fb);
|
||||
~FGLRenderer() ;
|
||||
|
||||
|
|
@ -104,13 +101,13 @@ public:
|
|||
|
||||
void ClearBorders();
|
||||
|
||||
void FlushTextures();
|
||||
void SetupLevel();
|
||||
void ResetSWScene();
|
||||
|
||||
void PresentStereo();
|
||||
void RenderScreenQuad();
|
||||
void PostProcessScene(int fixedcm, const std::function<void()> &afterBloomDrawEndScene2D);
|
||||
void AmbientOccludeScene();
|
||||
void AmbientOccludeScene(float m5);
|
||||
void UpdateCameraExposure();
|
||||
void BloomScene(int fixedcm);
|
||||
void TonemapScene();
|
||||
|
|
@ -127,6 +124,10 @@ public:
|
|||
void WriteSavePic(player_t *player, FileWriter *file, int width, int height);
|
||||
sector_t *RenderView(player_t *player);
|
||||
void BeginFrame();
|
||||
|
||||
void Set3DViewport(bool mainview);
|
||||
sector_t *RenderViewpoint (FRenderViewpoint &mainvp, AActor * camera, IntRect * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen);
|
||||
|
||||
|
||||
bool StartOffscreen();
|
||||
void EndOffscreen();
|
||||
|
|
@ -134,9 +135,6 @@ public:
|
|||
void FillSimplePoly(FTexture *texture, FVector2 *points, int npoints,
|
||||
double originx, double originy, double scalex, double scaley,
|
||||
DAngle rotation, const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip);
|
||||
|
||||
static float GetZNear() { return 5.f; }
|
||||
static float GetZFar() { return 65536.f; }
|
||||
};
|
||||
|
||||
#include "hwrenderer/scene/hw_fakeflat.h"
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ void gl_SetTextureMode(int type);
|
|||
FRenderState gl_RenderState;
|
||||
|
||||
CVAR(Bool, gl_direct_state_change, true, 0)
|
||||
CVAR(Bool, gl_bandedswlight, false, CVAR_ARCHIVE)
|
||||
|
||||
|
||||
static VSMatrix identityMatrix(1);
|
||||
|
|
@ -62,7 +61,7 @@ static void matrixToGL(const VSMatrix &mat, int loc)
|
|||
void FRenderState::Reset()
|
||||
{
|
||||
mTextureEnabled = true;
|
||||
mClipLineShouldBeActive = mClipLineEnabled = mSplitEnabled = mBrightmapEnabled = mFogEnabled = mGlowEnabled = false;
|
||||
mSplitEnabled = mBrightmapEnabled = mFogEnabled = mGlowEnabled = false;
|
||||
mColorMask[0] = mColorMask[1] = mColorMask[2] = mColorMask[3] = true;
|
||||
currentColorMask[0] = currentColorMask[1] = currentColorMask[2] = currentColorMask[3] = true;
|
||||
mFogColor.d = -1;
|
||||
|
|
@ -81,8 +80,6 @@ void FRenderState::Reset()
|
|||
mLightParms[0] = mLightParms[1] = mLightParms[2] = 0.0f;
|
||||
mLightParms[3] = -1.f;
|
||||
mSpecialEffect = EFF_NONE;
|
||||
mClipHeight = 0.f;
|
||||
mClipHeightDirection = 0.f;
|
||||
mGlossiness = 0.0f;
|
||||
mSpecularLevel = 0.0f;
|
||||
mShaderTimer = 0.0f;
|
||||
|
|
@ -96,19 +93,15 @@ void FRenderState::Reset()
|
|||
mInterpolationFactor = 0.0f;
|
||||
|
||||
mColor.Set(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
mCameraPos.Set(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
mGlowTop.Set(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
mGlowBottom.Set(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
mGlowTopPlane.Set(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
mGlowBottomPlane.Set(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
mSplitTopPlane.Set(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
mSplitBottomPlane.Set(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
mClipLine.Set(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
mDynColor.Set(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
mEffectState = 0;
|
||||
activeShader = nullptr;
|
||||
mProjectionMatrix.loadIdentity();
|
||||
mViewMatrix.loadIdentity();
|
||||
mModelMatrix.loadIdentity();
|
||||
mTextureMatrix.loadIdentity();
|
||||
mPassType = NORMAL_PASS;
|
||||
|
|
@ -162,23 +155,17 @@ bool FRenderState::ApplyShader()
|
|||
|
||||
activeShader->muDesaturation.Set(mDesaturation / 255.f);
|
||||
activeShader->muFogEnabled.Set(fogset);
|
||||
activeShader->muPalLightLevels.Set(static_cast<int>(gl_bandedswlight) | (static_cast<int>(gl_fogmode) << 8));
|
||||
activeShader->muGlobVis.Set(GLRenderer->mGlobVis / 32.0f);
|
||||
activeShader->muTextureMode.Set(mTextureMode == TM_MODULATE && mTempTM == TM_OPAQUE ? TM_OPAQUE : mTextureMode);
|
||||
activeShader->muCameraPos.Set(mCameraPos.vec);
|
||||
activeShader->muLightParms.Set(mLightParms);
|
||||
activeShader->muFogColor.Set(mFogColor);
|
||||
activeShader->muObjectColor.Set(mObjectColor);
|
||||
activeShader->muObjectColor2.Set(mObjectColor2);
|
||||
activeShader->muDynLightColor.Set(mDynColor.vec);
|
||||
activeShader->muInterpolationFactor.Set(mInterpolationFactor);
|
||||
activeShader->muClipHeight.Set(mClipHeight);
|
||||
activeShader->muClipHeightDirection.Set(mClipHeightDirection);
|
||||
activeShader->muTimer.Set((double)(screen->FrameTime - firstFrame) * (double)mShaderTimer / 1000.);
|
||||
activeShader->muAlphaThreshold.Set(mAlphaThreshold);
|
||||
activeShader->muLightIndex.Set(-1);
|
||||
activeShader->muClipSplit.Set(mClipSplit);
|
||||
activeShader->muViewHeight.Set(viewheight);
|
||||
activeShader->muSpecularMaterial.Set(mGlossiness, mSpecularLevel);
|
||||
|
||||
if (mGlowEnabled)
|
||||
|
|
@ -213,17 +200,6 @@ bool FRenderState::ApplyShader()
|
|||
activeShader->currentsplitstate = 0;
|
||||
}
|
||||
|
||||
if (mClipLineEnabled)
|
||||
{
|
||||
activeShader->muClipLine.Set(mClipLine.vec);
|
||||
activeShader->currentcliplinestate = 1;
|
||||
}
|
||||
else if (activeShader->currentcliplinestate)
|
||||
{
|
||||
activeShader->muClipLine.Set(-10000000.0, 0, 0, 0);
|
||||
activeShader->currentcliplinestate = 0;
|
||||
}
|
||||
|
||||
if (mTextureMatrixEnabled)
|
||||
{
|
||||
matrixToGL(mTextureMatrix, activeShader->texturematrix_index);
|
||||
|
|
@ -304,14 +280,6 @@ void FRenderState::ApplyColorMask()
|
|||
}
|
||||
}
|
||||
|
||||
void FRenderState::ApplyMatrices()
|
||||
{
|
||||
if (GLRenderer->mShaderManager != NULL)
|
||||
{
|
||||
GLRenderer->mShaderManager->ApplyMatrices(&mProjectionMatrix, &mViewMatrix, mPassType);
|
||||
}
|
||||
}
|
||||
|
||||
void FRenderState::ApplyLightIndex(int index)
|
||||
{
|
||||
if (index > -1 && GLRenderer->mLights->GetBufferType() == GL_UNIFORM_BUFFER)
|
||||
|
|
@ -320,20 +288,3 @@ void FRenderState::ApplyLightIndex(int index)
|
|||
}
|
||||
activeShader->muLightIndex.Set(index);
|
||||
}
|
||||
|
||||
void FRenderState::SetClipHeight(float height, float direction)
|
||||
{
|
||||
mClipHeight = height;
|
||||
mClipHeightDirection = direction;
|
||||
|
||||
if (gl.flags & RFL_NO_CLIP_PLANES) return;
|
||||
|
||||
if (direction != 0.f)
|
||||
{
|
||||
glEnable(GL_CLIP_DISTANCE0);
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable(GL_CLIP_DISTANCE0); // GL_CLIP_PLANE0 is the same value so no need to make a distinction
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,8 +79,6 @@ class FRenderState
|
|||
uint8_t mFogEnabled;
|
||||
bool mGlowEnabled;
|
||||
bool mSplitEnabled;
|
||||
bool mClipLineEnabled;
|
||||
bool mClipLineShouldBeActive;
|
||||
bool mBrightmapEnabled;
|
||||
bool mColorMask[4];
|
||||
bool currentColorMask[4];
|
||||
|
|
@ -96,18 +94,15 @@ class FRenderState
|
|||
bool mTextureMatrixEnabled;
|
||||
bool mLastDepthClamp;
|
||||
float mInterpolationFactor;
|
||||
float mClipHeight, mClipHeightDirection;
|
||||
float mGlossiness, mSpecularLevel;
|
||||
float mShaderTimer;
|
||||
|
||||
FVertexBuffer *mVertexBuffer, *mCurrentVertexBuffer;
|
||||
FStateVec4 mNormal;
|
||||
FStateVec4 mColor;
|
||||
FStateVec4 mCameraPos;
|
||||
FStateVec4 mGlowTop, mGlowBottom;
|
||||
FStateVec4 mGlowTopPlane, mGlowBottomPlane;
|
||||
FStateVec4 mSplitTopPlane, mSplitBottomPlane;
|
||||
FStateVec4 mClipLine;
|
||||
PalEntry mFogColor;
|
||||
PalEntry mObjectColor;
|
||||
PalEntry mObjectColor2;
|
||||
|
|
@ -131,11 +126,8 @@ class FRenderState
|
|||
|
||||
public:
|
||||
|
||||
VSMatrix mProjectionMatrix;
|
||||
VSMatrix mViewMatrix;
|
||||
VSMatrix mModelMatrix;
|
||||
VSMatrix mTextureMatrix;
|
||||
VSMatrix mNormalViewMatrix;
|
||||
|
||||
FRenderState()
|
||||
{
|
||||
|
|
@ -162,7 +154,6 @@ public:
|
|||
|
||||
void Apply();
|
||||
void ApplyColorMask();
|
||||
void ApplyMatrices();
|
||||
void ApplyLightIndex(int index);
|
||||
|
||||
void SetVertexBuffer(FVertexBuffer *vb)
|
||||
|
|
@ -176,33 +167,6 @@ public:
|
|||
mCurrentVertexBuffer = NULL;
|
||||
}
|
||||
|
||||
float GetClipHeight()
|
||||
{
|
||||
return mClipHeight;
|
||||
}
|
||||
|
||||
float GetClipHeightDirection()
|
||||
{
|
||||
return mClipHeightDirection;
|
||||
}
|
||||
|
||||
FStateVec4 &GetClipLine()
|
||||
{
|
||||
return mClipLine;
|
||||
}
|
||||
|
||||
bool GetClipLineState()
|
||||
{
|
||||
return mClipLineEnabled;
|
||||
}
|
||||
|
||||
bool GetClipLineShouldBeActive()
|
||||
{
|
||||
return mClipLineShouldBeActive;
|
||||
}
|
||||
|
||||
void SetClipHeight(float height, float direction);
|
||||
|
||||
void SetNormal(FVector3 norm)
|
||||
{
|
||||
mNormal.Set(norm.X, norm.Y, norm.Z, 0.f);
|
||||
|
|
@ -307,32 +271,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void SetClipLine(line_t *line)
|
||||
{
|
||||
mClipLine.Set(line->v1->fX(), line->v1->fY(), line->Delta().X, line->Delta().Y);
|
||||
}
|
||||
|
||||
void EnableClipLine(bool on)
|
||||
{
|
||||
if (!(gl.flags & RFL_NO_CLIP_PLANES))
|
||||
{
|
||||
mClipLineEnabled = on;
|
||||
if (on)
|
||||
{
|
||||
glEnable(GL_CLIP_DISTANCE0);
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable(GL_CLIP_DISTANCE0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// this needs to be flagged because in this case per-sector plane rendering needs to be disabled if a clip plane is active.
|
||||
mClipLineShouldBeActive = on;
|
||||
}
|
||||
}
|
||||
|
||||
void EnableBrightmap(bool on)
|
||||
{
|
||||
mBrightmapEnabled = on;
|
||||
|
|
@ -348,11 +286,6 @@ public:
|
|||
mTextureMatrixEnabled = on;
|
||||
}
|
||||
|
||||
void SetCameraPos(float x, float y, float z)
|
||||
{
|
||||
mCameraPos.Set(x, z, y, 0);
|
||||
}
|
||||
|
||||
void SetGlowParams(float *t, float *b)
|
||||
{
|
||||
mGlowTop.Set(t[0], t[1], t[2], t[3]);
|
||||
|
|
|
|||
364
src/gl/renderer/gl_stereo3d.cpp
Normal file
364
src/gl/renderer/gl_stereo3d.cpp
Normal file
|
|
@ -0,0 +1,364 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2015 Christopher Bruns
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
/*
|
||||
** gl_stereo3d.cpp
|
||||
** Stereoscopic 3D API
|
||||
**
|
||||
*/
|
||||
|
||||
#include "gl_load/gl_system.h"
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/renderer/gl_renderbuffers.h"
|
||||
#include "hwrenderer/utility/hw_vrmodes.h"
|
||||
#include "gl/system/gl_framebuffer.h"
|
||||
#include "gl/renderer/gl_postprocessstate.h"
|
||||
#include "hwrenderer/postprocessing/hw_presentshader.h"
|
||||
#include "hwrenderer/postprocessing/hw_present3dRowshader.h"
|
||||
|
||||
EXTERN_CVAR(Int, vr_mode)
|
||||
EXTERN_CVAR(Float, vid_saturation)
|
||||
EXTERN_CVAR(Float, vid_brightness)
|
||||
EXTERN_CVAR(Float, vid_contrast)
|
||||
EXTERN_CVAR(Int, gl_satformula)
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void PresentAnaglyph(bool r, bool g, bool b)
|
||||
{
|
||||
GLRenderer->mBuffers->BindOutputFB();
|
||||
GLRenderer->ClearBorders();
|
||||
|
||||
glColorMask(r, g, b, 1);
|
||||
GLRenderer->mBuffers->BindEyeTexture(0, 0);
|
||||
GLRenderer->DrawPresentTexture(screen->mOutputLetterbox, true);
|
||||
|
||||
glColorMask(!r, !g, !b, 1);
|
||||
GLRenderer->mBuffers->BindEyeTexture(1, 0);
|
||||
GLRenderer->DrawPresentTexture(screen->mOutputLetterbox, true);
|
||||
|
||||
glColorMask(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void PresentSideBySide()
|
||||
{
|
||||
GLRenderer->mBuffers->BindOutputFB();
|
||||
GLRenderer->ClearBorders();
|
||||
|
||||
// Compute screen regions to use for left and right eye views
|
||||
int leftWidth = screen->mOutputLetterbox.width / 2;
|
||||
int rightWidth = screen->mOutputLetterbox.width - leftWidth;
|
||||
IntRect leftHalfScreen = screen->mOutputLetterbox;
|
||||
leftHalfScreen.width = leftWidth;
|
||||
IntRect rightHalfScreen = screen->mOutputLetterbox;
|
||||
rightHalfScreen.width = rightWidth;
|
||||
rightHalfScreen.left += leftWidth;
|
||||
|
||||
GLRenderer->mBuffers->BindEyeTexture(0, 0);
|
||||
GLRenderer->DrawPresentTexture(leftHalfScreen, true);
|
||||
|
||||
GLRenderer->mBuffers->BindEyeTexture(1, 0);
|
||||
GLRenderer->DrawPresentTexture(rightHalfScreen, true);
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void PresentTopBottom()
|
||||
{
|
||||
GLRenderer->mBuffers->BindOutputFB();
|
||||
GLRenderer->ClearBorders();
|
||||
|
||||
// Compute screen regions to use for left and right eye views
|
||||
int topHeight = screen->mOutputLetterbox.height / 2;
|
||||
int bottomHeight = screen->mOutputLetterbox.height - topHeight;
|
||||
IntRect topHalfScreen = screen->mOutputLetterbox;
|
||||
topHalfScreen.height = topHeight;
|
||||
topHalfScreen.top = topHeight;
|
||||
IntRect bottomHalfScreen = screen->mOutputLetterbox;
|
||||
bottomHalfScreen.height = bottomHeight;
|
||||
bottomHalfScreen.top = 0;
|
||||
|
||||
GLRenderer->mBuffers->BindEyeTexture(0, 0);
|
||||
GLRenderer->DrawPresentTexture(topHalfScreen, true);
|
||||
|
||||
GLRenderer->mBuffers->BindEyeTexture(1, 0);
|
||||
GLRenderer->DrawPresentTexture(bottomHalfScreen, true);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void prepareInterleavedPresent(FPresentShaderBase& shader)
|
||||
{
|
||||
GLRenderer->mBuffers->BindOutputFB();
|
||||
GLRenderer->ClearBorders();
|
||||
|
||||
|
||||
// Bind each eye texture, for composition in the shader
|
||||
GLRenderer->mBuffers->BindEyeTexture(0, 0);
|
||||
GLRenderer->mBuffers->BindEyeTexture(1, 1);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
const IntRect& box = screen->mOutputLetterbox;
|
||||
glViewport(box.left, box.top, box.width, box.height);
|
||||
|
||||
shader.Bind(NOQUEUE);
|
||||
|
||||
if (GLRenderer->framebuffer->IsHWGammaActive())
|
||||
{
|
||||
shader.Uniforms->InvGamma = 1.0f;
|
||||
shader.Uniforms->Contrast = 1.0f;
|
||||
shader.Uniforms->Brightness = 0.0f;
|
||||
shader.Uniforms->Saturation = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
shader.Uniforms->InvGamma = 1.0f / clamp<float>(Gamma, 0.1f, 4.f);
|
||||
shader.Uniforms->Contrast = clamp<float>(vid_contrast, 0.1f, 3.f);
|
||||
shader.Uniforms->Brightness = clamp<float>(vid_brightness, -0.8f, 0.8f);
|
||||
shader.Uniforms->Saturation = clamp<float>(vid_saturation, -15.0f, 15.0f);
|
||||
shader.Uniforms->GrayFormula = static_cast<int>(gl_satformula);
|
||||
}
|
||||
shader.Uniforms->Scale = {
|
||||
screen->mScreenViewport.width / (float)GLRenderer->mBuffers->GetWidth(),
|
||||
screen->mScreenViewport.height / (float)GLRenderer->mBuffers->GetHeight()
|
||||
};
|
||||
shader.Uniforms.Set();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void PresentColumnInterleaved()
|
||||
{
|
||||
FGLPostProcessState savedState;
|
||||
savedState.SaveTextureBindings(2);
|
||||
prepareInterleavedPresent(*GLRenderer->mPresent3dColumnShader);
|
||||
|
||||
// Compute absolute offset from top of screen to top of current display window
|
||||
// because we need screen-relative, not window-relative, scan line parity
|
||||
|
||||
// Todo:
|
||||
//auto clientoffset = screen->GetClientOffset();
|
||||
//auto windowHOffset = clientoffset.X % 2;
|
||||
int windowHOffset = 0;
|
||||
|
||||
GLRenderer->mPresent3dColumnShader->Uniforms->WindowPositionParity = windowHOffset;
|
||||
GLRenderer->mPresent3dColumnShader->Uniforms.Set();
|
||||
|
||||
GLRenderer->RenderScreenQuad();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void PresentRowInterleaved()
|
||||
{
|
||||
FGLPostProcessState savedState;
|
||||
savedState.SaveTextureBindings(2);
|
||||
prepareInterleavedPresent(*GLRenderer->mPresent3dRowShader);
|
||||
|
||||
// Todo:
|
||||
//auto clientoffset = screen->GetClientOffset();
|
||||
//auto windowVOffset = clientoffset.Y % 2;
|
||||
int windowVOffset = 0;
|
||||
|
||||
GLRenderer->mPresent3dRowShader->Uniforms->WindowPositionParity =
|
||||
(windowVOffset
|
||||
+ screen->mOutputLetterbox.height + 1 // +1 because of origin at bottom
|
||||
) % 2;
|
||||
|
||||
GLRenderer->mPresent3dRowShader->Uniforms.Set();
|
||||
GLRenderer->RenderScreenQuad();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void PresentCheckerInterleaved()
|
||||
{
|
||||
FGLPostProcessState savedState;
|
||||
savedState.SaveTextureBindings(2);
|
||||
prepareInterleavedPresent(*GLRenderer->mPresent3dCheckerShader);
|
||||
|
||||
// Compute absolute offset from top of screen to top of current display window
|
||||
// because we need screen-relative, not window-relative, scan line parity
|
||||
|
||||
//auto clientoffset = screen->GetClientOffset();
|
||||
//auto windowHOffset = clientoffset.X % 2;
|
||||
//auto windowVOffset = clientoffset.Y % 2;
|
||||
int windowHOffset = 0;
|
||||
int windowVOffset = 0;
|
||||
|
||||
GLRenderer->mPresent3dCheckerShader->Uniforms->WindowPositionParity =
|
||||
(windowVOffset
|
||||
+ windowHOffset
|
||||
+ screen->mOutputLetterbox.height + 1 // +1 because of origin at bottom
|
||||
) % 2; // because we want the top pixel offset, but gl_FragCoord.y is the bottom pixel offset
|
||||
|
||||
GLRenderer->mPresent3dCheckerShader->Uniforms.Set();
|
||||
GLRenderer->RenderScreenQuad();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Sometimes the stereo render context is not ready immediately at start up
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool QuadStereoCheckInitialRenderContextState()
|
||||
{
|
||||
// Keep trying until we see at least one good OpenGL context to render to
|
||||
static bool bQuadStereoSupported = false;
|
||||
static bool bDecentContextWasFound = false;
|
||||
static int contextCheckCount = 0;
|
||||
if ((!bDecentContextWasFound) && (contextCheckCount < 200))
|
||||
{
|
||||
contextCheckCount += 1;
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); // This question is about the main screen display context
|
||||
GLboolean supportsStereo, supportsBuffered;
|
||||
glGetBooleanv(GL_DOUBLEBUFFER, &supportsBuffered);
|
||||
if (supportsBuffered) // Finally, a useful OpenGL context
|
||||
{
|
||||
// This block will be executed exactly ONCE during a game run
|
||||
bDecentContextWasFound = true; // now we can stop checking every frame...
|
||||
// Now check whether this context supports hardware stereo
|
||||
glGetBooleanv(GL_STEREO, &supportsStereo);
|
||||
bQuadStereoSupported = supportsStereo && supportsBuffered;
|
||||
}
|
||||
}
|
||||
return bQuadStereoSupported;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void PresentQuadStereo()
|
||||
{
|
||||
if (QuadStereoCheckInitialRenderContextState())
|
||||
{
|
||||
GLRenderer->mBuffers->BindOutputFB();
|
||||
|
||||
glDrawBuffer(GL_BACK_LEFT);
|
||||
GLRenderer->ClearBorders();
|
||||
GLRenderer->mBuffers->BindEyeTexture(0, 0);
|
||||
GLRenderer->DrawPresentTexture(screen->mOutputLetterbox, true);
|
||||
|
||||
glDrawBuffer(GL_BACK_RIGHT);
|
||||
GLRenderer->ClearBorders();
|
||||
GLRenderer->mBuffers->BindEyeTexture(1, 0);
|
||||
GLRenderer->DrawPresentTexture(screen->mOutputLetterbox, true);
|
||||
|
||||
glDrawBuffer(GL_BACK);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLRenderer->mBuffers->BindOutputFB();
|
||||
GLRenderer->ClearBorders();
|
||||
GLRenderer->mBuffers->BindEyeTexture(0, 0);
|
||||
GLRenderer->DrawPresentTexture(screen->mOutputLetterbox, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FGLRenderer::PresentStereo()
|
||||
{
|
||||
switch (vr_mode)
|
||||
{
|
||||
default:
|
||||
return;
|
||||
|
||||
case VR_GREENMAGENTA:
|
||||
PresentAnaglyph(false, true, false);
|
||||
break;
|
||||
|
||||
case VR_REDCYAN:
|
||||
PresentAnaglyph(true, false, false);
|
||||
break;
|
||||
|
||||
case VR_AMBERBLUE:
|
||||
PresentAnaglyph(true, true, false);
|
||||
break;
|
||||
|
||||
case VR_SIDEBYSIDEFULL:
|
||||
case VR_SIDEBYSIDESQUISHED:
|
||||
PresentSideBySide();
|
||||
break;
|
||||
|
||||
case VR_TOPBOTTOM:
|
||||
PresentTopBottom();
|
||||
break;
|
||||
|
||||
case VR_ROWINTERLEAVED:
|
||||
PresentRowInterleaved();
|
||||
break;
|
||||
|
||||
case VR_COLUMNINTERLEAVED:
|
||||
PresentColumnInterleaved();
|
||||
break;
|
||||
|
||||
case VR_CHECKERINTERLEAVED:
|
||||
PresentCheckerInterleaved();
|
||||
break;
|
||||
|
||||
case VR_QUADSTEREO:
|
||||
PresentQuadStereo();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -37,13 +37,23 @@
|
|||
|
||||
#include "gl/data/gl_vertexbuffer.h"
|
||||
#include "gl/scene/gl_drawinfo.h"
|
||||
#include "hwrenderer/scene/hw_clipper.h"
|
||||
#include "gl/scene/gl_portal.h"
|
||||
#include "gl/scene/gl_scenedrawer.h"
|
||||
#include "gl/renderer/gl_renderstate.h"
|
||||
#include "gl/stereo3d/scoped_color_mask.h"
|
||||
#include "gl/renderer/gl_quaddrawer.h"
|
||||
#include "gl/dynlights/gl_lightbuffer.h"
|
||||
|
||||
class FDrawInfoList
|
||||
{
|
||||
public:
|
||||
TDeletingArray<FDrawInfo *> mList;
|
||||
|
||||
|
||||
FDrawInfo * GetNew();
|
||||
void Release(FDrawInfo *);
|
||||
};
|
||||
|
||||
|
||||
static FDrawInfo * gl_drawinfo;
|
||||
FDrawInfoList di_list;
|
||||
|
||||
|
|
@ -63,7 +73,7 @@ void FDrawInfo::DoDrawSorted(HWDrawList *dl, SortNode * head)
|
|||
if (dl->drawitems[head->itemindex].rendertype == GLDIT_FLAT)
|
||||
{
|
||||
z = dl->flats[dl->drawitems[head->itemindex].index]->z;
|
||||
relation = z > r_viewpoint.Pos.Z ? 1 : -1;
|
||||
relation = z > Viewpoint.Pos.Z ? 1 : -1;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -164,23 +174,6 @@ void FDrawInfoList::Release(FDrawInfo * di)
|
|||
mList.Push(di);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FDrawInfo::FDrawInfo()
|
||||
{
|
||||
next = NULL;
|
||||
}
|
||||
|
||||
FDrawInfo::~FDrawInfo()
|
||||
{
|
||||
ClearBuffers();
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Sets up a new drawinfo struct
|
||||
|
|
@ -190,12 +183,21 @@ FDrawInfo::~FDrawInfo()
|
|||
// OpenGL has no use for multiple clippers so use the same one for all DrawInfos.
|
||||
static Clipper staticClipper;
|
||||
|
||||
FDrawInfo *FDrawInfo::StartDrawInfo(GLSceneDrawer *drawer)
|
||||
FDrawInfo *FDrawInfo::StartDrawInfo(FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms)
|
||||
{
|
||||
FDrawInfo *di=di_list.GetNew();
|
||||
di->mDrawer = drawer;
|
||||
di->mVBO = GLRenderer->mVBO;
|
||||
di->mClipper = &staticClipper;
|
||||
di->Viewpoint = parentvp;
|
||||
if (uniforms)
|
||||
{
|
||||
di->VPUniforms = *uniforms;
|
||||
// The clip planes will never be inherited from the parent drawinfo.
|
||||
di->VPUniforms.mClipLine.X = -1000001.f;
|
||||
di->VPUniforms.mClipHeight = 0;
|
||||
}
|
||||
else di->VPUniforms.SetDefaults();
|
||||
di->mClipper->SetViewpoint(di->Viewpoint);
|
||||
staticClipper.Clear();
|
||||
di->StartScene();
|
||||
return di;
|
||||
|
|
@ -205,7 +207,7 @@ void FDrawInfo::StartScene()
|
|||
{
|
||||
ClearBuffers();
|
||||
|
||||
next = gl_drawinfo;
|
||||
outer = gl_drawinfo;
|
||||
gl_drawinfo = this;
|
||||
for (int i = 0; i < GLDL_TYPES; i++) drawlists[i].Reset();
|
||||
decals[0].Clear();
|
||||
|
|
@ -213,7 +215,7 @@ void FDrawInfo::StartScene()
|
|||
hudsprites.Clear();
|
||||
|
||||
// Fullbright information needs to be propagated from the main view.
|
||||
if (next != nullptr) FullbrightFlags = next->FullbrightFlags;
|
||||
if (outer != nullptr) FullbrightFlags = outer->FullbrightFlags;
|
||||
else FullbrightFlags = 0;
|
||||
|
||||
}
|
||||
|
|
@ -223,15 +225,15 @@ void FDrawInfo::StartScene()
|
|||
//
|
||||
//
|
||||
//==========================================================================
|
||||
void FDrawInfo::EndDrawInfo()
|
||||
FDrawInfo *FDrawInfo::EndDrawInfo()
|
||||
{
|
||||
FDrawInfo * di = gl_drawinfo;
|
||||
|
||||
for(int i=0;i<GLDL_TYPES;i++) di->drawlists[i].Reset();
|
||||
gl_drawinfo=di->next;
|
||||
di_list.Release(di);
|
||||
assert(this == gl_drawinfo);
|
||||
for(int i=0;i<GLDL_TYPES;i++) drawlists[i].Reset();
|
||||
gl_drawinfo=static_cast<FDrawInfo*>(outer);
|
||||
di_list.Release(this);
|
||||
if (gl_drawinfo == nullptr)
|
||||
ResetRenderDataAllocator();
|
||||
return gl_drawinfo;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -245,31 +247,30 @@ void FDrawInfo::EndDrawInfo()
|
|||
|
||||
void FDrawInfo::SetupFloodStencil(wallseg * ws)
|
||||
{
|
||||
int recursion = GLPortal::GetRecursion();
|
||||
int recursion = GLRenderer->mPortalState.GetRecursion();
|
||||
|
||||
// Create stencil
|
||||
glStencilFunc(GL_EQUAL, recursion, ~0); // create stencil
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); // increment stencil of valid pixels
|
||||
{
|
||||
// Use revertible color mask, to avoid stomping on anaglyph 3D state
|
||||
ScopedColorMask colorMask(0, 0, 0, 0); // glColorMask(0, 0, 0, 0); // don't write to the graphics buffer
|
||||
gl_RenderState.EnableTexture(false);
|
||||
gl_RenderState.ResetColor();
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(true);
|
||||
glColorMask(0, 0, 0, 0); // don't write to the graphics buffer
|
||||
gl_RenderState.EnableTexture(false);
|
||||
gl_RenderState.ResetColor();
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(true);
|
||||
|
||||
gl_RenderState.Apply();
|
||||
FQuadDrawer qd;
|
||||
qd.Set(0, ws->x1, ws->z1, ws->y1, 0, 0);
|
||||
qd.Set(1, ws->x1, ws->z2, ws->y1, 0, 0);
|
||||
qd.Set(2, ws->x2, ws->z2, ws->y2, 0, 0);
|
||||
qd.Set(3, ws->x2, ws->z1, ws->y2, 0, 0);
|
||||
qd.Render(GL_TRIANGLE_FAN);
|
||||
gl_RenderState.Apply();
|
||||
FQuadDrawer qd;
|
||||
qd.Set(0, ws->x1, ws->z1, ws->y1, 0, 0);
|
||||
qd.Set(1, ws->x1, ws->z2, ws->y1, 0, 0);
|
||||
qd.Set(2, ws->x2, ws->z2, ws->y2, 0, 0);
|
||||
qd.Set(3, ws->x2, ws->z1, ws->y2, 0, 0);
|
||||
qd.Render(GL_TRIANGLE_FAN);
|
||||
|
||||
glStencilFunc(GL_EQUAL, recursion + 1, ~0); // draw sky into stencil
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // this stage doesn't modify the stencil
|
||||
glStencilFunc(GL_EQUAL, recursion + 1, ~0); // draw sky into stencil
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // this stage doesn't modify the stencil
|
||||
|
||||
} // glColorMask(1, 1, 1, 1); // don't write to the graphics buffer
|
||||
glColorMask(1, 1, 1, 1); // don't write to the graphics buffer
|
||||
gl_RenderState.EnableTexture(true);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(false);
|
||||
|
|
@ -277,28 +278,27 @@ void FDrawInfo::SetupFloodStencil(wallseg * ws)
|
|||
|
||||
void FDrawInfo::ClearFloodStencil(wallseg * ws)
|
||||
{
|
||||
int recursion = GLPortal::GetRecursion();
|
||||
int recursion = GLRenderer->mPortalState.GetRecursion();
|
||||
|
||||
glStencilOp(GL_KEEP,GL_KEEP,GL_DECR);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
|
||||
gl_RenderState.EnableTexture(false);
|
||||
{
|
||||
// Use revertible color mask, to avoid stomping on anaglyph 3D state
|
||||
ScopedColorMask colorMask(0, 0, 0, 0); // glColorMask(0,0,0,0); // don't write to the graphics buffer
|
||||
gl_RenderState.ResetColor();
|
||||
// Use revertible color mask, to avoid stomping on anaglyph 3D state
|
||||
glColorMask(0, 0, 0, 0); // don't write to the graphics buffer
|
||||
gl_RenderState.ResetColor();
|
||||
|
||||
gl_RenderState.Apply();
|
||||
FQuadDrawer qd;
|
||||
qd.Set(0, ws->x1, ws->z1, ws->y1, 0, 0);
|
||||
qd.Set(1, ws->x1, ws->z2, ws->y1, 0, 0);
|
||||
qd.Set(2, ws->x2, ws->z2, ws->y2, 0, 0);
|
||||
qd.Set(3, ws->x2, ws->z1, ws->y2, 0, 0);
|
||||
qd.Render(GL_TRIANGLE_FAN);
|
||||
gl_RenderState.Apply();
|
||||
FQuadDrawer qd;
|
||||
qd.Set(0, ws->x1, ws->z1, ws->y1, 0, 0);
|
||||
qd.Set(1, ws->x1, ws->z2, ws->y1, 0, 0);
|
||||
qd.Set(2, ws->x2, ws->z2, ws->y2, 0, 0);
|
||||
qd.Set(3, ws->x2, ws->z1, ws->y2, 0, 0);
|
||||
qd.Render(GL_TRIANGLE_FAN);
|
||||
|
||||
// restore old stencil op.
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
glStencilFunc(GL_EQUAL, recursion, ~0);
|
||||
gl_RenderState.EnableTexture(true);
|
||||
} // glColorMask(1, 1, 1, 1);
|
||||
// restore old stencil op.
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
glStencilFunc(GL_EQUAL, recursion, ~0);
|
||||
gl_RenderState.EnableTexture(true);
|
||||
glColorMask(1, 1, 1, 1);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(true);
|
||||
}
|
||||
|
|
@ -341,9 +341,9 @@ void FDrawInfo::DrawFloodedPlane(wallseg * ws, float planez, sector_t * sec, boo
|
|||
SetFog(lightlevel, rel, &Colormap, false);
|
||||
gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false);
|
||||
|
||||
float fviewx = r_viewpoint.Pos.X;
|
||||
float fviewy = r_viewpoint.Pos.Y;
|
||||
float fviewz = r_viewpoint.Pos.Z;
|
||||
float fviewx = Viewpoint.Pos.X;
|
||||
float fviewy = Viewpoint.Pos.Y;
|
||||
float fviewz = Viewpoint.Pos.Z;
|
||||
|
||||
gl_RenderState.SetPlaneTextureRotation(&plane, gltexture);
|
||||
gl_RenderState.Apply();
|
||||
|
|
@ -394,7 +394,7 @@ void FDrawInfo::FloodUpperGap(seg_t * seg)
|
|||
double frontz = fakefsector->ceilingplane.ZatPoint(seg->v1);
|
||||
|
||||
if (fakebsector->GetTexture(sector_t::ceiling)==skyflatnum) return;
|
||||
if (backz < r_viewpoint.Pos.Z) return;
|
||||
if (backz < Viewpoint.Pos.Z) return;
|
||||
|
||||
if (seg->sidedef == seg->linedef->sidedef[0])
|
||||
{
|
||||
|
|
@ -447,7 +447,7 @@ void FDrawInfo::FloodLowerGap(seg_t * seg)
|
|||
|
||||
|
||||
if (fakebsector->GetTexture(sector_t::floor) == skyflatnum) return;
|
||||
if (fakebsector->GetPlaneTexZ(sector_t::floor) > r_viewpoint.Pos.Z) return;
|
||||
if (fakebsector->GetPlaneTexZ(sector_t::floor) > Viewpoint.Pos.Z) return;
|
||||
|
||||
if (seg->sidedef == seg->linedef->sidedef[0])
|
||||
{
|
||||
|
|
@ -478,22 +478,17 @@ void FDrawInfo::FloodLowerGap(seg_t * seg)
|
|||
ClearFloodStencil(&ws);
|
||||
}
|
||||
|
||||
// This was temporarily moved out of gl_renderhacks.cpp so that the dependency on GLWall could be eliminated until things have progressed a bit.
|
||||
void FDrawInfo::ProcessLowerMinisegs(TArray<seg_t *> &lowersegs)
|
||||
{
|
||||
for(unsigned int j=0;j<lowersegs.Size();j++)
|
||||
{
|
||||
seg_t * seg=lowersegs[j];
|
||||
GLWall wall;
|
||||
wall.ProcessLowerMiniseg(this, seg, seg->Subsector->render_sector, seg->PartnerSeg->Subsector->render_sector);
|
||||
rendered_lines++;
|
||||
}
|
||||
}
|
||||
|
||||
// Same here for the dependency on the portal.
|
||||
void FDrawInfo::AddSubsectorToPortal(FSectorPortalGroup *portal, subsector_t *sub)
|
||||
void FDrawInfo::AddSubsectorToPortal(FSectorPortalGroup *ptg, subsector_t *sub)
|
||||
{
|
||||
portal->GetRenderState()->AddSubsector(sub);
|
||||
auto portal = FindPortal(ptg);
|
||||
if (!portal)
|
||||
{
|
||||
portal = new GLScenePortal(&GLRenderer->mPortalState, new HWSectorStackPortal(ptg));
|
||||
Portals.Push(portal);
|
||||
}
|
||||
auto ptl = static_cast<HWSectorStackPortal*>(static_cast<GLScenePortal*>(portal)->mScene);
|
||||
ptl->AddSubsector(sub);
|
||||
}
|
||||
|
||||
std::pair<FFlatVertex *, unsigned int> FDrawInfo::AllocVertices(unsigned int count)
|
||||
|
|
@ -515,5 +510,10 @@ int FDrawInfo::UploadLights(FDynLightData &data)
|
|||
return GLRenderer->mLights->UploadLights(data);
|
||||
}
|
||||
|
||||
bool FDrawInfo::SetDepthClamp(bool on)
|
||||
{
|
||||
return gl_RenderState.SetDepthClamp(on);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -4,13 +4,12 @@
|
|||
#include "gl/renderer/gl_lightdata.h"
|
||||
#include "hwrenderer/scene/hw_drawlist.h"
|
||||
#include "hwrenderer/scene/hw_weapon.h"
|
||||
#include "hwrenderer/scene/hw_viewpointuniforms.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4244)
|
||||
#endif
|
||||
|
||||
class GLSceneDrawer;
|
||||
|
||||
enum DrawListType
|
||||
{
|
||||
GLDL_PLAINWALLS,
|
||||
|
|
@ -36,16 +35,12 @@ enum Drawpasses
|
|||
|
||||
struct FDrawInfo : public HWDrawInfo
|
||||
{
|
||||
GLSceneDrawer *mDrawer;
|
||||
|
||||
FDrawInfo * next;
|
||||
HWDrawList drawlists[GLDL_TYPES];
|
||||
TArray<HUDSprite> hudsprites; // These may just be stored by value.
|
||||
TArray<GLDecal *> decals[2]; // the second slot is for mirrors which get rendered in a separate pass.
|
||||
|
||||
FDrawInfo();
|
||||
~FDrawInfo();
|
||||
|
||||
void ApplyVPUniforms() override;
|
||||
|
||||
void AddWall(GLWall *wall) override;
|
||||
void AddMirrorSurface(GLWall *w) override;
|
||||
GLDecal *AddDecal(bool onmirror) override;
|
||||
|
|
@ -57,15 +52,6 @@ struct FDrawInfo : public HWDrawInfo
|
|||
std::pair<FFlatVertex *, unsigned int> AllocVertices(unsigned int count) override;
|
||||
int UploadLights(FDynLightData &data) override;
|
||||
|
||||
// Legacy GL only.
|
||||
bool PutWallCompat(GLWall *wall, int passflag);
|
||||
bool PutFlatCompat(GLFlat *flat, bool fog);
|
||||
void RenderFogBoundaryCompat(GLWall *wall);
|
||||
void RenderLightsCompat(GLWall *wall, int pass);
|
||||
void DrawSubsectorLights(GLFlat *flat, subsector_t * sub, int pass);
|
||||
void DrawLightsCompat(GLFlat *flat, int pass);
|
||||
|
||||
|
||||
void DrawDecal(GLDecal *gldecal);
|
||||
void DrawDecals();
|
||||
void DrawDecalsForMirror(GLWall *wall);
|
||||
|
|
@ -103,11 +89,19 @@ struct FDrawInfo : public HWDrawInfo
|
|||
void DrawSorted(int listindex);
|
||||
|
||||
// These two may be moved to the API independent part of the renderer later.
|
||||
void ProcessLowerMinisegs(TArray<seg_t *> &lowersegs) override;
|
||||
void AddSubsectorToPortal(FSectorPortalGroup *portal, subsector_t *sub) override;
|
||||
|
||||
void CreateScene();
|
||||
void RenderScene(int recursion);
|
||||
void RenderTranslucent();
|
||||
void DrawScene(int drawmode);
|
||||
void ProcessScene(bool toscreen = false);
|
||||
void EndDrawScene(sector_t * viewsector);
|
||||
void DrawEndScene2D(sector_t * viewsector);
|
||||
bool SetDepthClamp(bool on) override;
|
||||
|
||||
static FDrawInfo *StartDrawInfo(GLSceneDrawer *drawer);
|
||||
static void EndDrawInfo();
|
||||
static FDrawInfo *StartDrawInfo(FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms);
|
||||
FDrawInfo *EndDrawInfo();
|
||||
|
||||
gl_subsectorrendernode * GetOtherFloorPlanes(unsigned int sector)
|
||||
{
|
||||
|
|
@ -133,16 +127,6 @@ struct FDrawInfo : public HWDrawInfo
|
|||
|
||||
};
|
||||
|
||||
class FDrawInfoList
|
||||
{
|
||||
TDeletingArray<FDrawInfo *> mList;
|
||||
|
||||
public:
|
||||
|
||||
FDrawInfo *GetNew();
|
||||
void Release(FDrawInfo *);
|
||||
};
|
||||
|
||||
|
||||
void gl_SetRenderStyle(FRenderStyle style, bool drawopaque, bool allowcolorblending);
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@
|
|||
#include "gl/data/gl_vertexbuffer.h"
|
||||
#include "gl/dynlights/gl_lightbuffer.h"
|
||||
#include "gl/scene/gl_drawinfo.h"
|
||||
#include "gl/scene/gl_scenedrawer.h"
|
||||
#include "gl/renderer/gl_quaddrawer.h"
|
||||
|
||||
//==========================================================================
|
||||
|
|
@ -167,7 +166,7 @@ void FDrawInfo::ProcessLights(GLFlat *flat, bool istrans)
|
|||
{
|
||||
flat->dynlightindex = GLRenderer->mLights->GetIndexPtr();
|
||||
|
||||
if (flat->sector->ibocount > 0 && !gl_RenderState.GetClipLineShouldBeActive())
|
||||
if (flat->sector->ibocount > 0 && !ClipLineShouldBeActive())
|
||||
{
|
||||
SetupSectorLights(flat, GLPASS_LIGHTSONLY, nullptr);
|
||||
}
|
||||
|
|
@ -216,7 +215,7 @@ void FDrawInfo::DrawSubsectors(GLFlat *flat, int pass, bool processlights, bool
|
|||
|
||||
if (iboindex >= 0)
|
||||
{
|
||||
if (vcount > 0 && !gl_RenderState.GetClipLineShouldBeActive())
|
||||
if (vcount > 0 && !ClipLineShouldBeActive())
|
||||
{
|
||||
if (processlights) SetupSectorLights(flat, GLPASS_ALL, &dli);
|
||||
drawcalls.Clock();
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -37,218 +37,59 @@
|
|||
#define __GL_PORTAL_H
|
||||
|
||||
#include "tarray.h"
|
||||
#include "r_utility.h"
|
||||
#include "actor.h"
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/scene/gl_drawinfo.h"
|
||||
#include "hwrenderer/scene/hw_drawstructs.h"
|
||||
#include "hwrenderer/scene/hw_portal.h"
|
||||
|
||||
extern UniqueList<GLSkyInfo> UniqueSkies;
|
||||
extern UniqueList<GLHorizonInfo> UniqueHorizons;
|
||||
extern UniqueList<secplane_t> UniquePlaneMirrors;
|
||||
struct GLEEHorizonPortal;
|
||||
class GLSceneDrawer;
|
||||
|
||||
class GLPortal : public IPortal
|
||||
{
|
||||
static TArray<GLPortal *> portals;
|
||||
static int recursion;
|
||||
static unsigned int QueryObject;
|
||||
protected:
|
||||
static TArray<float> planestack;
|
||||
static int MirrorFlag;
|
||||
static int PlaneMirrorFlag;
|
||||
static int renderdepth;
|
||||
|
||||
public:
|
||||
static GLSceneDrawer *drawer;
|
||||
static int PlaneMirrorMode;
|
||||
static int inupperstack;
|
||||
static bool inskybox;
|
||||
|
||||
private:
|
||||
void DrawPortalStencil();
|
||||
|
||||
DVector3 savedviewpath[2];
|
||||
DVector3 savedViewPos;
|
||||
DVector3 savedViewActorPos;
|
||||
DRotator savedAngles;
|
||||
bool savedshowviewer;
|
||||
AActor * savedviewactor;
|
||||
ActorRenderFlags savedvisibility;
|
||||
GLPortal *PrevPortal;
|
||||
TArray<unsigned int> mPrimIndices;
|
||||
|
||||
protected:
|
||||
TArray<GLWall> lines;
|
||||
int level;
|
||||
|
||||
GLPortal(bool local = false) { if (!local) portals.Push(this); }
|
||||
virtual ~GLPortal() { }
|
||||
GLPortal(FPortalSceneState *state, bool local = false) : IPortal(state, local) { }
|
||||
|
||||
bool Start(bool usestencil, bool doquery, FDrawInfo *outer_di, FDrawInfo **pDi);
|
||||
void End(bool usestencil);
|
||||
virtual void DrawContents(FDrawInfo *di)=0;
|
||||
virtual void * GetSource() const =0; // GetSource MUST be implemented!
|
||||
void ClearClipper(FDrawInfo *di);
|
||||
bool Start(bool usestencil, bool doquery, HWDrawInfo *outer_di, HWDrawInfo **pDi) override;
|
||||
void End(HWDrawInfo *di, bool usestencil) override;
|
||||
void ClearScreen(HWDrawInfo *di);
|
||||
};
|
||||
|
||||
class GLScenePortal : public GLPortal
|
||||
{
|
||||
public:
|
||||
HWScenePortalBase *mScene;
|
||||
GLScenePortal(FPortalSceneState *state, HWScenePortalBase *handler) : GLPortal(state)
|
||||
{
|
||||
mScene = handler;
|
||||
handler->SetOwner(this);
|
||||
}
|
||||
~GLScenePortal() { delete mScene; }
|
||||
virtual void * GetSource() const { return mScene->GetSource(); }
|
||||
virtual const char *GetName() { return mScene->GetName(); }
|
||||
virtual bool IsSky() { return false; }
|
||||
virtual bool NeedCap() { return true; }
|
||||
virtual bool NeedDepthBuffer() { return true; }
|
||||
void ClearScreen();
|
||||
virtual const char *GetName() = 0;
|
||||
virtual void PushState() {}
|
||||
virtual void PopState() {}
|
||||
|
||||
public:
|
||||
|
||||
void RenderPortal(bool usestencil, bool doquery, FDrawInfo *outer_di)
|
||||
{
|
||||
// Start may perform an occlusion query. If that returns 0 there
|
||||
// is no need to draw the stencil's contents and there's also no
|
||||
// need to restore the affected area becasue there is none!
|
||||
FDrawInfo *di;
|
||||
if (Start(usestencil, doquery, outer_di, &di))
|
||||
virtual void DrawContents(HWDrawInfo *di)
|
||||
{
|
||||
if (mScene->Setup(di, di->mClipper))
|
||||
{
|
||||
DrawContents(di);
|
||||
End(usestencil);
|
||||
static_cast<FDrawInfo*>(di)->DrawScene(DM_PORTAL);
|
||||
mScene->Shutdown(di);
|
||||
}
|
||||
else ClearScreen(di);
|
||||
}
|
||||
|
||||
void AddLine(GLWall * l)
|
||||
{
|
||||
lines.Push(*l);
|
||||
}
|
||||
|
||||
static int GetRecursion()
|
||||
{
|
||||
return recursion;
|
||||
}
|
||||
|
||||
static bool isMirrored() { return !!((MirrorFlag ^ PlaneMirrorFlag) & 1); }
|
||||
|
||||
virtual void RenderAttached(FDrawInfo *di) {}
|
||||
|
||||
static void BeginScene();
|
||||
static void StartFrame();
|
||||
static bool RenderFirstSkyPortal(int recursion, FDrawInfo *outer_di);
|
||||
static void EndFrame(FDrawInfo *outer_di);
|
||||
static GLPortal * FindPortal(const void * src);
|
||||
|
||||
static void Initialize();
|
||||
static void Shutdown();
|
||||
};
|
||||
|
||||
struct GLLinePortal : public GLPortal
|
||||
{
|
||||
// this must be the same as at the start of line_t, so that we can pass in this structure directly to P_ClipLineToPortal.
|
||||
vertex_t *v1, *v2; // vertices, from v1 to v2
|
||||
DVector2 delta; // precalculated v2 - v1 for side checking
|
||||
|
||||
angle_t angv1, angv2; // for quick comparisons with a line or subsector
|
||||
|
||||
GLLinePortal(line_t *line)
|
||||
{
|
||||
v1 = line->v1;
|
||||
v2 = line->v2;
|
||||
CalcDelta();
|
||||
}
|
||||
|
||||
GLLinePortal(FLinePortalSpan *line)
|
||||
{
|
||||
if (line->lines[0]->mType != PORTT_LINKED || line->v1 == nullptr)
|
||||
{
|
||||
// For non-linked portals we must check the actual linedef.
|
||||
line_t *lline = line->lines[0]->mDestination;
|
||||
v1 = lline->v1;
|
||||
v2 = lline->v2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// For linked portals we can check the merged span.
|
||||
v1 = line->v1;
|
||||
v2 = line->v2;
|
||||
}
|
||||
CalcDelta();
|
||||
}
|
||||
|
||||
void CalcDelta()
|
||||
{
|
||||
delta = v2->fPos() - v1->fPos();
|
||||
}
|
||||
|
||||
line_t *line()
|
||||
{
|
||||
vertex_t **pv = &v1;
|
||||
return reinterpret_cast<line_t*>(pv);
|
||||
}
|
||||
|
||||
virtual int ClipSeg(seg_t *seg);
|
||||
virtual int ClipSubsector(subsector_t *sub);
|
||||
virtual int ClipPoint(const DVector2 &pos);
|
||||
virtual bool NeedCap() { return false; }
|
||||
virtual void PushState();
|
||||
virtual void PopState();
|
||||
};
|
||||
|
||||
|
||||
struct GLMirrorPortal : public GLLinePortal
|
||||
{
|
||||
// mirror portals always consist of single linedefs!
|
||||
line_t * linedef;
|
||||
|
||||
protected:
|
||||
virtual void DrawContents(FDrawInfo *di);
|
||||
virtual void * GetSource() const { return linedef; }
|
||||
virtual const char *GetName();
|
||||
|
||||
public:
|
||||
|
||||
GLMirrorPortal(line_t * line)
|
||||
: GLLinePortal(line)
|
||||
{
|
||||
linedef=line;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct GLLineToLinePortal : public GLLinePortal
|
||||
{
|
||||
FLinePortalSpan *glport;
|
||||
protected:
|
||||
virtual void DrawContents(FDrawInfo *di);
|
||||
virtual void * GetSource() const { return glport; }
|
||||
virtual const char *GetName();
|
||||
virtual line_t *ClipLine() { return line(); }
|
||||
virtual void RenderAttached(FDrawInfo *di);
|
||||
|
||||
public:
|
||||
|
||||
GLLineToLinePortal(FLinePortalSpan *ll)
|
||||
: GLLinePortal(ll)
|
||||
{
|
||||
glport = ll;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct GLSkyboxPortal : public GLPortal
|
||||
{
|
||||
FSectorPortal * portal;
|
||||
|
||||
protected:
|
||||
virtual void DrawContents(FDrawInfo *di);
|
||||
virtual void * GetSource() const { return portal; }
|
||||
virtual bool IsSky() { return true; }
|
||||
virtual const char *GetName();
|
||||
|
||||
public:
|
||||
|
||||
|
||||
GLSkyboxPortal(FSectorPortal * pt)
|
||||
{
|
||||
portal=pt;
|
||||
}
|
||||
|
||||
virtual void RenderAttached(HWDrawInfo *di) { return mScene->RenderAttached(di); }
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -258,7 +99,7 @@ struct GLSkyPortal : public GLPortal
|
|||
friend struct GLEEHorizonPortal;
|
||||
|
||||
protected:
|
||||
virtual void DrawContents(FDrawInfo *di);
|
||||
virtual void DrawContents(HWDrawInfo *di);
|
||||
virtual void * GetSource() const { return origin; }
|
||||
virtual bool IsSky() { return true; }
|
||||
virtual bool NeedDepthBuffer() { return false; }
|
||||
|
|
@ -267,61 +108,14 @@ protected:
|
|||
public:
|
||||
|
||||
|
||||
GLSkyPortal(GLSkyInfo * pt, bool local = false)
|
||||
: GLPortal(local)
|
||||
GLSkyPortal(FPortalSceneState *state, GLSkyInfo * pt, bool local = false)
|
||||
: GLPortal(state, local)
|
||||
{
|
||||
origin=pt;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct GLSectorStackPortal : public GLPortal
|
||||
{
|
||||
TArray<subsector_t *> subsectors;
|
||||
protected:
|
||||
virtual ~GLSectorStackPortal();
|
||||
virtual void DrawContents(FDrawInfo *di);
|
||||
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();
|
||||
FSectorPortalGroup *origin;
|
||||
|
||||
public:
|
||||
|
||||
GLSectorStackPortal(FSectorPortalGroup *pt)
|
||||
{
|
||||
origin=pt;
|
||||
}
|
||||
void SetupCoverage(FDrawInfo *di);
|
||||
void AddSubsector(subsector_t *sub)
|
||||
{
|
||||
subsectors.Push(sub);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct GLPlaneMirrorPortal : public GLPortal
|
||||
{
|
||||
protected:
|
||||
virtual void DrawContents(FDrawInfo *di);
|
||||
virtual void * GetSource() const { return origin; }
|
||||
virtual const char *GetName();
|
||||
virtual void PushState();
|
||||
virtual void PopState();
|
||||
secplane_t * origin;
|
||||
|
||||
public:
|
||||
|
||||
GLPlaneMirrorPortal(secplane_t * pt)
|
||||
{
|
||||
origin=pt;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct GLHorizonPortal : public GLPortal
|
||||
{
|
||||
GLHorizonInfo * origin;
|
||||
|
|
@ -330,7 +124,7 @@ struct GLHorizonPortal : public GLPortal
|
|||
friend struct GLEEHorizonPortal;
|
||||
|
||||
protected:
|
||||
virtual void DrawContents(FDrawInfo *di);
|
||||
virtual void DrawContents(HWDrawInfo *di);
|
||||
virtual void * GetSource() const { return origin; }
|
||||
virtual bool NeedDepthBuffer() { return false; }
|
||||
virtual bool NeedCap() { return false; }
|
||||
|
|
@ -338,7 +132,7 @@ protected:
|
|||
|
||||
public:
|
||||
|
||||
GLHorizonPortal(GLHorizonInfo * pt, bool local = false);
|
||||
GLHorizonPortal(FPortalSceneState *state, GLHorizonInfo * pt, FRenderViewpoint &vp, bool local = false);
|
||||
};
|
||||
|
||||
struct GLEEHorizonPortal : public GLPortal
|
||||
|
|
@ -346,7 +140,7 @@ struct GLEEHorizonPortal : public GLPortal
|
|||
FSectorPortal * portal;
|
||||
|
||||
protected:
|
||||
virtual void DrawContents(FDrawInfo *di);
|
||||
virtual void DrawContents(HWDrawInfo *di);
|
||||
virtual void * GetSource() const { return portal; }
|
||||
virtual bool NeedDepthBuffer() { return false; }
|
||||
virtual bool NeedCap() { return false; }
|
||||
|
|
@ -354,7 +148,7 @@ protected:
|
|||
|
||||
public:
|
||||
|
||||
GLEEHorizonPortal(FSectorPortal *pt)
|
||||
GLEEHorizonPortal(FPortalSceneState *state, FSectorPortal *pt) : GLPortal(state)
|
||||
{
|
||||
portal=pt;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,11 +50,10 @@
|
|||
#include "gl/renderer/gl_renderbuffers.h"
|
||||
#include "gl/data/gl_vertexbuffer.h"
|
||||
#include "hwrenderer/scene/hw_clipper.h"
|
||||
#include "hwrenderer/scene/hw_portal.h"
|
||||
#include "gl/scene/gl_drawinfo.h"
|
||||
#include "gl/scene/gl_portal.h"
|
||||
#include "gl/scene/gl_scenedrawer.h"
|
||||
#include "gl/stereo3d/gl_stereo3d.h"
|
||||
#include "hwrenderer/utility/scoped_view_shifter.h"
|
||||
#include "hwrenderer/utility/hw_vrmodes.h"
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
@ -72,136 +71,25 @@ EXTERN_CVAR (Bool, r_deathcamera)
|
|||
EXTERN_CVAR (Float, r_visibility)
|
||||
EXTERN_CVAR (Bool, r_drawvoxels)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// R_FrustumAngle
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
angle_t GLSceneDrawer::FrustumAngle()
|
||||
|
||||
void FDrawInfo::ApplyVPUniforms()
|
||||
{
|
||||
float tilt = fabs(GLRenderer->mAngles.Pitch.Degrees);
|
||||
VPUniforms.CalcDependencies();
|
||||
GLRenderer->mShaderManager->ApplyMatrices(&VPUniforms, NORMAL_PASS);
|
||||
|
||||
// If the pitch is larger than this you can look all around at a FOV of 90°
|
||||
if (tilt > 46.0f) return 0xffffffff;
|
||||
|
||||
// ok, this is a gross hack that barely works...
|
||||
// but at least it doesn't overestimate too much...
|
||||
double floatangle = 2.0 + (45.0 + ((tilt / 1.9)))*GLRenderer->mCurrentFoV*48.0 / AspectMultiplier(r_viewwindow.WidescreenRatio) / 90.0;
|
||||
angle_t a1 = DAngle(floatangle).BAMs();
|
||||
if (a1 >= ANGLE_180) return 0xffffffff;
|
||||
return a1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// resets the 3D viewport
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GLSceneDrawer::Reset3DViewport()
|
||||
{
|
||||
glViewport(screen->mScreenViewport.left, screen->mScreenViewport.top, screen->mScreenViewport.width, screen->mScreenViewport.height);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// sets 3D viewport and initial state
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GLSceneDrawer::Set3DViewport(bool mainview)
|
||||
{
|
||||
if (mainview && GLRenderer->buffersActive)
|
||||
if (!(gl.flags & RFL_NO_CLIP_PLANES))
|
||||
{
|
||||
bool useSSAO = (gl_ssao != 0);
|
||||
GLRenderer->mBuffers->BindSceneFB(useSSAO);
|
||||
gl_RenderState.SetPassType(useSSAO ? GBUFFER_PASS : NORMAL_PASS);
|
||||
gl_RenderState.EnableDrawBuffers(gl_RenderState.GetPassDrawBufferCount());
|
||||
gl_RenderState.Apply();
|
||||
if (VPUniforms.mClipHeightDirection != 0.f || VPUniforms.mClipLine.X > -10000000.0f)
|
||||
{
|
||||
glEnable(GL_CLIP_DISTANCE0);
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable(GL_CLIP_DISTANCE0);
|
||||
}
|
||||
}
|
||||
|
||||
// Always clear all buffers with scissor test disabled.
|
||||
// This is faster on newer hardware because it allows the GPU to skip
|
||||
// reading from slower memory where the full buffers are stored.
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glClearColor(GLRenderer->mSceneClearColor[0], GLRenderer->mSceneClearColor[1], GLRenderer->mSceneClearColor[2], 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
const auto &bounds = screen->mSceneViewport;
|
||||
glViewport(bounds.left, bounds.top, bounds.width, bounds.height);
|
||||
glScissor(bounds.left, bounds.top, bounds.width, bounds.height);
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
glStencilFunc(GL_ALWAYS,0,~0); // default stencil
|
||||
glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Setup the camera position
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GLSceneDrawer::SetViewAngle(DAngle viewangle)
|
||||
{
|
||||
GLRenderer->mAngles.Yaw = float(270.0-viewangle.Degrees);
|
||||
DVector2 v = r_viewpoint.Angles.Yaw.ToVector();
|
||||
GLRenderer->mViewVector.X = v.X;
|
||||
GLRenderer->mViewVector.Y = v.Y;
|
||||
|
||||
R_SetViewAngle(r_viewpoint, r_viewwindow);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// SetProjection
|
||||
// sets projection matrix
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GLSceneDrawer::SetProjection(VSMatrix matrix)
|
||||
{
|
||||
gl_RenderState.mProjectionMatrix.loadIdentity();
|
||||
gl_RenderState.mProjectionMatrix.multMatrix(matrix);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Setup the modelview matrix
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GLSceneDrawer::SetViewMatrix(float vx, float vy, float vz, bool mirror, bool planemirror)
|
||||
{
|
||||
float mult = mirror? -1:1;
|
||||
float planemult = planemirror? -level.info->pixelstretch : level.info->pixelstretch;
|
||||
|
||||
gl_RenderState.mViewMatrix.loadIdentity();
|
||||
gl_RenderState.mViewMatrix.rotate(GLRenderer->mAngles.Roll.Degrees, 0.0f, 0.0f, 1.0f);
|
||||
gl_RenderState.mViewMatrix.rotate(GLRenderer->mAngles.Pitch.Degrees, 1.0f, 0.0f, 0.0f);
|
||||
gl_RenderState.mViewMatrix.rotate(GLRenderer->mAngles.Yaw.Degrees, 0.0f, mult, 0.0f);
|
||||
gl_RenderState.mViewMatrix.translate(vx * mult, -vz * planemult , -vy);
|
||||
gl_RenderState.mViewMatrix.scale(-mult, planemult, 1);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// SetupView
|
||||
// Setup the view rotation matrix for the given viewpoint
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void GLSceneDrawer::SetupView(float vx, float vy, float vz, DAngle va, bool mirror, bool planemirror)
|
||||
{
|
||||
SetViewAngle(va);
|
||||
SetViewMatrix(vx, vy, vz, mirror, planemirror);
|
||||
gl_RenderState.ApplyMatrices();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
|
|
@ -211,48 +99,45 @@ void GLSceneDrawer::SetupView(float vx, float vy, float vz, DAngle va, bool mirr
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GLSceneDrawer::CreateScene(FDrawInfo *di)
|
||||
void FDrawInfo::CreateScene()
|
||||
{
|
||||
const auto &vp = Viewpoint;
|
||||
angle_t a1 = FrustumAngle();
|
||||
di->mClipper->SafeAddClipRangeRealAngles(r_viewpoint.Angles.Yaw.BAMs() + a1, r_viewpoint.Angles.Yaw.BAMs() - a1);
|
||||
mClipper->SafeAddClipRangeRealAngles(vp.Angles.Yaw.BAMs() + a1, vp.Angles.Yaw.BAMs() - a1);
|
||||
|
||||
// reset the portal manager
|
||||
GLPortal::StartFrame();
|
||||
GLRenderer->mPortalState.StartFrame();
|
||||
PO_LinkToSubsectors();
|
||||
|
||||
ProcessAll.Clock();
|
||||
|
||||
// clip the scene and fill the drawlists
|
||||
for(auto p : level.portalGroups) p->glportal = nullptr;
|
||||
Bsp.Clock();
|
||||
GLRenderer->mVBO->Map();
|
||||
GLRenderer->mLights->Begin();
|
||||
|
||||
// Give the DrawInfo the viewpoint in fixed point because that's what the nodes are.
|
||||
di->viewx = FLOAT2FIXED(r_viewpoint.Pos.X);
|
||||
di->viewy = FLOAT2FIXED(r_viewpoint.Pos.Y);
|
||||
viewx = FLOAT2FIXED(vp.Pos.X);
|
||||
viewy = FLOAT2FIXED(vp.Pos.Y);
|
||||
|
||||
validcount++; // used for processing sidedefs only once by the renderer.
|
||||
|
||||
di->mAngles = GLRenderer->mAngles;
|
||||
di->mViewVector = GLRenderer->mViewVector;
|
||||
di->mViewActor = GLRenderer->mViewActor;
|
||||
di->mShadowMap = &GLRenderer->mShadowMap;
|
||||
mShadowMap = &GLRenderer->mShadowMap;
|
||||
|
||||
di->RenderBSPNode (level.HeadNode());
|
||||
di->PreparePlayerSprites(r_viewpoint.sector, di->in_area);
|
||||
RenderBSPNode (level.HeadNode());
|
||||
PreparePlayerSprites(vp.sector, in_area);
|
||||
|
||||
// Process all the sprites on the current portal's back side which touch the portal.
|
||||
if (GLRenderer->mCurrentPortal != NULL) GLRenderer->mCurrentPortal->RenderAttached(di);
|
||||
if (mCurrentPortal != nullptr) mCurrentPortal->RenderAttached(this);
|
||||
Bsp.Unclock();
|
||||
|
||||
// And now the crappy hacks that have to be done to avoid rendering anomalies.
|
||||
// These cannot be multithreaded when the time comes because all these depend
|
||||
// on the global 'validcount' variable.
|
||||
|
||||
di->HandleMissingTextures(di->in_area); // Missing upper/lower textures
|
||||
di->HandleHackedSubsectors(); // open sector hacks for deep water
|
||||
di->ProcessSectorStacks(di->in_area); // merge visplanes of sector stacks
|
||||
HandleMissingTextures(in_area); // Missing upper/lower textures
|
||||
HandleHackedSubsectors(); // open sector hacks for deep water
|
||||
ProcessSectorStacks(in_area); // merge visplanes of sector stacks
|
||||
GLRenderer->mLights->Finish();
|
||||
GLRenderer->mVBO->Unmap();
|
||||
|
||||
|
|
@ -268,36 +153,35 @@ void GLSceneDrawer::CreateScene(FDrawInfo *di)
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GLSceneDrawer::RenderScene(FDrawInfo *di, int recursion)
|
||||
void FDrawInfo::RenderScene(int recursion)
|
||||
{
|
||||
const auto &vp = Viewpoint;
|
||||
RenderAll.Clock();
|
||||
|
||||
glDepthMask(true);
|
||||
if (!gl_no_skyclear) GLPortal::RenderFirstSkyPortal(recursion, di);
|
||||
|
||||
gl_RenderState.SetCameraPos(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z);
|
||||
if (!gl_no_skyclear) GLRenderer->mPortalState.RenderFirstSkyPortal(recursion, this);
|
||||
|
||||
gl_RenderState.EnableFog(true);
|
||||
gl_RenderState.BlendFunc(GL_ONE,GL_ZERO);
|
||||
|
||||
if (gl_sort_textures)
|
||||
{
|
||||
di->drawlists[GLDL_PLAINWALLS].SortWalls();
|
||||
di->drawlists[GLDL_PLAINFLATS].SortFlats();
|
||||
di->drawlists[GLDL_MASKEDWALLS].SortWalls();
|
||||
di->drawlists[GLDL_MASKEDFLATS].SortFlats();
|
||||
di->drawlists[GLDL_MASKEDWALLSOFS].SortWalls();
|
||||
drawlists[GLDL_PLAINWALLS].SortWalls();
|
||||
drawlists[GLDL_PLAINFLATS].SortFlats();
|
||||
drawlists[GLDL_MASKEDWALLS].SortWalls();
|
||||
drawlists[GLDL_MASKEDFLATS].SortFlats();
|
||||
drawlists[GLDL_MASKEDWALLSOFS].SortWalls();
|
||||
}
|
||||
|
||||
// if we don't have a persistently mapped buffer, we have to process all the dynamic lights up front,
|
||||
// so that we don't have to do repeated map/unmap calls on the buffer.
|
||||
if (gl.lightmethod == LM_DEFERRED && level.HasDynamicLights && !di->isFullbrightScene())
|
||||
if (gl.lightmethod == LM_DEFERRED && level.HasDynamicLights && !isFullbrightScene())
|
||||
{
|
||||
GLRenderer->mLights->Begin();
|
||||
di->drawlists[GLDL_PLAINFLATS].DrawFlats(di, GLPASS_LIGHTSONLY);
|
||||
di->drawlists[GLDL_MASKEDFLATS].DrawFlats(di, GLPASS_LIGHTSONLY);
|
||||
di->drawlists[GLDL_TRANSLUCENTBORDER].Draw(di, GLPASS_LIGHTSONLY);
|
||||
di->drawlists[GLDL_TRANSLUCENT].Draw(di, GLPASS_LIGHTSONLY, true);
|
||||
drawlists[GLDL_PLAINFLATS].DrawFlats(this, GLPASS_LIGHTSONLY);
|
||||
drawlists[GLDL_MASKEDFLATS].DrawFlats(this, GLPASS_LIGHTSONLY);
|
||||
drawlists[GLDL_TRANSLUCENTBORDER].Draw(this, GLPASS_LIGHTSONLY);
|
||||
drawlists[GLDL_TRANSLUCENT].Draw(this, GLPASS_LIGHTSONLY, true);
|
||||
GLRenderer->mLights->Finish();
|
||||
}
|
||||
|
||||
|
|
@ -310,8 +194,8 @@ void GLSceneDrawer::RenderScene(FDrawInfo *di, int recursion)
|
|||
|
||||
gl_RenderState.EnableTexture(gl_texture);
|
||||
gl_RenderState.EnableBrightmap(true);
|
||||
di->drawlists[GLDL_PLAINWALLS].DrawWalls(di, pass);
|
||||
di->drawlists[GLDL_PLAINFLATS].DrawFlats(di, pass);
|
||||
drawlists[GLDL_PLAINWALLS].DrawWalls(this, pass);
|
||||
drawlists[GLDL_PLAINFLATS].DrawFlats(this, pass);
|
||||
|
||||
|
||||
// Part 2: masked geometry. This is set up so that only pixels with alpha>gl_mask_threshold will show
|
||||
|
|
@ -321,20 +205,20 @@ void GLSceneDrawer::RenderScene(FDrawInfo *di, int recursion)
|
|||
gl_RenderState.SetTextureMode(TM_MASK);
|
||||
}
|
||||
gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
|
||||
di->drawlists[GLDL_MASKEDWALLS].DrawWalls(di, pass);
|
||||
di->drawlists[GLDL_MASKEDFLATS].DrawFlats(di, pass);
|
||||
drawlists[GLDL_MASKEDWALLS].DrawWalls(this, pass);
|
||||
drawlists[GLDL_MASKEDFLATS].DrawFlats(this, pass);
|
||||
|
||||
// Part 3: masked geometry with polygon offset. This list is empty most of the time so only waste time on it when in use.
|
||||
if (di->drawlists[GLDL_MASKEDWALLSOFS].Size() > 0)
|
||||
if (drawlists[GLDL_MASKEDWALLSOFS].Size() > 0)
|
||||
{
|
||||
glEnable(GL_POLYGON_OFFSET_FILL);
|
||||
glPolygonOffset(-1.0f, -128.0f);
|
||||
di->drawlists[GLDL_MASKEDWALLSOFS].DrawWalls(di, pass);
|
||||
drawlists[GLDL_MASKEDWALLSOFS].DrawWalls(this, pass);
|
||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
glPolygonOffset(0, 0);
|
||||
}
|
||||
|
||||
di->drawlists[GLDL_MODELS].Draw(di, pass);
|
||||
drawlists[GLDL_MODELS].Draw(this, pass);
|
||||
|
||||
gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
|
|
@ -343,7 +227,7 @@ void GLSceneDrawer::RenderScene(FDrawInfo *di, int recursion)
|
|||
glEnable(GL_POLYGON_OFFSET_FILL);
|
||||
glPolygonOffset(-1.0f, -128.0f);
|
||||
glDepthMask(false);
|
||||
di->DrawDecals();
|
||||
DrawDecals();
|
||||
|
||||
gl_RenderState.SetTextureMode(TM_MODULATE);
|
||||
|
||||
|
|
@ -361,7 +245,7 @@ void GLSceneDrawer::RenderScene(FDrawInfo *di, int recursion)
|
|||
gl_RenderState.EnableFog(true);
|
||||
gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
|
||||
gl_RenderState.BlendFunc(GL_ONE,GL_ZERO);
|
||||
di->DrawUnhandledMissingTextures();
|
||||
DrawUnhandledMissingTextures();
|
||||
glDepthMask(true);
|
||||
|
||||
glPolygonOffset(0.0f, 0.0f);
|
||||
|
|
@ -378,20 +262,18 @@ void GLSceneDrawer::RenderScene(FDrawInfo *di, int recursion)
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GLSceneDrawer::RenderTranslucent(FDrawInfo *di)
|
||||
void FDrawInfo::RenderTranslucent()
|
||||
{
|
||||
RenderAll.Clock();
|
||||
|
||||
gl_RenderState.SetCameraPos(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z);
|
||||
|
||||
// final pass: translucent stuff
|
||||
gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_sprite_threshold);
|
||||
gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
gl_RenderState.EnableBrightmap(true);
|
||||
di->drawlists[GLDL_TRANSLUCENTBORDER].Draw(di, GLPASS_TRANSLUCENT);
|
||||
drawlists[GLDL_TRANSLUCENTBORDER].Draw(this, GLPASS_TRANSLUCENT);
|
||||
glDepthMask(false);
|
||||
di->DrawSorted(GLDL_TRANSLUCENT);
|
||||
DrawSorted(GLDL_TRANSLUCENT);
|
||||
gl_RenderState.EnableBrightmap(false);
|
||||
|
||||
|
||||
|
|
@ -411,10 +293,11 @@ void GLSceneDrawer::RenderTranslucent(FDrawInfo *di)
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GLSceneDrawer::DrawScene(FDrawInfo *di, int drawmode)
|
||||
void FDrawInfo::DrawScene(int drawmode)
|
||||
{
|
||||
static int recursion=0;
|
||||
static int ssao_portals_available = 0;
|
||||
const auto &vp = Viewpoint;
|
||||
|
||||
bool applySSAO = false;
|
||||
if (drawmode == DM_MAINVIEW)
|
||||
|
|
@ -432,35 +315,35 @@ void GLSceneDrawer::DrawScene(FDrawInfo *di, int drawmode)
|
|||
ssao_portals_available--;
|
||||
}
|
||||
|
||||
if (r_viewpoint.camera != nullptr)
|
||||
if (vp.camera != nullptr)
|
||||
{
|
||||
ActorRenderFlags savedflags = r_viewpoint.camera->renderflags;
|
||||
CreateScene(di);
|
||||
r_viewpoint.camera->renderflags = savedflags;
|
||||
ActorRenderFlags savedflags = vp.camera->renderflags;
|
||||
CreateScene();
|
||||
vp.camera->renderflags = savedflags;
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateScene(di);
|
||||
CreateScene();
|
||||
}
|
||||
|
||||
RenderScene(di, recursion);
|
||||
RenderScene(recursion);
|
||||
|
||||
if (applySSAO && gl_RenderState.GetPassType() == GBUFFER_PASS)
|
||||
{
|
||||
gl_RenderState.EnableDrawBuffers(1);
|
||||
GLRenderer->AmbientOccludeScene();
|
||||
GLRenderer->AmbientOccludeScene(VPUniforms.mProjectionMatrix.get()[5]);
|
||||
GLRenderer->mBuffers->BindSceneFB(true);
|
||||
gl_RenderState.EnableDrawBuffers(gl_RenderState.GetPassDrawBufferCount());
|
||||
gl_RenderState.Apply();
|
||||
gl_RenderState.ApplyMatrices();
|
||||
ApplyVPUniforms();
|
||||
}
|
||||
|
||||
// Handle all portals after rendering the opaque objects but before
|
||||
// doing all translucent stuff
|
||||
recursion++;
|
||||
GLPortal::EndFrame(di);
|
||||
GLRenderer->mPortalState.EndFrame(this);
|
||||
recursion--;
|
||||
RenderTranslucent(di);
|
||||
RenderTranslucent();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -470,7 +353,7 @@ void GLSceneDrawer::DrawScene(FDrawInfo *di, int drawmode)
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
void GLSceneDrawer::EndDrawScene(FDrawInfo *di, sector_t * viewsector)
|
||||
void FDrawInfo::EndDrawScene(sector_t * viewsector)
|
||||
{
|
||||
gl_RenderState.EnableFog(false);
|
||||
|
||||
|
|
@ -480,12 +363,11 @@ void GLSceneDrawer::EndDrawScene(FDrawInfo *di, sector_t * viewsector)
|
|||
{
|
||||
// [BB] The HUD model should be drawn over everything else already drawn.
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
di->DrawPlayerSprites(true);
|
||||
DrawPlayerSprites(true);
|
||||
}
|
||||
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
|
||||
Reset3DViewport();
|
||||
glViewport(screen->mScreenViewport.left, screen->mScreenViewport.top, screen->mScreenViewport.width, screen->mScreenViewport.height);
|
||||
|
||||
// Restore standard rendering state
|
||||
gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
|
@ -494,19 +376,19 @@ void GLSceneDrawer::EndDrawScene(FDrawInfo *di, sector_t * viewsector)
|
|||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
void GLSceneDrawer::DrawEndScene2D(FDrawInfo *di, sector_t * viewsector)
|
||||
void FDrawInfo::DrawEndScene2D(sector_t * viewsector)
|
||||
{
|
||||
const bool renderHUDModel = IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player);
|
||||
auto vrmode = VRMode::GetVRMode(true);
|
||||
|
||||
// This should be removed once all 2D stuff is really done through the 2D interface.
|
||||
gl_RenderState.mViewMatrix.loadIdentity();
|
||||
gl_RenderState.mProjectionMatrix.ortho(0, screen->GetWidth(), screen->GetHeight(), 0, -1.0f, 1.0f);
|
||||
gl_RenderState.ApplyMatrices();
|
||||
VPUniforms.mViewMatrix.loadIdentity();
|
||||
VPUniforms.mProjectionMatrix = vrmode->GetHUDSpriteProjection();
|
||||
ApplyVPUniforms();
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_MULTISAMPLE);
|
||||
|
||||
|
||||
di->DrawPlayerSprites(false);
|
||||
DrawPlayerSprites(false);
|
||||
|
||||
gl_RenderState.SetSoftLightLevel(-1);
|
||||
|
||||
|
|
@ -523,152 +405,99 @@ void GLSceneDrawer::DrawEndScene2D(FDrawInfo *di, sector_t * viewsector)
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GLSceneDrawer::ProcessScene(FDrawInfo *di, bool toscreen)
|
||||
void FDrawInfo::ProcessScene(bool toscreen)
|
||||
{
|
||||
iter_dlightf = iter_dlight = draw_dlight = draw_dlightf = 0;
|
||||
GLPortal::BeginScene();
|
||||
GLRenderer->mPortalState.BeginScene();
|
||||
|
||||
int mapsection = R_PointInSubsector(r_viewpoint.Pos)->mapsection;
|
||||
di->CurrentMapSections.Set(mapsection);
|
||||
GLRenderer->mCurrentPortal = nullptr;
|
||||
DrawScene(di, toscreen ? DM_MAINVIEW : DM_OFFSCREEN);
|
||||
int mapsection = R_PointInSubsector(Viewpoint.Pos)->mapsection;
|
||||
CurrentMapSections.Set(mapsection);
|
||||
DrawScene(toscreen ? DM_MAINVIEW : DM_OFFSCREEN);
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// sets 3D viewport and initial state
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FGLRenderer::Set3DViewport(bool mainview)
|
||||
{
|
||||
if (mainview && buffersActive)
|
||||
{
|
||||
bool useSSAO = (gl_ssao != 0);
|
||||
mBuffers->BindSceneFB(useSSAO);
|
||||
gl_RenderState.SetPassType(useSSAO ? GBUFFER_PASS : NORMAL_PASS);
|
||||
gl_RenderState.EnableDrawBuffers(gl_RenderState.GetPassDrawBufferCount());
|
||||
gl_RenderState.Apply();
|
||||
}
|
||||
|
||||
// Always clear all buffers with scissor test disabled.
|
||||
// This is faster on newer hardware because it allows the GPU to skip
|
||||
// reading from slower memory where the full buffers are stored.
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glClearColor(mSceneClearColor[0], mSceneClearColor[1], mSceneClearColor[2], 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
const auto &bounds = screen->mSceneViewport;
|
||||
glViewport(bounds.left, bounds.top, bounds.width, bounds.height);
|
||||
glScissor(bounds.left, bounds.top, bounds.width, bounds.height);
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
glStencilFunc(GL_ALWAYS,0,~0); // default stencil
|
||||
glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Renders one viewpoint in a scene
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
sector_t * GLSceneDrawer::RenderViewpoint (AActor * camera, IntRect * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen)
|
||||
{
|
||||
sector_t * lviewsector;
|
||||
GLRenderer->mSceneClearColor[0] = 0.0f;
|
||||
GLRenderer->mSceneClearColor[1] = 0.0f;
|
||||
GLRenderer->mSceneClearColor[2] = 0.0f;
|
||||
R_SetupFrame (r_viewpoint, r_viewwindow, camera);
|
||||
sector_t * FGLRenderer::RenderViewpoint (FRenderViewpoint &mainvp, AActor * camera, IntRect * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen)
|
||||
{
|
||||
R_SetupFrame (mainvp, r_viewwindow, camera);
|
||||
|
||||
GLRenderer->mGlobVis = R_GetGlobVis(r_viewwindow, r_visibility);
|
||||
|
||||
// We have to scale the pitch to account for the pixel stretching, because the playsim doesn't know about this and treats it as 1:1.
|
||||
double radPitch = r_viewpoint.Angles.Pitch.Normalized180().Radians();
|
||||
double angx = cos(radPitch);
|
||||
double angy = sin(radPitch) * level.info->pixelstretch;
|
||||
double alen = sqrt(angx*angx + angy*angy);
|
||||
|
||||
GLRenderer->mAngles.Pitch = (float)RAD2DEG(asin(angy / alen));
|
||||
GLRenderer->mAngles.Roll.Degrees = r_viewpoint.Angles.Roll.Degrees;
|
||||
|
||||
if (camera->player && camera->player-players==consoleplayer &&
|
||||
((camera->player->cheats & CF_CHASECAM) || (r_deathcamera && camera->health <= 0)) && camera==camera->player->mo)
|
||||
// Render (potentially) multiple views for stereo 3d
|
||||
// Fixme. The view offsetting should be done with a static table and not require setup of the entire render state for the mode.
|
||||
auto vrmode = VRMode::GetVRMode(mainview && toscreen);
|
||||
for (int eye_ix = 0; eye_ix < vrmode->mEyeCount; ++eye_ix)
|
||||
{
|
||||
GLRenderer->mViewActor=NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
GLRenderer->mViewActor=camera;
|
||||
}
|
||||
|
||||
// 'viewsector' will not survive the rendering so it cannot be used anymore below.
|
||||
lviewsector = r_viewpoint.sector;
|
||||
|
||||
// Render (potentially) multiple views for stereo 3d
|
||||
float viewShift[3];
|
||||
const s3d::Stereo3DMode& stereo3dMode = mainview && toscreen? s3d::Stereo3DMode::getCurrentMode() : s3d::Stereo3DMode::getMonoMode();
|
||||
stereo3dMode.SetUp();
|
||||
for (int eye_ix = 0; eye_ix < stereo3dMode.eye_count(); ++eye_ix)
|
||||
{
|
||||
const s3d::EyePose * eye = stereo3dMode.getEyePose(eye_ix);
|
||||
eye->SetUp();
|
||||
const auto &eye = vrmode->mEyes[eye_ix];
|
||||
screen->SetViewportRects(bounds);
|
||||
Set3DViewport(mainview);
|
||||
GLRenderer->mDrawingScene2D = true;
|
||||
GLRenderer->mCurrentFoV = fov;
|
||||
|
||||
FDrawInfo *di = FDrawInfo::StartDrawInfo(this);
|
||||
FDrawInfo *di = FDrawInfo::StartDrawInfo(mainvp, nullptr);
|
||||
auto &vp = di->Viewpoint;
|
||||
di->SetViewArea();
|
||||
auto cm = di->SetFullbrightFlags(mainview ? r_viewpoint.camera->player : nullptr);
|
||||
auto cm = di->SetFullbrightFlags(mainview ? vp.camera->player : nullptr);
|
||||
di->Viewpoint.FieldOfView = fov; // Set the real FOV for the current scene (it's not necessarily the same as the global setting in r_viewpoint)
|
||||
|
||||
// Stereo mode specific perspective projection
|
||||
SetProjection( eye->GetProjection(fov, ratio, fovratio) );
|
||||
// SetProjection(fov, ratio, fovratio); // switch to perspective mode and set up clipper
|
||||
SetViewAngle(r_viewpoint.Angles.Yaw);
|
||||
// Stereo mode specific viewpoint adjustment - temporarily shifts global ViewPos
|
||||
eye->GetViewShift(GLRenderer->mAngles.Yaw.Degrees, viewShift);
|
||||
ScopedViewShifter viewShifter(r_viewpoint.Pos, viewShift);
|
||||
SetViewMatrix(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z, false, false);
|
||||
gl_RenderState.ApplyMatrices();
|
||||
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);
|
||||
|
||||
ProcessScene(di, toscreen);
|
||||
|
||||
di->ProcessScene(toscreen);
|
||||
|
||||
if (mainview)
|
||||
{
|
||||
if (toscreen) EndDrawScene(di, lviewsector); // do not call this for camera textures.
|
||||
GLRenderer->PostProcessScene(cm, [&]() { DrawEndScene2D(di, lviewsector); });
|
||||
|
||||
// This should be done after postprocessing, not before.
|
||||
GLRenderer->mBuffers->BindCurrentFB();
|
||||
glViewport(screen->mScreenViewport.left, screen->mScreenViewport.top, screen->mScreenViewport.width, screen->mScreenViewport.height);
|
||||
|
||||
if (!toscreen)
|
||||
{
|
||||
gl_RenderState.mViewMatrix.loadIdentity();
|
||||
gl_RenderState.mProjectionMatrix.ortho(screen->mScreenViewport.left, screen->mScreenViewport.width, screen->mScreenViewport.height, screen->mScreenViewport.top, -1.0f, 1.0f);
|
||||
gl_RenderState.ApplyMatrices();
|
||||
}
|
||||
if (toscreen) di->EndDrawScene(mainvp.sector); // do not call this for camera textures.
|
||||
PostProcessScene(cm, [&]() { di->DrawEndScene2D(mainvp.sector); });
|
||||
}
|
||||
FDrawInfo::EndDrawInfo();
|
||||
GLRenderer->mDrawingScene2D = false;
|
||||
if (!stereo3dMode.IsMono())
|
||||
GLRenderer->mBuffers->BlitToEyeTexture(eye_ix);
|
||||
eye->TearDown();
|
||||
di->EndDrawInfo();
|
||||
if (vrmode->mEyeCount > 1)
|
||||
mBuffers->BlitToEyeTexture(eye_ix);
|
||||
}
|
||||
stereo3dMode.TearDown();
|
||||
|
||||
interpolator.RestoreInterpolations ();
|
||||
return lviewsector;
|
||||
return mainvp.sector;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Render the view to a savegame picture
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void GLSceneDrawer::WriteSavePic (player_t *player, FileWriter *file, int width, int height)
|
||||
{
|
||||
IntRect bounds;
|
||||
bounds.left = 0;
|
||||
bounds.top = 0;
|
||||
bounds.width = width;
|
||||
bounds.height = height;
|
||||
|
||||
// if GLRenderer->mVBO is persistently mapped we must be sure the GPU finished reading from it before we fill it with new data.
|
||||
glFinish();
|
||||
|
||||
// Switch to render buffers dimensioned for the savepic
|
||||
GLRenderer->mBuffers = GLRenderer->mSaveBuffers;
|
||||
|
||||
P_FindParticleSubsectors(); // make sure that all recently spawned particles have a valid subsector.
|
||||
gl_RenderState.SetVertexBuffer(GLRenderer->mVBO);
|
||||
GLRenderer->mVBO->Reset();
|
||||
GLRenderer->mLights->Clear();
|
||||
|
||||
sector_t *viewsector = RenderViewpoint(players[consoleplayer].camera, &bounds, r_viewpoint.FieldOfView.Degrees, 1.6f, 1.6f, true, false);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
gl_RenderState.SetSoftLightLevel(-1);
|
||||
GLRenderer->CopyToBackbuffer(&bounds, false);
|
||||
|
||||
// strictly speaking not needed as the glReadPixels should block until the scene is rendered, but this is to safeguard against shitty drivers
|
||||
glFinish();
|
||||
|
||||
uint8_t * scr = (uint8_t *)M_Malloc(width * height * 3);
|
||||
glReadPixels(0,0,width, height,GL_RGB,GL_UNSIGNED_BYTE,scr);
|
||||
M_CreatePNG (file, scr + ((height-1) * width * 3), NULL, SS_RGB, width, height, -width * 3, Gamma);
|
||||
M_Free(scr);
|
||||
|
||||
// Switch back the screen render buffers
|
||||
screen->SetViewportRects(nullptr);
|
||||
GLRenderer->mBuffers = GLRenderer->mScreenBuffers;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,47 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "r_defs.h"
|
||||
#include "m_fixed.h"
|
||||
#include "hwrenderer/scene/hw_clipper.h"
|
||||
#include "gl_portal.h"
|
||||
#include "gl/renderer/gl_lightdata.h"
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "r_utility.h"
|
||||
#include "c_cvars.h"
|
||||
|
||||
struct HUDSprite;
|
||||
|
||||
class GLSceneDrawer
|
||||
{
|
||||
TMap<DPSprite*, int> weapondynlightindex;
|
||||
|
||||
void RenderMultipassStuff(FDrawInfo *di);
|
||||
|
||||
void RenderScene(FDrawInfo *di, int recursion);
|
||||
void RenderTranslucent(FDrawInfo *di);
|
||||
|
||||
void CreateScene(FDrawInfo *di);
|
||||
|
||||
public:
|
||||
GLSceneDrawer()
|
||||
{
|
||||
GLPortal::drawer = this;
|
||||
}
|
||||
|
||||
angle_t FrustumAngle();
|
||||
|
||||
void SetViewMatrix(float vx, float vy, float vz, bool mirror, bool planemirror);
|
||||
void SetupView(float vx, float vy, float vz, DAngle va, bool mirror, bool planemirror);
|
||||
void SetViewAngle(DAngle viewangle);
|
||||
void SetProjection(VSMatrix matrix);
|
||||
void Set3DViewport(bool mainview);
|
||||
void Reset3DViewport();
|
||||
void DrawScene(FDrawInfo *di, int drawmode);
|
||||
void ProcessScene(FDrawInfo *di, bool toscreen = false);
|
||||
void EndDrawScene(FDrawInfo *di, sector_t * viewsector);
|
||||
void DrawEndScene2D(FDrawInfo *di, sector_t * viewsector);
|
||||
|
||||
sector_t *RenderViewpoint(AActor * camera, IntRect * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen);
|
||||
sector_t *RenderView(player_t *player);
|
||||
void WriteSavePic(player_t *player, FileWriter *file, int width, int height);
|
||||
};
|
||||
|
|
@ -32,9 +32,10 @@
|
|||
#include "gl_load/gl_interface.h"
|
||||
#include "gl/data/gl_vertexbuffer.h"
|
||||
#include "gl/renderer/gl_lightdata.h"
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/renderer/gl_renderstate.h"
|
||||
#include "gl/scene/gl_drawinfo.h"
|
||||
#include "gl/scene/gl_scenedrawer.h"
|
||||
#include "gl/scene/gl_portal.h"
|
||||
#include "gl/shaders/gl_shader.h"
|
||||
|
||||
|
||||
|
|
@ -209,9 +210,10 @@ static void RenderBox(FTextureID texno, FMaterial * gltex, float x_offset, bool
|
|||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void GLSkyPortal::DrawContents(FDrawInfo *di)
|
||||
void GLSkyPortal::DrawContents(HWDrawInfo *di)
|
||||
{
|
||||
bool drawBoth = false;
|
||||
auto &vp = di->Viewpoint;
|
||||
|
||||
// We have no use for Doom lighting special handling here, so disable it for this function.
|
||||
int oldlightmode = ::level.lightmode;
|
||||
|
|
@ -228,8 +230,7 @@ void GLSkyPortal::DrawContents(FDrawInfo *di)
|
|||
gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
bool oldClamp = gl_RenderState.SetDepthClamp(true);
|
||||
|
||||
gl_MatrixStack.Push(gl_RenderState.mViewMatrix);
|
||||
drawer->SetupView(0, 0, 0, r_viewpoint.Angles.Yaw, !!(MirrorFlag & 1), !!(PlaneMirrorFlag & 1));
|
||||
di->SetupView(0, 0, 0, !!(mState->MirrorFlag & 1), !!(mState->PlaneMirrorFlag & 1));
|
||||
|
||||
gl_RenderState.SetVertexBuffer(GLRenderer->mSkyVBO);
|
||||
if (origin->texture[0] && origin->texture[0]->tex->bSkybox)
|
||||
|
|
@ -268,8 +269,7 @@ void GLSkyPortal::DrawContents(FDrawInfo *di)
|
|||
}
|
||||
}
|
||||
gl_RenderState.SetVertexBuffer(GLRenderer->mVBO);
|
||||
gl_MatrixStack.Pop(gl_RenderState.mViewMatrix);
|
||||
gl_RenderState.ApplyMatrices();
|
||||
di->ApplyVPUniforms();
|
||||
::level.lightmode = oldlightmode;
|
||||
gl_RenderState.SetDepthClamp(oldClamp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@
|
|||
#include "gl/renderer/gl_renderstate.h"
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/scene/gl_drawinfo.h"
|
||||
#include "gl/scene/gl_scenedrawer.h"
|
||||
#include "gl/models/gl_models.h"
|
||||
#include "gl/renderer/gl_quaddrawer.h"
|
||||
#include "gl/dynlights/gl_lightbuffer.h"
|
||||
|
|
@ -79,6 +78,7 @@ void FDrawInfo::DrawSprite(GLSprite *sprite, int pass)
|
|||
bool additivefog = false;
|
||||
bool foglayer = false;
|
||||
int rel = sprite->fullbright? 0 : getExtraLight();
|
||||
auto &vp = Viewpoint;
|
||||
|
||||
if (pass==GLPASS_TRANSLUCENT)
|
||||
{
|
||||
|
|
@ -112,7 +112,7 @@ void FDrawInfo::DrawSprite(GLSprite *sprite, int pass)
|
|||
// fog + fuzz don't work well without some fiddling with the alpha value!
|
||||
if (!sprite->Colormap.FadeColor.isBlack())
|
||||
{
|
||||
float dist=Dist2(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, sprite->x, sprite->y);
|
||||
float dist=Dist2(vp.Pos.X, vp.Pos.Y, sprite->x, sprite->y);
|
||||
int fogd = hw_GetFogDensity(sprite->lightlevel, sprite->Colormap.FadeColor, sprite->Colormap.FogDensity);
|
||||
|
||||
// this value was determined by trial and error and is scale dependent!
|
||||
|
|
@ -221,7 +221,7 @@ void FDrawInfo::DrawSprite(GLSprite *sprite, int pass)
|
|||
secplane_t *lowplane = i == (*lightlist).Size() - 1 ? &bottomp : &(*lightlist)[i + 1].plane;
|
||||
|
||||
int thislight = (*lightlist)[i].caster != nullptr ? hw_ClampLight(*(*lightlist)[i].p_lightlevel) : sprite->lightlevel;
|
||||
int thisll = sprite->actor == nullptr? thislight : (uint8_t)sprite->actor->Sector->CheckSpriteGlow(thislight, sprite->actor->InterpolatedPosition(r_viewpoint.TicFrac));
|
||||
int thisll = sprite->actor == nullptr? thislight : (uint8_t)sprite->actor->Sector->CheckSpriteGlow(thislight, sprite->actor->InterpolatedPosition(vp.TicFrac));
|
||||
|
||||
FColormap thiscm;
|
||||
thiscm.CopyFog(sprite->Colormap);
|
||||
|
|
@ -249,7 +249,8 @@ void FDrawInfo::DrawSprite(GLSprite *sprite, int pass)
|
|||
|
||||
FVector3 v[4];
|
||||
gl_RenderState.SetNormal(0, 0, 0);
|
||||
if (sprite->CalculateVertices(this, v))
|
||||
|
||||
if (sprite->CalculateVertices(this, v, &vp.Pos))
|
||||
{
|
||||
glEnable(GL_POLYGON_OFFSET_FILL);
|
||||
glPolygonOffset(-1.0f, -128.0f);
|
||||
|
|
@ -276,7 +277,8 @@ void FDrawInfo::DrawSprite(GLSprite *sprite, int pass)
|
|||
}
|
||||
else
|
||||
{
|
||||
gl_RenderModel(sprite, sprite->dynlightindex);
|
||||
FGLModelRenderer renderer(this, sprite->dynlightindex);
|
||||
renderer.RenderModel(sprite->x, sprite->y, sprite->z, sprite->modelframe, sprite->actor, vp.TicFrac);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@
|
|||
#include "gl/dynlights/gl_lightbuffer.h"
|
||||
#include "gl/scene/gl_drawinfo.h"
|
||||
#include "gl/scene/gl_portal.h"
|
||||
#include "gl/scene/gl_scenedrawer.h"
|
||||
|
||||
EXTERN_CVAR(Bool, gl_seamless)
|
||||
|
||||
|
|
@ -94,7 +93,6 @@ void FDrawInfo::RenderMirrorSurface(GLWall *wall)
|
|||
|
||||
// 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.
|
||||
gl_RenderState.EnableTextureMatrix(true);
|
||||
gl_RenderState.mTextureMatrix.computeNormalMatrix(gl_RenderState.mViewMatrix);
|
||||
|
||||
// Use sphere mapping for this
|
||||
gl_RenderState.SetEffect(EFF_SPHEREMAP);
|
||||
|
|
@ -339,7 +337,8 @@ void FDrawInfo::AddMirrorSurface(GLWall *w)
|
|||
|
||||
void FDrawInfo::AddPortal(GLWall *wall, int ptype)
|
||||
{
|
||||
GLPortal * portal;
|
||||
auto &pstate = GLRenderer->mPortalState;
|
||||
IPortal * portal;
|
||||
|
||||
wall->MakeVertices(this, false);
|
||||
switch (ptype)
|
||||
|
|
@ -347,42 +346,63 @@ void FDrawInfo::AddPortal(GLWall *wall, int ptype)
|
|||
// portals don't go into the draw list.
|
||||
// Instead they are added to the portal manager
|
||||
case PORTALTYPE_HORIZON:
|
||||
wall->horizon = UniqueHorizons.Get(wall->horizon);
|
||||
portal = GLPortal::FindPortal(wall->horizon);
|
||||
if (!portal) portal = new GLHorizonPortal(wall->horizon);
|
||||
wall->horizon = pstate.UniqueHorizons.Get(wall->horizon);
|
||||
portal = FindPortal(wall->horizon);
|
||||
if (!portal)
|
||||
{
|
||||
portal = new GLHorizonPortal(&pstate, wall->horizon, Viewpoint);
|
||||
Portals.Push(portal);
|
||||
}
|
||||
portal->AddLine(wall);
|
||||
break;
|
||||
|
||||
case PORTALTYPE_SKYBOX:
|
||||
portal = GLPortal::FindPortal(wall->secportal);
|
||||
portal = FindPortal(wall->secportal);
|
||||
if (!portal)
|
||||
{
|
||||
// either a regular skybox or an Eternity-style horizon
|
||||
if (wall->secportal->mType != PORTS_SKYVIEWPOINT) portal = new GLEEHorizonPortal(wall->secportal);
|
||||
else portal = new GLSkyboxPortal(wall->secportal);
|
||||
if (wall->secportal->mType != PORTS_SKYVIEWPOINT) portal = new GLEEHorizonPortal(&pstate, wall->secportal);
|
||||
else
|
||||
{
|
||||
portal = new GLScenePortal(&pstate, new HWSkyboxPortal(wall->secportal));
|
||||
Portals.Push(portal);
|
||||
}
|
||||
}
|
||||
portal->AddLine(wall);
|
||||
break;
|
||||
|
||||
case PORTALTYPE_SECTORSTACK:
|
||||
portal = wall->portal->GetRenderState();
|
||||
portal = FindPortal(wall->portal);
|
||||
if (!portal)
|
||||
{
|
||||
portal = new GLScenePortal(&pstate, new HWSectorStackPortal(wall->portal));
|
||||
Portals.Push(portal);
|
||||
}
|
||||
portal->AddLine(wall);
|
||||
break;
|
||||
|
||||
case PORTALTYPE_PLANEMIRROR:
|
||||
if (GLPortal::PlaneMirrorMode * wall->planemirror->fC() <= 0)
|
||||
if (pstate.PlaneMirrorMode * wall->planemirror->fC() <= 0)
|
||||
{
|
||||
//@sync-portal
|
||||
wall->planemirror = UniquePlaneMirrors.Get(wall->planemirror);
|
||||
portal = GLPortal::FindPortal(wall->planemirror);
|
||||
if (!portal) portal = new GLPlaneMirrorPortal(wall->planemirror);
|
||||
wall->planemirror = pstate.UniquePlaneMirrors.Get(wall->planemirror);
|
||||
portal = FindPortal(wall->planemirror);
|
||||
if (!portal)
|
||||
{
|
||||
portal = new GLScenePortal(&pstate, new HWPlaneMirrorPortal(wall->planemirror));
|
||||
Portals.Push(portal);
|
||||
}
|
||||
portal->AddLine(wall);
|
||||
}
|
||||
break;
|
||||
|
||||
case PORTALTYPE_MIRROR:
|
||||
portal = GLPortal::FindPortal(wall->seg->linedef);
|
||||
if (!portal) portal = new GLMirrorPortal(wall->seg->linedef);
|
||||
portal = FindPortal(wall->seg->linedef);
|
||||
if (!portal)
|
||||
{
|
||||
portal = new GLScenePortal(&pstate, new HWMirrorPortal(wall->seg->linedef));
|
||||
Portals.Push(portal);
|
||||
}
|
||||
portal->AddLine(wall);
|
||||
if (gl_mirror_envmap)
|
||||
{
|
||||
|
|
@ -392,23 +412,28 @@ void FDrawInfo::AddPortal(GLWall *wall, int ptype)
|
|||
break;
|
||||
|
||||
case PORTALTYPE_LINETOLINE:
|
||||
portal = GLPortal::FindPortal(wall->lineportal);
|
||||
portal = FindPortal(wall->lineportal);
|
||||
if (!portal)
|
||||
{
|
||||
line_t *otherside = wall->lineportal->lines[0]->mDestination;
|
||||
if (otherside != NULL && otherside->portalindex < level.linePortals.Size())
|
||||
if (otherside != nullptr && otherside->portalindex < level.linePortals.Size())
|
||||
{
|
||||
ProcessActorsInPortal(otherside->getPortal()->mGroup, in_area);
|
||||
}
|
||||
portal = new GLLineToLinePortal(wall->lineportal);
|
||||
portal = new GLScenePortal(&pstate, new HWLineToLinePortal(wall->lineportal));
|
||||
Portals.Push(portal);
|
||||
}
|
||||
portal->AddLine(wall);
|
||||
break;
|
||||
|
||||
case PORTALTYPE_SKY:
|
||||
wall->sky = UniqueSkies.Get(wall->sky);
|
||||
portal = GLPortal::FindPortal(wall->sky);
|
||||
if (!portal) portal = new GLSkyPortal(wall->sky);
|
||||
wall->sky = pstate.UniqueSkies.Get(wall->sky);
|
||||
portal = FindPortal(wall->sky);
|
||||
if (!portal)
|
||||
{
|
||||
portal = new GLSkyPortal(&pstate, wall->sky);
|
||||
Portals.Push(portal);
|
||||
}
|
||||
portal->AddLine(wall);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,9 +37,7 @@
|
|||
#include "gl/renderer/gl_renderstate.h"
|
||||
#include "gl/data/gl_vertexbuffer.h"
|
||||
#include "gl/scene/gl_drawinfo.h"
|
||||
#include "gl/scene/gl_scenedrawer.h"
|
||||
#include "gl/models/gl_models.h"
|
||||
#include "gl/stereo3d/gl_stereo3d.h"
|
||||
#include "gl/dynlights/gl_lightbuffer.h"
|
||||
|
||||
//==========================================================================
|
||||
|
|
@ -66,7 +64,8 @@ void FDrawInfo::DrawPSprite (HUDSprite *huds)
|
|||
if (huds->mframe)
|
||||
{
|
||||
gl_RenderState.AlphaFunc(GL_GEQUAL, 0);
|
||||
gl_RenderHUDModel(huds->weapon, huds->mx, huds->my, huds->lightindex);
|
||||
FGLModelRenderer renderer(this, huds->lightindex);
|
||||
renderer.RenderHUDModel(huds->weapon, huds->mx, huds->my);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -91,8 +90,6 @@ void FDrawInfo::DrawPSprite (HUDSprite *huds)
|
|||
|
||||
void FDrawInfo::DrawPlayerSprites(bool hudModelStep)
|
||||
{
|
||||
s3d::Stereo3DMode::getCurrentMode().AdjustPlayerSprites();
|
||||
|
||||
int oldlightmode = level.lightmode;
|
||||
if (!hudModelStep && level.lightmode == 8) level.lightmode = 2; // Software lighting cannot handle 2D content so revert to lightmode 2 for that.
|
||||
for(auto &hudsprite : hudsprites)
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "cmdlib.h"
|
||||
#include "hwrenderer/utility/hw_shaderpatcher.h"
|
||||
#include "hwrenderer/data/shaderuniforms.h"
|
||||
#include "hwrenderer/scene/hw_viewpointuniforms.h"
|
||||
|
||||
#include "gl_load/gl_interface.h"
|
||||
#include "gl/system/gl_debug.h"
|
||||
|
|
@ -307,10 +308,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
|
|||
|
||||
muDesaturation.Init(hShader, "uDesaturationFactor");
|
||||
muFogEnabled.Init(hShader, "uFogEnabled");
|
||||
muPalLightLevels.Init(hShader, "uPalLightLevels");
|
||||
muGlobVis.Init(hShader, "uGlobVis");
|
||||
muTextureMode.Init(hShader, "uTextureMode");
|
||||
muCameraPos.Init(hShader, "uCameraPos");
|
||||
muLightParms.Init(hShader, "uLightAttr");
|
||||
muClipSplit.Init(hShader, "uClipSplit");
|
||||
muLightIndex.Init(hShader, "uLightIndex");
|
||||
|
|
@ -324,13 +322,9 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
|
|||
muGlowTopPlane.Init(hShader, "uGlowTopPlane");
|
||||
muSplitBottomPlane.Init(hShader, "uSplitBottomPlane");
|
||||
muSplitTopPlane.Init(hShader, "uSplitTopPlane");
|
||||
muClipLine.Init(hShader, "uClipLine");
|
||||
muInterpolationFactor.Init(hShader, "uInterpolationFactor");
|
||||
muClipHeight.Init(hShader, "uClipHeight");
|
||||
muClipHeightDirection.Init(hShader, "uClipHeightDirection");
|
||||
muAlphaThreshold.Init(hShader, "uAlphaThreshold");
|
||||
muSpecularMaterial.Init(hShader, "uSpecularMaterial");
|
||||
muViewHeight.Init(hShader, "uViewHeight");
|
||||
muTimer.Init(hShader, "timer");
|
||||
|
||||
lights_index = glGetUniformLocation(hShader, "lights");
|
||||
|
|
@ -344,6 +338,13 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
|
|||
normalviewmatrix_index = glGetUniformLocation(hShader, "NormalViewMatrix");
|
||||
normalmodelmatrix_index = glGetUniformLocation(hShader, "NormalModelMatrix");
|
||||
quadmode_index = glGetUniformLocation(hShader, "uQuadMode");
|
||||
viewheight_index = glGetUniformLocation(hShader, "uViewHeight");
|
||||
camerapos_index = glGetUniformLocation(hShader, "uCameraPos");
|
||||
pallightlevels_index = glGetUniformLocation(hShader, "uPalLightLevels");
|
||||
globvis_index = glGetUniformLocation(hShader, "uGlobVis");
|
||||
clipheight_index = glGetUniformLocation(hShader, "uClipHeight");
|
||||
clipheightdirection_index = glGetUniformLocation(hShader, "uClipHeightDirection");
|
||||
clipline_index = glGetUniformLocation(hShader, "uClipLine");
|
||||
|
||||
if (!(gl.flags & RFL_SHADER_STORAGE_BUFFER))
|
||||
{
|
||||
|
|
@ -434,12 +435,19 @@ FShader *FShaderCollection::Compile (const char *ShaderName, const char *ShaderP
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void FShader::ApplyMatrices(VSMatrix *proj, VSMatrix *view, VSMatrix *norm)
|
||||
void FShader::ApplyMatrices(HWViewpointUniforms *u)
|
||||
{
|
||||
Bind();
|
||||
glUniformMatrix4fv(projectionmatrix_index, 1, false, proj->get());
|
||||
glUniformMatrix4fv(viewmatrix_index, 1, false, view->get());
|
||||
glUniformMatrix4fv(normalviewmatrix_index, 1, false, norm->get());
|
||||
glUniformMatrix4fv(projectionmatrix_index, 1, false, u->mProjectionMatrix.get());
|
||||
glUniformMatrix4fv(viewmatrix_index, 1, false, u->mViewMatrix.get());
|
||||
glUniformMatrix4fv(normalviewmatrix_index, 1, false, u->mNormalViewMatrix.get());
|
||||
|
||||
glUniform4fv(camerapos_index, 1, &u->mCameraPos[0]);
|
||||
glUniform1i(viewheight_index, u->mViewHeight);
|
||||
glUniform1i(pallightlevels_index, u->mPalLightLevels);
|
||||
glUniform1f(globvis_index, u->mGlobVis);
|
||||
glUniform1f(clipheight_index, u->mClipHeight);
|
||||
glUniform1f(clipheightdirection_index, u->mClipHeightDirection);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
@ -539,10 +547,10 @@ FShader *FShaderManager::Get(unsigned int eff, bool alphateston, EPassType passT
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void FShaderManager::ApplyMatrices(VSMatrix *proj, VSMatrix *view, EPassType passType)
|
||||
void FShaderManager::ApplyMatrices(HWViewpointUniforms *u, EPassType passType)
|
||||
{
|
||||
if (passType < mPassShaders.Size())
|
||||
mPassShaders[passType]->ApplyMatrices(proj, view);
|
||||
mPassShaders[passType]->ApplyMatrices(u);
|
||||
|
||||
if (mActiveShader)
|
||||
mActiveShader->Bind();
|
||||
|
|
@ -687,28 +695,25 @@ FShader *FShaderCollection::BindEffect(int effect)
|
|||
//==========================================================================
|
||||
EXTERN_CVAR(Int, gl_fuzztype)
|
||||
|
||||
void FShaderCollection::ApplyMatrices(VSMatrix *proj, VSMatrix *view)
|
||||
void FShaderCollection::ApplyMatrices(HWViewpointUniforms *u)
|
||||
{
|
||||
VSMatrix norm;
|
||||
norm.computeNormalMatrix(*view);
|
||||
|
||||
for (int i = 0; i < SHADER_NoTexture; i++)
|
||||
{
|
||||
mMaterialShaders[i]->ApplyMatrices(proj, view, &norm);
|
||||
mMaterialShadersNAT[i]->ApplyMatrices(proj, view, &norm);
|
||||
mMaterialShaders[i]->ApplyMatrices(u);
|
||||
mMaterialShadersNAT[i]->ApplyMatrices(u);
|
||||
}
|
||||
mMaterialShaders[SHADER_NoTexture]->ApplyMatrices(proj, view, &norm);
|
||||
mMaterialShaders[SHADER_NoTexture]->ApplyMatrices(u);
|
||||
if (gl_fuzztype != 0)
|
||||
{
|
||||
mMaterialShaders[SHADER_NoTexture + gl_fuzztype]->ApplyMatrices(proj, view, &norm);
|
||||
mMaterialShaders[SHADER_NoTexture + gl_fuzztype]->ApplyMatrices(u);
|
||||
}
|
||||
for (unsigned i = FIRST_USER_SHADER; i < mMaterialShaders.Size(); i++)
|
||||
{
|
||||
mMaterialShaders[i]->ApplyMatrices(proj, view, &norm);
|
||||
mMaterialShaders[i]->ApplyMatrices(u);
|
||||
}
|
||||
for (int i = 0; i < MAX_EFFECTS; i++)
|
||||
{
|
||||
mEffectShaders[i]->ApplyMatrices(proj, view, &norm);
|
||||
mEffectShaders[i]->ApplyMatrices(u);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ enum
|
|||
};
|
||||
|
||||
class FShaderCollection;
|
||||
struct HWViewpointUniforms;
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
@ -242,10 +243,7 @@ class FShader
|
|||
|
||||
FBufferedUniform1f muDesaturation;
|
||||
FBufferedUniform1i muFogEnabled;
|
||||
FBufferedUniform1i muPalLightLevels;
|
||||
FBufferedUniform1f muGlobVis;
|
||||
FBufferedUniform1i muTextureMode;
|
||||
FBufferedUniform4f muCameraPos;
|
||||
FBufferedUniform4f muLightParms;
|
||||
FBufferedUniform2f muClipSplit;
|
||||
FBufferedUniform1i muLightIndex;
|
||||
|
|
@ -259,22 +257,27 @@ class FShader
|
|||
FUniform4f muGlowTopPlane;
|
||||
FUniform4f muSplitBottomPlane;
|
||||
FUniform4f muSplitTopPlane;
|
||||
FUniform4f muClipLine;
|
||||
FBufferedUniform1f muInterpolationFactor;
|
||||
FBufferedUniform1f muClipHeight;
|
||||
FBufferedUniform1f muClipHeightDirection;
|
||||
FBufferedUniform1f muAlphaThreshold;
|
||||
FBufferedUniform1i muViewHeight;
|
||||
FBufferedUniform2f muSpecularMaterial;
|
||||
FBufferedUniform1f muTimer;
|
||||
|
||||
int lights_index;
|
||||
int projectionmatrix_index;
|
||||
int viewmatrix_index;
|
||||
int normalviewmatrix_index;
|
||||
int modelmatrix_index;
|
||||
int normalmodelmatrix_index;
|
||||
int texturematrix_index;
|
||||
|
||||
int projectionmatrix_index;
|
||||
int viewmatrix_index;
|
||||
int normalviewmatrix_index;
|
||||
int viewheight_index;
|
||||
int camerapos_index;
|
||||
int pallightlevels_index;
|
||||
int globvis_index;
|
||||
int clipheight_index;
|
||||
int clipheightdirection_index;
|
||||
int clipline_index;
|
||||
|
||||
public:
|
||||
int vertexmatrix_index;
|
||||
int texcoordmatrix_index;
|
||||
|
|
@ -306,7 +309,7 @@ public:
|
|||
bool Bind();
|
||||
unsigned int GetHandle() const { return hShader; }
|
||||
|
||||
void ApplyMatrices(VSMatrix *proj, VSMatrix *view, VSMatrix *norm);
|
||||
void ApplyMatrices(HWViewpointUniforms *u);
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -326,7 +329,7 @@ public:
|
|||
|
||||
FShader *BindEffect(int effect, EPassType passType);
|
||||
FShader *Get(unsigned int eff, bool alphateston, EPassType passType);
|
||||
void ApplyMatrices(VSMatrix *proj, VSMatrix *view, EPassType passType);
|
||||
void ApplyMatrices(HWViewpointUniforms *u, EPassType passType);
|
||||
|
||||
private:
|
||||
FShader *mActiveShader = nullptr;
|
||||
|
|
@ -348,7 +351,7 @@ public:
|
|||
FShader *Compile(const char *ShaderName, const char *ShaderPath, const char *LightModePath, const char *shaderdefines, bool usediscard, EPassType passType);
|
||||
int Find(const char *mame);
|
||||
FShader *BindEffect(int effect);
|
||||
void ApplyMatrices(VSMatrix *proj, VSMatrix *view);
|
||||
void ApplyMatrices(HWViewpointUniforms *u);
|
||||
|
||||
FShader *Get(unsigned int eff, bool alphateston)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,84 +0,0 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2015 Christopher Bruns
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
/*
|
||||
** gl_anaglyph.cpp
|
||||
** Color mask based stereoscopic 3D modes for GZDoom
|
||||
**
|
||||
*/
|
||||
|
||||
#include "gl_anaglyph.h"
|
||||
#include "gl/renderer/gl_renderbuffers.h"
|
||||
|
||||
namespace s3d {
|
||||
|
||||
MaskAnaglyph::MaskAnaglyph(const ColorMask& leftColorMask, double ipdMeters)
|
||||
: leftEye(leftColorMask, ipdMeters), rightEye(leftColorMask.inverse(), ipdMeters)
|
||||
{
|
||||
eye_ptrs.Push(&leftEye);
|
||||
eye_ptrs.Push(&rightEye);
|
||||
}
|
||||
|
||||
void MaskAnaglyph::Present() const
|
||||
{
|
||||
GLRenderer->mBuffers->BindOutputFB();
|
||||
GLRenderer->ClearBorders();
|
||||
|
||||
gl_RenderState.SetColorMask(leftEye.GetColorMask().r, leftEye.GetColorMask().g, leftEye.GetColorMask().b, true);
|
||||
gl_RenderState.ApplyColorMask();
|
||||
GLRenderer->mBuffers->BindEyeTexture(0, 0);
|
||||
GLRenderer->DrawPresentTexture(screen->mOutputLetterbox, true);
|
||||
|
||||
gl_RenderState.SetColorMask(rightEye.GetColorMask().r, rightEye.GetColorMask().g, rightEye.GetColorMask().b, true);
|
||||
gl_RenderState.ApplyColorMask();
|
||||
GLRenderer->mBuffers->BindEyeTexture(1, 0);
|
||||
GLRenderer->DrawPresentTexture(screen->mOutputLetterbox, true);
|
||||
|
||||
gl_RenderState.ResetColorMask();
|
||||
gl_RenderState.ApplyColorMask();
|
||||
}
|
||||
|
||||
|
||||
/* static */
|
||||
const GreenMagenta& GreenMagenta::getInstance(float ipd)
|
||||
{
|
||||
static GreenMagenta instance(ipd);
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
/* static */
|
||||
const RedCyan& RedCyan::getInstance(float ipd)
|
||||
{
|
||||
static RedCyan instance(ipd);
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
/* static */
|
||||
const AmberBlue& AmberBlue::getInstance(float ipd)
|
||||
{
|
||||
static AmberBlue instance(ipd);
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
} /* namespace s3d */
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2015 Christopher Bruns
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
/*
|
||||
** gl_anaglyph.h
|
||||
** Color mask based stereoscopic 3D modes for GZDoom
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef GL_ANAGLYPH_H_
|
||||
#define GL_ANAGLYPH_H_
|
||||
|
||||
#include "gl_stereo3d.h"
|
||||
#include "gl_stereo_leftright.h"
|
||||
#include "gl_load/gl_system.h"
|
||||
#include "gl/renderer/gl_renderstate.h"
|
||||
|
||||
|
||||
namespace s3d {
|
||||
|
||||
|
||||
class ColorMask
|
||||
{
|
||||
public:
|
||||
ColorMask(bool r, bool g, bool b) : r(r), g(g), b(b) {}
|
||||
ColorMask inverse() const { return ColorMask(!r, !g, !b); }
|
||||
|
||||
bool r;
|
||||
bool g;
|
||||
bool b;
|
||||
};
|
||||
|
||||
|
||||
class AnaglyphLeftPose : public LeftEyePose
|
||||
{
|
||||
public:
|
||||
AnaglyphLeftPose(const ColorMask& colorMask, float ipd) : LeftEyePose(ipd), colorMask(colorMask) {}
|
||||
ColorMask GetColorMask() const { return colorMask; }
|
||||
|
||||
private:
|
||||
ColorMask colorMask;
|
||||
};
|
||||
|
||||
class AnaglyphRightPose : public RightEyePose
|
||||
{
|
||||
public:
|
||||
AnaglyphRightPose(const ColorMask& colorMask, float ipd) : RightEyePose(ipd), colorMask(colorMask) {}
|
||||
ColorMask GetColorMask() const { return colorMask; }
|
||||
|
||||
private:
|
||||
ColorMask colorMask;
|
||||
};
|
||||
|
||||
class MaskAnaglyph : public Stereo3DMode
|
||||
{
|
||||
public:
|
||||
MaskAnaglyph(const ColorMask& leftColorMask, double ipdMeters);
|
||||
void Present() const override;
|
||||
private:
|
||||
AnaglyphLeftPose leftEye;
|
||||
AnaglyphRightPose rightEye;
|
||||
};
|
||||
|
||||
|
||||
class RedCyan : public MaskAnaglyph
|
||||
{
|
||||
public:
|
||||
static const RedCyan& getInstance(float ipd);
|
||||
|
||||
RedCyan(float ipd) : MaskAnaglyph(ColorMask(true, false, false), ipd) {}
|
||||
};
|
||||
|
||||
class GreenMagenta : public MaskAnaglyph
|
||||
{
|
||||
public:
|
||||
static const GreenMagenta& getInstance(float ipd);
|
||||
|
||||
GreenMagenta(float ipd) : MaskAnaglyph(ColorMask(false, true, false), ipd) {}
|
||||
};
|
||||
|
||||
class AmberBlue : public MaskAnaglyph
|
||||
{
|
||||
public:
|
||||
static const AmberBlue& getInstance(float ipd);
|
||||
|
||||
AmberBlue(float ipd) : MaskAnaglyph(ColorMask(true, true, false), ipd) {}
|
||||
};
|
||||
|
||||
// TODO matrix anaglyph
|
||||
|
||||
|
||||
} /* namespace s3d */
|
||||
|
||||
|
||||
#endif /* GL_ANAGLYPH_H_ */
|
||||
|
|
@ -1,232 +0,0 @@
|
|||
/*
|
||||
** gl_interleaved3d.cpp
|
||||
** Interleaved image stereoscopic 3D modes for GZDoom
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2016 Christopher Bruns
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
**
|
||||
*/
|
||||
|
||||
#include "gl_interleaved3d.h"
|
||||
#include "gl/renderer/gl_renderbuffers.h"
|
||||
#include "gl/renderer/gl_postprocessstate.h"
|
||||
#include "gl/system/gl_framebuffer.h"
|
||||
#include "hwrenderer/postprocessing/hw_present3dRowshader.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "hardware.h"
|
||||
#endif // _WIN32
|
||||
|
||||
EXTERN_CVAR(Float, vid_saturation)
|
||||
EXTERN_CVAR(Float, vid_brightness)
|
||||
EXTERN_CVAR(Float, vid_contrast)
|
||||
EXTERN_CVAR(Int, gl_satformula)
|
||||
EXTERN_CVAR(Bool, fullscreen)
|
||||
EXTERN_CVAR(Int, win_x) // screen pixel position of left of display window
|
||||
EXTERN_CVAR(Int, win_y) // screen pixel position of top of display window
|
||||
|
||||
namespace s3d {
|
||||
|
||||
/* static */
|
||||
const CheckerInterleaved3D& CheckerInterleaved3D::getInstance(float ipd)
|
||||
{
|
||||
static CheckerInterleaved3D instance(ipd);
|
||||
return instance;
|
||||
}
|
||||
|
||||
/* static */
|
||||
const ColumnInterleaved3D& ColumnInterleaved3D::getInstance(float ipd)
|
||||
{
|
||||
static ColumnInterleaved3D instance(ipd);
|
||||
return instance;
|
||||
}
|
||||
|
||||
/* static */
|
||||
const RowInterleaved3D& RowInterleaved3D::getInstance(float ipd)
|
||||
{
|
||||
static RowInterleaved3D instance(ipd);
|
||||
return instance;
|
||||
}
|
||||
|
||||
static void prepareInterleavedPresent(FPresentShaderBase& shader)
|
||||
{
|
||||
GLRenderer->mBuffers->BindOutputFB();
|
||||
GLRenderer->ClearBorders();
|
||||
|
||||
|
||||
// Bind each eye texture, for composition in the shader
|
||||
GLRenderer->mBuffers->BindEyeTexture(0, 0);
|
||||
GLRenderer->mBuffers->BindEyeTexture(1, 1);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
const IntRect& box = screen->mOutputLetterbox;
|
||||
glViewport(box.left, box.top, box.width, box.height);
|
||||
|
||||
shader.Bind(NOQUEUE);
|
||||
|
||||
if ( GLRenderer->framebuffer->IsHWGammaActive() )
|
||||
{
|
||||
shader.Uniforms->InvGamma = 1.0f;
|
||||
shader.Uniforms->Contrast = 1.0f;
|
||||
shader.Uniforms->Brightness = 0.0f;
|
||||
shader.Uniforms->Saturation = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
shader.Uniforms->InvGamma = 1.0f / clamp<float>(Gamma, 0.1f, 4.f);
|
||||
shader.Uniforms->Contrast = clamp<float>(vid_contrast, 0.1f, 3.f);
|
||||
shader.Uniforms->Brightness = clamp<float>(vid_brightness, -0.8f, 0.8f);
|
||||
shader.Uniforms->Saturation = clamp<float>(vid_saturation, -15.0f, 15.0f);
|
||||
shader.Uniforms->GrayFormula = static_cast<int>(gl_satformula);
|
||||
}
|
||||
shader.Uniforms->Scale = {
|
||||
screen->mScreenViewport.width / (float)GLRenderer->mBuffers->GetWidth(),
|
||||
screen->mScreenViewport.height / (float)GLRenderer->mBuffers->GetHeight()
|
||||
};
|
||||
shader.Uniforms.Set();
|
||||
}
|
||||
|
||||
// fixme: I don't know how to get absolute window position on Mac and Linux
|
||||
// fixme: I don't know how to get window border decoration size anywhere
|
||||
// So for now I'll hard code the border effect on my test machine.
|
||||
// Workaround for others is to fuss with vr_swap_eyes CVAR until it looks right.
|
||||
// Presumably the top/left window border on my test machine has an odd number of pixels
|
||||
// in the horizontal direction, and an even number in the vertical direction.
|
||||
#define WINDOW_BORDER_HORIZONTAL_PARITY 1
|
||||
#define WINDOW_BORDER_VERTICAL_PARITY 0
|
||||
|
||||
void CheckerInterleaved3D::Present() const
|
||||
{
|
||||
FGLPostProcessState savedState;
|
||||
savedState.SaveTextureBindings(2);
|
||||
prepareInterleavedPresent(*GLRenderer->mPresent3dCheckerShader);
|
||||
|
||||
// Compute absolute offset from top of screen to top of current display window
|
||||
// because we need screen-relative, not window-relative, scan line parity
|
||||
int windowVOffset = 0;
|
||||
int windowHOffset = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
/* this needs to be done differently!
|
||||
if (!fullscreen) {
|
||||
I_SaveWindowedPos(); // update win_y CVAR
|
||||
windowHOffset = (win_x + WINDOW_BORDER_HORIZONTAL_PARITY) % 2;
|
||||
windowVOffset = (win_y + WINDOW_BORDER_VERTICAL_PARITY) % 2;
|
||||
}
|
||||
*/
|
||||
#endif // _WIN32
|
||||
|
||||
GLRenderer->mPresent3dCheckerShader->Uniforms->WindowPositionParity =
|
||||
(windowVOffset
|
||||
+ windowHOffset
|
||||
+ screen->mOutputLetterbox.height + 1 // +1 because of origin at bottom
|
||||
) % 2; // because we want the top pixel offset, but gl_FragCoord.y is the bottom pixel offset
|
||||
|
||||
GLRenderer->mPresent3dCheckerShader->Uniforms.Set();
|
||||
GLRenderer->RenderScreenQuad();
|
||||
}
|
||||
|
||||
void s3d::CheckerInterleaved3D::AdjustViewports() const
|
||||
{
|
||||
// decrease the total pixel count by 2, but keep the same aspect ratio
|
||||
const float sqrt2 = 1.41421356237f;
|
||||
// Change size of renderbuffer, and align to screen
|
||||
screen->mSceneViewport.height /= sqrt2;
|
||||
screen->mSceneViewport.top /= sqrt2;
|
||||
screen->mSceneViewport.width /= sqrt2;
|
||||
screen->mSceneViewport.left /= sqrt2;
|
||||
|
||||
screen->mScreenViewport.height /= sqrt2;
|
||||
screen->mScreenViewport.top /= sqrt2;
|
||||
screen->mScreenViewport.width /= sqrt2;
|
||||
screen->mScreenViewport.left /= sqrt2;
|
||||
}
|
||||
|
||||
void ColumnInterleaved3D::Present() const
|
||||
{
|
||||
FGLPostProcessState savedState;
|
||||
savedState.SaveTextureBindings(2);
|
||||
prepareInterleavedPresent(*GLRenderer->mPresent3dColumnShader);
|
||||
|
||||
// Compute absolute offset from top of screen to top of current display window
|
||||
// because we need screen-relative, not window-relative, scan line parity
|
||||
int windowHOffset = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
/* this needs to be done differently!
|
||||
if (!fullscreen) {
|
||||
I_SaveWindowedPos(); // update win_y CVAR
|
||||
windowHOffset = (win_x + WINDOW_BORDER_HORIZONTAL_PARITY) % 2;
|
||||
}
|
||||
*/
|
||||
#endif // _WIN32
|
||||
|
||||
GLRenderer->mPresent3dColumnShader->Uniforms->WindowPositionParity = windowHOffset;
|
||||
GLRenderer->mPresent3dColumnShader->Uniforms.Set();
|
||||
|
||||
GLRenderer->RenderScreenQuad();
|
||||
}
|
||||
|
||||
void RowInterleaved3D::Present() const
|
||||
{
|
||||
FGLPostProcessState savedState;
|
||||
savedState.SaveTextureBindings(2);
|
||||
prepareInterleavedPresent(*GLRenderer->mPresent3dRowShader);
|
||||
|
||||
// Compute absolute offset from top of screen to top of current display window
|
||||
// because we need screen-relative, not window-relative, scan line parity
|
||||
int windowVOffset = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
/* this needs to be done differently!
|
||||
if (! fullscreen) {
|
||||
I_SaveWindowedPos(); // update win_y CVAR
|
||||
windowVOffset = (win_y + WINDOW_BORDER_VERTICAL_PARITY) % 2;
|
||||
}
|
||||
*/
|
||||
#endif // _WIN32
|
||||
|
||||
GLRenderer->mPresent3dRowShader->Uniforms->WindowPositionParity =
|
||||
(windowVOffset
|
||||
+ screen->mOutputLetterbox.height + 1 // +1 because of origin at bottom
|
||||
) % 2;
|
||||
|
||||
GLRenderer->mPresent3dRowShader->Uniforms.Set();
|
||||
GLRenderer->RenderScreenQuad();
|
||||
}
|
||||
|
||||
|
||||
} /* namespace s3d */
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
** gl_interleaved3d.h
|
||||
** Interleaved stereoscopic 3D modes for GZDoom
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2016 Christopher Bruns
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef GL_INTERLEAVED3D_H_
|
||||
#define GL_INTERLEAVED3D_H_
|
||||
|
||||
#include "gl_stereo3d.h"
|
||||
#include "gl_stereo_leftright.h"
|
||||
#include "gl_sidebyside3d.h"
|
||||
#include "gl_load/gl_system.h"
|
||||
#include "gl/renderer/gl_renderstate.h"
|
||||
|
||||
namespace s3d {
|
||||
|
||||
class CheckerInterleaved3D : public SideBySideSquished
|
||||
{
|
||||
public:
|
||||
static const CheckerInterleaved3D& getInstance(float ipd);
|
||||
CheckerInterleaved3D(double ipdMeters) : SideBySideSquished(ipdMeters) {}
|
||||
void Present() const override;
|
||||
void AdjustViewports() const override;
|
||||
};
|
||||
|
||||
class ColumnInterleaved3D : public SideBySideSquished
|
||||
{
|
||||
public:
|
||||
static const ColumnInterleaved3D& getInstance(float ipd);
|
||||
ColumnInterleaved3D(double ipdMeters) : SideBySideSquished(ipdMeters) {}
|
||||
void Present() const override;
|
||||
};
|
||||
|
||||
class RowInterleaved3D : public TopBottom3D
|
||||
{
|
||||
public:
|
||||
static const RowInterleaved3D& getInstance(float ipd);
|
||||
RowInterleaved3D(double ipdMeters) : TopBottom3D(ipdMeters) {}
|
||||
void Present() const override;
|
||||
};
|
||||
|
||||
} /* namespace s3d */
|
||||
|
||||
|
||||
#endif /* GL_INTERLEAVED3D_H_ */
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2015 Christopher Bruns
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
/*
|
||||
** gl_quadstereo.cpp
|
||||
** Quad-buffered OpenGL stereoscopic 3D mode for GZDoom
|
||||
**
|
||||
*/
|
||||
|
||||
#include "gl_quadstereo.h"
|
||||
#include "gl/renderer/gl_renderbuffers.h"
|
||||
|
||||
namespace s3d {
|
||||
|
||||
QuadStereo::QuadStereo(double ipdMeters)
|
||||
: leftEye(ipdMeters), rightEye(ipdMeters)
|
||||
{
|
||||
// Check whether quad-buffered stereo is supported in the current context
|
||||
// We are assuming the OpenGL context is already current at this point,
|
||||
// i.e. this constructor is called "just in time".
|
||||
|
||||
// First initialize to mono-ish initial state
|
||||
bQuadStereoSupported = leftEye.bQuadStereoSupported = rightEye.bQuadStereoSupported = false;
|
||||
eye_ptrs.Push(&leftEye); // We ALWAYS want to show at least this one view...
|
||||
// We will possibly advance to true stereo mode in the Setup() method...
|
||||
}
|
||||
|
||||
// Sometimes the stereo render context is not ready immediately at start up
|
||||
/* private */
|
||||
void QuadStereo::checkInitialRenderContextState()
|
||||
{
|
||||
// Keep trying until we see at least one good OpenGL context to render to
|
||||
static bool bDecentContextWasFound = false;
|
||||
static int contextCheckCount = 0;
|
||||
if ( (! bDecentContextWasFound) && (contextCheckCount < 200) )
|
||||
{
|
||||
contextCheckCount += 1;
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); // This question is about the main screen display context
|
||||
GLboolean supportsStereo, supportsBuffered;
|
||||
glGetBooleanv(GL_DOUBLEBUFFER, &supportsBuffered);
|
||||
if (supportsBuffered) // Finally, a useful OpenGL context
|
||||
{
|
||||
// This block will be executed exactly ONCE during a game run
|
||||
bDecentContextWasFound = true; // now we can stop checking every frame...
|
||||
// Now check whether this context supports hardware stereo
|
||||
glGetBooleanv(GL_STEREO, &supportsStereo);
|
||||
bQuadStereoSupported = supportsStereo && supportsBuffered;
|
||||
leftEye.bQuadStereoSupported = bQuadStereoSupported;
|
||||
rightEye.bQuadStereoSupported = bQuadStereoSupported;
|
||||
if (bQuadStereoSupported)
|
||||
eye_ptrs.Push(&rightEye); // Use the other eye too, if we can do stereo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QuadStereo::Present() const
|
||||
{
|
||||
if (bQuadStereoSupported)
|
||||
{
|
||||
GLRenderer->mBuffers->BindOutputFB();
|
||||
|
||||
glDrawBuffer(GL_BACK_LEFT);
|
||||
GLRenderer->ClearBorders();
|
||||
GLRenderer->mBuffers->BindEyeTexture(0, 0);
|
||||
GLRenderer->DrawPresentTexture(screen->mOutputLetterbox, true);
|
||||
|
||||
glDrawBuffer(GL_BACK_RIGHT);
|
||||
GLRenderer->ClearBorders();
|
||||
GLRenderer->mBuffers->BindEyeTexture(1, 0);
|
||||
GLRenderer->DrawPresentTexture(screen->mOutputLetterbox, true);
|
||||
|
||||
glDrawBuffer(GL_BACK);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLRenderer->mBuffers->BindOutputFB();
|
||||
GLRenderer->ClearBorders();
|
||||
GLRenderer->mBuffers->BindEyeTexture(0, 0);
|
||||
GLRenderer->DrawPresentTexture(screen->mOutputLetterbox, true);
|
||||
}
|
||||
}
|
||||
|
||||
void QuadStereo::SetUp() const
|
||||
{
|
||||
Stereo3DMode::SetUp();
|
||||
// Maybe advance to true stereo mode (ONCE), after the stereo context is finally ready
|
||||
const_cast<QuadStereo*>(this)->checkInitialRenderContextState();
|
||||
}
|
||||
|
||||
/* static */
|
||||
const QuadStereo& QuadStereo::getInstance(float ipd)
|
||||
{
|
||||
static QuadStereo instance(ipd);
|
||||
return instance;
|
||||
}
|
||||
|
||||
} /* namespace s3d */
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2015 Christopher Bruns
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
/*
|
||||
** gl_quadstereo.h
|
||||
** Quad-buffered OpenGL stereoscopic 3D mode for GZDoom
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef GL_QUADSTEREO_H_
|
||||
#define GL_QUADSTEREO_H_
|
||||
|
||||
#include "gl_stereo3d.h"
|
||||
#include "gl_stereo_leftright.h"
|
||||
#include "gl_load/gl_system.h"
|
||||
|
||||
namespace s3d {
|
||||
|
||||
|
||||
class QuadStereoLeftPose : public LeftEyePose
|
||||
{
|
||||
public:
|
||||
QuadStereoLeftPose(float ipd) : LeftEyePose(ipd), bQuadStereoSupported(false) {}
|
||||
bool bQuadStereoSupported;
|
||||
};
|
||||
|
||||
class QuadStereoRightPose : public RightEyePose
|
||||
{
|
||||
public:
|
||||
QuadStereoRightPose(float ipd) : RightEyePose(ipd), bQuadStereoSupported(false){}
|
||||
bool bQuadStereoSupported;
|
||||
};
|
||||
|
||||
// To use Quad-buffered stereo mode with nvidia 3d vision glasses,
|
||||
// you must either:
|
||||
// A) be using a Quadro series video card, OR
|
||||
//
|
||||
// B) be using nvidia driver version 314.07 or later
|
||||
// AND have your monitor set to 120 Hz refresh rate
|
||||
// AND have gzdoom in true full screen mode
|
||||
class QuadStereo : public Stereo3DMode
|
||||
{
|
||||
public:
|
||||
QuadStereo(double ipdMeters);
|
||||
void Present() const override;
|
||||
void SetUp() const override;
|
||||
static const QuadStereo& getInstance(float ipd);
|
||||
private:
|
||||
QuadStereoLeftPose leftEye;
|
||||
QuadStereoRightPose rightEye;
|
||||
bool bQuadStereoSupported;
|
||||
void checkInitialRenderContextState();
|
||||
};
|
||||
|
||||
|
||||
} /* namespace s3d */
|
||||
|
||||
|
||||
#endif /* GL_QUADSTEREO_H_ */
|
||||
|
|
@ -1,149 +0,0 @@
|
|||
/*
|
||||
** gl_sidebyside3d.cpp
|
||||
** Mosaic image stereoscopic 3D modes for GZDoom
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2016 Christopher Bruns
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
**
|
||||
*/
|
||||
|
||||
#include "gl_sidebyside3d.h"
|
||||
#include "gl/renderer/gl_renderbuffers.h"
|
||||
|
||||
namespace s3d {
|
||||
|
||||
void SideBySideBase::Present() const
|
||||
{
|
||||
GLRenderer->mBuffers->BindOutputFB();
|
||||
GLRenderer->ClearBorders();
|
||||
|
||||
// Compute screen regions to use for left and right eye views
|
||||
int leftWidth = screen->mOutputLetterbox.width / 2;
|
||||
int rightWidth = screen->mOutputLetterbox.width - leftWidth;
|
||||
IntRect leftHalfScreen = screen->mOutputLetterbox;
|
||||
leftHalfScreen.width = leftWidth;
|
||||
IntRect rightHalfScreen = screen->mOutputLetterbox;
|
||||
rightHalfScreen.width = rightWidth;
|
||||
rightHalfScreen.left += leftWidth;
|
||||
|
||||
GLRenderer->mBuffers->BindEyeTexture(0, 0);
|
||||
GLRenderer->DrawPresentTexture(leftHalfScreen, true);
|
||||
|
||||
GLRenderer->mBuffers->BindEyeTexture(1, 0);
|
||||
GLRenderer->DrawPresentTexture(rightHalfScreen, true);
|
||||
}
|
||||
|
||||
// AdjustViewports() is called from within FLGRenderer::SetOutputViewport(...)
|
||||
void SideBySideBase::AdjustViewports() const
|
||||
{
|
||||
// Change size of renderbuffer, and align to screen
|
||||
screen->mSceneViewport.width /= 2;
|
||||
screen->mSceneViewport.left /= 2;
|
||||
screen->mScreenViewport.width /= 2;
|
||||
screen->mScreenViewport.left /= 2;
|
||||
}
|
||||
|
||||
/* static */
|
||||
const SideBySideSquished& SideBySideSquished::getInstance(float ipd)
|
||||
{
|
||||
static SideBySideSquished instance(ipd);
|
||||
return instance;
|
||||
}
|
||||
|
||||
SideBySideSquished::SideBySideSquished(double ipdMeters)
|
||||
: leftEye(ipdMeters), rightEye(ipdMeters)
|
||||
{
|
||||
eye_ptrs.Push(&leftEye);
|
||||
eye_ptrs.Push(&rightEye);
|
||||
}
|
||||
|
||||
/* static */
|
||||
const SideBySideFull& SideBySideFull::getInstance(float ipd)
|
||||
{
|
||||
static SideBySideFull instance(ipd);
|
||||
return instance;
|
||||
}
|
||||
|
||||
SideBySideFull::SideBySideFull(double ipdMeters)
|
||||
: leftEye(ipdMeters), rightEye(ipdMeters)
|
||||
{
|
||||
eye_ptrs.Push(&leftEye);
|
||||
eye_ptrs.Push(&rightEye);
|
||||
}
|
||||
|
||||
/* virtual */
|
||||
void SideBySideFull::AdjustPlayerSprites() const /* override */
|
||||
{
|
||||
// Show weapon at double width, so it would appear normal width after rescaling
|
||||
int w = screen->mScreenViewport.width;
|
||||
int h = screen->mScreenViewport.height;
|
||||
gl_RenderState.mProjectionMatrix.ortho(w/2, w + w/2, h, 0, -1.0f, 1.0f);
|
||||
gl_RenderState.ApplyMatrices();
|
||||
}
|
||||
|
||||
/* static */
|
||||
const TopBottom3D& TopBottom3D::getInstance(float ipd)
|
||||
{
|
||||
static TopBottom3D instance(ipd);
|
||||
return instance;
|
||||
}
|
||||
|
||||
void TopBottom3D::Present() const
|
||||
{
|
||||
GLRenderer->mBuffers->BindOutputFB();
|
||||
GLRenderer->ClearBorders();
|
||||
|
||||
// Compute screen regions to use for left and right eye views
|
||||
int topHeight = screen->mOutputLetterbox.height / 2;
|
||||
int bottomHeight = screen->mOutputLetterbox.height - topHeight;
|
||||
IntRect topHalfScreen = screen->mOutputLetterbox;
|
||||
topHalfScreen.height = topHeight;
|
||||
topHalfScreen.top = topHeight;
|
||||
IntRect bottomHalfScreen = screen->mOutputLetterbox;
|
||||
bottomHalfScreen.height = bottomHeight;
|
||||
bottomHalfScreen.top = 0;
|
||||
|
||||
GLRenderer->mBuffers->BindEyeTexture(0, 0);
|
||||
GLRenderer->DrawPresentTexture(topHalfScreen, true);
|
||||
|
||||
GLRenderer->mBuffers->BindEyeTexture(1, 0);
|
||||
GLRenderer->DrawPresentTexture(bottomHalfScreen, true);
|
||||
}
|
||||
|
||||
// AdjustViewports() is called from within FLGRenderer::SetOutputViewport(...)
|
||||
void TopBottom3D::AdjustViewports() const
|
||||
{
|
||||
// Change size of renderbuffer, and align to screen
|
||||
screen->mSceneViewport.height /= 2;
|
||||
screen->mSceneViewport.top /= 2;
|
||||
screen->mScreenViewport.height /= 2;
|
||||
screen->mScreenViewport.top /= 2;
|
||||
}
|
||||
|
||||
} /* namespace s3d */
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
/*
|
||||
** gl_sidebyside3d.h
|
||||
** Mosaic image stereoscopic 3D modes for GZDoom
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2016 Christopher Bruns
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef GL_SIDEBYSIDE3D_H_
|
||||
#define GL_SIDEBYSIDE3D_H_
|
||||
|
||||
#include "gl_stereo3d.h"
|
||||
#include "gl_stereo_leftright.h"
|
||||
#include "gl_load/gl_system.h"
|
||||
#include "gl/renderer/gl_renderstate.h"
|
||||
|
||||
|
||||
namespace s3d {
|
||||
|
||||
class SideBySideBase : public Stereo3DMode
|
||||
{
|
||||
public:
|
||||
void Present() const override;
|
||||
virtual void AdjustViewports() const override;
|
||||
};
|
||||
|
||||
class SideBySideSquished : public SideBySideBase
|
||||
{
|
||||
public:
|
||||
static const SideBySideSquished& getInstance(float ipd);
|
||||
SideBySideSquished(double ipdMeters);
|
||||
private:
|
||||
LeftEyePose leftEye;
|
||||
RightEyePose rightEye;
|
||||
};
|
||||
|
||||
class SBSFLeftEyePose : public LeftEyePose {
|
||||
public:
|
||||
SBSFLeftEyePose(double ipdMeters) : LeftEyePose(ipdMeters) {}
|
||||
virtual VSMatrix GetProjection(float fov, float aspectRatio, float fovRatio) const override {
|
||||
return LeftEyePose::GetProjection(fov, 0.5f * aspectRatio, fovRatio);
|
||||
}
|
||||
};
|
||||
|
||||
class SBSFRightEyePose : public RightEyePose {
|
||||
public:
|
||||
SBSFRightEyePose(double ipdMeters) : RightEyePose(ipdMeters) {}
|
||||
virtual VSMatrix GetProjection(float fov, float aspectRatio, float fovRatio) const override {
|
||||
return RightEyePose::GetProjection(fov, 0.5f * aspectRatio, fovRatio);
|
||||
}
|
||||
};
|
||||
|
||||
class SideBySideFull : public SideBySideBase
|
||||
{
|
||||
public:
|
||||
static const SideBySideFull& getInstance(float ipd);
|
||||
SideBySideFull(double ipdMeters);
|
||||
virtual void AdjustPlayerSprites() const override;
|
||||
private:
|
||||
SBSFLeftEyePose leftEye;
|
||||
SBSFRightEyePose rightEye;
|
||||
};
|
||||
|
||||
class TopBottom3D : public SideBySideSquished
|
||||
{
|
||||
public:
|
||||
static const TopBottom3D& getInstance(float ipd);
|
||||
TopBottom3D(double ipdMeters) : SideBySideSquished(ipdMeters) {}
|
||||
void Present() const override;
|
||||
virtual void AdjustViewports() const override;
|
||||
};
|
||||
|
||||
} /* namespace s3d */
|
||||
|
||||
|
||||
#endif /* GL_SIDEBYSIDE3D_H_ */
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2015 Christopher Bruns
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
/*
|
||||
** gl_stereo3d.cpp
|
||||
** Stereoscopic 3D API
|
||||
**
|
||||
*/
|
||||
|
||||
#include "gl_load/gl_system.h"
|
||||
#include "gl/stereo3d/gl_stereo3d.h"
|
||||
|
||||
namespace s3d {
|
||||
|
||||
|
||||
/* virtual */
|
||||
VSMatrix EyePose::GetProjection(float fov, float aspectRatio, float fovRatio) const
|
||||
{
|
||||
VSMatrix result;
|
||||
|
||||
// Lifted from gl_scene.cpp FGLRenderer::SetProjection()
|
||||
float fovy = (float)(2 * RAD2DEG(atan(tan(DEG2RAD(fov) / 2) / fovRatio)));
|
||||
result.perspective(fovy, aspectRatio, FGLRenderer::GetZNear(), FGLRenderer::GetZFar());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* virtual */
|
||||
Viewport EyePose::GetViewport(const Viewport& fullViewport) const
|
||||
{
|
||||
return fullViewport;
|
||||
}
|
||||
|
||||
|
||||
/* virtual */
|
||||
void EyePose::GetViewShift(float yaw, float outViewShift[3]) const
|
||||
{
|
||||
// pass-through for Mono view
|
||||
outViewShift[0] = 0;
|
||||
outViewShift[1] = 0;
|
||||
outViewShift[2] = 0;
|
||||
}
|
||||
|
||||
|
||||
Stereo3DMode::Stereo3DMode()
|
||||
{
|
||||
}
|
||||
|
||||
Stereo3DMode::~Stereo3DMode()
|
||||
{
|
||||
}
|
||||
|
||||
// Avoid static initialization order fiasco by declaring first Mode type (Mono) here in the
|
||||
// same source file as Stereo3DMode::getCurrentMode()
|
||||
// https://isocpp.org/wiki/faq/ctors#static-init-order
|
||||
|
||||
/* static */
|
||||
const MonoView& MonoView::getInstance()
|
||||
{
|
||||
static MonoView instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
} /* namespace s3d */
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2015 Christopher Bruns
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
/*
|
||||
** gl_stereo3d.h
|
||||
** Stereoscopic 3D API
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef GL_STEREO3D_H_
|
||||
#define GL_STEREO3D_H_
|
||||
|
||||
#include <cstring> // needed for memcpy on linux, which is needed by VSMatrix copy ctor
|
||||
#include "tarray.h"
|
||||
#include "r_data/matrix.h"
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
|
||||
|
||||
/* stereoscopic 3D API */
|
||||
namespace s3d {
|
||||
|
||||
|
||||
/* Subregion of current display window */
|
||||
class Viewport
|
||||
{
|
||||
public:
|
||||
int x, y;
|
||||
int width, height;
|
||||
};
|
||||
|
||||
|
||||
/* Viewpoint of one eye */
|
||||
class EyePose
|
||||
{
|
||||
public:
|
||||
EyePose() {}
|
||||
virtual ~EyePose() {}
|
||||
virtual VSMatrix GetProjection(float fov, float aspectRatio, float fovRatio) const;
|
||||
virtual Viewport GetViewport(const Viewport& fullViewport) const;
|
||||
virtual void GetViewShift(float yaw, float outViewShift[3]) const;
|
||||
virtual void SetUp() const {};
|
||||
virtual void TearDown() const {};
|
||||
};
|
||||
|
||||
|
||||
/* Base class for stereoscopic 3D rendering modes */
|
||||
class Stereo3DMode
|
||||
{
|
||||
public:
|
||||
/* static methods for managing the selected stereoscopic view state */
|
||||
static const Stereo3DMode& getCurrentMode();
|
||||
static const Stereo3DMode& getMonoMode();
|
||||
|
||||
Stereo3DMode();
|
||||
virtual ~Stereo3DMode();
|
||||
virtual int eye_count() const { return eye_ptrs.Size(); }
|
||||
virtual const EyePose * getEyePose(int ix) const { return eye_ptrs(ix); }
|
||||
|
||||
/* hooks for setup and cleanup operations for each stereo mode */
|
||||
virtual void SetUp() const {};
|
||||
virtual void TearDown() const {};
|
||||
|
||||
virtual bool IsMono() const { return false; }
|
||||
virtual void AdjustViewports() const {};
|
||||
virtual void AdjustPlayerSprites() const {};
|
||||
virtual void Present() const = 0;
|
||||
|
||||
protected:
|
||||
TArray<const EyePose *> eye_ptrs;
|
||||
|
||||
private:
|
||||
static Stereo3DMode const * currentStereo3DMode;
|
||||
static void setCurrentMode(const Stereo3DMode& mode);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Ordinary non-3D rendering
|
||||
*/
|
||||
class MonoView : public Stereo3DMode
|
||||
{
|
||||
public:
|
||||
static const MonoView& getInstance();
|
||||
|
||||
bool IsMono() const override { return true; }
|
||||
void Present() const override { }
|
||||
|
||||
protected:
|
||||
MonoView() { eye_ptrs.Push(¢ralEye); }
|
||||
EyePose centralEye;
|
||||
};
|
||||
|
||||
|
||||
} /* namespace st3d */
|
||||
|
||||
|
||||
#endif /* GL_STEREO3D_H_ */
|
||||
|
|
@ -1,127 +0,0 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2015 Christopher Bruns
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
/*
|
||||
** gl_stereo_cvars.cpp
|
||||
** Console variables related to stereoscopic 3D in GZDoom
|
||||
**
|
||||
*/
|
||||
|
||||
#include "gl/stereo3d/gl_stereo3d.h"
|
||||
#include "gl/stereo3d/gl_stereo_leftright.h"
|
||||
#include "gl/stereo3d/gl_anaglyph.h"
|
||||
#include "gl/stereo3d/gl_quadstereo.h"
|
||||
#include "gl/stereo3d/gl_sidebyside3d.h"
|
||||
#include "gl/stereo3d/gl_interleaved3d.h"
|
||||
#include "version.h"
|
||||
|
||||
// Set up 3D-specific console variables:
|
||||
CVAR(Int, vr_mode, 0, CVAR_GLOBALCONFIG)
|
||||
|
||||
// switch left and right eye views
|
||||
CVAR(Bool, vr_swap_eyes, false, CVAR_GLOBALCONFIG)
|
||||
|
||||
// intraocular distance in meters
|
||||
CVAR(Float, vr_ipd, 0.062f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // METERS
|
||||
|
||||
// distance between viewer and the display screen
|
||||
CVAR(Float, vr_screendist, 0.80f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // METERS
|
||||
|
||||
// default conversion between (vertical) DOOM units and meters
|
||||
CVAR(Float, vr_hunits_per_meter, 41.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // METERS
|
||||
|
||||
// Manage changing of 3D modes:
|
||||
namespace s3d {
|
||||
|
||||
// Initialize static member
|
||||
Stereo3DMode const * Stereo3DMode::currentStereo3DMode = 0; // "nullptr" not resolved on linux (presumably not C++11)
|
||||
|
||||
/* static */
|
||||
void Stereo3DMode::setCurrentMode(const Stereo3DMode& mode) {
|
||||
Stereo3DMode::currentStereo3DMode = &mode;
|
||||
}
|
||||
|
||||
/* static */
|
||||
const Stereo3DMode& Stereo3DMode::getCurrentMode()
|
||||
{
|
||||
// NOTE: Ensure that these vr_mode values correspond to the ones in wadsrc/static/menudef.z
|
||||
switch (vr_mode)
|
||||
{
|
||||
case 1:
|
||||
setCurrentMode(GreenMagenta::getInstance(vr_ipd));
|
||||
break;
|
||||
case 2:
|
||||
setCurrentMode(RedCyan::getInstance(vr_ipd));
|
||||
break;
|
||||
case 3:
|
||||
setCurrentMode(SideBySideFull::getInstance(vr_ipd));
|
||||
break;
|
||||
case 4:
|
||||
setCurrentMode(SideBySideSquished::getInstance(vr_ipd));
|
||||
break;
|
||||
case 5:
|
||||
setCurrentMode(LeftEyeView::getInstance(vr_ipd));
|
||||
break;
|
||||
case 6:
|
||||
setCurrentMode(RightEyeView::getInstance(vr_ipd));
|
||||
break;
|
||||
case 7:
|
||||
if (screen->enable_quadbuffered) {
|
||||
setCurrentMode(QuadStereo::getInstance(vr_ipd));
|
||||
}
|
||||
else {
|
||||
setCurrentMode(MonoView::getInstance());
|
||||
}
|
||||
break;
|
||||
// TODO: 8: Oculus Rift
|
||||
case 9:
|
||||
setCurrentMode(AmberBlue::getInstance(vr_ipd));
|
||||
break;
|
||||
// TODO: 10: HTC Vive/OpenVR
|
||||
case 11:
|
||||
setCurrentMode(TopBottom3D::getInstance(vr_ipd));
|
||||
break;
|
||||
case 12:
|
||||
setCurrentMode(RowInterleaved3D::getInstance(vr_ipd));
|
||||
break;
|
||||
case 13:
|
||||
setCurrentMode(ColumnInterleaved3D::getInstance(vr_ipd));
|
||||
break;
|
||||
case 14:
|
||||
setCurrentMode(CheckerInterleaved3D::getInstance(vr_ipd));
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
setCurrentMode(MonoView::getInstance());
|
||||
break;
|
||||
}
|
||||
return *currentStereo3DMode;
|
||||
}
|
||||
|
||||
const Stereo3DMode& Stereo3DMode::getMonoMode()
|
||||
{
|
||||
setCurrentMode(MonoView::getInstance());
|
||||
return *currentStereo3DMode;
|
||||
}
|
||||
|
||||
|
||||
} /* namespace s3d */
|
||||
|
||||
|
|
@ -1,116 +0,0 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2015 Christopher Bruns
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
/*
|
||||
** gl_stereo_leftright.cpp
|
||||
** Offsets for left and right eye views
|
||||
**
|
||||
*/
|
||||
|
||||
#include "gl_stereo_leftright.h"
|
||||
#include "vectors.h" // RAD2DEG
|
||||
#include "doomtype.h" // M_PI
|
||||
#include "hwrenderer/utility/hw_cvars.h"
|
||||
#include "gl_load/gl_system.h"
|
||||
#include "gl/renderer/gl_renderstate.h"
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/renderer/gl_renderbuffers.h"
|
||||
|
||||
EXTERN_CVAR(Float, vr_screendist)
|
||||
EXTERN_CVAR(Float, vr_hunits_per_meter)
|
||||
EXTERN_CVAR(Bool, vr_swap_eyes)
|
||||
|
||||
namespace s3d {
|
||||
|
||||
|
||||
/* virtual */
|
||||
VSMatrix ShiftedEyePose::GetProjection(float fov, float aspectRatio, float fovRatio) const
|
||||
{
|
||||
double zNear = 5.0;
|
||||
double zFar = 65536.0;
|
||||
|
||||
// For stereo 3D, use asymmetric frustum shift in projection matrix
|
||||
// Q: shouldn't shift vary with roll angle, at least for desktop display?
|
||||
// A: No. (lab) roll is not measured on desktop display (yet)
|
||||
double frustumShift = zNear * getShift() / vr_screendist; // meters cancel, leaving doom units
|
||||
// double frustumShift = 0; // Turning off shift for debugging
|
||||
double fH = zNear * tan(DEG2RAD(fov) / 2) / fovRatio;
|
||||
double fW = fH * aspectRatio;
|
||||
double left = -fW - frustumShift;
|
||||
double right = fW - frustumShift;
|
||||
double bottom = -fH;
|
||||
double top = fH;
|
||||
|
||||
VSMatrix result(1);
|
||||
result.frustum(left, right, bottom, top, zNear, zFar);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* virtual */
|
||||
void ShiftedEyePose::GetViewShift(float yaw, float outViewShift[3]) const
|
||||
{
|
||||
float dx = -cos(DEG2RAD(yaw)) * vr_hunits_per_meter * getShift();
|
||||
float dy = sin(DEG2RAD(yaw)) * vr_hunits_per_meter * getShift();
|
||||
outViewShift[0] = dx;
|
||||
outViewShift[1] = dy;
|
||||
outViewShift[2] = 0;
|
||||
}
|
||||
|
||||
float ShiftedEyePose::getShift() const
|
||||
{
|
||||
return vr_swap_eyes ? -shift : shift;
|
||||
}
|
||||
|
||||
/* static */
|
||||
const LeftEyeView& LeftEyeView::getInstance(float ipd)
|
||||
{
|
||||
static LeftEyeView instance(ipd);
|
||||
instance.setIpd(ipd);
|
||||
return instance;
|
||||
}
|
||||
|
||||
void LeftEyeView::Present() const
|
||||
{
|
||||
GLRenderer->mBuffers->BindOutputFB();
|
||||
GLRenderer->ClearBorders();
|
||||
GLRenderer->mBuffers->BindEyeTexture(0, 0);
|
||||
GLRenderer->DrawPresentTexture(screen->mOutputLetterbox, true);
|
||||
}
|
||||
|
||||
/* static */
|
||||
const RightEyeView& RightEyeView::getInstance(float ipd)
|
||||
{
|
||||
static RightEyeView instance(ipd);
|
||||
instance.setIpd(ipd);
|
||||
return instance;
|
||||
}
|
||||
|
||||
void RightEyeView::Present() const
|
||||
{
|
||||
GLRenderer->mBuffers->BindOutputFB();
|
||||
GLRenderer->ClearBorders();
|
||||
GLRenderer->mBuffers->BindEyeTexture(0, 0);
|
||||
GLRenderer->DrawPresentTexture(screen->mOutputLetterbox, true);
|
||||
}
|
||||
|
||||
|
||||
} /* namespace s3d */
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2015 Christopher Bruns
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
/*
|
||||
** gl_stereo_leftright.h
|
||||
** Offsets for left and right eye views
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef GL_STEREO_LEFTRIGHT_H_
|
||||
#define GL_STEREO_LEFTRIGHT_H_
|
||||
|
||||
#include "gl_stereo3d.h"
|
||||
|
||||
namespace s3d {
|
||||
|
||||
|
||||
class ShiftedEyePose : public EyePose
|
||||
{
|
||||
public:
|
||||
ShiftedEyePose(float shift) : shift(shift) {};
|
||||
float getShift() const;
|
||||
virtual VSMatrix GetProjection(float fov, float aspectRatio, float fovRatio) const;
|
||||
virtual void GetViewShift(float yaw, float outViewShift[3]) const;
|
||||
|
||||
protected:
|
||||
void setShift(float shift) { this->shift = shift; }
|
||||
|
||||
private:
|
||||
float shift;
|
||||
};
|
||||
|
||||
|
||||
class LeftEyePose : public ShiftedEyePose
|
||||
{
|
||||
public:
|
||||
LeftEyePose(float ipd) : ShiftedEyePose( float(-0.5) * ipd) {}
|
||||
float getIpd() const { return float(fabs(2.0f*getShift())); }
|
||||
void setIpd(float ipd) { setShift(float(-0.5)*ipd); }
|
||||
};
|
||||
|
||||
|
||||
class RightEyePose : public ShiftedEyePose
|
||||
{
|
||||
public:
|
||||
RightEyePose(float ipd) : ShiftedEyePose(float(+0.5)*ipd) {}
|
||||
float getIpd() const { return float(fabs(2.0f*getShift())); }
|
||||
void setIpd(float ipd) { setShift(float(+0.5)*ipd); }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* As if viewed through the left eye only
|
||||
*/
|
||||
class LeftEyeView : public Stereo3DMode
|
||||
{
|
||||
public:
|
||||
static const LeftEyeView& getInstance(float ipd);
|
||||
|
||||
LeftEyeView(float ipd) : eye(ipd) { eye_ptrs.Push(&eye); }
|
||||
float getIpd() const { return eye.getIpd(); }
|
||||
void setIpd(float ipd) { eye.setIpd(ipd); }
|
||||
void Present() const override;
|
||||
protected:
|
||||
LeftEyePose eye;
|
||||
};
|
||||
|
||||
|
||||
class RightEyeView : public Stereo3DMode
|
||||
{
|
||||
public:
|
||||
static const RightEyeView& getInstance(float ipd);
|
||||
|
||||
RightEyeView(float ipd) : eye(ipd) { eye_ptrs.Push(&eye); }
|
||||
float getIpd() const { return eye.getIpd(); }
|
||||
void setIpd(float ipd) { eye.setIpd(ipd); }
|
||||
void Present() const override;
|
||||
protected:
|
||||
RightEyePose eye;
|
||||
};
|
||||
|
||||
|
||||
} /* namespace s3d */
|
||||
|
||||
#endif /* GL_STEREO_LEFTRIGHT_H_ */
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2015 Christopher Bruns
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
/*
|
||||
** scoped_color_mask.h
|
||||
** Stack-scoped class for temporarily changing the OpenGL color mask setting.
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef GL_STEREO3D_SCOPED_COLOR_MASK_H_
|
||||
#define GL_STEREO3D_SCOPED_COLOR_MASK_H_
|
||||
|
||||
#include "gl_load/gl_system.h"
|
||||
|
||||
/**
|
||||
* Temporarily change color mask
|
||||
*/
|
||||
class ScopedColorMask
|
||||
{
|
||||
public:
|
||||
ScopedColorMask(bool r, bool g, bool b, bool a)
|
||||
{
|
||||
gl_RenderState.GetColorMask(saved[0], saved[1], saved[2], saved[3]);
|
||||
gl_RenderState.SetColorMask(r, g, b, a);
|
||||
gl_RenderState.ApplyColorMask();
|
||||
gl_RenderState.EnableDrawBuffers(1);
|
||||
}
|
||||
~ScopedColorMask() {
|
||||
gl_RenderState.EnableDrawBuffers(gl_RenderState.GetPassDrawBufferCount());
|
||||
gl_RenderState.SetColorMask(saved[0], saved[1], saved[2], saved[3]);
|
||||
gl_RenderState.ApplyColorMask();
|
||||
}
|
||||
private:
|
||||
bool saved[4];
|
||||
};
|
||||
|
||||
|
||||
#endif // GL_STEREO3D_SCOPED_COLOR_MASK_H_
|
||||
|
|
@ -37,10 +37,10 @@
|
|||
#include "gl/renderer/gl_renderbuffers.h"
|
||||
#include "gl/textures/gl_samplers.h"
|
||||
#include "hwrenderer/utility/hw_clock.h"
|
||||
#include "hwrenderer/utility/hw_vrmodes.h"
|
||||
#include "gl/data/gl_vertexbuffer.h"
|
||||
#include "gl/data/gl_uniformbuffer.h"
|
||||
#include "gl/models/gl_models.h"
|
||||
#include "gl/stereo3d/gl_stereo3d.h"
|
||||
#include "gl/shaders/gl_shaderprogram.h"
|
||||
#include "gl_debug.h"
|
||||
#include "r_videoscale.h"
|
||||
|
|
@ -342,7 +342,7 @@ IHardwareTexture *OpenGLFrameBuffer::CreateHardwareTexture(FTexture *tex)
|
|||
|
||||
FModelRenderer *OpenGLFrameBuffer::CreateModelRenderer(int mli)
|
||||
{
|
||||
return new FGLModelRenderer(mli);
|
||||
return new FGLModelRenderer(nullptr, mli);
|
||||
}
|
||||
|
||||
IUniformBuffer *OpenGLFrameBuffer::CreateUniformBuffer(size_t size, bool staticuse)
|
||||
|
|
@ -361,11 +361,6 @@ void OpenGLFrameBuffer::UnbindTexUnit(int no)
|
|||
FHardwareTexture::Unbind(no);
|
||||
}
|
||||
|
||||
void OpenGLFrameBuffer::FlushTextures()
|
||||
{
|
||||
if (GLRenderer) GLRenderer->FlushTextures();
|
||||
}
|
||||
|
||||
void OpenGLFrameBuffer::TextureFilterChanged()
|
||||
{
|
||||
if (GLRenderer != NULL && GLRenderer->mSamplerManager != NULL) GLRenderer->mSamplerManager->SetTextureFilterMode();
|
||||
|
|
@ -380,7 +375,10 @@ void OpenGLFrameBuffer::SetViewportRects(IntRect *bounds)
|
|||
{
|
||||
Super::SetViewportRects(bounds);
|
||||
if (!bounds)
|
||||
s3d::Stereo3DMode::getCurrentMode().AdjustViewports();
|
||||
{
|
||||
auto vrmode = VRMode::GetVRMode(true);
|
||||
vrmode->AdjustViewport(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ public:
|
|||
IHardwareTexture *CreateHardwareTexture(FTexture *tex) override;
|
||||
FModelRenderer *CreateModelRenderer(int mli) override;
|
||||
void UnbindTexUnit(int no) override;
|
||||
void FlushTextures() override;
|
||||
void TextureFilterChanged() override;
|
||||
void BeginFrame() override;
|
||||
void SetViewportRects(IntRect *bounds) override;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue