I render everything in my game in 2D with SpriteBatch with the exception of a spherical entity (orb) that I render as a spinning and dynamically lit (custom effect) sphere in 3D. I capture the sphere into a RenderTarget every frame and then use the image in the SpriteBatch to render in 2D. The composed image is aliased as any model.

I do not enable MSAA because various platforms that my game runs on (WinRT, as an example) do not support it. I tried FXAA as a custom effect, but the problem is that it does not appear to support transparency (I render the sphere on a transparent background).

My rudimentary solution is to render the sphere into a RenderTarget of size X and then render the result with SpriteBatch into a RenderTarget of size X/2. I set the SamplerState for the SpriteBatch draw call for the half size rendering to anisotropic, although I am not 100% sure this increases the quality of the final output dramatically (and at what cost?).

This solution appears to work fine but is not without its flaws. Mobile devices are slowed down by the multiple SetRenderTarget calls per frame, especially since I render more than one orb type.

Are there other approaching to this?

  • 1
    \$\begingroup\$ If you're already special-casing the sphere, is there a reason you don't want to render it directly onto the final target? Also you should be able to get at least 4x MSAA if you use the BGRA surface format, at least on WinRT. \$\endgroup\$
    – MooseBoys
    Jan 6 '14 at 23:35
  • \$\begingroup\$ I meant the Windows Store apps. MSAA is not supported: social.msdn.microsoft.com/Forums/windowsapps/en-US/… \$\endgroup\$ Jan 7 '14 at 4:36
  • 1
    \$\begingroup\$ MSAA is supported, but you must use ResolveSubresource from your primary render target (of a Texture2D) to the back buffer, rather than using an MSAA swap chain directly. There is no performance overhead since MSAA swap chains automatically resolve on Present anyway. The last post on the thread you linked to shows how to do this. \$\endgroup\$
    – MooseBoys
    Jan 7 '14 at 7:48
  • \$\begingroup\$ I looked into it. It looks like the sample is using DX11.2. I also couldn't get it to work in SharpDX. While it does create the RT (doesn't throw any of the usual exceptions that the parameters are invalid for that GraphicsDevice) no matter what I do with it, it always captures a black frame. I'll explore this further. \$\endgroup\$ Jan 8 '14 at 20:00
  • \$\begingroup\$ @MooseBoys By the way, that wouldn't be a go on, say Windows Phone, for sure. \$\endgroup\$ Jan 8 '14 at 20:01

Well for antialiasing there are many approaches like yours, downsampling an oversampled picture, which is very costly.

Using a renderTarget seems also overkill to me.

The best option would be to make a custom shader for you SpriteBatch that does parametric sphere ray-casting (not that expensive, was working on my old Sony Ericsson Mini Pro).

You can apply your light shading, textures, etc. and use the smoothstep function on the borders, it is not even needed if you add a "glow". Plus you'll have a lot of control on effects you want to add.

Other advantage fragment shader process only once for each pixel, so its the same for 10 or 100 orbs.

Example here of what I've done with this approach: https://www.shadertoy.com/view/XdsGDX (btw shaderToy is a must when coding & debuging fragment shaders)

I'm using this approach for my 3D space game right now and I was able to display more than a hundred stars at 60fps like in the example on a integrated graphic chip.

  • \$\begingroup\$ "custom shader for you SpriteBatch that does parametric sphere ray-casting". This is interesting, but if I were to draw 15 of them, as an example, wouldn't that mean that the shader would run 15 times? Is that more efficient than doing the RT magic that I mentioned? \$\endgroup\$ Jan 7 '14 at 4:44
  • \$\begingroup\$ Well no, as it told pixel shader monstly run once per pixel so it's more screen coverage than the number of elements that would take resources. Of course there are more processing for 15 elements but if they cover only a half of the screen it will be more efficient than 1 element covering the whole screen. In my memory rt is very expensive, I'd use them only if it's mandatory otherwise I'd prefer a single pass process. \$\endgroup\$
    – StackHola
    Jan 7 '14 at 9:49

If I would have to solve this I think I would use a simple small gaussian blur. As a shader this shouldn't be that big performance issue and simple to implement, and also be a very nice-looking approach.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.