qt opengl 3d纹理

   3d纹理在现实世界中并不存在,也不能用图片工具查看。可以理解为一个实心的立文体数据块,可以通过,x,y,z坐标获取对应点的纹素(像素)。

     这里我学习了一个梯子的3d纹理,在实现3d纹理的同时,在其中加入了光照,效果如下

其渲染器实现如下

#ifndef TEXTURE3DRENDER_H
#define TEXTURE3DRENDER_H

#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
#include <QOpenGLBuffer>
#include <QOpenGLExtraFunctions>
class Texture3DRender
{
public:
    Texture3DRender() = default;
    void initsize();
    void render(QOpenGLExtraFunctions *f,QMatrix4x4 &pMatrix,QMatrix4x4 &vMatrix,QMatrix4x4 &mMatrix,QVector3D &cameraLocation,QVector3D &lightLocation);

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

#endif // TEXTURE3DRENDER_H
#include "texture3drender.h"

void Texture3DRender::initsize()
{
    program_.addCacheableShaderFromSourceFile(QOpenGLShader::Vertex,"vsrc.vert");
    program_.addCacheableShaderFromSourceFile(QOpenGLShader::Fragment,"fsrc.frag");

    GLfloat texData[]{
        255,0,0,255,255,255,255,255,
        255,255,255,255,255,0,0,255,
        255,255,255,255,255,0,0,255,
        255,255,255,255,255,0,0,255,
        255,0,0,255,255,255,255,255
    };
    texture_ = new QOpenGLTexture(QOpenGLTexture::Target3D);
    texture_->create();
    texture_->setSize(2,2,2);
    texture_->setFormat(QOpenGLTexture::RGBA8_UNorm);
    texture_->allocateStorage();
    texture_->setData(QOpenGLTexture::RGBA,QOpenGLTexture::Float32,texData);
    texture_->setMinMagFilters(QOpenGLTexture::Nearest,QOpenGLTexture::Nearest);
    texture_->setWrapMode(QOpenGLTexture::DirectionS,QOpenGLTexture::ClampToEdge);
    texture_->setWrapMode(QOpenGLTexture::DirectionT,QOpenGLTexture::ClampToEdge);
    texture_->setWrapMode(QOpenGLTexture::DirectionR,QOpenGLTexture::ClampToEdge);

    GLfloat xSize=0.2f;
    GLfloat y1Size=0.1f;
    GLfloat y2Size=0.2f;
    GLfloat y3Size=0.3f;
    GLfloat y4Size=0.4f;
    GLfloat z1Size=0.4f;
    GLfloat z2Size=0.3f;
    GLfloat z3Size=0.2f;
    GLfloat z4Size=0.1f;
    GLfloat vertices[]{
            //第四个(最下面)立方体的下面
            xSize,0,0,
            xSize,0,z1Size,
            -xSize,0,z1Size,
            -xSize,0,z1Size,
            -xSize,0,0,
            xSize,0,0,
            //第四个(最下面)立方体的上面
            xSize,y1Size,0,
            -xSize,y1Size,0,
            -xSize,y1Size,z1Size,
            -xSize,y1Size,z1Size,
            xSize,y1Size,z1Size,
            xSize,y1Size,0,
            //第四个(最下面)立方体的前面
            xSize,y1Size,z1Size,
            -xSize,y1Size,z1Size,
            -xSize,0,z1Size,
            -xSize,0,z1Size,
            xSize,0,z1Size,
            xSize,y1Size,z1Size,
            //第四个(最下面)立方体的后面
            xSize,y1Size,0,
            xSize,0,0,
            -xSize,0,0,
            -xSize,0,0,
            -xSize,y1Size,0,
            xSize,y1Size,0,
            //第四个(最下面)立方体的左面
            -xSize,y1Size,z1Size,
            -xSize,y1Size,0,
            -xSize,0,0,
            -xSize,0,0,
            -xSize,0,z1Size,
            -xSize,y1Size,z1Size,
            //第四个(最下面)立方体的右面
            xSize,y1Size,z1Size,
            xSize,0,z1Size,
            xSize,0,0,
            xSize,0,0,
            xSize,y1Size,0,
            xSize,y1Size,z1Size,

            //第三个立方体的上面
            xSize,y2Size,0,
            -xSize,y2Size,0,
            -xSize,y2Size,z2Size,
            -xSize,y2Size,z2Size,
            xSize,y2Size,z2Size,
            xSize,y2Size,0,
            //第三个立方体的前面
            xSize,y2Size,z2Size,
            -xSize,y2Size,z2Size,
            -xSize,y1Size,z2Size,
            -xSize,y1Size,z2Size,
            xSize,y1Size,z2Size,
            xSize,y2Size,z2Size,
            //第三个立方体的后面
            xSize,y2Size,0,
            xSize,y1Size,0,
            -xSize,y1Size,0,
            -xSize,y1Size,0,
            -xSize,y2Size,0,
            xSize,y2Size,0,
            //第三个立方体的左面
            -xSize,y2Size,z2Size,
            -xSize,y2Size,0,
            -xSize,y1Size,0,
            -xSize,y1Size,0,
            -xSize,y1Size,z2Size,
            -xSize,y2Size,z2Size,
            //第三个立方体的右面
            xSize,y2Size,z2Size,
            xSize,y1Size,z2Size,
            xSize,y1Size,0,
            xSize,y1Size,0,
            xSize,y2Size,0,
            xSize,y2Size,z2Size,

            //第二个立方体的上面
            xSize,y3Size,0,
            -xSize,y3Size,0,
            -xSize,y3Size,z3Size,
            -xSize,y3Size,z3Size,
            xSize,y3Size,z3Size,
            xSize,y3Size,0,
            //第二个立方体的前面
            xSize,y3Size,z3Size,
            -xSize,y3Size,z3Size,
            -xSize,y2Size,z3Size,
            -xSize,y2Size,z3Size,
            xSize,y2Size,z3Size,
            xSize,y3Size,z3Size,
            //第二个立方体的后面
            xSize,y3Size,0,
            xSize,y2Size,0,
            -xSize,y2Size,0,
            -xSize,y2Size,0,
            -xSize,y3Size,0,
            xSize,y3Size,0,
            //第二个立方体的左面
            -xSize,y3Size,z3Size,
            -xSize,y3Size,0,
            -xSize,y2Size,0,
            -xSize,y2Size,0,
            -xSize,y2Size,z3Size,
            -xSize,y3Size,z3Size,
            //第二个立方体的右面
            xSize,y3Size,z3Size,
            xSize,y2Size,z3Size,
            xSize,y2Size,0,
            xSize,y2Size,0,
            xSize,y3Size,0,
            xSize,y3Size,z3Size,

            //第一个立方体的上面
            xSize,y4Size,0,
            -xSize,y4Size,0,
            -xSize,y4Size,z4Size,
            -xSize,y4Size,z4Size,
            xSize,y4Size,z4Size,
            xSize,y4Size,0,
            //第一个立方体的前面
            xSize,y4Size,z4Size,
            -xSize,y4Size,z4Size,
            -xSize,y3Size,z4Size,
            -xSize,y3Size,z4Size,
            xSize,y3Size,z4Size,
            xSize,y4Size,z4Size,
            //第一个立方体的后面
            xSize,y4Size,0,
            xSize,y3Size,0,
            -xSize,y3Size,0,
            -xSize,y3Size,0,
            -xSize,y4Size,0,
            xSize,y4Size,0,
            //第一个立方体的左面
            -xSize,y4Size,z4Size,
            -xSize,y4Size,0,
            -xSize,y3Size,0,
            -xSize,y3Size,0,
            -xSize,y3Size,z4Size,
            -xSize,y4Size,z4Size,
            //第一个立方体的右面
            xSize,y4Size,z4Size,
            xSize,y3Size,z4Size,
            xSize,y3Size,0,
            xSize,y3Size,0,
            xSize,y4Size,0,
            xSize,y4Size,z4Size,

            //第四个(最下面)立方体的下面
            0,-1,0, 0,-1,0, 0,-1,0,
            0,-1,0, 0,-1,0, 0,-1,0,
            //第四个(最下面)立方体的上面
            0,1,0, 0,1,0, 0,1,0,
            0,1,0, 0,1,0, 0,1,0,
            //第四个(最下面)立方体的前面
            0,0,1, 0,0,1, 0,0,1,
            0,0,1, 0,0,1, 0,0,1,
            //第四个(最下面)立方体的后面
            0,0,-1, 0,0,-1, 0,0,-1,
            0,0,-1, 0,0,-1, 0,0,-1,
            //第四个(最下面)立方体的左面
            -1,0,0, -1,0,0, -1,0,0,
            -1,0,0, -1,0,0, -1,0,0,
            //第四个(最下面)立方体的右面
            1,0,0, 1,0,0, 1,0,0,
            1,0,0, 1,0,0, 1,0,0,

            //第三个立方体的上面
            0,1,0, 0,1,0, 0,1,0,
            0,1,0, 0,1,0, 0,1,0,
            //第三个立方体的前面
            0,0,1, 0,0,1, 0,0,1,
            0,0,1, 0,0,1, 0,0,1,
            //第三个立方体的后面
            0,0,-1, 0,0,-1, 0,0,-1,
            0,0,-1, 0,0,-1, 0,0,-1,
            //第三个立方体的左面
            -1,0,0, -1,0,0, -1,0,0,
            -1,0,0, -1,0,0, -1,0,0,
            //第三个立方体的右面
            1,0,0, 1,0,0, 1,0,0,
            1,0,0, 1,0,0, 1,0,0,

             //第二个立方体的上面
             0,1,0, 0,1,0, 0,1,0,
             0,1,0, 0,1,0, 0,1,0,
             //第二个立方体的前面
             0,0,1, 0,0,1, 0,0,1,
             0,0,1, 0,0,1, 0,0,1,
             //第二个立方体的后面
             0,0,-1, 0,0,-1, 0,0,-1,
             0,0,-1, 0,0,-1, 0,0,-1,
             //第二个立方体的左面
             -1,0,0, -1,0,0, -1,0,0,
             -1,0,0, -1,0,0, -1,0,0,
             //第二个立方体的右面
             1,0,0, 1,0,0, 1,0,0,
             1,0,0, 1,0,0, 1,0,0,

             //第一个立方体的上面
             0,1,0, 0,1,0, 0,1,0,
             0,1,0, 0,1,0, 0,1,0,
             //第一个立方体的前面
             0,0,1, 0,0,1, 0,0,1,
             0,0,1, 0,0,1, 0,0,1,
             //第一个立方体的后面
             0,0,-1, 0,0,-1, 0,0,-1,
             0,0,-1, 0,0,-1, 0,0,-1,
             //第一个立方体的左面
             -1,0,0, -1,0,0, -1,0,0,
             -1,0,0, -1,0,0, -1,0,0,
             //第一个立方体的右面
             1,0,0, 1,0,0, 1,0,0,
             1,0,0, 1,0,0, 1,0,0,
    };
    vbo_.create();
    vbo_.bind();
    vbo_.allocate(vertices,sizeof vertices);
}

void Texture3DRender::render(QOpenGLExtraFunctions *f, QMatrix4x4 &pMatrix, QMatrix4x4 &vMatrix, QMatrix4x4 &mMatrix, QVector3D &cameraLocation, QVector3D &lightLocation)
{
    f->glEnable(GL_CULL_FACE);
    f->glEnable(GL_DEPTH_TEST);

    program_.bind();
    vbo_.bind();
    f->glActiveTexture(GL_TEXTURE0 + 0);
    program_.setUniformValue("uPMatrix",pMatrix);
    program_.setUniformValue("uVMatrix",vMatrix);
    program_.setUniformValue("uMMatrix",mMatrix);
    program_.setUniformValue("uCamera",cameraLocation);
    program_.setUniformValue("uLightLocation",lightLocation);
    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,21*6*3*sizeof(GLfloat),3,3*sizeof(GLfloat));
    texture_->bind(0);
    f->glDrawArrays(GL_TRIANGLES,0,21 * 6);

