【问题标题】:How do I use a shader to colour lines drawn with GL_LINES and OpenGL ES 2.0如何使用着色器为使用 GL_LINES 和 OpenGL ES 2.0 绘制的线条着色
【发布时间】:2025-12-07 04:40:02
【问题描述】:

我有一个使用 OpenGL ES 2.0 的 Android 应用程序。我需要从一个数组中绘制 10 条线,每条线都由起点和终点描述。所以有 10 行 = 20 个点 = 60 个浮点值。没有一个点是连接的,因此数组中的每一对点都与其他点无关,因此我使用 GL_LINES 进行绘制。

我通过将值放入浮点缓冲区并调用一些辅助代码来绘制它们,如下所示:

public void drawLines(FloatBuffer vertexBuffer, float lineWidth,
        int numPoints, float colour[]) {
    GLES20.glLineWidth(lineWidth);
    drawShape(vertexBuffer, GLES20.GL_LINES, numPoints, colour);
}

protected void drawShape(FloatBuffer vertexBuffer, int drawType,
        int numPoints, float colour[]) {
    // ... set shader ...
    GLES20.glDrawArrays(drawType, 0, numPoints);
}

drawLines 采用浮点缓冲区(60 个浮点数)、一个线宽、点数(20)和一个 4 个浮点数颜色值数组。我没有显示着色器设置代码,但它基本上将颜色变量暴露给统一的 uColour 值。

拾取 uColour 的片段着色器只是将其直接插入输出。

/* Fragment */
precision mediump float;

uniform vec4 uColour;
uniform float uTime;

void main() {
    gl_FragColor = uColour;
}

顶点着色器:

uniform mat4 uMVPMatrix;

attribute vec4 vPosition;

void main() {
    gl_Position = uMVPMatrix * vPosition;
}

但现在我想做一些不同的事情。我希望缓冲区中的每一行都有不同的颜色。颜色是数组中线条位置的函数。我想将开始的线涂成白色,最后的深灰色和两者之间的渐变线,例如#ffffff、#eeeeee、#dddddd 等。

我显然可以只画每条线,每次都将一个新值插入到 uColour 中,但这效率低下。我不想调用 GL 10 次,因为我可以调用一次并每次都修改着色器中的值。

也许我可以在我的顶点着色器中声明一个名为 uVertexCount 的统一值?在绘制之前,我将 uVertexCount 设置为 0,并且每次调用顶点着色器时,我都会增加该值。片段着色器可以通过查看 uVertexCount 来确定行索引。然后,它可以在某个开始值和结束值或其他方式之间插入一个颜色值。但这取决于是每条线或点都被认为是一个基元,还是整个线阵列都是一个基元。

这可行吗?我不知道每个片段着色器调用顶点着色器多少次。调用是否以这样的方式交错以使其可行,即顶点 0、顶点 1、x * 片段、顶点 2、顶点 3、x * 片段等。

有没有人知道一些合理的示例代码可以展示这个概念或指出我做类似事情的其他方式?

【问题讨论】:

  • 为什么不使用颜色作为属性?在 VertexBuffer 中添加颜色信息。
  • 我可以将它添加为属性,但我仍然需要知道片段着色器中的点/线索引,以便知道我应该使用属性中的哪种颜色。即,如果我将 10 种颜色的数组作为属性传递,我的片段着色器如何知道它应该使用这 10 种颜色中的哪一种?
  • 不是自动完成的......如果你有一个统一的数组,你需要索引,但当你有一个属性时不需要。一个属性只连接到一个顶点。所以你的每个顶点都有一个位置和颜色。
  • 能否请您展示您的顶点着色器? :)

标签: java android opengl-es-2.0


【解决方案1】:

将颜色信息添加到您的 Vertexbuffer (Floatbuffer) 并在着色器中使用该属性。

示例顶点缓冲区:

uniform mat4 uMVPMatrix;

attribute vec4 vPosition;
attribute vec3 vColor;

varying vec3 color;

void main() {
    gl_Position = uMVPMatrix * vPosition;
    color = vColor;
}

片段着色器示例:

precision mediump float;

varying vec3 color;

void main() {
    gl_FragColor = color;
}

【讨论】:

  • 您是否建议我在这里使用 glDrawElements 而不是 glDrawArray 以某种方式将 vColor 推入矢量着色器?颜色是否最终被插值或由此产生的任何东西,或者我是否必须为起点/终点提供相同的颜色以确保变化的值不会改变?今晚我会试试看,看看我的进展如何。
  • 我想我现在明白了。我必须将 glVertexAttribPointer / glEnableVertexAttribArray 绑定到颜色的浮点数组。我可能必须将线条的每一端的颜色加倍,但这应该很简单。当我有这个地方时,我会发布更新。