-1

I am useing OpenGL with GLEW and GLFW. I have created two shaders and they compile fine:

#include <iostream> #include <GL/glew.h> #include <OpenGL/OpenGL.h> #include <GLFW/glfw3.h> static unsigned int CompileShader( unsigned int type, const std::string source){ unsigned int id = glCreateShader(type); const char* src = source.c_str(); glShaderSource(id, 1, &src, nullptr); glCompileShader(id); int result; glGetShaderiv(id, GL_COMPILE_STATUS, &result); if (result == GL_FALSE){ int length; glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length); char* message = (char*)alloca(length * sizeof(char)); glGetShaderInfoLog(id, length, &length, message); std::cout <<"failed to compile " << (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << " shader" <<"\n"; std::cout << message << "\n"; glDeleteShader(id); return 0; } return id; } static int CreateShader(const std::string& VertexShader, const std::string& FragmentShader){ unsigned int program = glCreateProgram(); unsigned int vs = CompileShader(GL_VERTEX_SHADER, VertexShader); unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, FragmentShader); glAttachShader(program, vs); glAttachShader(program, fs); glLinkProgram(program); glValidateProgram(program); glDeleteShader(vs); glDeleteShader(fs); return program; } int main(void){ /* Initialize the library */ GLFWwindow* window; if (!glfwInit()){return -1;} glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #ifdef __APPLE__ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); #endif /* Create a windowed mode window and its OpenGL context */ window = glfwCreateWindow(640, 480, "Gaston", NULL, NULL); if (!window){ glfwTerminate(); return -1; } /* Make the window's context current */ glfwMakeContextCurrent(window); if (glewInit() != GLEW_OK){ std::cout <<"glewunit(); failed\n"; } float positions[6] = { -0.5f, -0.5f, -.9f, .5f, 0.5f, 0.5f }; unsigned int buffer; glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer); glBufferData(GL_ARRAY_BUFFER, sizeof(positions) * sizeof(float), positions, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float)*2, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); std::string vertexshader = "#version 330 core\n" "\n" "layout(location = 0) in vec4 position;\n" "\n" "void main()\n" "{\n" " gl_Position = position;\n" "}\n"; std::string fragmentshader = "#version 330 core\n" "\n" "layout(location = 0) out vec4 colour;\n" "\n" "void main()\n" "{\n" " colour = vec4(1.0, 0.0, 0.0, 1.0);\n" "}\n"; unsigned int shader = CreateShader(vertexshader, fragmentshader); glUseProgram(shader); /* Loop until the user closes the window */ while (!glfwWindowShouldClose(window)){ /* Render here */ glClear(GL_COLOR_BUFFER_BIT); glDrawArrays(GL_TRIANGLES, 0, 3); /* Swap front and back buffers */ glfwSwapBuffers(window); /* Poll for and process events */ glfwPollEvents(); } glfwTerminate(); return 0; } 

...but the triangle does not show up. All I get is a blank screen.

The ideal result is a red triangle.

2
  • 2
    sizeof(positions) is already the correct size. Multiplying that by sizeof float is wrong. Making position a vec4 and then only supplying a vec2 is misleading but not per se wrong. Commented Nov 29, 2024 at 7:54
  • 1
    If you're using OpenGL 3.3 Core I suspect you need to have at least one Vertex Array Object. Commented Nov 29, 2024 at 11:00

1 Answer 1

2

A few things:

  • As @G.M. pointed out you need a vertex array object (VAO) bound and then populated (with VBO bindings & vertex attrib enablements) to render things in Core contexts. For example:

    GLuint vao = 0; glCreateVertexArrays(1, &vao); glBindVertexArray(vao); 
  • Shader linking can fail too, make sure to check for that via glGetProgramiv() & co.

  • A debug context and debug message callback would have shown the glDrawArrays() call to be throwing a GL_INVALID_OPERATION:

    if( glewIsSupported( "GL_ARB_debug_output" ) ) { glEnable( GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB ); glDebugMessageControlARB( GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE ); glDebugMessageCallbackARB( []( GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar* message, const void* ) { std::cerr << "GL: " << message << std::endl; }, 0 ); } 

    Output:

    GL: GL_INVALID_OPERATION in glDrawArrays 
  • Raw string literals make for more readable inline GLSL, no newlines or excessive quotes needed:

    const char* const vert = R"GLSL( #version 330 core layout( location = 0 ) in vec4 position; void main() { gl_Position = position; }; )GLSL"; 
  • As @Botje pointed out you're over-allocating storage for your VBO; sizeof(array) is already the size of array in bytes, no need to multiply by sizeof(float).

    Do be careful if you try to pass arrays as function arguments though, in that context they decay to pointers and sizeof(pointer) == 4 or 8, not the size of the original array. Pass in an additional size argument or use a range/container.