    program_.disableAttributeArray(0);
    program_.disableAttributeArray(1);
    texture_->release();
    vbo_.release();
    program_.release();

    f->glDisable(GL_CULL_FACE);
    f->glDisable(GL_DEPTH_TEST);
}

其shader实现如下

#version 330
uniform mat4 uPMatrix,uVMatrix,uMMatrix;
uniform vec3 uCamera,uLightLocation;
layout (location = 0) in vec3 aPosition;
layout (location = 1) in vec3 aNormal;
smooth out vec3 vPosition;
smooth out vec4 vAmbient,vDiffuse,vSpecular;

void pointLight(in vec3 normal,inout vec4 ambient,inout vec4 diffuse,inout vec4 specular,in vec4 lightAmbient,in vec4 lightDiffuse,in vec4 lightSpecular,in float shininess){
    ambient = lightAmbient;

    vec3 normalTarget = aPosition + normal;
    vec3 newNormal = normalize((uMMatrix * vec4(normalTarget,1)).xyz - (uMMatrix * vec4(aPosition,1)).xyz);
    vec3 eye = normalize(uCamera - (uMMatrix * vec4(aPosition,1)).xyz);
    vec3 vp = normalize(uLightLocation - (uMMatrix * vec4(aPosition,1)).xyz);
    vec3 halfVector = normalize(eye + vp);

    float nDotViewPotision = max(0.0,dot(newNormal,vp));
    diffuse = lightDiffuse * nDotViewPotision;

    float nDotViewHalfVector = dot(newNormal,halfVector);
    float powerFactor = max(0.0,pow(nDotViewHalfVector,shininess));
    specular = lightSpecular * powerFactor;
}
void main(void)
{
    gl_Position = uPMatrix * uVMatrix * uMMatrix * vec4(aPosition,1);
    vec4 ambient = vec4(0.0,0.0,0.0,0.0),diffuse = vec4(0.0,0.0,0.0,0.0),specular = vec4(0.0,0.0,0.0,0.0);
    pointLight(aNormal,ambient,diffuse,specular,vec4(0.15,0.15,0.15,1),vec4(0.8,0.8,0.8,1),vec4(0.7,0.7,0.7,1),50.0);
    vAmbient = ambient;
    vDiffuse = diffuse;
    vSpecular = specular;
    vPosition = aPosition;
}
#version 330
uniform sampler3D sTexture;
in vec3 vPosition;
in vec4 vAmbient,vDiffuse,vSpecular;
out vec4 fragColor;

