如何使用多个着色器程序? [关闭]

Posted

技术标签:

【中文标题】如何使用多个着色器程序? [关闭]【英文标题】:How to use more than one shader program? [closed] 【发布时间】:2014-07-11 20:59:27 【问题描述】:

使用一个着色器程序,我的代码如下所示:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
InitFunctions();
glUseProgram(ShaderProgram);

//render objects

glutSwapBuffers();

但我想添加另一个着色器程序,但它似乎清除了屏幕。即使只是在渲染对象后放置它也会清除屏幕:

glUseProgram(ShaderProgramNew);

屏幕不清除屏幕的唯一一次是当我在 glUseProgram() 的两次使用中使用相同的着色器时

要加载着色器,我使用这个函数:

GLuint ShaderProgramManager::loadProgram(char* VertexShaderFileLocation, char*     FragmentShaderFileLocation)

cout << "Creating Shader...\n";
cout << "Initalizing Variables\n";
GLuint ShaderProgram = glCreateProgram();
GLuint VertexShader = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

string VString = loadShader(VertexShaderFileLocation);
string FString = loadShader(FragmentShaderFileLocation);

const GLchar* VText = (const GLchar*)VString.c_str();
const GLchar* FText = (const GLchar*)FString.c_str();

cout << "Load VertexShader and FragmentShader\n";

const GLchar* pp[1];
pp[0] = FText;
GLint Lengthss[1];
Lengthss[0] = strlen(FText);
glShaderSource(FragmentShader, 1, (const GLchar**)&pp, Lengthss);
glCompileShader(FragmentShader);

const GLchar* p[1];
p[0] = VText;
GLint Lengths[1];
Lengths[0] = strlen(VText);
glShaderSource(VertexShader, 1, (const GLchar**)&p, Lengths);
glCompileShader(VertexShader);

GLint success;
glGetShaderiv(FragmentShader, GL_COMPILE_STATUS, &success);
if (!success) 
    GLchar InfoLog[1024];
    glGetShaderInfoLog(FragmentShader, sizeof(InfoLog), NULL, InfoLog);
    fprintf(stderr, "Error compiling shader type %d: '%s'\n", GL_FRAGMENT_SHADER, InfoLog);



glGetShaderiv(VertexShader, GL_COMPILE_STATUS, &success);
if (!success) 
    GLchar InfoLog[1024];
    glGetShaderInfoLog(VertexShader, sizeof(InfoLog), NULL, InfoLog);
    fprintf(stderr, "Error compiling shader type %d: '%s'\n", GL_VERTEX_SHADER, InfoLog);


cout << "Shaders Compiled.\n";



cout << "Attach Shaders\n";
glAttachShader(ShaderProgram, VertexShader);
glAttachShader(ShaderProgram, FragmentShader);

cout << "Link Program\n";
glLinkProgram(ShaderProgram);

cout << "Validate Program\n";
glValidateProgram(ShaderProgram);
cout << "Complete.\n";
return ShaderProgram;

还有这个:

string ShaderProgramManager::loadShader(char* location)

string textS = "";
string line;
ifstream myfile(location);

cout << "Start of shader tex:\n" << "\n";

    while (getline(myfile, line))
    
        //cout << line << "\n\n";
        textS = textS + line + "\n";
    

    cout << "End of shader text" << "\n";

    //text = new char[sizeOfCharArray];
    //strcat(text, textS.c_str());
    myfile.close();

    cout << "Shader Finished Loading.\n";


    return  textS;

在程序开始时我运行这个

ShaderProgramManager spm;

    ShaderProgram = spm.loadProgram("data/Shaders/VertexShader.txt", "data/Shaders/FragmentShader.txt");

        gWorldLocation = glGetUniformLocation(ShaderProgram, "gWorld");
        rotmLocation = glGetUniformLocation(ShaderProgram, "rotm");
        PermLocation = glGetUniformLocation(ShaderProgram, "persm");

【问题讨论】:

如果没有看到着色器程序就无法回答这个问题。着色器的创建。制服和属性是如何配置的等等。 我不介意人们投反对票,但我希望有一个理由让我可以解决问题。 我没有投反对票,但在您的编辑中,您上传了许多用于编译程序的通用代码,这可能很好,因为您的一个着色器可以工作。但没有关于 ShaderProgramNew 内容和设置的详细信息。我敢打赌,ShaderProgramNew 无效或使用不当。 我不认为 ShaderProgramNew 是无效的,因为如果我把它放在两个 glUseProgram() 中,它就会按预期工作 无论你的着色器是好是坏,我想不出这样一种可能的情况,即简单地使用任何类型的着色器调用glUseProgram() 会清除以前的渲染。这里肯定有其他事情发生。 【参考方案1】:

当我想在一次渲染过程中使用 2 个不同的着色器时,此解决方案非常适合我。

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shaderProgram01);

// Do Modelview and projection matrix stuff and uniforms

// Render objects with fstshaderProgram

glUseProgram(shaderProgram02);
// Do Modelview and projection matrix stuff and uniforms

// Render objects with 2nd shaderProgram

glutSwapBuffers();

非常重要的是您必须重新上传所有需要的制服。对于这种方法,我假设您正确加载着色器并且它们工作正常。 使用 glut 您每次迭代只需调用一个 glutSwapBuffers() 。

【讨论】:

你是对的!我在渲染函数开始时上传了我所有的制服,而不是在调用 glUseProgram() 之后只上传那个着色器程序的制服 现在可以用了吗? 是的。它现在正在工作。 虽然这可能会解决 OP 的问题,但解释确实不正确。您不必每次调用glUseProgram() 后都重新上传制服。唯一重要的是在绑定正确的程序时设置制服。在那之后,他们坚持这个计划。引用规范:“Uniforms 是程序对象特定的状态。一旦加载,它们就会保留其值,并且只要程序对象未被重新链接,它们的值就会在使用程序对象时恢复。”

以上是关于如何使用多个着色器程序? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

GLSL 问题:一个程序中有多个着色器

c ++ opengl我如何制作着色器文件并在主cpp中使用它[关闭]

当有多个着色器程序时使用 glClear()

在opengl矩形上使用着色器会导致它消失[关闭]

如何在片段着色器中平铺部分纹理

如何使用着色器程序将 2D 场景放入 QOpenGLWidget 窗口?