📅  最后修改于: 2023-12-03 15:22:27.345000             🧑  作者: Mango
本文介绍使用Java代码实现颜色交换方法对图形进行顶点着色的方法。该方法可以用于绘制三角形、多边形等简单图形,并可以自定义颜色和顶点坐标。
程序的实现步骤如下所示:
float[] colors = {
// R, G, B, A
1.0f, 0.0f, 0.0f, 1.0f, // 红色
0.0f, 1.0f, 0.0f, 1.0f, // 绿色
0.0f, 0.0f, 1.0f, 1.0f, // 蓝色
};
int[] indices = { 0, 1, 2 }; // 三角形
float[] vertices = {
// X, Y, Z
-0.5f, -0.5f, 0f, // 左下角
0.5f, -0.5f, 0f, // 右下角
0.0f, 0.5f, 0f, // 顶部
};
String vertexShaderSource =
"attribute vec3 a_Position;\n" +
"attribute vec4 a_Color;\n" +
"varying vec4 v_Color;\n" +
"void main() {\n" +
" gl_Position = vec4(a_Position, 1.0);\n" +
" v_Color = a_Color;\n" +
"}";
着色器中将传入的顶点坐标和颜色值赋值给 gl_Position
和 v_Color
变量。varying
关键字用来将颜色值从顶点着色器传递到片元着色器。
String fragmentShaderSource =
"precision mediump float;\n" +
"varying vec4 v_Color;\n" +
"void main() {\n" +
" gl_FragColor = v_Color;\n" +
"}";
片元着色器的作用是计算每个像素的颜色值。在本例中,我们直接将 v_Color
变量的值赋给 gl_FragColor
,达到绘制多个颜色的目的。
int program = GLES20.glCreateProgram(); // 创建绘制程序
int vertexShader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER); // 创建顶点着色器
int fragmentShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER); // 创建片元着色器
GLES20.glShaderSource(vertexShader, vertexShaderSource);
GLES20.glCompileShader(vertexShader);
GLES20.glShaderSource(fragmentShader, fragmentShaderSource);
GLES20.glCompileShader(fragmentShader);
GLES20.glAttachShader(program, vertexShader);
GLES20.glAttachShader(program, fragmentShader);
GLES20.glLinkProgram(program); // 链接绘制程序
在创建绘制程序、顶点着色器和片元着色器后,需要将着色器源码分别加载到对应的着色器中,并编译。接着将着色器附加到绘制程序中,并链接绘制程序。
GLES20.glUseProgram(program); // 激活程序
int positionHandle = GLES20.glGetAttribLocation(program, "a_Position");
GLES20.glEnableVertexAttribArray(positionHandle);
GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 0, verticesBuffer);
int colorHandle = GLES20.glGetAttribLocation(program, "a_Color");
GLES20.glEnableVertexAttribArray(colorHandle);
GLES20.glVertexAttribPointer(colorHandle, 4, GLES20.GL_FLOAT, false, 0, colorsBuffer);
激活绘制程序后,需要指定顶点着色器中定义的顶点坐标和颜色属性。glGetAttribLocation
函数返回顶点属性的位置,并启用顶点纹理坐标属性。glVertexAttribPointer
函数则将属性绑定到顶点数组中。
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length, GLES20.GL_UNSIGNED_INT, indicesBuffer);
glDrawElements
函数用于实际绘制图形。本例中使用 GL_TRIANGLES
三角形绘制模式,并将顶点坐标和索引数组传递给函数。
GLES20.glDisableVertexAttribArray(positionHandle);
GLES20.glDisableVertexAttribArray(colorHandle);
GLES20.glDeleteShader(vertexShader);
GLES20.glDeleteShader(fragmentShader);
完整的示例代码如下所示:
import android.opengl.GLES20;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
public class TriangleRenderer implements GLSurfaceView.Renderer {
private static final String VERTEX_SHADER_SOURCE =
"attribute vec3 a_Position;\n" +
"attribute vec4 a_Color;\n" +
"varying vec4 v_Color;\n" +
"void main() {\n" +
" gl_Position = vec4(a_Position, 1.0);\n" +
" v_Color = a_Color;\n" +
"}";
private static final String FRAGMENT_SHADER_SOURCE =
"precision mediump float;\n" +
"varying vec4 v_Color;\n" +
"void main() {\n" +
" gl_FragColor = v_Color;\n" +
"}";
private static final float[] COLORS = {
// R, G, B, A
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f
};
private static final int[] INDICES = { 0, 1, 2 };
private static final float[] VERTICES = {
-0.5f, -0.5f, 0f,
0.5f, -0.5f, 0f,
0.0f, 0.5f, 0f
};
private final FloatBuffer verticesBuffer;
private final IntBuffer indicesBuffer;
private final FloatBuffer colorsBuffer;
public TriangleRenderer() {
verticesBuffer = ByteBuffer
.allocateDirect(VERTICES.length * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
verticesBuffer.put(VERTICES).position(0);
indicesBuffer = ByteBuffer
.allocateDirect(INDICES.length * 4)
.order(ByteOrder.nativeOrder())
.asIntBuffer();
indicesBuffer.put(INDICES).position(0);
colorsBuffer = ByteBuffer
.allocateDirect(COLORS.length * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
colorsBuffer.put(COLORS).position(0);
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
int program = GLES20.glCreateProgram();
int vertexShader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
int fragmentShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
GLES20.glShaderSource(vertexShader, VERTEX_SHADER_SOURCE);
GLES20.glCompileShader(vertexShader);
GLES20.glShaderSource(fragmentShader, FRAGMENT_SHADER_SOURCE);
GLES20.glCompileShader(fragmentShader);
GLES20.glAttachShader(program, vertexShader);
GLES20.glAttachShader(program, fragmentShader);
GLES20.glLinkProgram(program);
GLES20.glUseProgram(program);
int positionHandle = GLES20.glGetAttribLocation(program, "a_Position");
GLES20.glEnableVertexAttribArray(positionHandle);
GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT,
false, 0, verticesBuffer);
int colorHandle = GLES20.glGetAttribLocation(program, "a_Color");
GLES20.glEnableVertexAttribArray(colorHandle);
GLES20.glVertexAttribPointer(colorHandle, 4, GLES20.GL_FLOAT,
false, 0, colorsBuffer);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, INDICES.length,
GLES20.GL_UNSIGNED_INT, indicesBuffer);
GLES20.glDisableVertexAttribArray(positionHandle);
GLES20.glDisableVertexAttribArray(colorHandle);
GLES20.glDeleteShader(vertexShader);
GLES20.glDeleteShader(fragmentShader);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);
}
@Override
public void onDrawFrame(GL10 gl) {}
}
本文介绍了使用颜色交换方法对图形进行顶点着色的Java程序。该程序可以用于绘制简单的三角形、多边形等图形,并可以自定义顶点坐标和颜色。程序代码非常简单易懂,适合OpenGL初学者入门。