How do I clear a Direct2D render target to fully transparent
Asked Answered
P

3

8

I'm trying to draw semi-transparent rectangles on an invisible HWND. However, clearing the window with ID2D1HwndRenderTarget::Clear just makes the entire window black, so when I draw rectangles on top, they look semi-black.

If I don't Clear() and don't draw, then the window is invisible, as it should be. Clear() is the culprit here; however if I don't use it then painting messes up pretty badly.

Here's the code I'm using in my WindowProc:

case WM_PAINT:
    // Begin drawing
    pRenderTarget->BeginDraw();
    pRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());

    // Clear the window
    pRenderTarget->Clear();

    // Paint the panel and its children
    D2DSurface()->StartPainting();
    {
        D2DSurface()->PaintTraverse(panel);
    }
    D2DSurface()->FinishPainting();

    // Finish drawing
    HRESULT hr = plat->pRenderTarget->EndDraw();

Thanks in advance!

Pulvinus answered 8/4, 2010 at 20:37 Comment(2)
Note: I have tried clearing with 0.0 as the opacity, with exactly the same outcome.Pulvinus
Can you paste a picture of the transparent effect? I just want to know how it works.Wrote
J
1

When creating your RenderTarget, you'll have to tell D2D that you want to use alpha (in premultiplied mode) in the pixel format:

  HRESULT hr = mD2DFactory->CreateHwndRenderTarget(
    D2D1::RenderTargetProperties( D2D1_RENDER_TARGET_TYPE_DEFAULT, D2D1::PixelFormat( DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED ) ),
    D2D1::HwndRenderTargetProperties( mWindow, size ),
    &mRenderTarget );

After this, calling Clear() with an alpha value of zero works just fine.

Jester answered 16/5, 2012 at 22:29 Comment(14)
Are you sure this works? this will clear the background of the render target to black too. as the D2D1_ALPHA_MODE_PREMULTIPLIED flag will multiply the alpha component to each color, so if you use the zero alpha, that means r * 0, g * 0, b * 0 which result in a (0, 0, 0, 0), that's a black color.Wrote
Yes, this works perfectly. You need to use D2D1_ALPHA_MODE_PREMULTIPLIED when drawing to a window, and the background color is not black, it's transparent.Jester
it doesn't work for me, I got black background with your method, can you paste the code to the Clear method? or paste a screenshot of the transparent window?Wrote
How on earth would a screenshot help you? Sure, here's how you call clear: mRenderTarget->BeginDraw(); mRenderTarget->SetTransform( D2D1::Matrix3x2F::Identity() ); mRenderTarget->Clear( D2D1::ColorF( 0, 0.0f ) ); mRenderTarget->EndDraw(); I hope you've also made sure your window class has no background brush assigned to it. See my comments in the other answer for the WS_EX_COMPOSITED method on Aero.Jester
Still not work, I didn't have background brush for my window, Do I need to do any extra settings when creating the window? for example, the window style?Wrote
I paste all my code here, goo.gl/MvRQt, please help to see where is wrong.Wrote
Hi Noora, I still want to see a picture of the effect, you said it works perfectly, can you paste a picture of the transparent window?Wrote
zdd: take a look at the MSDN page for D2D1_ALPHA_MODE (bit.ly/U3DZM1) under the "Alpha Mode for Render Targets" heading. Noora's code should work perfectly.Pulvinus
@Pulvinus Rennison, But, in fact, it does not work! please paste code or screen shot if it works for you.Wrote
@SaulRennison, would you mind accepting the answer, and canceling out the downvote? You know my answer works, and I don't feel like losing reputation because a third person is acting like an a-hole.Jester
@Wrote How did you achieve this transparency after all? Your explanation would be so obliged. Thank you.Millard
@mk1 I think you should ask Saul Rennison since this does not work for me, I have ask the poster to paste some screen shots, but no reply yet.Wrote
@Wrote I reposted the question here hopefully to increase the traction of this problem since it wasn't really answered clearly. #18837421Millard
there is an old good article on the topic: learn.microsoft.com/en-us/archive/msdn-magazine/2009/december/…Starrstarred
W
5

Transparency is a problem. The only window that support per-pixel transparency are WS_EX_LAYERED windows. These windows were designed for uses like drag-drop icons, and that leads to problems in every other usage.

Using D2D with WS_EX_LAYERED windows requires that you use a DXGI render target. To EndDraw, you get a DC out of the render target then pass that into the layered window and tell the layered window to update itself. (Try this with a HWNDRenderTarget - it will probably crash the device driver).

