coordmap (cam::Mat 4 4 Float) (p::Vec 4 Float) = cam *. p blendplane = -- NoBlending -- BlendLogicOp Xor Blend (FuncAdd,FuncAdd) ((OneBF,SrcAlpha),(DstAlpha,DstAlpha)) (V4 0 0 0 0) point :: Vec 3 Float -> Vec 4 Float point p = V4 p%x p%y p%z 1 homoproj :: Vec 4 Float -> Vec 3 Float homoproj v = v%xyz *! (1 / v%w) type Position = Vec 4 Float type TextureCoord = Vec 3 Float type Normal = Vec 3 Float type Overlay = ( (FragmentOperation Depth, FragmentOperation (Color (VecScalar 4 Float))) , FragmentStream 1 ((Vec 4 Float)) ) -- This lighting model ignores the normal vector and simply applies -- ambient lighting and a texture map. -- -- "Color on and Ambient off" -- inputs: Kd, map_Kd -- -- illum 0 -- color = Kd ambientOnly :: Mat 4 4 Float -> Vec 4 Float -> Texture -> PrimitiveStream Triangle (Position,TextureCoord,Normal) -> Overlay ambientOnly cam color texture prims = prims & mapPrimitives (\(p,n,uvw) -> ( coordmap cam p, V2 uvw%x (1 - uvw%y) )) & rasterizePrimitives (TriangleCtx CullBack PolygonFill NoOffset LastVertex) ((Smooth)) & mapFragments (\((uv)) -> ((color * texture2D (Sampler PointFilter MirroredRepeat texture) uv ))) & accumulateWith (DepthOp Less True, ColorOp NoBlending (V4 True True True True)) -- ½ ambient + ½ lambertian reflectance -- lambertian reflectance = (light ∙ normal) * diffuse * intensity -- I_d = (L ∙ N) C_d I_L -- -- "Color on and Ambient on" -- Chrome example indicates: Ka, Kd, Ks, refl -- -- illum 1 -- color = KaIa + Kd { SUM j=1..ls, (N ∙ Lj)Ij } -- -- The illum 0 can be implemented using illum 1 code by setting -- KaIa = Kd -- Ij = 0 forall j -- -- The spec seems to require settings for Ia and Ij (j = light number). -- Ka should probably be calculated similar to Kd: using a Ka_map texture. lambertianReflectance cam lightpos color texture prims = prims & mapPrimitives (\(p,n,uvw) -> let light_vector = normalize $ -- light direction from surface if lightpos%w == 0 then lightpos%xyz else homoproj lightpos - homoproj p lambertian = dot light_vector (normalize n) in ( coordmap cam p, V2 uvw%x (1 - uvw%y), lambertian )) & rasterizePrimitives (TriangleCtx CullBack PolygonFill NoOffset LastVertex) (Smooth,Smooth) & mapFragments (\(uv,lambertian) -> ((color * texture2D (Sampler PointFilter MirroredRepeat texture) uv *! (0.5 + 0.5*lambertian) ))) & accumulateWith (DepthOp Less True, ColorOp NoBlending (V4 True True True True)) -- Blinn-Phong -- -- illum 0 -- color = Kd -- illum 1 -- color = KaIa + Kd { SUM j=1..ls, (N ∙ Lj)Ij } -- illum 2 -- color = KaIa + Kd { SUM j=1..ls, (N ∙ Lj)Ij } + Ks { SUM j=1..ls, ((H∙Hj)^Ns)Ij } -- -- The illum 1 can be implemented using illum2 code by setting -- Ks = 0 (specular reflectance) -- -- TODO: Add (H∙Hj)^Ns term -- -- Okay, I don't understand why the spec says H∙Hj. I think it means N∙Hj. -- So i'm implementing that. blinnPhong cam lightpos color texture specular prims = prims & mapPrimitives (\(p,n,uvw) -> let light_vector = normalize $ -- light direction from surface if lightpos%w == 0 then lightpos%xyz else homoproj lightpos - homoproj p lambertian = dot light_vector (normalize n) in ( coordmap cam p, V2 uvw%x (1 - uvw%y), lambertian, n, p )) & rasterizePrimitives (TriangleCtx CullBack PolygonFill NoOffset LastVertex) (Smooth,Smooth,Smooth,Smooth) & mapFragments (\(uv,lambertian, n, p) -> let ct = texture2D (Sampler PointFilter MirroredRepeat texture) uv ns = specular%w ks = point $ specular%xyz campos = cam *. V4 0 0 0 1 view_vector = normalize $ homoproj campos - homoproj p h = normalize $ light_vector + view_vector refl = dot h (normalize n) light_vector = normalize $ -- light direction from surface if lightpos%w == 0 then lightpos%xyz else homoproj lightpos - homoproj p in (( color * ct *! (0.5 + 0.5*lambertian) + if refl>0 then ks *! pow refl ns else zero )) ) & accumulateWith (DepthOp Less True, ColorOp NoBlending (V4 True True True True)) makeFrame (cubemap :: TextureCube) (skybox :: PrimitiveStream Triangle ((Vec 3 Float))) (cameraPosition :: Vec 3 Float) (cam :: Mat 4 4 Float) (color :: Vec 4 Float) (texture :: Texture) (specular :: Vec 4 Float) (prims0 :: PrimitiveStream Triangle (Vec 4 Float, Vec 3 Float, Vec 3 Float)) (prims1 :: PrimitiveStream Triangle (Vec 4 Float, Vec 3 Float, Vec 3 Float)) (prims2 :: PrimitiveStream Triangle (Vec 4 Float, Vec 3 Float, Vec 3 Float)) (plane :: PrimitiveStream Triangle ((Vec 4 Float))) (lines :: PrimitiveStream Line (Vec 3 Float, Vec 3 Float)) (points :: PrimitiveStream Point (Vec 3 Float, Vec 3 Float)) (plane_mat :: Mat 4 4 Float) = imageFrame (emptyDepthImage 1, emptyColorImage (V4 0 0 0.4 1)) `overlay` skybox & mapPrimitives (\((p)) -> let texcoord = V3 p%x (p%y) (p%z) p' = cam *. point (p + cameraPosition) in (p', texcoord)) & rasterizePrimitives (TriangleCtx CullNone PolygonFill NoOffset LastVertex) ((Smooth)) & mapFragments (\((d)) -> (( textureCube cubemap d ))) & accumulateWith (DepthOp Always False, ColorOp NoBlending (V4 True True True True)) `overlay` ambientOnly cam color texture prims0 `overlay` lambertianReflectance cam (V4 0 20 10 1) color texture prims1 `overlay` blinnPhong cam (V4 0 20 10 1) color texture specular prims2 `overlay` plane & mapPrimitives (\((p)) -> let p' = coordmap cam $ plane_mat *. p in (p', p%xz)) & rasterizePrimitives (TriangleCtx CullNone PolygonFill NoOffset LastVertex) ((Smooth)) & mapFragments (\((uv)) -> let c = mixB zero one (fract uv >= (one *! (0.95::Float))) r = V4 1 1 1 0 *! (max c%x c%y) in ((r + V4 0 0 0 (0.8)))) & accumulateWith (DepthOp Less True, ColorOp blendplane (V4 True True True True)) `overlay` lines & mapPrimitives (\(p,c) -> let p' = coordmap cam $ point p w = p'%w yellowish = normalize c `dot` V3 1 1 0 p2 = if yellowish >= 0.9*sqrt 2 then V4 p'%x p'%y 0.1 w else V4 p'%x p'%y 0.11 w in (p2, point c)) & renderPoints cam (LineCtx 1.0 LastVertex) `overlay` points & mapPrimitives (\(p,c) -> let p' = coordmap cam $ point p w = p'%w yellowish = normalize c `dot` V3 1 1 0 p2 = if yellowish >= 0.9*sqrt 2 then V4 p'%x p'%y 0.1 w else V4 p'%x p'%y 0.11 w in (p2, point c)) & renderPoints cam (PointCtx (PointSize 5.0) 1.0 LowerLeft) renderPoints :: Mat 4 4 Float -> RasterContext (Vec 4 Float, Vec 4 Float) pr -> PrimitiveStream pr (Vec 4 Float, Vec 4 Float) -> ( (FragmentOperation Depth, FragmentOperation (Color (VecScalar 4 Float))) , FragmentStream 1 ((Vec 4 Float)) ) renderPoints cam ctx points = points & rasterizePrimitives ctx ((Flat)) & mapFragments (\((c)) -> ((c))) & accumulateWith (DepthOp Less True, ColorOp NoBlending (V4 True True True True)) main :: Output main = renderFrame $ makeFrame (TextureCubeSlot "CubeMap") (fetch "SkyCube" ((Attribute "position"))) (Uniform "CameraPosition") (Uniform "ViewProjection") (Uniform "diffuseColor") (Texture2DSlot "diffuseTexture") (Uniform "specularReflectivity") (fetch "objects0" (Attribute "position", Attribute "normal", Attribute "uvw")) (fetch "objects1" (Attribute "position", Attribute "normal", Attribute "uvw")) (fetch "objects2" (Attribute "position", Attribute "normal", Attribute "uvw")) (fetch "plane" ((Attribute "position"))) (fetch "Curve" (Attribute "position", Attribute "color")) (fetch "Points" (Attribute "position", Attribute "color")) (Uniform "PlaneModel")