This commit is contained in:
raa-eruanna 2016-09-09 11:31:31 -04:00
commit b0e104d566
18 changed files with 277 additions and 66 deletions

View file

@ -378,7 +378,7 @@ void F2DDrawer::AddPixel(int x1, int y1, int palcolor, uint32 color)
//
//==========================================================================
void F2DDrawer::Flush()
void F2DDrawer::Draw()
{
F2DDrawer::EDrawType lasttype = DrawTypeTexture;
@ -490,10 +490,12 @@ void F2DDrawer::Flush()
}
i += dg->mLen;
}
mVertices.Clear();
mData.Clear();
gl_RenderState.SetVertexBuffer(GLRenderer->mVBO);
glset.lightmode = savedlightmode;
}
void F2DDrawer::Clear()
{
mVertices.Clear();
mData.Clear();
}

View file

@ -66,7 +66,8 @@ public:
void AddLine(int x1, int y1, int x2, int y2, int palcolor, uint32 color);
void AddPixel(int x1, int y1, int palcolor, uint32 color);
void Flush();
void Draw();
void Clear();
};

View file

@ -75,6 +75,7 @@
#include "gl/shaders/gl_lensshader.h"
#include "gl/shaders/gl_presentshader.h"
#include "gl/renderer/gl_2ddrawer.h"
#include "gl/stereo3d/gl_stereo3d.h"
//==========================================================================
//
@ -375,6 +376,41 @@ void FGLRenderer::LensDistortScene()
FGLDebug::PopGroup();
}
//-----------------------------------------------------------------------------
//
// Copies the rendered screen to its final destination
//
//-----------------------------------------------------------------------------
void FGLRenderer::Flush()
{
const s3d::Stereo3DMode& stereo3dMode = s3d::Stereo3DMode::getCurrentMode();
if (stereo3dMode.IsMono() || !FGLRenderBuffers::IsEnabled())
{
CopyToBackbuffer(nullptr, true);
}
else
{
// Render 2D to eye textures
for (int eye_ix = 0; eye_ix < stereo3dMode.eye_count(); ++eye_ix)
{
FGLDebug::PushGroup("Eye2D");
mBuffers->BindEyeFB(eye_ix);
glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
glScissor(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
m2DDrawer->Draw();
FGLDebug::PopGroup();
}
m2DDrawer->Clear();
FGLPostProcessState savedState;
FGLDebug::PushGroup("PresentEyes");
stereo3dMode.Present();
FGLDebug::PopGroup();
}
}
//-----------------------------------------------------------------------------
//
// Gamma correct while copying to frame buffer
@ -383,7 +419,9 @@ void FGLRenderer::LensDistortScene()
void FGLRenderer::CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma)
{
m2DDrawer->Flush(); // draw all pending 2D stuff before copying the buffer
m2DDrawer->Draw(); // draw all pending 2D stuff before copying the buffer
m2DDrawer->Clear();
FGLDebug::PushGroup("CopyToBackbuffer");
if (FGLRenderBuffers::IsEnabled())
{
@ -401,28 +439,8 @@ void FGLRenderer::CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma)
box = mOutputLetterbox;
}
// Present what was rendered:
glViewport(box.left, box.top, box.width, box.height);
mPresentShader->Bind();
mPresentShader->InputTexture.Set(0);
if (!applyGamma || framebuffer->IsHWGammaActive())
{
mPresentShader->InvGamma.Set(1.0f);
mPresentShader->Contrast.Set(1.0f);
mPresentShader->Brightness.Set(0.0f);
}
else
{
mPresentShader->InvGamma.Set(1.0f / clamp<float>(Gamma, 0.1f, 4.f));
mPresentShader->Contrast.Set(clamp<float>(vid_contrast, 0.1f, 3.f));
mPresentShader->Brightness.Set(clamp<float>(vid_brightness, -0.8f, 0.8f));
}
mPresentShader->Scale.Set(mScreenViewport.width / (float)mBuffers->GetWidth(), mScreenViewport.height / (float)mBuffers->GetHeight());
mBuffers->BindCurrentTexture(0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
RenderScreenQuad();
DrawPresentTexture(box, applyGamma);
}
else if (!bounds)
{
@ -432,6 +450,32 @@ void FGLRenderer::CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma)
FGLDebug::PopGroup();
}
void FGLRenderer::DrawPresentTexture(const GL_IRECT &box, bool applyGamma)
{
glViewport(box.left, box.top, box.width, box.height);
glActiveTexture(GL_TEXTURE0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
mPresentShader->Bind();
mPresentShader->InputTexture.Set(0);
if (!applyGamma || framebuffer->IsHWGammaActive())
{
mPresentShader->InvGamma.Set(1.0f);
mPresentShader->Contrast.Set(1.0f);
mPresentShader->Brightness.Set(0.0f);
}
else
{
mPresentShader->InvGamma.Set(1.0f / clamp<float>(Gamma, 0.1f, 4.f));
mPresentShader->Contrast.Set(clamp<float>(vid_contrast, 0.1f, 3.f));
mPresentShader->Brightness.Set(clamp<float>(vid_brightness, -0.8f, 0.8f));
}
mPresentShader->Scale.Set(mScreenViewport.width / (float)mBuffers->GetWidth(), mScreenViewport.height / (float)mBuffers->GetHeight());
RenderScreenQuad();
}
//-----------------------------------------------------------------------------
//
// Fills the black bars around the screen letterbox

View file

@ -85,6 +85,7 @@ FGLRenderBuffers::~FGLRenderBuffers()
{
ClearScene();
ClearPipeline();
ClearEyeBuffers();
ClearBloom();
}
@ -119,6 +120,18 @@ void FGLRenderBuffers::ClearBloom()
}
}
void FGLRenderBuffers::ClearEyeBuffers()
{
for (auto handle : mEyeFBs)
DeleteFrameBuffer(handle);
for (auto handle : mEyeTextures)
DeleteTexture(handle);
mEyeTextures.Clear();
mEyeFBs.Clear();
}
void FGLRenderBuffers::DeleteTexture(GLuint &handle)
{
if (handle != 0)
@ -202,6 +215,7 @@ bool FGLRenderBuffers::Setup(int width, int height, int sceneWidth, int sceneHei
{
ClearScene();
ClearPipeline();
ClearEyeBuffers();
ClearBloom();
mWidth = 0;
mHeight = 0;
@ -239,6 +253,7 @@ void FGLRenderBuffers::CreateScene(int width, int height, int samples)
void FGLRenderBuffers::CreatePipeline(int width, int height)
{
ClearPipeline();
ClearEyeBuffers();
for (int i = 0; i < NumPipelineTextures; i++)
{
@ -279,6 +294,35 @@ void FGLRenderBuffers::CreateBloom(int width, int height)
}
}
//==========================================================================
//
// Creates eye buffers if needed
//
//==========================================================================
void FGLRenderBuffers::CreateEyeBuffers(int eye)
{
if (mEyeFBs.Size() > eye)
return;
GLint activeTex, textureBinding, frameBufferBinding;
glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTex);
glActiveTexture(GL_TEXTURE0);
glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding);
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &frameBufferBinding);
while (mEyeFBs.Size() <= eye)
{
GLuint texture = Create2DTexture("EyeTexture", GL_RGBA16F, mWidth, mHeight);
mEyeTextures.Push(texture);
mEyeFBs.Push(CreateFrameBuffer("EyeFB", texture));
}
glBindTexture(GL_TEXTURE_2D, textureBinding);
glActiveTexture(activeTex);
glBindFramebuffer(GL_FRAMEBUFFER, frameBufferBinding);
}
//==========================================================================
//
// Creates a 2D texture defaulting to linear filtering and clamp to edge
@ -471,6 +515,43 @@ void FGLRenderBuffers::BlitSceneToTexture()
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
//==========================================================================
//
// Eye textures and their frame buffers
//
//==========================================================================
void FGLRenderBuffers::BlitToEyeTexture(int eye)
{
CreateEyeBuffers(eye);
glBindFramebuffer(GL_READ_FRAMEBUFFER, mPipelineFB[mCurrentPipelineTexture]);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mEyeFBs[eye]);
glBlitFramebuffer(0, 0, mWidth, mHeight, 0, 0, mWidth, mHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
if ((gl.flags & RFL_INVALIDATE_BUFFER) != 0)
{
GLenum attachments[2] = { GL_COLOR_ATTACHMENT0, GL_DEPTH_STENCIL_ATTACHMENT };
glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 2, attachments);
}
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
void FGLRenderBuffers::BindEyeTexture(int eye, int texunit)
{
CreateEyeBuffers(eye);
glActiveTexture(GL_TEXTURE0 + texunit);
glBindTexture(GL_TEXTURE_2D, mEyeTextures[eye]);
}
void FGLRenderBuffers::BindEyeFB(int eye, bool readBuffer)
{
CreateEyeBuffers(eye);
glBindFramebuffer(readBuffer ? GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER, mEyeFBs[eye]);
}
//==========================================================================
//
// Makes the scene frame buffer active (multisample, depth, stecil, etc.)

