Add materials for diffuse + specular shading

This commit is contained in:
karl 2020-01-15 18:25:04 +01:00
parent 30b36bd9f8
commit d538ff64ec
13 changed files with 1956 additions and 1376 deletions

View File

@ -7,7 +7,7 @@ find_package(OpenGL REQUIRED)
find_package(glfw3 REQUIRED) find_package(glfw3 REQUIRED)
find_package(glm REQUIRED) find_package(glm REQUIRED)
add_executable(ecsgame Util/glad.c Util/OBJ_Loader.h Rendering/Shader.cpp Rendering/Shader.h main.cpp ECS/Components/Transform.h ECS/Components/Movement.h ECS/Events/InputEvent.h ECS/Events/MouseMoveEvent.h ECS/Systems/GravitySystem.h ECS/Systems/PositionDebugSystem.h ECS/Systems/KeyboardMovementSystem.h ECS/Components/Camera.h ECS/Systems/RenderSystem.h ECS/Components/Mesh.h ECS/Systems/MouseLookSystem.h ECS/Components/MouseLook.h ECS/Components/ObjMesh.h Util/stb_setup.cpp ECS/Components/Texture.h ECS/Components/LODObjMesh.h ECS/Components/SineAnimation.h ECS/Systems/SineAnimationSystem.h ECS/Components/DirectionalLight.h) add_executable(ecsgame Util/glad.c Util/OBJ_Loader.h Rendering/Shader.cpp Rendering/Shader.h main.cpp ECS/Components/Transform.h ECS/Components/Movement.h ECS/Events/InputEvent.h ECS/Events/MouseMoveEvent.h ECS/Systems/GravitySystem.h ECS/Systems/PositionDebugSystem.h ECS/Systems/KeyboardMovementSystem.h ECS/Components/Camera.h ECS/Systems/RenderSystem.h ECS/Components/Mesh.h ECS/Systems/MouseLookSystem.h ECS/Components/MouseLook.h ECS/Components/ObjMesh.h Util/stb_setup.cpp ECS/Components/Texture.h ECS/Components/LODObjMesh.h ECS/Components/SineAnimation.h ECS/Systems/SineAnimationSystem.h ECS/Components/DirectionalLight.h Rendering/Material.h)
include_directories(${OPENGL_INCLUDE_DIRS}) include_directories(${OPENGL_INCLUDE_DIRS})

View File

@ -0,0 +1,14 @@
//
// Created by karl on 15.01.20.
//
#ifndef ECSGAME_DIRECTIONALLIGHT_H
#define ECSGAME_DIRECTIONALLIGHT_H
struct DirectionalLight {
explicit DirectionalLight(const glm::vec3 &direction) : direction(direction) {}
glm::vec3 direction;
};
#endif //ECSGAME_DIRECTIONALLIGHT_H

View File

