KiCad PCB EDA Suite
Loading...
Searching...
No Matches
render_3d_raytrace_base.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2015-2020 Mario Luzeiro <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include <algorithm>
26#include <atomic>
27#include <chrono>
28#include <thread>
29
31#include "mortoncodes.h"
32#include "../color_rgba.h"
33#include "3d_fastmath.h"
34#include "3d_math.h"
35#include <thread_pool.h>
36#include <core/profile.h> // To use GetRunningMicroSecs or another profiling utility
37#include <wx/log.h>
38
39
40#ifdef USE_SRGB_SPACE
41
43#define SRGB_GAMA 2.4f
44
45
46// This function implements the conversion from linear RGB to sRGB
47// https://github.com/g-truc/glm/blob/master/glm/gtc/color_space.inl#L12
48static SFVEC3F convertLinearToSRGB( const SFVEC3F& aRGBcolor )
49{
50 const float gammaCorrection = 1.0f / SRGB_GAMA;
51 const SFVEC3F clampedColor = glm::clamp( aRGBcolor, SFVEC3F( 0.0f ), SFVEC3F( 1.0f ) );
52
53 return glm::mix( glm::pow( clampedColor, SFVEC3F(gammaCorrection) ) * 1.055f - 0.055f,
54 clampedColor * 12.92f,
55 glm::lessThan( clampedColor, SFVEC3F(0.0031308f) ) );
56}
57
58
59static SFVEC4F convertLinearToSRGBA( const SFVEC4F& aRGBAcolor )
60{
61 return SFVEC4F( convertLinearToSRGB( SFVEC3F( aRGBAcolor ) ), aRGBAcolor.a );
62}
63
64
65// This function implements the conversion from sRGB to linear RGB
66// https://github.com/g-truc/glm/blob/master/glm/gtc/color_space.inl#L35
68{
69 const float gammaCorrection = SRGB_GAMA;
70
71 return glm::mix( glm::pow( ( aSRGBcolor + SFVEC3F( 0.055f ) )
72 * SFVEC3F( 0.94786729857819905213270142180095f ),
73 SFVEC3F( gammaCorrection ) ),
74 aSRGBcolor * SFVEC3F( 0.07739938080495356037151702786378f ),
75 glm::lessThanEqual( aSRGBcolor, SFVEC3F( 0.04045f ) ) );
76}
77
78
80{
81 return SFVEC4F( ConvertSRGBToLinear( SFVEC3F( aSRGBAcolor ) ), aSRGBAcolor.a );
82}
83
84#endif
85
86
88 RENDER_3D_BASE( aAdapter, aCamera ),
89 m_postShaderSsao( aCamera )
90{
91 wxLogTrace( m_logTrace, wxT( "RENDER_3D_RAYTRACE_BASE::RENDER_3D_RAYTRACE_BASE" ) );
92
93 //m_pboId = GL_NONE;
94 //m_pboDataSize = 0;
95 m_accelerator = nullptr;
98 m_oldWindowsSize.x = 0;
99 m_oldWindowsSize.y = 0;
100 m_outlineBoard2dObjects = nullptr;
102 m_firstHitinfo = nullptr;
103 m_shaderBuffer = nullptr;
104 m_cameraLight = nullptr;
105
106 m_xoffset = 0;
107 m_yoffset = 0;
108
110 m_isPreview = false;
111 m_renderState = RT_RENDER_STATE_MAX; // Set to an initial invalid state
114}
115
116
118{
119 wxLogTrace( m_logTrace, wxT( "RENDER_3D_RAYTRACE_BASE::~RENDER_3D_RAYTRACE_BASE" ) );
120
121 delete m_accelerator;
122 m_accelerator = nullptr;
123
125 m_outlineBoard2dObjects = nullptr;
126
129
130 delete[] m_shaderBuffer;
131 m_shaderBuffer = nullptr;
132}
133
134
136{
137 return 200; // ms
138}
139
140
142{
144
147
148 m_postShaderSsao.InitFrame();
149
151
152 // Mark the blocks not processed yet
153 std::fill( m_blockPositionsWasProcessed.begin(), m_blockPositionsWasProcessed.end(), 0 );
154}
155
156
157static inline void SetPixel( uint8_t* p, const COLOR_RGBA& v )
158{
159 p[0] = v.c[0];
160 p[1] = v.c[1];
161 p[2] = v.c[2];
162 p[3] = v.c[3];
163}
164
165
166static void SetPixelSRGBA( uint8_t* p, const COLOR_RGBA& v )
167{
168 SFVEC4F color = v;
169
170#ifdef USE_SRGB_SPACE
172#endif
173
174 COLOR_RGBA rgba( color );
175 SetPixel( p, rgba );
176}
177
178
180{
181 return SFVEC4F( aInput.r * aInput.a, aInput.g * aInput.a, aInput.b * aInput.a, aInput.a );
182}
183
184
185void RENDER_3D_RAYTRACE_BASE::render( uint8_t* ptrPBO, REPORTER* aStatusReporter )
186{
188 {
190
191 if( m_cameraLight )
192 m_cameraLight->SetDirection( -m_camera.GetDir() );
193
194 if( m_boardAdapter.m_Cfg->m_Render.engine == RENDER_ENGINE::OPENGL )
195 {
196 // Set all pixels of PBO transparent (Alpha to 0)
197 // This way it will draw the full buffer but only shows the updated (
198 // already calculated) squares
199 unsigned int nPixels = m_realBufferSize.x * m_realBufferSize.y;
200 uint8_t* tmp_ptrPBO = ptrPBO + 3; // PBO is RGBA
201
202 for( unsigned int i = 0; i < nPixels; ++i )
203 {
204 *tmp_ptrPBO = 0;
205 tmp_ptrPBO += 4; // PBO is RGBA
206 }
207 }
208
213 }
214
215 switch( m_renderState )
216 {
218 renderTracing( ptrPBO, aStatusReporter );
219 break;
220
222 postProcessShading( ptrPBO, aStatusReporter );
223 break;
224
226 postProcessBlurFinish( ptrPBO, aStatusReporter );
227 break;
228
229 default:
230 wxASSERT_MSG( false, wxT( "Invalid state on m_renderState" ) );
232 break;
233 }
234
235 if( aStatusReporter && ( m_renderState == RT_RENDER_STATE_FINISH ) )
236 {
237 // Calculation time in seconds
238 const double elapsed_time = (double) ( GetRunningMicroSecs() - m_renderStartTime ) / 1e6;
239
240 aStatusReporter->Report( wxString::Format( _( "Rendering time %.3f s" ), elapsed_time ) );
241 }
242}
243
244
245void RENDER_3D_RAYTRACE_BASE::renderTracing( uint8_t* ptrPBO, REPORTER* aStatusReporter )
246{
247 m_isPreview = false;
248
249 auto startTime = std::chrono::steady_clock::now();
250 std::atomic<size_t> numBlocksRendered( 0 );
251 std::atomic<size_t> currentBlock( 0 );
252
254 const int timeLimit = m_blockPositions.size() > 40000 ? 750 : 400;
255
256 auto processBlocks = [&]()
257 {
258 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_task( 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 {
295 if( m_boardAdapter.m_Cfg->m_Render.raytrace_post_processing )
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 const SFVEC2F randDisp = ( m_camera.GetProjection() == PROJECTION_TYPE::ORTHO ) ?
490 SFVEC2F( 0.0f, 0.0f ) :
492
493 RAYPACKET blockPacket( m_camera, (SFVEC2F) blockPosI + randDisp,
494 randDisp /* Displacement random factor */ );
495
496
498
499 HITINFO_PACKET_init( hitPacket_X0Y0 );
500
501 // Calculate background gradient color
502 SFVEC4F bgColor[RAYPACKET_DIM];// Store a vertical gradient color
503
504 for( unsigned int y = 0; y < RAYPACKET_DIM; ++y )
505 {
506 const float posYfactor = (float) ( blockPosI.y + y ) / (float) m_windowSize.y;
507
508 bgColor[y] = m_backgroundColorTop * SFVEC4F(posYfactor) +
509 m_backgroundColorBottom * ( SFVEC4F(1.0f) - SFVEC4F(posYfactor) );
510 }
511
512 // Intersect ray packets (calculate the intersection with rays and objects)
513 if( !m_accelerator->Intersect( blockPacket, hitPacket_X0Y0 ) )
514 {
515 // If block is empty then set shades and continue
516 if( m_boardAdapter.m_Cfg->m_Render.raytrace_post_processing )
517 {
518 for( unsigned int y = 0; y < RAYPACKET_DIM; ++y )
519 {
520 const SFVEC4F& outColor = bgColor[y];
521
522 const unsigned int yBlockPos = blockPos.y + y;
523
524 for( unsigned int x = 0; x < RAYPACKET_DIM; ++x )
525 {
526 m_postShaderSsao.SetPixelData( blockPos.x + x, yBlockPos,
527 SFVEC3F( 0.0f ), outColor,
528 SFVEC3F( 0.0f ), 0, 1.0f );
529 }
530 }
531 }
532
533 // This will set the output color to be displayed
534 // If post processing is enabled, it will not reflect the final result (as the final
535 // color will be computed on post processing) but it is used for report progress
536 const bool isFinalColor = !m_boardAdapter.m_Cfg->m_Render.raytrace_post_processing;
537
538 for( unsigned int y = 0; y < RAYPACKET_DIM; ++y )
539 {
540 const SFVEC4F& outColor = bgColor[y];
541
542 const unsigned int yConst = blockPos.x + ( ( y + blockPos.y ) * m_realBufferSize.x );
543
544 for( unsigned int x = 0; x < RAYPACKET_DIM; ++x )
545 {
546 uint8_t* ptr = &ptrPBO[( yConst + x ) * 4];
547
548 renderFinalColor( ptr, outColor, isFinalColor );
549 }
550 }
551
552 // There is nothing more here to do.. there are no hits ..
553 // just background so continue
554 return;
555 }
556
557 SFVEC4F hitColor_X0Y0[RAYPACKET_RAYS_PER_PACKET];
558
559 // Shade original (0, 0) hits ("paint" the intersected objects)
560 renderRayPackets( bgColor, blockPacket.m_ray, hitPacket_X0Y0,
561 m_boardAdapter.m_Cfg->m_Render.raytrace_shadows, hitColor_X0Y0 );
562
563 if( m_boardAdapter.m_Cfg->m_Render.raytrace_anti_aliasing )
564 {
565 SFVEC4F hitColor_AA_X1Y1[RAYPACKET_RAYS_PER_PACKET];
566
567 // Intersect one blockPosI + (0.5, 0.5) used for anti aliasing calculation
568 HITINFO_PACKET hitPacket_AA_X1Y1[RAYPACKET_RAYS_PER_PACKET];
569 HITINFO_PACKET_init( hitPacket_AA_X1Y1 );
570
571 RAYPACKET blockPacket_AA_X1Y1( m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.5f, 0.5f ),
572 randDisp );
573
574 if( !m_accelerator->Intersect( blockPacket_AA_X1Y1, hitPacket_AA_X1Y1 ) )
575 {
576 // Missed all the package
577 for( unsigned int y = 0, i = 0; y < RAYPACKET_DIM; ++y )
578 {
579 const SFVEC4F& outColor = bgColor[y];
580
581 for( unsigned int x = 0; x < RAYPACKET_DIM; ++x, ++i )
582 hitColor_AA_X1Y1[i] = outColor;
583 }
584 }
585 else
586 {
587 renderRayPackets( bgColor, blockPacket_AA_X1Y1.m_ray, hitPacket_AA_X1Y1,
588 m_boardAdapter.m_Cfg->m_Render.raytrace_shadows, hitColor_AA_X1Y1 );
589 }
590
591 SFVEC4F hitColor_AA_X1Y0[RAYPACKET_RAYS_PER_PACKET];
592 SFVEC4F hitColor_AA_X0Y1[RAYPACKET_RAYS_PER_PACKET];
593 SFVEC4F hitColor_AA_X0Y1_half[RAYPACKET_RAYS_PER_PACKET];
594
595 for( unsigned int i = 0; i < RAYPACKET_RAYS_PER_PACKET; ++i )
596 {
597 SFVEC4F color_average = ( hitColor_X0Y0[i] + hitColor_AA_X1Y1[i] ) * SFVEC4F( 0.5f );
598
599 hitColor_AA_X1Y0[i] = color_average;
600 hitColor_AA_X0Y1[i] = color_average;
601 hitColor_AA_X0Y1_half[i] = color_average;
602 }
603
604 RAY blockRayPck_AA_X1Y0[RAYPACKET_RAYS_PER_PACKET];
605 RAY blockRayPck_AA_X0Y1[RAYPACKET_RAYS_PER_PACKET];
606 RAY blockRayPck_AA_X1Y1_half[RAYPACKET_RAYS_PER_PACKET];
607
609 m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.5f - randDisp.x, randDisp.y ),
610 randDisp, blockRayPck_AA_X1Y0 );
611
613 m_camera, (SFVEC2F) blockPosI + SFVEC2F( randDisp.x, 0.5f - randDisp.y ),
614 randDisp, blockRayPck_AA_X0Y1 );
615
617 m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.25f - randDisp.x, 0.25f - randDisp.y ),
618 randDisp, blockRayPck_AA_X1Y1_half );
619
620 renderAntiAliasPackets( bgColor, hitPacket_X0Y0, hitPacket_AA_X1Y1, blockRayPck_AA_X1Y0,
621 hitColor_AA_X1Y0 );
622
623 renderAntiAliasPackets( bgColor, hitPacket_X0Y0, hitPacket_AA_X1Y1, blockRayPck_AA_X0Y1,
624 hitColor_AA_X0Y1 );
625
626 renderAntiAliasPackets( bgColor, hitPacket_X0Y0, hitPacket_AA_X1Y1,
627 blockRayPck_AA_X1Y1_half, hitColor_AA_X0Y1_half );
628
629 // Average the result
630 for( unsigned int i = 0; i < RAYPACKET_RAYS_PER_PACKET; ++i )
631 {
632 hitColor_X0Y0[i] = ( hitColor_X0Y0[i] + hitColor_AA_X1Y1[i] + hitColor_AA_X1Y0[i] +
633 hitColor_AA_X0Y1[i] + hitColor_AA_X0Y1_half[i] ) *
634 SFVEC4F( 1.0f / 5.0f );
635 }
636 }
637
638 // Copy results to the next stage
639 uint8_t* ptr = &ptrPBO[( blockPos.x + ( blockPos.y * m_realBufferSize.x ) ) * 4];
640
641 const uint32_t ptrInc = ( m_realBufferSize.x - RAYPACKET_DIM ) * 4;
642
643 if( m_boardAdapter.m_Cfg->m_Render.raytrace_post_processing )
644 {
645 SFVEC2I bPos;
646 bPos.y = blockPos.y;
647
648 for( unsigned int y = 0, i = 0; y < RAYPACKET_DIM; ++y )
649 {
650 bPos.x = blockPos.x;
651
652 for( unsigned int x = 0; x < RAYPACKET_DIM; ++x, ++i )
653 {
654 const SFVEC4F& hColor = hitColor_X0Y0[i];
655
656 if( hitPacket_X0Y0[i].m_hitresult == true )
657 {
658 m_postShaderSsao.SetPixelData( bPos.x, bPos.y,
659 hitPacket_X0Y0[i].m_HitInfo.m_HitNormal,
660 hColor,
661 blockPacket.m_ray[i].at(
662 hitPacket_X0Y0[i].m_HitInfo.m_tHit ),
663 hitPacket_X0Y0[i].m_HitInfo.m_tHit,
664 hitPacket_X0Y0[i].m_HitInfo.m_ShadowFactor );
665 }
666 else
667 {
668 m_postShaderSsao.SetPixelData( bPos.x, bPos.y, SFVEC3F( 0.0f ), hColor,
669 SFVEC3F( 0.0f ), 0, 1.0f );
670 }
671
672 renderFinalColor( ptr, hColor, false );
673
674 bPos.x++;
675 ptr += 4;
676 }
677
678 ptr += ptrInc;
679 bPos.y++;
680 }
681 }
682 else
683 {
684 for( unsigned int y = 0, i = 0; y < RAYPACKET_DIM; ++y )
685 {
686 for( unsigned int x = 0; x < RAYPACKET_DIM; ++x, ++i )
687 {
688 renderFinalColor( ptr, hitColor_X0Y0[i], true );
689 ptr += 4;
690 }
691
692 ptr += ptrInc;
693 }
694 }
695}
696
697
698void RENDER_3D_RAYTRACE_BASE::postProcessShading( uint8_t* /* ptrPBO */, REPORTER* aStatusReporter )
699{
700 if( m_boardAdapter.m_Cfg->m_Render.raytrace_post_processing )
701 {
702 if( aStatusReporter )
703 aStatusReporter->Report( _( "Rendering: Post processing shader" ) );
704
705 m_postShaderSsao.SetShadowsEnabled( m_boardAdapter.m_Cfg->m_Render.raytrace_shadows );
706
707 std::atomic<size_t> nextBlock( 0 );
708 std::atomic<size_t> threadsFinished( 0 );
709
710 size_t parallelThreadCount = std::max<size_t>( std::thread::hardware_concurrency(), 2 );
711
712 for( size_t ii = 0; ii < parallelThreadCount; ++ii )
713 {
714 std::thread t = std::thread( [&]()
715 {
716 for( size_t y = nextBlock.fetch_add( 1 ); y < m_realBufferSize.y;
717 y = nextBlock.fetch_add( 1 ) )
718 {
719 SFVEC3F* ptr = &m_shaderBuffer[ y * m_realBufferSize.x ];
720
721 for( signed int x = 0; x < (int)m_realBufferSize.x; ++x )
722 {
723 *ptr = m_postShaderSsao.Shade( SFVEC2I( x, y ) );
724 ptr++;
725 }
726 }
727
728 threadsFinished++;
729 } );
730
731 t.detach();
732 }
733
734 while( threadsFinished < parallelThreadCount )
735 std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
736
737 m_postShaderSsao.SetShadedBuffer( m_shaderBuffer );
738
739 // Set next state
741 }
742 else
743 {
744 // As this was an invalid state, set to finish
746 }
747}
748
749
751 REPORTER* /* aStatusReporter */ )
752{
753 if( m_boardAdapter.m_Cfg->m_Render.raytrace_post_processing )
754 {
755 // Now blurs the shader result and compute the final color
756 std::atomic<size_t> nextBlock( 0 );
757 std::atomic<size_t> threadsFinished( 0 );
758
759 size_t parallelThreadCount = std::max<size_t>( std::thread::hardware_concurrency(), 2 );
760
761 for( size_t ii = 0; ii < parallelThreadCount; ++ii )
762 {
763 std::thread t = std::thread( [&]()
764 {
765 for( size_t y = nextBlock.fetch_add( 1 ); y < m_realBufferSize.y;
766 y = nextBlock.fetch_add( 1 ) )
767 {
768 uint8_t* ptr = &ptrPBO[ y * m_realBufferSize.x * 4 ];
769
770 for( signed int x = 0; x < (int)m_realBufferSize.x; ++x )
771 {
772 const SFVEC3F bluredShadeColor = m_postShaderSsao.Blur( SFVEC2I( x, y ) );
773
774#ifdef USE_SRGB_SPACE
775 const SFVEC4F originColor = convertLinearToSRGBA(
776 m_postShaderSsao.GetColorAtNotProtected( SFVEC2I( x, y ) ) );
777#else
778 const SFVEC4F originColor =
779 m_postShaderSsao.GetColorAtNotProtected( SFVEC2I( x, y ) );
780#endif
781 const SFVEC4F shadedColor = m_postShaderSsao.ApplyShadeColor(
782 SFVEC2I( x, y ), originColor, bluredShadeColor );
783
784 renderFinalColor( ptr, shadedColor, false );
785
786 ptr += 4;
787 }
788 }
789
790 threadsFinished++;
791 } );
792
793 t.detach();
794 }
795
796 while( threadsFinished < parallelThreadCount )
797 std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
798
799 // Debug code
800 //m_postShaderSsao.DebugBuffersOutputAsImages();
801 }
802
803 // End rendering
805}
806
807
809{
810 m_isPreview = true;
811
815
816 std::atomic<size_t> nextBlock( 0 );
817 std::atomic<size_t> threadsFinished( 0 );
818
819 size_t parallelThreadCount = std::min<size_t>(
820 std::max<size_t>( std::thread::hardware_concurrency(), 2 ),
821 m_blockPositions.size() );
822
823 for( size_t ii = 0; ii < parallelThreadCount; ++ii )
824 {
825 std::thread t = std::thread( [&]()
826 {
827 for( size_t iBlock = nextBlock.fetch_add( 1 ); iBlock < m_blockPositionsFast.size();
828 iBlock = nextBlock.fetch_add( 1 ) )
829 {
830 const SFVEC2UI& windowPosUI = m_blockPositionsFast[ iBlock ];
831 const SFVEC2I windowsPos = SFVEC2I( windowPosUI.x + m_xoffset,
832 windowPosUI.y + m_yoffset );
833
834 RAYPACKET blockPacket( m_camera, windowsPos, 4 );
835
837
838 // Initialize hitPacket with a "not hit" information
839 for( HITINFO_PACKET& packet : hitPacket )
840 {
841 packet.m_HitInfo.m_tHit = std::numeric_limits<float>::infinity();
842 packet.m_HitInfo.m_acc_node_info = 0;
843 packet.m_hitresult = false;
844 }
845
846 // Intersect packet block
847 m_accelerator->Intersect( blockPacket, hitPacket );
848
849 // Calculate background gradient color
850 SFVEC4F bgColor[RAYPACKET_DIM];
851
852 SFVEC4F bgTopColor = m_backgroundColorTop;
853 SFVEC4F bgBotColor = m_backgroundColorBottom;
854
855 for( unsigned int y = 0; y < RAYPACKET_DIM; ++y )
856 {
857 const float posYfactor =
858 (float) ( windowsPos.y + y * 4.0f ) / (float) m_windowSize.y;
859
860 bgColor[y] = bgTopColor * SFVEC4F( posYfactor )
861 + bgBotColor * ( SFVEC4F( 1.0f ) - SFVEC4F( posYfactor ) );
862 }
863
864 COLOR_RGBA hitColorShading[RAYPACKET_RAYS_PER_PACKET];
865
866 for( unsigned int i = 0; i < RAYPACKET_RAYS_PER_PACKET; ++i )
867 {
868 const SFVEC4F bhColorY = bgColor[i / RAYPACKET_DIM];
869
870 if( hitPacket[i].m_hitresult == true )
871 {
872 const SFVEC4F hitColor = shadeHit( bhColorY, blockPacket.m_ray[i],
873 hitPacket[i].m_HitInfo, false,
874 0, false );
875
876 hitColorShading[i] = COLOR_RGBA( hitColor );
877 }
878 else
879 hitColorShading[i] = bhColorY;
880 }
881
882 COLOR_RGBA cLRB_old[( RAYPACKET_DIM - 1 )];
883
884 for( unsigned int y = 0; y < ( RAYPACKET_DIM - 1 ); ++y )
885 {
886 const SFVEC4F bgColorY = bgColor[y];
887 const COLOR_RGBA bgColorYRGB = COLOR_RGBA( bgColorY );
888
889 // This stores cRTB from the last block to be reused next time in a cLTB pixel
890 COLOR_RGBA cRTB_old;
891
892 //RAY cRTB_ray;
893 //HITINFO cRTB_hitInfo;
894
895 for( unsigned int x = 0; x < ( RAYPACKET_DIM - 1 ); ++x )
896 {
897 // pxl 0 pxl 1 pxl 2 pxl 3 pxl 4
898 // x0 x1 ...
899 // .---------------------------.
900 // y0 | cLT | cxxx | cLRT | cxxx | cRT |
901 // | cxxx | cLTC | cxxx | cRTC | cxxx |
902 // | cLTB | cxxx | cC | cxxx | cRTB |
903 // | cxxx | cLBC | cxxx | cRBC | cxxx |
904 // '---------------------------'
905 // y1 | cLB | cxxx | cLRB | cxxx | cRB |
906
907 const unsigned int iLT = ( ( x + 0 ) + RAYPACKET_DIM * ( y + 0 ) );
908 const unsigned int iRT = ( ( x + 1 ) + RAYPACKET_DIM * ( y + 0 ) );
909 const unsigned int iLB = ( ( x + 0 ) + RAYPACKET_DIM * ( y + 1 ) );
910 const unsigned int iRB = ( ( x + 1 ) + RAYPACKET_DIM * ( y + 1 ) );
911
912 // !TODO: skip when there are no hits
913 const COLOR_RGBA& cLT = hitColorShading[ iLT ];
914 const COLOR_RGBA& cRT = hitColorShading[ iRT ];
915 const COLOR_RGBA& cLB = hitColorShading[ iLB ];
916 const COLOR_RGBA& cRB = hitColorShading[ iRB ];
917
918 // Trace and shade cC
919 COLOR_RGBA cC = bgColorYRGB;
920
921 const SFVEC3F& oriLT = blockPacket.m_ray[ iLT ].m_Origin;
922 const SFVEC3F& oriRB = blockPacket.m_ray[ iRB ].m_Origin;
923
924 const SFVEC3F& dirLT = blockPacket.m_ray[ iLT ].m_Dir;
925 const SFVEC3F& dirRB = blockPacket.m_ray[ iRB ].m_Dir;
926
927 SFVEC3F oriC;
928 SFVEC3F dirC;
929
930 HITINFO centerHitInfo;
931 centerHitInfo.m_tHit = std::numeric_limits<float>::infinity();
932
933 bool hittedC = false;
934
935 if( ( hitPacket[iLT].m_hitresult == true )
936 || ( hitPacket[iRT].m_hitresult == true )
937 || ( hitPacket[iLB].m_hitresult == true )
938 || ( hitPacket[iRB].m_hitresult == true ) )
939 {
940 oriC = ( oriLT + oriRB ) * 0.5f;
941 dirC = glm::normalize( ( dirLT + dirRB ) * 0.5f );
942
943 // Trace the center ray
944 RAY centerRay;
945 centerRay.Init( oriC, dirC );
946
947 const unsigned int nodeLT = hitPacket[ iLT ].m_HitInfo.m_acc_node_info;
948 const unsigned int nodeRT = hitPacket[ iRT ].m_HitInfo.m_acc_node_info;
949 const unsigned int nodeLB = hitPacket[ iLB ].m_HitInfo.m_acc_node_info;
950 const unsigned int nodeRB = hitPacket[ iRB ].m_HitInfo.m_acc_node_info;
951
952 if( nodeLT != 0 )
953 hittedC |= m_accelerator->Intersect( centerRay, centerHitInfo,
954 nodeLT );
955
956 if( ( nodeRT != 0 ) && ( nodeRT != nodeLT ) )
957 hittedC |= m_accelerator->Intersect( centerRay, centerHitInfo,
958 nodeRT );
959
960 if( ( nodeLB != 0 ) && ( nodeLB != nodeLT ) && ( nodeLB != nodeRT ) )
961 hittedC |= m_accelerator->Intersect( centerRay, centerHitInfo,
962 nodeLB );
963
964 if( ( nodeRB != 0 ) && ( nodeRB != nodeLB ) && ( nodeRB != nodeLT )
965 && ( nodeRB != nodeRT ) )
966 hittedC |= m_accelerator->Intersect( centerRay, centerHitInfo,
967 nodeRB );
968
969 if( hittedC )
970 {
971 cC = COLOR_RGBA( shadeHit( bgColorY, centerRay, centerHitInfo,
972 false, 0, false ) );
973 }
974 else
975 {
976 centerHitInfo.m_tHit = std::numeric_limits<float>::infinity();
977 hittedC = m_accelerator->Intersect( centerRay, centerHitInfo );
978
979 if( hittedC )
980 cC = COLOR_RGBA( shadeHit( bgColorY, centerRay, centerHitInfo,
981 false, 0, false ) );
982 }
983 }
984
985 // Trace and shade cLRT
986 COLOR_RGBA cLRT = bgColorYRGB;
987
988 const SFVEC3F& oriRT = blockPacket.m_ray[ iRT ].m_Origin;
989 const SFVEC3F& dirRT = blockPacket.m_ray[ iRT ].m_Dir;
990
991 if( y == 0 )
992 {
993 // Trace the center ray
994 RAY rayLRT;
995 rayLRT.Init( ( oriLT + oriRT ) * 0.5f,
996 glm::normalize( ( dirLT + dirRT ) * 0.5f ) );
997
998 HITINFO hitInfoLRT;
999 hitInfoLRT.m_tHit = std::numeric_limits<float>::infinity();
1000
1001 if( hitPacket[iLT].m_hitresult && hitPacket[iRT].m_hitresult
1002 && ( hitPacket[iLT].m_HitInfo.pHitObject
1003 == hitPacket[iRT].m_HitInfo.pHitObject ) )
1004 {
1005 hitInfoLRT.pHitObject = hitPacket[ iLT ].m_HitInfo.pHitObject;
1006 hitInfoLRT.m_tHit = ( hitPacket[ iLT ].m_HitInfo.m_tHit +
1007 hitPacket[ iRT ].m_HitInfo.m_tHit ) * 0.5f;
1008 hitInfoLRT.m_HitNormal =
1009 glm::normalize( ( hitPacket[iLT].m_HitInfo.m_HitNormal
1010 + hitPacket[iRT].m_HitInfo.m_HitNormal )
1011 * 0.5f );
1012
1013 cLRT = COLOR_RGBA( shadeHit( bgColorY, rayLRT, hitInfoLRT, false,
1014 0, false ) );
1015 cLRT = BlendColor( cLRT, BlendColor( cLT, cRT ) );
1016 }
1017 else
1018 {
1019 // If any hits
1020 if( hitPacket[ iLT ].m_hitresult || hitPacket[ iRT ].m_hitresult )
1021 {
1022 const unsigned int nodeLT =
1023 hitPacket[ iLT ].m_HitInfo.m_acc_node_info;
1024 const unsigned int nodeRT =
1025 hitPacket[ iRT ].m_HitInfo.m_acc_node_info;
1026
1027 bool hittedLRT = false;
1028
1029 if( nodeLT != 0 )
1030 hittedLRT |= m_accelerator->Intersect( rayLRT, hitInfoLRT,
1031 nodeLT );
1032
1033 if( ( nodeRT != 0 ) && ( nodeRT != nodeLT ) )
1034 hittedLRT |= m_accelerator->Intersect( rayLRT, hitInfoLRT,
1035 nodeRT );
1036
1037 if( hittedLRT )
1038 cLRT = COLOR_RGBA( shadeHit( bgColorY, rayLRT, hitInfoLRT,
1039 false, 0, false ) );
1040 else
1041 {
1042 hitInfoLRT.m_tHit = std::numeric_limits<float>::infinity();
1043
1044 if( m_accelerator->Intersect( rayLRT,hitInfoLRT ) )
1045 cLRT = COLOR_RGBA( shadeHit( bgColorY, rayLRT,
1046 hitInfoLRT, false,
1047 0, false ) );
1048 }
1049 }
1050 }
1051 }
1052 else
1053 {
1054 cLRT = cLRB_old[x];
1055 }
1056
1057 // Trace and shade cLTB
1058 COLOR_RGBA cLTB = bgColorYRGB;
1059
1060 if( x == 0 )
1061 {
1062 const SFVEC3F &oriLB = blockPacket.m_ray[ iLB ].m_Origin;
1063 const SFVEC3F& dirLB = blockPacket.m_ray[ iLB ].m_Dir;
1064
1065 // Trace the center ray
1066 RAY rayLTB;
1067 rayLTB.Init( ( oriLT + oriLB ) * 0.5f,
1068 glm::normalize( ( dirLT + dirLB ) * 0.5f ) );
1069
1070 HITINFO hitInfoLTB;
1071 hitInfoLTB.m_tHit = std::numeric_limits<float>::infinity();
1072
1073 if( hitPacket[ iLT ].m_hitresult && hitPacket[ iLB ].m_hitresult
1074 && ( hitPacket[ iLT ].m_HitInfo.pHitObject ==
1075 hitPacket[ iLB ].m_HitInfo.pHitObject ) )
1076 {
1077 hitInfoLTB.pHitObject = hitPacket[ iLT ].m_HitInfo.pHitObject;
1078 hitInfoLTB.m_tHit = ( hitPacket[ iLT ].m_HitInfo.m_tHit +
1079 hitPacket[ iLB ].m_HitInfo.m_tHit ) * 0.5f;
1080 hitInfoLTB.m_HitNormal =
1081 glm::normalize( ( hitPacket[iLT].m_HitInfo.m_HitNormal
1082 + hitPacket[iLB].m_HitInfo.m_HitNormal )
1083 * 0.5f );
1084 cLTB = COLOR_RGBA(
1085 shadeHit( bgColorY, rayLTB, hitInfoLTB, false, 0, false ) );
1086 cLTB = BlendColor( cLTB, BlendColor( cLT, cLB) );
1087 }
1088 else
1089 {
1090 // If any hits
1091 if( hitPacket[ iLT ].m_hitresult || hitPacket[ iLB ].m_hitresult )
1092 {
1093 const unsigned int nodeLT =
1094 hitPacket[ iLT ].m_HitInfo.m_acc_node_info;
1095 const unsigned int nodeLB =
1096 hitPacket[ iLB ].m_HitInfo.m_acc_node_info;
1097
1098 bool hittedLTB = false;
1099
1100 if( nodeLT != 0 )
1101 hittedLTB |= m_accelerator->Intersect( rayLTB, hitInfoLTB,
1102 nodeLT );
1103
1104 if( ( nodeLB != 0 ) && ( nodeLB != nodeLT ) )
1105 hittedLTB |= m_accelerator->Intersect( rayLTB, hitInfoLTB,
1106 nodeLB );
1107
1108 if( hittedLTB )
1109 cLTB = COLOR_RGBA( shadeHit( bgColorY, rayLTB, hitInfoLTB,
1110 false, 0, false ) );
1111 else
1112 {
1113 hitInfoLTB.m_tHit = std::numeric_limits<float>::infinity();
1114
1115 if( m_accelerator->Intersect( rayLTB, hitInfoLTB ) )
1116 cLTB = COLOR_RGBA( shadeHit( bgColorY, rayLTB,
1117 hitInfoLTB, false,
1118 0, false ) );
1119 }
1120 }
1121 }
1122 }
1123 else
1124 {
1125 cLTB = cRTB_old;
1126 }
1127
1128 // Trace and shade cRTB
1129 COLOR_RGBA cRTB = bgColorYRGB;
1130
1131 // Trace the center ray
1132 RAY rayRTB;
1133 rayRTB.Init( ( oriRT + oriRB ) * 0.5f,
1134 glm::normalize( ( dirRT + dirRB ) * 0.5f ) );
1135
1136 HITINFO hitInfoRTB;
1137 hitInfoRTB.m_tHit = std::numeric_limits<float>::infinity();
1138
1139 if( hitPacket[ iRT ].m_hitresult && hitPacket[ iRB ].m_hitresult
1140 && ( hitPacket[ iRT ].m_HitInfo.pHitObject ==
1141 hitPacket[ iRB ].m_HitInfo.pHitObject ) )
1142 {
1143 hitInfoRTB.pHitObject = hitPacket[ iRT ].m_HitInfo.pHitObject;
1144
1145 hitInfoRTB.m_tHit = ( hitPacket[ iRT ].m_HitInfo.m_tHit +
1146 hitPacket[ iRB ].m_HitInfo.m_tHit ) * 0.5f;
1147
1148 hitInfoRTB.m_HitNormal =
1149 glm::normalize( ( hitPacket[iRT].m_HitInfo.m_HitNormal
1150 + hitPacket[iRB].m_HitInfo.m_HitNormal )
1151 * 0.5f );
1152
1153 cRTB = COLOR_RGBA( shadeHit( bgColorY, rayRTB, hitInfoRTB, false, 0,
1154 false ) );
1155 cRTB = BlendColor( cRTB, BlendColor( cRT, cRB ) );
1156 }
1157 else
1158 {
1159 // If any hits
1160 if( hitPacket[ iRT ].m_hitresult || hitPacket[ iRB ].m_hitresult )
1161 {
1162 const unsigned int nodeRT =
1163 hitPacket[ iRT ].m_HitInfo.m_acc_node_info;
1164 const unsigned int nodeRB =
1165 hitPacket[ iRB ].m_HitInfo.m_acc_node_info;
1166
1167 bool hittedRTB = false;
1168
1169 if( nodeRT != 0 )
1170 hittedRTB |= m_accelerator->Intersect( rayRTB, hitInfoRTB,
1171 nodeRT );
1172
1173 if( ( nodeRB != 0 ) && ( nodeRB != nodeRT ) )
1174 hittedRTB |= m_accelerator->Intersect( rayRTB, hitInfoRTB,
1175 nodeRB );
1176
1177 if( hittedRTB )
1178 {
1179 cRTB = COLOR_RGBA( shadeHit( bgColorY, rayRTB, hitInfoRTB,
1180 false, 0, false) );
1181 }
1182 else
1183 {
1184 hitInfoRTB.m_tHit = std::numeric_limits<float>::infinity();
1185
1186 if( m_accelerator->Intersect( rayRTB, hitInfoRTB ) )
1187 cRTB = COLOR_RGBA( shadeHit( bgColorY, rayRTB, hitInfoRTB,
1188 false, 0, false ) );
1189 }
1190 }
1191 }
1192
1193 cRTB_old = cRTB;
1194
1195 // Trace and shade cLRB
1196 COLOR_RGBA cLRB = bgColorYRGB;
1197
1198 const SFVEC3F& oriLB = blockPacket.m_ray[ iLB ].m_Origin;
1199 const SFVEC3F& dirLB = blockPacket.m_ray[ iLB ].m_Dir;
1200
1201 // Trace the center ray
1202 RAY rayLRB;
1203 rayLRB.Init( ( oriLB + oriRB ) * 0.5f,
1204 glm::normalize( ( dirLB + dirRB ) * 0.5f ) );
1205
1206 HITINFO hitInfoLRB;
1207 hitInfoLRB.m_tHit = std::numeric_limits<float>::infinity();
1208
1209 if( hitPacket[iLB].m_hitresult && hitPacket[iRB].m_hitresult
1210 && ( hitPacket[iLB].m_HitInfo.pHitObject ==
1211 hitPacket[iRB].m_HitInfo.pHitObject ) )
1212 {
1213 hitInfoLRB.pHitObject = hitPacket[ iLB ].m_HitInfo.pHitObject;
1214
1215 hitInfoLRB.m_tHit = ( hitPacket[ iLB ].m_HitInfo.m_tHit +
1216 hitPacket[ iRB ].m_HitInfo.m_tHit ) * 0.5f;
1217
1218 hitInfoLRB.m_HitNormal =
1219 glm::normalize( ( hitPacket[iLB].m_HitInfo.m_HitNormal
1220 + hitPacket[iRB].m_HitInfo.m_HitNormal )
1221 * 0.5f );
1222
1223 cLRB = COLOR_RGBA( shadeHit( bgColorY, rayLRB, hitInfoLRB, false, 0,
1224 false ) );
1225 cLRB = BlendColor( cLRB, BlendColor( cLB, cRB ) );
1226 }
1227 else
1228 {
1229 // If any hits
1230 if( hitPacket[ iLB ].m_hitresult || hitPacket[ iRB ].m_hitresult )
1231 {
1232 const unsigned int nodeLB =
1233 hitPacket[ iLB ].m_HitInfo.m_acc_node_info;
1234 const unsigned int nodeRB =
1235 hitPacket[ iRB ].m_HitInfo.m_acc_node_info;
1236
1237 bool hittedLRB = false;
1238
1239 if( nodeLB != 0 )
1240 hittedLRB |= m_accelerator->Intersect( rayLRB, hitInfoLRB,
1241 nodeLB );
1242
1243 if( ( nodeRB != 0 ) && ( nodeRB != nodeLB ) )
1244 hittedLRB |= m_accelerator->Intersect( rayLRB, hitInfoLRB,
1245 nodeRB );
1246
1247 if( hittedLRB )
1248 {
1249 cLRB = COLOR_RGBA( shadeHit( bgColorY, rayLRB, hitInfoLRB,
1250 false, 0, false ) );
1251 }
1252 else
1253 {
1254 hitInfoLRB.m_tHit = std::numeric_limits<float>::infinity();
1255
1256 if( m_accelerator->Intersect( rayLRB, hitInfoLRB ) )
1257 cLRB = COLOR_RGBA( shadeHit( bgColorY, rayLRB, hitInfoLRB,
1258 false, 0, false ) );
1259 }
1260 }
1261 }
1262
1263 cLRB_old[x] = cLRB;
1264
1265 // Trace and shade cLTC
1266 COLOR_RGBA cLTC = BlendColor( cLT , cC );
1267
1268 if( hitPacket[ iLT ].m_hitresult || hittedC )
1269 {
1270 // Trace the center ray
1271 RAY rayLTC;
1272 rayLTC.Init( ( oriLT + oriC ) * 0.5f,
1273 glm::normalize( ( dirLT + dirC ) * 0.5f ) );
1274
1275 HITINFO hitInfoLTC;
1276 hitInfoLTC.m_tHit = std::numeric_limits<float>::infinity();
1277
1278 bool hitted = false;
1279
1280 if( hittedC )
1281 hitted = centerHitInfo.pHitObject->Intersect( rayLTC, hitInfoLTC );
1282 else if( hitPacket[ iLT ].m_hitresult )
1283 hitted = hitPacket[ iLT ].m_HitInfo.pHitObject->Intersect(
1284 rayLTC,
1285 hitInfoLTC );
1286
1287 if( hitted )
1288 cLTC = COLOR_RGBA( shadeHit( bgColorY, rayLTC, hitInfoLTC, false,
1289 0, false ) );
1290 }
1291
1292 // Trace and shade cRTC
1293 COLOR_RGBA cRTC = BlendColor( cRT , cC );
1294
1295 if( hitPacket[ iRT ].m_hitresult || hittedC )
1296 {
1297 // Trace the center ray
1298 RAY rayRTC;
1299 rayRTC.Init( ( oriRT + oriC ) * 0.5f,
1300 glm::normalize( ( dirRT + dirC ) * 0.5f ) );
1301
1302 HITINFO hitInfoRTC;
1303 hitInfoRTC.m_tHit = std::numeric_limits<float>::infinity();
1304
1305 bool hitted = false;
1306
1307 if( hittedC )
1308 hitted = centerHitInfo.pHitObject->Intersect( rayRTC, hitInfoRTC );
1309 else if( hitPacket[ iRT ].m_hitresult )
1310 hitted = hitPacket[iRT].m_HitInfo.pHitObject->Intersect(
1311 rayRTC, hitInfoRTC );
1312
1313 if( hitted )
1314 cRTC = COLOR_RGBA( shadeHit( bgColorY, rayRTC, hitInfoRTC, false,
1315 0, false ) );
1316 }
1317
1318 // Trace and shade cLBC
1319 COLOR_RGBA cLBC = BlendColor( cLB , cC );
1320
1321 if( hitPacket[ iLB ].m_hitresult || hittedC )
1322 {
1323 // Trace the center ray
1324 RAY rayLBC;
1325 rayLBC.Init( ( oriLB + oriC ) * 0.5f,
1326 glm::normalize( ( dirLB + dirC ) * 0.5f ) );
1327
1328 HITINFO hitInfoLBC;
1329 hitInfoLBC.m_tHit = std::numeric_limits<float>::infinity();
1330
1331 bool hitted = false;
1332
1333 if( hittedC )
1334 hitted = centerHitInfo.pHitObject->Intersect( rayLBC, hitInfoLBC );
1335 else if( hitPacket[ iLB ].m_hitresult )
1336 hitted = hitPacket[iLB].m_HitInfo.pHitObject->Intersect(
1337 rayLBC, hitInfoLBC );
1338
1339 if( hitted )
1340 cLBC = COLOR_RGBA( shadeHit( bgColorY, rayLBC, hitInfoLBC, false,
1341 0, false ) );
1342 }
1343
1344 // Trace and shade cRBC
1345 COLOR_RGBA cRBC = BlendColor( cRB , cC );
1346
1347 if( hitPacket[ iRB ].m_hitresult || hittedC )
1348 {
1349 // Trace the center ray
1350 RAY rayRBC;
1351 rayRBC.Init( ( oriRB + oriC ) * 0.5f,
1352 glm::normalize( ( dirRB + dirC ) * 0.5f ) );
1353
1354 HITINFO hitInfoRBC;
1355 hitInfoRBC.m_tHit = std::numeric_limits<float>::infinity();
1356
1357 bool hitted = false;
1358
1359 if( hittedC )
1360 hitted = centerHitInfo.pHitObject->Intersect( rayRBC, hitInfoRBC );
1361 else if( hitPacket[ iRB ].m_hitresult )
1362 hitted = hitPacket[iRB].m_HitInfo.pHitObject->Intersect(
1363 rayRBC, hitInfoRBC );
1364
1365 if( hitted )
1366 cRBC = COLOR_RGBA( shadeHit( bgColorY, rayRBC, hitInfoRBC, false,
1367 0, false ) );
1368 }
1369
1370 // Set pixel colors
1371 uint8_t* ptr =
1372 &ptrPBO[( 4 * x + m_blockPositionsFast[iBlock].x
1374 * ( m_blockPositionsFast[iBlock].y + 4 * y ) ) * 4];
1375
1376 SetPixelSRGBA( ptr + 0, cLT );
1377 SetPixelSRGBA( ptr + 4, BlendColor( cLT, cLRT, cLTC ) );
1378 SetPixelSRGBA( ptr + 8, cLRT );
1379 SetPixelSRGBA( ptr + 12, BlendColor( cLRT, cRT, cRTC ) );
1380
1381 ptr += m_realBufferSize.x * 4;
1382 SetPixelSRGBA( ptr + 0, BlendColor( cLT , cLTB, cLTC ) );
1383 SetPixelSRGBA( ptr + 4, BlendColor( cLTC, BlendColor( cLT , cC ) ) );
1384 SetPixelSRGBA( ptr + 8, BlendColor( cC, BlendColor( cLRT, cLTC, cRTC ) ) );
1385 SetPixelSRGBA( ptr + 12, BlendColor( cRTC, BlendColor( cRT , cC ) ) );
1386
1387 ptr += m_realBufferSize.x * 4;
1388 SetPixelSRGBA( ptr + 0, cLTB );
1389 SetPixelSRGBA( ptr + 4, BlendColor( cC, BlendColor( cLTB, cLTC, cLBC ) ) );
1390 SetPixelSRGBA( ptr + 8, cC );
1391 SetPixelSRGBA( ptr + 12, BlendColor( cC, BlendColor( cRTB, cRTC, cRBC ) ) );
1392
1393 ptr += m_realBufferSize.x * 4;
1394 SetPixelSRGBA( ptr + 0, BlendColor( cLB , cLTB, cLBC ) );
1395 SetPixelSRGBA( ptr + 4, BlendColor( cLBC, BlendColor( cLB , cC ) ) );
1396 SetPixelSRGBA( ptr + 8, BlendColor( cC, BlendColor( cLRB, cLBC, cRBC ) ) );
1397 SetPixelSRGBA( ptr + 12, BlendColor( cRBC, BlendColor( cRB , cC ) ) );
1398 }
1399 }
1400 }
1401
1402 threadsFinished++;
1403 } );
1404
1405 t.detach();
1406 }
1407
1408 while( threadsFinished < parallelThreadCount )
1409 std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
1410}
1411
1412
1413#define USE_EXPERIMENTAL_SOFT_SHADOWS 1
1414
1416 HITINFO& aHitInfo, bool aIsInsideObject,
1417 unsigned int aRecursiveLevel, bool is_testShadow ) const
1418{
1419 const MATERIAL* objMaterial = aHitInfo.pHitObject->GetMaterial();
1420 wxASSERT( objMaterial != nullptr );
1421
1422 SFVEC4F outColor =
1423 SFVEC4F( objMaterial->GetEmissiveColor() + objMaterial->GetAmbientColor(), 1.0f );
1424
1425 if( aRecursiveLevel > 7 )
1426 return outColor;
1427
1428 SFVEC3F hitPoint = aHitInfo.m_HitPoint;
1429
1430 hitPoint += aHitInfo.m_HitNormal * m_boardAdapter.GetNonCopperLayerThickness() * 0.6f;
1431
1432 const SFVEC4F diffuseColorObj =
1433 SFVEC4F( aHitInfo.pHitObject->GetDiffuseColor( aHitInfo ), 1.0f );
1434
1435#if USE_EXPERIMENTAL_SOFT_SHADOWS
1436 bool is_aa_enabled = m_boardAdapter.m_Cfg->m_Render.raytrace_anti_aliasing && !m_isPreview;
1437#endif
1438
1439 float shadow_att_factor_sum = 0.0f;
1440
1441 unsigned int nr_lights_that_can_cast_shadows = 0;
1442
1443 for( const LIGHT* light : m_lights )
1444 {
1445 SFVEC3F vectorToLight;
1446 SFVEC3F colorOfLight;
1447 float distToLight;
1448
1449 light->GetLightParameters( hitPoint, vectorToLight, colorOfLight, distToLight );
1450
1451 const float NdotL = glm::dot( aHitInfo.m_HitNormal, vectorToLight );
1452
1453 // Only calc shade if the normal is facing the direction of light,
1454 // otherwise it is in the shadow
1455 if( NdotL >= FLT_EPSILON )
1456 {
1457 float shadow_att_factor_light = 1.0f;
1458
1459 if( is_testShadow && light->GetCastShadows() )
1460 {
1461 nr_lights_that_can_cast_shadows++;
1462#if USE_EXPERIMENTAL_SOFT_SHADOWS
1463 // For rays that are recursive, just calculate one hit shadow
1464 if( aRecursiveLevel > 0 )
1465 {
1466#endif
1467 RAY rayToLight;
1468 rayToLight.Init( hitPoint, vectorToLight );
1469
1470 // Test if point is not in the shadow.
1471 // Test for any hit from the point in the direction of light
1472 if( m_accelerator->IntersectP( rayToLight, distToLight ) )
1473 shadow_att_factor_light = 0.0f;
1474
1475#if USE_EXPERIMENTAL_SOFT_SHADOWS
1476 }
1477 else // Experimental softshadow calculation
1478 {
1479 const unsigned int shadow_number_of_samples =
1480 m_boardAdapter.m_Cfg->m_Render.raytrace_nrsamples_shadows;
1481 const float shadow_inc_factor = 1.0f / (float) ( shadow_number_of_samples );
1482
1483 for( unsigned int i = 0; i < shadow_number_of_samples; ++i )
1484 {
1485 RAY rayToLight;
1486
1487 if( i == 0 )
1488 {
1489 rayToLight.Init( hitPoint, vectorToLight );
1490 }
1491 else
1492 {
1493 const SFVEC3F unifVector = UniformRandomHemisphereDirection();
1494 const SFVEC3F disturbed_vector_to_light =
1495 glm::normalize( vectorToLight + unifVector *
1496 m_boardAdapter.m_Cfg->m_Render.raytrace_spread_shadows );
1497
1498 rayToLight.Init( hitPoint, disturbed_vector_to_light );
1499 }
1500
1501 // !TODO: there are multiple ways that this tests can be
1502 // optimized. Eg: by packing rays or to test against the
1503 // latest hit object.
1504 if( m_accelerator->IntersectP( rayToLight, distToLight ) )
1505 {
1506 shadow_att_factor_light -= shadow_inc_factor;
1507 }
1508 }
1509 }
1510#endif
1511 shadow_att_factor_sum += shadow_att_factor_light;
1512 }
1513
1514 outColor += SFVEC4F( objMaterial->Shade( aRay, aHitInfo, NdotL, diffuseColorObj,
1515 vectorToLight, colorOfLight,
1516 shadow_att_factor_light ),
1517 1.0 );
1518 }
1519 }
1520
1521 // Improvement: this is not taking in account the lightcolor
1522 if( nr_lights_that_can_cast_shadows > 0 )
1523 {
1524 aHitInfo.m_ShadowFactor = glm::max(
1525 shadow_att_factor_sum / (float) ( nr_lights_that_can_cast_shadows * 1.0f ), 0.0f );
1526 }
1527 else
1528 {
1529 aHitInfo.m_ShadowFactor = 1.0f;
1530 }
1531
1532 // Clamp color to not be brighter than 1.0f
1533 outColor = glm::min( outColor, SFVEC4F( 1.0f ) );
1534
1535 if( !m_isPreview )
1536 {
1537 // Reflections
1538 if( ( objMaterial->GetReflection() > 0.0f )
1539 && m_boardAdapter.m_Cfg->m_Render.raytrace_reflections
1540 && ( aRecursiveLevel < objMaterial->GetReflectionRecursionCount() ) )
1541 {
1542 const unsigned int reflection_number_of_samples =
1543 objMaterial->GetReflectionRayCount();
1544
1545 SFVEC4F sum_color = SFVEC4F( 0.0f );
1546
1547 const SFVEC3F reflectVector = aRay.m_Dir - 2.0f *
1548 glm::dot( aRay.m_Dir, aHitInfo.m_HitNormal ) * aHitInfo.m_HitNormal;
1549
1550 for( unsigned int i = 0; i < reflection_number_of_samples; ++i )
1551 {
1552 RAY reflectedRay;
1553
1554 if( i == 0 )
1555 {
1556 reflectedRay.Init( hitPoint, reflectVector );
1557 }
1558 else
1559 {
1560 // Apply some randomize to the reflected vector
1561 const SFVEC3F random_reflectVector =
1562 glm::normalize( reflectVector
1564 * m_boardAdapter.m_Cfg->m_Render
1565 .raytrace_spread_reflections );
1566
1567 reflectedRay.Init( hitPoint, random_reflectVector );
1568 }
1569
1570 HITINFO reflectedHit;
1571 reflectedHit.m_tHit = std::numeric_limits<float>::infinity();
1572
1573 if( m_accelerator->Intersect( reflectedRay, reflectedHit ) )
1574 {
1575 SFVEC4F add = ( diffuseColorObj + SFVEC4F( objMaterial->GetSpecularColor(),
1576 1.0f ) ) *
1577 shadeHit( aBgColor, reflectedRay, reflectedHit, false,
1578 aRecursiveLevel + 1, is_testShadow ) *
1579 SFVEC4F( objMaterial->GetReflection() *
1580 // Falloff factor
1581 (1.0f / ( 1.0f + 0.75f * reflectedHit.m_tHit *
1582 reflectedHit.m_tHit) ) );
1583
1584 sum_color += add;
1585 }
1586 }
1587
1588 outColor += (sum_color / SFVEC4F( (float)reflection_number_of_samples) );
1589 }
1590
1591 // Refraction
1592 const float objTransparency = aHitInfo.pHitObject->GetModelTransparency();
1593
1594 if( ( objTransparency > 0.0f ) && m_boardAdapter.m_Cfg->m_Render.raytrace_refractions
1595 && ( aRecursiveLevel < objMaterial->GetRefractionRecursionCount() ) )
1596 {
1597 const float airIndex = 1.000293f;
1598 const float glassIndex = 1.49f;
1599 const float air_over_glass = airIndex / glassIndex;
1600 const float glass_over_air = glassIndex / airIndex;
1601
1602 const float refractionRatio = aIsInsideObject?glass_over_air:air_over_glass;
1603
1604 SFVEC3F refractedVector;
1605
1606 if( Refract( aRay.m_Dir, aHitInfo.m_HitNormal, refractionRatio, refractedVector ) )
1607 {
1608 // This increase the start point by a "fixed" factor so it will work the
1609 // same for all distances
1610 const SFVEC3F startPoint =
1611 aRay.at( aHitInfo.m_tHit + m_boardAdapter.GetNonCopperLayerThickness() *
1612 0.25f );
1613
1614 const unsigned int refractions_number_of_samples =
1615 objMaterial->GetRefractionRayCount();
1616
1617 SFVEC4F sum_color = SFVEC4F( 0.0f );
1618
1619 for( unsigned int i = 0; i < refractions_number_of_samples; ++i )
1620 {
1621 RAY refractedRay;
1622
1623 if( i == 0 )
1624 {
1625 refractedRay.Init( startPoint, refractedVector );
1626 }
1627 else
1628 {
1629 // apply some randomize to the refracted vector
1630 const SFVEC3F randomizeRefractedVector =
1631 glm::normalize( refractedVector +
1633 m_boardAdapter.m_Cfg->m_Render.raytrace_spread_refractions );
1634
1635 refractedRay.Init( startPoint, randomizeRefractedVector );
1636 }
1637
1638 HITINFO refractedHit;
1639 refractedHit.m_tHit = std::numeric_limits<float>::infinity();
1640
1641 SFVEC4F refractedColor = aBgColor;
1642
1643 if( m_accelerator->Intersect( refractedRay, refractedHit ) )
1644 {
1645 refractedColor = shadeHit( aBgColor, refractedRay, refractedHit,
1646 !aIsInsideObject, aRecursiveLevel + 1, false );
1647
1648 const SFVEC4F absorbance = ( SFVEC4F(1.0f) - diffuseColorObj ) *
1649 (1.0f - objTransparency ) *
1650 objMaterial->GetAbsorvance() *
1651 refractedHit.m_tHit;
1652
1653 const SFVEC4F transparency = 1.0f / ( absorbance + 1.0f );
1654
1655 sum_color += refractedColor * transparency;
1656 }
1657 else
1658 {
1659 sum_color += refractedColor;
1660 }
1661 }
1662
1663 outColor = outColor * ( 1.0f - objTransparency ) + objTransparency * sum_color
1664 / SFVEC4F( (float) refractions_number_of_samples );
1665 }
1666 else
1667 {
1668 outColor = outColor * ( 1.0f - objTransparency ) + objTransparency * aBgColor;
1669 }
1670 }
1671 }
1672
1673 return outColor;
1674}
1675
1676
1677static float distance( const SFVEC2UI& a, const SFVEC2UI& b )
1678{
1679 const float dx = (float) a.x - (float) b.x;
1680 const float dy = (float) a.y - (float) b.y;
1681 return hypotf( dx, dy );
1682}
1683
1684
1686{
1688
1689 // Calc block positions for fast preview mode
1690 m_blockPositionsFast.clear();
1691
1692 unsigned int i = 0;
1693
1694 while(1)
1695 {
1696 const unsigned int mX = DecodeMorton2X(i);
1697 const unsigned int mY = DecodeMorton2Y(i);
1698
1699 i++;
1700
1701 const SFVEC2UI blockPos( mX * 4 * RAYPACKET_DIM - mX * 4,
1702 mY * 4 * RAYPACKET_DIM - mY * 4 );
1703
1704 if( ( blockPos.x >= ( (unsigned int)m_windowSize.x - ( 4 * RAYPACKET_DIM + 4 ) ) ) &&
1705 ( blockPos.y >= ( (unsigned int)m_windowSize.y - ( 4 * RAYPACKET_DIM + 4 ) ) ) )
1706 break;
1707
1708 if( ( blockPos.x < ( (unsigned int)m_windowSize.x - ( 4 * RAYPACKET_DIM + 4 ) ) ) &&
1709 ( blockPos.y < ( (unsigned int)m_windowSize.y - ( 4 * RAYPACKET_DIM + 4 ) ) ) )
1710 {
1711 m_blockPositionsFast.push_back( blockPos );
1712
1713 if( blockPos.x > m_realBufferSize.x )
1714 m_realBufferSize.x = blockPos.x;
1715
1716 if( blockPos.y > m_realBufferSize.y )
1717 m_realBufferSize.y = blockPos.y;
1718 }
1719 }
1720
1722
1725
1726 m_xoffset = ( m_windowSize.x - m_realBufferSize.x ) / 2;
1727 m_yoffset = ( m_windowSize.y - m_realBufferSize.y ) / 2;
1728
1729 m_postShaderSsao.UpdateSize( m_realBufferSize );
1730
1731 // Calc block positions for regular rendering. Choose an 'inside out' style of rendering.
1732 m_blockPositions.clear();
1733 const int blocks_x = m_realBufferSize.x / RAYPACKET_DIM;
1734 const int blocks_y = m_realBufferSize.y / RAYPACKET_DIM;
1735 m_blockPositions.reserve( blocks_x * blocks_y );
1736
1737 // Hilbert curve position calculation
1738 // modified from Matters Computational, Springer 2011
1739 // GPLv3, Copyright Joerg Arndt
1740 constexpr auto hilbert_get_pos = []( size_t aT, size_t& aX, size_t& aY )
1741 {
1742 static const size_t htab[] = { 0b0010, 0b0100, 0b1100, 0b1001, 0b1111, 0b0101,
1743 0b0001, 0b1000, 0b0000, 0b1010, 0b1110, 0b0111,
1744 0b1101, 0b1011, 0b0011, 0b0110 };
1745 static const size_t size = sizeof( size_t ) * 8;
1746 size_t xv = 0;
1747 size_t yv = 0;
1748 size_t c01 = 0;
1749
1750 for( size_t i = 0; i < ( size / 2 ); ++i )
1751 {
1752 size_t abi = aT >> ( size - 2 );
1753 aT <<= 2;
1754
1755 size_t st = htab[( c01 << 2 ) | abi];
1756 c01 = st & 3;
1757
1758 yv = ( yv << 1 ) | ( ( st >> 2 ) & 1 );
1759 xv = ( xv << 1 ) | ( st >> 3 );
1760 }
1761
1762 aX = xv;
1763 aY = yv;
1764 };
1765
1766 size_t total_blocks = blocks_x * blocks_y;
1767 size_t pos = 0;
1768 size_t x = 0;
1769 size_t y = 0;
1770
1771 while( m_blockPositions.size() < total_blocks )
1772 {
1773 hilbert_get_pos( pos++, x, y );
1774
1775 if( x < blocks_x && y < blocks_y )
1776 m_blockPositions.emplace_back( x * RAYPACKET_DIM, y * RAYPACKET_DIM );
1777 }
1778
1779 // Create m_shader buffer
1780 delete[] m_shaderBuffer;
1782
1783 initPbo();
1784}
1785
1786
1788{
1789 HITINFO hitInfo;
1790 hitInfo.m_tHit = std::numeric_limits<float>::infinity();
1791
1792 if( m_accelerator )
1793 {
1794 if( m_accelerator->Intersect( aRay, hitInfo ) )
1795 {
1796 if( hitInfo.pHitObject )
1797 return hitInfo.pHitObject->GetBoardItem();
1798 }
1799 }
1800
1801 return nullptr;
1802}
Defines math related functions.
Defines math related functions.
bool Refract(const SFVEC3F &aInVector, const SFVEC3F &aNormal, float aRin_over_Rout, SFVEC3F &aOutVector)
Based on: https://github.com/mmp/pbrt-v3/blob/master/src/core/reflection.h See also: http://www....
Definition 3d_math.h:112
SFVEC3F UniformRandomHemisphereDirection()
Definition 3d_math.h:55
int color
Helper class to handle information needed to display 3D board.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:79
A class used to derive camera objects from.
Definition camera.h:103
A base light class to derive to implement other light classes.
Definition light.h:41
Base material class that can be used to derive other material implementations.
Definition material.h:240
float GetAbsorvance() const
Definition material.h:275
virtual SFVEC3F Shade(const RAY &aRay, const HITINFO &aHitInfo, float NdotL, const SFVEC3F &aDiffuseObjColor, const SFVEC3F &aDirToLight, const SFVEC3F &aLightColor, float aShadowAttenuationFactor) const =0
Shade an intersection point.
const SFVEC3F & GetAmbientColor() const
Definition material.h:268
unsigned int GetRefractionRayCount() const
Definition material.h:276
const SFVEC3F & GetSpecularColor() const
Definition material.h:270
const SFVEC3F & GetEmissiveColor() const
Definition material.h:269
float GetReflection() const
Definition material.h:274
unsigned int GetReflectionRayCount() const
Definition material.h:277
virtual SFVEC3F GetDiffuseColor(const HITINFO &aHitInfo) const =0
BOARD_ITEM * GetBoardItem() const
Definition object_3d.h:56
virtual bool Intersect(const RAY &aRay, HITINFO &aHitInfo) const =0
float GetModelTransparency() const
Definition object_3d.h:65
const MATERIAL * GetMaterial() const
Definition object_3d.h:64
RENDER_3D_BASE(BOARD_ADAPTER &aBoardAdapter, CAMERA &aCamera)
wxSize m_windowSize
The window size that this camera is working.
BOARD_ADAPTER & m_boardAdapter
Settings reference in use for this render.
void renderBlockTracing(uint8_t *ptrPBO, signed int iBlock)
static SFVEC4F premultiplyAlpha(const SFVEC4F &aInput)
RENDER_3D_RAYTRACE_BASE(BOARD_ADAPTER &aAdapter, CAMERA &aCamera)
void renderFinalColor(uint8_t *ptrPBO, const SFVEC4F &rgbColor, bool applyColorSpaceConversion)
void renderTracing(uint8_t *ptrPBO, REPORTER *aStatusReporter)
void render(uint8_t *ptrPBO, REPORTER *aStatusReporter)
void postProcessBlurFinish(uint8_t *ptrPBO, REPORTER *aStatusReporter)
void renderAntiAliasPackets(const SFVEC4F *aBgColorY, const HITINFO_PACKET *aHitPck_X0Y0, const HITINFO_PACKET *aHitPck_AA_X1Y1, const RAY *aRayPck, SFVEC4F *aOutHitColor)
void postProcessShading(uint8_t *ptrPBO, REPORTER *aStatusReporter)
std::vector< int > m_blockPositionsWasProcessed
Flag if a position was already processed (cleared each new render).
BOARD_ITEM * IntersectBoardItem(const RAY &aRay)
RT_RENDER_STATE m_renderState
State used on quality render.
void renderRayPackets(const SFVEC4F *bgColorY, const RAY *aRayPkt, HITINFO_PACKET *aHitPacket, bool is_testShadow, SFVEC4F *aOutHitColor)
int GetWaitForEditingTimeOut() override
Give the interface the time (in ms) that it should wait for editing or movements before (this works f...
std::vector< SFVEC2UI > m_blockPositionsFast
Encode the Morton code positions (on fast preview mode).
SFVEC4F shadeHit(const SFVEC4F &aBgColor, const RAY &aRay, HITINFO &aHitInfo, bool aIsInsideObject, unsigned int aRecursiveLevel, bool is_testShadow) const
BVH_CONTAINER_2D * m_antioutlineBoard2dObjects
wxSize m_oldWindowsSize
Used to see if the windows size changed.
void renderPreview(uint8_t *ptrPBO)
virtual void initPbo()=0
size_t m_blockRenderProgressCount
Save the number of blocks progress of the render.
int64_t m_renderStartTime
Time that the render starts.
std::vector< SFVEC2UI > m_blockPositions
Encode Morton code positions.
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:73
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
Definition reporter.h:102
COLOR_RGBA BlendColor(const COLOR_RGBA &aC1, const COLOR_RGBA &aC2)
#define _(s)
static const wxChar * m_logTrace
Trace mask used to enable or disable the trace output of this class.
uint32_t DecodeMorton2Y(uint32_t code)
uint32_t DecodeMorton2X(uint32_t code)
Implements Morton Codes https://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes/ http://www....
int64_t GetRunningMicroSecs()
An alternate way to calculate an elapsed time (in microsecondes) to class PROF_COUNTER.
void RAYPACKET_InitRays_with2DDisplacement(const CAMERA &aCamera, const SFVEC2F &aWindowsPosition, const SFVEC2F &a2DWindowsPosDisplacementFactor, RAY *aRayPck)
#define RAYPACKET_INVMASK
Definition raypacket.h:34
#define RAYPACKET_RAYS_PER_PACKET
Definition raypacket.h:35
#define RAYPACKET_DIM
Definition raypacket.h:32
#define SRGB_GAMA
static SFVEC4F convertLinearToSRGBA(const SFVEC4F &aRGBAcolor)
SFVEC3F ConvertSRGBToLinear(const SFVEC3F &aSRGBcolor)
static void SetPixel(uint8_t *p, const COLOR_RGBA &v)
static void HITINFO_PACKET_init(HITINFO_PACKET *aHitPacket)
static SFVEC3F convertLinearToSRGB(const SFVEC3F &aRGBcolor)
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
static void SetPixelSRGBA(uint8_t *p, const COLOR_RGBA &v)
#define DISP_FACTOR
SFVEC4F ConvertSRGBAToLinear(const SFVEC4F &aSRGBAcolor)
@ RT_RENDER_STATE_POST_PROCESS_SHADE
@ RT_RENDER_STATE_POST_PROCESS_BLUR_AND_FINISH
@ RT_RENDER_STATE_FINISH
@ RT_RENDER_STATE_TRACING
@ RT_RENDER_STATE_MAX
SFVEC4F ConvertSRGBAToLinear(const SFVEC4F &aSRGBAcolor)
bool m_hitresult
Definition hitinfo.h:57
HITINFO m_HitInfo
Definition hitinfo.h:58
Stores the hit information of a ray with a point on the surface of a object.
Definition hitinfo.h:36
unsigned int m_acc_node_info
( 4) The acc stores here the node that it hits
Definition hitinfo.h:42
float m_tHit
( 4) distance
Definition hitinfo.h:38
const OBJECT_3D * pHitObject
( 4) Object that was hitted
Definition hitinfo.h:40
float m_ShadowFactor
( 4) Shadow attenuation (1.0 no shadow, 0.0f darkness)
Definition hitinfo.h:45
SFVEC3F m_HitNormal
(12) normal at the hit point
Definition hitinfo.h:37
SFVEC3F m_HitPoint
(12) hit position
Definition hitinfo.h:44
RAY m_ray[RAYPACKET_RAYS_PER_PACKET]
Definition raypacket.h:54
Definition ray.h:63
SFVEC3F m_Dir
Definition ray.h:67
void Init(const SFVEC3F &o, const SFVEC3F &d)
Definition ray.cpp:35
SFVEC3F m_Origin
Definition ray.h:64
SFVEC3F at(float t) const
Definition ray.h:84
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
static thread_pool * tp
BS::thread_pool< 0 > thread_pool
Definition thread_pool.h:31
unsigned char c[4]
Definition color_rgba.h:36
glm::ivec2 SFVEC2I
Definition xv3d_types.h:39
glm::vec2 SFVEC2F
Definition xv3d_types.h:42
glm::vec3 SFVEC3F
Definition xv3d_types.h:44
glm::uvec2 SFVEC2UI
Definition xv3d_types.h:38
glm::vec4 SFVEC4F
Definition xv3d_types.h:46