View file

@ -32,6 +32,10 @@ public:
void BindOutputFB();
void BlitToEyeTexture(int eye);
void BindEyeTexture(int eye, int texunit);
void BindEyeFB(int eye, bool readBuffer = false);
enum { NumBloomLevels = 4 };
FGLBloomTextureLevel BloomLevels[NumBloomLevels];
@ -43,10 +47,12 @@ public:
private:
void ClearScene();
void ClearPipeline();
void ClearEyeBuffers();
void ClearBloom();
void CreateScene(int width, int height, int samples);
void CreatePipeline(int width, int height);
void CreateBloom(int width, int height);
void CreateEyeBuffers(int eye);
GLuint Create2DTexture(const FString &name, GLuint format, int width, int height);
GLuint CreateRenderBuffer(const FString &name, GLuint format, int width, int height);
GLuint CreateRenderBuffer(const FString &name, GLuint format, int samples, int width, int height);
@ -83,6 +89,10 @@ private:
// Back buffer frame buffer
GLuint mOutputFB = 0;
// Eye buffers
TArray<GLuint> mEyeTextures;
TArray<GLuint> mEyeFBs;
static bool FailedCreate;
static bool BuffersActive;
};

View file

@ -173,7 +173,8 @@ public:
void ClearTonemapPalette();
void LensDistortScene();
void CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma);
void Flush() { CopyToBackbuffer(nullptr, true); }
void DrawPresentTexture(const GL_IRECT &box, bool applyGamma);
void Flush();
void SetProjection(float fov, float ratio, float fovratio);
void SetProjection(VSMatrix matrix); // raw matrix input from stereo 3d modes

