Introduce normal mapping

This commit is contained in:
2021-02-21 19:54:17 +01:00
parent 194ae3abf4
commit 164c76f4a3
15 changed files with 155 additions and 77 deletions

1
.gitignore vendored
View File

@@ -4,3 +4,4 @@ build
res/models
res/textures
.kdev4
.cache

View File

@@ -1,5 +1,5 @@
if(UNIX)
set(CMAKE_GENERATOR "Ninja" CACHE INTERNAL "" FORCE)
set(CMAKE_GENERATOR "Unix Makefiles" CACHE INTERNAL "" FORCE)
endif(UNIX)
if(WIN32)

View File

@@ -15,6 +15,10 @@
{
"unique_name": "cube",
"path": "data/res/models/cube.ffo"
},
{
"unique_name": "container",
"path": "data/res/models/container.ffo"
}
],
"entities": [
@@ -26,6 +30,13 @@
"rotation": [0.0, 0.0, 0.0],
"scale": 0.6
},
{
"unique_name": "container",
"model": "container",
"shaderProgram": "defaultProgram",
"position": [10.0, 1.0, 0.0],
"rotation": [45.0, 45.0, 45.0]
},
{
"unique_name": "ground",
"model": "ground",
@@ -37,6 +48,12 @@
"shaderProgram": "lightProgram"
}
],
"textures" : [
{
"unique_name": "fallback_normal",
"path": "data/res/models/tex/fallback_normal.png"
}
],
"skybox": {
"texturePath": "data/res/textures/skybox/"
}

View File

