From 31b77ed2e0c037e5718b9ecd06d3941600cc8815 Mon Sep 17 00:00:00 2001 From: aura Date: Tue, 10 Mar 2026 02:08:32 +0100 Subject: wip on 2d batching --- src/render/gl.cpp | 2 +- src/render/gl_2d.cpp | 271 ++++++++++++++++++++++++++++++++++++++------------ src/render/gl_2d.h | 39 ++++++-- src/render/gl_batch.h | 7 +- 4 files changed, 246 insertions(+), 73 deletions(-) (limited to 'src/render') diff --git a/src/render/gl.cpp b/src/render/gl.cpp index c1b6d19..9aef44c 100644 --- a/src/render/gl.cpp +++ b/src/render/gl.cpp @@ -484,7 +484,7 @@ STAT gl_endframe( GL_DATA* gl ) { SDL_GL_SwapWindow( gl->window ); // 1000 fps max be real - while( true ) { + while( 1 ) { U64 diff = u_tick() - gl->last_tick; if( diff < TICK_RESOLUTION / 1000 ) usleep( 10 ); diff --git a/src/render/gl_2d.cpp b/src/render/gl_2d.cpp index b5203b2..506d0da 100644 --- a/src/render/gl_2d.cpp +++ b/src/render/gl_2d.cpp @@ -27,6 +27,26 @@ GL_SHADER_PROGRAM* gl_2d_init( GL_DATA* gl, VEC2 screensize, const char* shadern return program; } +void gl_2d_batch_setup( GL_BATCH2D* batch ) { + glUseProgram( batch->shader->id ); + glBindBuffer( GL_ARRAY_BUFFER, batch->vbuffer ); + + I32 position = glGetAttribLocation( batch->shader->id, "in_pos" ); + I32 color = glGetAttribLocation( batch->shader->id, "in_clr" ); + I32 texcoord = glGetAttribLocation( batch->shader->id, "in_texcoord" ); + I32 sampler = glGetAttribLocation( batch->shader->id, "in_sampler" ); + + glEnableVertexAttribArray( position ); + glVertexAttribPointer( position, 2, GL_FLOAT, 0, sizeof(VERTEX), 0 ); + glEnableVertexAttribArray( color ); + glVertexAttribPointer( color, 4, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->clr ); + glEnableVertexAttribArray( texcoord ); + glVertexAttribPointer( texcoord, 2, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->uv ); + glEnableVertexAttribArray( sampler ); + glVertexAttribPointer( sampler, 1, GL_UNSIGNED_BYTE, 1, sizeof(VERTEX), &( (VERTEX*)nullptr)->sampler ); + glBindBuffer( GL_ARRAY_BUFFER, 0 ); +} + void gl_2d_line( GL_SHADER_PROGRAM* gl2d, VEC2 start, VEC2 end, CLR col ) { static const U16 order[] = { 0, 1 }; @@ -84,66 +104,6 @@ void gl_2d_rect( GL_SHADER_PROGRAM* gl2d, VEC2 origin, VEC2 dim, CLR col ) { glDrawElements( GL_LINE_STRIP, 5, GL_UNSIGNED_SHORT, order ); } -void gl_2d_textured_frect( GL_SHADER_PROGRAM* gl2d, VEC2 origin, VEC2 dim, GL_TEX2D* texture, CLR col, VEC2* uv, F32 rotation ) { - static const U16 order[] = { 0, 1, 2, 3 }; - - glUseProgram( gl2d->id ); - - VERTEX vertices[] = { - { { origin.x, origin.y }, uv? uv[0] : VEC2{ 0.f, 0.f }, col, 0 }, - { { origin.x + dim.x, origin.y }, uv? uv[1] : VEC2{ 1.f, 0.f }, col, 0 }, - { { origin.x, origin.y + dim.y }, uv? uv[2] : VEC2{ 0.f, 1.f }, col, 0 }, - { { origin.x + dim.x, origin.y + dim.y }, uv? uv[3] : VEC2{ 1.f, 1.f }, col, 0 } - }; - - rotation = remainderf( rotation, 360.f ); - if( rotation != 0.f ) { - F32 rad2dg = rotation * (M_PI / 180.f); - - // rotate texture coordinates - for( U32 i = 0; i < 4; ++i ) { - F32 x = vertices[i].uv.x - 0.5f; - F32 y = vertices[i].uv.y - 0.5f; - vertices[i].uv.x = x * cosf( rad2dg ) - y * sinf( rad2dg ) + 0.5f; - vertices[i].uv.y = x * sinf( rad2dg ) + y * cosf( rad2dg ) + 0.5f; - if( vertices[i].uv.x < 0.f ) vertices[i].uv.x = 0.f; - if( vertices[i].uv.x > 1.f ) vertices[i].uv.x = 1.f; - } - } - - glBindBuffer( GL_ARRAY_BUFFER, gl2d->gl->vbuffer ); - glBufferData( GL_ARRAY_BUFFER, sizeof(vertices), &vertices[0], GL_DYNAMIC_DRAW ); - - I32 position = glGetAttribLocation( gl2d->id, "in_pos" ); - I32 color = glGetAttribLocation( gl2d->id, "in_clr" ); - I32 texcoord = glGetAttribLocation( gl2d->id, "in_texcoord" ); - I32 sampler = glGetAttribLocation( gl2d->id, "in_sampler" ); - - glEnableVertexAttribArray( position ); - glVertexAttribPointer( position, 2, GL_FLOAT, 0, sizeof(VERTEX), 0 ); - - glEnableVertexAttribArray( color ); - glVertexAttribPointer( color, 4, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->clr ); - - glEnableVertexAttribArray( texcoord ); - glVertexAttribPointer( texcoord, 2, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->uv ); - - glEnableVertexAttribArray( sampler ); - glVertexAttribPointer( sampler, 1, GL_UNSIGNED_BYTE, 1, sizeof(VERTEX), &( (VERTEX*)nullptr)->sampler ); - - glActiveTexture( GL_TEXTURE0 ); - glBindTexture( GL_TEXTURE_2D, texture->id ); - - glBindBuffer( GL_ARRAY_BUFFER, 0 ); - - glActiveTexture( GL_TEXTURE0 ); - glBindTexture( GL_TEXTURE_2D, texture->id ); - - // glUniform1f( glGetUniformLocation( gl2d->id, "in_time" ), u_time() ); - - glDrawElements( GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, order ); - glBindTexture( GL_TEXTURE_2D, 0 ); -} void gl_2d_frect( GL_SHADER_PROGRAM* gl2d, VEC2 origin, VEC2 dim, CLR col ) { static const U16 order[] = { 0, 1, 2, 3 }; @@ -281,7 +241,7 @@ void gl_2d_fcircle( GL_SHADER_PROGRAM* gl2d, VEC2 origin, F32 radius, CLR col, U free( vertices ); } -void gl_polygon( GL_SHADER_PROGRAM* gl2d, VERTEX* vertices, U32 vertices_count ) { +void gl_2d_polygon( GL_SHADER_PROGRAM* gl2d, VERTEX* vertices, U32 vertices_count ) { glUseProgram( gl2d->id ); glBindBuffer( GL_ARRAY_BUFFER, gl2d->gl->vbuffer ); @@ -309,7 +269,7 @@ void gl_polygon( GL_SHADER_PROGRAM* gl2d, VERTEX* vertices, U32 vertices_count ) glDrawElements( GL_TRIANGLE_FAN, vertices_count, GL_UNSIGNED_SHORT, order ); } -void gl_textured_polygon( +void gl_2d_textured_polygon( GL_SHADER_PROGRAM *gl2d, VERTEX *vertices, U32 vertices_count, @@ -340,11 +300,194 @@ void gl_textured_polygon( glActiveTexture( GL_TEXTURE0 ); glBindTexture( GL_TEXTURE_2D, tex->id ); - glUniform1f( glGetUniformLocation( gl2d->id, "in_time" ), u_time() ); - U16* order = (U16*)alloca( sizeof(U16) * vertices_count ); for( U32 i = 0; i < vertices_count; i++ ) order[i] = i; glDrawElements( GL_TRIANGLE_FAN, vertices_count, GL_UNSIGNED_SHORT, order ); } + +void gl_2d_textured_frect( GL_SHADER_PROGRAM* gl2d, VEC2 origin, VEC2 dim, GL_TEX2D* texture, CLR col, VEC2* uv, F32 rotation ) { + static const U16 order[] = { 0, 1, 2, 3 }; + + glUseProgram( gl2d->id ); + + VERTEX vertices[] = { + { { origin.x, origin.y }, uv? uv[0] : VEC2{ 0.f, 0.f }, col, 0 }, + { { origin.x + dim.x, origin.y }, uv? uv[1] : VEC2{ 1.f, 0.f }, col, 0 }, + { { origin.x, origin.y + dim.y }, uv? uv[2] : VEC2{ 0.f, 1.f }, col, 0 }, + { { origin.x + dim.x, origin.y + dim.y }, uv? uv[3] : VEC2{ 1.f, 1.f }, col, 0 } + }; + + rotation = remainderf( rotation, 360.f ); + if( rotation != 0.f ) { + F32 rad2dg = rotation * (M_PI / 180.f); + + // rotate texture coordinates + for( U32 i = 0; i < 4; ++i ) { + F32 x = vertices[i].uv.x - 0.5f; + F32 y = vertices[i].uv.y - 0.5f; + vertices[i].uv.x = x * cosf( rad2dg ) - y * sinf( rad2dg ) + 0.5f; + vertices[i].uv.y = x * sinf( rad2dg ) + y * cosf( rad2dg ) + 0.5f; + if( vertices[i].uv.x < 0.f ) vertices[i].uv.x = 0.f; + if( vertices[i].uv.x > 1.f ) vertices[i].uv.x = 1.f; + } + } + + glBindBuffer( GL_ARRAY_BUFFER, gl2d->gl->vbuffer ); + glBufferData( GL_ARRAY_BUFFER, sizeof(vertices), &vertices[0], GL_DYNAMIC_DRAW ); + + I32 position = glGetAttribLocation( gl2d->id, "in_pos" ); + I32 color = glGetAttribLocation( gl2d->id, "in_clr" ); + I32 texcoord = glGetAttribLocation( gl2d->id, "in_texcoord" ); + I32 sampler = glGetAttribLocation( gl2d->id, "in_sampler" ); + + glEnableVertexAttribArray( position ); + glVertexAttribPointer( position, 2, GL_FLOAT, 0, sizeof(VERTEX), 0 ); + + glEnableVertexAttribArray( color ); + glVertexAttribPointer( color, 4, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->clr ); + + glEnableVertexAttribArray( texcoord ); + glVertexAttribPointer( texcoord, 2, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->uv ); + + glEnableVertexAttribArray( sampler ); + glVertexAttribPointer( sampler, 1, GL_UNSIGNED_BYTE, 1, sizeof(VERTEX), &( (VERTEX*)nullptr)->sampler ); + + glActiveTexture( GL_TEXTURE0 ); + glBindTexture( GL_TEXTURE_2D, texture->id ); + + glBindBuffer( GL_ARRAY_BUFFER, 0 ); + + glActiveTexture( GL_TEXTURE0 ); + glBindTexture( GL_TEXTURE_2D, texture->id ); + + // glUniform1f( glGetUniformLocation( gl2d->id, "in_time" ), u_time() ); + + glDrawElements( GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, order ); + glBindTexture( GL_TEXTURE_2D, 0 ); +} + +void gl_2d_line( GL_BATCH2D* batch, VEC2 start, VEC2 end, CLR col ) { + VERTEX vertices[] = { + { .pos = { start.x, start.y }, .clr = col }, + { .pos = { end.x, end.y }, .clr = col }, + }; + + gl_batch_insert( batch, vertices, 2, 0, GL_LINES ); +} + + +void gl_2d_rect( GL_BATCH2D* batch, VEC2 origin, VEC2 dim, CLR col ) { + VERTEX vertices[] = { + { .pos = { origin.x , origin.y }, .clr = col }, + { .pos = { origin.x + dim.x, origin.y }, .clr = col }, + { .pos = { origin.x + dim.x, origin.y + dim.y }, .clr = col }, + { .pos = { origin.x , origin.y + dim.y }, .clr = col }, + { .pos = { origin.x , origin.y }, .clr = col }, + }; + + gl_batch_insert( batch, vertices, 5, 0, GL_LINE_STRIP ); +} + +void gl_2d_frect( GL_BATCH2D* batch, VEC2 origin, VEC2 dim, CLR col ) { + VERTEX vertices[] = { + { .pos = { origin.x, origin.y }, .uv = { 0.f, 0.f }, .clr = col }, + { .pos = { origin.x + dim.x, origin.y }, .uv = { 1.f, 0.f }, .clr = col }, + { .pos = { origin.x, origin.y + dim.y }, .uv = { 0.f, 1.f }, .clr = col }, + { .pos = { origin.x + dim.x, origin.y + dim.y }, .uv = { 1.f, 1.f }, .clr = col } + }; + + gl_batch_insert( batch, vertices, 4, 0, GL_TRIANGLE_STRIP ); +} + +void gl_2d_circle( GL_BATCH2D* batch, VEC2 origin, F32 radius, CLR col, U32 res ) { + const F32 step = 360.f / (F32)res; + VERTEX* vertices = (VERTEX*)malloc( sizeof( VERTEX ) * (res + 1) ); + for( U32 i = 0; i < res + 1; ++i ) { + VEC2 offset = m_radial_offset( step * ( i == res? 0 : i ), radius ); + + vertices[i] = (VERTEX){ + .pos = { + origin.x + offset.x, + origin.y + offset.y, + }, + .uv = {}, + .clr = col + }; + } + + gl_batch_insert( batch, vertices, res + 1, 0, GL_LINE_STRIP ); +} + +void gl_2d_fcircle( GL_BATCH2D* batch, VEC2 origin, F32 radius, CLR col, U32 res ) { + const F32 step = 360.f / (F32)res; + + VERTEX* vertices = (VERTEX*)malloc( sizeof(VERTEX) * (res * 2) ); + for( U32 i = 0; i < res * 2; i += 2 ) { + VEC2 offset = m_radial_offset( step * i, radius ); + vertices[i].pos = (VEC2){ + origin.x, + origin.y, + }; + + vertices[i + 1].pos = (VEC2){ + origin.x + offset.x, + origin.y + offset.y, + }; + + vertices[i].uv = (VEC2){ 0.5f, 0.5f }; + vertices[i + 1].uv = (VEC2){ + 0.5f + ( offset.x * 0.5f ) / radius, + 0.5f + ( offset.y * 0.5f ) / radius + }; + + vertices[i].clr = col; + vertices[i + 1].clr = col; + }; + + gl_batch_insert( batch, vertices, res * 2, 0, GL_TRIANGLE_STRIP ); +} + + +extern void gl_2d_textured_frect( + GL_BATCH2D* batch, + VEC2 origin, + VEC2 dim, + GL_TEX2D* texture, + CLR col, + VEC2* uv, + F32 rotation +) { + VERTEX vertices[] = { + { { origin.x, origin.y }, uv? uv[0] : VEC2{ 0.f, 0.f }, col, 0 }, + { { origin.x + dim.x, origin.y }, uv? uv[1] : VEC2{ 1.f, 0.f }, col, 0 }, + { { origin.x, origin.y + dim.y }, uv? uv[2] : VEC2{ 0.f, 1.f }, col, 0 }, + { { origin.x + dim.x, origin.y + dim.y }, uv? uv[3] : VEC2{ 1.f, 1.f }, col, 0 } + }; + + rotation = remainderf( rotation, 360.f ); + if( rotation != 0.f ) { + F32 rad2dg = rotation * (M_PI / 180.f); + + // rotate texture coordinates + for( U32 i = 0; i < 4; ++i ) { + F32 x = vertices[i].uv.x - 0.5f; + F32 y = vertices[i].uv.y - 0.5f; + vertices[i].uv.x = x * cosf( rad2dg ) - y * sinf( rad2dg ) + 0.5f; + vertices[i].uv.y = x * sinf( rad2dg ) + y * cosf( rad2dg ) + 0.5f; + if( vertices[i].uv.x < 0.f ) vertices[i].uv.x = 0.f; + if( vertices[i].uv.x > 1.f ) vertices[i].uv.x = 1.f; + } + } + + gl_batch_insert( batch, vertices, 4, texture, GL_TRIANGLE_FAN ); +} + +void gl_2d_polygon( GL_BATCH2D* batch, VERTEX* vertices, U32 vertices_count ) { + gl_batch_insert( batch, vertices, vertices_count, 0, GL_TRIANGLE_FAN ); +} + +void gl_2d_textured_polygon( GL_BATCH2D* batch, VERTEX* vertices, U32 vertices_count, GL_TEX2D* tex ) { + gl_batch_insert( batch, vertices, vertices_count, tex, GL_TRIANGLE_FAN ); +} diff --git a/src/render/gl_2d.h b/src/render/gl_2d.h index 9830516..25dbd4d 100644 --- a/src/render/gl_2d.h +++ b/src/render/gl_2d.h @@ -1,21 +1,24 @@ #pragma once #include "gl.h" +#include "gl_batch.h" +using GL_BATCH2D = GL_BATCH; extern GL_SHADER_PROGRAM* gl_2d_init( GL_DATA* gl, VEC2 screensize, const char* shadername ); -void gl_polygon( GL_SHADER_PROGRAM* gl2d, VERTEX* vertices, U32 vertices_count ); -void gl_textured_polygon( - GL_SHADER_PROGRAM* gl2d, - VERTEX* vertices, - U32 vertices_count, - GL_TEX2D* tex -); +extern void gl_2d_batch_setup( GL_BATCH2D* batch ); extern void gl_2d_line( GL_SHADER_PROGRAM* gl2d, VEC2 start, VEC2 end, CLR col ); extern void gl_2d_rect( GL_SHADER_PROGRAM* gl2d, VEC2 origin, VEC2 dimensions, CLR col ); extern void gl_2d_frect( GL_SHADER_PROGRAM* gl2d, VEC2 origin, VEC2 dimensions, CLR col ); extern void gl_2d_circle( GL_SHADER_PROGRAM* gl2d, VEC2 origin, F32 radius, CLR col, U32 res = 48 ); extern void gl_2d_fcircle( GL_SHADER_PROGRAM* gl2d, VEC2 origin, F32 radius, CLR col, U32 res = 48 ); +extern void gl_2d_polygon( GL_SHADER_PROGRAM* gl2d, VERTEX* vertices, U32 vertices_count ); +extern void gl_2d_textured_polygon( + GL_SHADER_PROGRAM* gl2d, + VERTEX* vertices, + U32 vertices_count, + GL_TEX2D* tex +); extern void gl_2d_textured_frect( GL_SHADER_PROGRAM* gl2d, VEC2 origin, @@ -25,3 +28,25 @@ extern void gl_2d_textured_frect( VEC2* uv = 0, F32 rotation = 0.F ); + +extern void gl_2d_line( GL_BATCH2D* batch, VEC2 start, VEC2 end, CLR col ); +extern void gl_2d_rect( GL_BATCH2D* batch, VEC2 origin, VEC2 dimensions, CLR col ); +extern void gl_2d_frect( GL_BATCH2D* batch, VEC2 origin, VEC2 dimensions, CLR col ); +extern void gl_2d_circle( GL_BATCH2D* batch, VEC2 origin, F32 radius, CLR col, U32 res = 48 ); +extern void gl_2d_fcircle( GL_BATCH2D* batch, VEC2 origin, F32 radius, CLR col, U32 res = 48 ); +extern void gl_2d_polygon( GL_BATCH2D* batch, VERTEX* vertices, U32 vertices_count ); +extern void gl_2d_textured_polygon( + GL_BATCH2D* batch, + VERTEX* vertices, + U32 vertices_count, + GL_TEX2D* tex +); +extern void gl_2d_textured_frect( + GL_BATCH2D* batch, + VEC2 origin, + VEC2 dim, + GL_TEX2D* texture, + CLR col = { 1.f, 1.f, 1.f, 1.f }, + VEC2* uv = 0, + F32 rotation = 0.F +); diff --git a/src/render/gl_batch.h b/src/render/gl_batch.h index 944521f..12b512f 100644 --- a/src/render/gl_batch.h +++ b/src/render/gl_batch.h @@ -133,6 +133,11 @@ inline GL_BATCH_CALL* gl_batch_get_call( GL_BATCH* batch, GL_TEX && vp_start == last->clip_start && vp_dim == last->viewport_dim && clip_start == last->clip_start && clip_dim == last->clip_dim ) { + if( !tex ) { + *texid = SAMPLER_ID_NONE; + return last; + } + I32 idx = last->textures.idx_of( tex ); if( idx != -1 ) { *texid = idx; @@ -187,7 +192,7 @@ inline void gl_batch_insert( call = gl_batch_get_call( batch, tex, primitive, &texid ); for( U32 i = 0; i < count; ++i ) { - vertices[i].sampler = (!!tex)? texid : SAMPLER_ID_NONE; + vertices[i].sampler = texid; call->vertices.push( vertices[i] ); } } -- cgit v1.2.3