美文网首页
OpenGL ES之绘制点、线、三角形

OpenGL ES之绘制点、线、三角形

作者: 放羊娃华振 | 来源:发表于2022-10-01 10:03 被阅读0次

    一、绘制点

    前面讲了一些关于OpenGL ES相关的知识,接下来就开始利用OpenGL ES在Android平台上实现各种效果。首先介绍利用OpenGL ES2.0实现点的绘制。首先看下效果图:


    image.png

    通过该效果图,可以看出,是在黑色的背景上绘制了两个红色的点。

    实现

    1.Activity实现

    /**
     * @Description: 点
     * @Author: dzh
     * @CreateDate: 2020-06-16 17:03
     */
    public class PointActivity extends Activity {
    
        private GLSurfaceView mGLSurfaceView;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            mGLSurfaceView = new GLSurfaceView(this);
            //设置使用OpenGL2.0版本
            mGLSurfaceView.setEGLContextClientVersion(2);
            mGLSurfaceView.setRenderer(new PointRenderer(this));
            //设置渲染模式:requestRender方法触发会渲染
            mGLSurfaceView.setRenderMode(DGLSurfaceView.RENDERMODE_WHEN_DIRTY);
            setContentView(mGLSurfaceView);
        }
    }
    

    把创建的GLSurfaceView设置给Activity,并且设置OpenGL ES的版本号为2,渲染模式为手动触发,渲染器为PointRenderer。
    2.PointRenderer实现
    2.1 编写顶点着色器

    attribute vec4 av_Position;
    uniform float p_Size;
    void main(){
    gl_Position = av_Position;
    gl_PointSize = p_Size;
    }
    

    备注:顶点着色器会把av_Position赋值给gl_Position,把p_Size赋值给gl_PointSize。
    2.2 编写片元着色器

    precision mediump float;
        uniform vec4 af_Color;
        void main(){
            gl_FragColor = af_Color;
        }
    

    备注:片元着色器会把af_Color赋值给gl_FragColor。
    2.3 设置顶点坐标
    上图两个红点的位置是:(0,0),(0.5,0.5),在OpenGL ES中,顶点坐标的值是float类型,用数组标示即为:

    private float[] vertexData = {
              0f, 0f,
              0.5f, 0.5f
        };
    

    上面数组是加载在jvm中,为了提供效率需要把顶点坐标存放到内存数组中:

    vertexBuffer = ByteBuffer.allocateDirect(vertexData.length * 4)
          .order(ByteOrder.nativeOrder())
          .asFloatBuffer()
          .put(vertexData);
    

    备注:vertexData.length * 4是因为float占4个字节
    2.4 加载着色器
    1、创建shader(着色器:顶点或片元)

    int shader = GLES20.glCreateShader(shaderType);
    

    2、加载shader源码并编译shader

    GLES20.glShaderSource(shader, source);
    GLES20.glCompileShader(shader);
    

    3、检查是否编译成功:

    GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
    

    4、创建一个渲染程序:

     int program = GLES20.glCreateProgram();
    

    5、将着色器程序添加到渲染程序中:

    GLES20.glAttachShader(program, vertexShader);
    

    6、链接源程序:

    GLES20.glLinkProgram(program);
    

    7、检查链接源程序是否成功

    GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
    

    8、得到着色器中的属性:

    int vPosition = GLES20.glGetAttribLocation(program, "v_Position");
    

    9、使用源程序:

    GLES20.glUseProgram(program);
    

    10、使顶点属性数组有效:

    GLES20.glEnableVertexAttribArray(vPosition);
    

    11、为顶点属性赋值:

    GLES20.glVertexAttribPointer(vPosition, 2, GLES20.GL_FLOAT, false, 8, vertexBuffer);
    

    12、绘制图形:

    GLES20.glDrawArrays(GLES20.GL_POINTS, 0, 2);
    

    但是我后面又把上面的步骤进行了一次封装,使用相对简单了些:

    package com.stormdzh.openglanimation.util.shader;
    
    import android.content.Context;  import android.opengl.GLES20;  import android.util.Log;
    
    import [java.io](http://java.io/).BufferedReader;  import [java.io](http://java.io/).InputStream;  import [java.io](http://java.io/).InputStreamReader;
    
    /**  * @Description: ShaderUtil  * @Author: dzh  * @CreateDate: 2020-06-16 19:45  */  public class ShaderUtil {
    
    public static String readRawText(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) {
    
    int shader = GLES20.glCreateShader(shaderType);  if (shader != 0) {  GLES20.glShaderSource(shader, source);  GLES20.glCompileShader(shader);  int[] compile = new int[1];  GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compile, 0);  if (compile[0] != GLES20.GL_TRUE) {  Log.i("DzhShaderUtil", " compile 失败");  GLES20.glDeleteShader(shader);  shader = 0;  }
    
    }  return shader;
    
    }
    
    public static int creteProgram(String vertexSource, String fragmentSource) {
    
    int vettexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);  if (vettexShader == 0) {
    
    return 0;  }
    
    int fragmentShaper = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
    
    if (fragmentShaper == 0) {
    
    return 0;  }
    
    int program = GLES20.glCreateProgram();
    
    if (program != 0) {  GLES20.glAttachShader(program, vettexShader);  GLES20.glAttachShader(program, fragmentShaper);  GLES20.glLinkProgram(program);  int[] linsStatus = new int[1];  GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linsStatus, 0);  if (linsStatus[0] != GLES20.GL_TRUE) {  Log.i("DzhShaderUtil", " linsStatus 失败");  GLES20.glDeleteProgram(program);  program = 0;
    
    }  }
    
    return program;  }  }
    
    

    这个类有三个方法,分别是读取raw目录下着色器脚本,加载着色器、和创建渲染程序。
    那么绘制点的三行核心代码是:

    //给颜色赋值
    GLES20.glUniform4f(afColor, 1f, 0, 0, 1);
    //设置点的大小
    GLES20.glUniform1f(pSize, 20.0f);
    //绘制
    GLES20.glDrawArrays(GLES20.GL_POINTS, 0, vertexData.length / 2);
    

    二、绘制线

    首先看一下线条的预览图:


    image.png

    绘制步骤和点的步骤几乎是一样的,只是绘制的图元需要修改下:

    //绘制
    GLES20.glDrawArrays(GLES20.GL_LINES, 0, 2);
    

    三、绘制三角形

    首先看一下三角形的预览图:


    image.png

    绘制三角形和绘制点和直线的区别,在于顶点坐标的格式,和绘制方式,所以必须定义三个顶点:

    //顶点数据
    private float[] vertexData = {
    0f, 1f,
    -1f, -1f,
    1f, -1f
    };
    

    之后需要修改绘制方式:

    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 3);
    

    相关文章

      网友评论

          本文标题:OpenGL ES之绘制点、线、三角形

          本文链接:https://www.haomeiwen.com/subject/gnnbkrtx.html