Compare commits

..

4 Commits

22 changed files with 1982 additions and 2141 deletions

View File

@ -1,9 +1,9 @@
#!/bin/bash #!/bin/bash
CC=clang CC=clang
CFLAGS="-g -c -Wall -Isrc/glad/include" CFLAGS="-O3 -c -Wall -Isrc/glad/include"
CXX=clang++ CXX=clang++
CXXFLAGS="-g -Wall -std=c++20 $(pkg-config --cflags sdl2) -Isrc/glad/include -Isrc/glm -Isrc/assimp/include -Isrc/assimp/build/include" CXXFLAGS="-O3 -Wall -std=c++20 $(pkg-config --cflags sdl2) -Isrc/glad/include -Isrc/glm -Isrc/assimp/include -Isrc/assimp/build/include"
LIBS="$(pkg-config --libs sdl2) -ldl -lz -lminizip -Lsrc/assimp/build/lib/ -lassimp" LIBS="$(pkg-config --libs sdl2) -ldl -lz -lminizip -Lsrc/assimp/build/lib/ -lassimp"
GLAD_SRC="src/glad/src/glad.c" GLAD_SRC="src/glad/src/glad.c"
GLAD_OBJ="glad.o" GLAD_OBJ="glad.o"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 723 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 462 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 588 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 525 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 338 KiB

File diff suppressed because it is too large Load Diff

View File

@ -35,40 +35,33 @@ struct SpotLight {
float outer_cutoff; float outer_cutoff;
}; };
in VS_OUT { in vec3 vert_normal;
vec3 vert_normal; in vec3 frag_position;
vec3 frag_position; in vec2 uv_coords;
vec2 uv_coords;
} fs_in; out vec4 color;
uniform Material material; uniform Material material;
uniform DirLight directional_light; uniform DirLight directional_light;
uniform PointLight point_lights[POINT_LIGHT_COUNT]; uniform PointLight point_lights[POINT_LIGHT_COUNT];
uniform SpotLight spot_light; uniform SpotLight spot_light;
uniform vec3 camera_position;
layout (std140) uniform Common {
mat4 projection;
mat4 view;
vec3 camera_position;
};
vec3 calc_dir_light(DirLight light, vec3 normal, vec3 view_direction); vec3 calc_dir_light(DirLight light, vec3 normal, vec3 view_direction);
vec3 calc_point_light(PointLight light, vec3 normal, vec3 frag_position, vec3 view_direction); vec3 calc_point_light(PointLight light, vec3 normal, vec3 frag_position, vec3 view_direction);
vec3 calc_spot_light(SpotLight light, vec3 normal, vec3 frag_position, vec3 view_direction); vec3 calc_spot_light(SpotLight light, vec3 normal, vec3 frag_position, vec3 view_direction);
out vec4 color;
void main() { void main() {
vec3 normal = normalize(fs_in.vert_normal); vec3 normal = normalize(vert_normal);
vec3 view_direction = normalize(fs_in.frag_position - camera_position); vec3 view_direction = normalize(camera_position - frag_position);
vec3 result = calc_dir_light(directional_light, normal, view_direction); vec3 result = calc_dir_light(directional_light, normal, view_direction);
for (int i = 0; i < POINT_LIGHT_COUNT; ++i) { for (int i = 0; i < POINT_LIGHT_COUNT; ++i) {
result += calc_point_light(point_lights[i], normal, fs_in.frag_position, view_direction); result += calc_point_light(point_lights[i], normal, frag_position, view_direction);
} }
result += calc_spot_light(spot_light, normal, fs_in.frag_position, view_direction); result += calc_spot_light(spot_light, normal, frag_position, view_direction);
color = vec4(result, 1.0); color = vec4(result, 1.0);
}; };
@ -77,11 +70,11 @@ vec3 calc_dir_light(DirLight light, vec3 normal, vec3 view_direction) {
vec3 light_direction = normalize(-light.direction); vec3 light_direction = normalize(-light.direction);
vec3 reflect_direction = reflect(-light_direction, normal); vec3 reflect_direction = reflect(-light_direction, normal);
float diff = max(dot(normal, light_direction), 0.0); float diff = max(dot(normal, light_direction), 0.0);
vec3 diff_tex = vec3(texture(material.diffuse1, fs_in.uv_coords)); vec3 diff_tex = vec3(texture(material.diffuse1, uv_coords));
float spec = pow(max(dot(reflect_direction, view_direction), 0.0), material.shininess); float spec = pow(max(dot(reflect_direction, view_direction), 0.0), material.shininess);
vec3 ambient = light.ambient * diff_tex; vec3 ambient = light.ambient * diff_tex;
vec3 diffuse = light.diffuse * (diff * diff_tex); vec3 diffuse = light.diffuse * (diff * diff_tex);
vec3 specular = light.specular * (spec * vec3(texture(material.specular1, fs_in.uv_coords))); vec3 specular = light.specular * (spec * vec3(texture(material.specular1, uv_coords)));
return ambient + diffuse + specular; return ambient + diffuse + specular;
} }
@ -92,11 +85,11 @@ vec3 calc_point_light(PointLight light, vec3 normal, vec3 frag_position, vec3 vi
float distance = length(light.position - frag_position); float distance = length(light.position - frag_position);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance)); float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
float diff = max(dot(normal, light_direction), 0.0); float diff = max(dot(normal, light_direction), 0.0);
vec3 diff_tex = vec3(texture(material.diffuse1, fs_in.uv_coords)); vec3 diff_tex = vec3(texture(material.diffuse1, uv_coords));
float spec = pow(max(dot(reflect_direction, view_direction), 0.0), material.shininess); float spec = pow(max(dot(reflect_direction, view_direction), 0.0), material.shininess);
vec3 ambient = light.ambient * diff_tex * attenuation; vec3 ambient = light.ambient * diff_tex * attenuation;
vec3 diffuse = light.diffuse * (diff * diff_tex) * attenuation; vec3 diffuse = light.diffuse * (diff * diff_tex) * attenuation;
vec3 specular = light.specular * (spec * vec3(texture(material.specular1, fs_in.uv_coords))) * attenuation; vec3 specular = light.specular * (spec * vec3(texture(material.specular1, uv_coords))) * attenuation;
return ambient + diffuse + specular; return ambient + diffuse + specular;
} }
@ -109,10 +102,10 @@ vec3 calc_spot_light(SpotLight light, vec3 normal, vec3 frag_position, vec3 view
float intensity = clamp((theta - light.outer_cutoff) / epsilon, 0.0, 1.0); float intensity = clamp((theta - light.outer_cutoff) / epsilon, 0.0, 1.0);
float diff = max(dot(normal, light_direction), 0.0); float diff = max(dot(normal, light_direction), 0.0);
float spec = pow(max(dot(reflect_direction, view_direction), 0.0), material.shininess); float spec = pow(max(dot(reflect_direction, view_direction), 0.0), material.shininess);
vec3 diff_tex = vec3(texture(material.diffuse1, fs_in.uv_coords)); vec3 diff_tex = vec3(texture(material.diffuse1, uv_coords));
vec3 ambient = light.ambient * diff_tex; vec3 ambient = light.ambient * diff_tex;
vec3 diffuse = light.diffuse * (diff * diff_tex) * intensity; vec3 diffuse = light.diffuse * (diff * diff_tex) * intensity;
vec3 specular = light.specular * (spec * vec3(texture(material.specular1, fs_in.uv_coords))) * intensity; vec3 specular = light.specular * (spec * vec3(texture(material.specular1, uv_coords))) * intensity;
return ambient + diffuse + specular; return ambient + diffuse + specular;
} }

