270 likes | 484 Views
Dot Product Texture Shaders in OpenGL. Cass Everitt NVIDIA Corporation cass@nvidia.com. Overview. What are the “dot product” texture shaders? HILO and RGBA texture formats DOT_PRODUCT_NV DOT_PRODUCT_TEXTURE_2D_NV DOT_PRODUCT_TEXTURE_CUBE_MAP_NV DOT_PRODUCT_REFLECT_CUBE_MAP_NV
E N D
Dot Product Texture Shadersin OpenGL Cass Everitt NVIDIA Corporation cass@nvidia.com
Overview • What are the “dot product” texture shaders? • HILO and RGBA texture formats • DOT_PRODUCT_NV • DOT_PRODUCT_TEXTURE_2D_NV • DOT_PRODUCT_TEXTURE_CUBE_MAP_NV • DOT_PRODUCT_REFLECT_CUBE_MAP_NV • DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV • DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV • DOT_PRODUCT_DEPTH_REPLACE_NV • Using the “Texel Matrix” (T)
What are the “dot product” texture shaders? • Texture Shaders (when enabled) replace the standard OpenGL texture fetch mechanism ARB_multitexture only ARB_multitexture with NV_texture_shader unit 0fetch stage 0math & fetch (s,t,r,q)0 (s,t,r,q)0 GL_TEXTURE0_ARB GL_TEXTURE0_ARB unit 1fetch stage 1math & fetch (s,t,r,q)1 (s,t,r,q)1 GL_TEXTURE1_ARB GL_TEXTURE1_ARB iterated texture coordinates… iterated texture coordinates… to the combiners… to the combiners… unit 2fetch stage 2math & fetch (s,t,r,q)2 (s,t,r,q)2 GL_TEXTURE2_ARB GL_TEXTURE2_ARB
What are the “dot product” texture shaders? (2) • The NV_texture_shader extension exposes a number of canned programs or modes that can be used to compute texture coordinates per-fragment rather than simply using the iterated per-vertex coordinates. • The “dot product” programs compute the dot product of the stage’s (s,t,r) and a vector derived from a previous stage’s texture lookup.
What are the “dot product” texture shaders? (2) Example configuration: stage 0 TEXTURE_2D (s0,t0) n n derived from HILOor RGB lookup in stage 0 stage 1 DOT_PRODUCT_NV (v1• n) on to texture environment or register combiners (s1,t1,r1) v1 stage 2 DOT_PRODUCT_-TEXTURE_2D_NV (v2• n) RGBA result (s2,t2,r2) v2
HILO and RGBA texture formats • NV_texture_shader defines some new internal texture formats that are useful for encoding vectors • GL_SIGNED_HILO_NV • Two 16-bit signed components • HI and LO mapped to [-1,1] range • Vector is ( HI, LO, sqrt(1- HI2- LO2) ) • GL_HILO_NV • Two 16-bit unsigned components • HI and LO mapped to [0,1] range • Vector is (HI, LO, 1)
HILO and RGBA texture formats (2) • GL_SIGNED_RGB_NV and GL_SIGNED_RGBA_NV • Three (and four) 8-bit signed components • All components mapped to [-1,1] range • Vector is ( R, G, B ) • GL_RGB and GL_RGBA can still be used • There is a GL_EXPAND_NORMAL_NV mapping for unsigned RGB and RGBA formats
DOT_PRODUCT_NV • Simply calculates a dot product -- it’s result is a high-precision, floating-point scalar • Useful only in combination with other dot product programs • All dot product programs can be considered to perform this operation, the others just do something with the accumulated scalars. n n derived from HILO or RGB lookup in previous stage shader stage DOT_PRODUCT_NV (v• n) RGBA result (0,0,0,0) (s,t,r) v High-precision floating-point scalar result
DOT_PRODUCT_TEXTURE_2D_NV • Previous stage must be DOT_PRODUCT_NV • Looks up into a 2D texture target with (s,t) (vi-1•n, vi•n) n n derived from HILO or RGB lookup in previous stage stage i-1 DOT_PRODUCT_NV vi-1 RGBA result (0,0,0,0) stage i DOT_PRODUCT_-TEXTURE_2D_NV lookup2D(<vi-1,n>, <vi ,n>) vi RGBA result
DOT_PRODUCT_TEXTURE_2D_NV (2) • Example draws a single bump-mapped quad • Normal map encodes a hemisphere • (s,t) = (<l,n>, <h,n>) • Luminance-alpha texture • Luminance is diffuse (simply <l,n>) • Alpha is specular (<h,n>shininess)
DOT_PRODUCT_TEXTURE_-CUBE_MAP_NV • Previous two stages must be DOT_PRODUCT_NV • Looks up into a cube map texture target with(s,t,r) (vi-2•n, vi-1•n, vi•n) • Another way to think of this is that the texture coordinate vectors (si-2, ti-2, ri-2), (si-1, ti-1, ri-1), and(si, ti, ri) form a matrix (T) that transforms the vector n to make n’.
DOT_PRODUCT_TEXTURE_-CUBE_MAP_NV (2) • This can be used to • look up into a pre-calculated diffuse lighting solution cubemap • perform simple refraction-like effects
DOT_PRODUCT_TEXTURE_-CUBE_MAP_NV (3) n n derived from HILO or RGB lookup in previous stage stage i-2 DOT_PRODUCT_NV RGBA result (0,0,0,0) vi-2 stage i-1 DOT_PRODUCT_NV RGBA result (0,0,0,0) vi-1 stage i DOT_PRODUCT_TEX-TURE_CUBE_MAP_NV lookup_cube_map(<vi-2,n>, <vi-1,n>, <vi ,n>) vi RGBA result
DOT_PRODUCT_REFLECT_-CUBE_MAP_NV • This program computes n’ like in the previous case, but the (s,t,r) used for cube map lookup is computed as the reflection of the eye vector about n’ • The eye vector is passed in through the q coordinate of the three dot product stages e = (qi-2, qi-1, qi)n’ = Tn = (vi-2•n, vi-1•n, vi•n)(s,t,r) = reflect(e, n’) = 2n’<n’,e> - e
DOT_PRODUCT_REFLECT_-CUBE_MAP_NV (2) n n derived from HILO or RGB lookup in previous stage stage i-2 DOT_PRODUCT_NV RGBA result (0,0,0,0) vi-2 stage i-1 DOT_PRODUCT_NV RGBA result (0,0,0,0) vi-1 stage i DOT_PRODUCT_REF-LECT_CUBE_MAP_NV lookup_cube_map(reflect(e,n’)) vi RGBA result
DOT_PRODUCT_REFLECT_-CUBE_MAP_NV (3) Screenshots from DOT_PRODUCT_REFLECT_- CUBE_MAP_NV demo programs
DOT_PRODUCT_CONST_EYE_-REFLECT_CUBE_MAP_NV • Identical to the DOT_PRODUCT_REFLECT_-CUBE_MAP_NV program except that the eye vector is passed in as a constant rather than in the q coordinates • Infinite viewer version of the previous program
DOT_PRODUCT_DIFFUSE_CUBE_-MAP_NV • The “reflect cube map” dot product programs require computing n’ as an intermediate term • As a special case, if the program for i-1 is DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV, n’ is used as the (s,t,r) to look into a cube map • In this way, the shader RGBA results for stagesi-1 and i can be used for diffuse and specular colors, respectively • If the cube map targets for these stages hold identity (or normalization) cube maps, the vectors can be used for further computation with NV_register_combiners
DOT_PRODUCT_DEPTH_-REPLACE_NV • Previous stage must be DOT_PRODUCT_NV • Replaces fragment’s window z with fragment_z (vi-1•n)/(vi•n) n n derived from HILO or RGB lookup in previous stage stage i-1 DOT_PRODUCT_NV RGBA result (0,0,0,0) vi-1 stage i DOT_PRODUCT_-DEPTH_REPLACE_NV fragment_z = <vi-1,n>/<vi,n> vi RGBA result (0,0,0,0)
DOT_PRODUCT_DEPTH_-REPLACE_NV (2) • Example illustrates using the depth replace • Sprites with z included • Correctly interpenetrate using depth test
The “Texel Matrix” (T) • To compute per-pixel lighting with GeForce, we must transform the L and H vectors into the space of the normal map vectors (typically either object- or tangent-space) • NV_texture_shader allows us to transform the normal map vectors into other spaces • All lighting computations can happen in the same space now! • This enables the use of cube maps for specular and diffuse lighting solutions
The “Texel Matrix” (T) (2) • Tangent-space normal maps can be moved into object space directly from the tangent-space basis vectors T, B, and N Note that S is simply the transpose (or inverse) of the matrix used to move L and H into tangent space for GeForce per-pixel lighting
The “Texel Matrix” (T) (3) • The previous transform puts the normals into object space, but we really need them in the space of the cube map • We can accomplish this by concatenating the relevant transforms • If S is the tangent space matrix, and M is the upper 3x3 portion of the modelview matrix, thenT = MS andn’ = Tn = MSnwhere n’ is the normal map vector transformed into eye space
The “Texel Matrix” (T) (4) • If the cube maps are defined in eye space, then life is pretty simple • For diffuse lighting, setting the texel matrix to MS is all that’s required • For specular, the eye vector is simply passed in per-vertex as the negated vertex position in eye space in addition to setting the texel matrix to MS
The “Texel Matrix” (T) (5) • Life gets a little more complicated if the cube map is rotated with respect to eye space • If C is the rotation of the cube map with respect to eye space, then we must set the texel matrix to T = CMS • This is all that is required for the diffuse solution to work, but now we must transform the eye vector into cube map space for specular to behave correctly • eeye = negate(eye_space_vertex_position) • ecubemap= Ceeye • ecubemap is passed in as the eye coordinates
Conclusions • NV_texture_shader’s dot product programs take per-pixel shading to the next level! • Lots of floating-point per-pixel math intermingled with texture lookup, and you still have register combiners to combine the texture shader results in interesting ways • Use NV_vertex_program to make programming the dot product texture shaders much easier and faster • Easier because it’s simple to let the vertex program do things like put the eye vector in the appropriate q coordinates • Faster because the GPU is doing the calculations