Reputation: 17
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
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