Conflict drawing on OpenGLES on iOS

2019-08-09 23:39发布

问题:

I'm writing an app allows drawing free style (using finger) and drawing image. I posted one of my problems at OpenGL ES glFragColor depend on if condition on Fragment shader in iOS. Thanks for many suggestions, I solved that. Now I still have another new issue.

I have 2 programs which have id PROGRAM_POINT (drawing free style) and PROGRAM_POINT_0 (draw image). Those are initialized. Each program has a pair of shader files. PROGRAM_POINT has shader files named point.vsh and point.fsh. For PROGRAM_POINT_0 is texture.vsh and texture.fsh.

Here are these files

---- point.vsh ------

attribute vec4 inVertex;

uniform mat4 MVP;
uniform float pointSize;
uniform lowp vec4 vertexColor;

varying lowp vec4 color;

void main()
{
    gl_Position = MVP * inVertex;
    gl_PointSize = pointSize;
    color = vertexColor;
}

---- point.fsh -------

precision mediump float;

uniform sampler2D texture;
varying lowp vec4 color;

void main()
{
    //Drawing point
    gl_FragColor = color * texture2D(texture, gl_PointCoord);
}

---- texture.vsh --------

attribute vec4 a_Position;
attribute vec2 a_TextureCoordinates;

varying vec2 v_TextureCoordinates;

void main()
{
    v_TextureCoordinates = a_TextureCoordinates;
    gl_Position = a_Position;
}

---- texture.fsh ------

precision mediump float;

uniform sampler2D u_TextureUnit;
varying vec2 v_TextureCoordinates;

void main()
{
    //Draw texture
    gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates);
}

Besides, here are the drawing free style and image

--- Drawing free style -----

    glBindBuffer(GL_ARRAY_BUFFER, vboId);
    glBufferData(GL_ARRAY_BUFFER, vertexCount*2*sizeof(GLfloat), vertexBuffer, GL_DYNAMIC_DRAW);

    glEnableVertexAttribArray(ATTRIB_VERTEX);
    glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, 0);

    // the brush texture will be bound to texture unit 0
    glUniform1i(program[PROGRAM_POINT].uniform[UNIFORM_TEXTURE], 0);

    glUseProgram(program[PROGRAM_POINT].id);
    glDrawArrays(GL_POINTS, 0, (int)vertexCount);

--- Drawing image -----

    GLuint a_position_location = glGetAttribLocation(program[PROGRAM_POINT_0].id, "a_Position");
    GLuint a_texture_coordinates_location = glGetAttribLocation(program[PROGRAM_POINT_0].id, "a_TextureCoordinates");
    GLuint u_texture_unit_location = glGetUniformLocation(program[PROGRAM_POINT_0].id, "u_TextureUnit");

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texName);
    glUniform1i(u_texture_unit_location, 0);

    const float textrect[] = {-1.0f, -1.0f, 0.0f, 0.0f,
        -1.0f,  1.0f, 0.0f, 1.0f,
        1.0f, -1.0f, 1.0f, 0.0f,
        1.0f,  1.0f, 1.0f, 1.0f};

    glBindBuffer(GL_ARRAY_BUFFER, vboId_1);
    glBufferData(GL_ARRAY_BUFFER, sizeof(textrect), textrect, GL_STATIC_DRAW);

    glVertexAttribPointer(a_position_location, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(0));
    glVertexAttribPointer(a_texture_coordinates_location, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));

    glEnableVertexAttribArray(a_position_location);
    glEnableVertexAttribArray(a_texture_coordinates_location);

    glUseProgram(program[PROGRAM_POINT_0].id);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    [context presentRenderbuffer:GL_RENDERBUFFER];

And now the issue happens if I do the following steps:

  • Drawing free style (still fine)

  • Drawing image (still fine)

  • Drawing free style again (PROBLEM HAPPEN!!!)

The colors of the number 3 and 4 are changed and seems terrible. I suppose does it merged or conflicted after drawing image. Do I need clear the buffer after drawing image

回答1:

point.fsh fragment shader uses a texture, but your "Drawing free style" GL code doesn't have glBindTexture. So it will use the last glBindTexture-ed texture.

Also, "Drawing free style" enables one vertex attribute array.

glEnableVertexAttribArray(ATTRIB_VERTEX)

However "Drawing image" enables two attribute arrays.

glEnableVertexAttribArray(a_position_location);
glEnableVertexAttribArray(a_texture_coordinates_location);

You should call glDisableVertexAttribArray before another glDrawArrays.

Or you can use VAO. Please take a look at the Apple Document.



回答2:

I've found the solution, just simply re-bind brush texture (texture for drawing free style) after drawing image. Drawing image will bind another texture to buffer and then continue drawing free style cause openGLES still uses the previous binding texture, in this case is the image.