Hello
I am currently trying to render a Pixel Buffer with an RGBA8 Pixel Format to the Screen using Sokol and Odin. I have come pretty far. I have a quad on the screen and the color is also displayed. I do have one weird problem, though. The color red 0xff0000ff works fine. When I try the color blue which is 0x0000ffff I get yellow. and when I try the color green 0x00ff00ff I get magenta. For clearing I use my clear_color_buffer method. I think it is either something with the pixel format or with my GLSL shading code. I am running this on MacOS using the Metal API. I have generated the Shader using the sokol-shdc tool. Any help would be greatly appreciated as I am currently pretty stuck. The code as well as the shader code can be found below.
//------------------------------------------------------------------------------
package main
import "core:fmt"
import "base:runtime"
import slog "../../sokol/log"
import sg "../../sokol/gfx"
import sapp "../../sokol/app"
import sglue "../../sokol/glue"
window_width: i32 : 800
window_height: i32 : 600
state: struct {
pass_action: sg.Pass_Action,
pip: sg.Pipeline,
bind: sg.Bindings,
pixel_buffer: [window_width*window_height]u32
}
init :: proc "c" () {
context = runtime.default_context()
sg.setup({
environment = sglue.environment(),
logger = { func = slog.func },
})
vertices := [?]f32 {
// positions uvs
-1.0, 1.0, 0.0, 0.0, 0.0,
1.0, 1.0, 0.0, 1.0, 0.0,
1.0, -1.0, 0.0, 1.0, 1.0,
-1.0, -1.0, 0.0, 0.0, 1.0
}
pixel_format_info := sg.query_pixelformat(.RGBA8)
fmt.printfln("Got pixel format info ", pixel_format_info)
// vertex buffer
state.bind.vertex_buffers[0] = sg.make_buffer({
data = { ptr = &vertices, size = size_of(vertices) },
})
// an index buffer
indices := [?]u16 { 0, 1, 2, 0, 2, 3 }
state.bind.index_buffer = sg.make_buffer({
type = .INDEXBUFFER,
data = { ptr = &indices, size = size_of(indices) },
})
// image which can be dynamically updated
img := sg.make_image({
width = window_width,
height = window_height,
pixel_format = .RGBA8,
sample_count = 1,
usage = .STREAM,
label = "dynamic-texture"
});
state.bind.images[IMG_tex] = img
// a sampler object
sampler := sg.make_sampler({
min_filter = .NEAREST,
mag_filter = .NEAREST,
wrap_u = .CLAMP_TO_EDGE,
wrap_v = .CLAMP_TO_EDGE,
});
state.bind.samplers[SMP_smp] = sampler
// a shader and pipeline object
state.pip = sg.make_pipeline({
shader = sg.make_shader(quad_shader_desc(sg.query_backend())),
index_type = .UINT16,
layout = {
attrs = {
ATTR_quad_position = { format = .FLOAT3 },
ATTR_quad_texcoord0 = { format = .FLOAT2 }
},
},
})
// default pass action
state.pass_action = {
colors = {
0 = { load_action = .CLEAR, clear_value = { 0, 0, 0, 1 }},
},
}
}
clear_color_buffer :: proc(color: u32) {
for y in 0..<window_height {
for x in 0..<window_width {
state.pixel_buffer[(y * window_width) + x] = color
}
}
}
frame :: proc "c" () {
context = runtime.default_context()
// clear_color_buffer(0xff0000ff)
clear_color_buffer(0x0000ffff)
// Update image
size := u64(size_of(state.pixel_buffer))
image_data: sg.Image_Data
image_data.subimage[0][0] = {
ptr = &state.pixel_buffer,
size = size
}
sg.update_image(state.bind.images[IMG_tex], image_data);
sg.begin_pass({ action = state.pass_action, swapchain = sglue.swapchain() })
sg.apply_pipeline(state.pip)
sg.apply_bindings(state.bind)
sg.draw(0, 6, 1)
sg.end_pass()
sg.commit()
}
cleanup :: proc "c" () {
context = runtime.default_context()
sg.shutdown()
}
main :: proc () {
sapp.run({
init_cb = init,
frame_cb = frame,
cleanup_cb = cleanup,
width = window_width,
height = window_height,
window_title = "quad",
icon = { sokol_default = true },
logger = { func = slog.func },
})
}
@header package main
@header import sg "../../sokol/gfx"
@vs vs
in vec4 position;
in vec2 texcoord0;
layout(location=0) out vec2 uv;
void main() {
gl_Position = position;
uv = texcoord0;
}
@end
@fs fs
layout(binding=0) uniform texture2D tex;
layout(binding=0) uniform sampler smp;
layout(location=0) in vec2 uv;
out vec4 frag_color;
void main() {
frag_color = texture(sampler2D(tex, smp), uv);
}
@end
@program quad vs fs