Compare commits
No commits in common. "main" and "01-lighting" have entirely different histories.
main
...
01-lightin
3
.gitmodules
vendored
@ -1,3 +0,0 @@
|
|||||||
[submodule "src/assimp"]
|
|
||||||
path = src/assimp
|
|
||||||
url = git@github.com:assimp/assimp
|
|
8
compile
@ -3,16 +3,16 @@
|
|||||||
CC=clang
|
CC=clang
|
||||||
CFLAGS="-g -c -Wall -Isrc/glad/include"
|
CFLAGS="-g -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="-g -Wall -std=c++20 $(pkg-config --cflags sdl2) -Isrc/glad/include -Isrc/glm"
|
||||||
LIBS="$(pkg-config --libs sdl2) -ldl -lz -lminizip -Lsrc/assimp/build/lib/ -lassimp"
|
LIBS="$(pkg-config --libs sdl2) -ldl"
|
||||||
GLAD_SRC="src/glad/src/glad.c"
|
GLAD_SRC="src/glad/src/glad.c"
|
||||||
GLAD_OBJ="glad.o"
|
GLAD_OBJ="glad.o"
|
||||||
SRC="src/*.cc $GLAD_OBJ src/glm/glm/glm.cppm"
|
SRC="src/*.cc $GLAD_OBJ src/glm/glm/glm.cppm"
|
||||||
OUT=main
|
OUT=main
|
||||||
|
|
||||||
(set -x ; $CC $CFLAGS $GLAD_SRC -o $GLAD_OBJ)
|
(set -x ; $CC $CFLAGS $GLAD_SRC -o $GLAD_OBJ)
|
||||||
(set -x ; $CXX $CXXFLAGS $SRC $LIBS -o $OUT)
|
(set -x ; $CXX $CXXFLAGS $LIBS $SRC -o $OUT)
|
||||||
|
|
||||||
if [[ -f $GLAD_OBJ ]]; then
|
if [[ -f $GLAD_OBJ ]]; then
|
||||||
rm $GLAD_OBJ
|
rm $GLAD_OBJ
|
||||||
fi
|
fi
|
||||||
|
Before Width: | Height: | Size: 723 KiB |
Before Width: | Height: | Size: 274 KiB |
Before Width: | Height: | Size: 462 KiB |
Before Width: | Height: | Size: 588 KiB |
Before Width: | Height: | Size: 525 KiB |
Before Width: | Height: | Size: 338 KiB |
Before Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 526 KiB |
@ -1,12 +0,0 @@
|
|||||||
# Blender 4.3.2 MTL File: 'None'
|
|
||||||
# www.blender.org
|
|
||||||
|
|
||||||
newmtl Material
|
|
||||||
Ka 1.000000 1.000000 1.000000
|
|
||||||
Ks 0.500000 0.500000 0.500000
|
|
||||||
Ke 0.000000 0.000000 0.000000
|
|
||||||
Ni 1.450000
|
|
||||||
d 1.000000
|
|
||||||
illum 2
|
|
||||||
map_Kd diffuse.png
|
|
||||||
map_Ks specular.png
|
|
@ -3,8 +3,8 @@
|
|||||||
#define POINT_LIGHT_COUNT 4
|
#define POINT_LIGHT_COUNT 4
|
||||||
|
|
||||||
struct Material {
|
struct Material {
|
||||||
sampler2D diffuse1;
|
sampler2D diffuse;
|
||||||
sampler2D specular1;
|
sampler2D specular;
|
||||||
float shininess;
|
float shininess;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -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.diffuse, 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.specular, 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.diffuse, 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.specular, 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.diffuse, 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.specular, uv_coords))) * intensity;
|
||||||
|
|
||||||
return ambient + diffuse + specular;
|
return ambient + diffuse + specular;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
|
||||||
};
|
|
@ -1,7 +0,0 @@
|
|||||||
#version 330 core
|
|
||||||
|
|
||||||
out vec4 color;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
color = vec4(1.0, 1.0, 0.0, 1.0);
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
};
|
|
@ -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);
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
#version 330 core
|
|
||||||
|
|
||||||
in vec3 uv_coords;
|
|
||||||
|
|
||||||
uniform samplerCube cubemap;
|
|
||||||
|
|
||||||
out vec4 color;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
color = texture(cubemap, uv_coords);
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -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 +0,0 @@
|
|||||||
Subproject commit 258cdfd2bc29a920bbe749962abbcd58caa76422
|
|
793
src/main.cc
@ -14,14 +14,6 @@
|
|||||||
#include "glm/gtx/rotate_vector.hpp"
|
#include "glm/gtx/rotate_vector.hpp"
|
||||||
#include "glm/gtx/string_cast.hpp"
|
#include "glm/gtx/string_cast.hpp"
|
||||||
|
|
||||||
// Assimp
|
|
||||||
#include "assimp/Importer.hpp"
|
|
||||||
#include "assimp/postprocess.h"
|
|
||||||
#include "assimp/scene.h"
|
|
||||||
#include "assimp/mesh.h"
|
|
||||||
#include "assimp/material.h"
|
|
||||||
#include "assimp/types.h"
|
|
||||||
|
|
||||||
// SDL
|
// SDL
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include <SDL2/SDL_timer.h>
|
#include <SDL2/SDL_timer.h>
|
||||||
@ -48,27 +40,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,95 +59,28 @@ 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);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TextureType : unsigned char {
|
|
||||||
TEXTURE_TYPE_DIFFUSE,
|
|
||||||
TEXTURE_TYPE_SPECULAR,
|
|
||||||
};
|
|
||||||
|
|
||||||
class Texture2D {
|
class Texture2D {
|
||||||
public:
|
public:
|
||||||
Texture2D(const char *filename, GLint texture_unit, TextureType type);
|
Texture2D(const char *filename, GLint texture_unit);
|
||||||
~Texture2D();
|
~Texture2D();
|
||||||
void activate() const;
|
void activate();
|
||||||
std::string name(unsigned int index) const;
|
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
int channels;
|
int channels;
|
||||||
const char *filename;
|
|
||||||
GLint texture_unit;
|
|
||||||
TextureType type;
|
|
||||||
private:
|
private:
|
||||||
GLuint texture;
|
GLuint texture;
|
||||||
|
GLint texture_unit;
|
||||||
GLint format;
|
GLint format;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Vertex {
|
|
||||||
glm::vec3 position;
|
|
||||||
glm::vec3 normal;
|
|
||||||
glm::vec2 tex_coord;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Mesh {
|
|
||||||
public:
|
|
||||||
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_instanced(Shader &Shader, unsigned int count = 1);
|
|
||||||
private:
|
|
||||||
GLuint vao, vbo, ebo;
|
|
||||||
void setup_mesh();
|
|
||||||
void set_mesh_textures_for_drawing(Shader &shader);
|
|
||||||
};
|
|
||||||
|
|
||||||
class Model {
|
|
||||||
public:
|
|
||||||
Model(const char *path) {
|
|
||||||
load_model(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw(Shader &shader);
|
|
||||||
private:
|
|
||||||
std::vector<Texture2D> loaded_textures;
|
|
||||||
std::vector<Mesh> meshes;
|
|
||||||
std::string directory;
|
|
||||||
GLint texture_unit = GL_TEXTURE0;
|
|
||||||
|
|
||||||
void load_model(std::string path);
|
|
||||||
void process_node(aiNode *node, const aiScene *scene);
|
|
||||||
Mesh process_mesh(aiMesh *mesh, const aiScene *scene);
|
|
||||||
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 +92,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,48 +107,41 @@ 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);
|
||||||
|
|
||||||
|
stbi_set_flip_vertically_on_load(true);
|
||||||
|
|
||||||
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<GLfloat> vertices = {
|
||||||
// positions // normals // texture coords
|
// positions // normals // texture coords
|
||||||
Vertex{glm::vec3(-0.5f, -0.5f, -0.5f), glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec2(0.0f, 1.0f)},
|
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
|
||||||
Vertex{glm::vec3( 0.5f, 0.5f, 0.5f), glm::vec3( 1.0f, 0.0f, 0.0f), glm::vec2(1.0f, 0.0f)},
|
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
|
||||||
Vertex{glm::vec3( 0.5f, 0.5f, -0.5f), glm::vec3( 1.0f, 0.0f, 0.0f), glm::vec2(1.0f, 1.0f)},
|
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
|
||||||
Vertex{glm::vec3(-0.5f, 0.5f, 0.5f), glm::vec3( 0.0f, 0.0f, 1.0f), glm::vec2(0.0f, 1.0f)},
|
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
|
||||||
Vertex{glm::vec3( 0.5f, -0.5f, 0.5f), glm::vec3( 1.0f, 0.0f, 0.0f), glm::vec2(0.0f, 0.0f)},
|
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
|
||||||
Vertex{glm::vec3( 0.5f, -0.5f, -0.5f), glm::vec3( 0.0f, -1.0f, 0.0f), glm::vec2(1.0f, 1.0f)},
|
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f,
|
||||||
Vertex{glm::vec3(-0.5f, -0.5f, -0.5f), glm::vec3( 0.0f, 0.0f, -1.0f), glm::vec2(0.0f, 0.0f)},
|
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
|
||||||
Vertex{glm::vec3( 0.5f, -0.5f, 0.5f), glm::vec3( 0.0f, 0.0f, 1.0f), glm::vec2(1.0f, 0.0f)},
|
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f,
|
||||||
Vertex{glm::vec3(-0.5f, -0.5f, -0.5f), glm::vec3( 0.0f, -1.0f, 0.0f), glm::vec2(0.0f, 1.0f)},
|
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f,
|
||||||
Vertex{glm::vec3( 0.5f, 0.5f, 0.5f), glm::vec3( 0.0f, 0.0f, 1.0f), glm::vec2(1.0f, 1.0f)},
|
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
|
||||||
Vertex{glm::vec3( 0.5f, -0.5f, 0.5f), glm::vec3( 0.0f, -1.0f, 0.0f), glm::vec2(1.0f, 0.0f)},
|
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,
|
||||||
Vertex{glm::vec3(-0.5f, -0.5f, 0.5f), glm::vec3( 0.0f, -1.0f, 0.0f), glm::vec2(0.0f, 0.0f)},
|
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f,
|
||||||
Vertex{glm::vec3( 0.5f, 0.5f, -0.5f), glm::vec3( 0.0f, 0.0f, -1.0f), glm::vec2(1.0f, 1.0f)},
|
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
|
||||||
Vertex{glm::vec3( 0.5f, 0.5f, 0.5f), glm::vec3( 0.0f, 1.0f, 0.0f), glm::vec2(1.0f, 0.0f)},
|
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
|
||||||
Vertex{glm::vec3( 0.5f, -0.5f, -0.5f), glm::vec3( 0.0f, 0.0f, -1.0f), glm::vec2(1.0f, 0.0f)},
|
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f,
|
||||||
Vertex{glm::vec3(-0.5f, 0.5f, 0.5f), glm::vec3( 0.0f, 1.0f, 0.0f), glm::vec2(0.0f, 0.0f)},
|
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
|
||||||
Vertex{glm::vec3(-0.5f, 0.5f, -0.5f), glm::vec3( 0.0f, 1.0f, 0.0f), glm::vec2(0.0f, 1.0f)},
|
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
|
||||||
Vertex{glm::vec3(-0.5f, -0.5f, 0.5f), glm::vec3( 0.0f, 0.0f, 1.0f), glm::vec2(0.0f, 0.0f)},
|
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
|
||||||
Vertex{glm::vec3(-0.5f, -0.5f, 0.5f), glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec2(0.0f, 0.0f)},
|
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
|
||||||
Vertex{glm::vec3(-0.5f, 0.5f, -0.5f), glm::vec3( 0.0f, 0.0f, -1.0f), glm::vec2(0.0f, 1.0f)},
|
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f,
|
||||||
Vertex{glm::vec3(-0.5f, 0.5f, -0.5f), glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec2(1.0f, 1.0f)},
|
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
|
||||||
Vertex{glm::vec3( 0.5f, 0.5f, -0.5f), glm::vec3( 0.0f, 1.0f, 0.0f), glm::vec2(1.0f, 1.0f)},
|
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
|
||||||
Vertex{glm::vec3(-0.5f, 0.5f, 0.5f), glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec2(1.0f, 0.0f)},
|
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
|
||||||
Vertex{glm::vec3( 0.5f, -0.5f, -0.5f), glm::vec3( 1.0f, 0.0f, 0.0f), glm::vec2(0.0f, 1.0f)},
|
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<GLuint> indices = {
|
std::vector<GLuint> indices = {
|
||||||
@ -256,74 +159,57 @@ int main() {
|
|||||||
13, 15, 16
|
13, 15, 16
|
||||||
};
|
};
|
||||||
|
|
||||||
Model suzanne = {"models/suzanne/suzanne.obj"};
|
GLuint vao = 0;
|
||||||
Mesh light = {vertices, indices, {}};
|
glGenVertexArrays(1, &vao);
|
||||||
|
glBindVertexArray(vao);
|
||||||
|
|
||||||
std::vector<Vertex> skybox_vertices = {
|
GLuint ebo = 0;
|
||||||
Vertex{glm::vec3(-1.0f, 1.0f, -1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)},
|
glGenBuffers(1, &ebo);
|
||||||
Vertex{glm::vec3(-1.0f, -1.0f, -1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)},
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||||
Vertex{glm::vec3( 1.0f, -1.0f, -1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)},
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), indices.data(), GL_STATIC_DRAW);
|
||||||
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 = {
|
GLuint vbo = 0;
|
||||||
0, 1, 2,
|
glGenBuffers(1, &vbo);
|
||||||
2, 3, 0,
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||||
4, 1, 0,
|
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), vertices.data(), GL_STATIC_DRAW);
|
||||||
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, {}};
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void *)0);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void *)(3 * sizeof(GLfloat)));
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void *)(6 * sizeof(GLfloat)));
|
||||||
|
glEnableVertexAttribArray(2);
|
||||||
|
|
||||||
std::vector<Vertex> screen_vertices = {
|
GLuint light_vao = 0;
|
||||||
Vertex{glm::vec3(-1.0f, -1.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(0.0f, 0.0f)},
|
glGenVertexArrays(1, &light_vao);
|
||||||
Vertex{glm::vec3( 1.0f, -1.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 0.0f)},
|
glBindVertexArray(light_vao);
|
||||||
Vertex{glm::vec3(-1.0f, 1.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(0.0f, 1.0f)},
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||||
Vertex{glm::vec3( 1.0f, 1.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)},
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<GLuint> screen_indices = {
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void *)0);
|
||||||
0, 1, 2,
|
glEnableVertexAttribArray(0);
|
||||||
2, 1, 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mesh screen = {screen_vertices, screen_indices, {}};
|
glBindVertexArray(0);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
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
|
Texture2D diffuse_map = Texture2D("images/container2.png", GL_TEXTURE0);
|
||||||
Shader light_shader {"shaders/light_vert.glsl", "shaders/light_frag.glsl"};
|
Texture2D specular_map = Texture2D("images/container2_specular.png", GL_TEXTURE1);
|
||||||
std::vector<glm::mat4> light_shader_model_mats;
|
main_shader.set_int("material.diffuse", 0);
|
||||||
#endif
|
main_shader.set_int("material.specular", 1);
|
||||||
|
|
||||||
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,25 +217,41 @@ 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_vec3 ("material.specular", glm::vec3(0.5f, 0.5f, 0.5f));
|
||||||
|
main_shader.set_float("material.shininess", 32.0f);
|
||||||
|
|
||||||
|
light_shader.set_mat4("projection", projection);
|
||||||
|
|
||||||
|
std::vector<glm::vec3> cube_positions = {
|
||||||
|
glm::vec3( 0.0f, 0.0f, 0.0f),
|
||||||
|
glm::vec3( 4.0f, 6.0f, -15.0f),
|
||||||
|
glm::vec3(-3.5f, -3.2f, -2.5f),
|
||||||
|
glm::vec3(-5.8f, -3.0f, -12.3f),
|
||||||
|
glm::vec3( 4.4f, -1.4f, -3.5f),
|
||||||
|
glm::vec3(-3.7f, 4.0f, -7.5f),
|
||||||
|
glm::vec3( 3.3f, -3.0f, -2.5f),
|
||||||
|
glm::vec3( 3.5f, 3.0f, -2.5f),
|
||||||
|
glm::vec3( 3.5f, 1.2f, -1.5f),
|
||||||
|
glm::vec3(-3.3f, 2.0f, -1.5f)
|
||||||
|
};
|
||||||
|
|
||||||
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),
|
||||||
glm::vec3(-4.0f, 2.0f, -12.0f),
|
glm::vec3(-4.0f, 2.0f, -12.0f),
|
||||||
glm::vec3( 1.0f, 0.0f, -18.0f)
|
glm::vec3( 0.0f, 0.0f, -3.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);
|
||||||
main_shader.set_vec3("directional_light.diffuse", light_diffuse * 0.25f);
|
main_shader.set_vec3("directional_light.diffuse", light_diffuse);
|
||||||
main_shader.set_vec3("directional_light.specular", light_specular);
|
main_shader.set_vec3("directional_light.specular", light_specular);
|
||||||
|
|
||||||
main_shader.set_vec3("spot_light.ambient", light_ambient);
|
main_shader.set_vec3("spot_light.ambient", light_ambient);
|
||||||
main_shader.set_vec3("spot_light.diffuse", light_diffuse * 0.5f);
|
main_shader.set_vec3("spot_light.diffuse", light_diffuse);
|
||||||
main_shader.set_vec3("spot_light.specular", light_specular * 0.25f);
|
main_shader.set_vec3("spot_light.specular", light_specular);
|
||||||
|
|
||||||
for (int i = 0; i < point_light_positions.size(); ++i) {
|
for (int i = 0; i < point_light_positions.size(); ++i) {
|
||||||
char base[256] = {0};
|
char base[256] = {0};
|
||||||
@ -372,8 +274,8 @@ int main() {
|
|||||||
|
|
||||||
main_shader.set_vec3(position, point_light_positions[i]);
|
main_shader.set_vec3(position, point_light_positions[i]);
|
||||||
main_shader.set_vec3(ambient, light_ambient);
|
main_shader.set_vec3(ambient, light_ambient);
|
||||||
main_shader.set_vec3(diffuse, light_diffuse * 0.25f);
|
main_shader.set_vec3(diffuse, light_diffuse);
|
||||||
main_shader.set_vec3(specular, light_specular * 0.5f);
|
main_shader.set_vec3(specular, light_specular);
|
||||||
main_shader.set_float(constant, 1.0f);
|
main_shader.set_float(constant, 1.0f);
|
||||||
main_shader.set_float(linear, 0.09f);
|
main_shader.set_float(linear, 0.09f);
|
||||||
main_shader.set_float(quadratic, 0.032f);
|
main_shader.set_float(quadratic, 0.032f);
|
||||||
@ -386,76 +288,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 +353,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 +364,40 @@ 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);
|
for (int i = 0; i < cube_positions.size(); ++i) {
|
||||||
glDepthFunc(GL_LEQUAL);
|
model = glm::translate(glm::mat4(1.0f), cube_positions[i]);
|
||||||
glEnable(GL_CULL_FACE);
|
model = glm::rotate(model, glm::radians(10.0f * i), glm::vec3(1.0f, 0.3f, 0.5f));
|
||||||
|
normal_mat = glm::transpose(glm::inverse(model));
|
||||||
|
main_shader.activate();
|
||||||
|
main_shader.set_mat4("model", model);
|
||||||
|
main_shader.set_mat3("normal_mat", normal_mat);
|
||||||
|
diffuse_map.activate();
|
||||||
|
specular_map.activate();
|
||||||
|
glBindVertexArray(vao);
|
||||||
|
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, (void *)0);
|
||||||
|
}
|
||||||
|
|
||||||
model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 0.0f));
|
// Draw light source
|
||||||
normal_mat = glm::transpose(glm::inverse(model));
|
for (int i = 0; i < point_light_positions.size(); ++i) {
|
||||||
main_shader.activate();
|
model = glm::translate(glm::mat4(1.0f), point_light_positions[i]);
|
||||||
main_shader.set_mat4("model", model);
|
model = glm::scale(model, glm::vec3(0.2f));
|
||||||
main_shader.set_mat3("normal_mat", normal_mat);
|
light_shader.activate();
|
||||||
suzanne.draw(main_shader);
|
light_shader.set_mat4("model", model);
|
||||||
|
light_shader.set_vec3("light_diffuse", light_diffuse);
|
||||||
#if NORMALS
|
glBindVertexArray(light_vao);
|
||||||
normal_mat = glm::transpose(glm::inverse(view * model));
|
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, (void *)0);
|
||||||
normal_vis_shader.activate();
|
}
|
||||||
normal_vis_shader.set_mat4("model", model);
|
|
||||||
normal_vis_shader.set_mat3("normal_mat", normal_mat);
|
|
||||||
suzanne.draw(normal_vis_shader);
|
|
||||||
#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.draw_instanced(light_shader, point_light_positions.size());
|
|
||||||
#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 +410,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 +460,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;
|
||||||
@ -791,7 +546,7 @@ const char *Shader::get_shader_type_string(GLenum shader_type) {
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture2D::Texture2D(const char *filename, GLint texture_unit, TextureType type) : filename(filename), texture_unit(texture_unit), type(type) {
|
Texture2D::Texture2D(const char *filename, GLint texture_unit) : texture_unit(texture_unit) {
|
||||||
uint8_t *image = stbi_load(filename, &width, &height, &channels, 0);
|
uint8_t *image = stbi_load(filename, &width, &height, &channels, 0);
|
||||||
if (!image) {
|
if (!image) {
|
||||||
return;
|
return;
|
||||||
@ -817,295 +572,7 @@ Texture2D::Texture2D(const char *filename, GLint texture_unit, TextureType type)
|
|||||||
|
|
||||||
Texture2D::~Texture2D() {}
|
Texture2D::~Texture2D() {}
|
||||||
|
|
||||||
void Texture2D::activate() const {
|
void Texture2D::activate() {
|
||||||
glActiveTexture(texture_unit);
|
glActiveTexture(texture_unit);
|
||||||
glBindTexture(GL_TEXTURE_2D, texture);
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Texture2D::name(unsigned int index) const {
|
|
||||||
std::string output = "material.";
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case TEXTURE_TYPE_DIFFUSE:
|
|
||||||
output += "diffuse";
|
|
||||||
break;
|
|
||||||
case TEXTURE_TYPE_SPECULAR:
|
|
||||||
output += "specular";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
output += std::to_string(index);
|
|
||||||
|
|
||||||
return output.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
Mesh::Mesh(std::vector<Vertex> vertices, std::vector<GLuint> indices, std::vector<Texture2D> textures)
|
|
||||||
: vertices(vertices), indices(indices), textures(textures) {
|
|
||||||
setup_mesh();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mesh::setup_mesh() {
|
|
||||||
glGenVertexArrays(1, &vao);
|
|
||||||
glGenBuffers(1, &ebo);
|
|
||||||
glGenBuffers(1, &vbo);
|
|
||||||
|
|
||||||
glBindVertexArray(vao);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), indices.data(), GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)0);
|
|
||||||
glEnableVertexAttribArray(0);
|
|
||||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)(offsetof(Vertex, normal)));
|
|
||||||
glEnableVertexAttribArray(1);
|
|
||||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)(offsetof(Vertex, tex_coord)));
|
|
||||||
glEnableVertexAttribArray(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mesh::set_mesh_textures_for_drawing(Shader &shader) {
|
|
||||||
unsigned int diffuse = 1;
|
|
||||||
unsigned int specular = 1;
|
|
||||||
unsigned int index;
|
|
||||||
|
|
||||||
for (int i = 0; i < textures.size(); ++i) {
|
|
||||||
const Texture2D &texture = textures[i];
|
|
||||||
index = texture.type == TEXTURE_TYPE_DIFFUSE ? diffuse++ : specular++;
|
|
||||||
shader.set_int(texture.name(index).c_str(), texture.texture_unit - GL_TEXTURE0);
|
|
||||||
texture.activate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mesh::activate() {
|
|
||||||
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);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Model::draw(Shader &shader) {
|
|
||||||
shader.activate();
|
|
||||||
|
|
||||||
for (int i = 0; i < meshes.size(); ++i) {
|
|
||||||
meshes[i].draw(shader);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Model::load_model(std::string path) {
|
|
||||||
Assimp::Importer importer;
|
|
||||||
const aiScene *scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs);
|
|
||||||
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) {
|
|
||||||
printf("Failed to load model: %s. Error: %s\n", path.c_str(), importer.GetErrorString());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
directory = path.substr(0, path.find_last_of('/'));
|
|
||||||
process_node(scene->mRootNode, scene);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Model::process_node(aiNode *node, const aiScene *scene) {
|
|
||||||
for (unsigned int i = 0; i < node->mNumMeshes; ++i) {
|
|
||||||
aiMesh *mesh = scene->mMeshes[node->mMeshes[i]];
|
|
||||||
meshes.push_back(process_mesh(mesh, scene));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < node->mNumChildren; ++i) {
|
|
||||||
process_node(node->mChildren[i], scene);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Mesh Model::process_mesh(aiMesh *mesh, const aiScene *scene) {
|
|
||||||
std::vector<Vertex> vertices;
|
|
||||||
std::vector<GLuint> indices;
|
|
||||||
std::vector<Texture2D> textures;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
|
|
||||||
Vertex vertex;
|
|
||||||
|
|
||||||
vertex.position = glm::vec3(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z);
|
|
||||||
vertex.normal = glm::vec3(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z);
|
|
||||||
if (mesh->mTextureCoords[0]) {
|
|
||||||
vertex.tex_coord = glm::vec2(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y);
|
|
||||||
} else {
|
|
||||||
vertex.tex_coord = glm::vec2(0.0f, 0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
vertices.push_back(vertex);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < mesh->mNumFaces; ++i) {
|
|
||||||
aiFace face = mesh->mFaces[i];
|
|
||||||
for (unsigned int j = 0; j < face.mNumIndices; ++j) {
|
|
||||||
indices.push_back(face.mIndices[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mesh->mMaterialIndex >= 0) {
|
|
||||||
aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex];
|
|
||||||
|
|
||||||
std::vector<Texture2D> diffuse_maps = load_material_textures(material, aiTextureType_DIFFUSE);
|
|
||||||
textures.insert(textures.end(), diffuse_maps.begin(), diffuse_maps.end());
|
|
||||||
|
|
||||||
std::vector<Texture2D> specular_maps = load_material_textures(material, aiTextureType_SPECULAR);
|
|
||||||
textures.insert(textures.end(), specular_maps.begin(), specular_maps.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
return Mesh(vertices, indices, textures);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Texture2D> Model::load_material_textures(aiMaterial *material, aiTextureType type) {
|
|
||||||
std::vector<Texture2D> textures;
|
|
||||||
for (unsigned int i = 0; i < material->GetTextureCount(type); ++i) {
|
|
||||||
aiString path;
|
|
||||||
material->GetTexture(type, i, &path);
|
|
||||||
std::string absolute_path = directory + '/' + path.C_Str();
|
|
||||||
|
|
||||||
bool skip = false;
|
|
||||||
for (unsigned int j = 0; j < loaded_textures.size(); ++j) {
|
|
||||||
if (std::strcmp(loaded_textures[j].filename, absolute_path.c_str()) == 0) {
|
|
||||||
textures.push_back(loaded_textures[j]);
|
|
||||||
skip = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!skip) {
|
|
||||||
TextureType tex_type = type == aiTextureType_DIFFUSE ? TEXTURE_TYPE_DIFFUSE : TEXTURE_TYPE_SPECULAR;
|
|
||||||
Texture2D texture = {absolute_path.c_str(), texture_unit++, tex_type};
|
|
||||||
textures.push_back(texture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|