How to draw a triangle on the screen using OpenGL with FreeGLUT, Shaders and GLEW in C++

1 Answer

0 votes
#include <iostream> // For std::cerr, std::cout
#include <fstream>  // For std::ifstream
#include <string>   // For std::string
#include <cstring>  // For strlen
#include <sstream>  // For std::stringstream (used in ReadFile)
#include <GL/glew.h> 
#include <freeglut.h> 

struct Vec3 {
    float x, y, z;

    Vec3() {}

    Vec3(float _x, float _y, float _z) {
        x = _x;
        y = _y;
        z = _z;
    }
};

GLuint VBO;

static void RenderScene() { 
    glClear(GL_COLOR_BUFFER_BIT);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);

    glEnableVertexAttribArray(0);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

    // void glDrawArrays(GLenum mode, GLint first, GLsizei count);
    glDrawArrays(GL_TRIANGLES, 0, 3);

    glDisableVertexAttribArray(0);

    glutSwapBuffers();
}

static void AddShader(GLuint ShaderProgram, const char* pShaderText, GLenum ShaderType) {
    GLuint ShaderObj = glCreateShader(ShaderType);

    if (ShaderObj == 0) {
        fprintf(stderr, "Error creating shader type %d\n", ShaderType);
        exit(0);
    }

    const GLchar* p[1];
    p[0] = pShaderText;

    GLint len[1];
    len[0] = (GLint)strlen(pShaderText);

    glShaderSource(ShaderObj, 1, p, len);

    glCompileShader(ShaderObj);

    GLint success;
    glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success);

    if (!success) {
        GLchar InfoLog[1024];
        glGetShaderInfoLog(ShaderObj, 1024, NULL, InfoLog);
        fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, InfoLog);
        exit(1);
    }

    glAttachShader(ShaderProgram, ShaderObj);
}

const char* pVSFileName = "shader.vs";
const char* pFSFileName = "shader.fs";

static bool ReadFile(const char* pFileName, std::string& outFile)
{
    std::ifstream f(pFileName); // Open the file

    bool rv = false;
    if (f.is_open()) {
        std::stringstream ss;
        ss << f.rdbuf(); // Read entire file buffer into stringstream
        outFile = ss.str(); // Convert stringstream to std::string
        rv = true;
    }
    else {
        std::cerr << "Error opening file: " << pFileName << std::endl;
    }

    return rv;
}

static void CompileShaders()
{
    GLuint ShaderProgram = glCreateProgram();

    if (ShaderProgram == 0) {
        fprintf(stderr, "Error creating shader program - glCreateProgram\n");
        exit(1);
    }

    std::string vs, fs;

    if (!ReadFile(pVSFileName, vs)) {
        exit(1);
    };

    AddShader(ShaderProgram, vs.c_str(), GL_VERTEX_SHADER);

    if (!ReadFile(pFSFileName, fs)) {
        exit(1);
    };

    AddShader(ShaderProgram, fs.c_str(), GL_FRAGMENT_SHADER);

    GLint Success = 0;
    GLchar ErrorLog[1024] = { 0 };

    glLinkProgram(ShaderProgram);

    glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success);
    if (Success == 0) {
        glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
        fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);
        exit(1);
    }

    glValidateProgram(ShaderProgram);
    glGetProgramiv(ShaderProgram, GL_VALIDATE_STATUS, &Success);
    if (!Success) {
        glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
        fprintf(stderr, "Invalid shader program: '%s'\n", ErrorLog);
        exit(1);
    }

    glUseProgram(ShaderProgram);
}

static void CreateVertexBuffer() {
    Vec3 Vertices[3];
    Vertices[0] = Vec3(-1.0f, -1.0f, 0.0f); // bottom left
    Vertices[1] = Vec3(0.0f, 1.0f, 0.0f);   // top
    Vertices[2] = Vec3(1.0f, -1.0f, 0.0f);  // bottom right

    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);

    int width = 800;
    int height = 600;
    glutInitWindowSize(width, height);

    int win = glutCreateWindow("freeglut - glutCreateWindow() - Draw Triangle with Shaders");

    GLenum res = glewInit();
    if (res != GLEW_OK) {
        std::cout << glewGetErrorString(res);
        return 1;
    }

    GLclampf Red = 0.0f, Green = 0.0f, Blue = 0.0f, Alpha = 0.0f;
    glClearColor(Red, Green, Blue, Alpha);

    CreateVertexBuffer();

    CompileShaders();

    glutDisplayFunc(RenderScene);

    glutMainLoop();

    return 0;
}




/*
run



*/
// shader.vs

#version 460 core

layout (location = 0) in vec3 Position;

void main()
{
    gl_Position = vec4(0.5 * Position.x, 0.5 * Position.y, Position.z, 1.0);
}


// shader.fs

#version 460 core

out vec4 FragColor;

void main()
{
    FragColor = vec4(1.0, 0.0, 0.0, 0.0); // Red
}

 



answered Jun 29, 2025 by avibootz
edited Jun 29, 2025 by avibootz
...