0

I'm learning how to code graphics with OpenGL. So far I have created IndexBuffer, VertexBuffer, VertexArray, Camera, Texture and Shader. Now I'm trying to make a Mesh class with vertices, indices and textures. But when I call the "Draw(Shader& shader, Camera& camera)" function it doesn't show anything. All the vertices, indices and textures are passed in correctly (I've already checked this).

Here is my code for Mesh class

#pragma once

#include <vector>

#include"VAO.h"
#include"EBO.h"
#include"Camera.h"
#include"Texture.h"

class Mesh
{
public:
    Mesh(std::vector <Vertex>& vertices, std::vector <GLuint>& indices, std::vector <Texture>& textures);
    void Draw(Shader& shader, Camera& camera);
private:
    std::vector <Vertex> m_Vertices;
    std::vector <unsigned int> m_Indices;
    std::vector <Texture> m_Textures;
    VAO VAO;
};

---------------------------------------------

#include "Mesh.h"

#include <iostream>

Mesh::Mesh(std::vector<Vertex>& vertices, std::vector<GLuint>& indices, std::vector<Texture>& textures)
    : m_Vertices(vertices), m_Indices(indices), m_Textures(textures)
{
    VAO.Bind();
    // Generates Vertex Buffer Object and links it to vertices
    VBO VBO(vertices);
    // Generates Element Buffer Object and links it to indices
    EBO EBO(indices);
    // Links VBO attributes such as coordinates and colors to VAO
    VAO.LinkAttrib(VBO, 0, 3, GL_FLOAT, false, sizeof(Vertex), (void*)0);
    VAO.LinkAttrib(VBO, 1, 3, GL_FLOAT, false, sizeof(Vertex), (void*)(3 * sizeof(float)));
    VAO.LinkAttrib(VBO, 2, 3, GL_FLOAT, false, sizeof(Vertex), (void*)(6 * sizeof(float)));
    VAO.LinkAttrib(VBO, 3, 2, GL_FLOAT, false, sizeof(Vertex), (void*)(9 * sizeof(float)));
    // Unbind all to prevent accidentally modifying them
    VAO.Unbind();
    VBO.Unbind();
    EBO.Unbind();
}

void Mesh::Draw(Shader& shader, Camera& camera)
{
    // Bind shader to be able to access uniforms
    shader.Use();
    VAO.Bind();

    // Keep track of how many of each type of textures we have
    unsigned int numDiffuse = 0;
    unsigned int numSpecular = 0;

    for (unsigned int i = 0; i < m_Textures.size(); i++)
    {
        std::string num;
        std::string type = m_Textures[i].GetType();
        if (type == "diffuse")
        {
            num = std::to_string(numDiffuse++);
        }
        else if (type == "specular")
        {
            num = std::to_string(numSpecular++);
        }
        m_Textures[i].SetUniform(shader, (type + num).c_str(), i);
        m_Textures[i].Bind();
    }
    // Take care of the camera Matrix
    shader.SetUniform3f("camPos", camera.GetCameraPosition().x, camera.GetCameraPosition().y, camera.GetCameraPosition().z);
    camera.SetMatrix(shader, "camMatrix");

    // Draw the actual mesh
    glDrawElements(GL_TRIANGLES, m_Indices.size(), GL_UNSIGNED_INT, 0);
}

My texture class:

#pragma once
#include <string>
#include "Shader.h"

class Texture
{
public:
    Texture(const std::string& filepath, const std::string& texType, unsigned int slot, unsigned int format, unsigned int pixelType);
    ~Texture();

    void SetUniform(const Shader& shader, const std::string& name, unsigned int unit) const;

    void Bind() const;
    void Unbind() const;

    inline unsigned int GetID() const { return m_ID; }
    inline std::string GetType() const { return m_Type; }
private:
    unsigned int m_ID;
    std::string m_Type;
    unsigned int m_Unit;
};

#include "Texture.h"
#include <GL/glew.h>
#include "stb_image.h"

Texture::Texture(const std::string& filepath, const std::string& texType, unsigned int slot, unsigned int format, unsigned int pixelType)
    : m_Type(texType), m_Unit(slot)
{
    // Stores the width, height, and the number of color channels of the image
    int widthImg, heightImg, numColCh;
    // Flips the image so it appears right side up
    stbi_set_flip_vertically_on_load(true);
    // Reads the image from a file and stores it in bytes
    unsigned char* bytes = stbi_load(filepath.c_str(), &widthImg, &heightImg, &numColCh, 0);

    // Generates an OpenGL texture object
    glGenTextures(1, &m_ID);
    // Assigns the texture to a Texture Unit
    glActiveTexture(GL_TEXTURE0 + slot);
    glBindTexture(GL_TEXTURE_2D, m_ID);

    // Configures the type of algorithm that is used to make the image smaller or bigger
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    // Configures the way the texture repeats (if it does at all)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

    // Assigns the image to the OpenGL Texture object
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, widthImg, heightImg, 0, format, pixelType, bytes);
    // Generates MipMaps
    glGenerateMipmap(GL_TEXTURE_2D);

    // Deletes the image data as it is already in the OpenGL Texture object
    stbi_image_free(bytes);

    // Unbinds the OpenGL Texture object so that it can't accidentally be modified
    glBindTexture(GL_TEXTURE_2D, 0);

}

Texture::~Texture()
{
    glDeleteTextures(1, &m_ID);
}

