繁体   English   中英

将 position 从顶点着色器传递到片段着色器的问题

[英]Problem in passing position from vertex shader to fragment shader

//Vertex Shader
#version 450 core
out vec3 vs_color;
layout(location=0) in vec3 position;
layout(location=1) in vec3 colors;
uniform float x_offset;
void main(void)
{   
    gl_Position = vec4(position,1.0);
    gl_Position.x += x_offset;
    //vs_color = colors;
    vs_color = position;
}

//Fragment Shader
#version 450 core
out vec4 color;
in vec3 vs_color;
void main(void)
{
    color = vec4(vs_color,1);
}

这仅在我在顶点着色器中使用 vs_color = colors 时才有效,对于任何其他值,例如:位置(包含顶点的 xyz 坐标)或 vec3(0.1,0.1,0.1),它会在 glDrawArrays() 处引发此异常:

Exception thrown at 0x048D1AD0 (nvoglv32.dll) in OpenGL Starting Out.exe: 
0xC0000005: Access violation reading location 0x00000000.

为什么会发生这种情况,我该如何解决? (我想尝试将 position 值设置为颜色值)编辑:
另外,如果我不使用启用第二个顶点属性
glEnableVertexArrayAttrib(VAO,1) //VAO is my vertex array object我可以做我想做的(将 position 传递给片段着色器)

但是如果我启用它,我需要将它传递给片段着色器,然后将颜色传递给 output(如果我在片段着色器中不做任何事情,它会给出相同的错误)
以下是属性的设置方式:

    glBufferData(GL_ARRAY_BUFFER, sizeof(verticesAndcolors), verticesAndcolors, GL_STATIC_DRAW);
    glVertexAttribPointer(
        glGetAttribLocation(rendering_program,"position"),          
        3,                                                          
        GL_FLOAT,                                                   
        GL_FALSE,                                                   
        6*sizeof(float),        
        (void*)0                        
    );
    glVertexAttribPointer(
        glGetAttribLocation(rendering_program,"colors"),    
        3,                                                  
        GL_FLOAT,
        GL_FALSE,
        6*sizeof(float),    
        (void*)(3*sizeof(float))
    );
    glEnableVertexArrayAttrib(VAO, 0);
    glEnableVertexArrayAttrib(VAO, 1);

编辑2:
如果我做:

gl_Position = vec4(colors,1.0);
vs_color = position;

它不会造成访问冲突并且有效,
我检查了我是如何设置顶点属性的,但我无法做到这一点。

问题的根本原因在于:

 glVertexAttribPointer(glGetAttribLocation(rendering_program,"position"), ...) glVertexAttribPointer(glGetAttribLocation(rendering_program,"colors"), ...); ... glEnableVertexArrayAttrib(VAO, 0); glEnableVertexArrayAttrib(VAO, 1);

只有活动属性才会有位置,如果您使用layout(location=...)限定属性并不重要。 如果着色器中没有使用该属性,则该属性将被优化掉,因此将没有位置。 glGetAttribLocation()返回一个签名的 integer 并使用返回值-1表示没有具有该名称的活动属性。 glVertexAttribPointer()需要一个无符号的属性位置,并且(GLuint)-1最终会以一个非常高的数字结束,超出允许的范围,所以这个 function 只会产生一个 GL 错误,但不会设置任何指针。

但是,您将glEnableVertexArrayAttrib()硬编码位置01一起使用。

每个属性的默认顶点属性指针为0 ,绑定此属性的默认 cvertex 数组缓冲区也是0 ,因此该指针将被解释为指向客户端 memory 的指针。

这意味着如果positioncolor都处于活动状态(意思是:在代码中以某种方式使用,以便着色器编译器/链接器不能完全排除它可能影响输出),您的代码将按预期工作。

但是,如果您只使用一个,则不会为另一个设置指针,但仍启用该数组 这意味着您的驱动程序实际上将访问地址0的 memory :

在 OpenGL 的 0x048D1AD0 (nvoglv32.dll) 处引发异常,开始 Out.exe:0xC0000005:访问冲突读取位置 0x00000000。

所以这里有几件事:

  • 始终检查glGetAttribLocation()的结果,并正确处理-1情况。
  • 永远不要使用不同的方式来获取传递给glVertexAttribPointer的属性索引和对应的glEnableVertexAttrib()
  • 检查总帐错误。 在任何地方,在应用程序开发过程中都可以使用GL 调试 output功能,以获得一种很好且有效的方式来通知所有 GL 错误(以及您的驱动程序可以检测到的其他问题)。 例如,我的实现(Nvidia/Linux)会报告API error high [0x501]: GL_INVALID_VALUE error generated. Index out of range. API error high [0x501]: GL_INVALID_VALUE error generated. Index out of range. 当我调用glVertexAttribPointer(-1,...)时。

我终于能够解决这个问题:
我在我的绘图循环中调用glUseProgram(programObj) ,将它移出它解决了问题

我不确定为什么会导致问题发生,但我的猜测是 openGL 在未使用顶点属性时做了一些事情,然后该更改导致下一次迭代中的访问冲突。

如果您知道原因,请随时告诉我

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM