I am currently building a Win2D CanvasGeometry out of lines, arcs, and beziers using CanvasPathBuilder. I need to be able to only draw the stroke for some of them, the others need to participate in the placement of subsequent segments but not be drawn. Is there any way to do this in Win2D?
I ended up just building multiple figures, since for each segment I had the end point, so if there was a segment that didn't need a stroke I could start a new figure. Seems to work ok.
Related
I want to detect that the sprite has encountered a color in pygame, which function should I use to achieve this function.
Though it is possible to get the color at any point in the surface that you want to check against using get_at() (docs here). You would need to find the new area that your sprite covered that it did not cover last time and check every pixel in that, and if other things were moving around you would have to check if your sprite now overlapped with any of those area and check that. Or you could decide that was too complicated and just run through every pixel under your sprites location (without you sprite drawn yet) and check for that color.
It is possible, but would likely not be very fast.
An alternative is if you know where those colors are you can mark those areas using rects, circles, sprites or masks (see here and here) that you can check against. That is usually much faster. These do not have to be drawn and so would be invisible. They would just be used to mark areas for the collision check.
If you do not know exactly where the colors are in the background or the other images, you can create masks based on the colors in them using pygame.mask.from_surface() or pygame.mask.from_threshold() (docs here and here).
I succeeded in retrieving the exact tile my player is on, at runtime when walking around the tiledmap. I'd like now to add some alpha marks on the terrain when passing over, and to do that I need to modify the color of some pixels of the tile.
I really don't know how to do it right now.. any hints?
thanks.
You probably want to draw decorations on top of the tiles, rather than modifying the tiles themselves. The tile images are shared across all cells using a tile, so if you modify the tile itself you would see the change everywhere it was used. Further, modifying the texture is a relatively expensive operation that you probably should try to avoid.
To draw on top the tiles, you might draw additional sprites, or use a custom shader.
Background
Using gluTess to build a triangle list in Direct3D9 from a GDI+ DrawString(..) path:
A pixel shader (v3.0) is then used to fill in the shape. When painting with opaque values, everything looks fine:
The problem
At certain font sizes, if the color has an alpha component (ie Argb #55FFFFFF) we begin to see these nasty tessellation artifacts where triangles may overlap ever so slightly:
At larger font sizes the problem is sometimes not present:
Using Intel's excellent GPA Frame Analyzer Pixel History tool, we can see in areas where the artifacts occur, the pixel has been "touched" 3 times from the single Erg.
I'm trying to figure out how I can stop my pixel shader from touching the same pixel more than once.
Other solutions relating to overdraw prevention seem to be all about zbuffer strategies, however this problem is more to do with painting of a single 2D triangle list within a single pixel shader pass.
I'm at a bit of a loss trying to come up with a solution on this one. I was hoping that HLSL might have some sort of "touch each pixel only once" flag, but I've been unable to find anything like that. The closest I've found was to set the BLENDOP to MAX instead of ADD. But the output is not correct when blending over other colors in the scene.
I also have SRCBLEND = ONE, DSTBLEND = INVSRCALPHA. The only combination of flags which produce correct output (albeit with overdraw artifacts.)
I have played with SEPARATEALPHABLENDENABLE in the GPA frame analyzer, which sounded like almost exactly what I need here -- set blending to MAX but only on the "alpha" channel, however from what I can determine, that setting (and corresponding BLENDOPALPHA) affects nothing at all.
One final thing I thought of was to bake text as opaque onto a texture, and then repaint that texture into the scene with the appropriate alpha value applied, however this doesn't actually work in this project because I also support gradient brushes, where stop values may contain alpha, meaning either the artifacts would still be seen, or the final output just plain wrong if we stripped the alpha away from the stop values prior to baking to a texture. Also the whole endeavor would be hideously expensive.
Any hints or pointers would be appreciated. Thanks for reading.
The problem you're seeing shouldn't happen.
If two of your triangles are overlapping it's because you've placed the vertices in such a way that when the adjacent triangles are drawn, they overlap. What's probably happening is that these two adjacent triangles share two vertices, but each triangle has its own copy of each vertex that's been calculated to be in a very, very slightly different position.
The solution to the problem isn't to try and make the pixel shader touch the pixel only once it's to use an index buffer (if you aren't already) and have the shared vertices between each triangle actually share the same vertex and not use one that's ever-so-slightly not in the same place as the one used by the adjacent triangle.
If you aren't in control of the tessellation algorithm being used you may have to run a pass over the vertex buffer after its been generated to detect and merge vertices that are within some very small tolerance of one another. Even without an index buffer, a naive solution would be this:
For each vertex in the vertex buffer, compare its position to every other vertex in the rest of the vertex buffer.
If two vertices are within some small tolerance of another, replace the second vertex's position with the position of the one you are comparing it against.
This should have the effect of pairing up the positions of two vertices if they are close enough that you deem them to be the same.
You now shouldn't have any problem with overlapping triangles. In everyday rendering two triangles share edges with each other all the time and you won't ever get the effect where they appear to every-so-slightly overlap. The hardware guarantees that a sample point is either on one side of the line or the other, but never both at the same time, no matter how close the point is to the line (even if it's mathematically on the line, it still fails on one side or the other).
I need to write some code (for a web.py webapp with a straight-HTML/JS client) that will generate a visual representation of a set of point-values. Each point has an X and Y coordinate, and the value is an integer. If I can use SVG to do this, then I can scale the image client-side with no extra code. Can I actually do this? I am concerned about a couple of things:
The points don't necessarily have any relation to each other. They aren't necessarily in a grid, nor can we say how many points are nearby, etc.
Gradients are primarily one-direction, and multiple gradients on the same shape seems to be a foreign concept.
Fills require an existing image, at which point, I'd be better off generating the entire image server-side anyway.
Objects always have a layering, even if it isn't specified, which can change how the image is rendered.
If it helps, consider a situation where we have a point surrounded by 5 others, where one of them is a bit closer than the others (exact distances and sizes can be adjusted). All six of the points have different colors (Red, Green, Blue, Cyan, Magenta, Yellow, with red in the center and Yellow being slightly closer), and the outer five points are arranged roughly in a pentagon. Note that this situation is not the only option, just a theoretically possible situation.
Can I do this with SVG, or should I render an image server-side?
EDIT: The main difficulty isn't in drawing the points, it is in filling the space between the points so that there is no whitespace, and color transitions aren't harsh/unpredictable if you know the data.
I don't entirely understand the different issues you are having with wanting to use svg. I am currently using the set up you are describing to render X-Y scatter plots and gaussian curves and found that it works great.
Regarding the last point about object layering, you have to be particularly careful when layering objects with less than 100% opacity which are different colors. The way the colors "add" depends on the order in which you add the objects to your svg drawing.
Thankfully you can use different filters to overlay the colors without blending them. Specifically I am using the FeComposite filter element. There is a good example of its usage here:
http://www.w3.org/TR/SVG/filters.html#feCompositeElement
Does anyone know of a graphics system which handles composition of multiple anti-aliased lines well?
I'm showing a dependency diagram and have a bunch of curves emanating from a point. These are drawn anti-aliased in the usual way, of blending partially covered pixels. So if two lines would occupy the same half of a pixel, the antialiasing blends it to 75% filled rather than 50% filled. With enough lines drawn on top of each other, the pixel blend clamps and you end up with aliased lines.
I know anti-grain geometry has algorithms for calculating blends which cater for lines which abut, and that oversampling might work, but are there any other approaches?
Handling this form of line composition well is going to be slow (you have to consider all the lines that impinge upon each pixel using a deferred rendering approach). I doubt that there are many (if any) libraries out there that will do it for you.
The quickest and easiest method (and possibly the only realistic and cost effective solution for your case), which will work with virtually any drawing library would be to supersample it - draw to an offscreen bitmap at much higher resolution (e.g. 4 times wider and higher, with lines of 4 pixels width. Disable antialiasing when drawing this as it'll only slow it down) and then scale the result down with bilinear filtering. The main down-side is that it uses a lot of memory for the offscreen bitmap.
If you need an existing system that gets antialiased lines "visually correct", you might try using one of several existing RenderMan-compliant 3D renderers. The REYES algorithm, which many of these renderers use, works by breaking up primitives into micropolygons, then sampling them at several random point locations within each pixel. So even if you have a million lines collectively obscuring 50% of a pixel, the resulting image value will show roughly 50% coverage. (This is, for example, how the millions of antialiased hairs are drawn on characters in many animated movies.)
Of course, using a full-blown 3D renderer to draw 2D lines is like driving nails with a sledgehammer. You'd need a fairly pathological scenario for the 3D renderer to be any more efficient than simply supersampling with a traditional 2D renderer.
It sounds like you want a premade drawing library, which I do not know of.
However, to answer your question of knowing any approach that would work, you can consider a pixel to be a square. You can then approximate any shape that you draw as a polygon that intersects the pixel box. By clipping these polygons against the box of the pixel and against each other, you can get a very good estimate of the areas associated with each color that intersects the pixel for accurate antialiasing. This is, of course, very slow to calculate and is not suitable for interactive drawing.