diff options
author | Joe Crayne <joe@jerkface.net> | 2019-07-23 00:19:18 -0400 |
---|---|---|
committer | Joe Crayne <joe@jerkface.net> | 2019-07-23 00:19:18 -0400 |
commit | 4026bea0ec0e2604ebcac6e31ae9ba79a85a034a (patch) | |
tree | bdda064243b16dfb8c6e07930f507d1910208736 | |
parent | 6bdffaf86341d118a965f7316c7141baea58d87c (diff) |
Implement 3 distinct lighting models.
-rw-r--r-- | LoadMesh.hs | 43 | ||||
-rw-r--r-- | MeshSketch.hs | 11 | ||||
-rw-r--r-- | hello_obj2.lc | 101 |
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 | |||
126 | uploadOBJToGPU scalebb (subModels,(mtlLib,objpath)) = do | 126 | uploadOBJToGPU 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 | ||
207 | searchMaterial :: V.Vector (Map Text (ObjMaterial, TextureData)) | 205 | searchMaterial |
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) | ||
210 | searchMaterial mtlLib (count,name) = foldr go id (V.drop (V.length mtlLib - count) mtlLib) Nothing | 209 | searchMaterial 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 | ||
216 | addOBJToObjectArray :: GLStorage -> String -> [MaterialMesh GPUMesh] -> V.Vector (Map Text (ObjMaterial,TextureData)) | 215 | addOBJToObjectArray :: GLStorage -> String |
216 | -> [MaterialMesh GPUMesh] | ||
217 | -> V.Vector (Map Text (ObjMaterial,TextureData)) | ||
217 | -> IO [MaskableObject] | 218 | -> IO [MaskableObject] |
218 | addOBJToObjectArray storage slotName objMesh mtlLib = forM objMesh $ \matmesh -> do | 219 | addOBJToObjectArray 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 | |||
10 | point :: Vec 3 Float -> Vec 4 Float | 10 | point :: Vec 3 Float -> Vec 4 Float |
11 | point p = V4 p%x p%y p%z 1 | 11 | point p = V4 p%x p%y p%z 1 |
12 | 12 | ||
13 | homoproj :: Vec 4 Float -> Vec 3 Float | ||
14 | homoproj v = v%xyz *! (1 / v%w) | ||
15 | |||
16 | type Position = Vec 4 Float | ||
17 | type TextureCoord = Vec 3 Float | ||
18 | type Normal = Vec 3 Float | ||
19 | type 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 | ||
29 | ambientOnly :: Mat 4 4 Float -> Vec 4 Float -> Texture -> PrimitiveStream Triangle (Position,TextureCoord,Normal) | ||
30 | -> Overlay | ||
31 | ambientOnly 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 | ||
49 | lambertianReflectance 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. | ||
75 | blinnPhong 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 | ||
14 | makeFrame (cubemap :: TextureCube) | 96 | makeFrame (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")) |