All together:

screenshot of red triangle

// g++ main.cpp $(pkg-config --cflags --libs glew glfw3) #include <GL/glew.h> #include <GLFW/glfw3.h> #include <iostream> void CheckStatus( GLuint obj, bool isShader ) { GLint status = GL_FALSE, log[ 1 << 11 ] = { 0 }; ( isShader ? glGetShaderiv : glGetProgramiv )( obj, isShader ? GL_COMPILE_STATUS : GL_LINK_STATUS, &status ); if( status == GL_TRUE ) return; ( isShader ? glGetShaderInfoLog : glGetProgramInfoLog )( obj, sizeof( log ), NULL, (GLchar*)log ); std::cerr << (GLchar*)log << "\n"; std::exit( EXIT_FAILURE ); } void AttachShader( GLuint program, GLenum type, const char* src ) { GLuint shader = glCreateShader( type ); glShaderSource( shader, 1, &src, NULL ); glCompileShader( shader ); CheckStatus( shader, true ); glAttachShader( program, shader ); glDeleteShader( shader ); } const char* const vert = R"GLSL( #version 330 core layout( location = 0 ) in vec4 position; void main() { gl_Position = position; }; )GLSL"; const char* const frag = R"GLSL( #version 330 core layout(location = 0) out vec4 colour; void main() { colour = vec4( 1.0, 0.0, 0.0, 1.0 ); }; )GLSL"; int main( void ) { /* Initialize the library */ glfwSetErrorCallback( []( int, const char* desc ) { std::cerr << desc << "\n"; std::exit( EXIT_FAILURE ); } ); if( !glfwInit() ) { return -1; } glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 ); glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 3 ); glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE ); #ifdef __APPLE__ glfwWindowHint( GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE ); #endif glfwWindowHint( GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE ); /* Create a windowed mode window and its OpenGL context */ GLFWwindow* window = glfwCreateWindow( 640, 480, "Gaston", NULL, NULL ); if( !window ) { glfwTerminate(); return -1; } /* Make the window's context current */ glfwMakeContextCurrent( window ); if( glewInit() != GLEW_OK ) { std::cout << "glewunit(); failed\n"; } if( glewIsSupported( "GL_ARB_debug_output" ) ) { glEnable( GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB ); glDebugMessageControlARB( GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE ); glDebugMessageCallbackARB( []( GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar* message, const void* ) { std::cerr << "GL: " << message << std::endl; }, 0 ); } float positions[ 6 ] = { -0.5f, -0.5f, -.9f, .5f, 0.5f, 0.5f }; GLuint vao = 0; glCreateVertexArrays(1, &vao); glBindVertexArray(vao); unsigned int buffer; glGenBuffers( 1, &buffer ); glBindBuffer( GL_ARRAY_BUFFER, buffer ); glBufferData( GL_ARRAY_BUFFER, sizeof( positions ), positions, GL_STATIC_DRAW ); glEnableVertexAttribArray( 0 ); glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, sizeof( float ) * 2, 0 ); glBindBuffer( GL_ARRAY_BUFFER, 0 ); GLuint prog = glCreateProgram(); AttachShader( prog, GL_VERTEX_SHADER, vert ); AttachShader( prog, GL_FRAGMENT_SHADER, frag ); glLinkProgram( prog ); CheckStatus( prog, false ); glUseProgram( prog ); /* Loop until the user closes the window */ while( !glfwWindowShouldClose( window ) ) { /* Render here */ glClear( GL_COLOR_BUFFER_BIT ); glDrawArrays( GL_TRIANGLES, 0, 3 ); /* Swap front and back buffers */ glfwSwapBuffers( window ); /* Poll for and process events */ glfwPollEvents(); } glfwTerminate(); return 0; } 
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! I added these things and the program works fine.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.