OpenGL ReverseZ

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

测试代码

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

//计算nativeZ
float NativeZ(double nearv, double farv, double EyePosZ)
{
    /*
    float a = -(farv + nearv) / (farv - nearv);
    float b = -(2.0 * farv* nearv / (farv - nearv));
    float depthv =  (a *EyePosZ + b) / -EyePosZ;  //模拟除以w值, -zeye的值
    return depthv;*/

    float a = -(farv + nearv) / (farv - nearv) *EyePosZ;
    float b = -(2.0 * farv* nearv / (farv - nearv));
    float depthv = (a  + b) / -EyePosZ;  //模拟除以w值, -zeye的值
    return depthv; 
}


float ReverseZ(double nearz, double farz, double EyePosZ)
{
    float a = nearz / (farz - nearz);
    float b = farz * nearz / (farz- nearz);

    float depthv = (a *EyePosZ  + b) / -EyePosZ;  //模拟除以w值, -zeye的值

    return depthv;
}


//NativeZ to LinearZ
float LinearizeDepth(float nearv,float farv,float Nativedepth)
{
    float a = -(farv + nearv) / (farv - nearv);
    float b = -(2.0 * farv* nearv / (farv - nearv));

    //float z = Nativedepth * 2.0 - 1.0; // back to NDC 
    //return (2.0 * nearv * farv) / (farv + nearv - z * (farv - nearv)) ;

    float eyeposZ = -b / (a + Nativedepth);

    return (-eyeposZ -nearv) /(farv -nearv);
}

//NativeZ to LinearZ
float LinearizeDepthold(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)) - nearv) / (farv - nearv);
}

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

    float x = (zv -nearv) ;

    return x /(farv - nearv);
}

float ReverseZToLinear(float nearz, float farz, float reversedz)
{
    float a = nearz / (farz - nearz);
    float b = farz * nearz / (farz - nearz);

    float eyeposZ = -b / (a + reversedz);

    return eyeposZ ;
}





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


int main()
{
    const int stepN = 400;
    /*
    for (int n = 0; n < stepN; ++n)
    {
        float eyePosZ = -n * (CameraFar -CameraNear) / (float)stepN - CameraNear;
        float nativeZ = NativeZold(CameraNear, CameraFar, eyePosZ);
        float linearv = LinearizeDepthold(CameraNear, CameraFar, nativeZ * 0.50 -0.50);
        float myCalcZ = MyLinearCalcold(CameraNear, CameraFar, eyePosZ);
        
        float newNativeZ = NativeZ(CameraNear, CameraFar, eyePosZ);
        float newLinearZ = LinearizeDepth(CameraNear, CameraFar, nativeZ);
        printf("nativeZ:%f  %f  %f %f  %f  %f 
",eyePosZ, nativeZ,newNativeZ, linearv,myCalcZ ,newLinearZ);
    }*/

    
    for (unsigned int n = 0; n <= stepN; ++n)
    {
        float oneStep = (CameraFar - CameraNear) / (float)stepN;
        float eyePosZ = -(n * oneStep )- CameraNear;
        float reverseZv = ReverseZ(CameraNear, CameraFar, eyePosZ);
        float nativeZ = NativeZ(CameraNear, CameraFar, eyePosZ) ;
        float eyeposRev = ReverseZToLinear(CameraNear, CameraFar, reverseZv);
        float eyeposNativ = LinearizeDepth(CameraNear, CameraFar, nativeZ);
        float myCalcZ = MyLinearCalc(CameraNear, CameraFar, eyePosZ);
        float lineardepthold = LinearizeDepthold(CameraNear, CameraFar, nativeZ * 0.5f+ 0.5);
        printf("nativeZ:%f  %f  -- %f  %f  %f  %f
", eyePosZ,reverseZv,nativeZ,  eyeposNativ,lineardepthold, myCalcZ);
    }

    int delay;
    scanf("%d",&delay);
}

为了展示,我线性化后的,否则一片漆黑

原文地址:https://www.cnblogs.com/dragon2012/p/14880373.html