本章用来作为Starling的滤镜实现原理的一个补充,但是为了了解原理,我们会使用原生API进行编码。

我们知道,当我们调用drawTriangles方法时,我们的图像是绘制到后台缓冲区的,只有调用present方法时才会把图像呈现到屏幕。

我们先来看看Context3D的两个方法:

  1. setRenderToTexture:我们默认的渲染都是在后台缓冲区进行的,使用该方法可以把渲染修改到一个纹理上,调用该方法后,Context3D对象的渲染操作(clear、drawTriangles等)都会渲染到指定的纹理上而不是后台缓冲区。
  2. setRenderToBackBuffer:配合setRenderToTexture的方法,可以将使用的缓冲区还原到后台缓冲区。

如果本章看不明白可以看这篇文章进行补充:stage3D 搭建2d图形引擎 (八) 动态纹理

先想一下我们的渲染过程:提交顶点数据和纹理,设定着色器和常量,最后调用drawTriangles配合索引缓冲进行绘制。

对于绘制到后台缓冲区的模型,我们就不能再次进行操作了,如果我们想要对一个模型进行多次不同的渲染就需要使用setRenderToTexture方法了。

先看看正常渲染的情况:

 package
{
import com.adobe.utils.AGALMiniAssembler; import flash.display.Bitmap;
import flash.display.Sprite;
import flash.display.Stage3D;
import flash.display3D.Context3D;
import flash.display3D.Context3DProfile;
import flash.display3D.Context3DProgramType;
import flash.display3D.Context3DRenderMode;
import flash.display3D.Context3DTextureFormat;
import flash.display3D.Context3DVertexBufferFormat;
import flash.display3D.IndexBuffer3D;
import flash.display3D.Program3D;
import flash.display3D.VertexBuffer3D;
import flash.display3D.textures.Texture;
import flash.events.ErrorEvent;
import flash.events.Event; [SWF(width=400, height=400, frameRate=60)]
public class FilterDemo extends Sprite
{
[Embed(source="img.png")]
private var IMG_CLASS:Class; private var _stage3D:Stage3D;
private var _context3D:Context3D;
private var _vertexBuffer:VertexBuffer3D;
private var _indexBuffer:IndexBuffer3D;
private var _texture:Texture;
private var _program3D:Program3D; //会被作为目标渲染的纹理
private var _filterTexture1:Texture;
private var _filterTexture2:Texture; public function FilterDemo()
{
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
} private function addedToStageHandler(event:Event):void
{
if(stage.stage3Ds.length > 0)
{
_stage3D = stage.stage3Ds[0];
_stage3D.addEventListener(ErrorEvent.ERROR, stage3DErrorHandler);
_stage3D.addEventListener(Event.CONTEXT3D_CREATE, context3DCreateHandler);
_stage3D.requestContext3D(Context3DRenderMode.AUTO, Context3DProfile.BASELINE);
}
} private function stage3DErrorHandler(event:ErrorEvent):void
{
trace("Context3D对象请求失败:", event.text);
} private function context3DCreateHandler(event:Event):void
{
initContext3D();
initBuffer();
initTexture();
normalRander();
// filterRander1();
// filterRander2();
// finallyRander();
} private function initContext3D():void
{
_context3D = _stage3D.context3D;
_context3D.configureBackBuffer(400, 400, 2);
} private function initBuffer():void
{
var vertexData:Vector.<Number> = Vector.<Number>(
[
-0.5, -0.5, 0, 0, 1,
0.5, -0.5, 0, 1, 1,
0.5, 0.5, 0, 1, 0,
-0.5, 0.5, 0, 0, 0
]); _vertexBuffer = _context3D.createVertexBuffer(vertexData.length / 5, 5);
_vertexBuffer.uploadFromVector(vertexData, 0, vertexData.length / 5); var indexData:Vector.<uint> = Vector.<uint>(
[
0, 3, 1,
1, 2, 3
]); _indexBuffer = _context3D.createIndexBuffer(indexData.length);
_indexBuffer.uploadFromVector(indexData, 0, indexData.length);
} private function initTexture():void
{
var bitmap:Bitmap = new IMG_CLASS() as Bitmap;
_texture = _context3D.createTexture(128, 128, Context3DTextureFormat.BGRA, true);
_texture.uploadFromBitmapData(bitmap.bitmapData, 0);
} /**
* 正常渲染.
*/
private function normalRander():void
{
var vertexArr:Array =
[
"mov op, va0",
"mov v0, va1"
]; var fragmentArr:Array =
[
"tex ft0, v0, fs0 <2d,repeat,linear,nomip>",
"mov oc, ft0"
]; var assembler:AGALMiniAssembler = new AGALMiniAssembler();
_program3D = assembler.assemble2(_context3D, 1, vertexArr.join("\n"), fragmentArr.join("\n")); _context3D.clear();
_context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
_context3D.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2);
_context3D.setTextureAt(0, _texture);
_context3D.setProgram(_program3D);
_context3D.drawTriangles(_indexBuffer);
_context3D.present();
} /**
* 使用灰色滤镜渲染到纹理.
*/
private function filterRander1():void
{
_filterTexture1 = _context3D.createTexture(128, 128, Context3DTextureFormat.BGRA, true); var vertexArr:Array =
[
"mov op, va0",
"mov v0, va1"
]; var fragmentArr:Array =
[
"tex ft0, v0, fs0 <2d,linear,clamp>",
"add ft1.x, ft0.x, ft0.y",
"add ft1.x, ft1.x, ft0.z",
"div ft1.x, ft1.x, fc0.w",
"mov ft0.xyz, ft1.xxx",
"mov oc ft0"
]; var assembler:AGALMiniAssembler = new AGALMiniAssembler();
_program3D = assembler.assemble2(_context3D, 1, vertexArr.join("\n"), fragmentArr.join("\n")); //设定渲染目标为我们的纹理
_context3D.setRenderToTexture(_filterTexture1);
_context3D.clear();
_context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
_context3D.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2);
//传递到灰色滤镜的设定值
_context3D.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, Vector.<Number>([0.299, 0.587, 0.114, 3]));
_context3D.setTextureAt(0, _texture);
_context3D.setProgram(_program3D);
_context3D.drawTriangles(_indexBuffer);
} /**
* 使用波浪滤镜再一次渲染到纹理.
*/
private function filterRander2():void
{
_filterTexture2 = _context3D.createTexture(128, 128, Context3DTextureFormat.BGRA, true); var vertexArr:Array =
[
"mov op, va0",
"mov v0, va1"
]; var fragmentArr:Array =
[
"tex ft0,v0,fs0<2d,clamp,linear>",
"sub ft0.x,v0.x,fc0.w",
"mul ft0.x,ft0.x,ft0.x",
"sub ft0.y,v0.y,fc0.w",
"mul ft0.y,ft0.y,ft0.y",
"add ft0.z,ft0.x,ft0.y",
"sqt ft0.z,ft0.z",
"mul ft0.z,ft0.z,fc0.x",
"sub ft0.z,ft0.z,fc0.z",
"sin ft0.z,ft0.z",
"mul ft0.z,ft0.z,fc0.y",
"add ft0,v0,ft0.zzz",
"tex oc,ft0,fs0<2d,clamp,linear>"
]; var assembler:AGALMiniAssembler = new AGALMiniAssembler();
_program3D = assembler.assemble2(_context3D, 1, vertexArr.join("\n"), fragmentArr.join("\n")); //设定渲染目标为我们的纹理
_context3D.setRenderToTexture(_filterTexture2);
_context3D.clear();
_context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
_context3D.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2);
//设置波浪的常量
_context3D.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, new <Number>[100, 0.01, 0, 0.5]);
_context3D.setTextureAt(0, _filterTexture1);
_context3D.setProgram(_program3D);
_context3D.drawTriangles(_indexBuffer); //还原后台缓冲区为渲染目标
_context3D.setRenderToBackBuffer();
} /**
* 把最终的结果渲染到舞台.
*/
private function finallyRander():void
{
var vertexArr:Array =
[
"mov op, va0",
"mov v0, va1"
]; var fragmentArr:Array =
[
"tex ft0, v0, fs0 <2d,repeat,linear,nomip>",
"mov oc, ft0"
]; var assembler:AGALMiniAssembler = new AGALMiniAssembler();
_program3D = assembler.assemble2(_context3D, 1, vertexArr.join("\n"), fragmentArr.join("\n")); _context3D.clear();
_context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
_context3D.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2);
_context3D.setTextureAt(0, _filterTexture2);
_context3D.setProgram(_program3D);
_context3D.drawTriangles(_indexBuffer);
_context3D.present();
}
}
}

