c – 将骨骼数据发送到glsl着色器
好的,所以我能够加载一个带有顶点,纹理坐标和法线的基本模型,并且可以毫无问题地渲染它.
但是,当我尝试投入一些骨骼信息时,当我尝试在着色器中操作骨骼数据时,骨骼数据似乎正在被破坏(或其他什么?). 这是我加载和渲染数据到opengl的代码(设置着色器并发送视图矩阵,世界矩阵等在另一个类中完成): /* * Mesh.cpp * * Created on: 2011-05-08 * Author: jarrett */ #include <boost/log/trivial.hpp> #include "../common/utilities/AssImpUtilities.h" #include "Mesh.h" namespace glr { namespace glw { Mesh::Mesh(IOpenGlDevice* openGlDevice,const std::string path,std::vector< glm::vec3 > vertices,std::vector< glm::vec3 > normals,std::vector< glm::vec2 > textureCoordinates,std::vector< glm::vec4 > colors,std::vector<VertexBoneData > bones,BoneData boneData) : openGlDevice_(openGlDevice),vertices_(vertices),normals_(normals),textureCoordinates_(textureCoordinates),colors_(colors),bones_(bones),boneData_(boneData) { BOOST_LOG_TRIVIAL(debug) << "loading mesh into video memory..."; // create our vao glGenVertexArrays(1,&vaoId_); glBindVertexArray(vaoId_); // create our vbos glGenBuffers(5,&vboIds_[0]); glBindBuffer(GL_ARRAY_BUFFER,vboIds_[0]); glBufferData(GL_ARRAY_BUFFER,vertices_.size() * sizeof(glm::vec3),&vertices_[0],GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0); glBindBuffer(GL_ARRAY_BUFFER,vboIds_[1]); glBufferData(GL_ARRAY_BUFFER,textureCoordinates_.size() * sizeof(glm::vec2),&textureCoordinates_[0],GL_STATIC_DRAW); glEnableVertexAttribArray(1); glVertexAttribPointer(1,2,vboIds_[2]); glBufferData(GL_ARRAY_BUFFER,normals_.size() * sizeof(glm::vec3),&normals_[0],GL_STATIC_DRAW); glEnableVertexAttribArray(2); glVertexAttribPointer(2,0); std::cout << "SIZE: " << vertices_.size() << " " << sizeof(glm::ivec4) << " " << bones_.size() << " " << sizeof(VertexBoneData) << std::endl; // Convert data into simple vectors,then send to OpenGL std::vector< glm::ivec4 > boneIds = std::vector< glm::ivec4 >(); std::vector< glm::vec4 > weights = std::vector< glm::vec4 >(); for ( VertexBoneData& d : bones_ ) { boneIds.push_back( d.boneIds ); weights.push_back( d.weights ); } glBindBuffer(GL_ARRAY_BUFFER,vboIds_[3]); glBufferData(GL_ARRAY_BUFFER,boneIds.size() * sizeof(glm::ivec4),&boneIds[0],GL_STATIC_DRAW); glEnableVertexAttribArray(3); glVertexAttribPointer(3,4,GL_INT,vboIds_[4]); glBufferData(GL_ARRAY_BUFFER,weights.size() * sizeof(glm::vec4),&weights[0],GL_STATIC_DRAW); glEnableVertexAttribArray(4); glVertexAttribPointer(4,0); // Disable our Vertex Array Object //glEnableVertexAttribArray(0); // Disable our Vertex Buffer Object glBindVertexArray(0); GlError err = openGlDevice_->getGlError(); if (err.type != GL_NONE) { // TODO: throw error BOOST_LOG_TRIVIAL(error) << "Error loading mesh in opengl"; BOOST_LOG_TRIVIAL(error) << "OpenGL error: " << err.name; } else { BOOST_LOG_TRIVIAL(debug) << "Successfully loaded mesh."; } } Mesh::~Mesh() { } void Mesh::render() { glBindVertexArray(vaoId_); glDrawArrays(GL_TRIANGLES,vertices_.size()); glBindVertexArray(0); } BoneData& Mesh::getBoneData() { return boneData_; } } } 我的实际着色器是这样的: #version 150 core struct Light { vec4 ambient; vec4 diffuse; vec4 specular; vec4 position; vec4 direction; }; in vec3 in_Position; in vec2 in_Texture; in vec3 in_Normal; in ivec4 in_BoneIds; in vec4 in_BoneWeights; out vec2 textureCoord; out vec3 normalDirection; out vec3 lightDirection; out float bug; layout(std140) uniform Lights { Light lights[ 1 ]; }; void main() { gl_Position = pvmMatrix * vec4(in_Position,1.0); vec4 lightDirTemp = viewMatrix * lights[0].direction; textureCoord = in_Texture; //vec4 normalDirTemp = boneTransform * vec4(in_Normal,1.0); //normalDirection = normalize(normalMatrix * normalDirTemp.xyz); normalDirection = normalize(normalMatrix * in_Normal); lightDirection = normalize(vec3(lightDirTemp)); // If we have any bugs,should highlight the vertex red or green bug = 0.0; float sum = in_BoneWeights[0] + in_BoneWeights[1] + in_BoneWeights[2] + in_BoneWeights[3]; if (sum > 1.5f) bug = 1.0; else if (sum < 0.95f) bug = 2.0; // disable bug highlighting //bug = 0.0; } 如果bug = 1.0,则顶点为红色,如果= = 2.0,则顶点为绿色.我看到所有的顶点现在都是红色的,这意味着总和大于1.5f. 我已经确认每组权重的总和实际上是<= 1.0f ...所以在世界中如何在着色器中不是这种情况? 有人看到任何明显我失踪的东西吗? 编辑:看起来我发现了问题 – 我没有在任何变量上调用glBindAttribLocation – 添加后: glBindAttribLocation(programId_,"in_Position"); glBindAttribLocation(programId_,1,"in_Texture"); glBindAttribLocation(programId_,"in_Color"); glBindAttribLocation(programId_,"in_BoneIds"); glBindAttribLocation(programId_,"in_BoneWeights"); 我的着色器加载代码,它工作正常.奇怪的是 – 我没有必要为前3(位置,纹理和颜色)这样做,它工作得很好.但是当我添加骨骼信息时,我突然需要这个……为什么? 解决方法
您需要使用glVertexAttribIPointer(…)将数据提供给ivec< N>顶点属性.如果您认为在设置属性位置之前遇到“损坏”,请等到您在着色器中编写实际需要骨骼ID的代码…这些值将毫无意义,因为您使用了错误的API调用来关联属性具有特定绑定位置的数据.
glVertexAttribPointer(…)变体在获取GL_INT数据类型时没有问题,但它会将其转换为浮点(并且它可以在过程中规范化定点值,因此额外的参数).因此,期望该变体将数据提供给vec< N>.顶点属性,而不是ivec< N>. 更简洁地说,对整数顶点属性使用glVertexAttribIPointer,对浮点使用glVertexAttribPointer. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |