Compare commits
12 Commits
00-getting
...
01-lightin
Author | SHA1 | Date | |
---|---|---|---|
c65a3ba314 | |||
b7e5eea448 | |||
e720355d04 | |||
fbda4821ee | |||
cc1f6afb26 | |||
621204abe5 | |||
1193e128e8 | |||
d0070045b1 | |||
6bcd4802aa | |||
9cbfa55c89 | |||
d8ab418180 | |||
babe58f0a5 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
.cache
|
||||
compile_commands.json
|
||||
main
|
||||
*.py
|
||||
|
BIN
images/container2.png
Normal file
BIN
images/container2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 457 KiB |
BIN
images/container2_specular.png
Normal file
BIN
images/container2_specular.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 141 KiB |
@@ -1,13 +1,111 @@
|
||||
#version 330 core
|
||||
|
||||
in vec2 tex_coords;
|
||||
#define POINT_LIGHT_COUNT 4
|
||||
|
||||
struct Material {
|
||||
sampler2D diffuse;
|
||||
sampler2D specular;
|
||||
float shininess;
|
||||
};
|
||||
|
||||
struct DirLight {
|
||||
vec3 direction;
|
||||
vec3 ambient;
|
||||
vec3 diffuse;
|
||||
vec3 specular;
|
||||
};
|
||||
|
||||
struct PointLight {
|
||||
vec3 position;
|
||||
vec3 ambient;
|
||||
vec3 diffuse;
|
||||
vec3 specular;
|
||||
float constant;
|
||||
float linear;
|
||||
float quadratic;
|
||||
};
|
||||
|
||||
struct SpotLight {
|
||||
vec3 position;
|
||||
vec3 direction;
|
||||
vec3 ambient;
|
||||
vec3 diffuse;
|
||||
vec3 specular;
|
||||
float cutoff;
|
||||
float outer_cutoff;
|
||||
};
|
||||
|
||||
in vec3 vert_normal;
|
||||
in vec3 frag_position;
|
||||
in vec2 uv_coords;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform float mix_factor;
|
||||
uniform sampler2D texture0;
|
||||
uniform sampler2D texture1;
|
||||
uniform Material material;
|
||||
uniform DirLight directional_light;
|
||||
uniform PointLight point_lights[POINT_LIGHT_COUNT];
|
||||
uniform SpotLight spot_light;
|
||||
uniform vec3 camera_position;
|
||||
|
||||
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_spot_light(SpotLight light, vec3 normal, vec3 frag_position, vec3 view_direction);
|
||||
|
||||
void main() {
|
||||
color = mix(texture(texture0, tex_coords), texture(texture1, tex_coords), mix_factor);
|
||||
vec3 normal = normalize(vert_normal);
|
||||
vec3 view_direction = normalize(camera_position - frag_position);
|
||||
|
||||
vec3 result = calc_dir_light(directional_light, normal, view_direction);
|
||||
|
||||
for (int i = 0; i < POINT_LIGHT_COUNT; ++i) {
|
||||
result += calc_point_light(point_lights[i], normal, frag_position, view_direction);
|
||||
}
|
||||
|
||||
result += calc_spot_light(spot_light, normal, frag_position, view_direction);
|
||||
|
||||
color = vec4(result, 1.0);
|
||||
};
|
||||
|
||||
vec3 calc_dir_light(DirLight light, vec3 normal, vec3 view_direction) {
|
||||
vec3 light_direction = normalize(-light.direction);
|
||||
vec3 reflect_direction = reflect(-light_direction, normal);
|
||||
float diff = max(dot(normal, light_direction), 0.0);
|
||||
vec3 diff_tex = vec3(texture(material.diffuse, uv_coords));
|
||||
float spec = pow(max(dot(reflect_direction, view_direction), 0.0), material.shininess);
|
||||
vec3 ambient = light.ambient * diff_tex;
|
||||
vec3 diffuse = light.diffuse * (diff * diff_tex);
|
||||
vec3 specular = light.specular * (spec * vec3(texture(material.specular, uv_coords)));
|
||||
|
||||
return ambient + diffuse + specular;
|
||||
}
|
||||
|
||||
vec3 calc_point_light(PointLight light, vec3 normal, vec3 frag_position, vec3 view_direction) {
|
||||
vec3 light_direction = normalize(light.position - frag_position);
|
||||
vec3 reflect_direction = reflect(-light_direction, normal);
|
||||
float distance = length(light.position - frag_position);
|
||||
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
|
||||
float diff = max(dot(normal, light_direction), 0.0);
|
||||
vec3 diff_tex = vec3(texture(material.diffuse, uv_coords));
|
||||
float spec = pow(max(dot(reflect_direction, view_direction), 0.0), material.shininess);
|
||||
vec3 ambient = light.ambient * diff_tex * attenuation;
|
||||
vec3 diffuse = light.diffuse * (diff * diff_tex) * attenuation;
|
||||
vec3 specular = light.specular * (spec * vec3(texture(material.specular, uv_coords))) * attenuation;
|
||||
|
||||
return ambient + diffuse + specular;
|
||||
}
|
||||
|
||||
vec3 calc_spot_light(SpotLight light, vec3 normal, vec3 frag_position, vec3 view_direction) {
|
||||
vec3 light_direction = normalize(light.position - frag_position);
|
||||
vec3 reflect_direction = reflect(-light_direction, normal);
|
||||
float theta = dot(light_direction, normalize(-light.direction));
|
||||
float epsilon = light.cutoff - light.outer_cutoff;
|
||||
float intensity = clamp((theta - light.outer_cutoff) / epsilon, 0.0, 1.0);
|
||||
float diff = max(dot(normal, light_direction), 0.0);
|
||||
float spec = pow(max(dot(reflect_direction, view_direction), 0.0), material.shininess);
|
||||
vec3 diff_tex = vec3(texture(material.diffuse, uv_coords));
|
||||
vec3 ambient = light.ambient * diff_tex;
|
||||
vec3 diffuse = light.diffuse * (diff * diff_tex) * intensity;
|
||||
vec3 specular = light.specular * (spec * vec3(texture(material.specular, uv_coords))) * intensity;
|
||||
|
||||
return ambient + diffuse + specular;
|
||||
}
|
||||
|
9
shaders/light_frag.glsl
Normal file
9
shaders/light_frag.glsl
Normal file
@@ -0,0 +1,9 @@
|
||||
#version 330 core
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform vec3 light_diffuse;
|
||||
|
||||
void main() {
|
||||
color = vec4(light_diffuse, 1.0);
|
||||
}
|
@@ -1,15 +1,21 @@
|
||||
#version 330 core
|
||||
|
||||
layout(location=0) in vec3 position;
|
||||
layout(location=1) in vec2 uv;
|
||||
layout(location=1) in vec3 normal;
|
||||
layout(location=2) in vec2 uv;
|
||||
|
||||
out vec3 vert_normal;
|
||||
out vec3 frag_position;
|
||||
out vec2 uv_coords;
|
||||
|
||||
uniform mat3 normal_mat;
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
out vec2 tex_coords;
|
||||
|
||||
void main() {
|
||||
tex_coords = uv;
|
||||
gl_Position = projection * view * model * vec4(position, 1.0);
|
||||
vert_normal = normal_mat * normal;
|
||||
frag_position = vec3(model * vec4(position, 1.0));
|
||||
uv_coords = uv;
|
||||
gl_Position = projection * view * model * vec4(position, 1.0);
|
||||
};
|
||||
|
393
src/main.cc
393
src/main.cc
@@ -1,6 +1,10 @@
|
||||
// GLAD
|
||||
#include "glad/glad.h"
|
||||
|
||||
// STB Image
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
|
||||
// GLM
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include "glm/ext/matrix_transform.hpp"
|
||||
@@ -10,10 +14,6 @@
|
||||
#include "glm/gtx/rotate_vector.hpp"
|
||||
#include "glm/gtx/string_cast.hpp"
|
||||
|
||||
// STB Image
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
|
||||
// SDL
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_timer.h>
|
||||
@@ -31,11 +31,15 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#define WINDOW_WIDTH 1280
|
||||
#define WINDOW_HEIGHT 720
|
||||
#define WINDOW_HALF_WIDTH 640
|
||||
#define WINDOW_WIDTH 1280
|
||||
#define WINDOW_HEIGHT 720
|
||||
#define WINDOW_HALF_WIDTH 640
|
||||
#define WINDOW_HALF_HEIGHT 360
|
||||
|
||||
#define min(a, b) (a < b ? a : b)
|
||||
#define max(a, b) (a > b ? a : b)
|
||||
#define clamp(v, a, b) (min(max(v, a), b))
|
||||
|
||||
enum exit_codes : int {
|
||||
EXIT_CODE_SUCCESS,
|
||||
EXIT_CODE_SDL_INIT_FAILED,
|
||||
@@ -49,6 +53,12 @@ class Shader {
|
||||
Shader(const std::string &vert_file, const std::string &frag_file);
|
||||
~Shader();
|
||||
void activate();
|
||||
void set_int(const char *name, int value);
|
||||
void set_float(const char *name, float value);
|
||||
void set_vec3(const char *name, glm::vec3 vector);
|
||||
void set_vec4(const char *name, glm::vec4 vector);
|
||||
void set_mat3(const char *name, glm::mat3 matrix);
|
||||
void set_mat4(const char *name, glm::mat4 matrix);
|
||||
GLuint program;
|
||||
private:
|
||||
void link_program(GLuint vert, GLuint frag);
|
||||
@@ -57,6 +67,20 @@ class Shader {
|
||||
static const char *get_shader_type_string(GLenum shader_type);
|
||||
};
|
||||
|
||||
class Texture2D {
|
||||
public:
|
||||
Texture2D(const char *filename, GLint texture_unit);
|
||||
~Texture2D();
|
||||
void activate();
|
||||
int width;
|
||||
int height;
|
||||
int channels;
|
||||
private:
|
||||
GLuint texture;
|
||||
GLint texture_unit;
|
||||
GLint format;
|
||||
};
|
||||
|
||||
int main() {
|
||||
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
|
||||
return EXIT_CODE_SDL_INIT_FAILED;
|
||||
@@ -86,49 +110,53 @@ int main() {
|
||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||
SDL_WarpMouseInWindow(window, WINDOW_HALF_WIDTH, WINDOW_HALF_HEIGHT);
|
||||
|
||||
// Set texture options
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
stbi_set_flip_vertically_on_load(true);
|
||||
|
||||
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
std::vector<GLfloat> vertices = {
|
||||
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, // position, uv
|
||||
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f, // position, uv
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, // position, uv
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, // position, uv
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, // position, uv
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, // position, uv
|
||||
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, // position, uv
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, // position, uv
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, // position, uv
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, // position, uv
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, // position, uv
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, // position, uv
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, // position, uv
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, // position, uv
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, // position, uv
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 1.0f, // position, uv
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f // position, uv
|
||||
// positions // normals // texture coords
|
||||
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f,
|
||||
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
|
||||
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
|
||||
};
|
||||
|
||||
std::vector<GLuint> indices = {
|
||||
14, 5, 9,
|
||||
9, 7, 14,
|
||||
4, 3, 12,
|
||||
12, 8, 4,
|
||||
1, 6, 13,
|
||||
13, 4, 1,
|
||||
2, 9, 15,
|
||||
15, 0, 2,
|
||||
13, 10, 3,
|
||||
3, 4, 13,
|
||||
7, 9, 2,
|
||||
2, 11, 16
|
||||
6, 14, 12,
|
||||
12, 19, 6,
|
||||
17, 7, 9,
|
||||
9, 3, 17,
|
||||
22, 20, 0,
|
||||
0, 18, 22,
|
||||
1, 2, 23,
|
||||
23, 4, 1,
|
||||
8, 5, 10,
|
||||
10, 11, 8,
|
||||
16, 21, 13,
|
||||
13, 15, 16
|
||||
};
|
||||
|
||||
GLuint vao = 0;
|
||||
@@ -145,90 +173,130 @@ int main() {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), vertices.data(), GL_STATIC_DRAW);
|
||||
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void *)0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void *)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void *)(3 * sizeof(GLfloat)));
|
||||
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);
|
||||
|
||||
GLuint light_vao = 0;
|
||||
glGenVertexArrays(1, &light_vao);
|
||||
glBindVertexArray(light_vao);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void *)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
stbi_set_flip_vertically_on_load(true);
|
||||
Shader main_shader {"shaders/vert.glsl", "shaders/frag.glsl"};
|
||||
Shader light_shader {"shaders/vert.glsl", "shaders/light_frag.glsl"};
|
||||
|
||||
// Load texture
|
||||
int32_t width[2], height[2], channels[2];
|
||||
uint8_t *container = stbi_load("images/container.jpg", &width[0], &height[0], &channels[0], 0);
|
||||
uint8_t *awesomeface = stbi_load("images/awesomeface.png", &width[1], &height[1], &channels[1], 0);
|
||||
|
||||
GLuint textures[2];
|
||||
glGenTextures(2, textures);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0); // activate the texture unit first before binding texture
|
||||
glBindTexture(GL_TEXTURE_2D, textures[0]);
|
||||
if (container) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width[0], height[0], 0, GL_RGB, GL_UNSIGNED_BYTE, container);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
stbi_image_free(container);
|
||||
} else {
|
||||
printf("Failed to load container texture \n");
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE1); // activate the texture unit first before binding texture
|
||||
glBindTexture(GL_TEXTURE_2D, textures[1]);
|
||||
if (awesomeface) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width[1], height[1], 0, GL_RGBA, GL_UNSIGNED_BYTE, awesomeface);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
stbi_image_free(awesomeface);
|
||||
} else {
|
||||
printf("Failed to load container texture \n");
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
Shader main_shader {"shaders/vert.glsl", "shaders/frag.glsl"};
|
||||
main_shader.activate();
|
||||
glUniform1i(glGetUniformLocation(main_shader.program, "texture0"), 0);
|
||||
glUniform1i(glGetUniformLocation(main_shader.program, "texture1"), 1);
|
||||
|
||||
float texture_mix_factor = 0.2f;
|
||||
|
||||
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)
|
||||
};
|
||||
Texture2D diffuse_map = Texture2D("images/container2.png", GL_TEXTURE0);
|
||||
Texture2D specular_map = Texture2D("images/container2_specular.png", GL_TEXTURE1);
|
||||
main_shader.set_int("material.diffuse", 0);
|
||||
main_shader.set_int("material.specular", 1);
|
||||
|
||||
const float camera_speed = 25.0f;
|
||||
glm::vec3 camera_position = glm::vec3(0.0f, 0.0f, 4.0f);
|
||||
glm::vec3 camera_position = glm::vec3(-2.0f, 0.0f, 6.0f);
|
||||
glm::vec3 camera_forward = glm::vec3(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_diffuse = glm::vec3(0.75f, 0.75f, 0.75f);
|
||||
glm::vec3 light_specular = glm::vec3(1.0f, 1.0f, 1.0f);
|
||||
|
||||
float yaw = -90.0f;
|
||||
float pitch = 0.0f;
|
||||
float yaw = -70.0f;
|
||||
float pitch = 0.0f;
|
||||
|
||||
glm::mat4 model = glm::mat4(1.0f);
|
||||
glm::mat4 view = glm::mat4(1.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);
|
||||
|
||||
glUniformMatrix4fv(glGetUniformLocation(main_shader.program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||
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);
|
||||
|
||||
const float sensitivity = 0.1f;
|
||||
int last_mouse_x = WINDOW_HALF_WIDTH;
|
||||
int last_mouse_y = WINDOW_HALF_HEIGHT;
|
||||
uint32_t last_frame = SDL_GetTicks();
|
||||
float delta = 0.0f;
|
||||
bool running = true;
|
||||
SDL_Event event = {};
|
||||
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 = {
|
||||
glm::vec3( 0.7f, 0.2f, 2.0f),
|
||||
glm::vec3( 2.3f, -3.3f, -4.0f),
|
||||
glm::vec3(-4.0f, 2.0f, -12.0f),
|
||||
glm::vec3( 0.0f, 0.0f, -3.0f)
|
||||
};
|
||||
|
||||
// Setup lights
|
||||
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.diffuse", light_diffuse);
|
||||
main_shader.set_vec3("directional_light.specular", light_specular);
|
||||
|
||||
main_shader.set_vec3("spot_light.ambient", light_ambient);
|
||||
main_shader.set_vec3("spot_light.diffuse", light_diffuse);
|
||||
main_shader.set_vec3("spot_light.specular", light_specular);
|
||||
|
||||
for (int i = 0; i < point_light_positions.size(); ++i) {
|
||||
char base[256] = {0};
|
||||
char position[512] = {0};
|
||||
char ambient[512] = {0};
|
||||
char diffuse[512] = {0};
|
||||
char specular[512] = {0};
|
||||
char constant[512] = {0};
|
||||
char linear[512] = {0};
|
||||
char quadratic[512] = {0};
|
||||
|
||||
snprintf(base, sizeof(base) - 1, "point_lights[%d]", i);
|
||||
snprintf(position, sizeof(position) - 1, "%s.position", base);
|
||||
snprintf(ambient, sizeof(ambient) - 1, "%s.ambient", base);
|
||||
snprintf(diffuse, sizeof(diffuse) - 1, "%s.diffuse", base);
|
||||
snprintf(specular, sizeof(specular) - 1, "%s.specular", base);
|
||||
snprintf(constant, sizeof(constant) - 1, "%s.constant", base);
|
||||
snprintf(linear, sizeof(linear) - 1, "%s.linear", base);
|
||||
snprintf(quadratic, sizeof(quadratic) - 1, "%s.quadratic", base);
|
||||
|
||||
main_shader.set_vec3(position, point_light_positions[i]);
|
||||
main_shader.set_vec3(ambient, light_ambient);
|
||||
main_shader.set_vec3(diffuse, light_diffuse);
|
||||
main_shader.set_vec3(specular, light_specular);
|
||||
main_shader.set_float(constant, 1.0f);
|
||||
main_shader.set_float(linear, 0.09f);
|
||||
main_shader.set_float(quadratic, 0.032f);
|
||||
|
||||
memset(base, 0, sizeof(base));
|
||||
memset(position, 0, sizeof(position));
|
||||
memset(ambient, 0, sizeof(ambient));
|
||||
memset(diffuse, 0, sizeof(diffuse));
|
||||
memset(specular, 0, sizeof(specular));
|
||||
memset(constant, 0, sizeof(constant));
|
||||
memset(linear, 0, sizeof(linear));
|
||||
memset(quadratic, 0, sizeof(quadratic));
|
||||
}
|
||||
|
||||
const float sensitivity = 0.1f;
|
||||
int last_mouse_x = WINDOW_HALF_WIDTH;
|
||||
int last_mouse_y = WINDOW_HALF_HEIGHT;
|
||||
uint32_t last_frame = SDL_GetTicks();
|
||||
float delta = 0.0f;
|
||||
bool running = true;
|
||||
SDL_Event event = {};
|
||||
|
||||
while (running) {
|
||||
uint32_t ticks = SDL_GetTicks();
|
||||
@@ -243,10 +311,6 @@ int main() {
|
||||
case SDL_KEYDOWN:
|
||||
if (event.key.keysym.sym == SDLK_ESCAPE) {
|
||||
running = false;
|
||||
} else if (event.key.keysym.sym == SDLK_UP) {
|
||||
texture_mix_factor += 0.1f;
|
||||
} else if (event.key.keysym.sym == SDLK_DOWN) {
|
||||
texture_mix_factor -= 0.1f;
|
||||
} else if (event.key.keysym.sym == SDLK_w) {
|
||||
camera_position += camera_speed * delta * camera_forward;
|
||||
} else if (event.key.keysym.sym == SDLK_s) {
|
||||
@@ -294,35 +358,45 @@ int main() {
|
||||
}
|
||||
}
|
||||
|
||||
texture_mix_factor = texture_mix_factor < 0.0f ?
|
||||
0.0f : texture_mix_factor > 1.0f ?
|
||||
1.0f : texture_mix_factor;
|
||||
|
||||
camera_forward.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
|
||||
camera_forward.y = sin(glm::radians(pitch));
|
||||
camera_forward.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
|
||||
camera_forward = glm::normalize(camera_forward);
|
||||
|
||||
view = glm::lookAt(camera_position, camera_position + camera_forward, world_up);
|
||||
glUniformMatrix4fv(glGetUniformLocation(main_shader.program, "view"), 1, GL_FALSE, glm::value_ptr(view));
|
||||
main_shader.set_vec3("camera_position", camera_position);
|
||||
main_shader.set_vec3("spot_light.position", camera_position);
|
||||
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.outer_cutoff", glm::cos(glm::radians(17.5)));
|
||||
main_shader.set_mat4("view", view);
|
||||
light_shader.set_mat4("view", view);
|
||||
|
||||
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||
glClearColor(0.04f, 0.08f, 0.08f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
main_shader.activate();
|
||||
glUniform1f(glGetUniformLocation(main_shader.program, "mix_factor"), texture_mix_factor);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, textures[0]);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, textures[1]);
|
||||
glBindVertexArray(vao);
|
||||
|
||||
for (int i = 0; i < sizeof(cube_positions) / sizeof(cube_positions[0]); ++i) {
|
||||
float angle = 20.0f * i;
|
||||
for (int i = 0; i < cube_positions.size(); ++i) {
|
||||
model = glm::translate(glm::mat4(1.0f), cube_positions[i]);
|
||||
model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));
|
||||
glUniformMatrix4fv(glGetUniformLocation(main_shader.program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, (void *)0);
|
||||
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);
|
||||
}
|
||||
|
||||
// Draw light source
|
||||
for (int i = 0; i < point_light_positions.size(); ++i) {
|
||||
model = glm::translate(glm::mat4(1.0f), point_light_positions[i]);
|
||||
model = glm::scale(model, glm::vec3(0.2f));
|
||||
light_shader.activate();
|
||||
light_shader.set_mat4("model", model);
|
||||
light_shader.set_vec3("light_diffuse", light_diffuse);
|
||||
glBindVertexArray(light_vao);
|
||||
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, (void *)0);
|
||||
}
|
||||
|
||||
SDL_GL_SwapWindow(window);
|
||||
@@ -356,6 +430,36 @@ void Shader::activate() {
|
||||
}
|
||||
}
|
||||
|
||||
void Shader::set_int(const char *name, int value) {
|
||||
activate();
|
||||
glUniform1i(glGetUniformLocation(program, name), value);
|
||||
}
|
||||
|
||||
void Shader::set_float(const char *name, float value) {
|
||||
activate();
|
||||
glUniform1f(glGetUniformLocation(program, name), value);
|
||||
}
|
||||
|
||||
void Shader::set_vec3(const char *name, glm::vec3 vector) {
|
||||
activate();
|
||||
glUniform3f(glGetUniformLocation(program, name), vector.x, vector.y, vector.z);
|
||||
}
|
||||
|
||||
void Shader::set_vec4(const char *name, glm::vec4 vector) {
|
||||
activate();
|
||||
glUniform4f(glGetUniformLocation(program, name), vector.x, vector.y, vector.z, vector.w);
|
||||
}
|
||||
|
||||
void Shader::set_mat3(const char *name, glm::mat3 matrix) {
|
||||
activate();
|
||||
glUniformMatrix3fv(glGetUniformLocation(program, name), 1, GL_FALSE, glm::value_ptr(matrix));
|
||||
}
|
||||
|
||||
void Shader::set_mat4(const char *name, glm::mat4 matrix) {
|
||||
activate();
|
||||
glUniformMatrix4fv(glGetUniformLocation(program, name), 1, GL_FALSE, glm::value_ptr(matrix));
|
||||
}
|
||||
|
||||
void Shader::link_program(GLuint vert, GLuint frag) {
|
||||
program = glCreateProgram();
|
||||
glAttachShader(program, vert);
|
||||
@@ -441,3 +545,34 @@ const char *Shader::get_shader_type_string(GLenum shader_type) {
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
Texture2D::Texture2D(const char *filename, GLint texture_unit) : texture_unit(texture_unit) {
|
||||
uint8_t *image = stbi_load(filename, &width, &height, &channels, 0);
|
||||
if (!image) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO (Abdelrahman): This doesn't handle all formats
|
||||
format = channels > 3 ? GL_RGBA : GL_RGB;
|
||||
|
||||
glGenTextures(1, &texture);
|
||||
activate();
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
stbi_image_free(image);
|
||||
}
|
||||
|
||||
Texture2D::~Texture2D() {}
|
||||
|
||||
void Texture2D::activate() {
|
||||
glActiveTexture(texture_unit);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
}
|
||||
|
Reference in New Issue
Block a user