Skip to content

Higher order functions

rookboom edited this page Nov 14, 2012 · 3 revisions
Marbled Lumpy Crinkled

This sample is an implementation of Perlin noise as presented by Ken Perlin and Simon Green in GPU Gems Volumes 1 and 2 respectively.

Notable in this sample is the use of higher order functions. Each of the examples above uses bump mapping to perturb the surface normal in some way. Different functions can be passed as arguments to the bump mapping function to get the desired effects.

The details of the perlin noise calculation is elided below. You can find the full source code here

module Perlin =
    [<ReflectedDefinition>]
    type Shader(...) =

        let perlin (pos:float3) =
            ...
            ...

        let stripes x f =
            let PI = 3.14159265f;
            let t = 0.5f + 0.5f * sin(f * 2.0f*PI * x);
            t * t - 0.5f;

        let turbulance(pos:float3) =
            let absNoise =  perlin >> abs
            let mutable t = -0.5f
            let mutable f = 1.0f
            for i in 1..7 do
                let n = absNoise(pos*f)
                t <- t + n/f
                f <- f*2.0f
            t

        let bump F (input:PSInput) =
            let perturbedNormal =
                let normal = input.Normal |> normalize
                let pos = input.PositionOS
                let f0 = F(pos)
                let epsilon = 0.01f
                let dx = float3(epsilon,0.0f,0.0f)
                let dy = float3(0.0f,epsilon,0.0f)
                let dz = float3(0.0f,0.0f,epsilon)
                let fx = F(pos + dx)
                let fy = F(pos + dy)
                let fz = F(pos + dz)
                let dF = float3(fx-f0,fy-f0,fz-f0)/epsilon
                normal - dF|> normalize

            BlinnPhong.surfaceColor scene mat input.PositionWS perturbedNormal

        [<PixelShader>]
        member m.lumpy input =
            bump(fun pos -> 0.03f*perlin(pos*10.0f)) input

        [<PixelShader>]
        member m.marbled input =
            bump(fun pos -> 0.01f*stripes (pos.x + 2.0f*turbulance(pos)) 1.6f) input

        [<PixelShader>]
        member m.crinkled input =
            bump(fun pos -> -0.15f*turbulance pos) input

Clone this wiki locally