Direct2D 位图画笔拉伸

3
我需要在屏幕外的位图上绘制形状,但是当我尝试渲染位图时出现了奇怪的问题。

这是图片应该显示的方式:

enter image description here

而这是我看到位图的方式:

enter image description here

以下是我用来创建位图画刷的代码:

const auto size = renderTarget->GetSize();
const auto pxSize = D2D1::SizeU(size.width * 4, size.height * 4);

ID2D1BitmapRenderTarget* compatibleRenderTarget;
HRESULT hr = renderTarget->CreateCompatibleRenderTarget(size, pxSize, &compatibleRenderTarget);

if (SUCCEEDED(hr))
{
  // compute visible area and the current transformation matrix
  const auto area = get_visible_area(renderTarget);
  const auto transform = D2D1::Matrix3x2F::Identity();

  // offscreen bitmap rendering
  compatibleRenderTarget->BeginDraw();

  // draw all shapes

  compatibleRenderTarget->EndDraw();

  // Retrieve the bitmap from the render target.
  ID2D1Bitmap* bitmap;
  hr = compatibleRenderTarget->GetBitmap(&bitmap);

  // release the compatible render target
  compatibleRenderTarget->Release();

  // Create the bitmap brush
  ID2D1BitmapBrush* bitmapBrush = nullptr;
  hr = renderTarget->CreateBitmapBrush(bitmap, D2D1::BitmapBrushProperties(), &bitmapBrush);
  bitmap->Release();


  // draw bitmap
  renderTarget->FillRectangle(area, bitmapBrush);
}

你的问题是关于扩展底线还是位图质量的损失? - Anton Angelov
@AntonAngelov 这是关于扩展底线的问题。实际上,我只需将兼容渲染目标的大小加倍即可解决它,但我无法说出原因... - Nick
为什么不使用ID2D1RenderTarget :: DrawBitmap()并传递屏幕外位图,而不是创建位图刷? 这样更加简单。另外第二个问题..每次在HWND渲染目标上渲染时,您是否重新绘制屏幕外位图? - Anton Angelov
@AntonAngelov 我会尝试使用DrawBitmap方法,是的,我确实在每次调用渲染方法时重新绘制位图(也就是每次需要添加新的“自由绘图”形状时,不幸的是这种情况经常发生,因为几何对象是不可变的)。有没有办法避免重新绘制位图的需要? - Nick
如果每次渲染到窗口时都重新绘制离屏位图,则会失去使用离屏位图的所有好处。这没有任何意义。因此,您必须编写单独的函数(1)用于绘制到离屏位图和(2)用于在HWND渲染目标上绘制的函数。仅在某些形状发生更改时调用第一个函数(1),而不是每次在HWN RT上渲染时都调用。在HWND RT上绘制时,首先计算离屏位图的可见区域(仅在缩放时),然后使用DrawBitmap()将此特定区域复制到HWND RT上。 - Anton Angelov
有一个误解,我只写了一次离屏位图(并且也只在变换,比如缩放或平移,改变时写入)。我在渲染函数中始终调用的唯一方法是FillRectangle(现在我将用DrawBitmap方法来替换它)。 - Nick
1个回答

3
效果是标准行为的结果。如果您使用位图画刷,可以选择不同的扩展模式(默认为clamp)。这定义了当几何体大小超过位图大小时会发生什么情况(就像在FillRect()中一样)。您必须在传递给ID2D1RenderTarget::CreateBitmapBrush()的D2D1_BITMAP_BRUSH_PROPERTIES结构中为X和Y轴定义扩展模式。
您可以在以下选项之间进行选择(如此陈述):
- Clamp(重复位图的最后一行) - Wrap(平铺位图) - Mirror 如果您不希望将位图夹住或平铺,请改用ID2D1RenderTarget::DrawBitmap()方法。 编辑:如果sourceRectangledestinationRectangle的大小不同,则位图将被拉伸。您可以通过指定D2D1_BITMAP_INTERPOLATION_MODE来调整拉伸质量(算法)。我认为它默认为最近邻插值,但线性插值具有更好的质量。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接