qt opengl 天空盒

30 篇文章 10 订阅

     这个效果比较简单,用一个立文体把我们要绘制的东西包起来即可,把摄像机的位置放到立文体内,这样就给人一个有天空,有陆地感觉。  我在这个工程中加入了以前的圆环体,其渲染器实现方法,可以查阅以前的文章。效果如下

    我使用的是一个包含6个纹理图片的纹理数组,一次性把6个面都画好了,并完成了贴图。其渲染器实现如下:

#ifndef BOXSHADER_H
#define BOXSHADER_H

#include <QOpenGLExtraFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QOpenGLTexture>
#include <QImage>
class BoxShader
{
public:
    BoxShader() = default;
    ~BoxShader();
    void initsize(int width,int height,QImage &left,QImage &bebind,QImage &right,QImage &front,QImage &top,QImage &bottom);
    void render(QOpenGLExtraFunctions *f, QMatrix4x4 &pMatrix, QMatrix4x4 &vMatrix, QMatrix4x4 &mMatrix);

private:
    QOpenGLTexture *textureArray_{nullptr};
    QOpenGLShaderProgram program_;
    QOpenGLBuffer vbo_;
};

#endif // BOXSHADER_H
#include "boxshader.h"

BoxShader::~BoxShader()
{
    textureArray_->destroy();
    delete textureArray_;
}

void BoxShader::initsize(int width, int height, QImage &left, QImage &bebind, QImage &right, QImage &front, QImage &top, QImage &bottom)
{
    program_.addCacheableShaderFromSourceFile(QOpenGLShader::Vertex,"vsrc.vert");
    program_.addCacheableShaderFromSourceFile(QOpenGLShader::Fragment,"fsrc.frag");
    program_.link();

    textureArray_ = new QOpenGLTexture(QOpenGLTexture::Target2DArray);
    textureArray_->create();
    textureArray_->setSize(width,height);
    textureArray_->setLayers(6);
    textureArray_->setFormat(QOpenGLTexture::RGB8_UNorm);
    textureArray_->allocateStorage();

    textureArray_->setData(0,0,QOpenGLTexture::RGB,QOpenGLTexture::UInt8,left.convertToFormat(QImage::Format_RGB888).constBits());
    textureArray_->setData(0,1,QOpenGLTexture::RGB,QOpenGLTexture::UInt8,bebind.convertToFormat(QImage::Format_RGB888).constBits());
    textureArray_->setData(0,2,QOpenGLTexture::RGB,QOpenGLTexture::UInt8,right.convertToFormat(QImage::Format_RGB888).constBits());
    textureArray_->setData(0,3,QOpenGLTexture::RGB,QOpenGLTexture::UInt8,front.convertToFormat(QImage::Format_RGB888).constBits());
    textureArray_->setData(0,4,QOpenGLTexture::RGB,QOpenGLTexture::UInt8,top.convertToFormat(QImage::Format_RGB888).constBits());
    textureArray_->setData(0,5,QOpenGLTexture::RGB,QOpenGLTexture::UInt8,bottom.convertToFormat(QImage::Format_RGB888).constBits());
    textureArray_->setMinMagFilters(QOpenGLTexture::Nearest,QOpenGLTexture::Nearest);
    textureArray_->setWrapMode(QOpenGLTexture::ClampToEdge);

    const GLfloat vertexs[]{
        //vertex points
        //left side
        -1.0,+1.0,+1.0,
        -1.0,-1.0,+1.0,
        -1.0,-1.0,-1.0,
        -1.0,+1.0,-1.0,
        //behind side
        -1.0,+1.0,-1.0,
        -1.0,-1.0,-1.0,
        +1.0,-1.0,-1.0,
        +1.0,+1.0,-1.0,
        //right side
        +1.0,+1.0,-1.0,
        +1.0,-1.0,-1.0,
        +1.0,-1.0,+1.0,
        +1.0,+1.0,+1.0,
        //front side
        -1.0,+1.0,+1.0,
        +1.0,+1.0,+1.0,
        +1.0,-1.0,+1.0,
        -1.0,-1.0,+1.0,
        //top side
        -1.0,+1.0,-1.0,
        +1.0,+1.0,-1.0,
        +1.0,+1.0,+1.0,
        -1.0,+1.0,+1.0,
        //bottom side
        -1.0,-1.0,-1.0,
        -1.0,-1.0,+1.0,
        +1.0,-1.0,+1.0,
        +1.0,-1.0,-1.0,

        //texture points
        //left side
        +0.0,+0.0,
        +0.0,+1.0,
        +1.0,+1.0,
        +1.0,+0.0,
        //behind side
        +0.0,+0.0,
        +0.0,+1.0,
        +1.0,+1.0,
        +1.0,+0.0,
        //right side
        +0.0,+0.0,
        +0.0,+1.0,
        +1.0,+1.0,
        +1.0,+0.0,
        //front side
        +1.0,+0.0,
        +0.0,+0.0,
        +0.0,+1.0,
        +1.0,+1.0,
        //top side
        +0.0,+1.0,
        +1.0,+1.0,
        +1.0,+0.0,
        +0.0,+0.0,
        //bottom side
        +0.0,+0.0,
        +0.0,+1.0,
        +1.0,+1.0,
        +1.0,+0.0,
    };
    vbo_.create();
    vbo_.bind();
    vbo_.allocate(vertexs,sizeof(vertexs));;
}

