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