Created
June 26, 2022 18:37
-
-
Save ryuukk/1c8b7af3265389ed94467bef2fd70d30 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct UIRenderer | |
{ | |
enum MAX_C = 8192; | |
enum MAX_V = 512 * 1024; | |
enum MAX_I = 128 * 1024; | |
Context* ctx; | |
ShaderProgram program_nuklear; | |
uint nk_vao; | |
uint nk_vbo; | |
uint nk_ibo; | |
nk.nk_context nk_ctx = void; | |
nk.nk_allocator nk_allocator = void; | |
nk.nk_buffer nk_commands = void; | |
nk.nk_buffer nk_vertices = void; | |
nk.nk_buffer nk_indices = void; | |
nk.nk_font_atlas nk_atlas; | |
nk.struct_nk_vec2 tmp_scroll = { x: 0, y: 0 }; | |
int attrib_pos; | |
int attrib_uv; | |
int attrib_col; | |
void create_gl_ressource() | |
{ | |
import gl = dawn.gl; | |
program_nuklear.create(VS, FS); | |
attrib_pos = gl.glGetAttribLocation(program_nuklear.program, "aPos"); | |
attrib_uv = gl.glGetAttribLocation(program_nuklear.program, "aTexCoord"); | |
attrib_col = gl.glGetAttribLocation(program_nuklear.program, "aColor"); | |
gl.glGenBuffers(1, &nk_vbo); | |
gl.glGenBuffers(1, &nk_ibo); | |
gl.glGenVertexArrays(1, &nk_vao); | |
gl.glBindVertexArray(nk_vao); | |
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, nk_vbo); | |
gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, nk_ibo); | |
gl.glEnableVertexAttribArray(0); | |
gl.glEnableVertexAttribArray(1); | |
gl.glEnableVertexAttribArray(2); | |
gl.glVertexAttribPointer(attrib_pos, 2, gl.GL_FLOAT, gl.GL_FALSE, 8 * float.sizeof, cast(uint*) (0 * float.sizeof)); | |
gl.glVertexAttribPointer(attrib_uv, 2, gl.GL_FLOAT, gl.GL_FALSE, 8 * float.sizeof, cast(uint*) (2 * float.sizeof)); | |
gl.glVertexAttribPointer(attrib_col, 4, gl.GL_FLOAT, gl.GL_FALSE, 8 * float.sizeof, cast(uint*) (4 * float.sizeof)); | |
gl.glBindTexture(gl.GL_TEXTURE_2D, 0); | |
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0); | |
gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, 0); | |
gl.glBindVertexArray(0); | |
} | |
void create_nk_ressource() | |
{ | |
nk_allocator.userdata.ptr = ctx; | |
nk_allocator.alloc = &dnk_allocate; | |
nk_allocator.free = &dnk_free; | |
nk.nk_font_atlas fontAtlas = void; | |
nk.nk_font_atlas_init(&fontAtlas, &nk_allocator); | |
nk.nk_font_atlas_begin(&fontAtlas); | |
auto fontConfig = nk.nk_font_config(16.0); | |
fontConfig.oversample_h = 6; | |
fontConfig.oversample_v = 6; | |
auto font = nk.nk_font_atlas_add_default(&fontAtlas, 16.0, &fontConfig); | |
// create tex | |
int imgWidth = 0; | |
int imgHeight = 0; | |
auto img = nk.nk_font_atlas_bake(&fontAtlas, &imgWidth, &imgHeight, nk.NK_FONT_ATLAS_RGBA32); | |
auto atlasTex = dawn.texture.create_texture(imgWidth, imgHeight, cast(ubyte*) img); | |
LINFO("font tex: {}:{}", imgWidth, imgHeight); | |
nk.nk_font_atlas_end(&fontAtlas, nk.nk_handle_id(atlasTex.gl_handle), null); | |
if (nk.nk_init(&nk_ctx, &nk_allocator, &font.handle) == 0) { | |
// if (nk.test() == 0) { | |
panic("problem with nk"); | |
} | |
else | |
{ | |
nk.nk_buffer_init(&nk_commands, &nk_allocator, MAX_C); | |
nk.nk_buffer_init(&nk_vertices, &nk_allocator, MAX_V); | |
nk.nk_buffer_init(&nk_indices, &nk_allocator, MAX_I); | |
} | |
} | |
void begin() | |
{ | |
nk.nk_input_begin(&nk_ctx); | |
auto cursorPosX = ctx.engine.input.mouse_x; | |
auto cursorPosY = ctx.engine.input.mouse_y; | |
nk.nk_input_motion(&nk_ctx, cursorPosX, cursorPosY); | |
nk.nk_input_button(&nk_ctx, nk.NK_BUTTON_LEFT, cursorPosX, cursorPosY, ctx.engine.input.mouse_pressed ? 1 : 0); | |
// TODO: middle, right | |
nk.nk_input_scroll(&nk_ctx, tmp_scroll); | |
tmp_scroll = nk.nk_vec2(0,0); | |
nk.nk_input_end(&nk_ctx); | |
} | |
void render() | |
{ | |
import gl = dawn.gl; | |
gl.glEnable(gl.GL_BLEND); | |
gl.glBlendEquation(gl.GL_FUNC_ADD); | |
gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA); | |
gl.glDisable(gl.GL_CULL_FACE); | |
gl.glDisable(gl.GL_DEPTH_TEST); | |
gl.glEnable(gl.GL_SCISSOR_TEST); | |
gl.glActiveTexture(gl.GL_TEXTURE0); | |
nk.nk_draw_vertex_layout_element[4] vertexLayout = [ | |
{ attribute: nk.NK_VERTEX_POSITION, format: nk.NK_FORMAT_FLOAT, offset: 0 }, | |
{ attribute: nk.NK_VERTEX_TEXCOORD, format: nk.NK_FORMAT_FLOAT, offset: 8 }, | |
{ attribute: nk.NK_VERTEX_COLOR, format: nk.NK_FORMAT_R32G32B32A32_FLOAT, offset: 16 }, | |
// end of vertex layout | |
{ attribute: nk.NK_VERTEX_ATTRIBUTE_COUNT, format: nk.NK_FORMAT_COUNT, offset: 0 }, | |
]; | |
nk.nk_convert_config convertConfig = { | |
global_alpha: 1.0, | |
line_AA: nk.NK_ANTI_ALIASING_ON, | |
shape_AA: nk.NK_ANTI_ALIASING_ON, | |
vertex_layout: vertexLayout.ptr, | |
vertex_size: 8 * float.sizeof, | |
vertex_alignment: float.alignof, | |
circle_segment_count: 22, | |
curve_segment_count: 22, | |
arc_segment_count: 22, | |
nulll: { | |
texture: { id: 0 }, | |
uv: { x: 0, y: 0 } | |
} | |
}; | |
if (nk.nk_convert(&nk_ctx, &nk_commands, &nk_vertices, &nk_indices, &convertConfig) != 0) { | |
panic("nk_convert error"); | |
} | |
float[4][4] ortho = [ | |
[2.0, 0.0, 0.0, 0.0], | |
[0.0,-2.0, 0.0, 0.0], | |
[0.0, 0.0,-1.0, 0.0], | |
[-1.0,1.0, 0.0, 1.0], | |
]; | |
ortho[0][0] = ortho[0][0] / cast(float)(ctx.engine.backbuffer_width); | |
ortho[1][1] = ortho[1][1] / cast(float)(ctx.engine.backbuffer_height); | |
auto ptr = &ortho[0][0]; | |
auto mptr = cast(mat4*)(ptr); | |
program_nuklear.bind(); | |
program_nuklear.set_uniformi("uTexture", 0); | |
program_nuklear.set_uniform_mat4("projMatrix", *mptr); | |
gl.glBindVertexArray(nk_vao); | |
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, nk_vbo); | |
gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, nk_ibo); | |
gl.glBufferData(gl.GL_ARRAY_BUFFER, cast(uint)(nk.nk_buffer_total(&nk_vertices)), nk.nk_buffer_memory_const(&nk_vertices), gl.GL_STREAM_DRAW); | |
gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER, cast(uint)(nk.nk_buffer_total(&nk_indices)), nk.nk_buffer_memory_const(&nk_indices), gl.GL_STREAM_DRAW); | |
auto cmd = nk.nk__draw_begin(&nk_ctx, &nk_commands); | |
uint offset = 0; | |
while(cmd) { | |
auto count = cmd.elem_count; | |
auto tex = cmd.texture.id; | |
if (count > 0) { | |
program_nuklear.set_uniformi("useTexture", tex != 0 ? 1 : 0); | |
gl.glBindTexture(gl.GL_TEXTURE_2D,cast(uint) tex); | |
auto clip = cmd.clip_rect; | |
gl.glScissor( | |
cast(int)(clip.x), | |
cast(int)(cast(float)(engine.backbuffer_height) - (clip.y + clip.h)), | |
cast(int)(clip.w), | |
cast(int)(clip.h), | |
); | |
gl.glDrawElements(gl.GL_TRIANGLES, cast(int) count, gl.GL_UNSIGNED_SHORT, cast(void*)(offset * 2)); | |
dawn.gfx.check_gl_error(); | |
} | |
offset += count; | |
cmd = nk.nk__draw_next(cmd, &nk_commands, &nk_ctx); | |
} | |
nk.nk_clear(&nk_ctx); | |
nk.nk_buffer_clear(&nk_commands); | |
nk.nk_buffer_clear(&nk_vertices); | |
nk.nk_buffer_clear(&nk_indices); | |
} | |
void create(Context* ctx) | |
{ | |
this.ctx = ctx; | |
create_gl_ressource(); | |
create_nk_ressource(); | |
} | |
extern(C) static void* dnk_allocate(nk.nk_handle handle, void* old, nk.nk_size size) | |
{ | |
if (old) | |
{ | |
LWARN("need handle realloc {}", size); | |
} | |
auto ctx = cast(Context*) handle.ptr; | |
return ctx.engine.allocator.allocate(size); | |
} | |
extern(C) static void dnk_free(nk.nk_handle handle, void* old) | |
{ | |
auto ctx = cast(Context*) handle.ptr; | |
if (!old) | |
{ | |
LWARN("trying to free null ptr"); | |
return; | |
} | |
ctx.engine.allocator.free(old); | |
} | |
enum VS =" | |
#version 300 es | |
in vec2 aPos; | |
in vec2 aTexCoord; | |
in vec4 aColor; | |
uniform mat4 projMatrix; | |
out vec2 texCoord; | |
out vec4 vertexColor; | |
void main() { | |
gl_Position = projMatrix * vec4(aPos, 0, 1); | |
texCoord = aTexCoord; | |
vertexColor = aColor; | |
}"; | |
enum FS = | |
" | |
#version 300 es | |
precision mediump float; | |
in vec2 texCoord; | |
in vec4 vertexColor; | |
uniform bool useTexture; | |
uniform sampler2D uTexture; | |
out vec4 fragColor; | |
void main() { | |
if (useTexture) { | |
fragColor = texture(uTexture, texCoord) * vertexColor; | |
} else { | |
fragColor = vertexColor; | |
} | |
}"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment