我在谷歌上看过,但我唯一能找到的是关于如何使用 photoshop 创建一个教程。不感兴趣!我需要它背后的逻辑。
(我不需要如何“使用”凹凸贴图的逻辑,我想知道如何“制作”一个!)

我正在编写我自己的 HLSL 着色器,并且已经意识到两个像素之间存在某种渐变,这将显示其正常 - 因此可以相应地点亮灯光的位置。

我想实时执行此操作,以便当纹理发生变化时,凹凸贴图也会发生变化。

谢谢

最佳答案

我意识到我参加这个聚会已经很晚了,但我最近在尝试为 3ds max 编写自己的法线贴图生成器时也遇到了同样的情况。 C# 有庞大且不必要的库,但没有任何简单的、基于数学的解决方案。
所以我使用转换背后的数学运算:Sobel 算子。这就是您希望在着色器脚本中使用的内容。
下面的类是我见过的最简单的 C# 实现。它完全按照它应该做的事情做,并且完全达到了预期的效果:基于高度图、纹理甚至是您提供的以编程方式生成的程序的法线贴图。
正如您在代码中看到的那样,我已经实现了 if/else 来减轻边缘检测宽度和高度限制引发的异常。
它的作用:对每个像素/相邻像素的 HSB 亮度进行采样,以确定输出色相/饱和度值的比例,随后为 SetPixel 操作将这些值转换为 RGB。
顺便说一句:您可以实现一个输入控件来缩放输出色相/饱和度值的强度,以缩放输出法线贴图将提供几何/照明的后续影响。
就是这样。不再需要处理已弃用的小窗口 PhotoShop 插件。天空是极限。
C# winforms 实现的屏幕截图(源/输出):
c# - 从纹理创建法线贴图背后的逻辑是什么?-LMLPHP
从源图像实现基于 Sobel 的法线贴图的 C# 类:

using System.Drawing;
using System.Windows.Forms;

namespace heightmap.Class
{
    class Normal
    {
        public void calculate(Bitmap image, PictureBox pic_normal)
        {
            Bitmap image = (Bitmap) Bitmap.FromFile(@"yourpath/yourimage.jpg");
            #region Global Variables
            int w = image.Width - 1;
            int h = image.Height - 1;
            float sample_l;
            float sample_r;
            float sample_u;
            float sample_d;
            float x_vector;
            float y_vector;
            Bitmap normal = new Bitmap(image.Width, image.Height);
            #endregion
            for (int y = 0; y < w + 1; y++)
            {
                for (int x = 0; x < h + 1; x++)
                {
                    if (x > 0) { sample_l = image.GetPixel(x - 1, y).GetBrightness(); }
                    else { sample_l = image.GetPixel(x, y).GetBrightness(); }
                    if (x < w) { sample_r = image.GetPixel(x + 1, y).GetBrightness(); }
                    else { sample_r = image.GetPixel(x, y).GetBrightness(); }
                    if (y > 1) { sample_u = image.GetPixel(x, y - 1).GetBrightness(); }
                    else { sample_u = image.GetPixel(x, y).GetBrightness(); }
                    if (y < h) { sample_d = image.GetPixel(x, y + 1).GetBrightness(); }
                    else { sample_d = image.GetPixel(x, y).GetBrightness(); }
                    x_vector = (((sample_l - sample_r) + 1) * .5f) * 255;
                    y_vector = (((sample_u - sample_d) + 1) * .5f) * 255;
                    Color col = Color.FromArgb(255, (int)x_vector, (int)y_vector, 255);
                    normal.SetPixel(x, y, col);
                }
            }
            pic_normal.Image = normal; // set as PictureBox image
        }
    }
}

关于c# - 从纹理创建法线贴图背后的逻辑是什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10652797/

10-12 03:17