#### mrkite77

##### Terrarian

A while ago I wrote a quick little command-line program that can disassemble xnb shaders. You can download the source here.

If you disassemble the TileShaders.xnb, you'll see a lot of definitions that describe techniques and passes.

If you scroll down you'll see multiple Resources. Each Resource is a shader for a different paint color.

Near the bottom, you'll see the shader for Pass2, which is the Red paint. We'll use that one as an example.

It's small, so I'll put it here:

dcl v

dcl t.xy

dcl_2d s

texld r, t, s

max r1.x, r.x, r.y

min r1.y, r.y, r.x

add r1.w, -r.z, r1.x

mov r1.z, r.z

cmp r2.x, r1.w, r1.x, r1.z

cmp r2.y, r1.w, r1.z, r1.x

min r.yz, r2.y, r1.y

mov r.x, r2.x

mul r, r, v

mov oC, r

dcl t.xy

dcl_2d s

texld r, t, s

max r1.x, r.x, r.y

min r1.y, r.y, r.x

add r1.w, -r.z, r1.x

mov r1.z, r.z

cmp r2.x, r1.w, r1.x, r1.z

cmp r2.y, r1.w, r1.z, r1.x

min r.yz, r2.y, r1.y

mov r.x, r2.x

mul r, r, v

mov oC, r

This shader (like all pixel shaders) is called repeatedly for each pixel in the texture.

The first 3 lines define variables passed in from the program. v is most likely the lighting color (we'll ignore it),

t.xy is the XY coordinate for the current pixel we're shading in the texture, s is the texture.

texld sets the vector 'r' to be the RGBA value of the current pixel in the texture.

Now the rest of the code refers to components of 'r' as 'r.x' and 'r.y' and 'r.z' but since we know that r is actually an RGB value,

those are misleading. r.x = red, r.y = green, r.z = blue (and r.w = alpha if the shader actually cared about the alpha channel)...

so in all future references I'll translate "r.x" into "red"... and so on.

Converting the rest into pseudocode, we basically have:

r1.x = max(red, green)

r1.y = min(red, green)

r1.w = r1.x - blue

r1.z = blue

if (r1.w >= 0) r2.x = r1.x else r2.x = r1.z

if (r1.w >= 0) r2.y = r1.z else r2.y = r1.x

blue = green = min(r2.y, r1.y)

red = r2.x

r *= v // apply the lighting.. we're ignoring this, but i translated it for you anyway

outputPixel = r // oC = the final RGB for this pixel

Shader code always assumes that red/green/blue are values from 0.0 to 1.0.

Which is why you can apply the lighting by multiplying two vectors together.

It's then best to go back through that pseudocode and clean up the variable names to make it clearer what is actually happening.

You might then realize that those if statements basically just check to see if blue is greater than the max or lower than the min

and then assign the appropriate output.

The whole thing boils down to:

out_red = max(red, green, blue)

out_green = out_blue = min(red, green, blue)

and that's how red paint is applied to each pixel of a tile.