OpenGL浅析

openGLES2.0程序设计主要实现流程有如下顺序:

 定义物体顶点信息 –> 编辑着色器代码 –> 编译连接着色器程序 -> 物体顶点信息传入着色器 –> GLSurfaceView加载Renderer –> Activity加载GLSurfaceView -> 渲染物体输出屏幕

 操作名称和实现方法如下: 

1、定义物体顶点信息 顶点信息一般包括: 

 (1)三维坐标信息; 

 (2)三维法向量信息;

 (3)颜色信息或二维贴图坐标信息; 

 复杂物体的坐标通常通过特定的软件绘制生成顶点信息文件,然后进行解读; 

2、编辑着色器代码 

   着色器语言编写的代码, 通常后缀名.sh, 语法和C相似95%以上, 是OpenGLES2.0的可编程渲染通道, 增加了编程难度, 但是能实现更绚丽多彩的效果。 

  一般编写好的着色器代码放在android工程目录下的assets文件, assets常用轻量资源的读写。 

3、编译连接着色器 

 从assets获取着色器脚本, 并返回脚本字符串的过程:

  主要方法:(1. InputStream in = rgetAssets .open(fname); 

      (2. in 转化为 ByteArrayOutputStream out 

      (3. byte[] bout = out.toByteArray(); 记得close in&out 

      (4. String result = (new String(bout, “UTF-8”)).replaceAll(\\r\\n, “\n”); 

   加载片元着色器和顶点着色器的方法: 

       (1. 申请特定着色器 int shaderId = GLES20.glCreateShader(shaderType); //shaderType GLES20.GL_VERTEX_SHADER(顶点) GLES20.GL_FRAGMENT_SHADER(片元)

       如果申请成功则返回的shaderId不为零 

       (2. 给申请成功的着色器加载脚本并编译,查错 

       GLES20.glShaderSource(shaderId, source);/// source是脚本字符串

        GLES20.glCompileShader(shaderId);///编译

int compiles[1];
GLES20.glGetShaderiv(shaderId, GLES20._GL_COMPILE_STATUS, compiles, 0);///查看编译情况if(compiles[0] == 0){ //编译失败,释放申请的着色器 

   GLES20.glDeleteShader(shaderId); 

   shaderId = 0;

}

编译连接并生成着色器程序:

  (1. 申请着色器程序:int program = GLES20.glCreateProgram();
  (2. 加入两种着色器并查错(方法一样):

   GLES20.glAttachShader(programe, vertexShaderId);

   int error;
 while((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR){ 

   throw (new RuntimeException(ShaderName + “attach Error”))

 }

 (3. 连接着色器程序,并查看连接情况
    GLES20.glLinkProgram(program);
    int LinkStatus[1];
    GLES20.glGetPromgramiv(program, GLES20.GL_LINK_STATUS, LinkStatus, 0);
   if(LinkStatus[0]!= GLES20.GL_TRUE){
         Log.e(“Link Error”, GLES20.glGetProgramInfoLog(program));
        GLES20.glDeletePromgram(program);
        program = 0;

   }

 至此可以利用program进行该着色器的利用。

4、物体顶点信息传入着色器

   生成顶点信息, 用FloatBuffer类存储的一般方法:
    float vertexs[] = {1, 2, 3}
    ByteBuffer bbv = ByteBuffer.allocateDirect(vertexs.length * 4);//一个float 4个字节
    bbv.order(ByteOrder.nativeOrder());///前期设置
   vertexBuffer = bbv.asFloatBuffer();//作为中介开辟FloatBuffer
    vertexBuffer.put(vertexs); //存入信息
    vertexBuffer.position(0); //设置起始位置为0;
   获取着色器参数ID
    int maPositionHandler = GLES20.glGetAttribLocation(program, “aPosition”);
   传入数据
    GLES20.glVertexAttribPointer(
    maPositionHandle,
    3,
    GLES20.GL_FLOAT,
    false,
   3*4,
    mVertexBuffer
    );
   使用数据: GLES20.glEnableVertexAttribArray(maPositionHandle); 

5、GLSurfaceView加载Renderer

  初始化GLSurfaceView
  setEGLContextClientVersion(2);//设置版本
  setRanderer(new MyRenderer());//增添渲染器
  setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//主动渲染模式
  自定义渲染器,实现3个渲染接口,例如:
  

private class MyRenderer implements GLSurfaceView.Renderer{  
    Triangle tle;  
    public void onDrawFrame(GL10 gl)  {  
        //清除深度缓冲与颜色缓冲  
        GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);         //绘制三角形对  
        tle.drawSelf();     
     }  
    public void onSurfaceChanged(GL10 gl, int width, int height)  {  
        //设置视窗大小及位置  
        GLES20.glViewport(0, 0, width, height);  
        //计算GLSurfaceView的宽高比   
        float ratio = (float) width / height;  
        //调用此方法计算产生透视投影矩阵  
        Matrix.frustumM(Triangle.mProjMatrix, 0, -ratio, ratio, -1, 1, 1, 100);  
        //调用此方法产生摄像机9参数位置矩阵  
        Matrix.setLookAtM(Triangle.mVMatrix, 0, 0,0,3,0f,0f,0f,0f,1.0f,0.0f);  
    }  
    public void onSurfaceCreated(GL10 gl, EGLConfig config)  {  
        //设置屏幕背景色RGBA  
        GLES20.glClearColor(0,0,0,1.0f);   
        //创建三角形对对象  
        tle=new Triangle(MyTDView.this);         
        //打开深度检测  
        GLES20.glEnable(GLES20.GL_DEPTH_TEST);  
        rthread=new RotateThread();  
        rthread.start();       
    }  
}复制代码


OpenGL ES2.0中几个基本概念

1、顶点着色器

  着色器(Shader)是在GPU上运行的小程序。从名称可以看出,可通过处理它们来处理顶点。此程序使用OpenGL ES SL语言来编写。它是一个描述顶点或像素特性的简单程序。

  对于发送给GPU的每一个顶点,都要执行一次顶点着色器。其功能是把每个顶点在虚拟空间中的三维坐标变换为可以在屏幕上显示的二维坐标,并带有用于z-buffer的深度信息。顶点着色器可以操作的属性有:位置、颜色、纹理坐标,但是不能创建新的顶点。   

2、片元着色器

  片元着色器计算每个像素的颜色和其它属性。它通过应用光照值、凹凸贴图,阴影,镜面高光,半透明等处理来计算像素的颜色并输出。它也可改变像素的深度(z-buffering)或在多个渲染目标被激活的状态下输出多种颜色。一个片元着色器不能产生复杂的效果,因为它只在一个像素上进行操作,而不知道场景的几何形状。

3、着色器语言

  着色器语言(Shading Language)是一种高级的图形编程语言,仅适合于GPU编程,其源自应用广泛的C语言。对于顶点着色器和片元着色器的开发都需要用到着色器语言进行开发。它是面向过程的而非面向对象。

4、坐标系

  OpenGL ES采用的是右手坐标,选取屏幕中心为原点,从原点到屏幕边缘默认长度为1,也就是说默认情况下,从原点到(1,0,0)的距离和到(0,1,0)的距离在屏幕上展示的并不相同。即向右为X正轴方向,向左为X负轴方向,向上为Y轴正轴方向,向下为Y轴负轴方向,屏幕面垂直向上为Z轴正轴方向,垂直向下为Z轴负轴方向。

5、图形的绘制

  OpenGL ES2.0的世界里面只有点、线、三角形,其它更为复杂的几何形状都是由三角形构成的。包括正方形、圆形、正方体、球体等。但是其他更为复杂的物体,我们不可能都自己去用三角形构建,这个时候就需要通过加载利用其他软件(比如3DMax)构建的3D模型。

6、投影

  OpenGL ES 的世界是3D的,但是手机屏幕能够给我展示的终究是一个平面,只不过是在绘制的过程中利用色彩和线条让画面呈现出3D的效果。OpenGL ES将这种从3D到2D的转换过程利用投影的方式使计算相对使用者来说变得简单可设置。 OpenGL ES中有两种投影方式:正交投影和透视投影。正交投影,物体不会随距离观测点的位置而大小发生变化。而透视投影,距离观测点越远,物体越小,距离观测点越近,物体越大。

7、光照

  如果利用直接给出颜色的方式来对3D场景中的物体进行着色渲染,很难使3D场景拥有较强的真实感。一般来说,曲面物体比平面物体更能体现出光照效果。想用数学模型完全模拟真实世界的光照情况是很难的,而OpenGL ES 2.0采用的光照模型相对真实世界的光照是进行了很大的简化。在OpenGL ES 2.0中,光照由三种元素组成(也可以说是三种通道组成),分别为环境光、镜面光及散射光。

8、纹理影射

  现实世界中的物体往往是绚丽多彩的,要模拟现实世界的绚丽多彩,绘制出更加真实、酷炫的3D物体,就需要用到纹理映射了。纹理映射是将2D的纹理映射到3D场景中的立体物体上。


OpenGL ES2.0渲染过程

读取顶点数据——执行顶点着色器——组装图元——光栅化图元——执行片元着色器——写入帧缓冲区——显示到屏幕上

注:

   OpenGL作为本地库直接运行在硬件上,没有虚拟机,也没有垃圾回收或者内存压缩。在Java层定义图像的数据需要能被OpenGL存取,因此,需要把内存从Java堆复制到本地堆。

    顶点着色器是针对每个顶点都会执行的程序,是确定每个顶点的位置。同理,片元着色器是针对每个片元都会执行的程序,确定每个片元的颜色。

     着色器需要进行编译,然后链接到OpenGL程序中。一个OpenGL的程序就是把一个顶点着色器和一个片段着色器链接在一起变成单个对象。


转载于:https://juejin.im/post/5b8ca68be51d453885033a2b

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值