render: Make apply-* procedures public.
[chickadee.git] / chickadee / render / framebuffer.scm
1 ;;; Chickadee Game Toolkit
2 ;;; Copyright © 2017 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 ;; Render to texture.
21 ;;
22 ;;; Code:
23
24 (define-module (chickadee render framebuffer)
25 #:use-module (oop goops)
26 #:use-module (ice-9 match)
27 #:use-module (srfi srfi-9)
28 #:use-module (system foreign)
29 #:use-module (gl)
30 #:use-module (gl enums)
31 #:use-module (chickadee math matrix)
32 #:use-module (chickadee render gl)
33 #:use-module (chickadee render gpu)
34 #:use-module ((chickadee render texture) #:select (make-texture null-texture))
35 #:use-module (chickadee render viewport)
36 #:export (make-framebuffer
37 framebuffer?
38 framebuffer-texture
39 framebuffer-viewport
40 framebuffer-projection
41 null-framebuffer
42 apply-framebuffer))
43
44 (define (generate-framebuffer)
45 "Generate a new OpenGL framebuffer object."
46 (let ((bv (u32vector 1)))
47 (gl-gen-framebuffers 1 (bytevector->pointer bv))
48 (u32vector-ref bv 0)))
49
50 (define (generate-renderbuffer)
51 "Generate a new OpenGL renderbuffer object."
52 (let ((bv (u32vector 1)))
53 (gl-gen-renderbuffers 1 (bytevector->pointer bv))
54 (u32vector-ref bv 0)))
55
56 (define-record-type <framebuffer>
57 (%make-framebuffer id renderbuffer-id texture viewport projection)
58 framebuffer?
59 (id framebuffer-id)
60 (renderbuffer-id framebuffer-renderbuffer-id)
61 (texture framebuffer-texture)
62 (viewport framebuffer-viewport)
63 (projection framebuffer-projection))
64
65 (define null-framebuffer
66 (%make-framebuffer 0 0 null-texture null-viewport (make-identity-matrix4)))
67
68 (define <<framebuffer>> (class-of null-framebuffer))
69
70 (define (free-framebuffer framebuffer)
71 (gl-delete-renderbuffers 1
72 (bytevector->pointer
73 (u32vector
74 (framebuffer-renderbuffer-id framebuffer))))
75 (gl-delete-framebuffers 1
76 (bytevector->pointer
77 (u32vector
78 (framebuffer-id framebuffer)))))
79
80 (define-method (gpu-finalize (framebuffer <<framebuffer>>))
81 (free-framebuffer framebuffer))
82
83 (define (apply-framebuffer framebuffer)
84 (gl-bind-framebuffer (version-3-0 framebuffer)
85 (framebuffer-id framebuffer)))
86
87 (define make-framebuffer
88 (let ((draw-buffers (u32vector (version-3-0 color-attachment0))))
89 (lambda* (width height #:key (min-filter 'linear) (mag-filter 'linear)
90 (wrap-s 'repeat) (wrap-t 'repeat))
91 "Create a new framebuffer that renders to a texture with
92 dimensions WIDTH x HEIGHT."
93 (let* ((framebuffer-id (generate-framebuffer))
94 (renderbuffer-id (generate-renderbuffer))
95 (texture (make-texture #f width height
96 #:flip? #t
97 #:min-filter min-filter
98 #:mag-filter mag-filter
99 #:wrap-s wrap-s
100 #:wrap-t wrap-t))
101 ;; It is convenient to make a default viewport and
102 ;; projection matrix for the framebuffer so that the
103 ;; rendering engine can set it whenever it changes to
104 ;; this framebuffer, saving users the trouble of having
105 ;; to this tedious task themselves.
106 (viewport (make-viewport 0 0 width height))
107 (projection (orthographic-projection 0 width height 0 0 1))
108 (framebuffer (%make-framebuffer framebuffer-id
109 renderbuffer-id
110 texture
111 viewport
112 projection)))
113 (set-gpu-framebuffer! (current-gpu) framebuffer)
114 ;; Setup depth buffer.
115 (gl-bind-renderbuffer (version-3-0 renderbuffer)
116 renderbuffer-id)
117 (gl-renderbuffer-storage (version-3-0 renderbuffer)
118 (pixel-format depth-component)
119 width
120 height)
121 (gl-framebuffer-renderbuffer (version-3-0 framebuffer)
122 (arb-framebuffer-object depth-attachment)
123 (version-3-0 renderbuffer)
124 renderbuffer-id)
125 ;; Setup framebuffer.
126 (gl-framebuffer-texture-2d (version-3-0 framebuffer)
127 (version-3-0 color-attachment0)
128 (texture-target texture-2d)
129 ((@@ (chickadee render texture) texture-id)
130 texture)
131 0)
132 (gl-draw-buffers 1 (bytevector->pointer draw-buffers))
133 ;; Check for errors.
134 (unless (= (gl-check-framebuffer-status (version-3-0 framebuffer))
135 (version-3-0 framebuffer-complete))
136 (error "Framebuffer cannot be created"))
137 framebuffer))))