;;;; wh-engine/render/render-system.lisp ;;;; render system main code (defpackage wh-engine/render (:nicknames whe/render) (:use common-lisp 3d-vectors 3d-matrices wh-engine) (:import-from sb-ext weak-pointer weak-pointer-p make-weak-pointer weak-pointer-value) (:import-from objective-lisp O!) (:export ;; render/drawable.lisp drawable ; virtual properties culling-box ; methods draw drawable-test ;; render/view.lisp view ; properties render-pass render-mask cull-p ; virtual properties view-matrix world-matrix ; methods view-point render-view render-drawable *view-width* *view-height* *view-ppu* *pixel-scale* ;; render/render-target.lisp render-target ; properties width height framebuffer renderbuffer render-texture ; methods bind-for-rendering )) (in-package wh-engine/render) (defun opengl-matrix (matrix) (declare (type mat3 matrix)) (with-fast-matref (m matrix 3) (make-array '(16) :initial-contents `(,(m 0 0) ,(m 0 1) 0.0 ,(m 0 2) ,(m 1 0) ,(m 1 1) 0.0 ,(m 1 2) 0.0 0.0 1.0 0.0 ,(m 2 0) ,(m 2 1) 0.0 ,(m 2 2)) ))) (defvar *view-width* 512 "View-space width in pixels.") (defvar *view-height* 384 "View-space height in pixels.") (defvar *view-ppu* 64 "Pixels in view-space per unit in world-space.") (defvar *pixel-scale* 2 "Scaling factor for rendered pixels.") (defvar *world-drawables* () "List of all known drawables.") (defvar *world-views* () "List of all known views.") (defun sort-world-views () "Re-sort the *world-views* list by render pass." (sort *world-views* #'< :key (lambda (v) (o! (deref-pointer v) render-pass)))) (declaim (special *projection*)) (let (render-target win-width win-height) (defun render-system-init () (setf win-width (* *view-width* *pixel-scale*) win-height (* *view-height* *pixel-scale*) render-target (make-instance 'render-target :width *view-width* :height *view-height*)) (load #p"wh-engine/render/shaders/basic-shaders.lisp") ;; change render target mode (gl:bind-texture :texture-2d (o! render-target render-texture)) (gl:tex-parameter :texture-2d :texture-min-filter :nearest) (gl:tex-parameter :texture-2d :texture-mag-filter :nearest) (gl:bind-texture :texture-2d 0) ;; set up gl (gl:matrix-mode :projection) (gl:ortho 0 *view-width* 0 *view-height* -1024 1024) (gl:matrix-mode :modelview) (gl:load-identity) (gl:clear-color 0.0 0.0 0.0 1.0) (gl:clear :color-buffer :depth-buffer :stencil-buffer)) (defun render-system-update () ;; draw to render texture (o! render-target (bind-for-rendering)) (gl:clear :color-buffer) (gl:enable :depth-test) (let ((render-pass nil)) (loop for view-ptr in *world-views* for view = (ensure-live (weak-pointer-value view-ptr)) when (and (o! view active-p) (o! view actor tree-active-p)) do (progn (unless (eql (o! view render-pass) render-pass) (setf render-pass (o! view render-pass)) (gl:clear :depth-buffer)) (o! view (render-view *world-drawables*))))) (gl:flush) ;; now draw to window (gl:bind-framebuffer :framebuffer 0) (gl:viewport 0 0 win-width win-height) (gl:clear :color-buffer) (gl:disable :depth-test) (gl:enable :texture-2d) (gl:bind-texture :texture-2d (o! render-target render-texture)) (gl:matrix-mode :modelview) (gl:load-identity) (gl:with-primitives :quads (gl:color 1.0 1.0 1.0 1.0) (gl:tex-coord 0.0 0.0) (gl:vertex 0.0 0.0) (gl:tex-coord 1.0 0.0) (gl:vertex *view-width* 0.0) (gl:tex-coord 1.0 1.0) (gl:vertex *view-width* *view-height*) (gl:tex-coord 0.0 1.0) (gl:vertex 0.0 *view-height*)) (gl:disable :texture-2d) (gl:flush))) (register-system :wh-engine/render 'render-system-init 'render-system-update nil) (install-systems :wh-engine/render)