I'm writing an object loader in lisp using cl-opengl, and when trying to render the loaded vertices/elements using glDrawElements
, I'm left with a blank screen.
(require :cl-opengl)
(require :sdl2)
(defvar *vertices* nil)
(defvar *elements* nil)
(setf *vertices* (make-array 9 :fill-pointer 0))
(setf *elements* (make-array 9 :fill-pointer 0))
(defvar *vertex-shader* "
#version 330 core
layout (location = 0) in vec3 aPos;
void main() {
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
")
(defvar *fragment-shader* "
#version 330 core
out vec4 FragColor;
void main() {
FragColor = vec4(0.95f, 0.98f, 0.65f, 1.0f);
}
")
(defun split-str-1 (string &optional (separator " ") (r nil))
(let ((n (position separator string
:from-end t
:test #'(lambda (x y)
(find y x :test #'string=)))))
(if n
(split-str-1 (subseq string 0 n) separator (cons (subseq string (1+ n)) r))
(cons string r))))
(defun split-str (string &optional (separator " "))
(split-str-1 string separator))
(defun parse-float (number)
(with-input-from-string (in number)
(read in)))
(defun load-obj (file-name)
(let ((file (open file-name)))
(with-open-stream (source file)
(loop for line = (read-line source nil nil)
while line do
(let* ((split-line (split-str line " "))
(header (car split-line))
(rest (cdr split-line)))
(cond ((string= header "v")
(dolist (vertex rest)
(vector-push-extend (parse-float vertex) vertices)))
((string= header "f")
(dolist (face rest)
(let ((element (parse-integer (car (split-str face "/")))))
(vector-push-extend (- element 1) elements))))))))))
(defun main ()
(load-obj "tortoise.obj")
(sdl2:with-init (:everything)
(sdl2:gl-set-attr :context-profile-mask 0)
(sdl2:gl-set-attr :context-major-version 3)
(sdl2:gl-set-attr :context-minor-version 3)
(sdl2:with-window (win :flags `(:shown :opengl))
(sdl2:with-gl-context (gl-context win)
(sdl2:gl-make-current win gl-context)
(gl:viewport 0 0 800 600)
(gl:clear-color 0.957 0.376 0.286 1.0)
(let ((glarray (gl:alloc-gl-array :float (length vertices)))
(glarray-2 (gl:alloc-gl-array :unsigned-short (length elements))))
(dotimes (i (length elements))
(setf (gl:glaref glarray-2 i) (aref elements i)))
(dotimes (i (length vertices))
(setf (gl:glaref glarray i) (aref vertices i)))
(let ((vbo (gl:gen-buffer))
(vao (gl:gen-vertex-array))
(ebo (gl:gen-buffer)))
(gl:bind-vertex-array vao)
(gl:bind-buffer :array-buffer vbo)
(gl:buffer-data :array-buffer :static-draw glarray)
(gl:free-gl-array glarray)
(gl:bind-buffer :element-array-buffer ebo)
(gl:buffer-data :element-array-buffer :static-draw glarray-2)
(gl:vertex-attrib-pointer 0 4 :float nil 0 0)
(gl:enable-vertex-attrib-array 0)
(let ((vertex-shader (gl:create-shader :vertex-shader))
(fragment-shader (gl:create-shader :fragment-shader)))
(gl:shader-source vertex-shader *vertex-shader*)
(gl:shader-source fragment-shader *fragment-shader*)
(gl:compile-shader vertex-shader)
(gl:compile-shader fragment-shader)
(print (gl:get-shader-info-log vertex-shader))
(print (gl:get-shader-info-log fragment-shader))
(let ((program (gl:create-program)))
(gl:attach-shader program vertex-shader)
(gl:attach-shader program fragment-shader)
(gl:link-program program)
(gl:delete-shader vertex-shader)
(gl:delete-shader fragment-shader)
(gl:use-program program)))
(sdl2:with-event-loop (:method :poll)
(:idle ()
(gl:clear :color-buffer)
(gl:bind-vertex-array vao)
(gl:draw-elements :triangles glarray-2)
(gl:flush)
(sdl2:gl-swap-window win))
(:quit () t))))))))
I've experimented with multiple obj files, and the results are the same; nothing is drawn to the screen. I've looked at some of the other SO posts and haven't found anything particularly helpful and can't really think of anything that would be causing this.