View file

@ -419,15 +419,17 @@ void GLFlat::Draw(int pass, bool trans) // trans only has meaning for GLPASS_LIG
if (renderstyle==STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE);
gl_SetColor(lightlevel, rel, Colormap, alpha);
gl_SetFog(lightlevel, rel, &Colormap, false);
gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
if (!gltexture)
{
gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
gl_RenderState.EnableTexture(false);
DrawSubsectors(pass, false, true);
gl_RenderState.EnableTexture(true);
}
else
{
if (!gltexture->GetTransparent()) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
else gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false);
gl_SetPlaneTextureRotation(&plane, gltexture);
DrawSubsectors(pass, !gl.legacyMode, true);
@ -477,6 +479,21 @@ inline void GLFlat::PutFlat(bool fog)
// translucent 3D floors go into the regular translucent list, translucent portals go into the translucent border list.
list = (renderflags&SSRF_RENDER3DPLANES) ? GLDL_TRANSLUCENT : GLDL_TRANSLUCENTBORDER;
}
else if (gltexture->GetTransparent())
{
if (stack)
{
list = GLDL_TRANSLUCENTBORDER;
}
else if ((renderflags&SSRF_RENDER3DPLANES) && !plane.plane.isSlope())
{
list = GLDL_TRANSLUCENT;
}
else
{
list = GLDL_PLAINFLATS;
}
}
else
{
bool masked = gltexture->isMasked() && ((renderflags&SSRF_RENDER3DPLANES) || stack);

View file

@ -863,6 +863,8 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo
DrawBlend(lviewsector);
}
mDrawingScene2D = false;
if (!stereo3dMode.IsMono() && FGLRenderBuffers::IsEnabled())
mBuffers->BlitToEyeTexture(eye_ix);
eye->TearDown();
}
stereo3dMode.TearDown();

