qt opengl 天空穹

30 篇文章 10 订阅

    制作天空穹与前面的球体一样,只是这里画了个半球;还有就是绕线方式不一样,因为摄像机是放在球的里面。我实现的效果如下

   其渲染器实现如下:

#ifndef BALLTEXTURERENDER_H
#define BALLTEXTURERENDER_H

#include <QOpenGLExtraFunctions>
#include <QOpenGLTexture>
#include <QOpenGLBuffer>
#include <QOpenGLShaderProgram>
#include <QImage>
#define PI 3.14159265f

class BallTextureRender
{
public:
    BallTextureRender() = default;
    ~BallTextureRender();
    void initsize(float radius, QImage &img);
    void render(QOpenGLExtraFunctions *f,QMatrix4x4 &pMatrix,QMatrix4x4 &vMatrix,QMatrix4x4 &mMatrix);

private:
    QOpenGLShaderProgram program_;
    QOpenGLTexture *texture_{nullptr};
    QOpenGLBuffer vbo_;
    float r_ = 0.0f;
    QVector<GLfloat> vertexPoins_;
    QVector<GLfloat> points_;

    QVector<GLfloat> generateTexCoor(int bw, int bh);
};

#endif // BALLTEXTURERENDER_H
#include "balltexturerender.h"

BallTextureRender::~BallTextureRender()
{
    if(texture_){
        texture_->destroy();
        delete texture_;
    }
}

void BallTextureRender::initsize(float radius, QImage &img)
{
    program_.addCacheableShaderFromSourceFile(QOpenGLShader::Vertex,"vsrc.vert");
    program_.addCacheableShaderFromSourceFile(QOpenGLShader::Fragment,"fsrc.frag");
    program_.link();

    r_ = radius;//弧度 = 角度 * PI / 180
    float ANGLE_SPAN=18.0f;
    float angleV=90;
    for(float vAngle=angleV;vAngle>0;vAngle=vAngle-ANGLE_SPAN)//垂直方向angleSpan度一份
    {
        for(float hAngle=360;hAngle>0;hAngle=hAngle-ANGLE_SPAN)//水平方向angleSpan度一份
        {
            //纵向横向各到一个角度后计算对应的此点在球面上的四边形顶点坐标
            //并构建两个组成四边形的三角形
            double xozLength=radius*::cos(vAngle * PI / 180);
            float x1=(float)(xozLength*::cos(hAngle * PI / 180));
            float z1=(float)(xozLength*::sin(hAngle * PI / 180));
            float y1=(float)(radius*::sin(vAngle * PI / 180));

            xozLength=radius*::cos((vAngle-ANGLE_SPAN) * PI / 180);
            float x2=(float)(xozLength*::cos(hAngle * PI / 180));
            float z2=(float)(xozLength*::sin(hAngle * PI / 180));
            float y2=(float)(radius*::sin((vAngle-ANGLE_SPAN) * PI / 180));

            xozLength=radius*::cos((vAngle-ANGLE_SPAN) * PI / 180);
            float x3=(float)(xozLength*::cos((hAngle-ANGLE_SPAN) * PI / 180));
            float z3=(float)(xozLength*::sin((hAngle-ANGLE_SPAN) * PI / 180));
            float y3=(float)(radius*::sin((vAngle-ANGLE_SPAN) * PI / 180));

            xozLength=radius*::cos(vAngle * PI / 180);
            float x4=(float)(xozLength*::cos((hAngle-ANGLE_SPAN) * PI / 180));
            float z4=(float)(xozLength*::sin((hAngle-ANGLE_SPAN) * PI / 180));
            float y4=(float)(radius*::sin(vAngle * PI / 180));

            //构建第一三角形
            vertexPoins_ << x1 << y1 << z1
                    << x4 << y4 << z4
                    << x2 << y2 << z2;

            //构建第二三角形
            vertexPoins_ << x2 << y2 << z2
                    << x4 << y4 << z4
                    << x3 << y3 << z3;
        }
    }

    points_ << vertexPoins_ << generateTexCoor(static_cast<int>(360/ANGLE_SPAN),static_cast<int>(angleV/ANGLE_SPAN));

    texture_ = new QOpenGLTexture(img);
//    texture_->setMinMagFilters(QOpenGLTexture::NearestMipMapLinear,QOpenGLTexture::NearestMipMapLinear);
//    texture_->setWrapMode(QOpenGLTexture::ClampToEdge);
    vbo_.create();
    vbo_.bind();
    vbo_.allocate(points_.constData(),points_.count() * sizeof GLfloat);
}

