0
\$\begingroup\$

VBO cube on the right, two adjacent immediate-mode cubes on the left

I'm using JOGL and I'm trying to render a textured VBO cube with glDrawArrays. The cube renders, but the texture is stretched and stripy as seen in the picture above.

It seams that changing my texture coordinate array has no effect, and perhaps the same with my shaders, I couldn't really tell.

I've tried using different methods for my texture coordinate pointers and switching up the parameters in glBufferData but to no avail.

The biggest difference is when I mess with my texture pointer parameters (glTexCoordPointer()). When I change those numbers, the streaks go in different directions, but I have yet to find any reason behind it, and I'm not sure if more fussing with that will solve my problem

EDIT: I'm pretty sure that I am establishing my uniforms wrongly. My problem is that I don't know what I should set them too. I was previously using immediate mode for lighting and materials. Also, possibly because my uniforms are wrong, I can't bind the shaders correctly (or what I think is correct) without the program crashing.

initVBO is called once, and drawCubeVBO is called every frame

public void loadTexture(GL2 gl) {
    // Load texture from image
    try {
        // Create a OpenGL Texture object from (URL, mipmap, file suffix)
        // Use URL so that can read from JAR and disk file.
        texture = TextureIO.newTexture(getClass().getClassLoader()
                .getResource(textureFileName), // relative to project root
                false, textureFileType);

        texture.setTexParameteri(gl, GL2.GL_TEXTURE_MIN_FILTER,
                GL2.GL_LINEAR);
        texture.setTexParameteri(gl, GL2.GL_TEXTURE_MAG_FILTER,
                GL2.GL_LINEAR);
        texture.setTexParameteri(gl, GL2.GL_TEXTURE_WRAP_S,
                GL2.GL_CLAMP_TO_EDGE);
        texture.setTexParameteri(gl, GL2.GL_TEXTURE_WRAP_T,
                GL2.GL_CLAMP_TO_EDGE);

        // Texture image flips vertically. Shall use TextureCoords class to
        // retrieve
        // the top, bottom, left and right coordinates, instead of using
        // 0.0f and 1.0f.
        TextureCoords textureCoords = texture.getImageTexCoords();

        textureTop = textureCoords.top();
        textureBottom = textureCoords.bottom();
        textureLeft = textureCoords.left();
        textureRight = textureCoords.right();

        } catch (GLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private FloatBuffer vertices;
    // private ShortBuffer indices;
    private int VBOVertices;
    // private int VBOIndices;
    float x = 1f; // the length/width/height of the cube

    public void initVBO(GL2 gl, String textureFileName, String textureFileType) {

        // cube
        // ///////////////////////////////////////////////////////////////////////
        // v6----- v5
        // / |      /|
        // v1------v0|
        // | |     | |
        // | |v7---|-|v4
        // |/      |/
        // v2------v3

        // vertex coords array for glDrawArrays()
        // =====================================
        // A cube has 6 sides and each side has 2 triangles, therefore, a cube
        // consists
        // of 36 vertices (6 sides * 2 tris * 3 vertices = 36 vertices). And,
        // each
        // vertex is 3 components (x,y,z) of floats, therefore, the size of
        // vertex
        // array is 108 floats (36 * 3 = 108).

        float[] vertexArray = { 
                x, x, x, -x, x, x, -x, -x, x, // v0-v1-v2 (front)
                -x, -x, x, x, -x, x, x, x, x, // v2-v3-v0

                x, x, x, x, -x, x, x, -x, -x, // v0-v3-v4 (right)
                x, -x, -x, x, x, -x, x, x, x, // v4-v5-v0

                x, x, x, x, x, -x, -x, x, -x, // v0-v5-v6 (top)
                -x, x, -x, -x, x, x, x, x, x, // v6-v1-v0

                -x, x, x, -x, x, -x, -x, -x, -x, // v1-v6-v7 (left)
                -x, -x, -x, -x, -x, x, -x, x, x, // v7-v2-v1

                -x, -x, -x, x, -x, -x, x, -x, x, // v7-v4-v3 (bottom)
                x, -x, x, -x, -x, x, -x, -x, -x, // v3-v2-v7

                x, -x, -x, -x, -x, -x, -x, x, -x, // v4-v7-v6 (back)
                -x, x, -x, x, x, -x, x, -x, -x }; // v6-v5-v4

        vertices = Buffers.newDirectFloatBuffer(vertexArray.length);
        vertices.put(vertexArray);
        vertices.flip();

        this.textureFileName = textureFileName;
        this.textureFileType = textureFileType;
        loadTexture(gl);
        texture.enable(gl);
        gl.glEnable(GL2.GL_TEXTURE_2D);

        float[] textureArray = { 0, 0, 1, 0, 0, 1,

        1, 1, 1, 0, 0, 1 };

        FloatBuffer textureData = Buffers.newDirectFloatBuffer(12);
        // textureData.put(textureTop);
        // textureData.put(textureBottom);
        // textureData.put(textureRight);
        // textureData.put(textureLeft);
        textureData.put(textureArray);
        // textureData.order();
        textureData.flip();

        int[] temp = new int[4];
        gl.glGenBuffers(3, temp, 0);

        VBOVertices = temp[0];
        gl.glBindBuffer(GL.GL_ARRAY_BUFFER, VBOVertices);
        gl.glBufferData(GL.GL_ARRAY_BUFFER, vertices.capacity()
                * Buffers.SIZEOF_FLOAT, vertices, GL.GL_STATIC_DRAW);
        gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);

        vboTextureCoordHandle = temp[2];
        gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboTextureCoordHandle);
        gl.glBufferData(GL.GL_ARRAY_BUFFER, 4, textureData, GL.GL_STATIC_DRAW);
        gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);

        shader = new Shader(gl);
        shader.bind(gl);
        shader.attachVertexShader(gl);
        shader.attachFragmentShader(gl);
        shader.link(gl);
        // shader.unbind(gl);

        // setting the uniform
        shader.setUniform(gl, "texUnit", 0);
        shader.setUniform(gl, "Material", 1, 1, 1);
        shader.setUniform(gl, "Lights", 2);

        // activating textures
        gl.glActiveTexture(GL2.GL_TEXTURE0);
        texture.bind(gl);
        // gl.glBindTexture(GL.GL_TEXTURE_2D, GL.GL_TEXTURE0);

    }

    public void drawCubeVBO(GL2 gl, String textureFileName,
            String textureFileType) {

        // shader.bind(gl);

        // initializing textures

        // this.textureFileName = textureFileName;
        // this.textureFileType = textureFileType;
        // loadTexture(gl);
        // texture.enable(gl);
        // gl.glEnable(GL.GL_TEXTURE_2D);

        // drawing

        /* Setup Position Pointer */
        gl.glBindBuffer(GL.GL_ARRAY_BUFFER, VBOVertices);
        gl.glVertexPointer(3, GL.GL_FLOAT, 0, 0);

        /* Setup Texture Coordinate Pointer */
        gl.glBindBuffer(GL.GL_TEXTURE0, vboTextureCoordHandle);
        gl.glTexCoordPointer(3, GL.GL_FLOAT, 0, 0);

        // unbind the VBO
        gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);

        // actual drawing
        // gl.glBindBuffer(GL.GL_ARRAY_BUFFER, VBOVertices);
        gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL2.GL_TEXTURE_COORD_ARRAY);

        gl.glDrawArrays(GL.GL_TRIANGLES, 0, vertices.capacity());

        gl.glDisableClientState(GL2.GL_TEXTURE_COORD_ARRAY);
        gl.glDisableClientState(GL2.GL_VERTEX_ARRAY);

        // shader.unbind(gl);

    }
}