View File

@ -1,18 +0,0 @@
#version 330 core
#define POINT_LIGHT_COUNT 4
layout(location=0) in vec3 position;
layout(location=1) in vec3 normal;
layout(location=2) in vec2 uv;
layout(location=3) in mat4 model;
layout (std140) uniform Common {
mat4 projection;
mat4 view;
vec3 camera_position;
};
void main() {
gl_Position = projection * view * model * vec4(position, 1.0);
};

View File

@ -1,7 +0,0 @@
#version 330 core
out vec4 color;
void main() {
color = vec4(1.0, 1.0, 0.0, 1.0);
}

View File

@ -1,34 +0,0 @@
#version 330 core
#define MAGNITUDE 0.1
layout (triangles) in;
layout (line_strip, max_vertices = 6) out;
uniform float time;
in VS_OUT {
vec3 vert_normal;
} gs_in[];
layout (std140) uniform Common {
mat4 projection;
mat4 view;
vec3 camera_position;
};
void generate_line(int index) {
gl_Position = projection * gl_in[index].gl_Position;
EmitVertex();
gl_Position = projection * (gl_in[index].gl_Position + vec4(gs_in[index].vert_normal, 1.0) * MAGNITUDE);
EmitVertex();
EndPrimitive();
}
void main() {
for (int i = 0; i < 3; ++i) {
generate_line(i);
}
}

View File

@ -1,25 +0,0 @@
#version 330 core
layout(location=0) in vec3 position;
layout(location=1) in vec3 normal;
layout(location=2) in vec2 uv;
uniform mat3 normal_mat;
uniform mat4 model;
layout (std140) uniform Common {
mat4 projection;
mat4 view;
vec3 camera_position;
};
// interface block
out VS_OUT {
vec3 vert_normal;
} vs_out;
void main() {
vs_out.vert_normal = normal_mat * normal;
gl_Position = view * model * vec4(position, 1.0);
};

View File

@ -1,17 +0,0 @@
#version 330 core
struct Material {
sampler2D diffuse1;
sampler2D specular1;
float shininess;
};
in vec2 uv_coords;
uniform Material material;
out vec4 color;
void main() {
color = vec4(vec3(texture(material.diffuse1, uv_coords)), 1.0);
}

View File

@ -1,12 +0,0 @@
#version 330 core
layout(location=0) in vec3 position;
layout(location=1) in vec3 normal;
layout(location=2) in vec2 uv;
out vec2 uv_coords;
void main() {
gl_Position = vec4(position.x, position.y, 0.0, 1.0);
uv_coords = uv;
}

