Created
June 9, 2020 14:20
-
-
Save vaiorabbit/b44499fe86aa42e429d82ce312198110 to your computer and use it in GitHub Desktop.
Revisions
-
vaiorabbit created this gist
Jun 9, 2020 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,279 @@ # coding: utf-8 # # Ref.: bgfx/examples/06-bump/bump.cpp # https://github.com/vaiorabbit/sdl2-bindings # require 'rmath3d/rmath3d' require 'sdl2' require_relative '../../bindings/ruby/bgfx.rb' require_relative './logo.rb' require_relative './utils.rb' include SDL2 include RMath3D SDL2.load_lib(SampleUtils.sdl2_dll_path()) Bgfx.load_lib(SampleUtils.bgfx_dll_path()) ################################################################################ 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 success = SDL_Init(SDL_INIT_VIDEO) exit if success < 0 SDL_SetHint(SDL_HINT_RENDER_DRIVER, "metal") window_width = 1280 window_height = 720 window = SDL_CreateWindow("ruby-bgfx : 06-bump", 0, 0, window_width, window_height, 0) renderer = SDL_CreateRenderer(window, -1, 0) if renderer == nil pp "Failed to initialize SDL" exit end nwh = FFI::Pointer.new(:pointer, SampleUtils.native_window_handle(window)) 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::Metal 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::bgfx_set_debug(Bgfx::Debug_Wireframe) Bgfx::bgfx_set_debug(Bgfx::Debug_Stats) 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) time_prev = SDL_GetTicks() time_crnt = time_prev time = 0.0 event = SDL_Event.new done = false while not done while SDL_PollEvent(event) != 0 # 'type' and 'timestamp' are common members for all SDL Event structs. event_type = event[:common][:type] event_timestamp = event[:common][:timestamp] case event_type when SDL_KEYDOWN if event[:key][:keysym][:sym] == SDL2::SDLK_ESCAPE done = true end end end Bgfx::bgfx_reset(window_width, window_height, Bgfx::Reset_None, Bgfx::TextureFormat::Count) time_crnt = SDL_GetTicks() time += (time_crnt-time_prev).to_f * 0.001 time_prev = time_crnt 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) end 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 SDL_DestroyWindow(window) SDL_Quit() end This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,228 @@ require 'ffi' require 'sdl2' require 'rmath3d/rmath3d' module BgfxUtils ################################################################################ def self.load_shader(name, runtime_path = "../runtime/") shader_path = case Bgfx::bgfx_get_renderer_type() when Bgfx::RendererType::OpenGL "shaders/glsl/" when Bgfx::RendererType::Metal "shaders/metal/" else $stderr.puts "You should not be here!" end file_path = runtime_path + shader_path + name + ".bin" shader_binary = IO.binread(file_path) shader_mem = FFI::MemoryPointer.from_string(shader_binary) handle = Bgfx::bgfx_create_shader(Bgfx::bgfx_make_ref(shader_mem, shader_mem.size)) Bgfx::bgfx_set_shader_name(handle, name, 0x7fffffff) # 0x7fffffff == INT32_MAX return handle end def self.load_program(vs_name, fs_name, runtime_path = "../runtime/") vsh = load_shader(vs_name, runtime_path) fsh = fs_name != nil ? load_shader(fs_name, runtime_path) : Bgfx::Bgfx_Invalid_Handle return Bgfx::bgfx_create_program(vsh, fsh, true) end ################################################################################ def self.load_texture(name, runtime_path = "../runtime/") texture_raw = IO.binread(runtime_path + name) texture_mem = FFI::MemoryPointer.from_string(texture_raw) return Bgfx::bgfx_create_texture( Bgfx::bgfx_make_ref(texture_mem, texture_mem.size), Bgfx::Texture_None|Bgfx::Sampler_None, 0, nil ) end ################################################################################ def self.to_unorm(_value, _scale) ((_value.clamp(0.0, 1.0) * _scale) + 0.5).floor end # usage) pp BgfxUtils.encode_normal_rgba8(0.0, 1.0, 0.0).to_s(16) => "8080ff80" def self.encode_normal_rgba8(_x, _y = 0.0, _z = 0.0, _w = 0.0) to_unorm = lambda { |_value, _scale| ((_value.clamp(0.0, 1.0) * _scale) + 0.5).floor } src = [ _x * 0.5 + 0.5, _y * 0.5 + 0.5, _z * 0.5 + 0.5, _w * 0.5 + 0.5, ] dst = [ to_unorm(src[0], 255.0), to_unorm(src[1], 255.0), to_unorm(src[2], 255.0), to_unorm(src[3], 255.0), ] return dst.pack("C4").unpack1("L") end ################################################################################ class PosTexcoord def initialize @m_pos = FFI::MemoryPointer.new(:float, 4) @m_texcoord = FFI::MemoryPointer.new(:float, 4) end def m_x; @m_pos[0]; end def m_y; @m_pos[1]; end def m_z; @m_pos[2]; end def m_u; @m_texcoord[0]; end def m_v; @m_texcoord[1]; end end def self.calc_tangents(_vertices, _numVertices, _layout, _indices) tangents = Array.new (2 * _numVertices) { RVec3.new } v0 = PosTexcoord.new v1 = PosTexcoord.new v2 = PosTexcoord.new num = _indices.length / 3 num.times do |ii| indices = _indices[ii * 3, 3] i0 = indices[0] i1 = indices[1] i2 = indices[2] Bgfx::bgfx_vertex_unpack(v0.m_x, Bgfx::Attrib::Position, _layout, _vertices, i0) Bgfx::bgfx_vertex_unpack(v0.m_u, Bgfx::Attrib::TexCoord0, _layout, _vertices, i0) Bgfx::bgfx_vertex_unpack(v1.m_x, Bgfx::Attrib::Position, _layout, _vertices, i1) Bgfx::bgfx_vertex_unpack(v1.m_u, Bgfx::Attrib::TexCoord0, _layout, _vertices, i1) Bgfx::bgfx_vertex_unpack(v2.m_x, Bgfx::Attrib::Position, _layout, _vertices, i2) Bgfx::bgfx_vertex_unpack(v2.m_u, Bgfx::Attrib::TexCoord0, _layout, _vertices, i2) bax = v1.m_x.read_float - v0.m_x.read_float bay = v1.m_y.read_float - v0.m_y.read_float baz = v1.m_z.read_float - v0.m_z.read_float bau = v1.m_u.read_float - v0.m_u.read_float bav = v1.m_v.read_float - v0.m_v.read_float cax = v2.m_x.read_float - v0.m_x.read_float cay = v2.m_y.read_float - v0.m_y.read_float caz = v2.m_z.read_float - v0.m_z.read_float cau = v2.m_u.read_float - v0.m_u.read_float cav = v2.m_v.read_float - v0.m_v.read_float det = (bau * cav - bav * cau) invDet = 1.0 / det tx = (bax * cav - cax * bav) * invDet ty = (bay * cav - cay * bav) * invDet tz = (baz * cav - caz * bav) * invDet bx = (cax * bau - bax * cau) * invDet by = (cay * bau - bay * cau) * invDet bz = (caz * bau - baz * cau) * invDet 3.times do |jj| tanu = tangents[indices[jj] + 0] tanv = tangents[indices[jj] + 1] tanu[0] += tx tanu[1] += ty tanu[2] += tz tanv[0] += bx tanv[1] += by tanv[2] += bz end end nxyzw = FFI::MemoryPointer.new(:float, 4) tangent = FFI::MemoryPointer.new(:float, 4) _numVertices.times do |ii| tanu = tangents[ii + 0] tanv = tangents[ii + 1] Bgfx::bgfx_vertex_unpack(nxyzw, Bgfx::Attrib::Normal, _layout, _vertices, ii) normal = RVec3.new(*nxyzw.read_array_of_float(3)) ndt = RVec3.dot(normal, tanu) nxt = RVec3.cross(normal, tanu); tmp = (tanu - (ndt * normal)).normalize! tangent.write_array_of_float([*tmp.to_a, RVec3.dot(nxt, tanv) < 0 ? -1.0 : 1.0]) Bgfx::bgfx_vertex_pack(tangent, true, Bgfx::Attrib::Tangent, _layout, _vertices, ii) end end end #################################################################################################### module SampleUtils ################################################################################ def self.sdl2_dll_path path = case RUBY_PLATFORM when /mswin|msys|mingw|cygwin/ Dir.pwd + '/' + 'SDL2.dll' when /darwin/ '/usr/local/lib/libSDL2.dylib' when /linux/ './libSDL2.so' else raise RuntimeError, "Unknown OS: #{RUBY_PLATFORM}" end return path end ################################################################################ def self.bgfx_dll_path 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 return path end ################################################################################ def self.native_window_handle(sdl2_window) nwh = case RUBY_PLATFORM when /mswin|msys|mingw|cygwin/ wminfo = SDL_SysWMinfo_win.new # TODO Windows if SDL_GetWindowWMInfo(sdl2_window, wminfo) == SDL_TRUE wminfo[:info][:win][:window] else nil end when /darwin/ wminfo = SDL_SysWMinfo_cocoa.new # TODO Windows if SDL_GetWindowWMInfo(sdl2_window, wminfo) == SDL_TRUE wminfo[:info][:cocoa][:window] else nil end when /linux/ raise RuntimeError, "Not supported yet: #{RUBY_PLATFORM}" else raise RuntimeError, "Unknown OS: #{RUBY_PLATFORM}" end return nwh end end