Sign in to follow this  
  • entries
    135
  • comments
    130
  • views
    52447

Cloak shader

Sign in to follow this  
VisualLR

123 views

So, I offered I would write a little about the cloak shader I implemented, so here it is.

The vertex shader is really straightforward


struct a2v
{
float4 position: POSITION;
float3 normal: NORMAL;
float2 texcoord0: TEXCOORD0;
};

struct v2f
{
float4 position : POSITION0;
float3 normal : TEXCOORD0;
float3 view_vec : TEXCOORD1;
};

v2f main(a2v i){
v2f o;

o.position = mul( i.position, world_view_proj );
o.normal = mul( i.normal, model_to_world );
o.view_vec = camera_pos - i.position;
return o;
}


The only thing worth mentioning is that it is sending the view vector in TEXCOORD1 to the pixel shader, this will be used to calculate the reflection vector as well as lookup into a texture that gives the object the "oily" or "soapy" look to it. The pixel shader is where the fun stuff happens, the shader requires two textures, the first is a 1D texture that gives the object the "oily" feel described before. The next texture is the cube map that will be used for the object's reflection.


sampler Rainbow: register(s0);
sampler Environment: register(s1);

float rainbowiness: register(c0); // 0.0 - 1.0 ( 0.5 looks good )

float4 main(float3 normal: TEXCOORD0, float3 viewVec: TEXCOORD1) : COLOR
{
normal = normalize(normal);

float v = dot(normalize(viewVec), normal);

// lookup into the 1D rainbow texture
float3 rainbow = tex1D(Rainbow, v);

// Calculate the reflection vector, then lookup into cubemap
float3 reflVec = reflect(-viewVec, normal);
float3 refl = texCUBE(Environment, reflVec);

// interpolate reflection color to rainbow color
float3 color = lerp(refl, rainbow, rainbowiness * v);

// return the interpolated color and use 1-v as transparency
return float4(color, 1 - v);
}


The line:

float v = dot(normalize(viewVec), normal);

The first use for the dot product between the view vector and the normal is to lookup into the 1D "rainbow" texture, what this will give us, is a smooth sampling of the texture. The texture will be sampled from left to right, the leftmost color will be used for the places where the normal is least aligned to the view vector at, and gradually up to the rightmost color at the places in which the view and the normal are most aligned. Here's a screenshot of the effect only looking into the rainbow texture:




Click for full size



The next two lines are very straightforward

// Find the reflection
float3 reflVec = reflect(-viewVec, normal);
float3 refl = texCUBE(Environment, reflVec);

All they do is calculate the reflection vector and use it to lookup the appropiate texel in the cube map.

The next use for the dot product is to calculate the transparency of the object, it works in the same way, the object will be fully opaque when the normal is least aligned to the view vector and will gradually become transparent as the view vector and normal become aligned. You can see this in the last line of the shader:

return float4(color, 1 - v);

Here's a screenshot where I hardcoded the ship's color to green just so you can see how the alpha looks:




Click for full size


Here's the rainbow texture I used:




Right click here then Save as...


The pixel shader needs to be compiled in PS2.0 because of the dependent texture read where we lookup the rainbow texture.
Sign in to follow this  


0 Comments


Recommended Comments

There are no comments to display.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now