OpenGL in JUCE: basic working example?


#1

Hi jucers,

I’m trying to do a simple OpenGL application in JUCE able to draw a few moving triangles. The OpenGL demo of the teapot in examples is pretty impressive, but it is too complex for me.

I’ve been following OpenGL tutorials, e.g:
http://www.learnopengl.com/#!Getting-Started/Hello-Triangle

But I have a lot of doubts! I don’t understand which lines go to initialise(), and which ones to render(). I also have problems with shaders source code (apparently #version 330 is not supported). I’ve been trying to solve every issue, but my final result is always a sad black screen.

My question:

Do you know about a OpenGL template for JUCE including some basic initialization to draw basic primitives? Let’s say some basic polygons that move along the screen. It would be very helpful!

Thanks a lot,
Emilio.


#2

Have you had a look at the OpenGLAppExample in the examples folder?


#3

I second looking at OpenGLAppExample. The code you’re currently working with in your project is the OpenGL template provided by the Projucer right?

To answer some of your specific questions:

initialise() is intended to be used to set up your OpenGL context before entering your render loop. Things that you don’t want to update-per frame (i.e. once) should be set here, like shader loading/compilation/linking, global states like culling and such.

In the specific tutorial, you linked, you want the initialization code to go into the initialise() function, and the “game loop” code to go into the render() function.

One of the biggest things to remember is to not get discouraged. OpenGL is very difficult (MUCH more than it should be), frustrating, and inconsistent, for a number of reasons relating to graphics card manufacturers and the standard’s history. The first big hurdle to getting something cool going to it is getting a context displaying in a window, which luckily JUCE helps us do much faster and better than any other OpenGL windowing library I’ve found (GLFW, GLUT, etc) so you’re on the right track. Be sure to check out the OpenGLHelpers namespace, it has a lot of extremely helpful code that’s normally extremely annoying to have to write for things like shader loading/compilation.

Lastly, I want to leave you with this guy’s YouTube playlist, it’s phenomenal and where I learned OpenGL from, eventually leading me to getting a job writing core rendering code for CAD software:

He uses Qt but all the code is very easy to transfer over to JUCE since the ideas of the interfaces between JUCE and Qt (and most other windowing systems) OpenGL of initialize/render is nearly identical.


#4

Have you looked at this:

There is a link to download the OpenGL example with a lot of comments and useful( I think) hints:


#5

Thanks you all,

I’ve checked the OpenGL examples you mention :slight_smile: (Alan’s contribution is especially helpful), thanks! For sure, as soon as I can get started with a simple working example, the resources you mention will be a good way to keep improving quickly. However, still I’m not able to simplify those examples to get what I am looking for: a very basic program drawing a few moving triangles.

I’ve started with Jamie King tutorial: https://www.youtube.com/watch?list=PLRwVmtr-pp06qT6ckboaOhnm9FxmzHpbY&v=6c1QYZAEP2M

Very nice! But at some point he’s able to draw a triangle with his Qt-based program, but it doesn’t seem to work in my JUCE-based program.

I created this repository with my code:

By the moment it basically contains:

    (...)
    void initialise() override
    {
        GLfloat verts[]
        {
            +0.0f, +1.0f,
            -1.0f, -1.0f,
            +1.0f, -1.0f,
        };

        // Now we have to copy these vertices to my graphic card
        GLuint myBufferID;
        openGLContext.extensions.glGenBuffers(1, &myBufferID);
        openGLContext.extensions.glBindBuffer(GL_ARRAY_BUFFER, myBufferID);
        openGLContext.extensions.glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);

        // Vertex attributes (needed to draw the triangle)
        openGLContext.extensions.glEnableVertexAttribArray(0);
        openGLContext.extensions.glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
    }

    void render() override
    {
        OpenGLHelpers::clear (Colours::black);
        glViewport(0, 0, getWidth(), getHeight());
        glDrawArrays(GL_TRIANGLES, 0, 3);
    }
    (...)

May you help me to get it working?
Thanks!


#6

I took a look at the code in your repo and oddly, I couldn’t find anything that looked weird. I’m not sure if maybe there’s something wrong with how you’re using the openGLContext functions, as I’ve never used JUCE’s implementation, I always use GLEW (which I would highly recommend, as it’s always up to date with the OpenGL spec and doesn’t require "openGlContext.extensions.*").


#7

Thanks! I will keep trying, in case I get something I will let you know.


#8

Ok! I got what I was looking for:

I simplified the teapot example in order to control the vertices to be drawn. Now it is not very modular anymore, but it is useful to understand the basic flow of calls to OpenGL functions.


#9

Hi Alan,

Many thanks for your extraordinary example. It is brilliant.

I’m completely new to OpenGL and JUCE and so I decided to take your example as starting point for a project of mine. I’m attempting to replace the teapot with a sphere. I loaded the .obj file into my JUCE project using the BinaryData class and I swapped it for the teapot. Now the issue is that when I launch the app, the texture is applied to the background and not to the object anymore.

How can I apply the texture to the new object?

Many thanks for your contribution,
Balandino.

Following the bit of code where I replaced the teapot with the sphere:

// The obj file could contain multiple objects or groups but in this example // only one object has been used (shapeFile.shapes.size() = 1) if (shapeFile.load (BinaryData::sphere_obj).wasOk()) for (int i = 0; i < shapeFile.shapes.size(); ++i) // Store the ith object info into a vertex buffer which itself is part // of a vertex buffer list. Again here inly one buffer will be used. vertexBuffers.add (new VertexBuffer (openGLContext, *shapeFile.shapes.getUnchecked(i)));

Following the result.


#10

Unfortunately working on other projects at the moment so no time look into. But my guess is that your OBJ file is in wrong format. Make sure you can read it correctly with other software.


#11

Thanks Alan for your answer. Let me know if you have the chance to have a look at it.

Yes it is, X Code opens in the right way. That’s why I don’t see why it shouldn’t work.

All best,
Balandino.


#12

Sorted, it was the file format. I did create a new obj file using blender and it worked amicably!


#13

For anyone looking for just the basics:

void render() override
{
    OpenGLHelpers::clear (Colours::black);

    // Points in 3D space
    GLfloat verts[]
    {
        -1.0f, -1.0f, 0.0f,
         1.0f, -1.0f, 0.0f,
         0.0f,  1.0f, 0.0f
    };

    // An ID for your buffer
    GLuint bufferID;

    // Get the ID
    openGLContext.extensions.glGenBuffers (1, &bufferID);

    // Configure the buffer
    openGLContext.extensions.glBindBuffer (GL_ARRAY_BUFFER, bufferID);

    // Let GL know about our veritices
    openGLContext.extensions.glBufferData (GL_ARRAY_BUFFER, sizeof (verts), verts, GL_STATIC_DRAW);

    openGLContext.extensions.glEnableVertexAttribArray (0);

    openGLContext.extensions.glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);

    // Draw three verticies
    glDrawArrays (GL_TRIANGLES, 0, 3);

    openGLContext.extensions.glDisableVertexAttribArray (0);
}

#14

Thanks!
There is a “openGLContext.extensions.” missing in the las statement, but your code helped me set up my view, really appreciated!


#15

Fixed. Thanks!