2013-04-06 2 views
1

Я использую растровые рамки для генерации ландшафта. У меня есть рельеф, полученный из вершинного шейдера, но я не знаю, как вычислить нормали в шейдере. Это вызов функции в одном из классов, который генерирует нормали из рельефа, но это работает только в том случае, если рельеф был сгенерирован на процессоре. Heres код для вершинного шейдера Я использую:Нормальные вычисления в вершинном шейдере?

//////////////////////////////////////////////////////////////////////////////// 
// 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; 
} 
+0

Почему вы хотите это сделать? Вы хотите вычислить нормали каждый раз, когда вызывает вершинный шейдер? Я не думаю, что это хорошая идея. Почему вы не можете генерировать все нормали с процессором? – acrilige

+0

@Acrilige: чтобы сэкономить пропускную способность памяти ... Если вы превысили свой бюджет памяти, но имеете запасную мощность GPU, такие вещи могут быть очень полезными ... в равной степени вы не можете превысить свой бюджет памяти, но вы можете обнаружить, что вы можете затормозить нагрузку больше в ваши шейдеры, не нанося вреда производительности. Почему бы не использовать это? – Goz

+0

Я буду знать, спасибо за объяснение – acrilige

ответ

3

Ваша большая проблема с формированием нормалей в шейдере, что вам нужно знать, окружающих вершин. Это то, что вы можете преодолеть с помощью геометрического шейдера, но не с помощью вершинного шейдера. Простым способом вычисления нормали является вычисление нормалей многоугольника (возьмите вектор, образованный из 2 ребер и перекрестно произведите их для нормальной поверхности) всех полисов, которые попадают в вершину, на которую вы смотрите, а затем добавляете их и нормализуете. Таким образом, если у вас нет доступа к геометрическому шейдеру, единственным реальным решением является использование CPU. Даже тогда это не лучший способ вычислить нормали вершин. Возможно, вам все же будет лучше использовать более сложный алгоритм, и это даст вам еще больше проблем! Итак, да, процессор или геометрический шейдер ... это, в основном, ваши варианты.

+0

Как получить доступ к преобразованным вершинам? На процессоре у меня есть плоская плоскость в массиве, который я прокручиваю, чтобы вычислить нормали, но если я преобразую вершины в gpu, тогда значения массива не будут изменены с плоской поверхности, и я получу освещение, как если бы ландшафт был квартира. – ExplodingFirework

+0

Почему вам нужен преобразованный нормальный? Его просто мировую матрицу, умноженную на нормаль (убедитесь, что w равно 0 для этого умножения!) – Goz

+0

Я уже умножаю нормальную по мировой матрице, и она не светится должным образом. Что же касается w = 0, то input.position.w? Я попробовал это, и это ничего не изменило. – ExplodingFirework