Added model loading

Model loading is complex.
As such in the learnopengl.com tutorial we use assimp to make our life
a little easier.
This commit is contained in:
Nigel Barink 2022-02-22 00:32:22 +01:00
parent de96aa4136
commit 82cf5b9c93
24 changed files with 487 additions and 480 deletions

3
.gitattributes vendored Normal file
View File

@ -0,0 +1,3 @@
*.obj filter=lfs diff=lfs merge=lfs -text
*.mtl filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
lib/
build/
.vscode

View File

@ -1,6 +1,6 @@
CC = g++
CFLAGS = -std=c++17 -O2
LDFLAGS = -lglfw3 -lGL -ldl -lpthread -lX11 -lXxf86vm -lXrandr -lXi
CFLAGS = -std=c++17 -O2 -g
LDFLAGS = -lglfw3 -lGL -ldl -lpthread -lX11 -lXxf86vm -lXrandr -lXi -lz -lassimp
OUT_NAME = LearnOpenGL
build: src/*.cpp src/*.h
@ -9,4 +9,4 @@ build: src/*.cpp src/*.h
run: build build/$(OUT_NAME)
./build/$(OUT_NAME)
./build/$(OUT_NAME)

BIN
Models/ao.jpg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Models/backpack.mtl (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Models/backpack.obj (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Models/diffuse.jpg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Models/normal.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 MiB

BIN
Models/roughness.jpg (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,3 @@
Model by Berk Gedik, from: https://sketchfab.com/3d-models/survival-guitar-backpack-low-poly-799f8c4511f84fab8c3f12887f7e6b36
Modified material assignment (Joey de Vries) for easier load in OpenGL model loading chapter, and renamed albedo to diffuse and metallic to specular to match non-PBR lighting setup.

BIN
Models/specular.jpg (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 181 KiB

After

Width:  |  Height:  |  Size: 131 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 251 KiB

After

Width:  |  Height:  |  Size: 131 B

View File

@ -1,99 +1,11 @@
#version 460 core
out vec4 FragColor;
in vec3 Normal;
in vec3 FragPos;
in vec2 TexCoords;
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
struct DirLight {
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
struct PointLight{
vec3 position;
float constant;
float linear;
float quadratic;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
#define NR_POINT_LIGHTS 4
uniform PointLight PointLights[NR_POINT_LIGHTS];
uniform DirLight dirlight;
uniform Material material;
uniform vec3 viewPos;
vec3 CalcDirLight(DirLight light , vec3 normal , vec3 viewDir)
{
vec3 lightDir = normalize(-light.direction);
float diff = max(dot(normal,lightDir), 0.0);
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 ambient = light.ambient * vec3 (texture(material.diffuse, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
return (ambient + diffuse + specular);
}
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(light.position - fragPos );
float diff = max(dot(normal, lightDir), 0.0);
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance *distance));
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return (ambient + diffuse + specular);
}
uniform sampler2D texture_diffuse1;
void main()
{
vec3 norm = normalize(Normal);
vec3 viewDir = normalize(viewPos - FragPos);
// Fase 1 : Directional lighting
vec3 result = CalcDirLight(dirlight, norm, viewDir);
// Fase 2 : Point lights
for( int i = 0; i < NR_POINT_LIGHTS; i++){
result += CalcPointLight(PointLights[i], norm, FragPos, viewDir);
}
FragColor = vec4(result, 1.0);
FragColor = texture( texture_diffuse1, TexCoords);
}

View File

@ -7,15 +7,11 @@ uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoords;
void main(){
gl_Position = projection * view * model * vec4(aPos , 1.0);
FragPos = vec3(model * vec4(aPos, 1.0));
Normal = mat3(transpose(inverse(model))) * aNormal;
TexCoords = aTexCoords;
}

View File

@ -8,10 +8,9 @@
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "stb_image.h"
#include "shader.h"
#include "camera.h"
#include "model.h"
float deltaTime = 0.0f; // Time between current frame and last frame
float lastFrame = 0.0f; // Time of last frame
@ -86,148 +85,19 @@ int main() {
glViewport(0,0, 800, 600);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
//glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glfwSetCursorPosCallback(window, mouse_callback);
glfwSetScrollCallback(window, scroll_callback);
glEnable(GL_DEPTH_TEST);
stbi_set_flip_vertically_on_load(true);
Shader lightshader("lightsource.vs", "lightsource.fs");
Shader shader ("shader.vs", "shader.fs");
float vertices[] = {
// positions // normals // texture coords
-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, 0.0f, -1.0f, 1.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, 0.0f, -1.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, 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, 0.0f, 1.0f, 1.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, 0.0f, 1.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, 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, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-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, 0.0f, 0.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, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
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, 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, 1.0f, 0.0f, 0.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, -1.0f, 0.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, 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, 1.0f, 0.0f, 0.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, 0.0f, 1.0f, 0.0f, 1.0f, 0.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, 1.0f, 0.0f, 0.0f, 1.0f
};
glm::vec3 cubePositions[] = {
glm::vec3( 0.0f, 0.0f, 0.0f),
glm::vec3( 2.0f, 5.0f, -15.0f),
glm::vec3(-1.5f, -2.2f, -2.5f),
glm::vec3(-3.8f, -2.0f, -12.3f),
glm::vec3( 2.4f, -0.4f, -3.5f),
glm::vec3(-1.7f, 3.0f, -7.5f),
glm::vec3( 1.3f, -2.0f, -2.5f),
glm::vec3( 1.5f, 2.0f, -2.5f),
glm::vec3( 1.5f, 0.2f, -1.5f),
glm::vec3(-1.3f, 1.0f, -1.5f)
};
glm::vec3 lightPositions[] = {
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)
};
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*) (3*sizeof(float)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2,2,GL_FLOAT,GL_FALSE, 8 * sizeof(float), (void*) (6*sizeof(float)));
glEnableVertexAttribArray(2);
Model backpack("Models/backpack.obj");
unsigned int lightVAO;
glGenVertexArrays(1, &lightVAO);
glBindVertexArray(lightVAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE, 8* sizeof(float), (void*) 0);
glEnableVertexAttribArray(0);
// Load diffuse texture
int width, height, nrChannels;
unsigned int diffuseMap;
glGenTextures(1, &diffuseMap);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, diffuseMap);
glTextureParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTextureParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
unsigned char* data = stbi_load("Textures/container2.png", &width, &height, &nrChannels, 0);
if(data){
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
} else{
std::cout << "Error loading texture...." << std::endl;
}
stbi_image_free(data);
// Load Specular texture
unsigned int specularMap;
glGenTextures(1, &specularMap);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, specularMap);
unsigned char* specular_data = stbi_load("Textures/container2_specular.png", &width, &height, &nrChannels, 0);
if( specular_data ){
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, specular_data);
glGenerateMipmap(GL_TEXTURE_2D);
}else{
std::cout << "Error loading texture...." << std::endl;
}
stbi_image_free(specular_data);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glfwSetCursorPosCallback(window, mouse_callback);
glfwSetScrollCallback(window, scroll_callback);
glEnable(GL_DEPTH_TEST);
while(!glfwWindowShouldClose(window))
@ -241,155 +111,28 @@ while(!glfwWindowShouldClose(window))
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shader.use();
glm::mat4 model = glm::mat4(1.0f);
glm::mat4 view = glm::mat4(1.0f);
glm::mat4 projection = glm::mat4(1.0f);
view = camera.GetViewMatrix();
projection = glm::perspective(glm::radians(camera.Zoom), (float)800 / (float)600, 0.1f, 100.0f);
float orbital_speed = .4 ;
// draw cubes
shader.use();
shader.setInt("material.diffuse", 0);
shader.setInt("material.specular", 1);
shader.setVec3("material.specular", glm::vec3(0.5, 0.5f, 0.5f));
shader.setFloat("material.shininess", 32.0f);
/*
Directional light
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
*/
shader.setVec3("dirlight.direction", glm::vec3(1.0f,0.0f, 2.0f));
shader.setVec3("dirlight.ambient", glm::vec3(0.2f, 0.2f, 0.2f));
shader.setVec3("dirlight.diffuse", glm::vec3(0.5f, 0.5f, 0.5f));
shader.setVec3("dirlight.specular", glm::vec3(1.0f, 1.0f, 1.0f));
/*
Point Lights;
*/
shader.setVec3("PointLights[0].position", glm::vec3( 0.7f, 0.2f, 2.0f));
shader.setVec3("PointLights[1].position", glm::vec3( 2.3f, -3.3f, -4.0f));
shader.setVec3("PointLights[2].position", glm::vec3(-4.0f, 2.0f, -12.0f));
shader.setVec3("PointLights[3].position", glm::vec3( 0.0f, 0.0f, -3.0f));
shader.setVec3("PointLights[0].ambient", glm::vec3(0.2f, 0.2f, 0.2f));
shader.setVec3("PointLights[0].diffuse", glm::vec3(0.5f, 0.5f, 0.5f));
shader.setVec3("PointLights[0].specular", glm::vec3(1.0f, 1.0f, 1.0f));
shader.setVec3("PointLights[1].ambient", glm::vec3(0.2f, 0.2f, 0.2f));
shader.setVec3("PointLights[1].diffuse", glm::vec3(0.5f, 0.5f, 0.5f));
shader.setVec3("PointLights[1].specular", glm::vec3(1.0f, 1.0f, 1.0f));
shader.setVec3("PointLights[2].ambient", glm::vec3(0.2f, 0.2f, 0.2f));
shader.setVec3("PointLights[2].diffuse", glm::vec3(0.5f, 0.5f, 0.5f));
shader.setVec3("PointLights[2].specular", glm::vec3(1.0f, 1.0f, 1.0f));
shader.setVec3("PointLights[3].ambient", glm::vec3(0.2f, 0.2f, 0.2f));
shader.setVec3("PointLights[3].diffuse", glm::vec3(0.5f, 0.5f, 0.5f));
shader.setVec3("PointLights[3].specular", glm::vec3(1.0f, 1.0f, 1.0f));
shader.setFloat("PointLights[0].constant", 1.0f);
shader.setFloat("PointLights[1].constant", 1.0f);
shader.setFloat("PointLights[2].constant", 1.0f);
shader.setFloat("PointLights[3].constant", 1.0f);
shader.setFloat("PointLights[0].linear", 0.09f);
shader.setFloat("PointLights[1].linear", 0.09f);
shader.setFloat("PointLights[2].linear", 0.09f);
shader.setFloat("PointLights[3].linear", 0.09f);
shader.setFloat("PointLights[0].quadratic", 0.032f);
shader.setFloat("PointLights[1].quadratic", 0.032f);
shader.setFloat("PointLights[2].quadratic", 0.032f);
shader.setFloat("PointLights[3].quadratic", 0.032f);
shader.setVec3("viewPos", camera.Position);
shader.setMat4("view", view);
shader.setMat4("projection", projection);
projection = glm::perspective(glm::radians(camera.Zoom), (float)800 / (float)600, 0.1f, 100.0f);
model = glm::mat4(1.0);
shader.setMat4("projection", projection);
shader.setMat4("view", view);
shader.setMat4("model", model);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, diffuseMap);
backpack.Draw(shader);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, specularMap);
for( unsigned int i = 0; i < 10; i++ ){
glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model , cubePositions[i]);
float angle = 20.0f * i;
model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));
shader.setMat4("model", model);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 36);
}
// draw lights
lightshader.use();
lightshader.setMat4("view", view);
lightshader.setMat4("projection", projection);
model = glm::mat4(1.0f);
model = glm::translate(model, lightpos);
model = glm::scale(model, glm::vec3(0.2f));
for ( int i = 0; i < 4 ; i ++){
model = glm::translate(model, lightPositions[i]);
lightshader.setMat4("model", model);
glBindVertexArray(lightVAO);
glDrawArrays(GL_TRIANGLES, 0, 36);
}
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &VAO);
glDeleteVertexArrays(1, &lightVAO);
glDeleteBuffers(1, &VBO);
glfwTerminate();

