Open LeeMcQueen opened 2 years ago
往Vertex类 加入 1.glm::vec3 tangent 2.glm::vec3 bitangent
Vertex.h
class Vertex{
public:
//构造函数 Vertex() {};
//析构函数 ~Vertex() {};
//Vertex类的get和set void setPosition(const glm::vec3 position) { position = position; } void setNormal(const glm::vec3 normal) { normal = normal; } void setTexture(const glm::vec2 texture) { texture = texture; } void setBoneIds(const glm::vec4 boneIds) { boneIds = boneIds; } void setBoneIds_x(unsigned int boneIdsx) { boneIds.x = boneIds_x; } void setBoneIds_y(unsigned int boneIdsy) { boneIds.y = boneIds_y; } void setBoneIds_z(unsigned int boneIdsz) { boneIds.z = boneIds_z; } void setBoneIds_w(unsigned int boneIdsw) { boneIds.w = boneIdsw; } void setBoneWeights(const glm::vec4 boneWeights) { boneWeights = boneWeights; } void setBoneWeights_x(float boneWeightsx) { boneWeights.x = boneWeights_x; } void setBoneWeights_y(float boneWeightsy) { boneWeights.y = boneWeights_y; } void setBoneWeights_z(float boneWeightsz) { boneWeights.z = boneWeights_z; } void setBoneWeights_w(float boneWeightsw) { boneWeights.w = boneWeightsw; } void setTangent(const glm::vec3 tangent) { tangent = tengent; } void setBitangent(const glm::vec3 biTangent) { biTangent = biTangent; } glm::vec3 getPosition() const { return position; } glm::vec3 getNormal() const { return normal; } glm::vec2 getTexture() const { return texture; } glm::vec4 getBoneIds() const { return boneIds; } glm::vec4 getBoneWieghts() const { return boneWeights; } glm::vec3 getTangent() const { return tangent; } glm::vec3 getBitangent() const { return bitangent; }
//顶点坐标 glm::vec3 position; //法线坐标 glm::vec3 normal; //纹理坐标 glm::vec2 texture; //骨骼ID glm::vec4 boneIds; //骨骼权重 glm::vec4 boneWeights_;
//法线贴图成员变量 切线 glm::vec3 tangent; //法线贴图成员变量 副切线 glm::vec3 bitangent; };
void AnimaModelLoader::loadAssimpModel(const aiScene scene,
aiMesh mesh,
std::vector
//返回参数list初始化
verticesOutput = {};
indicesOutput = {};
//顶点类的实例化
Vertex vertex;
//加载顶点,法线,uv坐标
for (unsigned int i = 0; i < mesh->mNumVertices; i++) {
//空的Vec3的变量
glm::vec3 vector;
//取得顶点
vector.x = mesh->mVertices[i].x;
vector.y = mesh->mVertices[i].y;
vector.z = mesh->mVertices[i].z;
vertex.setPosition(vector);
//取得法线
vector.x = mesh->mNormals[i].x;
vector.y = mesh->mNormals[i].y;
vector.z = mesh->mNormals[i].z;
vertex.setNormal(vector);
//取得切线
vector.x = mesh->mTangents[i].x;
vector.y = mesh->mTangents[i].y;
vector.z = mesh->mTangents[i].z;
vertex.setTangent(vector);
//取得副切线
vector.x = mesh->mBitangents[i].x;
vector.y = mesh->mBitangents[i].y;
vector.z = mesh->mBitangents[i].z;
vertex.setBitangent(vector);
//空的Vec2的变量
glm::vec2 vec;
//注意这里就只有一个纹理,需要的话需要动态设定
vec.x = mesh->mTextureCoords[0][i].x;
vec.y = mesh->mTextureCoords[0][i].y;
vertex.setTexture(vec);
//初始化骨骼ID 一共创建顶点的数量个
vertex.setBoneIds(glm::ivec4(0));
vertex.setBoneWeights(glm::vec4(0.0f));
verticesOutput.push_back(vertex);
}
//加载骨骼数据到顶点数组
//boneInfo的结构是 骨骼名<string> 矩阵pair
std::unordered_map<std::string, std::pair<int, glm::mat4>> boneInfo = {};
std::vector<unsigned int> boneCounts;
//命名感觉不是很准确 顶点数同样数量的list
boneCounts.resize(verticesOutput.size(), 0);
//得到模型的总骨骼数
nBoneCount = mesh->mNumBones;
std::cout << "loadModel() nBoneCount" << nBoneCount << std::endl;
//循环骨骼数量得到()
for (unsigned int i = 0; i < nBoneCount; i++) {
//导入aiMesh对象中的顶点骨骼数据
aiBone *bone = mesh->mBones[i];
//从Assimp格式转换成glm格式
glm::mat4 matrix = assimpToGlmMatrix(bone->mOffsetMatrix);
//按照骨骼名称(string形式)往里面注入map, map的形式是(i, matrix)
boneInfo[bone->mName.C_Str()] = { i, matrix };
//循环骨骼里面的顶点(通过总权重数就知道有多少个顶点)
for (unsigned int j = 0; j < bone->mNumWeights; j++) {
//当前骨骼的顶点ID
unsigned int id = bone->mWeights[j].mVertexId;
//当前骨骼的顶点的权重值
float weight = bone->mWeights[j].mWeight;
boneCounts[id]++;
//根据
switch (boneCounts[id])
{
case 1:
verticesOutput[id].setBoneIds_x(i);
verticesOutput[id].setBoneWeights_x(weight);
break;
case 2:
verticesOutput[id].setBoneIds_y(i);
verticesOutput[id].setBoneWeights_y(weight);
break;
case 3:
verticesOutput[id].setBoneIds_z(i);
verticesOutput[id].setBoneWeights_z(weight);
break;
case 4:
verticesOutput[id].setBoneIds_w(i);
verticesOutput[id].setBoneWeights_w(weight);
break;
default:
break;
}
}
}
//让所有权重的和为1
for (unsigned int i = 0; i < verticesOutput.size(); i++) {
//取得所有顶点数组里面的骨骼权重
glm::vec4 &boneWeight = verticesOutput[i].getBoneWieghts();
float totalWeight = boneWeight.x + boneWeight.y + boneWeight.z + boneWeight.w;
if (totalWeight > 0.0f) {
verticesOutput[i].setBoneWeights(glm::vec4(
boneWeight.x / totalWeight,
boneWeight.y / totalWeight,
boneWeight.z / totalWeight,
boneWeight.w / totalWeight)
);
}
}
for (unsigned int i = 0; i < mesh->mNumFaces; i++) {
aiFace &face = mesh->mFaces[i];
for (unsigned int j = 0; j < face.mNumIndices; j++) {
indicesOutput.push_back(face.mIndices[j]);
}
}
readSkeleton(skeletonOutput, scene->mRootNode, boneInfo);
}
main.cpp createvertexArray函数
unsigned int createVertexArray(std::vector
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) *vertices.size(), &vertices[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
//VAO的通道号码(0~15) 三个长度为一个单位 是否需要正规化到正负1之间 下一个坐标要跳过多少 下一个信息的偏移量
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, position_));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, normal_));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, texture_));
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, boneIds_));
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, boneWeights_));
glEnableVertexAttribArray(5);
glVertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, tangent_));
glEnableVertexAttribArray(6);
glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, bitangent_));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
glBindVertexArray(0);
return vao;
}
main函数 骨骼shader参数设定
unsigned int vao = 0;
//图片初始化
unsigned int diffuseTexture;
diffuseTexture = loader.loadTexture("boss_lan");
unsigned int emissionTexture;
emissionTexture = loader.loadTexture("boss_green");
unsigned int normalTexture;
normalTexture = loader.loadTexture("boss_normal");
//创建骨骼动画的顶点数组对象
vao = createVertexArray(animaModelLoader.getVertices(), animaModelLoader.getIndices());
//得到动画个数,然后生成相应大小的list(空的matrix,之后用getpose得到对应的matrix)
glm::mat4 identity;
std::vector<glm::mat4> currentPose = {};
currentPose.resize(animaModelLoader.getbBoneCount(), identity);
//加载shader
unsigned int shader = createShader(vertexShaderSource, fragmentShaderSource);
//shader变量的设定和链接
//create camera
unsigned int viewMatrixLocation = glGetUniformLocation(shader, "view_Matrix");
unsigned int projectionMatrixLocation = glGetUniformLocation(shader, "projection_Matrix");
//modelMatrix变换
unsigned int modelMatrixLocation = glGetUniformLocation(shader, "model_matrix");
unsigned int boneMatricesLocation = glGetUniformLocation(shader, "bone_transforms");
unsigned int textureLocation = glGetUniformLocation(shader, "diff_texture");
unsigned int emissionLocation = glGetUniformLocation(shader, "emission_texture");
unsigned int normalLocation = glGetUniformLocation(shader, "normal_texture")
unsigned int timeLocation = glGetUniformLocation(shader, "time");
vertexShader
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 texture;
layout (location = 3) in vec4 boneIds;
layout (location = 4) in vec4 boneWeights;
layout (location = 5) in vec3 tangent;
layout (location = 6) in vec3 bitangent;
uniform mat4 bone_transforms[50]; //jointTransForms[MAX_JOINTS]
uniform mat4 view_Matrix;
uniform mat4 projection_Matrix;
uniform mat4 model_matrix;
vec3 cameraPosition(1.0);
vec3 lightPosition(1.0);
out vec2 tex_cord;
//out vec3 v_normal;
out vec3 v_pos;
out vec4 bw;
out vec3 TangentLightPos;
out vec3 TangentViewPos;
out vec3 TangentFragPos;
void main()
{
bw = vec4(0);
if(int(boneIds.x) == 1)
bw.z = boneIds.x;
mat4 boneTransform = mat4(0.0);
boneTransform += bone_transforms[int(boneIds.x)] * boneWeights.x;
boneTransform += bone_transforms[int(boneIds.y)] * boneWeights.y;
boneTransform += bone_transforms[int(boneIds.z)] * boneWeights.z;
boneTransform += bone_transforms[int(boneIds.w)] * boneWeights.w;
vec4 pos =boneTransform * vec4(position, 1.0);
gl_Position = projection_Matrix * view_Matrix * model_matrix * pos;
//其实就是世界坐标 mesh的position * boneTransform * model_matrix
//但是这里为甚要乘两次 boneTransform就不知道为什么了
//第一次 pos = position*boneTransform
//第二次 v_pos = pos*boneTransform*model_matrix
v_pos = vec3(model_matrix * boneTransform * pos);
tex_cord = texture;
v_normal = mat3(transpose(inverse(model_matrix * boneTransform))) * normal;
vec3 T = normalize(v_normal * tangent);
vec3 B = normalize(v_normal * bitangent);
vec3 N = normalize(v_normal * normal);
mat3 TBN = transpose(inverse(mat3(model_matrix)));
TangentLightPos = TBN * lightPos;
TangentViewPos = TBN * viewPos;
TangentFragPos = TBN * v_pos;
v_normal = normalize(v_normal);
}
fragmentShader
out vec4 color;
uniform sampler2D diff_texture;
uniform sampler2D emission_texture;
uniform sampler2D normal_texture;
uniform float times;
in vec2 tex_cord;
//in vec3 v_normal;
in vec3 v_pos;
in vec4 bw;
in vec3 TangentLightPos;
in vec3 TangentViewPos;
in vec3 TangentFragPos;
//vec3 lightPos = vec3(20.0, 55.0, 13.0);
void main()
{
vec3 normal = texture(normal_texture, tex_cord).rgb;
normal = normalize(normal * 2.0 - 1.0);
vec3 lightDir = normalize(TangentLightPos - TangentViewPos);
float diff = max(dot(normal, lightDir), 0.2);
vec3 dCol = diff * texture(diff_texture, tex_cord).rgb;
vec3 emission_texture = texture(emission_texture, tex_cord + vec2(0.0, time * 0.001)).rgb;
emission_texture = emission_texture * (sin(time) * 0.001 + 0.5) * 2.0;
color = vec4(dCol + emission_texture, 1.0f);
}
LoadedMesh_NM Model_NM::processMesh(aiMesh mesh, const aiScene scene) { std::vector vertices;
std::vector indices;
std::vector textures;
std::vector normalData;