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