65
src/mesh.cpp Normal file
View File

@ -0,0 +1,65 @@
#include "mesh.h"
Mesh::Mesh(std::vector<Vertex> vertices, std::vector<unsigned int> indices, std::vector<Texture> textures)
: vertices(vertices) , indices(indices), textures(textures){
setupMesh();
}
void Mesh::setupMesh(){
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
// vertex positions
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) 0);
// vertex normals
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal));
// vertex texture coords
glEnableVertexAttribArray(2);
glVertexAttribPointer(2,2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, TexCoords));
glBindVertexArray(0);
}
void Mesh::Draw( Shader &shader){
unsigned int diffuseNr = 1;
unsigned int specularNr = 1;
for(unsigned int i = 0; i < textures.size(); i++){
glActiveTexture(GL_TEXTURE0 + i);
std::string number;
std::string name = textures[i].type;
if( name == "texture_diffuse")
number = std::to_string(diffuseNr++);
else if(name == "texture_specular")
number = std::to_string(specularNr++);
glUniform1i( glGetUniformLocation( shader.ID, (name + number).c_str()), i);
glBindTexture(GL_TEXTURE_2D, textures[i].id);
}
// draw mesh
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, static_cast <unsigned int>(indices.size()), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glActiveTexture(GL_TEXTURE0);
}

