Add displacement mapping with TBN being affected
This commit is contained in:
parent
15dfce421e
commit
c9e4332a65
|
@ -3,7 +3,8 @@
|
|||
in layout(location = 0) vec3 vertex;
|
||||
in layout(location = 1) vec3 normal;
|
||||
in layout(location = 2) vec2 UV;
|
||||
in layout(location = 3) mat3 TBN;
|
||||
in layout(location = 3) vec3 tangent;
|
||||
in layout(location = 4) vec3 bitangent;
|
||||
|
||||
layout(binding = 0) uniform sampler2D diffuseTexture;
|
||||
layout(binding = 1) uniform sampler2D normalTexture;
|
||||
|
@ -45,11 +46,36 @@ out vec4 color;
|
|||
vec4 phong(vec4 basecolor) {
|
||||
vec3 nnormal; // normalized normal
|
||||
if (isNormalMapped) {
|
||||
vec3 tangential = texture(normalTexture, UV).rgb * 2.0 - 1.0;
|
||||
nnormal = TBN * normalize(tangential);
|
||||
mat3 TBN;
|
||||
if (isDisplacementMapped) {
|
||||
float o = texture(displacementTexture, UV).r * 2.0 - 1.0;
|
||||
float u = (texture(displacementTexture, UV + vec2(0.0001, 0.0)).r*2.0-1.0 - o) / 0.0004; // magic numbers are great
|
||||
float v = (texture(displacementTexture, UV + vec2(0.0, 0.0001)).r*2.0-1.0 - o) / 0.0004; // magic numbers are great
|
||||
TBN = mat3(
|
||||
normalize(tangent + normal*u),
|
||||
normalize(bitangent + normal*v),
|
||||
normalize(cross(tangent + normal*u, bitangent + normal*v))
|
||||
);
|
||||
}
|
||||
else {
|
||||
TBN = mat3(
|
||||
normalize(tangent),
|
||||
normalize(bitangent),
|
||||
normalize(normal)
|
||||
);
|
||||
}
|
||||
nnormal = TBN * normalize(texture(normalTexture, UV).rgb * 2.0 - 1.0);
|
||||
}
|
||||
else {
|
||||
nnormal = normalize(normal);
|
||||
if (isDisplacementMapped) {
|
||||
float o = texture(displacementTexture, UV).r * 2.0 - 1.0;
|
||||
float u = (texture(displacementTexture, UV + vec2(0.0001, 0.0)).r*2.0-1.0 - o) / 0.0004;
|
||||
float v = (texture(displacementTexture, UV + vec2(0.0, 0.0001)).r*2.0-1.0 - o) / 0.0004;
|
||||
nnormal = normalize(cross(tangent + normal*u, bitangent + normal*v));
|
||||
}
|
||||
else {
|
||||
nnormal = normalize(normal);
|
||||
}
|
||||
}
|
||||
|
||||
vec3 emmissive_component = vec3(0.0);
|
||||
|
@ -74,14 +100,14 @@ vec4 phong(vec4 basecolor) {
|
|||
), 0.0, 1.25);
|
||||
|
||||
float diffuse_i = dot(nnormal, L);
|
||||
float specular_i = dot(reflect(-L, nnormal), vec3(0.0)-normalize(vertex));
|
||||
float specular_i = dot(reflect(-L, nnormal), -normalize(vertex));
|
||||
specular_i = (specular_i>0)
|
||||
? pow(specular_i, shinyness)
|
||||
: 0;
|
||||
|
||||
emmissive_component += light[i].color_emissive;
|
||||
if (diffuse_i>0) diffuse_component += light[i].color_diffuse * diffuse_i * attenuation;
|
||||
specular_component += light[i].color_specular * specular_i * attenuation;
|
||||
if (diffuse_i>0) diffuse_component += light[i].color_diffuse * diffuse_i * attenuation;
|
||||
}
|
||||
|
||||
return vec4(basecolor.rgb * (emmissive_component + diffuse_component) + specular_component, basecolor.a);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#version 430 core
|
||||
|
||||
in layout(location = 0) vec3 position;
|
||||
in layout(location = 1) vec3 normal_in;
|
||||
in layout(location = 1) vec3 normal;
|
||||
in layout(location = 2) vec2 UV;
|
||||
in layout(location = 3) vec3 tangent;
|
||||
in layout(location = 4) vec3 bitangent;
|
||||
|
@ -12,24 +12,37 @@ uniform float displacementCoefficient;
|
|||
uniform mat4 MVP;
|
||||
uniform mat4 MV;
|
||||
uniform mat4 MVnormal;
|
||||
|
||||
uniform float shinyness;
|
||||
uniform vec2 uvOffset;
|
||||
|
||||
uniform bool isIlluminated;
|
||||
uniform bool isTextured;
|
||||
uniform bool isNormalMapped;
|
||||
uniform bool isDisplacementMapped;
|
||||
uniform bool isInverted;
|
||||
|
||||
out layout(location = 0) vec3 vertex_out;
|
||||
out layout(location = 1) vec3 normal_out;
|
||||
out layout(location = 2) vec2 uv_out;
|
||||
out layout(location = 3) mat3 TBN;
|
||||
out layout(location = 3) vec3 tangent_out;
|
||||
out layout(location = 4) vec3 bitangent_out;
|
||||
|
||||
void main() {
|
||||
TBN = mat3(
|
||||
normalize(vec3(MV * vec4(tangent, 0.0))),
|
||||
normalize(vec3(MV * vec4(bitangent, 0.0))),
|
||||
normalize(vec3(MV * vec4(normal_in, 0.0)))
|
||||
);
|
||||
vec3 displacement = vec3(0.0);
|
||||
if (isDisplacementMapped){
|
||||
float o = texture(displacementTexture, UV + uvOffset).r * 2.0 - 1.0;
|
||||
float u = (texture(displacementTexture, UV + uvOffset + vec2(0.001, 0.0)).r*2.0-1.0 - o) / 0.004;
|
||||
float v = (texture(displacementTexture, UV + uvOffset + vec2(0.0, 0.001)).r*2.0-1.0 - o) / 0.004;
|
||||
|
||||
normal_out = normalize(vec3(MVnormal * vec4(normal_in, 1.0f)));
|
||||
vertex_out = vec3(MV*vec4(position, 1.0f));
|
||||
uv_out = UV;
|
||||
gl_Position = MVP * vec4(position, 1.0f);
|
||||
displacement = normal * displacementCoefficient * o;
|
||||
}
|
||||
|
||||
normal_out = normalize(vec3(MVnormal * vec4(normal, 1.0f)));
|
||||
vertex_out = vec3(MV * vec4(position+displacement, 1.0f));
|
||||
uv_out = UV + uvOffset;
|
||||
gl_Position = MVP * vec4(position+displacement, 1.0f);
|
||||
|
||||
tangent_out = normalize(vec3(MVnormal * vec4(tangent, 1.0f)));
|
||||
bitangent_out = normalize(vec3(MVnormal * vec4(bitangent, 1.0f)));
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <utilities/timeutils.h>
|
||||
|
||||
using glm::vec3;
|
||||
using glm::vec4;
|
||||
using glm::mat4;
|
||||
typedef unsigned int uint;
|
||||
|
||||
|
@ -153,40 +154,30 @@ void initGame(GLFWwindow* window, CommandLineOptions gameOptions) {
|
|||
std::cout << "Ready. Click to start!" << std::endl;
|
||||
}
|
||||
|
||||
void updateNodeTransformations(SceneNode* node, mat4 transformationThusFar, mat4 V, mat4 P) {
|
||||
mat4 transformationMatrix(1.0);
|
||||
void updateNodeTransformations(SceneNode* node, mat4 transformationThusFar, mat4 const& V, mat4 const& P) {
|
||||
mat4 transformationMatrix
|
||||
= glm::translate(mat4(1.0), node->position)
|
||||
* glm::translate(mat4(1.0), node->referencePoint)
|
||||
* glm::rotate(mat4(1.0), node->rotation.z, vec3(0,0,1))
|
||||
* glm::rotate(mat4(1.0), node->rotation.y, vec3(0,1,0))
|
||||
* glm::rotate(mat4(1.0), node->rotation.x, vec3(1,0,0))
|
||||
* glm::scale(mat4(1.0), node->scale)
|
||||
* glm::translate(mat4(1.0), -node->referencePoint);
|
||||
|
||||
switch(node->nodeType) {
|
||||
case GEOMETRY:
|
||||
transformationMatrix =
|
||||
glm::translate(mat4(1.0), node->position)
|
||||
* glm::translate(mat4(1.0), node->referencePoint)
|
||||
* glm::rotate(mat4(1.0), node->rotation.z, vec3(0,0,1))
|
||||
* glm::rotate(mat4(1.0), node->rotation.y, vec3(0,1,0))
|
||||
* glm::rotate(mat4(1.0), node->rotation.x, vec3(1,0,0))
|
||||
* glm::translate(mat4(1.0), -node->referencePoint)
|
||||
* glm::scale(mat4(1.0), node->scale);
|
||||
break;
|
||||
case POINT_LIGHT:
|
||||
case SPOT_LIGHT:
|
||||
transformationMatrix =
|
||||
glm::translate(mat4(1.0), node->position);
|
||||
break;
|
||||
}
|
||||
mat4 M = transformationThusFar * transformationMatrix;
|
||||
mat4 MV = V*M;
|
||||
|
||||
node->MV = MV;
|
||||
node->MVP = P*MV;
|
||||
node->MVnormal = glm::inverse(glm::transpose(MV));
|
||||
node->MV = V*M;
|
||||
node->MVP = P*node->MV;
|
||||
node->MVnormal = glm::inverse(glm::transpose(node->MV));
|
||||
|
||||
for(SceneNode* child : node->children) {
|
||||
updateNodeTransformations(child, M, V, P);
|
||||
}
|
||||
|
||||
// move this into the renderNode method and have it be targeted_node from the spot
|
||||
if (node->targeted_by != nullptr) {
|
||||
assert(node->targeted_by->nodeType == SPOT_LIGHT);
|
||||
node->targeted_by->rotation = vec3(MV*glm::vec4(node->position, 1.0));
|
||||
node->targeted_by->rotation = vec3(node->MV*vec4(node->position, 1.0));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,10 +227,9 @@ void updateFrame(GLFWwindow* window, int windowWidth, int windowHeight) {
|
|||
mat4 projection = glm::perspective(
|
||||
glm::radians(45.0f), // fovy
|
||||
float(windowWidth) / float(windowHeight), // aspect
|
||||
0.1f, 50000.f // near, far
|
||||
0.1f, 5000.f // near, far
|
||||
);
|
||||
|
||||
// hardcoded camera position...
|
||||
mat4 cameraTransform
|
||||
= glm::lookAt(cameraPosition, cameraLookAt, cameraUpward);
|
||||
|
||||
|
@ -258,25 +248,28 @@ void updateFrame(GLFWwindow* window, int windowWidth, int windowHeight) {
|
|||
void renderNode(SceneNode* node, Gloom::Shader* parent_shader = default_shader) {
|
||||
struct Light { // lights as stored in the shader
|
||||
// coordinates in MV space
|
||||
vec3 position;
|
||||
vec3 spot_target;
|
||||
bool is_spot;
|
||||
float spot_cuttof_angle;
|
||||
vec3 position; // MV
|
||||
vec3 attenuation;
|
||||
vec3 color_emissive;
|
||||
vec3 color_diffuse;
|
||||
vec3 color_specular;
|
||||
|
||||
bool is_spot;
|
||||
vec3 spot_target; // MV
|
||||
float spot_cuttof_angle;
|
||||
|
||||
void push_to_shader(Gloom::Shader* shader, uint id) {
|
||||
#define l(x) shader->location("light[" + std::to_string(id) + "]." + #x)
|
||||
glUniform1i (l(is_spot) , is_spot);
|
||||
glUniform1f (l(spot_cuttof_angle), spot_cuttof_angle);
|
||||
glUniform3fv(l(position) , 1, glm::value_ptr(position));
|
||||
glUniform3fv(l(spot_target) , 1, glm::value_ptr(spot_target));
|
||||
glUniform3fv(l(attenuation) , 1, glm::value_ptr(attenuation));
|
||||
glUniform3fv(l(color_emissive) , 1, glm::value_ptr(color_emissive));
|
||||
glUniform3fv(l(color_diffuse) , 1, glm::value_ptr(color_diffuse));
|
||||
glUniform3fv(l(color_specular) , 1, glm::value_ptr(color_specular));
|
||||
#define L(x) shader->location("light[" + std::to_string(id) + "]." #x)
|
||||
#define V(x) glUniform3fv(L(x), 1, glm::value_ptr(x))
|
||||
glUniform1i (L(is_spot) , is_spot);
|
||||
glUniform1f (L(spot_cuttof_angle), spot_cuttof_angle);
|
||||
V(position);
|
||||
V(spot_target);
|
||||
V(attenuation);
|
||||
V(color_emissive);
|
||||
V(color_diffuse);
|
||||
V(color_specular);
|
||||
#undef v
|
||||
#undef l
|
||||
}
|
||||
};
|
||||
|
@ -300,6 +293,7 @@ void renderNode(SceneNode* node, Gloom::Shader* parent_shader = default_shader)
|
|||
glUniformMatrix4fv(s->location("MVP") , 1, GL_FALSE, glm::value_ptr(node->MVP));
|
||||
glUniformMatrix4fv(s->location("MV") , 1, GL_FALSE, glm::value_ptr(node->MV));
|
||||
glUniformMatrix4fv(s->location("MVnormal"), 1, GL_FALSE, glm::value_ptr(node->MVnormal));
|
||||
glUniform2fv(s->location("uvOffset") , 1, glm::value_ptr(node->uvOffset));
|
||||
glUniform1f( s->location("shinyness"), node->shinyness);
|
||||
glUniform1f( s->location("displacementCoefficient"), node->displacementCoefficient);
|
||||
glUniform1ui(s->location("isTextured"), node->isTextured);
|
||||
|
@ -318,10 +312,10 @@ void renderNode(SceneNode* node, Gloom::Shader* parent_shader = default_shader)
|
|||
case SPOT_LIGHT:
|
||||
case POINT_LIGHT: {
|
||||
uint id = node->lightID;
|
||||
lights[id].position = vec3(node->MV * glm::vec4(node->position, 1.0));
|
||||
lights[id].position = vec3(node->MV * vec4(1.0));
|
||||
lights[id].is_spot = node->nodeType == SPOT_LIGHT;
|
||||
lights[id].spot_target = node->rotation;
|
||||
lights[id].spot_cuttof_angle = node->spot_cuttof_angle;
|
||||
lights[id].spot_target = node->rotation; // already MV space, todo: change this
|
||||
lights[id].spot_cuttof_angle = glm::sin(node->spot_cuttof_angle);
|
||||
lights[id].attenuation = node->attenuation;
|
||||
lights[id].color_emissive = node->color_emissive;
|
||||
lights[id].color_diffuse = node->color_diffuse;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <utilities/shader.hpp>
|
||||
#include <vector>
|
||||
|
||||
using glm::vec2;
|
||||
using glm::vec3;
|
||||
using glm::mat4;
|
||||
using std::map;
|
||||
|
@ -45,6 +46,9 @@ struct SceneNode {
|
|||
void setTexture(PNGImage* diffuse, PNGImage* normal=nullptr, PNGImage* displacement=nullptr) {
|
||||
static map<PNGImage*, int> cache;
|
||||
assert(vertexArrayObjectID==-1);
|
||||
isTextured = false;
|
||||
isNormalMapped = false;
|
||||
isDisplacementMapped = false;
|
||||
|
||||
if (diffuse) {
|
||||
if (cache.find(diffuse) == cache.end())
|
||||
|
@ -75,8 +79,8 @@ struct SceneNode {
|
|||
// light specific:
|
||||
uint lightID = -1;
|
||||
vec3 color_emissive = vec3(0.0);
|
||||
vec3 color_diffuse = vec3(0.8);
|
||||
vec3 color_specular = vec3(0.5);
|
||||
vec3 color_diffuse = vec3(0.0);
|
||||
vec3 color_specular = vec3(0.0);
|
||||
vec3 attenuation = vec3(1.0, 0.0, 0.001); // 1 / (x + y*l + z*l*l)
|
||||
float spot_cuttof_angle = glm::radians(1.5); // radians
|
||||
SceneNode* targeted_by = nullptr; // spot will follow this node
|
||||
|
@ -93,6 +97,7 @@ struct SceneNode {
|
|||
|
||||
// textures
|
||||
float shinyness = 10.0; // specular power
|
||||
vec2 uvOffset = vec2(0.0, 0.0); // specular power
|
||||
uint diffuseTextureID;
|
||||
uint normalTextureID;
|
||||
uint displacementTextureID;
|
||||
|
@ -111,10 +116,6 @@ struct SceneNode {
|
|||
mat4 MV; // MV
|
||||
mat4 MVnormal; // transpose(inverse(MV))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
// Struct for keeping track of 2D coordinates
|
||||
|
|
Loading…
Reference in New Issue