3b / cl-opengl

cl-opengl is a set of CFFI bindings to the OpenGL, GLU and GLUT APIs.
http://common-lisp.net/project/cl-opengl/
Other
278 stars 59 forks source link

shader-vao is broken. #89

Open noloop opened 4 years ago

noloop commented 4 years ago

The example https://github.com/3b/cl-opengl/blob/master/examples/misc/shader-vao.lisp is opening and closing fast and breaking the slime connection.

noloop commented 4 years ago

I couldn't find where the problem is, but I reduced the sample code to a minimal example that works:

(require :sdl2)
(require :cl-opengl)
(require :cl-glut)

(defun runtime-load-shader (shader-type shader-src)
  (let ((shader (gl:create-shader shader-type)))
    (gl:shader-source shader shader-src)
    (gl:compile-shader shader) 
    shader))

(defun alloc-array-buffer (verts)
  (let ((array-buffer (gl:gen-buffer))
    (arr (gl:alloc-gl-array :float (length verts))))
    (gl:bind-buffer :array-buffer array-buffer)
    (dotimes (i (length verts))
      (setf (gl:glaref arr i) (aref verts i)))
    (gl:buffer-data :array-buffer :static-draw arr)
    (gl:free-gl-array arr)
    array-buffer))

(defun create-new-program (program)
  (let ((verts #(0.0 280.0
         -280.0 -280.0
         280.0 -280.0))
    (vs (runtime-load-shader :vertex-shader "#version 120

uniform mat4 projectionMatrix;
attribute vec2 coord2d;

void main(void) {
  gl_Position = projectionMatrix * vec4(coord2d, 0.0, 1.0);
}
"))
    (fs (runtime-load-shader :fragment-shader "#version 120

void main(void) {
  gl_FragColor[0] = 0.0;
  gl_FragColor[1] = 0.0;
  gl_FragColor[2] = 1.0;
}
"))
    (coord2d nil))
    (gl:attach-shader program vs)
    (gl:attach-shader program fs)
    (gl:link-program program)
    (alloc-array-buffer verts)
    (setf coord2d (gl:get-attrib-location program "coord2d"))
    (gl:use-program program)
    (gl:enable-vertex-attrib-array coord2d)
    (gl:vertex-attrib-pointer coord2d
                      2
                      :float
                      :false
                      0
                      (cffi:null-pointer))))

(defun draw-triangle ()
  (gl:draw-arrays :triangles 0 3))

(defun program-shutdown (program)
  (gl:delete-program program))

(defclass glut-test-window (glut:window)
  ((program :accessor program)) 
  (:default-initargs :width 800 :height 600
             :mode '(:double :rgb :depth) :title "shader-vao-test"))

(defmethod glut:display-window :before ((w glut-test-window))
  (setf (program w) (gl:create-program))
  (create-new-program (program w)))

(defmethod glut:display ((w glut-test-window))
  (gl:clear-color 0.0 0.0 0.2 1.0)
  (gl:clear :color-buffer-bit)
  (draw-triangle)
  (glut:swap-buffers))

(defmethod glut:reshape ((w glut-test-window) width height)
  (gl:viewport 0 0 800 600)
  (gl:matrix-mode :projection)
  (gl:load-identity)
  (gl:ortho -400 400 -300 300 -1.0 1.0)
  (when (program w)
      (let ((proj-mat (gl:get-float :projection-matrix)))
    (gl:uniform-matrix 
     (gl:get-uniform-location (program w) "projectionMatrix") 
     4 
     (vector proj-mat))))
  (gl:matrix-mode :modelview)
  (gl:load-identity))

(defmethod glut:keyboard ((w glut-test-window) key x y)
  (declare (ignore x y))
  (case key
    (#\Esc (glut:destroy-current-window))))

(defun glut-test ()
  (let ((w (make-instance 'glut-test-window)))
    (glut:display-window w)
    (program-shutdown (program w))))

(glut-test)

It is possible that I am missing of many things here, but I am trying to learn and keep things simple, the example given is big and scary for the beginner. Not that it isn't necessary, but it would also be nice to have a minimal example using modern opengl (although the above code is limiting itself to opengl ES 2.0 standards, so version 120 is being used, which is not that modern).