-1

I have follow several tutorials and i do not understand why this code does not display anything.

Please not that LoadShaders works great.

I have made a copy and paste so i do not think the problem comes from it...

#include <iostream>
#include <fstream>
#include <vector>  
#include <GL/glew.h>
#include <GL/gl.h>      
#include <GLFW/glfw3.h>

GLFWwindow* window;

int main(int argc, const char * argv[])
{
    if( !glfwInit() )
    {
        return -1;
    }
    glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // We want OpenGL 3.3
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);

    window = glfwCreateWindow(640, 480, "Test1", NULL, NULL);
    if( window == NULL )
    {
        return -1;
    }
    glfwMakeContextCurrent(window);

    glewExperimental = true; // Needed for core profile
    if (glewInit() != GLEW_OK)
    {
        return -1;
    }

    GLuint programID = LoadShaders( "SimpleVertexShader.vertexshader", "SimpleFragmentShader.fragmentshader" );

    glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
    glClearColor(0.0f, 1.0f, 1.0f, 1.0f);

    do
    {
        glfwPollEvents();

        glUseProgram(programID);
        float vertices[] = {-0.5, -0.5,   0.0, 0.5,   0.5, -0.5};
        glClear(GL_COLOR_BUFFER_BIT);
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
        glEnableVertexAttribArray(0);
        glDrawArrays(GL_TRIANGLES, 0, 3);
        glDisableVertexAttribArray(0);

        glfwSwapBuffers(window);
    }
    while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS && glfwWindowShouldClose(window) == 0 );

    glfwTerminate();

    return 0;
}

Thanks for your help

Note:

Here is SimpleFragmentShader.fragmentshader:

#version 330 core
out vec3 color;
void main()
{
    color = vec3(1,0,0);
}

And here is SimpleVertexShader.vertexshader:

#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
void main()
{
    gl_Position.xyz = vertexPosition_modelspace;
    gl_Position.w = 1.0;
}

Please note i have also tried to work on 3D coordinates like this:

float vertices[] = {-0.5, -0.5,0.0,   0.0, 0.5,0.0,   0.5, -0.5,0.0};

glClear(GL_COLOR_BUFFER_BIT);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Bob5421
  • 7,757
  • 14
  • 81
  • 175

2 Answers2

0

See docs.GL - OpenGL 3.3 - glVertexAttribPointer:

GL_INVALID_OPERATION is generated in the core context if there is no Vertex Array Object bound.

You have to create Vertex Array Object and a Vertex Buffer Object.

Generate (glGenVertexArrays) and bind (glBindVertexArray) a Vertex Array Object:

GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );

Generate (glGenBuffers) and bind (glBindBuffer) a Vertex Buffer Object:

GLuint vbo;
glGenBuffers( 1, &vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo );

Bind the buffer data (glBufferData), enable the vertex attribute and define the array of generic vertex attribute data:

float vertices[] = {-0.5, -0.5,   0.0, 0.5,   0.5, -0.5};
glBufferData( GL_ARRAY_BUFFER, 6 * sizeof( float ), vertices, GL_STATIC_DRAW );
glEnableVertexAttribArray( 0 );
glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 0, nullptr );
glBindVertexArray( 0 );

When you draw the mesh, you only have to bind the vertex array object:

glBindVertexArray( vao );
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray( 0 );


Note, since you are using a user defined out variable in your fragment shader, you should bind the fragment data location with glBindFragDataLocation. Note this has to be done after the fragment shader has been attached to the shader program, but before the shader program has been linked.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • That's only if the core context is enabled. If compatibility is used, his code is valid. – robthebloke Oct 03 '17 at 04:54
  • @robthebloke Yes this is mentioned in the answer "GL_INVALID_OPERATION is generated in the core context if there is no Vertex Array Object bound." and is wanted in the code of the question "We want OpenGL 3.3". – Rabbid76 Oct 03 '17 at 05:00
  • You have to opt into the core profile using GLFW_OPENGL_PROFILE – robthebloke Oct 03 '17 at 05:15
0

You aren't binding an output frag data location:

GLuint programID = LoadShaders( "SimpleVertexShader.vertexshader", "SimpleFragmentShader.fragmentshader" );

// make sure you set which colour is the output from the fragment shader!
glBindFragDataLocation(programID, 0, "color");

(That's assuming you are using OpenGL 3.3 on the desktop, and not OpenGL ES 3)


/edit And if you want an OpenGL 4.5 version:

#include <iostream>
#include <fstream>
#include <vector>  
#include <GL/glew.h>
#include <GL/gl.h>      
#include <GLFW/glfw3.h>

GLFWwindow* window;

int main(int argc, const char * argv[])
{
  if( !glfwInit() )
  {
    return -1;
  }
  glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing
  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); 
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);

  window = glfwCreateWindow(640, 480, "Test1", NULL, NULL);
  if( window == NULL )
  {
    return -1;
  }
  glfwMakeContextCurrent(window);

  glewExperimental = true; // Needed for core profile
  if (glewInit() != GLEW_OK)
  {
    return -1;
  }
  glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);

  GLuint programID = LoadShaders( "SimpleVertexShader.vertexshader", "SimpleFragmentShader.fragmentshader" );

  // make sure you set which colour is the output from the fragment shader!
  glBindFragDataLocation(programID, 0, "color");

  glClearColor(0.0f, 1.0f, 1.0f, 1.0f);

  GLuint vbo = 0, vao = 0;
  const float vertices[] = {-0.5, -0.5,   0.0, 0.5,   0.5, -0.5};

  // create the vbo identifier
  glCreateBuffers(1, &vbo);

  // load the vertex data into the vertex buffer object (using immutable read only storage)
  glNamedBufferStorage(vbo, 6 * sizeof(float), vertices, 0);

  // create the vertex array object (vao)
  GLuint vao = 0;
  glCreateVertexArrays(1, &vao);

  // attach vbo to slot 0 on the vao
  glVertexArrayVertexBuffer(vao, 0, vbo, 0, sizeof(float) * 2);

  // fetch attribute 0 from the buffer bound to slot 0
  glVertexArrayAttribBinding(vao, 0, 0);

  // enable the vertex attribute 0
  glEnableVertexArrayAttrib(vao, 0);

  // specify the data type found in attribute 0
  glVertexArrayAttribFormat(vao, 0, 2, GL_FLOAT, false, 0);

  do
  {
    glfwPollEvents();

    // specify which program to use
    glUseProgram(programID);

    // specify which buffers to bind to the shader inputs
    glBindVertexArray(vao);

    // draw the data 
    glDrawArrays(GL_TRIANGLES, 0, 3);

    // done with the vao binding
    glBindVertexArray(0);    

    glfwSwapBuffers(window);
  }
  while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS && glfwWindowShouldClose(window) == 0 );

  glfwTerminate();

  return 0;
}
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
robthebloke
  • 9,331
  • 9
  • 12
  • If you aren't binding the output fragment colour, nothing will display on screen. Assuming the OP is using the compatibility profile, then his posted code will work. – robthebloke Oct 03 '17 at 05:11
  • Given that there is a disagreement between how to spell 'colour', code that always binds to 'color' would be an extremely poor design. (and I have also taught OpenGL for many years to university students, so you get used to diagnosing the same usual problems) – robthebloke Oct 03 '17 at 05:25
  • It could also be a function that simply returns zero, or the first arg could be a fragment shader. Or the current working directory might be different from what the OP expects. For all you know the shaders may only have been attached to the program object. (FWIW whilst the spec says you need to call glBindFragDataLocation prior to linking, I'm not aware of any GPU where calling it after linking fails) – robthebloke Oct 03 '17 at 05:36