1 Commits

Author SHA1 Message Date
e503f75d62 Fix bug with generating textures 2024-12-07 22:42:32 +00:00
14 changed files with 165 additions and 3556 deletions

1
.gitignore vendored
View File

@@ -1,4 +1,3 @@
.cache
compile_commands.json
main
*.py

3
.gitmodules vendored
View File

@@ -1,3 +0,0 @@
[submodule "src/assimp"]
path = src/assimp
url = git@github.com:assimp/assimp

10
compile
View File

@@ -1,18 +1,18 @@
#!/bin/bash
CC=clang
CFLAGS="-O3 -c -Wall -Isrc/glad/include"
CFLAGS="-g -c -Wall -Isrc/glad/include"
CXX=clang++
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"
CXXFLAGS="-g -Wall -std=c++20 $(pkg-config --cflags sdl2) -Isrc/glad/include -Isrc/glm"
LIBS="$(pkg-config --libs sdl2) -ldl"
GLAD_SRC="src/glad/src/glad.c"
GLAD_OBJ="glad.o"
SRC="src/*.cc $GLAD_OBJ src/glm/glm/glm.cppm"
OUT=main
(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
rm $GLAD_OBJ
rm $GLAD_OBJ
fi

Binary file not shown.

Before

Width:  |  Height:  |  Size: 457 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 526 KiB

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -1,111 +1,13 @@
#version 330 core
#define POINT_LIGHT_COUNT 4
struct Material {
sampler2D diffuse1;
sampler2D specular1;
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;
in vec2 tex_coords;
out vec4 color;
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);
uniform float mix_factor;
uniform sampler2D texture0;
uniform sampler2D texture1;
void main() {
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);
color = mix(texture(texture0, tex_coords), texture(texture1, tex_coords), mix_factor);
};
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.diffuse1, 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.specular1, 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.diffuse1, 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.specular1, 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.diffuse1, uv_coords));
vec3 ambient = light.ambient * diff_tex;
vec3 diffuse = light.diffuse * (diff * diff_tex) * intensity;
vec3 specular = light.specular * (spec * vec3(texture(material.specular1, uv_coords))) * intensity;
return ambient + diffuse + specular;
}

View File

@@ -1,9 +0,0 @@
#version 330 core
out vec4 color;
uniform vec3 light_diffuse;
void main() {
color = vec4(light_diffuse, 1.0);
}

View File

@@ -1,21 +1,15 @@
#version 330 core
layout(location=0) in vec3 position;
layout(location=1) in vec3 normal;
layout(location=2) in vec2 uv;
layout(location=1) 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() {
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);
tex_coords = uv;
gl_Position = projection * view * model * vec4(position, 1.0);
};

Submodule src/assimp deleted from c35200e38e

View File

