Direct3D rendering 2D images with “multiply” blending mode and alpha

后端 未结 4 2012
暖寄归人
暖寄归人 2021-01-03 04:31

I\'m trying to replicate the Photoshop filter multiply with Direct3D. I\'ve been reading and googling about the different render states and I\'ve got the effect almost worki

4条回答
  •  一整个雨季
    2021-01-03 05:33

    OK this is not as simple as you would think. I would use an Effect & two renderTargets for this... I'm amusing your using one render pass to try to do this, which will not work. Photoshop has layers & each layers have an alpha channel. BTW it would be nice to know what kind of app your making.

    So first in D3D I would create 2 RGBA_32bit renderTargets of the same size as your window & clear them to color white. Make it an array like so (new RenderTarget[2];) for swapping.

    Now set the blending state to (AlphaFunc=Add, Src=SrcAlpha, Dst=InvSrcAlpha). For the first circle you draw it into renderTarget[0] using renderTarget[1] as a texture/sampler input source. You will render the circle with an Effect that will take the circles color & multiply it with renderTarget[1]'s sampler color. After you draw circle one you swap the renderTarget[0] with renderTarget[1] by simple indexing, so now renderTarget[1] is the one you draw to & renderTarget[0] is the one you sample from. Then you repeat the drawing process for circle 2 & so on.

    After you draw ever circle you copy the last drawn renderTarget to the backBuffer & present the scene.

    Here is an example of logically how you would do it. If you need reference for coding http://www.codesampler.com/ is a good place.

    void TestLayering()
    {
    bool rtIndex = false;
    RenderTarget* renderTarget = new RenderTarget[2];
    Effect effect = new Effect("multiplyEffect.fx");
    effect.Enable();
    BlendingFunc = Add;
    BlendingSource = SrcAlpha;
    BlendingDest = InvSrcAlpha;
    
    for(int i = 0; i != circleCount; ++i)
    {
      renderTarget[rtIndex].EnableAsRenderTarget();
      renderTarget[!rtIndex].EnableAsSampler();
      circle[i].Draw();
      rtIndex = !rtIndex;
    }
    
    //Use D3D9's StretchRect for this...
    backBuffer.CopyFromSurface(renderTarget[rtIndex]);
    }
    
    //Here is the effects pixel shader
    float4 PS_Main(InStruct In) : COLOR
    {
    float4 backGround = tex2D(someSampler, In.UV);
    return circleColor * backGround;
    }
    

提交回复
热议问题