summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2019-07-23 00:19:18 -0400
committerJoe Crayne <joe@jerkface.net>2019-07-23 00:19:18 -0400
commit4026bea0ec0e2604ebcac6e31ae9ba79a85a034a (patch)
treebdda064243b16dfb8c6e07930f507d1910208736
parent6bdffaf86341d118a965f7316c7141baea58d87c (diff)
Implement 3 distinct lighting models.
-rw-r--r--LoadMesh.hs43
-rw-r--r--MeshSketch.hs11
-rw-r--r--hello_obj2.lc101
3 files changed, 133 insertions, 22 deletions
diff --git a/LoadMesh.hs b/LoadMesh.hs
index cda6349..d8ce42b 100644
--- a/LoadMesh.hs
+++ b/LoadMesh.hs
@@ -126,8 +126,6 @@ uploadOBJToGPU :: Maybe BoundingBox -> MeshData -> IO ([MaterialMesh GPUMesh],Ma
126uploadOBJToGPU scalebb (subModels,(mtlLib,objpath)) = do 126uploadOBJToGPU scalebb (subModels,(mtlLib,objpath)) = do
127 let meshbb = foldMap (attribBoundingBox . mAttributes . materialMesh) subModels :: BoundingBox 127 let meshbb = foldMap (attribBoundingBox . mAttributes . materialMesh) subModels :: BoundingBox
128 m = maybe (ident 4) (scaleWithin meshbb) scalebb 128 m = maybe (ident 4) (scaleWithin meshbb) scalebb
129 -- BoundingBox {minX = -6.44698, maxX = 6.44698, minY = 0.0, maxY = 1.0e9, minZ = -0.768655, maxZ = 1.0e8}
130 -- BoundingBox {minX = -6.44698, maxX = 6.44698, minY = 0.0, maxY = 18.2027, minZ = -0.768655, maxZ = 2.238049}
131 putStrLn $ show meshbb 129 putStrLn $ show meshbb
132 gpuSubModels <- forM subModels $ \matmesh -> do 130 gpuSubModels <- forM subModels $ \matmesh -> do
133 a <- LambdaCubeGL.uploadMeshToGPU (transformMesh m (materialMesh matmesh)) 131 a <- LambdaCubeGL.uploadMeshToGPU (transformMesh m (materialMesh matmesh))
@@ -204,25 +202,44 @@ objSpan obj = case Map.elems (objAttributes obj) of
204 _ -> Mask [(0,1)] 202 _ -> Mask [(0,1)]
205 203
206 204
207searchMaterial :: V.Vector (Map Text (ObjMaterial, TextureData)) 205searchMaterial
208 -> (Int, Text) 206 :: V.Vector (Map Text (ObjMaterial, TextureData)) -- ^ Some tail end of this vector will be searched.
209 -> Maybe (ObjMaterial, TextureData) 207 -> (Int, Text) -- ^ Size of tail and material name to search for.
208 -> Maybe (ObjMaterial, TextureData)
210searchMaterial mtlLib (count,name) = foldr go id (V.drop (V.length mtlLib - count) mtlLib) Nothing 209searchMaterial mtlLib (count,name) = foldr go id (V.drop (V.length mtlLib - count) mtlLib) Nothing
211 where 210 where
212 go m f r = case Map.lookup name m of 211 go m f r = case Map.lookup name m of
213 Nothing -> f r 212 Nothing -> f r
214 x -> x :: Maybe (ObjMaterial,TextureData) 213 x -> x :: Maybe (ObjMaterial,TextureData)
215 214
216addOBJToObjectArray :: GLStorage -> String -> [MaterialMesh GPUMesh] -> V.Vector (Map Text (ObjMaterial,TextureData)) 215addOBJToObjectArray :: GLStorage -> String
216 -> [MaterialMesh GPUMesh]
217 -> V.Vector (Map Text (ObjMaterial,TextureData))
217 -> IO [MaskableObject] 218 -> IO [MaskableObject]
218addOBJToObjectArray storage slotName objMesh mtlLib = forM objMesh $ \matmesh -> do 219addOBJToObjectArray storage slotName objMesh mtlLib = forM objMesh $ \matmesh -> do
219 obj <- LambdaCubeGL.addMeshToObjectArray storage slotName ["diffuseTexture","diffuseColor"] (materialMesh matmesh) 220 obj <- case materialName matmesh >>= searchMaterial mtlLib of
220 -- diffuseTexture and diffuseColor values can change on each model 221 Nothing -> do
221 case materialName matmesh >>= searchMaterial mtlLib of 222 let slotnm = slotName ++ "0"
222 Nothing -> return () 223 obj <- LambdaCubeGL.addMeshToObjectArray storage
223 Just (ObjMaterial{..},t) -> LC.updateObjectUniforms obj $ do 224 slotnm
224 "diffuseTexture" @= return t -- set model's diffuse texture 225 [ "diffuseTexture"
225 "diffuseColor" @= let (r,g,b) = mtl_Kd in return (V4 r g b mtl_Tr) 226 , "diffuseColor"
227 , "specularReflectivity"]
228 (materialMesh matmesh)
229 return obj
230 Just (ObjMaterial{..},t) -> do
231 let slotnm = slotName ++ show (if 0 <= mtl_illum && mtl_illum <= 2 then mtl_illum else 2)
232 obj <- LambdaCubeGL.addMeshToObjectArray storage
233 slotnm
234 [ "diffuseTexture"
235 , "diffuseColor"
236 , "specularReflectivity"]
237 (materialMesh matmesh)
238 LC.updateObjectUniforms obj $ do
239 "diffuseTexture" @= return t -- set model's diffuse texture
240 "diffuseColor" @= let (r,g,b) = mtl_Kd in return (V4 r g b mtl_Tr)
241 "specularReflectivity" @= let (r,g,b) = mtl_Ks in return (V4 r g b mtl_Ns)
242 return obj
226 let matmask = maybe Map.empty (`Map.singleton` objSpan obj) 243 let matmask = maybe Map.empty (`Map.singleton` objSpan obj)
227 (fmap (\(c,n) -> "m:" <> pack (show c) <> ":" <> n) $ materialName matmesh) 244 (fmap (\(c,n) -> "m:" <> pack (show c) <> ":" <> n) $ materialName matmesh)
228 return $ MaskableObject obj (matmask `Map.union` materialMasks matmesh) 245 return $ MaskableObject obj (matmask `Map.union` materialMasks matmesh)
diff --git a/MeshSketch.hs b/MeshSketch.hs
index 56bbdaa..a51cd3d 100644
--- a/MeshSketch.hs
+++ b/MeshSketch.hs
@@ -333,7 +333,15 @@ new = do
333 mpipeline <- loadPipeline ppath $ do 333 mpipeline <- loadPipeline ppath $ do
334 defObjectArray "SkyCube" Triangles $ do 334 defObjectArray "SkyCube" Triangles $ do
335 "position" @: Attribute_V3F 335 "position" @: Attribute_V3F
336 defObjectArray "objects" Triangles $ do 336 defObjectArray "objects0" Triangles $ do
337 "position" @: Attribute_V4F
338 "normal" @: Attribute_V3F
339 "uvw" @: Attribute_V3F
340 defObjectArray "objects1" Triangles $ do
341 "position" @: Attribute_V4F
342 "normal" @: Attribute_V3F
343 "uvw" @: Attribute_V3F
344 defObjectArray "objects2" Triangles $ do
337 "position" @: Attribute_V4F 345 "position" @: Attribute_V4F
338 "normal" @: Attribute_V3F 346 "normal" @: Attribute_V3F
339 "uvw" @: Attribute_V3F 347 "uvw" @: Attribute_V3F
@@ -355,6 +363,7 @@ new = do
355 "PointsStart" @: Int 363 "PointsStart" @: Int
356 "diffuseTexture" @: FTexture2D 364 "diffuseTexture" @: FTexture2D
357 "diffuseColor" @: V4F 365 "diffuseColor" @: V4F
366 "specularReflectivity" @: V4F
358 return mpipeline 367 return mpipeline
359 either (\e _ -> hPutStrLn stderr e >> throwIO (userError e)) (&) m $ \pipeline -> do 368 either (\e _ -> hPutStrLn stderr e >> throwIO (userError e)) (&) m $ \pipeline -> do
360 mapM_ (putStrLn . ppShow) (targets $ dynamicPipeline pipeline) 369 mapM_ (putStrLn . ppShow) (targets $ dynamicPipeline pipeline)
diff --git a/hello_obj2.lc b/hello_obj2.lc
index 7e7defc..a6df7b7 100644
--- a/hello_obj2.lc
+++ b/hello_obj2.lc
@@ -10,6 +10,88 @@ blendplane = -- NoBlending -- BlendLogicOp Xor
10point :: Vec 3 Float -> Vec 4 Float 10point :: Vec 3 Float -> Vec 4 Float
11point p = V4 p%x p%y p%z 1 11point p = V4 p%x p%y p%z 1
12 12
13homoproj :: Vec 4 Float -> Vec 3 Float
14homoproj v = v%xyz *! (1 / v%w)
15
16type Position = Vec 4 Float
17type TextureCoord = Vec 3 Float
18type Normal = Vec 3 Float
19type Overlay = ( (FragmentOperation Depth, FragmentOperation (Color (VecScalar 4 Float)))
20 , FragmentStream 1 ((Vec 4 Float)) )
21
22-- This lighting model ignores the normal vector and simply applies
23-- ambient lighting and a texture map.
24--
25-- "Color on and Ambient off"
26-- inputs: Kd, map_Kd
27--
28-- illum 0 -- color = Kd
29ambientOnly :: Mat 4 4 Float -> Vec 4 Float -> Texture -> PrimitiveStream Triangle (Position,TextureCoord,Normal)
30 -> Overlay
31ambientOnly cam color texture prims = prims
32 & mapPrimitives (\(p,n,uvw) -> ( coordmap cam p, V2 uvw%x (1 - uvw%y) ))
33 & rasterizePrimitives (TriangleCtx CullBack PolygonFill NoOffset LastVertex) ((Smooth))
34 & mapFragments (\((uv)) -> ((color * texture2D (Sampler PointFilter MirroredRepeat texture) uv )))
35 & accumulateWith (DepthOp Less True, ColorOp NoBlending (V4 True True True True))
36
37-- ½ ambient + ½ lambertian reflectance
38-- lambertian reflectance = (light ∙ normal) * diffuse * intensity
39-- I_d = (L ∙ N) C_d I_L
40--
41-- "Color on and Ambient on"
42-- Chrome example indicates: Ka, Kd, Ks, refl
43--
44-- illum 1 -- color = KaIa + Kd { SUM j=1..ls, (N ∙ Lj)Ij }
45--
46-- The illum 0 can be implemented using illum 1 code by setting
47-- KaIa = Kd
48-- Ij = 0 forall j
49lambertianReflectance cam lightpos color texture prims = prims
50 & mapPrimitives (\(p,n,uvw) ->
51 let light_vector = normalize $ -- light direction from surface
52 if lightpos%w == 0
53 then lightpos%xyz
54 else homoproj lightpos - homoproj p
55 lambertian = dot light_vector (normalize n)
56 in ( coordmap cam p, V2 uvw%x (1 - uvw%y), lambertian ))
57 & rasterizePrimitives (TriangleCtx CullBack PolygonFill NoOffset LastVertex) (Smooth,Smooth)
58 & mapFragments (\(uv,lambertian) -> ((color * texture2D (Sampler PointFilter MirroredRepeat texture) uv *! (0.5 + 0.5*lambertian) )))
59 & accumulateWith (DepthOp Less True, ColorOp NoBlending (V4 True True True True))
60
61
62-- Blinn-Phong
63--
64-- illum 0 -- color = Kd
65-- illum 1 -- color = KaIa + Kd { SUM j=1..ls, (N ∙ Lj)Ij }
66-- illum 2 -- color = KaIa + Kd { SUM j=1..ls, (N ∙ Lj)Ij } + Ks { SUM j=1..ls, ((H∙Hj)^Ns)Ij }
67--
68-- The illum 1 can be implemented using illum2 code by setting
69-- Ks = 0 (specular reflectance)
70--
71-- TODO: Add (H∙Hj)^Ns term
72--
73-- Okay, I don't understand why the spec says H∙Hj. I think it means N∙Hj.
74-- So i'm implementing that.
75blinnPhong cam lightpos color texture specular prims = prims
76 & mapPrimitives (\(p,n,uvw) ->
77 let light_vector = normalize $ -- light direction from surface
78 if lightpos%w == 0
79 then lightpos%xyz
80 else homoproj lightpos - homoproj p
81 campos = cam *. V4 0 0 0 1
82 view_vector = normalize $ homoproj campos - homoproj p
83 h = normalize $ light_vector + view_vector
84 refl = dot h (normalize n)
85 lambertian = dot light_vector (normalize n)
86 in ( coordmap cam p, V2 uvw%x (1 - uvw%y), lambertian, refl ))
87 & rasterizePrimitives (TriangleCtx CullBack PolygonFill NoOffset LastVertex) (Smooth,Smooth,Smooth)
88 & mapFragments (\(uv,lambertian, refl) ->
89 let ct = texture2D (Sampler PointFilter MirroredRepeat texture) uv
90 ns = specular%w
91 ks = point $ specular%xyz
92 in (( color * ct *! (0.5 + 0.5*lambertian) + if refl>0 then ks *! pow refl ns else zero )) )
93 & accumulateWith (DepthOp Less True, ColorOp NoBlending (V4 True True True True))
94
13 95
14makeFrame (cubemap :: TextureCube) 96makeFrame (cubemap :: TextureCube)
15 (skybox :: PrimitiveStream Triangle ((Vec 3 Float))) 97 (skybox :: PrimitiveStream Triangle ((Vec 3 Float)))
@@ -17,7 +99,10 @@ makeFrame (cubemap :: TextureCube)
17 (cam :: Mat 4 4 Float) 99 (cam :: Mat 4 4 Float)
18 (color :: Vec 4 Float) 100 (color :: Vec 4 Float)
19 (texture :: Texture) 101 (texture :: Texture)
20 (prims :: PrimitiveStream Triangle (Vec 4 Float, Vec 3 Float, Vec 3 Float)) 102 (specular :: Vec 4 Float)
103 (prims0 :: PrimitiveStream Triangle (Vec 4 Float, Vec 3 Float, Vec 3 Float))
104 (prims1 :: PrimitiveStream Triangle (Vec 4 Float, Vec 3 Float, Vec 3 Float))
105 (prims2 :: PrimitiveStream Triangle (Vec 4 Float, Vec 3 Float, Vec 3 Float))
21 (plane :: PrimitiveStream Triangle ((Vec 4 Float))) 106 (plane :: PrimitiveStream Triangle ((Vec 4 Float)))
22 (lines :: PrimitiveStream Line (Vec 3 Float, Vec 3 Float)) 107 (lines :: PrimitiveStream Line (Vec 3 Float, Vec 3 Float))
23 (points :: PrimitiveStream Point (Vec 3 Float, Vec 3 Float)) 108 (points :: PrimitiveStream Point (Vec 3 Float, Vec 3 Float))
@@ -32,12 +117,9 @@ makeFrame (cubemap :: TextureCube)
32 & rasterizePrimitives (TriangleCtx CullNone PolygonFill NoOffset LastVertex) ((Smooth)) 117 & rasterizePrimitives (TriangleCtx CullNone PolygonFill NoOffset LastVertex) ((Smooth))
33 & mapFragments (\((d)) -> (( textureCube cubemap d ))) 118 & mapFragments (\((d)) -> (( textureCube cubemap d )))
34 & accumulateWith (DepthOp Always False, ColorOp NoBlending (V4 True True True True)) 119 & accumulateWith (DepthOp Always False, ColorOp NoBlending (V4 True True True True))
35 `overlay` 120 `overlay` ambientOnly cam color texture prims0
36 prims 121 `overlay` lambertianReflectance cam (V4 0 20 10 1) color texture prims1
37 & mapPrimitives (\(p,n,uvw) -> ( coordmap cam p, V2 uvw%x (1 - uvw%y) )) 122 `overlay` blinnPhong cam (V4 0 20 10 1) color texture specular prims2
38 & rasterizePrimitives (TriangleCtx CullBack PolygonFill NoOffset LastVertex) ((Smooth))
39 & mapFragments (\((uv)) -> ((color * texture2D (Sampler PointFilter MirroredRepeat texture) uv )))
40 & accumulateWith (DepthOp Less True, ColorOp NoBlending (V4 True True True True))
41 `overlay` 123 `overlay`
42 plane 124 plane
43 & mapPrimitives (\((p)) -> let p' = coordmap cam $ plane_mat *. p in (p', p%xz)) 125 & mapPrimitives (\((p)) -> let p' = coordmap cam $ plane_mat *. p in (p', p%xz))
@@ -89,7 +171,10 @@ main = renderFrame $
89 (Uniform "ViewProjection") 171 (Uniform "ViewProjection")
90 (Uniform "diffuseColor") 172 (Uniform "diffuseColor")
91 (Texture2DSlot "diffuseTexture") 173 (Texture2DSlot "diffuseTexture")
92 (fetch "objects" (Attribute "position", Attribute "normal", Attribute "uvw")) 174 (Uniform "specularReflectivity")
175 (fetch "objects0" (Attribute "position", Attribute "normal", Attribute "uvw"))
176 (fetch "objects1" (Attribute "position", Attribute "normal", Attribute "uvw"))
177 (fetch "objects2" (Attribute "position", Attribute "normal", Attribute "uvw"))
93 (fetch "plane" ((Attribute "position"))) 178 (fetch "plane" ((Attribute "position")))
94 (fetch "Curve" (Attribute "position", Attribute "color")) 179 (fetch "Curve" (Attribute "position", Attribute "color"))
95 (fetch "Points" (Attribute "position", Attribute "color")) 180 (fetch "Points" (Attribute "position", Attribute "color"))