How to vary point sizes in array of points data

I am trying to vary the point size throughout an array of point data. I am trying to learn OpenGL ES 2.0 and I am attempting to convert old OpenGL 1.x/2.0 code to ES 2.0 code. I am trying to draw a spiraling set of points and they increment in size from top to bottom. I am currently using a vertex attribute and pointSize attribute but that doesn’t seem to be working and I am not sure why. I am able to get a spiraling set of points however the size doesn’t change towards the top of the points :(. I am using Qt’s QGLWidget for my widget and their shader compatible stuff.

Here is the code widget code:


#include "glwidget.h"
#include "math.h"

#include <QGLShader>
#include <QGLShaderProgram>
#include <QKeyEvent>

namespace
{
    const float GL_PI = 3.1415f;
}

GLWidget::GLWidget(QWidget *parent)
    : QGLWidget(QGLFormat(QGL::DoubleBuffer | QGL::Rgba | QGL::DepthBuffer), parent)
    , vShader(0)
    , fShader(0)
    , program(0)
    , xRot(0.0f)
    , yRot(0.0f)
{
}

void GLWidget::initializeGL()
{
    vShader = new QGLShader(QGLShader::Vertex, context(), this);
    vShader->compileSourceFile(":/shaders/vertex.vsh");

    fShader = new QGLShader(QGLShader::Fragment, context(), this);
    fShader->compileSourceFile(":/shaders/fragment.fsh");

    program = new QGLShaderProgram(context(), this);
    program->addShader(vShader);
    program->addShader(fShader);
    program->link();

    // attribute
    vertexAttribLoc = program->attributeLocation("a_vertex");
    pointSizeAttribLoc = program->attributeLocation("a_pointSize");

    // vertex shader uniform
    mvpMatrixUniLoc = program->uniformLocation("u_mvpMatrix");

    GLfloat x;
    GLfloat y;
    GLfloat z = -50.0f;
    
    GLfloat pointRangeSize[2];
    glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, pointRangeSize);

    GLfloat curSize = pointRangeSize[0];
    GLfloat stepSize = 0.125;

    for(GLfloat angle = 0.0f; angle <= (2.0f*GL_PI)*3.0f; angle += 0.1f)
    {
        x = 50.0f*sin(angle);
        y = 50.0f*cos(angle);

        // Specify the point and move the Z value up a little
        vertices.append(x);
        vertices.append(y);
        vertices.append(z);
        pointSize.append(curSize);

        z += 0.5f;
        curSize += step;
    }

    // fragment shader uniform
    colorUniformLoc = program->uniformLocation("u_color");

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}

void GLWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT);

    program->bind();

    int tupleSize = 1;
    program->setAttributeArray(pointSizeAttribLoc, GL_FLOAT, pointSize.data(), tupleSize);
    program->enableAttributeArray(pointSizeAttribLoc);

    tupleSize = 3;
    program->setAttributeArray(vertexAttribLoc, GL_FLOAT, vertices.data(), tupleSize);
    program->enableAttributeArray(vertexAttribLoc);

    QVector3D color(0.0f, 1.0f, 0.0f);
    program->setUniformValue(colorUniformLoc, color);

    QMatrix4x4 pointModel = modelMatrix;
    pointModel.rotate(xRot, 1.0f, 0.0f, 0.0f);
    pointModel.rotate(yRot, 0.0f, 1.0f, 0.0f);

    mvpMatrix = projectionMatrix * viewMatrix * pointModel;
    program->setUniformValue(mvpMatrixUniLoc, mvpMatrix);

    glDrawArrays(GL_POINTS, 0, vertices.size());

    swapBuffers();
}

void GLWidget::resizeGL(int w, int h)
{
    GLfloat nRange = 100.0f;
    GLfloat aspectRatio;

    if(h == 0)
    {
        h = 1;
    }

    glViewport(0, 0, w, h);

    projectionMatrix.setToIdentity();

    aspectRatio = (GLfloat) w / (GLfloat) h;

    if(w <= h)
    {
        projectionMatrix.ortho(-nRange, nRange, (-nRange * h) / w, (nRange * h) / w, -nRange, nRange);
    }
    else
    {
        projectionMatrix.ortho((-nRange * w) / h, (nRange * w) / h, -nRange, nRange, -nRange, nRange);
    }

    viewMatrix.setToIdentity();
    modelMatrix.setToIdentity();

    mvpMatrix = projectionMatrix * viewMatrix * modelMatrix;
}

void GLWidget::keyPressEvent(QKeyEvent *event)
{
   switch(event->key())
   {
   case Qt::Key_Up:
       xRot -= 5.0f;
       break;
   case Qt::Key_Down:
       xRot += 5.0f;
       break;
   case Qt::Key_Left:
       yRot -= 5.0f;
       break;
   case Qt::Key_Right:
       yRot += 5.0f;
       break;
   case Qt::Key_Q:
   case Qt::Key_Escape:
      exit(0);
   default:
       break;
   }

   if(xRot > 356.0f)
   {
       xRot = 0.0f;
   }

   if(xRot < -1.0f)
   {
       xRot = 355.0f;
   }

   if(yRot > 356.0f)
   {
       yRot = 0.0f;
   }

   if(yRot < -1.0f)
   {
       yRot = 355.0f;
   }

   update();
}

Here is the vertex shader:


attribute vec4 a_vertex;
attribute float a_pointSize;
uniform mat4 u_mvpMatrix;

void main(void)
{
    gl_Position = u_mvpMatrix * a_vertex;
    gl_PointSize = a_pointSize;
}

Here is the fragment shader:


uniform vec3 u_color;

void main(void)
{
    gl_FragColor = vec4(u_color, 1.0);
}

Your vertex shader does not write to gl_PointSize. For desktop OpenGL you also need to glEnable(GL_PROGRAM_POINT_SIZE​) to be able to control the point size from a shader, don’t know if that is needed for ES as well.

Sorry I put old code up I will update in a second

Updated code to include writing to vertex shader for the point sizes. the glEnable(GL_PROGRAM_POINT_SIZE) isn’t available in ES 2.0 I believe. I can’t find it in the glEnable function from this link: http://www.khronos.org/opengles/sdk/docs/man/

Hmm, did you print what is reported by glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, pointRangeSize), maybe your implementation only supports size 1? To check if your size data makes it to the shader you could use it as output color for your points (subtract 1 to get into the [0,1] range for colors).
Also, you are not clearing the depth buffer, but that should be unrelated :wink:

Thanks for the suggestion! It does appear that Qt 4.8 (the one I am using for work) does not support point size’s greater than 1. I was able to pass the size information to the fragment shader and manipulate the color to get a varying color range but not point sizes :). Just out of curiosity, is there a way to print standard output in the shaders? I don’t believe so but was wondering if someone has found a way to do so!