王学岗——————Opengl加载图片以(对应第34节课)

前言

1,做直播,要先美颜在推流
2,做直播三个数据,美颜数据,本地录制,推到网络。
3,图片美颜是通过openGL在GPU中做

架构

1,把图片渲染到OpenGL
2,在这里插入图片描述
3,在这里插入图片描述
4,openGL 世界坐标系

在这里插入图片描述
5,vPosition传递的是世界坐标系
6,Bitmap在代码里加载,代码运行再CPU,我们首先要做的事情就是要把bitmap从cpu传到GPU。要首先再GPU里准备个容器接收Bitmap,这个容器就叫纹理。
7,什么是纹理?
在这里插入图片描述

代码

package com.maniu.openglimage;

import static android.opengl.GLES20.GL_TEXTURE_2D;

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

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

//加载opengl程序
public class ImageFilter {

    protected int mProgId;
//世界坐标系,我们绘制的是一个矩形,传入这几个点就够啦
    static final float COORD1[] = {
            -1.0f, -1.0f,
            1.0f, -1.0f,
            -1.0f, 1.0f,
            1.0f, 1.0f
    };
//Android 布局坐标系
    static final float TEXTURE_COORD1[] = {
            0.0f, 1.0f,
            1.0f, 1.0f,
            0.0f, 0.0f,
            1.0f, 0.0f,
    };
    protected int mInputTexture;
    private String mVertexShader;
    private String mFragmentShader;

    private FloatBuffer mPositionBuffer;
    private FloatBuffer mCoordBuffer;
    protected int mPosition;
     protected int vCoord;
    public ImageFilter(Context context) {
        this(OpenGLUtils.readRawTextFile(context,R.raw.base_vert), OpenGLUtils.readRawTextFile(context,R.raw.base_frag));

    }
    public ImageFilter(String vertexShader, String fragmentShader) {
//        顶点程序读到vertexShader
        mVertexShader = vertexShader;
//        片元程序读到fragmentShader
        mFragmentShader = fragmentShader;
    }



    public void initShader() {
//加载程序
        mProgId = OpenGLUtils.loadProgram(mVertexShader, mFragmentShader);
        //        找到GPU的变量 第一步:定位变量在GPU的位置;第二部:实例化一个通道FloteBuffer
//     把cpu的值(如COORD1)传进来   第三步,把FloateBuffer的值再给GPU的变量
        mPosition = GLES20.glGetAttribLocation(mProgId, "vPosition");
        vCoord = GLES20.glGetAttribLocation(mProgId,
                "vCoord");
        mInputTexture = GLES20.glGetUniformLocation(mProgId, "inputImageTexture");
    }
//顶点程序
    public void loadVertex() {
        float[] coord = COORD1;
        float[] texture_coord = TEXTURE_COORD1;
//       四个坐标,所以乘以4
        mPositionBuffer= ByteBuffer.allocateDirect(coord.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();

        mPositionBuffer.put(coord).position(0);

        mCoordBuffer = ByteBuffer.allocateDirect(texture_coord.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        mCoordBuffer.put(texture_coord).position(0);
    }
    public int  init(Bitmap bitmap) {
        initShader();
        loadVertex();
        return  initTexture(bitmap);
    }
//    生成纹理层,接收Bitmap
    private int initTexture( Bitmap bitmap) {
//        入参出参对象,因为生成一个,所以填1
        int[] textures = new int[1];
//        生成纹理,1:生成几个;textures:纹理ID;第三个参数一般是0
        GLES20.glGenTextures(1, textures, 0);
//        使用纹理,绑定后对GLES20的操作都是针对这个纹理(textures)。最后一个参数如果传0就表示解绑
        GLES20.glBindTexture(GL_TEXTURE_2D, textures[0]);
//给纹理设置属性
//        GLES20.GL_TEXTURE_2D表示2D纹理,
//        GLES20.GL_TEXTURE_MAG_FILTER 过滤方式
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
                GLES20.GL_NEAREST);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
                GLES20.GL_LINEAR);
//        GLES20.GL_TEXTURE_WRAP_S代表水平方向
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
                GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
//        GLES20.GL_TEXTURE_WRAP_T代表垂直方向
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
                GLES20.GL_CLAMP_TO_EDGE);

//        有请 bitmap,第一个参数表示ID,第四个参数border:边缘边界
//    现在我们把bitmap传输到了GPU的纹理层。接下来针对纹理层采样就可以了,
//把bitmap中的像素一个一个的采样到矩形中就可以了,这样矩形就显示一张图片了。。
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
        return textures[0];

    }

    public int drawFrame(int glTextureId){
        GLES20.glUseProgram(mProgId);
        mPositionBuffer.position(0);
//        把数据从CPUmPositionBuffer传到GPUmPosition。立体的就是3,二维的就是2
        GLES20.glVertexAttribPointer(mPosition, 2, GLES20.GL_FLOAT, false, 0, mPositionBuffer);
        GLES20.glEnableVertexAttribArray(mPosition);


        mCoordBuffer.position(0);
        GLES20.glVertexAttribPointer(vCoord, 2, GLES20.GL_FLOAT, false, 0,
                mCoordBuffer);
        GLES20.glEnableVertexAttribArray(vCoord);
//        激活一个图层,给纹理使用(上一篇文章我们是个CameraX数据使用)
        GLES20.glActiveTexture(0);
//        图层和纹理绑定
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,glTextureId );
//        第0个图层
        GLES20.glUniform1i(mInputTexture, 0);
//  绘制
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
//图层使用完要解绑,0就代表解绑
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
        return glTextureId;
    }



}

package com.maniu.openglimage;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.ViewGroup;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

