Strange shader bug with no texture showing

I just encountered a rather strange bug. I’ll document it here, but it might be a little time before I can post replicating code as my example is quite complicated.

I have a program with two meshes. One has a shader attached to it, the other doesn’t. The second (without the shader) has a texture. When I draw them then only the mesh with a shader appears.

Experimenting leads to the following. Let’s call the meshes a and b.

  1. a has shader, b has texture => a drawn, b not.
  2. a has shader, b does not have texture (but has colour) => a drawn, b drawn.
  3. a does not have shader, b has texture => a drawn, b drawn
  4. a has shader, b has default shader and texture => a drawn, b drawn
  5. a has shader but is not drawn, b has texture => a not drawn, b drawn

It also appears that the order of drawing of a and b is immaterial. I think I see a “flash” whereby b is drawn initially and then disappears on subsequent draws.

So my guess is that when a is drawn then a shader is actually installed for b as well and this shader does not render the texture.

I’ve gotten round it by explicitly giving b a shader (case 4). I’ll try to pare down my program to a MWE that shows the bug.

I’ve seen some similar weirdness although never actually stopped to nail it down before. I also sometimes get weird not the texture I expected issues sometimes where you’ll get the made in codea watermark from video recording suddenly appearing as the mesh texture rather than what you thought you set.

I think this is fairly minimal. As shown, both meshes display. Instating the line a.shader = s then only the a rectangle shows. Further instating the line b.shader = s then both rectangles show again.

One thing to note: if I use addRect to add the rectangle to the a mesh then this behaviour doesn’t happen: both meshes display correctly. (I should say that this is not a feasible solution in my actual program.)

function setup()
    a = mesh()
    local o = vec2(WIDTH/2,HEIGHT/2)
    a.vertices = {
       o,
       o + vec2(0,-100),
       o + vec2(100,-100),
        o,
       o + vec2(100,0),
       o + vec2(100,-100)
    }
    local s = shader()
    s.vertexProgram = vertexProgram
    s.fragmentProgram = afragmentProgram
    --a.shader = s
    a:setColors(color(127,198,127,255))
    b = mesh()
    s = shader()
    s.vertexProgram = vertexProgram
    s.fragmentProgram = bfragmentProgram
    --b.shader = s
    b.texture = "Cargo Bot:Codea Icon"
    b:addRect(WIDTH/2,HEIGHT/2+200,200,200)

    b:setColors(255,255,0,255)
end

function draw()
    background(0, 0, 0, 255)

    a:draw()
    b:draw()
end

function touched(touch)
end

vertexProgram = [[
uniform mat4 modelViewProjection;

attribute vec4 position;
attribute vec4 color;
attribute vec2 texCoord;

varying lowp vec4 vColor;
varying highp vec2 vTexCoord;

void main()
{
    vColor = color;
    vTexCoord = texCoord;
    gl_Position = modelViewProjection * position;
}
]]

afragmentProgram = [[
precision highp float;
uniform lowp sampler2D texture;
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;

void main()
{
    lowp vec4 col = vColor;
    gl_FragColor = col;
}
]]
bfragmentProgram = [[
precision highp float;
uniform lowp sampler2D texture;
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;

void main()
{
    lowp vec4 col = texture2D( texture, vTexCoord );
    col *= vColor;
    gl_FragColor = col;
}
]]