PDA

View Full Version : Initialization and convex fill error! Amateur hour!



juhanikarlsson
03-20-2016, 09:21 AM
Yo talented fellas!

I hope you can help me : )
I using Nanogui and NanoVG for my application. There I have inherited the screen for my viewport object and have implemented the virtual draw functions.
Everything seems to work nice in my demo application like this.

https://www.dropbox.com/s/nyogn04hovehqys/testApplication.jpg?dl=0


namespace sintonic {

// Default constructor
Viewport::Viewport(const Vector2i size, const std::string caption, bool resize, bool fullscreen) : Screen(size, caption, resize, fullscreen) {


};

void Viewport::drawAll() {
glClearColor(mBackground[0], mBackground[1], mBackground[2], 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

initGL();
drawContents();
drawWidgets();

glfwSwapBuffers(mGLFWWindow);
}

void Viewport::drawContents() {
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}

void Viewport::initGL() {
// Temporary triangle for GL
GLfloat vertices[] = {
0.5f, 0.5f, 0.0f, // Top Right
0.5f, -0.5f, 0.0f, // Bottom Right
-0.5f, -0.5f, 0.0f, // Bottom Left
-0.5f, 0.5f, 0.0f // Top Left
};
GLuint indices[] = { // Note that we start from 0!
0, 1, 3, // First Triangle
1, 2, 3 // Second Triangle
};

// Build and compile our shader program
// Vertex shader
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// Check for compile time errors
GLint success;
GLchar infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Fragment shader
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// Check for compile time errors
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Link shaders
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// Check for linking errors
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}

GLuint VBO, VAO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
// Bind the Vertex Array Object first, then bind and set vertex buffer(s) and attribute pointer(s).
glBindVertexArray(VAO);

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);

glBindBuffer(GL_ARRAY_BUFFER, 0); // Note that this is allowed, the call to glVertexAttribPointer registered VBO as the currently bound vertex buffer object so afterwards we can safely unbind

glBindVertexArray(0); // Unbind VAO (it's always a good thing to unbind any buffer/array to prevent strange bugs), remember: do NOT unbind the EBO, keep it bound to this VAO

// Draw our first triangle
glUseProgram(shaderProgram);
glBindVertexArray(VAO);

}
}

However! If I change my initGL() to the class constructor I get Error 00000502 after convex fill ?
Like this.


// Default constructor
Viewport::Viewport(const Vector2i size, const std::string caption, bool resize, bool fullscreen) : Screen(size, caption, resize, fullscreen) {

initGL();
};

I would like to init the buffers only once and then simply draw them every frame. How could I acheve that and what I`m doing wrong? Uhh...

I bet I`m doing stupid things but please sensei help me!! : )

Thanks,
- J

Spoops
03-20-2016, 09:48 AM
The constructor is likely called before any OpenGL context is created, but you shouldn't put any OpenGL code in constructors or destructors. Check this wiki page (https://www.opengl.org/wiki/Common_Mistakes#The_Object_Oriented_Language_Probl em) about why you shouldn't wrap OpenGL objects in classes.

juhanikarlsson
03-21-2016, 04:49 AM
Thank you Spoops for answering my foolish questions!

Youre right! Also I had put my mind so much into writing raytracer that I forgot that openGL is very different. I realized that its actually my OBJECTS that need to draw themselves not the VIEWPORT!
I will also need to remove all those constructor initializations and go with member functions? The wiki page dosen`t give single solution to initializing objects, though.

I`m doing now simple scene graph and hopefully it will work better when I do the changes! : )

Thanks a lot for sharing your wisdom man,
- J

Spoops
03-21-2016, 11:22 AM
I'd say it's better to only have one monolithic class that makes all the OpenGL calls, as you will get lost very often when delegating code to objects. The actual objects should only contain data and act on that data.

If you want to keep it simple though, just create init and destroy member functions.

juhanikarlsson
03-22-2016, 03:15 AM
Ah! Okey.

Then I think I was doing it more or less correctly before(without the member functions tho)

My confusion comes partly from the Nanogui as well.. I don`t quite know how to integrate the main GL drawing loop into it. The author is so busy and the documentation is sparse.
Also he`s so badass coder that he`s examples are bit too advanced for me. I`m trying to use this as example as it has GL viewport https://github.com/wjakob/instant-meshes

I will post my progress once I get forward a bit haha : )

Thanks a lot,
- J