重新计算规则网格表面的法线(C ++ / OpenGL)

问题描述 投票:0回答:1

我正在尝试计算网格曲面的法线。地图为29952px x 19968px,每个单元格为128px x 128px。所以我有36895个顶点。

网格:Grid

我的平面地图数组发送到具有以下结构的着色器:

float vertices[368950] = {

  //  x     y     z    znoise   xTex  yTex  xNorm yNorm zNorm Type
    16384,16256,-16256,   0,    0.54, 0.45,   0,    0,   1,    1,
    16256,16384,-16384,   0,    0.54, 0.45,   0,    0,   1,    1,
    ......
} 

我用函数计算zNoise

float noise(float x, float y){};

并且它有效[[(我将其添加到顶点着色器中的y和z中]。

方法1

如果我使用

有限差分法]计算法线,则可以获得很好的结果。伪代码:

vec3 off = vec3(1.0, 1.0, 0.0); float hL = noise(P.xy - off.xz); float hR = noise(P.xy + off.xz); float hD = noise(P.xy - off.zy); float hU = noise(P.xy + off.zy); N.x = hL - hR; N.y = hD - hU; N.z = 2.0; N = normalize(N);
但是,在这种情况下,我需要手动编辑地图,例如在编辑器上下文中,您可以使用工具设置zNoise以根据需要创建山脉,此方法

无济于事

我得到了这个不错的结果(从小地图上可以看到)(故意使法线很暗):nice result

方法2

| | | --6----1----+- |\ |\ | Y | \ | \ | ^ | \ | \ | | | \| \| | --5----+----2-- +-----> X |\ |\ | | \ | \ | | \ | \ | | \| \| --+----4----3-- | | |

所以我试图使用相邻的三角形来计算法线,但结果却大不相同(似乎某处存在错误):

代码。

getVertex()是一个使用x且y返回与该顶点关联的顶点信息的函数。 VerticesPos是一维数组,其中包含

每个顶点的位置

,以便能够从vertices(上述的i,每个顶点具有10个值)中获取信息。我决定在顶点着色器中编辑y和z以保持x和y不变,并使用它们通过VerticesPos进行索引顶点。 (我希望这很清楚)。
glm::vec3 getVertex(int x, int y) { int j = VerticesPos[(int)(y/128 * 29952 / 128 + x/128)]; float zNoise = vertices[j * 10 + 3] * 2; float x1 = vertices[j * 10]; float y1 = vertices[j * 10 + 1] + zNoise; float z1 = vertices[j * 10 + 2] + zNoise; return glm::vec3(x1, y1, z1); }
getAdjacentVertices()是一个函数,它接受vec2d(x和y坐标)并返回

6个相邻顶点

,按顺时针方向排序std::array<glm::vec3, 6> getAdjacentVertices(glm::vec2 pos) { std::array<glm::vec3, 6> output; output = { getVertex(pos.x, pos.y + 128), // up getVertex(pos.x + 128, pos.y), // right getVertex(pos.x + 128, pos.y - 128), // down-right getVertex(pos.x, pos.y - 128), // down getVertex(pos.x - 128, pos.y), // left getVertex(pos.x - 128, pos.y + 128), // up-left }; return output; }
以及完成任务的最后一个功能:

glm::vec3 mapgen::updatedNormals(glm::vec2 pos) { bool notBorderLineX = pos.x > 128 && pos.x < 29952 - 128; bool notBorderLineY = pos.y > 128 && pos.y < 19968 - 128; if (notBorderLineX && notBorderLineY) { glm::vec3 a = getVertex(pos.x, pos.y); std::array<glm::vec3, 6> adjVertices = getAdjacentVertices(pos); glm::vec3 sum(0.f); for (int i = 0; i < 6; i++) { int j; (i == 0) ? j = 5 : j = i - 1; glm::vec3 side1 = adjVertices[i] - a; glm::vec3 side2 = adjVertices[j] - a; sum += glm::cross(side1, side2); } return glm::normalize(sum); } else { return glm::vec3(0.3333f); } }

很不幸,我得到了这个bad result(从小地图上看到):bad result

注意:使用两种方法,建筑物位于不同的位置,但表面

具有相同的种子

有人可以帮忙吗? :-)


编辑:

我添加了更多图像以帮助理解问题。方法1:“

方法2:“

我正在尝试计算网格曲面的法线。地图为29952px x 19968px,每个单元格为128px x 128px。所以我有36895个顶点。网格:我的平面地图数组通过...

c++ opengl glm-math vertex-shader normals
1个回答
© www.soinside.com 2019 - 2024. All rights reserved.