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