;;;; 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)))