28
src/mesh.h Normal file
View File

@ -0,0 +1,28 @@
#pragma once
#include <string>
#include <vector>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "vertex.h"
#include "texture.h"
#include "shader.h"
class Mesh{
public:
// Mesh data
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
std::vector<Texture> textures;
Mesh(std::vector<Vertex> vertices, std::vector<unsigned int> indices, std::vector<Texture> textures);
void Draw(Shader &shader);
private:
// render data
unsigned int VAO, VBO, EBO;
void setupMesh();
};

190
src/model.cpp Normal file
View File

@ -0,0 +1,190 @@
#include "model.h"
Model::Model(std::string const& path){
loadModel(path);
}
void Model::Draw(Shader& shader)
{
for(unsigned int i = 0; i < meshes.size(); i++)
meshes[i].Draw(shader);
}
void Model::loadModel(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)
{
std::cout << "ERROR::ASSIMP::" << importer.GetErrorString() << std::endl;
return;
}
directory = path.substr(0, path.find_last_of('/'));
processNode(scene->mRootNode, scene);
}
void Model::processNode (aiNode* node, const aiScene* scene)
{
for(unsigned int i = 0; i < node->mNumMeshes; i++)
{
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
meshes.push_back(processMesh(mesh, scene));
}
for(unsigned int i = 0; i < node->mNumChildren; i++)
{
processNode(node->mChildren[i], scene);
}
}
unsigned int TextureFromFile(const char* path, const std::string& directory)
{
std::string filename = std::string(path);
filename = directory + '/' + filename;
unsigned int textureID;
glGenTextures(1, &textureID);
int width, height, nrComponents;
unsigned char* data = stbi_load(filename.c_str(), &width, &height, &nrComponents, 0);
if(data)
{
GLenum format;
if(nrComponents == 1)
format = GL_RED;
else if (nrComponents == 3)
format = GL_RGB;
else if (nrComponents == 4)
format = GL_RGBA;
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
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);
} else{
std::cout << "Texture failed to load at path: " << path << std::endl;
}
stbi_image_free(data);
return textureID;
}
Mesh Model::processMesh (aiMesh* mesh, const aiScene* scene)
{
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
std::vector<Texture> textures;
for(unsigned int i = 0; i < mesh->mNumVertices; i++){
Vertex vertex;
// process vertex positions , normals and texture coordinates
glm::vec3 vector;
vector.x = mesh->mVertices[i].x;
vector.y = mesh->mVertices[i].y;
vector.z = mesh->mVertices[i].z;
vertex.Position = vector;
if( mesh->HasNormals()){
vector.x = mesh->mNormals[i].x;
vector.y = mesh->mNormals[i].y;
vector.z = mesh->mNormals[i].z;
vertex.Normal = vector;
}
if(mesh->mTextureCoords[0]){
glm::vec2 vec;
vec.x = mesh->mTextureCoords[0][i].x;
vec.y = mesh->mTextureCoords[0][i].y;
//std::cout << "texCoord: x=" << vec.x << " y=" << vec.y << std::endl;
vertex.TexCoords = vec;
} else{
vertex.TexCoords = glm::vec2(0,0);
}
vertices.push_back(vertex);
}
// process indices
for(unsigned int i = 0; i < mesh->mNumFaces; i++ ){
aiFace face = mesh->mFaces[i];
if(face.mNumIndices < 3)
continue;
for(unsigned int j = 0; j < face.mNumIndices; j++)
indices.push_back(face.mIndices[j]);
}
// process material
if(mesh->mMaterialIndex >= 0)
{
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
std::vector<Texture> diffuseMaps = loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse");
textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
std::vector<Texture> specularMaps = loadMaterialTextures(material, aiTextureType_SPECULAR, "texture_specular");
textures.insert(textures.end(),specularMaps.begin(), specularMaps.end());
}
return Mesh(vertices, indices, textures);
}
std::vector<Texture> Model::loadMaterialTextures(aiMaterial* mat, aiTextureType type, std::string typeName ){
std::vector<Texture> textures;
for(unsigned int i = 0; i < mat->GetTextureCount(type); i++)
{
aiString str;
mat->GetTexture(type, i, &str);
bool skip = false;
for(unsigned int j = 0; j < textures_loaded.size(); j++){
if( std::strcmp(textures_loaded[j].path.data(), str.C_Str()) == 0){
textures.push_back(textures_loaded[j]);
skip = true;
break;
}
}
if( !skip)
{
Texture texture;
texture.id = TextureFromFile(str.C_Str(), this->directory);
texture.type = typeName;
texture.path = str.C_Str();
textures.push_back(texture);
textures_loaded.push_back(texture);
}
}
return textures;
}

