KhronosGroup / glslang

Khronos-reference front end for GLSL/ESSL, partial front end for HLSL, and a SPIR-V generator.
Other
2.9k stars 814 forks source link

GLSL: Add a option to fix up clip space. #2944

Open chirsz-ever opened 2 years ago

chirsz-ever commented 2 years ago

OpenGL uses the NDC with z of [-1, 1], and Vulkan, DirectX, Metal use the NDC with z of [0, 1].

When we want fix a vertex shader originally written for OpenGL, we can add an extra line:

gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;

Or generate SPIR-V code of this meaning.

SPIRV-Cross has an option for it.

Like #2936, I want use the same source code of shaders for OpenGL and Vulkan.

greg-lunarg commented 2 years ago

OK. But this indeed can only be done under a new option. We can't regress code that has already taken this into account.

Note that #2936 is asking for the same transformation for GLSL as is done for HLSL. For fixup-clipspace, should we do for HLSL what is being requested for GLSL?

chirsz-ever commented 2 years ago

The strategy of SPIRV-Cross's fixup_clipspace option is:

For GLSL targets, enabling this will convert a shader which assumes [0, w] depth range (Vulkan / D3D / Metal) into [-w, w] range. For MSL and HLSL targets, enabling this will convert a shader in [-w, w] depth range (OpenGL) to [0, w] depth range.

IMO, this is because D3D and Metal have NDCs with [0, 1] z-range and OpenGL has a [-1, 1] z-range.

An HLSL shader always assumes that the NDC z-range is [0, 1], so we don't need to worry about it when convert it to SPIR-V for Vulkan.

But there are also SPIR-V for OpenGL and glslang support it. In this case maybe we need add a line to transform Z-coordinate form [0, 1] to [-1. 1]:

gl_Position.z = gl_Position.z * 2.0 - gl_Position.w;

I think this kind of situations is very rare.

My conclusion is, the --fixup-clipspace option should not be allowed or do the [0, w] to [-w, w] transformation if the source code format is HLSL.