diff options
| author | navewindre <boneyaard@gmail.com> | 2025-09-03 20:10:09 +0200 |
|---|---|---|
| committer | navewindre <boneyaard@gmail.com> | 2025-09-03 20:10:09 +0200 |
| commit | f8b92ce3aa08b1445c9f956d8166830946562d12 (patch) | |
| tree | 94e63a5aec9f8f52b577f56799e0c9201fd976a5 /src/render/gl_3d.cpp | |
a
Diffstat (limited to 'src/render/gl_3d.cpp')
| -rw-r--r-- | src/render/gl_3d.cpp | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/src/render/gl_3d.cpp b/src/render/gl_3d.cpp new file mode 100644 index 0000000..78e7f5e --- /dev/null +++ b/src/render/gl_3d.cpp @@ -0,0 +1,204 @@ +#include "gl_3d.h" +#include "../util/matrix.h" +#include "gl.h" +#include "gl_batch.h" + +GL_3D* gl_3d_init( GL_DATA* gl, VEC2 screensize, const char* shadername ) { + GL_3D *gl3d = (GL_3D*)gl_program_create( gl, shadername, sizeof(GL_3D) ); + if( !OK( gl_program_compile( gl, gl3d ) ) ) + dlog( "gl_2d_init() : error compiling shader %s\n", shadername ); + + gl3d->winsize = screensize; + gl3d->aspect = screensize.x / screensize.y; + + glUseProgram( gl3d->id ); + I32 samplers_location = glGetUniformLocation( gl3d->id, "g_samplers" ); + glUniform1iv( samplers_location, gl->shader_texture_limit, SAMPLER_INDICES ); + return gl3d; +} + +void gl_3d_projection_setup( GL_PROGRAM *_gl3d, VEC3 pos, F32 fov_deg, F32 yaw, F32 pitch, F32 near, F32 far, VEC2 winsize ) { + GL_3D* gl3d = (GL_3D*)_gl3d; + MAT4 proj, yaw_rot, pitch_rot, view, transl, tmp; + + F32 fov_rad = m_deg2rad( fov_deg ); + F32 yaw_rad = m_deg2rad( remainderf( yaw + 90.f, 360.f ) ); + F32 pitch_rad = m_deg2rad( remainderf( pitch , 360.f ) ); + gl3d->aspect = winsize.x / winsize.y; + gl3d->winsize = winsize; + + mat4_perspective( &proj, fov_rad, gl3d->aspect, near, far ); + mat4_rotation_y( &yaw_rot, -yaw_rad ); + mat4_rotation_x( &pitch_rot, -pitch_rad ); + mat4_translation( &transl, -pos.x, -pos.z, -pos.y ); + + mat4_mul( &yaw_rot, &transl, &tmp ); + mat4_mul( &pitch_rot, &tmp, &view ); + mat4_mul( &proj, &view, &gl3d->projmat ); + gl3d->gl->proj_matrix = &gl3d->projmat; + + glUseProgram( gl3d->id ); + I32 location = glGetUniformLocation( gl3d->id, "in_proj_matrix" ); + glUniformMatrix4fv( location, 1, 1, (GLfloat*)&gl3d->projmat ); + + glUniform1f( glGetUniformLocation( gl3d->id, "in_time" ), u_time() ); +} + +void gl_3d_batch_setup( GL_BATCH3D *batch ) { + glUseProgram( batch->shader->id ); + glBindBuffer( GL_ARRAY_BUFFER, batch->vbuffer ); + I32 position = glGetAttribLocation( batch->shader->id, "in_pos" ); + glEnableVertexAttribArray( position ); + glVertexAttribPointer( position, 3, GL_FLOAT, 0, sizeof(VERTEX3D), 0 ); + I32 color = glGetAttribLocation( batch->shader->id, "in_clr" ); + glEnableVertexAttribArray( color ); + glVertexAttribPointer( color, 3, GL_FLOAT, 0, sizeof(VERTEX3D), &( (VERTEX3D*)nullptr )->clr ); + I32 texcoord = glGetAttribLocation( batch->shader->id, "in_texcoord" ); + glEnableVertexAttribArray( texcoord ); + glVertexAttribPointer( texcoord, 2, GL_FLOAT, 0, sizeof(VERTEX3D), &( (VERTEX3D*)nullptr )->uv ); + I32 sampler = glGetAttribLocation( batch->shader->id, "in_sampler" ); + glEnableVertexAttribArray( sampler ); + glVertexAttribPointer( sampler, 1, GL_UNSIGNED_BYTE, 1, sizeof(VERTEX3D), &( (VERTEX3D*)nullptr )->sampler ); + glBindBuffer( GL_ARRAY_BUFFER, 0 ); +} + +void gl_3d_polygon( + GL_PROGRAM* gl3d, + VERTEX3D* vertices, + U32 vertices_count, + GL_TEX2D* tex +) { + glUseProgram( gl3d->id ); + + if( !!tex ) { + glActiveTexture( GL_TEXTURE0 ); + glBindTexture( GL_TEXTURE_2D, tex->id ); + } else { + for( U32 i = 0; i < vertices_count; ++i ) + vertices[i].sampler = SAMPLER_ID_NONE; + } + + glBindBuffer( GL_ARRAY_BUFFER, gl3d->gl->vbuffer ); + glBufferData( GL_ARRAY_BUFFER, sizeof(VERTEX3D) * vertices_count, vertices, GL_STATIC_DRAW ); + I32 position = glGetAttribLocation( gl3d->id, "in_pos" ); + glEnableVertexAttribArray( position ); + glVertexAttribPointer( position, 3, GL_FLOAT, 0, sizeof(VERTEX3D), 0 ); + I32 color = glGetAttribLocation( gl3d->id, "in_clr" ); + glEnableVertexAttribArray( color ); + glVertexAttribPointer( color, 3, GL_FLOAT, 0, sizeof(VERTEX3D), &( (VERTEX3D*)nullptr )->clr ); + I32 texcoord = glGetAttribLocation( gl3d->id, "in_texcoord" ); + glEnableVertexAttribArray( texcoord ); + glVertexAttribPointer( texcoord, 2, GL_FLOAT, 0, sizeof(VERTEX3D), &( (VERTEX3D*)nullptr )->uv ); + I32 sampler = glGetAttribLocation( gl3d->id, "in_sampler" ); + glEnableVertexAttribArray( sampler ); + glVertexAttribPointer( sampler, 1, GL_UNSIGNED_BYTE, 1, sizeof(VERTEX3D), &( (VERTEX3D*)nullptr )->sampler ); + + U16* order = (U16*)alloca( sizeof(U16) * vertices_count ); + for( U32 i = 0; i < vertices_count; i++ ) + order[i] = i; + + glBindBuffer( GL_ARRAY_BUFFER, 0 ); + glDrawElements( GL_TRIANGLE_FAN, vertices_count, GL_UNSIGNED_SHORT, order ); +} + +void gl_3d_polygon_fan( + GL_BATCH3D* batch, + VERTEX3D* vertices, + U32 vertices_count, + GL_TEX2D* tex +) { + if( vertices_count < 3 ) + return; + + LIST<VERTEX3D> list = triangle_fan_to_list( vertices, vertices_count ); + gl_batch_insert( + batch, + list.data, + list.size, + tex + ); +} + +void gl_3d_polygon( + GL_BATCH3D* batch, + VERTEX3D* vertices, + U32 vertices_count, + GL_TEX2D* tex +) { + gl_batch_insert( + batch, + vertices, + vertices_count, + tex + ); +} + +void build_plane( VERTEX3D* v, VEC3 pos, VEC2 size, VEC2 rot, CLR col ) { + F32 half_width = size.x * 0.5f; + F32 half_height = size.y * 0.5f; + + VEC3 vertices[4] = { + { -half_width, -half_height, 0 }, + { half_width, -half_height, 0 }, + { half_width, half_height, 0 }, + { -half_width, half_height, 0 } + }; + + F32 sin_pitch = sinf( m_deg2rad( rot.x ) ); + F32 cos_pitch = cosf( m_deg2rad( rot.x ) ); + F32 sin_yaw = sinf( m_deg2rad( rot.y ) ); + F32 cos_yaw = cosf( m_deg2rad( rot.y ) ); + + for( I32 i = 0; i < 4; i++) { + F32 x = vertices[i].x; + F32 y = vertices[i].y; + F32 z = vertices[i].z; + vertices[i].y = y * cos_pitch - z * sin_pitch; + vertices[i].z = y * sin_pitch + z * cos_pitch; + y = vertices[i].y; + vertices[i].x = x * cos_yaw - y * sin_yaw; + vertices[i].y = x * sin_yaw + y * cos_yaw; + + vertices[i].x += pos.x; + vertices[i].y += pos.y; + vertices[i].z += pos.z; + } + + VEC2 uvs[4] = { + { 0.0f, 1.0f }, + { 1.0f, 1.0f }, + { 1.0f, 0.0f }, + { 0.0f, 0.0f } + }; + + v[0] = { .pos = { vertices[0].x, vertices[0].z, vertices[0].y }, .uv = uvs[0], .clr = col, .sampler = 0 }; + v[1] = { .pos = { vertices[1].x, vertices[1].z, vertices[1].y }, .uv = uvs[1], .clr = col, .sampler = 0 }; + v[2] = { .pos = { vertices[2].x, vertices[2].z, vertices[2].y }, .uv = uvs[2], .clr = col, .sampler = 0 }; + v[3] = { .pos = { vertices[3].x, vertices[3].z, vertices[3].y }, .uv = uvs[3], .clr = col, .sampler = 0 }; +} + +void gl_3d_plane( + GL_SHADER_PROGRAM* gl3d, + VEC3 pos, + VEC2 size, + VEC2 rot, + GL_TEX2D* tex, + CLR col +) { + VERTEX3D v[4]; + build_plane( v, pos, size, rot, col ); + gl_3d_polygon( gl3d, v, 4, tex ); +} + +void gl_3d_plane( + GL_BATCH3D* batch, + VEC3 pos, + VEC2 size, + VEC2 rot, + GL_TEX2D* tex, + CLR col +) { + VERTEX3D v[4]; + build_plane( v, pos, size, rot, col ); + gl_3d_polygon_fan( batch, v, 4, tex ); +} |
