In che modo uno shader HLSL finisce per influire sull'output di rendering?


11

Capisco la sintassi di HLSL, per esempio facciamo finta di avere questo come mio 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;
}

e lo compilo così:

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);

Com'è ... sapere di cambiare ... Sono confuso su quale sia esattamente la pipeline tra HLSL e i pixel / vertici reali sullo schermo.

È questo ciò che realmente li "applica"?

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);

Tieni presente che sono un principiante letterale in queste cose. Qualcuno può forse spiegare cosa sta facendo? Suppongo che la funzione HLSL del vertice passi attraverso ogni vertice e poi li cambi in qualsiasi cosa io abbia nella funzione, e l'output è ciò che è stato cambiato ... e allo stesso modo per il pixel shader?

Un'altra confusione, so cos'è un pixel e capisco cos'è un vertice ... ma cosa fa esattamente il pixel shader?


Va bene, nessuno lo fa
bobobobo,

Risposte:


10

Com'è ...... sapere di cambiare ... Sono confuso esattamente sulla pipeline tra HLSL e i pixel / vertici reali sullo schermo.

Funziona più o meno in questo modo: quando si emette una chiamata di disegno (DrawPrimitives, DrawIndexedPrimitives in D3D, Draw in 10+, eccetera), vengono elaborati i dati della geometria associati alla pipeline (buffer dei vertici). Per ogni vertice, lo shader di vertice viene eseguito per produrre un vertice di output nello spazio della clip.

La GPU esegue quindi alcune funzioni fisse su quel vertice dello spazio di clip come ritaglio / abbattimento e portando il vertice nello spazio dello schermo, dove inizia a rasterizzare i triangoli. Durante la rasterizzazione di ciascun triangolo, la GPU interpola gli attributi dei vertici sulla superficie di quel triangolo, fornendo ciascun attributo interpolato al pixel shader per produrre un colore semifinale per quel pixel (la fusione viene applicata dopo l'esecuzione del pixel shader, quindi "semi- finale").

è questo ciò che effettivamente li "applica":

Il codice che hai pubblicato per prima compila gli shader, quindi li lega alla pipeline dove rimangono attivi per le successive chiamate di disegno fino a quando non vengono modificati. In realtà non li fa eseguire.

Qualcuno può forse spiegare COSA sta facendo, supponendo che la funzione Vertex HLSL attraversi tutti i vertici (come input Posizione: POSIZIONE e colore: COLORE) e poi li cambia in qualunque cosa io abbia nella funzione, e l'output è ciò che è stato cambiato. ... (lo stesso vale per Pixel Shader).

Un'altra confusione, so cos'è un pixel e capisco cos'è un vertice ..... ma cosa fa esattamente Pixel shader ......

Lo shader di vertice è responsabile della trasformazione dei vertici dallo spazio modello allo spazio clip.

Il pixel shader è responsabile del calcolo del penultimo colore / profondità per un pixel basato su attributi di vertice interpolati.


9

Proverò a spiegare come funzionano le cose senza usare molto gergo.

Se la preoccupazione piuttosto che la velocità interattiva è la tua preoccupazione, una superficie 3D nel computer sarebbe solo un'enorme nuvola di punti nello spazio, abbastanza densa da consentirci di renderizzare ogni punto individualmente, senza spazi vuoti tra di loro.

Vuoi memorizzare un modello solo una volta in memoria, ma devi visualizzarlo a varie dimensioni e da varie angolazioni, quindi quando esegui il rendering di un modello 3D, devi "trasformare" tutti i punti mentre li leggi dalla memoria. Ad esempio, per rendere il modello grande del 50%, è necessario ridimensionare le posizioni dei punti della metà:

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

Questo è quasi il più semplice "vertex shader" che si possa concepire: entra in una posizione di vertice dalla memoria, ed esce una nuova posizione di vertice, quasi grande. Il vertice mezzo grande non viene archiviato nella memoria: viene utilizzato immediatamente per il rendering e quindi gettato via.

Sebbene una grossa semplificazione eccessiva priva di concetti chiave , questo nello spirito descrive aspetti di come i film fanno la grafica.

La grafica interattiva (giochi) non può permettersi di essere così semplice, perché deve rendere la grafica di diversi ordini di grandezza più rapidamente di un film.

Nei giochi, non possiamo permetterci di rendere un punto per ogni pixel sullo schermo, oltre agli extra per coprire le lacune. Quindi, come compromesso, il divario tra i tre punti vicini viene visualizzato come un triangolo, che per vari motivi tecnici preferisce avere almeno 10 pixel sullo schermo.

Un triangolo 3D può essere proiettato su uno schermo 2D, quindi diviso in una pila di linee 1D, che possono essere divise in una pila di pixel 0D. Possiamo così dividere e conquistare il problema del rendering di un triangolo 3D nel problema più semplice del rendering di molti pixel 0D in isolamento. Un computer può risolvere problemi più semplici in meno tempo.

Un pixel shader è un piccolo programma che eseguiamo su ogni pixel così generato dallo smontaggio di un triangolo.

out.color = in.color;

Questo è quasi il "pixel shader" più semplice che si possa concepire: dentro va una miscela dei colori dei vertici di tre triangoli, e fuori va lo stesso colore. Gli ingressi provengono dalle uscite del "vertex shader" e le uscite sono scritte sullo schermo in memoria.

Quindi - il "vertex shader" è un programma che gira all'interno del chip GPU. Il suo input è un "buffer di vertici" nella memoria della GPU e il suo output viene inviato direttamente in un "pixel shader". Un "pixel shader" è anche un programma che viene eseguito all'interno del chip GPU. I suoi input sono una miscela di tre vertici dallo shader di vertice e il suo output è un pixel sullo schermo.



-2

Non preoccuparti di un pixel shader in questo momento. Se sei un principiante assoluto, dovresti essere ciao mondo di GLSL / HLSL solo con shader di vertici e frammenti. Una volta che hai familiarità e inizi a capire il movimento variabile e simili, quindi espandi i tuoi orizzonti.

Consiglio vivamente un libro di testo per ottenere il grintoso su come funziona l'API. I libri OpenGL fanno anche un buon lavoro illustrando come le cose sono cambiate nel corso degli anni dalla pipeline fissa alla pipeline dinamica programmabile.

Vai campione!


1
Uno shader di frammenti svolge la stessa funzione di uno shader di pixel.

1
Non credo che dalla domanda si possa dire se l'OP sia un principiante in tutte le programmazioni di gioco - ha solo dichiarato di essere un principiante nella scrittura di shader code. Imparare a scrivere shader è uno strumento molto importante avere in un capannone di uno sviluppatore di giochi, non mi limito brillantezza su di loro a meno che non sei solo ai molto fasi iniziali di apprendimento sviluppo del gioco.
Olhovsky,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.