31
src/model.h Normal file
View File

@ -0,0 +1,31 @@
#pragma once
#include <string>
#include <vector>
#include "mesh.h"
#include "shader.h"
#include "stb_image.h"
#include <assimp/Importer.hpp> // C++ importer interface
#include <assimp/scene.h> // Output data structure
#include <assimp/postprocess.h> // Post Processing flags
class Model {
public:
Model(std::string const& path);
void Draw(Shader& shader);
private:
// model data
std::vector<Texture> textures_loaded;
std::vector<Mesh> meshes;
std::string directory;
void loadModel(std::string path);
void processNode(aiNode* node, const aiScene* scene );
Mesh processMesh(aiMesh* mesh, const aiScene* scene);
std::vector<Texture> loadMaterialTextures(aiMaterial* mat, aiTextureType type, std::string typeName );
};

112
src/shader.cpp Normal file
View File

@ -0,0 +1,112 @@
#include "shader.h"
Shader::Shader(const char* vertextPath, const char* fragmentPath)
{
// retrieve the vertex / fragment source code from filepath
std::string vertexCode;
std::string fragmentCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try{
vShaderFile.open(vertextPath);
fShaderFile.open(fragmentPath);
std::stringstream vShaderStream,fShaderStream;
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
vShaderFile.close();
fShaderFile.close();
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
}
catch(std::ifstream::failure e){
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl << e.what() << std::endl ;
}
const char* vShaderCode = vertexCode.c_str();
const char* fShaderCode = fragmentCode.c_str();
// Compile Shaders
unsigned int vertex, fragment;
int success;
char infoLog[512];
// vertex shader
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, NULL);
glCompileShader(vertex);
// print any compile errors if there are any
glGetShaderiv(vertex,GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(vertex, 512, NULL, infoLog);
std::cout << "ERROR::SHADER:::VERTEX::COMPILATION_FAILED" << std::endl << infoLog << std::endl;
}
// fragment shader
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fShaderCode, NULL);
glCompileShader(fragment);
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
if(!success){
glGetShaderInfoLog(fragment, 512, NULL, infoLog);
std::cout << "ERROR::SHADER:::VERTEX::COMPILATION_FAILED" << std::endl << infoLog << std::endl;
}
// Shader Program
ID = glCreateProgram();
glAttachShader(ID, vertex);
glAttachShader(ID, fragment);
glLinkProgram(ID);
glGetProgramiv(ID, GL_LINK_STATUS, &success);
if(!success){
glGetProgramInfoLog(ID, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED" << std::endl << infoLog << std::endl;
}
// delete shaders as they're now linked into our program and no longer necessary
glDeleteShader(vertex);
glDeleteShader(fragment);
}
void Shader::use(){
glUseProgram(ID);
}
void Shader::setBool(const std::string &name, bool value) const{
glUniform1i(glGetUniformLocation(ID, name.c_str()), (int) value );
}
void Shader::setInt(const std::string &name, int value) const{
glUniform1i(glGetUniformLocation(ID, name.c_str()), value );
}
void Shader::setFloat(const std::string &name, float value) const{
glUniform1f(glGetUniformLocation(ID, name.c_str()), value );
}
void Shader::setMat4(const std::string &name, glm::mat4 value)const{
glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &value[0][0] );
}
void Shader::setVec3(const std::string &name, glm::vec3 value)const{
glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value.x);
}

