snowman4933
snowman4933

Reputation: 17

OpenGL doesn't render triangle

I have been trying to get OpenGL working, but for some weird reason, the triangle isn't being rendered. I have checked everything, vertex, fragment shader, the code, but didn't find any issue. The screen is being cleared, but the triangle isn't being rendered. I am following Official Guide to learning OpenGL version 4.3 by Dave Shreiner, Graham Sellers, John Kessenich, Bill Licea-Kane, Eighth edition. Necessary informations:

OS: Linux Mint 21.1 Vera

(from glxinfo)

OpenGL vendor string: AMD

OpenGL renderer string: RENOIR (renoir, LLVM 15.0.6, DRM 3.42, 5.15.0-75-generic)

OpenGL core profile version string: 4.6 (Core Profile) Mesa 22.2.5

OpenGL core profile shading language version string: 4.60

OpenGL core profile context flags: (none)

OpenGL core profile profile mask: core profile

OpenGL core profile extensions:

compilation command: g++ main.cpp LoadShaders.cpp -L/usr/lib64 -lGLEW -lGL -lX11 -lGLU -lSDL2 -llua5.4 -o exec

main.cpp

#include<cstdio>
#include<SDL2/SDL.h>
#include<GL/glew.h>
#include<GL/glxew.h>

#include "LoadShaders.hpp"

namespace Tutorial
{
    SDL_Window* window=nullptr;
    SDL_GLContext context=nullptr;
    GLuint va;
    GLuint buffer;
    GLuint Program;
}

bool InitGL()
{
    const float vPosition[6][2]={
        {-90.0f,-90.0f},
        { 0.85f, -0.90f },
        { -0.90f, 0.85 },
        { 0.90f, -0.85f },
        { 0.90f, 0.90f },
        { -0.85f, 0.90f }
    };

    glGenVertexArrays(1,&Tutorial::va);
    glBindVertexArray(Tutorial::va);
    glGenBuffers(1,&Tutorial::buffer);
    glBindBuffer(GL_ARRAY_BUFFER,Tutorial::buffer);
    glBufferData(0,sizeof(vPosition),vPosition,GL_STATIC_DRAW);
    if(!LoadShaders(&Tutorial::Program))
    {
        return false;
    }

    glUseProgram(Tutorial::Program);

    glVertexAttribPointer(0,2,GL_FLOAT,GL_FALSE,0,(void*)nullptr);
    glEnableVertexAttribArray(0);

    
    return true;
}

bool Init()
{
    if(SDL_Init(SDL_INIT_VIDEO))
    {
        fprintf(stderr,"failed to initialize SDL2: %s\n",SDL_GetError());
        return false;
    }
    else if(SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION,4) || SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION,6) || SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,SDL_GL_CONTEXT_PROFILE_CORE))
    {
        fprintf(stderr,"failed to set attribute: %s\n",SDL_GetError());
        return false;
    }
    else if(!(Tutorial::window=SDL_CreateWindow("OpenGL tutorial",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,512,512,SDL_WINDOW_OPENGL)))
    {
        fprintf(stderr,"failed to create window: %s\n",SDL_GetError());
        return false;
    }
    else if(!(Tutorial::context=SDL_GL_CreateContext(Tutorial::window)))
    {
        fprintf(stderr,"failed to create OpenGL context: %s\n",SDL_GetError());
        return false;
    }
    else if(GLenum glinit_ret; (glinit_ret=glewInit())!=GLEW_OK)
    {
        fprintf(stderr,"Failed to initialize glew: %s\n",glewGetErrorString(glinit_ret));
        return false;
    }

    return InitGL();

}

void Render()
{
    glClear(GL_COLOR_BUFFER_BIT);
    glBindVertexArray(Tutorial::va);
    glDrawArrays(GL_TRIANGLES,0,6);
    glFlush();
    SDL_GL_SwapWindow(Tutorial::window);
}

