62 for ( ; any( ( 1u << shift ) < dimension ); ++shift );
63 for ( --shift; shift >= 0; --shift ) {
65 uint
const bit = ( 1u << shift );
67 if ( coordinate.y & bit ) {
70 result += ( dimension.x << shift );
72 else if ( dimension.y > bit )
75 if ( coordinate.x & bit ) {
78 result += ( dimension.y << shift );
80 else if ( dimension.x > bit )
105 uint2 result = ( uint2 )( 0, 0 );
108 for ( ; any( ( 1u << shift ) < dimension ); ++shift );
109 for ( --shift; shift >= 0; --shift ) {
111 uint
const bit = ( 1u << shift );
113 { uint
const shifted = ( dimension.x << shift );
114 if ( index >= shifted ) {
120 else if ( dimension.y > bit )
124 { uint
const shifted = ( dimension.y << shift );
125 if ( index >= shifted ) {
131 else if ( dimension.x > bit )
160 float Project( __private float3* pProjected, float3
const ray ) {
163 ( pProjected->x >= 0 ) && ( pProjected->x <= 1 ) &&
164 ( pProjected->y >= 0 ) && ( pProjected->y <= 1 ) &&
165 ( pProjected->z >= 0 ) && ( pProjected->z <= 1 )
172 if ( pProjected->x < 0 ) {
176 float const lambda = -pProjected->x / ray.x;
177 float3 projected = *pProjected + lambda * ray;
179 ( projected.y >= 0 ) && ( projected.y <= 1 ) &&
180 ( projected.z >= 0 ) && ( projected.z <= 1 )
184 *pProjected = projected;
189 else if ( pProjected->x > 1 ) {
193 float const lambda = ( 1 - pProjected->x ) / ray.x;
194 float3 projected = *pProjected + lambda * ray;
196 ( projected.y >= 0 ) && ( projected.y <= 1 ) &&
197 ( projected.z >= 0 ) && ( projected.z <= 1 )
201 *pProjected = projected;
207 if ( pProjected->y < 0 ) {
211 float const lambda = -pProjected->y / ray.y;
212 float3 projected = *pProjected + lambda * ray;
214 ( projected.x >= 0 ) && ( projected.x <= 1 ) &&
215 ( projected.z >= 0 ) && ( projected.z <= 1 )
219 *pProjected = projected;
224 else if ( pProjected->y > 1 ) {
228 float const lambda = ( 1 - pProjected->y ) / ray.y;
229 float3 projected = *pProjected + lambda * ray;
231 ( projected.x >= 0 ) && ( projected.x <= 1 ) &&
232 ( projected.z >= 0 ) && ( projected.z <= 1 )
236 *pProjected = projected;
242 if ( pProjected->z < 0 ) {
246 float const lambda = -pProjected->z / ray.z;
247 float3 projected = *pProjected + lambda * ray;
249 ( projected.x >= 0 ) && ( projected.x <= 1 ) &&
250 ( projected.y >= 0 ) && ( projected.y <= 1 )
254 *pProjected = projected;
259 else if ( pProjected->z > 1 ) {
263 float const lambda = ( 1 - pProjected->z ) / ray.z;
264 float3 projected = *pProjected + lambda * ray;
266 ( projected.x >= 0 ) && ( projected.x <= 1 ) &&
267 ( projected.y >= 0 ) && ( projected.y <= 1 )
271 *pProjected = projected;
290 __private uint*
const pColor,
291 __private
float*
const pLambda,
292 __read_only image3d_t image,
294 __private float3*
const pRemaining,
295 __private float3*
const pRemainingMaximum,
299 sampler_t
const sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_NONE | CLK_FILTER_NEAREST;
301 uint
const mask = ( ( origin & 4 ) ? ( 3 << 22 ) : 0 ) | ( ( origin & 2 ) ? ( 3 << 11 ) : 0 ) | ( ( origin & 1 ) ? 3 : 0 );
303 *pRemainingMaximum /= 2;
304 if ( pRemaining->x >= pRemainingMaximum->x ) {
307 pRemaining->x -= pRemainingMaximum->x;
309 if ( pRemaining->y >= pRemainingMaximum->y ) {
311 index += ( 2 << 11 );
312 pRemaining->y -= pRemainingMaximum->y;
314 if ( pRemaining->z >= pRemainingMaximum->z ) {
316 index += ( 2 << 22 );
317 pRemaining->z -= pRemainingMaximum->z;
320 *pRemainingMaximum /= 2;
321 if ( pRemaining->x >= pRemainingMaximum->x ) {
324 pRemaining->x -= pRemainingMaximum->x;
326 if ( pRemaining->y >= pRemainingMaximum->y ) {
328 index += ( 1u << 11 );
329 pRemaining->y -= pRemainingMaximum->y;
331 if ( pRemaining->z >= pRemainingMaximum->z ) {
333 index += ( 1u << 22 );
334 pRemaining->z -= pRemainingMaximum->z;
340 uint
const source = ( index ^ mask );
341 int4 coordinate = ( int4 )( source & 0x7ff, ( source >> 11 ) & 0x7ff, source >> 22, 0 );
342 float4
const color = read_imagef(
347 if ( ( color.x + color.y + color.z ) > 0 ) {
350 *pColor = 0xff000000 + ( ( uint )( color.x * 255.99 ) << 16 ) + ( ( uint )( color.y * 255.99 ) << 8 ) + ( uint )( color.z * 255.99 );
351 goto texture_loop_end_label;
355 ( ( pRemaining->x < pRemaining->y ) ? 1 : 0 ) |
356 ( ( pRemaining->y < pRemaining->z ) ? 2 : 0 ) |
357 ( ( pRemaining->z < pRemaining->x ) ? 4 : 0 )
359 switch( comparisons ) {
364 *pLambda += pRemaining->x;
365 pRemaining->y -= pRemaining->x;
366 pRemaining->z -= pRemaining->x;
367 pRemaining->x = pRemainingMaximum->x;
369 if ( ( index & 3 ) == 0 ) {
372 goto texture_loop_end_label;
382 *pLambda += pRemaining->y;
383 pRemaining->x -= pRemaining->y;
384 pRemaining->z -= pRemaining->y;
385 pRemaining->y = pRemainingMaximum->y;
387 if ( ( ( index >> 11 ) & 3 ) == 0 ) {
389 index |= ( 3u << 11 );
390 goto texture_loop_end_label;
393 index -= ( 1u << 11 );
400 *pLambda += pRemaining->z;
401 pRemaining->x -= pRemaining->z;
402 pRemaining->y -= pRemaining->z;
403 pRemaining->z = pRemainingMaximum->z;
405 if ( ( ( index >> 22 ) & 3 ) == 0 ) {
407 index |= ( 3u << 22 );
408 goto texture_loop_end_label;
411 index -= ( 1u << 22 );
417 texture_loop_end_label:;
419 pRemaining->x += pRemainingMaximum->x * ( index & 3 );
420 pRemaining->y += pRemainingMaximum->y * ( ( index >> 11 ) & 3 );
421 pRemaining->z += pRemainingMaximum->z * ( ( index >> 22 ) & 3 );
423 *pRemainingMaximum *= 4;
437 __global uint*
const colorDestination,
438 __global
float*
const depthDestination,
440 __global
void const*
const heap,
441 __read_only image3d_t image,
447 float const epsilon = 1e-6;
450 float3 projected = pp;
451 float lambda =
Project( &projected, ray );
453 if ( isfinite( lambda ) ) {
456 float3 remaining = 1 - projected;
461 remaining.x = projected.x;
467 remaining.y = projected.y;
473 remaining.z = projected.z;
476 delta = max( delta, epsilon );
478 #if ( SETTING_MIPMAP != 0 )
479 float3
const mipmapCoordinate = fabs( pp - projected ) + remaining;
480 float const spreadInverse = 0.125 / spread;
481 #endif // SETTING_MIPMAP
483 float3 remainingMaximum = 1 / delta;
484 remaining *= remainingMaximum;
486 uint3 coordinate = ( uint3 )( 0, 0, 0 );
487 int coordinateDepth = 0;
489 __global
struct Node const* pNode = ( __global
struct Node const* )( ( __global uchar
const* )heap + root );
491 __global
struct Node const* childrenStack[ SETTING_TRACE_STACK_SIZE ];
499 while ( ( depth < coordinateDepth ) && ( pNode->children != OPENCL_NULL ) ) {
501 #if ( SETTING_MIPMAP != 0 )
502 uint3
const shiftedCoordinate = ( coordinate >> ( coordinateDepth - depth ) );
504 float3
const mipmapDistance = ldexp( mipmapCoordinate, depth ) - ( float3 )( shiftedCoordinate.x, shiftedCoordinate.y, shiftedCoordinate.z );
506 float const sideLengthInverse = ( 1 << depth );
507 float3
const mipmapDistance = mipmapCoordinate * sideLengthInverse - ( float3 )( shiftedCoordinate.x, shiftedCoordinate.y, shiftedCoordinate.z );
509 if ( any( mipmapDistance >= spreadInverse ) )
511 #endif // SETTING_MIPMAP
513 pNode = ( __global
struct Node const* )( ( __global uchar
const* )heap + pNode->children );
514 childrenStack[ depth ] = pNode;
517 uint
const mask = ( 1 << ( coordinateDepth - depth ) );
519 ( ( coordinate.x & mask ) ? 1 : 0 ) |
520 ( ( coordinate.y & mask ) ? 2 : 0 ) |
521 ( ( coordinate.z & mask ) ? 4 : 0 )
526 while ( depth < coordinateDepth ) {
529 int3
const comparison = ( ( coordinate & 1 ) != 0 );
530 remaining += as_float3( comparison & as_int3( remainingMaximum ) );
532 if ( coordinate.x & 1 )
533 remaining.x += remainingMaximum.x;
534 if ( coordinate.y & 1 )
535 remaining.y += remainingMaximum.y;
536 if ( coordinate.z & 1 )
537 remaining.z += remainingMaximum.z;
540 remainingMaximum *= 2;
548 while ( pNode->children != OPENCL_NULL ) {
550 #if ( SETTING_MIPMAP != 0 )
552 float3
const mipmapDistance = ldexp( mipmapCoordinate, depth ) - ( float3 )( coordinate.x, coordinate.y, coordinate.z );
554 float const sideLengthInverse = ( 1 << depth );
555 float3
const mipmapDistance = mipmapCoordinate * sideLengthInverse - ( float3 )( coordinate.x, coordinate.y, coordinate.z );
557 if ( any( mipmapDistance >= spreadInverse ) )
559 #endif // SETTING_MIPMAP
561 pNode = ( __global
struct Node const* )( ( __global uchar
const* )heap + pNode->children );
562 childrenStack[ depth ] = pNode;
568 remainingMaximum /= 2;
571 int3
const comparison = ( remaining >= remainingMaximum );
572 remaining -= as_float3( comparison & as_int3( remainingMaximum ) );
573 coordinate ^= ( comparison & 1 );
575 if ( remaining.x >= remainingMaximum.x ) {
577 remaining.x -= remainingMaximum.x;
580 if ( remaining.y >= remainingMaximum.y ) {
582 remaining.y -= remainingMaximum.y;
585 if ( remaining.z >= remainingMaximum.z ) {
587 remaining.z -= remainingMaximum.z;
593 ( ( coordinate.x & 1 ) ? 1 : 0 ) |
594 ( ( coordinate.y & 1 ) ? 2 : 0 ) |
595 ( ( coordinate.z & 1 ) ? 4 : 0 )
601 int comparisons = -1;
602 if ( pNode->texture != OPENCL_NULL ) {
604 comparisons = TraceTexture(
614 if ( comparisons < 0 )
615 goto main_loop_end_label;
620 ( ( remaining.x < remaining.y ) ? 1 : 0 ) |
621 ( ( remaining.y < remaining.z ) ? 2 : 0 ) |
622 ( ( remaining.z < remaining.x ) ? 4 : 0 )
624 switch( comparisons ) {
629 lambda += remaining.x;
630 remaining.y -= remaining.x;
631 remaining.z -= remaining.x;
632 remaining.x = remainingMaximum.x;
639 lambda += remaining.y;
640 remaining.x -= remaining.y;
641 remaining.z -= remaining.y;
642 remaining.y = remainingMaximum.y;
649 lambda += remaining.z;
650 remaining.x -= remaining.z;
651 remaining.y -= remaining.z;
652 remaining.z = remainingMaximum.z;
661 switch( comparisons ) {
666 if ( coordinate.x == 0 ) {
669 goto main_loop_end_label;
673 for ( uint mask = 1; ( coordinate.x & mask ) != 0; mask *= 2, --depth );
681 if ( coordinate.y == 0 ) {
684 goto main_loop_end_label;
688 for ( uint mask = 1; ( coordinate.y & mask ) != 0; mask *= 2, --depth );
696 if ( coordinate.z == 0 ) {
699 goto main_loop_end_label;
703 for ( uint mask = 1; ( coordinate.z & mask ) != 0; mask *= 2, --depth );
711 pNode = childrenStack[ depth - 1 ];
712 uint
const mask = ( 1 << ( coordinateDepth - depth ) );
714 ( ( coordinate.x & mask ) ? 1 : 0 ) |
715 ( ( coordinate.y & mask ) ? 2 : 0 ) |
716 ( ( coordinate.z & mask ) ? 4 : 0 )
719 main_loop_end_label:;
722 *colorDestination = color;
723 *depthDestination = lambda;
734 __kernel
void TraceScreen(
735 __global uint*
const colors,
736 __global
float*
const depths,
737 uint2
const dimension,
738 uint
const colorsPitch,
739 uint
const depthsPitch,
740 float2
const fieldOfView,
742 __global
void const*
const heap,
743 __read_only image3d_t image,
751 uint
const index = get_global_id( 0 );
752 if ( index < dimension.x * dimension.y ) {
760 float3
const spreadX = ( 2 * fieldOfView.x / dimension.x ) * xx;
761 float3
const spreadY = ( 2 * fieldOfView.y / dimension.y ) * yy;
764 ( coordinate.x + 0.5 - 0.5 * dimension.x ) * spreadX -
765 ( coordinate.y + 0.5 - 0.5 * dimension.y ) * spreadY -
769 __global uint*
const colorDestination = ( __global uint* )( ( __global uchar* )colors + coordinate.y * colorsPitch + coordinate.x *
sizeof( uint ) );
770 __global
float*
const depthDestination = ( __global
float* )( ( __global uchar* )depths + coordinate.y * depthsPitch + coordinate.x *
sizeof( float ) );
771 Trace( colorDestination, depthDestination, spread, heap, image, root, pp, ray );