Paint shader

May 2007.
The old fresnel shader was using a constant color for the reflection color, the result was not so good.
This shader use a fresnel term with a parametrable ior and a fake environ map.
The standard Lambert shading is also replaced with a Minnaert shading.
The fresnel term is stored in a 1D texture to have a per pixel computation, the light computation is done in a vertex shader so it can run on all hardwares.


// simple paint shader

float2 texDP (float3 dir)
{
// convert 3D lookup vector into 2D texture coordinates
float sgn = 0.5;
if( dir.z > 0.0 )
sgn = -0.5;
float m = 0.5* 1.0/sqrt( 2.0*(dir.z+1) );
return dir.xy * m + 0.5;
}

void main(
float4 position : POSITION,
float4 normal : NORMAL,
float4 itexcoord0: TEXCOORD0,
float4 iColor : COLOR,
uniform float4 iData,

out float4 oColor : COLOR,
out float4 oSpec : COLOR1,
out float4 oPosition: POSITION,
out float4 oTexcoord0: TEXCOORD0,
out float oTexfresnel: TEXCOORD1,
out float2 otexCoordEnv: TEXCOORD2)
{
float IOR = iData.x; // 0.04
float darkness = iData.y; // 0.6
float diffScale= iData.z; // 0.8
float specScale= iData.w; // 0.8
float4x4 mv = glstate.matrix.modelview[0];
float4x4 mvIT = glstate.matrix.invtrans.modelview[0];
float3 pos_WS = mul(mv, position).xyz;
float3 V = normalize( mv[3].xyz - pos_WS );
float3 N = normalize(mul(mvIT, normal).xyz);
float3 L = glstate.light[0].position.xyz;

float3 R = normalize(reflect(-V,N));
float3 H = R;
otexCoordEnv = texDP(R);

//calculate the diffuse and specular contributions
float NL = saturate( dot(N,L) ); // diffuse term
float NH = saturate( dot(N,H) );
float NV = max( 0.1, dot(N,V) );

float Minnaert = diffScale*pow( NL, darkness) * pow( NV, darkness - 1.0);
float baseCoat = Minnaert;
float specClearCoat = specScale * saturate(pow( NH , glstate.material.shininess.x ));

// IOR(1.5)=0.20
// IOR(1.8)=0.28
// IOR(200)=0.99
oTexfresnel = NV;
float4 ambColor = glstate.light[0].ambient * glstate.material.ambient + glstate.material.emission;
float4 diffColor = glstate.light[0].diffuse * glstate.material.diffuse * baseCoat;

oColor = diffColor + ambColor;
oColor.w = glstate.material.diffuse.w;

oSpec = glstate.light[0].specular * glstate.material.specular * specClearCoat;

oPosition = mul(glstate.matrix.mvp, position);
oTexcoord0 = itexcoord0;
}


On this screen shot the fuselage, the door and the right wing show a bit of reflection (ior = 1.2). The windshield uses a higher ior to obtain a glass look.

Home |

Last modified: 16/5/2007
Harald Johnsen hjohnsen at evc dot net