Android OpenGLES 绘制三角形 ,四边形
时间:2022-06-10
本文章向大家介绍Android OpenGLES 绘制三角形 ,四边形,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
- 验证是否支持OpenGLES2.0
//检查设备是否支持OpenGL ES 2.0
final ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
final boolean supportES2 = configurationInfo.reqGlEsVersion >= 0x00020000;
确保可用,在manifest里面添加验证
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
- 定义
vertex_shader.glsl
和fragment_shader.glsl
到res/raw
里面
vertex_shader.glsl
attribute vec4 vPosition;
void main(){
gl_Position = vPosition;
}
fragment_shader.glsl
precision mediump float;
uniform vec4 vColor;
void main(){
gl_FragColor = vColor;
}
OpenGL ES Shader的三种变量类型uniform,attribute和varying
- 定义形状
import android.content.Context;
import android.opengl.GLES20;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
public class Triangle {
//坐标本地内存地址
private FloatBuffer vertexBuffer;
//每一次取点的时候取几个点
static final int COORDS_PER_VERTEX = 3;
//绘制坐标
static float triangleCoords[] = { // in counterclockwise order:
0.0f, 0.622008459f, 0.0f, // top
-0.5f, -0.311004243f, 0.0f, // bottom left
0.5f, -0.311004243f, 0.0f // bottom right
};
// Set color with red, green, blue and alpha (opacity) values
float color[] = {0.63671875f, 0.76953125f, 0.22265625f, 1.0f};
private final int mProgram;
private int mPositionHandle;
private int mColorHandle;
private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
//每一次取的总的点 大小
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
public Triangle(Context context) {
//为坐标分配本地内存地址
vertexBuffer = ByteBuffer
.allocateDirect(triangleCoords.length * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer()
.put(triangleCoords);
vertexBuffer.position(0);
//根据shader代码和fragment代码 获取到一个渲染程序
mProgram = ShaderUtil.createProgram(ShaderUtil.readRawTxt(context, R.raw.vertex_shader),
ShaderUtil.readRawTxt(context, R.raw.fragment_shader));
if (mProgram > 0) {
//获取vertex shader的属性vPosition 的地址
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
//获取fragment shader的属性vColor 的地址
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
}
}
public void draw() {
//使用渲染程序
GLES20.glUseProgram(mProgram);
// 使顶点属性数组有效
GLES20.glEnableVertexAttribArray(mPositionHandle);
// 为顶点属性赋值
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
// 设置颜色
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
// 绘制图形
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
// 禁用顶点数组
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}
ShaderUtil.java
import android.content.Context;
import android.opengl.GLES20;
import android.util.Log;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
public class ShaderUtil {
private static final String TAG = "ShaderUtil";
public static String readRawTxt(Context context, int rawId) {
InputStream inputStream = context.getResources().openRawResource(rawId);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuffer sb = new StringBuffer();
String line;
try {
while ((line = reader.readLine()) != null) {
sb.append(line).append("n");
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
return sb.toString();
}
public static int loadShader(int shaderType, String source) {
// create a vertex shader type (GLES20.GL_VERTEX_SHADER)
// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
int shader = GLES20.glCreateShader(shaderType);
if (shader != 0) {
//添加代码到shader
GLES20.glShaderSource(shader, source);
//编译shader
GLES20.glCompileShader(shader);
int[] compile = new int[1];
//检测是否编译成功
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compile, 0);
if (compile[0] != GLES20.GL_TRUE) {
Log.d(TAG, "shader compile error");
GLES20.glDeleteShader(shader);
shader = 0;
}
}
return shader;
}
public static int createProgram(String vertexSource, String fragmentSource) {
//获取vertex shader
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
if (vertexShader == 0) {
return 0;
}
//获取fragment shader
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
if (fragmentShader == 0) {
return 0;
}
//创建一个空的渲染程序
int program = GLES20.glCreateProgram();
if (program != 0) {
//添加vertexShader到渲染程序
GLES20.glAttachShader(program, vertexShader);
//添加fragmentShader到渲染程序
GLES20.glAttachShader(program, fragmentShader);
//关联为可执行渲染程序
GLES20.glLinkProgram(program);
int[] linsStatus = new int[1];
//检测是否关联成功
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linsStatus, 0);
if (linsStatus[0] != GLES20.GL_TRUE) {
Log.d(TAG, "link program error");
GLES20.glDeleteProgram(program);
program = 0;
}
}
return program;
}
}
- 定义shader import android.content.Context; import android.opengl.GLES20; import android.opengl.GLSurfaceView; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; public class MyRender implements GLSurfaceView.Renderer { private Context context; private Triangle triangle; public MyRender(Context context) { this.context = context; } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { triangle = new Triangle(context); } @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.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); triangle.draw(); } }
- 设置
shader
到GLSurfaceView
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;
public class MyGLSurfaceView extends GLSurfaceView{
public MyGLSurfaceView(Context context) {
this(context, null);
}
public MyGLSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
setEGLContextClientVersion(2);
setRenderer(new MyRender(context));
}
}
上述三角形已经绘制成功。
- 绘制四边形
绘制四边形的方式是由两个三角形形成一个四边形,所以顶点位置一定要注意。
调用
GLES20.glDrawArrays
的时候设置flog
可以设置为GLES20.GL_TRIANGLE_STRIP
和GLES20.GL_TRIANGLES
,前者复用坐标,后者分别取几个坐标。
- Java面向对象抽象类案例分析
- 【Java学习笔记之二十三】instanceof运算符的用法小结
- 基础才是重中之重~多线程的代价~我的内存都被吃了!
- 【Java学习笔记之二十八】深入了解Java8新特性
- 【Java学习笔记之二十四】对Java多态性的一点理解
- 【Java学习笔记之二十六】深入理解Java匿名内部类
- 【Java学习笔记之二十五】初步认知Java内部类
- AIM Tech Round 4 (Div. 2)(A,暴力,B,组合数,C,STL+排序)
- 【Java学习笔记之三十】详解Java单例(Singleton)模式
- 基于Windows下处理Java错误:编码GBK的不可映射字符的解决方案
- 浅析ASCII、Unicode和UTF-8三种常见字符编码
- 【Java学习笔记之三十一】详解Java8 lambda表达式
- 2017 Multi-University Training Contest - Team 9 1003&&HDU 6163 CSGO【计算几何】
- 【Code】关关的刷题日记21——Leetcode 485. Max Consecutive Ones
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Spring源码-循环依赖(附25张调试截图)
- 二叉查找树
- 尺取法
- 关于一些技术点的随笔记录(二)
- 快速排序与三路快速排序
- 垃圾回收器 Krains 2020-08-07
- OWIN 请求处理与中间件
- 关于Spring AOP,除了动态代理、CGLIB,你还知道什么?
- elasticSearch学习(三)
- 挑苹果中的行为参数化思想
- 详解MapReduce(Spark和MapReduce对比铺垫篇)
- 使用 OWIN 作为 ASP.NET Web API 的宿主
- 二进制源码和补码的基础解释
- Spark推荐系统实践
- Xamarin Studio 比 Visual Studio 2013 好用的三个功能