From 815d5382f2ab7035db461fff080ea8659ecfb4ab Mon Sep 17 00:00:00 2001 From: headshot2017 Date: Tue, 27 Dec 2022 21:30:12 -0400 Subject: [PATCH] add OpenGL 2.0 and 3.3 Core renderers --- test/gl20/gl20_renderer.c | 171 ++++++++++++++++ test/gl20/gl20_renderer.h | 6 + test/gl33core/gl33core_renderer.c | 313 ++++++++++++++++++++++++++++++ test/gl33core/gl33core_renderer.h | 6 + test/renderer.h | 57 ++++++ 5 files changed, 553 insertions(+) create mode 100644 test/gl20/gl20_renderer.c create mode 100644 test/gl20/gl20_renderer.h create mode 100644 test/gl33core/gl33core_renderer.c create mode 100644 test/gl33core/gl33core_renderer.h create mode 100644 test/renderer.h diff --git a/test/gl20/gl20_renderer.c b/test/gl20/gl20_renderer.c new file mode 100644 index 0000000..cf846aa --- /dev/null +++ b/test/gl20/gl20_renderer.c @@ -0,0 +1,171 @@ +#include "gl20_renderer.h" + +#include + +#include "../../src/libsm64.h" +#include "../renderer.h" +#include "../context.h" +#include "../level.h" +#include + +static void load_collision_mesh( CollisionMesh *mesh ) +{ + mesh->num_vertices = 3 * surfaces_count; + mesh->position = malloc( sizeof( float ) * surfaces_count * 9 ); + mesh->normal = malloc( sizeof( float ) * surfaces_count * 9 ); + mesh->color = malloc( sizeof( float ) * surfaces_count * 9 ); + mesh->index = malloc( sizeof( uint16_t ) * surfaces_count * 3 ); + + for( size_t i = 0; i < surfaces_count; ++i ) + { + const struct SM64Surface *surf = &surfaces[i]; + + float x1 = mesh->position[9*i+0] = surf->vertices[0][0]; + float y1 = mesh->position[9*i+1] = surf->vertices[0][1]; + float z1 = mesh->position[9*i+2] = surf->vertices[0][2]; + float x2 = mesh->position[9*i+3] = surf->vertices[1][0]; + float y2 = mesh->position[9*i+4] = surf->vertices[1][1]; + float z2 = mesh->position[9*i+5] = surf->vertices[1][2]; + float x3 = mesh->position[9*i+6] = surf->vertices[2][0]; + float y3 = mesh->position[9*i+7] = surf->vertices[2][1]; + float z3 = mesh->position[9*i+8] = surf->vertices[2][2]; + + float nx = (y2 - y1) * (z3 - z2) - (z2 - z1) * (y3 - y2); + float ny = (z2 - z1) * (x3 - x2) - (x2 - x1) * (z3 - z2); + float nz = (x2 - x1) * (y3 - y2) - (y2 - y1) * (x3 - x2); + float mag = sqrtf(nx * nx + ny * ny + nz * nz); + nx /= mag; + ny /= mag; + nz /= mag; + + mesh->normal[9*i+0] = nx; + mesh->normal[9*i+1] = ny; + mesh->normal[9*i+2] = nz; + mesh->normal[9*i+3] = nx; + mesh->normal[9*i+4] = ny; + mesh->normal[9*i+5] = nz; + mesh->normal[9*i+6] = nx; + mesh->normal[9*i+7] = ny; + mesh->normal[9*i+8] = nz; + + for (int j=0; j<9; j++) + mesh->color[9*i+j] = (0.5 + 0.25 * 1) * (.5+.5*mesh->normal[9*i+j]); + + mesh->index[3*i+0] = 3*i+0; + mesh->index[3*i+1] = 3*i+1; + mesh->index[3*i+2] = 3*i+2; + } +} + +static void load_mario_mesh( MarioMesh *mesh, struct SM64MarioGeometryBuffers *marioGeo ) +{ + mesh->index = malloc( 3 * SM64_GEO_MAX_TRIANGLES * sizeof(uint16_t) ); + for( int i = 0; i < 3 * SM64_GEO_MAX_TRIANGLES; ++i ) + mesh->index[i] = i; + + mesh->num_vertices = 3 * SM64_GEO_MAX_TRIANGLES; +} + +static void update_mario_mesh( MarioMesh *mesh, struct SM64MarioGeometryBuffers *marioGeo ) +{ + if( mesh->index == NULL ) + load_mario_mesh( mesh, marioGeo ); + + mesh->num_vertices = 3 * marioGeo->numTrianglesUsed; + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + glVertexPointer(3, GL_FLOAT, 0, marioGeo->position); + glNormalPointer(GL_FLOAT, 0, marioGeo->normal); + glColorPointer(3, GL_FLOAT, 0, marioGeo->color); + glTexCoordPointer(2, GL_FLOAT, 0, marioGeo->uv); +} + +static void gl20_init(RenderState *renderState, uint8_t *marioTexture) +{ + load_collision_mesh( &renderState->collision ); + + glEnable( GL_CULL_FACE ); + glCullFace( GL_BACK ); + glClearColor( 0.2f, 0.2f, 0.2f, 1.0f ); + glDepthMask( GL_TRUE ); + glDepthFunc( GL_LEQUAL ); + glEnable( GL_DEPTH_TEST ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + glEnable( GL_BLEND ); + glColor4f(1,1,1,1); + + glGenTextures( 1, &renderState->mario_texture ); + glBindTexture( GL_TEXTURE_2D, renderState->mario_texture ); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SM64_TEXTURE_WIDTH, SM64_TEXTURE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, marioTexture); +} + +static void gl20_draw(RenderState *renderState, const vec3 camPos, const struct SM64MarioState *marioState, struct SM64MarioGeometryBuffers *marioGeo) +{ + mat4 model, view, projection; + glm_perspective( 45.0f, (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, 100.0f, 20000.0f, projection ); + glm_translate( view, (float*)camPos ); + glm_lookat( (float*)camPos, (float*)marioState->position, (vec3){0,1,0}, view ); + glm_mat4_identity( model ); + + glMatrixMode(GL_PROJECTION); + glLoadMatrixf((GLfloat*)projection); + + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf((GLfloat*)view); + + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + + // draw world + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, renderState->collision.position); + glNormalPointer(GL_FLOAT, 0, renderState->collision.normal); + glColorPointer(3, GL_FLOAT, 0, renderState->collision.color); + glDrawElements(GL_TRIANGLES, renderState->collision.num_vertices, GL_UNSIGNED_SHORT, renderState->collision.index); + + // create lighting on the scene + GLfloat light_position[] = { camPos[0], camPos[1], camPos[2], 1 }; + GLfloat light_diffuse[] = { 0.6f, 0.6f, 0.6f, 1 }; + GLfloat light_model[] = { 0.5f, 0.5f, 0.5f, 1 }; + glLightfv(GL_LIGHT0, GL_POSITION, light_position); + glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, light_model); + glShadeModel(GL_SMOOTH); + glEnable(GL_COLOR_MATERIAL); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + + // first, draw geometry without Mario's texture. + update_mario_mesh( &renderState->mario, marioGeo ); + uint32_t triangleSize = renderState->mario.num_vertices; + + glDrawElements(GL_TRIANGLES, triangleSize, GL_UNSIGNED_SHORT, renderState->mario.index); + + // now disable the color array and enable the texture. + glDisableClientState(GL_COLOR_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, renderState->mario_texture); + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + + glDrawElements(GL_TRIANGLES, triangleSize, GL_UNSIGNED_SHORT, renderState->mario.index); + + glDisable(GL_TEXTURE_2D); + glDisable(GL_LIGHTING); +} + +struct Renderer gl20_renderer = { + gl20_init, + gl20_draw +}; diff --git a/test/gl20/gl20_renderer.h b/test/gl20/gl20_renderer.h new file mode 100644 index 0000000..6b5afd2 --- /dev/null +++ b/test/gl20/gl20_renderer.h @@ -0,0 +1,6 @@ +#ifndef GL20_RENDERER_H +#define GL20_RENDERER_H + +extern struct Renderer gl20_renderer; + +#endif diff --git a/test/gl33core/gl33core_renderer.c b/test/gl33core/gl33core_renderer.c new file mode 100644 index 0000000..fb6d24f --- /dev/null +++ b/test/gl33core/gl33core_renderer.c @@ -0,0 +1,313 @@ +#include "gl33core_renderer.h" + +#include + +#include "../../src/libsm64.h" +#include "../renderer.h" +#include "../context.h" +#include "../cglm.h" +#include "../level.h" + +static const char *MARIO_SHADER = +"\n uniform mat4 view;" +"\n uniform mat4 projection;" +"\n uniform sampler2D marioTex;" +"\n " +"\n v2f vec3 v_color;" +"\n v2f vec3 v_normal;" +"\n v2f vec3 v_light;" +"\n v2f vec2 v_uv;" +"\n " +"\n #ifdef VERTEX" +"\n " +"\n layout(location = 0) in vec3 position;" +"\n layout(location = 1) in vec3 normal;" +"\n layout(location = 2) in vec3 color;" +"\n layout(location = 3) in vec2 uv;" +"\n " +"\n void main()" +"\n {" +"\n v_color = color;" +"\n v_normal = normal;" +"\n v_light = transpose( mat3( view )) * normalize( vec3( 1 ));" +"\n v_uv = uv;" +"\n " +"\n gl_Position = projection * view * vec4( position, 1. );" +"\n }" +"\n " +"\n #endif" +"\n #ifdef FRAGMENT" +"\n " +"\n out vec4 color;" +"\n " +"\n void main() " +"\n {" +"\n float light = .5 + .5 * clamp( dot( v_normal, v_light ), 0., 1. );" +"\n vec4 texColor = texture2D( marioTex, v_uv );" +"\n vec3 mainColor = mix( v_color, texColor.rgb, texColor.a ); // v_uv.x >= 0. ? texColor.a : 0. );" +"\n color = vec4( mainColor * light, 1 );" +"\n }" +"\n " +"\n #endif" +; +static const char *WORLD_SHADER = +"\n uniform mat4 model;" +"\n uniform mat4 view;" +"\n uniform mat4 projection;" +"\n uniform sampler2D tex;" +"\n " +"\n v2f vec3 v_normal;" +"\n v2f vec3 v_worldPos;" +"\n " +"\n #ifdef VERTEX" +"\n " +"\n layout(location = 0) in vec3 position;" +"\n layout(location = 1) in vec3 normal;" +"\n " +"\n void main()" +"\n {" +"\n v_normal = inverse(mat3(model)) * normal;" +"\n vec4 worldPos4 = model * vec4(position, 1.);" +"\n v_worldPos = worldPos4.xyz;" +"\n gl_Position = projection * view * worldPos4;" +"\n }" +"\n " +"\n #endif" +"\n #ifdef FRAGMENT" +"\n " +"\n vec3 tri( vec3 x )" +"\n {" +"\n return abs(x-floor(x)-.5);" +"\n } " +"\n float surfFunc( vec3 p )" +"\n {" +"\n float n = dot(tri(p*.15 + tri(p.yzx*.075)), vec3(.444));" +"\n p = p*1.5773 - n;" +"\n p.yz = vec2(p.y + p.z, p.z - p.y) * .866;" +"\n p.xz = vec2(p.x + p.z, p.z - p.x) * .866;" +"\n n += dot(tri(p*.225 + tri(p.yzx*.1125)), vec3(.222)); " +"\n return abs(n-.5)*1.9 + (1.-abs(sin(n*9.)))*.05;" +"\n }" +"\n " +"\n const vec3 light_x = vec3(-1.0, 0.4, 0.9);" +"\n " +"\n out vec4 color;" +"\n " +"\n void main() " +"\n {" +"\n float surfy = surfFunc( v_worldPos / 50. );" +"\n float brightness = smoothstep( .2, .3, surfy );" +"\n " +"\n color = vec4( (0.5 + 0.25 * brightness) * (.5+.5*v_normal), 1 );" +"\n }" +"\n " +"\n #endif" +; + +static void load_collision_mesh( CollisionMesh *mesh ) +{ + mesh->num_vertices = 3 * surfaces_count; + mesh->position = malloc( sizeof( float ) * surfaces_count * 9 ); + mesh->normal = malloc( sizeof( float ) * surfaces_count * 9 ); + mesh->index = malloc( sizeof( uint16_t ) * surfaces_count * 3 ); + + for( size_t i = 0; i < surfaces_count; ++i ) + { + const struct SM64Surface *surf = &surfaces[i]; + + float x1 = mesh->position[9*i+0] = surf->vertices[0][0]; + float y1 = mesh->position[9*i+1] = surf->vertices[0][1]; + float z1 = mesh->position[9*i+2] = surf->vertices[0][2]; + float x2 = mesh->position[9*i+3] = surf->vertices[1][0]; + float y2 = mesh->position[9*i+4] = surf->vertices[1][1]; + float z2 = mesh->position[9*i+5] = surf->vertices[1][2]; + float x3 = mesh->position[9*i+6] = surf->vertices[2][0]; + float y3 = mesh->position[9*i+7] = surf->vertices[2][1]; + float z3 = mesh->position[9*i+8] = surf->vertices[2][2]; + + float nx = (y2 - y1) * (z3 - z2) - (z2 - z1) * (y3 - y2); + float ny = (z2 - z1) * (x3 - x2) - (x2 - x1) * (z3 - z2); + float nz = (x2 - x1) * (y3 - y2) - (y2 - y1) * (x3 - x2); + float mag = sqrtf(nx * nx + ny * ny + nz * nz); + nx /= mag; + ny /= mag; + nz /= mag; + + mesh->normal[9*i+0] = nx; + mesh->normal[9*i+1] = ny; + mesh->normal[9*i+2] = nz; + mesh->normal[9*i+3] = nx; + mesh->normal[9*i+4] = ny; + mesh->normal[9*i+5] = nz; + mesh->normal[9*i+6] = nx; + mesh->normal[9*i+7] = ny; + mesh->normal[9*i+8] = nz; + + mesh->index[3*i+0] = 3*i+0; + mesh->index[3*i+1] = 3*i+1; + mesh->index[3*i+2] = 3*i+2; + } + + glGenVertexArrays( 1, &mesh->vao ); + glBindVertexArray( mesh->vao ); + + #define X( loc, buff, arr, type ) do { \ + glGenBuffers( 1, &buff ); \ + glBindBuffer( GL_ARRAY_BUFFER, buff ); \ + glBufferData( GL_ARRAY_BUFFER, mesh->num_vertices*sizeof( type ), arr, GL_STATIC_DRAW ); \ + glEnableVertexAttribArray( loc ); \ + glVertexAttribPointer( loc, sizeof( type ) / sizeof( float ), GL_FLOAT, GL_FALSE, sizeof( type ), NULL ); \ + } while( 0 ) + + X( 0, mesh->position_buffer, mesh->position, vec3 ); + X( 1, mesh->normal_buffer, mesh->normal, vec3 ); + + #undef X +} + +static void load_mario_mesh( MarioMesh *mesh, struct SM64MarioGeometryBuffers *marioGeo ) +{ + mesh->index = malloc( 3 * SM64_GEO_MAX_TRIANGLES * sizeof(uint16_t) ); + for( int i = 0; i < 3 * SM64_GEO_MAX_TRIANGLES; ++i ) + mesh->index[i] = i; + + mesh->num_vertices = 3 * SM64_GEO_MAX_TRIANGLES; + + glGenVertexArrays( 1, &mesh->vao ); + glBindVertexArray( mesh->vao ); + + #define X( loc, buff, arr, type ) do { \ + glGenBuffers( 1, &buff ); \ + glBindBuffer( GL_ARRAY_BUFFER, buff ); \ + glBufferData( GL_ARRAY_BUFFER, sizeof( type ) * 3 * SM64_GEO_MAX_TRIANGLES, arr, GL_DYNAMIC_DRAW ); \ + glEnableVertexAttribArray( loc ); \ + glVertexAttribPointer( loc, sizeof( type ) / sizeof( float ), GL_FLOAT, GL_FALSE, sizeof( type ), NULL ); \ + } while( 0 ) + + X( 0, mesh->position_buffer, marioGeo->position, vec3 ); + X( 1, mesh->normal_buffer, marioGeo->normal, vec3 ); + X( 2, mesh->color_buffer, marioGeo->color, vec3 ); + X( 3, mesh->uv_buffer, marioGeo->uv, vec2 ); + + #undef X +} + +static void update_mario_mesh( MarioMesh *mesh, struct SM64MarioGeometryBuffers *marioGeo ) +{ + if( mesh->index == NULL ) + load_mario_mesh( mesh, marioGeo ); + + mesh->num_vertices = 3 * marioGeo->numTrianglesUsed; + + glBindBuffer( GL_ARRAY_BUFFER, mesh->position_buffer ); + glBufferData( GL_ARRAY_BUFFER, sizeof( vec3 ) * 3 * SM64_GEO_MAX_TRIANGLES, marioGeo->position, GL_DYNAMIC_DRAW ); + glBindBuffer( GL_ARRAY_BUFFER, mesh->normal_buffer ); + glBufferData( GL_ARRAY_BUFFER, sizeof( vec3 ) * 3 * SM64_GEO_MAX_TRIANGLES, marioGeo->normal, GL_DYNAMIC_DRAW ); + glBindBuffer( GL_ARRAY_BUFFER, mesh->color_buffer ); + glBufferData( GL_ARRAY_BUFFER, sizeof( vec3 ) * 3 * SM64_GEO_MAX_TRIANGLES, marioGeo->color, GL_DYNAMIC_DRAW ); + glBindBuffer( GL_ARRAY_BUFFER, mesh->uv_buffer ); + glBufferData( GL_ARRAY_BUFFER, sizeof( vec2 ) * 3 * SM64_GEO_MAX_TRIANGLES, marioGeo->uv, GL_DYNAMIC_DRAW ); +} + +static GLuint shader_compile( const char *shaderContents, size_t shaderContentsLength, GLenum shaderType ) +{ + const GLchar *shaderDefine = shaderType == GL_VERTEX_SHADER + ? "\n#version 330\n#define VERTEX \n#define v2f out\n" + : "\n#version 330\n#define FRAGMENT\n#define v2f in \n"; + + const GLchar *shaderStrings[2] = { shaderDefine, shaderContents }; + GLint shaderStringLengths[2] = { strlen( shaderDefine ), (GLint)shaderContentsLength }; + + GLuint shader = glCreateShader( shaderType ); + glShaderSource( shader, 2, shaderStrings, shaderStringLengths ); + glCompileShader( shader ); + + GLint isCompiled; + glGetShaderiv( shader, GL_COMPILE_STATUS, &isCompiled ); + if( isCompiled == GL_FALSE ) + { + GLint maxLength; + glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &maxLength ); + char *log = (char*)malloc( maxLength ); + glGetShaderInfoLog( shader, maxLength, &maxLength, log ); + + printf( "Error in shader: %s\n%s\n%s\n", log, shaderStrings[0], shaderStrings[1] ); + exit( 1 ); + } + + return shader; +} + +static GLuint shader_load( const char *shaderContents ) +{ + GLuint result; + GLuint vert = shader_compile( shaderContents, strlen( shaderContents ), GL_VERTEX_SHADER ); + GLuint frag = shader_compile( shaderContents, strlen( shaderContents ), GL_FRAGMENT_SHADER ); + + GLuint ref = glCreateProgram(); + glAttachShader( ref, vert ); + glAttachShader( ref, frag ); + + glLinkProgram ( ref ); + glDetachShader( ref, vert ); + glDetachShader( ref, frag ); + result = ref; + + return result; +} + +static void gl33core_init(RenderState *renderState, uint8_t *marioTexture) +{ + load_collision_mesh( &renderState->collision ); + renderState->world_shader = shader_load( WORLD_SHADER ); + renderState->mario_shader = shader_load( MARIO_SHADER ); + + glEnable( GL_CULL_FACE ); + glCullFace( GL_BACK ); + glClearColor( 0.2f, 0.2f, 0.2f, 1.0f ); + glDepthMask( GL_TRUE ); + glDepthFunc( GL_LEQUAL ); + glEnable( GL_DEPTH_TEST ); + + glGenTextures( 1, &renderState->mario_texture ); + glBindTexture( GL_TEXTURE_2D, renderState->mario_texture ); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SM64_TEXTURE_WIDTH, SM64_TEXTURE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, marioTexture); +} + +static void gl33core_draw(RenderState *renderState, const vec3 camPos, const struct SM64MarioState *marioState, struct SM64MarioGeometryBuffers *marioGeo) +{ + update_mario_mesh( &renderState->mario, marioGeo ); + + mat4 model, view, projection; + glm_perspective( 45.0f, (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, 100.0f, 20000.0f, projection ); + glm_translate( view, (float*)camPos ); + glm_lookat( (float*)camPos, (float*)marioState->position, (vec3){0,1,0}, view ); + glm_mat4_identity( model ); + + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + + glUseProgram( renderState->world_shader ); + glBindVertexArray( renderState->collision.vao ); + glUniformMatrix4fv( glGetUniformLocation( renderState->world_shader, "model" ), 1, GL_FALSE, (GLfloat*)model ); + glUniformMatrix4fv( glGetUniformLocation( renderState->world_shader, "view" ), 1, GL_FALSE, (GLfloat*)view ); + glUniformMatrix4fv( glGetUniformLocation( renderState->world_shader, "projection" ), 1, GL_FALSE, (GLfloat*)projection ); + glDrawElements( GL_TRIANGLES, renderState->collision.num_vertices, GL_UNSIGNED_SHORT, renderState->collision.index ); + + glUseProgram( renderState->mario_shader ); + glActiveTexture( GL_TEXTURE0 ); + glBindTexture( GL_TEXTURE_2D, renderState->mario_texture ); + glBindVertexArray( renderState->mario.vao ); + glUniformMatrix4fv( glGetUniformLocation( renderState->mario_shader, "view" ), 1, GL_FALSE, (GLfloat*)view ); + glUniformMatrix4fv( glGetUniformLocation( renderState->mario_shader, "projection" ), 1, GL_FALSE, (GLfloat*)projection ); + glUniform1i( glGetUniformLocation( renderState->mario_shader, "marioTex" ), 0 ); + glDrawElements( GL_TRIANGLES, renderState->mario.num_vertices, GL_UNSIGNED_SHORT, renderState->mario.index ); +} + +struct Renderer gl33core_renderer = { + gl33core_init, + gl33core_draw +}; diff --git a/test/gl33core/gl33core_renderer.h b/test/gl33core/gl33core_renderer.h new file mode 100644 index 0000000..58ea14e --- /dev/null +++ b/test/gl33core/gl33core_renderer.h @@ -0,0 +1,6 @@ +#ifndef GL33CORE_RENDERER_H +#define GL33CORE_RENDERER_H + +extern struct Renderer gl33core_renderer; + +#endif diff --git a/test/renderer.h b/test/renderer.h new file mode 100644 index 0000000..f6f23fb --- /dev/null +++ b/test/renderer.h @@ -0,0 +1,57 @@ +#ifndef RENDERER_H +#define RENDERER_H + +#include +#include +#include + +#include "../src/libsm64.h" + +#include "context.h" +#include "cglm.h" + +typedef struct CollisionMesh +{ + size_t num_vertices; + float *position; + float *normal; + float *color; + uint16_t *index; + + GLuint vao; + GLuint position_buffer; + GLuint normal_buffer; +} +CollisionMesh; + +typedef struct MarioMesh +{ + size_t num_vertices; + uint16_t *index; + + GLuint vao; + GLuint position_buffer; + GLuint normal_buffer; + GLuint color_buffer; + GLuint uv_buffer; +} +MarioMesh; + +typedef struct RenderState +{ + CollisionMesh collision; + MarioMesh mario; + GLuint world_shader; + GLuint mario_shader; + GLuint mario_texture; +} +RenderState; + + +struct Renderer +{ + void (*init)(RenderState *renderState, uint8_t *marioTexture); + void (*draw)(RenderState *renderState, const vec3 camPos, const struct SM64MarioState *marioState, struct SM64MarioGeometryBuffers *marioGeo); +}; + +#endif