fix the render module to use the scene graph defined in game module

Modify the mesh class to use a foreign array for the vertex and index
streams to pass to opengl, but the memory is not yet properly managed.

Add a function to render each node in the scene graph when it finds a
mesh component.
This commit is contained in:
Renaud Casenave-Péré 2014-11-10 16:41:16 +09:00
parent d4fd7ecc55
commit 764baddb3c
5 changed files with 141 additions and 9 deletions

View file

@ -11,19 +11,22 @@
(in-package :stoe.render.mesh) (in-package :stoe.render.mesh)
(defstruct attrib (defstruct attrib
name (name "")
type type
size size
offset) offset)
(defstruct (vertex-buffer (:constructor %make-vertex-buffer)) (defstruct (vertex-buffer (:constructor %make-vertex-buffer))
data data
attribs) attribs
buffer-object)
(defstruct (index-buffer (:constructor %make-index-buffer)) (defstruct (index-buffer (:constructor %make-index-buffer))
type type
mode mode
data) size
data
buffer-object)
(defstruct (mesh-stream (:constructor %make-mesh-stream)) (defstruct (mesh-stream (:constructor %make-mesh-stream))
program program
@ -44,12 +47,12 @@
(size (third attrib)) (size (third attrib))
(buffer (fourth attrib))) (buffer (fourth attrib)))
(prog1 (prog1
(make-attrib :name name :type type (make-attrib :name (symbol-name name) :type type
:size size :offset end-offset) :size size :offset end-offset)
(setf buffer-data (cons buffer buffer-data)) (setf buffer-data (cons buffer buffer-data))
(let ((len (length buffer))) (let ((len (length buffer)))
(incf buffer-size len) (incf buffer-size len)
(incf end-offset (* len size (gl-utils:size-of type))))))) (incf end-offset (* len (gl-utils:size-of type)))))))
data)) data))
(vertex-buffer (%make-vertex-buffer :data (make-array buffer-size) :attribs attribs)) (vertex-buffer (%make-vertex-buffer :data (make-array buffer-size) :attribs attribs))
(buffer-index 0)) (buffer-index 0))
@ -58,10 +61,27 @@
do (dotimes (i (length buffer)) do (dotimes (i (length buffer))
(setf (aref (vertex-buffer-data vertex-buffer) buffer-index) (aref buffer i)) (setf (aref (vertex-buffer-data vertex-buffer) buffer-index) (aref buffer i))
(incf buffer-index))) (incf buffer-index)))
(setf (vertex-buffer-buffer-object vertex-buffer) (first (gl:gen-buffers 1)))
(let ((ptr (cffi:foreign-alloc :float :initial-contents (vertex-buffer-data vertex-buffer) :count end-offset)))
(gl:bind-buffer :array-buffer (vertex-buffer-buffer-object vertex-buffer))
(%gl:buffer-data :array-buffer end-offset ptr :static-draw)
(gl:bind-buffer :array-buffer 0)
(cffi:foreign-free ptr))
vertex-buffer))) vertex-buffer)))
(defun make-index-buffer (data) (defun make-index-buffer (data)
(%make-index-buffer :type (first data) :mode (second data) :data (third data))) (let ((type (first data))
(mode (second data))
(size (length (third data)))
(data (third data)))
(let ((index-buffer (%make-index-buffer :type type :mode mode :size size :data data)))
(setf (index-buffer-buffer-object index-buffer) (first (gl:gen-buffers 1)))
(let ((ptr (cffi:foreign-alloc type :initial-contents data :count size)))
(gl:bind-buffer :element-array-buffer (index-buffer-buffer-object index-buffer))
(%gl:buffer-data :element-array-buffer (* size (gl-utils:size-of type)) ptr :static-draw)
(gl:bind-buffer :element-array-buffer 0)
(cffi:foreign-free ptr))
index-buffer)))
(defun %set-mesh-stream-program (stream symbol) (defun %set-mesh-stream-program (stream symbol)
(setf (mesh-stream-program stream) symbol)) (setf (mesh-stream-program stream) symbol))

View file

