DirectX 11漫射照明实施

时间:2017-10-01 21:37:07

标签: directx-11 hlsl vertex-shader pixel-shader

以下:https://www.gamasutra.com/view/feature/131275/implementing_lighting_models_with_.php?page=2

我正在尝试实现漫反射照明,但我认为我不理解某些东西......而且我不知道我是否正确计算它。

多维数据集的顶点信息是:

SimpleVertex vertices[] =
        {
            { DirectX::XMFLOAT3(-1.0f, 1.0f, -1.0f), DirectX::XMFLOAT3(0.0f, 1.0f, 0.0f), DirectX::XMFLOAT2(1.0f, 0.0f) },
            { DirectX::XMFLOAT3(1.0f, 1.0f, -1.0f), DirectX::XMFLOAT3(0.0f, 1.0f, 0.0f), DirectX::XMFLOAT2(0.0f, 0.0f) },
            { DirectX::XMFLOAT3(1.0f, 1.0f, 1.0f), DirectX::XMFLOAT3(0.0f, 1.0f, 0.0f), DirectX::XMFLOAT2(0.0f, 1.0f) },
            { DirectX::XMFLOAT3(-1.0f, 1.0f, 1.0f), DirectX::XMFLOAT3(0.0f, 1.0f, 0.0f), DirectX::XMFLOAT2(1.0f, 1.0f) },

            { DirectX::XMFLOAT3(-1.0f, -1.0f, -1.0f), DirectX::XMFLOAT3(0.0f, -1.0f, 0.0f), DirectX::XMFLOAT2(0.0f, 0.0f) },
            { DirectX::XMFLOAT3(1.0f, -1.0f, -1.0f), DirectX::XMFLOAT3(0.0f, -1.0f, 0.0f), DirectX::XMFLOAT2(1.0f, 0.0f) },
            { DirectX::XMFLOAT3(1.0f, -1.0f, 1.0f), DirectX::XMFLOAT3(0.0f, -1.0f, 0.0f), DirectX::XMFLOAT2(1.0f, 1.0f) },
            { DirectX::XMFLOAT3(-1.0f, -1.0f, 1.0f), DirectX::XMFLOAT3(0.0f, -1.0f, 0.0f), DirectX::XMFLOAT2(0.0f, 1.0f) },

            { DirectX::XMFLOAT3(-1.0f, -1.0f, 1.0f), DirectX::XMFLOAT3(-1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2(0.0f, 1.0f) },
            { DirectX::XMFLOAT3(-1.0f, -1.0f, -1.0f), DirectX::XMFLOAT3(-1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2(1.0f, 1.0f) },
            { DirectX::XMFLOAT3(-1.0f, 1.0f, -1.0f), DirectX::XMFLOAT3(-1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2(1.0f, 0.0f) },
            { DirectX::XMFLOAT3(-1.0f, 1.0f, 1.0f), DirectX::XMFLOAT3(-1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2(0.0f, 0.0f) },

            { DirectX::XMFLOAT3(1.0f, -1.0f, 1.0f), DirectX::XMFLOAT3(1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2(1.0f, 1.0f) },
            { DirectX::XMFLOAT3(1.0f, -1.0f, -1.0f), DirectX::XMFLOAT3(1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2(0.0f, 1.0f) },
            { DirectX::XMFLOAT3(1.0f, 1.0f, -1.0f), DirectX::XMFLOAT3(1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2(0.0f, 0.0f) },
            { DirectX::XMFLOAT3(1.0f, 1.0f, 1.0f), DirectX::XMFLOAT3(1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2(1.0f, 0.0f) },

            { DirectX::XMFLOAT3(-1.0f, -1.0f, -1.0f), DirectX::XMFLOAT3(0.0f, 0.0f, -1.0f), DirectX::XMFLOAT2(0.0f, 1.0f) },
            { DirectX::XMFLOAT3(1.0f, -1.0f, -1.0f), DirectX::XMFLOAT3(0.0f, 0.0f, -1.0f), DirectX::XMFLOAT2(1.0f, 1.0f) },
            { DirectX::XMFLOAT3(1.0f, 1.0f, -1.0f), DirectX::XMFLOAT3(0.0f, 0.0f, -1.0f), DirectX::XMFLOAT2(1.0f, 0.0f) },
            { DirectX::XMFLOAT3(-1.0f, 1.0f, -1.0f), DirectX::XMFLOAT3(0.0f, 0.0f, -1.0f), DirectX::XMFLOAT2(0.0f, 0.0f) },

            { DirectX::XMFLOAT3(-1.0f, -1.0f, 1.0f), DirectX::XMFLOAT3(0.0f, 0.0f, 1.0f), DirectX::XMFLOAT2(1.0f, 1.0f) },
            { DirectX::XMFLOAT3(1.0f, -1.0f, 1.0f), DirectX::XMFLOAT3(0.0f, 0.0f, 1.0f), DirectX::XMFLOAT2(0.0f, 1.0f) },
            { DirectX::XMFLOAT3(1.0f, 1.0f, 1.0f), DirectX::XMFLOAT3(0.0f, 0.0f, 1.0f), DirectX::XMFLOAT2(0.0f, 0.0f) },
            { DirectX::XMFLOAT3(-1.0f, 1.0f, 1.0f), DirectX::XMFLOAT3(0.0f, 0.0f, 1.0f), DirectX::XMFLOAT2(1.0f, 0.0f) },
        };

顶点着色器是:

cbuffer ConstantBuffer : register( b0 )
{
    matrix World;
    matrix View;
    matrix Projection;
    float4 vMeshColor;
};

struct VS_INPUT
{
    float4 Position : POSITION;
    float3 Normal : NORMAL;
    float2 Texture : TEXCOORD0;
};

struct PS_INPUT
{
    float4 Position : SV_POSITION;
    float3 Normal : TEXCOORD0;
    float2 Texture : TEXCOORD1;
};

PS_INPUT VS( VS_INPUT input )
{
    PS_INPUT output = (PS_INPUT)0;

    output.Position = mul( input.Position, World );
    output.Position = mul( output.Position, View );
    output.Position = mul( output.Position, Projection );

    output.Normal = mul( input.Normal, World );
    output.Normal = mul( output.Normal, View );
    output.Normal = mul( output.Normal, Projection );
    output.Normal = normalize( output.Normal );

    output.Texture = input.Texture;

    return output;
}

Pixel Is:

PS_OUTPUT PS( PS_INPUT input )
{
    PS_OUTPUT output;
    float4 ambient = {0.1, 0.0, 0.0, 1.0};
    float4 lightColor = { 1.0f, 1.0f, 1.0f, 1.0f};

    float3 lightPosition = ( 1.0f, 1.0f, 0.0f );
    float3 lightDirection = normalize(lightPosition - input.Position);

    float1 diffuse = saturate( dot( lightDirection, input.Normal )) * lightColor;

    output.color = diffuse;

    //float4 solidColor = float4( 1.0f, 1.0f, 0.0f, 1.0f );
    //output.color = solidColor;
    return output;
}

结果(当立方体旋转50时): enter image description here

CPP:https://github.com/walbourn/directx-sdk-samples/blob/master/Direct3D11Tutorials/Tutorial06/Tutorial06.cpp

HLSL:https://github.com/walbourn/directx-sdk-samples/blob/master/Direct3D11Tutorials/Tutorial06/Tutorial06.fx

1 个答案:

答案 0 :(得分:1)

此处没有太多信息可以继续,但法线是从顶点(点)指向某个方向的方向向量(方向)。当你计算漫反射光照时,你得到光的位置,得到顶点的位置(点,在这种情况下,我假设从立方体),你找到两个矢量之间的角度。将其描绘为三角形,从光源位置到立方体上的顶点绘制一条直线,并计算该光线与光线之间的角度与法线向量(指向垂直,正交或直线的直线)之间的角度。立方体表面。这两个矢量之间的角度越大,它就越暗,因为你采用了#34;点积"。当角度成直角时,点积将为零,意味着没有光。当"正常"方向直接指向光的方向,点积的值为1,意味着全光。当您将此点积(基本上是光强度)与另一种颜色相乘时,您需要调整顶点(或立方体)所具有的原始颜色的亮度。这会调节您看到的颜色。希望能解释一下。

至于为何你在改变数字时看到你所看到的内容,我不知道。

我只是添加,关于为什么你看到一些不同的东西,如果你用位置改变法线,法线向量几乎总是一个单位向量(长度为1)。当您进行光照计算时,如果两个向量都被标准化,则只能获得0到1之间的所需值(既是单位向量,又是长度为1的向量)。否则你可以获得大量或小的负数。如果你使用像45这样的大量数字作为你的光照倍增系数,那么事情就不会是正确的。着色器中的颜色是介于0和1之间的值。

enter image description here

更新:好的,解释起来很复杂,而且我不知道我是否可以画一张照片来表明这一点。在这段代码中发生了什么,你正在对立方体的每个角顶点进行处理,然后将它与所谓的世界/视图/投影矩阵相乘。基本上,它采用立方体的顶点,将其移动到世界中的位置,然后将其移动到相机位置的倒数位置,这通常意味着靠近原点(0) ,0,0)在相机前面。然后投影矩阵将这些点转换到屏幕上。这里要记住的重要一点是,通过这个神奇的WVP矩阵将顶点着色器中的入射顶点相乘,最终结果是顶点最终位于摄像机前面,然后投影到屏幕上。

现在还有第二部分正在发生,这就是照明计算。它可以在世界空间中完成,或者在世界x视图转换完成后完成。在这种情况下,代码在世界空间中进行光照计算,这意味着无论多维数据集的顶点位于其局部空间中的哪个位置,它都会转换为其世界位置。它可能在世界的任何地方,也可能是(150,20,60)。你需要将它转换到这个世界位置,因为光线位置也在这个空间的世界某个地方。法向量通常是单位向量(长度为1的向量)。画出从(0,0,0)开始并指向一个方向的法线向量。

在第一个将法向量乘以世界矩阵的情况下,这是错误的。理想情况下,应该发生的是法线向量应该遵循'顶点位置的变换,然后从变换后的世界位置指出一个长度。我希望我可以画一些东西来更好地解释它。第一个肯定是错的,第二个你把位置乘以世界矩阵也是错误的我认为。

编辑:我浏览了教程代码,它运行正常。指定(1,1,0)的亮点,然后在着色器中使用它。另一方面,在本教程中,两个亮点是:

XMFLOAT4( -0.577f, 0.577f, -0.577f, 1.0f ),
XMFLOAT4( 0.0f, 0.0f, -1.0f, 1.0f ),

您将看到的第二个是单位向量,只有Z是-1。第一个也是单位向量(长度为1),因为A平方+ B平方+ C平方=长度。这就是为什么这两个都是单位向量和点积将正确的结果。另一方面,你的(1,1,0)向量不是一个单位向量。我不确定这是否有区别,但无论如何你的代码和教程都不一样,我不确定这些改变是否是原因你的代码不起作用。还要注意Chuck的光代码是有效的,因为立方体位于中心位置,如果它被移动到任何其他地方,你会在任何地方发现光线。我猜他只是为了演示这样做。