Hello Juce folks,
I decided to ask you about a strange problem. Since I tried to find a solution myself but could not.
The problem is:
if I’m adding OpenGL component to the standard component. Then all the components on the background is flickering with black color.
This is not happening on Mac OS X or in the iOS simulator. It’s happening only with a real device. (I tried with many… iPhone, iPad 13, iPad 11, even with lower iOS versions).
Some observations:
// 1. The flickering only appears if I’m attaching OpenGL component to the “*this”.
openGLContext.attachTo(*this);
// 2. But if I'm adding to the top component, then everything is fine.
openGLContext.attachTo(*getTopLevelComponent());
I would leave it as it is with the getTopLevelComponent, but the the whole system getting very, very slow in this case. Like I feel it draws all the components to the openGL as big picture. (not sure… I’m not a specialist), but if with attachTo “*this”, then it’s fast, but the flickering can appear any time.
Some notes about the code:
All my non-opengl components uses:
setBufferedToImage(true); // but even if I remove this, I still see flickering issue.
setOpaque(true);
Attached a video of this issue (the YELLOW/ORANGE rect, this is OpenGL Component): Juce OpenGL my flicking issue (private video) - YouTube
Thank you!
OpenGL Component:
#include “wave_table_gl.h”
#include “…/…/…/…/…/common/gui_colors.h”
namespace wks::gui {
WaveTableGL::WaveTableGL() {
// Indicates that no part of this Component is transparent.
setOpaque(true);
// Tell the context to repaint on a loop.
// openGLContext.setContinuousRepainting(true);
setVisible (true);
openGLContext.setContinuousRepainting (false);
// openGLContext.setOpenGLVersionRequired(juce::OpenGLContext::OpenGLVersion::openGL3_2);
}
WaveTableGL::~WaveTableGL() {
// Tell the context to stop using this Component.
openGLContext.detach();
}
void WaveTableGL::initialise() {
}
void WaveTableGL::shutdown() {
}
void WaveTableGL::render() {
}
void WaveTableGL::newOpenGLContextCreated() {
// Generate 1 buffer, using our vbo variable to store its ID.
openGLContext.extensions.glGenBuffers(1, &vbo);
// Generate 1 more buffer, this time using our IBO variable.
openGLContext.extensions.glGenBuffers(1, &ibo);
// Create 4 vertices each with a different colour.
vertexBuffer = {
// Vertex 0
{
{-1.0f, 1.0f}, // (-0.5, 0.5)
{1.f, 0.f, 0.f, 1.f} // Red
},
// Vertex 1
{
{1.0f, 1.0f}, // (0.5, 0.5)
{1.f, 0.5f, 0.f, 1.f} // Orange
},
// Vertex 2
{
{1.0f, -1.0f}, // (0.5, -0.5)
{1.f, 1.f, 0.f, 1.f} // Yellow
},
// Vertex 3
{
{-1.0f, -1.0f}, // (-0.5, -0.5)
{1.f, 0.f, 1.f, 1.f} // Purple
}
};
// We need 6 indices, 1 for each corner of the two triangles.
indexBuffer = {
0, 1, 2,
0, 2, 3
};
// Bind the VBO.
openGLContext.extensions.glBindBuffer(GL_ARRAY_BUFFER, vbo);
// Send the vertices data.
openGLContext.extensions.glBufferData(
GL_ARRAY_BUFFER, // The type of data we're sending.
sizeof(Vertex) * vertexBuffer.size(), // The size (in bytes) of the data.
vertexBuffer.data(), // A pointer to the actual data.
GL_STATIC_DRAW // How we want the buffer to be drawn.
);
// Bind the IBO.
openGLContext.extensions.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
// Send the indices data.
openGLContext.extensions.glBufferData(
GL_ELEMENT_ARRAY_BUFFER,
sizeof(unsigned int) * indexBuffer.size(),
indexBuffer.data(),
GL_STATIC_DRAW
);
// ...
vertexShader =
"attribute vec4 position;\n"
"\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = position;\n"
"}\n";
fragmentShader =
#if JUCE_OPENGL_ES
"varying lowp vec4 destinationColour;\n"
#else
"varying vec4 destinationColour;\n"
#endif
"\n"
"void main()\n"
"{\n"
" gl_FragColor =vec4(0.95, 0.57, 0.03, 0.7);\n"
"}\n";
// Create an instance of OpenGLShaderProgram
shaderProgram.reset(new OpenGLShaderProgram(openGLContext));
// Compile and link the shader.
// Each of these methods will return false if something goes wrong so we'll
// wrap them in an if statement
if (shaderProgram->addVertexShader(vertexShader)
&& shaderProgram->addFragmentShader(fragmentShader)
&& shaderProgram->link()) {
// No compilation errors - set the shader program to be active
shaderProgram->use();
} else {
// Oops - something went wrong with our shaders!
// Check the output window of your IDE to see what the error might be.
printf("!!!!!ERROR SHADER !!!!!!");
jassertfalse;
}
}
void WaveTableGL::renderOpenGL() {
// Clear the screen by filling it with black.
OpenGLHelpers::clear(colors::body);
// Tell the renderer to use this shader program
shaderProgram->use();
openGLContext.extensions.glBindBuffer(GL_ARRAY_BUFFER, vbo);
openGLContext.extensions.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
// Enable the position attribute.
openGLContext.extensions.glVertexAttribPointer(
0, // The attribute's index (AKA location).
2, // How many values this attribute contains.
GL_FLOAT, // The attribute's type (float).
GL_FALSE, // Tells OpenGL NOT to normalise the values.
sizeof(Vertex), // How many bytes to move to find the attribute with
// the same index in the next vertex.
nullptr // How many bytes to move from the start of this vertex
// to find this attribute (the default is 0 so we just
// pass nullptr here).
);
openGLContext.extensions.glEnableVertexAttribArray(0);
// Enable to colour attribute.
openGLContext.extensions.glVertexAttribPointer(
1, // This attribute has an index of 1
4, // This time we have four values for the
// attribute (r, g, b, a)
GL_FLOAT,
GL_FALSE,
sizeof(Vertex),
(GLvoid *) (sizeof(float) * 2) // This attribute comes after the
// position attribute in the Vertex
// struct, so we need to skip over the
// size of the position array to find
// the start of this attribute.
);
openGLContext.extensions.glEnableVertexAttribArray(1);
glDrawElements(
GL_TRIANGLES, // Tell OpenGL to render triangles.
indexBuffer.size(), // How many indices we have.
GL_UNSIGNED_INT, // What type our indices are.
nullptr // We already gave OpenGL our indices so we don't
// need to pass that again here, so pass nullptr.
);
openGLContext.extensions.glDisableVertexAttribArray(0);
openGLContext.extensions.glDisableVertexAttribArray(1);
}
void WaveTableGL::openGLContextClosing() {
}
void WaveTableGL::paint(Graphics &g) {
}
void WaveTableGL::parentHierarchyChanged() {
openGLContext.detach();
// Finally - we attach the context to this Component.
openGLContext.attachTo(*this);
}
}