免费dede企业网站模板,做网站怎么投放广告,随州网站建设有限公司,wordpress文章权限一#xff1a;图像成像过程 ①、将需要显示的图像#xff0c;由CPU和GPU通过总线连接起来#xff0c;在CPU中输出的位图经总线在合适的时机上传给GPU #xff0c;GPU拿到位图做相应位图的图层渲染、纹理合成。 ②、将渲染后的结果#xff0c;存储到帧缓存区#xff0c;帧…一图像成像过程 ①、将需要显示的图像由CPU和GPU通过总线连接起来在CPU中输出的位图经总线在合适的时机上传给GPU GPU拿到位图做相应位图的图层渲染、纹理合成。 ②、将渲染后的结果存储到帧缓存区帧缓存区中存储的格式是位图。 ③、由视屏控制器根据Vsync垂直同步信号在指定时间之前去提取对应帧缓冲区当中的屏幕内容交由显示器从左上角逐行扫描进行显示。 如图所示: 二图片纹理映射 我们在获取到图片的纹理数据后要将纹理显示到屏幕上先要做两件事 ①、将图片的纹理坐标通过 attribute方式经顶点着色器桥接给片元着色器 ②、将图片纹理数据通过Uniform传递给片元着色器由片元着色器进行图片颜色的填充 在图片进行纹理颜色填充时需要按照坐标进行一一对应纹理坐标默认左下角为00右上角为01。 纹理的坐标与图形的坐标一一对应最终会将图片正确的显示出来。如果纹理坐标映射的不正确则可能出现图片翻转、倒置等情况甚至图片信息错乱。 三图片解压
在解释图片解压之前我们先了解几个概念
①、位图 又叫像素图或栅格图它记录了图片每一个像素的颜色、深度、透明度等信息。这一系列像素按照一定的规则排列起来就形成了我们看到的图片。位图的优点是能够完整记录图片信息无论图片怎样拉伸都不会失真缺点是图片文件太大因此一般将位图压缩为jpg、png等格式。 ②、有损压缩 不会完全真实的记录图片信息会根据人眼观察世界的特性忽略掉部分会被人眼忽略的颜色信息代之以邻近的颜色。因此图片虽然大部分可以还原但某些情况下还是会失真常见的有损压缩格式有JPG等。 ③、无损压缩 无损压缩会完整记录图片颜色信息但是相同颜色的区域会被压缩记录因此无损压缩也可以比较完整的还原图片。不过由于能够保存的颜色值有限所以依然有可能会出现失真常见的格式有PNG等。 ④、解压流程 在我们的开发过程中我们使用比较多的都是 JPG 或者 PNG 等格式图片但是在图片真正显示之前都会被先解压成位图再重新渲染到屏幕上。所以图片解压的流程是 1、解压JPG/PNG图片获取图片信息 2、根据获取到的图片信息重新绘制位图即纹理数据 3、将纹理数据载入传入到片元着色器经过渲染后显示 ⑤、解压方法Core Graphic
UImage *image [UImage imageNamed:fly];
CGImageRef cgImageRef [image CGImage]; // 将UImage转换为CGImageRef// 获取图片宽高
GLuint width (GLuint)CGImageGetWidth(cgImageRef);
GLuint height (GLuint)CGImageGetHeight(cgImageRef);//获取图片的rect
CGRect rect CGRectMake(0, 0, width, height);//获取图片的颜色空间
CGColorSpaceRef colorSpace CGColorSpaceCreateDeviceRGB();// 为图片开辟一片内存区域
// 一个像素点的颜色值包含 RGBA 各8位共4个字节
void *imageData malloc(width * height * 4);// 创建上下文
/**
CGBitmapContextCreate(void * __nullable data,size_t width, size_t height, size_t bitsPerComponent, size_t bytesPerRow,CGColorSpaceRef cg_nullable space, uint32_t bitmapInfo)data如果不为 NULL 那么它应该指向一块大小至少为 bytesPerRow * height 字节的内存如果 为 NULL 那么系统就会为我们自动分配和释放所需的内存所以一般指定 NULL 即可
width: 图片宽度
height图片高度
bitsPerComponent每个颜色分量所占bit数此处传8位
bytesPerRow位图的每一行使用的字节数大小至少为 width * bytes per pixel 字节。当我们指定 0/NULL 时系统不仅会为我们自动计算而且还会进行cache line alignment 的优化
space颜色空间
bitmapInfo位图的信息此处采用RGBA即kCGImageAlphaPremultipliedLast
*/
CGContextRef context CGBitmapContextCreate(imageData, width, height, 8, width * 4, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);// 将图片翻转过来(图片默认是倒置的)
// 图片的坐标系左上角为(0,0)纹理坐标左下角为(0,0)因此需要翻转
CGContextTranslateCTM(context, 0, height);
CGContextScaleCTM(context, 1.0f, -1.0f);// 绘制前先清除颜色空间和绘图区域防止残留数据
CGColorSpaceRelease(colorSpace);
CGContextClearRect(context, rect);// 对图片进行重新绘制得到一张新的解压缩后的位图
CGContextDrawImage(context, rect, cgImageRef);// 设置图片纹理属性
// 获取纹理ID
GLuint textureID;
glGenTextures(1, textureID); // 获取一个纹理句柄
glBindTexture(GL_TEXTURE_2D, textureID); // 将句柄绑定到纹理目标上GL_TEXTURE_2D等// 设置纹理属性
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);// 结束后是否数据
glBindTexture(GL_TEXTURE_2D, 0); // 将纹理目标重新绑定为0CGContextRelease(context); // 释放context
free(imageData); // 释放图片数据区域
⑥、总结 1、图片文件只有在确认要显示时,CPU才会对齐进行解压缩.因为解压是非常消耗性能的事情.解压过的图片就不会重复解压,会缓存起来. 2、图片渲染到屏幕的过程: 读取文件-计算Frame-图片解码-解码后纹理图片位图数据通过数据总线交给GPU-GPU获取图片Frame-顶点变换计算-光栅化-根据纹理坐标获取每个像素点的颜色值(如果出现透明值需要将每个像素点的颜色*透明度值)-渲染到帧缓存区-渲染到屏幕 四、图片渲染流程 1、App通过CoreGraphics、CoreAnimation、CoreImage等框架的接口调用来触发图形渲染操作 2、CoreGraphics、CoreAnimation、CoreImage等框架将渲染交由OpenGL ES由OpenGL ES来驱动GPU做渲染最后显示到屏幕上 3、由于OpenGL ES 是跨平台的所以在他的实现中没有任何窗口相关的代码而是让各自的平台为OpenGL ES提供载体。在iOS中如果需要使用OpenGL ES就是通过CoreAnimation提供窗口让App可以去调用。 五、屏幕卡顿 屏幕卡顿是指图形图像的在显示时出现了撕裂即图片错位显示、掉帧重复显示同一帧数据等问题导致用户能直观的从屏幕上看到的一种异常现象。 ①、屏幕卡顿原因 1、由图像的显示原理我们知道一帧的显示是由CPU和GPU共同决定的。一般来说页面滑动流畅是60fps也就是1s有60帧更新即每隔16.7ms就要产生一帧画面而如果CPU和GPU加起来的处理时间超过了16.7ms从缓存区获取位图显示时下一帧数据还没准备好获取的仍是上一帧的数据产生掉帧现象掉帧就会导致屏幕卡顿。 2、苹果官方为解决屏幕撕裂问题目前使用的方案是垂直同步双缓存区可以从根本上防止和解决屏幕撕裂但是同时也导致了新的问题掉帧。虽然我们采用了双缓存区但是我们并不能解决CPU和GPU处理图形图像的速度问题导致屏幕在接收到垂直信号时数据尚未准备好缓存区仍是上一帧的数据因此导致掉帧如图5-1-2所示。 3、在垂直同步双缓存区方案的基础上提出将双缓存区改为三缓存区的优化但是这样并不能从根本解决掉帧问题只是比双缓存区掉帧的概率小很多用户可能无感知。 图5-1-2
②、垂直同步与双缓存区 1、VSync垂直同步信号是指给帧缓冲加锁当电子光束扫描的过程中只有扫描完成了才会读取下一帧的数据而不是只读取一部分 2、双缓存区采用两个帧缓冲区用来存储GPU处理的结果当屏幕显示其中一个缓存区内容时另一个缓冲区继续等待下一个缓冲结果两个缓冲区依次进行交替