Source

dbsdev / sources / opengl2_samples / test7_simplerenderer / GLMaterial.cpp

Full commit
#include <map>

#include "glfw_utils.h" // just to retrieve opengl symbols without conflicting with the include order
#include "stb_image.h"

#include "logger.h"

#include "GLShader.h"
#include "GLMaterial.h"


// ////////////// //
// local function //
// ////////////// //

namespace 
{

    // texture map
    std::map<std::string,GLuint> textures;


    // get or create an image, given its filename
    static GLuint getOrCreateImage(const std::string &name)
    {
        // check if already present
        if(textures.count(name)>0)
            return textures[name];

        // read image from file
        printf("loading Texture from file %s\n",name.c_str());
        int  w,h,n;
        unsigned char *data = stbi_load(name.c_str(), &w, &h, &n, 4);   // force rgba
        if (!data)
            return 0;
        stbi_flip_y(data,w,h,4);

        // create and load texture
        GLuint tid=0;
        glGenTextures(1, &tid);
        glBindTexture(GL_TEXTURE_2D, tid);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 
                                    0, GL_RGBA, GL_UNSIGNED_BYTE, data); // Texture specification
        glGenerateMipmap(GL_TEXTURE_2D);  //Generate mipmaps
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

        // add anisotropic filtering
        /// \warning NOT SAFE!!! no check if the extension is available
        GLfloat fLargest;
        glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest);
        fLargest = fLargest>4.0f ? 4.0f : fLargest; // limit to 4 the anisotropic filtering
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fLargest);

        stbi_image_free(data);

        // add to map and return 
        textures[name]=tid;

        printf("created Texture from file %s, with id=%u\n",name.c_str(),tid);
        return tid;
    }




}




// initialize the current material: 
// performa all the needed initializations here
bool initializeMaterial( GLMaterial *mat )
{
    // if invalid material: skip
    if (!mat)
    {
        logMessage("invalid material. skip\n");
        return false;        
    }
    if (!mat->shader)
    {
        logMessage("no shader associated to current material. skip\n");
        return false;        
    }

    // init material textures and uniforms
    for (unsigned int i=0; i<GLMaterial::evTextureTypeCount; i++)
    {
        if (mat->textures[i]!="")
        {
            mat->textureIds[i]       = getOrCreateImage(mat->textures[i]);
            mat->textureUniforms[i]  = glGetUniformLocation(mat->shader->programId, textureUniformNames[i]);
        }
    }

    return true;

}


// set the given material as the current 
bool applyMaterial( const GLMaterial *mat )
{
    // if invalid material: skip
    if (!mat)
    {
        logMessage("invalid material. skip\n");
        return false;        
    }
    // bind textures and uniforms
    unsigned int idx=0;
    for (unsigned int i=0; i<GLMaterial::evTextureTypeCount; i++)
    {
        if (mat->textures[i]!="")
        {
            glActiveTexture(GL_TEXTURE0+idx);
            glBindTexture(GL_TEXTURE_2D, mat->textureIds[i]);
            glUniform1i(mat->textureUniforms[i], idx);  // associate the current texture to the named uniform
            idx++;
        }
    }

    return true;

}