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 if (! fullscreen) { I_SaveWindowedPos(); // update win_y CVAR windowVOffset = (win_y + WINDOW_BORDER_VERTICAL_PARITY) % 2; } #endif // _WIN32 GLRenderer->mPresent3dRowShader->WindowPositionParity.Set( (windowVOffset + GLRenderer->mOutputLetterbox.height + 1 // +1 because of origin at bottom ) % 2 ); GLRenderer->RenderScreenQuad(); }
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 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 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 if (!fullscreen) { I_SaveWindowedPos(); // update win_y CVAR windowHOffset = (win_x + WINDOW_BORDER_HORIZONTAL_PARITY) % 2; } #endif // _WIN32 GLRenderer->mPresent3dColumnShader->WindowPositionParity.Set(windowHOffset); GLRenderer->RenderScreenQuad(); }
void FGLRenderBuffers::RenderEffect(const FString &name) { if (hw_postprocess.Effects[name].Size() == 0) return; FGLDebug::PushGroup(name.GetChars()); FGLPostProcessState savedState; for (const PPStep &step : hw_postprocess.Effects[name]) { // Bind input textures for (unsigned int index = 0; index < step.Textures.Size(); index++) { savedState.SaveTextureBindings(index + 1); const PPTextureInput &input = step.Textures[index]; int filter = (input.Filter == PPFilterMode::Nearest) ? GL_NEAREST : GL_LINEAR; int wrap = (input.Wrap == PPWrapMode::Clamp) ? GL_CLAMP : GL_REPEAT; switch (input.Type) { default: case PPTextureType::CurrentPipelineTexture: BindCurrentTexture(index, filter, wrap); break; case PPTextureType::NextPipelineTexture: I_FatalError("PPTextureType::NextPipelineTexture not allowed as input\n"); break; case PPTextureType::PPTexture: GLTextures[input.Texture].Bind(index, filter, wrap); break; case PPTextureType::SceneColor: BindSceneColorTexture(index); break; case PPTextureType::SceneFog: BindSceneFogTexture(index); break; case PPTextureType::SceneNormal: BindSceneNormalTexture(index); break; case PPTextureType::SceneDepth: BindSceneDepthTexture(index); break; } } // Set render target switch (step.Output.Type) { default: I_FatalError("Unsupported postprocess output type\n"); break; case PPTextureType::CurrentPipelineTexture: BindCurrentFB(); break; case PPTextureType::NextPipelineTexture: BindNextFB(); break; case PPTextureType::PPTexture: if (GLTextureFBs[step.Output.Texture]) GLTextureFBs[step.Output.Texture].Bind(); else GLTextureFBs[step.Output.Texture] = CreateFrameBuffer(step.Output.Texture.GetChars(), GLTextures[step.Output.Texture]); break; case PPTextureType::SceneColor: BindSceneFB(false); break; } // Set blend mode if (step.BlendMode.BlendOp == STYLEOP_Add && step.BlendMode.SrcAlpha == STYLEALPHA_One && step.BlendMode.DestAlpha == STYLEALPHA_Zero && step.BlendMode.Flags == 0) { glDisable(GL_BLEND); } else { // To do: support all the modes glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); if (step.BlendMode.SrcAlpha == STYLEALPHA_One && step.BlendMode.DestAlpha == STYLEALPHA_One) glBlendFunc(GL_ONE, GL_ONE); else glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } // Setup viewport glViewport(step.Viewport.left, step.Viewport.top, step.Viewport.width, step.Viewport.height); auto &shader = GLShaders[step.ShaderName]; // Set uniforms if (step.Uniforms.Data.Size() > 0) { if (!shader->Uniforms) shader->Uniforms.reset(screen->CreateDataBuffer(POSTPROCESS_BINDINGPOINT, false)); shader->Uniforms->SetData(step.Uniforms.Data.Size(), step.Uniforms.Data.Data()); shader->Uniforms->BindBase(); } // Set shader shader->Bind(NOQUEUE); // Draw the screen quad GLRenderer->RenderScreenQuad(); // Advance to next PP texture if our output was sent there if (step.Output.Type == PPTextureType::NextPipelineTexture) NextTexture(); } glViewport(screen->mScreenViewport.left, screen->mScreenViewport.top, screen->mScreenViewport.width, screen->mScreenViewport.height); FGLDebug::PopGroup(); }