Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Additional PBR textures, metallic/roughness texture + tangents #12

Merged
merged 3 commits into from
May 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions src/Text/GLTF/Loader/Gltf.hs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ module Text.GLTF.Loader.Gltf
Scene (..),
Texture (..),
TextureInfo (..),
NormalTextureInfo (..),
OcclusionTextureInfo (..),

-- * Lenses

Expand Down Expand Up @@ -149,8 +151,14 @@ data Material = Material
materialDoubleSided :: Bool,
-- | The factors for the emissive color of the material.
materialEmissiveFactor :: V3 Float,
-- | The texture for the emissive color of the material.
materialEmissiveTexture :: Maybe TextureInfo,
-- | The user-defined name of this object.
materialName :: Maybe Text,
-- | The material's tangent space normal map texture
materialNormalTexture :: Maybe NormalTextureInfo,
-- | The material's ambient occlusion texture
materialOcclusionTexture :: Maybe OcclusionTextureInfo,
-- | Metallic roughness Physically Based Rendering (PBR) methodology parameter values.
materialPbrMetallicRoughness :: Maybe PbrMetallicRoughness
}
Expand Down Expand Up @@ -233,6 +241,8 @@ data MeshPrimitive = MeshPrimitive
meshPrimitiveNormals :: Vector (V3 Float),
-- | A Vector of vertex positions.
meshPrimitivePositions :: Vector (V3 Float),
-- | A Vector of vertex tangents
meshPrimitiveTangents :: Vector (V4 Float),
-- | A Vector of vertex texture coordinates
meshPrimitiveTexCoords :: Vector (V2 Float),
-- | A Vector of vertex colors.
Expand Down Expand Up @@ -260,6 +270,8 @@ data PbrMetallicRoughness = PbrMetallicRoughness
pbrBaseColorTexture :: Maybe TextureInfo,
-- | The factor for the metalness of the material.
pbrMetallicFactor :: Float,
-- | The combined metallic roughness texture of the material
pbrMetallicRoughnessTexture :: Maybe TextureInfo,
-- | The factor for the roughness of the material.
pbrRoughnessFactor :: Float
}
Expand Down Expand Up @@ -308,6 +320,32 @@ data TextureInfo = TextureInfo
}
deriving (Eq, Show)

-- | Reference to a normal map texture
data NormalTextureInfo = NormalTextureInfo
{ -- | The index of the texture.
normalTextureId :: Int,
-- | This integer value is used to construct a string in the format
-- TEXCOORD_<set_index> which is a reference to a key in mesh.primitives.attributes
-- (e.g. a value of 0 corresponds to TEXCOORD_0).
normalTextureTexCoord :: Int,
-- | The scalar parameter applied to each normal vector of the normal
-- texture.
normalTextureScale :: Float
}
deriving (Eq, Show)

data OcclusionTextureInfo = OcclusionTextureInfo
{ -- | The index of the texture.
occlusionTextureId :: Int,
-- | This integer value is used to construct a string in the format
-- TEXCOORD_<set_index> which is a reference to a key in mesh.primitives.attributes
-- (e.g. a value of 0 corresponds to TEXCOORD_0).
occlusionTextureTexCoord :: Int,
-- | A scalar multiplier controlling the amount of occlusion applied.
occlusionTextureStrength :: Float
}
deriving (Eq, Show)

-- | Metadata about the glTF asset
_asset :: Lens' Gltf Asset
_asset = lens gltfAsset (\gltf asset -> gltf{gltfAsset = asset})
Expand Down
40 changes: 37 additions & 3 deletions src/Text/GLTF/Loader/Internal/Adapter.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
module Text.GLTF.Loader.Internal.Adapter
( attributePosition,
attributeNormal,
attributeTangent,
attributeTexCoord,
attributeColors,
runAdapter,
Expand Down Expand Up @@ -54,6 +55,9 @@ attributePosition = "POSITION"
attributeNormal :: Text
attributeNormal = "NORMAL"

attributeTangent :: Text
attributeTangent = "TANGENT"

attributeTexCoord :: Text
attributeTexCoord = "TEXCOORD_0"

Expand Down Expand Up @@ -149,8 +153,12 @@ adaptMaterial Material.Material{..} =
materialAlphaMode = adaptAlphaMode alphaMode,
materialDoubleSided = doubleSided,
materialEmissiveFactor = toV3 emissiveFactor,
materialEmissiveTexture = adaptTextureInfo <$> emissiveTexture,
materialName = name,
materialPbrMetallicRoughness = adaptPbrMetallicRoughness <$> pbrMetallicRoughness
materialNormalTexture = adaptNormalTextureInfo <$> normalTexture,
materialOcclusionTexture = adaptOcclusionTextureInfo <$> occlusionTexture,
materialPbrMetallicRoughness = adaptPbrMetallicRoughness
<$> pbrMetallicRoughness
}

