package renderer import "core:strings" import "core:c" import "vendor:stb/image" import "core:fmt" Texture :: struct { width, height, depth, channels: u16, format: Texture_Format, filter_mode: Texture_Filter_Mode, wrap_mode: Texture_Wrap_Mode, is_depth: bool, backend: Texture_Backend, } Texture_Format :: enum { RGBA8, RGBA16F, R11G11B10F, R8, R16F, R32F, Depth16, Depth24, Depth32F, Depth24_Stencil8, Depth32F_Stencil8, } Render_Target :: struct { color_texture, depth_texture: ^Texture, backend: Render_Target_Backend, } Texture_Filter_Mode :: enum { Nearest, Linear, Nearest_MipMap, Linear_MipMap, } Texture_Wrap_Mode :: enum { Clamp, Repeat, Mirror, } create_texture :: proc { create_texture_from_path, create_texture_raw, } create_texture_from_path :: proc(renderer: ^Renderer, path: string, filter_mode := Texture_Filter_Mode.Linear, wrap_mode := Texture_Wrap_Mode.Repeat) -> (Texture, bool) { width, height, channels, depth: c.int path_cstr := strings.clone_to_cstring(path) defer delete(path_cstr) image.set_flip_vertically_on_load(1) data := image.load(path_cstr, &width, &height, &channels, desired_channels = 0) if data == nil { return {}, false } depth = 8 t: Texture t.width = u16(width) t.height = u16(height) t.filter_mode = filter_mode t.wrap_mode = wrap_mode t.depth = u16(depth) t.channels = u16(channels) switch channels { case 1: { t.format = .R8 } case 3: { t.format = .RGBA8 } case 4: { t.format = .RGBA8 } case: { t.format = .RGBA8 } } when RENDER_BACKEND_OPENGL { if !opengl_load_texture(renderer, &t, data) { return {}, false } } return t, true } create_texture_raw :: proc(renderer: ^Renderer, width, height: u16, format: Texture_Format, filter_mode: Texture_Filter_Mode, wrap_mode: Texture_Wrap_Mode, is_depth: bool = false) -> (Texture, bool) { t: Texture t.width = width t.height = height t.format = format t.filter_mode = filter_mode t.wrap_mode = wrap_mode t.is_depth = is_depth when RENDER_BACKEND_OPENGL { if !opengl_load_texture(renderer, &t, nil) { return {}, false } } else { #assert(false) } return t, true } create_render_target :: proc(renderer: ^Renderer, color_texture, depth_texture: ^Texture) -> (Render_Target, bool) { rt: Render_Target rt.color_texture = color_texture rt.depth_texture = depth_texture when RENDER_BACKEND_OPENGL { if !opengl_create_render_target(renderer, &rt) { return {}, false } } return rt, true } delete_texture :: proc(renderer: ^Renderer, texture: ^Texture) { when RENDER_BACKEND_OPENGL { opengl_delete_texture(renderer, texture) } else { #assert(false) } }