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();
}
Exemple #2
0
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();
}