errorman

不积跬步,无以至千里

导航

QOpenGLShaderProgram Class

Posted on 2023-03-16 09:55  Clemens  阅读(223)  评论(0编辑  收藏  举报

Detailed Description 

Introduction

这个类支持使用OpenGL Shading Language (GLSL)和OpenGL/ES Shading Language (GLSL/ES)编写的着色器程序。QOpenGLShader和QOpenGLShaderProgram会帮助程序员隐藏编译和链接顶点和片段着色器的细节。下面的例子使用提供的源代码创建一个顶点着色器程序。一旦编译和链接完成,可以通过调用QOpenGLShaderProgram::bind()方法在当前的QOpenGLContext中激活着色器程序:

  QOpenGLShader shader(QOpenGLShader::Vertex);
  shader.compileSourceCode(code);

  QOpenGLShaderProgram program(context);
  program.addShader(&shader);
  program.link();

  program.bind();

Writing Portable Shaders 编写可移植的着色器

由于对标准顶点属性和统一变量的支持水平不同,着色器程序在OpenGL实现之间可能难以重用。特别是,GLSL/ES缺少所有在桌面OpenGL系统上存在的标准变量:gl_Vertex、gl_Normal、gl_Color等。桌面OpenGL则缺少变量限定符highp、mediump和lowp。

QOpenGLShaderProgram类通过在桌面OpenGL上为所有着色器程序加上以下行,使编写可移植着色器的过程更容易:

  #define highp
  #define mediump
  #define lowp

这使得大多数GLSL/ES着色器程序可以在桌面系统上运行。程序员应该限制自己只使用GLSL/ES中存在的功能,并避免仅适用于桌面的标准变量名称。

 

Simple Shader Example

  program.addShaderFromSourceCode(QOpenGLShader::Vertex,
      "attribute highp vec4 vertex;\n"
      "uniform highp mat4 matrix;\n"
      "void main(void)\n"
      "{\n"
      "   gl_Position = matrix * vertex;\n"
      "}");
  program.addShaderFromSourceCode(QOpenGLShader::Fragment,
      "uniform mediump vec4 color;\n"
      "void main(void)\n"
      "{\n"
      "   gl_FragColor = color;\n"
      "}");
  program.link();
  program.bind();

  int vertexLocation = program.attributeLocation("vertex");
  int matrixLocation = program.uniformLocation("matrix");
  int colorLocation = program.uniformLocation("color");

使用上述着色器程序,我们可以绘制一个绿色三角形,具体如下:

  static GLfloat const triangleVertices[] = {
      60.0f,  10.0f,  0.0f,
      110.0f, 110.0f, 0.0f,
      10.0f,  110.0f, 0.0f
  };

  QColor color(0, 255, 0, 255);

  QMatrix4x4 pmvMatrix;
  pmvMatrix.ortho(rect());

  program.enableAttributeArray(vertexLocation);
  program.setAttributeArray(vertexLocation, triangleVertices, 3);
  program.setUniformValue(matrixLocation, pmvMatrix);
  program.setUniformValue(colorLocation, color);

  glDrawArrays(GL_TRIANGLES, 0, 3);

  program.disableAttributeArray(vertexLocation);

 

Binary Shaders and Programs 二进制着色器和程序

可以使用QOpenGLShader::shaderId()的返回值在glShaderBinary()中指定二进制着色器。然后,包含二进制文件的QOpenGLShader实例可以通过addShader()添加到着色器程序中,并使用link()常规链接。

可以在programId()的返回值上使用glProgramBinaryOES()指定二进制程序。然后应用程序应调用link(),它将注意到程序已经被指定和链接,从而允许在着色器程序上执行其他操作。可以使用create()函数显式创建着色器程序的ID。

Caching Program Binaries 缓存程序二进制文件

从Qt 5.9开始,内置了在磁盘上缓存程序二进制文件的支持。要启用此功能,请切换到使用addCacheableShaderFromSourceCode()和addCacheableShaderFromSourceFile()。在使用OpenGL ES 3.x上下文或支持GL_ARB_get_program_binary时,这将在QStandardPaths::GenericCacheLocation或QStandardPaths::CacheLocation下透明地缓存程序二进制文件。当不支持时,调用可缓存的函数变体相当于普通的函数变体。

注意:一些驱动程序没有任何可用的二进制格式,即使它们广告该扩展或提供OpenGL ES 3.0。在这种情况下,程序二进制支持将被禁用。

另请参见QOpenGLShader。

 

Member Function Documentation

QOpenGLShaderProgram::QOpenGLShaderProgram(QObject *parent = nullptr)

构造一个新的着色器程序并将其附加到父项parent。在调用addShader()之前,该程序将无效。该着色器程序将与当前的QOpenGLContext相关联。

另请参见addShader()。

 

[virtual] QOpenGLShaderProgram::~QOpenGLShaderProgram()
Deletes this shader program.

 

bool QOpenGLShaderProgram::addCacheableShaderFromSourceCode(QOpenGLShader::ShaderType type, const char *source)

将指定类型typesource的着色器注册到此程序中。与addShaderFromSourceCode()不同,此函数不执行编译。编译延迟到link(),并且可能根本不会发生,因为link()可能会从Qt的着色器磁盘缓存中使用程序二进制文件。这通常会显着提高性能。

如果该着色器已成功注册或在非缓存情况下已成功编译,则返回true;如果出现错误,则返回false。编译错误消息可以通过log()获取。

当通过Qt::AA_DisableShaderDiskCache禁用磁盘缓存,或者OpenGL上下文不支持上下文二进制文件时,调用此函数等效于addShaderFromSourceCode()。

此函数在Qt 5.9中引入。

另请参见addShaderFromSourceCode()和addCacheableShaderFromSourceFile()。

 

bool QOpenGLShaderProgram::addShader(QOpenGLShader *shader)

将一个已编译的shader(着色器)添加到这个着色器程序中。如果可以添加着色器,则返回true,否则返回false。

shader对象的所有权仍然归调用者所有。当删除这个QOpenGLShaderProgram实例时,它不会被删除。这允许调用者将同一着色器添加到多个着色器程序中。

另请参阅addShaderFromSourceCode(),addShaderFromSourceFile(),removeShader(),link()和removeAllShaders()。

 

bool QOpenGLShaderProgram::addShaderFromSourceCode(QOpenGLShader::ShaderType type, const char *source)

source编译为指定type的着色器,并将其添加到此着色器程序中。如果编译成功,则返回true,否则返回false。编译错误和警告将通过log()方法提供。

该函数旨在为快速添加顶点着色器和片段着色器到着色器程序中提供便捷,而不需要先创建一个QOpenGLShader的实例。

另请参见addShader(),addShaderFromSourceFile(),removeShader(),link(),log()和removeAllShaders()。

 

int QOpenGLShaderProgram::attributeLocation(const char *name) const

返回属性名name在此着色器程序参数列表中的位置。如果属性名不是此着色器程序的有效属性,则返回-1。

另请参见uniformLocation()和bindAttributeLocation()。

 

bool QOpenGLShaderProgram::bind()

将此着色器程序绑定到活动的QOpenGLContext并使其成为当前着色器程序。任何先前绑定的着色器程序将被释放。这相当于在programId()上调用glUseProgram()。如果程序成功绑定,则返回true;否则返回false。如果着色器程序尚未链接或需要重新链接,则此函数将调用link()方法。

另请参见link()和release()。

 

void QOpenGLShaderProgram::bindAttributeLocation(const char *name, int location)

将属性名name绑定到指定位置location。此函数可以在程序链接之前或之后调用。当程序链接时没有显式绑定的属性将自动分配位置。 当在程序链接之后调用此函数时,需要重新链接程序才能使更改生效。

另请参见attributeLocation()。

 

bool QOpenGLShaderProgram::create()

立即请求创建着色器程序的id。如果成功,则返回true;否则返回false。

当将QOpenGLShaderProgram与直接操作着色器程序id的其他OpenGL函数(例如GL_OES_get_program_binary)组合使用时,此函数非常有用。

在正常使用着色器程序时,着色器程序的id将按需创建。 此函数在Qt 5.3中引入。

另请参见programId()。

 

QVector<float> QOpenGLShaderProgram::defaultInnerTessellationLevels() const

返回在Tessellation控制着色器没有输出时,Tessellation基元生成器要使用的默认内部细分级别。有关OpenGL和Tessellation着色器的更多详细信息,请参见OpenGL Tessellation Shaders。

返回描述内部细分级别的浮点数QVector。向量始终有两个元素,但并不是每种细分模式都有意义。

注意:这返回全局的OpenGL状态值。它不特定于此QOpenGLShaderProgram实例。

注意:此函数仅支持OpenGL >= 4.0,并且不会在OpenGL ES 3.2中返回有效结果。

另请参见setDefaultInnerTessellationLevels()和defaultOuterTessellationLevels()。

 

QVector<float> QOpenGLShaderProgram::defaultOuterTessellationLevels() const

返回在Tessellation控制着色器没有输出时,Tessellation基元生成器要使用的默认外部细分级别。有关OpenGL和Tessellation着色器的更多详细信息,请参见OpenGL Tessellation Shaders。

返回描述外部细分级别的浮点数QVector。向量始终有四个元素,但并不是每种细分模式都有意义。

注意:这返回全局的OpenGL状态值。它不特定于此QOpenGLShaderProgram实例。

注意:此函数仅支持OpenGL >= 4.0,并且不会在OpenGL ES 3.2中返回有效结果。

另请参见setDefaultOuterTessellationLevels()和defaultInnerTessellationLevels()。

 

void QOpenGLShaderProgram::disableAttributeArray(int location)

禁用此着色器程序中位置为location的顶点数组,该顶点数组是通过先前调用enableAttributeArray()启用的。

另请参见enableAttributeArray()、setAttributeArray()、setAttributeValue()和setUniformValue()。

 

void QOpenGLShaderProgram::enableAttributeArray(int location)

在此着色器程序中启用位置为location的顶点数组,以便该顶点数组上由setAttributeArray()设置的值将被着色器程序使用。

另请参见disableAttributeArray()、setAttributeArray()、setAttributeValue()和setUniformValue()。

 

[static] bool QOpenGLShaderProgram::hasOpenGLShaderPrograms(QOpenGLContext *context = nullptr)

如果此系统支持使用OpenGL Shading Language(GLSL)编写的着色器程序,则返回true;否则返回false。

上下文用于解析GLSL扩展。如果上下文为nullptr,则使用QOpenGLContext::currentContext()。

 

bool QOpenGLShaderProgram::isLinked() const

此函数返回一个布尔值,用于指示该着色器程序是否已经链接。如果已链接,返回true;否则返回false。

参见link()。

 

[virtual] bool QOpenGLShaderProgram::link()

将已经添加到该程序中的着色器用 addShader() 连接起来。如果链接成功,则返回 true,否则返回 false。如果链接失败,则可以通过 log() 获取错误消息。

子类可以重写此函数以初始化特定着色器程序中的属性和统一变量。

如果着色器程序已经链接,则再次调用此函数将强制重新链接。

当通过 addCacheableShaderFromSourceCode() 或 addCacheableShaderFromSourceFile() 将着色器添加到该程序时,支持程序二进制文件,并且在磁盘上有一个缓存二进制文件时,将跳过实际的编译和链接。相反,link() 将通过 glProgramBinary() 用二进制 blob 初始化程序。如果程序没有缓存

版本,或者是使用不同的驱动程序版本生成的,则将从源代码编译着色器,并正常链接程序。这允许无缝升级图形驱动程序,而不必担心可能不兼容的二进制格式。

参见 addShader() 和 log()。

 

QString QOpenGLShaderProgram::log() const

函数返回上一次调用link()或使用明确指定源代码的addShader()时发生的错误和警告信息。

参见link()。

 

int QOpenGLShaderProgram::maxGeometryOutputVertices() const

返回几何着色器可以输出的顶点数量的硬件限制。

 

int QOpenGLShaderProgram::patchVertexCount() const

返回用于渲染的每个细分片段的顶点数。

注意:此函数返回全局的OpenGL状态值,而非仅特定于此QOpenGLShaderProgram实例。

参见setPatchVertexCount()。

 

GLuint QOpenGLShaderProgram::programId() const

返回与该着色器程序相关联的OpenGL标识符。

参见QOpenGLShader::shaderId()。

 

void QOpenGLShaderProgram::release()

函数释放当前活动的着色器程序。它相当于调用glUseProgram(0)。可以使用 bind() 函数再次激活该着色器程序。

 

void QOpenGLShaderProgram::removeAllShaders()

从该程序中删除之前添加的所有着色器。如果 QOpenGLShader 对象是外部构造的,则不会被删除。由 QOpenGLShaderProgram 内部构造的 QOpenGLShader 对象将被删除。

另请参见 addShader() 和 removeShader()。

 

void QOpenGLShaderProgram::removeShader(QOpenGLShader *shader)

从此着色器程序中移除shader。对象不会被删除。 着色器程序必须在当前的QOpenGLContext中有效。

另请参阅addShader(),link()和removeAllShaders()。

 

void QOpenGLShaderProgram::setAttributeArray(int location, const GLfloat *values, int tupleSize, int stride = 0)

在该着色器程序的位置location处设置一个顶点值的数组。tupleSize表示每个顶点的分量数(1、2、3或4),stride表示顶点之间的字节数。默认的stride值为零,表示顶点在values中密集地打包。只有在调用location的enableAttributeArray()函数后,该数组才会变为活动状态。否则,将使用setAttributeValue()函数为location指定的值。

参见setAttributeValue()、setUniformValue()、enableAttributeArray()和disableAttributeArray()函数。

 

void QOpenGLShaderProgram::setAttributeBuffer(int location, GLenum type, int offset, int tupleSize, int stride = 0)

设置当前绑定的顶点缓冲中,从特定偏移量offset开始的顶点值数组到该着色器程序中的属性位置location。stride表示顶点之间的字节数,默认值为0,表示顶点在值数组中紧密排列。

type表示顶点值数组中元素的类型,通常为GL_FLOAT、GL_UNSIGNED_BYTE等。tupleSize表示每个顶点的分量数:1、2、3或4。

该数组将在调用位置的enableAttributeArray()时变为活动状态。否则,location的setAttributeValue()中指定的值将被使用。

注意:将启用标准化。如果不需要此操作,请通过QOpenGLFunctions直接调用glVertexAttribPointer。

参见setAttributeArray()。

 

void QOpenGLShaderProgram::setAttributeValue(int location, GLfloat value)

将当前上下文中位置为location的属性设置为value。

另请参阅 setUniformValue()。

 

void QOpenGLShaderProgram::setDefaultInnerTessellationLevels(const QVector<float> &levels)

设置用于Tessellation原语生成器的默认内细分级别,如果细分控制着色器没有将其输出到levels中。有关OpenGL和Tessellation着色器的更多详细信息,请参阅OpenGL Tessellation Shaders。

levels参数应该是由2个浮点数组成的QVector。并非所有值都适用于所有细分模式。如果您指定少于2个元素的向量,则剩余的元素将被赋予默认值1。

注意:这修改全局OpenGL状态,并不特定于此QOpenGLShaderProgram实例。您应在需要时在渲染函数中调用此函数,因为QOpenGLShaderProgram不会为您应用此函数。这仅是一个方便函数。

注意:此函数仅在OpenGL> = 4.0中可用,并且不支持OpenGL ES 3.2。

另请参见defaultInnerTessellationLevels()和setDefaultOuterTessellationLevels()。

 

void QOpenGLShaderProgram::setDefaultOuterTessellationLevels(const QVector<float> &levels)

设置用于Tessellation原语生成器的默认外细分级别,如果细分控制着色器没有将其输出到levels中。有关OpenGL和Tessellation着色器的更多详细信息,请参阅OpenGL Tessellation Shaders。

levels参数应该是由4个浮点数组成的QVector。并非所有值都适用于所有细分模式。如果您指定少于4个元素的向量,则剩余的元素将被赋予默认值1。

注意:这修改全局OpenGL状态,并不特定于此QOpenGLShaderProgram实例。您应在需要时在渲染函数中调用此函数,因为QOpenGLShaderProgram不会为您应用此函数。这仅是一个方便函数。

注意:此函数仅在OpenGL> = 4.0中可用,并且不支持OpenGL ES 3.2。

另请参见defaultOuterTessellationLevels()和setDefaultInnerTessellationLevels()。

 

void QOpenGLShaderProgram::setPatchVertexCount(int count)

使用此函数指定OpenGL中补丁中的顶点数count。补丁是一种自定义OpenGL原语,其解释完全由细分着色器阶段定义。因此,在使用包含细分阶段着色器的QOpenGLShaderProgram时,调用此函数才有意义。在使用OpenGL细分时,唯一可以使用glDraw*()函数呈现的原语是GL_PATCHES。

这相当于调用glPatchParameteri(GL_PATCH_VERTICES,count)。

注意:这修改全局OpenGL状态,并不特定于此QOpenGLShaderProgram实例。您应在需要时在渲染函数中调用此函数,因为QOpenGLShaderProgram不会为您应用此函数。这仅是一个方便函数。

另请参见patchVertexCount()。

 

void QOpenGLShaderProgram::setUniformValue(int location, GLfloat value)

将当前上下文中位置为location的uniform变量设置为value。

另请参见setAttributeValue()。

 

void QOpenGLShaderProgram::setUniformValueArray(int location, const GLfloat *values, int count, int tupleSize)

将当前上下文中位置为location的uniform变量数组设置为值数组values中的count个元素。每个元素有tupleSize个组件。tupleSize必须是1、2、3或4。

另请参见setAttributeValue()。

 

QList<QOpenGLShader *> QOpenGLShaderProgram::shaders() const

返回一个列表,其中包含使用addShader()添加到此着色器程序中的所有着色器。

另请参见addShader()和removeShader()。

 

int QOpenGLShaderProgram::uniformLocation(const char *name) const

返回此着色器程序参数列表中uniform变量名的位置。如果name不是此着色器程序的有效uniform变量,则返回-1。

另请参见attributeLocation()。