Opengl 使用着色器的顶点VBO颜色

Opengl 使用着色器的顶点VBO颜色,opengl,vbo,pyopengl,Opengl,Vbo,Pyopengl,我正在用OpenGL(PyOpenGL和Python)显示一个几何体(文件格式:.stl)。几何体数据具有相同的属性,并由三角形组合而成 我保存到VBO的数据;顶点、法线和颜色。由于法线仅为每3个顶点(三角形)定义,并且我为每个顶点定义了颜色向量,因此VBO中的数据具有以下形式: VBO = [v1x, v1y, v1z,...vNx, vNy, vNz, n1x, n1y, n1z,...nNx, nNy, nNz, R1, G1, B1,...RN, GN, BN

我正在用OpenGL(PyOpenGL和Python)显示一个几何体(文件格式:.stl)。几何体数据具有相同的属性,并由三角形组合而成

我保存到VBO的数据;顶点、法线和颜色。由于法线仅为每3个顶点(三角形)定义,并且我为每个顶点定义了颜色向量,因此VBO中的数据具有以下形式:

VBO = [v1x, v1y, v1z,...vNx, vNy, vNz,
       n1x, n1y, n1z,...nNx, nNy, nNz,
       R1, G1, B1,...RN, GN, BN]
用文字表达;首先我保存所有顶点,然后我“附加”(使用
glBufferSubData
)所有法线(法线的数量是顶点数量和vertice颜色的3倍),然后我附加每个顶点的颜色向量(使用
glBufferSubData
)。 我想知道这是否是个好主意,因为我在用不同的颜色绘制每个顶点时遇到了问题。绘图代码为:

glPushMatrix()
glEnableClientState(GL_VERTEX_ARRAY)
glVertexPointer(3, 
                GL_FLOAT, 
                0, 
                None)
glEnableClientState(GL_COLOR_ARRAY)
glColorPointer(3,
               GL_UNSIGNED_BYTE,
               0,
               self.data_size_vertices+self.data_size_normals)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.vbo_id)     
glDrawArrays(GL_TRIANGLES,
             0,
             self.N_vertices)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) # reset
glDisableClientState(GL_COLOR_ARRAY)
glDisableClientState(GL_VERTEX_ARRAY)
glPopMatrix()
我想我在
glColorPointer()
方面有问题。有人能指出这个问题吗?我还看到了另外两种将数据保存到VBO的方法:

  • 为顶点创建单独的VBO,为法线创建单独的VBO,为颜色创建单独的VBO
  • 一个VBO,但其格式为:
    [v1、c1、v2、c2、v3、c3、n1,…]
  • 这两者中有哪一个是更好的解决方案(在实践中更常见)?我是否必须为每个顶点指定一个三角形的法线,尽管它是相同的(对于定义三角形的3个顶点)?由于我希望获得如下所示的显示(左:当前状态,中:平面,右:理想-重点是曲面着色),我想请您为我提供一些如何实现这一点的指导(使用着色器)。
    必须为每个顶点复制法线。对于OpenGL,顶点是一组属性(如位置、颜色、法线、纹理坐标等)。顶点由其索引引用,因此第i个顶点将由所有启用属性数组的第i个元素组成

    顶点属性的常见布局是逐顶点交错属性,如

    v1x, v1y, v1z, n1x, n1y, n1z, R1, G1, B1, v2x, ...
    
    这样,为处理单个缓存而获取的所有数据都是彼此接近的本地数据,从而提高了缓存效率。您可以使用attrib指针的
    stride
    参数为这种布局进行设置


    在我看来,“当前状态”图像与未启用普通阵列(且照明仍处于启用状态)时的图像类似。然后,GL将为所有顶点重用当前设置的法线向量,从而生成您看到的着色。查看“理想”图像,我会得出结论,蓝色适合对象,因此我看不出颜色数组有什么问题。

    必须为每个顶点复制法线。对于OpenGL,顶点是一组属性(如位置、颜色、法线、纹理坐标等)。顶点由其索引引用,因此第i个顶点将由所有启用属性数组的第i个元素组成

    顶点属性的常见布局是逐顶点交错属性,如

    v1x, v1y, v1z, n1x, n1y, n1z, R1, G1, B1, v2x, ...
    
    这样,为处理单个缓存而获取的所有数据都是彼此接近的本地数据,从而提高了缓存效率。您可以使用attrib指针的
    stride
    参数为这种布局进行设置


    在我看来,“当前状态”图像与未启用普通阵列(且照明仍处于启用状态)时的图像类似。然后,GL将为所有顶点重用当前设置的法线向量,从而生成您看到的着色。查看“理想”图像,我会得出结论,蓝色适合对象,因此我看不出您的颜色数组有什么问题。

    您得到的图像有什么问题?“当前状态”是您应该从代码中获得的状态(忽略法线,就像您当前所做的那样)。@derhass OK。如果我理解正确,我必须使用
    glNormalPointer
    调用以获得类似于中间或右侧的显示?如果我使用
    glNormalPointer
    ,我是否必须使用着色器,或者该函数是否可以在没有着色器的情况下使用,并且仍然可以像中间或右侧那样显示?您得到的图像有什么问题?“当前状态”是您应该从代码中获得的状态(忽略法线,就像您当前所做的那样)。@derhass OK。如果我理解正确,我必须使用
    glNormalPointer
    调用以获得类似于中间或右侧的显示?如果我使用
    glNormalPointer
    ,我是否必须使用着色器,或者该函数是否可以在没有着色器的情况下使用,并且仍然可以像中间或右侧那样显示?确定。我将重塑数据,使其具有您建议的形状。此时未启用法线-“当前状态”。中间状态的颜色差异并不重要,重点是表面的着色或绘制以及如何着色。我是否必须使用
    glvertexattributepointer()
    函数,或者您建议使用哪些函数?我是否必须使用着色器来绘制每个顶点的不同颜色?我找不到一个明确的答案。@avstenit:很难猜测在查看结果图像时使用了什么照明模型。但是,它就像您显示的着色一样,可以通过使用固定的函数管道来实现。您只需要提供正确的法向量,设置适当的材质和灯光属性。然而,所有这些当然都可以通过着色器来实现,这将是当今推荐的方法。感谢您的回复。我希望我可以使用固定的函数管道(没有着色器)。我已经开始研究一点着色器(它正在工作),但理解其逻辑需要时间。由于可视化只是项目的一半,它不是重点,重点是物理部分,所以我想让它尽可能简单:)好的。我将重塑数据,使其具有您建议的形状。此时未启用法线-“当前状态”。中间状态的颜色差异并不重要,重点是表面的着色或绘制以及如何着色。我是否必须使用
    glvertexattributepointer()
    函数,或者您建议使用哪些函数?我是否必须使用着色器来绘制