@@ -5,42 +5,39 @@ layout(location = 0) out vec4 f_color;
in vec3 v_normal;
in vec2 v_texCoord;
in vec3 v_fragmentPosition;
in vec3 v_fragmentPositionTangent;
in vec4 v_fragmentPositionDirectionalLightSpace;
in vec3 v_lightDirectionTangent;
in vec3 v_lightPositionTangent0;
//in vec3 v_lightPositionTangent1;
//in vec3 v_lightPositionTangent2;
//in vec3 v_lightPositionTangent3;
in vec3 v_viewPositionTangent;
struct Material {
sampler2D texture_diffuse0;
sampler2D texture_diffuse1;
sampler2D texture_specular0;
sampler2D texture_specular1;
sampler2D texture_normal0;
sampler2D texture_normal1;
sampler2D texture_height0;
sampler2D texture_height1;
sampler2D texture_gloss0;
sampler2D texture_gloss1;
float shininess;
};
uniform Material u_material;
struct DirectionalLight {
bool isActive;
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
bool isActive;
vec3 color;
};
uniform DirectionalLight u_directionalLight;
struct PointLight {
bool isActive;
vec3 position;
float K_q;
vec3 ambient;
vec3 diffuse;
vec3 specular;
bool isActive;
vec3 color;
};
#define NUM_POINT_LIGHTS 1
uniform PointLight u_pointLight[NUM_POINT_LIGHTS];
@@ -62,7 +59,6 @@ uniform PointLight u_pointLight[NUM_POINT_LIGHTS];
uniform SpotLight u_spotLight;*/
uniform mat3 u_normalMatrix;
uniform vec3 u_viewPosition;
uniform sampler2D u_texture_directionalShadowMap;
uniform samplerCube u_texture_pointShadowMap0;
@@ -101,17 +97,18 @@ void main() {
vec3 fragmentColor = vec3(0.0f);
vec3 normal = normalize(u_normalMatrix * v_normal);
vec3 viewDir = normalize(u_viewPosition - v_fragmentPosition);
vec3 normal = texture(u_material.texture_normal0, v_texCoord).rgb;
normal = normalize(normal * 2.0 - 1.0);
vec3 viewDir = normalize(v_viewPositionTangent - v_fragmentPositionTangent);
fragmentColor += directionalLightContribution(u_directionalLight, normal, viewDir);
for(int i = 0; i < NUM_POINT_LIGHTS; i++) {
fragmentColor += pointLightContribution(u_pointLight[i], normal, v_fragmentPosition, viewDir);
fragmentColor += pointLightContribution(u_pointLight[i], normal, v_fragmentPositionTangent, viewDir);
}
// There are currently no spotlights
//fragmentColor += spotLightContribution(u_spotLight, normal, v_fragmentPosition, viewDir);
//fragmentColor += spotLightContribution(u_spotLight, normal, v_fragmentPositionTangent, viewDir);
f_color = vec4(fragmentColor, 1.0f);
@@ -123,10 +120,15 @@ vec3 directionalLightContribution(DirectionalLight light, vec3 normal, vec3 view
if(!light.isActive)
return vec3(0.0f);
vec3 lightDir = normalize(-light.direction);
//vec3 lightDir = normalize(-light.direction);
vec3 lightDir = normalize(-v_lightDirectionTangent);
vec3 diffuseColor = light.color;
vec3 specularColor = light.color;
vec3 ambientColor = light.color * 0.002f;
vec3 ambient, diffuse, specular;
computeShading(light.ambient, light.diffuse, light.specular, lightDir, viewDir, normal, ambient, diffuse, specular);
computeShading(ambientColor, diffuseColor, specularColor, lightDir, viewDir, normal, ambient, diffuse, specular);
float shadows = 0.0f;
if(b_drawShadows)
@@ -141,19 +143,23 @@ vec3 pointLightContribution(PointLight light, vec3 normal, vec3 fragPos, vec3 vi
if(!light.isActive)
return vec3(0.0f);
vec3 lightDir = normalize(light.position - fragPos);
vec3 lightDir = normalize(v_lightPositionTangent0 - fragPos);
vec3 diffuseColor = light.color;
vec3 specularColor = light.color;
vec3 ambientColor = light.color * 0.002f;
vec3 ambient, diffuse, specular;
computeShading(light.ambient, light.diffuse, light.specular, lightDir, viewDir, normal, ambient, diffuse, specular);
computeShading(ambientColor, diffuseColor, specularColor, lightDir, viewDir, normal, ambient, diffuse, specular);
float attenuation = computeAttenuation(light.position, fragPos, light.K_q);
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
float attenuation = computeAttenuation(v_lightPositionTangent0, fragPos, 0.032f);
//ambient *= attenuation;
//diffuse *= attenuation;
//specular *= attenuation;
float shadows = 0.0f;
if(b_drawShadows)
shadows = computePointShadows(fragPos, light.position);
shadows = computePointShadows(v_fragmentPosition, light.position);
return (ambient + (1.0f - shadows) * (diffuse + specular));
}
@@ -240,7 +246,6 @@ float computeDirectionalShadows(vec4 fragPosLightSpace, vec3 normal, vec3 lightD
}
shadow /= 9.0f;
return shadow;
}
@@ -255,7 +260,7 @@ float computePointShadows(vec3 fragPos, vec3 lightPos) {
float shadow = 0.0;
float bias = 0.05;
int samples = 20;
float viewDistance = length(u_viewPosition - fragPos);
float viewDistance = length(v_viewPositionTangent - fragPos);
float diskRadius = 0.05;
for(int i = 0; i < samples; ++i) {

View File

@@ -1,15 +1,42 @@
#version 330 core
layout(location = 0) in vec3 a_position;
layout(location = 1) in vec3 a_normal;
layout(location = 2) in vec2 a_texCoord;
layout(location = 1) in vec2 a_texCoord;
layout(location = 2) in vec3 a_normal;
layout(location = 3) in vec3 a_tangent;
layout(location = 4) in vec3 a_bitangent;
out vec3 v_normal;
out vec2 v_texCoord;
out vec3 v_fragmentPosition;
out vec3 v_fragmentPositionTangent;
out vec4 v_fragmentPositionDirectionalLightSpace;
out vec3 v_viewPositionTangent;
struct DirectionalLight {
vec3 direction;
bool isActive;
vec3 color;
};
uniform DirectionalLight u_directionalLight;
out vec3 v_lightDirectionTangent;
struct PointLight {
vec3 position;
bool isActive;
vec3 color;
};
#define NUM_POINT_LIGHTS 1
uniform PointLight u_pointLight[NUM_POINT_LIGHTS];
out vec3 v_lightPositionTangent0;
//out vec3 v_lightPositionTangent1;
//out vec3 v_lightPositionTangent2;
//out vec3 v_lightPositionTangent3;
uniform vec3 u_viewPosition;
uniform mat4 u_modelViewProjMatrix;
uniform mat4 u_modelMatrix;
@@ -18,8 +45,23 @@ uniform mat4 u_directionalLightViewProjMatrix;
void main() {
gl_Position = u_modelViewProjMatrix * vec4(a_position, 1.0f);
vec3 T = normalize(vec3(u_modelMatrix * vec4(a_tangent, 0.0f)));
vec3 B = normalize(vec3(u_modelMatrix * vec4(a_bitangent, 0.0f)));
vec3 N = normalize(vec3(u_modelMatrix * vec4(a_normal, 0.0f)));
mat3 TBN_transposed = transpose(mat3(T, B, N));
v_lightDirectionTangent = TBN_transposed * u_directionalLight.direction;
v_lightPositionTangent0 = TBN_transposed * u_pointLight[0].position;
//v_lightPositionTangent1 = vec3(0.0f);
//v_lightPositionTangent2 = vec3(0.0f);
//v_lightPositionTangent3 = vec3(0.0f);
v_fragmentPositionTangent = TBN_transposed * vec3(u_modelMatrix * vec4(a_position, 1.0f));
v_fragmentPosition = vec3(u_modelMatrix * vec4(a_position, 1.0f));
v_fragmentPositionDirectionalLightSpace = u_directionalLightViewProjMatrix * vec4(v_fragmentPosition, 1.0);
v_fragmentPositionDirectionalLightSpace = u_directionalLightViewProjMatrix * vec4(v_fragmentPosition, 1.0f);
v_viewPositionTangent = TBN_transposed * u_viewPosition;
v_normal = a_normal;
v_texCoord = a_texCoord;

View File

@@ -1,7 +1,7 @@
#version 330 core
layout(location = 0) in vec3 a_position;
layout(location = 2) in vec2 a_texCoord;
layout(location = 1) in vec2 a_texCoord;
out vec2 v_texCoord;

View File

@@ -9,7 +9,7 @@ Size=894,195
Collapsed=0
[Window][Debug Utils]
Pos=14,9
Pos=58,19
Size=791,379
Collapsed=0

View File

@@ -266,15 +266,12 @@ void Controller::renderImGui(World *world, PointLight *pointLight, glm::vec3 *li
// color picker
ImGui::Text("\nLight Source");
static float K_q = 1.0f;
ImGui::SliderFloat("Attenuation Parameter", &K_q, 0, 1.5f);
updateExposure(postProcessingProgram);
pointLight->setParameters(K_q);
static float color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
ImGui::SliderFloat("Intensity", intensity, 0, 50.f);
ImGui::SliderFloat("Intensity", intensity, 0, 250.f);
ImGui::ColorEdit3("Color", color);
lightColor->x = color[0];

View File

@@ -169,7 +169,7 @@ std::vector<Light*> JsonParser::getLights(ShaderProgram* shaderProgram)
const Json::Value pointLightsJson = root["pointLights"];
int index = 0;
for (; index < pointLightsJson.size(); index++) {
for (; index < (int)pointLightsJson.size(); index++) {
PointLight *current_pointLight;
const Json::Value positionJson = pointLightsJson[index]["position"];

View File

@@ -12,9 +12,6 @@ Light::Light(glm::vec3 color, float intensity, ShaderProgram* shaderProgram) :
{
id = id_counter++;
lightColor = color * intensity;
diffuseColor = lightColor * glm::vec3(1.0f);
ambientColor = diffuseColor * glm::vec3(0.002f);
specularColor = lightColor * glm::vec3(1.0f);
}
@@ -32,9 +29,6 @@ void Light::setShaderProgram(ShaderProgram* shaderProgram)
void Light::setColor(glm::vec3 color)
{
lightColor = color * intensity;
diffuseColor = lightColor * glm::vec3(1.0f);
ambientColor = diffuseColor * glm::vec3(0.002f);
specularColor = lightColor * glm::vec3(1.0f);
update();
}
@@ -65,10 +59,7 @@ void PointLight::update()
shaderProgram->setUniform((getStructMemberName() + "isActive").c_str(), isActive);
shaderProgram->setUniform((getStructMemberName() + "position").c_str(), position);
shaderProgram->setUniform((getStructMemberName() + "ambient").c_str(), ambientColor);
shaderProgram->setUniform((getStructMemberName() + "diffuse").c_str(), diffuseColor);
shaderProgram->setUniform((getStructMemberName() + "specular").c_str(), specularColor);
shaderProgram->setUniform((getStructMemberName() + "K_q").c_str(), K_q);
shaderProgram->setUniform((getStructMemberName() + "color").c_str(), lightColor);
shaderProgram->unbind();
}
@@ -91,11 +82,6 @@ void PointLight::setPosition(glm::vec3 position)
update();
}
void PointLight::setParameters(float K_q)
{
this->K_q = K_q;
}
// DirectionalLight
DirectionalLight::DirectionalLight(glm::vec3 direction, glm::vec3 color, float intensity, ShaderProgram *shaderProgram) :
@@ -111,9 +97,7 @@ void DirectionalLight::update()
shaderProgram->setUniform("u_directionalLight.isActive", isActive);
shaderProgram->setUniform("u_directionalLight.direction", direction);
shaderProgram->setUniform("u_directionalLight.ambient", ambientColor);
shaderProgram->setUniform("u_directionalLight.diffuse", diffuseColor);
shaderProgram->setUniform("u_directionalLight.specular", specularColor);
shaderProgram->setUniform("u_directionalLight.color", lightColor);
shaderProgram->unbind();
}

View File

@@ -36,9 +36,6 @@ protected:
// Color
glm::vec3 lightColor;
glm::vec3 diffuseColor;
glm::vec3 ambientColor;
glm::vec3 specularColor;
};
class PointLight : public Light
@@ -48,7 +45,6 @@ public:
~PointLight() = default;
void setPosition(glm::vec3 position);
void setParameters(float K_q);
glm::vec3 getPosition();
@@ -58,8 +54,6 @@ private:
private:
glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f);
float K_q = 0.032f;
};
class DirectionalLight : public Light

View File

@@ -77,6 +77,18 @@ void Model::loadModel(std::string &pathToModel)
loadedTextures.push_back(newTex);
}
// When there is no normal map bound, please use fallback texture
bool hasNormalMap = false;
for (auto it = textureTypes.begin(); it != textureTypes.end(); it++) {
if (*it == textureType::texture_normal)
hasNormalMap = true;
}
if (!hasNormalMap) {
Texture *newTex = new Texture("data/res/models/tex/fallback_normal.png", textureType::texture_normal);
loadedTextures.push_back(newTex);
}
// Here starts the first mesh
uint32_t numMeshes;
input.read((char *) &numMeshes, sizeof(uint32_t));
@@ -109,6 +121,11 @@ void Model::loadModel(std::string &pathToModel)
meshTextures.push_back(loadedTextures[currentTextureId]);
}
if (!hasNormalMap) {
// This will be the last texture
meshTextures.push_back(loadedTextures[numTextures]);
}
Mesh *currentMesh = new Mesh(meshVertices, meshIndices, meshTextures);
meshes.push_back(currentMesh);
}

