如何使用Android中的OpenGL ES媒体效果

如何使用Android中的OpenGL ES媒体效果,第1张

Android的媒体效果框架允许开发者可以很容易的应用多种令人印象深刻的视觉效果到照片或视频之上。作为这个媒体效果的框架,它使用GPU来处

理图片处理的过程,它仅仅接收OpenGL的纹理(texture)作为输入。在本次教程中,你将会学习到如何使用OpenGL

ES2.0将图片资源转化为纹理,以及如何使用框架为图片应用不同的处理效果。

准备

为了开始本次的教程,你必须具备:

1.一款支持Android开发的IDE,如果你没有的话,可以在Android Developer website下载最新版本的Android studio。

2.一款运行Android4.0之上Android手机,并且GPU支持OpenGL ES2.0

3.对OpenGL的基本知识了解

设置OpenGL ES环境

创建GLSurfaceView

为了显示OpenGL的图形,你需要使用GLSurfaceView类,就像其他任何的View子类意义,你可以将它添加到你的Activity或Fragment之上,通过在布局xml文件中定义或者在代码中创建实例。

在本次的教程中,我们使用GLSurfaceView作为唯一的View在我们的Activity中,因此,为了简便,我们在代码中创建

GLSurfaceView的实例并将其传入setContentView中,这样它将会填充你的整个手机屏幕。Activity中的onCreate方

法如下:

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState)

GLSurfaceView view = new GLSurfaceView(this)

setContentView(view)

}

因为媒体效果的框架仅仅支持OpenGL ES2.0及以上的版本,所以在setEGLContextClientVersion 方法中传入2;

view.setEGLContextClientVersion(2)

为了确保GLSurfaceView仅仅在必要的时候进行渲染,我们在setRenderMode 方法中进行设置:

view.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY)

创建Renderer

Renderer负责渲染GLSurfaceView中的内容。

创建类实现接口GLSurfaceView.Renderer,在这里我们打算将这个类命名为EffectsRenderer,添加构造函数并覆写接口中的抽象方法,如下:

public class EffectsRenderer implements GLSurfaceView.Renderer {

public EffectsRenderer(Context context){

super()

}

@Override

public void onSurfaceCreated(GL10 gl, EGLConfig config) {

}

@Override

public void onSurfaceChanged(GL10 gl, int width, int height) {

}

@Override

public void onDrawFrame(GL10 gl) {

}

}

回到Activity中调用setRenderer方法,让GLSurfaceView使用我们创建的Renderer:

view.setRenderer(new EffectsRenderer(this))

编写Manifest文件

如果你想要发布你的App到谷歌商店,在AndroidManifest.xml文件中添加如下语句:

这会确保你的app只能被安装在支持OpenGL ES2.0的设备之上。现在OpenGL环境准备完毕。

创建一个OpenGL平面

定义顶点

GLSurfaceView是不能直接显示一张照片的,照片首先应该被转化为纹理,应用在OpenGL square之上。在本次教程中,我将创建一个2D平面,并且具有4个顶点。为了简单,我将使用一个长方形,现在,创建一个新的类Square,用它来代表形状。

public class Square {

}

默认的OpenGL系统的坐标中的原点是在中心,因此4个角的坐标可以表示为:

左下角: (-1, -1) 右下角:(1, -1) 右上角:(1, 1) 左上角:(-1, 1)

我们使用OpenGL绘制的所有的物体都应该是由三角形决定的,为了画一个方形,我们需要两个具有一条公共边的三角形,那意味着这些三角形的坐标应该是:

triangle 1: (-1, -1), (1, -1), 和 (-1, 1) triangle 2: (1, -1), (-1, 1), 和 (1, 1)

创建一个float数组来代表这些顶点:

private float vertices[] = {

-1f, -1f,

1f, -1f,

-1f, 1f,

1f, 1f,

}

为了在square上定位纹理,需要确定纹理的顶点坐标,创建另一个数组来表示纹理顶点的坐标:private float textureVertices[] = {

0f,1f,

1f,1f,

0f,0f,

1f,0f

}

简单来说就是实现图形的底层渲染

A. 比如在游戏开发中,对于游戏场景/游戏人物的渲染

B. 比如在音视频开发中,对于视频解码后的数据渲染

C. 比如在地图引擎,对于地图上的数据渲染

D. 比如在动画中,实现动画的绘制

E. 比如在视频处理中,对于视频加上滤镜效果

OpenGL/OpenGL ES/Metal 在任何项目中解决问题的本质就是利用 GPU 芯片来高效渲染图形图像。

图形 API ios 开发者唯一接近 GPU 的方式。

OpenGL 阶段:

OpenGL ES 阶段:

Metal 阶段:

固定管线/存储着⾊器

顶点数据是由CPU/GPU来处理?

顶点缓存区:区域(不在内存!->显卡显存中。)

片元着色器

像素着色器

片元函数

GPUImage

[-1,1]标准化设备坐标系(NDC)

物体/世界/照相机空间->右手系

规范化设备坐标:左手系。

x,y,z =>0,1,2

注意OpenGL中坐标系 OpenGL中的物体,世界,照相机坐标系都属于右手坐标系,而规范化设备坐标系(NDC)属于左手坐标系。笼统的说OpenGL使用右手坐标系是不合适的