And my shaders:

private String vertexShaderString =
        "#version 330\n"+

        "layout (std140) uniform Matrices {\n"+
            "mat4 m_pvm;\n"+
            "mat4 m_viewModel;\n"+
            "mat3 m_normal;\n"+
        "};\n"+

        "layout (std140) uniform Lights {\n"+
            "vec3 l_dir;    // camera space\n"+
        "};\n"+

        "in vec4 position;   // local space\n"+
        "in vec3 normal;     // local space\n"+
        "in vec2 texCoord;\n"+

        // the data to be sent to the fragment shader
        "out Data {\n"+
            "vec3 normal;\n"+
            "vec4 eye;\n"+
            "vec2 texCoord;\n"+
        "} DataOut;\n"+

        "void main () {\n"+

            "DataOut.normal = normalize(m_normal * normal);\n"+
            "DataOut.eye = -(m_viewModel * position);\n"+
            "DataOut.texCoord = texCoord;\n"+

            "gl_Position = m_pvm * position; \n"+
        "}";

private String fragmentShaderString = 
        "#version 330\n"+

        "layout (std140) uniform Material {\n"+
            "vec4 diffuse;\n"+
            "vec4 ambient;\n"+
            "vec4 specular;\n"+
            "float shininess;\n"+
        "};\n"+

        "layout (std140) uniform Lights {\n"+
            "vec3 l_dir;    // camera space\n"+
        "};\n"+

        "in Data {\n"+
            "vec3 normal;\n"+
            "vec4 eye;\n"+
            "vec2 texCoord;\n"+
        "} DataIn;\n"+

        "uniform sampler2D texUnit;\n"+

        "out vec4 colorOut;\n"+

        "void main() {\n"+

            // set the specular term to black
            "vec4 spec = vec4(0.0);\n"+

            // normalize both input vectors
            "vec3 n = normalize(DataIn.normal);\n"+
            "vec3 e = normalize(vec3(DataIn.eye));\n"+

            "float intensity = max(dot(n,l_dir), 0.0);\n"+

            // if the vertex is lit compute the specular color
            "if (intensity > 0.0) {\n"+
                // compute the half vector
                "vec3 h = normalize(l_dir + e);\n"+  
                // compute the specular term into spec
                "float intSpec = max(dot(h,n), 0.0);\n"+
                "spec = specular * pow(intSpec,shininess);\n"+
            "}\n"+
            "vec4 texColor = texture(texUnit, DataIn.texCoord);\n"+
            "vec4 diffColor = intensity *  diffuse * texColor;\n"+
            "vec4 ambColor = ambient * texColor;\n"+

            "colorOut = max(diffColor + spec, ambColor);\n"+
        "}";