View File

@@ -21,13 +21,21 @@ VertexArray::VertexArray(void *vertexData, void *indexData, uint32_t numVertices
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *) offsetof(struct Vertex, position));
// Normal vectors
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *) offsetof(struct Vertex, normalVec));
// UV Texture Mapping
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *) offsetof(struct Vertex, textureCoords));
// Normal vectors
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *) offsetof(struct Vertex, textureCoords));
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *) offsetof(struct Vertex, normalVec));
// Tangent vectors
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *) offsetof(struct Vertex, tangentVec));
// Bitangent vectors
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *) offsetof(struct Vertex, bitangentVec));
// This will also unbind the vertex buffer and index buffer
glBindVertexArray(0);

View File

@@ -160,6 +160,18 @@ Mesh processMesh(aiMesh *mesh, const aiScene *scene, Model *model) {
vector.z = mesh->mNormals[i].z;
vertex.normalVec = vector;
// Tangents
vector.x = mesh->mTangents[i].x;
vector.y = mesh->mTangents[i].y;
vector.z = mesh->mTangents[i].z;
vertex.tangentVec = vector;
// Bitangents
vector.x = mesh->mBitangents[i].x;
vector.y = mesh->mBitangents[i].y;
vector.z = mesh->mBitangents[i].z;
vertex.bitangentVec = vector;
// Texture UV mapping
if(mesh->mTextureCoords[0]) {
glm::vec2 vec;
@@ -191,9 +203,10 @@ Mesh processMesh(aiMesh *mesh, const aiScene *scene, Model *model) {
std::vector<Texture> specularMaps = loadMaterialTextures(material, aiTextureType_SPECULAR, texture_specular, &currentMesh, model);
textures.insert(textures.end(), specularMaps.begin(), specularMaps.end());
std::vector<Texture> normalMaps = loadMaterialTextures(material, aiTextureType_NORMALS, texture_normal, &currentMesh, model);
std::vector<Texture> normalMaps = loadMaterialTextures(material, aiTextureType_HEIGHT, texture_normal, &currentMesh, model);
textures.insert(textures.end(), normalMaps.begin(), normalMaps.end());
// Not entirely sure if aiTextureType_HEIGHT is correct
std::vector<Texture> heightMaps = loadMaterialTextures(material, aiTextureType_HEIGHT, texture_height, &currentMesh, model);
textures.insert(textures.end(), heightMaps.begin(), heightMaps.end());
}