是否有可能从数学角度根据高度图纹理生成法线贴图?

时间:2015-05-18 11:37:41

标签: opengl graphics computational-geometry

我的观点是你不能只从高度图纹理生成法线贴图? 我是对还是不对?

数学参数:

假设表面具有连续的双射

enter image description here

S = [0,1]

T = [0,1]

让我们将SxT称为图像空间。

可以从差分几何中证明,与参数曲面垂直

enter image description here

如果假设从SxT图像空间到几何欧几里德空间的映射非常简单,那么我们可以进行检索:

enter image description here

然后你可以用一些差分格式计算这种偏导数。 我们来到这个简单的公式,只有粗体的建议,这个建议绝对不是真的。

来自图片的问题示例

假设我们在几何eclidian空间中有三个顶点的三角形。 条款是:

normalmap - 对于从(u,v)取得的(u,v,1-u-v)重心坐标从适当的2d纹理得到的点是正常的,并且它在局部坐标中。系统相对于三角形。

heihtmap - 相对于从(u,v)从适当的2d纹理中取出的三角形局部空间,在法线方向上的(u,v,1-u-v)重心坐标是点的几何偏移。

在构建法线贴图期间,我们绝对忽略高度贴图如何分布在(u,v,1-u-v)eculidian点附近。我们只检索一些法线贴图的近似值。

2 个答案:

答案 0 :(得分:0)

哦,看起来我的评论太简短了。

使用代码编写完整的答案来描述方法会更容易。

我将使用C ++和GLSL的伪代码混合。

constexpr int width = 32, height = 32;
constexpr float height_scale = 16.0f; // Change if necessary.

float hmap[W][H] = {...};
float normalmap[W][H];

vec3 GetPoint(ivec2 a)
{
    a.x %= W;
    a.y %= H;
    return {a.x, a.y, hmap[a.x][a.y] * height_scale};
}

vec3 GetNormal(ivec2 a, bool loop_hmap)
{
    vec3 o = GetPoint(a),
         a = GetPoint({a.x + 1, a.y}),
         b = GetPoint({a.x, a.y + 1}),
         c = GetPoint({a.x - 1, a.y}),
         d = GetPoint({a.x, a.y - 1});
    vec3 n1 = normalize(cross(a-o, b-o));
    vec3 n2 = normalize(cross(b-o, c-o));
    vec3 n3 = normalize(cross(c-o, d-o));
    vec3 n4 = normalize(cross(d-o, a-o));

    if (loop_hmap)
        return normalize(n1+n2+n3+n4);
    else
    {
        vec3 sum = {0,0,0};
        bool b1 = (a.x+1 >= 0 && a.y >= 0 && a.x+1 < W && a.y < H);
        bool b2 = (a.x >= 0 && a.y+1 >= 0 && a.x < W && a.y+1 < H);
        bool b3 = (a.x-1 >= 0 && a.y >= 0 && a.x-1 < W && a.y < H);
        bool b4 = (a.x >= 0 && a.y-1 >= 0 && a.x < W && a.y-1 < H);
        if (b1 && b2) sum += n1;
        if (b2 && b3) sum += n2;
        if (b3 && b4) sum += n3;
        if (b4 && b1) sum += n4;
        return normalize(sum);
    }
}

int main()
{
    for (int i = 0; i < H; i++)
        for (int j = 0; j < W; j++)
            normalmap[j][i] = GetNormal(j, i, 0);
}
loop_hmap

GetNormal()参数更改函数如何计算边缘像素的法线。 1应该用于平铺纹理,如沙子和水。 0应该用于非物品纹理,例如物品,小怪物,树木。

答案 1 :(得分:0)

对我来说,我自己的初步问题是无效的,它有一个错误!!!

  

I - 原始参数曲面,域为[0,1]的笛卡尔积,其范围为欧氏空间

     

II - 与原始表面垂直

     

III - 用高度图修改原始表面

     

IV - 我们想要接收的法线贴图,甚至忽略表面的几何修改“III”

enter image description here

最后的第四步包括很多要区分的东西:H(s,t)和函数的原始定义......我不会对这些方程进行进一步的分析......但对我来说,你可以& #39; t仅从(heightmap)...

生成法线贴图

P.S。要进行进一步的分析,如果你想这样做,请从该地点检索* .docx文件https://yadi.sk/d/Qqx-jO1Ugo3uL我知道无法将ms中的公式转换为乳胶,但无论如何请将其用作草稿。