summaryrefslogtreecommitdiff
path: root/2d/shader.scm
diff options
context:
space:
mode:
Diffstat (limited to '2d/shader.scm')
-rw-r--r--2d/shader.scm331
1 files changed, 0 insertions, 331 deletions
diff --git a/2d/shader.scm b/2d/shader.scm
deleted file mode 100644
index 56a4e03..0000000
--- a/2d/shader.scm
+++ /dev/null
@@ -1,331 +0,0 @@
-;;; guile-2d
-;;; Copyright (C) 2014 David Thompson <dthompson2@worcester.edu>
-;;;
-;;; This program 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.
-;;;
-;;; This program 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/>.
-
-(define-module (2d shader)
- #:use-module (system foreign)
- #:use-module (rnrs bytevectors)
- #:use-module (srfi srfi-1)
- #:use-module (srfi srfi-4)
- #:use-module (srfi srfi-9)
- #:use-module (ice-9 rdelim)
- #:use-module (gl)
- #:use-module (gl low-level)
- #:use-module (2d helpers)
- #:use-module (2d transform)
- #:use-module (2d vector)
- #:use-module (2d color)
- #:use-module (2d wrappers gl)
- #:export (make-shader
- make-vertex-shader
- make-fragment-shader
- load-shader
- load-vertex-shader
- load-fragment-shader
- shader?
- vertex-shader?
- fragment-shader?
- shader-compiled?
- shader-type
- shader-id
- make-shader-program
- load-shader-program
- shader-program-id
- shader-program?
- shader-program-linked?
- with-shader-program
- %uniform-setters
- register-uniform-setter!
- uniforms))
-
-(define-syntax-rule (define-logger name length-proc log-proc)
- (define (name obj)
- (let ((log-length (u32vector 0)))
- (length-proc obj (version-2-0 info-log-length)
- (bytevector->pointer log-length))
- (let ((log (make-u8vector (1+ (u32vector-ref log-length 0)))))
- (log-proc obj (u32vector-ref log-length 0) %null-pointer
- (bytevector->pointer log))
- (format #t "~a\n" (utf8->string log))))))
-
-(define-syntax-rule (define-status name status-proc status-name)
- (define (name obj)
- (let ((status (u32vector 0)))
- (status-proc obj (version-2-0 status-name)
- (bytevector->pointer status))
- (= (u32vector-ref status 0) 1))))
-
-;;;
-;;; Shaders
-;;;
-
-(define-record-type <shader>
- (%make-shader type id)
- shader?
- (type shader-type)
- (id shader-id))
-
-(define (vertex-shader? shader)
- "Return #t if SHADER is a vertex shader, #f otherwise."
- (eq? (shader-type shader) 'vertex))
-
-(define (fragment-shader? shader)
- "Return #t if SHADER is a fragment shader, #f otherwise."
- (eq? (shader-type shader) 'fragment))
-
-(define-guardian shader-guardian
- (lambda (shader)
- (false-if-exception
- (glDeleteShader (shader-id shader)))))
-
-;; Reap GL shaders when their wrapper objects are GC'd.
-(define-guardian shader-guardian
- (lambda (shader)
- (false-if-exception (glDeleteShader (shader-id shader)))))
-
-(define-status %shader-compiled? glGetShaderiv compile-status)
-
-(define (shader-compiled? shader)
- (%shader-compiled? (shader-id shader)))
-
-(define-logger %display-compilation-error glGetShaderiv glGetShaderInfoLog)
-
-(define (display-compilation-error shader)
- (%display-compilation-error (shader-id shader)))
-
-(define (compile-shader shader)
- "Attempt to compiler SHADER. Compilation errors are written to
-stdout."
- (glCompileShader (shader-id shader))
- (unless (shader-compiled? shader)
- (display "Failed to compile shader:\n")
- (display-compilation-error shader)))
-
-(define (set-shader-source shader source)
- "Use the GLSL source code in the string SOURCE for SHADER."
- (let ((length (u32vector (string-length source)))
- (str (u64vector (pointer-address (string->pointer source)))))
- (glShaderSource (shader-id shader) 1 (bytevector->pointer str)
- (bytevector->pointer length))))
-
-(define (gl-shader-type type)
- "Convert the symbol TYPE to the appropriate OpenGL shader constant."
- (cond ((eq? type 'vertex)
- (version-2-0 vertex-shader))
- ((eq? type 'fragment)
- (version-2-0 fragment-shader))
- (else
- (error "Invalid shader type: " type))))
-
-(define (make-shader type source)
- "Create a new GLSL shader of the given TYPE (vertex or fragment) and
-compile the GLSL program contained in the string SOURCE."
- (let* ((id (glCreateShader (gl-shader-type type)))
- (shader (%make-shader type id)))
- (shader-guardian shader)
- (set-shader-source shader source)
- (compile-shader shader)
- shader))
-
-(define (make-vertex-shader source)
- "Create a new GLSL vertex shader and compile the GLSL program
-contained in the string SOURCE."
- (make-shader 'vertex source))
-
-(define (make-fragment-shader source)
- "Create a new GLSL fragment shader and compile the GLSL program
-contained in the string SOURCE."
- (make-shader 'fragment source))
-
-(define (load-shader type filename)
- "Create a new GLSL shader of the given TYPE (vertex or fragment) and
-compile the GLSL program stored in the file FILENAME."
- (if (file-exists? filename)
- (make-shader type (call-with-input-file filename read-string))
- (error "File not found!" filename)))
-
-(define (load-vertex-shader filename)
- "Create a new GLSL vertex shader and compile the GLSL program stored
-in the file FILENAME."
- (load-shader 'vertex filename))
-
-(define (load-fragment-shader filename)
- "Create a new GLSL vertex shader and compile the GLSL program stored
-in the file FILENAME."
- (load-shader 'fragment filename))
-
-;;;
-;;; Programs
-;;;
-
-(define-record-type <shader-program>
- (%make-shader-program id)
- shader-program?
- (id shader-program-id))
-
-(define-guardian shader-program-guardian
- (lambda (shader-program)
- (false-if-exception
- (glDeleteProgram (shader-program-id shader-program)))))
-
-(define-status %shader-program-linked? glGetProgramiv link-status)
-
-(define (shader-program-linked? shader-program)
- "Return #t if SHADER-PROGRAM has been successfully linked with
-shaders or #f otherwise."
- (%shader-program-linked? (shader-program-id shader-program)))
-
-(define-logger %display-linking-error glGetProgramiv glGetProgramInfoLog)
-
-(define (display-linking-error shader-program)
- (%display-linking-error (shader-program-id shader-program)))
-
-(define (make-shader-program vertex-shader fragment-shader)
- "Create a new shader program that has been linked with the given
-VERTEX-SHADER and FRAGMENT-SHADER."
- (unless (and (vertex-shader? vertex-shader)
- (fragment-shader? fragment-shader))
- (error "Expected a vertex shader and fragment shader"
- vertex-shader fragment-shader))
- (let* ((id (glCreateProgram))
- (shader-program (%make-shader-program id))
- (shaders (list vertex-shader fragment-shader)))
- (shader-program-guardian shader-program)
- (for-each (lambda (shader)
- (glAttachShader id (shader-id shader)))
- shaders)
- (glLinkProgram id)
- (unless (shader-program-linked? shader-program)
- (display "Failed to link shader program:\n")
- (display-linking-error shader-program))
- ;; Once the program has been linked, the shaders can be detached.
- (for-each (lambda (shader)
- (glDetachShader id (shader-id shader)))
- shaders)
- shader-program))
-
-(define (load-shader-program vertex-shader-file-name fragment-shader-file-name)
- (make-shader-program (load-vertex-shader vertex-shader-file-name)
- (load-fragment-shader fragment-shader-file-name)))
-
-(define current-shader-program (make-parameter #f))
-
-(define-syntax-rule (with-shader-program shader-program body ...)
- "Evaluate BODY with SHADER-PROGRAM bound."
- (parameterize ((current-shader-program shader-program))
- (begin
- (glUseProgram (shader-program-id shader-program))
- (let ((return-value (begin body ...)))
- (glUseProgram 0)
- return-value))))
-
-(define-record-type <uniform-setter>
- (make-uniform-setter predicate proc)
- uniform-setter?
- (predicate uniform-setter-predicate)
- (proc uniform-setter-proc))
-
-(define %uniform-setters '())
-
-(define (register-uniform-setter! predicate setter)
- "Add a new type of uniform setter for shader programs where
-PREDICATE tests the type of a given value and SETTER performs the
-necessary OpenGL calls to set the uniform value in the proper
-location."
- (set! %uniform-setters
- (cons (make-uniform-setter predicate setter)
- %uniform-setters)))
-
-;; Built-in uniform setters for booleans, numbers, vectors, and
-;; colors.
-(register-uniform-setter! boolean?
- (lambda (location b)
- (glUniform1i location (if b 1 0))))
-
-(register-uniform-setter! number?
- (lambda (location n)
- (glUniform1f location n)))
-
-(register-uniform-setter! vector2?
- (lambda (location v)
- (glUniform2f location (vx v) (vy v))))
-
-(register-uniform-setter! vector3?
- (lambda (location v)
- (glUniform3f location (vx v) (vy v) (vz v))))
-
-(register-uniform-setter! vector4?
- (lambda (location v)
- (glUniform4f location (vx v) (vy v) (vz v) (vw v))))
-
-(register-uniform-setter! transform?
- (lambda (location t)
- (let ((pointer
- (bytevector->pointer
- (array-contents (transform-matrix t)))))
- (glUniformMatrix4fv location 1 #f
- pointer))))
-
-(register-uniform-setter! color?
- (lambda (location c)
- (glUniform4f location
- (color-r c)
- (color-g c)
- (color-b c)
- (color-a c))))
-
-(define uniform-location
- (memoize
- (lambda (shader-program name)
- "Retrieve the location for the uniform NAME within SHADER-PROGRAM."
- (glGetUniformLocation (shader-program-id shader-program)
- (symbol->string name)))))
-
-(define attribute-location
- (memoize
- (lambda (shader-program name)
- "Retrieve the location for the uniform NAME within SHADER-PROGRAM."
- (glGetAttribLocation (shader-program-id shader-program)
- (symbol->string name)))))
-
-(define (uniform-set! shader-program name value)
- "Use the appropriate setter procedure to translate VALUE into OpenGL
-compatible data and assign it to the location of the uniform NAME
-within SHADER-PROGRAM."
- (let ((setter (find (lambda (setter)
- ((uniform-setter-predicate setter) value))
- %uniform-setters))
- (location (uniform-location shader-program name)))
- (if setter
- ((uniform-setter-proc setter) location value)
- (error "Not a valid uniform data type" value))))
-
-;; Bind values to uniform variables within the current shader program
-;; via a let-style syntax. The types of the given values must be
-;; accounted for in the %uniform-setters list. This macro simply sets
-;; uniform values and does not restore the previous values after
-;; evaluating the body of the form.
-;;
-;; emacs: (put 'uniforms 'scheme-indent-function 1)
-(define-syntax uniforms
- (syntax-rules ()
- ((_ () body ...)
- (begin body ...))
- ((_ ((name value) ...) body ...)
- (begin
- (uniform-set! (current-shader-program) 'name value)
- ...
- body ...))))