mirror of
https://github.com/mattrberry/crab.git
synced 2025-01-29 20:35:13 +01:00
abstract shader implementation
This commit is contained in:
parent
9b0a5536b5
commit
719ca57c64
7 changed files with 61 additions and 39 deletions
|
@ -5,12 +5,13 @@ require "lib_gl"
|
|||
|
||||
require "./controllers/*"
|
||||
require "./widgets/*"
|
||||
require "./shaders/*"
|
||||
|
||||
class SDLOpenGLImGuiFrontend < Frontend
|
||||
CONTROLLERS = [StubbedController, GBController, GBAController]
|
||||
ROM_EXTENSIONS = CONTROLLERS.reduce([] of String) { |acc, controller| acc + controller.extensions }
|
||||
SCALE = 3
|
||||
SHADERS = "src/crab/common/shaders"
|
||||
SHADERS = Path["#{__DIR__}/shaders"]
|
||||
|
||||
@controller : Controller
|
||||
|
||||
|
@ -20,7 +21,7 @@ class SDLOpenGLImGuiFrontend < Frontend
|
|||
@shader_program : UInt32?
|
||||
@frag_shader_id : UInt32?
|
||||
|
||||
@shader_programs : Hash(Controller.class, UInt32)
|
||||
@shader_programs : Hash(Controller.class, Shader)
|
||||
|
||||
@microseconds = 0
|
||||
@frames = 0
|
||||
|
@ -52,17 +53,15 @@ class SDLOpenGLImGuiFrontend < Frontend
|
|||
)
|
||||
@gl_context = setup_gl
|
||||
|
||||
@shader_programs = Hash.zip(CONTROLLERS, CONTROLLERS.map { |controller| create_shader_program(controller.vertex_shader, controller.fragment_shader) })
|
||||
@shader_programs = Hash.zip(CONTROLLERS, CONTROLLERS.map { |controller| Shader.new(SHADERS / controller.vertex_shader, SHADERS / controller.fragment_shader)})
|
||||
shader_program = @shader_programs[@controller.class]
|
||||
LibGL.use_program(shader_program)
|
||||
shader_program.use
|
||||
|
||||
if stubbed?
|
||||
@crab_texture, canvas_aspect = texture_from_png("README/crab.png")
|
||||
window_aspect = @window.width / @window.height
|
||||
aspect = LibGL.get_uniform_location(shader_program, "aspect")
|
||||
LibGL.uniform_1f(aspect, window_aspect * canvas_aspect)
|
||||
scale = LibGL.get_uniform_location(shader_program, "scale")
|
||||
LibGL.uniform_1f(scale, 0.5)
|
||||
shader_program.aspect = window_aspect * canvas_aspect
|
||||
shader_program.scale = 0.5
|
||||
end
|
||||
|
||||
@opengl_info = OpenGLInfo.new
|
||||
|
@ -128,7 +127,7 @@ class SDLOpenGLImGuiFrontend < Frontend
|
|||
LibSDL.set_window_size(@window, @controller.window_width * SCALE, @controller.window_height * SCALE)
|
||||
LibSDL.set_window_position(@window, LibSDL::WindowPosition::CENTERED, LibSDL::WindowPosition::CENTERED)
|
||||
LibGL.viewport(0, 0, @window.width, @window.height)
|
||||
LibGL.use_program(@shader_programs[@controller.class])
|
||||
@shader_programs[@controller.class].use
|
||||
LibGL.disable(LibGL::BLEND)
|
||||
|
||||
pause(false)
|
||||
|
@ -170,10 +169,8 @@ class SDLOpenGLImGuiFrontend < Frontend
|
|||
end
|
||||
|
||||
private def render_game : Nil
|
||||
aspect = LibGL.get_uniform_location(@shader_programs[@controller.class], "aspect")
|
||||
LibGL.uniform_1f(aspect, 1)
|
||||
scale = LibGL.get_uniform_location(@shader_programs[@controller.class], "scale")
|
||||
LibGL.uniform_1f(scale, 1)
|
||||
@shader_programs[@controller.class].aspect = 1
|
||||
@shader_programs[@controller.class].scale = 1
|
||||
|
||||
LibGL.bind_texture(LibGL::TEXTURE_2D, @game_texture)
|
||||
LibGL.tex_image_2d(
|
||||
|
@ -305,21 +302,6 @@ class SDLOpenGLImGuiFrontend < Frontend
|
|||
end
|
||||
end
|
||||
|
||||
private def compile_shader(source : String, type : LibGL::Enum) : UInt32
|
||||
source_ptr = source.to_unsafe
|
||||
shader = LibGL.create_shader(type)
|
||||
LibGL.shader_source(shader, 1, pointerof(source_ptr), nil)
|
||||
LibGL.compile_shader(shader)
|
||||
LibGL.get_shader_iv(shader, LibGL::COMPILE_STATUS, out shader_compiled)
|
||||
if shader_compiled != LibGL::TRUE
|
||||
LibGL.get_shader_iv(shader, LibGL::INFO_LOG_LENGTH, out log_length)
|
||||
s = " " * log_length
|
||||
LibGL.get_shader_info_log(shader, log_length, out _, s) if log_length > 0
|
||||
abort "Error compiling shader: #{s}"
|
||||
end
|
||||
shader
|
||||
end
|
||||
|
||||
private def setup_gl : LibSDL::GLContext
|
||||
{% if flag?(:darwin) %}
|
||||
LibSDL.gl_set_attribute(LibSDL::GLattr::SDL_GL_CONTEXT_FLAGS, LibSDL::GLcontextFlag::FORWARD_COMPATIBLE_FLAG)
|
||||
|
@ -373,17 +355,6 @@ class SDLOpenGLImGuiFrontend < Frontend
|
|||
{crab_texture, canvas.height / canvas.width}
|
||||
end
|
||||
|
||||
private def create_shader_program(vertex_shader, fragment_shader : String) : UInt32
|
||||
shader_program = LibGL.create_program
|
||||
vert_shader_id = compile_shader(File.read("#{SHADERS}/#{vertex_shader}"), LibGL::VERTEX_SHADER)
|
||||
frag_shader_id = compile_shader(File.read("#{SHADERS}/#{fragment_shader}"), LibGL::FRAGMENT_SHADER)
|
||||
LibGL.attach_shader(shader_program, vert_shader_id)
|
||||
LibGL.attach_shader(shader_program, frag_shader_id)
|
||||
LibGL.link_program(shader_program)
|
||||
LibGL.validate_program(shader_program)
|
||||
shader_program
|
||||
end
|
||||
|
||||
private def setup_imgui : ImGui::ImGuiIO
|
||||
LibImGuiBackends.gl3wInit
|
||||
|
||||
|
|
51
src/crab/common/frontend/shaders/shader.cr
Normal file
51
src/crab/common/frontend/shaders/shader.cr
Normal file
|
@ -0,0 +1,51 @@
|
|||
require "lib_gl"
|
||||
|
||||
class Shader
|
||||
@id : UInt32
|
||||
|
||||
def initialize(vertex_shader_path : String | Path, fragment_shader_path : String | Path)
|
||||
@id = LibGL.create_program
|
||||
vert_shader_id = compile_shader(File.read(vertex_shader_path), LibGL::VERTEX_SHADER)
|
||||
frag_shader_id = compile_shader(File.read(fragment_shader_path), LibGL::FRAGMENT_SHADER)
|
||||
LibGL.attach_shader(@id, vert_shader_id)
|
||||
LibGL.attach_shader(@id, frag_shader_id)
|
||||
LibGL.link_program(@id)
|
||||
LibGL.validate_program(@id)
|
||||
end
|
||||
|
||||
def use : Nil
|
||||
LibGL.use_program(@id)
|
||||
end
|
||||
|
||||
macro method_missing(call)
|
||||
{% if !call.name.stringify.ends_with?("=") %}
|
||||
{% raise "#{@type.name}.#{call.name.stringify.id} does not exist" %}
|
||||
{% elsif call.args.size != 1 %}
|
||||
{% raise "Call to #{@type.name}.#{call.name.stringify.id} must take one argument" %}
|
||||
{% end %}
|
||||
|
||||
loc = LibGL.get_uniform_location(@id, {{ call.name.stringify[0..-2] }})
|
||||
|
||||
case {{call.args[0]}}
|
||||
when Float then LibGL.uniform_1f(loc, {{call.args[0]}})
|
||||
when Int then LibGL.uniform_1i(loc, {{call.args[0]}})
|
||||
when Bool then LibGL.uniform_1i(loc, {{call.args[0]}}.to_unsafe)
|
||||
else raise "Call to {{@type.name}}.{{call.name.stringify.id}}({{call.args[0]}}) must be of type (Float | Int | Bool)"
|
||||
end
|
||||
end
|
||||
|
||||
private def compile_shader(source : String, type : LibGL::Enum) : UInt32
|
||||
source_ptr = source.to_unsafe
|
||||
shader = LibGL.create_shader(type)
|
||||
LibGL.shader_source(shader, 1, pointerof(source_ptr), nil)
|
||||
LibGL.compile_shader(shader)
|
||||
LibGL.get_shader_iv(shader, LibGL::COMPILE_STATUS, out shader_compiled)
|
||||
if shader_compiled != LibGL::TRUE
|
||||
LibGL.get_shader_iv(shader, LibGL::INFO_LOG_LENGTH, out log_length)
|
||||
s = " " * log_length
|
||||
LibGL.get_shader_info_log(shader, log_length, out _, s) if log_length > 0
|
||||
abort "Error compiling shader: #{s}"
|
||||
end
|
||||
shader
|
||||
end
|
||||
end
|
Loading…
Add table
Reference in a new issue