关于OpenGL nativeZ 到 LinearZ 精度缺失问题探究

我再看其他引擎的时候看到一个点,就是他先渲染不透明物体到NativeZ,后面根据这个深度图,得到LinearZ

这里OpenGL教程里面也有

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

然后周末我自己也这样做了,后面反复思考这样有没有问题

下面是我做的实验代码

投影矩阵我是看这里写的

https://zhuanlan.zhihu.com/p/73034007

 

#include<stdio.h>
#include<conio.h>
#include<windows.h>
#include<iostream>
#include <cassert>

//计算nativeZ
float NativeZ(float nearv, float farv, float EyePosZ)
{
    
    float zx = (farv + nearv) / (farv - nearv) + (2.0 * farv* nearv / (farv - nearv)) / EyePosZ;
    return zx;
}

//NativeZ to LinearZ
float LinearizeDepth(float nearv,float farv,float Nativedepth)
{
    float z = Nativedepth * 2.0 - 1.0; // back to NDC 
    return (2.0 * nearv * farv) / (farv + nearv - z * (farv - nearv)) /(farv -nearv);
}

//自己计算LinearZ,不依赖NativeZ
float MyLinearCalc(float nearv, float farv, float eyePosZ)
{
    float zv = -eyePosZ; //Opengl相机空间里 z是负值

    float x = (zv -nearv) / (farv - nearv);

    return x;
}

const float CameraFar = 4000;
const float CameraNear = 2;


int main()
{
    const int stepN = 40;
    for (int n = 0; n < stepN; ++n)
    {
        float eyePosZ = -n * (CameraFar -CameraNear) / (float)stepN - CameraNear;
        float nativeZ = NativeZ(CameraNear, CameraFar, eyePosZ);
        float linearv = LinearizeDepth(CameraNear, CameraFar, nativeZ);
        float myCalcZ = MyLinearCalc(CameraNear, CameraFar, eyePosZ);


        printf("nativeZ:%f  %f  %f \n", nativeZ,linearv,myCalcZ);
    }
    int delay;
    scanf("%d",&delay);
}

代码很容易,先计算NativeZ,然后这个NativeZ 变换到Linearz,这是float32 的精度

这里写错了,有空来改

 

posted on 2021-05-17 09:11  c_dragon  阅读(93)  评论(0编辑  收藏  举报

导航