NVIDIA OptiX 8.0 nvidia_logo_transpbg.gif Up
optix_micromap_impl.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2023 NVIDIA Corporation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of NVIDIA CORPORATION nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29
36#ifndef OPTIX_OPTIX_MICROMAP_IMPL_H
37#define OPTIX_OPTIX_MICROMAP_IMPL_H
38
39#ifndef OPTIX_MICROMAP_FUNC
40#ifdef __CUDACC__
41#define OPTIX_MICROMAP_FUNC __device__
42#else
43#define OPTIX_MICROMAP_FUNC
44#endif
45#endif
46
47namespace optix_impl {
48
53#define OPTIX_MICROMAP_INLINE_FUNC OPTIX_MICROMAP_FUNC inline
54
55#ifdef __CUDACC__
56// the device implementation of __uint_as_float is declared in cuda_runtime.h
57#else
58// the host implementation of __uint_as_float
60{
61 union { float f; unsigned int i; } var;
62 var.i = x;
63 return var.f;
64}
65#endif
66
67// Extract even bits
68OPTIX_MICROMAP_INLINE_FUNC unsigned int extractEvenBits( unsigned int x )
69{
70 x &= 0x55555555;
71 x = ( x | ( x >> 1 ) ) & 0x33333333;
72 x = ( x | ( x >> 2 ) ) & 0x0f0f0f0f;
73 x = ( x | ( x >> 4 ) ) & 0x00ff00ff;
74 x = ( x | ( x >> 8 ) ) & 0x0000ffff;
75 return x;
76}
77
78
79// Calculate exclusive prefix or (log(n) XOR's and SHF's)
80OPTIX_MICROMAP_INLINE_FUNC unsigned int prefixEor( unsigned int x )
81{
82 x ^= x >> 1;
83 x ^= x >> 2;
84 x ^= x >> 4;
85 x ^= x >> 8;
86 return x;
87}
88
89// Convert distance along the curve to discrete barycentrics
90OPTIX_MICROMAP_INLINE_FUNC void index2dbary( unsigned int index, unsigned int& u, unsigned int& v, unsigned int& w )
91{
92 unsigned int b0 = extractEvenBits( index );
93 unsigned int b1 = extractEvenBits( index >> 1 );
94
95 unsigned int fx = prefixEor( b0 );
96 unsigned int fy = prefixEor( b0 & ~b1 );
97
98 unsigned int t = fy ^ b1;
99
100 u = ( fx & ~t ) | ( b0 & ~t ) | ( ~b0 & ~fx & t );
101 v = fy ^ b0;
102 w = ( ~fx & ~t ) | ( b0 & ~t ) | ( ~b0 & fx & t );
103}
104
105// Compute barycentrics of a sub or micro triangle wrt a base triangle. The order of the returned
106// bary0, bary1, bary2 matters and allows for using this function for sub triangles and the
107// conversion from sub triangle to base triangle barycentric space
108OPTIX_MICROMAP_INLINE_FUNC void micro2bary( unsigned int index, unsigned int subdivisionLevel, float2& bary0, float2& bary1, float2& bary2 )
109{
110 if( subdivisionLevel == 0 )
111 {
112 bary0 = { 0, 0 };
113 bary1 = { 1, 0 };
114 bary2 = { 0, 1 };
115 return;
116 }
117
118 unsigned int iu, iv, iw;
119 index2dbary( index, iu, iv, iw );
120
121 // we need to only look at "level" bits
122 iu = iu & ( ( 1 << subdivisionLevel ) - 1 );
123 iv = iv & ( ( 1 << subdivisionLevel ) - 1 );
124 iw = iw & ( ( 1 << subdivisionLevel ) - 1 );
125
126 int yFlipped = ( iu & 1 ) ^ ( iv & 1 ) ^ ( iw & 1 ) ^ 1;
127
128 int xFlipped = ( ( 0x8888888888888888ull ^ 0xf000f000f000f000ull ^ 0xffff000000000000ull ) >> index ) & 1;
129 xFlipped ^= ( ( 0x8888888888888888ull ^ 0xf000f000f000f000ull ^ 0xffff000000000000ull ) >> ( index >> 6 ) ) & 1;
130
131 const float levelScale = __uint_as_float( ( 127u - subdivisionLevel ) << 23 );
132
133 // scale the barycentic coordinate to the global space/scale
134 float du = 1.f * levelScale;
135 float dv = 1.f * levelScale;
136
137 // scale the barycentic coordinate to the global space/scale
138 float u = (float)iu * levelScale;
139 float v = (float)iv * levelScale;
140
141 // c d
142 // x-----x
143 // / \ /
144 // / \ /
145 // x-----x
146 // a b
147 //
148 // !xFlipped && !yFlipped: abc
149 // !xFlipped && yFlipped: cdb
150 // xFlipped && !yFlipped: bac
151 // xFlipped && yFlipped: dcb
152
153 bary0 = { u + xFlipped * du , v + yFlipped * dv };
154 bary1 = { u + (1-xFlipped) * du, v + yFlipped * dv };
155 bary2 = { u + yFlipped * du , v + (1-yFlipped) * dv };
156}
157
158// avoid any conflicts due to multiple definitions
159#define OPTIX_MICROMAP_FLOAT2_SUB(a,b) { a.x - b.x, a.y - b.y }
160
161// Compute barycentrics for micro triangle from base barycentrics
162OPTIX_MICROMAP_INLINE_FUNC float2 base2micro( const float2& baseBarycentrics, const float2 microVertexBaseBarycentrics[3] )
163{
164 float2 baryV0P = OPTIX_MICROMAP_FLOAT2_SUB( baseBarycentrics, microVertexBaseBarycentrics[0] );
165 float2 baryV0V1 = OPTIX_MICROMAP_FLOAT2_SUB( microVertexBaseBarycentrics[1], microVertexBaseBarycentrics[0] );
166 float2 baryV0V2 = OPTIX_MICROMAP_FLOAT2_SUB( microVertexBaseBarycentrics[2], microVertexBaseBarycentrics[0] );
167
168 float rdetA = 1.f / ( baryV0V1.x * baryV0V2.y - baryV0V1.y * baryV0V2.x );
169 float4 A = { baryV0V2.y, -baryV0V2.x, -baryV0V1.y, baryV0V1.x };
170
171 float2 localUV;
172 localUV.x = rdetA * ( baryV0P.x * A.x + baryV0P.y * A.y );
173 localUV.y = rdetA * ( baryV0P.x * A.z + baryV0P.y * A.w );
174
175 return localUV;
176}
177#undef OPTIX_MICROMAP_FLOAT2_SUB
178 // end group optix_utilities
180
181} // namespace optix_impl
182
183#endif // OPTIX_OPTIX_MICROMAP_IMPL_H
OPTIX_MICROMAP_INLINE_FUNC float2 base2micro(const float2 &baseBarycentrics, const float2 microVertexBaseBarycentrics[3])
Definition: optix_micromap_impl.h:162
#define OPTIX_MICROMAP_INLINE_FUNC
Definition: optix_micromap_impl.h:53
OPTIX_MICROMAP_INLINE_FUNC void micro2bary(unsigned int index, unsigned int subdivisionLevel, float2 &bary0, float2 &bary1, float2 &bary2)
Definition: optix_micromap_impl.h:108
OPTIX_MICROMAP_INLINE_FUNC unsigned int prefixEor(unsigned int x)
Definition: optix_micromap_impl.h:80
#define OPTIX_MICROMAP_FLOAT2_SUB(a, b)
Definition: optix_micromap_impl.h:159
OPTIX_MICROMAP_INLINE_FUNC float __uint_as_float(unsigned int x)
Definition: optix_micromap_impl.h:59
OPTIX_MICROMAP_INLINE_FUNC void index2dbary(unsigned int index, unsigned int &u, unsigned int &v, unsigned int &w)
Definition: optix_micromap_impl.h:90
OPTIX_MICROMAP_INLINE_FUNC unsigned int extractEvenBits(unsigned int x)
Definition: optix_micromap_impl.h:68
Definition: optix_device_impl_transformations.h:36