adaptMesh :: Mesh.Mesh -> Adapter Mesh
Expand Down Expand Up @@ -223,7 +231,9 @@ adaptPbrMetallicRoughness PbrMetallicRoughness.PbrMetallicRoughness{..} =
{ pbrBaseColorFactor = toV4 baseColorFactor,
pbrBaseColorTexture = adaptTextureInfo <$> baseColorTexture,
pbrMetallicFactor = metallicFactor,
pbrRoughnessFactor = roughnessFactor
pbrRoughnessFactor = roughnessFactor,
pbrMetallicRoughnessTexture = adaptTextureInfo
<$> metallicRoughnessTexture
}

adaptMeshPrimitives :: Vector Mesh.MeshPrimitive -> Adapter (Vector MeshPrimitive)
Expand All @@ -249,13 +259,35 @@ adaptSamplerWrap Sampler.MIRRORED_REPEAT = MirroredRepeat
adaptSamplerWrap Sampler.REPEAT = Repeat
adaptSamplerWrap mode = error $ "Invalid SamplerWrap: " <> show mode

adaptTextureInfo :: TextureInfo.TextureInfo a -> TextureInfo
adaptTextureInfo :: TextureInfo.TextureInfo_ -> TextureInfo
adaptTextureInfo TextureInfo.TextureInfo{..} =
TextureInfo
{ textureId = index,
textureTexCoord = texCoord
}

adaptNormalTextureInfo
:: TextureInfo.TextureInfo Material.MaterialNormal
-> NormalTextureInfo
adaptNormalTextureInfo TextureInfo.TextureInfo{..} =
let Material.MaterialNormal{..} = subtype
in NormalTextureInfo
{ normalTextureId = index,
normalTextureTexCoord = texCoord,
normalTextureScale = scale
}

adaptOcclusionTextureInfo
:: TextureInfo.TextureInfo Material.MaterialOcclusion
-> OcclusionTextureInfo
adaptOcclusionTextureInfo TextureInfo.TextureInfo{..} =
let Material.MaterialOcclusion{..} = subtype
in OcclusionTextureInfo
{ occlusionTextureId = index,
occlusionTextureTexCoord = texCoord,
occlusionTextureStrength = strength
}

