OpenGL texture issue on plane drawn using glDrawArrays()

388 Views Asked by At

I'm trying to apply a texture to a plane made up of 6 vertexes drawn using glDrawArrays() The first triangle drawn seems to be drawn correctly but the texture for the second triangle doesn't seem to align correctly and seems squished. I had the same issue when trying to draw using an index buffer using glDrawElements() as well.

My vertex array Object creation looks like this

// Position and Color data
GLfloat verts[] = {
    // Vertex Positions    // Colors (r,g,b,a)  //Texture Coordinates 
    -5, -1, 5, 1.0f, 0.0f, 0.0f, 1.0f,          0.0f, 0.0f, // front left vertex
    -5, -1, -5, 1.0f, 0.0f, 0.0f, 1.0f,         0.0f, 1.0f, // back left vertex
    5, -1, 5, 1.0f, 0.0f, 0.0f, 1.0f,           1.0f, 0.0f, // front right vertex
    -5, -1, -5, 1.0f, 0.0f, 0.0f, 1.0f,         0.0f, 1.0f, // back left vertex
    5, -1, -5, 1.0f, 0.0f, 0.0f, 1.0f,          1.0f, 1.0f,// back right vertex
    5, -1, 5, 1.0f, 0.0f, 0.0f, 1.0f,           1.0f, 0.0f // front right vertex
};

const GLuint floatsPerVertex = 3;
const GLuint floatsPerColor = 4;
const GLuint floatsPerUV = 2;

glGenVertexArrays(1, &mesh.vao); // we can also generate multiple VAOs or buffers at the same time
glBindVertexArray(mesh.vao);

// Create buffer: for the vertex data
glGenBuffers(1, &mesh.vbo);
glBindBuffer(GL_ARRAY_BUFFER, mesh.vbo); // Activates the buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); // Sends vertex or coordinate data to the GPU

// Strides between vertex coordinates is 9 (x, y, z, r, g, b, a). A tightly packed stride is 0.
GLint stride = sizeof(float) * (floatsPerVertex + floatsPerColor + floatsPerUV);// The number of floats before each
mesh.nVertices = 6;

// Create Vertex Attribute Pointers
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);

glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float) * floatsPerVertex));
glEnableVertexAttribArray(1);

glVertexAttribPointer(2, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float) * (floatsPerVertex + floatsPerColor)));
glEnableVertexAttribArray(2);

My Vertex and Fragment Shader are:

// Vertex Shader source code
const GLchar* vertexShaderSource = GLSL(440,
layout(location = 0) in vec3 position; // Vertex data from Vertex Attrib Pointer 0
layout(location = 1) in vec4 color; // Color data from Vertex Attrib Pointer 1
layout(location = 2) in vec2 textureCoordinate; // Texture cooridnates from vertex attirb pointer 2

out vec4 vertexColor; // Variable to transfer color data to the fragment shader
out vec2 vertexTextureCoordinate; // Varible to transfer texture coordinates to fragment shaders

// Global variables for the transform matrices
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    gl_Position = projection * view * model * vec4(position, 1.0f); // Transforms vertices to clip coordinates
    vertexColor = color; // References incoming color data
    vertexTextureCoordinate = textureCoordinate; // references income texture data
}
);

// Fragment Shader Source Code
const GLchar* fragmentShaderSource = GLSL(440,
in vec4 vertexColor; // Variable to hold incoming color data from vertex shader
in vec2 vertexTextureCoordinate;
out vec4 fragmentColor;

uniform sampler2D uTexture;

void main()
{
    fragmentColor = texture(uTexture, vertexTextureCoordinate); // sends texture to GPU for rendering 
}
);

Here is the code in my render function (I've cut out code to just where I draw the plane and variable set up:

// Enable z-depth 
glEnable(GL_DEPTH_TEST);

// Clear the frame and z buffers
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);

// Scales object
glm::mat4 scale = glm::scale(glm::vec3(1.0f, 1.0f, 1.0f));
// Rotate shape
glm::mat4 rotation = glm::rotate(45.0f, glm::vec3(1.0f, 1.0f, 0.0f));
// Place object at x, y, z
glm::mat4 translation = glm::translate(glm::vec3(-1.0f, 0.0f, 0.0f));
// Model matrix: transformations are applied right-to-left order
glm::mat4 model = translation * rotation * scale;

// Transforms the camera: move the camera back (z axis)
glm::mat4 view = gCamera.GetViewMatrix();
glm::mat4 projection;

// Create perspective projection
if (!perspectiveSwitch)
{

    projection = glm::perspective(45.0f, (GLfloat)WINDOW_WIDTH / (GLfloat)WINDOW_HEIGHT, 0.1f, 100.0f);
}

else
{
    projection = glm::ortho(-5.0f, 5.0f, -5.0f, 5.0f, 0.1f, 100.0f);
}

// Select shader program to be used
glUseProgram(gProgramId);

// Retrives and passes transfrom matrices to the shader program
GLint modelLoc = glGetUniformLocation(gProgramId, "model");
GLint viewLoc = glGetUniformLocation(gProgramId, "view");
GLint projLoc = glGetUniformLocation(gProgramId, "projection");

glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));


// Object remains same size
scale = glm::scale(glm::vec3(1.0f, 1.0f, 1.0f));
// object remains unrotated
rotation = glm::rotate(0.0f, glm::vec3(1.0f, 1.0f, 1.0f));
// Place object at the origin 
translation = glm::translate(glm::vec3(0.0f, 0.0f, 0.0f));
// Model matrix: transformations are applied right-to-left order
model = translation * rotation * scale;

//Send updated model information for next object
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));


// Activate the VBO contained within the mesh's VAO
glBindVertexArray(gPlane.vao);

// Bind texture for draw
glBindTexture(GL_TEXTURE_2D, tableTexture);

//Draws the triangles
glDrawArrays(GL_TRIANGLES, 0, gPlane.nVertices);

// Deactivate the Vertex Array Object
glBindVertexArray(0);

// glfw: swap buffers and poll IO events
glfwSwapBuffers(gWindow); // Flips the back buffer with the front buffer

Here is what my rendered object with the texture applied looks like and the original image of the texture.

https://prnt.sc/26w3evd

the original image of the texture.

(I can't seem to add multiple images to the post so I had to link one of them)

1

There are 1 best solutions below

0
Vincent Del Vecchio On

Discovered I was passing the wrong value in my attribute pointer for the number of values.

I had accidentally passed in the number of values for the color attribute instead of the number of values for the texture coordinate attributes.

// I had put this
glVertexAttribPointer(2, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float) * (floatsPerVertex + floatsPerColor)));
// Instead of this
glVertexAttribPointer(2, floatsPerUV, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float) * (floatsPerVertex + floatsPerColor)));