Qt编程环境下学习《OpenGL编程指南(原书第九版)》(二)

第二章

就像第一章所说,我们这次尝试使用原生的API来加载、编译和链接着色器代码。

首先还是看OpenGLWidget类定义:

class OpenGLWidget : public QOpenGLWidget,protected QOpenGLFunctions

{

    const char* vShader ={

        "#version 330 core\n"

        "uniform Uniforms {"

        "   vec3 translation;"

        "   float scale;"

        "   vec4    rotation;"

        "   bool    enabled;"

        "};"

        "in vec2 vPos;"

        "in vec3 vColor;"

        "out vec4 fColor;"

        "void main()"

        "{"

        "   vec3 pos = vec3(vPos, 0.0);"

        "   float angle = radians(rotation[0]);"

        "   vec3 axis = normalize(rotation.yzw);"

        "   mat3 I = mat3(1.0);"

        "   mat3 S = mat3( 0,-axis.z, axis.y,"

        "                               axis.z,0,-axis.x,"

        "                               -axis.y,axis.x,0);"

        "   mat3 uuT= outerProduct(axis,axis);"

        "   mat3 rot = uuT+cos(angle)*(I-uuT)+sin(angle)*S;"

        "   pos *= scale;"

        "   pos *= rot;"

        "   pos +=translation;"

        "   fColor = vec4(scale, scale, scale,1);"

        "   gl_Position = vec4(pos,1);"

        "}"

    };

    const char* fShader ={

        "#version 330 core\n"

        "uniform Uniforms {"

        "   vec3 translation;"

        "   float scale;"

        "   vec4 rotation;"

        "   bool enabled;"

        "};"

        "in vec4 fColor;"

        "out vec4 color;"

        "void main()"

        "{"

        "   color = fColor;"

        "}"

    };

    GLuint programId;

    GLuint vShaderId;

    GLuint fShaderId;

    QOpenGLShaderProgram *program;

public:

    explicit OpenGLWidget(QWidget *parent = 0);

 

protected:

    void initializeGL();

    void paintGL();

    void resizeGL(int w, int h);

    void initVbo();

    size_t TypeSize(GLenum type);

};

这次我们将顶点着色器和片元着色器的代码用vShader和fShader直接放入类。

主要变动的是:

void OpenGLWidget::initializeGL()

{

    initializeOpenGLFunctions();

    QOpenGLFunctions_4_5_Core *f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_4_5_Core>();

    if (!f){

        qWarning()<<"Could not obtain required OpenGL context version";

        exit(1);

    }

    GLint r;

    vSharderId = f->glCreateShader(GL_VERTEX_SHADER);

    f->glShaderSource(vSharderId,1,&vShader,0);

    f->glCompileShader(vSharderId);

    f->glGetShaderiv(vSharderId,GL_COMPILE_STATUS,&r);

    if (r!=GL_TRUE){

        char rst[512];

        f->glGetShaderInfoLog(vSharderId,512,NULL,rst);

        qDebug()<<"vShader create error!::"<<rst;

        return;

    }

    fSharderId = glCreateShader(GL_FRAGMENT_SHADER);

    f->glShaderSource(fSharderId,1,&fSharder,0);

    f->glCompileShader(fSharderId);

   f->glGetShaderiv(fSharderId,GL_COMPILE_STATUS,&r);

   if (r!=GL_TRUE){

       char rst[512];

       f->glGetShaderInfoLog(fSharderId,512,NULL,rst);

       qDebug()<<"fShader create error!::"<<rst;

       return;

   }

    programId =glCreateProgram();

    f->glAttachShader(programId,vSharderId);

    f->glAttachShader(programId,fSharderId);

    f->glLinkProgram(programId);

    f->glGetShaderiv(programId,GL_LINK_STATUS,&r);

    if (r!=GL_TRUE){

        char rst[512];

        f->glGetShaderInfoLog(programId,512,NULL,rst);

        qDebug()<<"fShader create error!::"<<rst;

        return;

    }

    f->glClearColor(1,0,0,1);

 

    f->glUseProgram(programId);

    /*init uniform*/

    GLuint uboIndex;

    GLint uboSize;

    GLuint ubo;

    GLvoid *buffer;

 

    uboIndex = f->glGetUniformBlockIndex(programId, "Uniforms");

 

    f->glGetActiveUniformBlockiv(programId, uboIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &uboSize);

 

    qDebug()<<"Uniform size:"<<uboSize;

    buffer = malloc(uboSize);

 

    if (buffer == NULL){

        qDebug()<<"malloc error";

        exit(EXIT_FAILURE);

    }else{

        enum {Translation, Scale, Rotation, Enabled, NumUniforms};

 

        GLfloat scale = 0.5f;

        GLfloat translation[] = { 0.1f, 0.1f, 0.0f};

        GLfloat rotation[] = {90.0f, 0.0f, 0.0f, 1.0f};

        GLboolean enabled = GL_TRUE;

 

        const char* names[NumUniforms] = {

            "translation",

            "scale",

            "rotation",

            "enabled",

        };

 

        GLuint indices[NumUniforms];

        GLint size[NumUniforms];

        GLint offset[NumUniforms];

        GLint type[NumUniforms];

 

        f->glGetUniformIndices(programId, NumUniforms, names, indices);

        f->glGetActiveUniformsiv(programId, NumUniforms, indices, GL_UNIFORM_OFFSET, offset);

        f->glGetActiveUniformsiv(programId, NumUniforms, indices, GL_UNIFORM_SIZE, size);

        f->glGetActiveUniformsiv(programId, NumUniforms, indices, GL_UNIFORM_TYPE, type);

 

        /*copy from uniform to buffer*/

        memcpy(static_cast<char*>(buffer)+offset[Scale], &scale, size[Scale]*TypeSize(type[Scale]));

        memcpy(static_cast<char*>(buffer)+offset[Translation], &translation, size[Translation]*TypeSize(type[Translation]));

        memcpy(static_cast<char*>(buffer)+offset[Rotation], &rotation, size[Rotation]*TypeSize(type[Rotation]));

        memcpy(static_cast<char*>(buffer)+offset[Enabled], &enabled, size[Enabled]*TypeSize(type[Enabled]));

 

 

        f->glGenBuffers(1, &ubo);

        f->glBindBuffer(GL_UNIFORM_BUFFER, ubo);

        f->glBufferData(GL_UNIFORM_BUFFER, uboSize, buffer, GL_STATIC_DRAW);

 

        f->glBindBufferBase(GL_UNIFORM_BUFFER, uboIndex, ubo);

    }

 

    initVbo();

}

对比第一章的加载、编译和链接部分,可以看出QOpenGLShaderProgram替我们完成了多少事情。原生API调用一般是按照glCreateShader》glShaderSource》glCompileShader》glGetShaderiv》glGetShaderInfoLog(如果失败获取原因)。让我们回顾下第一章的相关部分,首先构建一个QOpenGLShaderProgram对象实例,然后进行调用addShaderFromSourceCode、link、bind就可以了。

另外需要注意的一点是,按照原文的方式,memcpy(buffer+offset[Scale], &scale, size[Scale]*TypeSize(type[Scale]))将无法通过Qt的编译,所以我将buffer做了个静态转换。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值