diff --git a/res/shaders/simple.frag b/res/shaders/simple.frag index aab0a87..cf17b8c 100644 --- a/res/shaders/simple.frag +++ b/res/shaders/simple.frag @@ -16,12 +16,16 @@ uniform mat4 MVP; uniform mat4 MV; uniform mat4 MVnormal; +// material +uniform float opacity; uniform float shininess; -uniform vec4 basecolor; +uniform vec3 diffuse_color; +uniform vec3 specular_color; +uniform vec3 emissive_color; uniform bool isIlluminated; uniform bool isTextured; -uniform bool isColorMapped; +uniform bool isVertexColored; uniform bool isNormalMapped; uniform bool isDisplacementMapped; uniform bool isInverted; @@ -30,13 +34,11 @@ uniform bool isInverted; struct Light { // point lights, coordinates in MV space vec3 position; vec3 attenuation; // 1 / (x + y*l + z*l*l) - vec3 color_emissive; - vec3 color_diffuse; - vec3 color_specular; + vec3 color; bool is_spot; // false means point light - vec3 spot_target; - float spot_cuttof_angle; + vec3 spot_direction; + float spot_cuttof_cos; }; #define N_LIGHTS 1 @@ -46,7 +48,7 @@ uniform Light light[N_LIGHTS]; out vec4 color_out; -vec4 phong(vec4 basecolor) { +vec3 phong(vec3 basecolor) { vec3 nnormal; // normalized normal if (isNormalMapped) { mat3 TBN; @@ -72,8 +74,8 @@ vec4 phong(vec4 basecolor) { else { 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; + float u = (texture(displacementTexture, UV + vec2(0.00001, 0.0)).r*2.0-1.0 - o) / 0.00004; + float v = (texture(displacementTexture, UV + vec2(0.0, 0.00001)).r*2.0-1.0 - o) / 0.00004; nnormal = normalize(cross(tangent + normal*u, bitangent + normal*v)); } else { @@ -81,9 +83,10 @@ vec4 phong(vec4 basecolor) { } } - vec3 emmissive_component = vec3(0.0); - vec3 diffuse_component = vec3(0.0); - vec3 specular_component = vec3(0.0); + vec3 diffuse_component = vec3(0.0); + vec3 specular_component = vec3(0.0); + float diffuse_i_sum = 0.0; + //vec3 emissive_component = vec3(0.0); for (int i = 0; i0) diffuse_component += light[i].color_diffuse * diffuse_i * attenuation; + specular_component += specular_color * light[i].color * specular_i * attenuation; + if (diffuse_i>0) diffuse_component += diffuse_color * light[i].color * diffuse_i * attenuation; + //emissive_component += emissive_color*light[i].color*attenuation; } - return vec4(basecolor.rgb * (emmissive_component + diffuse_component) + specular_component, basecolor.a); + basecolor *= (emissive_color + diffuse_component); + return basecolor + specular_component; } void main() { - vec4 c = basecolor; - if (isColorMapped) c *= color; - if (isTextured) c *= texture(diffuseTexture, UV); - if (isIlluminated) c = phong(c); - if (isInverted) c.rgb = 1 - c.rgb; + vec4 c = vec4(vec3(1.0), opacity); + if (isVertexColored) c *= color; + if (isTextured) c *= texture(diffuseTexture, UV); + if (isInverted) c.rgb = 1 - c.rgb; + if (isIlluminated) c.rgb = phong(c.rgb); + else c.rgb *= diffuse_color; + //c.rgb = diffuse_color; + //c.rgb = emissive_color; + //c.rgb = specular_color; color_out = c; } diff --git a/res/shaders/simple.vert b/res/shaders/simple.vert index 6320aa2..8ea91c4 100644 --- a/res/shaders/simple.vert +++ b/res/shaders/simple.vert @@ -7,6 +7,8 @@ in layout(location = 3) vec4 color; in layout(location = 4) vec3 tangent; in layout(location = 5) vec3 bitangent; +layout(binding = 0) uniform sampler2D diffuseTexture; +layout(binding = 1) uniform sampler2D normalTexture; layout(binding = 2) uniform sampler2D displacementTexture; uniform float displacementCoefficient; @@ -14,13 +16,20 @@ uniform mat4 MVP; uniform mat4 MV; uniform mat4 MVnormal; -uniform float shininess; +// material uniform vec2 uvOffset; +uniform float opacity; +uniform float shininess; +uniform vec3 diffuse_color; +uniform vec3 specular_color; +uniform vec3 emissive_color; uniform bool isIlluminated; uniform bool isTextured; +uniform bool isVertexColored; uniform bool isNormalMapped; uniform bool isDisplacementMapped; +uniform bool isReflectionMapped; uniform bool isInverted; out layout(location = 0) vec3 vertex_out; @@ -32,7 +41,7 @@ out layout(location = 5) vec3 bitangent_out; void main() { vec3 displacement = vec3(0.0); - if (isDisplacementMapped){ + 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; diff --git a/src/gamelogic.cpp b/src/gamelogic.cpp index bf89e42..b923900 100644 --- a/src/gamelogic.cpp +++ b/src/gamelogic.cpp @@ -172,20 +172,19 @@ void initGame(GLFWwindow* window, CommandLineOptions gameOptions) { boxNode->shininess = 20; boxNode->displacementCoefficient = 40; rootNode->children.push_back(boxNode); - - sphereNode = createSceneNode(); - sphereNode->setTexture(&t_cobble_diff, &t_cobble_normal); - sphereNode->setMesh(&sphere); - sphereNode->scale *= 2; - sphereNode->scale.z *= 20; - //lightNode[1]->children.push_back(sphereNode); */ + sphereNode = createSceneNode(); + //sphereNode->setTexture(&t_cobble_diff, &t_cobble_normal); + sphereNode->setMesh(&sphere); + sphereNode->position = {500, 500, 100}; + sphereNode->scale *= 15; + sphereNode->diffuse_color; + sphereNode->setMaterial(Material().reflection_mapped(&t_reflection, 0.5).no_colors().no_texture_reset(), true); + //rootNode->children.push_back(sphereNode); + lightNode[0]->position = {-600, 1400, 800}; - lightNode[0]->color_emissive = vec3(0.35); - lightNode[0]->color_diffuse = vec3(0.6); - lightNode[0]->color_specular = vec3(0.1); - lightNode[0]->attenuation = vec3(1.0, 0.0, 0.0); + lightNode[0]->attenuation = vec3(1.8, 0.0, 0.0); textNode = createSceneNode(); @@ -302,27 +301,23 @@ void renderNode(SceneNode* node, Gloom::Shader* parent_shader = default_shader) // coordinates in MV space vec3 position; // MV vec3 attenuation; - vec3 color_emissive; - vec3 color_diffuse; - vec3 color_specular; + vec3 color; bool is_spot; - vec3 spot_target; // MV - float spot_cuttof_angle; + vec3 spot_direction; // MV, must be normalized + float spot_cuttof_cos; void push_to_shader(Gloom::Shader* shader, uint id) { #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); + glUniform1f (L(spot_cuttof_cos), spot_cuttof_cos); V(position); - V(spot_target); + V(spot_direction); V(attenuation); - V(color_emissive); - V(color_diffuse); - V(color_specular); - #undef v - #undef l + V(color); + #undef V + #undef L } }; static Light lights[N_LIGHTS]; @@ -346,16 +341,21 @@ void renderNode(SceneNode* node, Gloom::Shader* parent_shader = default_shader) 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)); - glUniform4fv(s->location("basecolor") , 1, glm::value_ptr(node->basecolor)); + glUniform3fv(s->location("diffuse_color") , 1, glm::value_ptr(node->diffuse_color)); + glUniform3fv(s->location("emissive_color"), 1, glm::value_ptr(node->emissive_color)); + glUniform3fv(s->location("specular_color"), 1, glm::value_ptr(node->specular_color)); + glUniform1f( s->location("opacity"), node->opacity); glUniform1f( s->location("shininess"), node->shininess); + glUniform1f( s->location("reflexiveness"), node->reflexiveness); glUniform1f( s->location("displacementCoefficient"), node->displacementCoefficient); glUniform1ui(s->location("isTextured"), node->isTextured); - glUniform1ui(s->location("isColorMapped"), node->isColorMapped); + glUniform1ui(s->location("isVertexColored"), node->isVertexColored); glUniform1ui(s->location("isNormalMapped"), node->isNormalMapped); glUniform1ui(s->location("isDisplacementMapped"), node->isDisplacementMapped); + glUniform1ui(s->location("isReflectionMapped"), node->isReflectionMapped); 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); @@ -368,12 +368,10 @@ void renderNode(SceneNode* node, Gloom::Shader* parent_shader = default_shader) uint id = node->lightID; lights[id].position = vec3(node->MV * vec4(vec3(0.0), 1.0)); lights[id].is_spot = node->nodeType == SPOT_LIGHT; - 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].spot_direction = node->spot_direction; // MV space + lights[id].spot_cuttof_cos = node->spot_cuttof_cos; 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].color = node->light_color; lights[id].push_to_shader(s, id); break; } diff --git a/src/sceneGraph.hpp b/src/sceneGraph.hpp index cad36f0..e579955 100644 --- a/src/sceneGraph.hpp +++ b/src/sceneGraph.hpp @@ -43,14 +43,20 @@ struct SceneNode { vertexArrayObjectID = cache[mesh]; VAOIndexCount = mesh->indices.size(); - isColorMapped = ! mesh->colors.empty(); + isVertexColored = ! mesh->colors.empty(); } - void setTexture(const PNGImage* diffuse, const PNGImage* normal=nullptr, const PNGImage* displacement=nullptr) { + void setTexture( + const PNGImage* diffuse, + const PNGImage* normal=nullptr, + const PNGImage* displacement=nullptr, + const PNGImage* reflection=nullptr, + bool texture_reset=true) { static map cache; - assert(vertexArrayObjectID==-1); - isTextured = false; - isNormalMapped = false; - isDisplacementMapped = false; + if (texture_reset){ + isTextured = false; + isNormalMapped = false; + isDisplacementMapped = false; + } if (diffuse) { if (cache.find(diffuse) == cache.end()) @@ -73,18 +79,32 @@ struct SceneNode { isDisplacementMapped = true; } } + void setMaterial(const Material& mat, bool recursive=false) { + if (!mat.ignore_diffuse) diffuse_color = mat.diffuse_color; + if (!mat.ignore_emissive) emissive_color = mat.emissive_color; + if (!mat.ignore_specular) specular_color = mat.specular_color; + if (!mat.ignore_specular) shininess = mat.shininess; + setTexture( + mat.diffuse_texture, + mat.normal_texture, + mat.displacement_texture, + mat.reflection_texture, + mat.texture_reset + ); + if (recursive) for (SceneNode* child : children) + child->setMaterial(mat, true); + } // this node SceneNodeType nodeType; vector children; // light specific: - uint lightID = -1; - vec3 color_emissive = vec3(0.0); - 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 + uint lightID = -1; + vec3 light_color = vec3(1.0); + vec3 attenuation = vec3(1.0, 0.0, 0.001); // 1 / (x + y*l + z*l*l) + vec3 spot_direction = vec3(0.0); // in MV space, must be normalized + float spot_cuttof_cos = glm::cos(glm::radians(1.5)); SceneNode* targeted_by = nullptr; // spot will follow this node // The node's position and rotation relative to its parent @@ -97,9 +117,12 @@ struct SceneNode { int vertexArrayObjectID = -1; uint VAOIndexCount = 0; - // textures - float shininess = 10.0; // specular power - vec4 basecolor = vec4(1.0); + // textures and materials + float opacity = 1.0; + float shininess = 1.0; // specular power + vec3 diffuse_color = vec3(1.0); + vec3 emissive_color = vec3(0.5); + vec3 specular_color = vec3(0.2); vec2 uvOffset = vec2(0.0, 0.0); // specular power uint diffuseTextureID; uint normalTextureID; @@ -108,7 +131,7 @@ struct SceneNode { // shader flags bool isTextured = false; - bool isColorMapped = false; + bool isVertexColored = false; bool isNormalMapped = false; bool isDisplacementMapped = false; bool isIlluminated = true; diff --git a/src/utilities/glutils.cpp b/src/utilities/glutils.cpp index 97bbdda..bba761a 100644 --- a/src/utilities/glutils.cpp +++ b/src/utilities/glutils.cpp @@ -51,7 +51,7 @@ uint generateBuffer(const Mesh &mesh, bool doAddTangents) { glEnableVertexAttribArray(3); } - if (doAddTangents && !mesh.textureCoordinates.empty()) + if (doAddTangents || !mesh.textureCoordinates.empty()) addTangents(vaoID, mesh); return vaoID;