summaryrefslogtreecommitdiff
path: root/chickadee/graphics/pbr.scm
diff options
context:
space:
mode:
Diffstat (limited to 'chickadee/graphics/pbr.scm')
-rw-r--r--chickadee/graphics/pbr.scm150
1 files changed, 150 insertions, 0 deletions
diff --git a/chickadee/graphics/pbr.scm b/chickadee/graphics/pbr.scm
new file mode 100644
index 0000000..375f5d0
--- /dev/null
+++ b/chickadee/graphics/pbr.scm
@@ -0,0 +1,150 @@
+;;; Chickadee Game Toolkit
+;;; Copyright © 2019 David Thompson <davet@gnu.org>
+;;;
+;;; Chickadee is free software: you can redistribute it and/or modify
+;;; it under the terms of the GNU General Public License as published
+;;; by the Free Software Foundation, either version 3 of the License,
+;;; or (at your option) any later version.
+;;;
+;;; Chickadee is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;;; General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with this program. If not, see
+;;; <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; Physically based lighting model.
+;;
+;;; Code:
+
+(define-module (chickadee graphics pbr)
+ #:use-module (chickadee math vector)
+ #:use-module (chickadee graphics)
+ #:use-module (chickadee graphics color)
+ #:use-module (chickadee graphics shader)
+ #:use-module (chickadee graphics texture)
+ #:use-module (srfi srfi-9)
+ #:export (make-pbr-material
+ pbr-material?
+ pbr-material-name
+ pbr-material-base-color-factor
+ pbr-material-base-color-texture
+ pbr-material-metallic-factor
+ pbr-material-roughness-factor
+ pbr-material-metallic-roughness-texture
+ pbr-material-normal-factor
+ pbr-material-normal-texture
+ pbr-material-occlusion-facgor
+ pbr-material-occlusion-texture
+ pbr-material-emissive-factor
+ pbr-material-emissive-texture
+ pbr-material-alpha-mode
+ pbr-material-alpha-cutoff
+ pbr-material-double-sided?
+ default-pbr-material
+ load-pbr-shader
+ gpu-apply/pbr))
+
+(define-shader-type <pbr-material>
+ make-pbr-material
+ pbr-material?
+ (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)
+ (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)
+ (float-vec3 occlusion-factor pbr-material-occlusion-factor)
+ (local-field occlusion-texture pbr-material-occlusion-texture)
+ (float-vec3 emissive-factor pbr-material-emissive-factor)
+ (local-field emissive-texture pbr-material-emissive-texture)
+ (local-field alpha-mode pbr-material-alpha-mode)
+ (float alpha-cutoff pbr-material-alpha-cutoff)
+ (bool 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
+ #:metallic-factor 1.0
+ #:roughness-factor 1.0
+ #:metallic-roughness-texture null-texture
+ #:normal-factor #v(1.0 1.0 1.0)
+ #:normal-texture null-texture
+ #:occlusion-factor #v(1.0 1.0 1.0)
+ #:occlusion-texture null-texture
+ #:emissive-factor #v(1.0 1.0 1.0)
+ #:emissive-texture null-texture
+ #:alpha-mode 'opaque
+ #:alpha-cutoff 0.5
+ #:double-sided? #f))
+
+;; TODO: Actually implement PBR. For now it's just the minimal amount
+;; of code needed to render the base texture of a mesh.
+(define pbr-shader
+ (delay
+ (strings->shader
+ "
+#ifdef GLSL330
+layout (location = 0) in vec3 position;
+layout (location = 1) in vec2 texcoord0;
+#elif defined(GLSL130)
+in vec3 position;
+in vec2 texcoord0;
+#elif defined(GLSL120)
+attribute vec3 position;
+attribute vec2 texcoord0;
+#endif
+#ifdef GLSL120
+varying vec2 fragTex;
+#else
+out vec2 fragTex;
+#endif
+uniform mat4 model;
+uniform mat4 view;
+uniform mat4 projection;
+
+void main(void) {
+ fragTex = texcoord0;
+ gl_Position = projection * view * model * vec4(position.xyz, 1.0);
+}
+"
+ "
+#ifdef GLSL120
+attribute vec2 fragTex;
+#else
+in vec2 fragTex;
+#endif
+#ifdef GLSL330
+out vec4 fragColor;
+#endif
+uniform vec3 baseColorFactor;
+uniform sampler2D baseColorTexture;
+
+void main (void) {
+#ifdef GLSL330
+ fragColor = texture(baseColorTexture, fragTex) *
+ vec4(baseColorFactor, 1.0);
+#else
+ gl_FragColor = texture2D(baseColorTexture, fragTex) *
+ vec4(baseColorFactor, 1.0);
+#endif
+}
+")))
+
+(define (load-pbr-shader)
+ (force pbr-shader))
+
+(define (gpu-apply/pbr shader vertex-array material model-matrix view-matrix)
+ (with-texture 0 (pbr-material-base-color-texture material)
+ (gpu-apply shader vertex-array
+ #:model model-matrix
+ #:view view-matrix
+ #:projection (current-projection)
+ #:base-color-factor (pbr-material-base-color-factor material))))