diff options
Diffstat (limited to 'chickadee/graphics/pbr.scm')
-rw-r--r-- | chickadee/graphics/pbr.scm | 150 |
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)))) |