Merge remote-tracking branch 'gzdoom/modern' into hw_postprocess

This commit is contained in:
Magnus Norddahl 2018-06-24 17:57:02 +02:00
commit 32d837cdf1
164 changed files with 23408 additions and 12966 deletions

View file

@ -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!

View file

@ -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"

View file

@ -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();
}
}

View file

@ -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);

View file

@ -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"

View file

@ -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
}
}

View file

@ -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]);

View 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;
}
}