@ -10,11 +10,11 @@
struct ObjMesh : public Mesh { struct ObjMesh : public Mesh {
struct Settings { struct Settings {
Settings(float minDistanceForRender, float maxDistanceForRender) : minDistanceForRender(
minDistanceForRender), maxDistanceForRender(maxDistanceForRender) {}
Settings() = default; Settings() = default;
Settings(float minDistanceForRender, float maxDistanceForRender, float diffuse, float specular)
: minDistanceForRender(minDistanceForRender), maxDistanceForRender(maxDistanceForRender) {}
float minDistanceForRender = 0.0; float minDistanceForRender = 0.0;
float maxDistanceForRender = 1000.0; float maxDistanceForRender = 1000.0;
}; };

View File

@ -13,6 +13,8 @@
#include "../Components/ObjMesh.h" #include "../Components/ObjMesh.h"
#include "../Components/Texture.h" #include "../Components/Texture.h"
#include "../Components/LODObjMesh.h" #include "../Components/LODObjMesh.h"
#include "../Components/DirectionalLight.h"
#include "../../Rendering/Material.h"
using namespace ECS; using namespace ECS;
@ -26,15 +28,22 @@ public:
shader.use(); shader.use();
// Lighting
// TODO: Currently only the last light is used!
pWorld->each<DirectionalLight>([&](Entity *ent, ComponentHandle<DirectionalLight> light) {
shader.setVec3("lightDirection", light->direction);
});
shader.setMat4("projection", camera->projection); shader.setMat4("projection", camera->projection);
shader.setMat4("view", glm::inverse(cameraTransform->matrix)); shader.setMat4("view", glm::inverse(cameraTransform->matrix));
shader.setVec3("cameraPosition", cameraTransform->getPosition());
std::vector<RenderObject> renderObjects; std::vector<RenderObject> renderObjects;
std::vector<RenderObject> transparentRenderObjects; std::vector<RenderObject> transparentRenderObjects;
pWorld->each<Mesh, Transform>([&](Entity *ent, ComponentHandle<Mesh> mesh, ComponentHandle<Transform> transform) { /*pWorld->each<Mesh, Transform>([&](Entity *ent, ComponentHandle<Mesh> mesh, ComponentHandle<Transform> transform) {
renderObjects.emplace_back(RenderObject(transform->matrix, 0, mesh.get(), 0)); renderObjects.emplace_back(RenderObject(transform->matrix, 0, mesh.get(), 0));
}); });*/
glm::vec3 cameraPos = cameraTransform->getPosition(); glm::vec3 cameraPos = cameraTransform->getPosition();
@ -55,26 +64,40 @@ public:
float distance = glm::distance(cameraPos, transform->getPosition()); float distance = glm::distance(cameraPos, transform->getPosition());
if (distance > mesh->minDistance && distance < mesh->maxDistance) { if (distance > mesh->minDistance && distance < mesh->maxDistance) {
// Get optional components
ComponentHandle<Texture> textureComponent = ent->get<Texture>();
ComponentHandle<Material> materialComponent = ent->get<Material>();
Material material = materialComponent.isValid() ? materialComponent.get() : Material();
unsigned int textureID = textureComponent.isValid() ? textureComponent->id : 0;
// Put it into the list of transparent render objects if the texture wants to be rendered transparently // Put it into the list of transparent render objects if the texture wants to be rendered transparently
if (texture->render_transparent) { if (textureComponent.isValid() && textureComponent->render_transparent) {
transparentRenderObjects.emplace_back(RenderObject(transform->matrix, texture->id, mesh.get(), distance)); transparentRenderObjects.emplace_back(RenderObject(transform->matrix, textureID, mesh.get(), distance, material));
} else { } else {
renderObjects.emplace_back(RenderObject(transform->matrix, texture->id, mesh.get(), distance)); renderObjects.emplace_back(RenderObject(transform->matrix, textureID, mesh.get(), distance, material));
} }
} }
}); });
// LODObjMesh with Texture // LODObjMesh with Texture
pWorld->each<LODObjMesh, Transform, Texture>([&](Entity *ent, ComponentHandle<LODObjMesh> lodMesh, ComponentHandle<Transform> transform, ComponentHandle<Texture> texture) { pWorld->each<LODObjMesh, Transform>([&](Entity *ent, ComponentHandle<LODObjMesh> lodMesh, ComponentHandle<Transform> transform) {
float distance = glm::distance(cameraPos, transform->getPosition()); float distance = glm::distance(cameraPos, transform->getPosition());
for (const auto &mesh : lodMesh->meshes) { for (const auto &mesh : lodMesh->meshes) {
if (distance > mesh.minDistance && distance < mesh.maxDistance) { if (distance > mesh.minDistance && distance < mesh.maxDistance) {
// Get optional components
ComponentHandle<Texture> textureComponent = ent->get<Texture>();
ComponentHandle<Material> materialComponent = ent->get<Material>();
Material material = materialComponent.isValid() ? materialComponent.get() : Material();
unsigned int textureID = textureComponent.isValid() ? textureComponent->id : 0;
// Put it into the list of transparent render objects if the texture wants to be rendered transparently // Put it into the list of transparent render objects if the texture wants to be rendered transparently
if (texture->render_transparent) { if (textureComponent.isValid() && textureComponent->render_transparent) {
transparentRenderObjects.emplace_back(RenderObject(transform->matrix, texture->id, mesh, distance)); transparentRenderObjects.emplace_back(RenderObject(transform->matrix, textureID, mesh, distance, material));
} else { } else {
renderObjects.emplace_back(RenderObject(transform->matrix, texture->id, mesh, distance)); renderObjects.emplace_back(RenderObject(transform->matrix, textureID, mesh, distance, material));
} }
} }
} }
@ -95,11 +118,12 @@ public:
} }
struct RenderObject { struct RenderObject {
RenderObject(const glm::mat4 &matrix, unsigned int textureId, const Mesh &mesh, float distance) RenderObject(const glm::mat4 &matrix, unsigned int textureId, const Mesh &mesh, float distance, const Material &material)
: matrix(matrix), : matrix(matrix),
texture_id(textureId), texture_id(textureId),
mesh(mesh), mesh(mesh),
distance(distance) {} distance(distance),
material(material) {}
void render(Shader shader) const { void render(Shader shader) const {
shader.setMat4("model", matrix); shader.setMat4("model", matrix);
@ -109,6 +133,9 @@ public:
glBindTexture(GL_TEXTURE_2D, texture_id); glBindTexture(GL_TEXTURE_2D, texture_id);
} }
shader.setFloat("diffuseStrength", material.diffuse);
shader.setFloat("specularStrength", material.specular);
mesh.render(); mesh.render();
} }
@ -116,6 +143,7 @@ public:
unsigned int texture_id; unsigned int texture_id;
Mesh mesh; Mesh mesh;
float distance; float distance;
Material material;
}; };
}; };

