Add model loading and simple phong color shading

This commit is contained in:
Mario Hüttel 2020-03-24 23:13:49 +01:00
parent 8238e94eea
commit 4893a36197
20 changed files with 8196 additions and 66 deletions

View File

@ -7,10 +7,11 @@ find_package(glm REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(EPOXY REQUIRED epoxy)
pkg_check_modules(SDL2 REQUIRED sdl2)
pkg_check_modules(ASSIMP REQUIRED assimp)
#find_package(OpenCL REQUIRED)
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/imgui-submodule/imgui/examples" "${CMAKE_CURRENT_SOURCE_DIR}/imgui-submodule/imgui" ${EPOXY_INCLUDE_DIRS} ${SDL2_INCLUDE_DIRS})
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/imgui-submodule/imgui/examples" "${CMAKE_CURRENT_SOURCE_DIR}/imgui-submodule/imgui" ${EPOXY_INCLUDE_DIRS} ${ASSIMP_INCLUDE_DIRS} ${SDL2_INCLUDE_DIRS})
configure_file("shaders/2d-passthrough-vertex.glsl" "shaders/2d-passthrough-vertex.glsl" COPYONLY)
@ -19,10 +20,12 @@ configure_file("shaders/triangle-gen-geometry.glsl" "shaders/triangle-gen-geomet
configure_file("shaders/triangle-gen-zoomed-geometry.glsl" "shaders/triangle-gen-zoomed-geometry.glsl" COPYONLY)
configure_file("shaders/textured-rectangle-vertex.glsl" "shaders/textured-rectangle-vertex.glsl" COPYONLY)
configure_file("shaders/textured-rectangle-fragment.glsl" "shaders/textured-rectangle-fragment.glsl" COPYONLY)
configure_file("shaders/2d-zoom-translate-vertex.glsl" "shaders/2d-zoom-translate-vertex.glsl" COPYONLY)
configure_file("shaders/mesh-vertex.glsl" "shaders/mesh-vertex.glsl" COPYONLY)
configure_file("shaders/mesh-fragment.glsl" "shaders/mesh-fragment.glsl" COPYONLY)
set(IMGUI_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/imgui-submodule/imgui/imgui.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/imgui-submodule/imgui/imgui_draw.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/imgui-submodule/imgui/imgui_demo.cpp"
@ -36,5 +39,5 @@ aux_source_directory("src" SOURCES)
add_compile_options(-Wall)
add_executable(${PROJECT_NAME} ${SOURCES} ${IMGUI_SOURCES})
target_link_libraries(${PROJECT_NAME} m pthread ${EPOXY_LIBRARIES} ${SDL2_LIBRARIES} glm)
target_link_libraries(${PROJECT_NAME} m pthread ${EPOXY_LIBRARIES} ${SDL2_LIBRARIES} ${ASSIMP_LIBRARIES} glm)
install (TARGETS ${PROJECT_NAME} DESTINATION bin)

View File

@ -11,11 +11,14 @@ class GlobalCanvasSettings
static const glm::mat4 &getViewMatrix();
static const glm::mat4 &getProjectionMatrix();
static const glm::mat4 &getPVMatrix();
static const glm::vec3 &getCameraPosition();
static void setCameraPosition(const glm::vec3 &cam_pos);
private:
static void calculatePVMatrix();
static glm::mat4 m_proj;
static glm::mat4 m_view;
static glm::mat4 m_proj_view;
static glm::vec3 m_cam_pos;
};
#endif // GLOBALCANVASSETTINGS_H

View File

@ -0,0 +1,28 @@
#ifndef MESH_H
#define MESH_H
#include <glm/glm.hpp>
#include <vector>
#include <opengl-playground/vertex.hpp>
#include <opengl-playground/opengltexture.hpp>
#include <opengl-playground/openglgraphics.hpp>
class Mesh : public OpenGlGraphics
{
public:
Mesh(std::vector<Vertex> vertices, std::vector<unsigned int> indices,
std::vector<std::shared_ptr<OpenGlTexture>> textures,
std::shared_ptr<OpenGlShaderProgram> shader);
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
std::vector<std::shared_ptr<OpenGlTexture>> textures;
void realize();
void render();
void render(const glm::mat4 &model_matrix, const glm::mat4 &normal_matrix);
private:
unsigned int vao;
unsigned int vbo;
unsigned int ebo;
};
#endif // MESH_H

View File

@ -0,0 +1,30 @@
#ifndef MODEL_H
#define MODEL_H
#include <opengl-playground/openglgraphics.hpp>
#include <opengl-playground/mesh.hpp>
#include <vector>
#include <string>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
class Model : public OpenGlGraphics
{
public:
Model(const std::string &path, const glm::vec4 &static_color, std::shared_ptr<OpenGlShaderProgram> shader);
void render();
void realize();
private:
std::string model_path;
glm::vec4 static_color;
/* Model Data */
std::vector<Mesh> meshes;
std::vector<std::shared_ptr<OpenGlTexture>> allocated_textures;
std::string directory;
std::vector<std::shared_ptr<OpenGlTexture>> loadMaterialTextures(aiMaterial *mat, aiTextureType type, TextureType tex_type);
void processNode(aiNode *node, const aiScene *scene);
Mesh processMesh(aiMesh *mesh, const aiScene *scene);
};
#endif // MODEL_H

View File

@ -16,9 +16,11 @@ class OpenGlGraphics
virtual void render() = 0;
void setModelMatrix(const glm::mat4 &model_matrix);
glm::mat4 getModelMatrix();
glm::mat4 getNormalMatrix();
protected:
std::shared_ptr<OpenGlShaderProgram> shaderprog;
glm::mat4 model_matrix;
glm::mat4 normal_matrix;
};
#endif // OPENGLGRAPHICS_H

View File

@ -19,6 +19,7 @@ class OpenGlShaderProgram
void setUniformFloat(const std::string &uniform, float value);
void setUniformInt(const std::string &uniform, int value);
void setUniformVec2(const std::string &uniform, float *vector);
void setUniformVec3(const std::string &uniform, const glm::vec3 &vector);
void setUniformMat4(const std::string &uniform, const glm::mat4 &matrix);
void setUniformVec4(const std::string &uniform, const glm::vec4 &vector);
private:

View File

@ -2,17 +2,28 @@
#define OPENGLTEXTURE_HPP
#include <epoxy/gl.h>
#include <string>
typedef enum {TEXTURE_DIFFUSE, TEXTURE_SPECULAR} TextureType;
class OpenGlTexture
{
public:
OpenGlTexture(TextureType type, const std::string &texture_path);
OpenGlTexture();
OpenGlTexture(const OpenGlTexture &tex) = delete;
OpenGlTexture(const OpenGlTexture &&tex) = delete;
~OpenGlTexture();
void setRGBDataFromBytes(unsigned int width, unsigned int height, char *buffer);
void loadFromImagePath(const std::string &base_directory);
void use(unsigned int slot);
void use();
const std::string &getPath();
TextureType getType();
private:
std::string texture_path;
TextureType type;
protected:
GLuint texture;

View File

@ -0,0 +1,13 @@
#ifndef VERTEX_H
#define VERTEX_H
#include <glm/glm.hpp>
struct Vertex
{
glm::vec3 Position;
glm::vec3 Normal;
glm::vec2 TextureCoords;
};
#endif // VERTEX_H

7656
include/stb/stb_image.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,46 @@
#version 330 core
struct Material {
sampler2D diffuse0;
sampler2D diffuse1;
sampler2D diffuse2;
sampler2D diffuse3;
sampler2D specular0;
sampler2D specular1;
sampler2D specular2;
sampler2D specular3;
};
out vec4 fragmentColor;
in vec3 Normal;
in vec3 FragPos;
in vec2 TexCoord;
in vec3 ViewPos;
uniform Material material;
void main()
{
const vec3 light_direction = vec3(-1.0, -1.0, -1.0);
const vec3 light_color = vec3(1.0, 1.0, 1.0);
const float light_amb = 0.1;
const float light_spec = 0.4;
const float light_diff = 0.7;
vec3 diffuseTexCol = vec3(texture(material.diffuse0, TexCoord));
vec3 specularTexCol = vec3(texture(material.specular0, TexCoord));
vec3 normal_n = normalize(Normal);
vec3 light_dir_n = normalize(light_direction);
vec3 view_dir = normalize(ViewPos - FragPos);
vec3 reflect_dir = reflect(light_dir_n, normal_n);
float shine = pow(max(dot(view_dir, reflect_dir), 0.0), 35);
vec3 ambient_light = light_amb * diffuseTexCol * light_color;
vec3 diffuse_light = max(dot(normal_n, -light_dir_n), 0.0) *light_diff * diffuseTexCol * light_color;
vec3 specular_light = shine * light_spec * specularTexCol * light_color;
vec3 color = ambient_light + diffuse_light + specular_light;
fragmentColor = vec4(color, 1.0);
}

24
shaders/mesh-vertex.glsl Normal file
View File

@ -0,0 +1,24 @@
#version 330 core
layout (location = 0) in vec3 aInputPosition;
layout (location = 1) in vec3 aInputNormal;
layout (location = 2) in vec2 aTextureCoord;
uniform mat4 model_matrix;
uniform mat4 normal_matrix;
uniform mat4 projection_view_matrix;
uniform vec3 camera_position;
out vec3 Normal;
out vec3 FragPos;
out vec2 TexCoord;
out vec3 ViewPos;
void main()
{
gl_Position = projection_view_matrix * model_matrix * vec4(aInputPosition, 1.0);
Normal = vec3(normal_matrix * vec4(aInputNormal, 0.0));
FragPos = vec3(model_matrix * vec4(aInputPosition, 1.0));
TexCoord = aTextureCoord;
ViewPos = camera_position;
}

View File

@ -3,6 +3,7 @@
glm::mat4 GlobalCanvasSettings::m_proj = glm::mat4(1.0f);
glm::mat4 GlobalCanvasSettings::m_view = glm::mat4(1.0f);
glm::mat4 GlobalCanvasSettings::m_proj_view = glm::mat4(1.0f);
glm::vec3 GlobalCanvasSettings::m_cam_pos = glm::vec3(0.0f);
void GlobalCanvasSettings::setProjectionMatrix(const glm::mat4 &proj)
{
@ -31,6 +32,16 @@ const glm::mat4 &GlobalCanvasSettings::getPVMatrix()
return GlobalCanvasSettings::m_proj_view;
}
const glm::vec3 &GlobalCanvasSettings::getCameraPosition()
{
return GlobalCanvasSettings::m_cam_pos;
}
void GlobalCanvasSettings::setCameraPosition(const glm::vec3 &cam_pos)
{
GlobalCanvasSettings::m_cam_pos = cam_pos;
}
void GlobalCanvasSettings::calculatePVMatrix()
{
GlobalCanvasSettings::m_proj_view = GlobalCanvasSettings::m_proj * GlobalCanvasSettings::m_view;

View File

@ -6,6 +6,7 @@
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <opengl-playground/model.hpp>
#include <imgui.h>
#include <imgui_impl_sdl.h>
@ -14,29 +15,15 @@
#define WINDOW_WIDTH 1200
#define WINDOW_HEIGHT 800
unsigned char tex[4*10000] = {255};
int main(int argc, char **argv)
{
(void)argc;
(void)argv;
SdlMainWindow *window;
bool run = true;
glm::mat4 view_matrix;
glm::mat4 projection_matrix;
glm::vec4 color = glm::vec4(1.0f);
float y_rotation = 0.0f;
bool proj_ortho = true;
float nav_point[2] = {0.0f, 0.0f};
float zoom = 1.0;
for (int i = 0; i < 10000; i++) {
tex[i*4] = 0xff;
tex[i*4+1] = 0x00;
tex[i*4+2] = 0x00;
tex[i*4+3] = 0xFF;
}
float fov_angle = 45.0f;
window = new SdlMainWindow(WINDOW_HEIGHT, WINDOW_WIDTH);
@ -49,20 +36,9 @@ int main(int argc, char **argv)
glClearColor(0.1f, 0.1f, 0.1f, 0.f);
glClear(GL_COLOR_BUFFER_BIT);
std::shared_ptr<OpenGlShaderProgram> textured_rect_prog =
std::make_shared<OpenGlShaderProgram>("shaders/textured-rectangle-vertex.glsl", "",
"shaders/textured-rectangle-fragment.glsl");
projection_matrix = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, -1.0f, 1.0f);
projection_matrix = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, -10.0f, 10.0f);
GlobalCanvasSettings::setProjectionMatrix(projection_matrix);
GlobalCanvasSettings::setViewMatrix(glm::mat4(1.0f));
textured_rect_prog->compile();
std::shared_ptr<OpenGlTexture> texture = std::make_shared<OpenGlTexture>();
texture->setRGBDataFromBytes(100,100, (char*)tex);
TexturedRectangle rect = TexturedRectangle(-3, -3, 3, 3, textured_rect_prog, texture);
rect.realize();
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
@ -79,30 +55,42 @@ int main(int argc, char **argv)
ImGui_ImplSDL2_InitForOpenGL(window->getWindow(), window->getContext());
ImGui_ImplOpenGL3_Init("#version 330");
auto shader = std::make_shared<OpenGlShaderProgram>("shaders/mesh-vertex.glsl", "", "shaders/mesh-fragment.glsl");
shader->compile();
Model m("nanosuit/nanosuit.obj", glm::vec4(1.0f, 0.0f, 0.0f, 1.0f), shader);
m.realize();
m.setModelMatrix(glm::scale(glm::mat4(1.0f), glm::vec3(0.2f, 0.2f, 0.2f)));
glEnable(GL_DEPTH_TEST);
while (run) {
SDL_Event event;
while (SDL_PollEvent(&event))
{
if (event.type == SDL_MOUSEWHEEL) {
if (event.wheel.y > 0) {
zoom += 0.1;
} else {
zoom -= 0.1;
}
}
ImGui_ImplSDL2_ProcessEvent(&event);
if (event.type == SDL_QUIT)
run = false;
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window->getWindow()))
run = false;
if (event.type == SDL_MOUSEWHEEL) {
if (event.wheel.y > 0) {
fov_angle -= 0.1;
if (fov_angle <= 1.0f)
fov_angle = 1.0f;
} else if (event.wheel.y < 0) {
fov_angle += 0.1;
if (fov_angle >= 60.0f)
fov_angle = 60.0f;
}
}
}
glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Start the Dear ImGui frame
ImGui_ImplOpenGL3_NewFrame();
@ -110,37 +98,76 @@ int main(int argc, char **argv)
ImGui::NewFrame();
view_matrix = glm::scale(glm::mat4(1.0f), glm::vec3(zoom, zoom, 1.0));
view_matrix = glm::translate(view_matrix, glm::vec3(-nav_point[0], -nav_point[1], -10.0f));
ImGui::Begin("Camera");
GlobalCanvasSettings::setViewMatrix(view_matrix);
rect.render();
ImGui::Begin("Rectangle");
ImGui::Text("Change the color of the rectangle below");
ImGui::NewLine();
ImGui::SliderFloat4("Rectangle Color", &color.r, 0.0f, 1.0f, "%.3f", 1.0f);
ImGui::Text("Rectangle Rotation:");
ImGui::NewLine();
ImGui::SliderAngle("Y Rotation", &y_rotation, -180.0f, +180.0f);
static int e = 0;
static int e = 1;
ImGui::RadioButton("Orthographic", &e, 0); ImGui::SameLine();
ImGui::RadioButton("Perspective", &e, 1);
static float view_z = 10.0f, view_x = 0.0f, view_y = 0.0f;
ImGui::SliderFloat("Camera x", &view_x, -20.0f, 20.0f);
ImGui::SliderFloat("Camera y", &view_y, -20.0f, 20.0f);
ImGui::SliderFloat("Camera z", &view_z, 0.0f, 20.0f);
ImGui::SliderFloat("Camera FOV", &fov_angle, 1.0f, 60.0f);
ImGui::Text("Framerate: %.01f Hz", io.Framerate);
GlobalCanvasSettings::setCameraPosition(glm::vec3(view_x, view_y, view_z));
const glm::mat4 view = glm::lookAt(GlobalCanvasSettings::getCameraPosition(),
glm::vec3(view_x, view_y, 0.0f),
glm::vec3(0.0f, 1.0f, 0.0f));
GlobalCanvasSettings::setViewMatrix(view);
if(!e) {
GlobalCanvasSettings::setProjectionMatrix(glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, -1.0f, 20.0f));
//GlobalCanvasSettings::setProjectionMatrix(glm::mat4(1.0f));
GlobalCanvasSettings::setProjectionMatrix(glm::ortho(-5.0f, 5.0f, -5.0f, 5.0f, -5.0f, 5.0f));
} else {
GlobalCanvasSettings::setProjectionMatrix(glm::perspective(glm::radians(120.0f), (float)1200/(float)800, 1.0f, 30.0f));
GlobalCanvasSettings::setProjectionMatrix(glm::perspective(glm::radians(fov_angle), (float)1200/(float)800, 0.2f, 30.0f));
}
ImGui::End();
{
ImGui::Begin("Model Matrix");
glm::mat4 mat = m.getModelMatrix();
static float x_pos = 0.0f;
static float y_rot = 0.0f, z_rot =0.0f, x_rot = 0.0f;
ImGui::Text("%.2f %.2f %.2f %.2f", mat[0][0], mat[1][0], mat[2][0], mat[3][0]);
ImGui::Text("%.2f %.2f %.2f %.2f", mat[0][1], mat[1][1], mat[2][1], mat[3][1]);
ImGui::Text("%.2f %.2f %.2f %.2f", mat[0][2], mat[1][2], mat[2][2], mat[3][2]);
ImGui::Text("%.2f %.2f %.2f %.2f", mat[0][3], mat[1][3], mat[2][3], mat[3][3]);
ImGui::SliderFloat("X Pos", &x_pos, -5, 5);
ImGui::SliderFloat("X Rotation", &x_rot, -180.0f, 180.0f);
ImGui::SliderFloat("Y Rotation", &y_rot, -180.0f, 180.0f);
ImGui::SliderFloat("Z Rotation", &z_rot, -180.0f, 180.0f);
mat = glm::scale(glm::mat4(1.0f), glm::vec3(0.2f, 0.2f, 0.2f));
mat = glm::rotate(mat, glm::radians(x_rot), glm::vec3(1.0f, 0.0f, 0.0f));
mat = glm::rotate(mat, glm::radians(y_rot), glm::vec3(0.0f, 1.0f, 0.0f));
mat = glm::rotate(mat, glm::radians(z_rot), glm::vec3(0.0f, 0.0f, 1.0f));
mat = glm::translate(glm::mat4(1.0), glm::vec3(x_pos, 0.0f, 0.0f)) * mat;
m.setModelMatrix(mat);
ImGui::End();
}
{
ImGui::Begin("Normal Matrix");
glm::mat4 mat = m.getNormalMatrix();
ImGui::Text("%.2f %.2f %.2f %.2f", mat[0][0], mat[1][0], mat[2][0], mat[3][0]);
ImGui::Text("%.2f %.2f %.2f %.2f", mat[0][1], mat[1][1], mat[2][1], mat[3][1]);
ImGui::Text("%.2f %.2f %.2f %.2f", mat[0][2], mat[1][2], mat[2][2], mat[3][2]);
ImGui::Text("%.2f %.2f %.2f %.2f", mat[0][3], mat[1][3], mat[2][3], mat[3][3]);
ImGui::End();
}
m.render();
glm::mat4 current_model_matrix = m.getModelMatrix();
current_model_matrix = glm::translate(glm::mat4(1.0f), glm::vec3(3.0f, 0.0f, 0.0f)) * current_model_matrix;
m.setModelMatrix(current_model_matrix);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
m.render();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glm::mat4 model_matrix = glm::rotate(glm::mat4(1.0f), y_rotation, glm::vec3(0.0f, 1.0f, 0.0f));
rect.setModelMatrix(model_matrix);
rect.setBaseColor(color);
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
@ -152,6 +179,7 @@ int main(int argc, char **argv)
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
textured_rect_prog->unload();
shader->unload();
delete window;
}

