Pixel Bender 3Dの勉強 その2 | Photoshop CC Tutorials
今回、まるで暗号のような「Pixel Bender 3D」のサンプルプログラムを読んでみましたが
ようやく基本的なプログラムを作成することができました。

今回のサンプルは三角形をただ回転させているだけですが
あとはカーネルを複雑なものに書き換えていけばAGAL以上のものができあがるはずです。

◆【できあがりはこちらをクリック】(要:FlashPlayer11、ビデオカード等GPU搭載PC)
$ピック社長のブログ

BulgeVertexProgram.pbvk

vertex kernel Bulge
<
namespace : "AIF Test";
vendor : "Adobe";
version : 1;
>
{
parameter float scale;
parameter float4x4 objectToClipSpaceTransform;

input vertex float4 vertexPosition
<
id : "PB3D_POSITION";
>;

output float4 vertexClipPosition;

void evaluateVertex()
{
vertexClipPosition = vertexPosition * objectToClipSpaceTransform;
}
}


phongShaderCylinderSphereTextured.pbmk

material kernel phong
<
namespace : "AIF Test";
vendor : "Adobe";
version : 1;
>
{
input vertex float4 vertexColor
<
id : "PB3D_COLOR";
>;

interpolated float4 color;

parameter float scalea;

output float4 result;

void evaluateVertex()
{
color = vertexColor;
}

void evaluateFragment()
{
result = color;
}
}


Main.as
package 
{
import com.adobe.pixelBender3D.AGALProgramPair;
import com.adobe.pixelBender3D.PBASMCompiler;
import com.adobe.pixelBender3D.PBASMProgram;
import com.adobe.pixelBender3D.RegisterMap;
import com.adobe.pixelBender3D.utils.VertexBufferHelper;
import com.adobe.pixelBender3D.utils.ProgramConstantsHelper;
import com.adobe.pixelBender3D.VertexRegisterInfo;

import com.adobe.utils.PerspectiveMatrix3D;
import flash.display.Sprite;
import flash.display.Stage3D;

import flash.display3D.Context3D;
import flash.display3D.Context3DCompareMode;
import flash.display3D.Context3DTriangleFace;
import flash.display3D.IndexBuffer3D;
import flash.display3D.Program3D;
import flash.display3D.VertexBuffer3D;
import flash.display3D.Context3DRenderMode;
import flash.display3D.Context3DProgramType;
import flash.display3D.Context3DBlendFactor;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.geom.Vector3D;
import flash.geom.Matrix3D;
import flash.utils.getTimer;
import flash.utils.Timer;

import ExampleUtils;

public class Main extends Sprite
{
[Embed (source="./vp_triangle.pbasm", mimeType="application/octet-stream")]
protected static const VertexPositionProgram : Class;

[Embed (source="./mv_triangle.pbasm", mimeType="application/octet-stream")]
protected static const VertexMaterialProgram : Class;

[Embed (source="./mf_triangle.pbasm", mimeType="application/octet-stream")]
protected static const FragmentMaterialProgram : Class;

public static const WIDTH:int = 400;
public static const HEIGHT:int = 400;

// molehill-related variables
private var context3D_ : Context3D;
private var indexBuffer_ : IndexBuffer3D;
private var rendertimer_ : Timer;
private var shaderProgram_ : Program3D;
private var vertexBuffer_ : VertexBuffer3D;

private var _stage3D:Stage3D;

// PB3D-related variables
private var vertexRegisterMap_ : RegisterMap;
private var fragmentRegisterMap_ : RegisterMap;
private var vertexBufferMap_ : VertexBufferHelper;
public var parameterBufferHelper_ : ProgramConstantsHelper;

private var _matProjection:PerspectiveMatrix3D;
private var _camera:Camera;

public function Main()
{
_stage3D = stage.stage3Ds[0];
_stage3D.addEventListener( Event.CONTEXT3D_CREATE, Context3DCreateHandler );
_stage3D.requestContext3D( Context3DRenderMode.AUTO );
}

private function Context3DCreateHandler(e:Event) : void
{
context3D_ = _stage3D.context3D;
init();
}

public function init():void
{
context3D_ = _stage3D.context3D;
context3D_.enableErrorChecking = true;
context3D_.configureBackBuffer( WIDTH, HEIGHT, 4, true );
context3D_.setCulling(Context3DTriangleFace.BACK);
context3D_.setBlendFactors(Context3DBlendFactor.SOURCE_ALPHA, Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA );
context3D_.setDepthTest(false, Context3DCompareMode.ALWAYS);

setupShadingPrograms();
setupGeometry();
InitCamera();
InitProjection();

vertexBufferMap_ = new VertexBufferHelper(context3D_,
vertexRegisterMap_.inputVertexRegisters,
vertexBuffer_
);

// at this point, our Triangle object has sufficient information to do
// its job when the render calls start coming in, so let's get them
// going

rendertimer_ = new Timer(1);
rendertimer_.addEventListener(TimerEvent.TIMER, frameEventHandler);
rendertimer_.start();
}

private function frameEventHandler(event : Event) : void
{
render(getTimer());
}

private var cnt:int = 0;
public function render(time : Number) : void
{
context3D_.clear(0, 0, 0, 0);

var mat:Matrix3D = new Matrix3D();
mat.appendRotation(cnt++, new Vector3D(0, 1, 0)); // ワールド座標変換
mat.append( _camera.matrix ); // ビュー座標変換
mat.append( _matProjection ); // プロジェクション座標変換

parameterBufferHelper_.setMatrixParameterByName(
Context3DProgramType.VERTEX,
"objectToClipSpaceTransform",
mat,
true
);

parameterBufferHelper_.update();

context3D_.setProgram(shaderProgram_);
vertexBufferMap_.setVertexBuffers();

context3D_.drawTriangles(indexBuffer_, 0, 1);
context3D_.present();
}

private function setupGeometry() : void
{
indexBuffer_ = context3D_.createIndexBuffer(3);
indexBuffer_.uploadFromVector(Vector.([0, 1, 2]), 0, 3);

vertexBuffer_ = context3D_.createVertexBuffer(3, 8); // 3 vertices, XYZW, RGBA

var size:Number = 0.5;
vertexBuffer_.uploadFromVector(Vector.([ -1 * size, -1 * size, 0 * size, 1, 1, 0, 0, 1,
0 * size, 1 * size, 0 * size, 1, 0, 1, 0, 1,
1 * size, -1 * size, 0 * size, 1, 0, 0, 1, 1]), 0, 3
);
}

private function setupShadingPrograms() : void
{
var vertexPositionProgram : PBASMProgram;
var vertexMaterialProgram : PBASMProgram;
var fragmentMaterialProgram : PBASMProgram;

vertexPositionProgram = ExampleUtils.resourceToPBASMProgram(VertexPositionProgram);
vertexMaterialProgram = ExampleUtils.resourceToPBASMProgram(VertexMaterialProgram);
fragmentMaterialProgram = ExampleUtils.resourceToPBASMProgram(FragmentMaterialProgram);

var translatedPrograms : AGALProgramPair;

translatedPrograms = PBASMCompiler.compile(vertexPositionProgram,
vertexMaterialProgram,
fragmentMaterialProgram);

// we'll need these in order to set variables without resorting to low
// level molehill calls. A later example will show PB3D use
// without use of RegisterMap objects.

vertexRegisterMap_ = translatedPrograms.vertexProgram.registers;
fragmentRegisterMap_ = translatedPrograms.fragmentProgram.registers;

// we've now translated everything to AGAL, the binary format that
// molehill accepts, so let's create a Molehill shader program and upload
// our binaries

parameterBufferHelper_ = new ProgramConstantsHelper( context3D_, vertexRegisterMap_, fragmentRegisterMap_ );

shaderProgram_ = context3D_.createProgram();
shaderProgram_.upload(translatedPrograms.vertexProgram.byteCode,
translatedPrograms.fragmentProgram.byteCode);
}

private function InitProjection() : void
{
_matProjection = new PerspectiveMatrix3D();
_matProjection.perspectiveFieldOfViewLH( 45 * Math.PI / 180, WIDTH / HEIGHT, 0.1, 3000 );
}

/**
* カメラの初期化を行う
*/
private function InitCamera() : void
{
_camera = new Camera();
// カメラ位置、注視点
_camera.InitView( new Vector3D(0, 0, -3), new Vector3D(0, 0, 0), new Vector3D(0, 1, 0) );
}

}

}

import flash.display.BitmapData;
import flash.display.Shape;
import flash.display3D.Context3D;
import flash.display3D.textures.Texture;
import flash.display3D.IndexBuffer3D;
import flash.display3D.VertexBuffer3D;
import flash.display3D.Context3DTextureFormat;
import flash.geom.Matrix;
import flash.geom.Matrix3D;
import flash.geom.Vector3D;

class Camera
{
private var _view:Matrix3D;
private var _from:Vector3D;
private var _at:Vector3D;
private var _up:Vector3D;

public function Camera()
{
_view = new Matrix3D();
}

/**
* ビュー行列の設定を行う
*/
public function InitView( from:Vector3D, at:Vector3D, up:Vector3D ) : void
{
var vz:Vector3D = at.subtract( from );
vz.normalize();
var vx:Vector3D = up.crossProduct( vz );
vx.normalize();
var vy:Vector3D = vz.crossProduct( vx );
vy.normalize();
var vtx:Number = vx.dotProduct( from ) * -1;
var vty:Number = vy.dotProduct( from ) * -1;
var vtz:Number = vz.dotProduct( from ) * -1;

_view.identity();
_view.rawData = Vector.([
vx.x, vy.x, vz.x, 0,
vx.y, vy.y, vz.y, 0,
vx.z, vy.z, vz.z, 0,
vtx, vty, vtz, 1,
]);

_from = from;
_at = at;
_up = up;
}

public function get matrix():Matrix3D
{
return _view;
}

public function get from() : Vector3D
{
return _from;
}

public function get at() : Vector3D
{
return _at;
}
}