I am drawing spheres on billboards by passing center world positions via a StructuredBuffer and use the geometry shader to build a billboard facing the camera. The sphere is drawn correctly and I can figure out the UVs. Now I would like to light it but I cannot figure how to calculate the normals in world coordinates...
The code look like this:
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;
}
I should have way more information than required to do the calculations but I cannot wrap my head about the calculation to make
UPDATE: I tried to create an Axis-Normal from the plane vector and create a rotation matrix that I would apply to the local normal n without success