Rendering a circle with a Vertex shader in DirectX

2.1k views Asked by At

I am trying to draw a simple 2D circle by manipulating texcoord coordinates inside a vertex shader. This is the code:

float2 uv2 = 2.0 * (TextureCoordinate.xy - 0.5);
float tnm = 1.0 - length(uv2);

In pixel shader, this draws a circle. The same code inside the vertex shader would draw plain white. I can get some diagonal gradient at best if I play with numbers, but no circles.

What is going on inside the vertex shader?

PS. I should clarify, there are no polygons or triangles or circle objects/meshes I want to create. I simply pass the texcoord to pixel shader and return it. Doing 1-texcoord in vertex flips the gradient as expected in pixel output. My goal is to generate some spherical normals procedurally.

PPS. Assuming it is [-1,-1] to [1,1] in vertex, I did:

(uv + 1) * 0.5;
circle code above which expects [0,1]
(result * 2) - 1;

But it didn't work.

1

There are 1 answers

2
Gnietschow On BEST ANSWER

First of all, I would like to suggest you to have a deeper look into the renderpipeline and the meanings of vertex shaders and pixel shaders. Dont't be angry with me, but it seems that you need some more basic understanding for this topic.

I'll try to give a quick overview about your problem: You won't achieve a good circle in the vertexshader, except you would highly tesselate your geometry. You need the pixelshader to get your sphere with normals.

What is going on inside the vertex shader?

That's the main problem here: The vertex shader transforms your given geometry, so it can be rastered to render pixels to your screen. The rasterizer will take the resulting triangles and generate a pixel for each pixel the triangle encloses on the screen. This pixel will be processed by the pixelshader and the resulting color is displayed. For the data each pixel is carrying the rasterizer interpolates the vertexdata of the three corners, so each pixel has it's own positionally depended data. This is your problem.

If you fill your vertices with the circle data this four points gain there mapping to the circle and will be linear interpolated for the other points between, but a circle can't be described linear in this way. A little image for clarification:

enter image description here

As you see the four corners texture coordinates are mapped to circle coordinates. They are lying outside so their y-height will be mapped to zero. Now these four points are interpolated for the pixelshader leading to even more zero-height and no real circle. Every interpolation in the vertexshader end in something rhombic, if you would split your quad once, you would get a rhombus, if you would split it more and more it would approximate a circle, but never would be perfect.

Therefore you need the pixel shader. So each pixel get its interpolated position to determine the correct sphere normal instead of wrong interpolated normals.

enter image description here

Because of this problem the most modern lighting computations are made in the pixelshader. Especially for specular lighting it is essential to get fine and precise highlights.

I hope my explanation was easy to understand :)