summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am1
-rw-r--r--chickadee/render.scm14
-rw-r--r--chickadee/render/framebuffer.scm125
-rw-r--r--chickadee/render/gl.scm22
4 files changed, 152 insertions, 10 deletions
diff --git a/Makefile.am b/Makefile.am
index fa84dd6..c9a563e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -54,6 +54,7 @@ SOURCES = \
chickadee/render/shader.scm \
chickadee/render/vertex-buffer.scm \
chickadee/render/viewport.scm \
+ chickadee/render/framebuffer.scm \
chickadee/render/shapes.scm \
chickadee/render/sprite.scm \
chickadee/render.scm \
diff --git a/chickadee/render.scm b/chickadee/render.scm
index efb5004..9588a95 100644
--- a/chickadee/render.scm
+++ b/chickadee/render.scm
@@ -26,16 +26,19 @@
#:use-module (chickadee math matrix)
#:use-module (chickadee render gpu)
#:use-module (chickadee render blend)
+ #:use-module (chickadee render framebuffer)
#:use-module (chickadee render shader)
#:use-module (chickadee render texture)
#:use-module (chickadee render vertex-buffer)
#:use-module (chickadee render viewport)
#:export (current-viewport
+ current-framebuffer
current-blend-mode
current-depth-test
current-texture
current-projection
with-viewport
+ with-framebuffer
with-blend-mode
with-depth-test
with-texture
@@ -44,6 +47,7 @@
gpu-apply*))
(define *current-viewport* null-viewport)
+(define *current-framebuffer* null-framebuffer)
(define *current-blend-mode* 'replace)
(define *current-depth-test* #f)
(define *current-texture* null-texture)
@@ -52,6 +56,9 @@
(define (current-viewport)
*current-viewport*)
+(define (current-framebuffer)
+ *current-framebuffer*)
+
(define (current-blend-mode)
*current-blend-mode*)
@@ -74,6 +81,9 @@
(define-syntax-rule (with-viewport viewport body ...)
(with (*current-viewport* viewport) body ...))
+(define-syntax-rule (with-framebuffer framebuffer body ...)
+ (with (*current-framebuffer* framebuffer) body ...))
+
(define-syntax-rule (with-blend-mode blend-mode body ...)
(with (*current-blend-mode* blend-mode) body ...))
@@ -133,6 +143,10 @@
(define-syntax-rule (gpu-apply* shader vertex-array count . uniforms)
(begin
+ ;; It's important that the framebuffer is set before setting the
+ ;; viewport because applying a new viewport will clear the current
+ ;; framebuffer.
+ (gpu-state-set! *framebuffer-state* (current-framebuffer))
(gpu-state-set! *viewport-state* (current-viewport))
(gpu-state-set! *blend-mode-state* (current-blend-mode))
(gpu-state-set! *depth-test-state* (current-depth-test))
diff --git a/chickadee/render/framebuffer.scm b/chickadee/render/framebuffer.scm
new file mode 100644
index 0000000..39e4bfa
--- /dev/null
+++ b/chickadee/render/framebuffer.scm
@@ -0,0 +1,125 @@
+;;; Chickadee Game Toolkit
+;;; Copyright © 2017 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:
+;;
+;; Render to texture.
+;;
+;;; Code:
+
+(define-module (chickadee render framebuffer)
+ #:use-module (oop goops)
+ #:use-module (ice-9 match)
+ #:use-module (srfi srfi-9)
+ #:use-module (system foreign)
+ #:use-module (gl)
+ #:use-module (gl enums)
+ #:use-module (chickadee render gl)
+ #:use-module (chickadee render gpu)
+ #:use-module ((chickadee render texture) #:select (make-texture null-texture))
+ #:export (make-framebuffer
+ framebuffer?
+ framebuffer-texture
+ null-framebuffer
+ apply-framebuffer
+ *framebuffer-state*))
+
+(define (generate-framebuffer)
+ "Generate a new OpenGL framebuffer object."
+ (let ((bv (u32vector 1)))
+ (gl-gen-framebuffers 1 (bytevector->pointer bv))
+ (u32vector-ref bv 0)))
+
+(define (generate-renderbuffer)
+ "Generate a new OpenGL renderbuffer object."
+ (let ((bv (u32vector 1)))
+ (gl-gen-renderbuffers 1 (bytevector->pointer bv))
+ (u32vector-ref bv 0)))
+
+(define-record-type <framebuffer>
+ (%make-framebuffer id renderbuffer-id texture)
+ framebuffer?
+ (id framebuffer-id)
+ (renderbuffer-id framebuffer-renderbuffer-id)
+ (texture framebuffer-texture))
+
+(define null-framebuffer
+ (%make-framebuffer 0 0 null-texture))
+
+(define <<framebuffer>> (class-of null-framebuffer))
+
+(define (free-framebuffer framebuffer)
+ (gl-delete-renderbuffers 1
+ (bytevector->pointer
+ (u32vector
+ (framebuffer-renderbuffer-id framebuffer))))
+ (gl-delete-framebuffers 1
+ (bytevector->pointer
+ (u32vector
+ (framebuffer-id framebuffer)))))
+
+(define-method (gpu-finalize (framebuffer <<framebuffer>>))
+ (free-framebuffer framebuffer))
+
+(define (apply-framebuffer framebuffer)
+ (gl-bind-framebuffer (version-3-0 framebuffer)
+ (framebuffer-id framebuffer)))
+
+(define *framebuffer-state*
+ (make-gpu-state apply-framebuffer null-framebuffer))
+
+(define make-framebuffer
+ (let ((draw-buffers (u32vector (version-3-0 color-attachment0))))
+ (lambda* (width height #:key (min-filter 'linear) (mag-filter 'linear)
+ (wrap-s 'repeat) (wrap-t 'repeat))
+ "Create a new framebuffer that renders to a texture with
+dimensions WIDTH x HEIGHT."
+ (let* ((framebuffer-id (generate-framebuffer))
+ (renderbuffer-id (generate-renderbuffer))
+ (texture (make-texture #f width height
+ #:min-filter min-filter
+ #:mag-filter mag-filter
+ #:wrap-s wrap-s
+ #:wrap-t wrap-t))
+ (framebuffer (%make-framebuffer framebuffer-id
+ renderbuffer-id
+ texture)))
+ (gpu-state-set! *framebuffer-state* framebuffer)
+ ;; Setup depth buffer.
+ (gl-bind-renderbuffer (version-3-0 renderbuffer)
+ renderbuffer-id)
+ (gl-renderbuffer-storage (version-3-0 renderbuffer)
+ (pixel-format depth-component)
+ width
+ height)
+ (gl-framebuffer-renderbuffer (version-3-0 framebuffer)
+ (arb-framebuffer-object depth-attachment)
+ (version-3-0 renderbuffer)
+ renderbuffer-id)
+ ;; Setup framebuffer.
+ (gl-framebuffer-texture-2d (version-3-0 framebuffer)
+ (version-3-0 color-attachment0)
+ (texture-target texture-2d)
+ ((@@ (chickadee render texture) texture-id)
+ texture)
+ 0)
+ (gl-draw-buffers 1 (bytevector->pointer draw-buffers))
+ ;; Check for errors.
+ (unless (= (gl-check-framebuffer-status (version-3-0 framebuffer))
+ (version-3-0 framebuffer-complete))
+ (error "Framebuffer cannot be created"))
+ framebuffer))))
diff --git a/chickadee/render/gl.scm b/chickadee/render/gl.scm
index 005194b..bbe3c44 100644
--- a/chickadee/render/gl.scm
+++ b/chickadee/render/gl.scm
@@ -220,16 +220,18 @@ object.")
-> void)
"Attach a renderbuffer object to a framebuffer object.")
-(export glGenFramebuffers
- glDeleteFramebuffers
- glBindFramebuffer
- glFramebufferTexture2D
- glCheckFramebufferStatus
- glGenRenderbuffers
- glDeleteRenderbuffers
- glBindRenderbuffer
- glRenderbufferStorage
- glFramebufferRenderbuffer)
+(export (glGenFramebuffers . gl-gen-framebuffers)
+ (glDeleteFramebuffers . gl-delete-framebuffers)
+ (glBindFramebuffer . gl-bind-framebuffer)
+ (glFramebufferTexture2D . gl-framebuffer-texture-2d)
+ (glCheckFramebufferStatus . gl-check-framebuffer-status)
+ (glGenRenderbuffers . gl-gen-renderbuffers)
+ (glDeleteRenderbuffers . gl-delete-renderbuffers)
+ (glBindRenderbuffer . gl-bind-renderbuffer)
+ (glRenderbufferStorage . gl-renderbuffer-storage)
+ (glFramebufferRenderbuffer . gl-framebuffer-renderbuffer))
+
+(re-export (%glDrawBuffers . gl-draw-buffers))
;;;