I am trying to render a 3D cube, and apply a single texture to all the faces of the cube. I feel like I am missing something critical here as it is applying to the front and back faces of the cube, but 'stretching' it across the other faces.
Example:
Object is created via:
void Engine::CreateObjects()
{
std::vector<unsigned int> indices;
indices.push_back(0);
indices.push_back(1);
indices.push_back(2);
indices.push_back(2);
indices.push_back(3);
indices.push_back(0);
indices.push_back(1);
indices.push_back(5);
indices.push_back(6);
indices.push_back(6);
indices.push_back(2);
indices.push_back(1);
indices.push_back(7);
indices.push_back(6);
indices.push_back(5);
indices.push_back(5);
indices.push_back(4);
indices.push_back(7);
indices.push_back(4);
indices.push_back(0);
indices.push_back(3);
indices.push_back(3);
indices.push_back(7);
indices.push_back(4);
indices.push_back(4);
indices.push_back(5);
indices.push_back(1);
indices.push_back(1);
indices.push_back(0);
indices.push_back(4);
indices.push_back(3);
indices.push_back(2);
indices.push_back(6);
indices.push_back(6);
indices.push_back(7);
indices.push_back(3);
std::vector<Vertex> vertices;
// xPos yPos zPos xTex yTes
vertices.push_back(Vertex(glm::vec3(-1.0f, -1.0f, 1.0f), glm::vec2(1.0f, 1.0f)));
vertices.push_back(Vertex(glm::vec3(1.0, -1.0, 1.0), glm::vec2(1.0f, 0.0f)));
vertices.push_back(Vertex(glm::vec3(1.0, 1.0, 1.0), glm::vec2(0.0f, 0.0f)));
vertices.push_back(Vertex(glm::vec3(-1.0, 1.0, 1.0), glm::vec2(0.0f, 1.0f)));
vertices.push_back(Vertex(glm::vec3(-1.0, -1.0, -1.0), glm::vec2(1.0f, 1.0f)));
vertices.push_back(Vertex(glm::vec3(1.0, -1.0, -1.0), glm::vec2(1.0f, 0.0f)));
vertices.push_back(Vertex(glm::vec3(1.0, 1.0, -1.0), glm::vec2(0.0f, 0.0f)));
vertices.push_back(Vertex(glm::vec3(-1.0, 1.0, -1.0), glm::vec2(0.0f, 1.0f)));
std::vector<Texture> textures;
Texture texture = Texture("src/Textures/wall.jpg");
textures.push_back(texture);
Mesh* obj1 = new Mesh(vertices, indices, textures);
meshList.push_back(obj1);
}
Vertex Struct:
#pragma once
#include <glm/glm.hpp>
struct Vertex
{
Vertex(glm::vec3 position, glm::vec2 texCoords) : Position(position), TexCoords(texCoords) {};
glm::vec3 Position;
glm::vec2 TexCoords;
};
Texture Struct:
#pragma once
#include "External/stb_image.h"
#include <string>
#include <iostream>
struct Texture
{
Texture(std::string path) : Id(0), Type(""), Path(path), Width(0), Height(0), nrChannels(0)
{
LoadTexture();
}
unsigned int Id;
int Width;
int Height;
int nrChannels;
std::string Type;
std::string Path;
private:
void LoadTexture()
{
glGenTextures(1, &Id);
glBindTexture(GL_TEXTURE_2D, Id);
// Wrapping
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
stbi_set_flip_vertically_on_load(true);
unsigned char* data = stbi_load(Path.c_str(), &Width, &Height, &nrChannels, 0);
if (!data)
{
std::cout << "Failed to load texture " << this->Path << std::endl;
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, Width, Height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
stbi_image_free(data);
}
};
And the actual drawing of the Mesh is done via these two functions (Draw, Setup):
void Mesh::Draw(Shader shader)
{
glBindTexture(GL_TEXTURE_2D, textures[0].Id);
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
void Mesh::SetupMesh()
{
glGenVertexArrays(1, &this->VAO);
glGenBuffers(1, &this->VBO);
glGenBuffers(1, &this->EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
auto size = vertices.size() * sizeof(Vertex);
glBufferData(GL_ARRAY_BUFFER,size, &vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
// vertex Positions
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
// vertex texture coords
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, TexCoords));
glBindVertexArray(0);
}
I understand this code is not ideal and am extremely open to different ways of constructing this cube, especially when it comes to listing the indices, but the primary issue is the texture stretching.
To me, it seems like the program is doing exactly what i'm telling it to do, however, I seem to have a knowledge gap on where to go from here to have the texture apply across the entire cube.