为啥 glDrawElments() 在不使用任何着色器的情况下工作?

Posted

技术标签:

【中文标题】为啥 glDrawElments() 在不使用任何着色器的情况下工作?【英文标题】:Why glDrawElments() is working without using any shader?为什么 glDrawElments() 在不使用任何着色器的情况下工作? 【发布时间】:2019-04-09 07:29:10 【问题描述】:

我正在尝试调试一些着色器,但我无法更改当前加载的着色器。我尝试在不加载任何着色器或链接任何程序的情况下运行它仍然可以工作。

我已经尝试从我的硬盘中完全删除着色器。我试图在调用 glDrawElements 之前调用 glUseProgram(任何随机数,包括 0),它仍然有效。即使我加载任何着色器,它也不会产生任何效果。如果我在文件中出错,它仍然会显示链接和编译错误,但是在运行可执行文件时它只会忽略着色器中的内容。

我用这个画顶点

void Renderer::renderFrame() 
    vao.bind();
    glUseProgram(0);
    glDrawElements(GL_LINE_LOOP, 3, GL_UNSIGNED_INT, nullptr);

这是我的窗口提示

void App::start() 
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 4);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

    window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 500,500, SDL_WINDOW_RESIZABLE|SDL_WINDOW_OPENGL);
    this->context = SDL_GL_CreateContext(window);
    glewInit();
    glClearColor(0.5,1.0,1.0,1.0);

     renderer.init();

【问题讨论】:

如果没有绑定有效的着色器,则使用默认的固定函数(你知道 GL 1.0 向后兼容性),所以如果你的属性位置与使用的固定函数匹配,你的 CPU 端代码仍然会渲染图像,请参见 @ 987654321@ 但是这些位置不是由任何标准定义的,因此对于任何供应商来说都是不同的(并且会随着时间而变化)。只有 nVidia 定义了它并在多年后仍在使用它。 @Spektre:代码明确请求核心配置文件。所以它不能使用固定功能的东西。 @NicolBolas:它为 next SDL_CreateWindow() 调用请求核心配置文件。 我认为@Spektre 是对的。修复代码正常工作后,我的顶点着色器在布局位置出现错误。我认为如果着色器不正确,它会引发错误,但看起来它会更改为兼容性。 @Spektre 您能否发表您的第一条评论作为答案,以便我接受? 【参考方案1】:

SDL_GL_SetAttribute() 仅影响 下一个 SDL_CreateWindow() 调用。

来自the doc wiki:

使用此函数在创建窗口之前 设置 OpenGL 窗口属性。

所以现在您很可能会获得一个兼容性上下文,其中无着色器绘制完全有效。您可以检查GL_VERSION 的值,看看您得到了什么。

如果你想要一个核心上下文,让那些SDL_GL_SetAttribute() 调用之前你的SDL_CreateWindow()

SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 500,500, SDL_WINDOW_RESIZABLE|SDL_WINDOW_OPENGL);
this->context = SDL_GL_CreateContext(window);

【讨论】:

对不起我的代码。这是一个错误的问题。在我的代码中,属性是之前设置的,但是当我写问题时,为了清楚起见,我把所有的方法都放在了一个方法中,并没有意识到我是在创建窗口之后放的。【参考方案2】:

如果没有绑定有效的着色器,则通常会使用默认的固定函数(您知道 GL 1.0 向后兼容,即使在 核心配置文件 上也是如此取决于供应商/驱动程序)。

因此,如果您的 属性位置 与使用的 固定功能 匹配,您的 CPU 端代码仍会呈现图像,请参阅:

What are the Attribute locations for fixed function pipeline in OpenGL 4.0++ core profile?

但是,位置没有由任何标准定义,因此对于任何供应商来说都是不同的(并且可以随时间/驱动程序版本而变化)。只有 nVidia 定义了它并在多年后仍在使用它......

因此,最好检查 GLSL 编译器/链接器日志以了解开发中的任何着色器以避免混淆......有关如何获取它们的更多信息,请参阅:

complete GL+GLSL+VAO/VBO C++ example

顺便说一句,一些 gfx 驱动程序支持日志记录,如果启用,它会将 GLSL 日志保存到自己的文件中...例如可以使用 nVidia 驱动程序和NVEmulate utility

【讨论】:

以上是关于为啥 glDrawElments() 在不使用任何着色器的情况下工作?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 C# 中的数字格式字符串在不使用小数 (F0) 时会将数字四舍五入?

为啥我要在不调试的情况下开始调试构建?

为啥 scipy.optimize.minimize (默认)在不使用 Skyfield 的情况下报告成功?

为啥我可以键入别名函数并在不强制转换的情况下使用它们?

为啥我可以在不使用 std::getline 的情况下调用 getline?

为啥我在不使用 get 方法时不断收到“The GET method...”? [复制]