OpenGL ES 2.0 in Cocos2d-x

Long story short, establishing OpenGL ES 2.0 is slightly different than WebGL, but the basic principle is similar.

Cocos2d-x provides you with a few ..uh, inconvenient wrappers.. that can help you started with custom shaders but if you don’t have the knowledge in everything that is OpenGL it can get a bit hectic, plus it’s hard to find a good reference.

OpenGL is a gigantic topic so I’ll explain just the basic parts (plus I’m not an expert as well) so hopefully the below will helps you a bit.

Add Vertex Shader (triangle.vsh)

attribute vec4 a_position;

void main(void) {
    gl_Position = a_position;
}

and Fragment Shader (triangle.fsh)

void main(void) {
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

Add them to the compile resource list, like so
How to

Do some OpenGL ES

void HelloWorld::init() {

    // Creates a program object
    CCGLProgram *program = new CCGLProgram();

    // A (check below)
    bool loaded = program->initWithVertexShaderFilename("triangle.vsh","triangle.fsh");

    // Check if everything is ok
    if (!loaded) {
        CCLOG("oh, god no");
    }


    // B (check below)
    program->addAttribute(kCCAttributeNamePosition, 0);

    
    // link the programs
    program->link();
    
    // C (check below)
    program->updateUniforms();

    // D (check below)
    CCLOG("Program Log %s", program->programLog());

    // Set the program to the current node
    this->setShaderProgram(program);

    // Release it from the memory pool
    program->release();

    // Set the clear color, not required actually.
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

}

void HelloWorld::draw() {
    
    // Clear the color Buffer
    glClear(GL_COLOR_BUFFER_BIT);
    
    // E (check below)
    CC_NODE_DRAW_SETUP();
    
    // Draw the triangle
    GLfloat vVertices[9] = {
        0.0f, 0.5f, 0.0f,
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f
    };
    
    // F (check below)
    ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
    glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, 0, vVertices);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    
    // Not required, only for stats
    CC_INCREMENT_GL_DRAWS(1);
    
}

These are the necessary elements that an OpenGL needs, so let’s have a look;

A
bool loaded = program->initWithVertexShaderFilename("triangle.vsh","triangle.fsh");

initWithVertexShaderFilename as the name suggested, will loads all external files, compile, as well as attaching all the shaders into the program.

B
program->addAttribute(kCCAttributeNamePosition, 0);

addAttribute simply adds the attribute vec4 a_position; to 0, I’m not sure why Cocos2d-x have to make a function for it, because the actual call is just this;

glBindAttribLocation(programObject, index, attributeName);
C
program->updateUniforms();

During the compilation (Step A) Cocos2d-x will bind their own uniforms into your shaders.

"uniform mat4 CC_PMatrix;n"
"uniform mat4 CC_MVMatrix;n"
"uniform mat4 CC_MVPMatrix;n"
"uniform vec4 CC_Time;n"
"uniform vec4 CC_SinTime;n"
"uniform vec4 CC_CosTime;n"
"uniform vec4 CC_Random01;n"
"//CC INCLUDES ENDnn",
source,

Notice the end is source, which is our custom shaders.

D

Checking every step is absolutely necessary in OpenGL, since most of the times an error will not be reported, it will rather silently present you with a blank screen for you to stare into.

E
CC_NODE_DRAW_SETUP();

Gets the program, and sets the built-in uniforms value in step C.

F
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, 0, vVertices);
glDrawArrays(GL_TRIANGLES, 0, 3);

What glVertexAttribPointer does it retrieves the vertices from the buffer objects, so we need to tell it how to process those data, in order to understand it have a look at this interleaved array basics explanation.

glDrawArrays(GL_TRIANGLES, 0, 3); draws the primitives, there are 3 types of primitives which are Triangle, Lines, and Points, each one has its own types, again explaining those things in detail can have your mind tangled after a while, but in a nutshell GL_TRIANGLES simply means drawing 1 triangle by 3 given vertex (n/3).

ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); basically just enables the Vertex attribute array, although why does it need to be defined explicitly is a bit puzzling.

And here’s the result
Result

Not too exciting :p but you can plug in your own shaders now.

Resources

SIGGRAPH University : “An Introduction to OpenGL Programming”
OpenGL ES 2.0 programming guide
http://blog.db-in.com/all-about-opengl-es-2-x-part-1/

  1. Im using cocos2dx and im trying to draw a simple triangle using the “Node” class. I tried following your tutorial (except for a couple of deprecations, which i replaced) and i got a number of “OpenGL Error 0x501 [CCEAGLView swapBuffers] errors.”

    I tried to correct that by setting up my shaders differently, now the errors have stopped but i see nothing on screen!

    Do you have an example project of this i can look at?

    Thanks in advance!

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *