Directx 顶点着色器中的法线计算?

Directx 顶点着色器中的法线计算?,directx,shader,lighting,terrain,normals,Directx,Shader,Lighting,Terrain,Normals,我正在使用rastertek框架生成地形。我已经从顶点着色器渲染了地形,但我不知道如何计算着色器中的法线。其中一个类中有一个函数调用,用于从地形生成法线,但这仅在cpu上生成地形时有效。下面是我正在使用的顶点着色器的代码: //////////////////////////////////////////////////////////////////////////////// // Filename: terrain.vs /////////////////////////////////

我正在使用rastertek框架生成地形。我已经从顶点着色器渲染了地形,但我不知道如何计算着色器中的法线。其中一个类中有一个函数调用,用于从地形生成法线,但这仅在cpu上生成地形时有效。下面是我正在使用的顶点着色器的代码:

////////////////////////////////////////////////////////////////////////////////
// Filename: terrain.vs
////////////////////////////////////////////////////////////////////////////////
#include "terrain.fx"

/////////////
// GLOBALS //
/////////////

cbuffer MatrixBuffer
{
    matrix worldMatrix;
    matrix viewMatrix;
    matrix projectionMatrix;
};


//////////////
// TYPEDEFS //
//////////////
struct VertexInputType
{
    float4 position : POSITION;
    float3 normal : NORMAL;
};

struct PixelInputType
{
    float4 position : SV_POSITION;
    float3 normal : NORMAL;
};


////////////////////////////////////////////////////////////////////////////////
// Vertex Shader
////////////////////////////////////////////////////////////////////////////////
PixelInputType TerrainVertexShader(VertexInputType input)
{
    PixelInputType output;

    input.position.y = input.position.y + terrain(input.position.x,input.position.z);

    // Change the position vector to be 4 units for proper matrix calculations.
    input.position.w = 1.0f;

    // Calculate the position of the vertex against the world, view, and projection matrices.
    output.position = mul(input.position, worldMatrix);
    output.position = mul(output.position, viewMatrix);
    output.position = mul(output.position, projectionMatrix);

    // Calculate the normal vector against the world matrix only.
    output.normal = mul(input.normal, (float3x3)worldMatrix);

    // Normalize the normal vector.
    output.normal = normalize(output.normal);

    return output;
}


在着色器中生成法线的最大问题是需要了解周围顶点。这是可以用几何体着色器克服的,但不能用顶点着色器克服。计算法线的一种简单方法是计算多边形法线,取由2条边形成的向量,将它们与所有多边形的面法线进行叉积,然后将它们相加并进行法线化。因此,如果您没有访问几何体着色器,唯一真正的解决方案是使用CPU。即使如此,这也不是计算顶点法线的最佳方法。您可能仍然会发现使用更复杂的算法更好,这会给您带来更多问题!是的,CPU或几何体着色器。。。这些基本上是您的选项。

在着色器中生成法线的最大问题是您需要了解周围顶点。这是可以用几何体着色器克服的,但不能用顶点着色器克服。计算法线的一种简单方法是计算多边形法线,取由2条边形成的向量,将它们与所有多边形的面法线进行叉积,然后将它们相加并进行法线化。因此,如果您没有访问几何体着色器,唯一真正的解决方案是使用CPU。即使如此,这也不是计算顶点法线的最佳方法。您可能仍然会发现使用更复杂的算法更好,这会给您带来更多问题!是的,CPU或几何体着色器。。。这些基本上是你的选择。

你为什么要这样做?是否要在每次顶点着色器调用时计算法线?我认为这不是个好主意。为什么不能用cpu生成所有法线?@Acrilige:为了节省内存带宽。。。如果你的内存超出预算,但有多余的GPU电源,这样的事情可以非常有用。。。同样,您可能不会超出内存预算,但您可能会发现可以在不影响性能的情况下将更多负载塞入着色器。为什么不用呢?我会知道的,谢谢你解释你为什么要这么做?是否要在每次顶点着色器调用时计算法线?我认为这不是个好主意。为什么不能用cpu生成所有法线?@Acrilige:为了节省内存带宽。。。如果你的内存超出预算,但有多余的GPU电源,这样的事情可以非常有用。。。同样,您可能不会超出内存预算,但您可能会发现可以在不影响性能的情况下将更多负载塞入着色器。为什么不使用它呢?我会知道的,谢谢你的解释。但是我如何访问转换的顶点?在cpu上,我在一个数组中有一个平面,我循环通过它来计算法线,但是如果我在gpu上变换顶点,那么数组值就不会从平面上改变,我得到的照明就好像地形是平的一样。为什么需要变换的法线?它只不过是世界矩阵乘以法线,但要确保乘法的w为0!我已经将法线乘以世界矩阵,但它不能正常发光。至于使w=0,这是输入.position.w吗?我试过了,它没有改变任何东西。不,方向向量的w值应该是0。。。一个位置向量的w值应该是1…但是我的法线只有x,y,z,我应该做float4吗?但是我如何访问变换的顶点?在cpu上,我在一个数组中有一个平面,我循环通过它来计算法线,但是如果我在gpu上变换顶点,那么数组值就不会从平面上改变,我得到的照明就好像地形是平的一样。为什么需要变换的法线?它只不过是世界矩阵乘以法线,但要确保乘法的w为0!我已经将法线乘以世界矩阵,但它不能正常发光。至于使w=0,这是输入.position.w吗?我试过了,它没有改变任何东西。不,方向向量的w值应该是0。。。一个位置向量的w值应该是1…但是我的法线只有x,y,z,我应该做float4吗?