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