From: Luke Lau Date: Tue, 27 Nov 2018 01:22:06 +0000 (+0000) Subject: Bones and skeletal animation X-Git-Tag: cs7gv3-a3~13 X-Git-Url: http://git.lukelau.me/?p=opengl.git;a=commitdiff_plain;h=be8759aec179d6d7bed58732134673870c596b4f Bones and skeletal animation --- diff --git a/Makefile b/Makefile index 208ae4f..98f6c27 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ all: main main: - clang++ -g --std=c++17 *.cpp *.mm -L/usr/local/lib -lassimp -framework OpenGL -framework glut -framework CoreGraphics -framework CoreFoundation -framework Cocoa -framework ImageIO -lglew -o bin/main + clang++ -g --std=c++17 *.cpp *.mm -L../assimp/lib -lassimp -I../assimp/include -framework OpenGL -framework glut -framework CoreGraphics -framework CoreFoundation -framework Cocoa -framework ImageIO -lglew -o bin/main ctags *.cpp diff --git a/main.cpp b/main.cpp index fcc7a1e..635e182 100644 --- a/main.cpp +++ b/main.cpp @@ -108,6 +108,7 @@ void drawLight(Light &light) { void display() { glClearColor(0.5, 0.5, 0.5, 1); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + glViewport(0, 0, windowWidth * 2, windowHeight * 2); float d = (float)glutGet(GLUT_ELAPSED_TIME) * 0.001f; @@ -123,7 +124,7 @@ void display() { glUniform3fv(glGetUniformLocation(pbrProg->progId, "lightPositions"), 4, glm::value_ptr(lightPositions[0])); glUniform3fv(glGetUniformLocation(pbrProg->progId, "lightColors"), 4, glm::value_ptr(lightColors[0])); - pbr->draw(skyboxes[activeSkybox]); + pbr->draw(skyboxes[activeSkybox], d * 1000); for (Light &light: lights) drawLight(light); @@ -160,12 +161,14 @@ void init() { pbrProg = new Program("pbrvert.glsl", "pbrfrag.glsl"); glUseProgram(pbrProg->progId); - pbr = new Model("models/sphereMetal.gltf", *pbrProg); + pbr = new Model("models/newtonsCradle.gltf", *pbrProg); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); // prevent edge artifacts in specular cubemaps glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + + glViewport(0, 0, windowWidth, windowHeight); } bool* keyStates = new bool[256]; @@ -248,7 +251,6 @@ void mouse(int button, int state, int x, int y) { } void reshape(int newWidth, int newHeight) { - glViewport(0, 0, newWidth * 2, newHeight * 2); windowWidth = newWidth, windowHeight = newHeight; } @@ -257,6 +259,7 @@ int main(int argc, char** argv) { glutInitDisplayMode(GLUT_DEPTH|GLUT_DOUBLE|GLUT_RGB|GLUT_3_2_CORE_PROFILE); glutInitWindowSize(windowWidth, windowHeight); int win = glutCreateWindow("Physically Based Rendering"); + makeRetina(); glutDisplayFunc(display); glutReshapeFunc(reshape); @@ -264,8 +267,6 @@ int main(int argc, char** argv) { init(); - makeRetina(); - glutKeyboardFunc(keyboard); glutKeyboardUpFunc(keyboardUp); glutTimerFunc(16, timer, 0); diff --git a/metallicroughness.py b/metallicroughness.py index e4bf1b8..bc82363 100755 --- a/metallicroughness.py +++ b/metallicroughness.py @@ -9,7 +9,7 @@ roughness = cv2.imread(sys.argv[2]) roughness[:,:,0] = 0 roughness[:,:,2] = 0 -metallic[:,:,0] = 0 metallic[:,:,1] = 0 +metallic[:,:,2] = 0 -cv2.imwrite(sys.argv[3], roughness + metallic) +cv2.imwrite(sys.argv[3], metallic + roughness) diff --git a/model.cpp b/model.cpp index ee11595..0bb5837 100644 --- a/model.cpp +++ b/model.cpp @@ -1,8 +1,18 @@ #include "model.hpp" #include #include +#include #include +glm::mat4 aiMatrixToMat4(aiMatrix4x4 from) { + glm::mat4 to; + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + to[i][j] = from[j][i]; + return to; +} + + Model::Mesh::Mesh(const aiMesh *aiMesh, GLuint progId) { std::vector vertices, normals, tangents, bitangents; @@ -20,15 +30,6 @@ Model::Mesh::Mesh(const aiMesh *aiMesh, GLuint progId) { std::cerr << "Missing normals" << std::endl; exit(1); } - 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 { - std::cerr << "Missing tangents: make sure blender has UV maps" << std::endl; - exit(1); - } // check for texture coord set 0 if (aiMesh->HasTextureCoords(0)) { const aiVector3D v = aiMesh->mTextureCoords[0][i]; @@ -58,7 +59,7 @@ Model::Mesh::Mesh(const aiMesh *aiMesh, GLuint progId) { 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 boneVbo = vbos[4]; GLuint posLoc = glGetAttribLocation(progId, "pos"); glBindBuffer(GL_ARRAY_BUFFER, vertexVbo); @@ -78,52 +79,202 @@ Model::Mesh::Mesh(const aiMesh *aiMesh, GLuint progId) { 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); + + // bones + std::vector vertBones(aiMesh->mNumVertices); + + std::map>> boneWeightMap; + + for (unsigned int i = 0; i < aiMesh->mNumBones; i++) { + aiBone *aiBone = aiMesh->mBones[i]; + + boneMap[std::string(aiBone->mName.C_Str())] = std::pair(i + 1, aiMatrixToMat4(aiBone->mOffsetMatrix)); + + for (int j = 0; j < aiBone->mNumWeights; j++) { + aiVertexWeight vw = aiBone->mWeights[j]; + + if (!boneWeightMap.count(vw.mVertexId)) boneWeightMap[vw.mVertexId] = std::vector>(); + boneWeightMap[vw.mVertexId].push_back(std::pair(i + 1, vw.mWeight)); + } + } + + for (auto pair: boneWeightMap) { + unsigned int vertexId = pair.first; + for (int i = 0; i < pair.second.size() && i < 4; i++) { + unsigned int boneId = pair.second[i].first; + float weight = pair.second[i].second; + vertBones[vertexId].ids[i] = boneId; + vertBones[vertexId].weights[i] = weight; + } + } + + glBindBuffer(GL_ARRAY_BUFFER, boneVbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(VertBones) * vertBones.size(), &vertBones[0], GL_STATIC_DRAW); + + GLuint boneIdLoc = glGetAttribLocation(progId, "boneIds"); + glEnableVertexAttribArray(boneIdLoc); + glVertexAttribIPointer(boneIdLoc, 4, GL_INT, sizeof(VertBones), 0); + + GLuint boneWeightLoc = glGetAttribLocation(progId, "boneWeights"); + glEnableVertexAttribArray(boneWeightLoc); + glVertexAttribPointer(boneWeightLoc, 4, GL_FLOAT, GL_FALSE, sizeof(VertBones), (const GLvoid *)sizeof(VertBones::ids)); } -Model::Node::Node(const aiNode &node, GLuint progId): ai(node), progId(progId) { +Model::Node::Node(const aiNode &node, GLuint progId, AnimMap *am): ai(node), progId(progId), animMap(am) { for (int i = 0; i < node.mNumMeshes; i++) { meshIndices.push_back(node.mMeshes[i]); } for (int i = 0; i < node.mNumChildren; i++) { const aiNode *child = node.mChildren[i]; - children.push_back(new Node(*child, progId)); + children.push_back(new Node(*child, progId, am)); } } -glm::mat4 aiMatrixToMat4(aiMatrix4x4 from) { - glm::mat4 to; - for (int i = 0; i < 4; i++) - for (int j = 0; j < 4; j++) - to[i][j] = from[j][i]; - return to; +glm::mat4 lerp(const aiNodeAnim *anim, const float tick) { + + if (anim->mNumPositionKeys == 0) return glm::mat4(1.f); + + int yIndex = -1; + for (int i = 0; i < anim->mNumPositionKeys; i++) { + aiVectorKey vk = anim->mPositionKeys[i]; + if (vk.mTime > tick) { + yIndex = i; + break; + } + } + aiVector3D lerpPos; + if (yIndex < 1) { + lerpPos = anim->mPositionKeys[0].mValue; + } else { + auto X = anim->mPositionKeys[yIndex - 1]; + auto Y = anim->mPositionKeys[yIndex]; + + lerpPos = (X.mValue * (float)(Y.mTime - tick) + Y.mValue * (float)(tick - X.mTime)) / (float)(Y.mTime - X.mTime); + } + aiMatrix4x4 result; + aiMatrix4x4::Translation(lerpPos, result); + return aiMatrixToMat4(result); +} + +glm::mat4 lerpRotation(const aiNodeAnim *anim, const float tick) { + int yIndex = -1; + for (int i = 0; i < anim->mNumRotationKeys; i++) { + aiQuatKey vk = anim->mRotationKeys[i]; + if (vk.mTime > tick) { + yIndex = i; + break; + } + } + + aiQuaternion result; + if (yIndex < 1) { + result = anim->mRotationKeys[0].mValue; + } else { + + auto X = anim->mRotationKeys[yIndex - 1]; + auto Y = anim->mRotationKeys[yIndex]; + + float mix = (tick - X.mTime) / (Y.mTime - X.mTime); + + aiQuaternion::Interpolate(result, X.mValue, Y.mValue, mix); + + } + return aiMatrixToMat4(aiMatrix4x4(result.GetMatrix())); +} + +glm::mat4 lerpScaling(const aiNodeAnim *anim, const float tick) { + int yIndex = -1; + for (int i = 0; i < anim->mNumScalingKeys; i++) { + aiVectorKey vk = anim->mScalingKeys[i]; + if (vk.mTime > tick) { + yIndex = i; + break; + } + } + + aiVector3D lerpPos; + if (yIndex < 1) { + lerpPos = anim->mScalingKeys[0].mValue; + } else { + auto X = anim->mScalingKeys[yIndex - 1]; + auto Y = anim->mScalingKeys[yIndex]; + + lerpPos = (X.mValue * (float)(Y.mTime - tick) + Y.mValue * (float)(tick - X.mTime)) / (float)(Y.mTime - X.mTime); + } + aiMatrix4x4 result; + aiMatrix4x4::Scaling(lerpPos, result); + return aiMatrixToMat4(result); } void Model::Node::draw( const std::vector &meshes, const std::vector &materials, const Skybox skybox, - glm::mat4 parentTrans = glm::mat4(1)) const { + const float tick, + glm::mat4 parentTrans = glm::mat4(1), + BoneTransforms boneTransforms = BoneTransforms()) const { GLuint modelLoc = glGetUniformLocation(progId, "model"); - glm::mat4 m = parentTrans * aiMatrixToMat4(ai.mTransformation) * model; + + glm::mat4 animTrans(1.f); + if (animMap->count(std::string(ai.mName.C_Str()))) { + for (const Animation anim: animMap->at(std::string(ai.mName.C_Str()))) { + float t = fmod(tick, anim.duration); + for (const aiNodeAnim *nodeAnim: anim.nodeAnims) { + animTrans *= lerp(nodeAnim, t); + animTrans *= lerpRotation(nodeAnim, t); + animTrans *= lerpScaling(nodeAnim, t); + } + } + /* std::cerr << std::string(ai.mName.C_Str()) << animTrans[0][0] << std::endl; */ + } + + + glm::mat4 m = parentTrans * animTrans * aiMatrixToMat4(ai.mTransformation) * model; + + for (auto child: children) { + //set to parent transforms + boneTransforms[std::string(ai.mName.C_Str())] = m; + } for (unsigned int i: meshIndices) { const Mesh &mesh = meshes[i]; glBindVertexArray(mesh.vao); + // bones + std::vector idBones(17, glm::mat4(1.f)); + glUniformMatrix4fv(glGetUniformLocation(progId, "bones"), 17, GL_FALSE, glm::value_ptr(idBones[0])); + + for (std::pair> pair: mesh.boneMap) { + + std::string nodeName = pair.first; + unsigned int boneId = pair.second.first; + glm::mat4 boneOffset = pair.second.second; + + glm::mat4 boneTrans(1.f); + if (boneTransforms.count(nodeName)) boneTrans = boneTransforms[nodeName]; + int j = 0; + for (const Animation anim: animMap->at(nodeName)) { + float t = fmod(tick, anim.duration); + for (const aiNodeAnim *nodeAnim: anim.nodeAnims) { + boneTrans = boneTrans * lerp(nodeAnim, t); + boneTrans = boneTrans * lerpRotation(nodeAnim, t); + /* boneTrans = boneTrans * lerpScaling(nodeAnim, t); */ + j++; + } + } + assert(j == 1); + + + boneTrans = boneTrans * glm::inverse(boneOffset); + + + std::string boneLocStr = "bones[" + std::to_string(boneId) + "]"; + GLuint boneLoc = glGetUniformLocation(progId, boneLocStr.c_str()); + glUniformMatrix4fv(boneLoc, 1, GL_FALSE, glm::value_ptr(boneTrans)); + } + Material material = materials[mesh.materialIndex]; material.bind(); @@ -143,14 +294,14 @@ void Model::Node::draw( const std::vector &meshes, glDrawElements(GL_TRIANGLES, mesh.numIndices, GL_UNSIGNED_INT, 0); } - for (Node *child: children) child->draw(meshes, materials, skybox, m); + for (Node *child: children) child->draw(meshes, materials, skybox, tick, m, boneTransforms); } Model::Model(const std::string &path, Program p): program(p) { glUseProgram(p.progId); const aiScene *scene = importer.ReadFile(path, - aiProcess_Triangulate | aiProcess_CalcTangentSpace | aiProcess_GenNormals); + aiProcess_Triangulate | aiProcess_CalcTangentSpace | aiProcess_GenNormals | aiProcess_FlipUVs); if (!scene) { std::cerr << importer.GetErrorString() << std::endl; exit(1); @@ -161,22 +312,49 @@ Model::Model(const std::string &path, Program p): program(p) { meshes.push_back(Mesh(mesh, p.progId)); } - for (unsigned int i = 0; i < scene->mNumMaterials; i++) { + // TODO: handle default material inserted at the end by assimp + for (unsigned int i = 0; i < scene->mNumMaterials - 1; i++) { const aiMaterial &material = *scene->mMaterials[i]; materials.push_back(Material(material, p.progId)); } - root = new Node(*(scene->mRootNode), p.progId); + AnimMap *animMap = new AnimMap(); + for (int i = 0; i < scene->mNumAnimations; i++) { + const aiAnimation *aiAnim = scene->mAnimations[i]; + + std::map> nodeAnims; + + for (int j = 0; j < aiAnim->mNumChannels; j++) { + const aiNodeAnim *nodeAnim = aiAnim->mChannels[j]; + std::string nodeName = std::string(nodeAnim->mNodeName.C_Str()); + + if (!nodeAnims.count(nodeName)) nodeAnims[nodeName] = std::vector(); + + nodeAnims[nodeName].push_back(nodeAnim); + } + + for (std::pair> pair: nodeAnims) { + std::string nodeName = pair.first; + + if (!animMap->count(nodeName)) (*animMap)[nodeName] = std::vector(); + (*animMap)[nodeName].push_back({ 7500, pair.second }); + } + } + + root = new Node(*(scene->mRootNode), p.progId, animMap); } -void Model::draw(Skybox skybox) const { +void Model::draw(Skybox skybox, const float tick) const { glUseProgram(program.progId); - root->draw(meshes, materials, skybox); - program.validate(); + root->draw(meshes, materials, skybox, tick); } Model::Node* Model::find(const std::string &name) { - const aiNode *node = root->ai.FindNode(aiString(name)); + return find(aiString(name)); +} + +Model::Node* Model::find(const aiString name) { + const aiNode *node = root->ai.FindNode(name); Model::Node* res = root->findNode(*node); return res; } diff --git a/model.hpp b/model.hpp index 358b92d..5c74cb3 100644 --- a/model.hpp +++ b/model.hpp @@ -1,4 +1,5 @@ #include +#include #ifdef __APPLE__ #include #else @@ -13,32 +14,50 @@ class Model { + struct Animation { + double duration; + std::vector nodeAnims; + }; + + typedef std::map> BoneMap; + typedef std::map> AnimMap; + typedef std::map BoneTransforms; + + struct VertBones { + unsigned int ids[4] = {0, 0, 0 ,0}; + float weights[4] = {1, 0, 0, 0}; + }; + struct Mesh { Mesh(const aiMesh *aiMesh, GLuint progId); GLuint progId, vao, numIndices; unsigned int materialIndex; + BoneMap boneMap; }; public: Model(const std::string &path, Program p); - void draw(Skybox skybox) const; + void draw(Skybox skybox, const float tick) const; class Node { public: - Node(const aiNode &aiNode, GLuint progId); - void draw(const std::vector &meshes, const std::vector &materials, const Skybox s, glm::mat4 parentModel) const; + Node(const aiNode &aiNode, GLuint progId, AnimMap *animMap); + void draw(const std::vector &meshes, const std::vector &materials, const Skybox s, const float tick, glm::mat4 parentModel, BoneTransforms boneTransforms) const; const std::vector &getChildren() const { return children; } Node* findNode(const aiNode &aiNode); glm::mat4 model = glm::mat4(1); const aiNode &ai; + private: const GLuint progId; + const AnimMap *animMap; std::vector children; std::vector meshIndices; }; Node* getRoot() { return root; } + Node* find(const aiString name); Node* find(const std::string &name); private: diff --git a/models/greasy-pan-2-metallicroughness.png b/models/greasy-pan-2-metallicroughness.png index 3fae941..51f175a 100644 Binary files a/models/greasy-pan-2-metallicroughness.png and b/models/greasy-pan-2-metallicroughness.png differ diff --git a/models/materials/greasy-pan-2/greasy-pan-2-metallicroughness.png b/models/materials/greasy-pan-2/greasy-pan-2-metallicroughness.png index 3fae941..51f175a 100644 Binary files a/models/materials/greasy-pan-2/greasy-pan-2-metallicroughness.png and b/models/materials/greasy-pan-2/greasy-pan-2-metallicroughness.png differ diff --git a/models/materials/streakedmetal/streakedmetal-metallicroughness.png b/models/materials/streakedmetal/streakedmetal-metallicroughness.png index a192a45..8e69ee2 100644 Binary files a/models/materials/streakedmetal/streakedmetal-metallicroughness.png and b/models/materials/streakedmetal/streakedmetal-metallicroughness.png differ diff --git a/models/scuffed-plastic-ao.png b/models/scuffed-plastic-ao.png index 05536ef..e204022 100644 Binary files a/models/scuffed-plastic-ao.png and b/models/scuffed-plastic-ao.png differ diff --git a/models/scuffed-plastic-normal.png b/models/scuffed-plastic-normal.png index 935bf6e..67b9771 100644 Binary files a/models/scuffed-plastic-normal.png and b/models/scuffed-plastic-normal.png differ diff --git a/models/scuffed-plastic4-alb.png b/models/scuffed-plastic4-alb.png index f5787bc..664481c 100644 Binary files a/models/scuffed-plastic4-alb.png and b/models/scuffed-plastic4-alb.png differ diff --git a/models/sphereMetal.bin b/models/sphereMetal.bin deleted file mode 100644 index b4184d8..0000000 Binary files a/models/sphereMetal.bin and /dev/null differ diff --git a/models/sphereMetal.blend b/models/sphereMetal.blend deleted file mode 100644 index 1700b22..0000000 Binary files a/models/sphereMetal.blend and /dev/null differ diff --git a/models/sphereMetal.gltf b/models/sphereMetal.gltf deleted file mode 100644 index c51b46f..0000000 --- a/models/sphereMetal.gltf +++ /dev/null @@ -1,744 +0,0 @@ -{ - "accessors" : [ - { - "bufferView" : 0, - "componentType" : 5123, - "count" : 29400, - "max" : [ - 5003 - ], - "min" : [ - 0 - ], - "type" : "SCALAR" - }, - { - "bufferView" : 1, - "componentType" : 5126, - "count" : 5004, - "max" : [ - 1.0000009536743164, - 1.0, - 1.0000017881393433 - ], - "min" : [ - -1.0000007152557373, - -1.0, - -1.0 - ], - "type" : "VEC3" - }, - { - "bufferView" : 2, - "componentType" : 5126, - "count" : 5004, - "max" : [ - 1.0, - 1.0, - 1.0 - ], - "min" : [ - -1.0, - -1.0, - -1.0 - ], - "type" : "VEC3" - }, - { - "bufferView" : 3, - "componentType" : 5126, - "count" : 5004, - "max" : [ - 0.9990525245666504, - 0.1821206957101822, - 0.9870549440383911, - 1.0 - ], - "min" : [ - -0.9990525245666504, - -0.1808946281671524, - -0.987054705619812, - -1.0 - ], - "type" : "VEC4" - }, - { - "bufferView" : 4, - "componentType" : 5126, - "count" : 5004, - "max" : [ - 1.4449338912963867, - 0.9933801889419556 - ], - "min" : [ - 0.00026097893714904785, - 0.006618916988372803 - ], - "type" : "VEC2" - }, - { - "bufferView" : 5, - "componentType" : 5123, - "count" : 118800, - "max" : [ - 19999 - ], - "min" : [ - 0 - ], - "type" : "SCALAR" - }, - { - "bufferView" : 6, - "componentType" : 5126, - "count" : 20000, - "max" : [ - 1.0000005960464478, - 1.0, - 1.0000009536743164 - ], - "min" : [ - -0.9999977946281433, - -1.0, - -1.0 - ], - "type" : "VEC3" - }, - { - "bufferView" : 7, - "componentType" : 5126, - "count" : 20000, - "max" : [ - 1.0, - 1.0, - 1.0 - ], - "min" : [ - -1.0, - -1.0, - -0.999969482421875 - ], - "type" : "VEC3" - }, - { - "bufferView" : 8, - "componentType" : 5126, - "count" : 20000, - "max" : [ - 0.9809380769729614, - 0.3905962109565735, - 0.9425740242004395, - 1.0 - ], - "min" : [ - -0.980937659740448, - -0.3905961215496063, - -0.9425736665725708, - 1.0 - ], - "type" : "VEC4" - }, - { - "bufferView" : 9, - "componentType" : 5126, - "count" : 20000, - "max" : [ - 1.3736257553100586, - 0.9968895316123962 - ], - "min" : [ - 3.013014793395996e-05, - 0.0031104683876037598 - ], - "type" : "VEC2" - }, - { - "bufferView" : 10, - "componentType" : 5123, - "count" : 29400, - "max" : [ - 5003 - ], - "min" : [ - 0 - ], - "type" : "SCALAR" - }, - { - "bufferView" : 11, - "componentType" : 5126, - "count" : 5004, - "max" : [ - 1.0000009536743164, - 1.0, - 1.0000017881393433 - ], - "min" : [ - -1.0000007152557373, - -1.0, - -1.0 - ], - "type" : "VEC3" - }, - { - "bufferView" : 12, - "componentType" : 5126, - "count" : 5004, - "max" : [ - 1.0, - 1.0, - 1.0 - ], - "min" : [ - -1.0, - -1.0, - -1.0 - ], - "type" : "VEC3" - }, - { - "bufferView" : 13, - "componentType" : 5126, - "count" : 5004, - "max" : [ - 0.9990525245666504, - 0.1821206957101822, - 0.9870549440383911, - 1.0 - ], - "min" : [ - -0.9990525245666504, - -0.1808946281671524, - -0.987054705619812, - -1.0 - ], - "type" : "VEC4" - }, - { - "bufferView" : 14, - "componentType" : 5126, - "count" : 5004, - "max" : [ - 1.4449338912963867, - 0.9933801889419556 - ], - "min" : [ - 0.00026097893714904785, - 0.006618916988372803 - ], - "type" : "VEC2" - }, - { - "bufferView" : 15, - "componentType" : 5123, - "count" : 2904, - "max" : [ - 506 - ], - "min" : [ - 0 - ], - "type" : "SCALAR" - }, - { - "bufferView" : 16, - "componentType" : 5126, - "count" : 507, - "max" : [ - 1.3671875, - 0.984375, - 0.8515625 - ], - "min" : [ - -1.3671875, - -0.984375, - -0.8515625 - ], - "type" : "VEC3" - }, - { - "bufferView" : 17, - "componentType" : 5126, - "count" : 507, - "max" : [ - 0.9989318251609802, - 0.999725341796875, - 0.999969482421875 - ], - "min" : [ - -0.9989318251609802, - -0.9862666726112366, - -0.9753105044364929 - ], - "type" : "VEC3" - }, - { - "bufferView" : 18, - "componentType" : 5126, - "count" : 507, - "max" : [ - 0.9987419247627258, - 0.9946793913841248, - 0.9965001940727234, - 1.0 - ], - "min" : [ - -0.9963445067405701, - -0.999483048915863, - -0.9972872734069824, - 1.0 - ], - "type" : "VEC4" - }, - { - "bufferView" : 19, - "componentType" : 5126, - "count" : 507, - "max" : [ - 0.9998813271522522, - 0.9998813555357629 - ], - "min" : [ - 0.0001186444642371498, - 0.06660735607147217 - ], - "type" : "VEC2" - } - ], - "asset" : { - "generator" : "Khronos Blender glTF 2.0 exporter", - "version" : "2.0" - }, - "bufferViews" : [ - { - "buffer" : 0, - "byteLength" : 58800, - "byteOffset" : 0, - "target" : 34963 - }, - { - "buffer" : 0, - "byteLength" : 60048, - "byteOffset" : 58800, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 60048, - "byteOffset" : 118848, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 80064, - "byteOffset" : 178896, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 40032, - "byteOffset" : 258960, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 237600, - "byteOffset" : 298992, - "target" : 34963 - }, - { - "buffer" : 0, - "byteLength" : 240000, - "byteOffset" : 536592, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 240000, - "byteOffset" : 776592, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 320000, - "byteOffset" : 1016592, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 160000, - "byteOffset" : 1336592, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 58800, - "byteOffset" : 1496592, - "target" : 34963 - }, - { - "buffer" : 0, - "byteLength" : 60048, - "byteOffset" : 1555392, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 60048, - "byteOffset" : 1615440, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 80064, - "byteOffset" : 1675488, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 40032, - "byteOffset" : 1755552, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 5808, - "byteOffset" : 1795584, - "target" : 34963 - }, - { - "buffer" : 0, - "byteLength" : 6084, - "byteOffset" : 1801392, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 6084, - "byteOffset" : 1807476, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 8112, - "byteOffset" : 1813560, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 4056, - "byteOffset" : 1821672, - "target" : 34962 - } - ], - "buffers" : [ - { - "byteLength" : 1825728, - "uri" : "sphereMetal.bin" - } - ], - "images" : [ - { - "name" : "greasy-pan-2-albedo", - "uri" : "greasy-pan-2-albedo.png" - }, - { - "name" : "greasy-pan-2-normal", - "uri" : "greasy-pan-2-normal.png" - }, - { - "name" : "greasy-pan-2-ao", - "uri" : "greasy-pan-2-ao.png" - }, - { - "name" : "greasy-pan-2-metallicroughness", - "uri" : "greasy-pan-2-metallicroughness.png" - }, - { - "name" : "scuffed-plastic4-alb", - "uri" : "scuffed-plastic4-alb.png" - }, - { - "name" : "scuffed-plastic-metallicroughness", - "uri" : "scuffed-plastic-metallicroughness.png" - }, - { - "name" : "scuffed-plastic-normal", - "uri" : "scuffed-plastic-normal.png" - }, - { - "name" : "scuffed-plastic-ao", - "uri" : "scuffed-plastic-ao.png" - }, - { - "name" : "streakedmetal-albedo", - "uri" : "streakedmetal-albedo.png" - }, - { - "name" : "streakedmetal-normal", - "uri" : "streakedmetal-normal.png" - }, - { - "name" : "streakedmetal-metallicroughness", - "uri" : "streakedmetal-metallicroughness.png" - }, - { - "name" : "streakedmetal-ao", - "uri" : "streakedmetal-ao.png" - } - ], - "materials" : [ - { - "name" : "Greasy Metal", - "normalTexture" : { - "index" : 1 - }, - "occlusionTexture" : { - "index" : 2 - }, - "pbrMetallicRoughness" : { - "baseColorTexture" : { - "index" : 0 - }, - "metallicRoughnessTexture" : { - "index" : 3 - } - } - }, - { - "name" : "Plastic", - "normalTexture" : { - "index" : 6 - }, - "occlusionTexture" : { - "index" : 7 - }, - "pbrMetallicRoughness" : { - "baseColorTexture" : { - "index" : 4 - }, - "metallicRoughnessTexture" : { - "index" : 5 - } - } - }, - { - "name" : "Streaked Metal", - "normalTexture" : { - "index" : 9 - }, - "occlusionTexture" : { - "index" : 11 - }, - "pbrMetallicRoughness" : { - "baseColorTexture" : { - "index" : 8 - }, - "metallicRoughnessTexture" : { - "index" : 10 - } - } - } - ], - "meshes" : [ - { - "name" : "Sphere.001", - "primitives" : [ - { - "attributes" : { - "NORMAL" : 2, - "POSITION" : 1, - "TANGENT" : 3, - "TEXCOORD_0" : 4 - }, - "indices" : 0, - "material" : 2 - } - ] - }, - { - "name" : "Sphere", - "primitives" : [ - { - "attributes" : { - "NORMAL" : 7, - "POSITION" : 6, - "TANGENT" : 8, - "TEXCOORD_0" : 9 - }, - "indices" : 5, - "material" : 0 - } - ] - }, - { - "name" : "Sphere.002", - "primitives" : [ - { - "attributes" : { - "NORMAL" : 12, - "POSITION" : 11, - "TANGENT" : 13, - "TEXCOORD_0" : 14 - }, - "indices" : 10, - "material" : 1 - } - ] - }, - { - "name" : "Suzanne", - "primitives" : [ - { - "attributes" : { - "NORMAL" : 17, - "POSITION" : 16, - "TANGENT" : 18, - "TEXCOORD_0" : 19 - }, - "indices" : 15, - "material" : 2 - } - ] - } - ], - "nodes" : [ - { - "name" : "Camera", - "rotation" : [ - 0.483536034822464, - 0.33687159419059753, - -0.20870360732078552, - 0.7804827094078064 - ], - "translation" : [ - 7.481131553649902, - 5.34366512298584, - 6.5076398849487305 - ] - }, - { - "name" : "Lamp", - "rotation" : [ - 0.16907575726509094, - 0.7558802962303162, - -0.27217137813568115, - 0.570947527885437 - ], - "scale" : [ - 1.0, - 1.0, - 0.9999999403953552 - ], - "translation" : [ - 4.076245307922363, - 4.028226852416992, - -1.0054539442062378 - ] - }, - { - "mesh" : 1, - "name" : "Sphere" - }, - { - "mesh" : 0, - "name" : "Sphere.001", - "translation" : [ - 2.5, - 0.0, - -0.0 - ] - }, - { - "mesh" : 2, - "name" : "Sphere.002", - "translation" : [ - -2.5, - 0.0, - -0.0 - ] - }, - { - "mesh" : 3, - "name" : "Suzanne", - "rotation" : [ - 0.0, - 0.7071068286895752, - -0.0, - 0.7071067690849304 - ], - "translation" : [ - 0.0, - 0.0, - -2.5 - ] - } - ], - "samplers" : [ - {} - ], - "scene" : 0, - "scenes" : [ - { - "name" : "Scene", - "nodes" : [ - 5, - 3, - 2, - 1, - 0, - 4 - ] - } - ], - "textures" : [ - { - "sampler" : 0, - "source" : 0 - }, - { - "sampler" : 0, - "source" : 1 - }, - { - "sampler" : 0, - "source" : 2 - }, - { - "sampler" : 0, - "source" : 3 - }, - { - "sampler" : 0, - "source" : 4 - }, - { - "sampler" : 0, - "source" : 5 - }, - { - "sampler" : 0, - "source" : 6 - }, - { - "sampler" : 0, - "source" : 7 - }, - { - "sampler" : 0, - "source" : 8 - }, - { - "sampler" : 0, - "source" : 9 - }, - { - "sampler" : 0, - "source" : 10 - }, - { - "sampler" : 0, - "source" : 11 - } - ] -} diff --git a/models/streakedmetal-metallicroughness.png b/models/streakedmetal-metallicroughness.png index a192a45..8e69ee2 100644 Binary files a/models/streakedmetal-metallicroughness.png and b/models/streakedmetal-metallicroughness.png differ diff --git a/pbrfrag.glsl b/pbrfrag.glsl index 8f41bfb..4460872 100644 --- a/pbrfrag.glsl +++ b/pbrfrag.glsl @@ -68,7 +68,7 @@ vec3 getNormalFromMap() { void main() { vec3 albedo = pow(texture(albedoMap, texCoords).rgb, vec3(2.2)); vec3 normal = getNormalFromMap(); - float metallic = texture(metallicRoughnessMap, texCoords).r; + float metallic = texture(metallicRoughnessMap, texCoords).b; float roughness = texture(metallicRoughnessMap, texCoords).g; float ao = texture(aoMap, texCoords).r; diff --git a/pbrvert.glsl b/pbrvert.glsl index ec37a9c..1cea9a8 100644 --- a/pbrvert.glsl +++ b/pbrvert.glsl @@ -3,10 +3,15 @@ in vec3 pos; in vec3 unscaledNormal; in vec2 vTexCoord; +in ivec4 boneIds; +in vec4 boneWeights; + uniform mat4 model; uniform mat4 view; uniform mat4 projection; +uniform mat4 bones[16 + 1]; + out vec3 normal; out vec2 texCoords; @@ -15,10 +20,17 @@ out vec3 lightPos, viewPos, worldPos; void main() { texCoords = vTexCoord; - worldPos = vec3(model * vec4(pos, 1.f)); + mat4 boneTrans = bones[boneIds.x] * boneWeights.x; + /* boneTrans += bones[boneIds.y] * boneWeights.y; */ + /* boneTrans += bones[boneIds.z] * boneWeights.z; */ + /* boneTrans += bones[boneIds.w] * boneWeights.w; */ + + mat4 bonedModel = boneTrans * model; + + worldPos = vec3(bonedModel * vec4(pos, 1.f)); - normal = mat3(transpose(inverse(model))) * unscaledNormal; + normal = mat3(transpose(inverse(bonedModel))) * unscaledNormal; - gl_Position = projection * view * model * vec4(pos, 1.f); + gl_Position = projection * view * bonedModel * vec4(pos, 1.f); }