examples: annotate examples
[nit.git] / lib / glesv2 / examples / opengles2_hello_triangle.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Basic example of OpenGL ES 2.0 usage using SDL 2
18 #
19 # From the book OpenGL ES 2.0 Programming Guide, see code reference:
20 # https://code.google.com/p/opengles-book-samples/source/browse/trunk/LinuxX11/Chapter_2/Hello_Triangle/Hello_Triangle.c
21 module opengles2_hello_triangle is example
22
23 import glesv2
24 import egl
25 import sdl2
26
27 import realtime
28
29 if "NIT_TESTING".environ == "true" then exit(0)
30
31 var window_width = 800
32 var window_height = 600
33
34 #
35 ## SDL2
36 #
37 assert sdl.initialize((new SDLInitFlags).video) else
38 print sdl.error
39 end
40
41 var sdl_window = new SDLWindow("Title".to_cstring, window_width, window_height, (new SDLWindowFlags).opengl)
42 assert not sdl_window.address_is_null else print sdl.error
43
44 var sdl_wm_info = sdl_window.wm_info
45 var native_window = sdl_wm_info.window_handle
46 var native_display = sdl_wm_info.display_handle
47 assert not native_display.address_is_null else print "Failed to get handle to native display"
48
49 #
50 ## EGL
51 #
52 var egl_display = new EGLDisplay(native_display)
53 assert egl_display.is_valid else print "EGL display is not valid"
54
55 egl_display.initialize
56 assert egl_display.is_valid else print egl_display.error
57
58 print "EGL version: {egl_display.version}"
59 print "EGL vendor: {egl_display.vendor}"
60 print "EGL extensions: \n* {egl_display.extensions.join("\n* ")}"
61 print "EGL client APIs: {egl_display.client_apis.join(", ")}"
62
63 var config_chooser = new EGLConfigChooser
64 #config_chooser.surface_type_egl
65 config_chooser.blue_size = 8
66 config_chooser.green_size = 8
67 config_chooser.red_size = 8
68 #config_chooser.alpha_size = 8
69 #config_chooser.depth_size = 8
70 #config_chooser.stencil_size = 8
71 #config_chooser.sample_buffers = 1
72 config_chooser.close
73
74 var configs = config_chooser.choose(egl_display)
75 assert configs != null else print "choosing config failed: {egl_display.error}"
76 assert not configs.is_empty else print "no EGL config"
77
78 print "{configs.length} EGL configs available"
79 for config in configs do
80 var attribs = config.attribs(egl_display)
81 print "* caveats: {attribs.caveat}"
82 print " conformant to: {attribs.conformant}"
83 print " size of RGBA: {attribs.red_size} {attribs.green_size} {attribs.blue_size} {attribs.alpha_size}"
84 print " buffer, depth, stencil: {attribs.buffer_size} {attribs.depth_size} {attribs.stencil_size}"
85 end
86
87 var config = configs.first
88
89 var surface = egl_display.create_window_surface(config, native_window, [0])
90 assert surface.is_ok else print egl_display.error
91
92 var context = egl_display.create_context(config)
93 assert context.is_ok else print egl_display.error
94
95 var make_current_res = egl_display.make_current(surface, surface, context)
96 assert make_current_res else print egl_display.error
97
98 var width = surface.attribs(egl_display).width
99 var height = surface.attribs(egl_display).height
100 print "Width: {width}"
101 print "Height: {height}"
102
103 assert egl_bind_opengl_es_api else print "eglBingAPI failed: {egl_display.error}"
104
105 #
106 ## GLESv2
107 #
108
109 print "Can compile shaders? {gl.shader_compiler}"
110 assert_no_gl_error
111
112 assert gl.shader_compiler else print "Cannot compile shaders"
113
114 # gl program
115 print glGetError.to_s
116 var program = new GLProgram
117 if not glIsProgram(program) then
118 print "Program is not ok: {glGetError.to_s}\nLog:"
119 print glGetProgramInfoLog(program)
120 abort
121 end
122 assert_no_gl_error
123
124 # vertex shader
125 var vertex_shader = new GLVertexShader
126 assert glIsShader(vertex_shader) else print "Vertex shader is not ok: {glGetError}"
127 glShaderSource(vertex_shader, """
128 attribute vec4 vPosition;
129 void main()
130 {
131 gl_Position = vPosition;
132 }
133 """.to_cstring)
134 glCompileShader vertex_shader
135 assert vertex_shader.is_compiled else print "Vertex shader compilation failed with: {glGetShaderInfoLog(vertex_shader)} {glGetProgramInfoLog(program)}"
136 assert_no_gl_error
137
138 # fragment shader
139 var fragment_shader = new GLFragmentShader
140 assert glIsShader(fragment_shader) else print "Fragment shader is not ok: {glGetError}"
141 glShaderSource(fragment_shader, """
142 precision mediump float;
143 void main()
144 {
145 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
146 }
147 """.to_cstring)
148 glCompileShader(fragment_shader)
149 assert fragment_shader.is_compiled else print "Fragment shader compilation failed with: {glGetShaderInfoLog(fragment_shader)}"
150 assert_no_gl_error
151
152 glAttachShader(program, vertex_shader)
153 glAttachShader(program, fragment_shader)
154 program.bind_attrib_location(0, "vPosition")
155 glLinkProgram program
156 assert program.is_linked else print "Linking failed: {glGetProgramInfoLog(program)}"
157 assert_no_gl_error
158
159 # prepare
160 glViewport(0, 0, width, height)
161 glClearColor(0.5, 0.0, 0.5, 1.0)
162
163 # draw!
164 var vertices = [0.0, 0.5, 0.0, -0.5, -0.5, 0.0, 0.5, -0.5, 0.0]
165 var vertex_array = new VertexArray(0, 3, vertices)
166 vertex_array.attrib_pointer
167
168 var clock = new Clock
169
170 var n_frames = 1000
171 for i in [0..n_frames[ do
172 printn "."
173 assert_no_gl_error
174
175 glClear gl_COLOR_BUFFER_BIT
176 glUseProgram program
177 vertex_array.enable
178 glDrawArrays(gl_TRIANGLES, 0, 3)
179 egl_display.swap_buffers(surface)
180 end
181
182 print "FPS: {n_frames.to_f/clock.lapse.to_f}"
183
184 # delete
185 glDeleteProgram program
186 glDeleteShader vertex_shader
187 glDeleteShader fragment_shader
188
189 #
190 ## EGL
191 #
192 # close
193 egl_display.make_current(new EGLSurface.none, new EGLSurface.none, new EGLContext.none)
194 egl_display.destroy_context context
195 egl_display.destroy_surface surface
196
197 #
198 ## SDL2
199 #
200 # close
201 sdl.quit