PDA

View Full Version : How to vary point sizes in array of points data



jshafferman
09-24-2014, 12:29 PM
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);
}

carsten neumann
09-24-2014, 12:46 PM
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.

jshafferman
09-24-2014, 01:08 PM
Sorry I put old code up I will update in a second

jshafferman
09-24-2014, 01:10 PM
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/

carsten neumann
09-24-2014, 02:04 PM
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 ;)

jshafferman
09-25-2014, 06:58 AM
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!