imgui-bindings 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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