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