Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eyebuffers #96

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/gl/renderer/gl_2ddrawer.cpp
Expand Up @@ -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;

Expand Down Expand Up @@ -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();
}
3 changes: 2 additions & 1 deletion src/gl/renderer/gl_2ddrawer.h
Expand Up @@ -66,7 +66,8 @@ class F2DDrawer : public FSimpleVertexBuffer
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();
};


Expand Down
88 changes: 66 additions & 22 deletions src/gl/renderer/gl_postprocess.cpp
Expand Up @@ -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"

//==========================================================================
//
Expand Down Expand Up @@ -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
Expand All @@ -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())
{
Expand All @@ -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)
{
Expand All @@ -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
Expand Down
81 changes: 81 additions & 0 deletions src/gl/renderer/gl_renderbuffers.cpp
Expand Up @@ -85,6 +85,7 @@ FGLRenderBuffers::~FGLRenderBuffers()
{
ClearScene();
ClearPipeline();
ClearEyeBuffers();
ClearBloom();
}

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -202,6 +215,7 @@ bool FGLRenderBuffers::Setup(int width, int height, int sceneWidth, int sceneHei
{
ClearScene();
ClearPipeline();
ClearEyeBuffers();
ClearBloom();
mWidth = 0;
mHeight = 0;
Expand Down Expand Up @@ -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++)
{
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.)
Expand Down
10 changes: 10 additions & 0 deletions src/gl/renderer/gl_renderbuffers.h
Expand Up @@ -32,6 +32,10 @@ class FGLRenderBuffers

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

Expand All @@ -43,10 +47,12 @@ class FGLRenderBuffers
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);
Expand Down Expand Up @@ -83,6 +89,10 @@ class FGLRenderBuffers
// Back buffer frame buffer
GLuint mOutputFB = 0;

// Eye buffers
TArray<GLuint> mEyeTextures;
TArray<GLuint> mEyeFBs;

static bool FailedCreate;
static bool BuffersActive;
};
Expand Down
3 changes: 2 additions & 1 deletion src/gl/renderer/gl_renderer.h
Expand Up @@ -173,7 +173,8 @@ class FGLRenderer
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
Expand Down
2 changes: 2 additions & 0 deletions src/gl/scene/gl_scene.cpp
Expand Up @@ -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();
Expand Down
21 changes: 21 additions & 0 deletions src/gl/stereo3d/gl_anaglyph.cpp
Expand Up @@ -34,6 +34,8 @@
*/

#include "gl_anaglyph.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/renderer/gl_renderbuffers.h"

namespace s3d {

Expand All @@ -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)
Expand Down