Hi,
I’m trying to create a single program to draw a point/line/rectangle and point array. The code is below:
#define COORDS_PER_VERTEX 3
GLfloat ftransp[16], f255[256];
#define POINTS_VERTEX_CODE \
"attribute vec4 a_Position; " \
"attribute vec4 a_Color; " \
"varying vec4 v_Color; " \
"uniform mat4 projectionMatrix; " \
"void main() {v_Color = a_Color; gl_Position = a_Position * projectionMatrix;}"
#define POINTS_FRAGMENT_CODE \
"precision mediump float;" \
"varying vec4 v_Color;" \
"uniform vec4 one_Color;" \
"uniform bool singleColor;" \
"void main() {gl_FragColor = singleColor ? one_Color : v_Color;}"
static GLuint pointsProgram;
static GLuint pointsPosition;
static GLuint pointsColor;
static GLuint pointsSingleColor,pointsOneColor;
static GLushort rectOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices
GLuint loadShader(GLenum shaderType, const char* pSource)
{
GLint ret=1;
GLuint shader = glCreateShader(shaderType);
glShaderSource(shader, 1, &pSource, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &ret);
if(!ret)
{
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &ret);
GLchar buffer[ret];
glGetShaderInfoLog(shader, ret, &ret, buffer);
debug("Shader compiler error: %s",buffer);
}
return shader;
}
static void initPoints()
{
GLint ret=1;
pointsProgram = glCreateProgram();
glAttachShader(pointsProgram, loadShader(GL_VERTEX_SHADER, POINTS_VERTEX_CODE));
glAttachShader(pointsProgram, loadShader(GL_FRAGMENT_SHADER, POINTS_FRAGMENT_CODE));
glLinkProgram(pointsProgram);
glGetProgramiv(pointsProgram, GL_LINK_STATUS, &ret);
if (!ret)
{
glGetProgramiv(pointsProgram, GL_INFO_LOG_LENGTH, &ret);
GLchar buffer[ret];
glGetProgramInfoLog(pointsProgram, ret, &ret, buffer);
debug("Link error: %s",buffer);
}
glUseProgram(pointsProgram);
pointsOneColor = glGetUniformLocation(pointsProgram, "one_Color");
pointsSingleColor = glGetUniformLocation(pointsProgram, "singleColor");
pointsColor = glGetAttribLocation(pointsProgram, "a_Color");
pointsPosition = glGetAttribLocation(pointsProgram, "a_Position");
glEnableVertexAttribArray(pointsColor);
glEnableVertexAttribArray(pointsPosition);
}
void glDrawPixels(Context c, int32 n)
{
glUniform1i(pointsSingleColor, 0);
glVertexAttribPointer(pointsColor, 4 * n, GL_FLOAT, GL_FALSE, 4 * sizeof(float), c->glcolors);
glVertexAttribPointer(pointsPosition, COORDS_PER_VERTEX * n, GL_FLOAT, GL_FALSE, COORDS_PER_VERTEX * sizeof(float), c->glcoords);
glDrawArrays(GL_POINTS, 0,n);
}
void glDrawPixel(Context c, int32 x, int32 y, int32 rgb)
{
GLfloat* coords = c->glcoords;
PixelConv pc;
pc.pixel = rgb;
coords[0] = x;
coords[1] = y;
glUniform1i(pointsSingleColor, 1);
glUniform4f(pointsOneColor, f255[pc.r], f255[pc.g], f255[pc.b], 1);
glVertexAttribPointer(pointsPosition, COORDS_PER_VERTEX, GL_FLOAT, GL_FALSE, COORDS_PER_VERTEX * sizeof(float), coords); // Prepare the triangle coordinate data
glDrawArrays(GL_POINTS, 0,1);
}
void glDrawLine(Context c, int32 x1, int32 y1, int32 x2, int32 y2, int32 rgb)
{
GLfloat* coords = c->glcoords;
PixelConv pc;
pc.pixel = rgb;
coords[0] = x1;
coords[1] = y1;
coords[3] = x2;
coords[4] = y2;
glUniform1i(pointsSingleColor, 1);
glUniform4f(pointsOneColor, f255[pc.r], f255[pc.g], f255[pc.b], 1);
glVertexAttribPointer(pointsPosition, COORDS_PER_VERTEX, GL_FLOAT, GL_FALSE, COORDS_PER_VERTEX * sizeof(float), coords); // Prepare the triangle coordinate data
glDrawArrays(GL_LINES, 0,2);
}
void glFillRect(Context c, int32 x, int32 y, int32 w, int32 h, int32 rgb)
{
GLfloat* coords = c->glcoords;
PixelConv pc;
pc.pixel = rgb;
coords[0] = x;
coords[1] = y;
coords[3] = x;
coords[4] = y+h;
coords[6] = x+w;
coords[7] = y+h;
coords[9] = x+w;
coords[10] = y;
glUniform1i(pointsSingleColor, 0);
glUniform4f(pointsOneColor, f255[pc.r], f255[pc.g], f255[pc.b], 1);
glVertexAttribPointer(pointsPosition, COORDS_PER_VERTEX, GL_FLOAT, GL_FALSE, COORDS_PER_VERTEX * sizeof(float), coords); // Prepare the triangle coordinate data
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, rectOrder); // GL_LINES, GL_TRIANGLES, GL_POINTS
}
static void setProjectionMatrix(GLfloat w, GLfloat h)
{
GLfloat mat[16] =
{
2.0/w, 0.0, 0.0, -1.0,
0.0, -2.0/h, 0.0, 1.0,
0.0, 0.0, -1.0, 0.0,
0.0, 0.0, 0.0, 1.0
};
glUniformMatrix4fv(glGetUniformLocation(pointsProgram , "projectionMatrix"), 1, 0, mat);
}
The shader code compiles and links without errors; however, all i get is a black screen. If i change the shader code to:
#define POINTS_VERTEX_CODE \
"attribute vec4 a_Position; attribute vec4 a_Color; varying vec4 v_Color; " \
"uniform mat4 projectionMatrix; " \
"void main() {v_Color = a_Color; gl_Position = a_Position * projectionMatrix;}"
#define POINTS_FRAGMENT_CODE \
"precision mediump float;" \
"varying vec4 v_Color;" \
"void main() {gl_FragColor = v_Color;}"
static void initPoints()
{
pointsProgram = glCreateProgram();
glAttachShader(pointsProgram, loadShader(GL_VERTEX_SHADER, POINTS_VERTEX_CODE));
glAttachShader(pointsProgram, loadShader(GL_FRAGMENT_SHADER, POINTS_FRAGMENT_CODE));
glLinkProgram(pointsProgram);
glUseProgram(pointsProgram);
pointsColor = glGetAttribLocation(pointsProgram, "a_Color");
pointsPosition = glGetAttribLocation(pointsProgram, "a_Position"); // get handle to vertex shader's vPosition member
glEnableVertexAttribArray(pointsColor); // Enable a handle to the colors - since this is the only one used, keep it enabled all the time
glEnableVertexAttribArray(pointsPosition); // Enable a handle to the vertices - since this is the only one used, keep it enabled all the time
}
void glDrawPixels(Context c, int32 n)
{
glUseProgram(pointsProgram);
glVertexAttribPointer(pointsColor, 4 * n, GL_FLOAT, GL_FALSE, 4 * sizeof(float), c->glcolors);
glVertexAttribPointer(pointsPosition, COORDS_PER_VERTEX * n, GL_FLOAT, GL_FALSE, COORDS_PER_VERTEX * sizeof(float), c->glcoords);
glDrawArrays(GL_POINTS, 0,n);
}
void glDrawPixel(Context c, int32 x, int32 y, int32 rgb)
{
GLfloat* coords = c->glcoords;
GLfloat* colors = c->glcolors;
PixelConv pc;
pc.pixel = rgb;
coords[0] = x;
coords[1] = y;
colors[0] = f255[pc.r];
colors[1] = f255[pc.g];
colors[2] = f255[pc.b];
colors[3] = 1;
glUseProgram(pointsProgram);
glVertexAttribPointer(pointsColor, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), colors);
glVertexAttribPointer(pointsPosition, COORDS_PER_VERTEX, GL_FLOAT, GL_FALSE, COORDS_PER_VERTEX * sizeof(float), coords); // Prepare the triangle coordinate data
glDrawArrays(GL_POINTS, 0,1);
}
void glDrawLine(Context c, int32 x1, int32 y1, int32 x2, int32 y2, int32 rgb)
{
GLfloat* coords = c->glcoords;
GLfloat* colors = c->glcolors;
PixelConv pc;
pc.pixel = rgb;
coords[0] = x1;
coords[1] = y1;
coords[3] = x2;
coords[4] = y2;
colors[0] = colors[4] = f255[pc.r];
colors[1] = colors[5] = f255[pc.g];
colors[2] = colors[6] = f255[pc.b];
colors[3] = colors[7] = 1;
glUseProgram(pointsProgram);
glVertexAttribPointer(pointsColor, 4*2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), colors);
glVertexAttribPointer(pointsPosition, COORDS_PER_VERTEX, GL_FLOAT, GL_FALSE, COORDS_PER_VERTEX * sizeof(float), coords); // Prepare the triangle coordinate data
glDrawArrays(GL_LINES, 0,2);
}
void glFillRect(Context c, int32 x, int32 y, int32 w, int32 h, int32 rgb)
{
GLfloat* coords = c->glcoords;
GLfloat* colors = c->glcolors;
PixelConv pc;
pc.pixel = rgb;
coords[0] = x;
coords[1] = y;
coords[3] = x;
coords[4] = y+h;
coords[6] = x+w;
coords[7] = y+h;
coords[9] = x+w;
coords[10] = y;
colors[0] = colors[4] = colors[8] = colors[12] = colors[16] = colors[20] = f255[pc.r];
colors[1] = colors[5] = colors[9] = colors[13] = colors[17] = colors[21] = f255[pc.g];
colors[2] = colors[6] = colors[10] = colors[14] = colors[18] = colors[22] = f255[pc.b];
colors[3] = colors[7] = colors[11] = colors[15] = colors[19] = colors[23] = 1;
glUseProgram(pointsProgram);
glVertexAttribPointer(pointsColor, 4*6, GL_FLOAT, GL_FALSE, 4 * sizeof(float), colors);
glVertexAttribPointer(pointsPosition, COORDS_PER_VERTEX, GL_FLOAT, GL_FALSE, COORDS_PER_VERTEX * sizeof(float), coords); // Prepare the triangle coordinate data
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, rectOrder); // GL_LINES, GL_TRIANGLES, GL_POINTS
}
… then everything works. Actually, i’m trying to figure how to make the if/else (or ?: ) work to use with other things too.
Thanks in advance,
guich