From fb089a182bf475ed8383f703dd1bf7b79b205d59 Mon Sep 17 00:00:00 2001 From: Alex Shvartzkop Date: Thu, 29 Feb 2024 23:39:48 +0300 Subject: [PATCH] 3D viewer: support transparent background in Raytracing mode. --- 3d-viewer/3d_rendering/buffers_debug.cpp | 40 +++- 3d-viewer/3d_rendering/buffers_debug.h | 5 +- .../{color_rgb.cpp => color_rgba.cpp} | 35 ++- .../{color_rgb.h => color_rgba.h} | 38 ++-- .../3d_rendering/opengl/render_3d_opengl.cpp | 11 +- 3d-viewer/3d_rendering/post_shader.cpp | 12 +- 3d-viewer/3d_rendering/post_shader.h | 14 +- 3d-viewer/3d_rendering/post_shader_ssao.cpp | 40 ++-- 3d-viewer/3d_rendering/post_shader_ssao.h | 6 +- .../3d_rendering/raytracing/create_scene.cpp | 14 +- .../raytracing/render_3d_raytrace.cpp | 205 ++++++++++-------- .../raytracing/render_3d_raytrace.h | 20 +- 3d-viewer/CMakeLists.txt | 2 +- 13 files changed, 279 insertions(+), 163 deletions(-) rename 3d-viewer/3d_rendering/{color_rgb.cpp => color_rgba.cpp} (59%) rename 3d-viewer/3d_rendering/{color_rgb.h => color_rgba.h} (58%) diff --git a/3d-viewer/3d_rendering/buffers_debug.cpp b/3d-viewer/3d_rendering/buffers_debug.cpp index f3b69a0308..ae1f0832c7 100644 --- a/3d-viewer/3d_rendering/buffers_debug.cpp +++ b/3d-viewer/3d_rendering/buffers_debug.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2016 Mario Luzeiro - * Copyright (C) 2016-2020 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2024 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -46,6 +46,19 @@ static void dbg_save_rgb_buffer( const wxString& aFileName, unsigned char *aRGBp } +static void dbg_save_rgb_a_buffer( const wxString& aFileName, unsigned char* aRGBpixelBuffer, + unsigned char* aAlphaBuffer, unsigned int aXSize, + unsigned int aYSize ) +{ + wxImage image( aXSize, aYSize ); + image.SetData( aRGBpixelBuffer ); + image.SetAlpha( aAlphaBuffer ); + image = image.Mirror( false ); + image.SaveFile( aFileName + wxT( ".png" ), wxBITMAP_TYPE_PNG ); + image.Destroy(); +} + + void DBG_SaveBuffer( const wxString& aFileName, const unsigned char *aInBuffer, unsigned int aXSize, unsigned int aYSize ) { @@ -110,6 +123,31 @@ void DBG_SaveBuffer( const wxString& aFileName, const SFVEC3F *aInBuffer, } +void DBG_SaveBuffer( const wxString& aFileName, const SFVEC4F *aInBuffer, + unsigned int aXSize, unsigned int aYSize ) +{ + const unsigned int wxh = aXSize * aYSize; + + unsigned char *pixelbuffer = (unsigned char*) malloc( wxh * 4 ); + unsigned char *alphabuffer = (unsigned char*) malloc( wxh ); + + for( unsigned int i = 0; i < wxh; ++i ) + { + const SFVEC4F &v = aInBuffer[i]; + const unsigned int ix3 = i * 3; + + // Set RGB value with all same values intensities + pixelbuffer[ix3 + 0] = (unsigned char) glm::min( (int) ( v.r * 255.0f ), 255 ); + pixelbuffer[ix3 + 1] = (unsigned char) glm::min( (int) ( v.g * 255.0f ), 255 ); + pixelbuffer[ix3 + 2] = (unsigned char) glm::min( (int) ( v.b * 255.0f ), 255 ); + + alphabuffer[i] = (unsigned char) glm::min( (int) ( v.a * 255.0f ), 255 ); + } + + dbg_save_rgb_a_buffer( aFileName, pixelbuffer, alphabuffer, aXSize, aYSize ); +} + + void DBG_SaveNormalsBuffer( const wxString& aFileName, const SFVEC3F *aInNormalsBuffer, unsigned int aXSize, unsigned int aYSize ) { diff --git a/3d-viewer/3d_rendering/buffers_debug.h b/3d-viewer/3d_rendering/buffers_debug.h index 9e5fd9700a..e954743c64 100644 --- a/3d-viewer/3d_rendering/buffers_debug.h +++ b/3d-viewer/3d_rendering/buffers_debug.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2016 Mario Luzeiro - * Copyright (C) 2016-2020 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2024 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -42,6 +42,9 @@ void DBG_SaveBuffer( const wxString& aFileName, const float *aInBuffer, void DBG_SaveBuffer( const wxString& aFileName, const SFVEC3F *aInBuffer, unsigned int aXSize, unsigned int aYSize ); +void DBG_SaveBuffer( const wxString& aFileName, const SFVEC4F *aInBuffer, + unsigned int aXSize, unsigned int aYSize ); + void DBG_SaveNormalsBuffer( const wxString& aFileName, const SFVEC3F *aInNormalsBuffer, unsigned int aXSize, unsigned int aYSize ); diff --git a/3d-viewer/3d_rendering/color_rgb.cpp b/3d-viewer/3d_rendering/color_rgba.cpp similarity index 59% rename from 3d-viewer/3d_rendering/color_rgb.cpp rename to 3d-viewer/3d_rendering/color_rgba.cpp index 16f6146301..1c4bd904fc 100644 --- a/3d-viewer/3d_rendering/color_rgb.cpp +++ b/3d-viewer/3d_rendering/color_rgba.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2015-2016 Mario Luzeiro - * Copyright (C) 2015-2020 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2015-2024 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -23,47 +23,60 @@ */ /** - * @file color_rgb.cpp + * @file color_rgba.cpp */ -#include "color_rgb.h" +#include "color_rgba.h" -COLOR_RGB::COLOR_RGB( const SFVEC3F& aColor ) +COLOR_RGBA::COLOR_RGBA( const SFVEC3F& aColor ) { r = (unsigned int) glm::clamp( (int) ( aColor.r * 255 ), 0, 255 ); g = (unsigned int) glm::clamp( (int) ( aColor.g * 255 ), 0, 255 ); b = (unsigned int) glm::clamp( (int) ( aColor.b * 255 ), 0, 255 ); + a = 255; } -COLOR_RGB BlendColor( const COLOR_RGB& aC1, const COLOR_RGB& aC2 ) +COLOR_RGBA::COLOR_RGBA( const SFVEC4F& aColor ) +{ + r = (unsigned int) glm::clamp( (int) ( aColor.r * 255 ), 0, 255 ); + g = (unsigned int) glm::clamp( (int) ( aColor.g * 255 ), 0, 255 ); + b = (unsigned int) glm::clamp( (int) ( aColor.b * 255 ), 0, 255 ); + a = (unsigned int) glm::clamp( (int) ( aColor.a * 255 ), 0, 255 ); +} + + +COLOR_RGBA BlendColor( const COLOR_RGBA& aC1, const COLOR_RGBA& aC2 ) { const unsigned int r = aC1.r + aC2.r; const unsigned int g = aC1.g + aC2.g; const unsigned int b = aC1.b + aC2.b; + const unsigned int a = aC1.a + aC2.a; - return COLOR_RGB( ( r >> 1 ), ( g >> 1 ), ( b >> 1 ) ); + return COLOR_RGBA( ( r >> 1 ), ( g >> 1 ), ( b >> 1 ), ( a >> 1 ) ); } -COLOR_RGB BlendColor( const COLOR_RGB& aC1, const COLOR_RGB& aC2, const COLOR_RGB& aC3 ) +COLOR_RGBA BlendColor( const COLOR_RGBA& aC1, const COLOR_RGBA& aC2, const COLOR_RGBA& aC3 ) { const unsigned int r = aC1.r + aC2.r + aC3.r; const unsigned int g = aC1.g + aC2.g + aC3.g; const unsigned int b = aC1.b + aC2.b + aC3.b; + const unsigned int a = aC1.a + aC2.a + aC3.a; - return COLOR_RGB( ( r / 3 ), ( g / 3 ), ( b / 3 ) ); + return COLOR_RGBA( ( r / 3 ), ( g / 3 ), ( b / 3 ), ( a / 3 ) ); } -COLOR_RGB BlendColor( const COLOR_RGB& aC1, const COLOR_RGB& aC2, const COLOR_RGB& aC3, - const COLOR_RGB& aC4 ) +COLOR_RGBA BlendColor( const COLOR_RGBA& aC1, const COLOR_RGBA& aC2, const COLOR_RGBA& aC3, + const COLOR_RGBA& aC4 ) { const unsigned int r = aC1.r + aC2.r + aC3.r + aC4.r; const unsigned int g = aC1.g + aC2.g + aC3.g + aC4.g; const unsigned int b = aC1.b + aC2.b + aC3.b + aC4.b; + const unsigned int a = aC1.a + aC2.a + aC3.a + aC4.a; - return COLOR_RGB( ( r >> 2 ), ( g >> 2 ), ( b >> 2 ) ); + return COLOR_RGBA( ( r >> 2 ), ( g >> 2 ), ( b >> 2 ), ( a >> 2 ) ); } diff --git a/3d-viewer/3d_rendering/color_rgb.h b/3d-viewer/3d_rendering/color_rgba.h similarity index 58% rename from 3d-viewer/3d_rendering/color_rgb.h rename to 3d-viewer/3d_rendering/color_rgba.h index 89e7d2a008..fdb38a1f99 100644 --- a/3d-viewer/3d_rendering/color_rgb.h +++ b/3d-viewer/3d_rendering/color_rgba.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2015-2016 Mario Luzeiro - * Copyright (C) 2015-2020 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2015-2024 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -23,39 +23,49 @@ */ /** - * @file color_rgb.h + * @file color_rgba.h */ -#ifndef COLOR_RGB_H -#define COLOR_RGB_H +#ifndef COLOR_RGBA_H +#define COLOR_RGBA_H #include -union COLOR_RGB +union COLOR_RGBA { - unsigned char c[3]; + unsigned char c[4]; struct { unsigned char r; unsigned char g; unsigned char b; + unsigned char a; }; - COLOR_RGB( const SFVEC3F& aColor ); - COLOR_RGB() { r = 0; g = 0; b = 0; } - COLOR_RGB( unsigned char aR, unsigned char aG, unsigned char aB ) + COLOR_RGBA( const SFVEC3F& aColor ); + COLOR_RGBA( const SFVEC4F& aColor ); + COLOR_RGBA() { r = 0; g = 0; b = 0; a = 0; } + COLOR_RGBA( unsigned char aR, unsigned char aG, unsigned char aB ) { r = aR; g = aG; b = aB; } + + COLOR_RGBA( unsigned char aR, unsigned char aG, unsigned char aB, unsigned char aA ) + { + r = aR; + g = aG; + b = aB; + a = aA; + } }; -COLOR_RGB BlendColor( const COLOR_RGB& aC1, const COLOR_RGB& aC2 ); -COLOR_RGB BlendColor( const COLOR_RGB& aC1, const COLOR_RGB& aC2, const COLOR_RGB& aC3 ); -COLOR_RGB BlendColor( const COLOR_RGB& aC1, const COLOR_RGB& aC2, const COLOR_RGB& aC3, - const COLOR_RGB& aC4 ); +COLOR_RGBA BlendColor( const COLOR_RGBA& aC1, const COLOR_RGBA& aC2 ); +COLOR_RGBA BlendColor( const COLOR_RGBA& aC1, const COLOR_RGBA& aC2, const COLOR_RGBA& aC3 ); +COLOR_RGBA BlendColor( const COLOR_RGBA& aC1, const COLOR_RGBA& aC2, const COLOR_RGBA& aC3, + const COLOR_RGBA& aC4 ); -#endif // COLOR_RGB_H +#endif // COLOR_RGBA_H diff --git a/3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp b/3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp index 652107aacf..b05bbd34bb 100644 --- a/3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp +++ b/3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp @@ -3,7 +3,7 @@ * * Copyright (C) 2015-2020 Mario Luzeiro * Copyright (C) 2023 CERN - * Copyright (C) 2015-2023 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2015-2024 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -444,6 +444,12 @@ void RENDER_3D_OPENGL::renderBoardBody( bool aSkipRenderHoles ) } +static inline SFVEC4F premultiplyAlpha( const SFVEC4F& aInput ) +{ + return SFVEC4F( aInput.r * aInput.a, aInput.g * aInput.a, aInput.b * aInput.a, aInput.a ); +} + + bool RENDER_3D_OPENGL::Redraw( bool aIsMoving, REPORTER* aStatusReporter, REPORTER* aWarningReporter ) { @@ -503,7 +509,8 @@ bool RENDER_3D_OPENGL::Redraw( bool aIsMoving, REPORTER* aStatusReporter, OglResetTextureState(); // Draw the background ( rectangle with color gradient) - OglDrawBackground( m_boardAdapter.m_BgColorTop, m_boardAdapter.m_BgColorBot ); + OglDrawBackground( premultiplyAlpha( m_boardAdapter.m_BgColorTop ), + premultiplyAlpha( m_boardAdapter.m_BgColorBot ) ); glEnable( GL_DEPTH_TEST ); diff --git a/3d-viewer/3d_rendering/post_shader.cpp b/3d-viewer/3d_rendering/post_shader.cpp index 42a5602bef..9687ad30cb 100644 --- a/3d-viewer/3d_rendering/post_shader.cpp +++ b/3d-viewer/3d_rendering/post_shader.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2015-2016 Mario Luzeiro - * Copyright (C) 2015-2020 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2015-2024 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -63,7 +63,7 @@ void POST_SHADER::UpdateSize( unsigned int xSize, unsigned int ySize ) const unsigned int n_elements = xSize * ySize; m_normals = new SFVEC3F[n_elements]; - m_color = new SFVEC3F[n_elements]; + m_color = new SFVEC4F[n_elements]; m_depth = new float[n_elements]; m_wc_hitposition = new SFVEC3F[n_elements]; m_shadow_att_factor = new float[n_elements]; @@ -77,7 +77,7 @@ void POST_SHADER::UpdateSize( const SFVEC2UI& aSize ) void POST_SHADER::SetPixelData( unsigned int x, unsigned int y, const SFVEC3F& aNormal, - const SFVEC3F& aColor, const SFVEC3F& aHitPosition, + const SFVEC4F& aColor, const SFVEC3F& aHitPosition, float aDepth, float aShadowAttFactor ) { wxASSERT( x < m_size.x ); @@ -125,7 +125,7 @@ const SFVEC3F& POST_SHADER::GetNormalAt( const SFVEC2F& aPos ) const } -const SFVEC3F& POST_SHADER::GetColorAt( const SFVEC2F& aPos ) const +const SFVEC4F& POST_SHADER::GetColorAt( const SFVEC2F& aPos ) const { return m_color[GetIndex( aPos )]; } @@ -149,13 +149,13 @@ const SFVEC3F& POST_SHADER::GetNormalAt( const SFVEC2I& aPos ) const } -const SFVEC3F& POST_SHADER::GetColorAt( const SFVEC2I& aPos ) const +const SFVEC4F& POST_SHADER::GetColorAt( const SFVEC2I& aPos ) const { return m_color[GetIndex( aPos )]; } -const SFVEC3F& POST_SHADER::GetColorAtNotProtected( const SFVEC2I& aPos ) const +const SFVEC4F& POST_SHADER::GetColorAtNotProtected( const SFVEC2I& aPos ) const { return m_color[ aPos.x + m_size.x * aPos.y ]; } diff --git a/3d-viewer/3d_rendering/post_shader.h b/3d-viewer/3d_rendering/post_shader.h index 564d70088d..9d05f91142 100644 --- a/3d-viewer/3d_rendering/post_shader.h +++ b/3d-viewer/3d_rendering/post_shader.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2015-2016 Mario Luzeiro - * Copyright (C) 2015-2020 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2015-2024 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -46,7 +46,7 @@ public: * @param aShadeColor The result of the shader. * @return the result of the shade process */ - virtual SFVEC3F ApplyShadeColor( const SFVEC2I& aShaderPos, const SFVEC3F& aInputColor, + virtual SFVEC4F ApplyShadeColor( const SFVEC2I& aShaderPos, const SFVEC4F& aInputColor, const SFVEC3F& aShadeColor ) const = 0; void UpdateSize( const SFVEC2UI& aSize ); @@ -56,10 +56,10 @@ public: void InitFrame() { m_tmin = FLT_MAX; m_tmax = 0.0f; } void SetPixelData( unsigned int x, unsigned int y, const SFVEC3F& aNormal, - const SFVEC3F& aColor, const SFVEC3F& aHitPosition, + const SFVEC4F& aColor, const SFVEC3F& aHitPosition, float aDepth, float aShadowAttFactor ); - const SFVEC3F& GetColorAtNotProtected( const SFVEC2I& aPos ) const; + const SFVEC4F& GetColorAtNotProtected( const SFVEC2I& aPos ) const; void DebugBuffersOutputAsImages() const; @@ -88,12 +88,12 @@ public: protected: const SFVEC3F& GetNormalAt( const SFVEC2F& aPos ) const; - const SFVEC3F& GetColorAt( const SFVEC2F& aPos ) const; + const SFVEC4F& GetColorAt( const SFVEC2F& aPos ) const; const SFVEC3F& GetPositionAt( const SFVEC2F& aPos ) const; float GetDepthAt( const SFVEC2F& aPos ) const; const SFVEC3F& GetNormalAt( const SFVEC2I& aPos ) const; - const SFVEC3F& GetColorAt( const SFVEC2I& aPos ) const; + const SFVEC4F& GetColorAt( const SFVEC2I& aPos ) const; const SFVEC3F& GetPositionAt( const SFVEC2I& aPos ) const; const float& GetShadowFactorAt( const SFVEC2I& aPos ) const; @@ -109,7 +109,7 @@ protected: SFVEC2UI m_size; SFVEC3F* m_normals; - SFVEC3F* m_color; + SFVEC4F* m_color; SFVEC3F* m_wc_hitposition; float* m_depth; float* m_shadow_att_factor; diff --git a/3d-viewer/3d_rendering/post_shader_ssao.cpp b/3d-viewer/3d_rendering/post_shader_ssao.cpp index 4f46e6f307..2f2389f1eb 100644 --- a/3d-viewer/3d_rendering/post_shader_ssao.cpp +++ b/3d-viewer/3d_rendering/post_shader_ssao.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2015-2016 Mario Luzeiro - * Copyright (C) 2015-2020 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2015-2024 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -187,21 +187,21 @@ SFVEC3F POST_SHADER_SSAO::Shade( const SFVEC2I& aShaderPos ) const ao += aoFF( aShaderPos, ddiff8, n, shadowAt8, shadowAt0, -npw, ph ); gi += giFF( aShaderPos, ddiff , n, shadowAt1, npw, nph) * - giColorCurve( GetColorAt( aShaderPos + SFVEC2I( npw, nph ) ) ); + giColorCurveShade( GetColorAt( aShaderPos + SFVEC2I( npw, nph ) ) ); gi += giFF( aShaderPos, ddiff2, n, shadowAt2, npw, -nph) * - giColorCurve( GetColorAt( aShaderPos + SFVEC2I( npw,-nph ) ) ); + giColorCurveShade( GetColorAt( aShaderPos + SFVEC2I( npw,-nph ) ) ); gi += giFF( aShaderPos, ddiff3, n, shadowAt3, -npw, nph) * - giColorCurve( GetColorAt( aShaderPos + SFVEC2I( -npw, nph ) ) ); + giColorCurveShade( GetColorAt( aShaderPos + SFVEC2I( -npw, nph ) ) ); gi += giFF( aShaderPos, ddiff4, n, shadowAt4, -npw, -nph) * - giColorCurve( GetColorAt( aShaderPos + SFVEC2I( -npw,-nph ) ) ); + giColorCurveShade( GetColorAt( aShaderPos + SFVEC2I( -npw,-nph ) ) ); gi += giFF( aShaderPos, ddiff5, n, shadowAt5 , pw, nph) * - giColorCurve( GetColorAt( aShaderPos + SFVEC2I( pw, nph ) ) ); + giColorCurveShade( GetColorAt( aShaderPos + SFVEC2I( pw, nph ) ) ); gi += giFF( aShaderPos, ddiff6, n, shadowAt6, pw,-nph) * - giColorCurve( GetColorAt( aShaderPos + SFVEC2I( pw,-nph ) ) ); + giColorCurveShade( GetColorAt( aShaderPos + SFVEC2I( pw,-nph ) ) ); gi += giFF( aShaderPos, ddiff7, n, shadowAt7, npw, ph) * - giColorCurve( GetColorAt( aShaderPos + SFVEC2I( npw, ph ) ) ); + giColorCurveShade( GetColorAt( aShaderPos + SFVEC2I( npw, ph ) ) ); gi += giFF( aShaderPos, ddiff8, n, shadowAt8, -npw, ph) * - giColorCurve( GetColorAt( aShaderPos + SFVEC2I( -npw, ph ) ) ); + giColorCurveShade( GetColorAt( aShaderPos + SFVEC2I( -npw, ph ) ) ); } // If it received direct light, it shouldn't consider much AO @@ -227,18 +227,20 @@ SFVEC3F POST_SHADER_SSAO::Shade( const SFVEC2I& aShaderPos ) const } -SFVEC3F POST_SHADER_SSAO::ApplyShadeColor( const SFVEC2I& aShaderPos, const SFVEC3F& aInputColor, +SFVEC4F POST_SHADER_SSAO::ApplyShadeColor( const SFVEC2I& aShaderPos, const SFVEC4F& aInputColor, const SFVEC3F& aShadeColor ) const { - SFVEC3F outColor; + SFVEC4F outColor; + SFVEC3F inColor( aInputColor ); - const SFVEC3F subtracted = aInputColor - aShadeColor; - const SFVEC3F mixed = glm::mix( aInputColor, aInputColor * 0.50f - aShadeColor * 0.05f, + const SFVEC3F subtracted = inColor - aShadeColor; + const SFVEC3F mixed = glm::mix( inColor, inColor * 0.50f - aShadeColor * 0.05f, glm::min( aShadeColor, 1.0f ) ); outColor.r = ( aShadeColor.r < 0.0f ) ? subtracted.r : mixed.r; outColor.g = ( aShadeColor.g < 0.0f ) ? subtracted.g : mixed.g; outColor.b = ( aShadeColor.b < 0.0f ) ? subtracted.b : mixed.b; + outColor.a = std::max( aInputColor.a, ( aShadeColor.r + aShadeColor.g + aShadeColor.b ) / 3 ); return outColor; } @@ -256,6 +258,18 @@ SFVEC3F POST_SHADER_SSAO::giColorCurve( const SFVEC3F& aColor ) const } +SFVEC4F POST_SHADER_SSAO::giColorCurve( const SFVEC4F& aColor ) const +{ + return SFVEC4F( giColorCurve( SFVEC3F( aColor ) ), aColor.a ); +} + + +SFVEC3F POST_SHADER_SSAO::giColorCurveShade( const SFVEC4F& aColor ) const +{ + return giColorCurve( SFVEC3F( aColor ) ); +} + + SFVEC3F POST_SHADER_SSAO::Blur( const SFVEC2I& aShaderPos ) const { const float dCenter = GetDepthAt( aShaderPos ); diff --git a/3d-viewer/3d_rendering/post_shader_ssao.h b/3d-viewer/3d_rendering/post_shader_ssao.h index f6263fb952..3f700dcc94 100644 --- a/3d-viewer/3d_rendering/post_shader_ssao.h +++ b/3d-viewer/3d_rendering/post_shader_ssao.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2015-2016 Mario Luzeiro - * Copyright (C) 2015-2020 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2015-2024 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -40,7 +40,7 @@ public: explicit POST_SHADER_SSAO( const CAMERA& aCamera ); SFVEC3F Shade(const SFVEC2I& aShaderPos ) const override; - SFVEC3F ApplyShadeColor( const SFVEC2I& aShaderPos, const SFVEC3F& aInputColor, + SFVEC4F ApplyShadeColor( const SFVEC2I& aShaderPos, const SFVEC4F& aInputColor, const SFVEC3F& aShadeColor ) const override; SFVEC3F Blur( const SFVEC2I& aShaderPos ) const; @@ -77,6 +77,8 @@ private: * @return transformed color. */ SFVEC3F giColorCurve( const SFVEC3F& aColor ) const; + SFVEC4F giColorCurve( const SFVEC4F& aColor ) const; + SFVEC3F giColorCurveShade( const SFVEC4F& aColor ) const; SFVEC3F* m_shadedBuffer; diff --git a/3d-viewer/3d_rendering/raytracing/create_scene.cpp b/3d-viewer/3d_rendering/raytracing/create_scene.cpp index d0384e8d23..9a7a6e3c1f 100644 --- a/3d-viewer/3d_rendering/raytracing/create_scene.cpp +++ b/3d-viewer/3d_rendering/raytracing/create_scene.cpp @@ -3,7 +3,7 @@ * * Copyright (C) 2015-2022 Mario Luzeiro * Copyright (C) 2023 CERN - * Copyright (C) 2015-2023 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2015-2024 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -170,7 +170,7 @@ void RENDER_3D_RAYTRACE::setupMaterials() m_materials.m_Floor = BLINN_PHONG_MATERIAL( bgTop * 0.125f, SFVEC3F( 0.0f, 0.0f, 0.0f ), ( SFVEC3F( 1.0f ) - bgTop ) / 3.0f, - 0.10f * 128.0f, 0.0f, 0.50f ); + 0.10f * 128.0f, 1.0f, 0.50f ); m_materials.m_Floor.SetCastShadows( false ); m_materials.m_Floor.SetReflectionRecursionCount( 1 ); } @@ -817,7 +817,7 @@ void RENDER_3D_RAYTRACE::Reload( REPORTER* aStatusReporter, REPORTER* aWarningRe const SFVEC3F v2 = SFVEC3F( v1.x, v3.y, v1.z ); const SFVEC3F v4 = SFVEC3F( v3.x, v1.y, v1.z ); - SFVEC3F backgroundColor = ConvertSRGBToLinear( m_boardAdapter.m_BgColorTop ); + SFVEC3F floorColor = ConvertSRGBToLinear( m_boardAdapter.m_BgColorTop ); TRIANGLE* newTriangle1 = new TRIANGLE( v1, v2, v3 ); TRIANGLE* newTriangle2 = new TRIANGLE( v3, v4, v1 ); @@ -828,8 +828,8 @@ void RENDER_3D_RAYTRACE::Reload( REPORTER* aStatusReporter, REPORTER* aWarningRe newTriangle1->SetMaterial( &m_materials.m_Floor ); newTriangle2->SetMaterial( &m_materials.m_Floor ); - newTriangle1->SetColor( backgroundColor ); - newTriangle2->SetColor( backgroundColor ); + newTriangle1->SetColor( floorColor ); + newTriangle2->SetColor( floorColor ); // Ceiling triangles const float maxZ = glm::max( containerBBox.Max().z, boardBBox.Max().z ); @@ -848,8 +848,8 @@ void RENDER_3D_RAYTRACE::Reload( REPORTER* aStatusReporter, REPORTER* aWarningRe newTriangle3->SetMaterial( &m_materials.m_Floor ); newTriangle4->SetMaterial( &m_materials.m_Floor ); - newTriangle3->SetColor( backgroundColor ); - newTriangle4->SetColor( backgroundColor ); + newTriangle3->SetColor( floorColor ); + newTriangle4->SetColor( floorColor ); } } } diff --git a/3d-viewer/3d_rendering/raytracing/render_3d_raytrace.cpp b/3d-viewer/3d_rendering/raytracing/render_3d_raytrace.cpp index 4dc706d4a7..8e516d323e 100644 --- a/3d-viewer/3d_rendering/raytracing/render_3d_raytrace.cpp +++ b/3d-viewer/3d_rendering/raytracing/render_3d_raytrace.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2015-2020 Mario Luzeiro - * Copyright (C) 2015-2023 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2015-2024 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -31,7 +31,7 @@ #include "render_3d_raytrace.h" #include "mortoncodes.h" -#include "../color_rgb.h" +#include "../color_rgba.h" #include "3d_fastmath.h" #include "3d_math.h" #include "../common_ogl/ogl_utils.h" @@ -136,12 +136,18 @@ void RENDER_3D_RAYTRACE::restartRenderState() } -static inline void SetPixel( GLubyte* p, const COLOR_RGB& v ) +static inline void SetPixel( GLubyte* p, const COLOR_RGBA& v ) { p[0] = v.c[0]; p[1] = v.c[1]; p[2] = v.c[2]; - p[3] = 255; + p[3] = v.c[3]; +} + + +static inline SFVEC4F premultiplyAlpha( const SFVEC4F& aInput ) +{ + return SFVEC4F( aInput.r * aInput.a, aInput.g * aInput.a, aInput.b * aInput.a, aInput.a ); } @@ -220,7 +226,8 @@ bool RENDER_3D_RAYTRACE::Redraw( bool aIsMoving, REPORTER* aStatusReporter, if( m_cameraLight ) m_cameraLight->SetDirection( -m_camera.GetDir() ); - OglDrawBackground( m_boardAdapter.m_BgColorTop, m_boardAdapter.m_BgColorBot ); + OglDrawBackground( premultiplyAlpha( m_boardAdapter.m_BgColorTop ), + premultiplyAlpha( m_boardAdapter.m_BgColorBot ) ); // Bind PBO glBindBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, m_pboId ); @@ -306,8 +313,10 @@ void RENDER_3D_RAYTRACE::render( GLubyte* ptrPBO, REPORTER* aStatusReporter ) } } - m_backgroundColorTop = ConvertSRGBToLinear( (SFVEC3F)m_boardAdapter.m_BgColorTop ); - m_backgroundColorBottom = ConvertSRGBToLinear( (SFVEC3F)m_boardAdapter.m_BgColorBot ); + m_backgroundColorTop = + ConvertSRGBAToLinear( premultiplyAlpha( m_boardAdapter.m_BgColorTop ) ); + m_backgroundColorBottom = + ConvertSRGBAToLinear( premultiplyAlpha( m_boardAdapter.m_BgColorBot ) ); } switch( m_renderState ) @@ -423,6 +432,11 @@ static SFVEC3F convertLinearToSRGB( const SFVEC3F& aRGBcolor ) glm::lessThan( clampedColor, SFVEC3F(0.0031308f) ) ); } +static SFVEC4F convertLinearToSRGBA( const SFVEC4F& aRGBAcolor ) +{ + return SFVEC4F( convertLinearToSRGB( SFVEC3F( aRGBAcolor ) ), aRGBAcolor.a ); +} + // This function implements the conversion from sRGB to linear RGB // https://github.com/g-truc/glm/blob/master/glm/gtc/color_space.inl#L35 @@ -437,13 +451,18 @@ SFVEC3F ConvertSRGBToLinear( const SFVEC3F& aSRGBcolor ) glm::lessThanEqual( aSRGBcolor, SFVEC3F( 0.04045f ) ) ); } +SFVEC4F ConvertSRGBAToLinear( const SFVEC4F& aSRGBAcolor ) +{ + return SFVEC4F( ConvertSRGBToLinear( SFVEC3F( aSRGBAcolor ) ), aSRGBAcolor.a ); +} + #endif -void RENDER_3D_RAYTRACE::renderFinalColor( GLubyte* ptrPBO, const SFVEC3F& rgbColor, +void RENDER_3D_RAYTRACE::renderFinalColor( GLubyte* ptrPBO, const SFVEC4F& rgbColor, bool applyColorSpaceConversion ) { - SFVEC3F color = rgbColor; + SFVEC4F color = rgbColor; #ifdef USE_SRGB_SPACE /// @note This should be used in future when the KiCad support a greater version of glm lib. @@ -457,7 +476,7 @@ void RENDER_3D_RAYTRACE::renderFinalColor( GLubyte* ptrPBO, const SFVEC3F& rgbCo ptrPBO[0] = (unsigned int) glm::clamp( (int) ( color.r * 255 ), 0, 255 ); ptrPBO[1] = (unsigned int) glm::clamp( (int) ( color.g * 255 ), 0, 255 ); ptrPBO[2] = (unsigned int) glm::clamp( (int) ( color.b * 255 ), 0, 255 ); - ptrPBO[3] = 255; + ptrPBO[3] = (unsigned int) glm::clamp( (int) ( color.a * 255 ), 0, 255 ); } @@ -475,9 +494,9 @@ static void HITINFO_PACKET_init( HITINFO_PACKET* aHitPacket ) } -void RENDER_3D_RAYTRACE::renderRayPackets( const SFVEC3F* bgColorY, const RAY* aRayPkt, +void RENDER_3D_RAYTRACE::renderRayPackets( const SFVEC4F* bgColorY, const RAY* aRayPkt, HITINFO_PACKET* aHitPacket, bool is_testShadow, - SFVEC3F* aOutHitColor ) + SFVEC4F* aOutHitColor ) { for( unsigned int y = 0, i = 0; y < RAYPACKET_DIM; ++y ) { @@ -497,10 +516,10 @@ void RENDER_3D_RAYTRACE::renderRayPackets( const SFVEC3F* bgColorY, const RAY* a } -void RENDER_3D_RAYTRACE::renderAntiAliasPackets( const SFVEC3F* aBgColorY, +void RENDER_3D_RAYTRACE::renderAntiAliasPackets( const SFVEC4F* aBgColorY, const HITINFO_PACKET* aHitPck_X0Y0, const HITINFO_PACKET* aHitPck_AA_X1Y1, - const RAY* aRayPck, SFVEC3F* aOutHitColor ) + const RAY* aRayPck, SFVEC4F* aOutHitColor ) { const bool is_testShadow = m_boardAdapter.m_Cfg->m_Render.raytrace_shadows; @@ -636,14 +655,14 @@ void RENDER_3D_RAYTRACE::renderBlockTracing( GLubyte* ptrPBO, signed int iBlock HITINFO_PACKET_init( hitPacket_X0Y0 ); // Calculate background gradient color - SFVEC3F bgColor[RAYPACKET_DIM];// Store a vertical gradient color + SFVEC4F bgColor[RAYPACKET_DIM];// Store a vertical gradient color for( unsigned int y = 0; y < RAYPACKET_DIM; ++y ) { const float posYfactor = (float) ( blockPosI.y + y ) / (float) m_windowSize.y; - bgColor[y] = m_backgroundColorTop * SFVEC3F(posYfactor) + - m_backgroundColorBottom * ( SFVEC3F(1.0f) - SFVEC3F(posYfactor) ); + bgColor[y] = m_backgroundColorTop * SFVEC4F(posYfactor) + + m_backgroundColorBottom * ( SFVEC4F(1.0f) - SFVEC4F(posYfactor) ); } // Intersect ray packets (calculate the intersection with rays and objects) @@ -654,7 +673,7 @@ void RENDER_3D_RAYTRACE::renderBlockTracing( GLubyte* ptrPBO, signed int iBlock { for( unsigned int y = 0; y < RAYPACKET_DIM; ++y ) { - const SFVEC3F& outColor = bgColor[y]; + const SFVEC4F& outColor = bgColor[y]; const unsigned int yBlockPos = blockPos.y + y; @@ -674,7 +693,7 @@ void RENDER_3D_RAYTRACE::renderBlockTracing( GLubyte* ptrPBO, signed int iBlock for( unsigned int y = 0; y < RAYPACKET_DIM; ++y ) { - const SFVEC3F& outColor = bgColor[y]; + const SFVEC4F& outColor = bgColor[y]; const unsigned int yConst = blockPos.x + ( ( y + blockPos.y ) * m_realBufferSize.x ); @@ -691,7 +710,7 @@ void RENDER_3D_RAYTRACE::renderBlockTracing( GLubyte* ptrPBO, signed int iBlock return; } - SFVEC3F hitColor_X0Y0[RAYPACKET_RAYS_PER_PACKET]; + SFVEC4F hitColor_X0Y0[RAYPACKET_RAYS_PER_PACKET]; // Shade original (0, 0) hits ("paint" the intersected objects) renderRayPackets( bgColor, blockPacket.m_ray, hitPacket_X0Y0, @@ -699,7 +718,7 @@ void RENDER_3D_RAYTRACE::renderBlockTracing( GLubyte* ptrPBO, signed int iBlock if( m_boardAdapter.m_Cfg->m_Render.raytrace_anti_aliasing ) { - SFVEC3F hitColor_AA_X1Y1[RAYPACKET_RAYS_PER_PACKET]; + SFVEC4F hitColor_AA_X1Y1[RAYPACKET_RAYS_PER_PACKET]; // Intersect one blockPosI + (0.5, 0.5) used for anti aliasing calculation HITINFO_PACKET hitPacket_AA_X1Y1[RAYPACKET_RAYS_PER_PACKET]; @@ -713,7 +732,7 @@ void RENDER_3D_RAYTRACE::renderBlockTracing( GLubyte* ptrPBO, signed int iBlock // Missed all the package for( unsigned int y = 0, i = 0; y < RAYPACKET_DIM; ++y ) { - const SFVEC3F& outColor = bgColor[y]; + const SFVEC4F& outColor = bgColor[y]; for( unsigned int x = 0; x < RAYPACKET_DIM; ++x, ++i ) hitColor_AA_X1Y1[i] = outColor; @@ -725,13 +744,13 @@ void RENDER_3D_RAYTRACE::renderBlockTracing( GLubyte* ptrPBO, signed int iBlock m_boardAdapter.m_Cfg->m_Render.raytrace_shadows, hitColor_AA_X1Y1 ); } - SFVEC3F hitColor_AA_X1Y0[RAYPACKET_RAYS_PER_PACKET]; - SFVEC3F hitColor_AA_X0Y1[RAYPACKET_RAYS_PER_PACKET]; - SFVEC3F hitColor_AA_X0Y1_half[RAYPACKET_RAYS_PER_PACKET]; + SFVEC4F hitColor_AA_X1Y0[RAYPACKET_RAYS_PER_PACKET]; + SFVEC4F hitColor_AA_X0Y1[RAYPACKET_RAYS_PER_PACKET]; + SFVEC4F hitColor_AA_X0Y1_half[RAYPACKET_RAYS_PER_PACKET]; for( unsigned int i = 0; i < RAYPACKET_RAYS_PER_PACKET; ++i ) { - SFVEC3F color_average = ( hitColor_X0Y0[i] + hitColor_AA_X1Y1[i] ) * SFVEC3F( 0.5f ); + SFVEC4F color_average = ( hitColor_X0Y0[i] + hitColor_AA_X1Y1[i] ) * SFVEC4F( 0.5f ); hitColor_AA_X1Y0[i] = color_average; hitColor_AA_X0Y1[i] = color_average; @@ -768,7 +787,7 @@ void RENDER_3D_RAYTRACE::renderBlockTracing( GLubyte* ptrPBO, signed int iBlock { hitColor_X0Y0[i] = ( hitColor_X0Y0[i] + hitColor_AA_X1Y1[i] + hitColor_AA_X1Y0[i] + hitColor_AA_X0Y1[i] + hitColor_AA_X0Y1_half[i] ) * - SFVEC3F( 1.0f / 5.0f ); + SFVEC4F( 1.0f / 5.0f ); } } @@ -788,7 +807,7 @@ void RENDER_3D_RAYTRACE::renderBlockTracing( GLubyte* ptrPBO, signed int iBlock for( unsigned int x = 0; x < RAYPACKET_DIM; ++x, ++i ) { - const SFVEC3F& hColor = hitColor_X0Y0[i]; + const SFVEC4F& hColor = hitColor_X0Y0[i]; if( hitPacket_X0Y0[i].m_hitresult == true ) { @@ -908,13 +927,13 @@ void RENDER_3D_RAYTRACE::postProcessBlurFinish( GLubyte* ptrPBO, REPORTER* /* aS const SFVEC3F bluredShadeColor = m_postShaderSsao.Blur( SFVEC2I( x, y ) ); #ifdef USE_SRGB_SPACE - const SFVEC3F originColor = convertLinearToSRGB( + const SFVEC4F originColor = convertLinearToSRGBA( m_postShaderSsao.GetColorAtNotProtected( SFVEC2I( x, y ) ) ); #else - const SFVEC3F originColor = + const SFVEC4F originColor = m_postShaderSsao.GetColorAtNotProtected( SFVEC2I( x, y ) ); #endif - const SFVEC3F shadedColor = m_postShaderSsao.ApplyShadeColor( + const SFVEC4F shadedColor = m_postShaderSsao.ApplyShadeColor( SFVEC2I( x, y ), originColor, bluredShadeColor ); renderFinalColor( ptr, shadedColor, false ); @@ -979,45 +998,47 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO ) m_accelerator->Intersect( blockPacket, hitPacket ); // Calculate background gradient color - SFVEC3F bgColor[RAYPACKET_DIM]; + SFVEC4F bgColor[RAYPACKET_DIM]; + + SFVEC4F bgTopColor = premultiplyAlpha( m_boardAdapter.m_BgColorTop ); + SFVEC4F bgBotColor = premultiplyAlpha( m_boardAdapter.m_BgColorBot ); for( unsigned int y = 0; y < RAYPACKET_DIM; ++y ) { const float posYfactor = (float) ( windowsPos.y + y * 4.0f ) / (float) m_windowSize.y; - bgColor[y] = (SFVEC3F) m_boardAdapter.m_BgColorTop * SFVEC3F( posYfactor ) - + (SFVEC3F) m_boardAdapter.m_BgColorBot - * ( SFVEC3F( 1.0f ) - SFVEC3F( posYfactor ) ); + bgColor[y] = bgTopColor * SFVEC4F( posYfactor ) + + bgBotColor * ( SFVEC4F( 1.0f ) - SFVEC4F( posYfactor ) ); } - COLOR_RGB hitColorShading[RAYPACKET_RAYS_PER_PACKET]; + COLOR_RGBA hitColorShading[RAYPACKET_RAYS_PER_PACKET]; for( unsigned int i = 0; i < RAYPACKET_RAYS_PER_PACKET; ++i ) { - const SFVEC3F bhColorY = bgColor[i / RAYPACKET_DIM]; + const SFVEC4F bhColorY = bgColor[i / RAYPACKET_DIM]; if( hitPacket[i].m_hitresult == true ) { - const SFVEC3F hitColor = shadeHit( bhColorY, blockPacket.m_ray[i], + const SFVEC4F hitColor = shadeHit( bhColorY, blockPacket.m_ray[i], hitPacket[i].m_HitInfo, false, 0, false ); - hitColorShading[i] = COLOR_RGB( hitColor ); + hitColorShading[i] = COLOR_RGBA( hitColor ); } else hitColorShading[i] = bhColorY; } - COLOR_RGB cLRB_old[(RAYPACKET_DIM - 1)]; + COLOR_RGBA cLRB_old[(RAYPACKET_DIM - 1)]; for( unsigned int y = 0; y < (RAYPACKET_DIM - 1); ++y ) { - const SFVEC3F bgColorY = bgColor[y]; - const COLOR_RGB bgColorYRGB = COLOR_RGB( bgColorY ); + const SFVEC4F bgColorY = bgColor[y]; + const COLOR_RGBA bgColorYRGB = COLOR_RGBA( bgColorY ); // This stores cRTB from the last block to be reused next time in a cLTB pixel - COLOR_RGB cRTB_old; + COLOR_RGBA cRTB_old; //RAY cRTB_ray; //HITINFO cRTB_hitInfo; @@ -1040,13 +1061,13 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO ) const unsigned int iRB = ( ( x + 1 ) + RAYPACKET_DIM * ( y + 1 ) ); // !TODO: skip when there are no hits - const COLOR_RGB& cLT = hitColorShading[ iLT ]; - const COLOR_RGB& cRT = hitColorShading[ iRT ]; - const COLOR_RGB& cLB = hitColorShading[ iLB ]; - const COLOR_RGB& cRB = hitColorShading[ iRB ]; + const COLOR_RGBA& cLT = hitColorShading[ iLT ]; + const COLOR_RGBA& cRT = hitColorShading[ iRT ]; + const COLOR_RGBA& cLB = hitColorShading[ iLB ]; + const COLOR_RGBA& cRB = hitColorShading[ iRB ]; // Trace and shade cC - COLOR_RGB cC = bgColorYRGB; + COLOR_RGBA cC = bgColorYRGB; const SFVEC3F& oriLT = blockPacket.m_ray[ iLT ].m_Origin; const SFVEC3F& oriRB = blockPacket.m_ray[ iRB ].m_Origin; @@ -1098,7 +1119,7 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO ) if( hittedC ) { - cC = COLOR_RGB( shadeHit( bgColorY, centerRay, centerHitInfo, + cC = COLOR_RGBA( shadeHit( bgColorY, centerRay, centerHitInfo, false, 0, false ) ); } else @@ -1107,13 +1128,13 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO ) hittedC = m_accelerator->Intersect( centerRay, centerHitInfo ); if( hittedC ) - cC = COLOR_RGB( shadeHit( bgColorY, centerRay, centerHitInfo, + cC = COLOR_RGBA( shadeHit( bgColorY, centerRay, centerHitInfo, false, 0, false ) ); } } // Trace and shade cLRT - COLOR_RGB cLRT = bgColorYRGB; + COLOR_RGBA cLRT = bgColorYRGB; const SFVEC3F& oriRT = blockPacket.m_ray[ iRT ].m_Origin; const SFVEC3F& dirRT = blockPacket.m_ray[ iRT ].m_Dir; @@ -1139,7 +1160,7 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO ) glm::normalize( ( hitPacket[ iLT ].m_HitInfo.m_HitNormal + hitPacket[ iRT ].m_HitInfo.m_HitNormal ) * 0.5f ); - cLRT = COLOR_RGB( shadeHit( bgColorY, rayLRT, hitInfoLRT, false, + cLRT = COLOR_RGBA( shadeHit( bgColorY, rayLRT, hitInfoLRT, false, 0, false ) ); cLRT = BlendColor( cLRT, BlendColor( cLT, cRT ) ); } @@ -1164,14 +1185,14 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO ) nodeRT ); if( hittedLRT ) - cLRT = COLOR_RGB( shadeHit( bgColorY, rayLRT, hitInfoLRT, + cLRT = COLOR_RGBA( shadeHit( bgColorY, rayLRT, hitInfoLRT, false, 0, false ) ); else { hitInfoLRT.m_tHit = std::numeric_limits::infinity(); if( m_accelerator->Intersect( rayLRT,hitInfoLRT ) ) - cLRT = COLOR_RGB( shadeHit( bgColorY, rayLRT, + cLRT = COLOR_RGBA( shadeHit( bgColorY, rayLRT, hitInfoLRT, false, 0, false ) ); } @@ -1184,7 +1205,7 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO ) } // Trace and shade cLTB - COLOR_RGB cLTB = bgColorYRGB; + COLOR_RGBA cLTB = bgColorYRGB; if( x == 0 ) { @@ -1209,7 +1230,7 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO ) hitInfoLTB.m_HitNormal = glm::normalize( ( hitPacket[ iLT ].m_HitInfo.m_HitNormal + hitPacket[ iLB ].m_HitInfo.m_HitNormal ) * 0.5f ); - cLTB = COLOR_RGB( shadeHit( bgColorY, rayLTB, hitInfoLTB, false, + cLTB = COLOR_RGBA( shadeHit( bgColorY, rayLTB, hitInfoLTB, false, 0, false ) ); cLTB = BlendColor( cLTB, BlendColor( cLT, cLB) ); } @@ -1234,14 +1255,14 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO ) nodeLB ); if( hittedLTB ) - cLTB = COLOR_RGB( shadeHit( bgColorY, rayLTB, hitInfoLTB, + cLTB = COLOR_RGBA( shadeHit( bgColorY, rayLTB, hitInfoLTB, false, 0, false ) ); else { hitInfoLTB.m_tHit = std::numeric_limits::infinity(); if( m_accelerator->Intersect( rayLTB, hitInfoLTB ) ) - cLTB = COLOR_RGB( shadeHit( bgColorY, rayLTB, + cLTB = COLOR_RGBA( shadeHit( bgColorY, rayLTB, hitInfoLTB, false, 0, false ) ); } @@ -1254,7 +1275,7 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO ) } // Trace and shade cRTB - COLOR_RGB cRTB = bgColorYRGB; + COLOR_RGBA cRTB = bgColorYRGB; // Trace the center ray RAY rayRTB; @@ -1277,7 +1298,7 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO ) glm::normalize( ( hitPacket[ iRT ].m_HitInfo.m_HitNormal + hitPacket[ iRB ].m_HitInfo.m_HitNormal ) * 0.5f ); - cRTB = COLOR_RGB( shadeHit( bgColorY, rayRTB, hitInfoRTB, false, 0, + cRTB = COLOR_RGBA( shadeHit( bgColorY, rayRTB, hitInfoRTB, false, 0, false ) ); cRTB = BlendColor( cRTB, BlendColor( cRT, cRB ) ); } @@ -1303,7 +1324,7 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO ) if( hittedRTB ) { - cRTB = COLOR_RGB( shadeHit( bgColorY, rayRTB, hitInfoRTB, + cRTB = COLOR_RGBA( shadeHit( bgColorY, rayRTB, hitInfoRTB, false, 0, false) ); } else @@ -1311,7 +1332,7 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO ) hitInfoRTB.m_tHit = std::numeric_limits::infinity(); if( m_accelerator->Intersect( rayRTB, hitInfoRTB ) ) - cRTB = COLOR_RGB( shadeHit( bgColorY, rayRTB, hitInfoRTB, + cRTB = COLOR_RGBA( shadeHit( bgColorY, rayRTB, hitInfoRTB, false, 0, false ) ); } } @@ -1320,7 +1341,7 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO ) cRTB_old = cRTB; // Trace and shade cLRB - COLOR_RGB cLRB = bgColorYRGB; + COLOR_RGBA cLRB = bgColorYRGB; const SFVEC3F& oriLB = blockPacket.m_ray[ iLB ].m_Origin; const SFVEC3F& dirLB = blockPacket.m_ray[ iLB ].m_Dir; @@ -1346,7 +1367,7 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO ) glm::normalize( ( hitPacket[ iLB ].m_HitInfo.m_HitNormal + hitPacket[ iRB ].m_HitInfo.m_HitNormal ) * 0.5f ); - cLRB = COLOR_RGB( shadeHit( bgColorY, rayLRB, hitInfoLRB, false, 0, + cLRB = COLOR_RGBA( shadeHit( bgColorY, rayLRB, hitInfoLRB, false, 0, false ) ); cLRB = BlendColor( cLRB, BlendColor( cLB, cRB ) ); } @@ -1372,7 +1393,7 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO ) if( hittedLRB ) { - cLRB = COLOR_RGB( shadeHit( bgColorY, rayLRB, hitInfoLRB, + cLRB = COLOR_RGBA( shadeHit( bgColorY, rayLRB, hitInfoLRB, false, 0, false ) ); } else @@ -1380,7 +1401,7 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO ) hitInfoLRB.m_tHit = std::numeric_limits::infinity(); if( m_accelerator->Intersect( rayLRB, hitInfoLRB ) ) - cLRB = COLOR_RGB( shadeHit( bgColorY, rayLRB, hitInfoLRB, + cLRB = COLOR_RGBA( shadeHit( bgColorY, rayLRB, hitInfoLRB, false, 0, false ) ); } } @@ -1389,7 +1410,7 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO ) cLRB_old[x] = cLRB; // Trace and shade cLTC - COLOR_RGB cLTC = BlendColor( cLT , cC ); + COLOR_RGBA cLTC = BlendColor( cLT , cC ); if( hitPacket[ iLT ].m_hitresult || hittedC ) { @@ -1411,12 +1432,12 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO ) hitInfoLTC ); if( hitted ) - cLTC = COLOR_RGB( shadeHit( bgColorY, rayLTC, hitInfoLTC, false, + cLTC = COLOR_RGBA( shadeHit( bgColorY, rayLTC, hitInfoLTC, false, 0, false ) ); } // Trace and shade cRTC - COLOR_RGB cRTC = BlendColor( cRT , cC ); + COLOR_RGBA cRTC = BlendColor( cRT , cC ); if( hitPacket[ iRT ].m_hitresult || hittedC ) { @@ -1437,12 +1458,12 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO ) hitInfoRTC ); if( hitted ) - cRTC = COLOR_RGB( shadeHit( bgColorY, rayRTC, hitInfoRTC, false, + cRTC = COLOR_RGBA( shadeHit( bgColorY, rayRTC, hitInfoRTC, false, 0, false ) ); } // Trace and shade cLBC - COLOR_RGB cLBC = BlendColor( cLB , cC ); + COLOR_RGBA cLBC = BlendColor( cLB , cC ); if( hitPacket[ iLB ].m_hitresult || hittedC ) { @@ -1463,12 +1484,12 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO ) hitInfoLBC ); if( hitted ) - cLBC = COLOR_RGB( shadeHit( bgColorY, rayLBC, hitInfoLBC, false, + cLBC = COLOR_RGBA( shadeHit( bgColorY, rayLBC, hitInfoLBC, false, 0, false ) ); } // Trace and shade cRBC - COLOR_RGB cRBC = BlendColor( cRB , cC ); + COLOR_RGBA cRBC = BlendColor( cRB , cC ); if( hitPacket[ iRB ].m_hitresult || hittedC ) { @@ -1489,7 +1510,7 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO ) hitInfoRBC ); if( hitted ) - cRBC = COLOR_RGB( shadeHit( bgColorY, rayRBC, hitInfoRBC, false, + cRBC = COLOR_RGBA( shadeHit( bgColorY, rayRBC, hitInfoRBC, false, 0, false ) ); } @@ -1537,14 +1558,15 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO ) #define USE_EXPERIMENTAL_SOFT_SHADOWS 1 -SFVEC3F RENDER_3D_RAYTRACE::shadeHit( const SFVEC3F& aBgColor, const RAY& aRay, HITINFO& aHitInfo, +SFVEC4F RENDER_3D_RAYTRACE::shadeHit( const SFVEC4F& aBgColor, const RAY& aRay, HITINFO& aHitInfo, bool aIsInsideObject, unsigned int aRecursiveLevel, bool is_testShadow ) const { const MATERIAL* objMaterial = aHitInfo.pHitObject->GetMaterial(); wxASSERT( objMaterial != nullptr ); - SFVEC3F outColor = objMaterial->GetEmissiveColor() + objMaterial->GetAmbientColor(); + SFVEC4F outColor = + SFVEC4F( objMaterial->GetEmissiveColor() + objMaterial->GetAmbientColor(), 1.0f ); if( aRecursiveLevel > 7 ) return outColor; @@ -1553,7 +1575,8 @@ SFVEC3F RENDER_3D_RAYTRACE::shadeHit( const SFVEC3F& aBgColor, const RAY& aRay, hitPoint += aHitInfo.m_HitNormal * m_boardAdapter.GetNonCopperLayerThickness() * 0.6f; - const SFVEC3F diffuseColorObj = aHitInfo.pHitObject->GetDiffuseColor( aHitInfo ); + const SFVEC4F diffuseColorObj = + SFVEC4F( aHitInfo.pHitObject->GetDiffuseColor( aHitInfo ), 1.0f ); #if USE_EXPERIMENTAL_SOFT_SHADOWS bool is_aa_enabled = m_boardAdapter.m_Cfg->m_Render.raytrace_anti_aliasing && !m_isPreview; @@ -1637,8 +1660,10 @@ SFVEC3F RENDER_3D_RAYTRACE::shadeHit( const SFVEC3F& aBgColor, const RAY& aRay, shadow_att_factor_sum += shadow_att_factor_light; } - outColor += objMaterial->Shade( aRay, aHitInfo, NdotL, diffuseColorObj, vectorToLight, - colorOfLight, shadow_att_factor_light ); + outColor += SFVEC4F( objMaterial->Shade( aRay, aHitInfo, NdotL, diffuseColorObj, + vectorToLight, colorOfLight, + shadow_att_factor_light ), + 1.0 ); } // Only use the headlight for preview @@ -1658,7 +1683,7 @@ SFVEC3F RENDER_3D_RAYTRACE::shadeHit( const SFVEC3F& aBgColor, const RAY& aRay, } // Clamp color to not be brighter than 1.0f - outColor = glm::min( outColor, SFVEC3F( 1.0f ) ); + outColor = glm::min( outColor, SFVEC4F( 1.0f ) ); if( !m_isPreview ) { @@ -1670,7 +1695,7 @@ SFVEC3F RENDER_3D_RAYTRACE::shadeHit( const SFVEC3F& aBgColor, const RAY& aRay, const unsigned int reflection_number_of_samples = objMaterial->GetReflectionRayCount(); - SFVEC3F sum_color = SFVEC3F( 0.0f ); + SFVEC4F sum_color = SFVEC4F( 0.0f ); const SFVEC3F reflectVector = aRay.m_Dir - 2.0f * glm::dot( aRay.m_Dir, aHitInfo.m_HitNormal ) * aHitInfo.m_HitNormal; @@ -1699,17 +1724,19 @@ SFVEC3F RENDER_3D_RAYTRACE::shadeHit( const SFVEC3F& aBgColor, const RAY& aRay, if( m_accelerator->Intersect( reflectedRay, reflectedHit ) ) { - sum_color += ( diffuseColorObj + objMaterial->GetSpecularColor() ) * + SFVEC4F add = ( diffuseColorObj + SFVEC4F( objMaterial->GetSpecularColor(), 1.0f ) ) * shadeHit( aBgColor, reflectedRay, reflectedHit, false, aRecursiveLevel + 1, is_testShadow ) * - SFVEC3F( objMaterial->GetReflection() * + SFVEC4F( objMaterial->GetReflection() * // Falloff factor (1.0f / ( 1.0f + 0.75f * reflectedHit.m_tHit * reflectedHit.m_tHit) ) ); + + sum_color += add; } } - outColor += (sum_color / SFVEC3F( (float)reflection_number_of_samples) ); + outColor += (sum_color / SFVEC4F( (float)reflection_number_of_samples) ); } // Refraction @@ -1738,7 +1765,7 @@ SFVEC3F RENDER_3D_RAYTRACE::shadeHit( const SFVEC3F& aBgColor, const RAY& aRay, const unsigned int refractions_number_of_samples = objMaterial->GetRefractionRayCount(); - SFVEC3F sum_color = SFVEC3F(0.0f); + SFVEC4F sum_color = SFVEC4F( 0.0f ); for( unsigned int i = 0; i < refractions_number_of_samples; ++i ) { @@ -1762,19 +1789,19 @@ SFVEC3F RENDER_3D_RAYTRACE::shadeHit( const SFVEC3F& aBgColor, const RAY& aRay, HITINFO refractedHit; refractedHit.m_tHit = std::numeric_limits::infinity(); - SFVEC3F refractedColor = aBgColor; + SFVEC4F refractedColor = aBgColor; if( m_accelerator->Intersect( refractedRay, refractedHit ) ) { refractedColor = shadeHit( aBgColor, refractedRay, refractedHit, !aIsInsideObject, aRecursiveLevel + 1, false ); - const SFVEC3F absorbance = ( SFVEC3F(1.0f) - diffuseColorObj ) * + const SFVEC4F absorbance = ( SFVEC4F(1.0f) - diffuseColorObj ) * (1.0f - objTransparency ) * objMaterial->GetAbsorvance() * refractedHit.m_tHit; - const SFVEC3F transparency = 1.0f / ( absorbance + 1.0f ); + const SFVEC4F transparency = 1.0f / ( absorbance + 1.0f ); sum_color += refractedColor * transparency; } @@ -1785,7 +1812,7 @@ SFVEC3F RENDER_3D_RAYTRACE::shadeHit( const SFVEC3F& aBgColor, const RAY& aRay, } outColor = outColor * ( 1.0f - objTransparency ) + objTransparency * sum_color - / SFVEC3F( (float) refractions_number_of_samples ); + / SFVEC4F( (float) refractions_number_of_samples ); } else { diff --git a/3d-viewer/3d_rendering/raytracing/render_3d_raytrace.h b/3d-viewer/3d_rendering/raytracing/render_3d_raytrace.h index 3e7396f1e9..92eeac2309 100644 --- a/3d-viewer/3d_rendering/raytracing/render_3d_raytrace.h +++ b/3d-viewer/3d_rendering/raytracing/render_3d_raytrace.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2015-2020 Mario Luzeiro - * Copyright (C) 2015-2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2015-2024 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -87,20 +87,20 @@ private: void postProcessShading( GLubyte* ptrPBO, REPORTER* aStatusReporter ); void postProcessBlurFinish( GLubyte* ptrPBO, REPORTER* aStatusReporter ); void renderBlockTracing( GLubyte* ptrPBO , signed int iBlock ); - void renderFinalColor( GLubyte* ptrPBO, const SFVEC3F& rgbColor, + void renderFinalColor( GLubyte* ptrPBO, const SFVEC4F& rgbColor, bool applyColorSpaceConversion ); - void renderRayPackets( const SFVEC3F* bgColorY, const RAY* aRayPkt, HITINFO_PACKET* aHitPacket, - bool is_testShadow, SFVEC3F* aOutHitColor ); + void renderRayPackets( const SFVEC4F* bgColorY, const RAY* aRayPkt, HITINFO_PACKET* aHitPacket, + bool is_testShadow, SFVEC4F* aOutHitColor ); - void renderAntiAliasPackets( const SFVEC3F* aBgColorY, const HITINFO_PACKET* aHitPck_X0Y0, + void renderAntiAliasPackets( const SFVEC4F* aBgColorY, const HITINFO_PACKET* aHitPck_X0Y0, const HITINFO_PACKET* aHitPck_AA_X1Y1, const RAY* aRayPck, - SFVEC3F* aOutHitColor ); + SFVEC4F* aOutHitColor ); // Materials void setupMaterials(); - SFVEC3F shadeHit( const SFVEC3F& aBgColor, const RAY& aRay, HITINFO& aHitInfo, + SFVEC4F shadeHit( const SFVEC4F& aBgColor, const RAY& aRay, HITINFO& aHitInfo, bool aIsInsideObject, unsigned int aRecursiveLevel, bool is_testShadow ) const; @@ -180,8 +180,8 @@ private: ACCELERATOR_3D* m_accelerator; - SFVEC3F m_backgroundColorTop; - SFVEC3F m_backgroundColorBottom; + SFVEC4F m_backgroundColorTop; + SFVEC4F m_backgroundColorBottom; ///< Used to see if the windows size changed. wxSize m_oldWindowsSize; @@ -218,8 +218,10 @@ private: #ifdef USE_SRGB_SPACE extern SFVEC3F ConvertSRGBToLinear( const SFVEC3F& aSRGBcolor ); +extern SFVEC4F ConvertSRGBAToLinear( const SFVEC4F& aSRGBAcolor ); #else #define ConvertSRGBToLinear( v ) ( v ) +#define ConvertSRGBAToLinear( v ) ( v ) #endif #endif // RENDER_3D_RAYTRACE_H diff --git a/3d-viewer/CMakeLists.txt b/3d-viewer/CMakeLists.txt index 492b69f6ae..ccbda1c591 100644 --- a/3d-viewer/CMakeLists.txt +++ b/3d-viewer/CMakeLists.txt @@ -71,7 +71,7 @@ set(3D-VIEWER_SRCS ${DIR_RAY_3D}/triangle_3d.cpp 3d_rendering/buffers_debug.cpp 3d_rendering/render_3d_base.cpp - 3d_rendering/color_rgb.cpp + 3d_rendering/color_rgba.cpp 3d_rendering/image.cpp 3d_rendering/post_shader.cpp 3d_rendering/post_shader_ssao.cpp