imgui-bindings 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,513 @@
1
+ require 'ffi'
2
+ require 'opengl'
3
+ include OpenGL
4
+
5
+ require_relative 'imgui'
6
+
7
+ module ImGui
8
+
9
+ @@g_GlVersion = 0 # Extracted at runtime using GL_MAJOR_VERSION, GL_MINOR_VERSION queries.
10
+ @@g_GlslVersionString = "" # Specified by user or detected based on compile time
11
+ @@g_FontTexture = nil
12
+
13
+ @@g_ShaderHandle = 0
14
+
15
+ @@g_AttribLocationTex = 0
16
+ @@g_AttribLocationProjMtx = 0
17
+
18
+ @@g_AttribLocationVtxPos = 0
19
+ @@g_AttribLocationVtxUV = 0
20
+ @@g_AttribLocationVtxColor = 0
21
+
22
+ @@g_VboHandle = 0
23
+ @@g_ElementsHandle = 0
24
+
25
+ @@g_BackendRendererName = FFI::MemoryPointer.from_string("imgui_impl_opengl3")
26
+
27
+ def self.PrintShaderCompileStatus(handle)
28
+ rvalue = ' ' * 4
29
+ glGetShaderiv(handle, GL_COMPILE_STATUS, rvalue)
30
+ rvalue = rvalue.unpack1('L')
31
+ if rvalue == GL_FALSE
32
+ $stderr.puts "Error in compiling shader"
33
+ log_length = ' ' * 4
34
+ glGetShaderiv(handle, GL_INFO_LOG_LENGTH, log_length)
35
+ log_length = log_length.unpack1('L')
36
+ if log_length > 0
37
+ buf = ' ' * log_length
38
+ glGetShaderInfoLog(handle, log_length, nil, buf)
39
+ $stderr.puts(buf)
40
+ exit()
41
+ end
42
+ end
43
+ end
44
+
45
+ def self.PrintProgramLinkStatus(handle)
46
+ rvalue = ' ' * 4
47
+ glGetProgramiv(handle, GL_LINK_STATUS, rvalue)
48
+ rvalue = rvalue.unpack1('L')
49
+ if rvalue == GL_FALSE
50
+ $stderr.puts "Error in linking program"
51
+ log_length = ' ' * 4
52
+ glGetProgramiv(handle, GL_INFO_LOG_LENGTH, log_length)
53
+ log_length = log_length.unpack1('L')
54
+ if log_length > 0
55
+ buf = ' ' * log_length
56
+ glGetProgramInfoLog(handle, log_length, nil, buf)
57
+ $stderr.puts(buf)
58
+ exit()
59
+ end
60
+ end
61
+ end
62
+
63
+ def self.ImplOpenGL3_Init(glsl_version = nil)
64
+ major, minor = ' ' * 4, ' ' * 4
65
+ glGetIntegerv(GL_MAJOR_VERSION, major)
66
+ glGetIntegerv(GL_MINOR_VERSION, minor)
67
+ major = major.unpack1('L')
68
+ minor = minor.unpack1('L')
69
+ @@g_GlVersion = major * 1000 + minor
70
+
71
+ io = ImGuiIO.new(ImGui::GetIO())
72
+ io[:BackendRendererName] = @@g_BackendRendererName
73
+ io[:BackendFlags] |= ImGuiBackendFlags_RendererHasVtxOffset if @@g_GlVersion >= 3200
74
+
75
+ # Ref.: Fix imgui_impl_opengl3 on MacOS
76
+ # https://github.com/ocornut/imgui/pull/3199
77
+ if OpenGL.get_platform() == :OPENGL_PLATFORM_MACOSX
78
+ glsl_version = "#version 150" if glsl_version == nil
79
+ else
80
+ glsl_version = "#version 130" if glsl_version == nil
81
+ end
82
+
83
+ @@g_GlslVersionString = glsl_version.dup
84
+
85
+ return true
86
+ end
87
+
88
+ def self.ImplOpenGL3_Shutdown()
89
+ ImplOpenGL3_DestroyDeviceObjects()
90
+ end
91
+
92
+ def self.ImplOpenGL3_NewFrame()
93
+ ImplOpenGL3_CreateDeviceObjects() if @@g_ShaderHandle == 0
94
+ end
95
+
96
+ def self.ImplOpenGL3_RenderDrawData(draw_data_raw)
97
+ # Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
98
+ draw_data = ImDrawData.new(draw_data_raw)
99
+ fb_width = (draw_data[:DisplaySize][:x] * draw_data[:FramebufferScale][:x]).to_i
100
+ fb_height = (draw_data[:DisplaySize][:y] * draw_data[:FramebufferScale][:y]).to_i
101
+
102
+ return if fb_width == 0 || fb_height == 0
103
+
104
+ # Backup GL state
105
+ last_active_texture = ' ' * 4; glGetIntegerv(GL_ACTIVE_TEXTURE, last_active_texture)
106
+ last_program = ' ' * 4; glGetIntegerv(GL_CURRENT_PROGRAM, last_program)
107
+ last_texture = ' ' * 4; glGetIntegerv(GL_TEXTURE_BINDING_2D, last_texture)
108
+
109
+ last_sampler = ' ' * 4; glGetIntegerv(GL_SAMPLER_BINDING, last_sampler)
110
+ last_array_buffer = ' ' * 4; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, last_array_buffer)
111
+ last_vertex_array_object = ' ' * 4; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, last_vertex_array_object)
112
+
113
+ last_polygon_mode = ' ' * 8; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode)
114
+ last_viewport = ' ' * 16; glGetIntegerv(GL_VIEWPORT, last_viewport)
115
+ last_scissor_box = ' ' * 16; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box)
116
+
117
+ last_blend_src_rgb = ' ' * 4; glGetIntegerv(GL_BLEND_SRC_RGB, last_blend_src_rgb)
118
+ last_blend_dst_rgb = ' ' * 4; glGetIntegerv(GL_BLEND_DST_RGB, last_blend_dst_rgb)
119
+ last_blend_src_alpha = ' ' * 4; glGetIntegerv(GL_BLEND_SRC_ALPHA, last_blend_src_alpha)
120
+ last_blend_dst_alpha = ' ' * 4; glGetIntegerv(GL_BLEND_DST_ALPHA, last_blend_dst_alpha)
121
+ last_blend_equation_rgb = ' ' * 4; glGetIntegerv(GL_BLEND_EQUATION_RGB, last_blend_equation_rgb)
122
+ last_blend_equation_alpha = ' ' * 4; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, last_blend_equation_alpha)
123
+
124
+ last_enable_blend = glIsEnabled(GL_BLEND)
125
+ last_enable_cull_face = glIsEnabled(GL_CULL_FACE)
126
+ last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST)
127
+ last_enable_stencil_test = glIsEnabled(GL_STENCIL_TEST)
128
+ last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST)
129
+
130
+ # Setup desired GL state
131
+ vertex_array_object = ' ' * 4
132
+ glGenVertexArrays(1, vertex_array_object)
133
+ vertex_array_object = vertex_array_object.unpack1('L')
134
+ ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object)
135
+
136
+ # Will project scissor/clipping rectangles into framebuffer space
137
+ clip_off = draw_data[:DisplayPos] # (0,0) unless using multi-viewports
138
+ clip_scale = draw_data[:FramebufferScale] # (1,1) unless using retina display which are often (2,2)
139
+
140
+ # Render command lists
141
+ draw_data[:CmdListsCount].times do |n|
142
+
143
+ cmd_list = ImDrawList.new((draw_data[:CmdLists].pointer + 8 * n).read_pointer) # 8 == const ImDrawList*
144
+ vtx_buffer = ImDrawVert.new(cmd_list[:VtxBuffer][:Data]) # const ImDrawVert*
145
+ idx_buffer = cmd_list[:IdxBuffer][:Data] # const ImDrawIdx*
146
+
147
+ # Upload vertex/index buffers
148
+ glBufferData(GL_ARRAY_BUFFER, cmd_list[:VtxBuffer][:Size] * ImDrawVert.size, Fiddle::Pointer.new(cmd_list[:VtxBuffer][:Data]), GL_STREAM_DRAW)
149
+ # 2 == ImDrawIdx(:ushort).size
150
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, cmd_list[:IdxBuffer][:Size] * 2, Fiddle::Pointer.new(cmd_list[:IdxBuffer][:Data]), GL_STREAM_DRAW) # [TODO] Refer ImGui::ImDrawIdx
151
+ # glBufferData(GL_ELEMENT_ARRAY_BUFFER, cmd_list[:IdxBuffer][:Size] * ImDrawIdx.size, Fiddle::Pointer.new(cmd_list[:IdxBuffer][:Data]), GL_STREAM_DRAW)
152
+
153
+ cmd_list[:CmdBuffer][:Size].times do |cmd_i|
154
+ pcmd = ImDrawCmd.new(cmd_list[:CmdBuffer][:Data] + ImDrawCmd.size * cmd_i) # const ImDrawCmd*
155
+ if pcmd[:UserCallback] != nil
156
+ # [TODO] Handle user callback (Ref.: https://github.com/ffi/ffi/wiki/Callbacks )
157
+
158
+ # User callback, registered via ImDrawList::AddCallback()
159
+ # (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
160
+ # if pcmd[:UserCallback] == :ImDrawCallback_ResetRenderState
161
+ ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object)
162
+ # else
163
+ # pcmd[:UserCallback](cmd_list, pcmd)
164
+ # end
165
+ else
166
+ # Project scissor/clipping rectangles into framebuffer space
167
+ clip_rect = ImVec4.new
168
+ clip_rect[:x] = (pcmd[:ClipRect][:x] - clip_off[:x]) * clip_scale[:x]
169
+ clip_rect[:y] = (pcmd[:ClipRect][:y] - clip_off[:y]) * clip_scale[:y]
170
+ clip_rect[:z] = (pcmd[:ClipRect][:z] - clip_off[:x]) * clip_scale[:x]
171
+ clip_rect[:w] = (pcmd[:ClipRect][:w] - clip_off[:y]) * clip_scale[:y]
172
+
173
+ if (clip_rect[:x] < fb_width && clip_rect[:y] < fb_height && clip_rect[:z] >= 0.0 && clip_rect[:w] >= 0.0)
174
+ # Apply scissor/clipping rectangle
175
+ glScissor(clip_rect[:x].to_i, (fb_height - clip_rect[:w]).to_i, (clip_rect[:z] - clip_rect[:x]).to_i, (clip_rect[:w] - clip_rect[:y]).to_i)
176
+
177
+ # Bind texture, Draw
178
+ glBindTexture(GL_TEXTURE_2D, pcmd[:TextureId].address)
179
+
180
+ if @@g_GlVersion >= 3200
181
+ # 2 == ImDrawIdx(:ushort).size
182
+ glDrawElementsBaseVertex(GL_TRIANGLES, pcmd[:ElemCount], GL_UNSIGNED_SHORT, Fiddle::Pointer.new(pcmd[:IdxOffset] * 2), pcmd[:VtxOffset])
183
+ # glDrawElementsBaseVertex(GL_TRIANGLES, pcmd[:ElemCount], GL_UNSIGNED_SHORT, Fiddle::Pointer.new(pcmd[:IdxOffset] * ImDrawIdx.size), pcmd[:VtxOffset]) # [TODO] Refer ImGui::ImDrawIdx
184
+ else
185
+ # 2 == ImDrawIdx(:ushort).size
186
+ glDrawElements(GL_TRIANGLES, pcmd[:ElemCount], GL_UNSIGNED_SHORT, Fiddle::Pointer.new(pcmd[:IdxOffset] * 2))
187
+ # glDrawElements(GL_TRIANGLES, pcmd[:ElemCount], GL_UNSIGNED_SHORT, Fiddle::Pointer.new(pcmd[:IdxOffset] * ImDrawIdx.size)) # [TODO] Refer ImGui::ImDrawIdx
188
+ end
189
+ end
190
+
191
+ end
192
+ idx_buffer += pcmd[:ElemCount] * 2 # 2 == ImDrawIdx(:ushort).size
193
+ end
194
+ end
195
+
196
+ # Destroy the temporary VAO
197
+ glDeleteVertexArrays(1, [vertex_array_object].pack('L'))
198
+
199
+ # Restore modified GL state
200
+ glUseProgram(last_program.unpack1('L'))
201
+ glBindTexture(GL_TEXTURE_2D, last_texture.unpack1('L'))
202
+ glBindSampler(0, last_sampler.unpack1('L'))
203
+ glActiveTexture(last_active_texture.unpack1('L'))
204
+ glBindVertexArray(last_vertex_array_object.unpack1('L'))
205
+ glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer.unpack1('L'))
206
+ glBlendEquationSeparate(last_blend_equation_rgb.unpack1('L'), last_blend_equation_alpha.unpack1('L'))
207
+
208
+ if last_enable_blend then glEnable(GL_BLEND) else glDisable(GL_BLEND) end
209
+ if last_enable_cull_face then glEnable(GL_CULL_FACE) else glDisable(GL_CULL_FACE) end
210
+ if last_enable_depth_test then glEnable(GL_DEPTH_TEST) else glDisable(GL_DEPTH_TEST) end
211
+ if last_enable_stencil_test then glEnable(GL_STENCIL_TEST) else glDisable(GL_STENCIL_TEST) end
212
+ if last_enable_scissor_test then glEnable(GL_SCISSOR_TEST) else glDisable(GL_SCISSOR_TEST) end
213
+
214
+ last_polygon_mode = last_polygon_mode.unpack('L2')
215
+ glPolygonMode(GL_FRONT_AND_BACK, last_polygon_mode[0])
216
+ last_viewport = last_viewport.unpack('L4')
217
+ glViewport(last_viewport[0], last_viewport[1], last_viewport[2], last_viewport[3])
218
+ last_scissor_box = last_scissor_box.unpack('L4')
219
+ glScissor(last_scissor_box[0], last_scissor_box[1], last_scissor_box[2], last_scissor_box[3])
220
+
221
+ end
222
+
223
+ # private
224
+
225
+ def self.ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object)
226
+ # Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
227
+ glEnable(GL_BLEND)
228
+ glBlendEquation(GL_FUNC_ADD)
229
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA)
230
+ glDisable(GL_CULL_FACE)
231
+ glDisable(GL_DEPTH_TEST)
232
+ glDisable(GL_STENCIL_TEST)
233
+ glEnable(GL_SCISSOR_TEST)
234
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) # GL_POLYGON_MODE
235
+
236
+ # Setup viewport, orthographic projection matrix
237
+ # Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
238
+ glViewport(0, 0, fb_width, fb_height)
239
+ l = draw_data[:DisplayPos][:x]
240
+ r = draw_data[:DisplayPos][:x] + draw_data[:DisplaySize][:x]
241
+ t = draw_data[:DisplayPos][:y]
242
+ b = draw_data[:DisplayPos][:y] + draw_data[:DisplaySize][:y]
243
+ ortho_projection = [
244
+ 2.0/(r-l), 0.0, 0.0, 0.0,
245
+ 0.0, 2.0/(t-b), 0.0, 0.0,
246
+ 0.0, 0.0, -1.0, 0.0,
247
+ (r+l)/(l-r), (t+b)/(b-t), 0.0, 1.0,
248
+ ]
249
+ glUseProgram(@@g_ShaderHandle)
250
+ glUniform1i(@@g_AttribLocationTex, 0)
251
+ glUniformMatrix4fv(@@g_AttribLocationProjMtx, 1, GL_FALSE, ortho_projection.pack('F16'))
252
+ # GL_SAMPLER_BINDING
253
+ glBindSampler(0, 0) # We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise.
254
+
255
+ glBindVertexArray(vertex_array_object)
256
+
257
+ # Bind vertex/index buffers and setup attributes for ImDrawVert
258
+ glBindBuffer(GL_ARRAY_BUFFER, @@g_VboHandle)
259
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, @@g_ElementsHandle)
260
+
261
+ glEnableVertexAttribArray(@@g_AttribLocationVtxPos)
262
+ glEnableVertexAttribArray(@@g_AttribLocationVtxUV)
263
+ glEnableVertexAttribArray(@@g_AttribLocationVtxColor)
264
+
265
+ glVertexAttribPointer(@@g_AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, ImDrawVert.size, ImDrawVert.offset_of(:pos))
266
+ glVertexAttribPointer(@@g_AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, ImDrawVert.size, ImDrawVert.offset_of(:uv))
267
+ glVertexAttribPointer(@@g_AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, ImDrawVert.size, ImDrawVert.offset_of(:col))
268
+
269
+ end
270
+
271
+ def self.ImplOpenGL3_CreateFontsTexture()
272
+ # Build texture atlas
273
+ io = ImGuiIO.new(ImGui::GetIO())
274
+ pixels = FFI::MemoryPointer.new :pointer
275
+ width = FFI::MemoryPointer.new :int
276
+ height = FFI::MemoryPointer.new :int
277
+ io[:Fonts].GetTexDataAsRGBA32(pixels, width, height, nil) # Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
278
+
279
+ # Upload texture to graphics system
280
+ last_texture = ' ' * 4
281
+ @@g_FontTexture = ' ' * 4
282
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, last_texture)
283
+ glGenTextures(1, @@g_FontTexture)
284
+ glBindTexture(GL_TEXTURE_2D, @@g_FontTexture.unpack1('L'))
285
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
286
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
287
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0)
288
+ # Ruby/FFI <-> Fiddle pointer exchange
289
+ # p pixels
290
+ # p pixels.read_pointer
291
+ # p pixels.read_pointer.address.to_s(16)
292
+ pixels_ptr = Fiddle::Pointer.new(pixels.read_pointer.address)
293
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width.read_uint, height.read_uint, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels_ptr)
294
+
295
+ # Store our identifier
296
+ io[:Fonts][:TexID] = @@g_FontTexture.unpack1('L')
297
+
298
+ # Restore state
299
+ glBindTexture(GL_TEXTURE_2D, last_texture.unpack1('L'))
300
+
301
+ return true
302
+ end
303
+
304
+ def self.ImplOpenGL3_DestroyFontsTexture()
305
+ if @@g_FontTexture != 0
306
+ glDeleteTextures(1, @@g_FontTexture)
307
+ io = ImGuiIO.new(ImGui::GetIO())
308
+ io[:Fonts][:TexID] = 0
309
+ @@g_FontTexture = 0
310
+ end
311
+ end
312
+
313
+ def self.ImplOpenGL3_CreateDeviceObjects()
314
+ # Backup GL state
315
+ last_texture, last_array_buffer = ' ' * 4, ' ' * 4
316
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, last_texture)
317
+ glGetIntegerv(GL_ARRAY_BUFFER_BINDING, last_array_buffer)
318
+ last_texture = last_texture.unpack1('L')
319
+ last_array_buffer = last_array_buffer.unpack1('L')
320
+
321
+ last_vertex_array = ' ' * 4
322
+ glGetIntegerv(GL_VERTEX_ARRAY_BINDING, last_vertex_array)
323
+ last_vertex_array = last_vertex_array.unpack1('L')
324
+
325
+ glsl_version = @@g_GlslVersionString.split[1].to_i # == scanf(@@g_GlslVersionString, "#version %d")
326
+
327
+ vertex_shader_glsl_120 = <<-'SRC'
328
+ uniform mat4 ProjMtx;
329
+ attribute vec2 Position;
330
+ attribute vec2 UV;
331
+ attribute vec4 Color;
332
+ varying vec2 Frag_UV;
333
+ varying vec4 Frag_Color;
334
+ void main()
335
+ {
336
+ Frag_UV = UV;
337
+ Frag_Color = Color;
338
+ gl_Position = ProjMtx * vec4(Position.xy,0,1);
339
+ }
340
+ SRC
341
+
342
+ vertex_shader_glsl_130 = <<-'SRC'
343
+ uniform mat4 ProjMtx;
344
+ in vec2 Position;
345
+ in vec2 UV;
346
+ in vec4 Color;
347
+ out vec2 Frag_UV;
348
+ out vec4 Frag_Color;
349
+ void main()
350
+ {
351
+ Frag_UV = UV;
352
+ Frag_Color = Color;
353
+ gl_Position = ProjMtx * vec4(Position.xy,0,1);
354
+ }
355
+ SRC
356
+
357
+ vertex_shader_glsl_300_es = <<-'SRC'
358
+ precision mediump float;
359
+ layout (location = 0) in vec2 Position;
360
+ layout (location = 1) in vec2 UV;
361
+ layout (location = 2) in vec4 Color;
362
+ uniform mat4 ProjMtx;
363
+ out vec2 Frag_UV;
364
+ out vec4 Frag_Color;
365
+ void main()
366
+ {
367
+ Frag_UV = UV;
368
+ Frag_Color = Color;
369
+ gl_Position = ProjMtx * vec4(Position.xy,0,1);
370
+ }
371
+ SRC
372
+
373
+ vertex_shader_glsl_410_core = <<-'SRC'
374
+ layout (location = 0) in vec2 Position;
375
+ layout (location = 1) in vec2 UV;
376
+ layout (location = 2) in vec4 Color;
377
+ uniform mat4 ProjMtx;
378
+ out vec2 Frag_UV;
379
+ out vec4 Frag_Color;
380
+ void main()
381
+ {
382
+ Frag_UV = UV;
383
+ Frag_Color = Color;
384
+ gl_Position = ProjMtx * vec4(Position.xy,0,1);
385
+ }
386
+ SRC
387
+
388
+ fragment_shader_glsl_120 = <<-'SRC'
389
+ #ifdef GL_ES
390
+ precision mediump float;
391
+ #endif
392
+ uniform sampler2D Texture;
393
+ varying vec2 Frag_UV;
394
+ varying vec4 Frag_Color;
395
+ void main()
396
+ {
397
+ gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st);
398
+ }
399
+ SRC
400
+
401
+ fragment_shader_glsl_130 = <<-'SRC'
402
+ uniform sampler2D Texture;
403
+ in vec2 Frag_UV;
404
+ in vec4 Frag_Color;
405
+ out vec4 Out_Color;
406
+ void main()
407
+ {
408
+ Out_Color = Frag_Color * texture(Texture, Frag_UV.st);
409
+ }
410
+ SRC
411
+
412
+ fragment_shader_glsl_300_es = <<-'SRC'
413
+ precision mediump float;
414
+ uniform sampler2D Texture;
415
+ in vec2 Frag_UV;
416
+ in vec4 Frag_Color;
417
+ layout (location = 0) out vec4 Out_Color;
418
+ void main()
419
+ {
420
+ Out_Color = Frag_Color * texture(Texture, Frag_UV.st);
421
+ }
422
+ SRC
423
+
424
+ fragment_shader_glsl_410_core = <<-'SRC'
425
+ in vec2 Frag_UV;
426
+ in vec4 Frag_Color;
427
+ uniform sampler2D Texture;
428
+ layout (location = 0) out vec4 Out_Color;
429
+ void main()
430
+ {
431
+ Out_Color = Frag_Color * texture(Texture, Frag_UV.st);
432
+ }
433
+ SRC
434
+
435
+ vertex_shader, fragment_shader = if glsl_version < 130
436
+ [vertex_shader_glsl_120, fragment_shader_glsl_120]
437
+ elsif glsl_version >= 410
438
+ [vertex_shader_glsl_410_core, fragment_shader_glsl_410_core]
439
+ elsif glsl_version == 300
440
+ [vertex_shader_glsl_300_es, fragment_shader_glsl_300_es]
441
+ else
442
+ [vertex_shader_glsl_130, fragment_shader_glsl_130]
443
+ end
444
+
445
+ vertex_shader.prepend(@@g_GlslVersionString + "\n")
446
+ vert_handle = glCreateShader(GL_VERTEX_SHADER)
447
+ glShaderSource(vert_handle, 1, [vertex_shader].pack('p'), nil)
448
+ glCompileShader(vert_handle)
449
+ PrintShaderCompileStatus(vert_handle)
450
+
451
+ fragment_shader.prepend(@@g_GlslVersionString + "\n")
452
+ frag_handle = glCreateShader(GL_FRAGMENT_SHADER)
453
+ glShaderSource(frag_handle, 1, [fragment_shader].pack('p'), [fragment_shader.size].pack('I'))
454
+ glCompileShader(frag_handle)
455
+ PrintShaderCompileStatus(frag_handle)
456
+
457
+ @@g_ShaderHandle = glCreateProgram()
458
+ glAttachShader(@@g_ShaderHandle, vert_handle)
459
+ glAttachShader(@@g_ShaderHandle, frag_handle)
460
+ glLinkProgram(@@g_ShaderHandle)
461
+ PrintProgramLinkStatus(@@g_ShaderHandle)
462
+
463
+ glDetachShader(@@g_ShaderHandle, vert_handle)
464
+ glDetachShader(@@g_ShaderHandle, frag_handle)
465
+ glDeleteShader(vert_handle)
466
+ glDeleteShader(frag_handle)
467
+
468
+ @@g_AttribLocationTex = glGetUniformLocation(@@g_ShaderHandle, "Texture")
469
+ @@g_AttribLocationProjMtx = glGetUniformLocation(@@g_ShaderHandle, "ProjMtx")
470
+
471
+ @@g_AttribLocationVtxPos = glGetAttribLocation(@@g_ShaderHandle, "Position")
472
+ @@g_AttribLocationVtxUV = glGetAttribLocation(@@g_ShaderHandle, "UV")
473
+ @@g_AttribLocationVtxColor = glGetAttribLocation(@@g_ShaderHandle, "Color")
474
+
475
+ # Create buffers
476
+ posBuf = ' ' * 4
477
+ glGenBuffers(1, posBuf)
478
+ glBindBuffer(GL_ARRAY_BUFFER, posBuf.unpack('L')[0])
479
+
480
+ @@g_VboHandle, @@g_ElementsHandle = ' ' * 4, ' ' * 4
481
+ glGenBuffers(1, @@g_VboHandle)
482
+ glGenBuffers(1, @@g_ElementsHandle)
483
+ @@g_VboHandle = @@g_VboHandle.unpack1('L')
484
+ @@g_ElementsHandle = @@g_ElementsHandle.unpack1('L')
485
+
486
+ ImplOpenGL3_CreateFontsTexture()
487
+
488
+ # Restore modified GL state
489
+ glBindTexture(GL_TEXTURE_2D, last_texture)
490
+ glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer)
491
+ glBindVertexArray(last_vertex_array)
492
+
493
+ return true
494
+ end
495
+
496
+ def self.ImplOpenGL3_DestroyDeviceObjects()
497
+ if @@g_VboHandle != 0
498
+ glDeleteBuffers(1, [@@g_VboHandle].pack('L'))
499
+ @@g_VboHandle = 0
500
+ end
501
+ if @@g_ElementsHandle != 0
502
+ glDeleteBuffers(1, [@@g_ElementsHandle].pack('L'))
503
+ @@g_ElementsHandle = 0
504
+ end
505
+ if @@g_ShaderHandle != 0
506
+ glDeleteProgram(@@g_ShaderHandle)
507
+ @@g_ShaderHandle = 0
508
+ end
509
+
510
+ ImplOpenGL3_DestroyFontsTexture()
511
+ end
512
+
513
+ end