void Fini()
{
    if(Tutorial::Program)
    {
        glDeleteProgram(Tutorial::Program);
    }


    glUseProgram(0);
    glDeleteProgram(Tutorial::Program);
    glDisableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER,0);
    glDeleteBuffers(1,&Tutorial::buffer);
    glBindVertexArray(0);
    glDeleteVertexArrays(1,&Tutorial::va);

    SDL_DestroyWindow(Tutorial::window);
    SDL_Quit();

}


int main(int argc,char* argv[])
{
    if(Init())
    {
        printf("Successfully initialized\n");
        SDL_Event event;
        bool running=true;
        glClearColor(0.0f,0.0f,0.0f,1.0f);
        while(running)
        {
            while(SDL_PollEvent(&event))
            {
                if(event.type==SDL_QUIT)
                {
                    running=false;
                }
                else if(event.type==SDL_KEYDOWN && event.key.keysym.sym==SDLK_ESCAPE)
                {
                    running=false;
                }
            }

            if(!running)
                break;
            Render();
        }
    }

    Fini();
    return 0;
}

LoadShaders.cpp

#include<cstdio>
#include<cstring>
#include<GL/glew.h>
#include<GL/glxew.h>
extern "C"
{
    #include<lua5.4/lua.h>
    #include<lua5.4/lauxlib.h>
}
#include "LoadShaders.hpp"

const char* errmsg[8]={"GL_INVALID_ENUM","GL_INVALID_VALUE","GL_INVALID_OPERATION","GL_STACK_OVERFLOW",
"GL_STACK_UNDERFLOW","GL_OUT_OF_MEMORY","GL_INVALID_FRAMEBUFFER_OPERATION","GL_CONTEXT_LOST"};

const char* GetError(int errtype)
{
    if(errtype>=0x0500)
    {
        return errmsg[errtype-0x0500];
    }
    return nullptr;
}

bool CompileShaders(GLenum shader_t,const char* source,GLuint* shader)
{
    if(shader)
    {
        const char* Typename;
        switch(shader_t)
        {
            case GL_VERTEX_SHADER:
            {
                Typename="Vertex Shader";
                break;
            }
            case GL_FRAGMENT_SHADER:
            {
                Typename="Fragment Shader";
                break;
            }
            case GL_GEOMETRY_SHADER:
            {
                Typename="Geometry Shader";
                break;
            }
        }

        *shader=glCreateShader(shader_t);
        if(*shader==0)
        {
            fprintf(stderr,"failed to create %s: %s\n",Typename,GetError(glGetError()));
            return false;
        }

        glShaderSource(*shader,1,&source,nullptr);

        if(GLenum retval=glGetError();retval==GL_INVALID_VALUE || retval==GL_INVALID_OPERATION)
        {
            fprintf(stderr,"glGetError(): %x\n",retval);
            fprintf(stderr,"failed to load source for %s: %s\n",Typename,GetError(retval));
            fprintf(stderr,"printing the source: %s\n",source);
            glDeleteShader(*shader);
            *shader=0;
            return false;
        }

        glCompileShader(*shader);
        GLint status;
        glGetShaderiv(*shader,GL_COMPILE_STATUS,&status);
        if(status==GL_FALSE) //if compilation failed
        {
            //get the error msg
            glGetShaderiv(*shader,GL_INFO_LOG_LENGTH,&status);
            GLchar* logmsg=new GLchar[status];
            glGetShaderInfoLog(*shader,status,nullptr,logmsg);
            glDeleteShader(*shader);
            *shader=0;
            fprintf(stderr,"failed to compile %s: %s\n",Typename,logmsg);
            delete[] logmsg;
            return false;
        }

        return true;
    }
    return false;
}

