-
Notifications
You must be signed in to change notification settings - Fork 0
/
opengl-example.lisp
122 lines (90 loc) · 3.54 KB
/
opengl-example.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
;;;; opengl-example.lisp
(in-package #:opengl-example)
;;; "opengl-example" goes here. Hacks and glory await!
(defun show-demo ()
(let ((window (make-window))
(opengl-view (make-opengl-view)))
(#/setContentView: window opengl-view)
(#/orderFront: window nil)
window))
(defun make-window ()
(make-instance 'ns:ns-window
:width 300.0 :height 300.0))
(eval-when (:compile-toplevel :load-toplevel :execute)
(objc:load-framework "OpenGL" :gl)
(objc:defmethod (#/setWantsBestResolutionOpenGLSurface: :void)
((self ns:ns-object) (value :<BOOL>)))
(setf cl-opengl-bindings:*gl-get-proc-address* #'cffi:foreign-symbol-pointer))
(defun make-opengl-view ()
(let ((opengl-view (make-instance 'simple-gl-view)))
(#/setPixelFormat: opengl-view (make-pixel-format))
(#/setWantsBestResolutionOpenGLSurface: opengl-view 1)
(#/autorelease opengl-view)))
(defun make-pixel-format ()
(ccl:rlet ((attributes (:array (:unsigned 32) 3)))
(setf (ccl:%get-long attributes 0) 99)
(setf (ccl:%get-long attributes 4) #X3200)
(setf (ccl:%get-long attributes 8) 0)
(#/autorelease
(#/initWithAttributes: (#/alloc ns:ns-opengl-pixel-format)
attributes))))
(defclass simple-gl-view (ns:ns-opengl-view)
(vertex-array
vertex-buffer
shader-program)
(:metaclass ns:+ns-object))
(objc:defmethod (#/prepareOpenGL :void) ((self simple-gl-view))
(call-next-method)
(with-slots (vertex-array vertex-buffer shader-program) self
(setf vertex-array (cl-opengl:gen-vertex-array))
(setf vertex-buffer (car (cl-opengl:gen-buffers 1)))
(fill-buffer-with-demo-data vertex-buffer)
(setf shader-program (make-shader-program))))
(defun fill-buffer-with-demo-data (vertex-buffer)
(let ((array (cl-opengl:alloc-gl-array :float 9)))
(loop :for index :from 0
:for v :in '(-0.8 -0.8 -0.5
0.0 -0.8 -0.5
0.0 0.8 -0.5)
:do
(setf (gl:glaref array index) (coerce v 'single-float)))
(cl-opengl:bind-buffer :array-buffer vertex-buffer)
(cl-opengl:buffer-data :array-buffer :static-draw array)))
(defparameter *vertex-shader-source*
"#version 330
layout (location=0) in vec4 position;
void main () {
gl_Position = position;
}")
(defparameter *fragment-shader-source*
"#version 330
out vec4 finalColor;
void main () {
finalColor = vec4 (1.0, 0.0, 0.0, 1.0);
}")
(defun make-shader-program ()
(let ((program (opengl:create-program))
(vertex-shader (opengl:create-shader :vertex-shader))
(fragment-shader (opengl:create-shader :fragment-shader)))
(compile-shader vertex-shader *vertex-shader-source*)
(compile-shader fragment-shader *fragment-shader-source*)
(cl-opengl:attach-shader program vertex-shader)
(cl-opengl:attach-shader program fragment-shader)
(cl-opengl:link-program program)
(cl-opengl:delete-shader vertex-shader)
(cl-opengl:delete-shader fragment-shader)
program))
(defun compile-shader (shader source)
(cl-opengl:shader-source shader (alexandria:ensure-list source))
(cl-opengl:compile-shader shader))
(objc:defmethod (#/drawRect: :void) ((self simple-gl-view) (rect :<NSR>ect))
(with-slots (vertex-array vertex-buffer shader-program) self
(cl-opengl:clear-color 1.0 1.0 0.5 1.0)
(cl-opengl:clear :color-buffer-bit)
(cl-opengl:bind-vertex-array vertex-array)
(cl-opengl:bind-buffer :array-buffer vertex-buffer)
(cl-opengl:enable-vertex-attrib-array 0)
(cl-opengl:vertex-attrib-pointer 0 3 :float nil 0 0)
(cl-opengl:use-program shader-program)
(cl-opengl:draw-arrays :triangles 0 3)
(cl-opengl:flush)))