82
src/mesh.cpp Normal file
View File

@ -0,0 +1,82 @@
#include <opengl-playground/mesh.hpp>
#include <opengl-playground/globalcanvassettings.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <iostream>
Mesh::Mesh(std::vector<Vertex> vertices, std::vector<unsigned int> indices,
std::vector<std::shared_ptr<OpenGlTexture> > textures,
std::shared_ptr<OpenGlShaderProgram> shader) :
OpenGlGraphics(shader)
{
this->vertices = vertices;
this->indices = indices;
this->textures = textures;
}
void Mesh::realize()
{
glGenVertexArrays(1, &this->vao);
glGenBuffers(1, &this->vbo);
glGenBuffers(1, &this->ebo);
glBindVertexArray(this->vao);
glBindBuffer(GL_ARRAY_BUFFER, this->vbo);
glBufferData(GL_ARRAY_BUFFER, this->vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)offsetof(Vertex, Normal));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)offsetof(Vertex, TextureCoords));
glBindVertexArray(0);
std::cout << "Realizing Mesh" << std::endl;
}
void Mesh::render()
{
this->render(this->model_matrix, this->normal_matrix);
}
void Mesh::render(const glm::mat4 &model_matrix, const glm::mat4 &normal_matrix)
{
this->shaderprog->use();
this->shaderprog->setUniformMat4("model_matrix", model_matrix);
this->shaderprog->setUniformMat4("normal_matrix", normal_matrix);
this->shaderprog->setUniformMat4("projection_view_matrix", GlobalCanvasSettings::getPVMatrix());
this->shaderprog->setUniformVec3("camera_position", GlobalCanvasSettings::getCameraPosition());
int spec_num = 0;
int diff_num = 0;
/* Setup the texture samplers */
for (unsigned int i = 0; i < this->textures.size(); i++) {
std::string uniform_name;
textures[i]->use(i);
switch (textures[i]->getType()) {
case TEXTURE_DIFFUSE:
uniform_name = "material.diffuse" + std::to_string(diff_num++);
this->shaderprog->setUniformInt(uniform_name, i);
break;
case TEXTURE_SPECULAR:
uniform_name = "material.specular" + std::to_string(spec_num++);
this->shaderprog->setUniformInt(uniform_name, i);
break;
default:
break;
}
}
glBindVertexArray(this->vao);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}