View File

@ -1,24 +0,0 @@
#version 330 core
in VS_OUT {
vec3 vert_normal;
vec3 frag_position;
vec2 uv_coords;
} fs_in;
uniform samplerCube cubemap;
layout (std140) uniform Common {
mat4 projection;
mat4 view;
vec3 camera_position;
};
out vec4 color;
void main() {
vec3 view_direction = normalize(fs_in.frag_position - camera_position);
vec3 reflect_direction = reflect(view_direction, normalize(fs_in.vert_normal));
color = vec4(texture(cubemap, reflect_direction).rgb, 1.0);
}

View File

@ -1,27 +0,0 @@
#version 330 core
#define AIR_IOR 1.0
#define GLASS_IOR 1.52
in VS_OUT {
vec3 vert_normal;
vec3 frag_position;
vec2 uv_coords;
} fs_in;
uniform samplerCube cubemap;
layout (std140) uniform Common {
mat4 projection;
mat4 view;
vec3 camera_position;
};
out vec4 color;
void main() {
vec3 view_direction = normalize(fs_in.frag_position - camera_position);
vec3 refract_direction = refract(view_direction, normalize(fs_in.vert_normal), AIR_IOR / GLASS_IOR);
color = vec4(texture(cubemap, refract_direction).rgb, 1.0);
}

View File

@ -1,11 +0,0 @@
#version 330 core
in vec3 uv_coords;
uniform samplerCube cubemap;
out vec4 color;
void main() {
color = texture(cubemap, uv_coords);
}

View File

@ -1,21 +0,0 @@
#version 330 core
layout(location=0) in vec3 position;
layout(location=1) in vec3 normal;
layout(location=2) in vec2 uv;
uniform mat4 sb_view;
layout (std140) uniform Common {
mat4 projection;
mat4 view;
vec3 camera_position;
};
out vec3 uv_coords;
void main() {
vec4 pos = projection * sb_view * vec4(position, 1.0);
gl_Position = pos.xyww;
uv_coords = position;
}

View File

@ -4,26 +4,18 @@ layout(location=0) in vec3 position;
layout(location=1) in vec3 normal; layout(location=1) in vec3 normal;
layout(location=2) in vec2 uv; layout(location=2) in vec2 uv;
out vec3 vert_normal;
out vec3 frag_position;
out vec2 uv_coords;
uniform mat3 normal_mat; uniform mat3 normal_mat;
uniform mat4 model; uniform mat4 model;
uniform mat4 view;
layout (std140) uniform Common { uniform mat4 projection;
mat4 projection;
mat4 view;
vec3 camera_position;
};
// interface block
out VS_OUT {
vec3 vert_normal;
vec3 frag_position;
vec2 uv_coords;
} vs_out;
void main() { void main() {
vs_out.frag_position = vec3(model * vec4(position, 1.0)); vert_normal = normal_mat * normal;
vs_out.vert_normal = normal_mat * normal; frag_position = vec3(model * vec4(position, 1.0));
vs_out.uv_coords = uv; uv_coords = uv;
gl_Position = projection * view * model * vec4(position, 1.0); gl_Position = projection * view * model * vec4(position, 1.0);
}; };

@ -1 +1 @@
Subproject commit 258cdfd2bc29a920bbe749962abbcd58caa76422 Subproject commit c35200e38ea8f058812b83de2ef32c6093b0ece2

View File

