Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Page 1 of 2 12 LastLast
Results 1 to 10 of 21

Thread: Texture doesn't appear properly

Hybrid View

  1. #1
    Junior Member Newbie
    Join Date
    Dec 2012
    Posts
    8

    Texture doesn't appear properly

    Hello,

    This problem may not be related directly to shaders, but I don't even know exactly where the problem is. Since I moved from fixed pipeline to shaders, the texture appears wrong. Here is a screenshot about it:


    (The model has 2 planes which appears right, only the texture is wrong)

    Some information about my code: I wrote an exporter for Blender which creates a binary model file. I wrote a loader for it. The model file can handle multiple objects (meshes) in one model. Each object has different texture. The first version uses VBO without shaders and works pretty well. After that I studied how to use shaders I changed my code based on this tutorial: http://www.opengl-tutorial.org/begin...textured-cube/

    I think the main problem is that I don't know the concept of drawing a complex model with multiple object and texture. Most of the articles and tutorials shows how to draw one object.

    Here is my drawing function. I call this in the main loop after the keyboard handling and camera update.


    Code :
    void CModel::draw(glm::mat4 &MVP)
    {
        glActiveTexture(GL_TEXTURE0);
     
        for(unsigned int i=0; i<m_numObjects; i++)
        {
            glUseProgram(m_programID);
     
            unsigned int matrixUniform  = glGetUniformLocation(m_programID, "MVP");
            unsigned int textureUniform = glGetUniformLocation(m_programID, "myTextureSampler");
     
            glUniformMatrix4fv(matrixUniform, 1, GL_FALSE, &MVP[0][0]);
     
            glBindTexture(GL_TEXTURE_2D, m_textureIDs[i]);
     
            glUniform1i(textureUniform, 0);
     
            glBindBuffer(GL_ARRAY_BUFFER, m_bufferIDs[i]);
            // vertices
            glEnableVertexAttribArray(0);
            glVertexAttribPointer(
                    0,                  // must match the layout in the shader.
                    3,                  // size
                    GL_FLOAT,           // type
                    GL_FALSE,           // normalized?
                    sizeof(float)*8,    // stride
                    (void*)0            // array buffer offset
            );
     
            // UVs
            glEnableVertexAttribArray(1);
            glVertexAttribPointer(
                    1,
                    2,
                    GL_FLOAT,
                    GL_FALSE,
                    sizeof(float)*8,
                    (void*)6
            );
     
            glDrawArrays(GL_TRIANGLES, 0, m_numElements[i]);
     
            glDisableVertexAttribArray(0);
            glDisableVertexAttribArray(1);
     
            glUseProgram(0);
        }
     
        //glDisable(GL_TEXTURE_2D);
    }

    The data array which is sent to the buffer has this format: [vertex.x, vertex.y, vertex.z normal.x, normal.y, normal.z, textureCoord.u, textureCoord.v, ...]

    The vertex and fragment shaders worked in the first version. Here are the shaders, but I don't think it should be changed in any way.

    Code :
    #version 330 core
     
    // Input vertex data, different for all executions of this shader.
    layout(location = 0) in vec3 vertexPosition_modelspace;
    layout(location = 1) in vec2 vertexUV;
     
    // Output data ; will be interpolated for each fragment.
    out vec2 UV;
     
    // Values that stay constant for the whole mesh.
    uniform mat4 MVP;
     
    void main(){
     
    	// Output position of the vertex, in clip space : MVP * position
    	gl_Position =  MVP * vec4(vertexPosition_modelspace,1);
     
    	// UV of the vertex. No special space for this one.
    	UV = vertexUV;
    }

    Code :
    #version 330 core
     
    // Interpolated values from the vertex shaders
    in vec2 UV;
     
    // Ouput data
    out vec3 color;
     
    // Values that stay constant for the whole mesh.
    uniform sampler2D myTextureSampler;
     
    void main(){
     
    	// Output color = color of the texture at the specified UV
    	color = texture2D( myTextureSampler, UV ).rgb;
    }

  2. #2
    Junior Member Newbie
    Join Date
    Dec 2012
    Posts
    12
    As you are using 2 textures, it's better to use 2 texture units, i.e. GL_TEXTURE0, and GL_TEXTURE1.

  3. #3
    Junior Member Newbie
    Join Date
    Dec 2012
    Posts
    8
    Do you say that instead of using glActiveTexture(GL_TEXTURE0) before the loop I should call it inside the loop before glBindTexture and in each loop set different unit?
    I tried it but it doesn't work or I just misunderstood you.

  4. #4
    Junior Member Newbie
    Join Date
    Dec 2012
    Posts
    6
    pleeeeeeeaaaaaaaaaaaaase i neeed help in my hw pleas help we take simple code with our dr but he gave us a complex one to put comment on it and describe work each function

  5. #5
    Junior Member Newbie
    Join Date
    Dec 2012
    Posts
    12
    I did a test, which shows that you could just use one texture unit, such as GL_TEXTURE0.

    and it seems quite a few things are not quite right in your source code.
    Last edited by Power2012; 12-05-2012 at 12:54 PM.

  6. #6
    Junior Member Newbie
    Join Date
    Dec 2012
    Posts
    8
    Quote Originally Posted by Power2012 View Post
    I did a test, which shows that you could just use one texture unit, such as GL_TEXTURE0.

    and it seems quite a few things are not quite right in your source code.
    What is wrong exactly? Here is the whole class with the init method to get a clearer picture of my code:

    Code :
    #include "global.h"
    #include "CModel.h"
    #include "CModelLoader.h"
    #include "CShaderLoader.h"
     
    CModel::CModel(){}
     
    CModel::~CModel()
    {
        // TODO free memory
    }
     
    /** @brief Load mbm file
      *
      * @fileName: mdm model file name we want to load and draw
      */
    void CModel::init(char *fileName)
    {
        CModelLoader   loader;
        CShaderLoader  shaders;
     
        loader.loadData(fileName);
     
        loader.createDataArray( m_dataArray,
                                m_dataArraySizes,
                                m_numObjects,
                                m_numElements,
                                m_textureIDs );
     
        glGenVertexArrays(1, &m_vertexArrayID);
        glBindVertexArray(m_vertexArrayID);
     
        glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);
     
        m_programID      = shaders.loadShaders("vertexshader.vert", "fragmentshader.frag");
     
        //m_matrixUniform  = glGetUniformLocation(m_programID, "MVP");
        //m_textureUniform = glGetUniformLocation(m_programID, "myTextureSampler");
     
        m_bufferIDs      = new unsigned int[m_numObjects];
     
        glGenBuffers(m_numObjects, m_bufferIDs);
        for(unsigned int i=0; i<m_numObjects; i++)
        {
            glBindBuffer(GL_ARRAY_BUFFER, m_bufferIDs[i]);
            glBufferData(GL_ARRAY_BUFFER, sizeof(float)*m_dataArraySizes[i], m_dataArray[i], GL_STATIC_DRAW);
            glBindBuffer(GL_ARRAY_BUFFER, 0);
        }
     
    }
     
    void CModel::draw(glm::mat4 &MVP)
    {
        glActiveTexture(GL_TEXTURE0);
     
        for(unsigned int i=0; i<m_numObjects; i++)
        {
            glUseProgram(m_programID);
     
            unsigned int matrixUniform  = glGetUniformLocation(m_programID, "MVP");
            unsigned int textureUniform = glGetUniformLocation(m_programID, "myTextureSampler");
     
            glUniformMatrix4fv(matrixUniform, 1, GL_FALSE, &MVP[0][0]);
     
            glBindTexture(GL_TEXTURE_2D, m_textureIDs[i]);
     
            glUniform1i(textureUniform, 0);
     
            glBindBuffer(GL_ARRAY_BUFFER, m_bufferIDs[i]);
            // vertices
            glEnableVertexAttribArray(0);
            glVertexAttribPointer(
                    0,                  // must match the layout in the shader.
                    3,                  // size
                    GL_FLOAT,           // type
                    GL_FALSE,           // normalized?
                    sizeof(float)*8,    // stride
                    (void*)0            // array buffer offset
            );
     
            // UVs
            glEnableVertexAttribArray(1);
            glVertexAttribPointer(
                    1,
                    2,
                    GL_FLOAT,
                    GL_FALSE,
                    sizeof(float)*8,
                    (void*)6
            );
     
            glDrawArrays(GL_TRIANGLES, 0, m_numElements[i]);
     
            glDisableVertexAttribArray(0);
            glDisableVertexAttribArray(1);
     
            glUseProgram(0);
        }
     
        //glDisable(GL_TEXTURE_2D);
    }
     
        glUseProgram(0);
        //glDisable(GL_TEXTURE_2D);
    }

  7. #7
    Junior Member Newbie
    Join Date
    Dec 2012
    Posts
    12
    could you try to draw only the first object please, to do so just modify the for loop to for(unsigned int i=0; i<1; i++), see what if you get the texture right or not.

  8. #8
    Junior Member Newbie
    Join Date
    Dec 2012
    Posts
    8
    Finally I solved it. The problem was that I used one array for vertices, normals and texture coordinates instead of storing in separate arrays and bind them separately.

  9. #9
    Junior Member Newbie
    Join Date
    Dec 2012
    Posts
    6
    please need help

  10. #10
    Junior Member Newbie
    Join Date
    Dec 2012
    Posts
    8
    Quote Originally Posted by safaaza View Post
    please need help
    You should open a new thread and describe exactly what is you problem, copy some sample from the code. We can't find out what is your home work, and it would be great to not spoil my thread.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •