Question

I've been tinkering with rendering billiard balls in XNA/D3D (DX11). I've written a Blinn-Phone shader that uses SamplerState in the HLSL to map my billiard textures to a sphere FBX that I generated in VisualStudio2012.

There are two problems I'm having, both most visible on the rightmost ball in the picture below.

1) You can see the texture reveals where the underlying polygons of the sphere are.
2) At the bottom edge of the third line where just a little white is visible below the stripe, it looks very aliased or jagged.

The texture application seems to be largely beyond my control, as the interpolation between the vertex normals is done within the pipeline, not by me.

So, how could I improve this? Generate a new sphere with more polygons?

I've done the following for the antialiasing, but frankly it seemed to do very little if anything:

        graphics.PreferMultiSampling = true;
        graphics.ApplyChanges();
        GraphicsDevice.PresentationParameters.MultiSampleCount = 4;

Here's my texture map state, for what its worth. Any ideas would be greatly appreciated. If you need more info, let me know!

sampler2D ColorSampler = sampler_state {
    Texture = <ColorTexture>;
    FILTER = MIN_MAG_MIP_LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};

Billiard Balls Rendered

Was it helpful?

Solution

To complement Rahul's answer, there is a third, more involved option (although I would definitely opt for simply increasing the number of polygons) : you mentioned that you are using a shader - and I'll assume you're talking about a pixel shader. The issue arises because the texture coordinates are linearly interpolated inside the triangles in the pixel shader : but since you know that you are dealing with spheres, it becomes possible to manually compute the UV coordinates per pixel in the pixel shader (use the standard acos(z) and atan(y/x) formula with the (x,y,z) point being the current point rasterized in the object coordinate).

Using that, even if you use a very coarsely tesselated sphere, your should still be able to get relatively smooth textures.

EDIT: although I don't have a snippet at hand, here is a pseudo code:

Vertex shader:
- take the initial coordinates of the current vertex (without any matrix transform ; I'll assume that your sphere vertices are centered around the origin) and pass them directly to the pixel shader as a varying vec3 P.

Pixel shader:
- r = sqrt(P.x*P.x + P.y*P.y + P.z*P.z)
- theta = acos(P.z/r)
- phi = atan2(P.y/r, P.x/r)
- u = theta*2/pi ; v = phi/(2*pi)+0.5
- use the (u,v) above to sample your texture in the tex2D()

You'll need to make sure that these uv coordinates indeed correspond to how your texture has been generated, but if so, you should get an almost distortion free mapping.

OTHER TIPS

You have a couple of options:

  1. Tesellate more finely. What you're seeing is the error in approximating a sphere via piecewise-planar geometry and one way to make it less visible is to split it into smaller pieces.

  2. Filter your textures to have a less sharp transition from blue -> white (apply a Gaussian blur and then use the blurred image as your texture).

To solve this I used 3DSMax instead of the built-in model builder of VS2012. I set the scale to 2" for the sphere and increased the number of segments to 64. When exporting to FBX I enabled "Turbo Smooth" without knowing what it is.

In the end, it turns out much better:

enter image description here

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top