Карта норм пикселей

Как обычно спасибо заранее..

Я использую Pixel Bender для генерации световых эффектов для ландшафта на основе карты высот. Я хотел бы сделать карту нормалей местности и оттуда усеять каждую нормаль к определенному направлению солнца. Довольно стандартная штука на самом деле, но пиксельный бендер играет не очень хорошо. У меня есть этот код:

void
evaluatePixel()
{
    float2 pt = outCoord();

    pixel3 a = sampleNearest(src,pt);
    pixel3 b = sampleNearest(src,float2(pt.x + 1.0, pt.y));
    pixel3 c = sampleNearest(src,float2(pt.x, pt.y + 1.0));

    float3 v1 = float3(1.0, 0.0, b.r - a.r);
    float3 v2 = float3(0.0, 1.0, c.r - a.r);

    normalize(v1);
    normalize(v2);

    float3 n = cross(v1,v2);

    dst = pixel3(n.x,n.y,n.z);
}

Я ожидал бы, что это произведет нормальную карту. Чтобы проверить, я предположил, что свет был направлен прямо вниз и просто использовать n.z в качестве выходного цвета. Это дает сплошной цвет. Если вы возьмете приведенный выше код и запустите его, вы увидите, что, хотя есть расхождение в красном и зеленом, синий всегда заполнен на 255. Почему это? Я ожидаю, что, учитывая v1 а также v2 нормализуются, что это не должно всегда выводить полный синий цвет?

Что я делаю неправильно?!?

1 ответ

Я на самом деле сделал что-то очень похожее с моими картами высот треугольной полосы.

input image3 verts;
output pixel3 triNorms;

void
evaluatePixel()
{
    float2 tCoord = outCoord() - 0.5; //move coord from pixel center to lower-left corner
    float quadIdx = mod(tCoord[0], 2.0); //potentially faster to use sign(fract(tCoord[0] / 2.0))
    float2 vCoord0 = float2(floor(tCoord.x / 2.0), tCoord.y);
    float2 vCoord1 = float2(vCoord0.x + 1.0, vCoord0.y + 1.0 - quadIdx);
    float2 vCoord2 = float2(vCoord0.x + quadIdx, vCoord0.y + 1.0);
    float3 v0 = sampleNearest(verts, vCoord0 + 0.5);
    float3 v1 = sampleNearest(verts, vCoord1 + 0.5);
    float3 v2 = sampleNearest(verts, vCoord2 + 0.5);
    float3 s0 = v1 - v0;
    float3 s1 = v2 - v0;
    float3 n = cross(s0, s1);
    float len = 1.0 / length(n);
    n.x *= len;
    n.y *= len;
    n.z *= len;
    triNorms = float3(n.x, n.y, n.z);
}

Это работает удивительно хорошо для меня. Проходит 1,8M вершин менее чем за 100 мс. Просто чтобы прояснить, я определяю свои треугольники как столбцы между вершинами. Это означает, что для каждых 4 вершин есть два треугольника. Я идентифицирую два треугольника на квад с "quadIdx".

Примечание: вы нормализуете, а затем вычисляете крест - это в обратном направлении, вам нужно нормализовать после. Кроме того, я действительно считаю, что нашел ошибку в normalize(). Он создавал NaN там, где я не ожидал. Я реализовал свою собственную нормализацию с помощью length(), и все это прекрасно работает!

Другие вопросы по тегам