【发布时间】:2015-06-13 07:35:07
【问题描述】:
我通过 StructuredBuffer 传递中心世界位置,在广告牌上绘制球体,并使用几何着色器构建面向相机的广告牌。球体绘制正确,我可以找出 UV。现在我想点亮它,但我不知道如何计算世界坐标中的法线......
代码如下:
StructuredBuffer<float3> bufferPositions;
VS_OUTPUT VS_Main(uint vertexId : SV_VertexId)
{
VS_OUTPUT res = (VS_OUTPUT)0;
res.position = float4(bufferPositions[vertexId], 1);
res.vertexId = vertexId;
return res;
}
[maxvertexcount(4)]
void GS_Main(point VS_OUTPUT input[1], inout TriangleStream<VS_OUTPUT> OutputStream)
{
float halfWidth = SIZE / 2.0f;
float3 objToCam = normalize(input[0].position.xyz - fCameraPos);
float3 upVector = float3(0.0f, 1.0f, 0.0f);
float3 rightVector = normalize(cross(objToCam, upVector));
rightVector = rightVector * halfWidth;
upVector = normalize(cross(rightVector, objToCam)) * halfWidth;
float3 vert[4];
vert[0] = input[0].position.xyz - rightVector - upVector; // Get bottom left vertex
vert[1] = input[0].position.xyz + rightVector - upVector; // Get bottom right vertex
vert[2] = input[0].position.xyz - rightVector + upVector; // Get top left vertex
vert[3] = input[0].position.xyz + rightVector + upVector; // Get top right vertex
float2 texCoord[4];
texCoord[0] = float2(-1, -1);
texCoord[1] = float2(1, -1);
texCoord[2] = float2(-1, 1);
texCoord[3] = float2(1, 1);
VS_OUTPUT outputVert;
for(int i = 0; i < 4; i++)
{
outputVert.position = mul(float4(vert[i], 1.0f), fViewProj);
outputVert.wpos = vert[i];
outputVert.normal = objToCam;
outputVert.texcoord0 = texCoord[i];
outputVert.vertexId = input[0].vertexId;
OutputStream.Append(outputVert);
}
}
PS_OUTPUT PS_Main(VS_OUTPUT input)
{
PS_OUTPUT res = (PS_OUTPUT)0;
float3 n = float3(input.texcoord0.x, input.texcoord0.y, 0);
float r2 = dot(n.xy, n.xy);
// if the texel is not inside the sphere
if(r2 > 1.0f)
discard;
n.z = sqrt(1 - r2);
// calculate UV mapping
float u = 0.5 + atan2(n.z, n.x) / (2.0 * PI);
float v = 0.5 - asin(n.y) / PI;
// how to calculate normal in world space ?
return res;
}
我应该拥有比进行计算所需的信息更多的信息,但我无法完全理解要进行的计算
更新:我尝试从平面向量创建一个 Axis-Normal 并创建一个旋转矩阵,我将其应用于局部法线 n 而没有成功
【问题讨论】:
-
我不太明白。法线仅对每个像素有意义,而不是每个广告牌。您应该从片段着色器中获得法线 - 而不是几何体。如果您的广告牌有法线贴图,您需要传递切线空间 (google) 基向量。在广告牌空间中,正前方的法线将是 (0,0,1)。或者 (dx,dy,1) 如果您有法线贴图。对于照明,您希望将其带入世界空间。什么是世界空间取决于你。这是一个广告牌!
-
我正在尝试在广告牌上绘制一个球体。我得到了正确的广告牌部分和球体的本地部分。像素着色器的“n”部分是广告牌局部空间中的球体,因此它不会因相机位置而异。我需要做的是从中心和法线方向计算球体世界矩阵,然后用它转换“n”,但我之前使用轴角到矩阵的尝试没有奏效,而且太重了..
-
第一:投影球体并不明显!大多数人认为一个球体投影到一个圆上。因此到一个边界正方形。那不是真的。画出来。不要粘在球体上。从概念上讲,它是一个虚假的朋友。我没有太多的空间和耐心来输入所有内容,但谷歌搜索“切线空间”。一开始需要花点功夫才能理解,但我认为你已经足够理解了!
-
检查球体光线投射以获得正确的球体。大多数方法也会为您提供相应的法线。