Из-за ограничений мне приходится вычислять нормали вершин внутри моего геометрического шейдера. Из-за этого ограничения нормали относятся к граням, а не интерполируются между гранями вершины, что означает, что направленное освещение для каждого пикселя — это пустая трата времени. Поскольку нормали известны только из геометрического шейдера и далее, я не могу выполнять математические расчеты освещения в вершинном шейдере.
Нормали, рассчитываемые в шейдере геометрии, находятся в пространстве экрана, но они верны в некоторых тестах, которые я провел.
Я могу указать направление света в мировом пространстве или умножить на вид/проекцию/транспонированную/инвертированную матрицу.
Следующий код отчасти работает, но меняется в зависимости от угла камеры/направления света:
void FlipFaceGS(triangle PS_IN input[3], inout TriangleStream<PS_IN> OutputStream)
{
PS_IN v1 = input[0];
PS_IN v2 = input[1];
PS_IN v3 = input[2];
float3 faceEdgeA = v2.pos - v1.pos;
float3 faceEdgeB = v3.pos - v1.pos;
float3 faceNormal = normalize(cross(faceEdgeA, faceEdgeB));
v1.norm = faceNormal;
v2.norm = faceNormal;
v3.norm = faceNormal;
float4 newColor = (v1.color * Light1Color * max(0, dot(v1.norm, Light1Direction)));
newColor.a = v1.color.a;//we don't want to affect the alpha levels
v1.color = newColor;
v2.color = newColor;
v3.color = newColor;
OutputStream.Append(v1);
OutputStream.Append(v2);
OutputStream.Append(v3);
OutputStream.RestartStrip();
}
В приведенном выше примере направление освещения умножается на матрицу ViewProjection камеры и нормализуется перед отправкой на графический процессор.
Какая математика необходима для правильного расчета света в геометрическом шейдере?