all: main
main:
- clang++ -g --std=c++11 *.cpp -L/usr/local/lib -lassimp -framework OpenGL -framework glut -lglew -o bin/main
+ clang++ -g --std=c++11 *.cpp -L/usr/local/lib -lassimp -framework OpenGL -framework glut -framework CoreGraphics -framework CoreFoundation -lglew -o bin/main
ctags *.cpp
using namespace std;
GLuint pyramidVao, lightVao, teapotVao;
-GLuint gradientProgId, plainProgId, normalProgId, solidProgId;
+GLuint gradientProgId, plainProgId, normalProgId, solidProgId, textureProgId;
glm::vec3 camPos = glm::vec3(0.0f, 0.0f, -10.0f);
glm::vec3 camFront = glm::vec3(0.0f, 0.0f, 1.0f);
glm::vec3 camUp = glm::vec3(0.0f, 1.0f, 0.0f);
GLuint lightPosLoc = glGetUniformLocation(progId, "lightPos");
glUniform3fv(lightPosLoc, 1, glm::value_ptr(lightPos));
+
+ GLuint viewPosLoc = glGetUniformLocation(progId, "viewPos");
+ glUniform3fv(viewPosLoc, 1, glm::value_ptr(camPos));
}
void drawLight(float d, glm::vec3 lightPos, glm::vec4 lightColor) {
setLightColorAndPos(gradientProgId, lightPos, lightColor);
- GLuint viewPosLoc = glGetUniformLocation(gradientProgId, "viewPos");
- glUniform3fv(viewPosLoc, 1, glm::value_ptr(camPos));
-
GLuint modelId = glGetUniformLocation(gradientProgId, "model");
for (int i = 0; i < 10; i++) {
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(sin(d) * 10, 0, cos(d) * 10); */
+ glm::vec3 lightPos = glm::vec3(0, 10, 10);
glm::vec4 lightColor(1, 1, 1, 1);
glViewport(0, 0, WIDTH, HEIGHT);
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 *top = chest->find("top");
top->model = glm::translate(glm::mat4(1), glm::vec3(0, 1, -1));
top->model = glm::rotate(top->model, sin(d / 2.5f) * 0.5f, glm::vec3(1, 0, 0));
top->model = glm::translate(top->model, glm::vec3(0, -1, 1));
- Model::Node *jewels = chest->find("jewels");
- jewels->model = glm::scale(glm::mat4(1), glm::vec3((sin(d) + 1.2f) / 2.f));
+ /* 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));
glUseProgram(solidProgId);
validateProgram(solidProgId);
+ textureProgId = compileShaders((char*)"vertex.glsl", (char*)"texturefrag.glsl");
+ glUseProgram(textureProgId);
+ validateProgram(textureProgId);
+
monkeyHead = new Model("monkeyhead_smooth.dae", solidProgId);
- chest = new Model("chest.dae", solidProgId);
+ chest = new Model("chest.dae", textureProgId);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
--- /dev/null
+#include "material.hpp"
+#include <iostream>
+#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()));
+ }
+ ai.Get(AI_MATKEY_SHININESS, shininess);
+ ai.Get(AI_MATKEY_COLOR_AMBIENT, ambient);
+ ai.Get(AI_MATKEY_COLOR_DIFFUSE, diffuse);
+ ai.Get(AI_MATKEY_COLOR_SPECULAR, specular);
+}
+
+Material::Texture::Texture(const std::string &path) {
+ auto provider = CGDataProviderCreateWithFilename(path.c_str());
+ auto ref = CGImageCreateWithJPEGDataProvider(provider, nullptr, false, kCGRenderingIntentDefault);
+ auto dataRef = CGDataProviderCopyData(CGImageGetDataProvider(ref));
+ auto img = (unsigned char*) CFDataGetBytePtr(dataRef);
+
+ glGenTextures(1, &texId);
+ glBindTexture(GL_TEXTURE_2D, texId);
+ auto width = CGImageGetWidth(ref), height = CGImageGetHeight(ref);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img);
+ glGenerateMipmap(GL_TEXTURE_2D);
+
+ CGImageRelease(ref);
+ CFRelease(dataRef);
+}
+
+void Material::bind() const {
+ glUniform3f(glGetUniformLocation(progId, "material.ambient"), ambient.r, ambient.g, ambient.b);
+ 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);
+
+ if (texture)
+ glBindTexture(GL_TEXTURE_2D, texture->texId);
+}
--- /dev/null
+#include <string>
+#ifdef __APPLE__
+#include <GL/glew.h>
+#else
+#include <OpenGL/glew.h>
+#endif
+#include <assimp/scene.h>
+
+class Material {
+ public:
+ Material(const aiMaterial &aiMaterial, GLuint progId);
+ void bind() const;
+ private:
+ GLuint progId;
+ aiColor3D ambient, diffuse, specular;
+ ai_real shininess;
+
+ struct Texture {
+ Texture(const std::string &path);
+ GLuint texId;
+ };
+ Texture *texture = nullptr;
+};
+
if (aiMesh->HasTextureCoords(0)) {
const aiVector3D v = aiMesh->mTextureCoords[0][i];
texCoords.push_back(glm::vec2(v.x, v.y));
+ } else {
+ texCoords.push_back(glm::vec2(0));
}
+ materialIndex = aiMesh->mMaterialIndex;
}
std::vector<GLuint> indices;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
- GLuint vbos[3];
- glGenBuffers(3, vbos);
- GLuint vertexVbo = vbos[0], normalVbo = vbos[1], indicesVbo = vbos[2];
+ GLuint vbos[4];
+ glGenBuffers(4, vbos);
+ GLuint vertexVbo = vbos[0], normalVbo = vbos[1], texCoordVbo = vbos[2], indicesVbo = vbos[3];
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(normalLoc);
glVertexAttribPointer(normalLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
+ 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);
+
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicesVbo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), &indices[0], GL_STATIC_DRAW);
};
return to;
}
-void Model::Node::draw(const std::vector<Mesh> &meshes, glm::mat4 parentTrans = glm::mat4(1)) const {
+void Model::Node::draw( const std::vector<Mesh> &meshes,
+ const std::vector<Material> &materials,
+ glm::mat4 parentTrans = glm::mat4(1)) const {
+
GLuint modelLoc = glGetUniformLocation(progId, "model");
glm::mat4 m = parentTrans * aiMatrixToMat4(ai.mTransformation) * model;
for (unsigned int i: meshIndices) {
const Mesh &mesh = meshes[i];
-
glBindVertexArray(mesh.vao);
+ Material material = materials[mesh.materialIndex];
+ material.bind();
+
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(m));
glDrawElements(GL_TRIANGLES, mesh.numIndices, GL_UNSIGNED_INT, 0);
}
- for (Node *child: children) child->draw(meshes, m);
+ for (Node *child: children) child->draw(meshes, materials, m);
}
Model::Model(const std::string &path, GLuint progId): progId(progId) {
meshes.push_back(Mesh(mesh, progId));
}
- for (int i = 0; i < scene->mNumMaterials; i++) {
+ for (unsigned int i = 0; i < scene->mNumMaterials; i++) {
const aiMaterial &material = *scene->mMaterials[i];
-
- for (int j = 0; j < material.GetTextureCount(aiTextureType_DIFFUSE); j++) {
- aiString path;
- material.GetTexture(aiTextureType_DIFFUSE, j, &path);
- }
- std::cout << material.GetTextureCount(aiTextureType_DIFFUSE) << std::endl;
- std::cout << path.C_Str() << std::endl;
+ materials.push_back(Material(material, progId));
}
root = new Node(*(scene->mRootNode), progId);
}
void Model::draw() const {
- root->draw(meshes);
+ root->draw(meshes, materials);
}
Model::Node* Model::find(const std::string &name) {
#include <glm/glm.hpp>
#include <assimp/scene.h>
#include <assimp/Importer.hpp>
+#include "material.hpp"
class Model {
struct Mesh {
Mesh(const aiMesh *aiMesh, GLuint progId);
- GLuint vao;
- GLuint numIndices;
+ GLuint progId, vao, numIndices;
+ unsigned int materialIndex;
};
public:
class Node {
public:
Node(const aiNode &aiNode, GLuint progId);
- void draw(const std::vector<Mesh> &meshes, glm::mat4 parentModel) const;
+ void draw(const std::vector<Mesh> &meshes, const std::vector<Material> &materials, glm::mat4 parentModel) const;
const std::vector<Node*> &getChildren() const { return children; }
Node* findNode(const aiNode &aiNode);
glm::mat4 model = glm::mat4(1);
std::vector<Mesh> meshes;
Node *root;
+
+ std::vector<Material> materials;
+
void loadModel(const std::string &path);
Assimp::Importer importer;
--- /dev/null
+#version 330
+
+struct Material {
+ vec3 ambient;
+ vec3 diffuse;
+ vec3 specular;
+ float shininess;
+ bool hasTexture;
+};
+
+in vec3 normal;
+in vec3 fragPos;
+in vec2 texCoord;
+
+uniform vec3 lightPos;
+uniform vec3 viewPos;
+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;
+
+ vec4 lighting = vec4(material.ambient + diffuse + specular, 1) * lightColor;
+
+ if (material.hasTexture)
+ FragColor = lighting * texture(tex, texCoord);
+ else
+ FragColor = lighting;
+}
+
in vec3 vPosition;
in vec4 vColor;
in vec3 vNormal;
+in vec2 vTexCoord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
out vec3 normal;
out vec3 fragPos;
out vec3 normalEye;
+out vec2 texCoord;
void main() {
vec4 pos = model * vec4(vPosition, 1.f);
color = vColor;
normal = vNormal;
normalEye = vec3(view * vec4(normal, 0.0));
+ texCoord = vTexCoord;
}