diff --git a/3d-viewer/3d_model_viewer/c3d_model_viewer.cpp b/3d-viewer/3d_model_viewer/c3d_model_viewer.cpp index e1bb868a0f..03af0beaab 100644 --- a/3d-viewer/3d_model_viewer/c3d_model_viewer.cpp +++ b/3d-viewer/3d_model_viewer/c3d_model_viewer.cpp @@ -313,7 +313,7 @@ void C3D_MODEL_VIEWER::OnPaint( wxPaintEvent &event ) m_ogl_3dmodel->BeginDrawMulti(); m_ogl_3dmodel->Draw_opaque(); - m_ogl_3dmodel->Draw_transparent(); + m_ogl_3dmodel->Draw_transparent( 1.0f ); m_ogl_3dmodel->EndDrawMulti(); diff --git a/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.cpp b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.cpp index ae9fb4ca17..002084e329 100644 --- a/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.cpp +++ b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.cpp @@ -361,27 +361,27 @@ void C3D_RENDER_OGL_LEGACY::set_layer_material( PCB_LAYER_ID aLayerID ) { case B_Mask: m_materials.m_SolderMaskBot.m_Diffuse = get_layer_color( aLayerID ); - OGL_SetMaterial( m_materials.m_SolderMaskBot ); + OGL_SetMaterial( m_materials.m_SolderMaskBot, 1.0f ); break; case F_Mask: m_materials.m_SolderMaskTop.m_Diffuse = get_layer_color( aLayerID ); - OGL_SetMaterial( m_materials.m_SolderMaskTop ); + OGL_SetMaterial( m_materials.m_SolderMaskTop, 1.0f ); break; case B_Paste: case F_Paste: m_materials.m_Paste.m_Diffuse = get_layer_color( aLayerID ); - OGL_SetMaterial( m_materials.m_Paste ); + OGL_SetMaterial( m_materials.m_Paste, 1.0f ); break; case B_SilkS: m_materials.m_SilkSBot.m_Diffuse = get_layer_color( aLayerID ); - OGL_SetMaterial( m_materials.m_SilkSBot ); + OGL_SetMaterial( m_materials.m_SilkSBot, 1.0f ); break; case F_SilkS: m_materials.m_SilkSTop.m_Diffuse = get_layer_color( aLayerID ); - OGL_SetMaterial( m_materials.m_SilkSTop ); + OGL_SetMaterial( m_materials.m_SilkSTop, 1.0f ); break; case B_Adhes: @@ -409,12 +409,12 @@ void C3D_RENDER_OGL_LEGACY::set_layer_material( PCB_LAYER_ID aLayerID ) m_materials.m_Plastic.m_Shininess = 0.078125f * 128.0f; m_materials.m_Plastic.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f ); - OGL_SetMaterial( m_materials.m_Plastic ); + OGL_SetMaterial( m_materials.m_Plastic, 1.0f ); break; default: m_materials.m_Copper.m_Diffuse = get_layer_color( aLayerID ); - OGL_SetMaterial( m_materials.m_Copper ); + OGL_SetMaterial( m_materials.m_Copper, 1.0f ); break; } @@ -589,6 +589,7 @@ bool C3D_RENDER_OGL_LEGACY::Redraw( glClearStencil( 0x00 ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ); + OGL_ResetTextureStateDefaults(); // Draw the background ( rectangle with color gradient) // ///////////////////////////////////////////////////////////////////////// @@ -659,7 +660,7 @@ bool C3D_RENDER_OGL_LEGACY::Redraw( m_ogl_disp_list_board->ApplyScalePosition( -m_boardAdapter.GetEpoxyThickness3DU() / 2.0f, m_boardAdapter.GetEpoxyThickness3DU() ); - OGL_SetMaterial( m_materials.m_EpoxyBoard ); + OGL_SetMaterial( m_materials.m_EpoxyBoard, 1.0f ); m_ogl_disp_list_board->SetItIsTransparent( false ); @@ -688,7 +689,7 @@ bool C3D_RENDER_OGL_LEGACY::Redraw( } else { - OGL_SetMaterial( m_materials.m_GrayMaterial ); + OGL_SetMaterial( m_materials.m_GrayMaterial, 1.0f ); } if( (!( skipRenderVias || skipRenderHoles ) ) && m_ogl_disp_list_via ) @@ -860,6 +861,8 @@ bool C3D_RENDER_OGL_LEGACY::Redraw( // Render 3D Models (Transparent) // ///////////////////////////////////////////////////////////////////////// + // !TODO: this can be optimized. If there are no transparent models (or no opacity), + // then there is no need to make this function call. render_3D_models( false, true ); render_3D_models( true, true ); @@ -1180,8 +1183,8 @@ void C3D_RENDER_OGL_LEGACY::render_3D_module( const MODULE* module, { if( const C_OGL_3DMODEL *modelPtr = cache_i->second ) { - if( ( (!aRenderTransparentOnly) && modelPtr->Have_opaque() ) || - ( aRenderTransparentOnly && modelPtr->Have_transparent() ) ) + if( ( (!aRenderTransparentOnly) && modelPtr->Have_opaque() && (sM.m_Opacity >= 1.0 ) ) || + ( aRenderTransparentOnly && ( modelPtr->Have_transparent() || (sM.m_Opacity < 1.0 ) ) ) ) { glPushMatrix(); @@ -1196,7 +1199,7 @@ void C3D_RENDER_OGL_LEGACY::render_3D_module( const MODULE* module, glMultMatrixf( glm::value_ptr( mtx ) ); if( aRenderTransparentOnly ) - modelPtr->Draw_transparent(); + modelPtr->Draw_transparent( sM.m_Opacity ); else modelPtr->Draw_opaque(); diff --git a/3d-viewer/3d_rendering/3d_render_ogl_legacy/c_ogl_3dmodel.cpp b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c_ogl_3dmodel.cpp index c24ffd1eda..68b12711ba 100644 --- a/3d-viewer/3d_rendering/3d_render_ogl_legacy/c_ogl_3dmodel.cpp +++ b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c_ogl_3dmodel.cpp @@ -391,8 +391,11 @@ void C_OGL_3DMODEL::EndDrawMulti() } -void C_OGL_3DMODEL::Draw( bool aTransparent ) const +void C_OGL_3DMODEL::Draw( bool aTransparent, float aOpacity ) const { + if( aOpacity <= FLT_EPSILON ) + return; + glBindBuffer( GL_ARRAY_BUFFER, m_vertex_buffer ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_index_buffer ); @@ -411,29 +414,61 @@ void C_OGL_3DMODEL::Draw( bool aTransparent ) const glTexCoordPointer( 2, GL_FLOAT, sizeof( VERTEX ), reinterpret_cast( offsetof( VERTEX, m_tex_uv ) ) ); + if( aTransparent ) + { + glEnable( GL_BLEND ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + + if( aOpacity < 1.0f ) + { + glEnable( GL_TEXTURE_2D ); + glActiveTexture( GL_TEXTURE0 ); + + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE ); + glTexEnvf( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE ); + glTexEnvf( GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE ); + + glTexEnvi( GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PRIMARY_COLOR ); + glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR ); + + glTexEnvi( GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PREVIOUS ); + glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR ); + + glTexEnvi( GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PRIMARY_COLOR ); + glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA ); + glTexEnvi( GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_CONSTANT ); + glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_CONSTANT ); + + const SFVEC4F param = SFVEC4F( 1.0f, 1.0f, 1.0f, aOpacity ); + + glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (const float*)¶m.x ); + } + } + // BeginDrawMulti(); for( auto& mat : m_materials ) { - if( mat.IsTransparent() != aTransparent ) - continue; + if( ( mat.IsTransparent() != aTransparent ) && + ( aOpacity >= 1.0f ) ) + continue; - switch( m_material_mode ) - { - case MATERIAL_MODE::NORMAL: - OGL_SetMaterial( mat ); - break; + switch( m_material_mode ) + { + case MATERIAL_MODE::NORMAL: + OGL_SetMaterial( mat, aOpacity ); + break; - case MATERIAL_MODE::DIFFUSE_ONLY: - OGL_SetDiffuseOnlyMaterial( mat.m_Diffuse ); - break; + case MATERIAL_MODE::DIFFUSE_ONLY: + OGL_SetDiffuseOnlyMaterial( mat.m_Diffuse, aOpacity ); + break; - case MATERIAL_MODE::CAD_MODE: - OGL_SetDiffuseOnlyMaterial( MaterialDiffuseToColorCAD( mat.m_Diffuse ) ); - break; + case MATERIAL_MODE::CAD_MODE: + OGL_SetDiffuseOnlyMaterial( MaterialDiffuseToColorCAD( mat.m_Diffuse ), aOpacity ); + break; - default: - break; + default: + break; } glDrawElements( GL_TRIANGLES, mat.m_render_idx_count, m_index_buffer_type, @@ -441,6 +476,16 @@ void C_OGL_3DMODEL::Draw( bool aTransparent ) const } // EndDrawMulti(); + + if( aTransparent ) + { + glDisable( GL_BLEND ); + + if( aOpacity < 1.0f ) + { + OGL_ResetTextureStateDefaults(); + } + } } C_OGL_3DMODEL::~C_OGL_3DMODEL() diff --git a/3d-viewer/3d_rendering/3d_render_ogl_legacy/c_ogl_3dmodel.h b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c_ogl_3dmodel.h index c5c25a2761..413c721bd9 100644 --- a/3d-viewer/3d_rendering/3d_render_ogl_legacy/c_ogl_3dmodel.h +++ b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c_ogl_3dmodel.h @@ -53,12 +53,12 @@ public: /** * @brief Draw_opaque - render the model into the current context */ - void Draw_opaque() const { Draw( false ); } + void Draw_opaque() const { Draw( false, 1.0f ); } /** * @brief Draw_transparent - render the model into the current context */ - void Draw_transparent() const { Draw( true ); } + void Draw_transparent( float aOpacity ) const { Draw( true, aOpacity ); } /** * @brief Have_opaque - return true if have opaque meshs to render @@ -155,7 +155,7 @@ private: VERTEX *aVtxOut, GLuint *aIdxOut, const glm::vec4 &aColor ); - void Draw( bool aTransparent ) const; + void Draw( bool aTransparent, float aOpacity ) const; }; #endif // _C_OGL_3DMODEL_H_ diff --git a/3d-viewer/common_ogl/ogl_utils.cpp b/3d-viewer/common_ogl/ogl_utils.cpp index ff8c0f6df4..edac752db5 100644 --- a/3d-viewer/common_ogl/ogl_utils.cpp +++ b/3d-viewer/common_ogl/ogl_utils.cpp @@ -141,11 +141,15 @@ GLuint OGL_LoadTexture( const CIMAGE &aImage ) } -void OGL_SetMaterial( const SMATERIAL & aMaterial ) +void OGL_SetMaterial( const SMATERIAL & aMaterial, float aOpacity ) { const SFVEC4F ambient = SFVEC4F( aMaterial.m_Ambient, 1.0f ); - const SFVEC4F diffuse = SFVEC4F( aMaterial.m_Diffuse, 1.0f - - aMaterial.m_Transparency ); + + // !TODO: at this moment, diffuse color is added via + // glEnableClientState( GL_COLOR_ARRAY ) so this line may has no effect + // but can be used for optimization + const SFVEC4F diffuse = SFVEC4F( aMaterial.m_Diffuse, + ( 1.0f - aMaterial.m_Transparency ) * aOpacity ); const SFVEC4F specular = SFVEC4F( aMaterial.m_Specular, 1.0f ); const SFVEC4F emissive = SFVEC4F( aMaterial.m_Emissive, 1.0f ); @@ -161,10 +165,10 @@ void OGL_SetMaterial( const SMATERIAL & aMaterial ) } -void OGL_SetDiffuseOnlyMaterial( const SFVEC3F &aMaterialDiffuse ) +void OGL_SetDiffuseOnlyMaterial( const SFVEC3F &aMaterialDiffuse, float aOpacity ) { const SFVEC4F ambient = SFVEC4F( 0.2f, 0.2f, 0.2f, 1.0f ); - const SFVEC4F diffuse = SFVEC4F( aMaterialDiffuse, 1.0f ); + const SFVEC4F diffuse = SFVEC4F( aMaterialDiffuse, aOpacity ); const SFVEC4F specular = SFVEC4F( 0.0f, 0.0f, 0.0f, 1.0f ); const SFVEC4F emissive = SFVEC4F( 0.0f, 0.0f, 0.0f, 1.0f ); @@ -203,3 +207,16 @@ void OGL_DrawBackground( const SFVEC3F &aTopColor, const SFVEC3F &aBotColor ) glVertex2f( 1.0, 1.0 ); // top right corner glEnd(); } + +void OGL_ResetTextureStateDefaults() +{ + glActiveTexture( GL_TEXTURE0 ); + glBindTexture( GL_TEXTURE_2D, 0 ); + glClientActiveTexture( GL_TEXTURE0 ); + glDisable( GL_TEXTURE_2D ); + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + + const SFVEC4F zero = SFVEC4F( 0.0f ); + + glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (const float*)&zero.x ); +} diff --git a/3d-viewer/common_ogl/ogl_utils.h b/3d-viewer/common_ogl/ogl_utils.h index 13c72ac31d..4c814890c5 100644 --- a/3d-viewer/common_ogl/ogl_utils.h +++ b/3d-viewer/common_ogl/ogl_utils.h @@ -38,8 +38,9 @@ /** * @brief OGL_SetMaterial - Set OpenGL materials * @param aMaterial: a material structure with parameters to set + * @param aOpacity: main model opacity 0.0 full transparente, 1.0 full opaque */ -void OGL_SetMaterial( const SMATERIAL & aMaterial ); +void OGL_SetMaterial( const SMATERIAL & aMaterial, float aOpacity ); /** @@ -47,7 +48,7 @@ void OGL_SetMaterial( const SMATERIAL & aMaterial ); * parameters with default values * @param aMaterialDiffuse: the diffese color to assign to material properties */ -void OGL_SetDiffuseOnlyMaterial( const SFVEC3F &aMaterialDiffuse ); +void OGL_SetDiffuseOnlyMaterial( const SFVEC3F &aMaterialDiffuse, float aOpacity ); /** @@ -72,4 +73,11 @@ void OGL_GetScreenshot( wxImage &aDstImage ); */ void OGL_DrawBackground( const SFVEC3F &aTopColor, const SFVEC3F &aBotColor ); + +/** + * @brief OGL_ResetTextureStateDefaults - resets to default state the texture settings + */ +void OGL_ResetTextureStateDefaults(); + + #endif // OGL_UTILS_H_