144 lines
3.0 KiB
Odin
144 lines
3.0 KiB
Odin
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)
|
|
}
|
|
} |