纹理映射与phong照明

时间:2013-10-19 14:41:02

标签: c++ opengl textures phong

我试图将Phong灯光添加到我已经加载纹理网格的场景中。这是我的网格加载类:

#define INVALID_OGL_VALUE 0xFFFFFFFF
#define INVALID_MATERIAL 0xFFFFFFFF
#define SAFE_DELETE(p) if (p) { delete p; p = NULL; }

Mesh::MeshEntry::MeshEntry()
{
    VB = INVALID_OGL_VALUE;
    IB = INVALID_OGL_VALUE;
    NumIndices  = 0;
    MaterialIndex = INVALID_MATERIAL;
};

Mesh::MeshEntry::~MeshEntry()
{
    if (VB != INVALID_OGL_VALUE)
    {
        glDeleteBuffers(1, &VB);
    }

    if (IB != INVALID_OGL_VALUE)
    {
        glDeleteBuffers(1, &IB);
    }
}

void Mesh::MeshEntry::Init(const std::vector<Vertex>& Vertices,
                          const std::vector<unsigned int>& Indices)
{
    NumIndices = Indices.size();

    glGenBuffers(1, &VB);
    glBindBuffer(GL_ARRAY_BUFFER, VB);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * Vertices.size(), &Vertices[0], GL_STATIC_DRAW);

    glGenBuffers(1, &IB);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IB);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * NumIndices, &Indices[0], GL_STATIC_DRAW);
}

Mesh::Mesh()
{
}


Mesh::~Mesh()
{
    Clear();
}


void Mesh::Clear()
{
    for (unsigned int i = 0 ; i < textures_cnt.size() ; i++) {
        SAFE_DELETE(textures_cnt[i]);
    }
}


/*Loads mesh
 *@Filename -   name of the .obj file
 **********************************************************/
bool Mesh::LoadMesh(const std::string& Filename){

    Assimp::Importer Importer;
    bool rc = false;

    //clear previous loaded mesh
    Clear();

    //read file content
    const aiScene* oScene = Importer.ReadFile(Filename.c_str(), aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_FlipUVs );

    if(oScene){

        printf ("  %i animations\n", oScene->mNumAnimations);
        printf ("  %i cameras\n", oScene->mNumCameras);
        printf ("  %i lights\n", oScene->mNumLights);
        printf ("  %i materials\n", oScene->mNumMaterials);
        printf ("  %i meshes\n", oScene->mNumMeshes);
        printf ("  %i textures\n", oScene->mNumTextures);

        submeshes_cnt.resize(oScene->mNumMeshes);
        textures_cnt.resize(oScene->mNumMaterials);

        /*.........Initialize the meshes in the scene one by one...........*/
        for (unsigned int i = 0 ; i < submeshes_cnt.size() ; i++) {

            const aiMesh* paiMesh = oScene->mMeshes[i];
            InitMesh(i, paiMesh);
        }

        // Extract the directory part from the file name
        std::string::size_type SlashIndex = Filename.find_last_of("/");
        std::string Dir;

        if (SlashIndex == std::string::npos) {
            Dir = ".";
        }
        else if (SlashIndex == 0) {
            Dir = "/";
        }
        else {
            Dir = Filename.substr(0, SlashIndex);
        }
        /*.................Initialization of meshes end....................*/



        /*.............Initialize the materials.............................*/
        for(unsigned int i = 0 ; i < oScene->mNumMaterials ; i++) {
            const aiMaterial* pMaterial = oScene->mMaterials[i];

            textures_cnt[i] = NULL;

            if (pMaterial->GetTextureCount(aiTextureType_DIFFUSE) > 0) {
                aiString Path;

                if (pMaterial->GetTexture(aiTextureType_DIFFUSE, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS) {
                    std::string FullPath = Dir + "/" + Path.data;
                    textures_cnt[i] = new Texture(GL_TEXTURE_2D, FullPath.c_str());

                    if (!textures_cnt[i]->Load()) {
                        printf("Error loading texture '%s'\n", FullPath.c_str());
                        delete textures_cnt[i];
                        textures_cnt[i] = NULL;
                        rc = false;
                    }
                    else {
                        printf("Loaded texture '%s'\n", FullPath.c_str());
                    }
                }
            }
        }
        /*.................Initialization of materials end....................*/
    }
    else {
        printf("Error parsing '%s': '%s'\n", Filename.c_str(), Importer.GetErrorString());
    }

    return rc;
}


void Mesh::InitMesh(unsigned int Index, const aiMesh* paiMesh)
{
    submeshes_cnt[Index].MaterialIndex = paiMesh->mMaterialIndex;

    std::vector<Vertex> Vertices;
    std::vector<unsigned int> Indices;

    const aiVector3D Zero3D(0.0f, 0.0f, 0.0f);

    for (unsigned int i = 0 ; i < paiMesh->mNumVertices ; i++) {
        const aiVector3D* pPos      = &(paiMesh->mVertices[i]);
        const aiVector3D* pNormal   = &(paiMesh->mNormals[i]);
        const aiVector3D* pTexCoord = paiMesh->HasTextureCoords(0) ? &(paiMesh->mTextureCoords[0][i]) : &Zero3D;

        Vertex v(Vector3f(pPos->x, pPos->y, pPos->z),
                 Vector2f(pTexCoord->x, pTexCoord->y),
                 Vector3f(pNormal->x, pNormal->y, pNormal->z));

        Vertices.push_back(v);
    }

    for (unsigned int i = 0 ; i < paiMesh->mNumFaces ; i++) {
        const aiFace& Face = paiMesh->mFaces[i];
        assert(Face.mNumIndices == 3);
        Indices.push_back(Face.mIndices[0]);
        Indices.push_back(Face.mIndices[1]);
        Indices.push_back(Face.mIndices[2]);
    }

    submeshes_cnt[Index].Init(Vertices, Indices);
}

void Mesh::Render(){

    //enable VAOs for vertices, normals, textures
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glEnableVertexAttribArray(2);

    for(unsigned int i = 0 ; i < submeshes_cnt.size() ; i++){

        glBindBuffer(GL_ARRAY_BUFFER, submeshes_cnt[i].VB);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)12);
        glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)20);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, submeshes_cnt[i].IB);

        const unsigned int MaterialIndex = submeshes_cnt[i].MaterialIndex;

        if (MaterialIndex < textures_cnt.size() && textures_cnt[MaterialIndex]) {
            textures_cnt[MaterialIndex]->Bind(GL_TEXTURE0);
        }

        glDrawElements(GL_TRIANGLES, submeshes_cnt[i].NumIndices, GL_UNSIGNED_INT, 0);
    }

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(2);


}

