ScreenPosition differs in OpenGL and DirectX

Using the ScreenPosition node in a material yields to different results in DirectX and OpenGL since they have different View space reference coordinates systems. For instance trying to make a parallax effect on a background sky material makes it move in the wrong vertical direction in one of the two platforms unless you add a manual factor set from code.

This may be intentional or a bug, but in any case it would be good to have a unified way to use screen position across platforms without having to resort to code like this:

// Set the screen ratio information
FVector2D ViewportSize(1, 1);
float Up = 1.0f;

if (GetWorld() && GetWorld()->GetGameViewport())
{
	auto Viewport = GetWorld()->GetGameViewport();
	Viewport->GetViewportSize(ViewportSize);
}

// Mega-hack :(
if (IsOpenGLPlatform(GMaxRHIShaderPlatform))
{
	Up = -1.0f;
}

FVector ScreenRatio = FVector(ViewportSize.X / ViewportSize.Y, Up, 0);
Instance->SetVectorParameterValue("ScreenPositionFactor", ScreenRatio);

I don’t think this is a bug. I have seen this in other game engines as well. Not sure why there is a difference. Might be the same as the difference of having left and right handed coordinate systems in render engines.

The difference is there because OpenGL and DirectX have different intermediate steps in the transformation pipeline for visualisation. The point is that i think this should be hidden to the users the same wah GLSL and HLSL are hidden :).

Thanks, learned something new :smiley:

Hey Anticto!

Just updating this thread as there have been some improvements to the ScreenPosition material expression and the way that it functions in 4.11 Preview 7, which is available in the launcher now.

You should find, now, that the viewspace reference coordinate systems for the ScreenPosition material expression function the same in OpenGL and DirectX. (no more inverse parallaxing!)

Additionally, you now have options on how to apply the values output by the material node:

SceneTextureUV: This is the old behavior of the node. It maps to the actual texture (more correctly its render target) and is potentially larger than the viewport. Useful for lookups into the Gbuffer for use with the ScreenTexture material expression.

ViewportUV: Uses the the viewport space and resizes the coordinates to match the viewport as it scales in the editor.

Hope this is helpful!

Regards,
Zac Wilson