Unsolved Problem rendering sphere in Mac and QOpenGLWidget (works on linux and windows)
-
Hi,
I'm developing a plugin for my application, and that plugin has a QOpenGLWidget on which i render a normal sphere. This is how it looks on Windows and Mac:
However, on Mac, the same code results in this:
Here is the relevant code:
#include "src/normalselectorwidget.h" #include <math.h> #include <QOpenGLFramebufferObject> #include <QOpenGLVersionProfile> #include <QOpenGLVertexArrayObject> #include <QOpenGLFunctions> #include <QMouseEvent> #include <QThread> #define PI 3.14159265359 void NormalSelectorWidget::renderSphere() { sphereVAO.bind(); glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_INT, 0); } NormalSelectorWidget::NormalSelectorWidget(QWidget *parent) { } void NormalSelectorWidget::initializeGL(){ initializeOpenGLFunctions(); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glClearColor(0.5, 0.5, 1.0, 1.0); glEnable(GL_DEPTH_TEST); setUpdateBehavior(QOpenGLWidget::PartialUpdate); sphere.link(); sphere.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/shaders/sphere_vertex.glsl"); sphere.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/shaders/sphere_fragment.glsl"); /* Prepare sphere */ plane.link(); plane.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/shaders/plane_vertex.glsl"); plane.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/shaders/plane_fragment.glsl"); if (!sphereVAO.isCreated()) { sphereVAO.create(); unsigned int vbo, ebo; glGenBuffers(1, &vbo); glGenBuffers(1, &ebo); QVector<QVector3D> positions; QVector<QVector2D> uv; QVector<QVector3D> normals; std::vector<unsigned int> indices; const unsigned int X_SEGMENTS = 64; const unsigned int Y_SEGMENTS = 64; for (unsigned int y = 0; y <= Y_SEGMENTS; ++y) { for (unsigned int x = 0; x <= X_SEGMENTS; ++x) { float xSegment = (float)x / (float)X_SEGMENTS; float ySegment = (float)y / (float)Y_SEGMENTS; float xPos = cos(xSegment * 2.0f * PI) * sin(ySegment * PI); float yPos = cos(ySegment * PI); float zPos = sin(xSegment * 2.0f * PI) * sin(ySegment * PI); positions.push_back(QVector3D(xPos, yPos, zPos)); uv.push_back(QVector2D(xSegment, ySegment)); normals.push_back(QVector3D(xPos, yPos, zPos)); } } bool oddRow = false; for (int y = 0; y < Y_SEGMENTS; ++y) { if (!oddRow) // even rows: y == 0, y == 2; and so on { for (int x = 0; x <= X_SEGMENTS; ++x) { indices.push_back(y * (X_SEGMENTS + 1) + x); indices.push_back((y + 1) * (X_SEGMENTS + 1) + x); } } else { for (int x = X_SEGMENTS; x >= 0; --x) { indices.push_back((y + 1) * (X_SEGMENTS + 1) + x); indices.push_back(y * (X_SEGMENTS + 1) + x); } } oddRow = !oddRow; } indexCount = indices.size(); std::vector<float> data; for (int i = 0; i < positions.size(); ++i) { data.push_back(positions[i].x()); data.push_back(positions[i].y()); data.push_back(positions[i].z()); if (uv.size() > 0) { data.push_back(uv[i].x()); data.push_back(uv[i].y()); } if (normals.size() > 0) { data.push_back(normals[i].x()); data.push_back(normals[i].y()); data.push_back(normals[i].z()); } } sphereVAO.bind(); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(float), &data[0], GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW); float stride = (3 + 2 + 3) * sizeof(float); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, stride, (void*)(3 * sizeof(float))); glEnableVertexAttribArray(2); glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, stride, (void*)(5 * sizeof(float))); } /* Prepare Plante */ planeVAO.create(); plane.link(); float vertices[] = { -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, // bot left 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, // bot right 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, // top right -1.0f, 1.0f, 0.0f, 0.0f, 0.0f // top left }; QOpenGLVertexArrayObject VAO; QOpenGLBuffer VBO; planeVAO.bind(); VBO.create(); VBO.bind(); VBO.allocate(vertices, sizeof(vertices)); int vertexLocation = plane.attributeLocation("aPos"); glVertexAttribPointer(static_cast<GLuint>(vertexLocation), 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), nullptr); glEnableVertexAttribArray(static_cast<GLuint>(vertexLocation)); int texCoordLocation = plane.attributeLocation("aTexCoord"); glVertexAttribPointer(static_cast<GLuint>(texCoordLocation), 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *)(3 * sizeof(float))); glEnableVertexAttribArray(static_cast<GLuint>(texCoordLocation)); planeVAO.release(); VBO.release(); } void NormalSelectorWidget::paintGL(){ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClearColor(0.5, 0.5, 1.0, 1.0); glEnable(GL_DEPTH_TEST); qreal aspect = qreal(width()) / qreal(height()? height() : 1); QMatrix4x4 projection; projection.setToIdentity(); projection.perspective(45, aspect, -1, 1); QMatrix4x4 view; view.setToIdentity(); view.translate(0,0,-2.8); QMatrix4x4 transform; transform.setToIdentity(); sphere.bind(); sphere.setUniformValue("transform", projection*view*transform); renderSphere(); rendered = grabFramebuffer(); glDisable(GL_DEPTH_TEST); planeVAO.bind(); plane.bind(); QVector3D normal(2*c.redF()-1,2*c.greenF()-1,c.blueF()); QVector3D pos = view.inverted()*projection.inverted()*QVector3D(p.x(),p.y(),0.8); transform.translate(pos); QVector3D rotation_axis = normal.crossProduct(QVector3D(0,0,1),normal); float rotation_angle = acos(normal.dotProduct(QVector3D(0,0,1),normal)); transform.rotate(rotation_angle*180/PI,rotation_axis); transform.scale(0.1); plane.setUniformValue("transform",projection*view*transform); plane.setUniformValue("color",c); glDrawArrays(GL_QUADS, 0, 4); QVector2D n(2*c.redF()-1,2*c.greenF()-1); if (normal.z() != 1){ glBegin(GL_LINES); glVertex3f(0,0,0); glVertex3f(0,0,5); glEnd(); } glBegin(GL_LINE_LOOP); for(int i =0; i <= 300; i++){ double angle = 2 * PI * i / 300; double x = cos(angle)*0.2; double y = sin(angle)*0.2; glVertex2d(x,y); } glEnd(); }
The complete plugin can be found here:
https://github.com/azagaya/LaigterNormalBrushPluginAny hints what could be wrong? why on linux and windows it works and in mac it doesn't? thanks in advance.