11
\$\begingroup\$

I understand the syntax of HLSL, for example let's pretend I have this as my 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;
}

and I compile it like this:

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

How does it like... know to change... I'm confused about exactly what the pipeline between HLSL and the actual pixels/vertices on the screen is.

Is this what actually "applies" them?

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

Keep in mind I'm like a literal beginner at this stuff. Can someone maybe explain what it's doing? I'm assuming the vertex HLSL function goes through every vertex and then changes them to whatever I have in the function, and the output is what was changed... and similarly for the pixel shader?

Another confusion, I know what a pixel is, and I understand what a vertex is... but what exactly does the pixel shader do?

\$\endgroup\$
1
  • \$\begingroup\$ That's ok, no one does \$\endgroup\$
    – bobobobo
    Commented Oct 17, 2011 at 22:29

4 Answers 4

10
\$\begingroup\$

How does it like......know to change....Im confused exactly at the pipeline between HLSL and the actual Pixels/Vertex on the screen.

It works roughly like this: when you issue a draw call (DrawPrimitives, DrawIndexedPrimitives in D3D, Draw in 10+, et cetera), the geometry data you've bound to the pipeline (your vertex buffers) are processed. For every vertex, the vertex shader is executed to produce an output vertex in clip space.

The GPU then performs some fixed functions on that clip space vertex such as clipping/culling and bringing the vertex into screen space, where it begins to rasterize the triangles. During rasterization of each triangle, the GPU interpolates vertex attributes across the surface of that triangle, feeding each interpolated attribute to the pixel shader to produce a semi-final color for that pixel (blending is applied after the pixel shader executes, thus "semi-final").

is this what actually "applies" them:

The code you posted first compiles the shaders, then binds them to the pipeline where they remain active for any subsequent draw calls until changed. It doesn't actually cause them to be executed.

Can someone maybe explain WHAT it's doing, im assuming the Vertex HLSL function goes through every vertex (as the input Position:POSITION and color: COLOR) and then changes them to whatever I have in the function, and the output is what was changed....(same goes for Pixel Shader).

Another confusion, I know what a pixel is, and I understand what a vertex is.....but what exactly does the Pixel shader do......

The vertex shader is responsible for transforming vertices from model space to clip space.

The pixel shader is responsible for computing the penultimate color/depth for a pixel based on interpolated vertex attributes.

\$\endgroup\$
9
\$\begingroup\$

I'll try to explain how things work without using much jargon.

If simplicity rather than interactive speed is your concern, a 3D surface in the computer would be just a huge cloud of points in space, dense enough so we can just render each point individually, without gaps between them.

You want to store a model only once in memory, but you need to display it at various sizes and from various angles, so when you render a 3D model, you need to "transform" all the points as you read them from memory. For example, to render the model 50% as big, you need to scale the positions of the points by half:

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

This is almost the simplest "vertex shader" one can conceive: in goes a vertex position from memory, and out comes a new vertex position, half-as-big. The half-as-big vertex is not stored back to memory - it's used immediately for rendering and then thrown away.

Though a gross oversimplification that lacks key concepts, this in spirit describes aspects of how movies do graphics.

Interactive graphics (games) can't afford to be this simple, because they need to render graphics several orders of magnitude more quickly than a movie.

In games, we can't afford to render one point for each pixel on screen, plus extras to cover the gaps. So as a compromise, the gap between each three nearby points is rendered as a triangle, which for various technical reasons prefers to be at least 10 pixels big on the screen.

A 3D triangle can be projected onto a 2D screen, then divided into a stack of 1D lines, which can each be divided into a stack of 0D pixels. We can thus divide-and-conquer the problem of rendering a 3D triangle into the simpler problem of rendering a lot of 0D pixels in isolation. A computer can solve simpler problems in less time.

A pixel shader is a little program that we run on each pixel so generated from disassembling a triangle.

out.color = in.color;

This is almost the simplest "pixel shader" one can conceive: in goes a blend of the colors of three triangle vertices, and out goes the same color. The inputs come from the outputs of the "vertex shader" and the outputs are written to the screen in memory.

So - the "vertex shader" is a program that runs inside the GPU chip. Its input is a "vertex buffer" in GPU memory, and its output is fed directly into a "pixel shader." A "pixel shader" is also a program that runs inside the GPU chip. Its inputs are a blend of three vertices from the vertex shader, and its output is a pixel on the screen.

\$\endgroup\$
1
\$\begingroup\$

Besides the other answers, here's a little picture of what goes on

d3d10 pipeline

From pipeline stages, d3d10 (same as d3d11).

See also

\$\endgroup\$
-2
\$\begingroup\$

Don't worry about a pixel shader right now. If you're complete beginner, you should being hello world of GLSL / HLSL with vertex and fragment shaders only. Once you're familiar and you start to understand variable movement and such, then expand your horizons.

I highly recommend a text book to get the nitty gritty as to how the API works. OpenGL books also do a good job illustrating how things have changed over the years from the fixed pipeline to the dynamic programmable pipeline.

Go champion!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ A fragment shader fulfills the same function as a pixel shader. \$\endgroup\$
    – user1430
    Commented May 11, 2011 at 16:43
  • 1
    \$\begingroup\$ I don't think we can tell from the question whether the OP is a beginner at all game programming -- he only stated that he's a beginner at writing shader code. Learning to write shaders is a very important tool to have in a game developer's shed, I wouldn't merely gloss over them unless you're only at the very beginning stages of learning game development. \$\endgroup\$
    – Olhovsky
    Commented May 11, 2011 at 21:51

You must log in to answer this question.