adaptMeshPrimitive :: Mesh.MeshPrimitive -> Adapter MeshPrimitive
adaptMeshPrimitive Mesh.MeshPrimitive{..} = do
gltf <- getGltf
Expand All @@ -268,13 +300,15 @@ adaptMeshPrimitive Mesh.MeshPrimitive{..} = do
meshPrimitiveMode = adaptMeshPrimitiveMode mode,
meshPrimitiveNormals = maybe mempty (vertexNormals gltf buffers') normals,
meshPrimitivePositions = maybe mempty (vertexPositions gltf buffers') positions,
meshPrimitiveTangents = maybe mempty (vertexTangents gltf buffers') tangents,
meshPrimitiveTexCoords = maybe mempty (vertexTexCoords gltf buffers') texCoords,
meshPrimitiveColors =
maybe mempty (fmap (mapV4 toRatio) . vertexColors gltf buffers') colors
}
where
positions = attributes HashMap.!? attributePosition
normals = attributes HashMap.!? attributeNormal
tangents = attributes HashMap.!? attributeTangent
texCoords = attributes HashMap.!? attributeTexCoord
colors = attributes HashMap.!? attributeColors
toRatio w = fromIntegral w / fromIntegral (maxBound :: Word16)
Expand Down
5 changes: 5 additions & 0 deletions src/Text/GLTF/Loader/Internal/BufferAccessor.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module Text.GLTF.Loader.Internal.BufferAccessor
vertexPositions,
vertexNormals,
vertexTexCoords,
vertexTangents,
vertexColors,
imageDataRaw,
) where
Expand Down Expand Up @@ -109,6 +110,10 @@ vertexPositions = readBufferWithGet getPositions
vertexNormals :: GlTF -> Vector GltfBuffer -> AccessorIx -> Vector (V3 Float)
vertexNormals = readBufferWithGet getNormals

-- | Decode vertex tangents
vertexTangents :: GlTF -> Vector GltfBuffer -> AccessorIx -> Vector (V4 Float)
vertexTangents = readBufferWithGet getTangents

-- | Decode texture coordinates. Note that we only use the first one.
vertexTexCoords :: GlTF -> Vector GltfBuffer -> AccessorIx -> Vector (V2 Float)
vertexTexCoords = readBufferWithGet getTexCoords
Expand Down
5 changes: 5 additions & 0 deletions src/Text/GLTF/Loader/Internal/Decoders.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module Text.GLTF.Loader.Internal.Decoders
getIndices32,
getPositions,
getNormals,
getTangents,
getTexCoords,
getColors,

Expand Down Expand Up @@ -46,6 +47,10 @@ getPositions = getVec3 getFloat
getNormals :: Get (Vector (V3 Float))
getNormals = getVec3 getFloat

-- | Vertex tangents binary decoder
getTangents :: Get (Vector (V4 Float))
getTangents = getVec4 getFloat

-- | Texture coordinates binary decoder
getTexCoords :: Get (Vector (V2 Float))
getTexCoords = getVec2 getFloat
Expand Down
41 changes: 38 additions & 3 deletions test/Text/GLTF/Loader/Internal/AdapterSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,15 @@ spec = do
Image.Image
{ uri = Nothing,
mimeType = Just "text/jpg",
bufferView = Just $ BufferView.BufferViewIx 4,
bufferView = Just $ BufferView.BufferViewIx 6,
name = Just "Image",
extensions = Nothing,
extras = Nothing
}

it "Adapts a BufferView image" $ do
env' <- env
let image = ImageBufferView (BufferView.BufferViewIx 5)
let image = ImageBufferView (BufferView.BufferViewIx 6)

runReader (adaptImage image codecImage) env'
`shouldBe` Image
Expand Down Expand Up @@ -277,7 +277,7 @@ spec = do
{ Mesh.attributes =
HashMap.insert
attributeColors
(Accessor.AccessorIx 4)
(Accessor.AccessorIx 5)
(Mesh.attributes mkCodecMeshPrimitive)
}
loaderMeshPrimitive' = loaderMeshPrimitive & _meshPrimitiveColors .~ [0, 0.2, 0.6, 1]
Expand Down Expand Up @@ -347,7 +347,10 @@ loaderMaterial =
materialAlphaMode = Opaque,
materialDoubleSided = True,
materialEmissiveFactor = V3 1.0 2.0 3.0,
materialEmissiveTexture = Just loaderEmissiveTexture,
materialName = Just "Material",
materialNormalTexture = Just loaderNormalTexture,
materialOcclusionTexture = Just loaderOcclusionTexture,
materialPbrMetallicRoughness = Just loaderPbrMetallicRoughness
}

Expand Down Expand Up @@ -402,6 +405,7 @@ loaderPbrMetallicRoughness =
{ pbrBaseColorFactor = V4 1.0 2.0 3.0 4.0,
pbrBaseColorTexture = Just loaderBaseColorTexture,
pbrMetallicFactor = 1.0,
pbrMetallicRoughnessTexture = Just loaderMetallicRoughnessTexture,
pbrRoughnessFactor = 2.0
}

Expand All @@ -413,6 +417,7 @@ loaderMeshPrimitive =
meshPrimitiveMode = Triangles,
meshPrimitiveNormals = fmap (\x -> V3 x x x) [5 .. 8],
meshPrimitivePositions = fmap (\x -> V3 x x x) [1 .. 4],
meshPrimitiveTangents = fmap (\x -> V4 x x x x) [13 .. 16],
meshPrimitiveTexCoords = fmap (\x -> V2 x x) [9 .. 12],
meshPrimitiveColors = []
}
Expand All @@ -423,3 +428,33 @@ loaderBaseColorTexture =
{ textureId = 15,
textureTexCoord = 10
}

loaderMetallicRoughnessTexture :: TextureInfo
loaderMetallicRoughnessTexture =
TextureInfo
{ textureId = 16,
textureTexCoord = 11
}

loaderEmissiveTexture :: TextureInfo
loaderEmissiveTexture =
TextureInfo
{ textureId = 17,
textureTexCoord = 12
}

loaderNormalTexture :: NormalTextureInfo
loaderNormalTexture =
NormalTextureInfo
{ normalTextureId = 18,
normalTextureTexCoord = 13,
normalTextureScale = 1
}

loaderOcclusionTexture :: OcclusionTextureInfo
loaderOcclusionTexture =
OcclusionTextureInfo
{ occlusionTextureId = 19,
occlusionTextureTexCoord = 14,
occlusionTextureStrength = 2
}
2 changes: 1 addition & 1 deletion test/Text/GLTF/Loader/Internal/BufferAccessorSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ spec = do
}

images <- loadImages gltf' basePath
images `shouldBe` [ImageBufferView (BufferView.BufferViewIx 5)]
images `shouldBe` [ImageBufferView (BufferView.BufferViewIx 6)]

it "Returns NoImage when no data specificed" $ do
let gltf' =
Expand Down
Loading
Loading