加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

opengl – perlin噪声的每顶点法线?

发布时间:2020-12-15 21:48:50 所属栏目:大数据 来源:网络整理
导读:我在Opengl几何着色器中生成地形,并且无法计算照明法线.我在每个帧中动态生成地形,并在几何着色器中实现了perlin噪声函数.因此,我需要一种基于噪声函数(无纹理或任何东西)计算每顶点法线的有效方法.我可以采用2面的交叉积来获得面法线,但它们是用几何体动态
我在Opengl几何着色器中生成地形,并且无法计算照明法线.我在每个帧中动态生成地形,并在几何着色器中实现了perlin噪声函数.因此,我需要一种基于噪声函数(无纹理或任何东西)计算每顶点法线的有效方法.我可以采用2面的交叉积来获得面法线,但它们是用几何体动态生成的,所以我不能再返回并平滑顶点法线的面法线.如何使用在y平面中生成地形高度的噪声函数(因此高度在1和-1之间),即时获取顶点法线.我相信我必须为每个顶点对噪声函数进行4次采样,但我尝试了类似下面的内容并且它不起作用……
vec3 xP1 = vertex + vec3(1.0,0.0,0.0);
vec3 xN1 = vertex + vec3(-1.0,0.0);
vec3 zP1 = vertex + vec3(0.0,1.0);
vec3 zN1 = vertex + vec3(0.0,-1.0);

float sx = snoise(xP1) - snoise(xN1);
float sz = snoise(zP1) - snoise(zN1);

vec3 n = vec3(-sx,1.0,sz);
normalize(n);

return n;

以上实际产生的照明像perlin噪音一样四处移动!那么关于如何正确获得每顶点法线的任何建议?

解决方法

你没有确切地说你实际上是如何产生这些职位的.因此,我将假设您使用Perlin噪声在高度图中生成高度值.因此,对于hieghtmap中的任何位置X,Y,您使用2D噪声函数来生成Z值.

所以,我们假设您的位置计算如下:

vec3 CalcPosition(in vec2 loc) {
    float height = MyNoiseFunc2D(loc);
    return vec3(loc,height);
}

这会生成3D位置.但这个位置在哪个空间?这就是问题所在.

大多数噪声函数都希望loc在某个特定的浮点范围内是两个值.您的噪声函数有多好将决定您可以传入值的范围.现在,如果您的模型空间2D位置不能保证在噪声函数的范围内,那么您需要将它们转换为该范围,进行计算,以及然后将其转换回模型空间.

这样,您现在拥有3D位置. X和Y值的变换很简单(与噪声函数空间的变换相反),但是Z的变换是什么?在这里,你必须在高度上应用某种比例.噪声函数将返回范围[0,1]上的数字,因此您需要将此范围缩放到与X和Y值相同的模型空间.这通常通过选择最大高度并适当地缩放位置来完成.因此,我们修改的计算位置看起来像这样:

vec3 CalcPosition(in vec2 modelLoc,const in mat3 modelToNoise,const in mat4 noiseToModel)
{
    vec2 loc = modelToNoise * vec3(modelLoc,1.0);
    float height = MyNoiseFunc2D(loc);
    vec4 modelPos = noiseToModel * vec4(loc,height,1.0);
    return modelPos.xyz;
}

两个矩阵转换为噪声函数的空间,然后转换回来.您的实际代码可能会使用不太复杂的结构,具体取决于您的用例,但完整的仿射变换很容易描述.

好了,既然我们已经确定了这一点,那么你需要记住的是:除非你知道它处于什么空间,否则没有任何意义.你的正常,你的立场,没有关系,直到你确定它所处的空间.

此函数返回模型空间中的位置.我们需要计算模型空间中的法线.要做到这一点,我们需要3个位置:顶点的当前位置,以及稍微偏离当前位置的两个位置.我们获得的位置必须在模型空间中,否则我们的正常情况不会.

因此,我们需要具备以下功能:

void CalcDeltas(in vec2 modelLoc,const in mat4 noiseToModel,out vec3 modelXOffset,out vec3 modelYOffset)
{
    vec2 loc = modelToNoise * vec3(modelLoc,1.0);
    vec2 xOffsetLoc = loc + vec2(delta,0.0);
    vec2 yOffsetLoc = loc + vec2(0.0,delta);
    float xOffsetHeight = MyNoiseFunc2D(xOffsetLoc);
    float yOffsetHeight = MyNoiseFunc2D(yOffsetLoc);
    modelXOffset = (noiseToModel * vec4(xOffsetLoc,xOffsetHeight,1.0)).xyz;
    modelYOffset = (noiseToModel * vec4(yOffsetLoc,yOffsetHeight,1.0)).xyz;
}

显然,您可以将这两个函数合并为一个.

增量值是噪声纹理输入空间中的小偏移量.此偏移的大小取决于您的噪声功能;它需要足够大才能返回与实际当前位置返回的高度明显不同的高度.但它需要足够小,以免你从噪声分布的随机部分中拉出来.

你应该了解你的噪音功能.

现在您在模型空间中有三个位置(当前位置,x偏移和y偏移),您可以在模型空间中计算顶点法线:

vec3 modelXGrad = modelXOffset - modelPosition;
vec3 modelYGrad = modelYOffset - modelPosition;

vec3 modelNormal = normalize(cross(modelXGrad,modelYGrad));

从这里开始做常规事.但永远不要忘记跟踪各种向量的空间.

哦,还有一件事:这应该在顶点着色器中完成.在几何着色器中没有理由这样做,因为没有计算影响其他顶点.让GPU的并行性为您服务.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读