@ -54,9 +54,10 @@ Destroy the opengl context and the related resources."
"Update the render module. "Update the render module.
Render a frame and swap buffers." Render a frame and swap buffers."
(declare (ignore delta-time)) (declare (ignore delta-time))
(gl:clear-color 0.0 0 0 0) (gl:clear-color 0 0 0 0)
(gl:clear-depth 1.0) (gl:clear-depth 1.0)
(gl:clear :color-buffer-bit :depth-buffer-bit) (gl:clear :color-buffer-bit :depth-buffer-bit)
(render-scene (game:get-world-origin))
(glop:swap-buffers *window*)) (glop:swap-buffers *window*))
(modules:register-initialize-fun #'initialize) (modules:register-initialize-fun #'initialize)
@ -71,3 +72,46 @@ This needs to be called once per frame, at the beginning of the loop."
(defmethod glop:on-event (window event) (defmethod glop:on-event (window event)
(declare (ignore window event))) (declare (ignore window event)))
(defun render-mesh (node mesh)
"Render a single mesh."
(loop for stream in (mesh::mesh-streams mesh)
do (shader::using-program (program (mesh::mesh-stream-program stream))
(shader::with-uniforms (model-to-camera camera-to-clip) program
(gl:uniform-matrix model-to-camera 4 (vector (m:* (go::view (game:get-current-camera))
(go::trans-matrix node))))
(gl:uniform-matrix camera-to-clip 4 (vector (go::projection (game:get-current-camera)))))
(let* ((vertex-buffer (mesh::mesh-stream-vertex-buffer stream))
(index-buffer (mesh::mesh-stream-index-buffer stream))
(attribs (mesh::vertex-buffer-attribs vertex-buffer)))
(gl:bind-buffer :array-buffer (mesh::vertex-buffer-buffer-object vertex-buffer))
(loop for attrib in attribs
do (let* ((attrib-name (mesh::attrib-name attrib))
(attrib-loc (shader::get-attrib-location program attrib-name)))
(gl-utils:gl-assert (gl:enable-vertex-attrib-array attrib-loc))
(gl-utils:gl-assert (gl:vertex-attrib-pointer attrib-loc (mesh::attrib-size attrib)
(mesh::attrib-type attrib) :false 0
(mesh::attrib-offset attrib)))))
(gl:bind-buffer :element-array-buffer (mesh::index-buffer-buffer-object index-buffer))
(gl-utils:gl-assert (%gl:draw-elements (mesh::index-buffer-mode index-buffer)
(mesh::index-buffer-size index-buffer)
(mesh::index-buffer-type index-buffer) 0))
(gl:disable-vertex-attrib-array 0)
(gl:bind-buffer :element-array-buffer 0)
(gl:bind-buffer :array-buffer 0)))))
(defun render-node (node)
"Render a single node."
(with-slots ((components go::components)) node
(let ((mesh (car (member-if (lambda (c) (typep c 'mesh::mesh)) components))))
(when mesh
(render-mesh node mesh)))))
(defun render-scene (node)
"Walk the scene graph and render the graphical components."
(with-slots ((children go::children)) node
(loop for child in children
do (progn
(go:update-trans-matrix child)
(render-node child)
(render-scene child)))))

View file

@ -136,10 +136,47 @@ Retrieve the attributes and uniform locations."
(format t "~%") (format t "~%")
(setf i 0)) (setf i 0))
(format t ".") (format t ".")
(compile-program program-symbol))))) (compile-program program-symbol)))
(format t "~%")))
(defun destroy-all-shaders () (defun destroy-all-shaders ()
"Destroy the programs registered in opengl." "Destroy the programs registered in opengl."
(format t "Deleting shaders") (format t "Deleting shaders")
(loop for program-symbol being the symbol in :%stoe.shaders (loop for program-symbol being the symbol in :%stoe.shaders
do (delete-program program-symbol))) do (delete-program program-symbol)))
(defun get-attrib-location (program symbol)
(fourth (first (member symbol (program-attribs program) :key #'car :test #'equal))))
(defmacro using-program ((var program) &body body)
"Use the specified program and bind all its attributes and uniform for use in `body'."
`(let ((,var (symbol-value (find-symbol (symbol-name ,program) :%stoe.shaders))))
(gl-utils:gl-assert (gl:use-program (program-gl-program ,var)))
,@body
(gl-utils:gl-assert (gl:use-program 0))))
(defmacro with-uniforms (vars program &body body)
`(let ,(mapcar (lambda (var)
(cond
((listp var) (list (first var)
`(fourth (first (member (symbol-name ',(second var))
(program-uniforms ,program)
:key #'car :test #'equal)))))
((symbolp var) (list var `(fourth (first (member (symbol-name ',var)
(program-uniforms ,program)
:key #'car :test #'equal)))))))
vars)
,@body))
(defmacro with-attribs (vars program &body body)
`(let ,(mapcar (lambda (var)
(cond
((listp var) (list (first var)
`(fourth (first (member (symbol-name ',(second var))
(program-attribs ,program)
:key #'car :test #'equal)))))
((symbolp var) (list var `(fourth (first (member (symbol-name ',var)
(program-attribs ,program)
:key #'car :test #'equal)))))))
vars)
,@body))

30
src/render/shaders.lisp Normal file
View file

@ -0,0 +1,30 @@
#|
This file is a part of stoe project.
Copyright (c) 2014 Renaud Casenave-Péré (renaud@casenave-pere.fr)
|#
(in-package :cl-user)
(defpackage stoe.render.shaders
(:nicknames :shaders)
(:use :cl
:shader))
(in-package :stoe.render.shaders)
(defshader simple-vertex (:version 330
:in ((position :vec4 :location 0)
(color :vec4 :location 1))
:out ((out-color :vec4 :interp :smooth))
:uniform ((camera-to-clip :mat4)
(model-to-camera :mat4))
)
"gl_Position = camera_to_clip * model_to_camera * position;
out_color = color;")
(defshader simple-fragment (:version 330
:in ((out-color :vec4))
:out ((frag-color :vec4)))
"frag_color = out_color;")
(defprogram simple-shader ()
:vertex-shader simple-vertex
:fragment-shader simple-fragment)

View file

@ -61,7 +61,8 @@
((:file "glsl-compiler") ((:file "glsl-compiler")
(:file "shader"))) (:file "shader")))
(:file "mesh") (:file "mesh")
(:file "render")) (:file "render")
(:file "shaders"))
:depends-on ("modules" "utils")) :depends-on ("modules" "utils"))
(:file "stoe" (:file "stoe"
:depends-on ("utils" "modules"))))) :depends-on ("utils" "modules")))))