If I want to add a drawing mode to TCastleImage.DrawFrom TDrawMode implements dmAnti mode how do I manipulate image pixels to achieve Anti effect

  • Thank you very much for guiding me
  • The cache template set by D3D implements anti
    FD3DDevice.SetRenderState(D3DRS_ALPHABLENDENABLE, iTrue);
    D3DDevice.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_INVDESTCOLOR);
    FD3DDevice.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);

I see this was left unanswered for a long time. Sorry! In case my answer may still be useful:

  1. DrawFrom is implemented in src/images/castleimages_draw.inc and you can follow the implementation of any other existing mode to see how to add a new one. For “anti”, I understand you want to negate pixel values, so basically GrayScaleValue := 255-GrayScaleValue.

    That said, while it answers your question literraly, I definitely do not advise this – that is, I do not advise to add new modes to DrawFrom and friends. Reasons: 1. It is quite tiresome job and requires lots of code to support all cases – as you can see in src/images/castleimages_draw.inc . 2. It is inherently not optimal, as it uses CPU for drawing, and this is always slower (also on Android and iOS that you mentioned in other threads).

    In the future, DrawFrom will likely be deprecated for these reasons. Instead drawing using TDrawableImage is much easier (already has lots of blending features, and can be enhanced using shaders) and is optimized using GPU.

  2. So, a better approach to do this using TDrawableImage:

    On source TDrawableImage, adjust

    MySourceImage.Alpha := acBlending;
    MySourceImage.BlendingSourceFactor := bsOneMinusDstColor;
    MySourceImage.BlendingDestinationFactor := bdOne;
    MyDestImage.DrawFrom(MySourceImage, ...);
    

    Disclaimer: I haven’t actually checked how it looks. But the above values correspond exactly to the D3D snippet you showed above,

    FD3DDevice.SetRenderState(D3DRS_ALPHABLENDENABLE, iTrue);
    D3DDevice.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_INVDESTCOLOR);
    FD3DDevice.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
    

    Hopefully this will help. See other possible blending factors in TBlendingSourceFactor , TBlendingDestinationFactor enums.

  3. Note that, depends on how you want to use the image, maybe you don’t need to modify if at all. You can use effects and shaders when displaying (e.g. TCastleImageControl.CustomShader) without the need to modify the image.