diff options
Diffstat (limited to 'src/render/gl_2d.cpp')
| -rw-r--r-- | src/render/gl_2d.cpp | 314 |
1 files changed, 314 insertions, 0 deletions
diff --git a/src/render/gl_2d.cpp b/src/render/gl_2d.cpp new file mode 100644 index 0000000..44e7e00 --- /dev/null +++ b/src/render/gl_2d.cpp @@ -0,0 +1,314 @@ +#include "gl_2d.h" +#include "../util.h" + +GL_PROGRAM* gl_2d_init( GL_DATA* gl, VEC2 screensize, const char* shadername ) { + GL_PROGRAM* program = gl_program_create( gl, shadername ); + if( !OK( gl_program_compile( gl, program ) ) ) + dlog( "gl_2d_init() : error compiling shader %s\n", shadername ); + + F32 screen_ratio[] = { + 2.f / screensize.x, + 2.f / screensize.y, + 1.f, + 1.f + }; + + glUseProgram( program->id ); + glEnable( GL_BLEND ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + + I32 ratio_location = glGetUniformLocation( program->id, "g_screenratio" ); + glUniform4fv( ratio_location, 1, &screen_ratio[0] ); + + I32 samplers_location = glGetUniformLocation( program->id, "g_samplers" ); + glUniform1iv( samplers_location, 255, SAMPLER_INDICES ); + + return program; +} + +void gl_2d_line( GL_PROGRAM* gl2d, VEC2 start, VEC2 end, CLR col ) { + static const U16 order[] = { 0, 1 }; + + glUseProgram( gl2d->id ); + + VERTEX vertices[] = { + { .pos = { start.x, start.y }, .clr = col }, + { .pos = { end.x, end.y }, .clr = col }, + }; + + 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" ); + glEnableVertexAttribArray( position ); + glVertexAttribPointer( position, 2, GL_FLOAT, 0, sizeof(VERTEX), 0 ); + I32 color = glGetAttribLocation( gl2d->id, "in_col" ); + glEnableVertexAttribArray( color ); + glVertexAttribPointer( color, 4, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->clr ); + + glBindBuffer( GL_ARRAY_BUFFER, 0 ); + glDrawElements( GL_LINES, 2, GL_UNSIGNED_SHORT, order ); +} + +void gl_2d_rect( GL_PROGRAM* gl2d, VEC2 origin, VEC2 dim, CLR col ) { + static const U16 order[] = { 0, 1, 2, 3, 4 }; + + glUseProgram( gl2d->id ); + + 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 }, + }; + + 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" ); + glEnableVertexAttribArray( position ); + glVertexAttribPointer( position, 2, GL_FLOAT, 0, sizeof(VERTEX), 0 ); + I32 color = glGetAttribLocation( gl2d->id, "in_col" ); + glEnableVertexAttribArray( color ); + glVertexAttribPointer( color, 4, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->clr ); + + glBindBuffer( GL_ARRAY_BUFFER, 0 ); + glDrawElements( GL_LINE_STRIP, 5, GL_UNSIGNED_SHORT, order ); +} + +void gl_2d_textured_frect( GL_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" ); + glEnableVertexAttribArray( position ); + glVertexAttribPointer( position, 2, GL_FLOAT, 0, sizeof(VERTEX), 0 ); + I32 color = glGetAttribLocation( gl2d->id, "in_col" ); + glEnableVertexAttribArray( color ); + glVertexAttribPointer( color, 4, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->clr ); + I32 texcoord = glGetAttribLocation( gl2d->id, "in_texcoord" ); + glEnableVertexAttribArray( texcoord ); + glVertexAttribPointer( texcoord, 2, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->uv ); + I32 sampler = glGetAttribLocation( gl2d->id, "in_sampler" ); + glEnableVertexAttribArray( sampler ); + glVertexAttribPointer( sampler, 1, GL_UNSIGNED_BYTE, 1, sizeof(VERTEX), &( (VERTEX*)nullptr)->sampler ); + + 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_PROGRAM* gl2d, VEC2 origin, VEC2 dim, CLR col ) { + static const U16 order[] = { 0, 1, 2, 3 }; + + glUseProgram( gl2d->id ); + 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 } + }; + + 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" ); + glEnableVertexAttribArray( position ); + glVertexAttribPointer( position, 2, GL_FLOAT, 0, sizeof(VERTEX), 0 ); + I32 color = glGetAttribLocation( gl2d->id, "in_col" ); + glEnableVertexAttribArray( color ); + glVertexAttribPointer( color, 4, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->clr ); + I32 texcoord = glGetAttribLocation( gl2d->id, "in_texcoord" ); + glEnableVertexAttribArray( texcoord ); + glVertexAttribPointer( texcoord, 2, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->uv ); + + glBindBuffer( GL_ARRAY_BUFFER, 0 ); + glDrawElements( GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, order ); +} + +void gl_2d_circle( GL_PROGRAM* gl2d, VEC2 origin, F32 radius, CLR col, U32 res ) { + static U16* order = 0; + const F32 step = 360.f / (F32)res; + + glUseProgram( gl2d->id ); + + if( !order ) { + order = (U16*)malloc( sizeof( U16 ) * (res + 1) ); + for( U32 i = 0; i < res + 1; ++i ) + order[i] = i; + } + + 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 + }; + } + + glBindBuffer( GL_ARRAY_BUFFER, gl2d->gl->vbuffer ); + glBufferData( GL_ARRAY_BUFFER, sizeof(VERTEX) * (res + 1), &vertices[0], GL_STATIC_DRAW ); + I32 position = glGetAttribLocation( gl2d->id, "in_pos" ); + glEnableVertexAttribArray( position ); + glVertexAttribPointer( position, 2, GL_FLOAT, 0, sizeof(VERTEX), 0 ); + I32 color = glGetAttribLocation( gl2d->id, "in_col" ); + glEnableVertexAttribArray( color ); + glVertexAttribPointer( color, 4, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->clr ); + + glBindBuffer( GL_ARRAY_BUFFER, 0 ); + + glDrawElements( GL_LINE_STRIP, res + 1, GL_UNSIGNED_SHORT, order ); + free( vertices ); +} + +void gl_2d_fcircle( GL_PROGRAM* gl2d, VEC2 origin, F32 radius, CLR col, U32 res ) { + static U16* order = 0; + const F32 step = 360.f / (F32)res; + + glUseProgram( gl2d->id ); + + if( !order ) { + order = (U16*)malloc( sizeof( U16 ) * (res * 2) ); + for( U32 i = 0; i < res * 2; ++i ) + order[i] = i; + } + + 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; + }; + + glBindBuffer( GL_ARRAY_BUFFER, gl2d->gl->vbuffer ); + glBufferData( GL_ARRAY_BUFFER, sizeof(VERTEX) * res * 2, &vertices[0], GL_STATIC_DRAW ); + I32 position = glGetAttribLocation( gl2d->id, "in_pos" ); + glEnableVertexAttribArray( position ); + glVertexAttribPointer( position, 2, GL_FLOAT, 0, sizeof(VERTEX), 0 ); + I32 color = glGetAttribLocation( gl2d->id, "in_col" ); + glEnableVertexAttribArray( color ); + glVertexAttribPointer( color, 4, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->clr ); + I32 texcoord = glGetAttribLocation( gl2d->id, "in_texcoord" ); + glEnableVertexAttribArray( texcoord ); + glVertexAttribPointer( texcoord, 2, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->uv ); + + glBindBuffer( GL_ARRAY_BUFFER, 0 ); + + glDrawElements( GL_TRIANGLE_STRIP, res + 2, GL_UNSIGNED_SHORT, order ); + free( vertices ); +} + +void gl_polygon( GL_PROGRAM* gl2d, VERTEX* vertices, U32 vertices_count ) { + glUseProgram( gl2d->id ); + + glBindBuffer( GL_ARRAY_BUFFER, gl2d->gl->vbuffer ); + glBufferData( GL_ARRAY_BUFFER, sizeof(VERTEX) * vertices_count, vertices, GL_STATIC_DRAW ); + + I32 position = glGetAttribLocation( gl2d->id, "in_pos" ); + glEnableVertexAttribArray( position ); + glVertexAttribPointer( position, 2, GL_FLOAT, 0, sizeof(VERTEX), 0 ); + I32 color = glGetAttribLocation( gl2d->id, "in_col" ); + glEnableVertexAttribArray( color ); + glVertexAttribPointer( color, 4, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->clr ); + I32 texcoord = glGetAttribLocation( gl2d->id, "in_texcoord" ); + glEnableVertexAttribArray( texcoord ); + glVertexAttribPointer( texcoord, 2, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->uv ); + + glBindBuffer( GL_ARRAY_BUFFER, 0 ); + + 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_textured_polygon( + GL_PROGRAM *gl2d, + VERTEX *vertices, + U32 vertices_count, + GL_TEX2D *tex +) { + glUseProgram( gl2d->id ); + + for( U32 i = 0; i < vertices_count; ++i ) + vertices[i].sampler = 0; + + glBindBuffer( GL_ARRAY_BUFFER, gl2d->gl->vbuffer ); + glBufferData( GL_ARRAY_BUFFER, sizeof(VERTEX) * vertices_count, vertices, GL_STATIC_DRAW ); + I32 position = glGetAttribLocation( gl2d->id, "in_pos" ); + glEnableVertexAttribArray( position ); + glVertexAttribPointer( position, 2, GL_FLOAT, 0, sizeof(VERTEX), 0 ); + I32 color = glGetAttribLocation( gl2d->id, "in_col" ); + glEnableVertexAttribArray( color ); + glVertexAttribPointer( color, 4, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->clr ); + I32 texcoord = glGetAttribLocation( gl2d->id, "in_texcoord" ); + glEnableVertexAttribArray( texcoord ); + glVertexAttribPointer( texcoord, 2, GL_FLOAT, 0, sizeof(VERTEX), &( (VERTEX*)nullptr)->uv ); + I32 sampler = glGetAttribLocation( gl2d->id, "in_sampler" ); + glEnableVertexAttribArray( sampler ); + glVertexAttribPointer( sampler, 1, GL_UNSIGNED_BYTE, 1, sizeof(VERTEX), &( (VERTEX*)nullptr)->sampler ); + + glBindBuffer( GL_ARRAY_BUFFER, 0 ); + + 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 ); +} |
