wh-engine/wh-engine/render/render-target.lisp

91 lines
4.4 KiB
Common Lisp

;;;; wh-engine/render/render-target.lisp
;;;; Render targets - structures that store a GL framebuffer, renderbuffer, and texture.
(in-package wh-engine/render)
(defclass render-target ()
((width :documentation "The width in pixels of this render target."
:reader width
:type fixnum
:initarg :width
:initform *view-width*)
(height :documentation "The height in pixels of this render target."
:reader height
:type fixnum
:initarg :height
:initform *view-height*)
(depth-texture-p :documentation "Whether or not to render depth (and stencil) information to a texture."
:reader depth-texture-p
:type boolean
:initarg :depth-texture-p
:initform nil)
(framebuffer :documentation "The GL framebuffer associated with this render target."
:reader framebuffer
:type (or fixnum null)
:initform nil)
(renderbuffer :documentation "The GL renderbuffer associated with this render target."
:reader renderbuffer
:type (or fixnum null)
:initform nil)
(depth-texture :documentation "The GL texture containing the depth and stencil output for this render target."
:reader depth-texture
:type (or fixnum null)
:initform nil)
(render-texture :documentation "The GL render texture containing the output of this render target."
:reader render-texture
:type (or fixnum null)
:initform nil))
(:documentation "Stores a GL framebuffer, and its associated renderbuffer and output texture."))
(defmethod make-load-form ((this render-target) &optional environment)
(declare (ignore environment))
`(make-instance ',(class-name (class-of this))
:width ,(o! this width) :height ,(o! this height)
:depth-texture-p ,(o! this depth-texture-p)))
(defmethod initialize-instance :after ((this render-target) &key)
;; create render texture
(setf (o! this :slot render-texture) (gl:gen-texture))
(gl:bind-texture :texture-2d (o! this :slot render-texture))
(gl:tex-image-2d :texture-2d 0 :rgba
(o! this :slot width) (o! this :slot height)
0 :rgba :unsigned-byte (cffi:null-pointer))
(gl:tex-parameter :texture-2d :texture-wrap-s :clamp-to-edge)
(gl:tex-parameter :texture-2d :texture-wrap-t :clamp-to-edge)
(gl:tex-parameter :texture-2d :texture-min-filter :linear)
(gl:tex-parameter :texture-2d :texture-mag-filter :linear)
(gl:bind-texture :texture-2d 0)
(if (o! this depth-texture-p)
(progn
;; create depth texture
(setf (o! this :slot depth-texture) (gl:gen-texture))
(gl:bind-texture :texture-2d (o! this :slot depth-texture))
(gl:tex-image-2d :texture-2d 0 :depth24-stencil8
(o! this :slot width) (o! this :slot height)
0 :depth-stencil :unsigned-int-24-8 (cffi:null-pointer))
(gl:tex-parameter :texture-2d :texture-wrap-s :clamp-to-edge)
(gl:tex-parameter :texture-2d :texture-wrap-t :clamp-to-edge)
(gl:tex-parameter :texture-2d :texture-min-filter :linear)
(gl:tex-parameter :texture-2d :texture-mag-filter :linear)
(gl:bind-texture :texture-2d 0))
(progn
;; create renderbuffer
(setf (o! this :slot renderbuffer) (gl:gen-renderbuffer))
(gl:bind-renderbuffer :renderbuffer (o! this :slot renderbuffer))
(gl:renderbuffer-storage :renderbuffer :depth24-stencil8 (o! this :slot width) (o! this :slot height))
(gl:bind-renderbuffer :renderbuffer 0)))
;; create framebuffer
(setf (o! this :slot framebuffer) (gl:gen-framebuffer))
(gl:bind-framebuffer :framebuffer (o! this :slot framebuffer))
(gl:framebuffer-texture-2d :framebuffer :color-attachment0 :texture-2d (o! this :slot render-texture) 0)
(if (o! this depth-texture-p)
(gl:framebuffer-texture-2d :framebuffer :depth-stencil-attachment :texture-2d (o! this :slot depth-texture) 0)
(gl:framebuffer-renderbuffer :framebuffer :depth-stencil-attachment :renderbuffer (o! this :slot renderbuffer)))
(gl:bind-framebuffer :framebuffer 0))
(defmethod bind-for-rendering ((this render-target))
(gl:bind-framebuffer :framebuffer (o! this framebuffer))
(gl:viewport 0 0 (o! this width) (o! this height)))