stoe/engine/render-gl.lisp
2018-05-02 22:14:03 +02:00

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