/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2015-2016 Mario Luzeiro * Copyright (C) 1992-2020 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 * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, you may find one here: * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * or you may search the http://www.gnu.org website for the version 2 license, * or you may write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ /** * @file ogl_utils.cpp * @brief implements generic openGL functions that are common to any openGL target */ #include // Must be included first #include "openGL_includes.h" #include "ogl_utils.h" void OGL_GetScreenshot( wxImage& aDstImage ) { struct viewport_params { GLint originX; GLint originY; GLint x; GLint y; } viewport; glGetIntegerv( GL_VIEWPORT, (GLint*) &viewport ); unsigned char* pixelbuffer = (unsigned char*) malloc( viewport.x * viewport.y * 3 ); // Alphabuffer was causing some transparency problems on some systems (Windows) // unsigned char* alphabuffer = (unsigned char*) malloc( viewport.x * viewport.y ); // Call glFinish before screenshot to ensure everything is fully drawn. glFinish(); glPixelStorei( GL_PACK_ALIGNMENT, 1 ); glReadBuffer( GL_BACK_LEFT ); glReadPixels( viewport.originX, viewport.originY, viewport.x, viewport.y, GL_RGB, GL_UNSIGNED_BYTE, pixelbuffer ); // glReadPixels( viewport.originX, viewport.originY, // viewport.x, viewport.y, // GL_ALPHA, GL_UNSIGNED_BYTE, alphabuffer ); // "Sets the image data without performing checks. // The data given must have the size (width*height*3) // The data must have been allocated with malloc() // If static_data is false, after this call the pointer to the data is owned // by the wxImage object, that will be responsible for deleting it." aDstImage.SetData( pixelbuffer, viewport.x, viewport.y, false ); //aDstImage.SetAlpha( alphabuffer, false ); aDstImage = aDstImage.Mirror( false ); } GLuint OGL_LoadTexture( const CIMAGE& aImage ) { unsigned char* rgbaBuffer = (unsigned char*) malloc( aImage.GetWidth() * aImage.GetHeight() * 4 ); unsigned char* dst = rgbaBuffer; const unsigned char* ori = aImage.GetBuffer(); for( unsigned int i = 0; i < ( aImage.GetWidth() * aImage.GetHeight() ); ++i ) { unsigned char v = *ori; ori++; dst[0] = v; dst[1] = v; dst[2] = v; dst[3] = v; dst+= 4; } GLuint texture; glPixelStorei( GL_UNPACK_ALIGNMENT, 4 ); glPixelStorei( GL_PACK_ALIGNMENT, 4 ); glGenTextures( 1, &texture ); glBindTexture( GL_TEXTURE_2D, texture ); /*gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, aImage.GetWidth(), aImage.GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE, rgbaBuffer );*/ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, aImage.GetWidth(), aImage.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, rgbaBuffer ); //glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); glBindTexture( GL_TEXTURE_2D, 0 ); glFlush(); free( rgbaBuffer ); return texture; } void OGL_SetMaterial( const SMATERIAL& aMaterial, float aOpacity, bool aUseSelectedMaterial, SFVEC3F aSelectionColor ) { const SFVEC4F ambient = SFVEC4F( aMaterial.m_Ambient, 1.0f ); // !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( aUseSelectedMaterial?aSelectionColor: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 ); const float shininess = 128.0f * ( (aMaterial.m_Shininess > 1.0f) ? 1.0f : aMaterial.m_Shininess ); glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT, &ambient.r ); glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, &diffuse.r ); glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, &specular.r ); glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, &emissive.r ); glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, shininess ); } 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, 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 ); glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT, &ambient.r ); glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, &diffuse.r ); glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, &specular.r ); glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, &emissive.r ); glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, 0.0f ); } void OGL_DrawBackground( const SFVEC3F& aTopColor, const SFVEC3F& aBotColor ) { glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glDisable( GL_LIGHTING ); glDisable( GL_COLOR_MATERIAL ); glDisable( GL_DEPTH_TEST ); glDisable( GL_TEXTURE_2D ); glDisable( GL_BLEND ); glDisable( GL_ALPHA_TEST ); glBegin( GL_QUADS ); glColor4f( aTopColor.x, aTopColor.y, aTopColor.z, 1.0f ); glVertex2f( -1.0, 1.0 ); // Top left corner glColor4f( aBotColor.x, aBotColor.y, aBotColor.z, 1.0f ); glVertex2f( -1.0,-1.0 ); // bottom left corner glVertex2f( 1.0,-1.0 ); // bottom right corner glColor4f( aTopColor.x, aTopColor.y, aTopColor.z, 1.0f ); glVertex2f( 1.0, 1.0 ); // top right corner glEnd(); } void OGL_ResetTextureStateDefaults() { if( !glActiveTexture || !glClientActiveTexture ) throw std::runtime_error( "The OpenGL context no longer exists: unable to Reset Textures" ); 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, static_cast( &zero.x ) ); }