Sure this is possible, for a given value of possible. It's somewhat unclear to me exactly what you're looking to do, but the basic principle of a vertex shader is to take a stream of inputs, execute a homogenous function for every vert, and produce a set of outputs.
In your case of a surface of revolution, I assume you mean you want to end up with a mesh like a lathed surface, given an input profile curve? If so, what you're intending to do is more commonly done on the CPU, written into a vertex buffer as a finished surface, and then displayed like any other mesh. Usually the vertex shader would only be used to apply a linear transformation + projection matrix to get a perspective render of the surface.
It's not entirely uncommon though to move some calculations to the vertex shader where you know that they will be heavy for the CPU to perform, and you intend to do them often, or you could save resources in some way by parametrizing the same input data over and over again. E.g. you wanted to draw 1000 similar lathed objects where only the radius varies.
If that's the case, then your first problem is that you cannot generate vertices in a vertex shader. There are two inputs into a vertex shader: varying/stream and uniform/constants. Varying inputs vary for each vertex, while uniform ones only change between draw calls.
All vertices you will draw will need to be present in the input stream. What this means is that you'll need to identify a common input stream pattern to all your possible instances. Let's say, for instance, that you'll be making lathed surfaces where:
- There are N segments around the axis of rotation (let's call it Y)
- You have a function that given a T value between 0 and 1 can give you the distance from the axis, and the distance along the axis for a vertex; i.e. the x and y of the profile curve.
So, you'll need to setup an input vertex buffer that provides for each vertex:
- An A value, which determines segment it is on, so that you can calculate how far around the axis it should be. Let's say we store this in radians.
- The T value, so that you can calculate where on the profile curve it should be. We'll store this as a value between 0 and 1.
So for an instance that had 3 segments, and 3 steps along the curve, your stream would look like: 0, 0, 0.5, 0, 1, 0, 0, 2/3pi, 0.5, 2/3pi, 1, 2/3pi, 0, 4/3pi, 0.5, 4/3pi, 1, 4/3pi. Note: with that vertex stream you'll need an index buffer to describe how to stitch those points into triangles.
You would then make a custom vertex declaration that described the two floats you need.
You would then make your vertex shader take these two inputs, and:
- Calculate the X/Y position using the T input.
- Rotate that point around the Y axis using the A value, creating a 3D point.
- Apply your view/projection transform.
Now, based on what you're trying to do, you can figure out what uniform inputs you'll need here, i.e. whatever your function that takes T to produce XY needs.
Once that's all done, you can now make individual draw calls reusing the same stream inputs, but varying the uniform inputs to create different lathed surfaces. You could also vary the vertex shader its self to apply different functions. You could also create multiple streams with varying amounts of tessellation. Swapping between these would allow you to cheaply adjust the level of detail for each instance.
That's the simplest usage of the GPU at this time. Different architectures offer alternative features that may contribute a different solution to your goal, but without knowing more about your goal or what your environment is, I can't speak to those.