We talk about this topic about how to pass color in for each vertex in OpenGL ES 2.0 based on the tutorial about Tizen OpenGL ES:
https://developer.tizen.org/development/tutorials/native-application/graphics/opengl-es-0
If you have not read it, please read it first.
We focus on how you specify color for each vertex.
Firstly, in the shader program, gl_FragColor got the passed in color array at last, and pass it to the GPU to shading color for each vertex.
But how to pass the color in? We need to use the attribute vector in vertex shader to accept the color data passed from C++ codes. And pass the color from vertex shader to fragment shader through a same name varing vector.
/* Vertex Shader Source */
static const char vertex_shader[] =
"attribute vec4 a_position;\n"
"attribute vec4 a_color;\n"
"varying vec4 v_color;\n"
"\n"
"void main()\n"
"{\n"
" v_color = a_color;\n" // pass it to varying vector, which is same name with the varing vector in fragment shader.
" gl_Position = a_position;\n"
"}";
/* Fragment Shader Source */
static const char fragment_shader[] =
"#ifdef GL_ES\n"
"precision mediump float;\n"
"#endif\n"
"varying vec4 v_color;\n" // same name with the varing vector in vertex shader
"\n"
"void main (void)\n"
"{\n"
" gl_FragColor = v_color;\n"
"}";
Then you need to prepare the color for each vertex in C++ codes. Both vertices and colors are hold by float array. We need to define color for each vertex, color array and vertex array should be one to one relationship.
const float coords_vertices[] =
{
0.0f, 0.75f, 0.0f, // [0] top
-0.6f, -0.4f, 0.0f, // [1] left bottom
0.6f, -0.4f, 0.0f, // [2] right bottom
};
const float coords_colors[] =
{
1.0, 0.0, 0.0, 1.0, // [0] is red, color for coords_vertices[0]
0.0, 1.0, 0.0, 1.0, // [1] is green, color for coords_vertices[1]
0.0, 0.0, 1.0, 1.0, // [2] is blue, color for coords_vertices[2]
};
And if we draw triangles or lines by glDrawElements, we need to specify the drawing sequence of the vertices by an index array as below.
const int coords_indices_count = 6;
const unsigned short coords_indices[] =
{
0, 1,
1, 2,
2, 0
};
The function glDrawElements to use this index array would be like:
glDrawElements(GL_LINES, coords_indices_count, GL_UNSIGNED_SHORT, coords_indices);
Then in C++ codes, before drawing the objects, we need create shaders, load shader sources, compile shaders, create shader program, attach shaders, link shader program and use shader program.
static void init_shaders(Evas_Object *obj) {
appdata_s *ad = evas_object_data_get(obj, "ad");
const char *p;
p = vertex_shader;
ad->vtx_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(ad->vtx_shader, 1, &p, NULL);
glCompileShader(ad->vtx_shader);
p = fragment_shader;
ad->fgmt_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(ad->fgmt_shader, 1, &p, NULL);
glCompileShader(ad->fgmt_shader);
ad->program = glCreateProgram();
glAttachShader(ad->program, ad->vtx_shader);
glAttachShader(ad->program, ad->fgmt_shader);
glLinkProgram(ad->program);
ad->idx_position = glGetAttribLocation(ad->program, "a_position");
ad->idx_color = glGetAttribLocation(ad->program, "a_color");
ad->idx_mvp = glGetUniformLocation(ad->program, "u_mvpMatrix");
glUseProgram(ad->program);
}
We can see above bold lines that take the vertex array location and color array location in the shader out as pointer.
Then fill the arrays by previously delared vertex array and color array into these shader location when drawing the objects represented by the vertices.
static void draw_gl(Evas_Object *obj) {
appdata_s *ad = evas_object_data_get(obj, "ad");
int w, h;
if (!ad)
return;
elm_glview_size_get(obj, &w, &h);
if (!h)
return;
glViewport(0, 0, w, h);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glVertexAttribPointer(ad->idx_position, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), coords_vertices);
glVertexAttribPointer(ad->idx_color, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), coords_colors);
glEnableVertexAttribArray(ad->idx_position);
glEnableVertexAttribArray(ad->idx_color);
glDrawElements(GL_LINES, coords_indices_count, GL_UNSIGNED_SHORT, coords_indices);
glFlush();
display_fps();
}
Then the three lines would be drawn with the color defined to each vertex.