忍者ブログ

Memeplexes

プログラミング、3DCGとその他いろいろについて

かんたんXNA その25 ブレンド関数

このページは古いです
最新版はこちら

物を半透明にするアルファ・ブレンディングですが、
ブレンド関数を使うことによってもっと別のことも出来ます。

アルファ・ブレンディングとはもう少し一般的にいうと、
色を混ぜる(ブレンドする)ということです。
ある混ぜ方をすると物が半透明になりますが、
別の混ぜ方をすれば別の効果が得られます。

前回では2つの色は常に足されましたが、(変わったのは係数だけ)
これは逆に引いたり、あるいは最大値をとったり、
最小値をとったりするようにも変更できます。
(そのため、アルファは単なる不透明度ではない場合だってたくさんあり、
むしろそれがほとんどなのです。)


このような、混ぜ方の関数を設定するのが
RenderState.BlendFunctionプロパティです。


public BlendFunction BlendFunction { get; set; }

これはMicrosoft.Xna.Framework.Graphics.BlendFunction列挙体を
セットまたはゲットします。

BlendFunction列挙体
メンバ名 説明
Add "最終的な色" = ("これから描画するポリゴンの色" × SourceBlend) + ("描画する前の色" × DestinationBlend)
Max "最終的な色" = max( ("これから描画するポリゴンの色" × SourceBlend), ("描画する前の色" × DestinationBlend) )
Min "最終的な色" = min( ("これから描画するポリゴンの色" × SourceBlend), ("描画する前の色" × DestinationBlend) )
ReverseSubtract "最終的な色" = ("描画する前の色" × DestinationBlend) - ("これから描画するポリゴンの色" × SourceBlend)
Subtract "最終的な色" = ("これから描画するポリゴンの色" × SourceBlend) - ("描画する前の色" × DestinationBlend)
SourceBlendとDestinationBlendというのは
前回のRenderState.SourceBlendプロパティとRenderState.DestinationBlendプロパティで
セットした値(により計算された値)です。
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;


class Triangle
{
    VertexPositionColor[] vertices = new VertexPositionColor[3];

    public Triangle(Vector3 p1, Vector3 p2, Vector3 p3, Color color)
    {
        vertices[0] = new VertexPositionColor(p1, color);
        vertices[1] = new VertexPositionColor(p2, color);
        vertices[2] = new VertexPositionColor(p3, color);
    }

    public void Draw(GraphicsDevice graphicsDevice, BasicEffect effect)
    {
        graphicsDevice.VertexDeclaration = new VertexDeclaration(
            graphicsDevice,
            VertexPositionColor.VertexElements);
        effect.VertexColorEnabled = true;

        effect.Begin();

        foreach (EffectPass pass in effect.CurrentTechnique.Passes)
        {
            pass.Begin();

            graphicsDevice.DrawUserPrimitives<VertexPositionColor>(
                PrimitiveType.TriangleList,
                vertices,
                0,
                1
                );

            pass.End();
        }

        effect.End();
    }
}

class MyGame : Game
{
    GraphicsDeviceManager graphics;
    BasicEffect basicEffect;

    Triangle redTriangle = new Triangle(
        new Vector3(1, 0.5f, -1),
        new Vector3(0, -1, -1),
        new Vector3(-1, 0.5f, -1),
        Color.Red
        );

    public MyGame()
    {
        graphics = new GraphicsDeviceManager(this);
    }

    protected override void LoadGraphicsContent(bool loadAllContent)
    {
        if (loadAllContent)
        {
            basicEffect = new BasicEffect(graphics.GraphicsDevice, null);
            basicEffect.View = Matrix.CreateLookAt(
                new Vector3(0, 0, 3),
                new Vector3(0, 0, 0),
                new Vector3(0, 1, 0)
                );
            basicEffect.Projection = Matrix.CreatePerspectiveFieldOfView(
                MathHelper.ToRadians(45),
                Window.ClientBounds.Width / (float)Window.ClientBounds.Height,
                1, 100
                );
        }
    }

    protected override void Draw(GameTime gameTime)
    {
        graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

        graphics.GraphicsDevice.RenderState.AlphaBlendEnable = true;
        graphics.GraphicsDevice.RenderState.DestinationBlend = Blend.One;
        graphics.GraphicsDevice.RenderState.BlendFunction = BlendFunction.ReverseSubtract;
        redTriangle.Draw(graphics.GraphicsDevice, basicEffect);
    }
}


blendFunctionReverseSubtract.JPG
さて、赤い三角形を描画したはずなのに青っぽくなっています。
どういうことでしょう?

これは、背景の色から赤い成分が引かれたのです。

"最終的な色(0, 149, 237)" = (コーンフラワーブルー(100, 149, 237) × 1) - (赤(255, 0, 0) × 1)

デフォルトでは成分は足されるのですが、ここでは引かれています。
このように、RenderState.BlendFunctionを使うと
アルファ・ブレンディングの詳しい混ぜ方を設定することが出来るのです。

拍手[0回]

PR