OpenGLES2.0笔记
来源:互联网 发布:php软件开发工具 编辑:程序博客网 时间:2024/05/21 06:16
capacity:容量
allocate:分配
Coord:坐标
vertex:顶点
Square:平面
Program:程序
Compile:编译
font:字体
pname:工程名称
Validate:验证
Uniform:均匀
ByteBuffer和FloatBuffer是java.nio包下的类
ByteBuffer bb=ByteBuffer.allocate(capacity);//参数是一个容量
ByteBuffer bb2=ByteBuffer.allocateDirect(capacity);//这个方法在参与I/O操作性能会更好
called unimplemented OpenGL ES API 报错。。
坐标系:安卓中的坐标系在横屏的时候会变形,变粗,所以在横屏的时候需要处理摄像机。
屏幕的左上角是(-1.0,1.0)横向向右为X轴正向,纵向向下为Y轴负向,其范围都是从 -1到 +1。
我们在该类中定义的float类型的数据并不能直接被opengl使用,float[]是属于虚拟机环境的,而Opengl作为本地系统库
直接运行在硬件上,所以我们需要将float[] 转化为FloatBuffer以使数据可以被opengl使用
//如下浮点数组代表的是一个三角形的顶点坐标
float[] vertex={0.1f,0.1f,
0.1f,0.1f,
0.1f,0.1f};
//浮点缓冲
FloatBuffer fb=FloatBuffer.allocate(int capacity);
//把顶点坐标添加到FloatBuffer中,并把位置0作为开始位置。
fb.put(vertex);
fb.position(0);
着色器语言(shading language),由C/C++编写
如下是顶点shader
attribute vec4 a_Position;
void main()
{
gl_Position = a_Position;
}
gl_Position即opengl定义的顶点的坐标,我们目的就是通过这个来告诉opengl我们的顶点数据。
vec4是着色器语言中的向量类型的一种,包含了四个浮点数的向量
如下是面shader
precision mediump float;
uniform vec4 u_Color;
void main()
{
gl_FragColor = u_Color;
}
传入一个颜色信息。这里注意一下 上面顶点着色器的 限定符 attribute 和 uniform 。attribute 一般用于每个顶点
各不相同的量,如顶点位置等,后者一般用于同一组顶点组成的相同的量,如光源位置,一组颜色等。
编写shader的帮助类ShaderHelper和TextResourceReader,可以直接使用。
在使用的时候通过TextResourceReader的readTextFileFromResource(Context context,int resourceId)方法返回shader字符串,然后再用ShaderHelper的buildProgram(String vertexShaderSource,String fragmentShaderSource)返回的内容直接使用。
ShaderHelper主要功能是
1,读取shader文本内容
2,编译shader
3,将顶点shader和面shader链接成program
4,验证program
TextResourceReader主要功能是
1,把shader源代码通过流的转换返回我们需要的shader字符串。
public class ShaderHelper { private static final String TAG = "ShaderHelper"; /** * 加载并编译顶点shader,返回得到的opengl id * @param shaderCode * @return */ public static int compileVertexShader(String shaderCode) { return compileShader(GL_VERTEX_SHADER, shaderCode); } /** * 加载并编译片段shader,返回opengl id * @param shaderCode * @return */ public static int compileFragmentShader(String shaderCode) { return compileShader(GL_FRAGMENT_SHADER, shaderCode); } /** * 加载并编译着色器,返回opengl id * @param type * @param shaderCode * @return */ private static int compileShader(int type, String shaderCode) { // 建立新的着色器对象 final int shaderObjectId = glCreateShader(type); if (shaderObjectId == 0) { if (LoggerConfig.ON) { Log.w(TAG, "不能创建新的着色器."); } return 0; } // 传递着色器资源代码. glShaderSource(shaderObjectId, shaderCode); //编译着色器 glCompileShader(shaderObjectId); // 获取编译的状态 final int[] compileStatus = new int[1]; glGetShaderiv(shaderObjectId, GL_COMPILE_STATUS, compileStatus, 0); if (LoggerConfig.ON) { //打印log Log.v(TAG, "代码编译结果:" + "\n" + shaderCode + "\n:" + glGetShaderInfoLog(shaderObjectId)); } // 确认编译的状态 if (compileStatus[0] == 0) { // 如果编译失败,则删除该对象 glDeleteShader(shaderObjectId); if (LoggerConfig.ON) { Log.w(TAG, "编译失败!."); } return 0; } // 返回着色器的opengl id return shaderObjectId; } /** * 链接顶点着色器和片段着色器成一个program * 并返回这个pragram的opengl id * @param vertexShaderId * @param fragmentShaderId * @return */ public static int linkProgram(int vertexShaderId, int fragmentShaderId) { // 新建一个program对象 final int programObjectId = glCreateProgram(); if (programObjectId == 0) { if (LoggerConfig.ON) { Log.w(TAG, "不能新建一个 program"); } return 0; } //把点shader添加到program中 glAttachShader(programObjectId, vertexShaderId); //把shader添加到program中 glAttachShader(programObjectId, fragmentShaderId); //将两个着色器连接成一个program glLinkProgram(programObjectId); // 获取连接状态 final int[] linkStatus = new int[1]; glGetProgramiv(programObjectId, GL_LINK_STATUS,linkStatus, 0); if (LoggerConfig.ON) { // Print the program info log to the Android log output. Log.v( TAG, "Results of linking program:\n" + glGetProgramInfoLog(programObjectId)); } // 验证连接状态 if (linkStatus[0] == 0) { // 如果失败就删除 glDeleteProgram(programObjectId); if (LoggerConfig.ON) { Log.w(TAG, "连接 program 失败!."); } return 0; } // Return the program object ID. return programObjectId; } /** * Validates an OpenGL program. Should only be called when developing the * application. */ public static boolean validateProgram(int programObjectId) { glValidateProgram(programObjectId); final int[] validateStatus = new int[1]; glGetProgramiv(programObjectId, GL_VALIDATE_STATUS, validateStatus, 0); Log.v(TAG, "Results of validating program: " + validateStatus[0] + "\nLog:" + glGetProgramInfoLog(programObjectId)); return validateStatus[0] != 0; } /** * /** * 编译,连接 ,返回 program 的 ID * @param vertexShaderSource * @param fragmentShaderSource * @return */ public static int buildProgram(String vertexShaderSource, String fragmentShaderSource) { int program; // Compile the shaders. int vertexShader = compileVertexShader(vertexShaderSource); int fragmentShader = compileFragmentShader(fragmentShaderSource); // Link them into a shader program. program = linkProgram(vertexShader, fragmentShader); if (LoggerConfig.ON) { validateProgram(program); } return program; }}
如下工具类TextResourceReader是把shader源代码通过流的转换返回我们需要的shader字符串。
public class TextResourceReader { public static String readTextFileFromResource(Context context, int resourceId) { StringBuilder body = new StringBuilder(); try { InputStream inputStream = context.getResources().openRawResource(resourceId); InputStreamReader inputStreamReader = new InputStreamReader(inputStream); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String nextLine; while ((nextLine = bufferedReader.readLine()) != null) { body.append(nextLine); body.append('\n'); } } catch (IOException e) { throw new RuntimeException( "Could not open resource: " + resourceId, e); } catch (Resources.NotFoundException nfe) { throw new RuntimeException("Resource not found: " + resourceId, nfe); } return body.toString(); }}
方便打印的工具类
public class LoggerConfig { public static final boolean ON = true;}
图形类
public class Square2 { private Context context; /*------------------第一步: 修改顶点数据-------------------------*/ //矩形(其实是菱形)顶点坐标 ,按逆时针 static float squareCoords[] = { -0.25f, 0.5f , // top left 0.75f, 0.5f , // top right -0.75f, -0.5f , // bottom left 0.25f, -0.5f }; // bottom right //float类型的字节数,用于给FloatBuffer指定容量时使用 private static final int BYTES_PER_FLOAT = 4; // 数组中每个顶点的坐标数 static final int COORDS_PER_VERTEX = 2; /*------------------第二步: 修改顶点个数-------------------------*/ private static final int POSITION_COMPONENT_COUNT = 4; //要把定义的float坐标数组转化成FloatBuffer类型,因为它是直接运行在硬件上的,不是java虚拟机。 private FloatBuffer vertexBuffer; //A_POSITION是顶点shader的变量名,U_COLOR是片段shader的变量名 ,它们用于匹配shader文件中的变量。 private static final String A_POSITION = "a_Position"; private static final String U_COLOR = "u_Color"; //------------获得program的ID的含义类似的 private int uColorLocation; private int aPositionLocation; private int program;//保存program的id //矩形的构造方法 public Square2(Context context) { this.context = context; vertexBuffer = ByteBuffer .allocateDirect(squareCoords.length * BYTES_PER_FLOAT) .order(ByteOrder.nativeOrder()) .asFloatBuffer(); // 把坐标数组加入FloatBuffer中,并且从0下标开始读取 vertexBuffer.put(squareCoords); vertexBuffer.position(0); getProgram(); //----------第三步: 获取这两个ID ,通过匹配shader文件中的变量来获取 uColorLocation = GLES20.glGetUniformLocation(program, U_COLOR); aPositionLocation = GLES20.glGetAttribLocation(program, A_POSITION); //---------第四步: 传入数据 //GLES20.glVertexAttribPointer(int indx, int size, int type, boolean normalized, int stride, Buffer ptr) //int index:??? //int size:每个顶点的坐标数 //int type:类型,用GLES20.GL_FLOAT //boolean normalized:???是否统一化 //int stride:???跨度 //Buffer ptr:承载坐标数组转换成的FloatBuffer。 GLES20.glVertexAttribPointer(aPositionLocation, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, vertexBuffer); //使面变成顶点数组??? GLES20.glEnableVertexAttribArray(aPositionLocation); } //获取program, private void getProgram(){ //获取顶点shader文本 String vertexShaderSource = TextResourceReader .readTextFileFromResource(context, R.raw.simple_vertex_shader); //获取片段shader文本 String fragmentShaderSource = TextResourceReader .readTextFileFromResource(context, R.raw.simple_fragment_shader); //获取program的id program = ShaderHelper.buildProgram(vertexShaderSource, fragmentShaderSource); //使用该program GLES20.glUseProgram(program); } public void draw(){ GLES20.glUniform4f(uColorLocation, 0.0f, 0.0f, 1.0f, 1.0f); //绘制模式 //GLES20.glDrawArrays(int mode, int first, int count) //int mode:绘制模式, GLES20.GL_TRIANGLE_STRIP:将传入的顶点按照顺序依次连接进行绘制 //int first:从数组的哪个位置开始 //int count:绘制的个数 GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, POSITION_COMPONENT_COUNT); }}
Render类
public class MyRender implements Renderer { private Context context; public MyRender(Context context){ this.context = context; } //定义三角形对象 Triangle triangle; Square2 square; public void onSurfaceCreated(GL10 gl, EGLConfig config) { Log.w("MyRender","onSurfaceCreated"); // TODO Auto-generated method stub //First:设置清空屏幕用的颜色,前三个参数对应红绿蓝,最后一个对应alpha glClearColor(1.0f, 1.0f, 1.0f, 0.0f);// triangle = new Triangle(context); square = new Square2(context); } public void onSurfaceChanged(GL10 gl, int width, int height) { Log.w("MyRender","onSurfaceChanged"); // TODO Auto-generated method stub //Second:设置视口尺寸,即告诉opengl可以用来渲染的surface大小 glViewport(0,0,width,height); } public void onDrawFrame(GL10 gl) { Log.w("MyRender","onDrawFrame"); // TODO Auto-generated method stub //Third:清空屏幕,擦除屏幕上所有的颜色,并用之前glClearColor定义的颜色填充整个屏幕 glClear(GL_COLOR_BUFFER_BIT); square.draw(); } }
Activity
public class MainActivity extends Activity { private GLSurfaceView glSurfaceView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); glSurfaceView = new GLSurfaceView(this); glSurfaceView.setEGLContextClientVersion(2); // Pick an OpenGL ES 2.0 context. glSurfaceView.setRenderer(new MyRender(this)); setContentView(glSurfaceView); } }
手机的屏幕和普通的OpenGL的坐标系不一样,因为手机横竖屏转换的时候会拉伸,
它的坐标系是Y轴向上为正,向下为负,X轴向右为正,X轴向左为负。
坐标范围是
左上角(-1.0,1.0);
右上角(1.0,1.0);
左下角(-1.0,-1.0);
右下角(1.0,-1.0);
一个正方形按照Z字形画出两个三角形,重合的点可以复用前提是在draw的时候使用GLES20.GL_TRIANGLE_STRIP模式,在画图之前需要指定顶点数量,每个顶点所占有的坐标数(坐标是从数组中依次获取,必须把float数组转换成FloatBuffer类型,OpenGL是直接在硬件中进行的,不是虚拟机)。如果使用的是不复用的模式,那么一个矩形需要指定6对坐标,也就是画出两个三角形。
画圆
- OpenGLES2.0笔记
- Opengles2.0 for android入门笔记(一)
- openglES2.0 时代来临?
- opengles2.0中的纹理
- opengles2.0 shader备忘
- OpenGLes2.0 什么是Pbuffer
- ndk opengles2.0 配置
- Opengles2.0入门
- 浅学OpenGLES2.0
- 浅学OpenGLES2.0
- 浅学OpenGLES2.0
- OpenGLES2.0 概念
- OpenGLES2.0原理浅析
- opengles2.0 headfirst Simple_VertexShader
- Android OpenGLES2.0(一)——了解OpenGLES2.0
- Android OpenGLES2.0(一)——了解OpenGLES2.0
- Android opengles2.0 背景透明
- opengles2.0 programming guide: attribute
- Linux下的正则表达式
- raw类型浅析
- java语言异常的使用方法和处理经验
- eclipse创建Maven项目报: Error merging velocity templates
- [OpenSceneGraph入门指导]1.6 OpenSceneGraph 概览
- OpenGLES2.0笔记
- 神经网络训练时精度问题
- MFC中给程序添加图标
- Linux C——数据库的基本知识
- mysql更改用户名和密码及mysql常用命令
- OpenCV实现朴素贝叶斯分类器诊断病情
- ViewPager,ScrollView 嵌套ViewPager滑动冲突解决
- XML选择器的使用
- 优化sql语句