下面是使用纹理渲染了2次滤镜的效果:

 package
{
import com.adobe.utils.AGALMiniAssembler; import flash.display.Bitmap;
import flash.display.Sprite;
import flash.display.Stage3D;
import flash.display3D.Context3D;
import flash.display3D.Context3DProfile;
import flash.display3D.Context3DProgramType;
import flash.display3D.Context3DRenderMode;
import flash.display3D.Context3DTextureFormat;
import flash.display3D.Context3DVertexBufferFormat;
import flash.display3D.IndexBuffer3D;
import flash.display3D.Program3D;
import flash.display3D.VertexBuffer3D;
import flash.display3D.textures.Texture;
import flash.events.ErrorEvent;
import flash.events.Event; [SWF(width=400, height=400, frameRate=60)]
public class FilterDemo extends Sprite
{
[Embed(source="img.png")]
private var IMG_CLASS:Class; private var _stage3D:Stage3D;
private var _context3D:Context3D;
private var _vertexBuffer:VertexBuffer3D;
private var _indexBuffer:IndexBuffer3D;
private var _texture:Texture;
private var _program3D:Program3D; //会被作为目标渲染的纹理
private var _filterTexture1:Texture;
private var _filterTexture2:Texture; public function FilterDemo()
{
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
} private function addedToStageHandler(event:Event):void
{
if(stage.stage3Ds.length > 0)
{
_stage3D = stage.stage3Ds[0];
_stage3D.addEventListener(ErrorEvent.ERROR, stage3DErrorHandler);
_stage3D.addEventListener(Event.CONTEXT3D_CREATE, context3DCreateHandler);
_stage3D.requestContext3D(Context3DRenderMode.AUTO, Context3DProfile.BASELINE);
}
} private function stage3DErrorHandler(event:ErrorEvent):void
{
trace("Context3D对象请求失败:", event.text);
} private function context3DCreateHandler(event:Event):void
{
initContext3D();
initBuffer();
initTexture();
// normalRander();
filterRander1();
filterRander2();
finallyRander();
} private function initContext3D():void
{
_context3D = _stage3D.context3D;
_context3D.configureBackBuffer(400, 400, 2);
} private function initBuffer():void
{
var vertexData:Vector.<Number> = Vector.<Number>(
[
-0.5, -0.5, 0, 0, 1,
0.5, -0.5, 0, 1, 1,
0.5, 0.5, 0, 1, 0,
-0.5, 0.5, 0, 0, 0
]); _vertexBuffer = _context3D.createVertexBuffer(vertexData.length / 5, 5);
_vertexBuffer.uploadFromVector(vertexData, 0, vertexData.length / 5); var indexData:Vector.<uint> = Vector.<uint>(
[
0, 3, 1,
1, 2, 3
]); _indexBuffer = _context3D.createIndexBuffer(indexData.length);
_indexBuffer.uploadFromVector(indexData, 0, indexData.length);
} private function initTexture():void
{
var bitmap:Bitmap = new IMG_CLASS() as Bitmap;
_texture = _context3D.createTexture(128, 128, Context3DTextureFormat.BGRA, true);
_texture.uploadFromBitmapData(bitmap.bitmapData, 0);
} /**
* 正常渲染.
*/
private function normalRander():void
{
var vertexArr:Array =
[
"mov op, va0",
"mov v0, va1"
]; var fragmentArr:Array =
[
"tex ft0, v0, fs0 <2d,repeat,linear,nomip>",
"mov oc, ft0"
]; var assembler:AGALMiniAssembler = new AGALMiniAssembler();
_program3D = assembler.assemble2(_context3D, 1, vertexArr.join("\n"), fragmentArr.join("\n")); _context3D.clear();
_context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
_context3D.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2);
_context3D.setTextureAt(0, _texture);
_context3D.setProgram(_program3D);
_context3D.drawTriangles(_indexBuffer);
_context3D.present();
} /**
* 使用灰色滤镜渲染到纹理.
*/
private function filterRander1():void
{
_filterTexture1 = _context3D.createTexture(128, 128, Context3DTextureFormat.BGRA, true); var vertexArr:Array =
[
"mov op, va0",
"mov v0, va1"
]; var fragmentArr:Array =
[
"tex ft0, v0, fs0 <2d,linear,clamp>",
"add ft1.x, ft0.x, ft0.y",
"add ft1.x, ft1.x, ft0.z",
"div ft1.x, ft1.x, fc0.w",
"mov ft0.xyz, ft1.xxx",
"mov oc ft0"
]; var assembler:AGALMiniAssembler = new AGALMiniAssembler();
_program3D = assembler.assemble2(_context3D, 1, vertexArr.join("\n"), fragmentArr.join("\n")); //设定渲染目标为我们的纹理
_context3D.setRenderToTexture(_filterTexture1);
_context3D.clear();
_context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
_context3D.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2);
//传递到灰色滤镜的设定值
_context3D.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, Vector.<Number>([0.299, 0.587, 0.114, 3]));
_context3D.setTextureAt(0, _texture);
_context3D.setProgram(_program3D);
_context3D.drawTriangles(_indexBuffer);
} /**
* 使用波浪滤镜再一次渲染到纹理.
*/
private function filterRander2():void
{
_filterTexture2 = _context3D.createTexture(128, 128, Context3DTextureFormat.BGRA, true); var vertexArr:Array =
[
"mov op, va0",
"mov v0, va1"
]; var fragmentArr:Array =
[
"tex ft0,v0,fs0<2d,clamp,linear>",
"sub ft0.x,v0.x,fc0.w",
"mul ft0.x,ft0.x,ft0.x",
"sub ft0.y,v0.y,fc0.w",
"mul ft0.y,ft0.y,ft0.y",
"add ft0.z,ft0.x,ft0.y",
"sqt ft0.z,ft0.z",
"mul ft0.z,ft0.z,fc0.x",
"sub ft0.z,ft0.z,fc0.z",
"sin ft0.z,ft0.z",
"mul ft0.z,ft0.z,fc0.y",
"add ft0,v0,ft0.zzz",
"tex oc,ft0,fs0<2d,clamp,linear>"
]; var assembler:AGALMiniAssembler = new AGALMiniAssembler();
_program3D = assembler.assemble2(_context3D, 1, vertexArr.join("\n"), fragmentArr.join("\n")); //设定渲染目标为我们的纹理
_context3D.setRenderToTexture(_filterTexture2);
_context3D.clear();
_context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
_context3D.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2);
//设置波浪的常量
_context3D.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, new <Number>[100, 0.01, 0, 0.5]);
_context3D.setTextureAt(0, _filterTexture1);
_context3D.setProgram(_program3D);
_context3D.drawTriangles(_indexBuffer); //还原后台缓冲区为渲染目标
_context3D.setRenderToBackBuffer();
} /**
* 把最终的结果渲染到舞台.
*/
private function finallyRander():void
{
var vertexArr:Array =
[
"mov op, va0",
"mov v0, va1"
]; var fragmentArr:Array =
[
"tex ft0, v0, fs0 <2d,repeat,linear,nomip>",
"mov oc, ft0"
]; var assembler:AGALMiniAssembler = new AGALMiniAssembler();
_program3D = assembler.assemble2(_context3D, 1, vertexArr.join("\n"), fragmentArr.join("\n")); _context3D.clear();
_context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
_context3D.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2);
_context3D.setTextureAt(0, _filterTexture2);
_context3D.setProgram(_program3D);
_context3D.drawTriangles(_indexBuffer);
_context3D.present();
}
}
}

