stoe/engine/render.lisp

102 lines
3.3 KiB
Common Lisp

#|
This file is a part of stoe project.
Copyright (c) 2015 Renaud Casenave-Péré (renaud@casenave-pere.fr)
|#
(uiop:define-package :stoe/engine/render
(:use :cl :cffi :maths :shader
:stoe/core/utils
:stoe/core/containers
:stoe/core/time
:stoe/core/modules
:stoe/core/thread
:stoe/core/jobs
:stoe/engine/gl-utils
:stoe/engine/mesh
:stoe/engine/viewport
:stoe/engine/scene)
(:export #:on-render-thread))
(in-package :stoe/engine/render)
(defclass render-thread (specialized-thread)
())
(defvar *render-thread* nil)
(defvar *frames-per-second* 0.0)
(defun initialize (&optional argv)
"Initialize the render module.
Create an opengl context attached to a window."
(format t "Initialize Render module~%")
(viewport-configure argv)
(setf *render-thread* (push-new-thread 'render-thread "Render thread")))
(defun finalize ()
"Finalize the render module.
Destroy the opengl context and the related resources."
(format t "Finalize Render module~%")
(terminate-thread *render-thread*))
(defun update (delta-time)
(declare (ignore delta-time)))
(defmodule stoe/engine/render :render)
(let ((time-counter 0.0)
(frames-counter 0))
(defun compute-fps (delta-time)
(incf time-counter delta-time)
(incf frames-counter)
(when (> time-counter 1000000.0)
(setf *frames-per-second* frames-counter)
(setf time-counter 0.0)
(setf frames-counter 0))))
(defun render-single-mesh (mesh transform)
(using-program (program 'blue-shader)
(with-locations (model-to-camera camera-to-clip) program
(let ((mtc (m* (view (get-current-camera)) transform))
(ctc (projection (get-current-camera))))
(gl:uniform-matrix model-to-camera 4 (vector (raw-data mtc)) nil)
(gl:uniform-matrix camera-to-clip 4 (vector (raw-data ctc)) nil)))
(render-mesh mesh program)))
(defun render-scene-node (node scene)
(loop for mesh-idx in (meshes node)
do (render-single-mesh (aref (meshes scene) mesh-idx) (transform node)))
(loop for child in (children node)
do (render-scene-node child scene)))
(defun render-world (world)
(unless (null world)
(with-lock-held ((scene-lock world))
(with-accessors ((scene world-scene)) world
(unless (null scene)
(render-scene-node (root-node scene) scene))))))
(defmethod thread-initialize ((thread render-thread))
(format t "Initialize ~a~%" (name thread))
(viewport-initialize)
(compile-all-shaders))
(defmethod thread-finalize ((thread render-thread))
(format t "Finalize ~a~%" (name thread))
(destroy-all-shaders)
(viewport-finalize))
(defmethod thread-process ((thread render-thread))
(let ((clock (make-clock)))
(loop until (thread-terminate-p thread)
do (restartable
(during-one-frame
(loop for job = (get-next-job thread)
while job
do (progn
(format t "Thread ~a: Running job ~a~%" (name thread) (id job))
(job-run job thread)))
(render-world (get-world)))
(update-clock clock)
(compute-fps (clock-delta clock))))))
(defmacro on-render-thread (args &body body)
`(eval-on-thread ,args *render-thread* ,@body))