diff options
Diffstat (limited to 'chickadee/render/phong.scm')
-rw-r--r-- | chickadee/render/phong.scm | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/chickadee/render/phong.scm b/chickadee/render/phong.scm new file mode 100644 index 0000000..07c0eeb --- /dev/null +++ b/chickadee/render/phong.scm @@ -0,0 +1,160 @@ +;;; 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: +;; +;; Simple forward rendered Phong lighting model. +;; +;;; Code: + +(define-module (chickadee render phong) + #:use-module (chickadee math vector) + #:use-module (chickadee render) + #:use-module (chickadee render color) + #:use-module (chickadee render shader) + #:use-module (srfi srfi-9) + #:export (make-phong-material + phong-material? + phong-material-name + phong-material-ambient + phong-material-diffuse + phong-material-specular + phong-material-specular-exponent + default-phong-material + load-phong-shader + gpu-apply/phong)) + + +;;; +;;; Phong Material +;;; + +(define-shader-type <phong-material> + make-phong-material + phong-material? + (local-field name phong-material-name) + (float-vec3 ambient phong-material-ambient) + (float-vec3 diffuse phong-material-diffuse) + (float-vec3 specular phong-material-specular) + (float shininess phong-material-shininess)) + +(define default-phong-material + (make-phong-material #:name "default" + #:ambient (vec3 0.5 0.5 0.5) + #:diffuse (vec3 0.5 0.5 0.5) + #:specular (vec3 0.5 0.5 0.5) + #:shininess 32.0)) + + +;;; +;;; Lights +;;; + +(define-shader-type <directional-light> + make-directional-light + directional-light? + (float-vec4 color directional-light-color) + (float-vec3 direction directional-light-direction) + (float-vec3 ambient directional-light-ambient) + (float-vec3 diffuse directional-light-diffuse) + (float-vec3 specular directional-light-specular) + (float shininess directional-light-shininess)) + +(define default-directional-light + (make-directional-light #:color white + #:direction (vec3 -1.0 0.0 -1.0) + #:ambient (vec3 0.5 0.5 0.5) + #:diffuse (vec3 0.5 0.5 0.5) + #:specular (vec3 0.5 0.5 0.5) + #:shininess 32.0)) + + +;;; +;;; Phong Shader +;;; + +(define phong-shader + (delay + (strings->shader + " +#version 130 + +in vec3 position; +in vec2 texcoord; +in vec3 normal; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +out vec3 fragNorm; +out vec2 fragTex; + +void main() { + gl_Position = projection * view * model * vec4(position, 1.0); + // TODO: Calculate normal matrix on CPU + fragNorm = normalize(model * vec4(normal, 1.0)).xyz; + fragTex = texcoord; +} +" + " +#version 130 + +struct Material { + vec3 ambient; + vec3 diffuse; + vec3 specular; + float shininess; +}; + +struct DirectionalLight { + vec4 color; + vec3 direction; + vec3 ambient; + vec3 diffuse; + vec3 specular; +}; + +in vec3 fragNorm; +in vec2 fragTex; + +uniform Material material; +uniform DirectionalLight directionalLight; + +void main() { + vec3 lightColor = directionalLight.color.xyz; + vec3 ambientColor = material.ambient * lightColor; + vec3 lightDir = normalize(-directionalLight.direction); + float diffuseFactor = max(dot(lightDir, fragNorm), 0.0); + vec3 diffuseColor = diffuseFactor * material.diffuse * lightColor; + vec3 reflectDir = reflect(-lightDir, fragNorm); + float specularFactor = pow(max(dot(lightDir, reflectDir), 0.0), material.shininess); + vec3 specularColor = specularFactor * material.specular * lightColor; + gl_FragColor = vec4(ambientColor + diffuseColor + specularColor, 1.0); +} +"))) + +(define (load-phong-shader) + (force phong-shader)) + +(define (gpu-apply/phong shader vertex-array material model-matrix view-matrix) + (gpu-apply shader vertex-array + #:model model-matrix + #:view view-matrix + #:projection (current-projection) + #:material material + #:directional-light default-directional-light)) |