// ProgramID
int programID;

// Vertex Shader ID
int vertexShaderID;

// Fragment Shader ID
int fragmentShaderID;

public Shader(GL2ES2 gl) {
    programID = gl.glCreateProgram();
}

public void attachVertexShader(GL2ES2 gl) {

    // Create GPU shader handles
    // OpenGL ES retuns a index id to be stored for future reference.
    vertexShaderID = gl.glCreateShader(GL2ES2.GL_VERTEX_SHADER);

    // Load and compile the source
    String[] vlines = new String[] { vertexShaderString };
    int[] vlengths = new int[] { vlines[0].length() };
    gl.glShaderSource(vertexShaderID, vlines.length, vlines, vlengths, 0);
    gl.glCompileShader(vertexShaderID);

    //Check compile status for errors
    int[] compiled = new int[1];
    gl.glGetShaderiv(vertexShaderID, GL2ES2.GL_COMPILE_STATUS, compiled,0);
    if(compiled[0]!=0){System.out.println("Horray! vertex shader compiled");}
    else {
        int[] logLength = new int[1];
        gl.glGetShaderiv(vertexShaderID, GL2ES2.GL_INFO_LOG_LENGTH, logLength, 0);

        byte[] log = new byte[logLength[0]];
        gl.glGetShaderInfoLog(vertexShaderID, logLength[0], (int[])null, 0, log, 0);

        System.err.println("Error compiling the vertex shader: " + new String(log));
        System.exit(1);
    }

    //Attach Shader
    gl.glAttachShader(programID, vertexShaderID);
}

public void attachFragmentShader(GL2ES2 gl) {

    // Create GPU shader handles
    // OpenGL ES retuns a index id to be stored for future reference.
    fragmentShaderID = gl.glCreateShader(GL2ES2.GL_FRAGMENT_SHADER);

    // Load and compile the source
    String[] vlines = new String[] { fragmentShaderString };
    int[] vlengths = new int[] { vlines[0].length() };
    gl.glShaderSource(fragmentShaderID, vlines.length, vlines, vlengths, 0);
    gl.glCompileShader(fragmentShaderID);

    //Check compile status for errors
    int[] compiled = new int[1];
    gl.glGetShaderiv(fragmentShaderID, GL2ES2.GL_COMPILE_STATUS, compiled,0);
    if(compiled[0]!=0){System.out.println("Horray! fragment shader compiled");}
    else {  
        int[] logLength = new int[1];
        gl.glGetShaderiv(fragmentShaderID, GL2ES2.GL_INFO_LOG_LENGTH, logLength, 0);

        byte[] log = new byte[logLength[0]];
        gl.glGetShaderInfoLog(fragmentShaderID, logLength[0], (int[])null, 0, log, 0);

        System.err.println("Error compiling the fragment shader: " + new String(log));
        System.exit(1);
    }

    //Attach Shader
    gl.glAttachShader(programID, fragmentShaderID);

}

