¿Cómo un sombreador HLSL realmente termina afectando la salida del render?

11

Entiendo la sintaxis de HLSL, por ejemplo, supongamos que tengo esto como mi HLSL:

struct VOut
{
    float4 position : SV_POSITION;
    float4 color : COLOR;
};

VOut VShader(float4 position : POSITION, float4 color : COLOR)
{
    VOut output;

    output.position = position;
    output.position.xy *= 0.7f;    // "shrink" the vertex on the x and y axes
    output.color = color;

    return output;
}


float4 PShader(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
    return color;
}

y lo compilo así:

D3DX11CompileFromFile(L"shaders.hlsl", 0, 0, "VShader", "vs_5_0", 0, 0, 0, &VS, 0, 0);
D3DX11CompileFromFile(L"shaders.hlsl", 0, 0, "PShader", "ps_5_0", 0, 0, 0, &PS, 0, 0);

¿Qué le parece ... saber cambiar ...? Estoy confundido acerca de cuál es exactamente la tubería entre HLSL y los píxeles / vértices reales en la pantalla.

¿Es esto lo que realmente los "aplica"?

dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);

// set the shader objects
devcon->VSSetShader(pVS, 0, 0);
devcon->PSSetShader(pPS, 0, 0);

Tenga en cuenta que soy como un principiante literal en estas cosas. ¿Alguien puede explicar lo que está haciendo? Supongo que la función de vértice HLSL pasa por cada vértice y luego los cambia a lo que tengo en la función, y la salida es lo que se cambió ... ¿y de manera similar para el sombreador de píxeles?

Otra confusión, sé qué es un píxel y entiendo qué es un vértice ... pero, ¿qué hace exactamente el sombreador de píxeles?


fuente
Está

Respuestas:

10

¿Cómo le gusta ... sepa cambiar? Estoy confundido exactamente en la tubería entre HLSL y los píxeles / vértices reales en la pantalla.

Funciona más o menos así: cuando emite una llamada de dibujo (DrawPrimitives, DrawIndexedPrimitives en D3D, Draw en 10+, etc.), se procesan los datos de geometría que ha vinculado a la tubería (sus búferes de vértices). Para cada vértice, el sombreador de vértices se ejecuta para producir un vértice de salida en el espacio del clip.

Luego, la GPU realiza algunas funciones fijas en el vértice del espacio de recorte, como recortar / eliminar y llevar el vértice al espacio de la pantalla, donde comienza a rasterizar los triángulos. Durante la rasterización de cada triángulo, la GPU interpola los atributos de vértice a través de la superficie de ese triángulo, alimentando cada atributo interpolado al sombreador de píxeles para producir un color semifinal para ese píxel (la combinación se aplica después de que se ejecuta el sombreador de píxeles, por lo tanto, "semi- final").

es esto lo que realmente los "aplica":

El código que publicó primero compila los sombreadores, luego los vincula a la tubería donde permanecen activos para cualquier llamada de sorteo posterior hasta que se modifique. En realidad, no hace que se ejecuten.

¿Alguien puede explicar QUÉ está haciendo? Supongo que la función Vertex HLSL pasa por cada vértice (como la posición de entrada: POSICIÓN y color: COLOR) y luego los cambia a lo que tengo en la función, y la salida es lo que cambió. ... (lo mismo ocurre con Pixel Shader).

Otra confusión, sé lo que es un píxel y entiendo lo que es un vértice ... pero qué hace exactamente el sombreador de píxeles ...

El sombreador de vértices es responsable de transformar los vértices del espacio modelo al espacio de recorte.

El sombreador de píxeles es responsable de calcular el penúltimo color / profundidad de un píxel basado en atributos de vértice interpolados.


fuente
9

Trataré de explicar cómo funcionan las cosas sin usar mucha jerga.

