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