18
Rendering/Material.h Normal file
View File

@ -0,0 +1,18 @@
//
// Created by karl on 15.01.20.
//
#ifndef ECSGAME_MATERIAL_H
#define ECSGAME_MATERIAL_H
struct Material {
Material() = default;
Material(float diffuse, float specular) : diffuse(diffuse), specular(specular) {}
float diffuse = 0.8;
float specular = 0.2;
};
#endif //ECSGAME_MATERIAL_H

View File

@ -92,6 +92,11 @@ void Shader::setMat4(const std::string &name, glm::mat4 mat) const {
glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, glm::value_ptr(mat)); glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, glm::value_ptr(mat));
} }
void Shader::setVec3(const std::string &name, glm::vec3 vec) const {
glUniform3f(glGetUniformLocation(ID, name.c_str()), vec.x, vec.y, vec.z);
}
void Shader::checkCompileErrors(unsigned int shader, const std::string &type) { void Shader::checkCompileErrors(unsigned int shader, const std::string &type) {
int success; int success;
char infoLog[1024]; char infoLog[1024];

View File

@ -32,6 +32,9 @@ public:
/// Set a uniform mat4 in the shader /// Set a uniform mat4 in the shader
void setMat4(const std::string &name, glm::mat4 mat) const; void setMat4(const std::string &name, glm::mat4 mat) const;
/// Set a uniform vec3 in the shader
void setVec3(const std::string &name, glm::vec3 vec) const;
private: private:
static void checkCompileErrors(unsigned int shader, const std::string &type); static void checkCompileErrors(unsigned int shader, const std::string &type);
}; };

View File

@ -1,12 +1,10 @@
# Blender MTL File: 'None' # Blender MTL File: 'None'
# Material Count: 1 # Material Count: 1
newmtl Material.001 newmtl None
Ns 225.000000 Ns 500
Ka 1.000000 1.000000 1.000000 Ka 0.8 0.8 0.8
Kd 0.800000 0.157242 0.044599 Kd 0.8 0.8 0.8
Ks 0.500000 0.500000 0.500000 Ks 0.8 0.8 0.8
Ke 0.0 0.0 0.0 d 1
Ni 1.450000 illum 2
d 0.619318
illum 9

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -3,8 +3,14 @@ out mediump vec4 FragColor;
in mediump vec2 TexCoord; in mediump vec2 TexCoord;
in mediump vec3 Normal; in mediump vec3 Normal;
in mediump vec3 FragPos;
uniform sampler2D tex; uniform sampler2D tex;
uniform mediump vec3 lightDirection;
uniform mediump vec3 cameraPosition;
uniform mediump float diffuseStrength;
uniform mediump float specularStrength;
void main() void main()
{ {
@ -14,5 +20,23 @@ void main()
if(texColor.a < 0.1) if(texColor.a < 0.1)
discard; discard;
FragColor = texColor; // Lighting
// Diffuse
mediump float diff = max(dot(Normal, lightDirection), 0.0);
// Ambient
mediump float ambient = 0.2;
// Specular
mediump vec3 viewDir = normalize(cameraPosition - FragPos);
mediump vec3 reflectDir = reflect(-lightDirection, Normal);
mediump float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32.0);
// Total
mediump float light = min(diff * diffuseStrength + ambient + spec * specularStrength, 1.0);
// Assign resulting color
mediump vec3 color = texColor.xyz * light;
FragColor = vec4(color, texColor.a);
} }

