LeeMcQueen / GameDemo

Demo
0 stars 0 forks source link

Assimp normalMap #35

Open LeeMcQueen opened 2 years ago

LeeMcQueen commented 2 years ago

LoadedMesh_NM Model_NM::processMesh(aiMesh mesh, const aiScene scene) { std::vector vertices; std::vector indices; std::vector textures; std::vector normalData;

for (unsigned int i = 0; i < mesh->mNumVertices; ++i)
{
    Vertex vertex;
    vertex.position.x = mesh->mVertices[i].x;
    vertex.position.y = mesh->mVertices[i].y;
    vertex.position.z = mesh->mVertices[i].z;

    vertex.normal.x = mesh->mNormals[i].x;
    vertex.normal.y = mesh->mNormals[i].y;
    vertex.normal.z = mesh->mNormals[i].z;

    //check if model has texture coordinates
    if (mesh->mTextureCoords[0])
    {
        vertex.textureCoords.x = mesh->mTextureCoords[0][i].x;
        vertex.textureCoords.y = mesh->mTextureCoords[0][i].y;

    }
    else
    {
        vertex.textureCoords = { 0.f, 0.f };
    }

    NormalData nmData;
    nmData.tangent.x = mesh->mTangents[i].x;
    nmData.tangent.y = mesh->mTangents[i].y;
    nmData.tangent.z = mesh->mTangents[i].z;
    nmData.tangent = glm::normalize(nmData.tangent);

    nmData.bitangent.x = mesh->mBitangents[i].x;
    nmData.bitangent.y = mesh->mBitangents[i].y;
    nmData.bitangent.z = mesh->mBitangents[i].z;
    nmData.bitangent = glm::normalize(nmData.bitangent);

    vertices.push_back(vertex);
    normalData.push_back(nmData);

    //glm::vec3 calcNormal = glm::normalize(glm::cross(nmData.tangent, nmData.bitangent));
    //float normalMatch = glm::dot(calcNormal, vertex.normal);
    //std::cout << normalMatch << std::endl;
}
LeeMcQueen commented 2 years ago

往Vertex类 加入 1.glm::vec3 tangent 2.glm::vec3 bitangent

LeeMcQueen commented 2 years ago

Vertex.h

pragma once

include <gtx\transform.hpp>

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; };

LeeMcQueen commented 2 years ago

void AnimaModelLoader::loadAssimpModel(const aiScene scene, aiMesh mesh, std::vector &verticesOutput, std::vector &indicesOutput, Bone &skeletonOutput, unsigned int &nBoneCount){

//返回参数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);

}

LeeMcQueen commented 2 years ago

main.cpp createvertexArray函数

unsigned int createVertexArray(std::vector &vertices, std::vector indices) { unsigned int vao = 0; unsigned int vbo = 0; unsigned int ebo = 0;

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;

}

LeeMcQueen commented 2 years ago

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");
LeeMcQueen commented 2 years ago

vertexShader

version 330 core

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);
}
LeeMcQueen commented 2 years ago

fragmentShader

version 330 core

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);
}