我尝试使用OpenGL - How to calculate normals in a terrain height grid?中描述的算法。我在我的顶点着色器中弹出它并使用一些perlin噪声函数来测试它,它就像一个魅力,但当我将它移植到Java时,它没有那么好用。
float nx = 0;
float ny = 0;
float nz = 0;
Vector3 P = new Vector3(vpx,vpy,vpz);
Vector3 off = new Vector3(1,1,0);
float hL = tryGetHeight(_mempoints2,P.x - off.x,P.z - off.z);
float hR = tryGetHeight(_mempoints2,P.x + off.x,P.z + off.z);
float hD = tryGetHeight(_mempoints2,P.x - off.z,P.z - off.y);
float hU = tryGetHeight(_mempoints2,P.x + off.z,P.z + off.y);
nx = hL - hR;
ny = hD - hU;
nz = 2.0f;
Vector3 v = new Vector3(nx,ny,nz);
v = v.nor();
nx = v.x;
ny = v.y;
nz = v.z;
顶点着色器中算法的结果:
我的缓冲区设置中的算法结果:
(很抱歉模糊不清,当我拍摄这些东西时,我正在测试一些景深。)
答案 0 :(得分:0)
顶点着色器中算法的结果:
不应在任何着色器阶段计算法线。顶点着色器没有关于相邻顶点的信息,几何着色器是一个性能值,tesselation着色器只能为本地tesselation提供法线。在片段着色器中进行屏幕空间正常计算是很奇怪的。预先计算CPU上的法线并将它们作为另一个顶点属性传递。
v = v.nor();
nor
功能不符合您的想法。它将矢量标准化为单位长度。 (矢量归一化= / =表面法线计算)。要计算法线,您必须计算局部斜率向量的叉积。
答案 1 :(得分:0)
你走在正确的轨道上。您尝试计算的交叉产品是
(1, 0, (R-L)/2)
x (0, 1, (U-D)/2)
-----------------
(-(R-L)/2, -(U-D)/2, 1)
与向量
具有相同的方向(L-R,D-U,2)
标准化后你有
N = norm(L-R,D-U,2)
你的左,右,上,下表面高度是
L = height(P.x - 1, P.y)
R = height(P.x + 1, P.y)
U = height(P.x, P.y + 1)
D = height(P.x, P.y - 1)
如果你看起来有一些错误的标志和不匹配的下标。