使用 glvertex4i 传递网格面索引时出现顶点着色器错误

Posted

技术标签:

【中文标题】使用 glvertex4i 传递网格面索引时出现顶点着色器错误【英文标题】:Vertex Shader error while Passing mesh face index using glvertex4i 【发布时间】:2020-01-21 01:14:40 【问题描述】:

正在初始化 GL_List 以进行处理。

glBegin(GL_POINTS); 
for (i = 0; i < faceNum; i++)

    mesh->GetFaceNodes(i + 1, ver[0], ver[1], ver[2], ver[3]);
    **glVertex4i(ver[0] - 1, ver[1] - 1, ver[2] - 1, i+1);**

glEnd();    
glEndList();

顶点着色器给我一个编译错误,不知道为什么。

顶点着色器:

varying out float final;

void main( void )

    final = float(gl_Vertex.w);       // want to pass this face index on to 

几何着色器:

varying in float final[];
varying out float final_tofrag;
final_tofrag=final[0];


//Doing other calculations here they are totally different 

片段着色器:

varying in float final_tofrag;

void main( void )

    if (color.z<0.0)
            gl_FragData[0] = vec4(float(final_frag),float(final_frag), -(gl_FragCoord.z), 0); // want to check that value of the final(gl_vertex.w) is being passed from vertex shader to fragment shader or not. Its giving me 0.00000;
    else
            gl_FragData[0] = vec4(float(final_frag), float(final_frag), gl_FragCoord.z, 0);

【问题讨论】:

【参考方案1】:

如果您确实在问题中发布了编译错误,这会有所帮助,否则 我们 不知道您的错误是什么。

所以,既然我是在黑暗中随机猜测,我会在这里做几个猜测。

    您将浮点数分配给整数,这可能会导致转换错误。
// this might now compile, but it will probably only ever give you
// zero or one. Was that the intent?
final = int(gl_Vertex.w); 

    您没有在顶点着色器中写入 gl_Position。如果您不写入该值,OpenGL 将无法执行您的顶点着色器。

    在片段着色器中,您正在检查值 color.z,但尚未将颜色声明为统一、着色器输入或 const。

    虽然这不会导致编译错误,但将 final(值为 1 或 0 的整数?)除以整数值 100 或 1000 只会得到零或一。是否打算将 final 用作浮点数而不是整数?

    您在片段着色器的 vec4 声明中混合了整数和浮点数。这可能会导致编译器出现问题。

很遗憾,如果无法访问 GLSL 错误日志,除了我上面列出的问题之外,任何人都无法识别您的问题。

【讨论】:

这不是 opengl 的工作方式。您在 C++ 中将数据指定为整数。 OpenGL 将简单地将整数数据转换为浮点数,以便在 GPU 上进行处理。在 gl_Vertex 的情况下,它始终是一个浮点 vec4。 您的着色器代码不可能链接或编译。调用glCompileShader后,glGetShaderInfoLog报的错误日志是什么? 再说一次,如果您没有在问题中提供错误,那么没有人会猜到您的问题的解决方案。 所以我更改了代码,因为 OpenGL 不支持可变 int。现在我可以使用上面的代码编译代码并使用上面的代码获取面部索引的输出,但不确定这些是面部索引,因为它们的值在 40000-20000 之间变化。网格中的总面数为 49000。【参考方案2】:

由于着色器不包含任何版本信息,它是一个OpenGL Shading Language 1.10 Specification 着色器。

在 GLSL 1.10 中,varying 类型为 int 的变量是不允许的,并且不支持从 intfloat 的隐式转换。 glsl 1.10 没有inout 变量。接口变量的关键字是varying

此外,变量color 未在片段着色器中定义。

varying float final;

void main( void )

    final = gl_Vertex.w;

    // [...]

varying float final_tofrag;

void main( void )

    if (final_tofrag < 0.0) // ?
         gl_FragData[0] = vec4(final_tofrag, final_tofrag, -gl_FragCoord.z, 0.0);
    else
         gl_FragData[0] = vec4(final_tofrag, final_tofrag, gl_FragCoord.z, 0.0);


我建议检查着色器编译是否成功以及程序对象是否链接成功。

如果着色器编译成功可以通过glGetShaderiv和参数GL_COMPILE_STATUS来检查。例如:

#include <iostream>
#include <vector>
bool CompileStatus( GLuint shader )

    GLint status = GL_TRUE;
    glGetShaderiv( shader, GL_COMPILE_STATUS, &status );
    if (status == GL_FALSE)
    
        GLint logLen;
        glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &logLen );
        std::vector< char >log( logLen );
        GLsizei written;
        glGetShaderInfoLog( shader, logLen, &written, log.data() );
        std::cout << "compile error:" << std::endl << log.data() << std::endl;
    
    return status != GL_FALSE;

程序链接是否成功可以通过glGetProgramiv和参数GL_LINK_STATUS来检查。例如:

bool LinkStatus( GLuint program )

    GLint status = GL_TRUE;
    glGetProgramiv( program, GL_LINK_STATUS, &status );
    if (status == GL_FALSE)
    
        GLint logLen;
        glGetProgramiv( program, GL_INFO_LOG_LENGTH, &logLen );
        std::vector< char >log( logLen );
        GLsizei written;
        glGetProgramInfoLog( program, logLen, &written, log.data() );
        std::cout << "link error:" << std::endl << log.data() << std::endl;
    
    return status != GL_FALSE;

【讨论】:

【参考方案3】:

问题中的代码没有任何意义。选择 GLSL 关键字 varying 是因为它旨在反映每个片段的数据将不同的属性,这是由于跨基元的自动插值。这只发生在 rasrerizer 和片段着色器之前的最后一个可编程着色器阶段之间。

一开始只有顶点着色器和片段着色器。 VS 将获得attributes 作为输入,并输出到varyings,这将是插值并成为 FS 的输入。

随着 GL 3.0 / GLSL 1.30 中几何着色器的引入,这种方案不再有意义。 VS 的输出将不再被插值,而是成为 GS 的直接输入。因此,关键字 attributevarying 其中 从 GLSL 中删除,取而代之的是更通用的 in / out 方案。

因此,具有varying 的 GS 不能存在。您要么使用不支持几何着色器的旧版 GLSL,要么使用带有 in/out 的较新 GLSL。

【讨论】:

以上是关于使用 glvertex4i 传递网格面索引时出现顶点着色器错误的主要内容,如果未能解决你的问题,请参考以下文章

当我在网格/面中实现索引时,为啥它会返回 OpenGL 错误?

CUDA笔记(一)线程与数据量的关系

计算数组时出现“列表分配索引超出范围”错误

将指向数组的指针传递给函数时出现分段错误(C++)

fluent中怎么使一个面旋转?

Kendo网格在网格中触发多个控件的数据源事件。(MVVM绑定)