summaryrefslogtreecommitdiff
path: root/chickadee/render/phong.scm
diff options
context:
space:
mode:
Diffstat (limited to 'chickadee/render/phong.scm')
-rw-r--r--chickadee/render/phong.scm160
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))