lispgames / cl-sdl2

Common Lisp bindings for SDL2 using C2FFI.
MIT License
308 stars 82 forks source link

gl:ortho doesn't working #125

Closed noloop closed 4 years ago

noloop commented 4 years ago

I tried configure the gl:ortho with the cl-sdl2, but it isn't working:

(gl:viewport 0 0 800 600)
(gl:matrix-mode :projection)
(gl:ortho -2 2 -2 2 -2 2)
(gl:matrix-mode :modelview)
(gl:load-identity)

When I configure any value to gl:ortho is the same that configure to:

(gl:ortho -1 1 -1 1 -1 1)

I tried like this:

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

(defparameter *width* 800)
(defparameter *height* 600)

(sdl2:with-init (:everything)
    (unless silent
      (format t "Using SDL Library Version: ~D.~D.~D~%"
              sdl2-ffi:+sdl-major-version+
              sdl2-ffi:+sdl-minor-version+
              sdl2-ffi:+sdl-patchlevel+)
      (finish-output))
    (sdl2:gl-set-attr :context-major-version 2)
    (sdl2:gl-set-attr :context-minor-version 0)
    (multiple-value-bind (d w h) (sdl2:get-current-display-mode 0)      
      (declare (ignore d))
      (unless *width* (setf *width* w))
      (unless *height* (setf *height* h)))
    (sdl2:with-window (win :flags '(:shown :opengl)
               :w *width*
               :h *height*)
      (sdl2:with-gl-context (gl-context win)
    (sdl2:gl-make-current win gl-context)
    (gl:viewport 0 0 *width* *height*)
        (gl:matrix-mode :projection)
        (gl:ortho (- (/ *width* 2)) (/ *width* 2) (- (/ *height* 2)) (/ *height* 2) -1.0 1.0)
        (gl:matrix-mode :modelview)
        (gl:load-identity)
    (if (not (gl::features-present-p (>= :glsl-version 1.2)))
        (sdl2:with-event-loop (:method :poll)
          (:idle ()
             (let ((verts #(0.0 280.0
                  -280.0 -280.0
                  280.0 -280.0))
             (vs (runtime-load-shader :vertex-shader "#version 120

attribute vec2 coord2d;

void main(void) {
  gl_Position = 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;
}
"))
             (program (gl:create-program))
             (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))
             (gl:draw-arrays :triangles 0 3)
             (gl:disable-vertex-attrib-array coord2d)
             (gl:delete-program program))
             (sdl2:gl-swap-window win))
          (:quit () t))))))

I tested it and it just doesn't work using shaders, but it works in the obsolete begin - end mode of the cl-sdl2 example, like this:

(gl:begin :triangles)
(gl:color 1.0 0.0 0.0)
(gl:vertex 0.0 280.0)
(gl:vertex -280.0 -280.0)
(gl:vertex 280.0 -280.0)
(gl:end)
noloop commented 4 years ago

I managed to make it work, the secret is that you need to multiply the projection matrix by the position in the vertex-shader, like is showed below:

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

(defun sdl2-test ()
  (sdl2:with-init (:everything)
    (sdl2:with-window (win :flags '(:shown :opengl))
      (sdl2:with-gl-context (gl-context win)
        (let ((program (gl:create-program)))
      (create-new-program program)

          (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
        (let ((proj-mat (gl:get-float :projection-matrix)))
          (gl:uniform-matrix 
           (gl:get-uniform-location program "projectionMatrix") 
           4 
           (vector proj-mat))))
      (gl:matrix-mode :modelview)
      (gl:load-identity)

      (sdl2:with-event-loop (:method :poll)
            (:idle ()
                   (gl:clear :color-buffer)
                   (gl:color 1.0 0.0 0.0)
           (draw-triangle)
                   (sdl2:gl-swap-window win))

            (:quit () t)))))))
(sdl2-test)