OpenGL希望每次顶点着色后,我们的可见顶点都为标准化设备坐标系 (Normalized Device Coordinate, NDC)。也就是说每个顶点的x,y,z都应该在-1到1之间,超出这个范围的顶点将是不可见的。

通常情况下我们会自己设定一个坐标系范围,之后再在顶点着色器中将这些坐标系变换为标准化设备坐标,然后这些标准化设备坐标传入光栅器(Rasterizer),将他们变换为屏幕上的二维坐标和像素。

将坐标变换为标准化设备坐标,接着再转化为屏幕坐标的过程通常是分布进行的,也是类似于流水线那样。在流水线中,物体的顶点在最终转化为屏幕坐标之前还会被变换到多个坐标系系统(Coordinate System)。将物体的坐标变到几个过渡坐标系(Intermediate Coordinate System)的优点在于 在这些特定的坐标系统中,一些 *** 作或运算更加方便和容易,这一点很快就变得明显。对我们来说比较重要的总共有5个不同的坐标系统。

这是一个顶点在最终被转化为片段之前需要经历的所有不同的状态。为了将坐标从一个坐标系变换到另一个坐标系,我们需要用到几个变换矩阵,最重要的几个分别是 模型(Model)、观察(View)、投影(Projection)三个矩阵。

物体顶点的起始坐标在局部空间(Local Space),这里称为局部坐标(Local Coordinate),他在之后在变成世界坐标(World Coordinate),观察坐标(View Coordinate),裁剪坐标(Clip Coordinate),并最后转为屏幕坐标(Screen Coordinate)

的形式结束。

物体坐标系: 每个物体都有他独立的坐标系,当物理移动或者改变方向时。该物体相关联的坐标系将随之移动或改变方向。

物体坐标系是以物体本身而言,比如,我先向你发指令,”向前走一步“,是向你的物体坐标系发指令。我并不知道你会往哪个绝对的方向移动。比如说,当你开车的时候,有人会说向左转,有人会说向东。但是,向左转是物体坐标系的概念,而向东则是世界坐标系概念。

在某种情况下,我们可以理解物体坐标系为模型坐标系。因为模型顶点的坐标都是在模型坐标系中描述的。

照相机坐标系: 照相机坐标系是和观察者密切相关的坐标系。照相机坐标系和屏幕坐标系相似,差别在于照相机坐标系处于3D空间中,而屏幕坐标系在2D平面里。

为什么要引入惯性坐标系? 因为物体坐标系转换到惯性坐标系只需要旋转,从惯性坐标系转换到世界坐标系只需要平移。

OpenGL最终的渲染设备是2D的,我们需要将3D表示的场景转换为最终的2D形式,前面使用模型变换和视觉变换将物体坐标转到照相机坐标系后,需要进行投影变换,将坐标从照相机坐标系转换为裁剪坐标系,经过透视除法后,变换到规范化设备坐标系(NDC),最后进行视口变换后,3D坐标才变换到屏幕上的2D坐标,这个过程入下图:

在上面的图中, 注意,OpenGL只定义了裁剪坐标系、规范化设备坐标系、屏幕坐标系,而局部坐标系、世界坐标系、照相机坐标系都是为了方便用户设计而自定义的坐标系,他们的关系如下图:

OpenGL 然后对裁剪坐标执行透视除法从而将他们变换到标准化设备坐标。 OpenGL 会使用glViewPort内部的参数来将标准化设备坐标映射到屏幕坐标,每个坐标关联一个屏幕上的点。这个过程称为视口变换

局部坐标系(模型坐标系)是为了方便构造模型而设立的坐标系,建立模型时我们无需关心最终对象显示在屏幕那个位置。

模型变换的主要目的是通过变换使得用顶点属性定义或者3d建模软件构造的模型,能够按照需要,通过缩小、平移等 *** 作放置到场景中合适的位置, 通过模型变换后,物体放置在一个全局的世界坐标系中,世界坐标系是所有物体交互的一个公共坐标系

视变换是为了方便观察场景中物体而建立的坐标系,在这个坐标系中相机是个假设的概念,是为了便于计算而引入的。相机坐标系中的坐标,就是从相机的角度来解释世界坐标系中的位置

OpenGL中相机始终位于原点,指向 -Z轴,而以相反的方式来调整场景中物体,从而达到相同的观察效果。例如要观察-Z轴方向的一个立方体的右侧面,可以有两种方式:

GLShaderManager的初始化

GLShaderManager shaderManager

shaderManager.InitializeStockShaders()

OpenGL是个专业的图形程序接口,是一个功能强大,调用方便的底层图形库。是三维软件必备的一个系统插件。

如果你学过编程就会很容易明白。

而MAYA和3DMAX、C4D这些只是三维软件,只是制作图像的。

举个例子吧。

就拿英雄联盟来说吧。里面的火焰,闪电都是用MAYA制作的,但如果要在电脑上安装使用MAYA,你的电脑上必须安装openGL,某些大型游戏也必须要在opengl的环境下运行。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/bake/11551433.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-16
下一篇 2023-05-16

发表评论

登录后才能评论

评论列表(0条)

保存