public class MainActivity extends AppCompatActivity {
    private GLSurfaceView mSurfaceView;
    private int mTextureId =-1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ViewGroup container = (ViewGroup) findViewById(R.id.main);
        mSurfaceView = new GLSurfaceView(this);
        mSurfaceView.setEGLContextClientVersion(2);
        container.addView(mSurfaceView);
        final ImageFilter filter = new ImageFilter(this);
//        要把Bitmap从CPU传到GPU
        final Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.demo);
        mSurfaceView.setRenderer(new GLSurfaceView.Renderer() {
            @Override
            public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// 把图片以openGL方式渲染到屏幕上
                mTextureId= filter.init(bitmap);
            }

            @Override
            public void onSurfaceChanged(GL10 gl, int width, int height) {
//                告诉opengl窗口是多少,surfaceChanged可能会改变
                GLES20.glViewport(0, 0, width, height);
            }
//渲染就会调用该方法,
            @Override
            public void onDrawFrame(GL10 gl) {
                filter.drawFrame(mTextureId);
            }
        });
    }
}
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;//0图层
//片元
void main(){
//  openGL渲染到Bitmap,texture2D就是采样器
    gl_FragColor = texture2D(inputImageTexture, textureCoordinate);

//    gl_FragColor = vec4(0,255,0,0);如果想变成绿色,改这里。
}
attribute vec4 vPosition;
attribute vec4 vCoord;
//varying修饰的就是传值的变量
varying vec2 textureCoordinate;
//顶点
void main(){
    //vPosition:传递的是世界坐标系
//    告诉opengl,我这里绘制的是矩形
    gl_Position = vPosition;
    //传给纹理坐标系的坐标
    textureCoordinate = vCoord.xy;
}
package com.maniu.openglimage;

import android.content.Context;
import android.opengl.GLES20;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class OpenGLUtils {
//100% 相同
    public static int loadProgram(String vSource, String fSource) {
//
        /**
         * 顶点着色器
         */
        int vShader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
        //加载着色器代码
        GLES20.glShaderSource(vShader, vSource);
        //编译(配置)
        GLES20.glCompileShader(vShader);
        //查看配置 是否成功
        int[] status = new int[1];
        GLES20.glGetShaderiv(vShader, GLES20.GL_COMPILE_STATUS, status, 0);
        if (status[0] != GLES20.GL_TRUE) {
            //失败
            throw new IllegalStateException("load vertex shader:" + GLES20.glGetShaderInfoLog
                    (vShader));
        }


        /**
         *  片元着色器
         *  流程和上面一样
         */
        int fShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
        //加载着色器代码
        GLES20.glShaderSource(fShader, fSource);
        //编译(配置)
        GLES20.glCompileShader(fShader);

        //查看配置 是否成功
        GLES20.glGetShaderiv(fShader, GLES20.GL_COMPILE_STATUS, status, 0);
        if (status[0] != GLES20.GL_TRUE) {
            //失败
            throw new IllegalStateException("load fragment shader:" + GLES20.glGetShaderInfoLog
                    (vShader));
        }


        /**
         * 创建着色器程序
         */
        int program = GLES20.glCreateProgram();
        //绑定顶点和片元
        GLES20.glAttachShader(program, vShader);
        GLES20.glAttachShader(program, fShader);
        //链接着色器程序
        GLES20.glLinkProgram(program);

//获得状态
        GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, status, 0);
        if (status[0] != GLES20.GL_TRUE) {
            throw new IllegalStateException("link program:" + GLES20.glGetProgramInfoLog(program));
        }
//        用完了一定要释放掉,
        GLES20.glDeleteShader(vShader);
        GLES20.glDeleteShader(fShader);
//        program就是总程序
        return program;
    }
    public static String readRawTextFile(Context context, int rawId) {
        InputStream is = context.getResources().openRawResource(rawId);
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        String line;
        StringBuilder sb = new StringBuilder();
        try {
            while ((line = br.readLine()) != null) {
                sb.append(line);
                sb.append("\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sb.toString();
    }





}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python的OpenGL库是一个用于渲染图形和实现3D图形应用的强大工具。如果你是一个初学者,以下是一些学习OpenGL的指南: 1. 学习基本的计算机图形学概念:在深入学习OpenGL之前,了解一些基本的计算机图形学概念是很重要的。你可以学习像坐标系、向量、矩阵变换等基础知识。 2. 学习Python语言基础:作为一个初学者,你需要先掌握Python的基本语法和编程概念。这将帮助你更好地理解和使用OpenGL库。 3. 安装OpenGL库:在开始之前,你需要确保你的计算机上已经安装了OpenGL库。你可以使用pip来安装PyOpenGL库。 4. 学习OpenGL的核心知识:一旦你准备好了,可以开始学习OpenGL的核心知识,如顶点缓冲对象(VBO)、着色器(programs)、着色器语言(GLSL)等。掌握这些基本概念对于理解和使用OpenGL非常重要。 5. 编写简单的OpenGL程序:接下来,你可以开始编写一些简单的OpenGL程序来实践所学的知识。你可以从简单的绘制一些基本图形开始,然后逐渐扩展到更复杂的场景和效果。 6. 学习OpenGL的高级特性:一旦你熟悉了OpenGL的基本知识,你可以探索一些更高级的主题,如光照、纹理映射、深度测试、投影等。这将帮助你创建更逼真和交互式的3D图形应用。 7. 参考文档和教程:除了上述的自学方法外,你还可以参考一些优秀的OpenGL文档和教程。一些推荐的资源包括OpenGL官方文档、PyOpenGL官方文档、学习OpenGL的在线教程等。 记住,学习OpenGL需要时间和实践。通过不断地编写代码和实验,你将逐渐掌握OpenGL的技能并创建出令人惊叹的图形应用。祝你好运!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值