仅使用顶点着色器有效地渲染

Render efficiently with only vertex shader

本文关键字:有效地 顶点      更新时间:2023-10-16

我有一个文件,我从中读取顶点位置/-uvs/-normals以及索引。我想以最有效的方式渲染它们。那不是问题。我还想使用顶点着色器来取代垂直的骨头和动画。

当然,我想以最有效的方式实现这一目标。质地在外部绑定,我什么都不关心。

我的第一个想法是使用glvertexattribute*和glbindbuffer*等。但是我无法找到一种方法来使我的正态通过glnormal时,gltexcoord,gltexcoord,它们会自动处理。

就像我说的那样,我只能使用顶点着色器,片段等。

您正在使用什么版本的GLSL?

这可能不会回答您的问题,但它显示了如何在不依赖非标准属性异化的情况下正确设置通用顶点属性。

对于所有版本(您使用通用顶点属性)的一般想法都是相同的,但是在GLSL中声明它们的语法有所不同。无论您使用的是什么版本,都需要将顶点着色器中的命名属性连接到与glVertexAttribPointer (...)相同的索引。

pre-GLSL 1.30(GL 2.0/2.1):

#version 110
attribute vec4 vtx_pos_NDC;
attribute vec2 vtx_tex;
attribute vec3 vtx_norm;
varying   vec2 texcoords;
varying   vec3 normal;
void main (void)
{
  gl_Position = vtx_pos_NDC;
  texcoords   = vtx_tex;
  normal      = vtx_norm;
}

GLSL 1.30(GL 3.0):

#version 130
in  vec4 vtx_pos_NDC;
in  vec2 vtx_tex;
in  vec3 vtx_norm;
out vec2 texcoords;
out vec3 normal;
void main (void)
{
  gl_Position = vtx_pos_NDC;
  texcoords   = vtx_tex;
  normal      = vtx_norm;
}

对于这两个着色器,您都可以为每个输入(链接之前)设置属性位置:

glBindAttribLocation (<GLSL_PROGRAM>, 0, "vtx_pos_NDC");
glBindAttribLocation (<GLSL_PROGRAM>, 1, "vtx_tex");
glBindAttribLocation (<GLSL_PROGRAM>, 2, "vtx_norm");

如果您有幸使用支持的实现 GL_ARB_explicit_attrib_location(或GLSL 3.30),您也可以做到这一点:

GLSL 3.30(GL 3.3)

#version 330
layout (location = 0) in vec4 vtx_pos_NDC;
layout (location = 1) in vec2 vtx_tex;
layout (location = 2) in vec3 vtx_norm;
out vec2 texcoords;
out vec3 normal;
void main (void)
{
  gl_Position = vtx_pos_NDC;
  texcoords   = vtx_tex;
  normal      = vtx_norm;
}

以下是如何在GL 3中设置带有包装顶点数据的顶点缓冲区的示例:位置,颜色,正常和一组纹理坐标

typedef struct ccqv {
    GLfloat Pos[3];
    unsigned int Col;
    GLfloat Norm[3];
    GLfloat Tex2[4];
} Vertex;
...
glGenVertexArrays( 1, _vertexArray );
glBindVertexArray(_vertexArray);
glGenBuffers( 1, _vertexBuffer );
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, _arraySize*sizeof(Vertex), NULL, GL_DYNAMIC_DRAW  );
glEnableVertexAttribArray(0); // vertex
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex,Pos));
glEnableVertexAttribArray(3); // primary color
glVertexAttribPointer( 3, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex,Col));
glEnableVertexAttribArray(2); // normal
glVertexAttribPointer( 2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex,Tex1));
glEnableVertexAttribArray(8); // texcoord0
glVertexAttribPointer( 8, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex,Tex2));
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);

属性函数的第一个参数是属性的索引。为简单起见,我正在使用为NVIDIA CG定义的别名:http://http.developer.nvidia.com/cg/gp4gp.html

如果您使用的是GLSL着色器,则需要使用glBindAttribLocation()来定义这些索引,如Andon M. Coleman的答案所述。