109 lines
3.5 KiB
Common Lisp
109 lines
3.5 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/core/entity
|
|
:stoe/engine/gl-utils
|
|
:stoe/engine/mesh
|
|
:stoe/engine/viewport
|
|
:stoe/engine/scene-graph
|
|
:stoe/engine/camera
|
|
:stoe/engine/scene)
|
|
(:export #:on-render-thread
|
|
#:render #:render-single-mesh))
|
|
(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* (if (> frames-counter 1)
|
|
frames-counter
|
|
(/ frames-counter (/ time-counter 1000000.0))))
|
|
(setf time-counter 0.0)
|
|
(setf frames-counter 0))))
|
|
|
|
(defun render-single-mesh (mesh transform)
|
|
(using-program (program 'simple-shader)
|
|
(with-locations (model-to-camera camera-to-clip) program
|
|
(with-components (camera-component) (main-camera (world))
|
|
(let ((mtc (m* (view camera-component) transform))
|
|
(ctc (projection camera-component)))
|
|
(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)))
|
|
|
|
(defgeneric render (node))
|
|
|
|
(defmethod render ((node graph-node-component)))
|
|
|
|
(defmethod render :after ((node graph-node-component))
|
|
(mapc #'render (children node)))
|
|
|
|
(defun render-world (world)
|
|
(unless (null world)
|
|
(locking-scene
|
|
(with-components ((root graph-node-component)) (current-scene)
|
|
(render root)))))
|
|
|
|
(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 (world)))
|
|
(update-clock clock)
|
|
(compute-fps (clock-delta clock))))))
|
|
|
|
(defmacro on-render-thread (args &body body)
|
|
`(eval-on-thread ,args *render-thread* ,@body))
|