I suspect your window appears transparent because it's not drawing at all.

Another gotcha you may run into... if the window is sufficiently transparent, mouse clicks will go through it to the underlying window.

Winch answered 28/10, 2010 at 2:10 Comment(2)
Not true. Firstly, WS_EX_LAYERED works just fine, all kinds of wacky windows have been created using it, without any major drawbacks, other than more code to hand-write. WS_EX_LAYERED is also not the only way to make per-pixel transparency anymore: On Windows Vista and upward, there's WS_EX_COMPOSITED, which features hugely better performance, since you're rendering straight to Aero's Direct3D surface. As for the mouse clicks, they will only go through 0-alpha pixels.Jester
That is, when you combine WS_EX_COMPOSITED with DwmExtendFrameIntoClientArea( mWindow, &m ); using a margin of -1, you'll have a clear window that draws straight to the D3D surface. You'll have to do click-through testing yourself when using this, unlike with layered windows.Jester
D
5

Use ID2D1DCRenderTarget instead of ID2D1HwndRendTarget, then bind the device context (DC) of your window before drawing begins.

Of course, you will need to set the WS_EX_LAYERED for your window and then call SetLayeredWindowAttributes to set the transparent color:

SetLayeredWindowAttributes(hWnd, RGB(0, 0, 0), 0, LWA_COLORKEY);

Screenshot:

Demography answered 8/12, 2015 at 3:28 Comment(0)
J
1

When creating your RenderTarget, you'll have to tell D2D that you want to use alpha (in premultiplied mode) in the pixel format:

  HRESULT hr = mD2DFactory->CreateHwndRenderTarget(
    D2D1::RenderTargetProperties( D2D1_RENDER_TARGET_TYPE_DEFAULT, D2D1::PixelFormat( DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED ) ),
    D2D1::HwndRenderTargetProperties( mWindow, size ),
    &mRenderTarget );

After this, calling Clear() with an alpha value of zero works just fine.

Jester answered 16/5, 2012 at 22:29 Comment(14)
Are you sure this works? this will clear the background of the render target to black too. as the D2D1_ALPHA_MODE_PREMULTIPLIED flag will multiply the alpha component to each color, so if you use the zero alpha, that means r * 0, g * 0, b * 0 which result in a (0, 0, 0, 0), that's a black color.Wrote
Yes, this works perfectly. You need to use D2D1_ALPHA_MODE_PREMULTIPLIED when drawing to a window, and the background color is not black, it's transparent.Jester
it doesn't work for me, I got black background with your method, can you paste the code to the Clear method? or paste a screenshot of the transparent window?Wrote
How on earth would a screenshot help you? Sure, here's how you call clear: mRenderTarget->BeginDraw(); mRenderTarget->SetTransform( D2D1::Matrix3x2F::Identity() ); mRenderTarget->Clear( D2D1::ColorF( 0, 0.0f ) ); mRenderTarget->EndDraw(); I hope you've also made sure your window class has no background brush assigned to it. See my comments in the other answer for the WS_EX_COMPOSITED method on Aero.Jester
Still not work, I didn't have background brush for my window, Do I need to do any extra settings when creating the window? for example, the window style?Wrote
I paste all my code here, goo.gl/MvRQt, please help to see where is wrong.Wrote
Hi Noora, I still want to see a picture of the effect, you said it works perfectly, can you paste a picture of the transparent window?Wrote
zdd: take a look at the MSDN page for D2D1_ALPHA_MODE (bit.ly/U3DZM1) under the "Alpha Mode for Render Targets" heading. Noora's code should work perfectly.Pulvinus
@Pulvinus Rennison, But, in fact, it does not work! please paste code or screen shot if it works for you.Wrote
@SaulRennison, would you mind accepting the answer, and canceling out the downvote? You know my answer works, and I don't feel like losing reputation because a third person is acting like an a-hole.Jester
@Wrote How did you achieve this transparency after all? Your explanation would be so obliged. Thank you.Millard
@mk1 I think you should ask Saul Rennison since this does not work for me, I have ask the poster to paste some screen shots, but no reply yet.Wrote
@Wrote I reposted the question here hopefully to increase the traction of this problem since it wasn't really answered clearly. #18837421Millard
there is an old good article on the topic: learn.microsoft.com/en-us/archive/msdn-magazine/2009/december/…Starrstarred

© 2022 - 2024 — McMap. All rights reserved.