View File

@ -1,6 +1,6 @@
#pragma once
#include <glad/glad.h>
#include <glm/glm.hpp>
#include <string>
#include <fstream>
#include <sstream>
@ -25,114 +25,3 @@ class Shader
};
Shader::Shader(const char* vertextPath, const char* fragmentPath)
{
// retrieve the vertex / fragment source code from filepath
std::string vertexCode;
std::string fragmentCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try{
vShaderFile.open(vertextPath);
fShaderFile.open(fragmentPath);
std::stringstream vShaderStream,fShaderStream;
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
vShaderFile.close();
fShaderFile.close();
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
}
catch(std::ifstream::failure e){
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl << e.what() << std::endl ;
}
const char* vShaderCode = vertexCode.c_str();
const char* fShaderCode = fragmentCode.c_str();
// Compile Shaders
unsigned int vertex, fragment;
int success;
char infoLog[512];
// vertex shader
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, NULL);
glCompileShader(vertex);
// print any compile errors if there are any
glGetShaderiv(vertex,GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(vertex, 512, NULL, infoLog);
std::cout << "ERROR::SHADER:::VERTEX::COMPILATION_FAILED" << std::endl << infoLog << std::endl;
}
// fragment shader
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fShaderCode, NULL);
glCompileShader(fragment);
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
if(!success){
glGetShaderInfoLog(fragment, 512, NULL, infoLog);
std::cout << "ERROR::SHADER:::VERTEX::COMPILATION_FAILED" << std::endl << infoLog << std::endl;
}
// Shader Program
ID = glCreateProgram();
glAttachShader(ID, vertex);
glAttachShader(ID, fragment);
glLinkProgram(ID);
glGetProgramiv(ID, GL_LINK_STATUS, &success);
if(!success){
glGetProgramInfoLog(ID, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED" << std::endl << infoLog << std::endl;
}
// delete shaders as they're now linked into our program and no longer necessary
glDeleteShader(vertex);
glDeleteShader(fragment);
}
void Shader::use(){
glUseProgram(ID);
}
void Shader::setBool(const std::string &name, bool value) const{
glUniform1i(glGetUniformLocation(ID, name.c_str()), (int) value );
}
void Shader::setInt(const std::string &name, int value) const{
glUniform1i(glGetUniformLocation(ID, name.c_str()), value );
}
void Shader::setFloat(const std::string &name, float value) const{
glUniform1f(glGetUniformLocation(ID, name.c_str()), value );
}
void Shader::setMat4(const std::string &name, glm::mat4 value)const{
glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &value[0][0] );
}
void Shader::setVec3(const std::string &name, glm::vec3 value)const{
glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value.x);
}

8
src/texture.h Normal file
View File

@ -0,0 +1,8 @@
#pragma once
#include <string>
struct Texture{
unsigned int id;
std::string type;
std::string path;
};

8
src/vertex.h Normal file
View File

@ -0,0 +1,8 @@
#pragma once
#include <glm/glm.hpp>
struct Vertex {
glm::vec3 Position;
glm::vec3 Normal;
glm::vec2 TexCoords;
};