Android OpenGL平滑着色

Android OpenGL平滑着色

首先申明下,本文为笔者学习《OpenGL ES应用开发实践指南》的笔记,并加入笔者自己的理解和归纳总结。

1、平滑着色

平滑着色可以平滑地混合一条直线或一个三角形的表面上每个顶点的颜色。
(1) 直线混合

value = (vertex_0_value * (1 - distance_ratio))
		+ (vertex_1_value * distance_ratio)
(2) 三角混合
对于三角形内任何给定的点,从那个点向每个顶点画条直线,生成三个内部三角形。这三个内部三角形的比例决定了那个点上每种颜色的权重。


value = (vertex_0_value * vertex_0_weight)
		+ (vertex_1_value * vertex_1_weight)
		+ (vertex_2_value * (1 - vertex_0_weight - vertex_1_weight))

2、着色器文件

(1) 顶点着色器,varying_vertex_shader.glsl文件
varying是一个特殊的变量类型,它把给它的那些值进行混合,并把这些混合后的值发给片段着色器

attribute vec4 a_Position;
attribute vec4 a_Color;

varying vec4 v_Color;

void main()
{
    v_Color = a_Color;

    gl_Position = a_Position;
    gl_PointSize = 10.0;
}
(2) 片段着色器,varying_fragment_shader.glsl文件
使用varying定义v_Color替代了原有的变量

precision mediump float;

varying vec4 v_Color;

void main()
{                    	
    gl_FragColor = v_Color;
}

3、三角扇形

一个三角扇形以一个中心顶点作为起始,使用相邻的两个顶点创建一个三角形,接下来的每个顶点都会创建一个三角形,围绕起始的中心点按扇形展开。
定义中心点和四个角的坐标,最后(-0.5f, -0.5f)是为了让扇形闭合。
float[] tableVerticesWithTriangles = {
		// 中心点
		0f, 0f,

		// 四个角
		-0.5f, -0.5f,
		 0.5f, -0.5f,
		 0.5f,  0.5f,
		 0.5f, -0.5f,
		-0.5f, -0.5f
};

绘制时,在onDrawFrame方法中调用

GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 6);

4、绘制着色器

(1) 顶点颜色数据
为每个顶点增加三个额外的数据,代表顶点的颜色。

float[] tableVerticesWithTriangles = {
		// 中心点
		0f, 0f, 1f, 1f, 1f,

		// 四个角
		-0.5f, -0.5f, 0.7f, 0.7f, 0.7f,
		 0.5f, -0.5f, 0.7f, 0.7f, 0.7f,
		 0.5f,  0.5f, 0.7f, 0.7f, 0.7f,
		-0.5f,  0.5f, 0.7f, 0.7f, 0.7f,
		-0.5f, -0.5f, 0.7f, 0.7f, 0.7f,

		// 直线
		-0.5f, 0f, 1f, 0f, 0f,
		 0.5f, 0f, 1f, 0f, 0f,

		// 点
		0f, -0.25f, 0, 0, 1,
		0f,  0.25f, 1, 0, 0
};
(2) 关联顶点颜色数据
position移动到位置2,COLOR_COMPONENT_COUNT的值为3,设置STRIDE的值来代表每次的跨距。

vertexData.position(2);
GLES20.glVertexAttribPointer(aColorLocation, COLOR_COMPONENT_COUNT,
		GLES20.GL_FLOAT, false, STRIDE, vertexData);
(3) OpenGLVaryingShaderRender类
tableVerticesWithTriangles中定义了顶点和颜色,glVertexAttribPointer方法需要使用stride来跳过多余数据。

private class OpenGLVaryingShaderRender implements GLSurfaceView.Renderer {
	private final static String A_POSITION = "a_Position";
	private final static String A_COLOR = "a_Color";

	private static final int POSITION_COMPONENT_COUNT = 2;
	private static final int COLOR_COMPONENT_COUNT = 3;
	private static final int BYTES_PER_FLOAT = 4;
	private static final int STRIDE = (POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT)
                * BYTES_PER_FLOAT;

	private FloatBuffer vertexData;
	private int mProgramId;
	private int aPositionLocation, aColorLocation;

	OpenGLVaryingShaderRender() {
		float[] tableVerticesWithTriangles = {
				// 中心点
				0f, 0f, 1f, 1f, 1f,

				// 四个角
				-0.5f, -0.5f, 0.7f, 0.7f, 0.7f,
				 0.5f, -0.5f, 0.7f, 0.7f, 0.7f,
				 0.5f,  0.5f, 0.7f, 0.7f, 0.7f,
				-0.5f,  0.5f, 0.7f, 0.7f, 0.7f,
				-0.5f, -0.5f, 0.7f, 0.7f, 0.7f,

				// 直线
				-0.5f, 0f, 1f, 0f, 0f,
				 0.5f, 0f, 1f, 0f, 0f,

				// 点
				0f, -0.25f, 0, 0, 1,
				0f,  0.25f, 1, 0, 0
		};

		vertexData = ByteBuffer
				.allocateDirect(tableVerticesWithTriangles.length * BYTES_PER_FLOAT)
				.order(ByteOrder.nativeOrder())
				.asFloatBuffer();
		vertexData.put(tableVerticesWithTriangles);
	}

	@Override
	public void onSurfaceCreated(GL10 gl, EGLConfig config) {
		GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

		mProgramId = useProgram(R.raw.varying_vertex_shader, R.raw.varying_fragment_shader);

		// 获取Attribute位置
		aPositionLocation = GLES20.glGetAttribLocation(mProgramId, A_POSITION);
		aColorLocation = GLES20.glGetAttribLocation(mProgramId, A_COLOR);

		vertexData.position(0);
		GLES20.glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT,
				GLES20.GL_FLOAT, false, STRIDE, vertexData);
		GLES20.glEnableVertexAttribArray(aPositionLocation);

		// position是2,颜色从第二位读取
		vertexData.position(2);
		GLES20.glVertexAttribPointer(aColorLocation, COLOR_COMPONENT_COUNT,
				GLES20.GL_FLOAT, false, STRIDE, vertexData);
		GLES20.glEnableVertexAttribArray(aColorLocation);
	}

	@Override
	public void onSurfaceChanged(GL10 gl, int width, int height) {
		GLES20.glViewport(0, 0, width, height);
	}

	@Override
	public void onDrawFrame(GL10 gl) {
		GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

		// 绘制三角形
		GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 6);

		// 绘制直线
		GLES20.glDrawArrays(GLES20.GL_LINES, 6, 2);

		// 绘制点
		GLES20.glDrawArrays(GLES20.GL_POINTS, 8, 1);

		// 绘制点
		GLES20.glDrawArrays(GLES20.GL_POINTS, 9, 1);
	}

}
显示如下
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值