(defpackage #:shader (:shadow #:load) (:use #:cl) (:export #:load #:use #:shader-program #:set-bool #:set-int #:set-float #:set-mat4 #:set-vec)) (in-package :shader) (defclass shader () ((program :accessor shader-program :initarg :program))) (defun read-shader-file (path) (with-open-file (stream path) (apply #'concatenate 'string (loop for line = (read-line stream nil nil) while line nconc (list line (string #\Newline)))))) (defun load (vertex-shader-path fragment-shader-path) (let ((vertex-shader-file (read-shader-file vertex-shader-path)) (fragment-shader-file (read-shader-file fragment-shader-path)) (vertex-shader (gl:create-shader :vertex-shader)) (fragment-shader (gl:create-shader :fragment-shader)) (program (gl:create-program))) (gl:shader-source vertex-shader vertex-shader-file) (gl:compile-shader vertex-shader) (gl:shader-source fragment-shader fragment-shader-file) (gl:compile-shader fragment-shader) (format t "~&Vertex shader info log: ~%~a" (gl:get-shader-info-log vertex-shader)) (format t "~&Fragment shader info log: ~%~a" (gl:get-shader-info-log fragment-shader)) (gl:attach-shader program vertex-shader) (gl:attach-shader program fragment-shader) (gl:link-program program) (gl:delete-shader vertex-shader) (gl:delete-shader fragment-shader) (make-instance 'shader :program program))) (defmethod use ((self shader)) (gl:use-program (shader-program self))) (defmacro define-set-uniform (name f) `(defmethod ,name ((self shader) name value) (,f (gl:get-uniform-location (shader-program self) name) value))) (define-set-uniform set-bool gl:uniformi) (define-set-uniform set-int gl:uniformi) (define-set-uniform set-float gl:uniformf) (define-set-uniform set-vec gl:uniformfv) (defmethod set-mat4 ((self shader) name matrice &optional (transpose t)) (gl:uniform-matrix-4fv (gl:get-uniform-location (shader-program self) name) (vector matrice) transpose))