我们发现最终的效果里我们的图像变小了很多,这是为啥呢?原因就是我们每次渲染时上传的顶点坐标是:

 var vertexData:Vector.<Number> = Vector.<Number>(
[
-0.5, -0.5, 0, 0, 1,
0.5, -0.5, 0, 1, 1,
0.5, 0.5, 0, 1, 0,
-0.5, 0.5, 0, 0, 0
]);

这样的结果是每次绘制图像都是占屏幕的一半,而我们经过3次渲染所以图像就变成了很小,要让图像不变的话,只有把顶点数据的0.5都改为1即可。

最终效果:

 package
{
import com.adobe.utils.AGALMiniAssembler; import flash.display.Bitmap;
import flash.display.Sprite;
import flash.display.Stage3D;
import flash.display3D.Context3D;
import flash.display3D.Context3DProfile;
import flash.display3D.Context3DProgramType;
import flash.display3D.Context3DRenderMode;
import flash.display3D.Context3DTextureFormat;
import flash.display3D.Context3DVertexBufferFormat;
import flash.display3D.IndexBuffer3D;
import flash.display3D.Program3D;
import flash.display3D.VertexBuffer3D;
import flash.display3D.textures.Texture;
import flash.events.ErrorEvent;
import flash.events.Event; [SWF(width=400, height=400, frameRate=60)]
public class FilterDemo extends Sprite
{
[Embed(source="img.png")]
private var IMG_CLASS:Class; private var _stage3D:Stage3D;
private var _context3D:Context3D;
private var _vertexBuffer:VertexBuffer3D;
private var _indexBuffer:IndexBuffer3D;
private var _texture:Texture;
private var _program3D:Program3D; //会被作为目标渲染的纹理
private var _filterTexture1:Texture;
private var _filterTexture2:Texture; public function FilterDemo()
{
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
} private function addedToStageHandler(event:Event):void
{
if(stage.stage3Ds.length > 0)
{
_stage3D = stage.stage3Ds[0];
_stage3D.addEventListener(ErrorEvent.ERROR, stage3DErrorHandler);
_stage3D.addEventListener(Event.CONTEXT3D_CREATE, context3DCreateHandler);
_stage3D.requestContext3D(Context3DRenderMode.AUTO, Context3DProfile.BASELINE);
}
} private function stage3DErrorHandler(event:ErrorEvent):void
{
trace("Context3D对象请求失败:", event.text);
} private function context3DCreateHandler(event:Event):void
{
initContext3D();
initBuffer();
initTexture();
// normalRander();
filterRander1();
filterRander2();
finallyRander();
} private function initContext3D():void
{
_context3D = _stage3D.context3D;
_context3D.configureBackBuffer(400, 400, 2);
} private function initBuffer():void
{
var vertexData:Vector.<Number> = Vector.<Number>(
[
-1, -1, 0, 0, 1,
1, -1, 0, 1, 1,
1, 1, 0, 1, 0,
-1, 1, 0, 0, 0
]); _vertexBuffer = _context3D.createVertexBuffer(vertexData.length / 5, 5);
_vertexBuffer.uploadFromVector(vertexData, 0, vertexData.length / 5); var indexData:Vector.<uint> = Vector.<uint>(
[
0, 3, 1,
1, 2, 3
]); _indexBuffer = _context3D.createIndexBuffer(indexData.length);
_indexBuffer.uploadFromVector(indexData, 0, indexData.length);
} private function initTexture():void
{
var bitmap:Bitmap = new IMG_CLASS() as Bitmap;
_texture = _context3D.createTexture(128, 128, Context3DTextureFormat.BGRA, true);
_texture.uploadFromBitmapData(bitmap.bitmapData, 0);
} /**
* 正常渲染.
*/
private function normalRander():void
{
var vertexArr:Array =
[
"mov op, va0",
"mov v0, va1"
]; var fragmentArr:Array =
[
"tex ft0, v0, fs0 <2d,repeat,linear,nomip>",
"mov oc, ft0"
]; var assembler:AGALMiniAssembler = new AGALMiniAssembler();
_program3D = assembler.assemble2(_context3D, 1, vertexArr.join("\n"), fragmentArr.join("\n")); _context3D.clear();
_context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
_context3D.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2);
_context3D.setTextureAt(0, _texture);
_context3D.setProgram(_program3D);
_context3D.drawTriangles(_indexBuffer);
_context3D.present();
} /**
* 使用灰色滤镜渲染到纹理.
*/
private function filterRander1():void
{
_filterTexture1 = _context3D.createTexture(128, 128, Context3DTextureFormat.BGRA, true); var vertexArr:Array =
[
"mov op, va0",
"mov v0, va1"
]; var fragmentArr:Array =
[
"tex ft0, v0, fs0 <2d,linear,clamp>",
"add ft1.x, ft0.x, ft0.y",
"add ft1.x, ft1.x, ft0.z",
"div ft1.x, ft1.x, fc0.w",
"mov ft0.xyz, ft1.xxx",
"mov oc ft0"
]; var assembler:AGALMiniAssembler = new AGALMiniAssembler();
_program3D = assembler.assemble2(_context3D, 1, vertexArr.join("\n"), fragmentArr.join("\n")); //设定渲染目标为我们的纹理
_context3D.setRenderToTexture(_filterTexture1);
_context3D.clear();
_context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
_context3D.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2);
//传递到灰色滤镜的设定值
_context3D.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, Vector.<Number>([0.299, 0.587, 0.114, 3]));
_context3D.setTextureAt(0, _texture);
_context3D.setProgram(_program3D);
_context3D.drawTriangles(_indexBuffer);
} /**
* 使用波浪滤镜再一次渲染到纹理.
*/
private function filterRander2():void
{
_filterTexture2 = _context3D.createTexture(128, 128, Context3DTextureFormat.BGRA, true); var vertexArr:Array =
[
"mov op, va0",
"mov v0, va1"
]; var fragmentArr:Array =
[
"tex ft0,v0,fs0<2d,clamp,linear>",
"sub ft0.x,v0.x,fc0.w",
"mul ft0.x,ft0.x,ft0.x",
"sub ft0.y,v0.y,fc0.w",
"mul ft0.y,ft0.y,ft0.y",
"add ft0.z,ft0.x,ft0.y",
"sqt ft0.z,ft0.z",
"mul ft0.z,ft0.z,fc0.x",
"sub ft0.z,ft0.z,fc0.z",
"sin ft0.z,ft0.z",
"mul ft0.z,ft0.z,fc0.y",
"add ft0,v0,ft0.zzz",
"tex oc,ft0,fs0<2d,clamp,linear>"
]; var assembler:AGALMiniAssembler = new AGALMiniAssembler();
_program3D = assembler.assemble2(_context3D, 1, vertexArr.join("\n"), fragmentArr.join("\n")); //设定渲染目标为我们的纹理
_context3D.setRenderToTexture(_filterTexture2);
_context3D.clear();
_context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
_context3D.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2);
//设置波浪的常量
_context3D.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, new <Number>[100, 0.01, 0, 0.5]);
_context3D.setTextureAt(0, _filterTexture1);
_context3D.setProgram(_program3D);
_context3D.drawTriangles(_indexBuffer); //还原后台缓冲区为渲染目标
_context3D.setRenderToBackBuffer();
} /**
* 把最终的结果渲染到舞台.
*/
private function finallyRander():void
{
var vertexArr:Array =
[
"mov op, va0",
"mov v0, va1"
]; var fragmentArr:Array =
[
"tex ft0, v0, fs0 <2d,repeat,linear,nomip>",
"mov oc, ft0"
]; var assembler:AGALMiniAssembler = new AGALMiniAssembler();
_program3D = assembler.assemble2(_context3D, 1, vertexArr.join("\n"), fragmentArr.join("\n")); _context3D.clear();
_context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
_context3D.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2);
_context3D.setTextureAt(0, _filterTexture2);
_context3D.setProgram(_program3D);
_context3D.drawTriangles(_indexBuffer);
_context3D.present();
}
}
}

