dev.nlited.com

>>

MapRects

<<<< prev
next >>>>

2022-12-17 19:29:21 chip Page 2475 📢 PUBLIC

December 17 2022

The role of the MapRect functions is still a bit fuzzy to me, time to take a closer look.

I changed the size of the source bitmaps so I could tell the difference. pbmSrc1 (the goldenrod box) is now 200x100 pixels, pbmSrc2 (the green circle) is now 100x200 pixels.

The first thing I noticed is that the circle is still round. When I changed the size of the bitmap before, the aspect ratio changed and the circle was rendered as an oblate oval. This confuses me a bit.

Before the effect is drawn, I see this sequence:
MyEffect:MapInToOut: 0 (0,0) 200x100 MyEffect:MapInToOut: 1 (0,0) 100x200 MyEffect:MapInToOut: rOut (0,0) 200x100 MyEffect:MapOutToIn: rOut (0,0) 200x100 This sequence makes sense if the input rectangles are always the root input, which dictates the output rectangle. But why would the rIn from MapOutToIn() be different than the original rIn from MapInToOut?

MapInToOut():
for(UINT n1=0;n1<ctIn;n1++) { rIn[n1]= prIn[n1]; Print(PRINT_DEBUG,"MyEffect:MapInToOut: %u (%d,%d) %dx%d",n1,prIn[n1].left,prIn[n1].top,RWID(prIn[n1]),RHGT(prIn[n1])); if(n1==0) { *prOut= prIn[n1]; } } The list of prIn is an input, and I am expected to set prOut and prInOpaque.

MapOutToIn():
for(UINT n1=0;n1<ctIn;n1++) { prIn[n1]= *prOut; } prOut is an input, and I am expected to set the list of prIn rectangles.

I suspect MapInToOut() is not quite right, the output rectange should be the union of the two rectangles:
for(UINT n1=0;n1<ctIn;n1++) { rIn[n1]= prIn[n1]; Print(PRINT_DEBUG,"MyEffect:MapInToOut: %u (%d,%d) %dx%d",n1,prIn[n1].left,prIn[n1].top,RWID(prIn[n1]),RHGT(prIn[n1])); if(n1==0) { *prOut= prIn[n1]; } else { prOut->left= min(prOut->left,prIn[n1].left); prOut->top= min(prOut->top,prIn[n1].top); prOut->right= max(prOut->right,prIn[n1].right); prOut->bottom= max(prOut->bottom,prIn[n1].bottom); } }

Direct2D then applies any clipping regions, or other restrictions, to the output rectangle and gives me a chance to update my input rectangles. So MapOutToIn() should then update rIn to be the intersection of rIn and rOut:
for(UINT n1=0;n1<ctIn;n1++) { prIn[n1].left= max(prOut->left,rIn[n1].left); prIn[n1].top= max(prOut->top,rIn[n1].top); prIn[n1].right= min(prOut->right,rIn[n1].right); prIn[n1].bottom= min(prOut->bottom,rIn[n1].bottom); }

That did not produce the expected result:
PxlShader MapRects
MyEffect:MapInToOut: 0 (0,0) 200x100 MyEffect:MapInToOut: 1 (0,0) 100x200 MyEffect:MapInToOut: rOut (0,0) 200x200 MyEffect:MapOutToIn: rOut (0,0) 200x135 MyEffect:MapOutToIn: rIn[0] (0,0) 200x100 MyEffect:MapOutToIn: rIn[1] (0,0) 100x135 Where does that 200x135 come from?

I kept the union code in MapInToOut and reverted MapOutToIn to
prIn[n1]= *prOut; And this drew correctly.
MyEffect:MapInToOut: 0 (0,0) 200x100 MyEffect:MapInToOut: 1 (0,0) 100x200 MyEffect:MapInToOut: rOut (0,0) 200x200 MyEffect:MapOutToIn: rOut (0,0) 200x135 MyEffect:MapOutToIn: rIn[0] (0,0) 200x135 MyEffect:MapOutToIn: rIn[1] (0,0) 200x135 rOut is still 200x135, the difference is that all the rIn rectangles are the same size. Was the distortion caused by the bottom 35 rows of pbmSrc1 being read incorrectly?

I also tried prIn[n1]= rIn[n1] to set the input rectangles back to the original values. This resulted in the same distortion. It appears the final prIn rectangles need to be of uniform size to avoid the distortion. This makes sense because my shader code is taking the average of the pixels from Input0 and Input1 using the same coordinates, so if the sizes are different I would, at some point, be trying to read input pixels that don't exist.

The flaw in this reasoning is that pbmSrc1 and pbmSrc2 are not the same size, so when the shader runs it would at some point be operating on pixels that exist in pbmSrc1 but are out of bounds for pbmSrc2. But if my shader is never called for those pixels, the problem would never occur. So I guess my shader is only being called for pixels that are in the intersection of pbmSrc1 and pbmSrc2.

Always setting all the prIn[] rectangles to prOut works because prOut is the clipped union of the input rectangles, which covers all the inputs and is a uniform size.

I might understand MapInToOut, but MapOutToIn is still a bit hazy.

What does MapInToOut(prOutOpaque) do?

ID2D1Transform::MapInputRectsToOutputRect()

[in] const D2D1_RECT_L *inputOpaqueRects
An array of input rectangles to be mapped to the opaque output rectangle.

[out] D2D1_RECT_L *outputOpaqueRect
The output rectangle that maps to the corresponding opaque input rectangle.

Unlike the MapOutputRectToInputRects and MapInvalidRect functions, this method is explicitly called by the renderer at a determined place in its rendering algorithm. The transform implementation may change its state based on the input rectangles and use this information to control its rendering information. This method is always called before the MapInvalidRect and MapOutputRectToInputRects methods of the transform.

I am ignoring prInOpaque and always setting prOutOpaque to {0,0,0,0}.


Moderator: close comments Comments are closed.

Comments are moderated. Anonymous comments are not visible to others until moderated. Comments are owned by the author but may be removed or reused (but not modified) by this site at any time without notice.

HTML
  1. Moderator: [] approve delete HTML



WebV7 (C)2018 nlited | Rendered by tikope in 50.405ms | 3.128.31.227