View File

@ -5,6 +5,7 @@ layout (location = 2) in vec2 UV;
out vec2 TexCoord; out vec2 TexCoord;
out vec3 Normal; out vec3 Normal;
out vec3 FragPos;
uniform mat4 model; uniform mat4 model;
uniform mat4 view; uniform mat4 view;
@ -15,4 +16,5 @@ void main()
gl_Position = projection * view * model * vec4(aPos, 1.0); gl_Position = projection * view * model * vec4(aPos, 1.0);
TexCoord = UV; TexCoord = UV;
Normal = NORMAL; Normal = NORMAL;
FragPos = vec3(model * vec4(aPos, 1.0));
} }

View File

@ -16,6 +16,7 @@
#include "ECS/Components/Texture.h" #include "ECS/Components/Texture.h"
#include "ECS/Components/SineAnimation.h" #include "ECS/Components/SineAnimation.h"
#include "ECS/Systems/SineAnimationSystem.h" #include "ECS/Systems/SineAnimationSystem.h"
#include "ECS/Components/DirectionalLight.h"
using namespace ECS; using namespace ECS;
@ -43,7 +44,7 @@ int main() {
return -1; return -1;
/* Create a windowed mode window and its OpenGL context */ /* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL); window = glfwCreateWindow(1280, 720, "Hello World", NULL, NULL);
if (!window) { if (!window) {
glfwTerminate(); glfwTerminate();
return -1; return -1;
@ -76,7 +77,7 @@ int main() {
// world->registerSystem(new GravitySystem(-9.8f)); // world->registerSystem(new GravitySystem(-9.8f));
// world->registerSystem(new PositionDebugOutputSystem()); // world->registerSystem(new PositionDebugOutputSystem());
world->registerSystem(new KeyboardMovementSystem()); world->registerSystem(new KeyboardMovementSystem());
world->registerSystem(new MouseLookSystem(640, 480)); world->registerSystem(new MouseLookSystem(1280, 720));
world->registerSystem(new SineAnimationSystem()); world->registerSystem(new SineAnimationSystem());
RenderSystem* renderSystem = new RenderSystem(); RenderSystem* renderSystem = new RenderSystem();
@ -85,33 +86,38 @@ int main() {
Entity *player = world->create(); Entity *player = world->create();
player->assign<Transform>(); player->assign<Transform>();
player->assign<Movement>(glm::vec3(2.f, 2.f, 2.f)); player->assign<Movement>(glm::vec3(2.f, 2.f, 2.f));
player->assign<Camera>(70.0f, 640, 480, 0.1f, 100.0f); player->assign<Camera>(70.0f, 1280, 720, 0.1f, 100.0f);
player->assign<MouseLook>(0.1); player->assign<MouseLook>(0.1);
player->get<Transform>()->translate(glm::vec3(0.0f, 1.0f, 2.0f)); player->get<Transform>()->translate(glm::vec3(0.0f, 1.0f, 2.0f));
Entity *monkey = world->create(); Entity *monkey = world->create();
monkey->assign<Transform>(); monkey->assign<Transform>();
monkey->assign<LODObjMesh>(std::vector{ObjMesh("Resources/Monkey.obj", ObjMesh::Settings(0.0, 8.0)), ObjMesh("Resources/MonkeySimple.obj", ObjMesh::Settings(8.0, 100.0))}); monkey->assign<LODObjMesh>(std::vector{ObjMesh("Resources/Monkey.obj",ObjMesh::Settings(0.0, 8.0, 0.4, 0.6)),
ObjMesh("Resources/MonkeySimple.obj", ObjMesh::Settings(8.0, 100.0, 0.4, 0.6))});
monkey->assign<Texture>("Resources/Marble.jpg", Texture::Settings(true, false)); monkey->assign<Texture>("Resources/Marble.jpg", Texture::Settings(true, false));
monkey->assign<SineAnimation>(glm::vec3(0.0, 0.3, 0.0), 0.5); monkey->assign<SineAnimation>(glm::vec3(0.0, 0.3, 0.0), 0.5);
monkey->assign<Material>(0.6, 0.6);
monkey->get<Transform>()->translate(glm::vec3(0.0f, 2.0f, -6.0f)); monkey->get<Transform>()->translate(glm::vec3(0.0f, 2.0f, -6.0f));
Entity *wall1 = world->create(); Entity *wall1 = world->create();
wall1->assign<Transform>(); wall1->assign<Transform>();
wall1->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings())); wall1->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings()));
wall1->assign<Texture>("Resources/Glass.png", Texture::Settings(true, true)); wall1->assign<Texture>("Resources/Glass.png", Texture::Settings(true, true));
wall1->assign<Material>(0.2, 0.8);
wall1->get<Transform>()->translate(glm::vec3(0.0f, 0.0f, -2.0f)); wall1->get<Transform>()->translate(glm::vec3(0.0f, 0.0f, -2.0f));
Entity *wall2 = world->create(); Entity *wall2 = world->create();
wall2->assign<Transform>(); wall2->assign<Transform>();
wall2->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings())); wall2->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings()));
wall2->assign<Texture>("Resources/Glass.png", Texture::Settings(true, true)); wall2->assign<Texture>("Resources/Glass.png", Texture::Settings(true, true));
wall2->assign<Material>(0.2, 0.8);
wall2->get<Transform>()->translate(glm::vec3(0.0f, 0.0f, -10.0f)); wall2->get<Transform>()->translate(glm::vec3(0.0f, 0.0f, -10.0f));
Entity *wall3 = world->create(); Entity *wall3 = world->create();
wall3->assign<Transform>(); wall3->assign<Transform>();
wall3->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings())); wall3->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings()));
wall3->assign<Texture>("Resources/Glass.png", Texture::Settings(true, true)); wall3->assign<Texture>("Resources/Glass.png", Texture::Settings(true, true));
wall3->assign<Material>(0.2, 0.8);
wall3->get<Transform>()->translate(glm::vec3(4.0f, 0.0f, -6.0f)); wall3->get<Transform>()->translate(glm::vec3(4.0f, 0.0f, -6.0f));
wall3->get<Transform>()->rotate(90.0, glm::vec3(0.0, 1.0, 0.0)); wall3->get<Transform>()->rotate(90.0, glm::vec3(0.0, 1.0, 0.0));
@ -119,6 +125,7 @@ int main() {
wall4->assign<Transform>(); wall4->assign<Transform>();
wall4->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings())); wall4->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings()));
wall4->assign<Texture>("Resources/Glass.png", Texture::Settings(true, true)); wall4->assign<Texture>("Resources/Glass.png", Texture::Settings(true, true));
wall4->assign<Material>(0.2, 0.8);
wall4->get<Transform>()->translate(glm::vec3(-4.0f, 0.0f, -6.0f)); wall4->get<Transform>()->translate(glm::vec3(-4.0f, 0.0f, -6.0f));
wall4->get<Transform>()->rotate(90.0, glm::vec3(0.0, 1.0, 0.0)); wall4->get<Transform>()->rotate(90.0, glm::vec3(0.0, 1.0, 0.0));
@ -128,6 +135,9 @@ int main() {
ground->assign<Texture>("Resources/Grass.jpg", Texture::Settings(true, false)); ground->assign<Texture>("Resources/Grass.jpg", Texture::Settings(true, false));
ground->get<Transform>()->translate(glm::vec3(0.0f, 0.0f, 0.0f)); ground->get<Transform>()->translate(glm::vec3(0.0f, 0.0f, 0.0f));
Entity *sun = world->create();
sun->assign<DirectionalLight>(glm::normalize(glm::vec3(1.0, 1.0, 1.0)));
Shader defaultShader("Shaders/default-vertex.vs", "Shaders/default-fragment.fs"); Shader defaultShader("Shaders/default-vertex.vs", "Shaders/default-fragment.fs");
double timeInLastFrame = glfwGetTime(); double timeInLastFrame = glfwGetTime();