可以法线贴图从纹理生成的? [英] Can normal maps be generated from a texture?

查看:195
本文介绍了可以法线贴图从纹理生成的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有质感,是它然后可以产生一个正常的地图为这个纹理,因此它可用于凹凸映射

If I have a texture, is it then possible to generate a normal-map for this texture, so it can be used for bump-mapping?

或者如何法线贴图通常由?

Or how are normal maps usually made?

推荐答案

是的。嗯,有点。法线贴图可以从高度地图中精确地进行。通常情况下,你也可以通过把一个普通的纹理和获得不俗成绩为好。记住有使得正常映射的其他方法,如采取高分辨率模式,使得它低的分辨率,然后做光线投射到看到正常应该是什么低分辨率模型来模拟的较高者。

Yes. Well, sort of. Normal maps can be accurately made from height-maps. Generally, you can also put a regular texture through and get decent results as well. Keep in mind there are other methods of making a normal map, such as taking a high-resolution model, making it low resolution, then doing ray casting to see what the normal should be for the low-resolution model to simulate the higher one.

有关高度的地图正常的地图,你可以使用 Sobel算。此操作员可在x方向上运行,告诉你在正常的x分量,然后在y方向上,告诉你的y分量。你可以计算与 1.0 /强度其中,实力是强调或法线贴图的深度Z。然后,采取的x,y和z,扔进一个载体,它正常化,你有你的正常在这一点上。恩code入像素就大功告成了。

For height-map to normal-map, you can use the Sobel Operator. This operator can be run in the x-direction, telling you the x-component of the normal, and then the y-direction, telling you the y-component. You can calculate z with 1.0 / strength where strength is the emphasis or "deepness" of the normal map. Then, take that x, y, and z, throw them into a vector, normalize it, and you have your normal at that point. Encode it into the pixel and you're done.

下面是一些老incomplete- code,它说明了这一点:

Here's some older incomplete-code that demonstrates this:

// pretend types, something like this
struct pixel
{
    uint8_t red;
    uint8_t green;
    uint8_t blue;
};

struct vector3d; // a 3-vector with doubles
struct texture; // a 2d array of pixels

// determine intensity of pixel, from 0 - 1
const double intensity(const pixel& pPixel)
{
    const double r = static_cast<double>(pPixel.red);
    const double g = static_cast<double>(pPixel.green);
    const double b = static_cast<double>(pPixel.blue);

    const double average = (r + g + b) / 3.0;

    return average / 255.0;
}

const int clamp(int pX, int pMax)
{
    if (pX > pMax)
    {
        return pMax;
    }
    else if (pX < 0)
    {
        return 0;
    }
    else
    {
        return pX;
    }
}

// transform -1 - 1 to 0 - 255
const uint8_t map_component(double pX)
{
    return (pX + 1.0) * (255.0 / 2.0);
}

texture normal_from_height(const texture& pTexture, double pStrength = 2.0)
{
    // assume square texture, not necessarily true in real code
    texture result(pTexture.size(), pTexture.size());

    const int textureSize = static_cast<int>(pTexture.size());
    for (size_t row = 0; row < textureSize; ++row)
    {
        for (size_t column = 0; column < textureSize; ++column)
        {
            // surrounding pixels
            const pixel topLeft = pTexture(clamp(row - 1, textureSize), clamp(column - 1, textureSize));
            const pixel top = pTexture(clamp(row - 1, textureSize), clamp(column, textureSize));
            const pixel topRight = pTexture(clamp(row - 1, textureSize), clamp(column + 1, textureSize));
            const pixel right = pTexture(clamp(row, textureSize), clamp(column + 1, textureSize));
            const pixel bottomRight = pTexture(clamp(row + 1, textureSize), clamp(column + 1, textureSize));
            const pixel bottom = pTexture(clamp(row + 1, textureSize), clamp(column, textureSize));
            const pixel bottomLeft = pTexture(clamp(row + 1, textureSize), clamp(column - 1, textureSize));
            const pixel left = pTexture(clamp(row, textureSize), clamp(column - 1, textureSize));

            // their intensities
            const double tl = intensity(topLeft);
            const double t = intensity(top);
            const double tr = intensity(topRight);
            const double r = intensity(right);
            const double br = intensity(bottomRight);
            const double b = intensity(bottom);
            const double bl = intensity(bottomLeft);
            const double l = intensity(left);

            // sobel filter
            const double dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl);
            const double dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr);
            const double dZ = 1.0 / pStrength;

            math::vector3d v(dX, dY, dZ);
            v.normalize();

            // convert to rgb
            result(row, column) = pixel(map_component(v.x), map_component(v.y), map_component(v.z));
        }
    }

    return result;
}

这篇关于可以法线贴图从纹理生成的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