Si le preocupa la simplicidad en lugar de la velocidad interactiva, una superficie 3D en la computadora sería solo una enorme nube de puntos en el espacio, lo suficientemente densa como para que podamos renderizar cada punto individualmente, sin espacios entre ellos.

Desea almacenar un modelo solo una vez en la memoria, pero necesita mostrarlo en varios tamaños y desde varios ángulos, por lo que cuando renderiza un modelo 3D, necesita "transformar" todos los puntos a medida que los lee de la memoria. Por ejemplo, para que el modelo sea un 50% más grande, debe escalar las posiciones de los puntos a la mitad:

out.position = in.position * 0.5;
out.color = in.color;

Este es casi el "sombreador de vértices" más simple que uno puede concebir: entra una posición de vértice de memoria y sale una nueva posición de vértice, casi igual de grande. El vértice medio grande no se almacena de nuevo en la memoria, se usa inmediatamente para renderizar y luego se desecha.

Aunque es una simplificación excesiva que carece de conceptos clave , esto en espíritu describe aspectos de cómo las películas hacen gráficos.

Los gráficos interactivos (juegos) no pueden permitirse el lujo de ser tan simples, ya que necesitan renderizar gráficos de varias órdenes de magnitud más rápidamente que una película.

En los juegos, no podemos permitirnos representar un punto por cada píxel en la pantalla, además de extras para cubrir los huecos. Entonces, como compromiso, la brecha entre cada uno de los tres puntos cercanos se representa como un triángulo, que por varias razones técnicas prefiere tener al menos 10 píxeles de tamaño en la pantalla.

Se puede proyectar un triángulo 3D en una pantalla 2D, luego dividirlo en una pila de líneas 1D, que pueden dividirse en una pila de píxeles 0D. Por lo tanto, podemos dividir y conquistar el problema de renderizar un triángulo 3D en el problema más simple de renderizar una gran cantidad de píxeles 0D de forma aislada. Una computadora puede resolver problemas más simples en menos tiempo.

Un sombreador de píxeles es un pequeño programa que ejecutamos en cada píxel que se genera al desmontar un triángulo.

out.color = in.color;

Este es casi el "sombreador de píxeles" más simple que uno puede concebir: entra una combinación de los colores de los vértices de tres triángulos, y sale el mismo color. Las entradas provienen de las salidas del "sombreador de vértices" y las salidas se escriben en la pantalla en la memoria.

Entonces, el "vertex shader" es un programa que se ejecuta dentro del chip GPU. Su entrada es un "búfer de vértices" en la memoria de la GPU, y su salida se alimenta directamente a un "sombreador de píxeles". Un "sombreador de píxeles" también es un programa que se ejecuta dentro del chip GPU. Sus entradas son una combinación de tres vértices del sombreador de vértices, y su salida es un píxel en la pantalla.

bmcnett
fuente
-2

No se preocupe por un sombreador de píxeles en este momento. Si eres un principiante completo, deberías ser hola mundo de GLSL / HLSL solo con sombreadores de vértices y fragmentos. Una vez que esté familiarizado y comience a comprender el movimiento variable y demás, amplíe sus horizontes.

Recomiendo encarecidamente un libro de texto para obtener información detallada sobre cómo funciona la API. Los libros de OpenGL también hacen un buen trabajo al ilustrar cómo han cambiado las cosas a lo largo de los años desde la tubería fija a la tubería dinámica programable.

¡Ve campeón!

Bryan C
fuente
1
Un sombreador de fragmentos cumple la misma función que un sombreador de píxeles.
1
No creo que podamos deducir de la pregunta si el OP es un principiante en toda la programación de juegos: solo declaró que es un principiante en la escritura de código de sombreador. Aprender a escribir shaders es una herramienta muy importante a tener en el cobertizo de un desarrollador de juegos, no habría más que brillo por encima de ellos a menos que esté sólo en las muy primeras etapas de aprendizaje de desarrollo de juegos.
Olhovsky