Work on passes/pipeline, render targets
This commit is contained in:
@@ -101,14 +101,15 @@ when RENDER_BACKEND_OPENGL {
|
||||
)
|
||||
}
|
||||
|
||||
opengl_clear_screen :: proc(renderer: ^Renderer, clear_depth: bool) {
|
||||
mask := u32(gl.COLOR_BUFFER_BIT)
|
||||
if clear_depth {
|
||||
gl.ClearDepth(1.0)
|
||||
mask |= gl.DEPTH_BUFFER_BIT
|
||||
opengl_clear_screen :: proc(renderer: ^Renderer, clear_color: bool, clear_depth: bool) {
|
||||
flags := u32(0)
|
||||
if clear_color {
|
||||
flags |= gl.COLOR_BUFFER_BIT
|
||||
}
|
||||
|
||||
gl.Clear(mask)
|
||||
if clear_depth {
|
||||
flags |= gl.DEPTH_BUFFER_BIT
|
||||
}
|
||||
gl.Clear(flags)
|
||||
}
|
||||
|
||||
opengl_swap_buffers :: proc(renderer: ^Renderer) {
|
||||
@@ -127,7 +128,8 @@ when RENDER_BACKEND_OPENGL {
|
||||
Shader_Backend :: Shader_OpenGL
|
||||
Shader_Program_Backend :: Shader_Program_OpenGL
|
||||
Texture_Backend :: Texture_OpenGL
|
||||
|
||||
Render_Target_Backend :: Render_Target_OpenGL
|
||||
|
||||
Mesh_OpenGL :: struct {
|
||||
vbo, vao, ebo: u32,
|
||||
}
|
||||
@@ -144,7 +146,11 @@ when RENDER_BACKEND_OPENGL {
|
||||
handle: u32,
|
||||
}
|
||||
|
||||
opengl_create_mesh :: proc(renderer: ^Renderer, vertices: []f32, indices: []u32) -> (Mesh_OpenGL, bool) {
|
||||
Render_Target_OpenGL :: struct {
|
||||
handle: u32,
|
||||
}
|
||||
|
||||
opengl_create_mesh :: proc(renderer: ^Renderer, layout: []Mesh_Layout, vertices: []f32, indices: []u32) -> (Mesh_OpenGL, bool) {
|
||||
// fmt.printfln("OPENGL: Creating mesh from vertices: %v.", vertices)
|
||||
|
||||
m: Mesh_OpenGL
|
||||
@@ -161,14 +167,20 @@ when RENDER_BACKEND_OPENGL {
|
||||
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, m.ebo)
|
||||
gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(indices) * size_of(u32), raw_data(indices), gl.STATIC_DRAW)
|
||||
|
||||
gl.VertexAttribPointer(0, 3, gl.FLOAT, gl.FALSE, 8 * size_of(f32), uintptr(0))
|
||||
gl.EnableVertexAttribArray(0)
|
||||
layout_total_stride := u32(0)
|
||||
for l in layout {
|
||||
layout_total_stride += u32(l.amount) * l.type_size;
|
||||
}
|
||||
|
||||
gl.VertexAttribPointer(1, 3, gl.FLOAT, gl.FALSE, 8 * size_of(f32), uintptr(3 * size_of(f32)))
|
||||
gl.EnableVertexAttribArray(1)
|
||||
offset := u32(0)
|
||||
for l, i in layout {
|
||||
// NOTE: SS - Hardcoded to 'gl.FLOAT'
|
||||
gl.VertexAttribPointer(u32(i), i32(l.amount), gl.FLOAT, gl.FALSE, i32(layout_total_stride), uintptr(offset))
|
||||
gl.EnableVertexAttribArray(u32(i))
|
||||
|
||||
offset += u32(l.amount) * l.type_size
|
||||
}
|
||||
|
||||
gl.VertexAttribPointer(2, 2, gl.FLOAT, gl.FALSE, 8 * size_of(f32), uintptr(6 * size_of(f32)))
|
||||
gl.EnableVertexAttribArray(2)
|
||||
}
|
||||
gl.BindVertexArray(0)
|
||||
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
|
||||
@@ -260,72 +272,153 @@ when RENDER_BACKEND_OPENGL {
|
||||
gl.UniformMatrix4fv(projection_matrix_loc, 1, false, &projection_matrix_as_f32_array[0])
|
||||
}
|
||||
|
||||
opengl_activate_fullscreen_material :: proc(material: ^Material) {
|
||||
assert(material != nil)
|
||||
gl.UseProgram(material.shader_program.backend.handle)
|
||||
|
||||
gl.ActiveTexture(gl.TEXTURE0)
|
||||
gl.BindTexture(gl.TEXTURE_2D, material.texture.backend.handle)
|
||||
|
||||
loc := gl.GetUniformLocation(material.shader_program.backend.handle, "texture0") // eller "uTex"
|
||||
if loc != -1 {
|
||||
gl.Uniform1i(loc, 0)
|
||||
}
|
||||
|
||||
gl.Disable(gl.DEPTH_TEST)
|
||||
gl.DepthMask(gl.FALSE)
|
||||
}
|
||||
|
||||
opengl_deactivate_fullscreen_material :: proc() {
|
||||
gl.DepthMask(gl.TRUE)
|
||||
gl.Enable(gl.DEPTH_TEST)
|
||||
}
|
||||
|
||||
opengl_draw_mesh :: proc(mesh: ^Mesh) {
|
||||
gl.BindVertexArray(mesh.backend.vao)
|
||||
assert(mesh.amount_of_indices < u32(max(i32)))
|
||||
gl.DrawElements(gl.TRIANGLES, i32(mesh.amount_of_indices), gl.UNSIGNED_INT, nil)
|
||||
}
|
||||
|
||||
opengl_texture_format_from_texture :: proc(t: ^Texture) -> (u32, u32, u32) {
|
||||
internal, format, type: u32
|
||||
|
||||
switch t.format {
|
||||
case .R8: {
|
||||
internal = gl.R8
|
||||
format = gl.RED
|
||||
type = gl.UNSIGNED_BYTE
|
||||
}
|
||||
case .R16F: {
|
||||
internal = gl.R16F
|
||||
format = gl.RED
|
||||
type = gl.HALF_FLOAT
|
||||
}
|
||||
case .R32F: {
|
||||
internal = gl.R32F
|
||||
format = gl.RED
|
||||
type = gl.FLOAT
|
||||
}
|
||||
case .RGBA8: {
|
||||
internal = gl.RGBA8
|
||||
|
||||
if t.channels == 3 {
|
||||
format = gl.RGB
|
||||
} else {
|
||||
format = gl.RGBA
|
||||
}
|
||||
|
||||
type = gl.UNSIGNED_BYTE
|
||||
}
|
||||
case .RGBA16F: {
|
||||
internal = gl.RGBA16F
|
||||
format = gl.RGBA
|
||||
type = gl.HALF_FLOAT
|
||||
}
|
||||
case .R11G11B10F: {
|
||||
internal = gl.R11F_G11F_B10F
|
||||
format = gl.RGB
|
||||
type = gl.UNSIGNED_INT_10F_11F_11F_REV
|
||||
}
|
||||
case .Depth16: {
|
||||
internal = gl.DEPTH_COMPONENT16
|
||||
format = gl.DEPTH_COMPONENT
|
||||
type = gl.UNSIGNED_SHORT
|
||||
}
|
||||
case .Depth24: {
|
||||
internal = gl.DEPTH_COMPONENT24
|
||||
format = gl.DEPTH_COMPONENT
|
||||
type = gl.UNSIGNED_INT
|
||||
}
|
||||
case .Depth32F: {
|
||||
internal = gl.DEPTH_COMPONENT32F
|
||||
format = gl.DEPTH_COMPONENT
|
||||
type = gl.FLOAT
|
||||
}
|
||||
case .Depth24_Stencil8: {
|
||||
internal = gl.DEPTH24_STENCIL8
|
||||
format = gl.DEPTH_STENCIL
|
||||
type = gl.UNSIGNED_INT_24_8
|
||||
}
|
||||
case .Depth32F_Stencil8: {
|
||||
internal = gl.DEPTH32F_STENCIL8
|
||||
format = gl.DEPTH_STENCIL
|
||||
type = gl.FLOAT_32_UNSIGNED_INT_24_8_REV
|
||||
}
|
||||
}
|
||||
|
||||
return internal, format, type
|
||||
}
|
||||
|
||||
|
||||
opengl_load_texture :: proc(renderer: ^Renderer, t: ^Texture, pixels: rawptr) -> bool {
|
||||
handle: u32
|
||||
gl.GenTextures(1, &handle)
|
||||
gl.BindTexture(gl.TEXTURE_2D, handle)
|
||||
|
||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT)
|
||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT)
|
||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR)
|
||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
|
||||
|
||||
type := gl.UNSIGNED_BYTE
|
||||
switch t.depth {
|
||||
case 8: type = gl.UNSIGNED_BYTE
|
||||
case 16: type = gl.UNSIGNED_SHORT
|
||||
case 32: type = gl.UNSIGNED_INT
|
||||
switch t.filter_mode {
|
||||
case .Nearest:
|
||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
|
||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
|
||||
case .Linear:
|
||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
|
||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
|
||||
case .Nearest_MipMap:
|
||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST)
|
||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
|
||||
case .Linear_MipMap:
|
||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR)
|
||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
|
||||
}
|
||||
|
||||
format := gl.RGBA
|
||||
switch t.channels {
|
||||
case 1: format = gl.RED
|
||||
case 2: format = gl.RG
|
||||
case 3: format = gl.RGB
|
||||
case 4: format = gl.RGBA
|
||||
switch t.wrap_mode {
|
||||
case .Clamp:
|
||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP)
|
||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP)
|
||||
case .Repeat:
|
||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT)
|
||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT)
|
||||
case .Mirror:
|
||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT)
|
||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT)
|
||||
}
|
||||
|
||||
internal := gl.RGBA8
|
||||
|
||||
if t.depth == 8 {
|
||||
switch t.channels {
|
||||
case 1: internal = gl.R8
|
||||
case 2: internal = gl.RG8
|
||||
case 3: internal = gl.RGB8
|
||||
case 4: internal = gl.RGBA8
|
||||
}
|
||||
} else if t.depth == 16 {
|
||||
switch t.channels {
|
||||
case 1: internal = gl.R16
|
||||
case 2: internal = gl.RG16
|
||||
case 3: internal = gl.RGB16
|
||||
case 4: internal = gl.RGBA16
|
||||
}
|
||||
}
|
||||
|
||||
// bytes.reverse(bytes.buffer_to_bytes(img.pixels))
|
||||
internal_format, format, type := opengl_texture_format_from_texture(t)
|
||||
|
||||
gl.TexImage2D(
|
||||
target = gl.TEXTURE_2D,
|
||||
level = 0,
|
||||
internalformat = i32(internal),
|
||||
width = i32(t.width),
|
||||
height = i32(t.height),
|
||||
border = 0,
|
||||
format = u32(format),
|
||||
type = u32(type),
|
||||
pixels = pixels,
|
||||
// pixels = &pixels[0]
|
||||
// pixels = &bytes.reverse(bytes.buffer_to_bytes(&img.pixels))[0]
|
||||
gl.TEXTURE_2D,
|
||||
0,
|
||||
i32(internal_format),
|
||||
i32(t.width),
|
||||
i32(t.height),
|
||||
0,
|
||||
u32(format),
|
||||
u32(type),
|
||||
pixels,
|
||||
)
|
||||
|
||||
gl.GenerateMipmap(gl.TEXTURE_2D)
|
||||
if !t.is_depth {
|
||||
gl.GenerateMipmap(gl.TEXTURE_2D)
|
||||
}
|
||||
|
||||
t.backend = Texture_OpenGL { handle = handle }
|
||||
return true
|
||||
@@ -335,12 +428,105 @@ when RENDER_BACKEND_OPENGL {
|
||||
gl.DeleteTextures(1, &t.backend.handle)
|
||||
}
|
||||
|
||||
opengl_enable_depth_testing :: proc(renderer: ^Renderer, enable: bool) {
|
||||
if enable {
|
||||
opengl_apply_depth :: proc(renderer: ^Renderer, test_depth, write_depth: bool) {
|
||||
if test_depth {
|
||||
gl.Enable(gl.DEPTH_TEST)
|
||||
}
|
||||
else {
|
||||
gl.Disable(gl.DEPTH_TEST)
|
||||
}
|
||||
|
||||
gl.DepthMask(write_depth)
|
||||
}
|
||||
|
||||
@(private="file") OPENGL_BLEND_FACTOR_U32_TABLE :: [Blend_Factor]u32 {
|
||||
.Zero = gl.ZERO,
|
||||
.One = gl.ONE,
|
||||
// Color.
|
||||
.Src_Color = gl.SRC_COLOR,
|
||||
.One_Minus_Src_Color = gl.ONE_MINUS_SRC_COLOR,
|
||||
.Dst_Color = gl.DST_COLOR,
|
||||
.One_Minus_Dst_Color = gl.ONE_MINUS_DST_COLOR,
|
||||
// Alpha.
|
||||
.Src_Alpha = gl.SRC_ALPHA,
|
||||
.One_Minus_Src_Alpha = gl.ONE_MINUS_SRC_ALPHA,
|
||||
.Dst_Alpha = gl.DST_ALPHA,
|
||||
.One_Minus_Dst_Alpha = gl.ONE_MINUS_DST_ALPHA,
|
||||
}
|
||||
|
||||
opengl_set_blending :: proc(renderer: ^Renderer, enable: bool, factors: Blend_Factors) {
|
||||
if enable {
|
||||
gl.Enable(gl.BLEND)
|
||||
}
|
||||
else {
|
||||
gl.Disable(gl.BLEND)
|
||||
// Not sure that I want to return here.. Pretty nice that the blendfunc gets reset correctly even if we're disabling blending.
|
||||
}
|
||||
|
||||
table := OPENGL_BLEND_FACTOR_U32_TABLE
|
||||
|
||||
gl.BlendFunc(
|
||||
sfactor = table[factors.source],
|
||||
dfactor = table[factors.destination],
|
||||
)
|
||||
}
|
||||
|
||||
opengl_bind_render_target :: proc(renderer: ^Renderer, rt: ^Render_Target) {
|
||||
if rt == nil {
|
||||
gl.BindFramebuffer(gl.FRAMEBUFFER, 0)
|
||||
|
||||
gl.Viewport(
|
||||
0,
|
||||
0,
|
||||
i32(renderer.viewport.width),
|
||||
i32(renderer.viewport.height),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
gl.BindFramebuffer(gl.FRAMEBUFFER, rt.backend.handle)
|
||||
|
||||
gl.Viewport(
|
||||
0,
|
||||
0,
|
||||
i32(rt.color_texture.width),
|
||||
i32(rt.color_texture.height),
|
||||
)
|
||||
}
|
||||
|
||||
opengl_create_render_target :: proc(renderer: ^Renderer, rt: ^Render_Target) -> bool {
|
||||
fb: u32
|
||||
gl.GenFramebuffers(1, &fb)
|
||||
gl.BindFramebuffer(gl.FRAMEBUFFER, fb)
|
||||
|
||||
gl.FramebufferTexture2D(
|
||||
gl.FRAMEBUFFER,
|
||||
gl.COLOR_ATTACHMENT0,
|
||||
gl.TEXTURE_2D,
|
||||
rt.color_texture.backend.handle,
|
||||
0
|
||||
)
|
||||
|
||||
if rt.depth_texture != nil {
|
||||
gl.FramebufferTexture2D(
|
||||
gl.FRAMEBUFFER,
|
||||
gl.DEPTH_ATTACHMENT,
|
||||
gl.TEXTURE_2D,
|
||||
rt.depth_texture.backend.handle,
|
||||
0
|
||||
)
|
||||
}
|
||||
|
||||
if gl.CheckFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE {
|
||||
fmt.printfln("Framebuffer status: %v", gl.CheckFramebufferStatus(gl.FRAMEBUFFER))
|
||||
return false
|
||||
}
|
||||
|
||||
rt.backend = Render_Target_OpenGL {
|
||||
handle = fb
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user