OpenGL ES 绘制图片

流程

1、编写着色器(顶点着色器和片元着色器)

2、设置顶点、纹理坐标

3、加载着色器

4、创建纹理

5、渲染图片


OpenGL ES 中的顶点坐标与纹理坐标


绘制四边形

规定:图形环绕方向必须一致

参数属性:三角形    GL_TRIANGLES
v1, v2, v3,
v3, v2, v4,

参数属性:三角形扇    GL_TRIANGLE_STRIP:
偶数:n-1, n-2, n
奇数:n-2, n-1, n


顶点内存数组

1、绘制坐标范围
    float[] vertexData = {
                       -1f, -1f,
                       1f, -1f,
                      -1f, 1f,
                      1f, 1f               };

2、为坐标分配本地内存地址
    FloatBuffer vertexBuffer;
    vertexBuffer = ByteBuffer.allocateDirect(vertexData.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer()
                .put(vertexData);
    vertexBuffer.position(0);


vertex_shader.glsl    顶点着色器shader

attribute vec4 v_Position;     //顶点坐标
attribute vec2 f_Position;      //纹理坐标
varying vec2 ft_Position;       //
void main() {
    ft_Position = f_Position;
    gl_Position = v_Position;
}

attribute 只能在vertex中使用varying 用于vertex顶点着色器    和    fragment片元着色器之间传递值


fragment_shader.glsl    片元着色器shader

precision mediump float;     //绘制精度
varying vec2 ft_Position;     //与顶点着色器中传值
uniform sampler2D sTexture;    //图片
void main() {
    gl_FragColor=texture2D(sTexture, ft_Position);
}

注: uniform 用于在application中向vertex和fragment中传递值。


OpenGL ES加载Shader

1、创建shader( shaderType 着色器类型:顶点或片元)
    int shader = GLES20.glCreateShader(shaderType);
2、加载shader源码并编译shader 
    GLES20.glShaderSource(shader, source);    //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、为顶点属性    vPosition     赋值:
GLES20.glVertexAttribPointer(vPosition, 2, GLES20.GL_FLOAT, false, 8 ,vertexBuffer);   // 2 两个属性确定一个点   GL_FLOAT类型     false是否需要归一化   8两点之间的跨度    vertexBuffer本地缓存

                                                                                                                                                //   取8位变成2个点    
12、绘制图形:
     GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);    //三角形带


工具方法

// 1 .从raw文件中获取字符串
public static String getRawResource(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();
}

//2 .根据顶点着色器字符串和片元着色器字符串创建 shader
private 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) {
            GLES20.glDeleteShader(shader);
            shader = 0;
        }
        return shader;
    } else {
        return 0;
    }
}

//3 .根据shader创建program
public static int createProgram(String vertexSource, String fragmentSoruce) {
    int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
    int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSoruce);

    if (vertexShader != 0 && fragmentShader != 0) {
        int program = GLES20.glCreateProgram();

        GLES20.glAttachShader(program, vertexShader);
        GLES20.glAttachShader(program, fragmentShader);

        GLES20.glLinkProgram(program);
        return program;
    }
    return 0;
}

GImgVideoView
 

package com.example.glivepush.opengl;

import android.content.Context;
import android.util.AttributeSet;

import com.example.glivepush.egl.GEGLSurfaceView;

public class OpenGLView extends GEGLSurfaceView {

    public OpenGLView(Context context) {
        this(context, null);
    }

    public OpenGLView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public OpenGLView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setRender(new OpenGLRender(context));
    }
}


GImgVideoRender

package com.example.glivepush.opengl;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;

import com.example.glivepush.R;
import com.example.glivepush.egl.GEGLSurfaceView;
import com.example.glivepush.egl.GShaderUtil;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

public class OpenGLRender implements GEGLSurfaceView.GGLRender {


    private Context context;
    //顶点坐标  主要用来在本地开辟内存
    private float[] vertexData = {
            -1f, -1f,
            1f, -1f,
            -1f, 1f,
            1f, 1f
    };
    //生成的本地内存
    private FloatBuffer vertexBuffer;

    //纹理坐标
    private float[] fragmentData = {
            0f, 1f,
            1f, 1f,
            0f, 0f,
            1f, 0f
    };
    //生成的本地内存
    private FloatBuffer fragmentBuffer;

    private int program;
    private int vPosition;
    private int fPosition;
    private int textureid;
    private int sampler;

    public OpenGLRender(Context context) {
        this.context = context;
        //生成的本地内存
        vertexBuffer = ByteBuffer.allocateDirect(vertexData.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer()
                .put(vertexData);
        vertexBuffer.position(0);
        fragmentBuffer = ByteBuffer.allocateDirect(fragmentData.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer()
                .put(fragmentData);
        fragmentBuffer.position(0);

    }

    @Override
    public void onSurfaceCreated() {
        //工具方法加载代码
        String vertexSource = GShaderUtil.getRawResource(context, R.raw.vertex_shader_screen);
        String fragmentSource = GShaderUtil.getRawResource(context, R.raw.fragment_shader_screen);
        //工具方法创建program
        program = GShaderUtil.createProgram(vertexSource, fragmentSource);

        if (program > 0) {
            //取出顶点坐标
            vPosition = GLES20.glGetAttribLocation(program, "v_Position");
            //取出纹理坐标
            fPosition = GLES20.glGetAttribLocation(program, "f_Position");

            sampler = GLES20.glGetUniformLocation(program, "sTexture");
        }

        //生成纹理
        int[] textureIds = new int[1];
        GLES20.glGenTextures(1, textureIds, 0);
        textureid = textureIds[0];
        //绑定纹理
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureid);
        //绑定至第0位
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        //将sampler绑定至第0位
        GLES20.glUniform1f(sampler, 0);

        //设置环绕过滤方法
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);

        //绘制图片
        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.img_1);
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
        bitmap.recycle();
        bitmap = null;
        //解绑
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
    }

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

    @Override
    public void onDrawFrame() {
        //清屏
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        GLES20.glClearColor(1f, 0f, 0f, 1f);

        //使程序生效
        GLES20.glUseProgram(program);

        //重新绑定
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureid);

        //使顶点属性数组有效
        GLES20.glEnableVertexAttribArray(vPosition);
        //为顶点属性赋值
        GLES20.glVertexAttribPointer(vPosition, 2, GLES20.GL_FLOAT, false, 8,
                vertexBuffer);
        //使纹理属性数组有效
        GLES20.glEnableVertexAttribArray(fPosition);
        //为顶点属性赋值
        GLES20.glVertexAttribPointer(fPosition, 2, GLES20.GL_FLOAT, false, 8,
                fragmentBuffer);
        //绘制图形
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);

        //解绑
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
    }

}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值