是啥导致基于 OpenGL 2.0 的着色器处理代码在 ::glBegin() 中崩溃?

Posted

技术标签:

【中文标题】是啥导致基于 OpenGL 2.0 的着色器处理代码在 ::glBegin() 中崩溃?【英文标题】:What is causing OpenGL 2.0 based shader handling code to crash in ::glBegin()?是什么导致基于 OpenGL 2.0 的着色器处理代码在 ::glBegin() 中崩溃? 【发布时间】:2012-03-05 07:55:59 【问题描述】:

物有所值:

我的图形驱动程序 (ATI Mobility Radeon 4570) 是最新的。 我之前已经设法让基于 ARB 扩展的着色器处理代码在相同的配置上工作(尽管我回到着色器之前已经有一段时间了)。 我在我的设置中遵循 Lighthouse3d 教程(...松散地:Lighthouse3d shader setup 着色器编译日志代码已从一个 SO 问题中撕下,抱歉缺乏信用,我现在似乎找不到它)

基本上,我所有的 OpenGL 操作似乎都成功执行了;着色器编译和程序链接。正如您在下面看到的,我在每次 gl*** 调用后都检查了 OpenGL 错误。着色器本身是微不足道的。

当然,我可能忽略了一些简单得可笑的事情。

#define GLOP(operation) operation; if(!GFX::CheckError(#operation)) exit(1)
// GFX::CheckError() prints an error message, if any.

  GFX::Init(640, 480, 24, 0);
  GLOP(Texture2D::Enable());

  // shader setup
  GLuint  hFrag = GLOP(::glCreateShader(GL_FRAGMENT_SHADER));
  GLuint  hVert = GLOP(::glCreateShader(GL_VERTEX_SHADER));
  GLuint  hProg = GLOP(::glCreateProgram());

  std::ifstream inFile;
  ReadOpen("shader.frag", inFile);
  std::string  str(ReadFile(inFile));
  const char* pSource = str.c_str();
  GLOP(::glShaderSource(hFrag, 1, &pSource, 0));
  GLOP(::glCompileShader(hFrag));

  GLint logLength;
  glGetShaderiv(hFrag, GL_INFO_LOG_LENGTH, &logLength);
  if (logLength > 0) 
      GLchar* log = (GLchar*)malloc(logLength);
      glGetShaderInfoLog(hFrag, logLength, &logLength, log);
      printf("Shader compile log:\n%s\n", log);
      free(log);
  

  XR::ReadOpen(core.GetPath() + "shader.vert", inFile);
  XRLOG(XR::GetFileSize(inFile) << " bytes in file." << std::endl);
  str = XR::ReadFile(inFile);
  pSource = str.c_str();
  GLOP(::glShaderSource(hVert, 1, &pSource, 0));
  GLOP(::glCompileShader(hVert));

  glGetShaderiv(hVert, GL_INFO_LOG_LENGTH, &logLength);
  if (logLength > 0) 
      GLchar* log = (GLchar*)malloc(logLength);
      glGetShaderInfoLog(hVert, logLength, &logLength, log);
      printf("Shader compile log:\n%s\n", log);
      free(log);
  

  GLOP(::glAttachShader(hProg, hFrag));
  GLOP(::glAttachShader(hProg, hVert));
  GLOP(::glLinkProgram(hProg));

  glGetProgramiv(hProg, GL_INFO_LOG_LENGTH, &logLength);
  if (logLength > 0) 
      GLchar* log = (GLchar*)malloc(logLength);
      glGetProgramInfoLog(hProg, logLength, &logLength, log);
      printf("Program link log:\n%s\n", log);
      free(log);
  

  GLOP(::glUseProgram(hProg));

  // get uniform's location
  GLint locTex0 = GLOP(::glGetUniformLocation(hProg, "tex0"));

  /// [loading image, creating texture goes here. works perfectly.]

  while(core.IsRunning())
  
    GLOP(::glActiveTexture(GL_TEXTURE0));
    GLOP(pTex->Bind());
    GLOP(::glUniform1i(locTex0, GL_TEXTURE0));
    GLOP(::glPushMatrix());
    GLOP(::glTranslatef(GFX::GetFlopWidth() / 2, GFX::GetHeight() / 2, .0f)); // still no errors
    ::glBegin(GL_TRIANGLE_FAN);  // crash
    ::glTexCoord2f(.0f, 1.0f);
    ::glVertex2f(-100.0f, -100.0f);
    ::glTexCoord2f(1.0f, 1.0f);
    ::glVertex2f(100.0f, -100.0f);
    ::glTexCoord2f(1.0f, .0f);
    ::glVertex2f(100.0f, 100.0f);
    ::glTexCoord2f(.0f, .0f);
    ::glVertex2f(-100.0f, 100.0f);
    ::glEnd();
    ::glPopMatrix();
  

顶点着色器:

void main( void )

  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
  gl_TexCoord[0] = gl_MultiTexCoord0;

片段着色器:

uniform sampler2D tex0;

void  main()

  vec2  texCoords = gl_TexCoord[0].st;
  vec3  pixel = texture2D(tex0, texCoords).xyz;
  gl_FragColor = vec4(pixel, 1.0);

输出:

Successfully set video mode 640x480@24
Shader compile log:
Fragment shader was successfully compiled to run on hardware.

Shader compile log:
Vertex shader was successfully compiled to run on hardware.

Program link log:
Vertex shader(s) linked, fragment shader(s) linked.

【问题讨论】:

【参考方案1】:

它会在第一帧崩溃吗?

我有点怀疑这与您的崩溃有关,但您应该知道您调用 glVertex/glTexcoord 的顺序错误。 glVertex 终止一个顶点,因此在您的情况下,第一个 glVertex 没有设置 texcoord,并且您的最后一个 texcoord 将在下一个循环中应用。

【讨论】:

是的,它在第一帧就崩溃了。感谢您指出 glVertex2f 和 glTexCoord2f 的错误顺序 - 这是仓促写出纹理四边形渲染的产物;我现在已经编辑过了。此示例中的运行时在崩溃之前永远不会到达那里。【参考方案2】:

核心配置文件不支持像这样提交顶点的立即模式,所以我想知道您是否在设置 OpenGL 上下文时指定了核心配置文件。这可以解释为什么它会在 glBegin 处死掉。

【讨论】:

似乎不太可能导致它硬崩溃。此外,他在前几行也调用了 glPushMatrix,这也不是核心。 好点。另外,我在自己的设置中尝试了这个,使用核心配置文件执行命令很好。他们只是没有做任何有用的事情。所以我现在认为其他地方存在问题,可能是由其他原因引起的某种堆栈损坏。

以上是关于是啥导致基于 OpenGL 2.0 的着色器处理代码在 ::glBegin() 中崩溃?的主要内容,如果未能解决你的问题,请参考以下文章

IOS:OpenGL ES 2.0 与 3.0 中动态分支着色器的性能

OpenGL ES 2.0 符点精度

如何在 OpenGL ES 2.0 中获得“发光”着色器效果?

用于模糊的 OpenGL ES 2.0 片段着色器速度慢且质量低

是否可以在顶点着色器内持续更改 iPhone OpenGL ES 2.0 上的 VBO 值?

如何在 OpenGL ES 2.0 中将视图/模型/投影矩阵传递给我的顶点着色器?