diff options
Diffstat (limited to '09-september/tomcat/renderer/renderer.c')
| -rw-r--r-- | 09-september/tomcat/renderer/renderer.c | 430 |
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, ¢er, &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) ); +} |
