blob: 44d8b052bedb767b211c57c4f338810b919d853e [file] [log] [blame]
Name Strings
Mark J. Kilgard, NVIDIA Corporation (mjk 'at'
Copyright NVIDIA Corporation, 1999, 2000.
NVIDIA no longer supports this extension in driver updates
after November 2002. Instead, use either ARB_vertex_program &
NVIDIA Date: January 3, 2003
$Date$ $Revision$
Written based on the wording of the OpenGL 1.2 specification but not
dependent on it.
The intent of this extension is to provide a means for blending
geometry based on two slightly differing modelview matrices.
The blending is based on a vertex weighting that can change on a
per-vertex basis. This provides a primitive form of skinning.
A second modelview matrix transform is introduced. When vertex
weighting is enabled, the incoming vertex object coordinates are
transformed by both the primary and secondary modelview matrices;
likewise, the incoming normal coordinates are transformed by the
inverses of both the primary and secondary modelview matrices.
The resulting two position coordinates and two normal coordinates
are blended based on the per-vertex vertex weight and then combined
by addition. The transformed, weighted, and combined vertex position
and normal are then used by OpenGL as the eye-space position and
normal for lighting, texture coordinate, generation, clipping,
and further vertex transformation.
Should the extension be written to extend to more than two vertex
weights and modelview matrices?
RESOLUTION: NO. Supports only one vertex weight and two modelview
matrices. If more than two is useful, that can be handled with
another extension.
Should the weighting factor be GLclampf instead of GLfloat?
RESOLUTION: GLfloat. Though the value of a weighting factors
outside the range of zero to one (and even weights that do not add
to one) is dubious, there is no reason to limit the implementation
to values between zero and one.
Should the weights and modelview matrices be labeled 1 & 2 or 0 & 1?
RESOLUTION: 0 & 1. This is consistent with the way lights and
texture units are named in OpenGL. Make GL_MODELVIEW0_EXT
be an alias for GL_MODELVIEW. Note that the GL_MODELVIEW0_EXT+1
will not be GL_MODELVIEW1_EXT as is the case with GL_LIGHT0 and
Should there be a way to simultaneously Rotate, Translate, Scale,
LoadMatrix, MultMatrix, etc. the two modelview matrices together?
RESOLUTION: NO. The application must use MatrixMode and repeated
calls to keep the matrices in sync if desired.
Should the secondary modelview matrix stack be as deep as the primary
matrix stack or can they be different sizes?
RESOLUTION: Must be the SAME size. This wastes a lot of memory
that will be probably never be used (the modelview matrix stack
must have at least 32 entries), but memory is cheap.
The value returned by MAX_MODELVIEW_STACK_DEPTH applies to both
modelview matrices.
Should there be any vertex array support for vertex weights.
Should we have a VertexWeight2fEXT that takes has two weight values?
RESOLUTION: NO. The weights are always vw and 1-vw.
What is the "correct" way to blend matrices, particularly when wo is
not one or the modelview matrix is projective?
RESOLUTION: While it may not be 100% correct, the extension blends
the vertices based on transforming the object coordinates by
both M0 and M1, but the resulting w coordinate comes from simply
transforming the object coordinates by M0 and extracting the w.
Another option would be to simply blend the two sets of eye
coordinates without any special handling of w. This is harder.
Another option would be to divide by w before blending the two
sets of eye coordinates. This is awkward because if the weight
is 1.0 with vertex weighting enabled, the result is not the
same as disabling vertex weighting since EYE_LINEAR texgen
is based of of the non-perspective corrected eye coordinates.
As specified, the normal weighting and combination is performed on
unnormalized normals. Would the math work better if the normals
were normalized before weighting and combining?
RESOLUTION: Vertex weighting of normals is after the
GL_RESCALE_NORMAL step and before the GL_NORMALIZE step.
As specified, feedback and selection should apply vertex weighting
if enabled. Yuck, that would mean that we need software code for
vertex weighting.
RESOLUTION: YES, it should work with feedback and selection.
Sometimes it would be useful to mirror changes in both modelview
matrices. For example, the viewing transforms are likely to be
different, just the final modeling transforms would be different.
Should there be an API support for mirroring transformations into
both matrices?
RESOLUTION: NO. Such support is likely to complicate the
matrix management in the OpenGL. Applications can do a
Get matrix from modelview0 and then a LoadMatrix into modelview1
manually if they need to mirror things.
I also worry that if we had a mirrored matrix mode, it would
double the transform concatenation work if used naively.
Many of the changes to the two modelview matrices will be the same.
For example, the initial view transform loaded into each will be the
same. Should there be a way to "mirror" changes to both modelview
RESOLUTION: NO. Mirroring matrix changes would complicate the
driver's management of matrices. Also, I am worried that naive
users would mirror all transforms and lead to lots of redundant
matrix concatenations. The most efficient way to handle the
slight differences between the modelview matrices is simply
to GetFloat the primary matrix, LoadMatrix the values in the
secondary modelview matrix, and then perform the "extra" transform
to the secondary modelview matrix.
Ideally, a glCopyMatrix(GLenum src, GLenum dst) type OpenGL
command could make this more efficient. There are similiar cases
where you want the modelview matrix mirrored in the texture matrix.
This is not the extension to solve this minor problem.
The post-vertex weighting normal is unlikely to be normalized.
Should this extension automatically enable normalization?
RESOLUTION: NO. Normalization should operate as specified.
The user is responsible for enabling GL_RESCALE_NORMAL or
GL_NORMALIZE as needed.
You could imagine cases where the application only sent
vertex weights of either zero or one and pre-normalized normals
so that GL_NORMALIZE would not strictly be required.
Note that the vertex weighting of transformed normals occurs
BEFORE normalize and AFTER rescaling. See the issue below for
why this can make a difference.
How does vertex weighting interact with OpenGL 1.2's GL_RESCALE_NORMAL
RESOLUTION: Vertex weighting of transformed normals occurs
BEFORE normalize and AFTER rescaling.
OpenGL 1.2 permits normal rescaling to behave just like normalize
and because normalize immediately follows rescaling, enabling
rescaling can be implementied by simply always enabling normalize.
Vertex weighting changes this. If one or both of the modelview
matrices has a non-uniform scale, it may be useful to enable
rescaling and normalize and this operates differently than
simply enabling normalize. The difference is that rescaling
occurs before the normal vertex weighting.
An implementation that truly treated rescaling as a normalize
would support both a pre-weighting normalize and a post-weighting
normalize. Arguably, this is a good thing.
For implementations that perform simply rescaling and not a full
normalize to implement rescaling, the rescaling factor can be
concatenated into each particular inverse modelview matrix.
New Procedures and Functions
void VertexWeightfEXT(float weight);
void VertexWeightfvEXT(float *weight);
void VertexWeightPointerEXT(int size, enum type, sizei stride, void *pointer);
New Tokens
Accepted by the <target> parameter of Enable:
Accepted by the <mode> parameter of MatrixMode:
MODELVIEW0_EXT 0x1700 (alias to MODELVIEW enumerant)
Accepted by the <pname> parameter of GetBooleanv, GetIntegerv,
GetFloatv, and GetDoublev:
Accepted by the <pname> parameter of GetPointerv:
Additions to Chapter 2 of the OpenGL 1.2.1 Specification (OpenGL Operation)
-- Section 2.6. 2nd paragraph changed:
"Each vertex is specified with two, three, or four coordinates.
In addition, a current normal, current texture coordinates, current
color, and current vertex weight may be used in processing each
-- Section 2.6. New paragraph after the 3rd paragraph:
"A vertex weight is associated with each vertex. When vertex
weighting is enabled, this weight is used as a blending factor
to blend the position and normals transformed by the primary and
secondary modelview matrix transforms. The vertex weighting
functionality takes place completely in the "vertex / normal
transformation" stage of Figure 2.2."
-- Section 2.6.3. First paragraph changed to
"The only GL commands that are allowed within any Begin/End pairs are
the commands for specifying vertex coordinates, vertex colors, normal
coordinates, and texture coordinates (Vertex, Color, VertexWeightEXT,
Index, Normal, TexCoord)..."
-- Section 2.7. New paragraph after the 4th paragraph:
"The current vertex weight is set using
void VertexWeightfEXT(float weight);
void VertexWeightfvEXT(float *weight);
This weight is used when vertex weighting is enabled."
-- Section 2.7. The last paragraph changes from
"... and one floating-point value to store the current color index."
"... one floating-point number to store the vertex weight, and one
floating-point value to store the current color index."
-- Section 2.8. Change 1st paragraph to say:
"The client may specify up to seven arrays: one each to store edge
flags, texture coordinates, colors, color indices, vertex weights,
normals, and vertices. The commands"
Add to functions listed following first paragraph:
void VertexWeightPointerEXT(int size, enum type, sizei stride, void *pointer);
Add to table 2.4 (p. 22):
Command Sizes Types
---------------------- ----- -----
VertexWeightPointerEXT 1 float
Starting with the second paragraph on p. 23, change to add
"An individual array is enabled or disabled by calling one of
void EnableClientState(enum array)
void DisableClientState(enum array)
for the edge flag, texture coordinate, color, secondary color,
color index, normal, or vertex array, respectively.
The ith element of every enabled array is transferred to the GL by calling
void ArrayElement(int i)
For each enabled array, it is as though the corresponding command
from section 2.7 or section 2.6.2 were called with a pointer to
element i. For the vertex array, the corresponding command is
Vertex<size><type>v, where <size> is one of [2,3,4], and <type> is
one of [s,i,f,d], corresponding to array types short, int, float, and
double respectively. The corresponding commands for the edge flag,
texture coordinate, color, secondary color, color index, and normal
arrays are EdgeFlagv, TexCoord<size><type>v, Color<size><type>v,
Index<type>v, VertexWeightfvEXT, and Normal<type>v, respectively..."
Change pseudocode on p. 27 to disable vertex weight array for canned
interleaved array formats. After the lines
insert the line
Substitute "seven" for every occurrence of "six" in the final
paragraph on p. 27.
-- Section 2.10. Change the sentence:
"The model-view matrix is applied to these coordinates to yield eye
"The primary modelview matrix is applied to these coordinates to
yield eye coordinates. When vertex weighting is enabled, a secondary
modelview matrix is also applied to the vertex coordinates, the
result of the two modelview transformations are weighted by its
respective vertex weighting factor and combined by addition to yield
the true eye coordinates. Vertex weighting is enabled or disabled
using Enable and Disable (see section 2.10.3) with an argument of
Change the 4th paragraph to:
"If vertex weighting is disabled and a vertex in object coordinates
is given by ( xo yo zo wo )' and the primary model-view matrix is
M0, then the vertex's eye coordinates are found as
(xe ye ze we)' = M0 (xo yo zo wo)'
If vertex weighting is enabled, then the vertex's eye coordinates
are found as
(xe0 ye0 ze0 we0)' = M0 (xo yo zo wo)'
(xe1 ye1 ze1 we1)' = M1 (xo yo zo wo)'
(xe,ye,ze)' = vw*(xe0,ye0,ze0)' + (1-vw) * (xe1,ye1,ze1)'
we = we0
where M1 is the secondary modelview matrix and vw is the current
vertex weight."
-- Section 2.10.2 Change the 1st paragraph to say:
"The projection matrix and the primary and secondary modelview
matrices are set and modified with a variety of commands. The
affected matrix is determined by the current matrix mode. The
current matrix mode is set with
void MatrixMode(enum mode);
which takes one of the four pre-defined constants TEXTURE,
alias for MODELVIEW0). TEXTURE is described later. If the current
matrix is MODELVIEW0, then matrix operations apply to the primary
modelview matrix; if MODELVIEW1, then matrix operations apply to
the secondary modelview matrix; if PROJECTION, then they apply to
the projection matrix."
Change the 9th paragraph to say:
"There is a stack of matrices for each of the matrix modes. For the
MODELVIEW0 and MODELVIEW1 modes, the stack is at least 32 (that is,
there is a stack of at least 32 modelview matrices). ..."
Change the last paragraph to say:
"The state required to implement transformations consists of a
four-valued integer indicating the current matrix mode, a stack of
at least two 4x4 matrices for each of PROJECTION and TEXTURE with
associated stack pointers, and two stacks of at least 32 4x4 matrices
with an associated stack pointer for MODELVIEW0 and MODELVIEW1.
Initially, there is only one matrix on each stack, and all matrices
are set to the identity. The initial matrix mode is MODELVIEW0."
-- Section 2.10.3 Change the 2nd and 7th paragraphs to say:
"For a modelview matrix M, the normal for this matrix is transformed
to eye coordinates by:
(nx' ny' nz' q') = (nx ny nz q) * M^-1
where, if (x y z w)' are the associated vertex coordinates, then
/ 0, w= 0
q = | -(nx ny nz) (x y z)' (2.1)
| --------------------, w != 0
\ w
Implementations may choose instead to transform (x y z)' to eye
coordinates using
(nx' ny' nz') = (nx ny nz) * Mu^-1
Where Mu is the upper leftmost 3x3 matrix taken from M.
Rescale multiplies the transformed normals by a scale factor
( nx" ny" nz" ) = f (nx' ny' nz')
If rescaling is disabled, then f = 1. If rescaling is enabled, then
f is computed as (mij denotes the matrix element in row i and column j
of M^-1, numbering the topmost row of the matrix as row 1 and the leftmost column
as column 1
f = ---------------------------
sqrt(m31^2 + m32^2 + m33^2)
Note that if the normals sent to GL were unit length and the model-view
matrix uniformly scales space, the rescale make sthe transformed normals
unit length.
Alternatively, an implementation may chose f as
f = ---------------------------
sqrt(nx'^2 + ny'^2 + nz'^2)
recomputing f for each normal. This makes all non-zero length
normals unit length regardless of their input length and the nature
of the modelview matrix.
After rescaling, the final transformed normal used in lighting, nf,
depends on whether vertex weighting is enabled or not.
When vertex weighting is disabled, nf is computed as
nf = m * ( nx"0 ny"0 nz"0 )
where (nx"0 ny"0 nz"0) is the normal transformed as described
above using the primary modelview matrix for M.
If normalization is enabled m=1. Otherwise
m = ------------------------------
sqrt(nx"0^2 + ny"0^2 + nz"0^2)
However when vertex weighting is enabled, the normal is transformed
twice as described above, once by the primary modelview matrix and
again by the secondary modelview matrix, weighted using the current
per-vertex weight, and normalized. So nf is computed as
nf = m * ( nx"w ny"w nz"w )
where nw is the weighting normal computed as
nw = vw * ( nx"0 ny"0 nz"0 ) + (1-vw) * (nx"1 ny"1 nz"1)
where (nx"0 ny"0 nz"0) is the normal transformed as described
above using the primary modelview matrix for M, and (nx"1 ny"1 nz"1) is the
normal transformed as described above using the secondary modelview matrix for
M, and vw is the current pver-vertex weight."
-- Section 2.12. Changes the 3rd paragraph:
"The coordinates are treated as if they were specified in a
Vertex command. The x, y, z, and w coordinates are transformed
by the current primary modelview and perspective matrices. These
coordinates, along with current values, are used to generate a
color and texture coordinates just as done for a vertex, except
that vertex weighting is always treated as if it is disabled."
Additions to Chapter 3 of the OpenGL 1.2.1 Specification (Rasterization)
Additions to Chapter 4 of the OpenGL 1.2.1 Specification (Per-Fragment Operations
and the Framebuffer)
Additions to Chapter 5 of the OpenGL 1.2.1 Specification (Special Functions)
Additions to Chapter 6 of the OpenGL 1.2.1 Specification (State and State Requests)
Additions to Appendix A of the OpenGL 1.2.1 Specification (Invariance)
Additions to the AGL/GLX/WGL Specifications
GLX Protocol
A new GL rendering command is added. The following command is sent
to the server as part of a glXRender request:
2 8 rendering command length
2 4135 rendering command opcode
4 FLOAT32 weight0
To support vertex arrays, the DrawArrays rendering command (sent via
a glXRender or glXRenderLarge request) is amended as follows:
The list of arrays listed for the third element in the ARRAY_INFO
structure is amended to include:
The VERTEX_DATA description is amended to include:
If the vertex weight array is enabled:
ws LISTofBYTE vertex weight array element
wp unused, wp=pad(ws)
with the following paragraph amended to read:
"where ns, cs, is, ts, es, vs, ws is the size of the normal, color,
index, texture, edge, vertex, and vertex weight array elements and
np, cp, ip, tp, ep, vp, wp is the padding for the normal, color,
index, texture, edge, vertex, and vertex weight array elements,
The current vertex weight can be updated at any time. In particular
WeightVertexEXT can be called between a call to Begin and the
corresponding call to End.
INVALID_VALUE is generated if VertexWeightPointerEXT parameter <size>
is not 1.
INVALID_ENUM is generated if VertexWeightPointerEXT parameter <type>
is not FLOAT.
INVALID_VALUE is generated if VertexWeightPointerEXT parameter <stride>
is negative.
New State
(table 6.5, p196)
Get Value Type Get Command Initial Value Description Sec Attribute
--------- ---- ----------- ------------- ----------- --- ---------
CURRENT_VERTEX_WEIGHT_EXT F GetFloatv 1 Current 2.8 current
vertex weight
(table 6.6, p197)
Get Value Type Get Command Initial Value Description Sec Attribute
--------- ---- ----------- ------------- ----------- --- ---------
VERTEX_WEIGHT_ARRAY_EXT B IsEnabled False Vertex weight enable 2.8 vertex-array
VERTEX_WEIGHT_ARRAY_SIZE_EXT Z+ GetIntegerv 1 Weights per vertex 2.8 vertex-array
VERTEX_WEIGHT_ARRAY_TYPE_EXT Z1 GetIntegerv FLOAT Type of weights 2.8 vertex-array
VERTEX_WEIGHT_ARRAY_STRIDE_EXT Z GetIntegerv 0 Stride between weights 2.8 vertex-array
VERTEX_WEIGHT_ARRAY_POINTER_EXT Y GetPointerv 0 Pointer to vertex weight array 2.8 vertex-array
(table 6.7, p198)
Get Value Type Get Command Initial Value Description Sec Attribute
--------- ---- ----------- ------------- ----------- ------ ---------
MODELVIEW0_MATRIX_EXT 32*xM4 GetFloatv Identity Primary modelview 2.10.2 -
MODELVIEW1_MATRIX_EXT 32*xM4 GetFloatv Identity Secondary modelview 2.10.2 -
MODELVIEW0_STACK_DEPTH_EXT Z+ GetIntegerv 1 Primary modelview 2.10.2 -
stack depth
MODELVIEW1_STACK_DEPTH_EXT Z+ GetIntegerv 1 Secondary modelview 2.10.2 -
stack depth
MATRIX_MODE Z4 GetIntegerv MODELVIEW0 Current matrix mode 2.10.2 transform
VERTEX_WEIGHTING_EXT B IsEnabled False Vertex weighting 2.10.2 transform/enable
New Implementation Dependent State
Revision History
12/16/2000 amended to include GLX protocol for vertex arrays
5/25/2000 added missing MODELVIEW#_MATRIX_EXT token values
1/3/2003 changed status to "discontinued"