void main(void)
{
    //根据片元的位置折算出3D纹理坐标
    vec3 texCoor=vec3(((vPosition.x/0.2)+1.0)/2.0,vPosition.y/0.4,vPosition.z/0.4);
    vec4 noiseVec=texture(sTexture,texCoor);
    //vec4 noiseVec = vec4(0.1,0.5,0.0,1.0); 用于测试顶点是否正确
    fragColor = noiseVec*vAmbient+noiseVec*vSpecular+noiseVec*vDiffuse;
}

在widget中的使用如下

#ifndef WIDGET_H
#define WIDGET_H

#include <QOpenGLWidget>
#include "texture3drender.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:
    Texture3DRender render_;
    QMatrix4x4 pMatrix_;
    QVector3D cameraLocation_,lightLocation_;
};

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

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

Widget::~Widget()
{

}

void Widget::initializeGL()
{
    render_.initsize();
    lightLocation_.setX(0.0);
    lightLocation_.setY(0.0);
    lightLocation_.setZ(5);
    cameraLocation_.setX(0.0);
    cameraLocation_.setY(1.0);
    cameraLocation_.setZ(1.5);
}

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

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

    QMatrix4x4 vMatrix;
    vMatrix.lookAt(cameraLocation_,QVector3D(0.0,0.0,0.0),QVector3D(0.0,1.0,0.0));

    QMatrix4x4 mMatrix;
    mMatrix.rotate(-30,0,1,0);
    render_.render(f,pMatrix_,vMatrix,mMatrix,cameraLocation_,lightLocation_);
}

 到此结束

猜你喜欢

转载自blog.csdn.net/wanghualin033/article/details/83217751
今日推荐