aboutsummaryrefslogtreecommitdiff
path: root/09-september/tomcat/renderer/renderer.c
diff options
context:
space:
mode:
authorThomas Guillermo Albers Raviola <thomas@thomaslabs.org>2026-01-16 23:02:32 +0100
committerThomas Guillermo Albers Raviola <thomas@thomaslabs.org>2026-01-16 23:02:32 +0100
commit6b8af9cf83851c075c6c9514b1deaa931c2b19a4 (patch)
tree428986b49c32e21d3f7a3c2dfa41858ae0153209 /09-september/tomcat/renderer/renderer.c
Initial commit
Diffstat (limited to '09-september/tomcat/renderer/renderer.c')
-rw-r--r--09-september/tomcat/renderer/renderer.c430
1 files changed, 430 insertions, 0 deletions
diff --git a/09-september/tomcat/renderer/renderer.c b/09-september/tomcat/renderer/renderer.c
new file mode 100644
index 0000000..307c543
--- /dev/null
+++ b/09-september/tomcat/renderer/renderer.c
@@ -0,0 +1,430 @@
+#include "renderer.h"
+#include "../util/util_time.h"
+#include "../util/util.h"
+
+#include <string.h>
+
+#define MAX_LIGHTS 4
+
+Renderer render;
+
+void Render_Init(Window *window)
+{
+ memset( &render, 0, sizeof(Renderer) );
+
+ if(glewInit() != GLEW_OK)
+ Util_FatalError("Glew could no be started!");
+
+ strcpy( render.info.version, (const char *) glGetString(GL_VERSION) );
+ strcpy( render.info.vendor, (const char *) glGetString(GL_VENDOR) );
+ strcpy( render.info.shading_version, (const char *) glGetString(GL_SHADING_LANGUAGE_VERSION) );
+
+ fprintf(stderr, "%s\n", render.info.version);
+
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+ glClearColor(0.0f, 0.0f, 0.39f, 1.0f);
+
+ //glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
+
+ render.default_quad = mesh_make_quad();
+
+ render.default_shader = shader_new("pass_shader", "resources/shaders/passShader.vert",
+ "resources/shaders/passShader.frag");
+ render.default_shader->totalTransform = shader_get_uniform_location(render.default_shader, "M_MVP");
+ render.default_shader->Texture = shader_get_uniform_location(render.default_shader, "Texture");
+
+
+ glBindVertexArray(render.default_quad->vao);
+ glCreateBuffers(1, &render.instance_vbo);
+
+ glBindBuffer(GL_ARRAY_BUFFER, render.instance_vbo);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 18 * 10000, NULL, GL_STREAM_DRAW);
+
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 18 * sizeof(GLfloat), (const void *)(sizeof(float) * 0));
+ glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 18 * sizeof(GLfloat), (const void *)(sizeof(float) * 2) );
+ glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 18 * sizeof(GLfloat), (const void *)(sizeof(float) * 6) );
+ glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, 18 * sizeof(GLfloat), (const void *)(sizeof(float) * 10) );
+ glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, 18 * sizeof(GLfloat), (const void *)(sizeof(float) * 14) );
+
+ glEnableVertexAttribArray(1);
+ glEnableVertexAttribArray(2);
+ glEnableVertexAttribArray(3);
+ glEnableVertexAttribArray(4);
+ glEnableVertexAttribArray(5);
+
+ glVertexAttribDivisor(1, 1);
+ glVertexAttribDivisor(2, 1);
+ glVertexAttribDivisor(3, 1);
+ glVertexAttribDivisor(4, 1);
+ glVertexAttribDivisor(5, 1);
+
+ glBindVertexArray(0);
+
+ render.window = window;
+ render.shadow_width = 1024;
+ render.shadow_height = 1024;
+
+ /** TEMP **/
+
+ Vec3 center = {0.0f, 0.0f, 0.0f};
+ Vec3 up = {0.0f, 1.0f, 0.0f};
+ render.inv_light_dir = (Vec3){11.54f, 66.74f, 9.93f};
+ Mat4 shadow_ortho_mat = mat4_orthographic(-100.0f, 100.0f, -100.0f, 100.0f, -100.0f, 200.0f);
+ Mat4 shadow_view_mat = mat4_lookAt(&render.inv_light_dir, &center, &up);
+ Mat4 shadow_model;
+ mat4_identity(&shadow_model);
+
+ render.shadow_mvp = mat4_mul(&shadow_ortho_mat, &shadow_view_mat);
+ render.shadow_mvp = mat4_mul(&render.shadow_mvp, &shadow_model);
+
+ render.shadow_shader = shader_new("s_shader", "resources/shaders/shadow_shader.vert",
+ "resources/shaders/shadow_shader.frag");
+ render.shadow_shader->totalTransform = shader_get_uniform_location(render.shadow_shader, "M_MVP");
+
+ /** TEMP **/
+
+ glGenFramebuffers(1, &render.shadow_fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, render.shadow_fbo);
+
+
+ glGenTextures(1, &render.shadow_map);
+ glBindTexture(GL_TEXTURE_2D, render.shadow_map);
+
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, render.shadow_width,
+ render.shadow_height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glGenTextures(1, &render.shadow_color);
+ glBindTexture(GL_TEXTURE_2D, render.shadow_color);
+
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, render.shadow_width,
+ render.shadow_height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, render.shadow_map, 0);
+ glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, render.shadow_color, 0);
+
+ //glDrawBuffer(GL_NONE);
+ GLenum draw_buffer = GL_COLOR_ATTACHMENT0;
+ glDrawBuffers(1, &draw_buffer);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ Util_FatalError("Could not create a frame buffer object\n");
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glViewport(0, 0, render.window->Width, render.window->Height);
+
+ Util_CheckGLError();
+}
+
+void Render_BeginFrame()
+{
+ glClearColor(0.0f, 0.0f, 0.39f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+
+ glBindFramebuffer(GL_FRAMEBUFFER, render.shadow_fbo);
+ glViewport(0, 0, render.shadow_width, render.shadow_height);
+ glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+}
+
+void Render_LoadLights(Shader *s, const Light *lights, int n)
+{
+ Vec3 light_positions[MAX_LIGHTS];
+ Vec4 light_colors[MAX_LIGHTS];
+ Vec3 attenuation[MAX_LIGHTS];
+ int i;
+
+ /* Default light in case we are not given enough lights (n < 4) */
+ static const Light defaultLight =
+ {
+ { 0.0f, 0.0f, 0.0f },
+ { 0.0f, 0.0f, 0.0f, 0.0f },
+ { 1.0f, 0.0f, 0.0f }
+ };
+
+ for(i = 0; i < MAX_LIGHTS; i++)
+ {
+ if(i < n)
+ {
+ light_positions[i] = lights[i].position;
+ light_colors[i] = lights[i].color;
+ attenuation[i] = lights[i].attenuation;
+ }
+ else
+ {
+ light_positions[i] = defaultLight.position;
+ light_colors[i] = defaultLight.color;
+ attenuation[i] = defaultLight.attenuation;
+ }
+
+ }
+
+ glUniform3fv(s->lightPosition, MAX_LIGHTS, (float *)light_positions);
+ glUniform4fv(s->lightColor, MAX_LIGHTS, (float *)light_colors);
+ glUniform3fv(s->lightAttenuation, MAX_LIGHTS, (float *)attenuation);
+}
+
+/******************************************************************************
+* *
+* Function Name: Render_DrawEntity *
+* *
+* Specific shader layout *
+* -> extra0 texture atlas number of rows *
+* -> extra1 texture atlas xy offset *
+* *
+*******************************************************************************/
+
+void Render_DrawEntity(Shader *s, Mat4 *projectedViewMatrix, Entity *entity)
+{
+ Mesh *mesh = entity->model->mesh;
+ /*We need the model to world matrix in our shader in order to rotate the normals*/
+ Mat4 modelTransform = Entity_GetModelTransform(entity);
+ Mat4 totalMatrix;
+
+ /** TEMP **/
+
+ /** TEMP**/
+
+ glUniformMatrix4fv(s->modelToWorld, 1, GL_FALSE, modelTransform.data);
+
+ totalMatrix = mat4_mul(projectedViewMatrix, &modelTransform);
+ glUniformMatrix4fv(s->totalTransform, 1, GL_FALSE, totalMatrix.data);
+
+ glUniform1i(s->Texture, 0);
+ texture_bind(entity->texture, 0);
+
+ glUniform1f(s->extra0, entity->texture->number_of_rows);
+ Vec2 tex_offset = Entity_GetTexOffset(entity);
+ glUniform2fv(s->extra1, 1, (float *)&tex_offset);
+
+ glBindVertexArray(mesh->vao);
+ glDrawElements(GL_TRIANGLES, mesh->num_indices, GL_UNSIGNED_SHORT, NULL);
+ glBindVertexArray(0);
+}
+
+/******************************************************************************
+* *
+* Function Name: Render_DrawTerrain *
+* *
+* Specific shader layout *
+* -> extra0 Texture_Background *
+* -> extra1 Texture_R *
+* -> extra2 Texture_G *
+* -> extra3 Texture_B *
+* -> extra4 Texture_BlendMap *
+* *
+*******************************************************************************/
+
+void Render_DrawTerrain(Shader *s, Mat4 *projectedViewMatrix, Terrain *terrain)
+{
+ Mat4 totalMatrix;
+ Mat4 modelTransform;
+
+ /* We need the model to world matrix in our shader in order to rotate the normals */
+ modelTransform = mat4_translate(&terrain->position);
+ glUniformMatrix4fv(s->modelToWorld, 1, GL_FALSE, modelTransform.data);
+
+ totalMatrix = mat4_mul(projectedViewMatrix, &modelTransform);
+ glUniformMatrix4fv(s->totalTransform, 1, GL_FALSE, totalMatrix.data);
+
+ /** Set textures for the terrain **/
+
+ glUniform1i(s->extra0, 0);
+ glUniform1i(s->extra1, 1);
+ glUniform1i(s->extra2, 2);
+ glUniform1i(s->extra3, 3);
+ glUniform1i(s->extra4, 4);
+
+ texture_bind(terrain->textures.texture[0], 0);
+ texture_bind(terrain->textures.texture[1], 1);
+ texture_bind(terrain->textures.texture[2], 2);
+ texture_bind(terrain->textures.texture[3], 3);
+ texture_bind(terrain->blendmap, 4);
+
+ /**********************************/
+
+ glBindVertexArray(terrain->mesh->vao);
+ glDrawElements(GL_TRIANGLES, terrain->mesh->num_indices, GL_UNSIGNED_SHORT, NULL);
+ glBindVertexArray(0);
+}
+
+void Render_DrawSky(Shader *s, Mat4 *viewMatrix, Mat4 *projectionMatrix, Skybox *sky)
+{
+ Mat4 myViewMatrix = *viewMatrix;
+ Mat4 totalTransform;
+ Mat4 rotateMatrix = mat4_rotate_y(sky->rotation);
+
+ sky->rotation += SKYBOX_ROTATION_SPEED * Time_GetFrameTime();
+
+ /* We don't want to move the skybox around (We want it to stay with the camera in the midle),
+ just rotate it with the camera so we remove the translations components of the matrix */
+
+ myViewMatrix.data[0 + 3 * 4] = 0.0f;
+ myViewMatrix.data[1 + 3 * 4] = 0.0f;
+ myViewMatrix.data[2 + 3 * 4] = 0.0f;
+
+ myViewMatrix = mat4_mul(&myViewMatrix, &rotateMatrix);
+ totalTransform = mat4_mul(projectionMatrix, &myViewMatrix);
+
+ glUniformMatrix4fv(s->totalTransform, 1, GL_FALSE, totalTransform.data );
+
+ texture_bind(sky->texture, 0);
+ glUniform1i(s->Texture, 0);
+
+ glBindVertexArray(sky->cube->vao);
+ glDrawArrays(GL_TRIANGLES, 0, 36);
+ glBindVertexArray(0);
+}
+
+/******************************************************************************
+* *
+* Function Name: Render_DrawParticles *
+* *
+* Specific shader layout *
+* -> extra0 texture atlas number of rows *
+* -> extra1 texture atlas xy offset *
+* *
+*******************************************************************************/
+
+void Render_DrawParticles(Shader *s, Mat4 *viewMatrix, Mat4 *projectionMatrix)
+{
+ Mat4 modelTransform, modelViewMatrix, totalTransform, scale;
+ Particle *c = NULL;
+ ParticleSystem *sys = NULL;
+
+ int num_particles = 0;
+ int i, j;
+
+
+ glEnable(GL_BLEND);
+ glDepthMask(GL_FALSE);
+ glUniform1i(s->Texture, 0);
+
+ for(i = 0; i < particles.num_systems; i++)
+ {
+ sys = particles.systems[i];
+
+ texture_bind(sys->texture, 0);
+ glUniform1f(s->extra0, sys->texture->number_of_rows);
+
+ /* Orphane the buffer */
+ glBindBuffer(GL_ARRAY_BUFFER, render.instance_vbo);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 18 * MAX_PARTICLES_PER_SYSTEM, NULL, GL_STREAM_DRAW);
+
+ if(sys->additive)
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ else
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ for(j = 0; j < sys->num_particles; j++)
+ {
+ c = &sys->particles[j];
+
+ modelTransform = mat4_translate(&c->position);
+ scale = mat4_scale(c->scale, c->scale, c->scale);
+ modelTransform = mat4_mul(&modelTransform, &scale);
+ /*
+ We eliminate the rotation from the view matrix so the particle is always facing the camera,
+ for this we add the transposed matrix from the rotation part of the viewmatrx and put it
+ on the model transform matrix
+ */
+ modelTransform.data[0] = viewMatrix->data[0];
+ modelTransform.data[4] = viewMatrix->data[1];
+ modelTransform.data[8] = viewMatrix->data[2];
+ modelTransform.data[1] = viewMatrix->data[4];
+ modelTransform.data[5] = viewMatrix->data[5];
+ modelTransform.data[9] = viewMatrix->data[6];
+ modelTransform.data[2] = viewMatrix->data[8];
+ modelTransform.data[6] = viewMatrix->data[9];
+ modelTransform.data[10] = viewMatrix->data[10];
+
+ modelViewMatrix = mat4_mul(viewMatrix, &modelTransform);
+ totalTransform = mat4_mul(projectionMatrix, &modelViewMatrix);
+
+ /* Load the texture atlas coods and MVP matrix */
+ glBufferSubData(GL_ARRAY_BUFFER, num_particles * sizeof(GLfloat), sizeof(Vec2), &c->tex_offset);
+ glBufferSubData(GL_ARRAY_BUFFER, (num_particles + 2) * sizeof(GLfloat), sizeof(Mat4), totalTransform.data);
+
+ num_particles += 18;
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glBindVertexArray(render.default_quad->vao);
+ glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, num_particles / 18);
+ }
+
+ glBindVertexArray(0);
+
+ glDepthMask(GL_TRUE);
+ glDisable(GL_BLEND);
+}
+
+void Render_EndFrame()
+{
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glViewport(0, 0, render.window->Width, render.window->Height);
+}
+
+void Render_Shutdown()
+{
+ int i;
+
+ glDeleteTextures(1, &render.shadow_map);
+ glDeleteFramebuffers(1, &render.shadow_fbo);
+
+ glDeleteBuffers(1, &render.instance_vbo);
+
+ /* Destroy all created textures */
+ for(i = 0; i < render.num_textures; i++)
+ {
+ texture_purge( render.textures[i] );
+ free(render.textures[i]);
+ }
+
+ /* Destroy all created models */
+ for(i = 0; i < render.num_models; i++)
+ {
+ model_purge(render.models[i]);
+ free(render.models[i]);
+ }
+
+ for(i = 0; i < render.num_meshes; i++)
+ {
+ mesh_purge(render.meshes[i]);
+ free(render.meshes[i]);
+ }
+
+ /* Destroy all created shaders */
+ for(i = 0; i < render.num_shaders; i++)
+ {
+ shader_purge(render.shaders[i]);
+ free(render.shaders[i]);
+ }
+
+ /* Just for checking */
+ printf("%d textures were deleted!\n", render.num_textures);
+ printf("%d models were deleted!\n", render.num_models);
+ printf("%d shaders were deleted!\n", render.num_shaders);
+ printf("%d meshes were deleted!\n", render.num_meshes);
+
+ /* Clear everything */
+ memset( &render, 0, sizeof(Renderer) );
+}