OpenGL 将打包的纹理坐标传递给着色器

OpenGL pass packed texture coordinates to the shader

我需要在我的游戏中做一些大量的优化,我在想既然我们可以将 vec4 颜色传递给打包成一个浮点数的着色器,有没有办法也传递 vec2 纹理坐标?例如,在下面的代码中,我可以将 2 个纹理坐标(它始终为 1 和 0)作为一个元素传递,就像它在颜色元素中发生的方式一样。

public void point(float x,float y,float z,float size,float color){
    float hsize=size/2;
    if(index>vertices.length-7)return;
    vertices[index++]=x-hsize;
    vertices[index++]=y-hsize;
    vertices[index++]=color;
    vertices[index++]=0;
    vertices[index++]=0;

    vertices[index++]=x+hsize;
    vertices[index++]=y-hsize;
    vertices[index++]=color;
    vertices[index++]=1;
    vertices[index++]=0;

    vertices[index++]=x+hsize;
    vertices[index++]=y+hsize;
    vertices[index++]=color;
    vertices[index++]=1;
    vertices[index++]=1;

    vertices[index++]=x-hsize;
    vertices[index++]=y+hsize;
    vertices[index++]=color;
    vertices[index++]=0;
    vertices[index++]=1;

    num++;
}
{
    mesh=new Mesh(false,COUNT*20, indices.length,
            new VertexAttribute(Usage.Position, 2,"a_position"),
            new VertexAttribute(Usage.ColorPacked, 4,"a_color"),
            new VertexAttribute(Usage.TextureCoordinates, 2,"a_texCoord0")
    );
}

片段着色器

varying vec4 v_color;
varying vec2 v_texCoords;
uniform sampler2D u_texture;

void main() {
    vec4 color=v_color * texture2D(u_texture, v_texCoords);
    gl_FragColor = color;
}

垂直着色器

attribute vec4 a_position;
attribute vec4 a_color;
attribute vec2 a_texCoord0;

uniform mat4 u_projTrans;

varying vec4 v_color;
varying vec2 v_texCoords;

void main() {
    v_color = a_color;
    v_texCoords = a_texCoord0;
    gl_Position = u_projTrans * a_position;
}

我知道这不会对性能产生太大影响,但我只是愿意在这里和那里多花一些时间来进行一些小的优化,以使我的游戏 运行 更快。

我还没有尝试过,但我认为它会起作用。只需使用 Usage.ColorPacked 作为您的纹理坐标。我不认为你可以发送小于 4 字节的任何东西,所以你也可以使用已经定义的打包颜色。您只会为每个顶点保存一个字节。你可以把你的坐标放在前两个元素里,忽略后两个元素。

mesh = new Mesh(false,COUNT*20, indices.length,
        new VertexAttribute(Usage.Position, 2,"a_position"),
        new VertexAttribute(Usage.ColorPacked, 4,"a_color"),
        new VertexAttribute(Usage.ColorPacked, 4,"a_texCoord0")
);

我不认为 VertexAttribute 的 usage 参数实际上被 Libgdx 中的任何东西使用。如果您查看源代码,它只会检查 usage 是否为 ColorPacked,并据此决定每个组件是使用单个字节还是使用 4 个字节。

在你的顶点着色器中:

attribute vec4 a_position;
attribute vec4 a_color;
attribute vec4 a_texCoord0; //note using vec4

uniform mat4 u_projTrans;

varying vec4 v_color;
varying vec2 v_texCoords;

void main() {
    v_color = a_color;
    v_texCoords = a_texCoord0.xy; //using the first two elements
    gl_Position = u_projTrans * a_position;
}

要正确转换纹理坐标:

final Color texCoordColor = new Color(0, 0, 0, 0);

//....

texCoordColor.r = texCoord.x;
texCoordColor.g = texCoord.y;
float texCoord = texCoordColor.toFloatBits();