Итак, я могу загрузить базовую модель с вершинами, координатами текстуры и нормалями и сделать ее без проблем.Отправка данных о костях в glsl shader
Однако, когда я пытаюсь бросить какую-то информацию о костях, данные о костях, кажется, повреждаются (или что-то?), Когда я пытаюсь манипулировать им в шейдере.
Вот мой код для загрузки и визуализации данных в 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, 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, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, vboIds_[2]);
glBufferData(GL_ARRAY_BUFFER, normals_.size() * sizeof(glm::vec3), &normals_[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 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, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, vboIds_[4]);
glBufferData(GL_ARRAY_BUFFER, weights.size() * sizeof(glm::vec4), &weights[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, 0, 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, 0, 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
, то вершины окрашены в красный цвет, а если but = 2.0
, то вершины окрашены в зеленый цвет. Я вижу, что все вершины окрашены в красный цвет прямо сейчас, что означает, что sum
больше, чем 1.5f
.
Я подтвердил, что сумма каждого набора весов фактически равна <= 1.0f
... так как в мире это не так в шейдере?
Кто-нибудь видит что-то очевидное, что мне не хватает?
EDIT: Похоже, я нашел эту проблему - я не звонил glBindAttribLocation
на любом из моих in
переменных - после добавления:
glBindAttribLocation(programId_, 0, "in_Position");
glBindAttribLocation(programId_, 1, "in_Texture");
glBindAttribLocation(programId_, 2, "in_Color");
glBindAttribLocation(programId_, 3, "in_BoneIds");
glBindAttribLocation(programId_, 4, "in_BoneWeights");
моей шейдер загрузки коды, он отлично работает. Нечеткое дело - мне не приходилось делать это для первых 3 (положение, текстура и цвет), и он работал нормально. Но когда я добавил информацию о костях, мне вдруг это нужно ... почему?
Так оно и было - после этого я мог также удалить вызовы 'glBindAttribLocation'. У меня теперь есть анимация! (в какой-то степени, кажется, исчезает в местах, поэтому я думаю, что нормали могут быть испорчены). Спасибо @ Эндон! – Jarrett