129
src/model.cpp Normal file
View File

@ -0,0 +1,129 @@
#include <opengl-playground/model.hpp>
#include <iostream>
Model::Model(const std::string &path, const glm::vec4 &static_color, std::shared_ptr<OpenGlShaderProgram> shader)
: OpenGlGraphics(shader)
{
this->model_path = path;
this->static_color = static_color;
}
void Model::render()
{
for (unsigned int i = 0; i < meshes.size(); i++) {
meshes[i].render(this->model_matrix, this->normal_matrix);
}
}
void Model::realize()
{
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(this->model_path, aiProcess_Triangulate | aiProcess_FlipUVs);
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) {
std::cout << "Error: Assimp: " << importer.GetErrorString() << std::endl;
return;
}
this->directory = this->model_path.substr(0, this->model_path.find_last_of('/'));
this->processNode(scene->mRootNode, scene);
importer.FreeScene();
}
void Model::processNode(aiNode *node, const aiScene *scene)
{
for(unsigned int i = 0; i < node->mNumMeshes; i++)
{
aiMesh *mesh = scene->mMeshes[node->mMeshes[i]];
this->meshes.push_back(this->processMesh(mesh, scene));
}
for(unsigned int i = 0; i < node->mNumChildren; i++)
{
this->processNode(node->mChildren[i], scene);
}
}
std::vector<std::shared_ptr<OpenGlTexture>> Model::loadMaterialTextures(aiMaterial *mat, aiTextureType type,
TextureType tex_type)
{
std::vector<std::shared_ptr<OpenGlTexture>> tex_vector;
for (unsigned int i = 0; i < mat->GetTextureCount(type); i++) {
aiString str;
mat->GetTexture(type, i, &str);
bool already_loaded = false;
for (unsigned int j = 0; j < this->allocated_textures.size(); j++) {
if (std::strcmp(this->allocated_textures[j]->getPath().c_str(), str.C_Str()) == 0) {
/* texture already loaded */
tex_vector.push_back(this->allocated_textures[j]);
already_loaded = true;
break;
}
}
if (!already_loaded) {
auto new_texture = std::make_shared<OpenGlTexture>(tex_type, str.C_Str());
new_texture->loadFromImagePath(this->directory);
tex_vector.push_back(new_texture);
this->allocated_textures.push_back(new_texture);
}
}
return tex_vector;
}
Mesh Model::processMesh(aiMesh *mesh, const aiScene *scene)
{
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
std::vector<std::shared_ptr<OpenGlTexture>> textures;
for(unsigned int i = 0; i < mesh->mNumVertices; i++)
{
Vertex vertex;
glm::vec3 vector;
vector.x = mesh->mVertices[i].x;
vector.y = mesh->mVertices[i].y;
vector.z = mesh->mVertices[i].z;
vertex.Position = vector;
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;
vertex.TextureCoords = vec;
} else {
vertex.TextureCoords = glm::vec2(0.0f, 0.0f);
}
vertices.push_back(vertex);
}
// process indices
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];
auto diffuseTextures = loadMaterialTextures(material, aiTextureType_DIFFUSE, TEXTURE_DIFFUSE);
auto specularTextures = loadMaterialTextures(material, aiTextureType_SPECULAR, TEXTURE_SPECULAR);
textures.insert(textures.end(), diffuseTextures.begin(), diffuseTextures.end());
textures.insert(textures.end(), specularTextures.begin(), specularTextures.end());
}
Mesh my_mesh = Mesh(vertices, indices, textures, this->shaderprog);
my_mesh.realize();
return my_mesh;
}