void BallTextureRender::render(QOpenGLExtraFunctions *f, QMatrix4x4 &pMatrix, QMatrix4x4 &vMatrix, QMatrix4x4 &mMatrix)
{
    f->glEnable(GL_DEPTH_TEST);
    f->glEnable(GL_CULL_FACE);
    program_.bind();
    vbo_.bind();
    f->glActiveTexture(GL_TEXTURE0 + 0);
    program_.setUniformValue("uPMatrix",pMatrix);
    program_.setUniformValue("uVMatrix",vMatrix);
    program_.setUniformValue("uMMatrix",mMatrix);
    program_.setUniformValue("uR",r_);
    program_.setUniformValue("sTexture",0);
    program_.enableAttributeArray(0);
    program_.enableAttributeArray(1);

    texture_->bind(0);
    program_.setAttributeBuffer(0,GL_FLOAT,0,3,3 * sizeof GLfloat);
    program_.setAttributeBuffer(1,GL_FLOAT,vertexPoins_.count()*sizeof(GLfloat),2,2 * sizeof GLfloat);
    f->glDrawArrays(GL_TRIANGLES,0,vertexPoins_.count() / 3);

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

QVector<GLfloat> BallTextureRender::generateTexCoor(int bw, int bh)
{
    QVector<GLfloat> texVec;
    float sizew=1.0f/bw;//列数
    float sizeh=1.0f/bh;//行数
    int c=0;
    for(int i=0;i<bh;i++)
    {
        for(int j=0;j<bw;j++)
        {
            //每行列一个矩形,由两个三角形构成,共六个点,12个纹理坐标
            float s=j*sizew;
            float t=i*sizeh;

            texVec << s << t
                   << s+sizew << t
                   << s << t+sizeh
                   << s << t+sizeh
                   << s+sizew << t
                   <<s+sizew << t+sizeh;
        }
    }
    return texVec;
}

    其shader如下:

#version 330
uniform mat4 uPMatrix,uVMatrix,uMMatrix;
uniform float uR;
layout (location = 0) in vec3 aPosition;
layout (location = 1) in vec2 aTexCood;
smooth out vec2 vTextureCood;

void main(void)
{
    gl_Position = uPMatrix * uVMatrix * uMMatrix * vec4(aPosition,1);
    vTextureCood = aTexCood;
}
#version 330
uniform sampler2D sTexture;
in vec2 vTextureCood;
out vec4 fragColor;

void main(void)
{
    vec4 finalColor = texture2D(sTexture,vTextureCood);
    fragColor = finalColor;
}

   上面效果的调用如下

#ifndef WIDGET_H
#define WIDGET_H

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

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

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

private:
    BallTextureRender render_;
    QVector3D lightLocation_,camera_;
    QMatrix4x4 pMatrix;
    QTimer tm_;
    float angle_ = 0;

private slots:
    void slotTimeout();
};

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

Widget::Widget(QWidget *parent)
    : QOpenGLWidget(parent)
{
    connect(&tm_,SIGNAL(timeout()),this,SLOT(slotTimeout()));
//    tm_.start(30);
}

Widget::~Widget()
{

}

void Widget::initializeGL()
{
    render_.initsize(1.0,QImage("sky.png"));
    lightLocation_ = QVector3D(50,10,0);
    camera_ = QVector3D(0,-1,0);
}

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 vMatrix;
    vMatrix.lookAt(camera_,QVector3D(0.2,1,0),QVector3D(0.2,0,0));

    QMatrix4x4 mMatrix;

    render_.render(f,pMatrix,vMatrix,mMatrix);
    angle_ += 5;
}

void Widget::resizeGL(int w, int h)
{
    pMatrix.setToIdentity();
    pMatrix.perspective(45,float(w)/h,0.01f,100.0f);
}

void Widget::slotTimeout()
{
    update();
}

  到此结束。 

 

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值