summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Thompson <dthompson2@worcester.edu>2021-05-07 21:17:59 -0400
committerDavid Thompson <dthompson2@worcester.edu>2021-05-07 21:17:59 -0400
commit271a2bb9775dd8a4a6e5a232f27af86ca7ffd83e (patch)
treedebf24d4cf81d50cf60fea9619063fc6cd1a4094
parentfeb3c58215960f2bac66922e8d1a1f8e32b7ff95 (diff)
model: Improve PBR material handling for glTF models.
-rw-r--r--chickadee/graphics/model.scm81
-rw-r--r--chickadee/graphics/pbr.scm53
-rw-r--r--data/shaders/pbr-frag.glsl73
3 files changed, 134 insertions, 73 deletions
diff --git a/chickadee/graphics/model.scm b/chickadee/graphics/model.scm
index ea4533f..caec045 100644
--- a/chickadee/graphics/model.scm
+++ b/chickadee/graphics/model.scm
@@ -43,7 +43,9 @@
#:use-module (rnrs bytevectors)
#:use-module (rnrs io ports)
#:use-module (srfi srfi-9)
+ #:use-module (srfi srfi-11)
#:use-module ((srfi srfi-43) #:select (vector-every))
+ #:use-module (web uri)
#:export (scene-node?
scene-node-name
scene-node-mesh
@@ -770,7 +772,7 @@
((string-prefix? base64-prefix uri)
(base64-decode (substring uri (string-length base64-prefix))))
(uri
- (call-with-input-file (scope-file uri)
+ (call-with-input-file (scope-file (uri-decode uri))
(lambda (port)
(get-bytevector-n port length))))
(else
@@ -870,7 +872,7 @@
(let ((image (vector-ref images (number-ref obj "source")))
(sampler
(vector-ref samplers (or (number-ref/optional obj "sampler") 0))))
- (load-image (scope-file (string-ref image "uri"))
+ (load-image (scope-file (uri-decode (string-ref image "uri")))
#:min-filter (texture-filter
(number-ref/optional sampler "minFilter"))
#:mag-filter (texture-filter
@@ -885,46 +887,24 @@
(let ((v (or (number-array-ref/optional pbrmr "baseColorFactor")
#(1.0 1.0 1.0 1.0))))
(vec3 (vector-ref v 0) (vector-ref v 1) (vector-ref v 2))))
- (base-color-texture
- (match (object-ref/optional pbrmr "baseColorTexture")
- (#f null-texture)
- (obj
- (vector-ref textures (number-ref obj "index")))))
(metallic-factor
(or (number-ref/optional pbrmr "metallicFactor")
1.0))
(roughness-factor
(or (number-ref/optional pbrmr "roughnessFactor")
1.0))
- (metallic-roughness-texture
- (match (object-ref/optional pbrmr "metallicRoughnessTexture")
- (#f #f)
- (obj
- (vector-ref textures (number-ref obj "index")))))
(normal-factor
(let ((v (or (array-ref/optional obj "normalFactor")
#(1.0 1.0 1.0))))
(vec3 (vector-ref v 0) (vector-ref v 1) (vector-ref v 2))))
- (normal-texture
- (match (object-ref/optional obj "normalTexture")
- (#f #f)
- (obj (vector-ref textures (number-ref obj "index")))))
(occlusion-factor
(let ((v (or (array-ref/optional obj "occlusionFactor")
#(1.0 1.0 1.0))))
(vec3 (vector-ref v 0) (vector-ref v 1) (vector-ref v 2))))
- (occlusion-texture
- (match (object-ref/optional obj "occlusionTexture")
- (#f #f)
- (obj (vector-ref textures (number-ref obj "index")))))
(emissive-factor
(let ((v (or (array-ref/optional obj "emissiveFactor")
#(1.0 1.0 1.0))))
(vec3 (vector-ref v 0) (vector-ref v 1) (vector-ref v 2))))
- (emissive-texture
- (match (object-ref/optional obj "emissiveTexture")
- (#f #f)
- (obj (vector-ref textures (number-ref obj "index")))))
(alpha-mode (match (or (string-ref/optional obj "alphaMode")
"BLEND")
("OPAQUE" 'opaque)
@@ -934,21 +914,44 @@
(double-sided? (boolean-ref/optional obj "doubleSided"))
(extensions (object-ref/optional obj "extensions"))
(extras (assoc-ref obj "extras")))
- (make-pbr-material #:name name
- #:base-color-factor base-color-factor
- #:base-color-texture base-color-texture
- #:metallic-factor metallic-factor
- #:roughness-factor roughness-factor
- #:metallic-roughness-texture metallic-roughness-texture
- #:normal-factor normal-factor
- #:normal-texture normal-texture
- #:occlusion-factor occlusion-factor
- #:occlusion-texture occlusion-texture
- #:emissive-factor emissive-factor
- #:emissive-texture emissive-texture
- #:alpha-mode alpha-mode
- #:alpha-cutoff alpha-cutoff
- #:double-sided? double-sided?)))
+ (define (parse-texture obj key)
+ (match (object-ref/optional obj key)
+ (#f (values null-texture 0))
+ (texture
+ (values (vector-ref textures (number-ref texture "index"))
+ (or (number-ref/optional texture "texCoord") 0)))))
+ (define (non-null-texture? texture)
+ (not (eq? texture null-texture)))
+ (let-values (((base-color-texture base-color-texcoord)
+ (parse-texture pbrmr "baseColorTexture"))
+ ((normal-texture normal-texcoord)
+ (parse-texture obj "normalTexture"))
+ ((occlusion-texture occlusion-texcoord)
+ (parse-texture obj "occlusionTexture"))
+ ((emissive-texture emissive-texcoord)
+ (parse-texture obj "emissiveTexture")))
+ (make-pbr-material #:name name
+ #:base-color-factor base-color-factor
+ #:base-color-texture base-color-texture
+ #:base-color-texture-enabled (non-null-texture? base-color-texture)
+ #:base-color-texcoord base-color-texcoord
+ #:metallic-factor metallic-factor
+ #:roughness-factor roughness-factor
+ #:normal-factor normal-factor
+ #:normal-texture normal-texture
+ #:normal-texture-enabled (non-null-texture? normal-texture)
+ #:normal-texcoord normal-texcoord
+ #:occlusion-factor occlusion-factor
+ #:occlusion-texture occlusion-texture
+ #:occlusion-texture-enabled (non-null-texture? occlusion-texture)
+ #:occlusion-texcoord occlusion-texcoord
+ #:emissive-factor emissive-factor
+ #:emissive-texture emissive-texture
+ #:emissive-texture-enabled (non-null-texture? emissive-texture)
+ #:emissive-texcoord emissive-texcoord
+ #:alpha-mode alpha-mode
+ #:alpha-cutoff alpha-cutoff
+ #:double-sided? double-sided?))))
(define (attribute-name->index name)
(let ((shader (graphics-variable-ref pbr-shader)))
(match name
diff --git a/chickadee/graphics/pbr.scm b/chickadee/graphics/pbr.scm
index 1ed3777..4b5b192 100644
--- a/chickadee/graphics/pbr.scm
+++ b/chickadee/graphics/pbr.scm
@@ -27,6 +27,7 @@
#:use-module (chickadee graphics buffer)
#:use-module (chickadee graphics color)
#:use-module (chickadee graphics engine)
+ #:use-module (chickadee graphics polygon)
#:use-module (chickadee graphics shader)
#:use-module (chickadee graphics texture)
#:use-module (srfi srfi-9)
@@ -35,15 +36,18 @@
pbr-material-name
pbr-material-base-color-factor
pbr-material-base-color-texture
+ pbr-material-base-color-texcoord
pbr-material-metallic-factor
pbr-material-roughness-factor
- pbr-material-metallic-roughness-texture
pbr-material-normal-factor
pbr-material-normal-texture
+ pbr-material-normal-texcoord
pbr-material-occlusion-facgor
pbr-material-occlusion-texture
+ pbr-material-occlusion-texcoord
pbr-material-emissive-factor
pbr-material-emissive-texture
+ pbr-material-emissive-texcoord
pbr-material-alpha-mode
pbr-material-alpha-cutoff
pbr-material-double-sided?
@@ -57,34 +61,48 @@
(local-field name pbr-material-name)
(float-vec3 base-color-factor pbr-material-base-color-factor)
(local-field base-color-texture pbr-material-base-color-texture)
+ (bool base-color-texture-enabled pbr-material-base-color-texture-enabled?)
+ (int base-color-texcoord pbr-material-base-color-texcoord)
(float metallic-factor pbr-material-metallic-factor)
(float roughness-factor pbr-material-roughness-factor)
- (local-field metallic-roughness-texture pbr-material-metallic-roughness-texture)
(float-vec3 normal-factor pbr-material-normal-factor)
(local-field normal-texture pbr-material-normal-texture)
+ (bool normal-texture-enabled pbr-material-normal-texture-enabled)
+ (int normal-texcoord pbr-material-normal-texcoord)
(float-vec3 occlusion-factor pbr-material-occlusion-factor)
(local-field occlusion-texture pbr-material-occlusion-texture)
+ (bool occlusion-texture-enabled pbr-material-occlusion-texture-enabled)
+ (int occlusion-texcoord pbr-material-occlusion-texcoord)
(float-vec3 emissive-factor pbr-material-emissive-factor)
(local-field emissive-texture pbr-material-emissive-texture)
+ (bool emissive-texture-enabled pbr-material-emissive-texture-enabled)
+ (int emissive-texcoord pbr-material-emissive-texcoord)
(local-field alpha-mode pbr-material-alpha-mode)
(float alpha-cutoff pbr-material-alpha-cutoff)
- (bool double-sided? pbr-material-double-sided?))
+ (local-field double-sided? pbr-material-double-sided?))
(define default-pbr-material
(make-pbr-material #:name "default"
#:base-color-factor #v(1.0 1.0 1.0)
#:base-color-texture null-texture
+ #:base-color-texture-enabled #f
+ #:base-color-texcoord 0
#:metallic-factor 1.0
#:roughness-factor 1.0
- #:metallic-roughness-texture #f
#:normal-factor #v(1.0 1.0 1.0)
- #:normal-texture #f
+ #:normal-texture null-texture
+ #:normal-texture-enabled #f
+ #:normal-texcoord 0
#:occlusion-factor #v(1.0 1.0 1.0)
- #:occlusion-texture #f
+ #:occlusion-texture null-texture
+ #:occlusion-texture-enabled #f
+ #:occlusion-texcoord 0
#:emissive-factor #v(1.0 1.0 1.0)
- #:emissive-texture #f
+ #:emissive-texture null-texture
+ #:emissive-texture-enabled #f
+ #:emissive-texcoord 0
#:alpha-mode 'opaque
- #:alpha-cutoff 0.5
+ #:alpha-cutoff 1.0
#:double-sided? #f))
(define-graphics-variable pbr-shader
@@ -93,24 +111,21 @@
(define (shader-apply/pbr vertex-array material model-matrix view-matrix)
(let* ((shader (graphics-variable-ref pbr-shader))
- (base-color-texture (pbr-material-base-color-texture material))
- (secondary-texture (or (pbr-material-metallic-roughness-texture material)
- (pbr-material-normal-texture material)
- (pbr-material-occlusion-texture material)
- (pbr-material-emissive-texture material)
- null-texture))
(vattrs (vertex-array-attributes vertex-array))
(sattrs (shader-attributes shader)))
- (with-graphics-state ((g:texture-0 base-color-texture)
- (g:texture-1 secondary-texture))
+ (with-graphics-state ((g:cull-face-mode (if (pbr-material-double-sided? material)
+ no-cull-face-mode
+ back-cull-face-mode))
+ (g:texture-0 (pbr-material-base-color-texture material))
+ (g:texture-1 (pbr-material-normal-texture material))
+ (g:texture-2 (pbr-material-occlusion-texture material))
+ (g:texture-3 (pbr-material-emissive-texture material)))
(shader-apply shader vertex-array
#:model model-matrix
#:view view-matrix
#:projection (current-projection)
- #:textured0 (not (eq? base-color-texture null-texture))
- #:textured1 (not (eq? secondary-texture null-texture))
#:vertex-colored (buffer-view?
(assv-ref vattrs
(attribute-location
(hash-ref sattrs "color0"))))
- #:base-color-factor (pbr-material-base-color-factor material)))))
+ #:material material))))
diff --git a/data/shaders/pbr-frag.glsl b/data/shaders/pbr-frag.glsl
index 813f9a9..ce252ab 100644
--- a/data/shaders/pbr-frag.glsl
+++ b/data/shaders/pbr-frag.glsl
@@ -1,5 +1,23 @@
// -*- mode: c -*-
+struct Material {
+ vec3 baseColorFactor;
+ bool baseColorTextureEnabled;
+ int baseColorTexcoord;
+ float metallicFactor;
+ float roughnessFactor;
+ vec3 normalFactor;
+ bool normalTextureEnabled;
+ int normalTexcoord;
+ vec3 occlusionFactor;
+ bool occlusionTextureEnabled;
+ int occlusionTexcoord;
+ vec3 emissiveFactor;
+ bool emissiveTextureEnabled;
+ int emissiveTexcoord;
+ float alphaCutoff;
+};
+
#ifdef GLSL120
attribute vec2 fragTexcoord0;
attribute vec2 fragTexcoord1
@@ -14,26 +32,51 @@ in vec4 fragColor0;
out vec4 fragColor;
#endif
-uniform bool textured0;
-uniform bool textured1;
+uniform Material material;
uniform bool vertexColored;
-uniform vec3 baseColorFactor;
-uniform sampler2D texture0;
-uniform sampler2D texture1;
+uniform sampler2D baseColorTexture;
+uniform sampler2D normalTexture;
+uniform sampler2D occlusionTexture;
+uniform sampler2D emissiveTexture;
+
+vec4 sampleTexture(sampler2D tex, bool enabled, int texcoord, vec3 factor, vec4 defaultColor) {
+ if(enabled && texcoord == 0) {
+ return texture(tex, fragTexcoord0) * vec4(factor, 1.0);
+ } else if(enabled && texcoord == 1) {
+ return texture(tex, fragTexcoord1) * vec4(factor, 1.0);
+ } else {
+ return defaultColor;
+ }
+}
-void main (void) {
- vec4 finalColor = vec4(baseColorFactor, 1.0);
- // Vertex coloring.
+void main(void) {
+ vec4 finalColor = sampleTexture(baseColorTexture,
+ material.baseColorTextureEnabled,
+ material.baseColorTexcoord,
+ material.baseColorFactor,
+ vec4(1.0, 1.0, 1.0, 1.0));
+
+ // Mix in vertex color, if present.
if(vertexColored) {
finalColor *= fragColor0;
}
- // Texture sampling.
- if(textured0) {
- finalColor *= texture(texture0, fragTexcoord0);
- }
- if(textured1) {
- finalColor += texture(texture1, fragTexcoord1);
- }
+
+ // TODO: Actually apply PBR calculations.
+ finalColor += sampleTexture(normalTexture,
+ material.normalTextureEnabled,
+ material.normalTexcoord,
+ material.normalFactor,
+ vec4(0.0, 0.0, 0.0, 0.0)) * 0.1;
+ finalColor += sampleTexture(occlusionTexture,
+ material.occlusionTextureEnabled,
+ material.occlusionTexcoord,
+ material.occlusionFactor,
+ vec4(0.0, 0.0, 0.0, 0.0)) * 0.1;
+ finalColor += sampleTexture(emissiveTexture,
+ material.emissiveTextureEnabled,
+ material.emissiveTexcoord,
+ material.emissiveFactor,
+ vec4(0.0, 0.0, 0.0, 0.0));
#ifdef GLSL330
fragColor = finalColor;
#else