GLuint pyramidVao, lightVao, teapotVao;
GLuint gradientProgId, plainProgId, normalProgId, solidProgId, textureProgId;
-glm::vec3 camPos = glm::vec3(0.0f, 0.0f, -10.0f);
+glm::vec3 camPos = glm::vec3(0.0f, 0.0f, 0.0f);
glm::vec3 camFront = glm::vec3(0.0f, 0.0f, 1.0f);
glm::vec3 camUp = glm::vec3(0.0f, 1.0f, 0.0f);
float yaw = 1.57, pitch = 0;
GLuint lightColorLoc = glGetUniformLocation(progId, "lightColor");
glUniform4fv(lightColorLoc, 1, glm::value_ptr(lightColor));
- GLuint lightPosLoc = glGetUniformLocation(progId, "lightPos");
+ GLuint lightPosLoc = glGetUniformLocation(progId, "vLightPos");
glUniform3fv(lightPosLoc, 1, glm::value_ptr(lightPos));
- GLuint viewPosLoc = glGetUniformLocation(progId, "viewPos");
+ GLuint viewPosLoc = glGetUniformLocation(progId, "vViewPos");
glUniform3fv(viewPosLoc, 1, glm::value_ptr(camPos));
}
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
float d = (float)glutGet(GLUT_ELAPSED_TIME) * 0.001f;
- /* glm::vec3 lightPos = glm::vec3(sin(d) * 10, 0, cos(d) * 10); */
- glm::vec3 lightPos = glm::vec3(0, 10, 10);
+ /* glm::vec3 lightPos = glm::vec3(sin(d / 10.f) * 10, 0, cos(d / 10.f) * 10); */
+ glm::vec3 lightPos = chestPos;
glm::vec4 lightColor(1, 1, 1, 1);
- glViewport(0, 0, WIDTH, HEIGHT);
- /* drawPyramids(d, lightPos, lightColor); */
drawLight(d, lightPos, lightColor);
- glUseProgram(solidProgId);
- setProjectionAndViewUniforms(solidProgId);
- setLightColorAndPos(solidProgId, lightPos, lightColor);
-
- GLuint colorLoc = glGetUniformLocation(solidProgId, "color");
- glm::vec4 c(1);
- glUniform4fv(colorLoc, 1, glm::value_ptr(c));
-
- monkeyHead->getRoot()->model = glm::translate(glm::mat4(1), glm::vec3(2, 0, 0));
- monkeyHead->draw();
-
glUseProgram(textureProgId);
setProjectionAndViewUniforms(textureProgId);
setLightColorAndPos(textureProgId, lightPos, lightColor);
/* Model::Node *jewels = chest->find("jewels"); */
/* jewels->model = glm::scale(glm::mat4(1), glm::vec3((sin(d) + 1.2f) / 2.f)); */
- Model::Node *lock = chest->find("lock");
- lock->model = glm::translate(glm::mat4(1), glm::vec3(0.22610, 3.36478, -0.75649));
- lock->model = glm::rotate(lock->model, (d / 2.5f), glm::vec3(0, 1, 0.4));
- lock->model = glm::translate(lock->model, -glm::vec3(0.22610, 3.36478, -0.75649));
+ /* Model::Node *lock = chest->find("lock"); */
+ /* lock->model = glm::translate(glm::mat4(1), glm::vec3(0.22610, 3.36478, -0.75649)); */
+ /* lock->model = glm::rotate(lock->model, (d / 2.5f), glm::vec3(0, 1, 0.4)); */
+ /* lock->model = glm::translate(lock->model, -glm::vec3(0.22610, 3.36478, -0.75649)); */
- Model::Node *key = chest->find("key");
- key->model = glm::translate(glm::mat4(1), glm::vec3(0, 0, sin(d)));
+ /* Model::Node *key = chest->find("key"); */
+ /* key->model = glm::translate(glm::mat4(1), glm::vec3(0, 0, sin(d))); */
- chest->getRoot()->model = glm::translate(glm::mat4(1), chestPos);
+ /* chest->getRoot()->model = glm::translate(glm::mat4(1), chestPos); */
chest->draw();
- /* drawTeapot(teapotCamera, false, d, lightPos, lightColor); */
-
- /* glClear(GL_DEPTH_BUFFER_BIT); */
-
- /* glViewport(0, 0, WIDTH / 4, HEIGHT / 4); */
- /* drawTeapot(teapotOrtho, false, d, lightPos, lightColor); */
-
- /* glViewport(WIDTH / 4, 0, WIDTH / 4, HEIGHT / 4); */
- /* drawTeapot(teapotOrtho, true, d, lightPos, lightColor); */
-
- /* glViewport(WIDTH / 4 * 2, 0, WIDTH / 4, HEIGHT / 4); */
- /* drawTeapot(teapotPerspStatic, false, d, lightPos, lightColor); */
-
- /* glViewport(WIDTH / 4 * 3, 0, WIDTH / 4, HEIGHT / 4); */
- /* drawTeapot(teapotPerspAnimated, false, d, lightPos, lightColor); */
-
-
glutSwapBuffers();
}
glUseProgram(solidProgId);
validateProgram(solidProgId);
- textureProgId = compileShaders((char*)"vertex.glsl", (char*)"texturefrag.glsl");
+ textureProgId = compileShaders((char*)"texturevertex.glsl", (char*)"texturefrag.glsl");
glUseProgram(textureProgId);
validateProgram(textureProgId);
if (keyStates['k']) chestPos.z -= 0.1f;
if (keyStates['h']) chestPos.x -= 0.1f;
if (keyStates['l']) chestPos.x += 0.1f;
+ if (keyStates['m']) chestPos.y -= 0.1f;
+ if (keyStates['n']) chestPos.y += 0.1f;
camPos.x += xSpeed * sin(yaw) + zSpeed * cos(yaw);
camPos.y += ySpeed;
#include "material.hpp"
#include <iostream>
+#include <fstream>
#include <CoreGraphics/CoreGraphics.h>
Material::Material(const aiMaterial &ai, GLuint progId): progId(progId) {
if (ai.GetTextureCount(aiTextureType_DIFFUSE) > 0) {
aiString path;
ai.GetTexture(aiTextureType_DIFFUSE, 0, &path);
- texture = new Texture(std::string(path.C_Str()));
+ diffuseMap = new Texture(std::string(path.C_Str()));
+ }
+ if (ai.GetTextureCount(aiTextureType_SPECULAR) > 0) {
+ aiString path;
+ ai.GetTexture(aiTextureType_SPECULAR, 0, &path);
+ specularMap = new Texture(std::string(path.C_Str()));
+ }
+ if (ai.GetTextureCount(aiTextureType_NORMALS) > 0) {
+ aiString path;
+ ai.GetTexture(aiTextureType_NORMALS, 0, &path);
+ normalMap = new Texture(std::string(path.C_Str()));
}
ai.Get(AI_MATKEY_SHININESS, shininess);
ai.Get(AI_MATKEY_COLOR_AMBIENT, ambient);
}
Material::Texture::Texture(const std::string &path) {
+
auto provider = CGDataProviderCreateWithFilename(path.c_str());
- auto ref = CGImageCreateWithJPEGDataProvider(provider, nullptr, false, kCGRenderingIntentDefault);
+ std::ifstream file(path);
+ long magic;
+ file.read((char*)&magic, 8);
+ file.close();
+
+ CGImageRef ref;
+
+ if (magic == 0x0a1a0a0d474e5089) // png magic number
+ ref = CGImageCreateWithPNGDataProvider(provider, nullptr, false, kCGRenderingIntentDefault);
+ else
+ ref = CGImageCreateWithJPEGDataProvider(provider, nullptr, false, kCGRenderingIntentDefault);
+
auto dataRef = CGDataProviderCopyData(CGImageGetDataProvider(ref));
auto img = (unsigned char*) CFDataGetBytePtr(dataRef);
glUniform3f(glGetUniformLocation(progId, "material.diffuse"), diffuse.r, diffuse.g, diffuse.b);
glUniform3f(glGetUniformLocation(progId, "material.specular"), specular.r, specular.g, specular.b);
glUniform1f(glGetUniformLocation(progId, "material.shininess"), shininess);
- glUniform1i(glGetUniformLocation(progId, "material.hasTexture"), texture != nullptr);
+ glUniform1i(glGetUniformLocation(progId, "material.hasTexture"), diffuseMap != nullptr);
+ glUniform1i(glGetUniformLocation(progId, "material.hasSpecularMap"), specularMap != nullptr);
+ glUniform1i(glGetUniformLocation(progId, "material.hasNormalMap"), normalMap != nullptr);
- if (texture)
- glBindTexture(GL_TEXTURE_2D, texture->texId);
+ if (diffuseMap) {
+ glUniform1i(glGetUniformLocation(progId, "material.diffuseMap"), 0);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, diffuseMap->texId);
+ }
+ if (specularMap) {
+ glUniform1i(glGetUniformLocation(progId, "material.specularMap"), 1);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, specularMap->texId);
+ }
+ if (normalMap) {
+ glUniform1i(glGetUniformLocation(progId, "material.normalMap"), 2);
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_2D, normalMap->texId);
+ }
}
Texture(const std::string &path);
GLuint texId;
};
- Texture *texture = nullptr;
+ Texture *diffuseMap = nullptr;
+ Texture *specularMap = nullptr;
+ Texture *normalMap = nullptr;
};
Model::Mesh::Mesh(const aiMesh *aiMesh, GLuint progId) {
- std::vector<glm::vec3> vertices, normals;
+ std::vector<glm::vec3> vertices, normals, tangents, bitangents;
std::vector<glm::vec2> texCoords;
for (int i = 0; i < aiMesh->mNumVertices; i++) {
vertices.push_back(glm::vec3(v.x, v.y, v.z));
}
if (aiMesh->HasNormals()) {
- const aiVector3D v = aiMesh->mNormals[i];
+ aiVector3D v = aiMesh->mNormals[i];
normals.push_back(glm::vec3(v.x, v.y, v.z));
} else {
normals.push_back(glm::vec3(0));
}
+ if (aiMesh->HasTangentsAndBitangents()) {
+ aiVector3D t = aiMesh->mTangents[i];
+ tangents.push_back(glm::vec3(t.x, t.y, t.z));
+ aiVector3D b = aiMesh->mBitangents[i];
+ bitangents.push_back(glm::vec3(b.x, b.y, b.z));
+ } else {
+ tangents.push_back(glm::vec3(0));
+ bitangents.push_back(glm::vec3(0));
+ }
// check for texture coord set 0
if (aiMesh->HasTextureCoords(0)) {
const aiVector3D v = aiMesh->mTextureCoords[0][i];
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
- GLuint vbos[4];
- glGenBuffers(4, vbos);
+ GLuint vbos[6];
+ glGenBuffers(6, vbos);
GLuint vertexVbo = vbos[0], normalVbo = vbos[1], texCoordVbo = vbos[2], indicesVbo = vbos[3];
+ GLuint tangentVbo = vbos[4], bitangentVbo = vbos[5];
GLuint posLoc = glGetAttribLocation(progId, "vPosition");
- GLuint normalLoc = glGetAttribLocation(progId, "vNormal");
- GLuint texCoordLoc = glGetAttribLocation(progId, "vTexCoord");
-
glBindBuffer(GL_ARRAY_BUFFER, vertexVbo);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(posLoc);
glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
+ GLuint normalLoc = glGetAttribLocation(progId, "vNormal");
glBindBuffer(GL_ARRAY_BUFFER, normalVbo);
glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), &normals[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(normalLoc);
glVertexAttribPointer(normalLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
+ GLuint texCoordLoc = glGetAttribLocation(progId, "vTexCoord");
glBindBuffer(GL_ARRAY_BUFFER, texCoordVbo);
glBufferData(GL_ARRAY_BUFFER, texCoords.size() * sizeof(glm::vec2), &texCoords[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(texCoordLoc);
glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
+ GLuint tangentLoc = glGetAttribLocation(progId, "tangent");
+ glBindBuffer(GL_ARRAY_BUFFER, tangentVbo);
+ glBufferData(GL_ARRAY_BUFFER, tangents.size() * sizeof(glm::vec3), &tangents[0], GL_STATIC_DRAW);
+ glEnableVertexAttribArray(tangentLoc);
+ glVertexAttribPointer(tangentLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
+
+ GLuint bitangentLoc = glGetAttribLocation(progId, "bitangent");
+ glBindBuffer(GL_ARRAY_BUFFER, bitangentVbo);
+ glBufferData(GL_ARRAY_BUFFER, bitangents.size() * sizeof(glm::vec3), &bitangents[0], GL_STATIC_DRAW);
+ glEnableVertexAttribArray(bitangentLoc);
+ glVertexAttribPointer(bitangentLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
+
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicesVbo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), &indices[0], GL_STATIC_DRAW);
};
Model::Model(const std::string &path, GLuint progId): progId(progId) {
const aiScene *scene = importer.ReadFile(path,
- aiProcess_Triangulate |
- aiProcess_GenNormals);
+ aiProcess_Triangulate | aiProcess_CalcTangentSpace | aiProcess_GenNormals);
if (!scene) {
std::cerr << importer.GetErrorString() << std::endl;
exit(1);
vec4 lighting = (ambient + diffuse + specular) * lightColor;
- FragColor = lighting * vec4(normalEye, 1);
+ FragColor = lighting * vec4((normal + 1) / 2, 1);
}
struct Material {
vec3 ambient;
vec3 diffuse;
+ sampler2D diffuseMap;
vec3 specular;
+ sampler2D specularMap;
float shininess;
+
bool hasTexture;
+ bool hasSpecularMap;
+
+ sampler2D normalMap;
+ bool hasNormalMap;
};
-in vec3 normal;
-in vec3 fragPos;
+in vec3 defNormal;
in vec2 texCoord;
-uniform vec3 lightPos;
-uniform vec3 viewPos;
+// These are all in tangent space
+in vec3 lightPos;
+in vec3 viewPos;
+in vec3 fragPos;
+
uniform vec4 lightColor;
uniform Material material;
-uniform sampler2D tex;
out vec4 FragColor;
void main() {
- vec3 lightDir = normalize(fragPos - lightPos);
- vec3 diffuse = max(0, dot(-normal, lightDir)) * material.diffuse;
- vec3 viewDir = normalize(fragPos - viewPos);
- vec3 reflectDir = reflect(-lightDir, normal);
- vec3 specular = pow(max(0, dot(viewDir, reflectDir)), material.shininess) * material.specular;
+ vec3 normal;
+ if (material.hasNormalMap) {
+ normal = texture(material.normalMap, texCoord).rgb;
+ normal = normalize(normal * 2 - 1);
+ } else {
+ normal = defNormal;
+ }
- vec4 lighting = vec4(material.ambient + diffuse + specular, 1) * lightColor;
+ vec3 lightDir = normalize(lightPos - fragPos);
+ vec4 diffTex;
if (material.hasTexture)
- FragColor = lighting * texture(tex, texCoord);
+ diffTex = texture(material.diffuseMap, texCoord);
else
+ diffTex = vec4(1);
+ vec4 diffuse = vec4(max(0, dot(lightDir, normal)) * material.diffuse, 1) * diffTex;
+
+ vec3 viewDir = normalize(viewPos - fragPos);
+ vec3 reflectDir = reflect(-lightDir, normal);
+
+
+ vec4 specTex;
+ if (material.hasSpecularMap)
+ specTex = texture(material.specularMap, texCoord);
+ else
+ specTex = vec4(1);
+
+ vec4 specular = vec4(pow(max(0, dot(viewDir, reflectDir)), material.shininess) * material.specular, 1) * specTex;
+
+ vec4 lighting = (vec4(material.ambient, 1) + diffuse + specular) * lightColor;
+
FragColor = lighting;
}
--- /dev/null
+#version 330
+in vec3 vPosition;
+in vec4 vColor;
+in vec3 vNormal;
+in vec3 tangent;
+in vec3 bitangent;
+in vec2 vTexCoord;
+uniform mat4 model;
+uniform mat4 view;
+uniform mat4 projection;
+out vec3 defNormal;
+out vec2 texCoord;
+
+uniform vec3 vLightPos;
+uniform vec3 vViewPos;
+
+out vec3 lightPos;
+out vec3 viewPos;
+out vec3 fragPos;
+
+struct Material {
+ vec3 ambient;
+ vec3 diffuse;
+ sampler2D diffuseMap;
+ vec3 specular;
+ sampler2D specularMap;
+ float shininess;
+
+ bool hasTexture;
+ bool hasSpecularMap;
+
+ sampler2D normalMap;
+ bool hasNormalMap;
+};
+
+uniform Material material;
+
+
+void main() {
+ vec4 pos = model * vec4(vPosition, 1.f);
+ defNormal = mat3(transpose(inverse(model))) * vNormal;
+ texCoord = vTexCoord;
+
+ //tangent space stuff
+ if (material.hasNormalMap) {
+ vec3 T = normalize(vec3(model * vec4(tangent, 0.0)));
+ vec3 B = normalize(vec3(model * vec4(bitangent, 0.0)));
+ vec3 N = normalize(vec3(model * vec4(vNormal, 0.0)));
+ // convert TBN to world->tangent space
+ mat3 TBN = transpose(mat3(T, B, N));
+ lightPos = TBN * vLightPos;
+ viewPos = TBN * vViewPos;
+ fragPos = TBN * vec3(pos);
+ } else {
+ lightPos = vLightPos;
+ viewPos = vViewPos;
+ fragPos = vec3(pos);
+ }
+
+ gl_Position = projection * view * pos;
+}
gl_Position = projection * view * pos;
fragPos = vec3(pos);
color = vColor;
- normal = vNormal;
+ normal = mat3(transpose(inverse(model))) * vNormal;
normalEye = vec3(view * vec4(normal, 0.0));
texCoord = vTexCoord;
}