bool LoadShaders(GLuint* pptr)
{
    
    if(pptr)
    {
        if(GLenum errret; (errret=glewInit())!=GLEW_OK)
        {
            fprintf(stderr,"failed to do glew initialize: %s\n",glewGetErrorString(errret));
            return false;
        }

        //get the source string
        lua_State* state=luaL_newstate();
        if(!state)
        {
            fprintf(stderr,"failed to create new lua state\n");
            return false;
        }

        if(luaL_loadfile(state,"VertexShader.lua") || lua_pcall(state,0,1,0))
        {
            fprintf(stderr,"failed to load file VertexShader.lua: %s\n",lua_tostring(state,-1));
            lua_close(state);
            return false;
        }

        char* vs_source=new char[strlen(lua_tostring(state,-1))];
        if(!vs_source)
        {
            fprintf(stderr,"failed to allocate memory for Vertex Shader source\n");
            lua_close(state);
            return false;
        }

        strcpy(vs_source,lua_tostring(state,-1));

        if(luaL_loadfile(state,"FragmentShader.lua") || lua_pcall(state,0,1,0))
        {
            fprintf(stderr,"failed to laod file FragmentShader.lua: %s\n",lua_tostring(state,-1));
            delete[] vs_source;
            lua_close(state);
            return false;
        }

        char* fs_source=new char[strlen(lua_tostring(state,-1))];
        if(!fs_source)
        {
            fprintf(stderr,"failed to allocate memory for Fragment Shader source\n");
            delete[] vs_source;
            lua_close(state);
            return false;
        }

        strcpy(fs_source,lua_tostring(state,-1));

        lua_close(state);

        //get the shader compiler do the compilation
        GLuint vshader,fshader;
        if(!CompileShaders(GL_VERTEX_SHADER,vs_source,&vshader) || !CompileShaders(GL_FRAGMENT_SHADER,fs_source,&fshader))
        {
            delete[] vs_source;
            delete[] fs_source;
            return false;
        }
        delete[] vs_source;
        delete[] fs_source;

        *pptr=glCreateProgram();
        if(*pptr==0)
        {
            glDeleteShader(vshader);
            glDeleteShader(fshader);
            return false;
        }

        glAttachShader(*pptr,vshader);
        glAttachShader(*pptr,fshader);

        glLinkProgram(*pptr);
        glDetachShader(*pptr,vshader);
        glDetachShader(*pptr,fshader);

        glDeleteShader(vshader);
        glDeleteShader(fshader);

        GLint status;
        glGetProgramiv(*pptr,GL_LINK_STATUS,&status);
        if(status==GL_FALSE)
        {
            glGetProgramiv(*pptr,GL_INFO_LOG_LENGTH,&status);
            GLchar* logmsg=new GLchar[status];
            glGetProgramInfoLog(*pptr,status,nullptr,logmsg);
            glDeleteProgram(*pptr);
            *pptr=0;

            fprintf(stderr,"failed to link program: %s\n",logmsg);
            delete[] logmsg;
            return false;
        }

        return true;
    }
    return false;
}

VertexShader.lua

return [[
#version 460 core
layout(location=0) in vec4 vPosition;
void main()
{
    gl_Position=vPosition;
    gl_Position.z=0.0;
    gl_Position.w=1.0;
}
]]

FragmentShader.lua

return [[
#version 460 core
out vec4 fcolor;
void main()
{
    fcolor=vec4(1.0f,1.0f,1.0f,1.0f);
}
]]

Upvotes: 1

Views: 86

Answers (1)

Rabbid76
Rabbid76

Reputation: 211220

The first argument of glBufferData specifies the target to which the buffer object is bound:

glBufferData(0, sizeof(vPosition), vPosition, GL_STATIC_DRAW)

glBufferData(GL_ARRAY_BUFFER, sizeof(vPosition), vPosition, GL_STATIC_DRAW);

glBufferData creates and initializes a buffer object's data store for the specified traget. When glVertexAttribPointer is called the buffer which is currently bound to the target ARRAY_BUFFER, is associated to the specified attribute index and the ID of the object is stored in the state vector of the currently bound VAO.

Upvotes: 2

Related Questions