Revamp the shader and lighting system
This commit is contained in:
parent
74d65ee092
commit
7135ebab6b
|
@ -1,102 +1,95 @@
|
|||
#version 430 core
|
||||
|
||||
in layout(location = 0) vec3 normal;
|
||||
in layout(location = 1) vec3 vertex;
|
||||
in layout(location = 0) vec3 vertex;
|
||||
in layout(location = 1) vec3 normal;
|
||||
in layout(location = 2) vec2 UV;
|
||||
in layout(location = 3) mat3 TBN;
|
||||
|
||||
layout(binding = 0) uniform sampler2D diffuseTexture;
|
||||
layout(binding = 1) uniform sampler2D normalTexture;
|
||||
layout(binding = 2) uniform sampler2D displacementTexture;
|
||||
uniform float displacementCoefficient;
|
||||
|
||||
uniform mat4 MVP;
|
||||
uniform mat4 MV;
|
||||
uniform mat4 MVnormal;
|
||||
|
||||
uniform float shininess;
|
||||
|
||||
uniform bool isIlluminated;
|
||||
uniform bool isTextured;
|
||||
uniform bool isNormalMapped;
|
||||
uniform bool isDisplacementMapped;
|
||||
uniform bool isInverted;
|
||||
|
||||
// lights
|
||||
struct Light { // coordinates in MV space
|
||||
struct Light { // point lights, coordinates in MV space
|
||||
vec3 position;
|
||||
vec3 spot_target;
|
||||
vec3 attenuation; // 1 / (x + y*l + z*l*l)
|
||||
vec3 color_emissive;
|
||||
vec3 color_diffuse;
|
||||
vec3 color_specular;
|
||||
|
||||
bool is_spot; // false means point light
|
||||
vec3 spot_target;
|
||||
float spot_cuttof_angle;
|
||||
};
|
||||
|
||||
//named
|
||||
#define N_LIGHTS 3
|
||||
|
||||
#define N_LIGHTS 1
|
||||
uniform Light light[N_LIGHTS];
|
||||
|
||||
|
||||
out vec4 color;
|
||||
|
||||
// constants
|
||||
float shininess = 15;
|
||||
vec3 c_diffuse = vec3(0.75390625, 0.4296875, 0.4375);
|
||||
vec3 c_emissive = vec3(0.01171875, 0.0, 0.15234375);
|
||||
vec3 c_specular = vec3(0.9453125, 0.94921875, 0.84765625);
|
||||
|
||||
float spot_cuttof_angle = cos(1.5 / 180.0 * 3.1415926535);
|
||||
|
||||
void main_(vec4 basecolor) {
|
||||
vec3 nnormal;
|
||||
vec4 phong(vec4 basecolor) {
|
||||
vec3 nnormal; // normalized normal
|
||||
if (isNormalMapped) {
|
||||
vec3 tangential = texture(normalTexture, UV).rgb * 2.0 - 1.0;
|
||||
nnormal = TBN * -normalize(tangential);
|
||||
} else {
|
||||
nnormal = TBN * normalize(tangential);
|
||||
}
|
||||
else {
|
||||
nnormal = normalize(normal);
|
||||
}
|
||||
|
||||
float diffuse_intensity = 0.0;
|
||||
float specular_intensity = 0.0;
|
||||
vec3 emmissive_component = vec3(0.0);
|
||||
vec3 diffuse_component = vec3(0.0);
|
||||
vec3 specular_component = vec3(0.0);
|
||||
|
||||
for (int i = 0; i<3; i++) {
|
||||
for (int i = 0; i<N_LIGHTS; i++) {
|
||||
vec3 L = light[i].position - vertex;
|
||||
float l = length(L);
|
||||
float attenuation = clamp(2000/(1 + 1*l + 0.1*l*l), 0.0, 1.25);
|
||||
L = normalize(L);
|
||||
|
||||
if (light[i].is_spot) {
|
||||
vec3 L2 = normalize(light[i].position - light[i].spot_target);
|
||||
if (dot(L2, L) < spot_cuttof_angle) {
|
||||
if (dot(normalize(light[i].position - light[i].spot_target), L) < light[i].spot_cuttof_angle) {
|
||||
continue;
|
||||
}
|
||||
attenuation *= 30;
|
||||
}
|
||||
|
||||
float attenuation = clamp(1 / (
|
||||
light[i].attenuation.x +
|
||||
light[i].attenuation.y * l +
|
||||
light[i].attenuation.z * l * l
|
||||
), 0.0, 1.25);
|
||||
|
||||
float diffuse_i = dot(nnormal, L);
|
||||
float specular_i = pow(dot(reflect(-L, nnormal), normalize(-vertex)), shininess);
|
||||
|
||||
float specular_i = pow(dot(reflect(-L, nnormal), normalize(vec3(0,0,0) - vertex)), shininess);
|
||||
|
||||
|
||||
if (diffuse_i > 0) diffuse_intensity += attenuation*diffuse_i;
|
||||
if (specular_i > 0) specular_intensity += attenuation*specular_i;
|
||||
emmissive_component += light[i].color_emissive;
|
||||
if (diffuse_i>0) diffuse_component += light[i].color_diffuse * diffuse_i * attenuation;
|
||||
if (specular_i>0) specular_component += light[i].color_specular * specular_i * attenuation;
|
||||
}
|
||||
|
||||
//diffuse_intensity *= 1.0 / N_LIGHTS;
|
||||
//specular_intensity *= 1.0 / N_LIGHTS;
|
||||
|
||||
|
||||
//float intensity = dot(normalize(normal), normalize(light_pos_2));
|
||||
//color = vec4(0.5 * normal + 0.5, 1.0);
|
||||
|
||||
color = basecolor * vec4(c_emissive
|
||||
+ c_diffuse*diffuse_intensity, 1.0f)
|
||||
+ vec4(c_specular*specular_intensity, 1.0f);
|
||||
return vec4(basecolor.rgb * (emmissive_component + diffuse_component) + specular_component, basecolor.a);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void main() {
|
||||
if(isIlluminated) {
|
||||
if (isTextured) {
|
||||
c_diffuse = vec3(0.9);
|
||||
c_emissive = vec3(0.2);
|
||||
main_(texture(diffuseTexture, UV));
|
||||
color = phong(texture(diffuseTexture, UV));
|
||||
} else {
|
||||
main_(vec4(1.0));
|
||||
|
||||
color = phong(vec4(1.0));
|
||||
}
|
||||
} else {
|
||||
color = texture(diffuseTexture, UV);
|
||||
|
|
|
@ -6,6 +6,9 @@ in layout(location = 2) vec2 UV;
|
|||
in layout(location = 3) vec3 tangent;
|
||||
in layout(location = 4) vec3 bitangent;
|
||||
|
||||
layout(binding = 2) uniform sampler2D displacementTexture;
|
||||
uniform float displacementCoefficient;
|
||||
|
||||
uniform mat4 MVP;
|
||||
uniform mat4 MV;
|
||||
uniform mat4 MVnormal;
|
||||
|
@ -13,8 +16,8 @@ uniform bool isIlluminated;
|
|||
uniform bool isTextured;
|
||||
uniform bool isNormalMapped;
|
||||
|
||||
out layout(location = 0) vec3 normal_out;
|
||||
out layout(location = 1) vec3 vertex_out;
|
||||
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;
|
||||
|
||||
|
|
|
@ -39,7 +39,8 @@ SceneNode* padNode;
|
|||
SceneNode* hudNode;
|
||||
SceneNode* textNode;
|
||||
|
||||
SceneNode* lightNode[3];
|
||||
const uint N_LIGHTS = 1;
|
||||
SceneNode* lightNode[N_LIGHTS];
|
||||
|
||||
// These are heap allocated, because they should not be initialised at the start of the program
|
||||
sf::Sound* sound;
|
||||
|
@ -122,7 +123,7 @@ void initGame(GLFWwindow* window, CommandLineOptions gameOptions) {
|
|||
plainNode->setTexture(&t_plain_diff, &t_plain_normal);
|
||||
|
||||
// add lights
|
||||
for (int i = 0; i<3; i++) {
|
||||
for (uint i = 0; i<N_LIGHTS; i++) {
|
||||
lightNode[i] = createSceneNode(POINT_LIGHT);
|
||||
lightNode[i]->lightID = i;
|
||||
}
|
||||
|
@ -151,8 +152,6 @@ void updateNodeTransformations(SceneNode* node, mat4 transformationThusFar, mat4
|
|||
mat4 transformationMatrix(1.0);
|
||||
|
||||
switch(node->nodeType) {
|
||||
case NORMAL_TEXTURED_GEOMETRY:
|
||||
case TEXTURED_GEOMETRY:
|
||||
case GEOMETRY:
|
||||
transformationMatrix =
|
||||
glm::translate(mat4(1.0), node->position)
|
||||
|
@ -254,19 +253,29 @@ 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;
|
||||
vec3 position;
|
||||
vec3 spot_target;
|
||||
bool is_spot;
|
||||
float spot_cuttof_angle;
|
||||
vec3 attenuation;
|
||||
vec3 color_emissive;
|
||||
vec3 color_diffuse;
|
||||
vec3 color_specular;
|
||||
|
||||
void push_to_shader(Gloom::Shader* shader, uint id) {
|
||||
#define l(x) shader->location("light[" + std::to_string(id) + "]." + #x)
|
||||
glUniform3fv (l(position) , 1, glm::value_ptr(position));
|
||||
glUniform3fv (l(spot_target), 1, glm::value_ptr(spot_target));
|
||||
glUniform1i (l(is_spot) , is_spot);
|
||||
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));
|
||||
#undef l
|
||||
}
|
||||
};
|
||||
static Light lights[3];
|
||||
static Light lights[N_LIGHTS];
|
||||
static Gloom::Shader* s = nullptr; // The currently active shader
|
||||
|
||||
// activate the correct shader
|
||||
|
@ -279,26 +288,24 @@ void renderNode(SceneNode* node, Gloom::Shader* parent_shader = default_shader)
|
|||
uint i = 0; for (Light l : lights) l.push_to_shader(s, i++);
|
||||
}
|
||||
|
||||
// load uniforms
|
||||
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));
|
||||
glUniform1ui(s->location("isNormalMapped"), false);
|
||||
glUniform1ui(s->location("isTextured"), false);
|
||||
|
||||
switch(node->nodeType) {
|
||||
case NORMAL_TEXTURED_GEOMETRY:
|
||||
glUniform1ui(s->location("isNormalMapped"), true);
|
||||
glBindTextureUnit(1, node->normalTextureID);
|
||||
[[fallthrough]];
|
||||
case TEXTURED_GEOMETRY:
|
||||
glUniform1ui(s->location("isTextured"), true);
|
||||
glBindTextureUnit(0, node->diffuseTextureID);
|
||||
[[fallthrough]];
|
||||
case GEOMETRY:
|
||||
if(node->vertexArrayObjectID != -1) {
|
||||
glUniform1ui(s->location("isIlluminated"), node->isIlluminated);
|
||||
glUniform1ui(s->location("isInverted"), node->isInverted);
|
||||
// load uniforms
|
||||
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));
|
||||
glUniform1f( s->location("shinyness"), node->shinyness);
|
||||
glUniform1f( s->location("displacementCoefficient"), node->displacementCoefficient);
|
||||
glUniform1ui(s->location("isTextured"), node->isTextured);
|
||||
glUniform1ui(s->location("isNormalMapped"), node->isNormalMapped);
|
||||
glUniform1ui(s->location("isDisplacementMapped"), node->isDisplacementMapped);
|
||||
glUniform1ui(s->location("isIlluminated"), node->isIlluminated);
|
||||
glUniform1ui(s->location("isInverted"), node->isInverted);
|
||||
|
||||
if (node->isTextured) glBindTextureUnit(0, node->diffuseTextureID);
|
||||
if (node->isNormalMapped) glBindTextureUnit(1, node->normalTextureID);
|
||||
if (node->isDisplacementMapped) glBindTextureUnit(2, node->displacementTextureID);
|
||||
glBindVertexArray(node->vertexArrayObjectID);
|
||||
glDrawElements(GL_TRIANGLES, node->VAOIndexCount, GL_UNSIGNED_INT, nullptr);
|
||||
}
|
||||
|
@ -306,9 +313,14 @@ 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].is_spot = node->nodeType == SPOT_LIGHT;
|
||||
lights[id].spot_target = node->rotation;
|
||||
lights[id].position = vec3(node->MV * glm::vec4(node->position, 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].attenuation = node->attenuation;
|
||||
lights[id].color_emissive = node->color_emissive;
|
||||
lights[id].color_diffuse = node->color_diffuse;
|
||||
lights[id].color_specular = node->color_specular;
|
||||
lights[id].push_to_shader(s, id);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
@ -22,7 +23,9 @@ using std::vector;
|
|||
typedef unsigned int uint;
|
||||
|
||||
enum SceneNodeType {
|
||||
GEOMETRY, POINT_LIGHT, SPOT_LIGHT, TEXTURED_GEOMETRY, NORMAL_TEXTURED_GEOMETRY
|
||||
GEOMETRY,
|
||||
POINT_LIGHT,
|
||||
SPOT_LIGHT,
|
||||
};
|
||||
|
||||
struct SceneNode {
|
||||
|
@ -34,58 +37,84 @@ struct SceneNode {
|
|||
static map<Mesh*, int> cache;
|
||||
|
||||
if (cache.find(mesh) == cache.end())
|
||||
cache[mesh] = generateBuffer(*mesh, nodeType==NORMAL_TEXTURED_GEOMETRY);
|
||||
cache[mesh] = generateBuffer(*mesh, isNormalMapped || isDisplacementMapped);
|
||||
|
||||
vertexArrayObjectID = cache[mesh];
|
||||
VAOIndexCount = mesh->indices.size();
|
||||
}
|
||||
void setTexture(PNGImage* diffuse, PNGImage* normal = nullptr) {
|
||||
void setTexture(PNGImage* diffuse, PNGImage* normal=nullptr, PNGImage* displacement=nullptr) {
|
||||
static map<PNGImage*, int> cache;
|
||||
assert(vertexArrayObjectID==-1);
|
||||
|
||||
if (cache.find(diffuse) == cache.end()) cache[diffuse] = generateTexture(*diffuse);
|
||||
diffuseTextureID = cache[diffuse];
|
||||
if (diffuse) {
|
||||
if (cache.find(diffuse) == cache.end())
|
||||
cache[diffuse] = generateTexture(*diffuse);
|
||||
diffuseTextureID = cache[diffuse];
|
||||
isTextured = true;
|
||||
}
|
||||
|
||||
if (!normal) return;
|
||||
if (cache.find(normal) == cache.end()) cache[normal] = generateTexture(*normal);
|
||||
normalTextureID = cache[normal];
|
||||
if (normal) {
|
||||
if (cache.find(normal) == cache.end())
|
||||
cache[normal] = generateTexture(*normal);
|
||||
normalTextureID = cache[normal];
|
||||
isNormalMapped = true;
|
||||
}
|
||||
|
||||
if (displacement) {
|
||||
if (cache.find(displacement) == cache.end())
|
||||
cache[displacement] = generateTexture(*displacement);
|
||||
displacementTextureID = cache[displacement];
|
||||
isDisplacementMapped = true;
|
||||
}
|
||||
}
|
||||
|
||||
// this node
|
||||
SceneNodeType nodeType;
|
||||
vector<SceneNode*> children;
|
||||
|
||||
// light specific:
|
||||
uint lightID = -1;
|
||||
vec3 color_emissive = vec3(0.0);
|
||||
vec3 color_diffuse = vec3(0.8);
|
||||
vec3 color_specular = vec3(0.5);
|
||||
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
|
||||
|
||||
// The node's position and rotation relative to its parent
|
||||
vec3 position = vec3(0, 0, 0);
|
||||
vec3 rotation = vec3(0, 0, 0);
|
||||
vec3 rotation = vec3(0, 0, 0); // also used as spot-target
|
||||
vec3 scale = vec3(1, 1, 1);
|
||||
|
||||
// set this if the shape uses a custom shader other than the inherited one
|
||||
Gloom::Shader* shader = nullptr;
|
||||
|
||||
// A transformation matrix representing the transformation of the node's location relative to its parent. This matrix is updated every frame.
|
||||
mat4 MVP; // MVP
|
||||
mat4 MV; // MV
|
||||
mat4 MVnormal; // transpose(inverse(MV))
|
||||
|
||||
// The location of the node's reference point (center of rotation)
|
||||
vec3 referencePoint = vec3(0, 0, 0);
|
||||
vec3 referencePoint = vec3(0, 0, 0); // center of rotation, in model space
|
||||
|
||||
// VAO IDs refering to a loaded Mesh and its length
|
||||
int vertexArrayObjectID = -1;
|
||||
uint VAOIndexCount = 0;
|
||||
|
||||
// textures
|
||||
float shinyness = 10.0; // specular power
|
||||
uint diffuseTextureID;
|
||||
uint normalTextureID;
|
||||
uint displacementTextureID;
|
||||
float displacementCoefficient = 0.1; // in units
|
||||
|
||||
// shader flags
|
||||
bool isTextured = false;
|
||||
bool isNormalMapped = false;
|
||||
bool isDisplacementMapped = false;
|
||||
bool isIlluminated = true;
|
||||
bool isInverted = false;
|
||||
|
||||
// Node type is used to determine how to handle the contents of a node
|
||||
SceneNodeType nodeType;
|
||||
// rendering
|
||||
Gloom::Shader* shader = nullptr;
|
||||
mat4 MVP; // MVP
|
||||
mat4 MV; // MV
|
||||
mat4 MVnormal; // transpose(inverse(MV))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// for lights:
|
||||
uint lightID;
|
||||
SceneNode* targeted_by = nullptr; // spot
|
||||
};
|
||||
|
||||
// Struct for keeping track of 2D coordinates
|
||||
|
|
|
@ -64,7 +64,7 @@ void addTangents(uint vaoID, Mesh& mesh) {
|
|||
vec2 deltaUV1 = uv2 - uv1;
|
||||
vec2 deltaUV2 = uv3 - uv1;
|
||||
|
||||
float f = -1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);
|
||||
float f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);
|
||||
|
||||
vec3 tangent{
|
||||
f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x),
|
||||
|
|
Loading…
Reference in New Issue