티스토리 뷰

Game/작업일지

Linearize Z

newpolaris 2018. 10. 12. 00:25

매번 까먹고 고통받는 부분

OpenGL 쪽 구현하려니 기억이 안난다

우선, 오차에 대해 조사한 부분인듯

https://mynameismjp.wordpress.com/2010/03/22/attack-of-the-depth-buffer/

내껀 LightScattering 소스의 depth test branch 에 대강

  • DirectX 의 LH / RH 개형

https://docs.microsoft.com/en-us/windows/desktop/direct3d9/d3dxmatrixperspectivefovlh

  • DirectX Linear Z 와 Reverse Z 에 대한 간단한 설명

http://dev.theomader.com/depth-precision/

  • Ray-MMD (DirectX 9.0)

Position 의 W 를 linearDepth 라 두고, 아래과 같이 사용, (Z 랑 값이 같음)

view = mul(Position, matProjectInverse).xyz
float3 viewPosition = view * material.linearDepth / view.z;

0 - 1 사이가 아닌, 그냥 z 값임

  • Mikudayo DirectX 11

https://github.com/newpolaris/Mikudayo/blob/Mikudayo/Core/Shaders/LinearizeDepthCS.hlsl

https://github.com/newpolaris/Mikudayo/blob/master/Mikudayo/Shaders/CommonInclude.hlsli

ScreenToView 라고 되어있다

그냥 1.0 / (depth / Near * (Far - Near) + 1.0) 이거 해석을 파일에 적어뒀는지 모르것음

  • GTEngine (DirectX)

https://www.geometrictools.com/GTEngine/Samples/Graphics/MultipleRenderTargets/Shaders/MultipleRenderTargets.hlsl

// For Direct3D, perspective depth d is computed from the camera
// z-value (view direction component) and the near and far plane
// values n and f using d = f*(1-n/z)/(f-n), where z in [n,f] and
// d in [0,1].  The values of perspectiveDepth are the interpolated
// d-values computed by the rasterizer.  Solve for linear depth
// L = (z-n)/(f-n) in [0,1] to obtain L = d/(r*(1-d)+d) where r = f/n.

float d = input.perspectiveDepth;
output.linearDepth = d / (farNearRatio * (1.0f - d) + d);
return output;
  • The danger zone

BakingLap 소스 찾는게 더 나을 듯

https://mynameismjp.wordpress.com/2010/09/05/position-from-depth-3/

  • reversed z in openGL

https://nlguillemot.wordpress.com/2016/12/07/reversed-z-in-opengl/

  • OpenGL projectio matrix 이용 (orthographic 포함)

https://github.com/pissang/claygl-advanced-renderer/blob/master/src/SSR.glsl

 projection[3][2] / (depth * projection[2][3] - projection[2][2])

https://stackoverflow.com/questions/51108596/linearize-depth

  • OpenGL (oliver 꺼 참고 할것)

http://www.geeks3d.com/20091216/geexlab-how-to-visualize-the-depth-buffer-in-glsl/

float LinearizeDepth(vec2 uv)
{
  float n = 1.0; // camera z near
  float f = 100.0; // camera z far
  float z = texture2D(depthSampler, uv).x;
  return (2.0 * n) / (f + n - z * (f - n));    
}
  • OpenGL / reconstruction (oliver 꺼 참고 할껏)

https://enginetrouble.net/2016/10/reconstructing-world-position-from-depth-2016.html#fn:3

  • gl_FragCoord.z / gl_FragCoord.w

https://stackoverflow.com/questions/13711252/what-does-gl-fragcoord-z-gl-fragcoord-w-represent?noredirect=1&lq=1

clip.w = -view.z
clip.z = A*view.z+B
ndc.z = clip.z / clip.w

// Transform to window coordinates,
// using the glDepthRange near/far values.
// default dfar = 1, dnear = 0
win.z = ((dfar-dnear)/2) * ndc.z + (dfar+dnear)/2
  • OpenGL 자세한 설명

http://web.archive.org/web/20130416194336/http://olivers.posterous.com/linear-depth-in-glsl-for-real

float A = gl_ProjectionMatrix[2].z;
float B = gl_ProjectionMatrix[3].z;
float zNear = - B / (1.0 - A);
float zFar  =   B / (1.0 + A);
//    float depthFF = 0.5*(-A*depth + B) / depth + 0.5;
//    float depthFF = gl_FragCoord.z;
//    gl_FragDepth  = depthFF;

gl_FlagCoord.z가 0.5*(gl_Position.z / gl_Position.w) + 0.5 라고 한다 그리고 그게 Depth로 기록된다네

z_e = 2*zFar*zNear / (zFar + zNear - (zFar - zNear)*(2*z_b -1))

view.z는 위를 통해 계산해야하는데

위의 geeks3D와 engine error 에서는 -1 to 1 로 안바꾸고

거기서 나온 z 값에 zFar를 나눈 형태라고 틀렸다고 하네

  • gl_FragDepth, gl_Position, early depth test

https://learnopengl.com/Advanced-OpenGL/Advanced-GLSL

https://learnopengl.com/Advanced-OpenGL/Depth-testing

float LinearizeDepth(float depth) 
{
    float z = depth * 2.0 - 1.0; // back to NDC 
    return (2.0 * near * far) / (far + near - z * (far - near));    
}

void main()
{             
    float depth = LinearizeDepth(gl_FragCoord.z) / far; // divide by far for demonstration
    FragColor = vec4(vec3(depth), 1.0);
}
  • 결론적으로 결국 어떻게든 값을 정해서 복원만 가능하면 되는거라

https://stackoverflow.com/questions/28066906/reconstructing-world-position-from-linear-depth

https://www.shellblade.net/unprojection.html

Depth = -p.z/Far; // z is negative in view space, negate to leave in [0,1]

'Game > 작업일지' 카테고리의 다른 글

Water Flow in Portal 2  (0) 2018.11.06
uniform update 수작업으로 진행 할 때의 고통  (0) 2018.10.24
2018.10.24 - OpenGL 작업 20일 째  (0) 2018.10.23
Normal Encode  (0) 2018.10.17
Automatic Exposure  (0) 2018.09.19
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크