View file

@ -34,6 +34,8 @@
*/
#include "gl_anaglyph.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/renderer/gl_renderbuffers.h"
namespace s3d {
@ -44,6 +46,25 @@ MaskAnaglyph::MaskAnaglyph(const ColorMask& leftColorMask, double ipdMeters)
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(GLRenderer->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(GLRenderer->mOutputLetterbox, true);
gl_RenderState.ResetColorMask();
gl_RenderState.ApplyColorMask();
}
/* static */
const GreenMagenta& GreenMagenta::getInstance(float ipd)

View file

@ -61,14 +61,8 @@ class AnaglyphLeftPose : public LeftEyePose
{
public:
AnaglyphLeftPose(const ColorMask& colorMask, float ipd) : LeftEyePose(ipd), colorMask(colorMask) {}
virtual void SetUp() const {
gl_RenderState.SetColorMask(colorMask.r, colorMask.g, colorMask.b, true);
gl_RenderState.ApplyColorMask();
}
virtual void TearDown() const {
gl_RenderState.ResetColorMask();
gl_RenderState.ApplyColorMask();
}
ColorMask GetColorMask() const { return colorMask; }
private:
ColorMask colorMask;
};
@ -77,14 +71,8 @@ class AnaglyphRightPose : public RightEyePose
{
public:
AnaglyphRightPose(const ColorMask& colorMask, float ipd) : RightEyePose(ipd), colorMask(colorMask) {}
virtual void SetUp() const {
gl_RenderState.SetColorMask(colorMask.r, colorMask.g, colorMask.b, true);
gl_RenderState.ApplyColorMask();
}
virtual void TearDown() const {
gl_RenderState.ResetColorMask();
gl_RenderState.ApplyColorMask();
}
ColorMask GetColorMask() const { return colorMask; }
private:
ColorMask colorMask;
};
@ -93,6 +81,7 @@ class MaskAnaglyph : public Stereo3DMode
{
public:
MaskAnaglyph(const ColorMask& leftColorMask, double ipdMeters);
void Present() const override;
private:
AnaglyphLeftPose leftEye;
AnaglyphRightPose rightEye;

View file

@ -34,6 +34,8 @@
*/
#include "gl_quadstereo.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/renderer/gl_renderbuffers.h"
namespace s3d {
@ -46,7 +48,7 @@ QuadStereo::QuadStereo(double ipdMeters)
GLboolean supportsStereo, supportsBuffered;
glGetBooleanv(GL_STEREO, &supportsStereo);
glGetBooleanv(GL_DOUBLEBUFFER, &supportsBuffered);
bool bQuadStereoSupported = supportsStereo && supportsBuffered;
bQuadStereoSupported = supportsStereo && supportsBuffered;
leftEye.bQuadStereoSupported = bQuadStereoSupported;
rightEye.bQuadStereoSupported = bQuadStereoSupported;
@ -57,6 +59,33 @@ QuadStereo::QuadStereo(double ipdMeters)
}
}
void QuadStereo::Present() const
{
if (bQuadStereoSupported)
{
GLRenderer->mBuffers->BindOutputFB();
glDrawBuffer(GL_BACK_LEFT);
GLRenderer->ClearBorders();
GLRenderer->mBuffers->BindEyeTexture(0, 0);
GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true);
glDrawBuffer(GL_BACK_RIGHT);
GLRenderer->ClearBorders();
GLRenderer->mBuffers->BindEyeTexture(1, 0);
GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true);
glDrawBuffer(GL_BACK);
}
else
{
GLRenderer->mBuffers->BindOutputFB();
GLRenderer->ClearBorders();
GLRenderer->mBuffers->BindEyeTexture(1, 0);
GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true);
}
}
/* static */
const QuadStereo& QuadStereo::getInstance(float ipd)
{

View file

@ -47,14 +47,6 @@ class QuadStereoLeftPose : public LeftEyePose
{
public:
QuadStereoLeftPose(float ipd) : LeftEyePose(ipd), bQuadStereoSupported(false) {}
virtual void SetUp() const {
if (bQuadStereoSupported)
glDrawBuffer(GL_BACK_LEFT);
}
virtual void TearDown() const {
if (bQuadStereoSupported)
glDrawBuffer(GL_BACK);
}
bool bQuadStereoSupported;
};
@ -62,14 +54,6 @@ class QuadStereoRightPose : public RightEyePose
{
public:
QuadStereoRightPose(float ipd) : RightEyePose(ipd), bQuadStereoSupported(false){}
virtual void SetUp() const {
if (bQuadStereoSupported)
glDrawBuffer(GL_BACK_RIGHT);
}
virtual void TearDown() const {
if (bQuadStereoSupported)
glDrawBuffer(GL_BACK);
}
bool bQuadStereoSupported;
};
@ -84,10 +68,12 @@ class QuadStereo : public Stereo3DMode
{
public:
QuadStereo(double ipdMeters);
void Present() const override;
static const QuadStereo& getInstance(float ipd);
private:
QuadStereoLeftPose leftEye;
QuadStereoRightPose rightEye;
bool bQuadStereoSupported;
};

View file

@ -85,6 +85,9 @@ public:
virtual void SetUp() const {};
virtual void TearDown() const {};
virtual bool IsMono() const { return false; }
virtual void Present() const = 0;
protected:
TArray<const EyePose *> eye_ptrs;
@ -102,6 +105,9 @@ class MonoView : public Stereo3DMode
public:
static const MonoView& getInstance();
bool IsMono() const override { return true; }
void Present() const override { }
protected:
MonoView() { eye_ptrs.Push(&centralEye); }
EyePose centralEye;

View file

@ -37,7 +37,10 @@
#include "vectors.h" // RAD2DEG
#include "doomtype.h" // M_PI
#include "gl/system/gl_cvars.h"
#include "gl/system/gl_system.h"
#include "gl/renderer/gl_renderstate.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/renderer/gl_renderbuffers.h"
#include <cmath>
EXTERN_CVAR(Float, vr_screendist)
@ -89,6 +92,13 @@ const LeftEyeView& LeftEyeView::getInstance(float ipd)
return instance;
}
void LeftEyeView::Present() const
{
GLRenderer->mBuffers->BindOutputFB();
GLRenderer->ClearBorders();
GLRenderer->mBuffers->BindEyeTexture(0, 0);
GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true);
}
/* static */
const RightEyeView& RightEyeView::getInstance(float ipd)
@ -98,5 +108,13 @@ const RightEyeView& RightEyeView::getInstance(float ipd)
return instance;
}
void RightEyeView::Present() const
{
GLRenderer->mBuffers->BindOutputFB();
GLRenderer->ClearBorders();
GLRenderer->mBuffers->BindEyeTexture(0, 0);
GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true);
}
} /* namespace s3d */

