You can not do clipping in vertex programs, because a single triangle can become several during clipping. You would be able to do clipping in fragment programs, but fragment.position is in window coordinates not world space.
You can stretch the processing over both of them to attempt trivial examples(i.e. depriving yourself of a texture coordinate to get a clip-coordinate). But as clever as that is, the interpolated value is not accurate to within any tolerance. Triangles that pierce the surface of the sphere are rendered incorrectly, and ones which all three vertices pierce the sphere aren’t rendered at all.
need…programmable hardware. How else would it work?
To clarify the following (large) post, Iw ant to define how I am going to use terms.
- [li] Fixed-Function: The functionality is [/li]determined by a fixed set of functions. One may set values, and set input, but the way in which the values and input are used is unchanging.[li] Programmable: The functionality is determined by a program which is executed. The way in which values and input are used is unrestricted, subject to the expressivity of the language. (This is usually more powerful than fixed-function).[] Clipping: Surface based clipping. The spherical clipping example, is still a clip-surface, though it does clip everything outside the sphere. A surface that prevents the rendering of view-obstructed geometry ( that is all the geometry between the surface and hither-plane).[] Volume Clipping: Using the same spherical example, if instead the interior of the sphere were clipped this would be a volume clip. A volume clip would be a region of space that doesn’t not allow rendering to occur. This is a more powerful form of clipping.
By these definitions clipping is fixed-function. Under this definition, I think ff-clipping will be here a long time. I would like to expand the set of available primitives.
OpenGL mandates a specific primitive in its ff-clipper: planes. It mandates supporting 12 of them, 6 being the view frustrum. Pair-wise they are the hither-yon, the ford-fare, and the zig-zag(AKA the near-far, left-right, and top-bottom).
In ff-rendering, every point, type of line, type of triangle, and type of quad is rendered using the same vertex transformation pipeline and lighting module. Each is available in a few types: Strips, Lists, and Fans. All of these together, form the set of supported primitives. Every renderable thing is specified in terms of these.
There should be support for planes and triangles in the ff-clipper. Lines and points cannot clip, as they are not 2 dimensional. When projected to the view-plane, they cover zero area and nothing would be clipped. Wide lines (lines with width larger than 0) and large points (points with size greater than 0) could be supported as well.
Every type of surface uses the same inside-outside test. In fact, it is nearly as hard to clip with a plane as it is with a triangle. Planar clipping can be achieved by testing the sign of “V dot N + D”, where N and D are properties of the plane(normal and offset). Triangle reconstruction occurs by determining the line segment of intersection with the plane, and taking the positively valued vertices and joining them with the vertices on the line segment, (which have interpolated values for the other vertex properties based on the shading model).
Clipping to a triangle, begins identically to planar clipping. During triangle reconstruction, the line segment of intersection of the plane is intersected with the clip-triangle. If no intersection occurs the data-triangle is passed whole. If the interection is contained entirely with the triangle, the data-trianfle is clipped as the plane. In the final case, the line segment is intersected to the side of the triangle, and the data triangle is split into two triangles. One which is passed whole, the other intersected to the plane.
I don’t know if the plane-clipping is done in hardware. I assume it is, as otherwise there would be 3 transfers of vertex data between system and hardware. If it is in hardware, triangle-clipping can be done in hardware using about the same amount of circuitry as the plane-clipping, and no more than twice as many clock-ticks. Ideally they would be integrated into the same unit, and then there would be minimal change to the current hardware.
The real problem depends on the amount of triangles and planes used in clipping. Given that the current rendering rate is at 6 clippers, the time spent in this section increases linearly with the number of clippers; using a naive hardware implementation. Better performance can be achieved by using effective space-partitioning, and determining nodes of influence for each clipper. Then the problem grows only as the spatial complexity of the clip-space, and the logarithm of the number of of clippers. It may be the case that software may run faster than hardware for a few years, but this is supposed to be a forward looking forum.
If I wanted to get something incorporated now, I would use the following:
- [li] State Variable:Description:Attribute Group:Initial Value:Get Command[] GL_CLIP_TRIANGLEi user clip-triangle coordinates transform (0,0,0,0,0,0,0,0,0) glGetClipTriangle()[] GL_CLIP_TRIANGLEi ith user clipping triangle enabled transform_enable GL_FALSE glIsEnabled()[/ul][/li][ul][li] New Functions[] void glClipTriangle(GLenum target, GLdouble coordinates)[] void glGetClipTriangle(GLenum target, GLdouble coordinates)
This only a baby-step toward the functionality I had previously described.
too complicated to implement in a fragment vertex program
I worry more about making errors, than about the complexity of any single conversion. It is a repetitive process, and just because I(or any one person in particular) can do it correctly, vehemently does not mean that any programmer user of openGL can do the same. And even I(or that particular person) will(not might) make a mistake in some conversion sometime. I strongly believe the conversion should be automated (say via an openGL API).
Ideally, I would like to be able to use code like the following.
name = glGenClips(1);
glNewClip(name);
//Geometry calls to form clip-surface
glEndList();
glEnableClip(name);
// work
valid = glIsClip(some_name);
glDisableClip(name);
//finish work
glDeleteClips(name, 1);
This way I do not have to reinvent the triangle every time I need to make a clip surface.
Volume clipping is a little more complicated. The same inside/outside tests occur, but in world-space instead of view-space. The same mechanism for triangle reconstruction as used in surface clipping can be used here.