This commit is contained in:
Peder Bergebakken Sundt 2019-03-14 12:43:41 +01:00
parent 101792b011
commit 9378c685a8
12 changed files with 276 additions and 30 deletions

2
.gitignore vendored
View File

@ -32,3 +32,5 @@
*.app
build/
res/textures/*.png

View File

@ -2,6 +2,20 @@
in layout(location = 0) vec3 normal;
in layout(location = 1) vec3 vertex;
in layout(location = 2) vec2 UV;
in layout(location = 3) mat3 TBN;
layout(binding = 0) uniform sampler2D diffuseTexture;
layout(binding = 1) uniform sampler2D normalTexture;
uniform bool isIlluminated;
uniform bool isTextured;
uniform bool isNormalMapped;
uniform bool isInverted;
uniform layout(location = 6) mat4 MVP;
uniform layout(location = 7) mat4 MV;
uniform layout(location = 8) mat4 MVnormal;
// point lights
struct Light {
@ -11,6 +25,7 @@ struct Light {
vec3 spot_target; // MV space coordinates
};
//named
#define N_LIGHTS 3
uniform Light light[N_LIGHTS];
@ -23,18 +38,24 @@ 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(4 / 180.0 * 3.1415926535);
float spot_cuttof_angle = cos(1.5 / 180.0 * 3.1415926535);
void main()
{
vec3 nnormal = normalize(normal);
void main_(vec4 basecolor) {
vec3 nnormal;
if (isNormalMapped) {
vec3 tangential = texture(normalTexture, UV).rgb * 2.0 - 1.0;
nnormal = TBN * -normalize(tangential);
} else {
nnormal = normalize(normal);
}
float diffuse_intensity = 0.0;
float specular_intensity = 0.0;
for (int i = 0; i<3; i++) {
vec3 L = vec3(light[i].MV * vec4(light[i].position, 1.0f)) - vertex;
float attenuation = clamp(1000/(1 + 40*length(L) + 0.1*length(L)*length(L)), 0.0, 1.25);
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) {
@ -42,7 +63,7 @@ void main()
if (dot(L2, L) < spot_cuttof_angle) {
continue;
}
attenuation *= 70;
attenuation *= 30;
}
float diffuse_i = dot(nnormal, L);
@ -61,7 +82,30 @@ void main()
//float intensity = dot(normalize(normal), normalize(light_pos_2));
//color = vec4(0.5 * normal + 0.5, 1.0);
color = vec4(c_emissive
+ c_diffuse*diffuse_intensity
+ c_specular*specular_intensity, 1.0f);
color = basecolor * vec4(c_emissive
+ c_diffuse*diffuse_intensity, 1.0f)
+ vec4(c_specular*specular_intensity, 1.0f);
}
void main() {
if(isIlluminated) {
if (isTextured) {
c_diffuse = vec3(0.9);
c_emissive = vec3(0.2);
main_(texture(diffuseTexture, UV));
} else {
main_(vec4(1.0));
}
} else {
color = texture(diffuseTexture, UV);
}
if (isInverted) {
color.r = 1 - color.r;
color.g = 1 - color.g;
color.b = 1 - color.b;
}
}

View File

@ -2,18 +2,33 @@
in layout(location = 0) vec3 position;
in layout(location = 1) vec3 normal_in;
in layout(location = 2) vec2 UV;
in layout(location = 3) vec3 tangent;
in layout(location = 4) vec3 bitangent;
uniform layout(location = 3) mat4 MVP;
uniform layout(location = 4) mat4 MV;
uniform layout(location = 5) mat4 MVnormal;
uniform layout(location = 6) mat4 MVP;
uniform layout(location = 7) mat4 MV;
uniform layout(location = 8) mat4 MVnormal;
//named
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 = 2) vec2 uv_out;
out layout(location = 3) mat3 TBN;
void main()
{
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)))
);
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);
}

View File

@ -9,6 +9,8 @@
#include <utilities/mesh.h>
#include <utilities/shapes.h>
#include <utilities/glutils.h>
#include <utilities/glfont.h>
#include <utilities/imageLoader.hpp>
#include <SFML/Audio/Sound.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
@ -33,6 +35,8 @@ SceneNode* rootNode;
SceneNode* boxNode;
SceneNode* ballNode;
SceneNode* padNode;
SceneNode* hudNode;
SceneNode* textNode;
SceneNode* lightNode[3];
@ -61,7 +65,11 @@ bool jumpedToNextFrame = false;
const float debug_startTime = 45;
double totalElapsedTime = debug_startTime;
// textures
PNGImage t_charmap;
PNGImage t_cobble_diff;
PNGImage t_cobble_normal;
void mouseCallback(GLFWwindow* window, double x, double y) {
int windowWidth, windowHeight;
@ -107,20 +115,37 @@ void initGame(GLFWwindow* window, CommandLineOptions gameOptions) {
Mesh sphere = generateSphere(1.0, 40, 40);
unsigned int ballVAO = generateBuffer(sphere);
unsigned int boxVAO = generateBuffer(box);
unsigned int boxVAO = generateBuffer(box, true);
unsigned int padVAO = generateBuffer(pad);
// textures
t_charmap = loadPNGFile("../res/textures/charmap.png");
t_cobble_diff = loadPNGFile("../res/textures/cobble_diff.png");
t_cobble_normal = loadPNGFile("../res/textures/cobble_normal.png");
unsigned int t_charmapID = generateTexture(t_charmap);
unsigned int t_cobble_diffID = generateTexture(t_cobble_diff);
unsigned int t_cobble_normalID = generateTexture(t_cobble_normal);
rootNode = createSceneNode();
boxNode = createSceneNode() ;
boxNode = createSceneNode(NORMAL_TEXTURED_GEOMETRY);
padNode = createSceneNode();
ballNode = createSceneNode();
hudNode = createSceneNode(HUD);
textNode = createSceneNode(TEXTURED_GEOMETRY);
rootNode->children.push_back(boxNode);
rootNode->children.push_back(padNode);
rootNode->children.push_back(ballNode);
rootNode->children.push_back(hudNode);
hudNode->children.push_back(textNode);
//rootNode->children.push_back(textNode);
boxNode->vertexArrayObjectID = boxVAO;
boxNode->VAOIndexCount = box.indices.size();
boxNode->diffuseTextureID = t_cobble_diffID;
boxNode->normalTextureID = t_cobble_normalID;
padNode->vertexArrayObjectID = padVAO;
padNode->VAOIndexCount = pad.indices.size();
@ -138,12 +163,24 @@ void initGame(GLFWwindow* window, CommandLineOptions gameOptions) {
rootNode->children.push_back(lightNode[1]);
ballNode->children.push_back(lightNode[2]);
lightNode[0]->position = {boxDimensions.x/2 - 10, boxDimensions.y/2 - 10, boxDimensions.z/2 - 10};
lightNode[1]->position = {300,300,400};
lightNode[1]->position = {-300, -500, 300};
lightNode[2]->position = {0, 0, 0};
lightNode[1]->nodeType = SPOT_LIGHT;
padNode->targeted_by = lightNode[1];
// hud
Mesh hello_world = generateTextGeometryBuffer("Skjer'a bagera?", 1.3, 2);
textNode->position = glm::vec3(-1.0, 0.0, 0.0);
textNode->rotation = glm::vec3(0.0, 0.0, 0.0);
textNode->vertexArrayObjectID = generateBuffer(hello_world);
textNode->VAOIndexCount = hello_world.indices.size();
textNode->diffuseTextureID = t_charmapID;
textNode->isIlluminated = false;
textNode->isInverted = true;
getTimeDeltaSeconds();
std::cout << "Ready. Click to start!" << std::endl;
@ -154,6 +191,14 @@ void updateNodeTransformations(SceneNode* node, glm::mat4 transformationThusFar,
glm::mat4 transformationMatrix(1.0);
switch(node->nodeType) {
case HUD:
// We orthographic now, bitches!
// set orthographic VP
V = glm::mat4(1.0);
P = glm::ortho(-float(windowWidth) / float(windowHeight), float(windowWidth) / float(windowHeight), -1.0f, 1.0f);//, -10.0f, 120.0f);
break;
case NORMAL_TEXTURED_GEOMETRY:
case TEXTURED_GEOMETRY:
case GEOMETRY:
transformationMatrix =
glm::translate(glm::mat4(1.0), node->position)
@ -342,13 +387,25 @@ void updateFrame(GLFWwindow* window) {
void renderNode(SceneNode* node) {
glUniformMatrix4fv(3, 1, GL_FALSE, glm::value_ptr(node->currentTransformationMatrix));
glUniformMatrix4fv(4, 1, GL_FALSE, glm::value_ptr(node->currentTransformationMatrixMV));
glUniformMatrix4fv(5, 1, GL_FALSE, glm::value_ptr(node->currentTransformationMatrixMVnormal));
glUniformMatrix4fv(6, 1, GL_FALSE, glm::value_ptr(node->currentTransformationMatrix));
glUniformMatrix4fv(7, 1, GL_FALSE, glm::value_ptr(node->currentTransformationMatrixMV));
glUniformMatrix4fv(8, 1, GL_FALSE, glm::value_ptr(node->currentTransformationMatrixMVnormal));
glUniform1ui(shader->location("isNormalMapped"), false);
glUniform1ui(shader->location("isTextured"), false);
switch(node->nodeType) {
case NORMAL_TEXTURED_GEOMETRY:
glUniform1ui(shader->location("isNormalMapped"), true);
glBindTextureUnit(1, node->normalTextureID);
[[fallthrough]];
case TEXTURED_GEOMETRY:
glUniform1ui(shader->location("isTextured"), true);
glBindTextureUnit(0, node->diffuseTextureID);
[[fallthrough]];
case GEOMETRY:
if(node->vertexArrayObjectID != -1) {
glUniform1ui(shader->location("isIlluminated"), node->isIlluminated);
glUniform1ui(shader->location("isInverted"), node->isInverted);
glBindVertexArray(node->vertexArrayObjectID);
glDrawElements(GL_TRIANGLES, node->VAOIndexCount, GL_UNSIGNED_INT, nullptr);
}
@ -365,6 +422,8 @@ void renderNode(SceneNode* node) {
break;
}
case HUD:
break;
}
for(SceneNode* child : node->children) {

View File

@ -24,6 +24,10 @@ void runProgram(GLFWwindow* window, CommandLineOptions options)
// Configure miscellaneous OpenGL settings
glEnable(GL_CULL_FACE);
//enable alpha
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Set default colour after clearing the colour buffer
glClearColor(0.3f, 0.5f, 0.8f, 1.0f);

View File

@ -4,6 +4,9 @@
SceneNode* createSceneNode() {
return new SceneNode();
}
SceneNode* createSceneNode(SceneNodeType type) {
return new SceneNode(type);
}
// Add a child node to its parent's list of children
void addChild(SceneNode* parent, SceneNode* child) {
@ -26,4 +29,3 @@ void printNode(SceneNode* node) {
node->referencePoint.x, node->referencePoint.y, node->referencePoint.z,
node->vertexArrayObjectID);
}

View File

@ -14,7 +14,7 @@
#include <fstream>
enum SceneNodeType {
GEOMETRY, POINT_LIGHT, SPOT_LIGHT
GEOMETRY, POINT_LIGHT, SPOT_LIGHT, HUD, TEXTURED_GEOMETRY, NORMAL_TEXTURED_GEOMETRY
};
// In case you haven't got much experience with C or C++, let me explain this "typedef" you see below.
@ -33,6 +33,12 @@ struct SceneNode {
nodeType = GEOMETRY;
targeted_by = nullptr;
isIlluminated = true;
isInverted = false;
}
SceneNode(SceneNodeType type) : SceneNode() {
nodeType = type;
}
// A list of all children that belong to this node.
@ -55,6 +61,12 @@ struct SceneNode {
// The ID of the VAO containing the "appearance" of this SceneNode.
int vertexArrayObjectID;
unsigned int VAOIndexCount;
unsigned int diffuseTextureID;
unsigned int normalTextureID;
bool isIlluminated;
bool isInverted;
// Node type is used to determine how to handle the contents of a node
SceneNodeType nodeType;
@ -67,6 +79,7 @@ struct SceneNode {
// Struct for keeping track of 2D coordinates
SceneNode* createSceneNode();
SceneNode* createSceneNode(SceneNodeType type);
void addChild(SceneNode* parent, SceneNode* child);
void printNode(SceneNode* node);

View File

@ -4,7 +4,8 @@
Mesh generateTextGeometryBuffer(std::string text, float characterHeightOverWidth, float totalTextWidth) {
float characterWidth = totalTextWidth / float(text.length());
float characterHeight = characterHeightOverWidth * characterWidth;
float textureWidth = 1.0 / 128.0;
unsigned int vertexCount = 4 * text.length();
unsigned int indexCount = 6 * text.length();
@ -12,11 +13,14 @@ Mesh generateTextGeometryBuffer(std::string text, float characterHeightOverWidth
mesh.vertices.resize(vertexCount);
mesh.indices.resize(indexCount);
mesh.textureCoordinates.resize(vertexCount);
for(unsigned int i = 0; i < text.length(); i++)
{
float baseXCoordinate = float(i) * characterWidth;
float baseXTexture = float(text[i]) * textureWidth;
mesh.vertices.at(4 * i + 0) = {baseXCoordinate, 0, 0};
mesh.vertices.at(4 * i + 1) = {baseXCoordinate + characterWidth, 0, 0};
mesh.vertices.at(4 * i + 2) = {baseXCoordinate + characterWidth, characterHeight, 0};
@ -32,7 +36,17 @@ Mesh generateTextGeometryBuffer(std::string text, float characterHeightOverWidth
mesh.indices.at(6 * i + 3) = 4 * i + 0;
mesh.indices.at(6 * i + 4) = 4 * i + 2;
mesh.indices.at(6 * i + 5) = 4 * i + 3;
mesh.textureCoordinates.at(4 * i + 0) = {baseXTexture, 0};
mesh.textureCoordinates.at(4 * i + 1) = {baseXTexture + textureWidth, 0};
mesh.textureCoordinates.at(4 * i + 2) = {baseXTexture + textureWidth, 1};
mesh.textureCoordinates.at(4 * i + 0) = {baseXTexture, 0};
mesh.textureCoordinates.at(4 * i + 2) = {baseXTexture + textureWidth, 1};
mesh.textureCoordinates.at(4 * i + 3) = {baseXTexture, 1};
}
return mesh;
}
}

View File

@ -2,7 +2,7 @@
#include <program.hpp>
#include "glutils.h"
unsigned int generateBuffer(Mesh &mesh) {
unsigned int generateBuffer(Mesh &mesh, bool isNormalMapped) {
unsigned int vaoID;
glGenVertexArrays(1, &vaoID);
glBindVertexArray(vaoID);
@ -26,6 +26,93 @@ unsigned int generateBuffer(Mesh &mesh) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh.indices.size() * sizeof(unsigned int), mesh.indices.data(), GL_STATIC_DRAW);
if (mesh.textureCoordinates.empty()) return vaoID;
unsigned int textureBufferID;
glGenBuffers(1, &textureBufferID);
glBindBuffer(GL_ARRAY_BUFFER, textureBufferID);
glBufferData(GL_ARRAY_BUFFER, mesh.textureCoordinates.size() * sizeof(glm::vec2), mesh.textureCoordinates.data(), GL_STATIC_DRAW);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), 0);
glEnableVertexAttribArray(2);
if (isNormalMapped) addTangents(vaoID, mesh);
return vaoID;
}
void addTangents(unsigned int vaoID, Mesh& mesh) {
glm::vec3 tangents[mesh.vertices.size()];
glm::vec3 bitangents[mesh.vertices.size()];
for (unsigned int i = 0; i < mesh.indices.size(); i+=3) {
const glm::vec3& pos1 = mesh.vertices[mesh.indices[i+0]];
const glm::vec3& pos2 = mesh.vertices[mesh.indices[i+1]];
const glm::vec3& pos3 = mesh.vertices[mesh.indices[i+2]];
const glm::vec2& uv1 = mesh.textureCoordinates[mesh.indices[i+0]];
const glm::vec2& uv2 = mesh.textureCoordinates[mesh.indices[i+1]];
const glm::vec2& uv3 = mesh.textureCoordinates[mesh.indices[i+2]];
glm::vec3 edge1 = pos2 - pos1;
glm::vec3 edge2 = pos3 - pos1;
glm::vec2 deltaUV1 = uv2 - uv1;
glm::vec2 deltaUV2 = uv3 - uv1;
float f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);
glm::vec3 tangent, bitangent;
tangent.x = f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x);
tangent.y = f * (deltaUV2.y * edge1.y - deltaUV1.y * edge2.y);
tangent.z = f * (deltaUV2.y * edge1.z - deltaUV1.y * edge2.z);
bitangent.x = f * (-deltaUV2.x * edge1.x + deltaUV1.x * edge2.x);
bitangent.y = f * (-deltaUV2.x * edge1.y + deltaUV1.x * edge2.y);
bitangent.z = f * (-deltaUV2.x * edge1.z + deltaUV1.x * edge2.z);
tangent = glm::normalize(tangent);
bitangent = glm::normalize(bitangent);
// handedness
tangents[i+0] = -tangent;
tangents[i+1] = -tangent;
tangents[i+2] = -tangent;
bitangents[i+0] = -bitangent;
bitangents[i+1] = -bitangent;
bitangents[i+2] = -bitangent;
}
glBindVertexArray(vaoID);
unsigned int tangentBufferID;
glGenBuffers(1, &tangentBufferID);
glBindBuffer(GL_ARRAY_BUFFER, tangentBufferID);
glBufferData(GL_ARRAY_BUFFER, mesh.vertices.size() * sizeof(glm::vec3), tangents, GL_STATIC_DRAW);
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
glEnableVertexAttribArray(3);
unsigned int bitangentBufferID;
glGenBuffers(1, &bitangentBufferID);
glBindBuffer(GL_ARRAY_BUFFER, bitangentBufferID);
glBufferData(GL_ARRAY_BUFFER, mesh.vertices.size() * sizeof(glm::vec3), bitangents, GL_STATIC_DRAW);
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
glEnableVertexAttribArray(4);
}
unsigned int generateTexture(PNGImage& texture) {
unsigned int id;
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture.width, texture.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture.pixels.data());
//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texture.width, texture.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture.pixels.data());
glGenerateMipmap(GL_TEXTURE_2D);
return id;
}

View File

@ -1,5 +1,11 @@
#pragma once
#include "mesh.h"
#include "imageLoader.hpp"
unsigned int generateBuffer(Mesh &mesh);
unsigned int generateBuffer(Mesh &mesh, bool isNormalMapped = false);
void addTangents(unsigned int vaoID, Mesh& mesh);
unsigned int generateTexture(PNGImage& texture);

View File

@ -38,4 +38,4 @@ PNGImage loadPNGFile(std::string fileName)
return image;
}
}

View File

@ -9,4 +9,4 @@ struct Mesh {
std::vector<glm::vec2> textureCoordinates;
std::vector<unsigned int> indices;
};
};