KiCad PCB EDA Suite
c3d_render_raytracing.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
5  * Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
30 #include <GL/glew.h>
31 #include <climits>
32 
33 #include "c3d_render_raytracing.h"
34 #include "mortoncodes.h"
35 #include "../ccolorrgb.h"
36 #include "3d_fastmath.h"
37 #include "3d_math.h"
38 #include "../common_ogl/ogl_utils.h"
39 #include <profile.h> // To use GetRunningMicroSecs or an other profiling utility
40 
41 // This should be used in future for the function
42 // convertLinearToSRGB
43 //#include <glm/gtc/color_space.hpp>
44 
45 #ifdef _OPENMP
46 #include <omp.h>
47 #endif
48 
50  C3D_RENDER_BASE( aSettings ),
51  m_postshader_ssao( aSettings.CameraGet() )
52 {
53  wxLogTrace( m_logTrace, wxT( "C3D_RENDER_RAYTRACING::C3D_RENDER_RAYTRACING" ) );
54 
56  m_pboId = GL_NONE;
57  m_pboDataSize = 0;
58  m_accelerator = NULL;
61  m_oldWindowsSize.x = 0;
62  m_oldWindowsSize.y = 0;
64  m_firstHitinfo = NULL;
65  m_shaderBuffer = NULL;
66  m_camera_light = NULL;
67 
68  m_xoffset = 0;
69  m_yoffset = 0;
70 
71  m_isPreview = false;
72  m_rt_render_state = RT_RENDER_STATE_MAX; // Set to an initial invalid state
73 }
74 
75 
77 {
78  wxLogTrace( m_logTrace, wxT( "C3D_RENDER_RAYTRACING::~C3D_RENDER_RAYTRACING" ) );
79 
80  delete m_accelerator;
81  m_accelerator = NULL;
82 
85 
86  delete[] m_shaderBuffer;
87  m_shaderBuffer = NULL;
88 
90 }
91 
92 
94 {
95  return 1000; // ms
96 }
97 
98 
100 {
101  // Delete PBO if it was created
103  {
104  if( glIsBufferARB( m_pboId ) )
105  glDeleteBuffers( 1, &m_pboId );
106 
107  m_pboId = GL_NONE;
108  }
109 }
110 
111 
112 void C3D_RENDER_RAYTRACING::SetCurWindowSize( const wxSize &aSize )
113 {
114  if( m_windowSize != aSize )
115  {
116  m_windowSize = aSize;
117  glViewport( 0, 0, m_windowSize.x, m_windowSize.y );
118 
120  }
121 }
122 
123 
125 {
127 
130 
132 
134 
135  // Mark the blocks not processed yet
136  std::fill( m_blockPositionsWasProcessed.begin(),
138  false );
139 }
140 
141 
142 static inline void SetPixel( GLubyte *p, const CCOLORRGB &v )
143 {
144  p[0] = v.c[0]; p[1] = v.c[1]; p[2] = v.c[2]; p[3] = 255;
145 }
146 
147 
148 bool C3D_RENDER_RAYTRACING::Redraw( bool aIsMoving, REPORTER *aStatusTextReporter )
149 {
150  bool requestRedraw = false;
151 
152  // Initialize openGL if need
153  // /////////////////////////////////////////////////////////////////////////
155  {
156  if( !initializeOpenGL() )
157  return false;
158 
159  //aIsMoving = true;
160  requestRedraw = true;
161 
162  // It will assign the first time the windows size, so it will now
163  // revert to preview mode the first time the Redraw is called
166  }
167 
168 
169  // Reload board if it was requested
170  // /////////////////////////////////////////////////////////////////////////
171  if( m_reloadRequested )
172  {
173  if( aStatusTextReporter )
174  aStatusTextReporter->Report( _( "Loading..." ) );
175 
176  //aIsMoving = true;
177  requestRedraw = true;
178  reload( aStatusTextReporter );
179  }
180 
181 
182  // Recalculate constants if windows size was changed
183  // /////////////////////////////////////////////////////////////////////////
185  {
187  aIsMoving = true;
188  requestRedraw = true;
189 
191  }
192 
193 
194  // Clear buffers
195  // /////////////////////////////////////////////////////////////////////////
196  glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
197  glClearDepth( 1.0f );
198  glClearStencil( 0x00 );
199  glClear( GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
200 
201  // 4-byte pixel alignment
202  glPixelStorei( GL_UNPACK_ALIGNMENT, 4 );
203 
204  glDisable( GL_STENCIL_TEST );
205  glDisable( GL_LIGHTING );
206  glDisable( GL_COLOR_MATERIAL );
207  glDisable( GL_DEPTH_TEST );
208  glDisable( GL_TEXTURE_2D );
209  glDisable( GL_BLEND );
210 
211 
212  const bool was_camera_changed = m_settings.CameraGet().ParametersChanged();
213 
214  if( requestRedraw || aIsMoving || was_camera_changed )
215  m_rt_render_state = RT_RENDER_STATE_MAX; // Set to an invalid state,
216  // so it will restart again latter
217 
218 
219  // This will only render if need, otherwise it will redraw the PBO on the screen again
220  if( aIsMoving || was_camera_changed )
221  {
222  // Set head light (camera view light) with the oposite direction of the camera
223  if( m_camera_light )
225 
228 
229  // Bind PBO
230  glBindBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, m_pboId );
231 
232  // Get the PBO pixel pointer to write the data
233  GLubyte *ptrPBO = (GLubyte *)glMapBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB,
234  GL_WRITE_ONLY_ARB );
235 
236  if( ptrPBO )
237  {
238  render_preview( ptrPBO );
239 
240  // release pointer to mapping buffer, this initialize the coping to PBO
241  glUnmapBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB );
242  }
243 
244  glWindowPos2i( m_xoffset, m_yoffset );
245  }
246  else
247  {
248  // Bind PBO
249  glBindBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, m_pboId );
250 
252  {
253  // Get the PBO pixel pointer to write the data
254  GLubyte *ptrPBO = (GLubyte *)glMapBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB,
255  GL_WRITE_ONLY_ARB );
256 
257  if( ptrPBO )
258  {
259  render( ptrPBO, aStatusTextReporter );
260 
262  requestRedraw = true;
263 
264  // release pointer to mapping buffer, this initialize the coping to PBO
265  glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB);
266  }
267  }
268 
270  {
271  glClear( GL_COLOR_BUFFER_BIT );
272  // Options if we want draw background instead
273  //OGL_DrawBackground( SFVEC3F(m_settings.m_BgColorTop),
274  // SFVEC3F(m_settings.m_BgColorBot) );
275  }
276 
277  glWindowPos2i( m_xoffset, m_yoffset );
278  }
279 
280  // This way it will blend the progress rendering with the last buffer. eg:
281  // if it was called after a openGL.
282  glEnable( GL_BLEND );
283  glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
284  glEnable( GL_ALPHA_TEST );
285 
286  glDrawPixels( m_realBufferSize.x,
288  GL_RGBA,
289  GL_UNSIGNED_BYTE,
290  0 );
291 
292  glBindBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, 0 );
293 
294  return requestRedraw;
295 }
296 
297 
298 void C3D_RENDER_RAYTRACING::render( GLubyte *ptrPBO , REPORTER *aStatusTextReporter )
299 {
302  {
304 
305  if( m_camera_light )
307 
309  {
310  // Set all pixels of PBO transparent (Alpha to 0)
311  // This way it will draw the full buffer but only shows the updated (
312  // already calculated) squares
313  // /////////////////////////////////////////////////////////////////////
314  unsigned int nPixels = m_realBufferSize.x * m_realBufferSize.y;
315  GLubyte *tmp_ptrPBO = ptrPBO + 3; // PBO is RGBA
316 
317  for( unsigned int i = 0; i < nPixels; ++i )
318  {
319  *tmp_ptrPBO = 0;
320  tmp_ptrPBO += 4; // PBO is RGBA
321  }
322  }
323 
326  }
327 
328  switch( m_rt_render_state )
329  {
331  rt_render_tracing( ptrPBO, aStatusTextReporter );
332  break;
333 
335  rt_render_post_process_shade( ptrPBO, aStatusTextReporter );
336  break;
337 
339  rt_render_post_process_blur_finish( ptrPBO, aStatusTextReporter );
340  break;
341 
342  default:
343  wxASSERT_MSG( false, "Invalid state on m_rt_render_state");
345  break;
346  }
347 
348  if( aStatusTextReporter && (m_rt_render_state == RT_RENDER_STATE_FINISH) )
349  {
350  // Calculation time in seconds
351  const double calculation_time = (double)( GetRunningMicroSecs() -
353 
354  aStatusTextReporter->Report( wxString::Format( _( "Rendering time %.3f s" ),
355  calculation_time ) );
356  }
357 }
358 
359 
361  REPORTER *aStatusTextReporter )
362 {
363  m_isPreview = false;
364  wxASSERT( m_blockPositions.size() <= LONG_MAX );
365 
366  const long nrBlocks = (long) m_blockPositions.size();
367  const unsigned startTime = GetRunningMicroSecs();
368  bool breakLoop = false;
369  int numBlocksRendered = 0;
370 
371  #pragma omp parallel for schedule(dynamic) shared(breakLoop) \
372  firstprivate(ptrPBO, nrBlocks, startTime) reduction(+:numBlocksRendered) default(none)
373  for( long iBlock = 0; iBlock < nrBlocks; iBlock++ )
374  {
375 
376  #pragma omp flush(breakLoop)
377  if( !breakLoop )
378  {
379  bool process_block;
380 
381  // std::vector<bool> stuffs eight bools to each byte, so access to
382  // them can never be natively atomic.
383  #pragma omp critical(checkProcessBlock)
384  {
385  process_block = !m_blockPositionsWasProcessed[iBlock];
386  m_blockPositionsWasProcessed[iBlock] = true;
387  }
388 
389  if( process_block )
390  {
391  rt_render_trace_block( ptrPBO, iBlock );
392  numBlocksRendered++;
393 
394 
395  // Check if it spend already some time render and request to exit
396  // to display the progress
397  #ifdef _OPENMP
398  if( omp_get_thread_num() == 0 )
399  #endif
400  if( (GetRunningMicroSecs() - startTime) > 150000 )
401  {
402  breakLoop = true;
403  #pragma omp flush(breakLoop)
404  }
405  }
406  }
407  }
408 
409  m_nrBlocksRenderProgress += numBlocksRendered;
410 
411  if( aStatusTextReporter )
412  aStatusTextReporter->Report( wxString::Format( _( "Rendering: %.0f %%" ),
413  (float)(m_nrBlocksRenderProgress * 100) /
414  (float)nrBlocks ) );
415 
416  // Check if it finish the rendering and if should continue to a post processing
417  // or mark it as finished
418  if( m_nrBlocksRenderProgress >= nrBlocks )
419  {
422  else
423  {
425  }
426  }
427 }
428 
429 #ifdef USE_SRGB_SPACE
430 
431 // This should be removed in future when the KiCad support a greater version of
432 // glm lib.
433 
434 #define SRGB_GAMA 2.4f
435 
436 // This function implements the conversion from linear RGB to sRGB
437 // https://github.com/g-truc/glm/blob/master/glm/gtc/color_space.inl#L12
438 static SFVEC3F convertLinearToSRGB( const SFVEC3F &aRGBcolor )
439 {
440  const float gammaCorrection = 1.0f / SRGB_GAMA;
441  const SFVEC3F clampedColor = glm::clamp( aRGBcolor, SFVEC3F(0.0f), SFVEC3F(1.0f) );
442 
443  return glm::mix(
444  glm::pow( clampedColor, SFVEC3F(gammaCorrection) ) * 1.055f - 0.055f,
445  clampedColor * 12.92f,
446  glm::lessThan( clampedColor, SFVEC3F(0.0031308f) ) );
447 }
448 
449 // This function implements the conversion from sRGB to linear RGB
450 // https://github.com/g-truc/glm/blob/master/glm/gtc/color_space.inl#L35
451 SFVEC3F ConvertSRGBToLinear( const SFVEC3F &aSRGBcolor )
452 {
453  const float gammaCorrection = SRGB_GAMA;
454 
455  return glm::mix(
456  glm::pow( (aSRGBcolor + SFVEC3F(0.055f)) * SFVEC3F(0.94786729857819905213270142180095f),
457  SFVEC3F(gammaCorrection) ),
458  aSRGBcolor * SFVEC3F(0.07739938080495356037151702786378f),
459  glm::lessThanEqual( aSRGBcolor, SFVEC3F(0.04045f) ) );
460 }
461 
462 #endif
463 
465  const SFVEC3F &rgbColor,
466  bool applyColorSpaceConversion )
467 {
468 
469  SFVEC3F color = rgbColor;
470 
471 #ifdef USE_SRGB_SPACE
472 
473  // This should be used in future when the KiCad support a greater version of
474  // glm lib.
475  // if( applyColorSpaceConversion )
476  // rgbColor = glm::convertLinearToSRGB( rgbColor );
477 
478  if( applyColorSpaceConversion )
479  color = convertLinearToSRGB( rgbColor );
480 #endif
481 
482  ptrPBO[0] = (unsigned int)glm::clamp( (int)(color.r * 255), 0, 255 );
483  ptrPBO[1] = (unsigned int)glm::clamp( (int)(color.g * 255), 0, 255 );
484  ptrPBO[2] = (unsigned int)glm::clamp( (int)(color.b * 255), 0, 255 );
485  ptrPBO[3] = 255;
486 }
487 
488 
489 static void HITINFO_PACKET_init( HITINFO_PACKET *aHitPacket )
490 {
491  // Initialize hitPacket with a "not hit" information
492  for( unsigned int i = 0; i < RAYPACKET_RAYS_PER_PACKET; ++i )
493  {
494  aHitPacket[i].m_HitInfo.m_tHit = std::numeric_limits<float>::infinity();
495  aHitPacket[i].m_HitInfo.m_acc_node_info = 0;
496  aHitPacket[i].m_hitresult = false;
497  aHitPacket[i].m_HitInfo.m_HitNormal = SFVEC3F();
498  aHitPacket[i].m_HitInfo.m_ShadowFactor = 1.0f;
499  }
500 }
501 
502 
504  const RAY *aRayPkt,
505  HITINFO_PACKET *aHitPacket,
506  bool is_testShadow,
507  SFVEC3F *aOutHitColor )
508 {
509  for( unsigned int y = 0, i = 0; y < RAYPACKET_DIM; ++y )
510  {
511  for( unsigned int x = 0; x < RAYPACKET_DIM; ++x, ++i )
512  {
513  if( aHitPacket[i].m_hitresult == true )
514  {
515  aOutHitColor[i] = shadeHit( bgColorY[y],
516  aRayPkt[i],
517  aHitPacket[i].m_HitInfo,
518  false,
519  0,
520  is_testShadow );
521  }
522  else
523  {
524  aOutHitColor[i] = bgColorY[y];
525  }
526  }
527  }
528 }
529 
530 
532  const HITINFO_PACKET *aHitPck_X0Y0,
533  const HITINFO_PACKET *aHitPck_AA_X1Y1,
534  const RAY *aRayPck,
535  SFVEC3F *aOutHitColor )
536 {
537  const bool is_testShadow = m_settings.GetFlag( FL_RENDER_RAYTRACING_SHADOWS );
538 
539  for( unsigned int y = 0, i = 0; y < RAYPACKET_DIM; ++y )
540  {
541  for( unsigned int x = 0; x < RAYPACKET_DIM; ++x, ++i )
542  {
543  const RAY &rayAA = aRayPck[i];
544 
545  HITINFO hitAA;
546  hitAA.m_tHit = std::numeric_limits<float>::infinity();
547  hitAA.m_acc_node_info = 0;
548 
549  bool hitted = false;
550 
551  const unsigned int idx0y1 = ( x + 0 ) + RAYPACKET_DIM * ( y + 1 );
552  const unsigned int idx1y1 = ( x + 1 ) + RAYPACKET_DIM * ( y + 1 );
553 
554  // Gets the node info from the hit.
555  const unsigned int nodex0y0 = aHitPck_X0Y0[ i ].m_HitInfo.m_acc_node_info;
556  const unsigned int node_AA_x0y0 = aHitPck_AA_X1Y1[ i ].m_HitInfo.m_acc_node_info;
557 
558  unsigned int nodex1y0 = 0;
559 
560  if( x < (RAYPACKET_DIM - 1) )
561  nodex1y0 = aHitPck_X0Y0[ i + 1 ].m_HitInfo.m_acc_node_info;
562 
563  unsigned int nodex0y1 = 0;
564 
565  if( y < (RAYPACKET_DIM - 1) )
566  nodex0y1 = aHitPck_X0Y0[ idx0y1 ].m_HitInfo.m_acc_node_info;
567 
568  unsigned int nodex1y1 = 0;
569 
570  if( ((x < (RAYPACKET_DIM - 1)) &&
571  (y < (RAYPACKET_DIM - 1))) )
572  nodex1y1 = aHitPck_X0Y0[ idx1y1 ].m_HitInfo.m_acc_node_info;
573 
574 
575  if( ((nodex0y0 == nodex1y0) || (nodex1y0 == 0)) && // If all notes are equal we assume there was no change on the object hits
576  ((nodex0y0 == nodex0y1) || (nodex0y1 == 0)) &&
577  ((nodex0y0 == nodex1y1) || (nodex1y1 == 0)) &&
578  (nodex0y0 == node_AA_x0y0) )
579  {
580  // Option 1
581  // This option will give a very good quality on reflections (slow)
582  /*
583  if( m_accelerator->Intersect( rayAA, hitAA, nodex0y0 ) )
584  {
585  aOutHitColor[i] += shadeHit( aBgColorY[y], rayAA, hitAA, false, 0 );
586  }
587  else
588  {
589  if( m_accelerator->Intersect( rayAA, hitAA ) )
590  aOutHitColor[i] += shadeHit( aBgColorY[y], rayAA, hitAA, false, 0 );
591  else
592  aOutHitColor[i] += hitColor[i];
593  }
594  */
595 
596  // Option 2
597  // Trace again with the same node,
598  // then if miss just give the same color as before
599  //if( m_accelerator->Intersect( rayAA, hitAA, nodex0y0 ) )
600  // aOutHitColor[i] += shadeHit( aBgColorY[y], rayAA, hitAA, false, 0 );
601 
602  // Option 3
603  // Use same color
604 
605  }
606  else
607  {
608  // Try to intersect the different nodes
609  // It tests the possible combination of hitted or not hitted points
610  // This will try to get the best hit for this ray
611 
612  if( nodex0y0 != 0 )
613  hitted |= m_accelerator->Intersect( rayAA, hitAA, nodex0y0 );
614 
615  if( ( nodex1y0 != 0 ) &&
616  ( nodex0y0 != nodex1y0 ) )
617  hitted |= m_accelerator->Intersect( rayAA, hitAA, nodex1y0 );
618 
619  if( ( nodex0y1 != 0 ) &&
620  ( nodex0y0 != nodex0y1 ) &&
621  ( nodex1y0 != nodex0y1 ) )
622  hitted |= m_accelerator->Intersect( rayAA, hitAA, nodex0y1 );
623 
624  if( (nodex1y1 != 0 ) &&
625  ( nodex0y0 != nodex1y1 ) &&
626  ( nodex0y1 != nodex1y1 ) &&
627  ( nodex1y0 != nodex1y1 ) )
628  hitted |= m_accelerator->Intersect( rayAA, hitAA, nodex1y1 );
629 
630  if( (node_AA_x0y0 != 0 ) &&
631  ( nodex0y0 != node_AA_x0y0 ) &&
632  ( nodex0y1 != node_AA_x0y0 ) &&
633  ( nodex1y0 != node_AA_x0y0 ) &&
634  ( nodex1y1 != node_AA_x0y0 ) )
635  hitted |= m_accelerator->Intersect( rayAA, hitAA, node_AA_x0y0 );
636 
637  if( hitted )
638  {
639  // If we got any result, shade it
640  aOutHitColor[i] = shadeHit( aBgColorY[y], rayAA, hitAA, false, 0, is_testShadow );
641  }
642  else
643  {
644  // Note: There are very few cases that will end on this situation
645  // so it is not so expensive to trace a single ray from the beginning
646 
647  // It was missed the 'last nodes' so, trace a ray from the beginning
648  if( m_accelerator->Intersect( rayAA, hitAA ) )
649  aOutHitColor[i] = shadeHit( aBgColorY[y], rayAA, hitAA, false, 0, is_testShadow );
650  }
651  }
652  }
653  }
654 }
655 
656 #define DISP_FACTOR 0.075f
657 
659  signed int iBlock )
660 {
661  // Initialize ray packets
662  // /////////////////////////////////////////////////////////////////////////
663  const SFVEC2UI &blockPos = m_blockPositions[iBlock];
664  const SFVEC2I blockPosI = SFVEC2I( blockPos.x + m_xoffset,
665  blockPos.y + m_yoffset );
666 
667  RAYPACKET blockPacket( m_settings.CameraGet(),
668  (SFVEC2F)blockPosI + SFVEC2F(DISP_FACTOR, DISP_FACTOR),
669  SFVEC2F(DISP_FACTOR, DISP_FACTOR) // Displacement random factor
670  );
671 
673 
674  HITINFO_PACKET_init( hitPacket_X0Y0 );
675 
676  // Calculate background gradient color
677  // /////////////////////////////////////////////////////////////////////////
678  SFVEC3F bgColor[RAYPACKET_DIM];// Store a vertical gradient color
679 
680  for( unsigned int y = 0; y < RAYPACKET_DIM; ++y )
681  {
682  const float posYfactor = (float)(blockPosI.y + y) / (float)m_windowSize.y;
683 
684  bgColor[y] = m_BgColorTop_LinearRGB * SFVEC3F(posYfactor) +
685  m_BgColorBot_LinearRGB * ( SFVEC3F(1.0f) - SFVEC3F(posYfactor) );
686  }
687 
688  // Intersect ray packets (calculate the intersection with rays and objects)
689  // /////////////////////////////////////////////////////////////////////////
690  if( !m_accelerator->Intersect( blockPacket, hitPacket_X0Y0 ) )
691  {
692 
693  // If block is empty then set shades and continue
695  {
696  for( unsigned int y = 0; y < RAYPACKET_DIM; ++y )
697  {
698  const SFVEC3F &outColor = bgColor[y];
699 
700  const unsigned int yBlockPos = blockPos.y + y;
701 
702  for( unsigned int x = 0; x < RAYPACKET_DIM; ++x )
703  {
704  m_postshader_ssao.SetPixelData( blockPos.x + x,
705  yBlockPos,
706  SFVEC3F(),
707  outColor,
708  SFVEC3F(),
709  0,
710  1.0f );
711  }
712  }
713  }
714 
715  // This will set the output color to be displayed
716  // If post processing is enabled, it will not reflect the final result
717  // (as the final color will be computed on post processing)
718  // but it is used for report progress
719 
720  const bool isFinalColor = !m_settings.GetFlag( FL_RENDER_RAYTRACING_POST_PROCESSING );
721 
722  for( unsigned int y = 0; y < RAYPACKET_DIM; ++y )
723  {
724  const SFVEC3F &outColor = bgColor[y];
725 
726  const unsigned int yConst = blockPos.x +
727  ( (y + blockPos.y) * m_realBufferSize.x);
728 
729  for( unsigned int x = 0; x < RAYPACKET_DIM; ++x )
730  {
731  GLubyte *ptr = &ptrPBO[ (yConst + x) * 4 ];
732 
733  rt_final_color( ptr, outColor, isFinalColor );
734  }
735  }
736 
737  // There is nothing more here to do.. there are no hits ..
738  // just background so continue
739  return;
740  }
741 
742 
743  SFVEC3F hitColor_X0Y0[RAYPACKET_RAYS_PER_PACKET];
744 
745  // Shade original (0, 0) hits ("paint" the intersected objects)
746  // /////////////////////////////////////////////////////////////////////////
747  rt_shades_packet( bgColor,
748  blockPacket.m_ray,
749  hitPacket_X0Y0,
751  hitColor_X0Y0 );
752 
754  {
755  SFVEC3F hitColor_AA_X1Y1[RAYPACKET_RAYS_PER_PACKET];
756 
757 
758  // Intersect one blockPosI + (0.5, 0.5) used for anti aliasing calculation
759  // /////////////////////////////////////////////////////////////////////////
760  HITINFO_PACKET hitPacket_AA_X1Y1[RAYPACKET_RAYS_PER_PACKET];
761  HITINFO_PACKET_init( hitPacket_AA_X1Y1 );
762 
763  RAYPACKET blockPacket_AA_X1Y1( m_settings.CameraGet(),
764  (SFVEC2F)blockPosI + SFVEC2F(0.5f, 0.5f),
765  SFVEC2F(DISP_FACTOR, DISP_FACTOR) // Displacement random factor
766  );
767 
768  if( !m_accelerator->Intersect( blockPacket_AA_X1Y1, hitPacket_AA_X1Y1 ) )
769  {
770  // Missed all the package
771  for( unsigned int y = 0, i = 0; y < RAYPACKET_DIM; ++y )
772  {
773  const SFVEC3F &outColor = bgColor[y];
774 
775  for( unsigned int x = 0; x < RAYPACKET_DIM; ++x, ++i )
776  {
777  hitColor_AA_X1Y1[i] = outColor;
778  }
779  }
780  }
781  else
782  {
783  rt_shades_packet( bgColor,
784  blockPacket_AA_X1Y1.m_ray,
785  hitPacket_AA_X1Y1,
787  hitColor_AA_X1Y1
788  );
789  }
790 
791  SFVEC3F hitColor_AA_X1Y0[RAYPACKET_RAYS_PER_PACKET];
792  SFVEC3F hitColor_AA_X0Y1[RAYPACKET_RAYS_PER_PACKET];
793  SFVEC3F hitColor_AA_X0Y1_half[RAYPACKET_RAYS_PER_PACKET];
794 
795  for( unsigned int i = 0; i < RAYPACKET_RAYS_PER_PACKET; ++i )
796  {
797  const SFVEC3F color_average = ( hitColor_X0Y0[i] +
798  hitColor_AA_X1Y1[i] ) * SFVEC3F(0.5f);
799 
800  hitColor_AA_X1Y0[i] = color_average;
801  hitColor_AA_X0Y1[i] = color_average;
802  hitColor_AA_X0Y1_half[i] = color_average;
803  }
804 
805  RAY blockRayPck_AA_X1Y0[RAYPACKET_RAYS_PER_PACKET];
806  RAY blockRayPck_AA_X0Y1[RAYPACKET_RAYS_PER_PACKET];
807  RAY blockRayPck_AA_X1Y1_half[RAYPACKET_RAYS_PER_PACKET];
808 
810  (SFVEC2F)blockPosI + SFVEC2F(0.5f - DISP_FACTOR, DISP_FACTOR),
811  SFVEC2F(DISP_FACTOR, DISP_FACTOR), // Displacement random factor
812  blockRayPck_AA_X1Y0 );
813 
815  (SFVEC2F)blockPosI + SFVEC2F(DISP_FACTOR, 0.5f - DISP_FACTOR),
816  SFVEC2F(DISP_FACTOR, DISP_FACTOR), // Displacement random factor
817  blockRayPck_AA_X0Y1 );
818 
820  (SFVEC2F)blockPosI + SFVEC2F(0.25f - DISP_FACTOR, 0.25f - DISP_FACTOR),
821  SFVEC2F(DISP_FACTOR, DISP_FACTOR), // Displacement random factor
822  blockRayPck_AA_X1Y1_half );
823 
824  rt_trace_AA_packet( bgColor,
825  hitPacket_X0Y0, hitPacket_AA_X1Y1,
826  blockRayPck_AA_X1Y0,
827  hitColor_AA_X1Y0 );
828 
829  rt_trace_AA_packet( bgColor,
830  hitPacket_X0Y0, hitPacket_AA_X1Y1,
831  blockRayPck_AA_X0Y1,
832  hitColor_AA_X0Y1 );
833 
834  rt_trace_AA_packet( bgColor,
835  hitPacket_X0Y0, hitPacket_AA_X1Y1,
836  blockRayPck_AA_X1Y1_half,
837  hitColor_AA_X0Y1_half );
838 
839  // Average the result
840  for( unsigned int i = 0; i < RAYPACKET_RAYS_PER_PACKET; ++i )
841  {
842  hitColor_X0Y0[i] = ( hitColor_X0Y0[i] +
843  hitColor_AA_X1Y1[i] +
844  hitColor_AA_X1Y0[i] +
845  hitColor_AA_X0Y1[i] +
846  hitColor_AA_X0Y1_half[i]
847  ) * SFVEC3F(1.0f / 5.0f);
848  }
849  }
850 
851 
852  // Copy results to the next stage
853  // /////////////////////////////////////////////////////////////////////
854 
855  GLubyte *ptr = &ptrPBO[ ( blockPos.x +
856  (blockPos.y * m_realBufferSize.x) ) * 4 ];
857 
858  const uint32_t ptrInc = (m_realBufferSize.x - RAYPACKET_DIM) * 4;
859 
861  {
862  SFVEC2I bPos;
863  bPos.y = blockPos.y;
864 
865  for( unsigned int y = 0, i = 0; y < RAYPACKET_DIM; ++y )
866  {
867  bPos.x = blockPos.x;
868 
869  for( unsigned int x = 0; x < RAYPACKET_DIM; ++x, ++i )
870  {
871  const SFVEC3F &hColor = hitColor_X0Y0[i];
872 
873  if( hitPacket_X0Y0[i].m_hitresult == true )
874  m_postshader_ssao.SetPixelData( bPos.x, bPos.y,
875  hitPacket_X0Y0[i].m_HitInfo.m_HitNormal,
876  hColor,
877  blockPacket.m_ray[i].at(
878  hitPacket_X0Y0[i].m_HitInfo.m_tHit ),
879  hitPacket_X0Y0[i].m_HitInfo.m_tHit,
880  hitPacket_X0Y0[i].m_HitInfo.m_ShadowFactor );
881  else
882  m_postshader_ssao.SetPixelData( bPos.x, bPos.y,
883  SFVEC3F(),
884  hColor,
885  SFVEC3F(),
886  0,
887  1.0f );
888 
889  rt_final_color( ptr, hColor, false );
890 
891  bPos.x++;
892  ptr += 4;
893  }
894 
895  ptr += ptrInc;
896  bPos.y++;
897  }
898  }
899  else
900  {
901  for( unsigned int y = 0, i = 0; y < RAYPACKET_DIM; ++y )
902  {
903  for( unsigned int x = 0; x < RAYPACKET_DIM; ++x, ++i )
904  {
905  rt_final_color( ptr, hitColor_X0Y0[i], true );
906  ptr += 4;
907  }
908 
909  ptr += ptrInc;
910  }
911  }
912 }
913 
914 
916  REPORTER *aStatusTextReporter )
917 {
918  (void)ptrPBO; // unused
919 
921  {
922  if( aStatusTextReporter )
923  aStatusTextReporter->Report( _("Rendering: Post processing shader") );
924 
925  // Compute the shader value
926  #pragma omp parallel for schedule(dynamic)
927  for( signed int y = 0; y < (int)m_realBufferSize.y; ++y )
928  {
929  SFVEC3F *ptr = &m_shaderBuffer[ y * m_realBufferSize.x ];
930 
931  for( signed int x = 0; x < (int)m_realBufferSize.x; ++x )
932  {
933  *ptr = m_postshader_ssao.Shade( SFVEC2I( x, y ) );
934  ptr++;
935  }
936  }
937 
938  // Wait for all threads to finish
939  #pragma omp barrier
940 
941  // Set next state
943  }
944  else
945  {
946  // As this was an invalid state, set to finish
948  }
949 }
950 
951 
953  REPORTER *aStatusTextReporter )
954 {
955  (void)aStatusTextReporter; //unused
956 
958  {
959  // Now blurs the shader result and compute the final color
960  #pragma omp parallel for schedule(dynamic)
961  for( signed int y = 0; y < (int)m_realBufferSize.y; ++y )
962  {
963  GLubyte *ptr = &ptrPBO[ y * m_realBufferSize.x * 4 ];
964 
965  SFVEC3F *ptrShaderY0 =
966  &m_shaderBuffer[ glm::max((int)y - 2, 0) * m_realBufferSize.x ];
967  SFVEC3F *ptrShaderY1 =
968  &m_shaderBuffer[ glm::max((int)y - 1, 0) * m_realBufferSize.x ];
969  SFVEC3F *ptrShaderY2 =
971  SFVEC3F *ptrShaderY3 =
972  &m_shaderBuffer[ glm::min((int)y + 1, (int)(m_realBufferSize.y - 1)) *
973  m_realBufferSize.x ];
974  SFVEC3F *ptrShaderY4 =
975  &m_shaderBuffer[ glm::min((int)y + 2, (int)(m_realBufferSize.y - 1)) *
976  m_realBufferSize.x ];
977 
978  for( signed int x = 0; x < (int)m_realBufferSize.x; ++x )
979  {
980 // This #if should be 1, it is here that can be used for debug proposes during development
981 #if 1
982 
983  SFVEC3F bluredShadeColor = (*ptrShaderY0) * 1.0f / 273.0f +
984  (*ptrShaderY1) * 4.0f / 273.0f +
985  (*ptrShaderY2) * 7.0f / 273.0f +
986  (*ptrShaderY3) * 4.0f / 273.0f +
987  (*ptrShaderY4) * 1.0f / 273.0f;
988  if( x > 1 )
989  {
990  ptrShaderY0++;
991  ptrShaderY1++;
992  ptrShaderY2++;
993  ptrShaderY3++;
994  ptrShaderY4++;
995  }
996 
997  bluredShadeColor += (*ptrShaderY0) * 4.0f / 273.0f +
998  (*ptrShaderY1) *16.0f / 273.0f +
999  (*ptrShaderY2) *26.0f / 273.0f +
1000  (*ptrShaderY3) *16.0f / 273.0f +
1001  (*ptrShaderY4) * 4.0f / 273.0f;
1002 
1003  if( x > 0 )
1004  {
1005  ptrShaderY0++;
1006  ptrShaderY1++;
1007  ptrShaderY2++;
1008  ptrShaderY3++;
1009  ptrShaderY4++;
1010  }
1011 
1012  bluredShadeColor += (*ptrShaderY0) * 7.0f / 273.0f +
1013  (*ptrShaderY1) *26.0f / 273.0f +
1014  (*ptrShaderY2) *41.0f / 273.0f +
1015  (*ptrShaderY3) *26.0f / 273.0f +
1016  (*ptrShaderY4) * 7.0f / 273.0f;
1017 
1018  if( x < ((int)m_realBufferSize.x - 1) )
1019  {
1020  ptrShaderY0++;
1021  ptrShaderY1++;
1022  ptrShaderY2++;
1023  ptrShaderY3++;
1024  ptrShaderY4++;
1025  }
1026 
1027  bluredShadeColor += (*ptrShaderY0) * 4.0f / 273.0f +
1028  (*ptrShaderY1) *16.0f / 273.0f +
1029  (*ptrShaderY2) *26.0f / 273.0f +
1030  (*ptrShaderY3) *16.0f / 273.0f +
1031  (*ptrShaderY4) * 4.0f / 273.0f;
1032 
1033  if( x < ((int)m_realBufferSize.x - 2) )
1034  {
1035  ptrShaderY0++;
1036  ptrShaderY1++;
1037  ptrShaderY2++;
1038  ptrShaderY3++;
1039  ptrShaderY4++;
1040  }
1041 
1042  bluredShadeColor += (*ptrShaderY0) * 1.0f / 273.0f +
1043  (*ptrShaderY1) * 4.0f / 273.0f +
1044  (*ptrShaderY2) * 7.0f / 273.0f +
1045  (*ptrShaderY3) * 4.0f / 273.0f +
1046  (*ptrShaderY4) * 1.0f / 273.0f;
1047 
1048  ptrShaderY0-= 3;
1049  ptrShaderY1-= 3;
1050  ptrShaderY2-= 3;
1051  ptrShaderY3-= 3;
1052  ptrShaderY4-= 3;
1053 
1054 #ifdef USE_SRGB_SPACE
1056 #else
1057  const SFVEC3F originColor = m_postshader_ssao.GetColorAtNotProtected( SFVEC2I( x,y ) );
1058 #endif
1059 
1060  const SFVEC3F shadedColor = m_postshader_ssao.ApplyShadeColor( SFVEC2I( x,y ), originColor, bluredShadeColor );
1061 #else
1062  // Debug code
1063  //const SFVEC3F shadedColor = SFVEC3F( 1.0f ) -
1064  // m_shaderBuffer[ y * m_realBufferSize.x + x];
1065  const SFVEC3F shadedColor = m_shaderBuffer[ y * m_realBufferSize.x + x ];
1066 #endif
1067 
1068  rt_final_color( ptr, shadedColor, false );
1069 
1070  ptr += 4;
1071  }
1072  }
1073 
1074  // Wait for all threads to finish
1075  #pragma omp barrier
1076 
1077  // Debug code
1078  //m_postshader_ssao.DebugBuffersOutputAsImages();
1079  }
1080 
1081  // End rendering
1083 }
1084 
1085 
1087 {
1088  m_isPreview = true;
1089 
1090  unsigned int nrBlocks = m_blockPositionsFast.size();
1091 
1092  #pragma omp parallel for schedule(dynamic)
1093  for( signed int iBlock = 0; iBlock < (int)nrBlocks; iBlock++ )
1094  {
1095  const SFVEC2UI &windowPosUI = m_blockPositionsFast[ iBlock ];
1096  const SFVEC2I windowsPos = SFVEC2I( windowPosUI.x + m_xoffset,
1097  windowPosUI.y + m_yoffset );
1098 
1099  RAYPACKET blockPacket( m_settings.CameraGet(), windowsPos, 4 );
1100 
1102 
1103  // Initialize hitPacket with a "not hit" information
1104  for( unsigned int i = 0; i < RAYPACKET_RAYS_PER_PACKET; ++i )
1105  {
1106  hitPacket[i].m_HitInfo.m_tHit = std::numeric_limits<float>::infinity();
1107  hitPacket[i].m_HitInfo.m_acc_node_info = 0;
1108  hitPacket[i].m_hitresult = false;
1109  }
1110 
1111  // Intersect packet block
1112  m_accelerator->Intersect( blockPacket, hitPacket );
1113 
1114 
1115  // Calculate background gradient color
1116  // /////////////////////////////////////////////////////////////////////
1117  SFVEC3F bgColor[RAYPACKET_DIM];
1118 
1119  for( unsigned int y = 0; y < RAYPACKET_DIM; ++y )
1120  {
1121  const float posYfactor = (float)(windowsPos.y + y * 4.0f) / (float)m_windowSize.y;
1122 
1123  bgColor[y] = (SFVEC3F)m_settings.m_BgColorTop * SFVEC3F(posYfactor) +
1124  (SFVEC3F)m_settings.m_BgColorBot * ( SFVEC3F(1.0f) - SFVEC3F(posYfactor) );
1125  }
1126 
1127  CCOLORRGB hitColorShading[RAYPACKET_RAYS_PER_PACKET];
1128 
1129  for( unsigned int i = 0; i < RAYPACKET_RAYS_PER_PACKET; ++i )
1130  {
1131  const SFVEC3F bhColorY = bgColor[i / RAYPACKET_DIM];
1132 
1133  if( hitPacket[i].m_hitresult == true )
1134  {
1135  const SFVEC3F hitColor = shadeHit( bhColorY,
1136  blockPacket.m_ray[i],
1137  hitPacket[i].m_HitInfo,
1138  false,
1139  0,
1140  false );
1141 
1142  hitColorShading[i] = CCOLORRGB( hitColor );
1143  }
1144  else
1145  hitColorShading[i] = bhColorY;
1146  }
1147 
1148  CCOLORRGB cLRB_old[(RAYPACKET_DIM - 1)];
1149 
1150  for( unsigned int y = 0; y < (RAYPACKET_DIM - 1); ++y )
1151  {
1152 
1153  const SFVEC3F bgColorY = bgColor[y];
1154  const CCOLORRGB bgColorYRGB = CCOLORRGB( bgColorY );
1155 
1156  // This stores cRTB from the last block to be reused next time in a cLTB pixel
1157  CCOLORRGB cRTB_old;
1158 
1159  //RAY cRTB_ray;
1160  //HITINFO cRTB_hitInfo;
1161 
1162  for( unsigned int x = 0; x < (RAYPACKET_DIM - 1); ++x )
1163  {
1164  // pxl 0 pxl 1 pxl 2 pxl 3 pxl 4
1165  // x0 x1 ...
1166  // .---------------------------.
1167  // y0 | cLT | cxxx | cLRT | cxxx | cRT |
1168  // | cxxx | cLTC | cxxx | cRTC | cxxx |
1169  // | cLTB | cxxx | cC | cxxx | cRTB |
1170  // | cxxx | cLBC | cxxx | cRBC | cxxx |
1171  // '---------------------------'
1172  // y1 | cLB | cxxx | cLRB | cxxx | cRB |
1173 
1174  const unsigned int iLT = ((x + 0) + RAYPACKET_DIM * (y + 0));
1175  const unsigned int iRT = ((x + 1) + RAYPACKET_DIM * (y + 0));
1176  const unsigned int iLB = ((x + 0) + RAYPACKET_DIM * (y + 1));
1177  const unsigned int iRB = ((x + 1) + RAYPACKET_DIM * (y + 1));
1178 
1179  // !TODO: skip when there are no hits
1180 
1181 
1182  const CCOLORRGB &cLT = hitColorShading[ iLT ];
1183  const CCOLORRGB &cRT = hitColorShading[ iRT ];
1184  const CCOLORRGB &cLB = hitColorShading[ iLB ];
1185  const CCOLORRGB &cRB = hitColorShading[ iRB ];
1186 
1187  // Trace and shade cC
1188  // /////////////////////////////////////////////////////////////
1189  CCOLORRGB cC = bgColorYRGB;
1190 
1191  const SFVEC3F &oriLT = blockPacket.m_ray[ iLT ].m_Origin;
1192  const SFVEC3F &oriRB = blockPacket.m_ray[ iRB ].m_Origin;
1193 
1194  const SFVEC3F &dirLT = blockPacket.m_ray[ iLT ].m_Dir;
1195  const SFVEC3F &dirRB = blockPacket.m_ray[ iRB ].m_Dir;
1196 
1197  SFVEC3F oriC;
1198  SFVEC3F dirC;
1199 
1200  HITINFO centerHitInfo;
1201  centerHitInfo.m_tHit = std::numeric_limits<float>::infinity();
1202 
1203  bool hittedC = false;
1204 
1205  if( (hitPacket[ iLT ].m_hitresult == true) ||
1206  (hitPacket[ iRT ].m_hitresult == true) ||
1207  (hitPacket[ iLB ].m_hitresult == true) ||
1208  (hitPacket[ iRB ].m_hitresult == true) )
1209  {
1210 
1211  oriC = ( oriLT + oriRB ) * 0.5f;
1212  dirC = glm::normalize( ( dirLT + dirRB ) * 0.5f );
1213 
1214  // Trace the center ray
1215  RAY centerRay;
1216  centerRay.Init( oriC, dirC );
1217 
1218  const unsigned int nodeLT = hitPacket[ iLT ].m_HitInfo.m_acc_node_info;
1219  const unsigned int nodeRT = hitPacket[ iRT ].m_HitInfo.m_acc_node_info;
1220  const unsigned int nodeLB = hitPacket[ iLB ].m_HitInfo.m_acc_node_info;
1221  const unsigned int nodeRB = hitPacket[ iRB ].m_HitInfo.m_acc_node_info;
1222 
1223  if( nodeLT != 0 )
1224  hittedC |= m_accelerator->Intersect( centerRay, centerHitInfo, nodeLT );
1225 
1226  if( ( nodeRT != 0 ) &&
1227  ( nodeRT != nodeLT ) )
1228  hittedC |= m_accelerator->Intersect( centerRay, centerHitInfo, nodeRT );
1229 
1230  if( ( nodeLB != 0 ) &&
1231  ( nodeLB != nodeLT ) &&
1232  ( nodeLB != nodeRT ) )
1233  hittedC |= m_accelerator->Intersect( centerRay, centerHitInfo, nodeLB );
1234 
1235  if( ( nodeRB != 0 ) &&
1236  ( nodeRB != nodeLB ) &&
1237  ( nodeRB != nodeLT ) &&
1238  ( nodeRB != nodeRT ) )
1239  hittedC |= m_accelerator->Intersect( centerRay, centerHitInfo, nodeRB );
1240 
1241  if( hittedC )
1242  cC = CCOLORRGB( shadeHit( bgColorY, centerRay, centerHitInfo, false, 0, false ) );
1243  else
1244  {
1245  centerHitInfo.m_tHit = std::numeric_limits<float>::infinity();
1246  hittedC = m_accelerator->Intersect( centerRay, centerHitInfo );
1247 
1248  if( hittedC )
1249  cC = CCOLORRGB( shadeHit( bgColorY,
1250  centerRay,
1251  centerHitInfo,
1252  false,
1253  0,
1254  false ) );
1255  }
1256  }
1257 
1258  // Trace and shade cLRT
1259  // /////////////////////////////////////////////////////////////
1260  CCOLORRGB cLRT = bgColorYRGB;
1261 
1262  const SFVEC3F &oriRT = blockPacket.m_ray[ iRT ].m_Origin;
1263  const SFVEC3F &dirRT = blockPacket.m_ray[ iRT ].m_Dir;
1264 
1265  if( y == 0 )
1266  {
1267  // Trace the center ray
1268  RAY rayLRT;
1269  rayLRT.Init( ( oriLT + oriRT ) * 0.5f,
1270  glm::normalize( ( dirLT + dirRT ) * 0.5f ) );
1271 
1272  HITINFO hitInfoLRT;
1273  hitInfoLRT.m_tHit = std::numeric_limits<float>::infinity();
1274 
1275  if( hitPacket[ iLT ].m_hitresult &&
1276  hitPacket[ iRT ].m_hitresult &&
1277  (hitPacket[ iLT ].m_HitInfo.pHitObject == hitPacket[ iRT ].m_HitInfo.pHitObject) )
1278  {
1279  hitInfoLRT.pHitObject = hitPacket[ iLT ].m_HitInfo.pHitObject;
1280  hitInfoLRT.m_tHit = ( hitPacket[ iLT ].m_HitInfo.m_tHit +
1281  hitPacket[ iRT ].m_HitInfo.m_tHit ) * 0.5f;
1282  hitInfoLRT.m_HitNormal =
1283  glm::normalize( ( hitPacket[ iLT ].m_HitInfo.m_HitNormal +
1284  hitPacket[ iRT ].m_HitInfo.m_HitNormal ) * 0.5f );
1285 
1286  cLRT = CCOLORRGB( shadeHit( bgColorY, rayLRT, hitInfoLRT, false, 0, false ) );
1287  cLRT = BlendColor( cLRT, BlendColor( cLT, cRT) );
1288  }
1289  else
1290  {
1291  if( hitPacket[ iLT ].m_hitresult ||
1292  hitPacket[ iRT ].m_hitresult ) // If any hits
1293  {
1294  const unsigned int nodeLT = hitPacket[ iLT ].m_HitInfo.m_acc_node_info;
1295  const unsigned int nodeRT = hitPacket[ iRT ].m_HitInfo.m_acc_node_info;
1296 
1297  bool hittedLRT = false;
1298 
1299  if( nodeLT != 0 )
1300  hittedLRT |= m_accelerator->Intersect( rayLRT, hitInfoLRT, nodeLT );
1301 
1302  if( ( nodeRT != 0 ) &&
1303  ( nodeRT != nodeLT ) )
1304  hittedLRT |= m_accelerator->Intersect( rayLRT,
1305  hitInfoLRT,
1306  nodeRT );
1307 
1308  if( hittedLRT )
1309  cLRT = CCOLORRGB( shadeHit( bgColorY,
1310  rayLRT,
1311  hitInfoLRT,
1312  false,
1313  0,
1314  false ) );
1315  else
1316  {
1317  hitInfoLRT.m_tHit = std::numeric_limits<float>::infinity();
1318 
1319  if( m_accelerator->Intersect( rayLRT,hitInfoLRT ) )
1320  cLRT = CCOLORRGB( shadeHit( bgColorY,
1321  rayLRT,
1322  hitInfoLRT,
1323  false,
1324  0,
1325  false ) );
1326  }
1327  }
1328  }
1329  }
1330  else
1331  cLRT = cLRB_old[x];
1332 
1333 
1334  // Trace and shade cLTB
1335  // /////////////////////////////////////////////////////////////
1336  CCOLORRGB cLTB = bgColorYRGB;
1337 
1338  if( x == 0 )
1339  {
1340  const SFVEC3F &oriLB = blockPacket.m_ray[ iLB ].m_Origin;
1341  const SFVEC3F &dirLB = blockPacket.m_ray[ iLB ].m_Dir;
1342 
1343  // Trace the center ray
1344  RAY rayLTB;
1345  rayLTB.Init( ( oriLT + oriLB ) * 0.5f,
1346  glm::normalize( ( dirLT + dirLB ) * 0.5f ) );
1347 
1348  HITINFO hitInfoLTB;
1349  hitInfoLTB.m_tHit = std::numeric_limits<float>::infinity();
1350 
1351  if( hitPacket[ iLT ].m_hitresult &&
1352  hitPacket[ iLB ].m_hitresult &&
1353  ( hitPacket[ iLT ].m_HitInfo.pHitObject ==
1354  hitPacket[ iLB ].m_HitInfo.pHitObject ) )
1355  {
1356  hitInfoLTB.pHitObject = hitPacket[ iLT ].m_HitInfo.pHitObject;
1357  hitInfoLTB.m_tHit = ( hitPacket[ iLT ].m_HitInfo.m_tHit +
1358  hitPacket[ iLB ].m_HitInfo.m_tHit ) * 0.5f;
1359  hitInfoLTB.m_HitNormal =
1360  glm::normalize( ( hitPacket[ iLT ].m_HitInfo.m_HitNormal +
1361  hitPacket[ iLB ].m_HitInfo.m_HitNormal ) * 0.5f );
1362  cLTB = CCOLORRGB( shadeHit( bgColorY, rayLTB, hitInfoLTB, false, 0, false ) );
1363  cLTB = BlendColor( cLTB, BlendColor( cLT, cLB) );
1364  }
1365  else
1366  {
1367  if( hitPacket[ iLT ].m_hitresult ||
1368  hitPacket[ iLB ].m_hitresult ) // If any hits
1369  {
1370  const unsigned int nodeLT = hitPacket[ iLT ].m_HitInfo.m_acc_node_info;
1371  const unsigned int nodeLB = hitPacket[ iLB ].m_HitInfo.m_acc_node_info;
1372 
1373  bool hittedLTB = false;
1374 
1375  if( nodeLT != 0 )
1376  hittedLTB |= m_accelerator->Intersect( rayLTB,
1377  hitInfoLTB,
1378  nodeLT );
1379 
1380  if( ( nodeLB != 0 ) &&
1381  ( nodeLB != nodeLT ) )
1382  hittedLTB |= m_accelerator->Intersect( rayLTB,
1383  hitInfoLTB,
1384  nodeLB );
1385 
1386  if( hittedLTB )
1387  cLTB = CCOLORRGB( shadeHit( bgColorY,
1388  rayLTB,
1389  hitInfoLTB,
1390  false,
1391  0,
1392  false ) );
1393  else
1394  {
1395  hitInfoLTB.m_tHit = std::numeric_limits<float>::infinity();
1396 
1397  if( m_accelerator->Intersect( rayLTB, hitInfoLTB ) )
1398  cLTB = CCOLORRGB( shadeHit( bgColorY,
1399  rayLTB,
1400  hitInfoLTB,
1401  false,
1402  0,
1403  false ) );
1404  }
1405  }
1406  }
1407  }
1408  else
1409  cLTB = cRTB_old;
1410 
1411 
1412  // Trace and shade cRTB
1413  // /////////////////////////////////////////////////////////////
1414  CCOLORRGB cRTB = bgColorYRGB;
1415 
1416  // Trace the center ray
1417  RAY rayRTB;
1418  rayRTB.Init( ( oriRT + oriRB ) * 0.5f,
1419  glm::normalize( ( dirRT + dirRB ) * 0.5f ) );
1420 
1421  HITINFO hitInfoRTB;
1422  hitInfoRTB.m_tHit = std::numeric_limits<float>::infinity();
1423 
1424  if( hitPacket[ iRT ].m_hitresult &&
1425  hitPacket[ iRB ].m_hitresult &&
1426  ( hitPacket[ iRT ].m_HitInfo.pHitObject ==
1427  hitPacket[ iRB ].m_HitInfo.pHitObject ) )
1428  {
1429  hitInfoRTB.pHitObject = hitPacket[ iRT ].m_HitInfo.pHitObject;
1430 
1431  hitInfoRTB.m_tHit = ( hitPacket[ iRT ].m_HitInfo.m_tHit +
1432  hitPacket[ iRB ].m_HitInfo.m_tHit ) * 0.5f;
1433 
1434  hitInfoRTB.m_HitNormal =
1435  glm::normalize( ( hitPacket[ iRT ].m_HitInfo.m_HitNormal +
1436  hitPacket[ iRB ].m_HitInfo.m_HitNormal ) * 0.5f );
1437 
1438  cRTB = CCOLORRGB( shadeHit( bgColorY, rayRTB, hitInfoRTB, false, 0, false ) );
1439  cRTB = BlendColor( cRTB, BlendColor( cRT, cRB) );
1440  }
1441  else
1442  {
1443  if( hitPacket[ iRT ].m_hitresult ||
1444  hitPacket[ iRB ].m_hitresult ) // If any hits
1445  {
1446  const unsigned int nodeRT = hitPacket[ iRT ].m_HitInfo.m_acc_node_info;
1447  const unsigned int nodeRB = hitPacket[ iRB ].m_HitInfo.m_acc_node_info;
1448 
1449  bool hittedRTB = false;
1450 
1451  if( nodeRT != 0 )
1452  hittedRTB |= m_accelerator->Intersect( rayRTB, hitInfoRTB, nodeRT );
1453 
1454  if( ( nodeRB != 0 ) &&
1455  ( nodeRB != nodeRT ) )
1456  hittedRTB |= m_accelerator->Intersect( rayRTB, hitInfoRTB, nodeRB );
1457 
1458  if( hittedRTB )
1459  cRTB = CCOLORRGB( shadeHit( bgColorY,
1460  rayRTB,
1461  hitInfoRTB,
1462  false,
1463  0,
1464  false) );
1465  else
1466  {
1467  hitInfoRTB.m_tHit = std::numeric_limits<float>::infinity();
1468 
1469  if( m_accelerator->Intersect( rayRTB, hitInfoRTB ) )
1470  cRTB = CCOLORRGB( shadeHit( bgColorY,
1471  rayRTB,
1472  hitInfoRTB,
1473  false,
1474  0,
1475  false ) );
1476  }
1477  }
1478  }
1479 
1480  cRTB_old = cRTB;
1481 
1482 
1483  // Trace and shade cLRB
1484  // /////////////////////////////////////////////////////////////
1485  CCOLORRGB cLRB = bgColorYRGB;
1486 
1487  const SFVEC3F &oriLB = blockPacket.m_ray[ iLB ].m_Origin;
1488  const SFVEC3F &dirLB = blockPacket.m_ray[ iLB ].m_Dir;
1489 
1490  // Trace the center ray
1491  RAY rayLRB;
1492  rayLRB.Init( ( oriLB + oriRB ) * 0.5f,
1493  glm::normalize( ( dirLB + dirRB ) * 0.5f ) );
1494 
1495  HITINFO hitInfoLRB;
1496  hitInfoLRB.m_tHit = std::numeric_limits<float>::infinity();
1497 
1498  if( hitPacket[ iLB ].m_hitresult &&
1499  hitPacket[ iRB ].m_hitresult &&
1500  ( hitPacket[ iLB ].m_HitInfo.pHitObject ==
1501  hitPacket[ iRB ].m_HitInfo.pHitObject ) )
1502  {
1503  hitInfoLRB.pHitObject = hitPacket[ iLB ].m_HitInfo.pHitObject;
1504 
1505  hitInfoLRB.m_tHit = ( hitPacket[ iLB ].m_HitInfo.m_tHit +
1506  hitPacket[ iRB ].m_HitInfo.m_tHit ) * 0.5f;
1507 
1508  hitInfoLRB.m_HitNormal =
1509  glm::normalize( ( hitPacket[ iLB ].m_HitInfo.m_HitNormal +
1510  hitPacket[ iRB ].m_HitInfo.m_HitNormal ) * 0.5f );
1511 
1512  cLRB = CCOLORRGB( shadeHit( bgColorY, rayLRB, hitInfoLRB, false, 0, false ) );
1513  cLRB = BlendColor( cLRB, BlendColor( cLB, cRB) );
1514  }
1515  else
1516  {
1517  if( hitPacket[ iLB ].m_hitresult ||
1518  hitPacket[ iRB ].m_hitresult ) // If any hits
1519  {
1520  const unsigned int nodeLB = hitPacket[ iLB ].m_HitInfo.m_acc_node_info;
1521  const unsigned int nodeRB = hitPacket[ iRB ].m_HitInfo.m_acc_node_info;
1522 
1523  bool hittedLRB = false;
1524 
1525  if( nodeLB != 0 )
1526  hittedLRB |= m_accelerator->Intersect( rayLRB, hitInfoLRB, nodeLB );
1527 
1528  if( ( nodeRB != 0 ) &&
1529  ( nodeRB != nodeLB ) )
1530  hittedLRB |= m_accelerator->Intersect( rayLRB, hitInfoLRB, nodeRB );
1531 
1532  if( hittedLRB )
1533  cLRB = CCOLORRGB( shadeHit( bgColorY, rayLRB, hitInfoLRB, false, 0, false ) );
1534  else
1535  {
1536  hitInfoLRB.m_tHit = std::numeric_limits<float>::infinity();
1537 
1538  if( m_accelerator->Intersect( rayLRB, hitInfoLRB ) )
1539  cLRB = CCOLORRGB( shadeHit( bgColorY,
1540  rayLRB,
1541  hitInfoLRB,
1542  false,
1543  0,
1544  false ) );
1545  }
1546  }
1547  }
1548 
1549  cLRB_old[x] = cLRB;
1550 
1551 
1552  // Trace and shade cLTC
1553  // /////////////////////////////////////////////////////////////
1554  CCOLORRGB cLTC = BlendColor( cLT , cC );
1555 
1556  if( hitPacket[ iLT ].m_hitresult || hittedC )
1557  {
1558  // Trace the center ray
1559  RAY rayLTC;
1560  rayLTC.Init( ( oriLT + oriC ) * 0.5f,
1561  glm::normalize( ( dirLT + dirC ) * 0.5f ) );
1562 
1563  HITINFO hitInfoLTC;
1564  hitInfoLTC.m_tHit = std::numeric_limits<float>::infinity();
1565 
1566  bool hitted = false;
1567 
1568  if( hittedC )
1569  hitted = centerHitInfo.pHitObject->Intersect( rayLTC, hitInfoLTC );
1570  else
1571  if( hitPacket[ iLT ].m_hitresult )
1572  hitted = hitPacket[ iLT ].m_HitInfo.pHitObject->Intersect( rayLTC,
1573  hitInfoLTC );
1574 
1575  if( hitted )
1576  cLTC = CCOLORRGB( shadeHit( bgColorY, rayLTC, hitInfoLTC, false, 0, false ) );
1577  }
1578 
1579 
1580  // Trace and shade cRTC
1581  // /////////////////////////////////////////////////////////////
1582  CCOLORRGB cRTC = BlendColor( cRT , cC );
1583 
1584  if( hitPacket[ iRT ].m_hitresult || hittedC )
1585  {
1586  // Trace the center ray
1587  RAY rayRTC;
1588  rayRTC.Init( ( oriRT + oriC ) * 0.5f,
1589  glm::normalize( ( dirRT + dirC ) * 0.5f ) );
1590 
1591  HITINFO hitInfoRTC;
1592  hitInfoRTC.m_tHit = std::numeric_limits<float>::infinity();
1593 
1594  bool hitted = false;
1595 
1596  if( hittedC )
1597  hitted = centerHitInfo.pHitObject->Intersect( rayRTC, hitInfoRTC );
1598  else
1599  if( hitPacket[ iRT ].m_hitresult )
1600  hitted = hitPacket[ iRT ].m_HitInfo.pHitObject->Intersect( rayRTC,
1601  hitInfoRTC );
1602 
1603  if( hitted )
1604  cRTC = CCOLORRGB( shadeHit( bgColorY, rayRTC, hitInfoRTC, false, 0, false ) );
1605  }
1606 
1607 
1608  // Trace and shade cLBC
1609  // /////////////////////////////////////////////////////////////
1610  CCOLORRGB cLBC = BlendColor( cLB , cC );
1611 
1612  if( hitPacket[ iLB ].m_hitresult || hittedC )
1613  {
1614  // Trace the center ray
1615  RAY rayLBC;
1616  rayLBC.Init( ( oriLB + oriC ) * 0.5f,
1617  glm::normalize( ( dirLB + dirC ) * 0.5f ) );
1618 
1619  HITINFO hitInfoLBC;
1620  hitInfoLBC.m_tHit = std::numeric_limits<float>::infinity();
1621 
1622  bool hitted = false;
1623 
1624  if( hittedC )
1625  hitted = centerHitInfo.pHitObject->Intersect( rayLBC, hitInfoLBC );
1626  else
1627  if( hitPacket[ iLB ].m_hitresult )
1628  hitted = hitPacket[ iLB ].m_HitInfo.pHitObject->Intersect( rayLBC,
1629  hitInfoLBC );
1630 
1631  if( hitted )
1632  cLBC = CCOLORRGB( shadeHit( bgColorY, rayLBC, hitInfoLBC, false, 0, false ) );
1633  }
1634 
1635 
1636  // Trace and shade cRBC
1637  // /////////////////////////////////////////////////////////////
1638  CCOLORRGB cRBC = BlendColor( cRB , cC );
1639 
1640  if( hitPacket[ iRB ].m_hitresult || hittedC )
1641  {
1642  // Trace the center ray
1643  RAY rayRBC;
1644  rayRBC.Init( ( oriRB + oriC ) * 0.5f,
1645  glm::normalize( ( dirRB + dirC ) * 0.5f ) );
1646 
1647  HITINFO hitInfoRBC;
1648  hitInfoRBC.m_tHit = std::numeric_limits<float>::infinity();
1649 
1650  bool hitted = false;
1651 
1652  if( hittedC )
1653  hitted = centerHitInfo.pHitObject->Intersect( rayRBC, hitInfoRBC );
1654  else
1655  if( hitPacket[ iRB ].m_hitresult )
1656  hitted = hitPacket[ iRB ].m_HitInfo.pHitObject->Intersect( rayRBC,
1657  hitInfoRBC );
1658 
1659  if( hitted )
1660  cRBC = CCOLORRGB( shadeHit( bgColorY, rayRBC, hitInfoRBC, false, 0, false ) );
1661  }
1662 
1663 
1664  // Set pixel colors
1665  // /////////////////////////////////////////////////////////////
1666 
1667  GLubyte *ptr = &ptrPBO[ (4 * x + m_blockPositionsFast[iBlock].x +
1668  m_realBufferSize.x *
1669  (m_blockPositionsFast[iBlock].y + 4 * y)) * 4 ];
1670  SetPixel( ptr + 0, cLT );
1671  SetPixel( ptr + 4, BlendColor( cLT, cLRT, cLTC ) );
1672  SetPixel( ptr + 8, cLRT );
1673  SetPixel( ptr + 12, BlendColor( cLRT, cRT, cRTC ) );
1674 
1675  ptr += m_realBufferSize.x * 4;
1676  SetPixel( ptr + 0, BlendColor( cLT , cLTB, cLTC ) );
1677  SetPixel( ptr + 4, BlendColor( cLTC, BlendColor( cLT , cC ) ) );
1678  SetPixel( ptr + 8, BlendColor( cC, BlendColor( cLRT, cLTC, cRTC ) ) );
1679  SetPixel( ptr + 12, BlendColor( cRTC, BlendColor( cRT , cC ) ) );
1680 
1681  ptr += m_realBufferSize.x * 4;
1682  SetPixel( ptr + 0, cLTB );
1683  SetPixel( ptr + 4, BlendColor( cC, BlendColor( cLTB, cLTC, cLBC ) ) );
1684  SetPixel( ptr + 8, cC );
1685  SetPixel( ptr + 12, BlendColor( cC, BlendColor( cRTB, cRTC, cRBC ) ) );
1686 
1687  ptr += m_realBufferSize.x * 4;
1688  SetPixel( ptr + 0, BlendColor( cLB , cLTB, cLBC ) );
1689  SetPixel( ptr + 4, BlendColor( cLBC, BlendColor( cLB , cC ) ) );
1690  SetPixel( ptr + 8, BlendColor( cC, BlendColor( cLRB, cLBC, cRBC ) ) );
1691  SetPixel( ptr + 12, BlendColor( cRBC, BlendColor( cRB , cC ) ) );
1692  }
1693  }
1694  }
1695 
1696  // Wait for all threads to finish (not sure if this is need)
1697  #pragma omp barrier
1698 }
1699 
1700 
1701 #define USE_EXPERIMENTAL_SOFT_SHADOWS 1
1702 
1704  const RAY &aRay,
1705  HITINFO &aHitInfo,
1706  bool aIsInsideObject,
1707  unsigned int aRecursiveLevel,
1708  bool is_testShadow ) const
1709 {
1710  if( aRecursiveLevel > 2 )
1711  return SFVEC3F( 0.0f );
1712 
1713  SFVEC3F hitPoint = aHitInfo.m_HitPoint;
1714 
1715  if( !m_isPreview )
1716  hitPoint += aHitInfo.m_HitNormal * m_settings.GetNonCopperLayerThickness3DU() * 1.0f;
1717 
1718  const CMATERIAL *objMaterial = aHitInfo.pHitObject->GetMaterial();
1719  wxASSERT( objMaterial != NULL );
1720 
1721  const SFVEC3F diffuseColorObj = aHitInfo.pHitObject->GetDiffuseColor( aHitInfo );
1722 
1723  SFVEC3F outColor = objMaterial->GetEmissiveColor();
1724 
1725  const LIST_LIGHT &lightList = m_lights.GetList();
1726 
1727 #if USE_EXPERIMENTAL_SOFT_SHADOWS
1728  const bool is_aa_enabled = m_settings.GetFlag( FL_RENDER_RAYTRACING_ANTI_ALIASING ) &&
1729  (!m_isPreview);
1730 #endif
1731 
1732  float shadow_att_factor_sum = 0.0f;
1733 
1734  unsigned int nr_lights_that_can_cast_shadows = 0;
1735 
1736  for( LIST_LIGHT::const_iterator ii = lightList.begin();
1737  ii != lightList.end();
1738  ++ii )
1739  {
1740  const CLIGHT *light = (CLIGHT *)*ii;
1741 
1742  SFVEC3F vectorToLight;
1743  SFVEC3F colorOfLight;
1744  float distToLight;
1745 
1746  light->GetLightParameters( hitPoint, vectorToLight, colorOfLight, distToLight );
1747 
1748  if( m_isPreview )
1749  colorOfLight = SFVEC3F( 1.0f );
1750 
1751  /*
1752  if( (!m_isPreview) &&
1753  // Little hack to make randomness to the shading and shadows
1754  m_settings.GetFlag( FL_RENDER_RAYTRACING_POST_PROCESSING ) )
1755  vectorToLight = glm::normalize( vectorToLight +
1756  UniformRandomHemisphereDirection() * 0.1f );
1757  */
1758 
1759  const float NdotL = glm::dot( aHitInfo.m_HitNormal, vectorToLight );
1760 
1761  // Only calc shade if the normal is facing the direction of light,
1762  // otherwise it is in the shadow
1763  if( NdotL >= FLT_EPSILON )
1764  {
1765  float shadow_att_factor_light = 1.0f;
1766 
1767  if( is_testShadow && light->GetCastShadows() )
1768  {
1769  nr_lights_that_can_cast_shadows++;
1770 #if USE_EXPERIMENTAL_SOFT_SHADOWS
1771  if( (!is_aa_enabled) ||
1772 
1773  // For rays that are recursive, just calculate one hit shadow
1774  (aRecursiveLevel > 0) ||
1775 
1776  // Only use soft shadows if using post processing
1778  )
1779  {
1780 #endif
1781  RAY rayToLight;
1782  rayToLight.Init( hitPoint, vectorToLight );
1783 
1784  // Test if point is not in the shadow.
1785  // Test for any hit from the point in the direction of light
1786  if( m_accelerator->IntersectP( rayToLight, distToLight ) )
1787  shadow_att_factor_light = 0.0f;
1788 
1789 #if USE_EXPERIMENTAL_SOFT_SHADOWS
1790  }
1791 
1792  // Experimental softshadow calculation
1793  else
1794  {
1795 
1796  const unsigned int shadow_number_of_samples = 3;
1797  const float shadow_inc_factor = 1.0f / (float)(shadow_number_of_samples);
1798 
1799  for( unsigned int i = 0; i < shadow_number_of_samples; ++i )
1800  {
1801  const SFVEC3F unifVector = UniformRandomHemisphereDirection();
1802  const SFVEC3F disturbed_vector_to_light = glm::normalize( vectorToLight +
1803  unifVector *
1804  0.05f );
1805 
1806  RAY rayToLight;
1807  rayToLight.Init( hitPoint, disturbed_vector_to_light );
1808 
1809  // !TODO: there are multiple ways that this tests can be
1810  // optimized. Eg: by packing rays or to test against the
1811  // latest hit object.
1812 
1813  if( m_accelerator->IntersectP( rayToLight, distToLight ) )
1814  {
1815  shadow_att_factor_light -= shadow_inc_factor;
1816  }
1817  }
1818  }
1819 #endif
1820  shadow_att_factor_sum += shadow_att_factor_light;
1821  }
1822 
1824  {
1825  outColor += objMaterial->Shade( aRay,
1826  aHitInfo,
1827  NdotL,
1828  diffuseColorObj,
1829  vectorToLight,
1830  colorOfLight,
1831  shadow_att_factor_light );
1832  }
1833  else
1834  {
1835  // This is a render hack in order to compensate for the lack of
1836  // ambient and too much darkness when using post process shader
1837  // It will calculate as it was not in shadow
1838  outColor += objMaterial->Shade( aRay,
1839  aHitInfo,
1840  NdotL,
1841  diffuseColorObj,
1842  vectorToLight,
1843  colorOfLight,
1844  // The sampled point will be darkshaded by the post
1845  // processing, so here it compensates to not shadow
1846  // so much
1847  glm::min( shadow_att_factor_light + (3.0f / 6.0f), 1.0f )
1848  );
1849  }
1850  }
1851  else
1852  {
1853  outColor += objMaterial->GetAmbientColor();
1854  }
1855 
1856  // Only use the headlight for preview
1857  if( m_isPreview )
1858  break;
1859  }
1860 
1861  // Improvement: this is not taking in account the lightcolor
1862  if( nr_lights_that_can_cast_shadows > 0 )
1863  {
1864  aHitInfo.m_ShadowFactor = glm::max( shadow_att_factor_sum /
1865  (float)(nr_lights_that_can_cast_shadows * 1.0f), 0.0f );
1866  }
1867  else
1868  {
1869  aHitInfo.m_ShadowFactor = 1.0f;
1870  }
1871 
1872  // Clamp color to not be brighter than 1.0f
1873  outColor = glm::min( outColor, SFVEC3F( 1.0f ) );
1874 
1875  if( !m_isPreview )
1876  {
1877  // Reflections
1878  // /////////////////////////////////////////////////////////////////////
1879 
1880  if( !aIsInsideObject &&
1881  (objMaterial->GetReflection() > 0.0f) &&
1883  {
1884  const unsigned int reflection_number_of_samples = objMaterial->GetNrReflectionsSamples();
1885 
1886  SFVEC3F sum_color = SFVEC3F(0.0f);
1887 
1888  const SFVEC3F reflectVector = aRay.m_Dir -
1889  2.0f * glm::dot( aRay.m_Dir, aHitInfo.m_HitNormal ) *
1890  aHitInfo.m_HitNormal;
1891 
1892  for( unsigned int i = 0; i < reflection_number_of_samples; ++i )
1893  {
1894  // Apply some randomize to the reflected vector
1895  const SFVEC3F random_reflectVector =
1896  glm::normalize( reflectVector +
1898  0.025f );
1899 
1900  RAY reflectedRay;
1901  reflectedRay.Init( hitPoint, random_reflectVector );
1902 
1903  HITINFO reflectedHit;
1904  reflectedHit.m_tHit = std::numeric_limits<float>::infinity();
1905 
1906  if( m_accelerator->Intersect( reflectedRay, reflectedHit ) )
1907  {
1908  sum_color += ( diffuseColorObj + objMaterial->GetSpecularColor() ) *
1909  shadeHit( aBgColor,
1910  reflectedRay,
1911  reflectedHit,
1912  false,
1913  aRecursiveLevel + 1,
1914  is_testShadow ) *
1915  SFVEC3F( objMaterial->GetReflection() *
1916  // Falloff factor
1917  (1.0f / ( 1.0f + 0.75f * reflectedHit.m_tHit *
1918  reflectedHit.m_tHit) ) );
1919  }
1920  }
1921 
1922  outColor += (sum_color / SFVEC3F( (float)reflection_number_of_samples) );
1923  }
1924 
1925 
1926  // Refractions
1927  // /////////////////////////////////////////////////////////////////////
1928 
1929  if( (objMaterial->GetTransparency() > 0.0f) &&
1931  {
1932  const float airIndex = 1.000293f;
1933  const float glassIndex = 1.49f;
1934  const float air_over_glass = airIndex / glassIndex;
1935  const float glass_over_air = glassIndex / airIndex;
1936 
1937  const float refractionRatio = aIsInsideObject?glass_over_air:air_over_glass;
1938 
1939  SFVEC3F refractedVector;
1940 
1941  if( Refract( aRay.m_Dir,
1942  aHitInfo.m_HitNormal,
1943  refractionRatio,
1944  refractedVector ) )
1945  {
1946  const float objTransparency = objMaterial->GetTransparency();
1947 
1948  // This increase the start point by a "fixed" factor so it will work the
1949  // same for all distances
1950  const SFVEC3F startPoint = aRay.at( NextFloatUp(
1951  NextFloatUp(
1952  NextFloatUp( aHitInfo.m_tHit ) ) ) );
1953 
1954  const unsigned int refractions_number_of_samples = objMaterial->GetNrRefractionsSamples();
1955 
1956  SFVEC3F sum_color = SFVEC3F(0.0f);
1957 
1958  for( unsigned int i = 0; i < refractions_number_of_samples; ++i )
1959  {
1960  RAY refractedRay;
1961 
1962  if( refractions_number_of_samples > 1 )
1963  {
1964  // apply some randomize to the refracted vector
1965  const SFVEC3F randomizeRefractedVector = glm::normalize( refractedVector +
1967  0.15f *
1968  (1.0f - objTransparency) );
1969 
1970  refractedRay.Init( startPoint, randomizeRefractedVector );
1971  }
1972  else
1973  {
1974  refractedRay.Init( startPoint, refractedVector );
1975  }
1976 
1977  HITINFO refractedHit;
1978  refractedHit.m_tHit = std::numeric_limits<float>::infinity();
1979 
1980  SFVEC3F refractedColor = objMaterial->GetAmbientColor();
1981 
1982  if( m_accelerator->Intersect( refractedRay, refractedHit ) )
1983  {
1984  refractedColor = shadeHit( aBgColor,
1985  refractedRay,
1986  refractedHit,
1987  true,
1988  aRecursiveLevel + 1,
1989  false );
1990 
1991  const SFVEC3F absorbance = ( SFVEC3F(1.0f) - diffuseColorObj ) *
1992  (1.0f - objTransparency ) *
1993  objMaterial->GetAbsorvance() * // Adjust falloff factor
1994  -refractedHit.m_tHit;
1995 
1996  const SFVEC3F transparency = SFVEC3F( expf( absorbance.r ),
1997  expf( absorbance.g ),
1998  expf( absorbance.b ) );
1999 
2000  sum_color += refractedColor * transparency * objTransparency;
2001  }
2002  else
2003  {
2004  sum_color += refractedColor * objTransparency;
2005  }
2006  }
2007 
2008  outColor = outColor * (1.0f - objTransparency) +
2009  (sum_color / SFVEC3F( (float)refractions_number_of_samples) );
2010  }
2011  }
2012  }
2013 
2014  //outColor += glm::max( -glm::dot( aHitInfo.m_HitNormal, aRay.m_Dir ), 0.0f ) *
2015  // objMaterial->GetAmbientColor();
2016 
2017  return outColor;
2018 }
2019 
2020 
2022 {
2023  opengl_init_pbo();
2024 }
2025 
2026 
2028 {
2029  if( GLEW_ARB_pixel_buffer_object )
2030  {
2032 
2033  // Try to delete vbo if it was already initialized
2035 
2036  // Learn about Pixel buffer objects at:
2037  // http://www.songho.ca/opengl/gl_pbo.html
2038  // http://web.eecs.umich.edu/~sugih/courses/eecs487/lectures/25-PBO+Mipmapping.pdf
2039  // "create 2 pixel buffer objects, you need to delete them when program exits.
2040  // glBufferDataARB with NULL pointer reserves only memory space."
2041 
2042  // This sets the number of RGBA pixels
2044 
2045  glGenBuffersARB( 1, &m_pboId );
2046  glBindBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, m_pboId );
2047  glBufferDataARB( GL_PIXEL_UNPACK_BUFFER_ARB, m_pboDataSize, 0, GL_STREAM_DRAW_ARB );
2048  glBindBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, 0 );
2049 
2050  wxLogTrace( m_logTrace,
2051  wxT( "C3D_RENDER_RAYTRACING:: GLEW_ARB_pixel_buffer_object is supported" ) );
2052  }
2053 }
2054 
2055 
2057 {
2058  m_is_opengl_initialized = true;
2059 
2060  return true;
2061 }
2062 
2063 
2065 {
2066 
2068 
2069  // Calc block positions for fast preview mode
2070  // /////////////////////////////////////////////////////////////////////
2071  m_blockPositionsFast.clear();
2072 
2073  unsigned int i = 0;
2074 
2075  while(1)
2076  {
2077  const unsigned int mX = DecodeMorton2X(i);
2078  const unsigned int mY = DecodeMorton2Y(i);
2079 
2080  i++;
2081 
2082  const SFVEC2UI blockPos( mX * 4 * RAYPACKET_DIM - mX * 4,
2083  mY * 4 * RAYPACKET_DIM - mY * 4);
2084 
2085  if( ( blockPos.x >= ( (unsigned int)m_windowSize.x - ( 4 * RAYPACKET_DIM + 4 ) ) ) &&
2086  ( blockPos.y >= ( (unsigned int)m_windowSize.y - ( 4 * RAYPACKET_DIM + 4 ) ) ) )
2087  break;
2088 
2089  if( ( blockPos.x < ( (unsigned int)m_windowSize.x - ( 4 * RAYPACKET_DIM + 4) ) ) &&
2090  ( blockPos.y < ( (unsigned int)m_windowSize.y - ( 4 * RAYPACKET_DIM + 4) ) ) )
2091  {
2092  m_blockPositionsFast.push_back( blockPos );
2093 
2094  if( blockPos.x > m_realBufferSize.x )
2095  m_realBufferSize.x = blockPos.x;
2096 
2097  if( blockPos.y > m_realBufferSize.y )
2098  m_realBufferSize.y = blockPos.y;
2099  }
2100  }
2101 
2103 
2106 
2107  m_xoffset = (m_windowSize.x - m_realBufferSize.x) / 2;
2108  m_yoffset = (m_windowSize.y - m_realBufferSize.y) / 2;
2109 
2111 
2112 
2113  // Calc block positions
2114  // /////////////////////////////////////////////////////////////////////
2115  m_blockPositions.clear();
2118 
2119  i = 0;
2120 
2121  while(1)
2122  {
2123  SFVEC2UI blockPos( DecodeMorton2X(i) * RAYPACKET_DIM,
2124  DecodeMorton2Y(i) * RAYPACKET_DIM );
2125  i++;
2126 
2127  if( (blockPos.x >= m_realBufferSize.x) && (blockPos.y >= m_realBufferSize.y) )
2128  break;
2129 
2130  if( (blockPos.x < m_realBufferSize.x) && (blockPos.y < m_realBufferSize.y) )
2131  m_blockPositions.push_back( blockPos );
2132  }
2133 
2134  // Create m_shader buffer
2135  delete[] m_shaderBuffer;
2137 
2138  opengl_init_pbo();
2139 }
std::vector< bool > m_blockPositionsWasProcessed
this flags if a position was already processed (cleared each new render)
#define RAYPACKET_DIM
Definition: raypacket.h:37
long m_nrBlocksRenderProgress
Save the number of blocks progress of the render.
float m_ShadowFactor
( 4) Shadow attenuation (1.0 no shadow, 0.0f darkness)
Definition: hitinfo.h:50
SFVEC3F ApplyShadeColor(const SFVEC2I &aShaderPos, const SFVEC3F &aInputColor, const SFVEC3F &aShadeColor) const override
ApplyShadeColor - apply the final color process using a previous stage color.
#define SRGB_GAMA
float GetTransparency() const
Definition: cmaterial.h:183
void rt_shades_packet(const SFVEC3F *bgColorY, const RAY *aRayPkt, HITINFO_PACKET *aHitPacket, bool is_testShadow, SFVEC3F *aOutHitColor)
const SFVEC3F & GetColorAtNotProtected(const SFVEC2I &aPos) const
Defines math related functions.
bool Redraw(bool aIsMoving, REPORTER *aStatusTextReporter) override
Redraw - Ask to redraw the view.
void rt_final_color(GLubyte *ptrPBO, const SFVEC3F &rgbColor, bool applyColorSpaceConversion)
SFVEC3F ConvertSRGBToLinear(const SFVEC3F &aSRGBcolor)
SFVEC3F Shade(const SFVEC2I &aShaderPos) const override
const LIST_LIGHT & GetList() const
GetList - get light list of this container.
Definition: clight.h:196
const SFVEC3F & GetAmbientColor() const
Definition: cmaterial.h:178
CPOSTSHADER_SSAO m_postshader_ssao
uint32_t DecodeMorton2X(uint32_t code)
Definition: mortoncodes.cpp:98
SFVEC3F shadeHit(const SFVEC3F &aBgColor, const RAY &aRay, HITINFO &aHitInfo, bool aIsInsideObject, unsigned int aRecursiveLevel, bool is_testShadow) const
A base material class that can be used to derive a material implementation.
Definition: cmaterial.h:167
wxSize m_oldWindowsSize
used to see if the windows size changed
void Init(const SFVEC3F &o, const SFVEC3F &d)
Definition: ray.cpp:38
virtual bool IntersectP(const RAY &aRay, float aMaxDistance) const =0
float GetAbsorvance() const
Definition: cmaterial.h:185
float GetNonCopperLayerThickness3DU() const
GetNonCopperLayerThickness3DU - Get the current non copper layers thickness.
Definition: cinfo3d_visu.h:159
#define RAYPACKET_INVMASK
Definition: raypacket.h:39
SFVEC3F at(float t) const
Definition: ray.h:65
void rt_render_post_process_shade(GLubyte *ptrPBO, REPORTER *aStatusTextReporter)
const CMATERIAL * GetMaterial() const
Definition: cobject.h:63
const SFVEC3F & GetSpecularColor() const
Definition: cmaterial.h:180
SFVEC3D m_BgColorBot
background bottom color
Definition: cinfo3d_visu.h:503
Definition: ray.h:43
const SFVEC3F & GetDir() const
Definition: ccamera.h:109
Class REPORTER is a pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:61
glm::ivec2 SFVEC2I
Definition: xv3d_types.h:42
CINFO3D_VISU & m_settings
settings refrence in use for this render
SFVEC3D m_BgColorTop
background top color
Definition: cinfo3d_visu.h:504
float m_tHit
( 4) distance
Definition: hitinfo.h:43
uint32_t DecodeMorton2Y(uint32_t code)
HITINFO_PACKET * m_firstHitinfo
unsigned int m_stats_converted_dummy_to_plane
bool Refract(const SFVEC3F &aInVector, const SFVEC3F &aNormal, float aRin_over_Rout, SFVEC3F &aOutVector)
Refract Based on: https://github.com/mmp/pbrt-v3/blob/master/src/core/reflection.h See also: http://w...
Definition: 3d_math.h:113
virtual SFVEC3F Shade(const RAY &aRay, const HITINFO &aHitInfo, float NdotL, const SFVEC3F &aDiffuseObjColor, const SFVEC3F &aDirToLight, const SFVEC3F &aLightColor, float aShadowAttenuationFactor) const =0
Shade - Shades an intersection point.
SFVEC3F m_HitPoint
(12) hit position
Definition: hitinfo.h:49
glm::uvec2 SFVEC2UI
Definition: xv3d_types.h:41
void OGL_DrawBackground(const SFVEC3F &aTopColor, const SFVEC3F &aBotColor)
OGL_DrawBackground.
Definition: ogl_utils.cpp:176
CGENERICACCELERATOR * m_accelerator
glm::vec2 SFVEC2F
Definition: xv3d_types.h:45
unsigned int GetNrReflectionsSamples() const
Definition: cmaterial.h:187
bool m_is_opengl_initialized
flag if the opengl specific for this render was already initialized
Implementes Morton Codes https://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes/ http://www...
virtual bool Intersect(const RAY &aRay, HITINFO &aHitInfo) const =0
RT_RENDER_STATE m_rt_render_state
State used on quality render.
Class CINFO3D_VISU Helper class to handle information needed to display 3D board. ...
Definition: cinfo3d_visu.h:70
void InitFrame()
Definition: cpostshader.h:54
HITINFO m_HitInfo
Definition: hitinfo.h:63
wxSize m_windowSize
The window size that this camera is working.
C3D_RENDER_RAYTRACING(CINFO3D_VISU &aSettings)
unsigned int m_stats_converted_roundsegment2d_to_roundsegment
void rt_render_tracing(GLubyte *ptrPBO, REPORTER *aStatusTextReporter)
int GetWaitForEditingTimeOut() override
GetWaitForEditingTimeOut - Give the interface the time (in ms) that it should wait for editing or mov...
void rt_render_post_process_blur_finish(GLubyte *ptrPBO, REPORTER *aStatusTextReporter)
void rt_trace_AA_packet(const SFVEC3F *aBgColorY, const HITINFO_PACKET *aHitPck_X0Y0, const HITINFO_PACKET *aHitPck_AA_X1Y1, const RAY *aRayPck, SFVEC3F *aOutHitColor)
unsigned int GetNrRefractionsSamples() const
Definition: cmaterial.h:186
const COBJECT * pHitObject
( 4) Object that was hitted
Definition: hitinfo.h:45
CDIRECTIONALLIGHT * m_camera_light
RENDER_ENGINE RenderEngineGet() const
RenderEngineGet.
Definition: cinfo3d_visu.h:234
std::vector< SFVEC2UI > m_blockPositionsFast
this encodes the Morton code positions (on fast preview mode)
unsigned char c[3]
Definition: ccolorrgb.h:37
A base light class to derive to implement other light classes.
Definition: clight.h:37
SFVEC3F m_Dir
Definition: ray.h:48
SFVEC3F UniformRandomHemisphereDirection()
Definition: 3d_math.h:54
static void HITINFO_PACKET_init(HITINFO_PACKET *aHitPacket)
bool GetFlag(DISPLAY3D_FLG aFlag) const
GetFlag - get a configuration status of a flag.
bool GetCastShadows() const
Definition: clight.h:58
void SetPixelData(unsigned int x, unsigned int y, const SFVEC3F &aNormal, const SFVEC3F &aColor, const SFVEC3F &aHitPosition, float aDepth, float aShadowAttFactor)
Definition: cpostshader.cpp:78
void SetDirection(const SFVEC3F &aDir)
SetDirection - Set directional light orientation.
Definition: clight.h:129
virtual bool Intersect(const RAY &aRay, HITINFO &aHitInfo) const =0
Functions Intersect.
static void SetPixel(GLubyte *p, const CCOLORRGB &v)
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
bool m_reloadRequested
!TODO: this must be reviewed in order to flag change types
Stores the hit information of a ray with a point on the surface of a object.
Definition: hitinfo.h:40
#define max(a, b)
Definition: auxiliary.h:86
#define RAYPACKET_RAYS_PER_PACKET
Definition: raypacket.h:40
CCAMERA & CameraGet() const
CameraGet - get current camera in use.
Definition: cinfo3d_visu.h:210
unsigned GetRunningMicroSecs()
Function GetRunningMicroSecs An alternate way to calculate an elapset time (in microsecondes) to clas...
unsigned int m_acc_node_info
( 4) The acc stores here the node that it hits
Definition: hitinfo.h:47
glm::vec3 SFVEC3F
Definition: xv3d_types.h:47
#define DISP_FACTOR
CCOLORRGB BlendColor(const CCOLORRGB &aC1, const CCOLORRGB &aC2)
Definition: ccolorrgb.cpp:42
std::vector< SFVEC2UI > m_blockPositions
this encodes the Morton code positions
unsigned long int m_stats_start_rendering_time
Time that the render starts.
float NextFloatUp(float v)
Definition: 3d_fastmath.h:136
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_UNDEFINED)=0
Function Report is a pure virtual function to override in the derived object.
Defines math related functions.
void SetCurWindowSize(const wxSize &aSize) override
SetCurWindowSize - Before each render, the canvas will tell the render what is the size of its window...
virtual void GetLightParameters(const SFVEC3F &aHitPoint, SFVEC3F &aOutVectorToLight, SFVEC3F &aOutLightColor, float &aOutDistance) const =0
GetLightParameters - Get parameters from this light.
SFVEC3F m_HitNormal
(12) normal at the hit point
Definition: hitinfo.h:42
CCONTAINER2D * m_outlineBoard2dObjects
std::list< CLIGHT * > LIST_LIGHT
Definition: clight.h:151
static SFVEC3F convertLinearToSRGB(const SFVEC3F &aRGBcolor)
const SFVEC3F & GetEmissiveColor() const
Definition: cmaterial.h:179
void UpdateSize(const SFVEC2UI &aSize)
Definition: cpostshader.cpp:72
bool m_hitresult
Definition: hitinfo.h:62
static const wxChar * m_logTrace
Trace mask used to enable or disable the trace output of this class.
void render_preview(GLubyte *ptrPBO)
void render(GLubyte *ptrPBO, REPORTER *aStatusTextReporter)
virtual SFVEC3F GetDiffuseColor(const HITINFO &aHitInfo) const =0
void RAYPACKET_InitRays_with2DDisplacement(const CCAMERA &aCamera, const SFVEC2F &aWindowsPosition, const SFVEC2F &a2DWindowsPosDisplacementFactor, RAY *aRayPck)
Definition: raypacket.cpp:174
float GetReflection() const
Definition: cmaterial.h:184
#define min(a, b)
Definition: auxiliary.h:85
void rt_render_trace_block(GLubyte *ptrPBO, signed int iBlock)
bool ParametersChanged()
Function ParametersChanged.
Definition: ccamera.cpp:567
This is a base class to hold data and functions for render targets.
void reload(REPORTER *aStatusTextReporter)