render: texture: Support using 32 texture units.
[chickadee.git] / chickadee / render.scm
CommitLineData
98dc87a0
DT
1;;; Chickadee Game Toolkit
2;;; Copyright © 2016 David Thompson <davet@gnu.org>
3;;;
4;;; Chickadee is free software: you can redistribute it and/or modify
5;;; it under the terms of the GNU General Public License as published
6;;; by the Free Software Foundation, either version 3 of the License,
7;;; or (at your option) any later version.
8;;;
9;;; Chickadee is distributed in the hope that it will be useful, but
10;;; WITHOUT ANY WARRANTY; without even the implied warranty of
11;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12;;; General Public License for more details.
13;;;
14;;; You should have received a copy of the GNU General Public License
15;;; along with this program. If not, see
16;;; <http://www.gnu.org/licenses/>.
17
18;;; Commentary:
19;;
20;; High-level rendering API.
21;;
22;;; Code:
23
24(define-module (chickadee render)
25 #:use-module (srfi srfi-88)
26 #:use-module (chickadee math matrix)
27 #:use-module (chickadee render gpu)
28 #:use-module (chickadee render blend)
d89629e4 29 #:use-module (chickadee render framebuffer)
98dc87a0
DT
30 #:use-module (chickadee render shader)
31 #:use-module (chickadee render texture)
32 #:use-module (chickadee render vertex-buffer)
3227d839
DT
33 #:use-module (chickadee render viewport)
34 #:export (current-viewport
d89629e4 35 current-framebuffer
3227d839 36 current-blend-mode
98dc87a0
DT
37 current-depth-test
38 current-texture
39 current-projection
3227d839 40 with-viewport
d89629e4 41 with-framebuffer
98dc87a0
DT
42 with-blend-mode
43 with-depth-test
44 with-texture
45 with-projection
46 gpu-apply
47 gpu-apply*))
48
3227d839 49(define *current-viewport* null-viewport)
d89629e4 50(define *current-framebuffer* null-framebuffer)
98dc87a0
DT
51(define *current-blend-mode* 'replace)
52(define *current-depth-test* #f)
98dc87a0 53(define *current-projection* (make-identity-matrix4))
8152ddc9 54(define *current-textures* (make-vector 32 null-texture))
98dc87a0 55
3227d839
DT
56(define (current-viewport)
57 *current-viewport*)
58
d89629e4
DT
59(define (current-framebuffer)
60 *current-framebuffer*)
61
98dc87a0
DT
62(define (current-blend-mode)
63 *current-blend-mode*)
64
65(define (current-depth-test)
66 *current-depth-test*)
67
8152ddc9
DT
68(define (current-texture i)
69 (vector-ref *current-textures* i))
98dc87a0
DT
70
71(define (current-projection)
72 *current-projection*)
73
74(define-syntax-rule (with (name value) body ...)
75 (let ((prev name))
76 (dynamic-wind
77 (lambda () (set! name value))
78 (lambda () body ...)
79 (lambda () (set! name prev)))))
80
3227d839
DT
81(define-syntax-rule (with-viewport viewport body ...)
82 (with (*current-viewport* viewport) body ...))
83
d89629e4 84(define-syntax-rule (with-framebuffer framebuffer body ...)
6a913492
DT
85 (with (*current-framebuffer* framebuffer)
86 ;; As a convenience, initialize the viewport as well so that
87 ;; the user doesn't have to explicitly make a viewport unless
88 ;; they actually want to do fancy viewport manipulations.
89 (with-viewport (framebuffer-viewport framebuffer)
90 body ...)))
d89629e4 91
98dc87a0
DT
92(define-syntax-rule (with-blend-mode blend-mode body ...)
93 (with (*current-blend-mode* blend-mode) body ...))
94
95(define-syntax-rule (with-depth-test depth-test body ...)
96 (with (*current-depth-test* depth-test) body ...))
97
8152ddc9
DT
98(define-syntax-rule (with-texture n texture body ...)
99 (let ((prev (vector-ref *current-textures* n)))
100 (dynamic-wind
101 (lambda () (vector-set! *current-textures* n texture))
102 (lambda () body ...)
103 (lambda () (vector-set! *current-textures* n prev)))))
98dc87a0
DT
104
105(define-syntax-rule (with-shader shader body ...)
106 (with (*current-shader* shader)
107 (initialize-uniforms)
108 body ...))
109
110(define-syntax-rule (with-vertex-array vertex-array body ...)
111 (with (*current-vertex-array* vertex-array) body ...))
112
113(define-syntax-rule (with-projection matrix body ...)
114 (with (*current-projection* matrix) body ...))
115
116;; (define (initialize-uniforms)
117;; (hash-for-each (lambda (name uniform)
118;; (unless (hash-get-handle *current-uniforms* name)
119;; (hash-set! *current-uniforms* name
120;; (uniform-default-value uniform))))
121;; (shader-uniforms *current-shader*)))
122
123;; (define-syntax uniform-let
124;; (syntax-rules ()
125;; ((_ () body ...) (begin body ...))
126;; ((_ ((name value) . rest) body ...)
127;; (let ((uniform (shader-uniform (current-shader) name))
128;; (prev (hash-ref *current-uniforms* name)))
129;; (if uniform
130;; (dynamic-wind
131;; (lambda ()
132;; (hash-set! *current-uniforms* name value))
133;; (lambda ()
134;; (uniform-let rest body ...))
135;; (lambda ()
136;; (hash-set! *current-uniforms* name prev)))
137;; (error "no such uniform: " name))))))
138
139;; (define (uniform-ref name)
140;; (uniform-value (shader-uniform (current-shader) name)))
141
142(define-syntax uniform-apply
143 (lambda (x)
144 (syntax-case x ()
145 ((_ shader ()) (datum->syntax x #t))
146 ((_ shader (name value . rest))
147 (with-syntax ((sname (datum->syntax x (keyword->string
148 (syntax->datum #'name)))))
149 #'(begin
150 (set-uniform-value! (shader-uniform shader sname) value)
151 (uniform-apply shader rest)))))))
152
153(define-syntax-rule (gpu-apply* shader vertex-array count . uniforms)
154 (begin
d89629e4
DT
155 ;; It's important that the framebuffer is set before setting the
156 ;; viewport because applying a new viewport will clear the current
157 ;; framebuffer.
158 (gpu-state-set! *framebuffer-state* (current-framebuffer))
3227d839 159 (gpu-state-set! *viewport-state* (current-viewport))
98dc87a0
DT
160 (gpu-state-set! *blend-mode-state* (current-blend-mode))
161 (gpu-state-set! *depth-test-state* (current-depth-test))
98dc87a0
DT
162 (gpu-state-set! *shader-state* shader)
163 (gpu-state-set! *vertex-array-state* vertex-array)
8152ddc9
DT
164 (let loop ((i 0))
165 (when (< i 32)
166 (texture-set! i (current-texture i))
167 (loop (1+ i))))
98dc87a0 168 (uniform-apply shader uniforms)
8152ddc9
DT
169 (hash-for-each (lambda (name uniform)
170 (when (eq? 'sampler-2d (uniform-type uniform))
171 (set-uniform-value! uniform (uniform-value uniform))))
172 (shader-uniforms shader))
98dc87a0
DT
173 (render-vertices count)))
174
175(define-syntax-rule (gpu-apply shader vertex-array uniforms ...)
176 (gpu-apply* shader vertex-array #f uniforms ...))