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