View File

@ -16,9 +16,15 @@ OpenGlGraphics::~OpenGlGraphics()
void OpenGlGraphics::setModelMatrix(const glm::mat4 &model_matrix)
{
this->model_matrix = model_matrix;
this->normal_matrix = glm::transpose(glm::inverse(model_matrix));
}
glm::mat4 OpenGlGraphics::getModelMatrix()
{
return this->model_matrix;
}
glm::mat4 OpenGlGraphics::getNormalMatrix()
{
return this->normal_matrix;
}

View File

@ -184,6 +184,14 @@ void OpenGlShaderProgram::setUniformVec2(const std::string &uniform, float *vect
}
}
void OpenGlShaderProgram::setUniformVec3(const std::string &uniform, const glm::vec3 &vector)
{
int loc = this->getUniformLoc(uniform);
if (loc >= 0) {
glUniform3fv(loc, 1, &vector.x);
}
}
void OpenGlShaderProgram::setUniformMat4(const std::string &uniform, const glm::mat4 &matrix)
{
int loc = this->getUniformLoc(uniform);

View File

@ -1,6 +1,10 @@
#include <opengl-playground/opengltexture.hpp>
OpenGlTexture::OpenGlTexture()
#define STB_IMAGE_IMPLEMENTATION
#include <stb/stb_image.h>
#include <iostream>
OpenGlTexture::OpenGlTexture(TextureType type, const std::string &texture_path)
{
glGenTextures(1, &this->texture);
glBindTexture(GL_TEXTURE_2D, this->texture);
@ -8,6 +12,13 @@ OpenGlTexture::OpenGlTexture()
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
this->type = type;
this->texture_path = texture_path;
}
OpenGlTexture::OpenGlTexture() : OpenGlTexture(TEXTURE_DIFFUSE, "")
{
}
OpenGlTexture::~OpenGlTexture()
@ -22,6 +33,36 @@ void OpenGlTexture::setRGBDataFromBytes(unsigned int width, unsigned int height,
glGenerateMipmap(GL_TEXTURE_2D);
}
void OpenGlTexture::loadFromImagePath(const std::string &base_directory)
{
int width, height, nrChannels;
std::string filename = this->texture_path;
filename = base_directory + '/' + filename;
unsigned char *data = stbi_load(filename.c_str(), &width, &height, &nrChannels, 0);
if (data) {
GLenum format = 0;
if (nrChannels == 1)
format = GL_RED;
else if (nrChannels == 3)
format = GL_RGB;
else if (nrChannels == 4)
format = GL_RGBA;
this->use();
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 loading of " << this->getPath() << " failed" << std::endl;
}
stbi_image_free(data);
}
void OpenGlTexture::use(unsigned int slot)
{
glActiveTexture(GL_TEXTURE0 + slot);
@ -32,3 +73,13 @@ void OpenGlTexture::use()
{
glBindTexture(GL_TEXTURE_2D, this->texture);
}
const std::string &OpenGlTexture::getPath()
{
return this->texture_path;
}
TextureType OpenGlTexture::getType()
{
return this->type;
}

View File

@ -17,7 +17,6 @@ SdlMainWindow::~SdlMainWindow()
void SdlMainWindow::show()
{
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 16);
this->window = SDL_CreateWindow("OpenGL Playground", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
this->width, this->height, SDL_WINDOW_OPENGL);
return;
@ -40,8 +39,6 @@ void SdlMainWindow::activateGlContext()
this->context = SDL_GL_CreateContext(this->window);
else
SDL_GL_MakeCurrent(this->window, this->context);
glEnable(GL_MULTISAMPLE);
}
SDL_Window *SdlMainWindow::getWindow()

1
src/vertex.cpp Normal file
View File

@ -0,0 +1 @@
#include <opengl-playground/vertex.hpp>