/* * 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 #include // Must be included first #include "openGL_includes.h" #include "ogl_utils.h" void OglGetScreenshot( 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 * 4 ); // 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_RGBA, GL_UNSIGNED_BYTE, pixelbuffer ); unsigned char* rgbBuffer = (unsigned char*) malloc( viewport.x * viewport.y * 3 ); unsigned char* alphaBuffer = (unsigned char*) malloc( viewport.x * viewport.y ); unsigned char* rgbaPtr = pixelbuffer; unsigned char* rgbPtr = rgbBuffer; unsigned char* alphaPtr = alphaBuffer; for( int y = 0; y < viewport.y; y++ ) { for( int x = 0; x < viewport.x; x++ ) { rgbPtr[0] = rgbaPtr[0]; rgbPtr[1] = rgbaPtr[1]; rgbPtr[2] = rgbaPtr[2]; alphaPtr[0] = rgbaPtr[3]; rgbaPtr += 4; rgbPtr += 3; alphaPtr += 1; } } // "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( rgbBuffer, viewport.x, viewport.y, false ); aDstImage.SetAlpha( alphaBuffer, false ); free( pixelbuffer ); aDstImage = aDstImage.Mirror( false ); } GLuint OglLoadTexture( const IMAGE& 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] = 255; dst[1] = 255; dst[2] = 255; 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 ); 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 ); 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 OglSetMaterial( 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 OglSetDiffuseMaterial( const SFVEC3F &aMaterialDiffuse, float aOpacity, bool aUseSelectedMaterial, SFVEC3F aSelectionColor ) { const SFVEC4F ambient = SFVEC4F( 0.2f, 0.2f, 0.2f, 1.0f ); const SFVEC4F diffuse = SFVEC4F( aUseSelectedMaterial ? aSelectionColor : 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 OglDrawBackground( const SFVEC4F& aTopColor, const SFVEC4F& 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.r, aTopColor.g, aTopColor.b, aTopColor.a ); glVertex2f( -1.0, 1.0 ); // Top left corner glColor4f( aBotColor.r, aBotColor.g, aBotColor.b, aBotColor.a ); glVertex2f( -1.0,-1.0 ); // bottom left corner glVertex2f( 1.0,-1.0 ); // bottom right corner glColor4f( aTopColor.r, aTopColor.g, aTopColor.b, aTopColor.a); glVertex2f( 1.0, 1.0 ); // top right corner glEnd(); } void OglResetTextureState() { 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 ) ); }