Stage3D学习笔记(七):动态纹理的更多相关文章

  1. Stage3D学习笔记(五):通过矩阵操作纹理

    虽然我们上一节已经实现了正交矩阵的显示,但是可以明显的感觉到要调整显示纹理的坐标和尺寸是相当复杂的,需要对每个顶点进行操作,如果还要加上注册点和旋转的话,用上一节的方法来做是会让人发疯的! 所以我们距 ...

  2. 【Stage3D学习笔记续】山寨Starling(八):核心优化(批处理)的实现

    批处理是使GPU进行高效绘制的一种技术手段,也是整个渲染流程中最核心的技术,到目前为止我们并没有使用到这种技术手段,下面我们看看我们现在的渲染机制. 先想一想我们最开始是怎么向GPU绘制一幅图像的,可 ...

  3. 【opencv学习笔记七】访问图像中的像素与图像亮度对比度调整

    今天我们来看一下如何访问图像的像素,以及如何改变图像的亮度与对比度. 在之前我们先来看一下图像矩阵数据的排列方式.我们以一个简单的矩阵来说明: 对单通道图像排列如下: 对于双通道图像排列如下: 那么对 ...

  4. go微服务框架kratos学习笔记七(kratos warden 负载均衡 balancer)

    目录 go微服务框架kratos学习笔记七(kratos warden 负载均衡 balancer) demo demo server demo client 池 dao service p2c ro ...

  5. (转)Qt Model/View 学习笔记 (七)——Delegate类

    Qt Model/View 学习笔记 (七) Delegate  类 概念 与MVC模式不同,model/view结构没有用于与用户交互的完全独立的组件.一般来讲, view负责把数据展示 给用户,也 ...

  6. Web Service学习笔记:动态调用WebService

    原文:Web Service学习笔记:动态调用WebService 多数时候我们通过 "添加 Web 引用..." 创建客户端代理类的方式调用WebService,但在某些情况下我 ...

  7. Learning ROS for Robotics Programming Second Edition学习笔记(七) indigo PCL xtion pro live

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS forRobotics Pro ...

  8. Typescript 学习笔记七:泛型

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  9. python3.4学习笔记(七) 学习网站博客推荐

    python3.4学习笔记(七) 学习网站博客推荐 深入 Python 3http://sebug.net/paper/books/dive-into-python3/<深入 Python 3& ...

  10. Go语言学习笔记七: 函数

    Go语言学习笔记七: 函数 Go语言有函数还有方法,神奇不.这有点像python了. 函数定义 func function_name( [parameter list] ) [return_types ...

随机推荐

  1. Android开发之IP拨号器原理

    IP拨号器,使用了Android的广播接收者(BroadCastReceiver),在广播中把已保存的ip号码放在拨打电话号码的前面(getResultData()),然后把修改后的号码设置到广播中( ...

  2. 实用的eclipse adt 快捷键

    Ctrl + Shift + T: 打开类型:显示"打开类型"对话框来在编辑器中打开类型."打开类型"选择对话框显示工作空间中存在的所有类型如类.接口等.    ...

  3. MarkupExtension的使用

    记得第一次看到MarkupExtension是在几年前的一次面试中.很不好意思说,当时不知道是什么东东.最近在项目中又用到了WPF的这个功能,决定在博客里记录一下. 在Xaml中为某个对象以Attri ...

  4. jquery UI Draggable和Droppable 案例

    <html> <head><title>draggable</title> <script type="text/javascript& ...

  5. 完全用xml实现imageview点击换一张图片

    <ImageView android:layout_width="60dp" android:layout_height="60dp" android:b ...

  6. apache开源项目--Shiro

    安全是企业应用中不可缺少的功能,在众多权限框架中,Shiro(其前身是JSecurity)因其简单而又不失强大的特点引起了不少开发者的注 意.随着Grails的关注度越来越高,在Grails社区也出现 ...

  7. Windows 之间用rsync同步数据(cwRsyncServer配置)

    rsync是一款优秀的数据同步软件,在跨服务器,跨机房,跨国备份服务器的首选工具,下面就来介绍下如何配置安装cwRsyncServer很大多数软件一样是B/C架构,cwRsyncServer是rsyn ...

  8. SSH信任

    配置SSH的目的就是使得两个节点的主机之间的相同用户可以无障碍的通信,SSH主要包括两条命令,即scp和ssh.当用户在一个节点上安装和配置RAC软件时,SSH将通过scp命令,以对等用户的身份,将软 ...

  9. JavaEE基本了解

    1.  为什么需要JavaEE 我们编写的JSP代码中,由于大量的显示代码和业务逻辑混淆在一起,彼此嵌套,不利于程序的维护和扩展.当业务需求发生变化的时候,对于程序员和美工都是一个很重的负担. 为了程 ...

  10. Fine Uploader文件上传组件

    最近在处理后台数据时需要实现文件上传.考虑到对浏览器适配上采用Fine Uploader. Fine Uploader 采用ajax方式实现对文件上传.同时在浏览器中直接支持文件拖拽[对浏览器版本有要 ...