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(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})

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 Settings {
Settings(float minDistanceForRender, float maxDistanceForRender) : minDistanceForRender(
minDistanceForRender), maxDistanceForRender(maxDistanceForRender) {}
Settings() = default;
Settings(float minDistanceForRender, float maxDistanceForRender, float diffuse, float specular)
: minDistanceForRender(minDistanceForRender), maxDistanceForRender(maxDistanceForRender) {}
float minDistanceForRender = 0.0;
float maxDistanceForRender = 1000.0;
};

View File

@ -13,6 +13,8 @@
#include "../Components/ObjMesh.h"
#include "../Components/Texture.h"
#include "../Components/LODObjMesh.h"
#include "../Components/DirectionalLight.h"
#include "../../Rendering/Material.h"
using namespace ECS;
@ -26,15 +28,22 @@ public:
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("view", glm::inverse(cameraTransform->matrix));
shader.setVec3("cameraPosition", cameraTransform->getPosition());
std::vector<RenderObject> renderObjects;
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));
});
});*/
glm::vec3 cameraPos = cameraTransform->getPosition();
@ -55,26 +64,40 @@ public:
float distance = glm::distance(cameraPos, transform->getPosition());
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
if (texture->render_transparent) {
transparentRenderObjects.emplace_back(RenderObject(transform->matrix, texture->id, mesh.get(), distance));
if (textureComponent.isValid() && textureComponent->render_transparent) {
transparentRenderObjects.emplace_back(RenderObject(transform->matrix, textureID, mesh.get(), distance, material));
} 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
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());
for (const auto &mesh : lodMesh->meshes) {
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
if (texture->render_transparent) {
transparentRenderObjects.emplace_back(RenderObject(transform->matrix, texture->id, mesh, distance));
if (textureComponent.isValid() && textureComponent->render_transparent) {
transparentRenderObjects.emplace_back(RenderObject(transform->matrix, textureID, mesh, distance, material));
} 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 {
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),
texture_id(textureId),
mesh(mesh),
distance(distance) {}
distance(distance),
material(material) {}
void render(Shader shader) const {
shader.setMat4("model", matrix);
@ -109,6 +133,9 @@ public:
glBindTexture(GL_TEXTURE_2D, texture_id);
}
shader.setFloat("diffuseStrength", material.diffuse);
shader.setFloat("specularStrength", material.specular);
mesh.render();
}
@ -116,6 +143,7 @@ public:
unsigned int texture_id;
Mesh mesh;
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));
}
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) {
int success;
char infoLog[1024];

View File

@ -32,6 +32,9 @@ public:
/// Set a uniform mat4 in the shader
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:
static void checkCompileErrors(unsigned int shader, const std::string &type);
};

View File

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

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 vec3 Normal;
in mediump vec3 FragPos;
uniform sampler2D tex;
uniform mediump vec3 lightDirection;
uniform mediump vec3 cameraPosition;
uniform mediump float diffuseStrength;
uniform mediump float specularStrength;
void main()
{
@ -14,5 +20,23 @@ void main()
if(texColor.a < 0.1)
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 vec3 Normal;
out vec3 FragPos;
uniform mat4 model;
uniform mat4 view;
@ -15,4 +16,5 @@ void main()
gl_Position = projection * view * model * vec4(aPos, 1.0);
TexCoord = UV;
Normal = NORMAL;
FragPos = vec3(model * vec4(aPos, 1.0));
}

View File

@ -16,6 +16,7 @@
#include "ECS/Components/Texture.h"
#include "ECS/Components/SineAnimation.h"
#include "ECS/Systems/SineAnimationSystem.h"
#include "ECS/Components/DirectionalLight.h"
using namespace ECS;
@ -43,7 +44,7 @@ int main() {
return -1;
/* 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) {
glfwTerminate();
return -1;
@ -76,7 +77,7 @@ int main() {
// world->registerSystem(new GravitySystem(-9.8f));
// world->registerSystem(new PositionDebugOutputSystem());
world->registerSystem(new KeyboardMovementSystem());
world->registerSystem(new MouseLookSystem(640, 480));
world->registerSystem(new MouseLookSystem(1280, 720));
world->registerSystem(new SineAnimationSystem());
RenderSystem* renderSystem = new RenderSystem();
@ -85,33 +86,38 @@ int main() {
Entity *player = world->create();
player->assign<Transform>();
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->get<Transform>()->translate(glm::vec3(0.0f, 1.0f, 2.0f));
Entity *monkey = world->create();
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<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));
Entity *wall1 = world->create();
wall1->assign<Transform>();
wall1->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings()));
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));
Entity *wall2 = world->create();
wall2->assign<Transform>();
wall2->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings()));
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));
Entity *wall3 = world->create();
wall3->assign<Transform>();
wall3->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings()));
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>()->rotate(90.0, glm::vec3(0.0, 1.0, 0.0));
@ -119,6 +125,7 @@ int main() {
wall4->assign<Transform>();
wall4->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings()));
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>()->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->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");
double timeInLastFrame = glfwGetTime();