一个主 OpenGL 程序中的多个着色器

Posted

技术标签:

【中文标题】一个主 OpenGL 程序中的多个着色器【英文标题】:Multiple shaders inside one Main OpenGL program 【发布时间】:2016-11-11 04:05:02 【问题描述】:

我正在尝试将不同的着色器附加到我的 OpenGL 主程序中的不同程序,以渲染不同的对象。更具体地说,我有一个行星对象(obj),我想将它渲染成两个不同的行星,一个带有凹凸贴图,另一个带有多个纹理。

我想出了以下框架,但它不起作用。

void setUp()
   planet_1_programID = createProgramAndAttachShader(parameters...)
   planet_2_programID = createProgramAndAttachShader(parameters...)

void sendDataToOpenGL()
    create VAO and bind the VAO
    load data into a VBO
    send the data to OpenGL


void paintGL(void)
    glm::mat4 lookatMatrix = ...
    glm::mat4 projectionMatrix = ...
    glm::mat4 lookatMatrix = ...        
    glm::mat4 transformationMatrix = ... 

    // planet 1
    glUseProgram(planet_1_programID)
    bind to the previous created VAO
    bind texture information
    some model transformation
    glDrawArrays();

    // planet 2
    glUseProgram(planet_2_programID)
    bind to the previous created VAO
    bind texture information
    some model transformation
    glDrawArrays();

渲染结果是最终场景中只出现了一颗行星。我想知道我是否以不正确的方式理解了函数 glUseProgram。谁能给我一些提示?

[update] 是不是因为在 glUseProgram 之后我需要重新定义所有变量?目前我在 glUseProgram 之前定义了大部分变量,因为这两个行星将具有基本相同的变量。

【问题讨论】:

“定义所有变量”是什么意思?如果您指的是设置程序统一 - 那么是的,它们是每个程序的,因此您必须将它们单独设置到每个程序 - 除非您使用统一缓冲区对象。您也可以查看程序管道对象。 【参考方案1】:

是不是因为我需要在 glUseProgram 之后重新定义所有变量?目前我在 glUseProgram 之前定义了大部分变量,因为这两个行星将具有基本相同的变量。

如果您指的是“制服”,那么类似的东西(!)就是您的问题。您会看到,每个程序存储统一值,因此您必须为每个程序至少设置一次统一值。不必在每个glUseProgram 之后都执行此操作,但您必须为每个“glUseProgram”执行至少一次。

【讨论】:

但是假设我的统一 MVP 矩阵对于所有对象都是相同的。每次使用程序后都需要分别设置吗? @LouisKuang:制服的值存储在程序对象中。因此,您必须为每个程序至少设置一次值。如果您认为这是低效的:是的,这就是 Uniform Buffer Objects 的原因:opengl.org/wiki/Uniform_Buffer_Object

以上是关于一个主 OpenGL 程序中的多个着色器的主要内容,如果未能解决你的问题,请参考以下文章

跨多个着色器的 OpenGL 统一

初识OpenGL 链接着色器

初识OpenGL 链接着色器

openGL一些概念02

osgEarth的Rex引擎原理分析(一二二)着色器程序的opengl过程

opengl着色器程序中的重复顶点