summaryrefslogtreecommitdiff
path: root/src/render/gl_3d.cpp
diff options
context:
space:
mode:
authornavewindre <boneyaard@gmail.com>2025-09-03 20:10:09 +0200
committernavewindre <boneyaard@gmail.com>2025-09-03 20:10:09 +0200
commitf8b92ce3aa08b1445c9f956d8166830946562d12 (patch)
tree94e63a5aec9f8f52b577f56799e0c9201fd976a5 /src/render/gl_3d.cpp
a
Diffstat (limited to 'src/render/gl_3d.cpp')
-rw-r--r--src/render/gl_3d.cpp204
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 );
+}