void Texture::SetUniform(const Shader& shader, const std::string& name, unsigned int unit) const
{
    shader.Use();
    shader.SetUniform1i(name, unit);
}

void Texture::Bind() const
{
    glActiveTexture(GL_TEXTURE0 + m_Unit);
    glBindTexture(GL_TEXTURE_2D, m_ID);
}

void Texture::Unbind() const
{
    glBindTexture(GL_TEXTURE_2D, 0);
}

And, finally, my shader code

#pragma once

#include <string>
#include <glm/glm.hpp>

std::string readFileContents(const std::string& filepath);

class Shader
{
public:
    Shader(const std::string& vertexPath, const std::string& fragmentPath);
    ~Shader();

    void SetUniform1f(const std::string& name, float v0) const;
    void SetUniform2f(const std::string& name, float v0, float v1) const;
    void SetUniform3f(const std::string& name, float v0, float v1, float v2) const;
    void SetUniform4f(const std::string& name, float v0, float v1, float v2, float v3) const;

    void SetUniform1i(const std::string& name, int v0) const;

    void SetUniformMatrix4f(const std::string& name, const glm::mat4& v0) const;

    void Use() const;

    inline unsigned int GetID() const { return m_ID; }
private:
    unsigned int m_ID;
};

#include "Shader.h"

#include <GL/glew.h>
#include <glm/gtc/type_ptr.hpp>

#include <fstream>
#include <sstream>
#include <iostream>

#include <vector>

std::string readFileContents(const std::string& filepath)
{
    std::string contents;
    std::ifstream in(filepath, std::ios::binary);
    if (in)
    {
        std::stringstream sstr;
        sstr << in.rdbuf();
        contents = sstr.str();
        in.close();
    }
    return contents;
}

static unsigned int CompileShader(const std::string& shaderPath, unsigned int shaderType)
{
    unsigned int shader = glCreateShader(shaderType);
    std::string shaderCode = readFileContents(shaderPath);
    const char* shaderSource = shaderCode.c_str();
    glShaderSource(shader, 1, &shaderSource, NULL);
    glCompileShader(shader);

    int result;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &result);
    if (result == GL_FALSE)
    {
        int infoLogLength;
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
        std::vector<char> errorMessage((long long)infoLogLength + 1);
        glGetShaderInfoLog(shader, infoLogLength, NULL, errorMessage.data());
        std::cout << errorMessage.data() << std::endl;
    }
    return shader;
}

Shader::Shader(const std::string& vertexPath, const std::string& fragmentPath)
{
    unsigned int vertexShader = CompileShader(vertexPath, GL_VERTEX_SHADER);
    unsigned int fragmentShader = CompileShader(fragmentPath, GL_FRAGMENT_SHADER);
    m_ID = glCreateProgram();
    glAttachShader(m_ID, vertexShader);
    glAttachShader(m_ID, fragmentShader);
    glLinkProgram(m_ID);

    int result;
    glGetProgramiv(m_ID, GL_COMPILE_STATUS, &result);
    if (result == GL_FALSE)
    {
        int infoLogLength;
        glGetProgramiv(m_ID, GL_INFO_LOG_LENGTH, &infoLogLength);
        std::vector<char> errorMessage((long long)infoLogLength + 1);
        glGetProgramInfoLog(m_ID, infoLogLength, NULL, errorMessage.data());
        std::cout << errorMessage.data() << std::endl;
    }

    glDetachShader(m_ID, vertexShader);
    glDetachShader(m_ID, fragmentShader);

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
}

Shader::~Shader()
{
    glDeleteProgram(m_ID);
}

void Shader::SetUniform1f(const std::string& name, float v0) const
{
    unsigned int location = glGetUniformLocation(m_ID, name.c_str());
    glUniform1f(location, v0);
}

void Shader::SetUniform2f(const std::string& name, float v0, float v1) const
{
    unsigned int location = glGetUniformLocation(m_ID, name.c_str());
    glUniform2f(location, v0, v1);
}

void Shader::SetUniform3f(const std::string& name, float v0, float v1, float v2) const
{
    unsigned int location = glGetUniformLocation(m_ID, name.c_str());
    glUniform3f(location, v0, v1, v2);
}

void Shader::SetUniform4f(const std::string& name, float v0, float v1, float v2, float v3) const
{
    unsigned int location = glGetUniformLocation(m_ID, name.c_str());
    glUniform4f(location, v0, v1, v2, v3);

}

void Shader::SetUniform1i(const std::string& name, int v0) const
{
    unsigned int location = glGetUniformLocation(m_ID, name.c_str());
    glUniform1i(location, v0);
}

void Shader::SetUniformMatrix4f(const std::string& name, const glm::mat4& v0) const
{
    unsigned int location = glGetUniformLocation(m_ID, name.c_str());
    glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(v0));

}

void Shader::Use() const
{
    glUseProgram(m_ID);
}

ALso, every "Bind()" function is like "glBindX(ENUM, m_ID);" and every "Unbind()" is like "glBindX(ENUM, 0);"

  • BTW: Wrapping every OpenGL function or object in a class is not a particularly productive way to "learn" OpenGL. Having a RAII container for a class makes some sense. Having that class expose a bunch of methods for that class does not. Especially if you're not using DSA to manipulate those objects. – Nicol Bolas Jan 07 '23 at 04:01

0 Answers0