qt opengl 点精灵

    点精灵就是在opengl中画点,在画点的同时指明点的大小,这样点就会变成一个实心的矩形(指明GL_POINT_SMOOTH可能不正确,大体是这个;就会是一个圆)。画每个矩形时,给每个矩形加载一个纹理图,就变成了点精灵;每个纹理坐标从内建变量gl_PointCoord获取。

50个随机点32*32效果图如下

 其渲染器实现如下

#ifndef POINTSPRINTRENDER_H
#define POINTSPRINTRENDER_H

#include <QOpenGLExtraFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QOpenGLTexture>

class PointSprintRender
{
public:
    PointSprintRender() = default;
    void initsize(QOpenGLExtraFunctions* f,QImage &textureImg,int pointsCount);//传入f获取最大、最小点精灵大小
    void render(QOpenGLExtraFunctions *f, QMatrix4x4 &pMatrix, QMatrix4x4 &vMatrix, QMatrix4x4 &mMatrix, float pointSize);

private:
    QOpenGLShaderProgram program_;
    QOpenGLBuffer vbo_;
    QOpenGLTexture *texture_{nullptr};
    int pointCount_ = 0;
    float maxPointSize_=0,minPointSize_=0;
};

#endif // POINTSPRINTRENDER_H

#include <random>
#include <chrono>
#include <QDebug>
#include "pointsprintrender.h"

void PointSprintRender::initsize(QOpenGLExtraFunctions *f, QImage &textureImg, int pointsCount)
{
    program_.addCacheableShaderFromSourceFile(QOpenGLShader::Vertex,"vsrc.vert");
    program_.addCacheableShaderFromSourceFile(QOpenGLShader::Fragment,"fsrc.frag");
    program_.link();

    texture_ = new QOpenGLTexture(textureImg);
    texture_->setWrapMode(QOpenGLTexture::DirectionS,QOpenGLTexture::ClampToEdge);
    texture_->setWrapMode(QOpenGLTexture::DirectionT,QOpenGLTexture::ClampToEdge);
    texture_->setMinMagFilters(QOpenGLTexture::Nearest,QOpenGLTexture::Linear);
    pointCount_ = pointsCount;
    //随机生成顶点
    QVector<GLfloat> vertVec;
    unsigned seed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
//    std::random_device rd;
    std::mt19937 gen(seed);
    std::uniform_real_distribution<float> dis(-1.0,1.0);
    for(int i = 0; i < pointCount_ * 3; i++){
        vertVec << dis(gen);
    }
    vbo_.create();
    vbo_.bind();
    vbo_.allocate(vertVec.data(),vertVec.count() * sizeof(GLfloat));

    float pointsSizeRange[2]{0};
    f->glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE,pointsSizeRange);
    minPointSize_ = pointsSizeRange[0];
    maxPointSize_ = pointsSizeRange[1];
    qDebug() << minPointSize_ << maxPointSize_;
}

void PointSprintRender::render(QOpenGLExtraFunctions *f, QMatrix4x4 &pMatrix, QMatrix4x4 &vMatrix, QMatrix4x4 &mMatrix,float pointSize)
{
    f->glEnable(GL_CULL_FACE);
    f->glEnable(GL_DEPTH_TEST);
    f->glEnable(GL_BLEND); //开启混合
    f->glEnable(GL_POINT_SPRITE); //开启点精灵模式,使用点块纹理
    f->glEnable(GL_PROGRAM_POINT_SIZE); //让顶点程序决定点块大小
    program_.bind();
    vbo_.bind();

    f->glActiveTexture(GL_TEXTURE0 + 0);
    program_.setUniformValue("sTexture",0);
    program_.setUniformValue("pMatrix",pMatrix);
    program_.setUniformValue("vMatrix",vMatrix);
    program_.setUniformValue("mMatrix",mMatrix);
    program_.setUniformValue("uPointSize",pointSize);
    program_.enableAttributeArray(0);

    texture_->bind(0);
    program_.setAttributeBuffer(0,GL_FLOAT,0,3,3 * sizeof(GLfloat));
    f->glDrawArrays(GL_POINTS,0,pointCount_);

    program_.disableAttributeArray(0);
    texture_->release();
    vbo_.release();
    program_.release();
    f->glDisable(GL_CULL_FACE);
    f->glDisable(GL_DEPTH_TEST);
    f->glDisable(GL_BLEND);
    f->glDisable(GL_POINT_SPRITE);
    f->glDisable(GL_PROGRAM_POINT_SIZE);
}

其shader如下

#version 330
uniform mat4 pMatrix,vMatrix,mMatrix;
uniform float uPointSize;
layout (location = 0) in vec3 aPosition;

void main(void)
{
    gl_Position = pMatrix * vMatrix * mMatrix * vec4(aPosition, 1);
    gl_PointSize = uPointSize; //设置点大小
}
#version 330
uniform sampler2D sTexture;
out vec4 fragColor;

void main(void)
{
    vec2 texCoor = gl_PointCoord; //用临时变量保存一下,以保证正常运行。避免出现异常情况
    fragColor = texture2D(sTexture, texCoor);
}

使用时传入对应的MVP矩阵坐标,点精灵数量就可以了

#ifndef WIDGET_H
#define WIDGET_H

#include <QOpenGLWidget>
#include "pointsprintrender.h"
class Widget : public QOpenGLWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();

protected:
    void initializeGL() override;
    void resizeGL(int w, int h) override;
    void paintGL() override;

private:
    PointSprintRender render_;
    QMatrix4x4 pMatrix_;
    QVector3D cameraLocation_;
};

#endif // WIDGET_H
#include "widget.h"

Widget::Widget(QWidget *parent)
    : QOpenGLWidget(parent)
{
}

Widget::~Widget()
{

}

void Widget::initializeGL()
{
    QOpenGLExtraFunctions *f = QOpenGLContext::currentContext()->extraFunctions();
    render_.initsize(f,QImage("fp.png"),50);
    cameraLocation_.setX(0);
    cameraLocation_.setY(0);
    cameraLocation_.setZ(3);
}

void Widget::resizeGL(int w, int h)
{
    pMatrix_.setToIdentity();
    pMatrix_.perspective(30,float(w)/h,0.01f,50.0f);
}

void Widget::paintGL()
{
    QOpenGLExtraFunctions *f = QOpenGLContext::currentContext()->extraFunctions();
    f->glClearColor(0.0,0.0,0.0,1.0);
    f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    QMatrix4x4 view;
    view.lookAt(cameraLocation_,QVector3D{0.0,0.0,0.0},QVector3D{0.0,1.0,0.0});

    QMatrix4x4 model;
    render_.render(f,pMatrix_,view,model,32);
}

 到此结束

猜你喜欢

转载自blog.csdn.net/wanghualin033/article/details/83050941