Created
June 7, 2020 12:27
-
-
Save vaiorabbit/3ef08afbfbca5dea008cac72c19b173b to your computer and use it in GitHub Desktop.
imgui_impl_bgfx.rb : Ruby-ImGui ( https://github.com/vaiorabbit/ruby-imgui ) rendering backend written in WIP Ruby-bgfx. Ref.: https://gist.github.com/vaiorabbit/29acb4ff3b94cefdbcfac3e2787eef50
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# coding: utf-8 | |
# | |
# Ref.: bgfx/examples/06-bump/bump.cpp | |
# https://github.com/vaiorabbit/ruby-opengl/tree/master/sample | |
# | |
require 'rmath3d/rmath3d' | |
require 'opengl' | |
require 'glfw' | |
require_relative '../../bindings/ruby/bgfx.rb' | |
require_relative './utils.rb' | |
require_relative 'imgui' | |
require_relative 'imgui_impl_bgfx' | |
$imgui_dll_path = case RUBY_PLATFORM | |
when /mswin|msys|mingw|cygwin/ | |
Dir.pwd + '/' + 'imgui.dll' | |
when /darwin/ | |
'./imgui.dylib' | |
when /linux/ | |
'../cimgui_impl_dll/build/imgui.so' | |
else | |
raise RuntimeError, "Unknown OS: #{RUBY_PLATFORM}" | |
end | |
$glfw_dll_path = case RUBY_PLATFORM | |
when /mswin|msys|mingw|cygwin/ | |
Dir.pwd + '/' + 'glfw3.dll' | |
when /darwin/ | |
'./libglfw.dylib' | |
when /linux/ | |
'./libglfw3.so' | |
else | |
raise RuntimeError, "Unknown OS: #{RUBY_PLATFORM}" | |
end | |
$bgfx_dll_path = case RUBY_PLATFORM | |
when /mswin|msys|mingw|cygwin/ | |
Dir.pwd + '/bgfx-shared-libDebug.dll' | |
when /darwin/ | |
'./libbgfx-shared-libDebug.dylib' | |
when /linux/ | |
'./libbgfx-shared-libDebug.so' | |
else | |
raise RuntimeError, "Unknown OS: #{RUBY_PLATFORM}" | |
end | |
OpenGL.load_lib() | |
GLFW.load_lib($glfw_dll_path) | |
ImGui.load_lib($imgui_dll_path) | |
Bgfx.load_lib($bgfx_dll_path) | |
include OpenGL | |
include GLFW | |
include RMath3D | |
################################################################################ | |
# Press ESC to exit. | |
key_callback = GLFW::create_callback(:GLFWkeyfun) do |window_handle, key, scancode, action, mods| | |
if key == GLFW_KEY_ESCAPE && action == GLFW_PRESS | |
glfwSetWindowShouldClose(window_handle, 1) | |
end | |
end | |
################################################################################ | |
class PosNormalTangentTexcoordVertex < FFI::Struct | |
@@ms_layout = Bgfx_vertex_layout_t.new | |
def self.ms_layout | |
@@ms_layout | |
end | |
layout( | |
:m_x, :float, | |
:m_y, :float, | |
:m_z, :float, | |
:m_normal, :uint32, | |
:m_tangent, :uint32, | |
:m_u, :int16, | |
:m_v, :int16 | |
) | |
def self.init() | |
Bgfx::bgfx_vertex_layout_begin(@@ms_layout, Bgfx::RendererType::Noop) | |
Bgfx::bgfx_vertex_layout_add(@@ms_layout, Bgfx::Attrib::Position, 3, Bgfx::AttribType::Float, false, false) | |
Bgfx::bgfx_vertex_layout_add(@@ms_layout, Bgfx::Attrib::Normal, 4, Bgfx::AttribType::Uint8, true, true) | |
Bgfx::bgfx_vertex_layout_add(@@ms_layout, Bgfx::Attrib::Tangent, 4, Bgfx::AttribType::Uint8, true, true) | |
Bgfx::bgfx_vertex_layout_add(@@ms_layout, Bgfx::Attrib::TexCoord0, 2, Bgfx::AttribType::Int16, true, true) | |
Bgfx::bgfx_vertex_layout_end(@@ms_layout) | |
end | |
end | |
# Ref: Array of Structs https://github.com/ffi/ffi/wiki/Structs | |
cubeVerticesSrc = [ | |
[-1.0, 1.0, 1.0, BgfxUtils.encode_normal_rgba8( 0.0, 0.0, 1.0), 0, 0, 0 ], | |
[ 1.0, 1.0, 1.0, BgfxUtils.encode_normal_rgba8( 0.0, 0.0, 1.0), 0, 0x7fff, 0 ], | |
[-1.0, -1.0, 1.0, BgfxUtils.encode_normal_rgba8( 0.0, 0.0, 1.0), 0, 0, 0x7fff ], | |
[ 1.0, -1.0, 1.0, BgfxUtils.encode_normal_rgba8( 0.0, 0.0, 1.0), 0, 0x7fff, 0x7fff ], | |
[-1.0, 1.0, -1.0, BgfxUtils.encode_normal_rgba8( 0.0, 0.0, -1.0), 0, 0, 0 ], | |
[ 1.0, 1.0, -1.0, BgfxUtils.encode_normal_rgba8( 0.0, 0.0, -1.0), 0, 0x7fff, 0 ], | |
[-1.0, -1.0, -1.0, BgfxUtils.encode_normal_rgba8( 0.0, 0.0, -1.0), 0, 0, 0x7fff ], | |
[ 1.0, -1.0, -1.0, BgfxUtils.encode_normal_rgba8( 0.0, 0.0, -1.0), 0, 0x7fff, 0x7fff ], | |
[-1.0, 1.0, 1.0, BgfxUtils.encode_normal_rgba8( 0.0, 1.0, 0.0), 0, 0, 0 ], | |
[ 1.0, 1.0, 1.0, BgfxUtils.encode_normal_rgba8( 0.0, 1.0, 0.0), 0, 0x7fff, 0 ], | |
[-1.0, 1.0, -1.0, BgfxUtils.encode_normal_rgba8( 0.0, 1.0, 0.0), 0, 0, 0x7fff ], | |
[ 1.0, 1.0, -1.0, BgfxUtils.encode_normal_rgba8( 0.0, 1.0, 0.0), 0, 0x7fff, 0x7fff ], | |
[-1.0, -1.0, 1.0, BgfxUtils.encode_normal_rgba8( 0.0, -1.0, 0.0), 0, 0, 0 ], | |
[ 1.0, -1.0, 1.0, BgfxUtils.encode_normal_rgba8( 0.0, -1.0, 0.0), 0, 0x7fff, 0 ], | |
[-1.0, -1.0, -1.0, BgfxUtils.encode_normal_rgba8( 0.0, -1.0, 0.0), 0, 0, 0x7fff ], | |
[ 1.0, -1.0, -1.0, BgfxUtils.encode_normal_rgba8( 0.0, -1.0, 0.0), 0, 0x7fff, 0x7fff ], | |
[ 1.0, -1.0, 1.0, BgfxUtils.encode_normal_rgba8( 1.0, 0.0, 0.0), 0, 0, 0 ], | |
[ 1.0, 1.0, 1.0, BgfxUtils.encode_normal_rgba8( 1.0, 0.0, 0.0), 0, 0x7fff, 0 ], | |
[ 1.0, -1.0, -1.0, BgfxUtils.encode_normal_rgba8( 1.0, 0.0, 0.0), 0, 0, 0x7fff ], | |
[ 1.0, 1.0, -1.0, BgfxUtils.encode_normal_rgba8( 1.0, 0.0, 0.0), 0, 0x7fff, 0x7fff ], | |
[-1.0, -1.0, 1.0, BgfxUtils.encode_normal_rgba8(-1.0, 0.0, 0.0), 0, 0, 0 ], | |
[-1.0, 1.0, 1.0, BgfxUtils.encode_normal_rgba8(-1.0, 0.0, 0.0), 0, 0x7fff, 0 ], | |
[-1.0, -1.0, -1.0, BgfxUtils.encode_normal_rgba8(-1.0, 0.0, 0.0), 0, 0, 0x7fff ], | |
[-1.0, 1.0, -1.0, BgfxUtils.encode_normal_rgba8(-1.0, 0.0, 0.0), 0, 0x7fff, 0x7fff ], | |
] | |
$s_cubeVertices = FFI::MemoryPointer.new(PosNormalTangentTexcoordVertex, cubeVerticesSrc.length) | |
cubeVertices = cubeVerticesSrc.length.times.collect do |i| | |
PosNormalTangentTexcoordVertex.new($s_cubeVertices + i * PosNormalTangentTexcoordVertex.size) | |
end | |
cubeVertices.each_with_index do |c, i| | |
c[:m_x], c[:m_y], c[:m_z], c[:m_normal], c[:m_tangent], c[:m_u], c[:m_v] = *cubeVerticesSrc[i] | |
end | |
cubeIndicesSrc = [ | |
0, 2, 1, | |
1, 2, 3, | |
4, 5, 6, | |
5, 7, 6, | |
8, 10, 9, | |
9, 10, 11, | |
12, 13, 14, | |
13, 15, 14, | |
16, 18, 17, | |
17, 18, 19, | |
20, 21, 22, | |
21, 23, 22, | |
] | |
$s_cubeIndices = FFI::MemoryPointer.new(:uint16, cubeIndicesSrc.length).write_array_of_ushort(cubeIndicesSrc) | |
################################################################################ | |
$m_vbh = nil # Bgfx_dynamic_vertex_buffer_handle_t | |
$m_ibh = nil # Bgfx_dynamic_index_buffer_handle_t | |
$m_program = nil # Bgfx_shader_handle_t | |
$s_texColor = nil # Bgfx_uniform_handle_t | |
$s_texNormal = nil # Bgfx_uniform_handle_t | |
$u_lightPosRadius = nil # Bgfx_uniform_handle_t | |
$u_lightRgbInnerR = nil # Bgfx_uniform_handle_t | |
$m_numLights = 4 # uint16 | |
$m_textureColor = nil # Bgfx_texture_handle_t | |
$m_textureNormal = nil # Bgfx_texture_handle_t | |
if __FILE__ == $0 | |
glfwInit() | |
window_width = 1280 | |
window_height = 720 | |
window = glfwCreateWindow( window_width, window_height, "ruby-bgfx : 06-bump", nil, nil ) | |
glfwMakeContextCurrent( window ) | |
glfwSetKeyCallback( window, key_callback ) | |
native_window_handle = case RUBY_PLATFORM | |
when /mswin|msys|mingw|cygwin/ | |
glfwGetWin32Window(window).to_i | |
when /darwin/ | |
glfwGetCocoaWindow(window).to_i | |
when /linux/ | |
glfwGetGLXWindow(window) | |
else | |
raise RuntimeError, "Unknown OS: #{RUBY_PLATFORM}" | |
end | |
nwh = FFI::Pointer.new(:pointer, native_window_handle) | |
pd = Bgfx_platform_data_t.new | |
pd[:ndt] = nil | |
pd[:nwh] = nwh | |
pd[:context] = nil | |
pd[:backBuffer] = nil | |
pd[:backBufferDS] = nil | |
Bgfx::bgfx_set_platform_data(pd) | |
init = Bgfx_init_t.new | |
init[:type] = Bgfx::RendererType::OpenGL | |
init[:vendorId] = Bgfx::Pci_Id_None | |
init[:resolution][:width] = window_width | |
init[:resolution][:height] = window_height | |
init[:resolution][:reset] = Bgfx::Reset_Vsync | |
init[:limits][:maxEncoders] = 1 | |
init[:limits][:transientVbSize] = 6<<20 | |
init[:limits][:transientIbSize] = 2<<20 | |
bgfx_init_success = Bgfx::bgfx_init(init) | |
pp "Failed to initialize Bgfx" unless bgfx_init_success | |
Bgfx::bgfx_set_debug(Bgfx::Debug_None) # (Bgfx::Debug_Text) | |
#Bgfx::bgfx_set_debug(Bgfx::Debug_Wireframe) # (Bgfx::Debug_Text) | |
#Bgfx::bgfx_set_debug(Bgfx::Debug_Stats | Bgfx::Debug_Text | Bgfx::Debug_Profiler) | |
Bgfx::bgfx_set_view_clear(0, Bgfx::Clear_Color|Bgfx::Clear_Depth, 0x303080ff, 1.0, 0) | |
PosNormalTangentTexcoordVertex.init() | |
BgfxUtils.calc_tangents($s_cubeVertices, $s_cubeVertices.size / $s_cubeVertices.type_size, PosNormalTangentTexcoordVertex.ms_layout, cubeIndicesSrc) | |
$m_vbh = Bgfx::bgfx_create_vertex_buffer( | |
Bgfx::bgfx_make_ref($s_cubeVertices, $s_cubeVertices.size), | |
PosNormalTangentTexcoordVertex.ms_layout, | |
Bgfx::Buffer_None | |
) | |
$m_ibh = Bgfx::bgfx_create_index_buffer( | |
Bgfx::bgfx_make_ref($s_cubeIndices, $s_cubeIndices.size), | |
Bgfx::Buffer_None | |
) | |
$s_texColor = Bgfx::bgfx_create_uniform("s_texColor", Bgfx::UniformType::Sampler, -1) | |
$s_texNormal = Bgfx::bgfx_create_uniform("s_texNormal", Bgfx::UniformType::Sampler, -1) | |
$u_lightPosRadius = Bgfx::bgfx_create_uniform("u_lightPosRadius", Bgfx::UniformType::Vec4, $m_numLights) | |
$u_lightRgbInnerR = Bgfx::bgfx_create_uniform("u_lightRgbInnerR", Bgfx::UniformType::Vec4, $m_numLights) | |
$m_textureColor = BgfxUtils.load_texture("textures/fieldstone-rgba.dds") | |
$m_textureNormal = BgfxUtils.load_texture("textures/fieldstone-n.dds") | |
$m_program = BgfxUtils.load_program("vs_bump", "fs_bump") | |
eye = RVec3.new(0.0, 0.0, -7.0) | |
at = RVec3.new(0.0, 0.0, 0.0) | |
up = RVec3.new(0.0, 1.0, 0.0) | |
mtxLookAt = RMtx4.new.lookAtRH( eye, at, up ) | |
view = FFI::MemoryPointer.new(:float, 16).write_array_of_float(mtxLookAt.to_a) | |
mtxProj = RMtx4.new.perspectiveFovRH( 60.0*Math::PI/180.0, window_width.to_f/window_height.to_f, 0.1, 100.0 ) # TODO bgfx::getCaps()->homogeneousDepth | |
proj = FFI::MemoryPointer.new(:float, 16).write_array_of_float(mtxProj.to_a) | |
ImGui::CreateContext() | |
ImGui::ImplBgfx_Init() | |
while glfwWindowShouldClose( window ) == 0 | |
width_ptr = ' ' * 8 | |
height_ptr = ' ' * 8 | |
glfwGetFramebufferSize(window, width_ptr, height_ptr) | |
width_current = width_ptr.unpack('L')[0] | |
height_current = height_ptr.unpack('L')[0] | |
ratio = width_current.to_f / height_current.to_f | |
if window_width != width_current || window_height != height_current | |
Bgfx::bgfx_reset(width_current, height_current, Bgfx::Reset_None, Bgfx::TextureFormat::Count) | |
end | |
window_width = width_current | |
window_height = height_current | |
time = glfwGetTime() | |
io = ImGuiIO.new(ImGui::GetIO()) | |
io[:DisplaySize][:x] = window_width | |
io[:DisplaySize][:y] = window_height | |
if window_width > 0 && window_height > 0 # TODO | |
io[:DisplayFramebufferScale][:x] = 1.0 | |
io[:DisplayFramebufferScale][:y] = 1.0 | |
end | |
io[:DeltaTime] = (1.0/60.0) # TODO | |
io[:BackendFlags] |= ImGuiBackendFlags_HasMouseCursors # We can honor GetMouseCursor() values (optional) | |
io[:BackendFlags] |= ImGuiBackendFlags_HasSetMousePos # We can honor io.WantSetMousePos requests (optional, rarely used) | |
# TODO UpdateMousePosAndButtons() | |
# TODO Glfw_UpdateMouseCursor() | |
ImGui::NewFrame() | |
ImGui::PushFont(ImGui::ImplBgfx_GetFont()) | |
ImGui::ShowDemoWindow() | |
ImGui::PopFont() | |
ImGui::Render() | |
ImGui::ImplBgfx_RenderDrawData(ImGui::GetDrawData()) | |
Bgfx::bgfx_set_view_transform(0, view, proj) | |
Bgfx::bgfx_set_view_rect(0, 0, 0, window_width, window_height) | |
Bgfx::bgfx_touch(0) | |
light_pos_radius = Array.new(4) { Array.new(4, 0.0) } | |
$m_numLights.times do |ii| | |
light_pos_radius[ii][0] = Math.sin( (time*(0.1 + ii*0.17) + ii*(0.5 * Math::PI) * 1.37 ) )*3.0 | |
light_pos_radius[ii][1] = Math.cos( (time*(0.2 + ii*0.29) + ii*(0.5 * Math::PI) * 1.49 ) )*3.0 | |
light_pos_radius[ii][2] = -2.5 | |
light_pos_radius[ii][3] = 3.0 | |
end | |
Bgfx::bgfx_set_uniform($u_lightPosRadius, light_pos_radius.flatten!.pack("F16"), $m_numLights) | |
light_rgb_inner_r = [ | |
[ 1.0, 0.7, 0.2, 0.8 ], | |
[ 0.7, 0.2, 1.0, 0.8 ], | |
[ 0.2, 1.0, 0.7, 0.8 ], | |
[ 1.0, 0.4, 0.2, 0.8 ], | |
] | |
Bgfx::bgfx_set_uniform($u_lightRgbInnerR, light_rgb_inner_r.flatten!.pack("F16"), $m_numLights) | |
state = 0 | Bgfx::State_Write_Rgb | Bgfx::State_Write_A | Bgfx::State_Write_Z | Bgfx::State_Depth_Test_Less | Bgfx::State_Msaa | |
3.times do |yy| | |
3.times do |xx| | |
mtxTransform = RMtx4.new.translation(-3.0 + xx * 3.0, -3.0 + yy * 3.0, 0.0) * RMtx4.new.rotationY(time * 0.03 + yy * 0.37) * RMtx4.new.rotationX(time * 0.23 + xx * 0.21) | |
mtx = FFI::MemoryPointer.new(:float, 16).write_array_of_float(mtxTransform.to_a) | |
Bgfx::bgfx_set_transform(mtx, 1) | |
Bgfx::bgfx_set_vertex_buffer(0, $m_vbh, 0, 0xffffffff) # 0xffffffff == UINT32_MAX | |
Bgfx::bgfx_set_index_buffer($m_ibh, 0, 0xffffffff) # 0xffffffff == UINT32_MAX | |
Bgfx::bgfx_set_texture(0, $s_texColor, $m_textureColor, 0xffffffff) # 0xffffffff == UINT32_MAX | |
Bgfx::bgfx_set_texture(1, $s_texNormal, $m_textureNormal, 0xffffffff) # 0xffffffff == UINT32_MAX | |
Bgfx::bgfx_set_state(state, 0) | |
Bgfx::bgfx_submit(0, $m_program, 0, Bgfx::Discard_All) | |
end | |
end | |
Bgfx::bgfx_frame(false) | |
#glfwSwapBuffers( window ) | |
glfwPollEvents() | |
end | |
ImGui::ImplBgfx_Shutdown() | |
ImGui::DestroyContext(nil) | |
if bgfx_init_success | |
Bgfx::bgfx_destroy_uniform($s_texColor) | |
Bgfx::bgfx_destroy_uniform($s_texNormal) | |
Bgfx::bgfx_destroy_uniform($u_lightPosRadius) | |
Bgfx::bgfx_destroy_uniform($u_lightRgbInnerR) | |
Bgfx::bgfx_destroy_texture($m_textureNormal) | |
Bgfx::bgfx_destroy_texture($m_textureColor) | |
Bgfx::bgfx_destroy_program($m_program) | |
Bgfx::bgfx_destroy_vertex_buffer($m_vbh) | |
Bgfx::bgfx_destroy_index_buffer($m_ibh) | |
Bgfx::bgfx_shutdown() | |
end | |
glfwDestroyWindow( window ) | |
glfwTerminate() | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# coding: utf-8 | |
require 'ffi' | |
require_relative '../../bindings/ruby/bgfx.rb' | |
require_relative 'imgui' | |
require_relative 'utils' | |
module ImGui | |
# [Not used yet] Structs for type conversion (or type-punning), used in ImplBgfx_RenderDrawData. | |
class TextureIdBgfx < FFI::Struct | |
layout :handle, Bgfx_texture_handle_t.by_value, | |
:flags, :uint8, | |
:mip, :uint8 | |
end | |
class TextureIdImGui < FFI::Union | |
layout :id, :ImTextureID, | |
:id, TextureIdBgfx.by_value | |
end | |
@@m_layout = Bgfx_vertex_layout_t.new # bgfx::VertexLayout | |
@@m_program = nil # bgfx::ProgramHandle | |
@@m_imageProgram = nil # bgfx::ProgramHandle | |
@@m_texture = nil # bgfx::TextureHandle | |
@@s_tex = nil # bgfx::UniformHandle | |
@@u_imageLodEnabled = nil # bgfx::UniformHandle | |
@@m_viewId = 255 # bgfx::ViewId | |
@@g_BackendRendererName = FFI::MemoryPointer.from_string("imgui_impl_bgfx") | |
@@font = nil | |
def self.ImplBgfx_GetFont() | |
return @@font | |
end | |
def self.ImplBgfx_Init() | |
io = ImGuiIO.new(ImGui::GetIO()) | |
io[:BackendRendererName] = @@g_BackendRendererName | |
@@m_program = BgfxUtils.load_program("vs_ocornut_imgui", "fs_ocornut_imgui", "./") | |
@@u_imageLodEnabled = Bgfx::bgfx_create_uniform("u_imageLodEnabled", Bgfx::UniformType::Vec4, -1) | |
@@m_imageProgram = BgfxUtils.load_program("vs_imgui_image", "fs_imgui_image", "./") | |
Bgfx::bgfx_vertex_layout_begin(@@m_layout, Bgfx::RendererType::Noop) | |
Bgfx::bgfx_vertex_layout_add(@@m_layout, Bgfx::Attrib::Position, 2, Bgfx::AttribType::Float, false, false) | |
Bgfx::bgfx_vertex_layout_add(@@m_layout, Bgfx::Attrib::TexCoord0, 2, Bgfx::AttribType::Float, false, false) | |
Bgfx::bgfx_vertex_layout_add(@@m_layout, Bgfx::Attrib::Color0, 4, Bgfx::AttribType::Uint8, true, false) | |
Bgfx::bgfx_vertex_layout_end(@@m_layout) | |
@@s_tex = Bgfx::bgfx_create_uniform("s_tex", Bgfx::UniformType::Sampler, -1) | |
io[:Fonts].AddFontDefault() | |
@@font = io[:Fonts].AddFontFromFileTTF('./jpfont/GenShinGothic-Normal.ttf', 24.0, nil, io[:Fonts].GetGlyphRangesChineseFull()) | |
pixels = FFI::MemoryPointer.new :pointer | |
width = FFI::MemoryPointer.new :int | |
height = FFI::MemoryPointer.new :int | |
io[:Fonts].GetTexDataAsRGBA32(pixels, width, height, nil) | |
ptr = Bgfx::bgfx_copy(pixels.read_pointer, width.read_uint16 * height.read_uint16 * 4) | |
mem = Bgfx_memory_t.new(ptr) | |
@@m_texture = Bgfx::bgfx_create_texture_2d(width.read_uint16, height.read_uint16, false, 1, Bgfx::TextureFormat::BGRA8, 0, mem) | |
return true | |
end | |
def self.ImplBgfx_Shutdown() | |
Bgfx::bgfx_destroy_uniform(@@s_tex) if @@s_tex != nil | |
Bgfx::bgfx_destroy_texture(@@m_texture) if @@m_texture != nil | |
Bgfx::bgfx_destroy_uniform(@@u_imageLodEnabled) if @@u_imageLodEnabled != nil | |
Bgfx::bgfx_destroy_program(@@m_imageProgram) if @@m_imageProgram != nil | |
Bgfx::bgfx_destroy_program(@@m_program) if @@m_program != nil | |
end | |
def self.ImplBgfx_RenderDrawData(draw_data_raw) | |
io = ImGuiIO.new(ImGui::GetIO()) | |
window_width = io[:DisplaySize][:x] | |
window_height = io[:DisplaySize][:y] | |
Bgfx::bgfx_set_view_name(@@m_viewId, "ImGui") | |
Bgfx::bgfx_set_view_mode(@@m_viewId, Bgfx::ViewMode::Sequential) | |
mtxOrtho = RMtx4.new.orthoRH(window_width.to_f, window_height.to_f, 0.0, 1000.0 ) # TODO bgfx::getCaps()->homogeneousDepth | |
ortho = FFI::MemoryPointer.new(:float, 16).write_array_of_float(mtxOrtho.to_a) | |
Bgfx::bgfx_set_view_transform(@@m_viewId, nil, ortho) | |
Bgfx::bgfx_set_view_rect(@@m_viewId, 0, 0, window_width, window_height) | |
draw_data = ImDrawData.new(draw_data_raw) | |
# Render command lists | |
draw_data[:CmdListsCount].times do |n| | |
tvb = Bgfx_transient_vertex_buffer_t.new | |
tib = Bgfx_transient_index_buffer_t.new | |
draw_list = ImDrawList.new((draw_data[:CmdLists].pointer + 8 * n).read_pointer) # 8 == const ImDrawList* | |
num_vertices = draw_list[:VtxBuffer][:Size] | |
num_indices = draw_list[:IdxBuffer][:Size] | |
transient_buffers_available = | |
(num_vertices == Bgfx::bgfx_get_avail_transient_vertex_buffer(num_vertices, @@m_layout)) && | |
(0 == num_indices || num_indices == Bgfx::bgfx_get_avail_transient_index_buffer(num_indices)) # == checkAvailTransientBuffers() | |
break if not transient_buffers_available | |
Bgfx::bgfx_alloc_transient_vertex_buffer(tvb, num_vertices, @@m_layout) | |
Bgfx::bgfx_alloc_transient_index_buffer(tib, num_indices) | |
tvb[:data].write_string(draw_list[:VtxBuffer][:Data].read_bytes(num_vertices * ImDrawVert.size)) | |
tib[:data].write_string(draw_list[:IdxBuffer][:Data].read_bytes(num_indices * 2)) # 2 == ImDrawIdx(== :ushort ).size | |
offset = 0 | |
draw_list[:CmdBuffer][:Size].times do |i| | |
cmd = ImDrawCmd.new(draw_list[:CmdBuffer][:Data] + ImDrawCmd.size * i) # const ImDrawCmd* | |
if cmd[:UserCallback] != nil | |
# [TODO] Handle user callback (Ref.: https://github.com/ffi/ffi/wiki/Callbacks ) | |
# cmd[:UserCallback](draw_list, cmd) | |
elsif cmd[:ElemCount] != 0 | |
state = 0 | Bgfx::State_Write_Rgb | Bgfx::State_Write_A | Bgfx::State_Msaa | |
th = @@m_texture | |
program = @@m_program | |
if cmd[:TextureId] != nil | |
puts "Not implemented yet" # TODO | |
else | |
# ↓state |= BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA); | |
state |= ((Bgfx::State_Blend_SrcAlpha | (Bgfx::State_Blend_InvSrcAlpha << 4)) | | |
((Bgfx::State_Blend_SrcAlpha | (Bgfx::State_Blend_InvSrcAlpha << 4)) << 8)) | |
end | |
xx = [cmd[:ClipRect][:x], 0.0].max.to_i | |
yy = [cmd[:ClipRect][:y], 0.0].max.to_i | |
Bgfx::bgfx_set_scissor(xx, yy, ([cmd[:ClipRect][:z], 65535.0].min-xx).to_i, ([cmd[:ClipRect][:w], 65535.0].min-yy).to_i) | |
Bgfx::bgfx_set_state(state, 0) | |
Bgfx::bgfx_set_texture(0, @@s_tex, th, 0xffffffff) # 0xffffffff == UINT32_MAX | |
Bgfx::bgfx_set_transient_vertex_buffer(0, tvb, 0, num_vertices) | |
Bgfx::bgfx_set_transient_index_buffer(tib, offset, cmd[:ElemCount]) | |
Bgfx::bgfx_submit(@@m_viewId, program, 0, Bgfx::Discard_All) | |
end | |
offset += cmd[:ElemCount] | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment