tessellation.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. // ======================================================================== //
  2. // Copyright 2009-2017 Intel Corporation //
  3. // //
  4. // Licensed under the Apache License, Version 2.0 (the "License"); //
  5. // you may not use this file except in compliance with the License. //
  6. // You may obtain a copy of the License at //
  7. // //
  8. // http://www.apache.org/licenses/LICENSE-2.0 //
  9. // //
  10. // Unless required by applicable law or agreed to in writing, software //
  11. // distributed under the License is distributed on an "AS IS" BASIS, //
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
  13. // See the License for the specific language governing permissions and //
  14. // limitations under the License. //
  15. // ======================================================================== //
  16. #pragma once
  17. namespace embree
  18. {
  19. /* adjust discret tessellation level for feature-adaptive pre-subdivision */
  20. __forceinline float adjustTessellationLevel(float l, const size_t sublevel)
  21. {
  22. for (size_t i=0; i<sublevel; i++) l *= 0.5f;
  23. float r = ceilf(l);
  24. for (size_t i=0; i<sublevel; i++) r *= 2.0f;
  25. return r;
  26. }
  27. __forceinline int stitch(const int x, const int fine, const int coarse) {
  28. return (2*x+1)*coarse/(2*fine);
  29. }
  30. __forceinline void stitchGridEdges(const unsigned int low_rate,
  31. const unsigned int high_rate,
  32. const unsigned int x0,
  33. const unsigned int x1,
  34. float * __restrict__ const uv_array,
  35. const unsigned int uv_array_step)
  36. {
  37. #if 1
  38. const float inv_low_rate = rcp((float)(low_rate-1));
  39. for (unsigned x=x0; x<=x1; x++) {
  40. uv_array[(x-x0)*uv_array_step] = float(stitch(x,high_rate-1,low_rate-1))*inv_low_rate;
  41. }
  42. if (unlikely(x1 == high_rate-1))
  43. uv_array[(x1-x0)*uv_array_step] = 1.0f;
  44. #else
  45. assert(low_rate < high_rate);
  46. assert(high_rate >= 2);
  47. const float inv_low_rate = rcp((float)(low_rate-1));
  48. const unsigned int dy = low_rate - 1;
  49. const unsigned int dx = high_rate - 1;
  50. int p = 2*dy-dx;
  51. unsigned int offset = 0;
  52. unsigned int y = 0;
  53. float value = 0.0f;
  54. for(unsigned int x=0;x<high_rate-1; x++) // '<=' would be correct but we will leave the 1.0f at the end
  55. {
  56. uv_array[offset] = value;
  57. offset += uv_array_step;
  58. if (unlikely(p > 0))
  59. {
  60. y++;
  61. value = (float)y * inv_low_rate;
  62. p -= 2*dx;
  63. }
  64. p += 2*dy;
  65. }
  66. #endif
  67. }
  68. __forceinline void stitchUVGrid(const float edge_levels[4],
  69. const unsigned int swidth,
  70. const unsigned int sheight,
  71. const unsigned int x0,
  72. const unsigned int y0,
  73. const unsigned int grid_u_res,
  74. const unsigned int grid_v_res,
  75. float * __restrict__ const u_array,
  76. float * __restrict__ const v_array)
  77. {
  78. const unsigned int x1 = x0+grid_u_res-1;
  79. const unsigned int y1 = y0+grid_v_res-1;
  80. const unsigned int int_edge_points0 = (unsigned int)edge_levels[0] + 1;
  81. const unsigned int int_edge_points1 = (unsigned int)edge_levels[1] + 1;
  82. const unsigned int int_edge_points2 = (unsigned int)edge_levels[2] + 1;
  83. const unsigned int int_edge_points3 = (unsigned int)edge_levels[3] + 1;
  84. if (unlikely(y0 == 0 && int_edge_points0 < swidth))
  85. stitchGridEdges(int_edge_points0,swidth,x0,x1,u_array,1);
  86. if (unlikely(y1 == sheight-1 && int_edge_points2 < swidth))
  87. stitchGridEdges(int_edge_points2,swidth,x0,x1,&u_array[(grid_v_res-1)*grid_u_res],1);
  88. if (unlikely(x0 == 0 && int_edge_points1 < sheight))
  89. stitchGridEdges(int_edge_points1,sheight,y0,y1,&v_array[grid_u_res-1],grid_u_res);
  90. if (unlikely(x1 == swidth-1 && int_edge_points3 < sheight))
  91. stitchGridEdges(int_edge_points3,sheight,y0,y1,v_array,grid_u_res);
  92. }
  93. __forceinline void gridUVTessellator(const float edge_levels[4],
  94. const unsigned int swidth,
  95. const unsigned int sheight,
  96. const unsigned int x0,
  97. const unsigned int y0,
  98. const unsigned int grid_u_res,
  99. const unsigned int grid_v_res,
  100. float * __restrict__ const u_array,
  101. float * __restrict__ const v_array)
  102. {
  103. assert( grid_u_res >= 1);
  104. assert( grid_v_res >= 1);
  105. assert( edge_levels[0] >= 1.0f );
  106. assert( edge_levels[1] >= 1.0f );
  107. assert( edge_levels[2] >= 1.0f );
  108. assert( edge_levels[3] >= 1.0f );
  109. #if defined(__AVX__)
  110. const vint8 grid_u_segments = vint8(swidth)-1;
  111. const vint8 grid_v_segments = vint8(sheight)-1;
  112. const vfloat8 inv_grid_u_segments = rcp(vfloat8(grid_u_segments));
  113. const vfloat8 inv_grid_v_segments = rcp(vfloat8(grid_v_segments));
  114. unsigned int index = 0;
  115. vint8 v_i( zero );
  116. for (unsigned int y=0;y<grid_v_res;y++,index+=grid_u_res,v_i += 1)
  117. {
  118. vint8 u_i ( step );
  119. const vbool8 m_v = v_i < grid_v_segments;
  120. for (unsigned int x=0;x<grid_u_res;x+=8, u_i += 8)
  121. {
  122. const vbool8 m_u = u_i < grid_u_segments;
  123. const vfloat8 u = select(m_u, vfloat8(x0+u_i) * inv_grid_u_segments, 1.0f);
  124. const vfloat8 v = select(m_v, vfloat8(y0+v_i) * inv_grid_v_segments, 1.0f);
  125. vfloat8::storeu(&u_array[index + x],u);
  126. vfloat8::storeu(&v_array[index + x],v);
  127. }
  128. }
  129. #else
  130. const vint4 grid_u_segments = vint4(swidth)-1;
  131. const vint4 grid_v_segments = vint4(sheight)-1;
  132. const vfloat4 inv_grid_u_segments = rcp(vfloat4(grid_u_segments));
  133. const vfloat4 inv_grid_v_segments = rcp(vfloat4(grid_v_segments));
  134. unsigned int index = 0;
  135. vint4 v_i( zero );
  136. for (unsigned int y=0;y<grid_v_res;y++,index+=grid_u_res,v_i += 1)
  137. {
  138. vint4 u_i ( step );
  139. const vbool4 m_v = v_i < grid_v_segments;
  140. for (unsigned int x=0;x<grid_u_res;x+=4, u_i += 4)
  141. {
  142. const vbool4 m_u = u_i < grid_u_segments;
  143. const vfloat4 u = select(m_u, vfloat4(x0+u_i) * inv_grid_u_segments, 1.0f);
  144. const vfloat4 v = select(m_v, vfloat4(y0+v_i) * inv_grid_v_segments, 1.0f);
  145. vfloat4::storeu(&u_array[index + x],u);
  146. vfloat4::storeu(&v_array[index + x],v);
  147. }
  148. }
  149. #endif
  150. }
  151. }