void BoxShader::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("pMatrix",pMatrix);
    program_.setUniformValue("vMatrix",vMatrix);
    program_.setUniformValue("mMatrix",mMatrix);
    program_.setUniformValue("sTexture",0);

    program_.enableAttributeArray(0);
    program_.enableAttributeArray(1);
    program_.setAttributeBuffer(0,GL_FLOAT,0,3,3*sizeof(GLfloat));
    program_.setAttributeBuffer(1,GL_FLOAT,6 * 4 * 3 * sizeof(GLfloat),2,2*sizeof(GLfloat));
    textureArray_->bind();
    f->glDrawArrays(GL_QUADS,0,24);
    program_.disableAttributeArray(0);
    program_.disableAttributeArray(1);

    textureArray_->release();
    vbo_.release();
    program_.release();
    f->glDisable(GL_DEPTH_TEST);
    f->glDisable(GL_CULL_FACE);
}

       其shader实现如下

#version 330
uniform mat4 pMatrix,vMatrix,mMatrix;
layout (location = 0) in vec3 aPosition;
layout (location = 1) in vec2 aTextureCood;
smooth out vec2 vTextureCoord;
out float vid;

void main(void)
{
    gl_Position = pMatrix * vMatrix * mMatrix * vec4(aPosition,1);
    vTextureCoord = aTextureCood;
    vid = gl_VertexID;//顶点序号
}
#version 330
uniform sampler2DArray sTexture;
in float vid;
in vec2 vTextureCoord;
out vec4 fragColor;

void main(void)
{
    vec3 texCood = vec3(vTextureCoord.st,floor(vid/4)); //根据vid顶点序号求出纹理索引
    fragColor = texture(sTexture,texCood);
}

调用如下

#ifndef WIDGET_H
#define WIDGET_H

#include <QOpenGLWidget>
#include <QTimer>
#include "boxshader.h"
#include "torusrender.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:
    BoxShader boxShader_;
    TorusRender toruRender_;
    QVector3D camera_;
    QMatrix4x4 pMatrix_;
    QTimer tm_;
    float angleX_ = 0, angleY_ = 0, angleZ_ = 0;

private slots:
    void slotTimeout();
};

#endif // WIDGET_H

#include <QWheelEvent>
#include "widget.h"

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

Widget::~Widget()
{

}

void Widget::initializeGL()
{
    camera_.setX(4.9);
    camera_.setY(4.9);
    camera_.setZ(4.9);
    toruRender_.initsize(0.9,0.5,13,30);
    boxShader_.initsize(256,256,QImage("side1.png"),QImage("side2.png"),QImage("side3.png"),QImage("side4.png"),QImage("side5.png"),QImage("side6.png"));
}

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

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

    QMatrix4x4 vMatrix;
    vMatrix.lookAt(camera_,QVector3D(-4.9,-4.9,-4.9),QVector3D(-1.0,1.0,-1.0));

    QMatrix4x4 mMatrix;
    mMatrix.rotate(angleX_,1,0,0);
    mMatrix.rotate(angleY_,0,1,0);
    mMatrix.rotate(angleZ_,0,0,1);
    mMatrix.scale(20);
    boxShader_.render(f,pMatrix_,vMatrix,mMatrix);

    mMatrix.setToIdentity();
    mMatrix.translate(-1.0,-4.9,-0.5);
    mMatrix.scale(2);
    mMatrix.rotate(-angleY_,0,1,0);
    toruRender_.render(f,pMatrix_,vMatrix,mMatrix);
}

void Widget::slotTimeout()
{
    angleY_ += 5;
    update();
}

  到此结束

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值