commit ebbb377ce8a51152e3586309505b2d8441b72939 Author: samstalhandske Date: Fri Nov 14 11:56:14 2025 +0100 Initial commit. diff --git a/renderer.odin b/renderer.odin new file mode 100644 index 0000000..08a016f --- /dev/null +++ b/renderer.odin @@ -0,0 +1,90 @@ +package renderer + +import "core:fmt" + +RENDER_BACKEND_OPENGL :: #config(RENDER_BACKEND_OPENGL, false) +RENDER_BACKEND_VULKAN :: #config(RENDER_BACKEND_VULKAN, false) +RENDER_BACKEND_DIRECTX11 :: #config(RENDER_BACKEND_DIRECTX11, false) +RENDER_BACKEND_METAL :: #config(RENDER_BACKEND_METAL, false) + +Renderer :: struct { + api: Renderer_API, + + viewport: Viewport, + surface_ptr: rawptr, + backend: rawptr, +} + +Viewport :: struct { + x, y, width, height: u16, +} + +Renderer_API :: enum { + OpenGL, + Vulkan, + DirectX11, + Metal, +} + + +create :: proc(surface_ptr: rawptr) -> (^Renderer, bool) { + renderer := new(Renderer) + renderer.surface_ptr = surface_ptr + + when RENDER_BACKEND_OPENGL { + if !opengl_init(renderer) { + fmt.printfln("Failed to initialize OpenGL.") + destroy(renderer) + return nil, false + } + } + else { + destroy(renderer) + + fmt.printfln("Unhandled backend or no backend selected.") + return nil, false + } + + // TODO: SS - Init renderer using 'api'. + return renderer, true +} + +set_viewport :: proc(renderer: ^Renderer, x, y, width, height: u16) { + fmt.printfln("Setting viewport to %v:%v, %vx%v.", x, y, width, height) + + renderer.viewport = { + x = x, + y = y, + width = width, + height = height, + } + + when RENDER_BACKEND_OPENGL { + opengl_viewport_changed(renderer) + } +} + +set_clear_color :: proc(renderer: ^Renderer, color: [3]u8) { + when RENDER_BACKEND_OPENGL { + opengl_set_clear_color(renderer, color) + } +} + +render_frame :: proc(renderer: ^Renderer) { + +} + +swap_buffers :: proc(renderer: ^Renderer) { + when RENDER_BACKEND_OPENGL { + opengl_swap_buffers(renderer) + } +} + +destroy :: proc(renderer: ^Renderer) { + when RENDER_BACKEND_OPENGL { + opengl_destroy(renderer) + } + + free(renderer) + renderer^ = {} +} \ No newline at end of file diff --git a/renderer_backend_opengl_windows.odin b/renderer_backend_opengl_windows.odin new file mode 100644 index 0000000..3ec2e15 --- /dev/null +++ b/renderer_backend_opengl_windows.odin @@ -0,0 +1,93 @@ +package renderer + +import "core:fmt" +import gl "vendor:OpenGL" +import win "core:sys/windows" + + +when RENDER_BACKEND_OPENGL { + Backend_OpenGL_Windows :: struct { + hwnd: win.HWND, + hdc: win.HDC, + gl_context: win.HGLRC, + } + + backend: Backend_OpenGL_Windows + + opengl_init :: proc(renderer: ^Renderer) -> bool { + renderer.backend = &backend + + backend.hwnd = win.HWND(renderer.surface_ptr) + backend.hdc = win.GetDC(backend.hwnd) + + pfd := win.PIXELFORMATDESCRIPTOR { + nSize = size_of(win.PIXELFORMATDESCRIPTOR), + nVersion = 1, + dwFlags = win.PFD_DRAW_TO_WINDOW | win.PFD_SUPPORT_OPENGL | win.PFD_DOUBLEBUFFER, + iPixelType = win.PFD_TYPE_RGBA, + cColorBits = 32, + cDepthBits = 24, + cStencilBits = 8, + iLayerType = win.PFD_MAIN_PLANE, + } + + format_index := win.ChoosePixelFormat(backend.hdc, &pfd) + assert(format_index != 0, "ChoosePixelFormat failed") + + set_pixel_format_ok := win.SetPixelFormat(backend.hdc, format_index, &pfd) + assert(set_pixel_format_ok == win.TRUE, "SetPixelFormat failed") + + backend.gl_context = win.wglCreateContext(backend.hdc) + assert(backend.gl_context != nil, "Failed to create OpenGL context") + + win.wglMakeCurrent(backend.hdc, backend.gl_context) + // fmt.printfln("GL Context: %v", backend.gl_context) + + gl.load_up_to(3, 3, proc(p: rawptr, name: cstring) { + addr := win.wglGetProcAddress(name) + if addr == nil { + dll := win.LoadLibraryW(win.utf8_to_wstring("opengl32.dll")) + addr = win.GetProcAddress(dll, name) + } + (^rawptr)(p)^ = addr + }) + + + opengl_swap_buffers(renderer) + + return true + } + + opengl_viewport_changed :: proc(renderer: ^Renderer) { + gl.Clear(gl.COLOR_BUFFER_BIT) + + gl.Viewport( + i32(renderer.viewport.x), + i32(renderer.viewport.y), + i32(renderer.viewport.width), + i32(renderer.viewport.height) + ) + } + + opengl_set_clear_color :: proc(renderer: ^Renderer, color: [3]u8) { + gl.ClearColor( + f32(color.r) / f32(max(u8)), + f32(color.g) / f32(max(u8)), + f32(color.b) / f32(max(u8)), + 1.0 + ) + } + + opengl_swap_buffers :: proc(renderer: ^Renderer) { + gl.Clear(gl.COLOR_BUFFER_BIT) + win.SwapBuffers(backend.hdc) + } + + opengl_destroy :: proc(renderer: ^Renderer) { + win.wglMakeCurrent(nil, nil) + win.wglDeleteContext(backend.gl_context) + win.ReleaseDC(backend.hwnd, backend.hdc) + + backend = {} + } +} \ No newline at end of file