A 3d fps game made in OpenGL
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
Symmetry/src/renderer.c

199 lines
5.9 KiB

#include "renderer.h"
#include "GLFW/glfw3.h"
#include "log.h"
#include "camera.h"
#include "model.h"
#include "texture.h"
#include "framebuffer.h"
#include "array.h"
#include "geometry.h"
#include "shader.h"
#include "num_types.h"
#include "window_system.h"
static int def_fbo = -1;
static int def_render_tex = -1;
static int def_depth_tex = -1;
static int quad_geo = -1;
static int fbo_shader = -1;
void on_framebuffer_size_change(GLFWwindow* window, int width, int height);
void renderer_init(GLFWwindow* window)
{
glClearColor(0.3f, 0.6f, 0.9f, 1.0f);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glfwSetFramebufferSizeCallback(window, on_framebuffer_size_change);
/* Quad geometry for final render */
vec3* vertices = array_new(vec3);
vec2* uvs = array_new(vec2);
vec3* normals = array_new(vec3);
uint* indices = array_new(uint);
vec3 temp_v3;
vec2 temp_v2;
/* Vertices */
temp_v3.x = -1; temp_v3.y = -1; temp_v3.z = 0; array_push(vertices, temp_v3, vec3);
temp_v3.x = 1; temp_v3.y = -1; temp_v3.z = 0; array_push(vertices, temp_v3, vec3);
temp_v3.x = 1; temp_v3.y = 1; temp_v3.z = 0; array_push(vertices, temp_v3, vec3);
temp_v3.x = -1; temp_v3.y = 1; temp_v3.z = 0; array_push(vertices, temp_v3, vec3);
/* Normals */
temp_v3.x = 0; temp_v3.y = 1; temp_v3.z = 0; array_push(normals, temp_v3, vec3);
temp_v3.x = 0; temp_v3.y = 1; temp_v3.z = 0; array_push(normals, temp_v3, vec3);
/* Uvs */
temp_v2.x = 0; temp_v2.y = 0; array_push(uvs, temp_v2, vec2);
temp_v2.x = 1; temp_v2.y = 0; array_push(uvs, temp_v2, vec2);
temp_v2.x = 1; temp_v2.y = 1; array_push(uvs, temp_v2, vec2);
temp_v2.x = 0; temp_v2.y = 1; array_push(uvs, temp_v2, vec2);
/* Indices */
array_push(indices, 0, uint); array_push(indices, 1, uint); array_push(indices, 2, uint);
array_push(indices, 2, uint); array_push(indices, 3, uint); array_push(indices, 0, uint);
quad_geo = geom_create("Quad", vertices, uvs, normals, indices, NULL);
array_free(vertices);
array_free(uvs);
array_free(normals);
array_free(indices);
/* Textues for default fbo */
int width = -1, height = -1;
window_get_size(&width, &height);
def_render_tex = texture_create("def_render_texture",
TU_DIFFUSE,
width, height,
GL_RGBA,
GL_RGBA8,
GL_UNSIGNED_BYTE,
NULL);
texture_set_param(def_render_tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
texture_set_param(def_render_tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
texture_set_param(def_render_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
texture_set_param(def_render_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
def_depth_tex = texture_create("def_depth_texture",
TU_SHADOWMAP1,
width, height,
GL_DEPTH_COMPONENT,
GL_DEPTH_COMPONENT,
GL_UNSIGNED_BYTE,
NULL);
texture_set_param(def_depth_tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
texture_set_param(def_depth_tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
texture_set_param(def_depth_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
texture_set_param(def_depth_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
texture_set_param(def_depth_tex, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
texture_set_param(def_depth_tex, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
def_fbo = framebuffer_create(width, height, 0, 1);
framebuffer_set_texture(def_fbo, def_render_tex, GL_COLOR_ATTACHMENT0);
framebuffer_set_texture(def_fbo, def_depth_tex, GL_DEPTH_ATTACHMENT);
fbo_shader = shader_create("fbo.vert", "fbo.frag");
}
void renderer_draw(void)
{
struct Camera* camera_list = camera_get_all();
for(int i = 0; i < array_len(camera_list); i++)
{
struct Camera* camera = &camera_list[i];
if(camera->node < 0)
continue;
int fbo = camera->fbo == -1 ? def_fbo : camera->fbo;
framebuffer_bind(fbo);
{
glViewport(0, 0, framebuffer_get_width(fbo), framebuffer_get_height(fbo));
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glDepthFunc(GL_LEQUAL);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glClearColor(camera->clear_color.x,
camera->clear_color.y,
camera->clear_color.z,
camera->clear_color.w);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
model_render_all(camera);
glDisable(GL_BLEND);
}
framebuffer_unbind();
}
int width, height;
window_get_size(&width, &height);
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
shader_bind(fbo_shader);
struct Camera* primary_camera = camera_get_primary();
texture_bind(primary_camera->render_tex);
geom_render(quad_geo);
texture_unbind(def_render_tex);
shader_unbind();
}
void renderer_cleanup(void)
{
geom_remove(quad_geo);
framebuffer_remove(def_fbo);
texture_remove(def_render_tex);
texture_remove(def_depth_tex);
}
void on_framebuffer_size_change(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
struct Camera* camera = camera_get(0);
float aspect = (float)width / (float)height;
camera->aspect_ratio = aspect > 0.f ? aspect : 4.f / 3.f;
camera_update_proj(camera);
}
void renderer_set_clearcolor(float red, float green, float blue, float alpha)
{
glClearColor(red, green, blue, alpha);
}
int renderer_check_glerror(const char* context)
{
int error = 1;
GLenum error_code = glGetError();
const char* errorString = "No Error";
switch(error_code)
{
case GL_INVALID_OPERATION:
errorString = "Invalid Operation";
break;
case GL_NO_ERROR:
errorString = "No Error";
break;
case GL_INVALID_ENUM:
errorString = "Invalid ENUM";
break;
case GL_INVALID_VALUE:
errorString = "Invalid Value";
break;
case GL_INVALID_FRAMEBUFFER_OPERATION:
errorString = "Invalid FrameBuffer Operation";
break;
case GL_OUT_OF_MEMORY:
errorString = "Out of Memory";
break;
case GL_STACK_UNDERFLOW:
errorString = "Stack Underflow";
break;
case GL_STACK_OVERFLOW:
errorString = "Stack Overflow";
break;
}
if(error_code != GL_NO_ERROR)
log_error(context, errorString);
else
error = 0;
return error;
}