Skip to content
Johan Verwey edited this page May 24, 2018 · 11 revisions

Blinn Phong Shader

Here is what a basic gouraud shader might look like written in F#.

type Shader(scene:SceneConstants,  
            obj:ObjectConstants,  
            mat:MaterialConstants) =  
[<VertexShader>]  
member m.vertex(input:VSInput) =
    PSInput(input.Position * obj.WorldViewProjection,  
            input.Normal * float3x3(obj.World))    
[<PixelShader>]  
member m.pixel(input:PSInput) =
    input.Normal 
    |> normalize
    |> dot -scene.LightDirection
    |> mul mat.Diffuse
    |> saturate
    |> withAlpha 1.0f

At runtime, this would be translated to the following HLSL:

	PSInput vertex(VSInput input)
	{
	    PSInput o;
	    o.PositionHS = mul(input.Position,WorldViewProjection);
	    o.Normal = mul(input.Normal,(float3x3)(World));
	    return o;
	};
	
	float4 pixel(PSInput input) : SV_TARGET
	{
	    float3 temp = saturate(mul(Diffuse,dot(-(LightDirection),normalize(input.Normal))));  
	    return float4(temp,1);
	};

Data Structures

The shaders constants are defined below. Note that the ConstantPacking attribute will enforce the HLSL packing rules at compile time to facilitate marshalling data from the Cpu to the Gpu.

Scene Constants
    [<Struct; ConstantPacking>]
    type SceneConstants(lightDir:float3) =
        member m.LightDirection = lightDir
Material Constants
    [<Struct; ConstantPacking>]
    type MaterialConstants(diffuse:float3) =
        member m.Diffuse = diffuse
Object Constants
    [<Struct; ConstantPacking>]
    type ObjectConstants(wvp:float4x4, w:float4x4) =
        member m.WorldViewProjection = wvp
        member m.World = w
Vertex Shader Input
    [<Struct>]
    type VSInput(p:float4, n:float3) =
        member m.Position = p
        member m.Normal = n
Pixel Shader Input
    [<Struct>]
    type PSInput(p:float4, n:float3) =
        member m.PositionHS = p
        member m.Normal = n