diff --git a/src/gl/data/gl_vertexbuffer.h b/src/gl/data/gl_vertexbuffer.h index b88cc6ca1..eeb3ace48 100644 --- a/src/gl/data/gl_vertexbuffer.h +++ b/src/gl/data/gl_vertexbuffer.h @@ -105,6 +105,16 @@ public: if (pcount) *pcount = count; } + void RenderScreenQuad(float maxU = 1.0f, float maxV = 1.0f) + { + FFlatVertex *ptr = GetBuffer(); + ptr->Set(-1.0f, -1.0f, 0, 0.0f, 0.0f); ptr++; + ptr->Set(-1.0f, 1.0f, 0, 0.0f, maxV); ptr++; + ptr->Set(1.0f, -1.0f, 0, maxU, 0.0f); ptr++; + ptr->Set(1.0f, 1.0f, 0, maxU, maxV); ptr++; + RenderCurrent(ptr, GL_TRIANGLE_STRIP); + } + #endif void Reset() { diff --git a/src/gl/renderer/gl_postprocess.cpp b/src/gl/renderer/gl_postprocess.cpp index 9dc0dd99e..5ccacf305 100644 --- a/src/gl/renderer/gl_postprocess.cpp +++ b/src/gl/renderer/gl_postprocess.cpp @@ -145,14 +145,7 @@ void FGLRenderer::BloomScene() mBloomExtractShader->Bind(); mBloomExtractShader->SceneTexture.Set(0); mBloomExtractShader->Exposure.Set(mCameraExposure); - { - FFlatVertex *ptr = mVBO->GetBuffer(); - ptr->Set(-1.0f, -1.0f, 0, 0.0f, 0.0f); ptr++; - ptr->Set(-1.0f, 1.0f, 0, 0.0f, 1.0f); ptr++; - ptr->Set(1.0f, -1.0f, 0, 1.0f, 0.0f); ptr++; - ptr->Set(1.0f, 1.0f, 0, 1.0f, 1.0f); ptr++; - mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP); - } + mVBO->RenderScreenQuad(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -183,14 +176,7 @@ void FGLRenderer::BloomScene() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); mBloomCombineShader->Bind(); mBloomCombineShader->BloomTexture.Set(0); - { - FFlatVertex *ptr = mVBO->GetBuffer(); - ptr->Set(-1.0f, -1.0f, 0, 0.0f, 0.0f); ptr++; - ptr->Set(-1.0f, 1.0f, 0, 0.0f, 1.0f); ptr++; - ptr->Set(1.0f, -1.0f, 0, 1.0f, 0.0f); ptr++; - ptr->Set(1.0f, 1.0f, 0, 1.0f, 1.0f); ptr++; - mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP); - } + mVBO->RenderScreenQuad(); } mBlurShader->BlurHorizontal(mVBO, blurAmount, sampleCount, level0.VTexture, level0.HFramebuffer, level0.Width, level0.Height); @@ -198,7 +184,7 @@ void FGLRenderer::BloomScene() // Add bloom back to scene texture: mBuffers->BindSceneTextureFB(); - glViewport(0, 0, mOutputViewport.width, mOutputViewport.height); + glViewport(mOutputViewport.left, mOutputViewport.top, mOutputViewport.width, mOutputViewport.height); glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_ONE, GL_ONE); @@ -208,14 +194,7 @@ void FGLRenderer::BloomScene() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); mBloomCombineShader->Bind(); mBloomCombineShader->BloomTexture.Set(0); - { - FFlatVertex *ptr = mVBO->GetBuffer(); - ptr->Set(-1.0f, -1.0f, 0, 0.0f, 0.0f); ptr++; - ptr->Set(-1.0f, 1.0f, 0, 0.0f, 1.0f); ptr++; - ptr->Set(1.0f, -1.0f, 0, 1.0f, 0.0f); ptr++; - ptr->Set(1.0f, 1.0f, 0, 1.0f, 1.0f); ptr++; - mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP); - } + mVBO->RenderScreenQuad(); if (blendEnabled) glEnable(GL_BLEND); @@ -263,13 +242,7 @@ void FGLRenderer::TonemapScene() mTonemapShader->Bind(); mTonemapShader->SceneTexture.Set(0); mTonemapShader->Exposure.Set(mCameraExposure); - - FFlatVertex *ptr = mVBO->GetBuffer(); - ptr->Set(-1.0f, -1.0f, 0, 0.0f, 0.0f); ptr++; - ptr->Set(-1.0f, 1.0f, 0, 0.0f, 1.0f); ptr++; - ptr->Set(1.0f, -1.0f, 0, 1.0f, 0.0f); ptr++; - ptr->Set(1.0f, 1.0f, 0, 1.0f, 1.0f); ptr++; - mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP); + mVBO->RenderScreenQuad(); if (blendEnabled) glEnable(GL_BLEND); @@ -287,7 +260,7 @@ void FGLRenderer::TonemapScene() // //----------------------------------------------------------------------------- -void FGLRenderer::Flush() +void FGLRenderer::CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma) { if (FGLRenderBuffers::IsEnabled()) { @@ -311,40 +284,51 @@ void FGLRenderer::Flush() mBuffers->BindOutputFB(); - // Calculate letterbox - int clientWidth = framebuffer->GetClientWidth(); - int clientHeight = framebuffer->GetClientHeight(); - float scaleX = clientWidth / (float)mOutputViewport.width; - float scaleY = clientHeight / (float)mOutputViewport.height; - float scale = MIN(scaleX, scaleY); - int width = (int)round(mOutputViewport.width * scale); - int height = (int)round(mOutputViewport.height * scale); - int x = (clientWidth - width) / 2; - int y = (clientHeight - height) / 2; + int x, y, width, height; + if (bounds) + { + x = bounds->left; + y = bounds->top; + width = bounds->width; + height = bounds->height; + } + else + { + // Calculate letterbox + int clientWidth = framebuffer->GetClientWidth(); + int clientHeight = framebuffer->GetClientHeight(); + float scaleX = clientWidth / (float)mScreenViewport.width; + float scaleY = clientHeight / (float)mScreenViewport.height; + float scale = MIN(scaleX, scaleY); + width = (int)round(mScreenViewport.width * scale); + height = (int)round(mScreenViewport.height * scale); + x = (clientWidth - width) / 2; + y = (clientHeight - height) / 2; - // Black bars around the box: - glViewport(0, 0, clientWidth, clientHeight); - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glEnable(GL_SCISSOR_TEST); - if (y > 0) - { - glScissor(0, 0, clientWidth, y); - glClear(GL_COLOR_BUFFER_BIT); - } - if (clientHeight - y - height > 0) - { - glScissor(0, y + height, clientWidth, clientHeight - y - height); - glClear(GL_COLOR_BUFFER_BIT); - } - if (x > 0) - { - glScissor(0, y, x, height); - glClear(GL_COLOR_BUFFER_BIT); - } - if (clientWidth - x - width > 0) - { - glScissor(x + width, y, clientWidth - x - width, height); - glClear(GL_COLOR_BUFFER_BIT); + // Black bars around the box: + glViewport(0, 0, clientWidth, clientHeight); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glEnable(GL_SCISSOR_TEST); + if (y > 0) + { + glScissor(0, 0, clientWidth, y); + glClear(GL_COLOR_BUFFER_BIT); + } + if (clientHeight - y - height > 0) + { + glScissor(0, y + height, clientWidth, clientHeight - y - height); + glClear(GL_COLOR_BUFFER_BIT); + } + if (x > 0) + { + glScissor(0, y, x, height); + glClear(GL_COLOR_BUFFER_BIT); + } + if (clientWidth - x - width > 0) + { + glScissor(x + width, y, clientWidth - x - width, height); + glClear(GL_COLOR_BUFFER_BIT); + } } glDisable(GL_SCISSOR_TEST); @@ -354,7 +338,7 @@ void FGLRenderer::Flush() mPresentShader->Bind(); mPresentShader->InputTexture.Set(0); - if (framebuffer->IsHWGammaActive()) + if (!applyGamma || framebuffer->IsHWGammaActive()) { mPresentShader->Gamma.Set(1.0f); mPresentShader->Contrast.Set(1.0f); @@ -367,13 +351,7 @@ void FGLRenderer::Flush() mPresentShader->Brightness.Set(clamp(vid_brightness, -0.8f, 0.8f)); } mBuffers->BindHudTexture(0); - - FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); - ptr->Set(-1.0f, -1.0f, 0, 0.0f, 0.0f); ptr++; - ptr->Set(-1.0f, 1.0f, 0, 0.0f, 1.0f); ptr++; - ptr->Set(1.0f, -1.0f, 0, 1.0f, 0.0f); ptr++; - ptr->Set(1.0f, 1.0f, 0, 1.0f, 1.0f); ptr++; - GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP); + mVBO->RenderScreenQuad(width / (float)mBuffers->GetWidth(), height / (float)mBuffers->GetHeight()); if (blendEnabled) glEnable(GL_BLEND); diff --git a/src/gl/renderer/gl_renderbuffers.h b/src/gl/renderer/gl_renderbuffers.h index b4765b544..37bbdc2e5 100644 --- a/src/gl/renderer/gl_renderbuffers.h +++ b/src/gl/renderer/gl_renderbuffers.h @@ -34,6 +34,9 @@ public: static bool IsEnabled(); + int GetWidth() const { return mWidth; } + int GetHeight() const { return mHeight; } + private: void ClearScene(); void ClearHud(); diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index a1d8bb2a7..d2a0cb959 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -185,6 +185,7 @@ void FGLRenderer::SetOutputViewport(GL_IRECT *bounds) { mOutputViewport = *bounds; mOutputViewportLB = *bounds; + mScreenViewport = *bounds; return; } @@ -209,6 +210,12 @@ void FGLRenderer::SetOutputViewport(GL_IRECT *bounds) int vw = viewwidth; int vh = viewheight; + // The entire renderable area, including the 2D HUD + mScreenViewport.left = 0; + mScreenViewport.top = 0; + mScreenViewport.width = framebuffer->GetWidth(); + mScreenViewport.height = framebuffer->GetHeight(); + // Letterboxed viewport for the main scene mOutputViewportLB.left = viewwindowx; mOutputViewportLB.top = trueheight - bars - (height + viewwindowy - ((height - vh) / 2)); @@ -242,12 +249,8 @@ void FGLRenderer::Begin2D() mBuffers->BindSceneFB(); else mBuffers->BindHudFB(); - glViewport(0, 0, mOutputViewport.width, mOutputViewport.height); - } - else - { - glViewport(mOutputViewport.left, mOutputViewport.top, mOutputViewport.width, mOutputViewport.height); } + glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height); gl_RenderState.EnableFog(false); gl_RenderState.Set2DMode(true); diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index ad2046cad..78eac4cbf 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -106,6 +106,7 @@ public: FSkyVertexBuffer *mSkyVBO; FLightBuffer *mLights; + GL_IRECT mScreenViewport; GL_IRECT mOutputViewportLB; GL_IRECT mOutputViewport; bool mDrawingScene2D = false; @@ -117,7 +118,7 @@ public: angle_t FrustumAngle(); void SetViewArea(); void SetOutputViewport(GL_IRECT *bounds); - void Set3DViewport(bool toscreen); + void Set3DViewport(bool mainview); void Reset3DViewport(); sector_t *RenderViewpoint (AActor * camera, GL_IRECT * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen); void RenderView(player_t *player); @@ -159,7 +160,8 @@ public: void EndDrawScene(sector_t * viewsector); void BloomScene(); void TonemapScene(); - void Flush(); + void CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma); + void Flush() { CopyToBackbuffer(nullptr, true); } void SetProjection(float fov, float ratio, float fovratio); void SetProjection(VSMatrix matrix); // raw matrix input from stereo 3d modes diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index b28e2c293..87197d09d 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -157,10 +157,7 @@ void FGLRenderer::SetViewArea() void FGLRenderer::Reset3DViewport() { - if (FGLRenderBuffers::IsEnabled()) - glViewport(0, 0, mOutputViewport.width, mOutputViewport.height); - else - glViewport(mOutputViewport.left, mOutputViewport.top, mOutputViewport.width, mOutputViewport.height); + glViewport(mOutputViewport.left, mOutputViewport.top, mOutputViewport.width, mOutputViewport.height); } //----------------------------------------------------------------------------- @@ -169,22 +166,18 @@ void FGLRenderer::Reset3DViewport() // //----------------------------------------------------------------------------- -void FGLRenderer::Set3DViewport(bool toscreen) +void FGLRenderer::Set3DViewport(bool mainview) { - const auto &bounds = mOutputViewportLB; - if (toscreen && FGLRenderBuffers::IsEnabled()) + if (mainview && FGLRenderBuffers::IsEnabled()) { mBuffers->Setup(mOutputViewport.width, mOutputViewport.height); mBuffers->BindSceneFB(); - glViewport(0, 0, bounds.width, bounds.height); - glScissor(0, 0, bounds.width, bounds.height); - } - else - { - glViewport(bounds.left, bounds.top, bounds.width, bounds.height); - glScissor(bounds.left, bounds.top, bounds.width, bounds.height); } + const auto &bounds = mOutputViewportLB; + glViewport(bounds.left, bounds.top, bounds.width, bounds.height); + glScissor(bounds.left, bounds.top, bounds.width, bounds.height); + glEnable(GL_SCISSOR_TEST); #ifdef _DEBUG @@ -847,7 +840,7 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo eye->SetUp(); // TODO: stereo specific viewport - needed when implementing side-by-side modes etc. SetOutputViewport(bounds); - Set3DViewport(toscreen); + Set3DViewport(mainview); mDrawingScene2D = true; mCurrentFoV = fov; // Stereo mode specific perspective projection @@ -865,8 +858,8 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo clipper.SafeAddClipRangeRealAngles(ViewAngle.BAMs() + a1, ViewAngle.BAMs() - a1); ProcessScene(toscreen); - if (mainview) EndDrawScene(retval); // do not call this for camera textures. - if (toscreen) + if (mainview && toscreen) EndDrawScene(retval); // do not call this for camera textures. + if (mainview) { if (FGLRenderBuffers::IsEnabled()) mBuffers->BlitSceneToTexture(); BloomScene(); @@ -983,6 +976,7 @@ void FGLRenderer::WriteSavePic (player_t *player, FILE *file, int width, int hei gl_RenderState.SetSoftLightLevel(-1); screen->Begin2D(false); DrawBlend(viewsector); + CopyToBackbuffer(&bounds, false); glFlush(); byte * scr = (byte *)M_Malloc(width * height * 3); diff --git a/src/gl/shaders/gl_presentshader.cpp b/src/gl/shaders/gl_presentshader.cpp index 0ebfc9945..2f9642458 100644 --- a/src/gl/shaders/gl_presentshader.cpp +++ b/src/gl/shaders/gl_presentshader.cpp @@ -58,6 +58,7 @@ void FPresentShader::Bind() mShader.SetFragDataLocation(0, "FragColor"); mShader.Link("shaders/glsl/present"); mShader.SetAttribLocation(0, "PositionInProjection"); + mShader.SetAttribLocation(1, "UV"); InputTexture.Init(mShader, "InputTexture"); Gamma.Init(mShader, "Gamma"); Contrast.Init(mShader, "Contrast"); diff --git a/src/gl/system/gl_wipe.cpp b/src/gl/system/gl_wipe.cpp index 4c6922e4f..781194ca4 100644 --- a/src/gl/system/gl_wipe.cpp +++ b/src/gl/system/gl_wipe.cpp @@ -233,7 +233,8 @@ bool OpenGLFrameBuffer::WipeDo(int ticks) if (FGLRenderBuffers::IsEnabled()) { GLRenderer->mBuffers->BindHudFB(); - glViewport(0, 0, GLRenderer->mOutputViewport.width, GLRenderer->mOutputViewport.height); + const auto &bounds = GLRenderer->mScreenViewport; + glViewport(bounds.left, bounds.top, bounds.width, bounds.height); } bool done = ScreenWipe->Run(ticks, this); diff --git a/wadsrc/static/shaders/glsl/present.vp b/wadsrc/static/shaders/glsl/present.vp index 5990669a5..fea7e25ad 100644 --- a/wadsrc/static/shaders/glsl/present.vp +++ b/wadsrc/static/shaders/glsl/present.vp @@ -1,9 +1,10 @@ in vec4 PositionInProjection; +in vec2 UV; out vec2 TexCoord; void main() { gl_Position = PositionInProjection; - TexCoord = PositionInProjection.xy * 0.5 + 0.5; + TexCoord = UV; }