Просмотр исходного кода

Optimized mesh skinning further, added support for GPU skinning

Ivan Safrin 11 лет назад
Родитель
Сommit
8be60d9cb7

+ 6 - 1
Core/Contents/Include/PolyGLVertexBuffer.h

@@ -51,7 +51,9 @@ namespace Polycode {
 		GLuint getColorBufferID();
 		GLuint getTangentBufferID();
 		GLuint getIndexBufferID();
-				
+		GLuint getBoneWeightBufferID();
+		GLuint getBoneIndexBufferID();
+        
 	protected:
 		
 		GLuint vertexBufferID;
@@ -60,6 +62,9 @@ namespace Polycode {
 		GLuint colorBufferID;	
 		GLuint tangentBufferID;
         GLuint indexBufferID;
+        
+        GLuint boneWeightBufferID;
+        GLuint boneIndexBufferID;
 	};
 	
 }

+ 1 - 1
Core/Contents/Include/PolyMesh.h

@@ -391,7 +391,7 @@ namespace Polycode {
             VertexDataArray vertexTangentArray;
         
             VertexDataArray vertexBoneWeightArray;
-            IndexDataArray vertexBoneIndexArray;
+            VertexDataArray vertexBoneIndexArray;
         
             IndexDataArray indexArray;
         

+ 4 - 1
Core/Contents/Include/PolySceneMesh.h

@@ -241,6 +241,8 @@ namespace Polycode {
              * If this flag is set to false, backface culling is disabled when rendering this entity, rendering both sides of each face. Set to true by default.
              */
             bool backfaceCulled;
+        
+            bool sendBoneMatricesToMaterial;
 			
 		protected:
 		
@@ -252,7 +254,8 @@ namespace Polycode {
 			ShaderBinding *localShaderOptions;
             String fileName;
         
-    
+            std::vector<Matrix4> materialBoneMatrices;
+        
             VertexDataArray skeletalVertexPositions;
             VertexDataArray skeletalVertexNormals;
         

+ 2 - 1
Core/Contents/Include/PolyShader.h

@@ -88,7 +88,7 @@ namespace Polycode {
 			const String& getName() const;
 			
 			ShaderBinding *createBinding();
-			virtual void reload() {}								
+			virtual void reload() {}
 			
 			int getExpectedParamType(String name);
 			
@@ -145,6 +145,7 @@ namespace Polycode {
 			void *data;
 			int type;
             bool ownsPointer;
+            unsigned int arraySize;
 		
             // Convenience getters/setters for Lua users
             Number getNumber();

+ 1 - 1
Core/Contents/Source/PolyBone.cpp

@@ -83,7 +83,7 @@ Matrix4 Bone::buildFinalMatrix() const {
 }
 
 void Bone::rebuildFinalMatrix() {
-    finalMatrix = buildFinalMatrix();
+    finalMatrix = restMatrix * buildFinalMatrix();
 }
 
 void Bone::setBoneMatrix(const Matrix4& matrix) {

+ 17 - 0
Core/Contents/Source/PolyGLRenderer.cpp

@@ -419,6 +419,20 @@ void OpenGLRenderer::drawVertexBuffer(VertexBuffer *buffer, bool enableColorBuff
         glVertexAttribPointer(6, 3, GL_FLOAT, 0, 0,  (char *)NULL);
 	}
     
+    if(glVertexBuffer->getBoneWeightBufferID() != -1) {
+        
+        glBindBufferARB( GL_ARRAY_BUFFER_ARB, glVertexBuffer->getBoneWeightBufferID());
+        glEnableVertexAttribArrayARB(7);
+        glVertexAttribPointer(7, 4, GL_FLOAT, 0, 0,  (char *)NULL);
+    }
+    
+    if(glVertexBuffer->getBoneIndexBufferID() != -1) {
+        
+        glBindBufferARB( GL_ARRAY_BUFFER_ARB, glVertexBuffer->getBoneIndexBufferID());
+        glEnableVertexAttribArrayARB(8);
+        glVertexAttribPointer(8, 4, GL_FLOAT, 0, 0,  (char *)NULL);
+    }
+    
 	GLenum mode = GL_TRIANGLES;
 	
 	switch(buffer->meshType) {
@@ -454,6 +468,9 @@ void OpenGLRenderer::drawVertexBuffer(VertexBuffer *buffer, bool enableColorBuff
 	}
     
     glDisableVertexAttribArrayARB(6);
+    glDisableVertexAttribArrayARB(7);
+    glDisableVertexAttribArrayARB(8);
+    
 	glDisableClientState( GL_VERTEX_ARRAY);
 	glDisableClientState( GL_TEXTURE_COORD_ARRAY );		
 	glDisableClientState( GL_NORMAL_ARRAY );

+ 3 - 1
Core/Contents/Source/PolyGLSLShader.cpp

@@ -121,7 +121,9 @@ void GLSLShader::linkProgram() {
 	shader_id = glCreateProgram();
     glAttachShader(shader_id, ((GLSLProgram*)fp)->program);
     glAttachShader(shader_id, ((GLSLProgram*)vp)->program);	
-	glBindAttribLocation(shader_id, 6, "vTangent");	
+	glBindAttribLocation(shader_id, 6, "vTangent");
+	glBindAttribLocation(shader_id, 7, "vBoneWeights");
+	glBindAttribLocation(shader_id, 8, "vBoneIndices");
     glLinkProgram(shader_id);
 	if(vp) {
 		vp->addEventListener(this, Event::RESOURCE_RELOAD_EVENT);

+ 14 - 1
Core/Contents/Source/PolyGLSLShaderModule.cpp

@@ -246,7 +246,20 @@ void GLSLShaderModule::updateGLSLParam(Renderer *renderer, GLSLShader *glslShade
 			break;
 			case ProgramParam::PARAM_MATRIX:
 				if(localParam) {
-					setUniformMatrix(paramLocation, localParam->getMatrix4());
+                    if(localParam->arraySize > 0) {
+                        Matrix4 *matPointer = (Matrix4*)localParam->data;
+                        std::vector<float> matrixData;
+                        for(int i=0; i < localParam->arraySize; i++) {
+                            for(int j=0; j < 16; j++) {
+                                matrixData.push_back(matPointer[i].ml[j]);
+                            }
+                        }
+                        
+                        glUniformMatrix4fv(paramLocation, localParam->arraySize, false, &matrixData[0]);
+                    
+                    } else {
+                        setUniformMatrix(paramLocation, localParam->getMatrix4());
+                    }
                 } else {
 					Matrix4 defaultMatrix;
 					setUniformMatrix(paramLocation, defaultMatrix);

+ 28 - 1
Core/Contents/Source/PolyGLVertexBuffer.cpp

@@ -54,6 +54,8 @@ OpenGLVertexBuffer::OpenGLVertexBuffer(Mesh *mesh) : VertexBuffer() {
     colorBufferID = -1;
     tangentBufferID = -1;
     indexBufferID = -1;
+    boneWeightBufferID = -1;
+    boneIndexBufferID = -1;
     
     
 	meshType = mesh->getMeshType();
@@ -85,7 +87,21 @@ OpenGLVertexBuffer::OpenGLVertexBuffer(Mesh *mesh) : VertexBuffer() {
         glBufferDataARB(GL_ARRAY_BUFFER_ARB,  mesh->vertexTangentArray.getDataSize() * sizeof(PolyRendererVertexType), mesh->vertexTangentArray.getArrayData(), GL_STATIC_DRAW_ARB);
     }
     
-    if(mesh->vertexTangentArray.getDataSize() == vertexCount * 4) {
+    if(mesh->vertexBoneWeightArray.getDataSize() == vertexCount * 4) {
+        glGenBuffersARB(1, &boneWeightBufferID);
+        glBindBufferARB(GL_ARRAY_BUFFER_ARB, boneWeightBufferID);
+        
+        glBufferDataARB(GL_ARRAY_BUFFER_ARB,  mesh->vertexBoneWeightArray.getDataSize() * sizeof(PolyRendererVertexType), mesh->vertexBoneWeightArray.getArrayData(), GL_STATIC_DRAW_ARB);
+    }
+    
+    if(mesh->vertexBoneIndexArray.getDataSize() == vertexCount * 4) {
+        glGenBuffersARB(1, &boneIndexBufferID);
+        glBindBufferARB(GL_ARRAY_BUFFER_ARB, boneIndexBufferID);
+        
+        glBufferDataARB(GL_ARRAY_BUFFER_ARB,  mesh->vertexBoneIndexArray.getDataSize() * sizeof(PolyRendererVertexType), mesh->vertexBoneIndexArray.getArrayData(), GL_STATIC_DRAW_ARB);
+    }
+    
+    if(mesh->vertexColorArray.getDataSize() == vertexCount * 4) {
         glGenBuffersARB(1, &colorBufferID);
         glBindBufferARB(GL_ARRAY_BUFFER_ARB, colorBufferID);
             
@@ -98,6 +114,7 @@ OpenGLVertexBuffer::OpenGLVertexBuffer(Mesh *mesh) : VertexBuffer() {
         glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,  mesh->indexArray.getDataSize() * sizeof(PolyRendererIndexType), mesh->indexArray.getArrayData(), GL_STATIC_DRAW_ARB);
         indexCount = mesh->indexArray.getDataSize();
     }
+    
 }
 
 OpenGLVertexBuffer::~OpenGLVertexBuffer() {
@@ -106,6 +123,16 @@ OpenGLVertexBuffer::~OpenGLVertexBuffer() {
 	glDeleteBuffersARB(1, &normalBufferID);
 	glDeleteBuffersARB(1, &colorBufferID);
 	glDeleteBuffersARB(1, &indexBufferID);
+	glDeleteBuffersARB(1, &boneWeightBufferID);
+	glDeleteBuffersARB(1, &boneIndexBufferID);
+}
+
+GLuint OpenGLVertexBuffer::getBoneWeightBufferID() {
+    return boneWeightBufferID;
+}
+
+GLuint OpenGLVertexBuffer::getBoneIndexBufferID() {
+    return boneIndexBufferID;
 }
 
 GLuint OpenGLVertexBuffer::getColorBufferID() {

+ 2 - 2
Core/Contents/Source/PolyMesh.cpp

@@ -197,7 +197,7 @@ void Mesh::saveToFile(OSFILE *outFile, bool writeNormals, bool writeTangents, bo
     
     if(writeBoneWeights) {
         writeVertexBlock(&vertexBoneWeightArray, outFile);
-        writeIndexBlock(&vertexBoneIndexArray, outFile);
+        writeVertexBlock(&vertexBoneIndexArray, outFile);
     }
 }
 
@@ -258,7 +258,7 @@ void Mesh::loadFromFileV2(OSFILE *inFile) {
             break;
             case RenderDataArray::BONE_INDEX_DATA_ARRAY:
                 vertexBoneIndexArray.data.resize(blockSize);
-                OSBasics::read(&vertexBoneIndexArray.data[0], sizeof(PolyRendererIndexType), blockSize, inFile);
+                OSBasics::read(&vertexBoneIndexArray.data[0], sizeof(PolyRendererVertexType), blockSize, inFile);
             break;
         }
     }

+ 18 - 4
Core/Contents/Source/PolySceneMesh.cpp

@@ -57,6 +57,7 @@ SceneMesh::SceneMesh(const String& fileName) : Entity(), texture(NULL), material
     forceMaterial = false;
     backfaceCulled = true;
 	alphaTest = false;
+    sendBoneMatricesToMaterial = false;
 }
 
 SceneMesh::SceneMesh(Mesh *mesh) : Entity(), texture(NULL), material(NULL), skeleton(NULL), localShaderOptions(NULL), skeletalVertexPositions(RenderDataArray::VERTEX_DATA_ARRAY), skeletalVertexNormals(RenderDataArray::NORMAL_DATA_ARRAY) {
@@ -74,6 +75,7 @@ SceneMesh::SceneMesh(Mesh *mesh) : Entity(), texture(NULL), material(NULL), skel
     forceMaterial = false;
     backfaceCulled = true;
 	alphaTest = false;
+    sendBoneMatricesToMaterial = false;
 }
 
 SceneMesh::SceneMesh(int meshType) : texture(NULL), material(NULL), skeleton(NULL), localShaderOptions(NULL), skeletalVertexPositions(RenderDataArray::VERTEX_DATA_ARRAY), skeletalVertexNormals(RenderDataArray::NORMAL_DATA_ARRAY) {
@@ -89,6 +91,7 @@ SceneMesh::SceneMesh(int meshType) : texture(NULL), material(NULL), skeleton(NUL
     forceMaterial = false;
     backfaceCulled = true;
 	alphaTest = false;
+    sendBoneMatricesToMaterial = false;
 }
 
 void SceneMesh::setMesh(Mesh *mesh) {
@@ -271,13 +274,11 @@ void SceneMesh::renderMeshLocally() {
                     Bone *bone = skeleton->getBone(mesh->vertexBoneIndexArray.data[(i*4)+b]);
                         
                     Vector3 restVert(mesh->vertexPositionArray.data[i*3], mesh->vertexPositionArray.data[(i*3)+1], mesh->vertexPositionArray.data[(i*3)+2]);
-                                         
-                    Vector3 vec = bone->restMatrix * restVert;
-                    tPos += bone->finalMatrix * vec * (boneWeight);
+                    
+                    tPos += bone->finalMatrix * restVert * (boneWeight);
                         
                     Vector3 nvec(mesh->vertexNormalArray.data[i*3], mesh->vertexNormalArray.data[(i*3)+1], mesh->vertexNormalArray.data[(i*3)+2]);
                     
-                    nvec = bone->restMatrix.rotateVector(nvec);
                     nvec = bone->finalMatrix.rotateVector(nvec);
                     
                     norm += nvec * (boneWeight);
@@ -379,6 +380,19 @@ void SceneMesh::Render() {
 			renderer->setTexture(NULL);
 	}
     
+    if(sendBoneMatricesToMaterial && localShaderOptions && skeleton) {
+        LocalShaderParam *skeletonMatrix = localShaderOptions->getLocalParamByName("skeletonMatrix[0]");
+        
+        if(skeletonMatrix) {
+            for(int i=0; i < skeleton->getNumBones(); i++) {
+                materialBoneMatrices[i] = skeleton->getBone(i)->getFinalMatrix();
+            }
+        } else {
+            materialBoneMatrices.resize(skeleton->getNumBones());
+            localShaderOptions->addParamPointer(ProgramParam::PARAM_MATRIX, "skeletonMatrix[0]", materialBoneMatrices.data())->arraySize = skeleton->getNumBones();
+        }
+    }
+    
 	if(useVertexBuffer) {
         VertexBuffer *vb = mesh->getVertexBuffer();
         if(vb){

+ 1 - 0
Core/Contents/Source/PolyShader.cpp

@@ -351,6 +351,7 @@ const String& Shader::getName() const {
 
 LocalShaderParam::LocalShaderParam() {
     data = NULL;
+    arraySize = 0;
     ownsPointer = true;
 }