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 \n",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\n", eyePosZ,reverseZv,nativeZ, eyeposNativ,lineardepthold, myCalcZ); } int delay; scanf("%d",&delay); }
为了展示,我线性化后的,否则一片漆黑