@@ -1,10 +1,6 @@
// 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"
@@ -14,13 +10,9 @@
#include "glm/gtx/rotate_vector.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"
// STB Image
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
// SDL
#include <SDL2/SDL.h>
@@ -39,15 +31,11 @@
#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,
@@ -61,12 +49,6 @@ 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);
@@ -75,66 +57,6 @@ class Shader {
static const char *get_shader_type_string(GLenum shader_type);
};
enum TextureType : unsigned char {
TEXTURE_TYPE_DIFFUSE,
TEXTURE_TYPE_SPECULAR,
};
class Texture2D {
public:
Texture2D(const char *filename, GLint texture_unit, TextureType type);
~Texture2D();
void activate() const;
std::string name(unsigned int index) const;
int width;
int height;
int channels;
const char *filename;
GLint texture_unit;
TextureType type;
private:
GLuint texture;
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 draw(Shader &Shader);
private:
GLuint vao, vbo, ebo;
void setup_mesh();
};
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);
};
int main() {
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
return EXIT_CODE_SDL_INIT_FAILED;
@@ -164,141 +86,149 @@ 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);
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
glEnable(GL_DEPTH_TEST);
std::vector<Vertex> vertices = {
// 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)},
Vertex{glm::vec3( 0.5f, 0.5f, 0.5f), glm::vec3( 1.0f, 0.0f, 0.0f), glm::vec2(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)},
Vertex{glm::vec3(-0.5f, 0.5f, 0.5f), glm::vec3( 0.0f, 0.0f, 1.0f), glm::vec2(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)},
Vertex{glm::vec3( 0.5f, -0.5f, -0.5f), glm::vec3( 0.0f, -1.0f, 0.0f), glm::vec2(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)},
Vertex{glm::vec3( 0.5f, -0.5f, 0.5f), glm::vec3( 0.0f, 0.0f, 1.0f), glm::vec2(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)},
Vertex{glm::vec3( 0.5f, 0.5f, 0.5f), glm::vec3( 0.0f, 0.0f, 1.0f), glm::vec2(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)},
Vertex{glm::vec3(-0.5f, -0.5f, 0.5f), glm::vec3( 0.0f, -1.0f, 0.0f), glm::vec2(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)},
Vertex{glm::vec3( 0.5f, 0.5f, 0.5f), glm::vec3( 0.0f, 1.0f, 0.0f), glm::vec2(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)},
Vertex{glm::vec3(-0.5f, 0.5f, 0.5f), glm::vec3( 0.0f, 1.0f, 0.0f), glm::vec2(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)},
Vertex{glm::vec3(-0.5f, -0.5f, 0.5f), glm::vec3( 0.0f, 0.0f, 1.0f), glm::vec2(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)},
Vertex{glm::vec3(-0.5f, 0.5f, -0.5f), glm::vec3( 0.0f, 0.0f, -1.0f), glm::vec2(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)},
Vertex{glm::vec3( 0.5f, 0.5f, -0.5f), glm::vec3( 0.0f, 1.0f, 0.0f), glm::vec2(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)},
Vertex{glm::vec3( 0.5f, -0.5f, -0.5f), glm::vec3( 1.0f, 0.0f, 0.0f), glm::vec2(0.0f, 1.0f)},
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
};
std::vector<GLuint> indices = {
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
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
};
Model backpack = {"models/suzanne/suzanne.obj"};
Mesh light = {vertices, indices, {}};
GLuint vao = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
Shader main_shader {"shaders/vert.glsl", "shaders/frag.glsl"};
Shader light_shader {"shaders/vert.glsl", "shaders/light_frag.glsl"};
GLuint ebo = 0;
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), indices.data(), GL_STATIC_DRAW);
GLuint vbo = 0;
glGenBuffers(1, &vbo);
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);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void *)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
stbi_set_flip_vertically_on_load(true);
// 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)
};
const float camera_speed = 25.0f;
glm::vec3 camera_position = glm::vec3(-2.0f, 0.0f, 6.0f);
glm::vec3 camera_position = glm::vec3(0.0f, 0.0f, 4.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 = -70.0f;
float pitch = 0.0f;
float yaw = -90.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);
main_shader.set_mat4 ("projection", projection);
main_shader.set_float("material.shininess", 32.0f);
glUniformMatrix4fv(glGetUniformLocation(main_shader.program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
light_shader.set_mat4("projection", projection);
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( 1.0f, 0.0f, -18.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 * 0.25f);
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 * 0.5f);
main_shader.set_vec3("spot_light.specular", light_specular * 0.25f);
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 * 0.25f);
main_shader.set_vec3(specular, light_specular * 0.5f);
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 = {};
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();
@@ -313,6 +243,10 @@ 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) {
@@ -360,38 +294,35 @@ 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);
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);
glUniformMatrix4fv(glGetUniformLocation(main_shader.program, "view"), 1, GL_FALSE, glm::value_ptr(view));
glClearColor(0.04f, 0.08f, 0.08f, 1.0f);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 0.0f));
normal_mat = glm::transpose(glm::inverse(model));
main_shader.activate();
main_shader.set_mat4("model", model);
main_shader.set_mat3("normal_mat", normal_mat);
backpack.draw(main_shader);
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);
// 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);
light.draw(light_shader);
for (int i = 0; i < sizeof(cube_positions) / sizeof(cube_positions[0]); ++i) {
float angle = 20.0f * 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);
}
SDL_GL_SwapWindow(window);
@@ -425,36 +356,6 @@ 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);
@@ -540,188 +441,3 @@ const char *Shader::get_shader_type_string(GLenum shader_type) {
return output;
}
Texture2D::Texture2D(const char *filename, GLint texture_unit, TextureType type) : filename(filename), texture_unit(texture_unit), type(type) {
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() const {
glActiveTexture(texture_unit);
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::draw(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();
}
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, (void *)0);
glBindVertexArray(0);
}
void Model::draw(Shader &shader) {
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;
}