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