View file

@ -83,6 +83,7 @@ public:
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;
};
@ -96,6 +97,7 @@ public:
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;
};

View file

@ -189,7 +189,8 @@ bool OpenGLFrameBuffer::WipeStartScreen(int type)
void OpenGLFrameBuffer::WipeEndScreen()
{
GLRenderer->m2DDrawer->Flush();
GLRenderer->m2DDrawer->Draw();
GLRenderer->m2DDrawer->Clear();
const auto &viewport = GLRenderer->mScreenViewport;
wipeendscreen = new FHardwareTexture(viewport.width, viewport.height, true);

View file

@ -380,7 +380,7 @@ struct bCopyAlpha
};
struct bOverlay
{
{
static __forceinline void OpC(BYTE &d, BYTE s, BYTE a, FCopyInfo *i) { d = (s*a + d*(255-a))/255; }
static __forceinline void OpA(BYTE &d, BYTE s, FCopyInfo *i) { d = MAX(s,d); }
static __forceinline bool ProcessAlpha0() { return false; }

View file

@ -629,8 +629,9 @@ int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rota
{
ret = Parts[i].Texture->CopyTrueColorPixels(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, &info);
}
if (ret > retv) retv = ret;
// treat -1 (i.e. unknown) as absolute. We have no idea if this may have overwritten previous info so a real check needs to be done.
if (ret == -1) retv = ret;
else if (retv != -1 && ret > retv) retv = ret;
}
// Restore previous clipping rectangle.
bmp->SetClipRect(saved_cr);