#include "MGCLStdAfx.h" #include #include #include #include "mgGL/glslprogram.h" #include "mgGL/Color.h" #include "mgGL/StaticGLAttrib.h" namespace{GLenum glErr;}; mgGLSLProgram::mgGLSLProgram():m_handle(0), m_linked(false){;} mgGLSLProgram::~mgGLSLProgram(){ freeProgram(); } ///Delete this program and initialize this. void mgGLSLProgram::freeProgram(){ if(m_handle) glDeleteProgram(m_handle); m_handle=0; m_linked=false; m_logString=""; } bool mgGLSLProgram::compileShaderFromFile( const char* fileName, GLSLShaderType type ){ if( !fileExists(fileName) ){ m_logString = "File not found."; return false; } if( m_handle <= 0 ){ m_handle = glCreateProgram(); if( m_handle == 0) { m_logString = "Unable to create shader program."; return false; } } std::ifstream inFile( fileName, std::ios::in ); if( !inFile ) { return false; } std::ostringstream code; while( inFile.good() ) { int c = inFile.get(); if( ! inFile.eof() ) code << (char) c; } inFile.close(); return compileShaderFromString(code.str(), type); } bool mgGLSLProgram::compileShaderFromString( const std::string& source, GLSLShaderType type ){ if( m_handle <= 0 ) { m_handle = glCreateProgram(); if( m_handle == 0) { m_logString = "Unable to create shader program."; return false; } } GLuint shaderHandle = 0; switch( type ) { case VERTEX: shaderHandle = glCreateShader(GL_VERTEX_SHADER); break; case FRAGMENT: shaderHandle = glCreateShader(GL_FRAGMENT_SHADER); break; case GEOMETRY: shaderHandle = glCreateShader(GL_GEOMETRY_SHADER); break; case TESS_CONTROL: shaderHandle = glCreateShader(GL_TESS_CONTROL_SHADER); break; case TESS_EVALUATION: shaderHandle = glCreateShader(GL_TESS_EVALUATION_SHADER); break; default: return false; } const char* c_code = source.c_str(); glShaderSource( shaderHandle, 1, &c_code, NULL ); // Compile the shader glCompileShader(shaderHandle ); // Check for errors int result; glGetShaderiv( shaderHandle, GL_COMPILE_STATUS, &result ); if( GL_FALSE == result ) { // Compile failed, store log and return false int length = 0; m_logString = ""; glGetShaderiv(shaderHandle, GL_INFO_LOG_LENGTH, &length ); if( length > 0 ) { char* c_log = new char[length]; int written = 0; glGetShaderInfoLog(shaderHandle, length, &written, c_log); m_logString = c_log; delete[] c_log; } return false; }else{ // Compile succeeded, attach shader and return true glAttachShader(m_handle, shaderHandle); return true; } } bool mgGLSLProgram::link(){ if( m_linked ) return true; if( m_handle <= 0 ) return false; glLinkProgram(m_handle); int status = 0; glGetProgramiv( m_handle, GL_LINK_STATUS, &status); if( GL_FALSE == status ) { // Store log and return false int length = 0; m_logString = ""; glGetProgramiv(m_handle, GL_INFO_LOG_LENGTH, &length ); if( length > 0 ) { char* c_log = new char[length]; int written = 0; glGetProgramInfoLog(m_handle, length, &written, c_log); m_logString = c_log; delete[] c_log; } return false; }else{ build_attribLocations(); build_attribLocationsLight(); m_linked = true; return m_linked; } } void DefaultLightsSetup(); void mgGLSLProgram::use(){ if( m_handle <= 0 || (! m_linked) ) return; glUseProgram( m_handle ); setCurrentGLSLProgram(this); // Set default lighting. DefaultLightsSetup(); } void mgGLSLProgram::setCurrentGLSLProgram(mgGLSLProgram* glsl){ m_CurrrentGLSL=glsl; } mgGLSLProgram* mgGLSLProgram::getCurrentGLSLProgram(){ return m_CurrrentGLSL; } std::string& mgGLSLProgram::log(){return m_logString;} int mgGLSLProgram::getHandle(){return m_handle;} bool mgGLSLProgram::isLinked(){return m_linked;} void mgGLSLProgram::bindAttribLocation( GLuint location, const char* name){ glBindAttribLocation(m_handle, location, name); } void mgGLSLProgram::bindFragDataLocation( GLuint location, const char* name ){ glBindFragDataLocation(m_handle, location, name); } ///in vec3 vPositionのlocationを求める。 int mgGLSLProgram::getvPositionLocation()const{ static char* name ={"vPosition"}; int loc = getAttribLocation(name); assert(loc>=0); return loc; } ///in vec4 vColorのlocationを求める。 int mgGLSLProgram::getvColorLocation()const{ static char* name ={"vColor"}; int loc = getAttribLocation(name); assert(loc>=0); return loc; } ///in vec3 vNormalのlocationを求める。 int mgGLSLProgram::getvNormalLocation()const{ static char* name ={"vNormal"}; int loc = getAttribLocation(name); //assert(loc>=0); return loc; } ///in vec2 vTextureのlocationを求める。 int mgGLSLProgram::getvTextureCoordLocation()const{ static char* name ={"vTextureCoord"}; int loc = getAttribLocation(name); //assert(loc>=0); return loc; } void mgGLSLProgram::setUniform( GLint loc, float x, float y, float z){ //ASSERT(loc>=0); glUniform3f(loc,x,y,z); } void mgGLSLProgram::setUniform( GLint loc, const glm::vec3 & v){ //ASSERT(loc>=0); glUniform3f(loc,v.x,v.y,v.z); } void mgGLSLProgram::setUniform( GLint loc, const glm::vec4 & v){ //ASSERT(loc>=0); glUniform4f(loc,v.x,v.y,v.z,v.w); } void mgGLSLProgram::setUniform( GLint loc, const glm::mat4 & m){ //ASSERT(loc>=0); glUniformMatrix4fv(loc, 1, GL_FALSE, &m[0][0]); } void mgGLSLProgram::setUniform( GLint loc, const glm::mat3 & m){ //ASSERT(loc>=0); glUniformMatrix3fv(loc, 1, GL_FALSE, &m[0][0]); } void mgGLSLProgram::setUniform( GLint loc, float val ){ //ASSERT(loc>=0); glUniform1f(loc, val); } void mgGLSLProgram::setUniform( GLint loc, int val ){ //ASSERT(loc>=0); glUniform1i(loc, val); } void mgGLSLProgram::setUniform( GLint loc, bool val ){ //ASSERT(loc>=0); glUniform1i(loc, val); } void mgGLSLProgram::printActiveUniforms(){ GLint nUniforms, size, location, maxLen; GLchar* name; GLsizei written; GLenum type; glGetProgramiv( m_handle, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLen); glGetProgramiv( m_handle, GL_ACTIVE_UNIFORMS, &nUniforms); name = (GLchar*) malloc( maxLen ); COUT<<"Active uniforms, Name:Index"<=0 && lightNo=0 && lightNo=0 && lightNo=0 && lightNo=0 && lightNo=0 && lightNo=0 && lightNo=0 && lightNo(userParam); if(stream!=NULL){ std::ostream& out = *stream; out<<"Severity:"; if(severity == GL_DEBUG_SEVERITY_HIGH_ARB) out<<"High"; else if(severity == GL_DEBUG_SEVERITY_MEDIUM_ARB) out<<"Medium"; else if(severity == GL_DEBUG_SEVERITY_LOW_ARB) out<<"Low"; out<<"\tType (DEBUG_TYPE):"; if(type == GL_DEBUG_TYPE_ERROR_ARB) out<<"ERROR"; else if(type == GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB) out <<"DEPRECATED_BEHAVIOR"; else if(type == GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB) out <<"UNDEFINED_BEHAVIOR"; else if(type == GL_DEBUG_TYPE_PORTABILITY_ARB) out <<"PORTABILITY "; else if(type == GL_DEBUG_TYPE_PERFORMANCE_ARB) out <<"PERFORMANCE"; else if(type == GL_DEBUG_TYPE_OTHER_ARB) out <<"OTHER"; out<< "\tSource:"; if(source == GL_DEBUG_SOURCE_API_ARB) out<<"GL_DEBUG_SOURCE_API_ARB"; else if(source == GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB) out<<"GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB"; else if(source == GL_DEBUG_SOURCE_SHADER_COMPILER_ARB) out<<"GL_DEBUG_SOURCE_SHADER_COMPILER_ARB"; else if(source == GL_DEBUG_SOURCE_THIRD_PARTY_ARB) out<<"GL_DEBUG_SOURCE_THIRD_PARTY_ARB"; else if(source == GL_DEBUG_SOURCE_APPLICATION_ARB) out<<"GL_DEBUG_SOURCE_APPLICATION_ARB"; else if(source == GL_DEBUG_SOURCE_OTHER_ARB) out<<"GL_DEBUG_SOURCE_OTHER_ARB"; else out<< source; out<0:Light is enabled. ){ if(mode<0) return; ASSERT(mgGLSLProgram::getCurrentGLSLProgram()!=NULL); mgGLSLProgram* pGLSL = mgGLSLProgram::getCurrentGLSLProgram(); ASSERT(pGLSL->isLinked()); mgGLSL::ShadeMode shadeMode = (mode) ? mgGLSL::Shading:mgGLSL::NoShading; pGLSL->setUniform(mgGLSLProgram::ShaderMode, shadeMode); mgStaticGLAttrib& cattr=mgGLSL::getCurrentStaticGLAttrib(); cattr.setLightMode(mode); } bool mgGLSL::LightEnabled(){ ASSERT(mgGLSLProgram::getCurrentGLSLProgram()!=NULL); mgGLSLProgram* pGLSL = mgGLSLProgram::getCurrentGLSLProgram(); ASSERT(pGLSL->isLinked()); return pGLSL->LightEnabled(); } void DefaultLightsSetup(){ mgGLSLProgram* pGLSL = mgGLSLProgram::getCurrentGLSLProgram(); // 両面描画 pGLSL->setUniform(mgGLSLProgram::LightTwoSides, true); // ForceLightモードをFALSEに。有効なライトがない場合は、 // Light-OFF状態で描画するように変更。Fugenの場合はTRUEとするところ。 pGLSL->setUniform(mgGLSLProgram::ForceLight, true); } void mgGLSL::execStaticColorAttrib( const float* colr ){ int vColorLoc=mgGLSLProgram::vColor; glDisableVertexAttribArray(vColorLoc); glErr=glGetError(); glVertexAttribPointer(vColorLoc,4,GL_FLOAT,GL_FALSE,0,0); glVertexAttrib4fv(vColorLoc,colr); mgStaticGLAttrib& cattr=mgGLSL::getCurrentStaticGLAttrib(); cattr.setColor(colr); } void mgGLSL::execStaticColorAttrib( const MGColor& color ){ if(color.defined()){ mgGLSL::execStaticColorAttrib(color.color()); } } void mgGLSL::execStaticLineWidth(float lineWidth){ if(lineWidth<=0.) return; glLineWidth(lineWidth); mgStaticGLAttrib& cattr=mgGLSL::getCurrentStaticGLAttrib(); cattr.setLineWidth(lineWidth); } ///Line stipple属性をセットする。 ///When factor=0 is input, line pattern is disabled. This means the line is solid. ///When factor<0, the stipple attribute is undefined. This means the attribute ///is defined by the environment. ///When factor<=0, pattern is unnecessary. void mgGLSL::execStaticLineStipple(short int factor, GLuint pattern){ if(factor<0) return; if(factor>0){ glEnable(GL_LINE_STIPPLE); glLineStipple((GLint)factor,pattern); }else glDisable(GL_LINE_STIPPLE); mgStaticGLAttrib& cattr=mgGLSL::getCurrentStaticGLAttrib(); cattr.setLineStipple(factor,pattern); } void mgGLSL::initializeStaticGLAttribStack(){ std::stack& attribs=mgGLSL::getStaticGLAttribStack(); if(attribs.empty()){ attribs.push(mgStaticGLAttrib()); } } std::stack& mgGLSL::getStaticGLAttribStack(){ static std::stack m_attribStack; return m_attribStack; } mgStaticGLAttrib& mgGLSL::getCurrentStaticGLAttrib(){ std::stack& attribs=mgGLSL::getStaticGLAttribStack(); return attribs.top(); } void mgGLSL::pushStaticGLAttrib(){ mgStaticGLAttrib& cattriv=mgGLSL::getCurrentStaticGLAttrib(); std::stack& attribs=mgGLSL::getStaticGLAttribStack(); attribs.push(cattriv); } void mgGLSL::popStaticGLAttrib(){ std::stack& attribs=mgGLSL::getStaticGLAttribStack(); if(attribs.size()>1) attribs.pop(); mgStaticGLAttrib& attrib=attribs.top(); mgGLSL::execStaticGLAttrib(attrib); } void mgGLSL::execStaticGLAttrib(const mgStaticGLAttrib& attrib){ mgGLSL::execStaticColorAttrib(attrib.color()); mgGLSL::execStaticLineWidth(attrib.getLineWidth()); short int factor; GLushort pattern; attrib.getLineStipple(factor, pattern); mgGLSL::execStaticLineStipple(factor, pattern); mgGLSL::execLightMode(attrib.getLightMode()); } void mgGLSLProgram:: setFuncType(mgGLSL::FuncType type) { // subroutine uniformに変更よてい GLint loc = getUniformLocation("funcType"); setUniform(loc, type); } int mgGLSLProgram:: getFuncType() { GLint loc = getUniformLocation("funcType"); GLint funcType; glGetUniformiv(m_handle, loc, &funcType); return funcType; } void printMatrix(glm::mat4& mat){ for(int i = 0; i<4;++i){ COUT<<"|"; for(int ii = 0; ii<4;++ii){ COUT <getFuncType(); m_pGLSL->setFuncType((mgGLSL::FuncType)type); } mgFuncTypeSwitcher::~mgFuncTypeSwitcher(){ m_pGLSL->setFuncType((mgGLSL::FuncType)m_orgFuncType); }