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 15

Thread: Applying texture coordinates with shaders

  1. #1
    Junior Member Newbie
    Join Date
    Apr 2011
    Posts
    8

    Applying texture coordinates with shaders

    Can I use glTexCoordPointer to specify texture coordinates for my shaders, or do I need to pass them in some other way? My program works fine aside from applying the texture. I have excluded what I believe to be irrelevant code in the interests of brevity.

    I thought I should be able to do something like this:

    Code :
    glTexCoordPointer(2, GL_FLOAT, 0, tcp); 
    //where tcp is a pointer to an array of GLfloats containing my texcoords
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); //not sure about this line

    And in my draw function:

    Code :
    glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
      glVertexAttribPointer(
    			position,                         /* attribute */
    			3,                                /* size */
    			GL_FLOAT,                         /* type */
    			GL_FALSE,                         /* normalized? */
    			0,                                /* stride */
    			(void*)0                          /* array buffer offset */
    			);
      glEnableVertexAttribArray(position);
     
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buffer);
     
     
      glDrawElements(
    		 GL_TRIANGLES,
    		 3 * g_total_tris,
    		 GL_UNSIGNED_SHORT,
    		 (GLvoid*) 0
    		 );
     
      glDisableVertexAttribArray(position);


    and then in the vertex shader something like

    Code :
    varying vec2 tex_coord;
     
    void main()
    {
    	tex_coord = gl_MultiTexCoord0.st;
    }

    and in the fragment shader

    Code :
    varying vec2 tex_coord;
    uniform sampler2D tex;
    void main()
    {
    gl_FragColor = gl_Color * texture2D(tex, tex_coord);
    }

    However, in debugging it appears that using texture2D(tex, tex_coord) or texture2D(tex, gl_TexCoord[0].st) in gl_FragColor will always paint my object black. The texture is definitely being sampled correctly, because I can manually specify an arbitrary vec2 value for the texcoord and paint the entire object a colour from one part of my texture. Should I be passing the texture coordinates into the shader using a uniform variable? Is the problem that the shader overrides the texcoordspointer function?

    Help is greatly appreciated, as I have spent hours and hours reading through the red book, opengl.org and random internet tutorials to find an answer.

  2. #2
    Member Regular Contributor
    Join Date
    Apr 2009
    Posts
    258

    Re: Applying texture coordinates with shaders

    You appear to be doing everything correctly (at least i cant see a problem here).
    Here are few tips:
    1. Verify that tex_coord is good in frag shader (output it to gl_FragColor directly, see whats there).
    2. glTexEnvf does nothing for you, its fixed-function only and you use shaders
    3. Post real code if possible (your vertex shader is pseudocode)
    4. You may want to pass your texcoords as generic attributes (as you have done with position) - this will simplify your code (but probably wont help with your issue)

  3. #3
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,714

    Re: Applying texture coordinates with shaders

    Wait: are you combining buffer objects (your positions via glVertexAttribPointer) with non-buffer object arrays (your texture coordinates)? If so, don't do that. It may work, but it's really bad form.

    Either all of your attributes should come from buffer objects or none of them should.

  4. #4
    Junior Member Newbie
    Join Date
    Apr 2011
    Posts
    8

    Re: Applying texture coordinates with shaders

    Well, I managed to get the texture mapped properly (it still didn't look quite right, but I think that was more an issue with clipping and vertex transformation), but I did it using the 'really bad form' way, so I obviously want to do it the right way.


    Okay, so I've tried putting the texture coordinates in a buffer and passing them in as follows:

    Code :
    GLfloat *texCoords_array;
    int texCoords_array_size;
     
    Code to set size of array and fill  with tex coords
     
     
    GLuint texCoord_buffer;
    texCoord_buffer = glGetAttribLocation(program, "texCoord_buffer");
     
     
    glGenBuffers(1, &texCoord_buffer);
        glBindBuffer(GL_ARRAY_BUFFER, texCoord_buffer);
        glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * texCoords_array_size, texCoords_array, GL_STATIC_DRAW);
     
     
    glBindBuffer(GL_ARRAY_BUFFER, texCoord_buffer);
      glVertexAttribPointer(
      			texCoord_buffer,                        /* attribute */
      			2,                                /* size */
      			GL_FLOAT,                         /* type */
      			GL_FALSE,                         /* normalized? */
      			0,                                /* stride */
      			(void*)0                          /* array buffer offset */
      			);
        glEnableVertexAttribArray(texCoord_buffer);
     
    glDrawElements(
    		 GL_TRIANGLES,
    		 3 * g_total_tris,
    		 GL_UNSIGNED_SHORT,
    		 (GLvoid*) 0
    		 );
     
      glDisableVertexAttribArray(position);
      glDisableVertexAttribArray(texCoord_buffer);

    and in the vertex shader:

    Code :
    attribute vec2 texCoord_buffer;
    varying vec2 tex_coord;
     
    void main() {
     
    tex_coord[0] = texCoord_buffer[0];
    tex_coord[1] = texCoord_buffer[1]; 
     
    }

    I would have thought moving the coordinates from texCoord_buffer into tex_coord would be redundant, but if I use texCoord_buffer in the fragment shader I just get a black model.

    and the fragment shader:

    Code :
     
    varying vec2 tex_coord;
     
    void main() {
    gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0) * texture2D(tex, tex_coord);
    }

    I presume I'm doing something wrong with getting the buffer into the shader. Should I be using glTexCoordPointer at all? How do the shaders loop through array buffer objects?

  5. #5
    Member Regular Contributor
    Join Date
    Apr 2009
    Posts
    258

    Re: Applying texture coordinates with shaders

    Quote Originally Posted by JimJones
    I would have thought moving the coordinates from texCoord_buffer into tex_coord would be redundant
    Why would you think so?

    Quote Originally Posted by JimJones
    but if I use texCoord_buffer in the fragment shader I just get a black model
    texCoord_buffer is an attribute - its accessible only in vertex shader.

    Quote Originally Posted by JimJones
    I presume I'm doing something wrong with getting the buffer into the shader. Should I be using glTexCoordPointer at all? How do the shaders loop through array buffer objects?
    You appear to be doing everything correctly (at least in the code you shown), and nope, dont use glTexCoordPointer.

  6. #6
    Super Moderator OpenGL Guru
    Join Date
    Feb 2000
    Location
    Montreal, Canada
    Posts
    4,421

    Re: Applying texture coordinates with shaders

    You can simplify this

    tex_coord[0] = texCoord_buffer[0];
    tex_coord[1] = texCoord_buffer[1];

    into this

    tex_coord = texCoord_buffer;

    because both are of type vec2. It would be only 1 MOV instruction.

    Here you go
    http://www.opengl.org/wiki/GLSL_:_co...se_the_Swizzle
    ------------------------------
    Sig: http://glhlib.sourceforge.net
    an open source GLU replacement library. Much more modern than GLU.
    float matrix[16], inverse_matrix[16];
    glhLoadIdentityf2(matrix);
    glhTranslatef2(matrix, 0.0, 0.0, 5.0);
    glhRotateAboutXf2(matrix, angleInRadians);
    glhScalef2(matrix, 1.0, 1.0, -1.0);
    glhQuickInvertMatrixf2(matrix, inverse_matrix);
    glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
    glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);

  7. #7
    Junior Member Newbie
    Join Date
    Apr 2011
    Posts
    8

    Re: Applying texture coordinates with shaders

    Been hacking at this for ages now and still can't get it to work using a texcoord buffer, so going to post more code:

    First the program makes resources as such:

    Code :
    int Draw::make_resources()
    {
        vertex_buffer = make_buffer(
            GL_ARRAY_BUFFER,
            g_vertex_buffer_data,
            3 * sizeof(GLfloat) * g_total_verts
        );
        element_buffer = make_buffer(
            GL_ELEMENT_ARRAY_BUFFER,
            g_element_buffer_data,
            3 *  sizeof(GLushort) * g_total_tris
            );
            for (int i =0; i < g_texCoords_array_size; i += 2)
            {
            	g_texCoords_array[i+1] = 1.0 - (g_texCoords_array[i+1]); //t value must be flipped to get UV mapping
            }
     
     
     
    texCoord_buffer = make_buffer(
    		GL_ARRAY_BUFFER,
    		g_texCoords_array,
    		sizeof(GLfloat) * g_texCoords_array_size
    		);
     
     
        //Make textures here
        g_textures[0] = read_texture(g_tex);
        if (g_textures[0] == 0)
        	return 0;
        glGenTextures(1, &amp;tex_id);
     
        vertex_shader = make_shader(
            GL_VERTEX_SHADER,
            "src/hello-gl.v.glsl"
        );
        if (vertex_shader == 0)
            return 0;
     
        fragment_shader = make_shader(
            GL_FRAGMENT_SHADER,
            "src/hello-gl.f.glsl"
        );
        if (fragment_shader == 0)
            return 0;
     
        program = make_program(vertex_shader, fragment_shader);
        if (program == 0)
            return 0;
     
     
        //shader variables
        position = glGetAttribLocation(program, "position");
        //texCoord_buffer = glGetAttribLocation(program, "texCoord_buffer");
        rotate_x = glGetUniformLocation(program, "rotate_x_theta");
        camera_uniform = glGetUniformLocation(program, "camera");
        GLint texSampler;
        texSampler = glGetUniformLocation(program, "tex");
        glUniform1i(texSampler, 1);
        return 1;
    }

    That gets executed from the class constructor. Then the draw function is called 60 times per second in an SDL loop:

    Code :
    void Draw::draw() {
      glUseProgram(program);
     
      glUniform1f(rotate_x, rotate_x_theta++);
     
     
      float * camera = Camera::getInstance().getCameraMat();
      glUniformMatrix4fv(camera_uniform, 1, false, camera);
     
      glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
     
      glVertexAttribPointer(
    			position,                         /* attribute */
    			3,                                /* size */
    			GL_FLOAT,                         /* type */
    			GL_FALSE,                         /* normalized? */
    			0,                                /* stride */
    			(void*)0                          /* array buffer offset */
    			);
     
      glEnableVertexAttribArray(position);
     
      glBindBuffer(GL_ARRAY_BUFFER, texCoord_buffer);
      glVertexAttribPointer(
      			texCoord_buffer,                        /* attribute */
      			2,                                /* size */
      			GL_FLOAT,                         /* type */
      			GL_FALSE,                         /* normalized? */
      			0,                                /* stride */
      			(void*)0                          /* array buffer offset */
      			);
        glEnableVertexAttribArray(texCoord_buffer);
     
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buffer);
     
     
      glDrawElements(
    		 GL_TRIANGLES,
    		 3 * g_total_tris,
    		 GL_UNSIGNED_SHORT,
    		 (GLvoid*) 0
    		 );
     
      glDisableVertexAttribArray(position);
      glDisableVertexAttribArray(texCoord_buffer);
    }

    Vertex shader:
    Code :
    #version 110
     
    attribute vec3 position;
    attribute vec2 texCoord_buffer;
    uniform float rotate_x_theta;
    uniform mat4 camera;
    varying vec2 tex_coord;
    varying vec4 frag_colour;
     
    mat4 view_frustum(
        float angle_of_view,
        float aspect_ratio,
        float z_near,
        float z_far
    ) {
        return mat4(
            vec4(1.0/tan(angle_of_view), 0.0, 0.0, 0.0),
            vec4(0.0, aspect_ratio/tan(angle_of_view), 0.0, 0.0),
            vec4(0.0, 0.0, (z_far+z_near)/(z_far-z_near), 1.0),
            vec4(0.0, 0.0, -2.0*z_far*z_near/(z_far-z_near), 0.0)
        );
    }
     
    mat4 translate(float x, float y, float z)
    {
        return mat4(
            vec4(1.0, 0.0, 0.0, 0.0),
            vec4(0.0, 1.0, 0.0, 0.0),
            vec4(0.0, 0.0, 1.0, 0.0),
            vec4(x, y, z, 1.0)
        );
    }
     
    mat4 rotate_x(float theta)
    {
        return mat4(
            vec4(1.0, 0.0, 0.0, 0.0),
            vec4(0.0, cos(theta), sin(theta), 0.0),
            vec4(0.0, -sin(theta), cos(theta), 0.0),
            vec4(0.0, 0.0, 0.0, 1.0)
        );
    }
     
    void main()
    {
        gl_Position = view_frustum(radians(45.0), 4.0/3.0, 0.5, 100.0)
        		* translate(0.0, 0.0, 50.0)
    		* rotate_x(radians(rotate_x_theta))
        		* vec4(position.x, position.y, position.z, 1.0);
        		tex_coord = texCoord_buffer;
    }

    Fragment shader:
    Code :
    #version 110
     
    uniform sampler2D tex;
    varying vec2 tex_coord;
     
    void main()
    {
     vec2 st;
     
     st[0] = 0.1674 * 0.33927;
     st[1] = 0.1648 * 1.1;
    gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0) * texture2D(tex, tex_coord);
    }

    With this code, my model is drawn, but it is all the same colour - if I replace tex_coord with st in the gl_FragColor line of the fragment shader it changes the colour of the model. So it would appear that it is reading reading the texture, but applying the same texture coordinate to every vertex. Alternatively, if I uncomment the line
    Code :
    texCoord_buffer = glGetAttribLocation(program, "texCoord_buffer");
    at the end of the make_resources function, the model is textured with a mixture of brown and orange (and maybe black?) as follows:



    My (probably uneducated) guess is that I'm screwing something up with the buffer and it's only reading a single texture coordinate or some garbage memory.

    Help still greatly appreciated.

  8. #8
    Junior Member Newbie
    Join Date
    Apr 2011
    Posts
    8

    Re: Applying texture coordinates with shaders

    Wow, didn't actually include what the make_buffer function does. Here it is:

    Code :
    GLuint Draw::make_buffer(
        GLenum target,
        const void *buffer_data,
        GLsizei buffer_size
    ) {
     
    	cout << "make_buffer" << endl;
        GLuint buffer;
        glGenBuffers(1, &amp;buffer);
        cout << "done make" << endl;
        glBindBuffer(target, buffer);
        glBufferData(target, buffer_size, buffer_data, GL_STATIC_DRAW);
     
        return buffer;
    }

    Still struggling to figure this out. Don't know what else to try at this point. Please help.

  9. #9
    Junior Member Newbie
    Join Date
    Apr 2011
    Posts
    8

    Re: Applying texture coordinates with shaders

    Wrote some code to move and rotate the model around and came upon this:




    You can see the entirety of the texture mapped to a small section of the model. This is only visible up close and is found in several parts of the model. The edges of the square texture also appear to be stretched out across the model in some parts. If I don't include the lines
    Code :
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    Then the single texture is mapped repeatedly across the whole model.

  10. #10
    Super Moderator OpenGL Lord
    Join Date
    Dec 2003
    Location
    Grenoble - France
    Posts
    5,655

    Re: Applying texture coordinates with shaders

    Your texture coordinates seem to be way off.
    They should be within the [0;1] range.
    Add some traces to verify how you specify texcoords.

Posting Permissions

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