LoginSignup
0
0

More than 5 years have passed since last update.

Alternativa3DでAGALの適用とアルファブレンド

Last updated at Posted at 2013-10-30

Alternativa3D(AlternativaPlatform)にて

  • テクスチャマテリアルに独自のAGALを適用
  • アルファ値を反映

...する解説です。

共通

Materialクラスを継承して fillResources()collectDraws() をoverrideします。

  • fillResources() で必要なGPUリソースをアップロードします。
  • collectDraws() で描画の準備と予約をする様です。

AGALの適用

camera:Camera3D から DrawUnit を生成し、vertexBuffer, indexBuffer, texture, shaderを準備します。

サンプルでは

  • vertexShader
    • 頂点にprojectionMatrixを反映
    • uvをfragmentShaderへ渡す
  • fragmentShader
    • 輝度を計算してRGBへ格納
    • アルファ値は指定の値を格納

としています。

アルファ値の反映

fragmentShaderで oc.w(oc.a) にアルファ値を代入しても反映されません。
Context3D#setBlendFactors で反映させる旨を指定する必要があります。
- Context3DBlendFactor - help.adobe.com
- Context3D#setBlendFactors - help.adobe.com

Alternativa3Dでは先のDrawUnitblendSourceblendDestinationに指定することで適用できます。

サンプル

LuminanceAndAlphaTextureMaterial.as - github にもあります。

LuminanceAndAlphaTextureMaterial.as
package 
{
    import alternativa.engine3d.alternativa3d;
    import alternativa.engine3d.core.Camera3D;
    import alternativa.engine3d.core.DrawUnit;
    import alternativa.engine3d.core.Light3D;
    import alternativa.engine3d.core.Object3D;
    import alternativa.engine3d.core.Renderer;
    import alternativa.engine3d.core.VertexAttributes;
    import alternativa.engine3d.materials.Material;
    import alternativa.engine3d.materials.ShaderProgram;
    import alternativa.engine3d.objects.Surface;
    import alternativa.engine3d.resources.Geometry;
    import alternativa.engine3d.resources.TextureResource;
    import com.adobe.utils.AGALMiniAssembler;
    import flash.display3D.Context3D;
    import flash.display3D.Context3DBlendFactor;
    import flash.display3D.Context3DProgramType;
    import flash.display3D.VertexBuffer3D;
    import flash.utils.Dictionary;

    use namespace alternativa3d;
    /**
     * ...
     * @author Toshiyuki Suzumura / @suzumura_ss
     */
    public class LuminanceAndAlphaTextureMaterial extends Material
    {
        private var _texture:TextureResource;
        private var _alpha:Number;
        private var _context3d:Context3D;
        private var _program:ShaderProgram = new ShaderProgram(null, null);
        private var _vertexShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler();
        private var _fragmentShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler();

        public function LuminanceAndAlphaTextureMaterial(texture:TextureResource, alpha:Number, context3d:Context3D)
        {
            _texture = texture;
            _alpha = alpha;
            _context3d = context3d;

            _vertexShaderAssembler.assemble(Context3DProgramType.VERTEX, [
                // op = va0[pos] * vc0[projection]
                "m44 op, va0, vc0",
                // v0 = va1[uv]
                "mov v0, va1",
            ].join("\n"));

            _fragmentShaderAssembler.assemble(Context3DProgramType.FRAGMENT, [
                // ft0 = sampler2d(fs0, v0[uv])
                "tex ft0, v0, fs0 <2d,linear,repeat>",
                // lum = 0.299r
                "mul ft0.x, ft0.x, fc0.x",
                // lum += 0.587g
                "mul ft0.y, ft0.y, fc0.y",
                "add ft0.x, ft0.x, ft0.y",
                // lum += 0.114b
                "mul ft0.z, ft0.z, fc0.z",
                "add ft0.x, ft0.x, ft0.z",
                // g = lum, b = lum
                "mov ft0.y, ft0.x",
                "mov ft0.z, ft0.x",
                // a = <_alpha>
                "mov ft0.w, fc0.w",
                "mov oc, ft0",
            ].join("\n"));
        }

        override alternativa3d function fillResources(resources:Dictionary, resourceType:Class):void
        {
            super.fillResources(resources, resourceType);

            if (_texture != null) {
                resources[_texture] = true;
            }
            _program.program = _context3d.createProgram();
            _program.program.upload(_vertexShaderAssembler.agalcode, _fragmentShaderAssembler.agalcode);
        }

        override alternativa3d function collectDraws(camera:Camera3D, surface:Surface, geometry:Geometry, lights:Vector.<Light3D>, lightsLength:int, useShadow:Boolean, objectRenderPriority:int = -1):void
        {
            var object:Object3D = surface.object;
            var posBuffer:VertexBuffer3D = geometry.getVertexBuffer(VertexAttributes.POSITION);
            var uvBuffer:VertexBuffer3D = geometry.getVertexBuffer(VertexAttributes.TEXCOORDS[0]);
            var drawUnit:DrawUnit = camera.renderer.createDrawUnit(object, _program.program, geometry._indexBuffer, surface.indexBegin, surface.numTriangles, _program);

            drawUnit.setProjectionConstants(camera, 0, object.localToCameraTransform);  // = vc0
            drawUnit.setVertexBufferAt(0, posBuffer, 0, "float3");                      // = va0
            drawUnit.setVertexBufferAt(1, uvBuffer,  3, "float2");                      // = va1
            drawUnit.setFragmentConstantsFromNumbers(0, 0.299, 0.587, 0.114, _alpha);   // = fc0
            drawUnit.setTextureAt(0, _texture._texture);                                // = fs0

            drawUnit.blendSource = Context3DBlendFactor.SOURCE_ALPHA;
            drawUnit.blendDestination = Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA;

            camera.renderer.addDrawUnit(drawUnit, (objectRenderPriority >= 0)? objectRenderPriority: Renderer.OPAQUE);
        }
    }
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0