http://blog.sina.com.cn/s/blog_7011f21c0101afz4.html
if ([_session canAddOutput:_videoOutput]) {
}
dispatch_queue_t videoCaptureQueue = dispatch_queue_create("video_capture_queue_",DISPATCH_QUEUE_SERIAL);
[_videoOutput setSampleBufferDelegate:self queue:videoCaptureQueue];
[_session startRunning];
在session start之后我们就可以通过回调 来得到
- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
}
拿到sbuf之后 我们就可以通过以下的方法来获取图片的首地址
CVPixelBufferRef
CVPixelBufferLockBaseAdd
int len = CVPixelBufferGetDataSize
UInt8 *pixel = (UInt8 *)CVPixelBufferGetBaseAddr
_render(pixel,len) //滤镜函数
这样其实就可以简单的实现照相时候的实时滤镜,当然作为高性能的标题,肯定实现不会这么简单,大家可以尝试一下这个方法的效果,我之前尝试的时候原本60帧左右的摄像,对rgb某个单通道操作影响不大,但是一旦操作到三个通道,降帧就很明显,更不用说在摄像时同时还要录音了。这时我们要解决这个问题就需要我们下一节来认识着色器。
认识着色器
attribute vec4 position;
attribute vec4 inputTextureCoordinate;
varying vec2 textureCoordinate;
precision mediump float;
uniform float overTurn;
void main()
{
gl_Position = position;
}
attribute 外部传入vsh文件的变量 每帧的渲染的可变参数 变化率高 用于定义每个点
varying 用于 vsh和fsh之间相互传递的参数
precision mediump float 定义中等精度的浮点数
uniform 外部传入vsh文件的变量 变化率较低 对于可能在整个渲染过程没有改变 只是个常量
在main()当overTurn大于0的时候 函数里面做的事情就是将纹理y轴反转
.fsh 是片段shader 在这里面我可以对于每一个像素点进行重新计算 从而达到我们滤镜效果
varying highp vec2 textureCoordinate;
precision mediump float;
uniform sampler2D videoFrame;
vec4 memoryRender(vec4 color)
{
}
void main()
{
}
varying
uniform
texture2D(videoFrame, textureCoordinate) 将纹理中的每个像素点颜色取出到pixelColor
我们可以用memoryRender(pixelColor)将我们取到像素点重新加工
总结:
对于着色器的编程并不是很困难,完全是C的语法 但是debug比较麻烦,对于类型的约束也很严格 必须是相同类型的才能进行算术运算。我们理解了这两个文件之后 就可以发挥我们的想象对纹理图片做出各种的处理。 了解如何编写着色器之后 我们就要在下篇开始 了解如何把AVFoundation中取到的图片帧来与我们的着色器结合,从来绘制出高性能的滤镜。