@ -48,27 +48,17 @@
#define max(a, b) (a > b ? a : b) #define max(a, b) (a > b ? a : b)
#define clamp(v, a, b) (min(max(v, a), b)) #define clamp(v, a, b) (min(max(v, a), b))
#define WIREFRAME 0
#define NORMALS 0
#define MSAA 1
#define POINT_LIGHTS 1
#if MSAA
#define MSAA_SAMPLE_COUNT 4
#endif
enum exit_codes : int { enum exit_codes : int {
EXIT_CODE_SUCCESS, EXIT_CODE_SUCCESS,
EXIT_CODE_SDL_INIT_FAILED, EXIT_CODE_SDL_INIT_FAILED,
EXIT_CODE_WINDOW_CREATION_FAILED, EXIT_CODE_WINDOW_CREATION_FAILED,
EXIT_CODE_OPENGL_CONTEXT_FAILED, EXIT_CODE_OPENGL_CONTEXT_FAILED,
EXIT_CODE_GLAD_LOADER_FAILED, EXIT_CODE_GLAD_LOADER_FAILED,
EXIT_CODE_INCOMPLETE_FRAME_BUFFER,
}; };
class Shader { class Shader {
public: public:
Shader(const std::string &vert_file, const std::string &frag_file, const std::string &geo_file = ""); Shader(const std::string &vert_file, const std::string &frag_file);
~Shader(); ~Shader();
void activate(); void activate();
void set_int(const char *name, int value); void set_int(const char *name, int value);
@ -77,10 +67,9 @@ class Shader {
void set_vec4(const char *name, glm::vec4 vector); void set_vec4(const char *name, glm::vec4 vector);
void set_mat3(const char *name, glm::mat3 matrix); void set_mat3(const char *name, glm::mat3 matrix);
void set_mat4(const char *name, glm::mat4 matrix); void set_mat4(const char *name, glm::mat4 matrix);
void set_uniform_block_binding_point(const char *block_name, GLuint binding_point);
GLuint program; GLuint program;
private: private:
void link_program(GLuint vert, GLuint frag, GLuint geo); void link_program(GLuint vert, GLuint frag);
GLuint load_and_compile_shader(const std::string &filepath, GLenum shader_type); GLuint load_and_compile_shader(const std::string &filepath, GLenum shader_type);
std::string load_shader_from_file(const std::string &filepath); std::string load_shader_from_file(const std::string &filepath);
static const char *get_shader_type_string(GLenum shader_type); static const char *get_shader_type_string(GLenum shader_type);
@ -121,14 +110,10 @@ class Mesh {
std::vector<Texture2D> textures; std::vector<Texture2D> textures;
Mesh(std::vector<Vertex> vertices, std::vector<GLuint> indices, std::vector<Texture2D> textures); Mesh(std::vector<Vertex> vertices, std::vector<GLuint> indices, std::vector<Texture2D> textures);
void activate();
void deactivate();
void draw(Shader &Shader); void draw(Shader &Shader);
void draw_instanced(Shader &Shader, unsigned int count = 1);
private: private:
GLuint vao, vbo, ebo; GLuint vao, vbo, ebo;
void setup_mesh(); void setup_mesh();
void set_mesh_textures_for_drawing(Shader &shader);
}; };
class Model { class Model {
@ -150,22 +135,6 @@ class Model {
std::vector<Texture2D> load_material_textures(aiMaterial *mat, aiTextureType type); std::vector<Texture2D> load_material_textures(aiMaterial *mat, aiTextureType type);
}; };
struct FrameBuffer {
GLuint fbo;
GLuint color;
GLuint depth_stencil;
GLuint width;
GLuint height;
};
FrameBuffer create_normal_frame_buffer(unsigned int width, unsigned int height);
#if MSAA
FrameBuffer create_multisample_frame_buffer(unsigned int width, unsigned int height);
void blit_multisample_frame_buffer(const FrameBuffer &multisample_buffer, const FrameBuffer &normal_buffer);
#endif
void delete_frame_buffer(FrameBuffer &buffer);
GLuint load_cubemap(std::vector<std::string> textures);
int main() { int main() {
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) { if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
return EXIT_CODE_SDL_INIT_FAILED; return EXIT_CODE_SDL_INIT_FAILED;
@ -177,11 +146,6 @@ int main() {
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
#if MSAA
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, MSAA_SAMPLE_COUNT);
#endif
SDL_Window *window = SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SDL_Window *window = SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
if (!window) { if (!window) {
@ -197,21 +161,12 @@ int main() {
return EXIT_CODE_GLAD_LOADER_FAILED; return EXIT_CODE_GLAD_LOADER_FAILED;
} }
#if MSAA
glEnable(GL_MULTISAMPLE);
#endif
SDL_SetRelativeMouseMode(SDL_TRUE); SDL_SetRelativeMouseMode(SDL_TRUE);
SDL_WarpMouseInWindow(window, WINDOW_HALF_WIDTH, WINDOW_HALF_HEIGHT); SDL_WarpMouseInWindow(window, WINDOW_HALF_WIDTH, WINDOW_HALF_HEIGHT);
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
#if MSAA glEnable(GL_DEPTH_TEST);
FrameBuffer multisample_buffer = create_multisample_frame_buffer(WINDOW_WIDTH, WINDOW_HEIGHT);
FrameBuffer offscreen_buffer = create_normal_frame_buffer(WINDOW_WIDTH, WINDOW_HEIGHT);
#else
FrameBuffer offscreen_buffer = create_normal_frame_buffer(WINDOW_WIDTH, WINDOW_HEIGHT);
#endif
std::vector<Vertex> vertices = { std::vector<Vertex> vertices = {
// positions // normals // texture coords // positions // normals // texture coords
@ -256,74 +211,21 @@ int main() {
13, 15, 16 13, 15, 16
}; };
Model suzanne = {"models/suzanne/suzanne.obj"}; Model backpack = {"models/suzanne/suzanne.obj"};
Mesh light = {vertices, indices, {}}; Mesh light = {vertices, indices, {}};
std::vector<Vertex> skybox_vertices = {
Vertex{glm::vec3(-1.0f, 1.0f, -1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)},
Vertex{glm::vec3(-1.0f, -1.0f, -1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)},
Vertex{glm::vec3( 1.0f, -1.0f, -1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)},
Vertex{glm::vec3( 1.0f, 1.0f, -1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)},
Vertex{glm::vec3(-1.0f, -1.0f, 1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)},
Vertex{glm::vec3(-1.0f, 1.0f, 1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)},
Vertex{glm::vec3( 1.0f, -1.0f, 1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)},
Vertex{glm::vec3( 1.0f, 1.0f, 1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)},
};
std::vector<GLuint> skybox_indices = {
0, 1, 2,
2, 3, 0,
4, 1, 0,
0, 5, 4,
2, 6, 7,
7, 3, 2,
4, 5, 7,
7, 6, 4,
0, 3, 7,
7, 5, 0,
1, 4, 2,
2, 4, 6,
};
Mesh skybox = {skybox_vertices, skybox_indices, {}};
std::vector<Vertex> screen_vertices = {
Vertex{glm::vec3(-1.0f, -1.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(0.0f, 0.0f)},
Vertex{glm::vec3( 1.0f, -1.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 0.0f)},
Vertex{glm::vec3(-1.0f, 1.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(0.0f, 1.0f)},
Vertex{glm::vec3( 1.0f, 1.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)},
};
std::vector<GLuint> screen_indices = {
0, 1, 2,
2, 1, 3,
};
Mesh screen = {screen_vertices, screen_indices, {}};
Shader main_shader {"shaders/vert.glsl", "shaders/frag.glsl"}; Shader main_shader {"shaders/vert.glsl", "shaders/frag.glsl"};
Shader skybox_shader {"shaders/sb_vert.glsl", "shaders/sb_frag.glsl"}; Shader light_shader {"shaders/vert.glsl", "shaders/light_frag.glsl"};
Shader reflective_shader {"shaders/vert.glsl", "shaders/reflective_frag.glsl"};
Shader refractive_shader {"shaders/vert.glsl", "shaders/refractive_frag.glsl"};
Shader post_processing {"shaders/pp_vert.glsl", "shaders/pp_frag.glsl"};
#if NORMALS
Shader normal_vis_shader {"shaders/normal_vert.glsl", "shaders/normal_frag.glsl", "shaders/normal_geo.glsl"};
#endif
#if POINT_LIGHTS
Shader light_shader {"shaders/light_vert.glsl", "shaders/light_frag.glsl"};
std::vector<glm::mat4> light_shader_model_mats;
#endif
const float camera_speed = 25.0f; const float camera_speed = 25.0f;
glm::vec3 camera_position = glm::vec3(-2.5f, 0.0f, 8.0f); glm::vec3 camera_position = glm::vec3(-2.0f, 0.0f, 6.0f);
glm::vec3 camera_forward = glm::vec3(0.0f); glm::vec3 camera_forward = glm::vec3(0.0f);
glm::vec3 world_up = glm::vec3(0.0f, 1.0f, 0.0f); glm::vec3 world_up = glm::vec3(0.0f, 1.0f, 0.0f);
glm::vec3 light_ambient = glm::vec3(0.2f, 0.2f, 0.2f); glm::vec3 light_ambient = glm::vec3(0.2f, 0.2f, 0.2f);
glm::vec3 light_diffuse = glm::vec3(0.75f, 0.75f, 0.75f); glm::vec3 light_diffuse = glm::vec3(0.75f, 0.75f, 0.75f);
glm::vec3 light_specular = glm::vec3(1.0f, 1.0f, 1.0f); glm::vec3 light_specular = glm::vec3(1.0f, 1.0f, 1.0f);
float yaw = -75.0f; float yaw = -70.0f;
float pitch = 0.0f; float pitch = 0.0f;
glm::mat4 model = glm::mat4(1.0f); glm::mat4 model = glm::mat4(1.0f);
@ -331,6 +233,11 @@ int main() {
glm::mat4 projection = glm::perspective(glm::radians(45.0f), (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, 0.1f, 100.0f); glm::mat4 projection = glm::perspective(glm::radians(45.0f), (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, 0.1f, 100.0f);
glm::mat3 normal_mat = glm::mat3(1.0f); glm::mat3 normal_mat = glm::mat3(1.0f);
main_shader.set_mat4 ("projection", projection);
main_shader.set_float("material.shininess", 32.0f);
light_shader.set_mat4("projection", projection);
std::vector<glm::vec3> point_light_positions = { std::vector<glm::vec3> point_light_positions = {
glm::vec3( 0.7f, 0.2f, 2.0f), glm::vec3( 0.7f, 0.2f, 2.0f),
glm::vec3( 2.3f, -3.3f, -4.0f), glm::vec3( 2.3f, -3.3f, -4.0f),
@ -338,9 +245,6 @@ int main() {
glm::vec3( 1.0f, 0.0f, -18.0f) glm::vec3( 1.0f, 0.0f, -18.0f)
}; };
// Setup material
main_shader.set_float("material.shininess", 32.0f);
// Setup lights // Setup lights
main_shader.set_vec3("directional_light.direction", glm::vec3(-0.2f, -1.0f, -0.3f)); main_shader.set_vec3("directional_light.direction", glm::vec3(-0.2f, -1.0f, -0.3f));
main_shader.set_vec3("directional_light.ambient", light_ambient); main_shader.set_vec3("directional_light.ambient", light_ambient);
@ -386,76 +290,8 @@ int main() {
memset(constant, 0, sizeof(constant)); memset(constant, 0, sizeof(constant));
memset(linear, 0, sizeof(linear)); memset(linear, 0, sizeof(linear));
memset(quadratic, 0, sizeof(quadratic)); memset(quadratic, 0, sizeof(quadratic));
#if POINT_LIGHTS
glm::mat4 light_shader_model_mat = glm::translate(glm::mat4(1.0f), point_light_positions[i]);
light_shader_model_mat = glm::scale(light_shader_model_mat, glm::vec3(0.2f));
light_shader_model_mats.push_back(light_shader_model_mat);
#endif
} }
#if POINT_LIGHTS
std::size_t vec4_size = sizeof(glm::vec4);
light.activate();
GLuint instanceVBO;
glGenBuffers(1, &instanceVBO);
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * light_shader_model_mats.size(), glm::value_ptr(light_shader_model_mats[0]), GL_STATIC_DRAW);
// Set up attribute pointers for each column of the matrix
for (unsigned int i = 3; i < 7; ++i) {
glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (void *)((i - 3) * vec4_size));
glEnableVertexAttribArray(i);
glVertexAttribDivisor(i, 1);
}
light.deactivate();
glBindBuffer(GL_ARRAY_BUFFER, 0);
#endif
// Load cube map
std::vector<std::string> cube_map_textures = {
"images/skybox/right.jpg",
"images/skybox/left.jpg",
"images/skybox/top.jpg",
"images/skybox/bottom.jpg",
"images/skybox/front.jpg",
"images/skybox/back.jpg",
};
GLuint cubemap = load_cubemap(cube_map_textures);
// Generate and bind uniform buffer
GLuint ubo;
GLuint ubo_binding_point = 0;
glGenBuffers(1, &ubo);
glBindBuffer(GL_UNIFORM_BUFFER, ubo);
glBufferData(GL_UNIFORM_BUFFER, 144, NULL, GL_STATIC_DRAW);
// Bind the uniform buffer object to a binding point
// Can also be done using glBindBufferRange instead of glBindBufferBase
glBindBufferBase(GL_UNIFORM_BUFFER, ubo_binding_point, ubo);
// Set the shaders binding points
main_shader.set_uniform_block_binding_point ("Common", ubo_binding_point);
skybox_shader.set_uniform_block_binding_point ("Common", ubo_binding_point);
reflective_shader.set_uniform_block_binding_point("Common", ubo_binding_point);
refractive_shader.set_uniform_block_binding_point("Common", ubo_binding_point);
#if NORMALS
normal_vis_shader.set_uniform_block_binding_point("Common", ubo_binding_point);
#endif
#if POINT_LIGHTS
light_shader.set_uniform_block_binding_point ("Common", ubo_binding_point);
#endif
// Add projection matrix to uniform buffer
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::mat4), glm::value_ptr(projection));
glBindBuffer(GL_UNIFORM_BUFFER, 0);
const float sensitivity = 0.1f; const float sensitivity = 0.1f;
int last_mouse_x = WINDOW_HALF_WIDTH; int last_mouse_x = WINDOW_HALF_WIDTH;
int last_mouse_y = WINDOW_HALF_HEIGHT; int last_mouse_y = WINDOW_HALF_HEIGHT;
@ -519,14 +355,6 @@ int main() {
SDL_GL_GetDrawableSize(wnd, &w, &h); SDL_GL_GetDrawableSize(wnd, &w, &h);
glViewport(0, 0, w, h); glViewport(0, 0, w, h);
SDL_WarpMouseInWindow(wnd, (int)(w * 0.5f), (int)(h * 0.5f)); SDL_WarpMouseInWindow(wnd, (int)(w * 0.5f), (int)(h * 0.5f));
// Recreate offscreen frame buffer
delete_frame_buffer(offscreen_buffer);
offscreen_buffer = create_normal_frame_buffer(w, h);
#if MSAA
delete_frame_buffer(multisample_buffer);
multisample_buffer = create_multisample_frame_buffer(w, h);
#endif
} }
break; break;
} }
@ -538,96 +366,33 @@ int main() {
camera_forward = glm::normalize(camera_forward); camera_forward = glm::normalize(camera_forward);
view = glm::lookAt(camera_position, camera_position + camera_forward, world_up); view = glm::lookAt(camera_position, camera_position + camera_forward, world_up);
main_shader.set_vec3("camera_position", camera_position);
// Add view matrix and camera_position to uniform buffer
glBindBuffer(GL_UNIFORM_BUFFER, ubo);
glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(view));
glBufferSubData(GL_UNIFORM_BUFFER, 2 * sizeof(glm::mat4), sizeof(glm::vec3), glm::value_ptr(camera_position));
glBindBuffer(GL_UNIFORM_BUFFER, 0);
main_shader.set_vec3("spot_light.position", camera_position); main_shader.set_vec3("spot_light.position", camera_position);
main_shader.set_vec3("spot_light.direction", camera_forward); main_shader.set_vec3("spot_light.direction", camera_forward);
main_shader.set_float("spot_light.cutoff", glm::cos(glm::radians(12.5))); main_shader.set_float("spot_light.cutoff", glm::cos(glm::radians(12.5)));
main_shader.set_float("spot_light.outer_cutoff", glm::cos(glm::radians(17.5))); main_shader.set_float("spot_light.outer_cutoff", glm::cos(glm::radians(17.5)));
skybox_shader.set_mat4("sb_view", glm::mat4(glm::mat3(view))); main_shader.set_mat4("view", view);
light_shader.set_mat4("view", view);
// Main render pass
#if MSAA
glBindFramebuffer(GL_FRAMEBUFFER, multisample_buffer.fbo);
#else
glBindFramebuffer(GL_FRAMEBUFFER, offscreen_buffer.fbo);
#endif
glClearColor(0.04f, 0.08f, 0.08f, 1.0f); glClearColor(0.04f, 0.08f, 0.08f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glEnable(GL_CULL_FACE);
model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 0.0f)); model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 0.0f));
normal_mat = glm::transpose(glm::inverse(model)); normal_mat = glm::transpose(glm::inverse(model));
main_shader.activate(); main_shader.activate();
main_shader.set_mat4("model", model); main_shader.set_mat4("model", model);
main_shader.set_mat3("normal_mat", normal_mat); main_shader.set_mat3("normal_mat", normal_mat);
suzanne.draw(main_shader); backpack.draw(main_shader);
#if NORMALS // Draw light source
normal_mat = glm::transpose(glm::inverse(view * model)); for (int i = 0; i < point_light_positions.size(); ++i) {
normal_vis_shader.activate(); model = glm::translate(glm::mat4(1.0f), point_light_positions[i]);
normal_vis_shader.set_mat4("model", model); model = glm::scale(model, glm::vec3(0.2f));
normal_vis_shader.set_mat3("normal_mat", normal_mat); light_shader.activate();
suzanne.draw(normal_vis_shader); light_shader.set_mat4("model", model);
#endif
model = glm::translate(glm::mat4(1.0f), glm::vec3(3.0f, 0.0f, 0.0f));
normal_mat = glm::transpose(glm::inverse(model));
reflective_shader.set_mat4("model", model);
reflective_shader.set_mat3("normal_mat", normal_mat);
suzanne.draw(reflective_shader);
glDisable(GL_CULL_FACE);
model = glm::translate(glm::mat4(1.0f), glm::vec3(-3.0f, 0.0f, 0.0f));
normal_mat = glm::transpose(glm::inverse(model));
refractive_shader.set_mat4("model", model);
refractive_shader.set_mat3("normal_mat", normal_mat);
suzanne.draw(refractive_shader);
#if POINT_LIGHTS
// Draw point lights
light_shader.set_vec3("light_diffuse", light_diffuse); light_shader.set_vec3("light_diffuse", light_diffuse);
light.draw_instanced(light_shader, point_light_positions.size()); light.draw(light_shader);
#endif }
// Draw skybox
skybox_shader.activate();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap);
skybox_shader.set_int("cubemap", 0);
skybox.draw(skybox_shader);
#if WIREFRAME
// wireframe mode
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
#endif
#if MSAA
blit_multisample_frame_buffer(multisample_buffer, offscreen_buffer);
#endif
// Post processing pass
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
post_processing.activate();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, offscreen_buffer.color);
post_processing.set_int("image_texture", 0);
screen.draw(post_processing);
SDL_GL_SwapWindow(window); SDL_GL_SwapWindow(window);
} }
@ -640,19 +405,12 @@ int main() {
} }
Shader::Shader(const std::string &vert_file, const std::string &frag_file, const std::string &geo_file) { Shader::Shader(const std::string &vert_file, const std::string &frag_file) {
GLuint vert = load_and_compile_shader(vert_file, GL_VERTEX_SHADER); GLuint vert = load_and_compile_shader(vert_file, GL_VERTEX_SHADER);
GLuint frag = load_and_compile_shader(frag_file, GL_FRAGMENT_SHADER); GLuint frag = load_and_compile_shader(frag_file, GL_FRAGMENT_SHADER);
GLuint geo = 0; link_program(vert, frag);
if (geo_file.size() > 0) {
geo = load_and_compile_shader(geo_file, GL_GEOMETRY_SHADER);
}
link_program(vert, frag, geo);
glDeleteShader(vert); glDeleteShader(vert);
glDeleteShader(frag); glDeleteShader(frag);
if (geo > 0) {
glDeleteShader(geo);
}
} }
Shader::~Shader() { Shader::~Shader() {
@ -697,18 +455,10 @@ void Shader::set_mat4(const char *name, glm::mat4 matrix) {
glUniformMatrix4fv(glGetUniformLocation(program, name), 1, GL_FALSE, glm::value_ptr(matrix)); glUniformMatrix4fv(glGetUniformLocation(program, name), 1, GL_FALSE, glm::value_ptr(matrix));
} }
void Shader::set_uniform_block_binding_point(const char *block_name, GLuint binding_point) { void Shader::link_program(GLuint vert, GLuint frag) {
GLuint block_index = glGetUniformBlockIndex(program, block_name);
glUniformBlockBinding(program, block_index, binding_point);
}
void Shader::link_program(GLuint vert, GLuint frag, GLuint geo) {
program = glCreateProgram(); program = glCreateProgram();
glAttachShader(program, vert); glAttachShader(program, vert);
glAttachShader(program, frag); glAttachShader(program, frag);
if (geo > 0) {
glAttachShader(program, geo);
}
glLinkProgram(program); glLinkProgram(program);
GLint program_linked; GLint program_linked;
@ -865,7 +615,7 @@ void Mesh::setup_mesh() {
glEnableVertexAttribArray(2); glEnableVertexAttribArray(2);
} }
void Mesh::set_mesh_textures_for_drawing(Shader &shader) { void Mesh::draw(Shader &shader) {
unsigned int diffuse = 1; unsigned int diffuse = 1;
unsigned int specular = 1; unsigned int specular = 1;
unsigned int index; unsigned int index;
@ -876,33 +626,13 @@ void Mesh::set_mesh_textures_for_drawing(Shader &shader) {
shader.set_int(texture.name(index).c_str(), texture.texture_unit - GL_TEXTURE0); shader.set_int(texture.name(index).c_str(), texture.texture_unit - GL_TEXTURE0);
texture.activate(); texture.activate();
} }
}
void Mesh::activate() {
glBindVertexArray(vao); glBindVertexArray(vao);
}
void Mesh::deactivate() {
glBindVertexArray(0);
}
void Mesh::draw(Shader &shader) {
set_mesh_textures_for_drawing(shader);
activate();
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, (void *)0); glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, (void *)0);
deactivate();
}
void Mesh::draw_instanced(Shader &shader, unsigned int count) {
set_mesh_textures_for_drawing(shader);
glBindVertexArray(vao);
glDrawElementsInstanced(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, (void *)0, count);
glBindVertexArray(0); glBindVertexArray(0);
} }
void Model::draw(Shader &shader) { void Model::draw(Shader &shader) {
shader.activate();
for (int i = 0; i < meshes.size(); ++i) { for (int i = 0; i < meshes.size(); ++i) {
meshes[i].draw(shader); meshes[i].draw(shader);
} }
@ -995,117 +725,3 @@ std::vector<Texture2D> Model::load_material_textures(aiMaterial *material, aiTex
return textures; return textures;
} }
FrameBuffer create_normal_frame_buffer(unsigned int width, unsigned int height) {
FrameBuffer buffer = {};
glGenFramebuffers(1, &buffer.fbo);
glBindFramebuffer(GL_FRAMEBUFFER, buffer.fbo);
// Create color texture
glGenTextures(1, &buffer.color);
glBindTexture(GL_TEXTURE_2D, buffer.color);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, buffer.color, 0);
// Create depth and stencil buffers
glGenRenderbuffers(1, &buffer.depth_stencil);
glBindRenderbuffer(GL_RENDERBUFFER, buffer.depth_stencil);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, buffer.depth_stencil);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
printf("Incomplete frame buffer\n");
exit(EXIT_CODE_INCOMPLETE_FRAME_BUFFER);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
buffer.width = width;
buffer.height = height;
return buffer;
}
#if MSAA
FrameBuffer create_multisample_frame_buffer(unsigned int width, unsigned int height) {
FrameBuffer buffer = {};
glGenFramebuffers(1, &buffer.fbo);
glBindFramebuffer(GL_FRAMEBUFFER, buffer.fbo);
// Create color texture
glGenTextures(1, &buffer.color);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, buffer.color);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, MSAA_SAMPLE_COUNT, GL_RGB, width, height, GL_TRUE);
glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, buffer.color, 0);
// Create depth and stencil buffers
glGenRenderbuffers(1, &buffer.depth_stencil);
glBindRenderbuffer(GL_RENDERBUFFER, buffer.depth_stencil);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, MSAA_SAMPLE_COUNT, GL_DEPTH24_STENCIL8, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, buffer.depth_stencil);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
printf("Incomplete frame buffer\n");
exit(EXIT_CODE_INCOMPLETE_FRAME_BUFFER);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
buffer.width = width;
buffer.height = height;
return buffer;
}
void blit_multisample_frame_buffer(const FrameBuffer &multisample_buffer, const FrameBuffer &normal_buffer) {
glBindFramebuffer(GL_READ_FRAMEBUFFER, multisample_buffer.fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, normal_buffer.fbo);
glBlitFramebuffer(
0, 0, multisample_buffer.width, multisample_buffer.height,
0, 0, normal_buffer.width, normal_buffer.height,
GL_COLOR_BUFFER_BIT, GL_NEAREST
);
}
#endif
void delete_frame_buffer(FrameBuffer &buffer) {
glDeleteFramebuffers(1, &buffer.fbo);
glDeleteTextures(1, &buffer.color);
glDeleteRenderbuffers(1, &buffer.depth_stencil);
}
GLuint load_cubemap(std::vector<std::string> textures) {
GLuint cubemap;
glGenTextures(1, &cubemap);
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap);
int width, height, channels;
uint8_t *tex;
for (unsigned int i = 0; i < textures.size(); ++i) {
tex = stbi_load(textures[i].c_str(), &width, &height, &channels, 0);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, tex);
stbi_image_free(tex);
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
return cubemap;
}