public void link(GL2ES2 gl) {

    //link
    gl.glLinkProgram(programID);


    //check for errors
    int[] compiled = new int[1];
    gl.glGetProgramiv(programID, GL2ES2.GL_LINK_STATUS, compiled,0);
    if(compiled[0]!=0){System.out.println("Horray! Shader program linked!");}
    else {
        int[] logLength = new int[1];
        gl.glGetProgramiv(programID, GL2ES2.GL_INFO_LOG_LENGTH, logLength, 0);

        byte[] log = new byte[logLength[0]];
        gl.glGetProgramInfoLog(programID, logLength[0], (int[])null, 0, log, 0);

        System.err.println("Error linking the program: " + new String(log));
        System.exit(1);
    }

}

public void bind(GL2ES2 gl) {
    //Associate attribute ids with the attribute names inside
    //the vertex shader.
    gl.glBindAttribLocation(programID, 0, "attribute_Position");
    gl.glBindAttribLocation(programID, 1, "attribute_Color");

    gl.glUseProgram(programID);
}

public void unbind(GL2ES2 gl) {
    gl.glUseProgram(0);
}

/**
 * Sets the uniforms in this shader
 * 
 * @param name    The name of the uniform
 * @param values  The values of the uniforms (Max 4)
 */
public void setUniform(GL2ES2 gl, String name, float... values)
{
    if (values.length > 4)
    {
        System.err.println("Uniforms cannot have more than 4 values");
        System.exit(1);
    }

    // Get the location of the uniform
    int location = gl.glGetUniformLocation(programID, name);

    // Set the uniform values
    switch (values.length)
    {
        case 1:
            gl.glUniform1f(location, values[0]);
            break;                
        case 2:
            gl.glUniform2f(location, values[0], values[1]);
            break;                
        case 3:
            gl.glUniform3f(location, values[0], values[1], values[2]);
            break;                
        case 4:
            gl.glUniform4f(location, values[0], values[1], values[2], values[3]);
            break;
    }
}

public void dispose(GL2ES2 gl) {
    gl.glUseProgram(0);

    gl.glDetachShader(programID, vertexShaderID);
    gl.glDeleteShader(vertexShaderID);
    gl.glDetachShader(programID, fragmentShaderID);
    gl.glDeleteShader(fragmentShaderID);
    gl.glDeleteProgram(programID);
}

public int getID() {
    return programID;
}
\$\endgroup\$
  • \$\begingroup\$ Hi Nate, did you solve? Still need help? \$\endgroup\$ – elect Aug 13 '15 at 12:05
  • \$\begingroup\$ I did, but I completely forget how because it was so long ago. If you want to sort through the code I put the whole project up on github github.com/nschultz14/prattle-and-twaddle \$\endgroup\$ – Nate Schultz Sep 1 '15 at 22:24
  • \$\begingroup\$ Ah good, just wanted to know if I could still help you \$\endgroup\$ – elect Sep 2 '15 at 5:54
0
\$\begingroup\$

I didn't check thoroughly, but one major problem I see here is that you aren't following the OpenGL manual: This line of code is never valid:

gl.glBindBuffer(GL.GL_TEXTURE0, vboTextureCoordHandle);

You must use a valid buffer bind target, in this case GL_ARRAY_BUFFER. As it stands now, you're using your model coordinates as the texture coordinates also, because they are still the active array buffer when you call glTexCoordPointer.

\$\endgroup\$
  • \$\begingroup\$ Thank you! When I tried to change that to GL_ARRAY_BUFFER, the texture disappeared. Does that mean the I'm not establishing my texture coordinates correctly? \$\endgroup\$ – Nate Schultz Jul 4 '14 at 4:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.