KiCad PCB EDA Suite
Loading...
Searching...
No Matches
render_3d_raytrace_base.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-2020 Mario Luzeiro <[email protected]>
5 * Copyright The 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, see <https://www.gnu.org/licenses/>.
19 */
20
22
23#include <algorithm>
24#include <atomic>
25#include <chrono>
26#include <thread>
27
28#include <wx/log.h>
29
30#include "mortoncodes.h"
31#include "../color_rgba.h"
32#include "3d_fastmath.h"
33#include "3d_math.h"
34#include <thread_pool.h>
35#include <core/profile.h> // To use GetRunningMicroSecs or another profiling utility
36
37#include <pad.h>
38#include <pcb_track.h>
39
40
41#ifdef USE_SRGB_SPACE
42
44#define SRGB_GAMA 2.4f
45
46
47// This function implements the conversion from linear RGB to sRGB
48// https://github.com/g-truc/glm/blob/master/glm/gtc/color_space.inl#L12
49static SFVEC3F convertLinearToSRGB( const SFVEC3F& aRGBcolor )
50{
51 const float gammaCorrection = 1.0f / SRGB_GAMA;
52 const SFVEC3F clampedColor = glm::clamp( aRGBcolor, SFVEC3F( 0.0f ), SFVEC3F( 1.0f ) );
53
54 return glm::mix( glm::pow( clampedColor, SFVEC3F(gammaCorrection) ) * 1.055f - 0.055f,
55 clampedColor * 12.92f,
56 glm::lessThan( clampedColor, SFVEC3F(0.0031308f) ) );
57}
58
59
60static SFVEC4F convertLinearToSRGBA( const SFVEC4F& aRGBAcolor )
61{
62 return SFVEC4F( convertLinearToSRGB( SFVEC3F( aRGBAcolor ) ), aRGBAcolor.a );
63}
64
65
66// This function implements the conversion from sRGB to linear RGB
67// https://github.com/g-truc/glm/blob/master/glm/gtc/color_space.inl#L35
69{
70 const float gammaCorrection = SRGB_GAMA;
71
72 return glm::mix( glm::pow( ( aSRGBcolor + SFVEC3F( 0.055f ) )
73 * SFVEC3F( 0.94786729857819905213270142180095f ),
74 SFVEC3F( gammaCorrection ) ),
75 aSRGBcolor * SFVEC3F( 0.07739938080495356037151702786378f ),
76 glm::lessThanEqual( aSRGBcolor, SFVEC3F( 0.04045f ) ) );
77}
78
79
81{
82 return SFVEC4F( ConvertSRGBToLinear( SFVEC3F( aSRGBAcolor ) ), aSRGBAcolor.a );
83}
84
85#endif
86
87
89 RENDER_3D_BASE( aAdapter, aCamera ),
90 m_postShaderSsao( aCamera )
91{
92 wxLogTrace( m_logTrace, wxT( "RENDER_3D_RAYTRACE_BASE::RENDER_3D_RAYTRACE_BASE" ) );
93
94 //m_pboId = GL_NONE;
95 //m_pboDataSize = 0;
98 m_oldWindowsSize.x = 0;
99 m_oldWindowsSize.y = 0;
100 m_outlineBoard2dObjects = nullptr;
102 m_firstHitinfo = nullptr;
103 m_shaderBuffer = nullptr;
104 m_cameraLight = nullptr;
105
106 m_xoffset = 0;
107 m_yoffset = 0;
108
110 m_isPreview = false;
111 m_renderState = RT_RENDER_STATE_MAX; // Set to an initial invalid state
114}
115
116
118{
119 wxLogTrace( m_logTrace, wxT( "RENDER_3D_RAYTRACE_BASE::~RENDER_3D_RAYTRACE_BASE" ) );
120
122 m_outlineBoard2dObjects = nullptr;
123
126
127 delete[] m_shaderBuffer;
128 m_shaderBuffer = nullptr;
129}
130
131
133{
134 return 200; // ms
135}
136
137
139{
141
144
145 m_postShaderSsao.InitFrame();
146
148
149 // Mark the blocks not processed yet
150 std::fill( m_blockPositionsWasProcessed.begin(), m_blockPositionsWasProcessed.end(), 0 );
151}
152
153
154static inline void SetPixel( uint8_t* p, const COLOR_RGBA& v )
155{
156 p[0] = v.c[0];
157 p[1] = v.c[1];
158 p[2] = v.c[2];
159 p[3] = v.c[3];
160}
161
162
163static void SetPixelSRGBA( uint8_t* p, const COLOR_RGBA& v )
164{
165 SFVEC4F color = v;
166
167#ifdef USE_SRGB_SPACE
168 color = convertLinearToSRGB( color );
169#endif
170
171 COLOR_RGBA rgba( color );
172 SetPixel( p, rgba );
173}
174
175
177{
178 return SFVEC4F( aInput.r * aInput.a, aInput.g * aInput.a, aInput.b * aInput.a, aInput.a );
179}
180
181
182void RENDER_3D_RAYTRACE_BASE::render( uint8_t* ptrPBO )
183{
185 {
187
188 if( m_cameraLight )
189 m_cameraLight->SetDirection( -m_camera.GetDir() );
190
191 if( m_boardAdapter.m_Cfg->m_Render.engine == RENDER_ENGINE::OPENGL )
192 {
193 // Set all pixels of PBO transparent (Alpha to 0)
194 // This way it will draw the full buffer but only shows the updated (
195 // already calculated) squares
196 unsigned int nPixels = m_realBufferSize.x * m_realBufferSize.y;
197 uint8_t* tmp_ptrPBO = ptrPBO + 3; // PBO is RGBA
198
199 for( unsigned int i = 0; i < nPixels; ++i )
200 {
201 *tmp_ptrPBO = 0;
202 tmp_ptrPBO += 4; // PBO is RGBA
203 }
204 }
205
210 }
211
212 switch( m_renderState )
213 {
215 renderTracing( ptrPBO );
216 break;
217
219 postProcessShading( ptrPBO );
220 break;
221
223 postProcessBlurFinish( ptrPBO );
224 break;
225
226 default:
227 wxASSERT_MSG( false, wxT( "Invalid state on m_renderState" ) );
229 break;
230 }
231
233 {
234 // Calculation time in seconds
235 const double elapsed_time = (double) ( GetRunningMicroSecs() - m_renderStartTime ) / 1e6;
236
237 m_activityReporter->Report( wxString::Format( _( "Rendering time %.3f s" ), elapsed_time ) );
238 }
239}
240
241
243{
244 m_isPreview = false;
245
246 auto startTime = std::chrono::steady_clock::now();
247 std::atomic<size_t> numBlocksRendered( 0 );
248 std::atomic<size_t> currentBlock( 0 );
249
251 const int timeLimit = m_blockPositions.size() > 40000 ? 750 : 400;
252
253 auto processBlocks = [&]()
254 {
255 for( size_t iBlock = currentBlock.fetch_add( 1 ); iBlock < m_blockPositions.size();
256 iBlock = currentBlock.fetch_add( 1 ) )
257 {
258 if( !m_blockPositionsWasProcessed[iBlock] )
259 {
260 renderBlockTracing( ptrPBO, iBlock );
262 numBlocksRendered++;
263 }
264
265 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::steady_clock::now()
266 - startTime );
267
268 if( diff.count() > timeLimit )
269 break;
270 }
271 };
272
273 BS::multi_future<void> futures;
274
275 for( size_t i = 0; i < tp.get_thread_count(); ++i )
276 futures.push_back( tp.submit_task( processBlocks ) );
277
278 futures.wait();
279
280 m_blockRenderProgressCount += numBlocksRendered;
281
283 {
284 m_activityReporter->Report(
285 wxString::Format( _( "Rendering: %.0f %%" ),
286 (float) ( m_blockRenderProgressCount * 100 ) / (float) m_blockPositions.size() ) );
287 }
288
289 // Check if it finish the rendering and if should continue to a post processing
290 // or mark it as finished
292 {
293 if( m_boardAdapter.m_Cfg->m_Render.raytrace_post_processing )
295 else
297 }
298}
299
300
301void RENDER_3D_RAYTRACE_BASE::renderFinalColor( uint8_t* ptrPBO, const SFVEC4F& rgbColor,
302 bool applyColorSpaceConversion )
303{
304 SFVEC4F color = rgbColor;
305
306#ifdef USE_SRGB_SPACE
308 // if( applyColorSpaceConversion )
309 // rgbColor = glm::convertLinearToSRGB( rgbColor );
310
311 if( applyColorSpaceConversion )
312 color = convertLinearToSRGB( rgbColor );
313#endif
314
315 ptrPBO[0] = (unsigned int) glm::clamp( (int) ( color.r * 255 ), 0, 255 );
316 ptrPBO[1] = (unsigned int) glm::clamp( (int) ( color.g * 255 ), 0, 255 );
317 ptrPBO[2] = (unsigned int) glm::clamp( (int) ( color.b * 255 ), 0, 255 );
318 ptrPBO[3] = (unsigned int) glm::clamp( (int) ( color.a * 255 ), 0, 255 );
319}
320
321
322static void HITINFO_PACKET_init( HITINFO_PACKET* aHitPacket )
323{
324 // Initialize hitPacket with a "not hit" information
325 for( unsigned int i = 0; i < RAYPACKET_RAYS_PER_PACKET; ++i )
326 {
327 aHitPacket[i].m_HitInfo.m_tHit = std::numeric_limits<float>::infinity();
328 aHitPacket[i].m_HitInfo.m_acc_node_info = 0;
329 aHitPacket[i].m_hitresult = false;
330 aHitPacket[i].m_HitInfo.m_HitNormal = SFVEC3F( 0.0f );
331 aHitPacket[i].m_HitInfo.m_ShadowFactor = 1.0f;
332 }
333}
334
335
336void RENDER_3D_RAYTRACE_BASE::renderRayPackets( const SFVEC4F* bgColorY, const RAY* aRayPkt,
337 HITINFO_PACKET* aHitPacket, bool is_testShadow,
338 SFVEC4F* aOutHitColor )
339{
340 for( unsigned int y = 0, i = 0; y < RAYPACKET_DIM; ++y )
341 {
342 for( unsigned int x = 0; x < RAYPACKET_DIM; ++x, ++i )
343 {
344 if( aHitPacket[i].m_hitresult == true )
345 {
346 aOutHitColor[i] = shadeHit( bgColorY[y], aRayPkt[i], aHitPacket[i].m_HitInfo,
347 false, 0, is_testShadow );
348 }
349 else
350 {
351 aOutHitColor[i] = bgColorY[y];
352 }
353 }
354 }
355}
356
357
359 const HITINFO_PACKET* aHitPck_X0Y0,
360 const HITINFO_PACKET* aHitPck_AA_X1Y1,
361 const RAY* aRayPck, SFVEC4F* aOutHitColor )
362{
363 const bool is_testShadow = m_boardAdapter.m_Cfg->m_Render.raytrace_shadows;
364
365 for( unsigned int y = 0, i = 0; y < RAYPACKET_DIM; ++y )
366 {
367 for( unsigned int x = 0; x < RAYPACKET_DIM; ++x, ++i )
368 {
369 const RAY& rayAA = aRayPck[i];
370
371 HITINFO hitAA;
372 hitAA.m_tHit = std::numeric_limits<float>::infinity();
373 hitAA.m_acc_node_info = 0;
374
375 bool hitted = false;
376
377 const unsigned int idx0y1 = ( x + 0 ) + RAYPACKET_DIM * ( y + 1 );
378 const unsigned int idx1y1 = ( x + 1 ) + RAYPACKET_DIM * ( y + 1 );
379
380 // Gets the node info from the hit.
381 const unsigned int nodex0y0 = aHitPck_X0Y0[ i ].m_HitInfo.m_acc_node_info;
382 const unsigned int node_AA_x0y0 = aHitPck_AA_X1Y1[ i ].m_HitInfo.m_acc_node_info;
383
384 unsigned int nodex1y0 = 0;
385
386 if( x < ( RAYPACKET_DIM - 1 ) )
387 nodex1y0 = aHitPck_X0Y0[i + 1].m_HitInfo.m_acc_node_info;
388
389 unsigned int nodex0y1 = 0;
390
391 if( y < ( RAYPACKET_DIM - 1 ) && idx0y1 < RAYPACKET_RAYS_PER_PACKET )
392 nodex0y1 = aHitPck_X0Y0[idx0y1].m_HitInfo.m_acc_node_info;
393
394 unsigned int nodex1y1 = 0;
395
396 if( ( x < ( RAYPACKET_DIM - 1 ) )
397 && ( y < ( RAYPACKET_DIM - 1 ) )
398 && idx1y1 < RAYPACKET_RAYS_PER_PACKET )
399 {
400 nodex1y1 = aHitPck_X0Y0[idx1y1].m_HitInfo.m_acc_node_info;
401 }
402
403 // If all nodes are equal we assume there was no change on the object hits.
404 if( ( nodex0y0 != nodex1y0 && nodex1y0 != 0 )
405 || ( nodex0y0 != nodex0y1 && nodex0y1 != 0 )
406 || ( nodex0y0 != nodex1y1 && nodex1y1 != 0 )
407 || ( nodex0y0 != node_AA_x0y0 ) )
408 {
409 // Try to intersect the different nodes
410 // It tests the possible combination of hitted or not hitted points
411 // This will try to get the best hit for this ray
412
413 if( nodex0y0 != 0 )
414 hitted |= m_accelerator->Intersect( rayAA, hitAA, nodex0y0 );
415
416 if( nodex1y0 != 0
417 && nodex0y0 != nodex1y0 )
418 {
419 hitted |= m_accelerator->Intersect( rayAA, hitAA, nodex1y0 );
420 }
421
422 if( nodex0y1 != 0
423 && nodex0y0 != nodex0y1
424 && nodex1y0 != nodex0y1 )
425 {
426 hitted |= m_accelerator->Intersect( rayAA, hitAA, nodex0y1 );
427 }
428
429 if( nodex1y1 != 0
430 && nodex0y0 != nodex1y1
431 && nodex0y1 != nodex1y1
432 && nodex1y0 != nodex1y1 )
433 {
434 hitted |= m_accelerator->Intersect( rayAA, hitAA, nodex1y1 );
435 }
436
437 if( node_AA_x0y0 != 0
438 && nodex0y0 != node_AA_x0y0
439 && nodex0y1 != node_AA_x0y0
440 && nodex1y0 != node_AA_x0y0
441 && nodex1y1 != node_AA_x0y0 )
442 {
443 hitted |= m_accelerator->Intersect( rayAA, hitAA, node_AA_x0y0 );
444 }
445
446 if( hitted )
447 {
448 // If we got any result, shade it
449 aOutHitColor[i] = shadeHit( aBgColorY[y], rayAA, hitAA, false, 0, is_testShadow );
450 }
451 else
452 {
453 // Note: There are very few cases that will end on this situation
454 // so it is not so expensive to trace a single ray from the beginning
455
456 // It was missed the 'last nodes' so, trace a ray from the beginning
457 if( m_accelerator->Intersect( rayAA, hitAA ) )
458 aOutHitColor[i] = shadeHit( aBgColorY[y], rayAA, hitAA, false, 0, is_testShadow );
459 }
460 }
461 }
462 }
463}
464
465
466#define DISP_FACTOR 0.075f
467
468
469void RENDER_3D_RAYTRACE_BASE::renderBlockTracing( uint8_t* ptrPBO, signed int iBlock )
470{
471 // Initialize ray packets
472 const SFVEC2UI& blockPos = m_blockPositions[iBlock];
473 const SFVEC2I blockPosI = SFVEC2I( blockPos.x + m_xoffset, blockPos.y + m_yoffset );
474 const SFVEC2F randDisp = ( m_camera.GetProjection() == PROJECTION_TYPE::ORTHO ) ?
475 SFVEC2F( 0.0f, 0.0f ) :
477
478 RAYPACKET blockPacket( m_camera, (SFVEC2F) blockPosI + randDisp,
479 randDisp /* Displacement random factor */ );
480
481
483
484 HITINFO_PACKET_init( hitPacket_X0Y0 );
485
486 // Calculate background gradient color
487 SFVEC4F bgColor[RAYPACKET_DIM];// Store a vertical gradient color
488
489 for( unsigned int y = 0; y < RAYPACKET_DIM; ++y )
490 {
491 const float posYfactor = (float) ( blockPosI.y + y ) / (float) m_windowSize.y;
492
493 bgColor[y] = m_backgroundColorTop * SFVEC4F(posYfactor) +
494 m_backgroundColorBottom * ( SFVEC4F(1.0f) - SFVEC4F(posYfactor) );
495 }
496
497 // Intersect ray packets (calculate the intersection with rays and objects)
498 if( !m_accelerator->Intersect( blockPacket, hitPacket_X0Y0 ) )
499 {
500 // If block is empty then set shades and continue
501 if( m_boardAdapter.m_Cfg->m_Render.raytrace_post_processing )
502 {
503 for( unsigned int y = 0; y < RAYPACKET_DIM; ++y )
504 {
505 const SFVEC4F& outColor = bgColor[y];
506
507 const unsigned int yBlockPos = blockPos.y + y;
508
509 for( unsigned int x = 0; x < RAYPACKET_DIM; ++x )
510 {
511 m_postShaderSsao.SetPixelData( blockPos.x + x, yBlockPos,
512 SFVEC3F( 0.0f ), outColor,
513 SFVEC3F( 0.0f ), 0, 1.0f );
514 }
515 }
516 }
517
518 // This will set the output color to be displayed
519 // If post processing is enabled, it will not reflect the final result (as the final
520 // color will be computed on post processing) but it is used for report progress
521 const bool isFinalColor = !m_boardAdapter.m_Cfg->m_Render.raytrace_post_processing;
522
523 for( unsigned int y = 0; y < RAYPACKET_DIM; ++y )
524 {
525 const SFVEC4F& outColor = bgColor[y];
526
527 const unsigned int yConst = blockPos.x + ( ( y + blockPos.y ) * m_realBufferSize.x );
528
529 for( unsigned int x = 0; x < RAYPACKET_DIM; ++x )
530 {
531 uint8_t* ptr = &ptrPBO[( yConst + x ) * 4];
532
533 renderFinalColor( ptr, outColor, isFinalColor );
534 }
535 }
536
537 // There is nothing more here to do.. there are no hits ..
538 // just background so continue
539 return;
540 }
541
542 SFVEC4F hitColor_X0Y0[RAYPACKET_RAYS_PER_PACKET];
543
544 // Shade original (0, 0) hits ("paint" the intersected objects)
545 renderRayPackets( bgColor, blockPacket.m_ray, hitPacket_X0Y0,
546 m_boardAdapter.m_Cfg->m_Render.raytrace_shadows, hitColor_X0Y0 );
547
548 if( m_boardAdapter.m_Cfg->m_Render.raytrace_anti_aliasing )
549 {
550 SFVEC4F hitColor_AA_X1Y1[RAYPACKET_RAYS_PER_PACKET];
551
552 // Intersect one blockPosI + (0.5, 0.5) used for anti aliasing calculation
553 HITINFO_PACKET hitPacket_AA_X1Y1[RAYPACKET_RAYS_PER_PACKET];
554 HITINFO_PACKET_init( hitPacket_AA_X1Y1 );
555
556 RAYPACKET blockPacket_AA_X1Y1( m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.5f, 0.5f ),
557 randDisp );
558
559 if( !m_accelerator->Intersect( blockPacket_AA_X1Y1, hitPacket_AA_X1Y1 ) )
560 {
561 // Missed all the package
562 for( unsigned int y = 0, i = 0; y < RAYPACKET_DIM; ++y )
563 {
564 const SFVEC4F& outColor = bgColor[y];
565
566 for( unsigned int x = 0; x < RAYPACKET_DIM; ++x, ++i )
567 hitColor_AA_X1Y1[i] = outColor;
568 }
569 }
570 else
571 {
572 renderRayPackets( bgColor, blockPacket_AA_X1Y1.m_ray, hitPacket_AA_X1Y1,
573 m_boardAdapter.m_Cfg->m_Render.raytrace_shadows, hitColor_AA_X1Y1 );
574 }
575
576 SFVEC4F hitColor_AA_X1Y0[RAYPACKET_RAYS_PER_PACKET];
577 SFVEC4F hitColor_AA_X0Y1[RAYPACKET_RAYS_PER_PACKET];
578 SFVEC4F hitColor_AA_X0Y1_half[RAYPACKET_RAYS_PER_PACKET];
579
580 for( unsigned int i = 0; i < RAYPACKET_RAYS_PER_PACKET; ++i )
581 {
582 SFVEC4F color_average = ( hitColor_X0Y0[i] + hitColor_AA_X1Y1[i] ) * SFVEC4F( 0.5f );
583
584 hitColor_AA_X1Y0[i] = color_average;
585 hitColor_AA_X0Y1[i] = color_average;
586 hitColor_AA_X0Y1_half[i] = color_average;
587 }
588
589 RAY blockRayPck_AA_X1Y0[RAYPACKET_RAYS_PER_PACKET];
590 RAY blockRayPck_AA_X0Y1[RAYPACKET_RAYS_PER_PACKET];
591 RAY blockRayPck_AA_X1Y1_half[RAYPACKET_RAYS_PER_PACKET];
592
594 m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.5f - randDisp.x, randDisp.y ),
595 randDisp, blockRayPck_AA_X1Y0 );
596
598 m_camera, (SFVEC2F) blockPosI + SFVEC2F( randDisp.x, 0.5f - randDisp.y ),
599 randDisp, blockRayPck_AA_X0Y1 );
600
602 m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.25f - randDisp.x, 0.25f - randDisp.y ),
603 randDisp, blockRayPck_AA_X1Y1_half );
604
605 renderAntiAliasPackets( bgColor, hitPacket_X0Y0, hitPacket_AA_X1Y1, blockRayPck_AA_X1Y0,
606 hitColor_AA_X1Y0 );
607
608 renderAntiAliasPackets( bgColor, hitPacket_X0Y0, hitPacket_AA_X1Y1, blockRayPck_AA_X0Y1,
609 hitColor_AA_X0Y1 );
610
611 renderAntiAliasPackets( bgColor, hitPacket_X0Y0, hitPacket_AA_X1Y1,
612 blockRayPck_AA_X1Y1_half, hitColor_AA_X0Y1_half );
613
614 // Average the result
615 for( unsigned int i = 0; i < RAYPACKET_RAYS_PER_PACKET; ++i )
616 {
617 hitColor_X0Y0[i] = ( hitColor_X0Y0[i] + hitColor_AA_X1Y1[i] + hitColor_AA_X1Y0[i] +
618 hitColor_AA_X0Y1[i] + hitColor_AA_X0Y1_half[i] ) *
619 SFVEC4F( 1.0f / 5.0f );
620 }
621 }
622
623 // Copy results to the next stage
624 uint8_t* ptr = &ptrPBO[( blockPos.x + ( blockPos.y * m_realBufferSize.x ) ) * 4];
625
626 const uint32_t ptrInc = ( m_realBufferSize.x - RAYPACKET_DIM ) * 4;
627
628 if( m_boardAdapter.m_Cfg->m_Render.raytrace_post_processing )
629 {
630 SFVEC2I bPos;
631 bPos.y = blockPos.y;
632
633 for( unsigned int y = 0, i = 0; y < RAYPACKET_DIM; ++y )
634 {
635 bPos.x = blockPos.x;
636
637 for( unsigned int x = 0; x < RAYPACKET_DIM; ++x, ++i )
638 {
639 const SFVEC4F& hColor = hitColor_X0Y0[i];
640
641 if( hitPacket_X0Y0[i].m_hitresult == true )
642 {
643 m_postShaderSsao.SetPixelData( bPos.x, bPos.y,
644 hitPacket_X0Y0[i].m_HitInfo.m_HitNormal,
645 hColor,
646 blockPacket.m_ray[i].at(
647 hitPacket_X0Y0[i].m_HitInfo.m_tHit ),
648 hitPacket_X0Y0[i].m_HitInfo.m_tHit,
649 hitPacket_X0Y0[i].m_HitInfo.m_ShadowFactor );
650 }
651 else
652 {
653 m_postShaderSsao.SetPixelData( bPos.x, bPos.y, SFVEC3F( 0.0f ), hColor,
654 SFVEC3F( 0.0f ), 0, 1.0f );
655 }
656
657 renderFinalColor( ptr, hColor, false );
658
659 bPos.x++;
660 ptr += 4;
661 }
662
663 ptr += ptrInc;
664 bPos.y++;
665 }
666 }
667 else
668 {
669 for( unsigned int y = 0, i = 0; y < RAYPACKET_DIM; ++y )
670 {
671 for( unsigned int x = 0; x < RAYPACKET_DIM; ++x, ++i )
672 {
673 renderFinalColor( ptr, hitColor_X0Y0[i], true );
674 ptr += 4;
675 }
676
677 ptr += ptrInc;
678 }
679 }
680}
681
682
684{
685 if( m_boardAdapter.m_Cfg->m_Render.raytrace_post_processing )
686 {
688 m_activityReporter->Report( _( "Rendering: Post processing shader" ) );
689
690 m_postShaderSsao.SetShadowsEnabled( m_boardAdapter.m_Cfg->m_Render.raytrace_shadows );
691
692 std::atomic<size_t> nextBlock( 0 );
693 std::atomic<size_t> threadsFinished( 0 );
694
695 size_t parallelThreadCount = std::max<size_t>( std::thread::hardware_concurrency(), 2 );
696
697 for( size_t ii = 0; ii < parallelThreadCount; ++ii )
698 {
699 std::thread t = std::thread( [&]()
700 {
701 for( size_t y = nextBlock.fetch_add( 1 ); y < m_realBufferSize.y;
702 y = nextBlock.fetch_add( 1 ) )
703 {
704 SFVEC3F* ptr = &m_shaderBuffer[ y * m_realBufferSize.x ];
705
706 for( signed int x = 0; x < (int)m_realBufferSize.x; ++x )
707 {
708 *ptr = m_postShaderSsao.Shade( SFVEC2I( x, y ) );
709 ptr++;
710 }
711 }
712
713 threadsFinished++;
714 } );
715
716 t.detach();
717 }
718
719 while( threadsFinished < parallelThreadCount )
720 std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
721
722 m_postShaderSsao.SetShadedBuffer( m_shaderBuffer );
723
724 // Set next state
726 }
727 else
728 {
729 // As this was an invalid state, set to finish
731 }
732}
733
734
736{
737 if( m_boardAdapter.m_Cfg->m_Render.raytrace_post_processing )
738 {
739 // Now blurs the shader result and compute the final color
740 std::atomic<size_t> nextBlock( 0 );
741 std::atomic<size_t> threadsFinished( 0 );
742
743 size_t parallelThreadCount = std::max<size_t>( std::thread::hardware_concurrency(), 2 );
744
745 for( size_t ii = 0; ii < parallelThreadCount; ++ii )
746 {
747 std::thread t = std::thread( [&]()
748 {
749 for( size_t y = nextBlock.fetch_add( 1 ); y < m_realBufferSize.y;
750 y = nextBlock.fetch_add( 1 ) )
751 {
752 uint8_t* ptr = &ptrPBO[ y * m_realBufferSize.x * 4 ];
753
754 for( signed int x = 0; x < (int)m_realBufferSize.x; ++x )
755 {
756 const SFVEC3F bluredShadeColor = m_postShaderSsao.Blur( SFVEC2I( x, y ) );
757
758#ifdef USE_SRGB_SPACE
759 const SFVEC4F originColor = convertLinearToSRGBA(
760 m_postShaderSsao.GetColorAtNotProtected( SFVEC2I( x, y ) ) );
761#else
762 const SFVEC4F originColor =
763 m_postShaderSsao.GetColorAtNotProtected( SFVEC2I( x, y ) );
764#endif
765 const SFVEC4F shadedColor = m_postShaderSsao.ApplyShadeColor(
766 SFVEC2I( x, y ), originColor, bluredShadeColor );
767
768 renderFinalColor( ptr, shadedColor, false );
769
770 ptr += 4;
771 }
772 }
773
774 threadsFinished++;
775 } );
776
777 t.detach();
778 }
779
780 while( threadsFinished < parallelThreadCount )
781 std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
782
783 // Debug code
784 //m_postShaderSsao.DebugBuffersOutputAsImages();
785 }
786
787 // End rendering
789}
790
791
793{
794 m_isPreview = true;
795
799
800 std::atomic<size_t> nextBlock( 0 );
801 std::atomic<size_t> threadsFinished( 0 );
802
803 size_t parallelThreadCount = std::min<size_t>(
804 std::max<size_t>( std::thread::hardware_concurrency(), 2 ),
805 m_blockPositions.size() );
806
807 for( size_t ii = 0; ii < parallelThreadCount; ++ii )
808 {
809 std::thread t = std::thread( [&]()
810 {
811 for( size_t iBlock = nextBlock.fetch_add( 1 ); iBlock < m_blockPositionsFast.size();
812 iBlock = nextBlock.fetch_add( 1 ) )
813 {
814 const SFVEC2UI& windowPosUI = m_blockPositionsFast[ iBlock ];
815 const SFVEC2I windowsPos = SFVEC2I( windowPosUI.x + m_xoffset,
816 windowPosUI.y + m_yoffset );
817
818 RAYPACKET blockPacket( m_camera, windowsPos, 4 );
819
821
822 // Initialize hitPacket with a "not hit" information
823 for( HITINFO_PACKET& packet : hitPacket )
824 {
825 packet.m_HitInfo.m_tHit = std::numeric_limits<float>::infinity();
826 packet.m_HitInfo.m_acc_node_info = 0;
827 packet.m_hitresult = false;
828 }
829
830 // Intersect packet block
831 m_accelerator->Intersect( blockPacket, hitPacket );
832
833 // Calculate background gradient color
834 SFVEC4F bgColor[RAYPACKET_DIM];
835
836 SFVEC4F bgTopColor = m_backgroundColorTop;
837 SFVEC4F bgBotColor = m_backgroundColorBottom;
838
839 for( unsigned int y = 0; y < RAYPACKET_DIM; ++y )
840 {
841 const float posYfactor =
842 (float) ( windowsPos.y + y * 4.0f ) / (float) m_windowSize.y;
843
844 bgColor[y] = bgTopColor * SFVEC4F( posYfactor )
845 + bgBotColor * ( SFVEC4F( 1.0f ) - SFVEC4F( posYfactor ) );
846 }
847
848 COLOR_RGBA hitColorShading[RAYPACKET_RAYS_PER_PACKET];
849
850 for( unsigned int i = 0; i < RAYPACKET_RAYS_PER_PACKET; ++i )
851 {
852 const SFVEC4F bhColorY = bgColor[i / RAYPACKET_DIM];
853
854 if( hitPacket[i].m_hitresult == true )
855 {
856 const SFVEC4F hitColor = shadeHit( bhColorY, blockPacket.m_ray[i],
857 hitPacket[i].m_HitInfo, false,
858 0, false );
859
860 hitColorShading[i] = COLOR_RGBA( hitColor );
861 }
862 else
863 hitColorShading[i] = bhColorY;
864 }
865
866 COLOR_RGBA cLRB_old[( RAYPACKET_DIM - 1 )];
867
868 for( unsigned int y = 0; y < ( RAYPACKET_DIM - 1 ); ++y )
869 {
870 const SFVEC4F bgColorY = bgColor[y];
871 const COLOR_RGBA bgColorYRGB = COLOR_RGBA( bgColorY );
872
873 // This stores cRTB from the last block to be reused next time in a cLTB pixel
874 COLOR_RGBA cRTB_old;
875
876 //RAY cRTB_ray;
877 //HITINFO cRTB_hitInfo;
878
879 for( unsigned int x = 0; x < ( RAYPACKET_DIM - 1 ); ++x )
880 {
881 // pxl 0 pxl 1 pxl 2 pxl 3 pxl 4
882 // x0 x1 ...
883 // .---------------------------.
884 // y0 | cLT | cxxx | cLRT | cxxx | cRT |
885 // | cxxx | cLTC | cxxx | cRTC | cxxx |
886 // | cLTB | cxxx | cC | cxxx | cRTB |
887 // | cxxx | cLBC | cxxx | cRBC | cxxx |
888 // '---------------------------'
889 // y1 | cLB | cxxx | cLRB | cxxx | cRB |
890
891 const unsigned int iLT = ( ( x + 0 ) + RAYPACKET_DIM * ( y + 0 ) );
892 const unsigned int iRT = ( ( x + 1 ) + RAYPACKET_DIM * ( y + 0 ) );
893 const unsigned int iLB = ( ( x + 0 ) + RAYPACKET_DIM * ( y + 1 ) );
894 const unsigned int iRB = ( ( x + 1 ) + RAYPACKET_DIM * ( y + 1 ) );
895
896 // !TODO: skip when there are no hits
897 const COLOR_RGBA& cLT = hitColorShading[ iLT ];
898 const COLOR_RGBA& cRT = hitColorShading[ iRT ];
899 const COLOR_RGBA& cLB = hitColorShading[ iLB ];
900 const COLOR_RGBA& cRB = hitColorShading[ iRB ];
901
902 // Trace and shade cC
903 COLOR_RGBA cC = bgColorYRGB;
904
905 const SFVEC3F& oriLT = blockPacket.m_ray[ iLT ].m_Origin;
906 const SFVEC3F& oriRB = blockPacket.m_ray[ iRB ].m_Origin;
907
908 const SFVEC3F& dirLT = blockPacket.m_ray[ iLT ].m_Dir;
909 const SFVEC3F& dirRB = blockPacket.m_ray[ iRB ].m_Dir;
910
911 SFVEC3F oriC;
912 SFVEC3F dirC;
913
914 HITINFO centerHitInfo;
915 centerHitInfo.m_tHit = std::numeric_limits<float>::infinity();
916
917 bool hittedC = false;
918
919 if( ( hitPacket[iLT].m_hitresult == true )
920 || ( hitPacket[iRT].m_hitresult == true )
921 || ( hitPacket[iLB].m_hitresult == true )
922 || ( hitPacket[iRB].m_hitresult == true ) )
923 {
924 oriC = ( oriLT + oriRB ) * 0.5f;
925 dirC = glm::normalize( ( dirLT + dirRB ) * 0.5f );
926
927 // Trace the center ray
928 RAY centerRay;
929 centerRay.Init( oriC, dirC );
930
931 const unsigned int nodeLT = hitPacket[ iLT ].m_HitInfo.m_acc_node_info;
932 const unsigned int nodeRT = hitPacket[ iRT ].m_HitInfo.m_acc_node_info;
933 const unsigned int nodeLB = hitPacket[ iLB ].m_HitInfo.m_acc_node_info;
934 const unsigned int nodeRB = hitPacket[ iRB ].m_HitInfo.m_acc_node_info;
935
936 if( nodeLT != 0 )
937 hittedC |= m_accelerator->Intersect( centerRay, centerHitInfo,
938 nodeLT );
939
940 if( ( nodeRT != 0 ) && ( nodeRT != nodeLT ) )
941 hittedC |= m_accelerator->Intersect( centerRay, centerHitInfo,
942 nodeRT );
943
944 if( ( nodeLB != 0 ) && ( nodeLB != nodeLT ) && ( nodeLB != nodeRT ) )
945 hittedC |= m_accelerator->Intersect( centerRay, centerHitInfo,
946 nodeLB );
947
948 if( ( nodeRB != 0 ) && ( nodeRB != nodeLB ) && ( nodeRB != nodeLT )
949 && ( nodeRB != nodeRT ) )
950 hittedC |= m_accelerator->Intersect( centerRay, centerHitInfo,
951 nodeRB );
952
953 if( hittedC )
954 {
955 cC = COLOR_RGBA( shadeHit( bgColorY, centerRay, centerHitInfo,
956 false, 0, false ) );
957 }
958 else
959 {
960 centerHitInfo.m_tHit = std::numeric_limits<float>::infinity();
961 hittedC = m_accelerator->Intersect( centerRay, centerHitInfo );
962
963 if( hittedC )
964 cC = COLOR_RGBA( shadeHit( bgColorY, centerRay, centerHitInfo,
965 false, 0, false ) );
966 }
967 }
968
969 // Trace and shade cLRT
970 COLOR_RGBA cLRT = bgColorYRGB;
971
972 const SFVEC3F& oriRT = blockPacket.m_ray[ iRT ].m_Origin;
973 const SFVEC3F& dirRT = blockPacket.m_ray[ iRT ].m_Dir;
974
975 if( y == 0 )
976 {
977 // Trace the center ray
978 RAY rayLRT;
979 rayLRT.Init( ( oriLT + oriRT ) * 0.5f,
980 glm::normalize( ( dirLT + dirRT ) * 0.5f ) );
981
982 HITINFO hitInfoLRT;
983 hitInfoLRT.m_tHit = std::numeric_limits<float>::infinity();
984
985 if( hitPacket[iLT].m_hitresult && hitPacket[iRT].m_hitresult
986 && ( hitPacket[iLT].m_HitInfo.pHitObject
987 == hitPacket[iRT].m_HitInfo.pHitObject ) )
988 {
989 hitInfoLRT.pHitObject = hitPacket[ iLT ].m_HitInfo.pHitObject;
990 hitInfoLRT.m_tHit = ( hitPacket[ iLT ].m_HitInfo.m_tHit +
991 hitPacket[ iRT ].m_HitInfo.m_tHit ) * 0.5f;
992 hitInfoLRT.m_HitNormal =
993 glm::normalize( ( hitPacket[iLT].m_HitInfo.m_HitNormal
994 + hitPacket[iRT].m_HitInfo.m_HitNormal )
995 * 0.5f );
996
997 cLRT = COLOR_RGBA( shadeHit( bgColorY, rayLRT, hitInfoLRT, false,
998 0, false ) );
999 cLRT = BlendColor( cLRT, BlendColor( cLT, cRT ) );
1000 }
1001 else
1002 {
1003 // If any hits
1004 if( hitPacket[ iLT ].m_hitresult || hitPacket[ iRT ].m_hitresult )
1005 {
1006 const unsigned int nodeLT =
1007 hitPacket[ iLT ].m_HitInfo.m_acc_node_info;
1008 const unsigned int nodeRT =
1009 hitPacket[ iRT ].m_HitInfo.m_acc_node_info;
1010
1011 bool hittedLRT = false;
1012
1013 if( nodeLT != 0 )
1014 hittedLRT |= m_accelerator->Intersect( rayLRT, hitInfoLRT,
1015 nodeLT );
1016
1017 if( ( nodeRT != 0 ) && ( nodeRT != nodeLT ) )
1018 hittedLRT |= m_accelerator->Intersect( rayLRT, hitInfoLRT,
1019 nodeRT );
1020
1021 if( hittedLRT )
1022 cLRT = COLOR_RGBA( shadeHit( bgColorY, rayLRT, hitInfoLRT,
1023 false, 0, false ) );
1024 else
1025 {
1026 hitInfoLRT.m_tHit = std::numeric_limits<float>::infinity();
1027
1028 if( m_accelerator->Intersect( rayLRT,hitInfoLRT ) )
1029 cLRT = COLOR_RGBA( shadeHit( bgColorY, rayLRT,
1030 hitInfoLRT, false,
1031 0, false ) );
1032 }
1033 }
1034 }
1035 }
1036 else
1037 {
1038 cLRT = cLRB_old[x];
1039 }
1040
1041 // Trace and shade cLTB
1042 COLOR_RGBA cLTB = bgColorYRGB;
1043
1044 if( x == 0 )
1045 {
1046 const SFVEC3F &oriLB = blockPacket.m_ray[ iLB ].m_Origin;
1047 const SFVEC3F& dirLB = blockPacket.m_ray[ iLB ].m_Dir;
1048
1049 // Trace the center ray
1050 RAY rayLTB;
1051 rayLTB.Init( ( oriLT + oriLB ) * 0.5f,
1052 glm::normalize( ( dirLT + dirLB ) * 0.5f ) );
1053
1054 HITINFO hitInfoLTB;
1055 hitInfoLTB.m_tHit = std::numeric_limits<float>::infinity();
1056
1057 if( hitPacket[ iLT ].m_hitresult && hitPacket[ iLB ].m_hitresult
1058 && ( hitPacket[ iLT ].m_HitInfo.pHitObject ==
1059 hitPacket[ iLB ].m_HitInfo.pHitObject ) )
1060 {
1061 hitInfoLTB.pHitObject = hitPacket[ iLT ].m_HitInfo.pHitObject;
1062 hitInfoLTB.m_tHit = ( hitPacket[ iLT ].m_HitInfo.m_tHit +
1063 hitPacket[ iLB ].m_HitInfo.m_tHit ) * 0.5f;
1064 hitInfoLTB.m_HitNormal =
1065 glm::normalize( ( hitPacket[iLT].m_HitInfo.m_HitNormal
1066 + hitPacket[iLB].m_HitInfo.m_HitNormal )
1067 * 0.5f );
1068 cLTB = COLOR_RGBA(
1069 shadeHit( bgColorY, rayLTB, hitInfoLTB, false, 0, false ) );
1070 cLTB = BlendColor( cLTB, BlendColor( cLT, cLB) );
1071 }
1072 else
1073 {
1074 // If any hits
1075 if( hitPacket[ iLT ].m_hitresult || hitPacket[ iLB ].m_hitresult )
1076 {
1077 const unsigned int nodeLT =
1078 hitPacket[ iLT ].m_HitInfo.m_acc_node_info;
1079 const unsigned int nodeLB =
1080 hitPacket[ iLB ].m_HitInfo.m_acc_node_info;
1081
1082 bool hittedLTB = false;
1083
1084 if( nodeLT != 0 )
1085 hittedLTB |= m_accelerator->Intersect( rayLTB, hitInfoLTB,
1086 nodeLT );
1087
1088 if( ( nodeLB != 0 ) && ( nodeLB != nodeLT ) )
1089 hittedLTB |= m_accelerator->Intersect( rayLTB, hitInfoLTB,
1090 nodeLB );
1091
1092 if( hittedLTB )
1093 cLTB = COLOR_RGBA( shadeHit( bgColorY, rayLTB, hitInfoLTB,
1094 false, 0, false ) );
1095 else
1096 {
1097 hitInfoLTB.m_tHit = std::numeric_limits<float>::infinity();
1098
1099 if( m_accelerator->Intersect( rayLTB, hitInfoLTB ) )
1100 cLTB = COLOR_RGBA( shadeHit( bgColorY, rayLTB,
1101 hitInfoLTB, false,
1102 0, false ) );
1103 }
1104 }
1105 }
1106 }
1107 else
1108 {
1109 cLTB = cRTB_old;
1110 }
1111
1112 // Trace and shade cRTB
1113 COLOR_RGBA cRTB = bgColorYRGB;
1114
1115 // Trace the center ray
1116 RAY rayRTB;
1117 rayRTB.Init( ( oriRT + oriRB ) * 0.5f,
1118 glm::normalize( ( dirRT + dirRB ) * 0.5f ) );
1119
1120 HITINFO hitInfoRTB;
1121 hitInfoRTB.m_tHit = std::numeric_limits<float>::infinity();
1122
1123 if( hitPacket[ iRT ].m_hitresult && hitPacket[ iRB ].m_hitresult
1124 && ( hitPacket[ iRT ].m_HitInfo.pHitObject ==
1125 hitPacket[ iRB ].m_HitInfo.pHitObject ) )
1126 {
1127 hitInfoRTB.pHitObject = hitPacket[ iRT ].m_HitInfo.pHitObject;
1128
1129 hitInfoRTB.m_tHit = ( hitPacket[ iRT ].m_HitInfo.m_tHit +
1130 hitPacket[ iRB ].m_HitInfo.m_tHit ) * 0.5f;
1131
1132 hitInfoRTB.m_HitNormal =
1133 glm::normalize( ( hitPacket[iRT].m_HitInfo.m_HitNormal
1134 + hitPacket[iRB].m_HitInfo.m_HitNormal )
1135 * 0.5f );
1136
1137 cRTB = COLOR_RGBA( shadeHit( bgColorY, rayRTB, hitInfoRTB, false, 0,
1138 false ) );
1139 cRTB = BlendColor( cRTB, BlendColor( cRT, cRB ) );
1140 }
1141 else
1142 {
1143 // If any hits
1144 if( hitPacket[ iRT ].m_hitresult || hitPacket[ iRB ].m_hitresult )
1145 {
1146 const unsigned int nodeRT =
1147 hitPacket[ iRT ].m_HitInfo.m_acc_node_info;
1148 const unsigned int nodeRB =
1149 hitPacket[ iRB ].m_HitInfo.m_acc_node_info;
1150
1151 bool hittedRTB = false;
1152
1153 if( nodeRT != 0 )
1154 hittedRTB |= m_accelerator->Intersect( rayRTB, hitInfoRTB,
1155 nodeRT );
1156
1157 if( ( nodeRB != 0 ) && ( nodeRB != nodeRT ) )
1158 hittedRTB |= m_accelerator->Intersect( rayRTB, hitInfoRTB,
1159 nodeRB );
1160
1161 if( hittedRTB )
1162 {
1163 cRTB = COLOR_RGBA( shadeHit( bgColorY, rayRTB, hitInfoRTB,
1164 false, 0, false) );
1165 }
1166 else
1167 {
1168 hitInfoRTB.m_tHit = std::numeric_limits<float>::infinity();
1169
1170 if( m_accelerator->Intersect( rayRTB, hitInfoRTB ) )
1171 cRTB = COLOR_RGBA( shadeHit( bgColorY, rayRTB, hitInfoRTB,
1172 false, 0, false ) );
1173 }
1174 }
1175 }
1176
1177 cRTB_old = cRTB;
1178
1179 // Trace and shade cLRB
1180 COLOR_RGBA cLRB = bgColorYRGB;
1181
1182 const SFVEC3F& oriLB = blockPacket.m_ray[ iLB ].m_Origin;
1183 const SFVEC3F& dirLB = blockPacket.m_ray[ iLB ].m_Dir;
1184
1185 // Trace the center ray
1186 RAY rayLRB;
1187 rayLRB.Init( ( oriLB + oriRB ) * 0.5f,
1188 glm::normalize( ( dirLB + dirRB ) * 0.5f ) );
1189
1190 HITINFO hitInfoLRB;
1191 hitInfoLRB.m_tHit = std::numeric_limits<float>::infinity();
1192
1193 if( hitPacket[iLB].m_hitresult && hitPacket[iRB].m_hitresult
1194 && ( hitPacket[iLB].m_HitInfo.pHitObject ==
1195 hitPacket[iRB].m_HitInfo.pHitObject ) )
1196 {
1197 hitInfoLRB.pHitObject = hitPacket[ iLB ].m_HitInfo.pHitObject;
1198
1199 hitInfoLRB.m_tHit = ( hitPacket[ iLB ].m_HitInfo.m_tHit +
1200 hitPacket[ iRB ].m_HitInfo.m_tHit ) * 0.5f;
1201
1202 hitInfoLRB.m_HitNormal =
1203 glm::normalize( ( hitPacket[iLB].m_HitInfo.m_HitNormal
1204 + hitPacket[iRB].m_HitInfo.m_HitNormal )
1205 * 0.5f );
1206
1207 cLRB = COLOR_RGBA( shadeHit( bgColorY, rayLRB, hitInfoLRB, false, 0,
1208 false ) );
1209 cLRB = BlendColor( cLRB, BlendColor( cLB, cRB ) );
1210 }
1211 else
1212 {
1213 // If any hits
1214 if( hitPacket[ iLB ].m_hitresult || hitPacket[ iRB ].m_hitresult )
1215 {
1216 const unsigned int nodeLB =
1217 hitPacket[ iLB ].m_HitInfo.m_acc_node_info;
1218 const unsigned int nodeRB =
1219 hitPacket[ iRB ].m_HitInfo.m_acc_node_info;
1220
1221 bool hittedLRB = false;
1222
1223 if( nodeLB != 0 )
1224 hittedLRB |= m_accelerator->Intersect( rayLRB, hitInfoLRB,
1225 nodeLB );
1226
1227 if( ( nodeRB != 0 ) && ( nodeRB != nodeLB ) )
1228 hittedLRB |= m_accelerator->Intersect( rayLRB, hitInfoLRB,
1229 nodeRB );
1230
1231 if( hittedLRB )
1232 {
1233 cLRB = COLOR_RGBA( shadeHit( bgColorY, rayLRB, hitInfoLRB,
1234 false, 0, false ) );
1235 }
1236 else
1237 {
1238 hitInfoLRB.m_tHit = std::numeric_limits<float>::infinity();
1239
1240 if( m_accelerator->Intersect( rayLRB, hitInfoLRB ) )
1241 cLRB = COLOR_RGBA( shadeHit( bgColorY, rayLRB, hitInfoLRB,
1242 false, 0, false ) );
1243 }
1244 }
1245 }
1246
1247 cLRB_old[x] = cLRB;
1248
1249 // Trace and shade cLTC
1250 COLOR_RGBA cLTC = BlendColor( cLT , cC );
1251
1252 if( hitPacket[ iLT ].m_hitresult || hittedC )
1253 {
1254 // Trace the center ray
1255 RAY rayLTC;
1256 rayLTC.Init( ( oriLT + oriC ) * 0.5f,
1257 glm::normalize( ( dirLT + dirC ) * 0.5f ) );
1258
1259 HITINFO hitInfoLTC;
1260 hitInfoLTC.m_tHit = std::numeric_limits<float>::infinity();
1261
1262 bool hitted = false;
1263
1264 if( hittedC )
1265 hitted = centerHitInfo.pHitObject->Intersect( rayLTC, hitInfoLTC );
1266 else if( hitPacket[ iLT ].m_hitresult )
1267 hitted = hitPacket[ iLT ].m_HitInfo.pHitObject->Intersect(
1268 rayLTC,
1269 hitInfoLTC );
1270
1271 if( hitted )
1272 cLTC = COLOR_RGBA( shadeHit( bgColorY, rayLTC, hitInfoLTC, false,
1273 0, false ) );
1274 }
1275
1276 // Trace and shade cRTC
1277 COLOR_RGBA cRTC = BlendColor( cRT , cC );
1278
1279 if( hitPacket[ iRT ].m_hitresult || hittedC )
1280 {
1281 // Trace the center ray
1282 RAY rayRTC;
1283 rayRTC.Init( ( oriRT + oriC ) * 0.5f,
1284 glm::normalize( ( dirRT + dirC ) * 0.5f ) );
1285
1286 HITINFO hitInfoRTC;
1287 hitInfoRTC.m_tHit = std::numeric_limits<float>::infinity();
1288
1289 bool hitted = false;
1290
1291 if( hittedC )
1292 hitted = centerHitInfo.pHitObject->Intersect( rayRTC, hitInfoRTC );
1293 else if( hitPacket[ iRT ].m_hitresult )
1294 hitted = hitPacket[iRT].m_HitInfo.pHitObject->Intersect(
1295 rayRTC, hitInfoRTC );
1296
1297 if( hitted )
1298 cRTC = COLOR_RGBA( shadeHit( bgColorY, rayRTC, hitInfoRTC, false,
1299 0, false ) );
1300 }
1301
1302 // Trace and shade cLBC
1303 COLOR_RGBA cLBC = BlendColor( cLB , cC );
1304
1305 if( hitPacket[ iLB ].m_hitresult || hittedC )
1306 {
1307 // Trace the center ray
1308 RAY rayLBC;
1309 rayLBC.Init( ( oriLB + oriC ) * 0.5f,
1310 glm::normalize( ( dirLB + dirC ) * 0.5f ) );
1311
1312 HITINFO hitInfoLBC;
1313 hitInfoLBC.m_tHit = std::numeric_limits<float>::infinity();
1314
1315 bool hitted = false;
1316
1317 if( hittedC )
1318 hitted = centerHitInfo.pHitObject->Intersect( rayLBC, hitInfoLBC );
1319 else if( hitPacket[ iLB ].m_hitresult )
1320 hitted = hitPacket[iLB].m_HitInfo.pHitObject->Intersect(
1321 rayLBC, hitInfoLBC );
1322
1323 if( hitted )
1324 cLBC = COLOR_RGBA( shadeHit( bgColorY, rayLBC, hitInfoLBC, false,
1325 0, false ) );
1326 }
1327
1328 // Trace and shade cRBC
1329 COLOR_RGBA cRBC = BlendColor( cRB , cC );
1330
1331 if( hitPacket[ iRB ].m_hitresult || hittedC )
1332 {
1333 // Trace the center ray
1334 RAY rayRBC;
1335 rayRBC.Init( ( oriRB + oriC ) * 0.5f,
1336 glm::normalize( ( dirRB + dirC ) * 0.5f ) );
1337
1338 HITINFO hitInfoRBC;
1339 hitInfoRBC.m_tHit = std::numeric_limits<float>::infinity();
1340
1341 bool hitted = false;
1342
1343 if( hittedC )
1344 hitted = centerHitInfo.pHitObject->Intersect( rayRBC, hitInfoRBC );
1345 else if( hitPacket[ iRB ].m_hitresult )
1346 hitted = hitPacket[iRB].m_HitInfo.pHitObject->Intersect(
1347 rayRBC, hitInfoRBC );
1348
1349 if( hitted )
1350 cRBC = COLOR_RGBA( shadeHit( bgColorY, rayRBC, hitInfoRBC, false,
1351 0, false ) );
1352 }
1353
1354 // Set pixel colors
1355 uint8_t* ptr =
1356 &ptrPBO[( 4 * x + m_blockPositionsFast[iBlock].x
1358 * ( m_blockPositionsFast[iBlock].y + 4 * y ) ) * 4];
1359
1360 SetPixelSRGBA( ptr + 0, cLT );
1361 SetPixelSRGBA( ptr + 4, BlendColor( cLT, cLRT, cLTC ) );
1362 SetPixelSRGBA( ptr + 8, cLRT );
1363 SetPixelSRGBA( ptr + 12, BlendColor( cLRT, cRT, cRTC ) );
1364
1365 ptr += m_realBufferSize.x * 4;
1366 SetPixelSRGBA( ptr + 0, BlendColor( cLT , cLTB, cLTC ) );
1367 SetPixelSRGBA( ptr + 4, BlendColor( cLTC, BlendColor( cLT , cC ) ) );
1368 SetPixelSRGBA( ptr + 8, BlendColor( cC, BlendColor( cLRT, cLTC, cRTC ) ) );
1369 SetPixelSRGBA( ptr + 12, BlendColor( cRTC, BlendColor( cRT , cC ) ) );
1370
1371 ptr += m_realBufferSize.x * 4;
1372 SetPixelSRGBA( ptr + 0, cLTB );
1373 SetPixelSRGBA( ptr + 4, BlendColor( cC, BlendColor( cLTB, cLTC, cLBC ) ) );
1374 SetPixelSRGBA( ptr + 8, cC );
1375 SetPixelSRGBA( ptr + 12, BlendColor( cC, BlendColor( cRTB, cRTC, cRBC ) ) );
1376
1377 ptr += m_realBufferSize.x * 4;
1378 SetPixelSRGBA( ptr + 0, BlendColor( cLB , cLTB, cLBC ) );
1379 SetPixelSRGBA( ptr + 4, BlendColor( cLBC, BlendColor( cLB , cC ) ) );
1380 SetPixelSRGBA( ptr + 8, BlendColor( cC, BlendColor( cLRB, cLBC, cRBC ) ) );
1381 SetPixelSRGBA( ptr + 12, BlendColor( cRBC, BlendColor( cRB , cC ) ) );
1382 }
1383 }
1384 }
1385
1386 threadsFinished++;
1387 } );
1388
1389 t.detach();
1390 }
1391
1392 while( threadsFinished < parallelThreadCount )
1393 std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
1394}
1395
1396
1397#define USE_EXPERIMENTAL_SOFT_SHADOWS 1
1398
1400 HITINFO& aHitInfo, bool aIsInsideObject,
1401 unsigned int aRecursiveLevel, bool is_testShadow ) const
1402{
1403 const MATERIAL* objMaterial = aHitInfo.pHitObject->GetMaterial();
1404 wxASSERT( objMaterial != nullptr );
1405
1406 SFVEC4F outColor =
1407 SFVEC4F( objMaterial->GetEmissiveColor() + objMaterial->GetAmbientColor(), 1.0f );
1408
1409 if( aRecursiveLevel > 7 )
1410 return outColor;
1411
1412 SFVEC3F hitPoint = aHitInfo.m_HitPoint;
1413
1414 hitPoint += aHitInfo.m_HitNormal * m_boardAdapter.GetNonCopperLayerThickness() * 0.6f;
1415
1416 const SFVEC4F diffuseColorObj =
1417 SFVEC4F( aHitInfo.pHitObject->GetDiffuseColor( aHitInfo ), 1.0f );
1418
1419 bool is_aa_enabled = m_boardAdapter.m_Cfg->m_Render.raytrace_anti_aliasing && !m_isPreview;
1420 float shadow_att_factor_sum = 0.0f;
1421
1422 unsigned int nr_lights_that_can_cast_shadows = 0;
1423
1424 for( const LIGHT* light : m_lights )
1425 {
1426 SFVEC3F vectorToLight;
1427 SFVEC3F colorOfLight;
1428 float distToLight;
1429
1430 light->GetLightParameters( hitPoint, vectorToLight, colorOfLight, distToLight );
1431
1432 const float NdotL = glm::dot( aHitInfo.m_HitNormal, vectorToLight );
1433
1434 // Only calc shade if the normal is facing the direction of light,
1435 // otherwise it is in the shadow
1436 if( NdotL >= FLT_EPSILON )
1437 {
1438 float shadow_att_factor_light = 1.0f;
1439
1440 if( is_testShadow && light->GetCastShadows() )
1441 {
1442 nr_lights_that_can_cast_shadows++;
1443
1444 // For rays that are recursive, just calculate one hit shadow
1445 if( aRecursiveLevel > 0 )
1446 {
1447 RAY rayToLight;
1448 rayToLight.Init( hitPoint, vectorToLight );
1449
1450 // Test if point is not in the shadow.
1451 // Test for any hit from the point in the direction of light
1452 if( m_accelerator->IntersectP( rayToLight, distToLight ) )
1453 shadow_att_factor_light = 0.0f;
1454
1455 }
1456 else // Experimental softshadow calculation
1457 {
1458 const unsigned int shadow_number_of_samples =
1459 m_boardAdapter.m_Cfg->m_Render.raytrace_nrsamples_shadows;
1460 const float shadow_inc_factor = 1.0f / (float) ( shadow_number_of_samples );
1461
1462 for( unsigned int i = 0; i < shadow_number_of_samples; ++i )
1463 {
1464 RAY rayToLight;
1465
1466 if( i == 0 )
1467 {
1468 rayToLight.Init( hitPoint, vectorToLight );
1469 }
1470 else
1471 {
1472 const SFVEC3F unifVector = UniformRandomHemisphereDirection();
1473 const SFVEC3F disturbed_vector_to_light =
1474 glm::normalize( vectorToLight + unifVector *
1475 m_boardAdapter.m_Cfg->m_Render.raytrace_spread_shadows );
1476
1477 rayToLight.Init( hitPoint, disturbed_vector_to_light );
1478 }
1479
1480 if( m_accelerator->IntersectP( rayToLight, distToLight ) )
1481 shadow_att_factor_light -= shadow_inc_factor;
1482 }
1483 }
1484
1485 shadow_att_factor_sum += shadow_att_factor_light;
1486 }
1487
1488 outColor += SFVEC4F( objMaterial->Shade( aRay, aHitInfo, NdotL, diffuseColorObj,
1489 vectorToLight, colorOfLight,
1490 shadow_att_factor_light ),
1491 1.0 );
1492 }
1493 }
1494
1495 // Improvement: this is not taking in account the lightcolor
1496 if( nr_lights_that_can_cast_shadows > 0 )
1497 {
1498 aHitInfo.m_ShadowFactor = glm::max(
1499 shadow_att_factor_sum / (float) ( nr_lights_that_can_cast_shadows * 1.0f ), 0.0f );
1500 }
1501 else
1502 {
1503 aHitInfo.m_ShadowFactor = 1.0f;
1504 }
1505
1506 // Clamp color to not be brighter than 1.0f
1507 outColor = glm::min( outColor, SFVEC4F( 1.0f ) );
1508
1509 if( !m_isPreview )
1510 {
1511 // Reflections
1512 if( ( objMaterial->GetReflection() > 0.0f )
1513 && m_boardAdapter.m_Cfg->m_Render.raytrace_reflections
1514 && ( aRecursiveLevel < objMaterial->GetReflectionRecursionCount() ) )
1515 {
1516 const unsigned int reflection_number_of_samples =
1517 objMaterial->GetReflectionRayCount();
1518
1519 SFVEC4F sum_color = SFVEC4F( 0.0f );
1520
1521 const SFVEC3F reflectVector = aRay.m_Dir - 2.0f *
1522 glm::dot( aRay.m_Dir, aHitInfo.m_HitNormal ) * aHitInfo.m_HitNormal;
1523
1524 for( unsigned int i = 0; i < reflection_number_of_samples; ++i )
1525 {
1526 RAY reflectedRay;
1527
1528 if( i == 0 )
1529 {
1530 reflectedRay.Init( hitPoint, reflectVector );
1531 }
1532 else
1533 {
1534 // Apply some randomize to the reflected vector
1535 const SFVEC3F random_reflectVector =
1536 glm::normalize( reflectVector
1538 * m_boardAdapter.m_Cfg->m_Render
1539 .raytrace_spread_reflections );
1540
1541 reflectedRay.Init( hitPoint, random_reflectVector );
1542 }
1543
1544 HITINFO reflectedHit;
1545 reflectedHit.m_tHit = std::numeric_limits<float>::infinity();
1546
1547 if( m_accelerator->Intersect( reflectedRay, reflectedHit ) )
1548 {
1549 SFVEC4F add = ( diffuseColorObj + SFVEC4F( objMaterial->GetSpecularColor(),
1550 1.0f ) ) *
1551 shadeHit( aBgColor, reflectedRay, reflectedHit, false,
1552 aRecursiveLevel + 1, is_testShadow ) *
1553 SFVEC4F( objMaterial->GetReflection() *
1554 // Falloff factor
1555 (1.0f / ( 1.0f + 0.75f * reflectedHit.m_tHit *
1556 reflectedHit.m_tHit) ) );
1557
1558 sum_color += add;
1559 }
1560 }
1561
1562 outColor += (sum_color / SFVEC4F( (float)reflection_number_of_samples) );
1563 }
1564
1565 // Refraction
1566 const float objTransparency = aHitInfo.pHitObject->GetModelTransparency();
1567
1568 if( ( objTransparency > 0.0f ) && m_boardAdapter.m_Cfg->m_Render.raytrace_refractions
1569 && ( aRecursiveLevel < objMaterial->GetRefractionRecursionCount() ) )
1570 {
1571 const float airIndex = 1.000293f;
1572 const float glassIndex = 1.49f;
1573 const float air_over_glass = airIndex / glassIndex;
1574 const float glass_over_air = glassIndex / airIndex;
1575
1576 const float refractionRatio = aIsInsideObject?glass_over_air:air_over_glass;
1577
1578 SFVEC3F refractedVector;
1579
1580 if( Refract( aRay.m_Dir, aHitInfo.m_HitNormal, refractionRatio, refractedVector ) )
1581 {
1582 // This increase the start point by a "fixed" factor so it will work the
1583 // same for all distances
1584 const SFVEC3F startPoint =
1585 aRay.at( aHitInfo.m_tHit + m_boardAdapter.GetNonCopperLayerThickness() *
1586 0.25f );
1587
1588 const unsigned int refractions_number_of_samples =
1589 objMaterial->GetRefractionRayCount();
1590
1591 SFVEC4F sum_color = SFVEC4F( 0.0f );
1592
1593 for( unsigned int i = 0; i < refractions_number_of_samples; ++i )
1594 {
1595 RAY refractedRay;
1596
1597 if( i == 0 )
1598 {
1599 refractedRay.Init( startPoint, refractedVector );
1600 }
1601 else
1602 {
1603 // apply some randomize to the refracted vector
1604 const SFVEC3F randomizeRefractedVector =
1605 glm::normalize( refractedVector +
1607 m_boardAdapter.m_Cfg->m_Render.raytrace_spread_refractions );
1608
1609 refractedRay.Init( startPoint, randomizeRefractedVector );
1610 }
1611
1612 HITINFO refractedHit;
1613 refractedHit.m_tHit = std::numeric_limits<float>::infinity();
1614
1615 SFVEC4F refractedColor = aBgColor;
1616
1617 if( m_accelerator->Intersect( refractedRay, refractedHit ) )
1618 {
1619 refractedColor = shadeHit( aBgColor, refractedRay, refractedHit,
1620 !aIsInsideObject, aRecursiveLevel + 1, false );
1621
1622 const SFVEC4F absorbance = ( SFVEC4F(1.0f) - diffuseColorObj ) *
1623 (1.0f - objTransparency ) *
1624 objMaterial->GetAbsorvance() *
1625 refractedHit.m_tHit;
1626
1627 const SFVEC4F transparency = 1.0f / ( absorbance + 1.0f );
1628
1629 sum_color += refractedColor * transparency;
1630 }
1631 else
1632 {
1633 sum_color += refractedColor;
1634 }
1635 }
1636
1637 outColor = outColor * ( 1.0f - objTransparency ) + objTransparency * sum_color
1638 / SFVEC4F( (float) refractions_number_of_samples );
1639 }
1640 else
1641 {
1642 outColor = outColor * ( 1.0f - objTransparency ) + objTransparency * aBgColor;
1643 }
1644 }
1645 }
1646
1647 return outColor;
1648}
1649
1650
1651static float distance( const SFVEC2UI& a, const SFVEC2UI& b )
1652{
1653 const float dx = (float) a.x - (float) b.x;
1654 const float dy = (float) a.y - (float) b.y;
1655 return hypotf( dx, dy );
1656}
1657
1658
1660{
1662
1663 // Calc block positions for fast preview mode
1664 m_blockPositionsFast.clear();
1665
1666 unsigned int i = 0;
1667
1668 while(1)
1669 {
1670 const unsigned int mX = DecodeMorton2X(i);
1671 const unsigned int mY = DecodeMorton2Y(i);
1672
1673 i++;
1674
1675 const SFVEC2UI blockPos( mX * 4 * RAYPACKET_DIM - mX * 4,
1676 mY * 4 * RAYPACKET_DIM - mY * 4 );
1677
1678 if( ( blockPos.x >= ( (unsigned int)m_windowSize.x - ( 4 * RAYPACKET_DIM + 4 ) ) ) &&
1679 ( blockPos.y >= ( (unsigned int)m_windowSize.y - ( 4 * RAYPACKET_DIM + 4 ) ) ) )
1680 break;
1681
1682 if( ( blockPos.x < ( (unsigned int)m_windowSize.x - ( 4 * RAYPACKET_DIM + 4 ) ) ) &&
1683 ( blockPos.y < ( (unsigned int)m_windowSize.y - ( 4 * RAYPACKET_DIM + 4 ) ) ) )
1684 {
1685 m_blockPositionsFast.push_back( blockPos );
1686
1687 if( blockPos.x > m_realBufferSize.x )
1688 m_realBufferSize.x = blockPos.x;
1689
1690 if( blockPos.y > m_realBufferSize.y )
1691 m_realBufferSize.y = blockPos.y;
1692 }
1693 }
1694
1696
1699
1700 m_xoffset = ( m_windowSize.x - m_realBufferSize.x ) / 2;
1701 m_yoffset = ( m_windowSize.y - m_realBufferSize.y ) / 2;
1702
1703 m_postShaderSsao.UpdateSize( m_realBufferSize );
1704
1705 // Calc block positions for regular rendering. Choose an 'inside out' style of rendering.
1706 m_blockPositions.clear();
1707 const int blocks_x = m_realBufferSize.x / RAYPACKET_DIM;
1708 const int blocks_y = m_realBufferSize.y / RAYPACKET_DIM;
1709 m_blockPositions.reserve( blocks_x * blocks_y );
1710
1711 // Hilbert curve position calculation
1712 // modified from Matters Computational, Springer 2011
1713 // GPLv3, Copyright Joerg Arndt
1714 constexpr auto hilbert_get_pos =
1715 []( size_t aT, size_t& aX, size_t& aY )
1716 {
1717 static const size_t htab[] = { 0b0010, 0b0100, 0b1100, 0b1001, 0b1111, 0b0101,
1718 0b0001, 0b1000, 0b0000, 0b1010, 0b1110, 0b0111,
1719 0b1101, 0b1011, 0b0011, 0b0110 };
1720 static const size_t size = sizeof( size_t ) * 8;
1721 size_t xv = 0;
1722 size_t yv = 0;
1723 size_t c01 = 0;
1724
1725 for( size_t i = 0; i < ( size / 2 ); ++i )
1726 {
1727 size_t abi = aT >> ( size - 2 );
1728 aT <<= 2;
1729
1730 size_t st = htab[( c01 << 2 ) | abi];
1731 c01 = st & 3;
1732
1733 yv = ( yv << 1 ) | ( ( st >> 2 ) & 1 );
1734 xv = ( xv << 1 ) | ( st >> 3 );
1735 }
1736
1737 aX = xv;
1738 aY = yv;
1739 };
1740
1741 size_t total_blocks = blocks_x * blocks_y;
1742 size_t pos = 0;
1743 size_t x = 0;
1744 size_t y = 0;
1745
1746 while( m_blockPositions.size() < total_blocks )
1747 {
1748 hilbert_get_pos( pos++, x, y );
1749
1750 if( x < blocks_x && y < blocks_y )
1751 m_blockPositions.emplace_back( x * RAYPACKET_DIM, y * RAYPACKET_DIM );
1752 }
1753
1754 // Create m_shader buffer
1755 delete[] m_shaderBuffer;
1757
1758 initPbo();
1759}
1760
1761
1763{
1764 std::lock_guard<std::mutex> lock( m_hitTestMutex );
1765
1766 m_accelerator.reset();
1767}
1768
1769
1771{
1772 std::lock_guard<std::mutex> lock( m_hitTestMutex );
1773
1774 HITINFO hitInfo;
1775 hitInfo.m_tHit = std::numeric_limits<float>::infinity();
1776
1777 if( m_accelerator )
1778 {
1779 if( m_accelerator->Intersect( aRay, hitInfo ) )
1780 {
1781 if( hitInfo.pHitObject )
1782 return hitInfo.pHitObject->GetBoardItem();
1783 }
1784 }
1785
1786 return nullptr;
1787}
Defines math related functions.
Defines math related functions.
bool Refract(const SFVEC3F &aInVector, const SFVEC3F &aNormal, float aRin_over_Rout, SFVEC3F &aOutVector)
Based on: https://github.com/mmp/pbrt-v3/blob/master/src/core/reflection.h See also: http://www....
Definition 3d_math.h:108
SFVEC3F UniformRandomHemisphereDirection()
Definition 3d_math.h:51
Helper class to handle information needed to display 3D board.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:84
A class used to derive camera objects from.
Definition camera.h:99
A base light class to derive to implement other light classes.
Definition light.h:37
Base material class that can be used to derive other material implementations.
Definition material.h:236
float GetAbsorvance() const
Definition material.h:271
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 an intersection point.
const SFVEC3F & GetAmbientColor() const
Definition material.h:264
unsigned int GetRefractionRayCount() const
Definition material.h:272
const SFVEC3F & GetSpecularColor() const
Definition material.h:266
const SFVEC3F & GetEmissiveColor() const
Definition material.h:265
float GetReflection() const
Definition material.h:270
unsigned int GetReflectionRayCount() const
Definition material.h:273
virtual SFVEC3F GetDiffuseColor(const HITINFO &aHitInfo) const =0
BOARD_ITEM * GetBoardItem() const
Definition object_3d.h:52
virtual bool Intersect(const RAY &aRay, HITINFO &aHitInfo) const =0
float GetModelTransparency() const
Definition object_3d.h:61
const MATERIAL * GetMaterial() const
Definition object_3d.h:60
RENDER_3D_BASE(BOARD_ADAPTER &aBoardAdapter, CAMERA &aCamera)
std::shared_ptr< REPORTER > m_activityReporter
wxSize m_windowSize
The window size that this camera is working.
BOARD_ADAPTER & m_boardAdapter
Settings reference in use for this render.
void renderBlockTracing(uint8_t *ptrPBO, signed int iBlock)
static SFVEC4F premultiplyAlpha(const SFVEC4F &aInput)
void renderTracing(uint8_t *ptrPBO)
RENDER_3D_RAYTRACE_BASE(BOARD_ADAPTER &aAdapter, CAMERA &aCamera)
void renderFinalColor(uint8_t *ptrPBO, const SFVEC4F &rgbColor, bool applyColorSpaceConversion)
std::mutex m_hitTestMutex
Serializes hover BVH use.
void InvalidateHitTesting()
Drop the hover BVH so IntersectBoardItem becomes a no-op.
void renderAntiAliasPackets(const SFVEC4F *aBgColorY, const HITINFO_PACKET *aHitPck_X0Y0, const HITINFO_PACKET *aHitPck_AA_X1Y1, const RAY *aRayPck, SFVEC4F *aOutHitColor)
std::vector< int > m_blockPositionsWasProcessed
Flag if a position was already processed (cleared each new render).
void postProcessShading(uint8_t *ptrPBO)
BOARD_ITEM * IntersectBoardItem(const RAY &aRay)
RT_RENDER_STATE m_renderState
State used on quality render.
void renderRayPackets(const SFVEC4F *bgColorY, const RAY *aRayPkt, HITINFO_PACKET *aHitPacket, bool is_testShadow, SFVEC4F *aOutHitColor)
int GetWaitForEditingTimeOut() override
Give the interface the time (in ms) that it should wait for editing or movements before (this works f...
void postProcessBlurFinish(uint8_t *ptrPBO)
std::vector< SFVEC2UI > m_blockPositionsFast
Encode the Morton code positions (on fast preview mode).
SFVEC4F shadeHit(const SFVEC4F &aBgColor, const RAY &aRay, HITINFO &aHitInfo, bool aIsInsideObject, unsigned int aRecursiveLevel, bool is_testShadow) const
BVH_CONTAINER_2D * m_antioutlineBoard2dObjects
std::unique_ptr< ACCELERATOR_3D > m_accelerator
wxSize m_oldWindowsSize
Used to see if the windows size changed.
void renderPreview(uint8_t *ptrPBO)
virtual void initPbo()=0
size_t m_blockRenderProgressCount
Save the number of blocks progress of the render.
int64_t m_renderStartTime
Time that the render starts.
std::vector< SFVEC2UI > m_blockPositions
Encode Morton code positions.
COLOR_RGBA BlendColor(const COLOR_RGBA &aC1, const COLOR_RGBA &aC2)
#define _(s)
static const wxChar * m_logTrace
Trace mask used to enable or disable the trace output of this class.
uint32_t DecodeMorton2Y(uint32_t code)
uint32_t DecodeMorton2X(uint32_t code)
Implements Morton Codes https://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes/ http://www....
int64_t GetRunningMicroSecs()
An alternate way to calculate an elapsed time (in microsecondes) to class PROF_COUNTER.
void RAYPACKET_InitRays_with2DDisplacement(const CAMERA &aCamera, const SFVEC2F &aWindowsPosition, const SFVEC2F &a2DWindowsPosDisplacementFactor, RAY *aRayPck)
#define RAYPACKET_INVMASK
Definition raypacket.h:30
#define RAYPACKET_RAYS_PER_PACKET
Definition raypacket.h:31
#define RAYPACKET_DIM
Definition raypacket.h:28
#define SRGB_GAMA
static SFVEC4F convertLinearToSRGBA(const SFVEC4F &aRGBAcolor)
SFVEC3F ConvertSRGBToLinear(const SFVEC3F &aSRGBcolor)
static void SetPixel(uint8_t *p, const COLOR_RGBA &v)
static void HITINFO_PACKET_init(HITINFO_PACKET *aHitPacket)
static SFVEC3F convertLinearToSRGB(const SFVEC3F &aRGBcolor)
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
static void SetPixelSRGBA(uint8_t *p, const COLOR_RGBA &v)
#define DISP_FACTOR
SFVEC4F ConvertSRGBAToLinear(const SFVEC4F &aSRGBAcolor)
@ RT_RENDER_STATE_POST_PROCESS_SHADE
@ RT_RENDER_STATE_POST_PROCESS_BLUR_AND_FINISH
@ RT_RENDER_STATE_FINISH
@ RT_RENDER_STATE_TRACING
@ RT_RENDER_STATE_MAX
SFVEC4F ConvertSRGBAToLinear(const SFVEC4F &aSRGBAcolor)
bool m_hitresult
Definition hitinfo.h:53
HITINFO m_HitInfo
Definition hitinfo.h:54
Stores the hit information of a ray with a point on the surface of a object.
Definition hitinfo.h:32
unsigned int m_acc_node_info
( 4) The acc stores here the node that it hits
Definition hitinfo.h:38
float m_tHit
( 4) distance
Definition hitinfo.h:34
const OBJECT_3D * pHitObject
( 4) Object that was hitted
Definition hitinfo.h:36
float m_ShadowFactor
( 4) Shadow attenuation (1.0 no shadow, 0.0f darkness)
Definition hitinfo.h:41
SFVEC3F m_HitNormal
(12) normal at the hit point
Definition hitinfo.h:33
SFVEC3F m_HitPoint
(12) hit position
Definition hitinfo.h:40
RAY m_ray[RAYPACKET_RAYS_PER_PACKET]
Definition raypacket.h:50
Definition ray.h:59
SFVEC3F m_Dir
Definition ray.h:63
void Init(const SFVEC3F &o, const SFVEC3F &d)
Definition ray.cpp:31
SFVEC3F m_Origin
Definition ray.h:60
SFVEC3F at(float t) const
Definition ray.h:80
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
static thread_pool * tp
BS::priority_thread_pool thread_pool
Definition thread_pool.h:27
unsigned char c[4]
Definition color_rgba.h:32
glm::ivec2 SFVEC2I
Definition xv3d_types.h:35
glm::vec2 SFVEC2F
Definition xv3d_types.h:38
glm::vec3 SFVEC3F
Definition xv3d_types.h:40
glm::uvec2 SFVEC2UI
Definition xv3d_types.h:34
glm::vec4 SFVEC4F
Definition xv3d_types.h:42