I have a microcomputer with GLES hardware acceleration. It uses risc-V archtechure so no GL drivers.
I'm currently working on adapting a QOpenGLWindow codebase to run on a device with GLES hardware acceleration.
Running this code in GL 3.2 softpipe draws everything perfectly, but because there is no HW acceleration I get less than 1 FPS:
#include <QApplication>
#include <QOpenGLFunctions>
#include <QOpenGLWindow>
#include <QTimer>
#include <QImage>
class OpenGLWindow : public QOpenGLWindow, protected QOpenGLFunctions
{
Q_OBJECT
public:
explicit OpenGLWindow(QWidget* parent = nullptr) : QOpenGLWindow() {
// Animation timer
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, [this]() {
this->angle += 1.0f;
this->update();
});
timer->start(1); // 60 кадров в секунду
}
~OpenGLWindow(){}
protected:
void initializeGL() override;
void paintGL() override;
void resizeGL(int w, int h) override;
private:
GLfloat arrow_vertices[9] = {
1.0f, 0.0f, 0.0f, // Вершина 1
-1.0f, 0.0f, 0.0f, // Вершина 2
0.0f, 1.0f, 0.0f // Вершина 3
};
GLfloat arrow_colors[9] = {
1.0f, 1.0f, 1.0f, // Вершина 1
1.0f, 1.0f, 1.0f, // Вершина 2
1.0f, 1.0f, 1.0f // Вершина 3
};
QImage horizontImage;
GLuint horizontID;
GLuint HUD_ID;
// Arrow angle
float angle = 0.0f;
// Arrow center
QPointF center;
QSurfaceFormat format;
QOpenGLFunctions *m_functions;
};
void OpenGLWindow::initializeGL()
{
// Initialize OpenGL ES
initializeOpenGLFunctions();
std::string glVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION));
std::string glslVer = reinterpret_cast<const char*>(glGetString(GL_SHADING_LANGUAGE_VERSION));
qDebug("glVer: %s\nglslVer: %s", glVersion.c_str(), glslVer.c_str());
// Enable 2D textures
glEnable(GL_TEXTURE_2D);
// Enable color blending for transparency
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
// Load the horizon image
horizontImage.load(":/resource/res/horizon.png");
horizontImage.convertTo(QImage::Format_RGBA8888);
// Create a texture for the PNG
glGenTextures(1, &horizontID);
glBindTexture(GL_TEXTURE_2D, horizontID);
// Set texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Load the PNG into the texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, horizontImage.width(), horizontImage.height(), 0,
GL_RGBA, GL_UNSIGNED_BYTE, horizontImage.bits());
// Create a texture for the watermark
glGenTextures(1, &HUD_ID);
glBindTexture(GL_TEXTURE_2D, HUD_ID);
// Set texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Load the watermark into the texture
QImage watermarkImage(":/resource/res/Desk_PIL.png");
watermarkImage.convertTo(QImage::Format_RGBA8888);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, watermarkImage.width(), watermarkImage.height(), 0,
GL_RGBA, GL_UNSIGNED_BYTE, watermarkImage.bits());
qDebug() << "First bit:" << watermarkImage.bits()[0] << watermarkImage.bits()[1] << watermarkImage.bits()[2] << watermarkImage.bits()[3];
glBindTexture(GL_TEXTURE_2D, 0);
// Set the background color
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
// Define the rotation center
center = QPointF(width() / 2, height() / 2);
}
void OpenGLWindow::paintGL()
{
// Clear the buffer
glClear(GL_COLOR_BUFFER_BIT);
// Draw the background
glLoadIdentity();
glTranslatef(0, sin(angle/60)*20, 0.0f); // Pitch oscillation
glRotatef(sin(angle/60/60)*0.05f, 0.0f, 0.0f, 1.0f); // Roll oscillation
glBindTexture(GL_TEXTURE_2D, horizontID); // Set the texture to the horizon
// Draw the rectangular background tile
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex2f(0, height());
glTexCoord2f(1.0f, 0.0f); glVertex2f(width(), height());
glTexCoord2f(1.0f, 1.0f); glVertex2f(width(),0);
glTexCoord2f(0.0f, 1.0f); glVertex2f(0,0);
glEnd();
// Set the projection matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f, width(), 0.0f, height(), -100.0f, 100.0f);
// Set the modelview matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Translate to the rotation center
glTranslatef(center.x(), center.y(), 0.0f);
// Rotate the arrow
glRotatef(angle, 0.0f, 0.0f, 1.0f);
// Scale the arrow
glScalef(10.0f,20.0f*3,1);
// Draw a triangle
glBindTexture(GL_TEXTURE_2D, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, arrow_vertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableClientState(GL_VERTEX_ARRAY);
// Draw a watermark
glLoadIdentity();
glBindTexture(GL_TEXTURE_2D, HUD_ID);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex2f(0, height());
glTexCoord2f(1.0f, 0.0f); glVertex2f(width(), height());
glTexCoord2f(1.0f, 1.0f); glVertex2f(width(),0);
glTexCoord2f(0.0f, 1.0f); glVertex2f(0,0);
glEnd();
}
void OpenGLWindow::resizeGL(int w, int h)
{
center = QPointF(w / 2, h / 2);
glViewport(0, 0, w, h);
}
static QSurfaceFormat createFormat(){
QSurfaceFormat format;
// OpenGL ES init
format.setRenderableType(QSurfaceFormat::OpenGLES);
format.setProfile(QSurfaceFormat::CoreProfile);
format.setVersion(3,0);
format.setDepthBufferSize(24);
format.setStencilBufferSize(8);
format.setSamples(4);
return format;
}
int main(int argc, char *argv[])
{
//// COMMENT FOR GL, UNCOMMENT FOR GLES
// QSurfaceFormat format = createFormat();
// QSurfaceFormat::setDefaultFormat(format);
// QCoreApplication::setAttribute(Qt::AA_UseOpenGLES, true);
// QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL, true);
// QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL, false);
QApplication app(argc, argv);
OpenGLWindow w;
w.show();
w.showFullScreen();
return app.exec();
}
However, when I run the code under GLES, I only see a green background. The vertices and textures are not being rendered.
Why might this be happening?
Why might this be happening?
You can't use fixed-function pipeline functionality like glBegin()
& friends on OpenGL ES 2.0+ contexts.
You'll need to port your logic over to the programmable pipeline: shaders, VAOs, client-side matrix stack, etc.