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
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
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/
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!