顶点着色器:

#version 420

uniform mat4 camera;
uniform mat4 model;

in vec3 vert;
in vec2 vertTexCoord;

out vec2 fragTexCoord;

void main() {
    // Pass the tex coord straight through to the fragment shader
    fragTexCoord = vertTexCoord;

    // Apply all matrix transformations to vert
    gl_Position = camera * model * vec4(vert, 1);
}

片段着色器:

#version 420

uniform sampler2D tex;

in vec2 fragTexCoord;

out vec4 finalColor;

void main() {
    //note: the texture function was called texture2D in older versions of GLSL
    finalColor = texture(tex, fragTexCoord);
}

这是我得到的: before

但是当我尝试添加phong光照时,当我将法线的属性添加到我的顶点着色器时,这就是我得到的: after

问题出在哪里? 谢谢你的帮助。

//编辑 着色器加载和链接

shprogram::shprogram(const std::vector<shader>& shaders) :
    _object(0)
{
    if(shaders.size() <= 0)
        throw std::runtime_error("No shaders were provided to create the program");

    //create the program object
    _object = glCreateProgram();
    if(_object == 0)
        throw std::runtime_error("glCreateProgram failed");

    //attach all the shaders
    for(unsigned i = 0; i < shaders.size(); ++i)
        glAttachShader(_object, shaders[i].getObject());

    //link the shaders together
    glLinkProgram(_object);

    //detach all the shaders
    for(unsigned i = 0; i < shaders.size(); ++i)
        glDetachShader(_object, shaders[i].getObject());

    //throw exception if linking failed
    GLint status;
    glGetProgramiv(_object, GL_LINK_STATUS, &status);
    if (status == GL_FALSE) {
        std::string msg("Program linking failure: ");

        GLint infoLogLength;
        glGetProgramiv(_object, GL_INFO_LOG_LENGTH, &infoLogLength);
        char* strInfoLog = new char[infoLogLength + 1];
        glGetProgramInfoLog(_object, infoLogLength, NULL, strInfoLog);
        msg += strInfoLog;
        delete[] strInfoLog;

        glDeleteProgram(_object); _object = 0;
        throw std::runtime_error(msg);
    }
}

shprogram::~shprogram() {
    //might be 0 if ctor fails by throwing exception
    if(_object != 0) glDeleteProgram(_object);
}

GLuint shprogram::object() const {
    return _object;
}

void shprogram::use() const {
    glUseProgram(_object);
}

bool shprogram::isInUse() const {
    GLint currentProgram = 0;
    glGetIntegerv(GL_CURRENT_PROGRAM, &currentProgram);
    return (currentProgram == (GLint)_object);
}

void shprogram::stopUsing() const {
    assert(isInUse());
    glUseProgram(0);
}

GLint shprogram::attrib(const GLchar* attribName) const {
    if(!attribName)
        throw std::runtime_error("attribName was NULL");

    GLint attrib = glGetAttribLocation(_object, attribName);
    if(attrib == -1)
        throw std::runtime_error(std::string("Program attribute not found: ") + attribName);

    return attrib;
}

GLint shprogram::uniform(const GLchar* uniformName) const {
    if(!uniformName)
        throw std::runtime_error("uniformName was NULL");

    GLint uniform = glGetUniformLocation(_object, uniformName);
    if(uniform == -1)
        throw std::runtime_error(std::string("Program uniform not found: ") + uniformName);

    return uniform;
}

void shprogram::setUniformMatrix2(const GLchar* name, const GLfloat* v, GLsizei count, GLboolean transpose) {
    assert(isInUse());
    glUniformMatrix2fv(uniform(name), count, transpose, v);
}

void shprogram::setUniformMatrix3(const GLchar* name, const GLfloat* v, GLsizei count, GLboolean transpose) {
    assert(isInUse());
    glUniformMatrix3fv(uniform(name), count, transpose, v);
}

void shprogram::setUniformMatrix4(const GLchar* name, const GLfloat* v, GLsizei count, GLboolean transpose) {
    assert(isInUse());
    glUniformMatrix4fv(uniform(name), count, transpose, v);
}

void shprogram::setUniform(const GLchar* name, const glm::mat2& m, GLboolean transpose) {
    assert(isInUse());
    glUniformMatrix2fv(uniform(name), 1, transpose, glm::value_ptr(m));
}

void shprogram::setUniform(const GLchar* name, const glm::mat3& m, GLboolean transpose) {
    assert(isInUse());
    glUniformMatrix3fv(uniform(name), 1, transpose, glm::value_ptr(m));
}

void shprogram::setUniform(const GLchar* name, const glm::mat4& m, GLboolean transpose) {
    assert(isInUse());
    glUniformMatrix4fv(uniform(name), 1, transpose, glm::value_ptr(m));
}

void shprogram::setUniform(const GLchar* uniformName, const glm::vec3& v) {
    setUniform3v(uniformName, glm::value_ptr(v));
}

void shprogram::setUniform(const GLchar* uniformName, const glm::vec4& v) {
    setUniform4v(uniformName, glm::value_ptr(v));
}

设置制服

//bind shader program
gProgram->use();

//set the "camera" uniform
gProgram->setUniform("camera", gCamera.matrix());

//set the "model" uniform in the vertex shader, based on the gDegreesRotated global
gProgram->setUniform("model", glm::rotate(glm::mat4(), 150.0f ,glm::vec3(0,1,0)));


gProgram->setUniform("light.position", gLight.position);
gProgram->setUniform("light.intensities", gLight.intensities);

1 个答案:

答案 0 :(得分:1)

您既不明确地在着色器源中设置属性位置,也不会在链接着色器之前绑定它们,也不会查询它们。 GL可以为任何活动的输入属性自由使用任何有效的属性索引。

你只是假设 0是位置,1是texcoord,2是正常的。对于position + texcoord案例,它可能会偶然起作用,但是当你添加法线时,索引可能会混淆。在GLSL代码中使用layout(location=...)(有关详细信息,请参阅GL_ARB_explicit_attrib_location),或使用glBindAttribLocation()指定所需的映射。