diff --git a/code/nel/include/nel/3d/dynamic_material.h b/code/nel/include/nel/3d/dynamic_material.h index a24516f25..aba5b8bdf 100644 --- a/code/nel/include/nel/3d/dynamic_material.h +++ b/code/nel/include/nel/3d/dynamic_material.h @@ -96,7 +96,7 @@ namespace NL3D SRenderPass* getPass( const std::string &name ); SRenderPass* getPass( uint32 i ); - uint32 count(){ return passes.size(); } + uint32 getPassCount(){ return passes.size(); } void getPassList( std::vector< std::string > &l ); private: diff --git a/code/nel/src/3d/driver/OpenGL3/driver_opengl.cpp b/code/nel/src/3d/driver/OpenGL3/driver_opengl.cpp index 7a45d7fb1..70f16a878 100644 --- a/code/nel/src/3d/driver/OpenGL3/driver_opengl.cpp +++ b/code/nel/src/3d/driver/OpenGL3/driver_opengl.cpp @@ -27,6 +27,8 @@ #include "nel/3d/vertex_buffer.h" #include "nel/3d/light.h" #include "nel/3d/index_buffer.h" +#include "nel/3d/usr_shader_manager.h" +#include "nel/3d/usr_shader_loader.h" #include "nel/misc/rect.h" #include "nel/misc/di_event_emitter.h" #include "nel/misc/mouse_device.h" @@ -333,8 +335,19 @@ CDriverGL3::CDriverGL3() _TextureTargetCubeFace = 0; _TextureTargetUpload = false; +#ifdef GLSL currentProgram = NULL; + dynMatProgram = NULL; + shaderGenerator = new CGLSLShaderGenerator(); + usrShaderManager = new CUsrShaderManager(); + + CUsrShaderLoader loader; + loader.setManager( usrShaderManager ); + loader.loadShaders( "./shaders" ); + +#endif + } // *************************************************************************** @@ -342,12 +355,20 @@ CDriverGL3::~CDriverGL3() { H_AUTO_OGL(CDriverGL3_CDriverGLDtor) + release(); + +#ifdef GLSL currentProgram = NULL; - release(); + if( dynMatProgram != NULL ) + delete dynMatProgram; + dynMatProgram = NULL; delete shaderGenerator; shaderGenerator = NULL; + delete usrShaderManager; + usrShaderManager = NULL; +#endif #if defined(NL_OS_MAC) [_autoreleasePool release]; @@ -2510,6 +2531,15 @@ void CDriverGL3::endDialogMode() { } +// *************************************************************************** +void CDriverGL3::reloadUserShaders() +{ + usrShaderManager->clear(); + NL3D::CUsrShaderLoader loader; + loader.setManager( usrShaderManager ); + loader.loadShaders( "./shaders" ); +} + // *************************************************************************** void displayGLError(GLenum error) { diff --git a/code/nel/src/3d/driver/OpenGL3/driver_opengl.h b/code/nel/src/3d/driver/OpenGL3/driver_opengl.h index b6d2c5183..e5fe91d75 100644 --- a/code/nel/src/3d/driver/OpenGL3/driver_opengl.h +++ b/code/nel/src/3d/driver/OpenGL3/driver_opengl.h @@ -279,9 +279,10 @@ public: void setupIndexBuffer(CIndexBuffer &vb); }; - +#ifdef GLSL class CGLSLShaderGenerator; - +class CUsrShaderManager; +#endif // *************************************************************************** class CDriverGL3 : public IDriver @@ -381,8 +382,8 @@ public: virtual bool setupMaterial(CMaterial& mat); void generateShaderDesc(CShaderDesc &desc, CMaterial &mat); bool setupProgram(CMaterial& mat); + bool setupDynMatProgram(CMaterial& mat, uint pass); void setupUniforms(CMaterial& mat); - void releaseProgram(); virtual void startSpecularBatch(); virtual void endSpecularBatch(); @@ -1067,11 +1068,13 @@ private: /// init multipass for _CurrentMaterial. return number of pass required to render this material. sint beginMultiPass(); /// active the ith pass of this material. - void setupPass(uint pass); + bool setupPass(uint pass); /// end multipass for this material. void endMultiPass(); // @} + bool setupDynMatPass( uint pass ); + /// LastVB for UV setup. CVertexBufferInfo _LastVB; CIndexBufferInfo _LastIB; @@ -1368,9 +1371,13 @@ private: private: +#ifdef GLSL CGLSLShaderGenerator *shaderGenerator; - + CUsrShaderManager *usrShaderManager; + IProgramObject *currentProgram; + IProgramObject *dynMatProgram; +#endif bool setupARBVertexProgram (const CVPParser::TProgram &parsedProgram, GLuint id, bool &specularWritten); @@ -1460,6 +1467,10 @@ private: private: CShaderCache shaderCache; + +public: + void reloadUserShaders(); + }; // *************************************************************************** diff --git a/code/nel/src/3d/driver/OpenGL3/driver_opengl_material.cpp b/code/nel/src/3d/driver/OpenGL3/driver_opengl_material.cpp index 14efeb284..ae407fee7 100644 --- a/code/nel/src/3d/driver/OpenGL3/driver_opengl_material.cpp +++ b/code/nel/src/3d/driver/OpenGL3/driver_opengl_material.cpp @@ -21,6 +21,7 @@ #include "nel/3d/texture_bump.h" #include "nel/3d/material.h" #include "nel/3d/i_program_object.h" +#include "nel/3d/dynamic_material.h" namespace NL3D { @@ -234,6 +235,17 @@ CMaterial::TShader CDriverGL3::getSupportedShader(CMaterial::TShader shader) bool CDriverGL3::setupMaterial(CMaterial& mat) { H_AUTO_OGL(CDriverGL3_setupMaterial) + +#ifdef GLSL + + if( mat.getDynMat() != NULL ) + { + _CurrentMaterial = &mat; + return true; + } + +#endif + CShaderGL3* pShader; GLenum glenum = GL_ZERO; uint32 touched = mat.getTouched(); @@ -497,6 +509,12 @@ bool CDriverGL3::setupMaterial(CMaterial& mat) sint CDriverGL3::beginMultiPass() { H_AUTO_OGL(CDriverGL3_beginMultiPass) + +#ifdef GLSL + if( _CurrentMaterial->getDynMat() != NULL ) + return _CurrentMaterial->getDynMat()->getPassCount(); +#endif + // Depending on material type and hardware, return number of pass required to draw this material. switch(_CurrentMaterialSupportedShader) { @@ -521,9 +539,16 @@ sint CDriverGL3::beginMultiPass() } // *************************************************************************** -void CDriverGL3::setupPass(uint pass) +bool CDriverGL3::setupPass(uint pass) { H_AUTO_OGL(CDriverGL3_setupPass) + +#ifdef GLSL + if( _CurrentMaterial->getDynMat() != NULL ) + return setupDynMatPass( pass ); + +#endif + switch(_CurrentMaterialSupportedShader) { case CMaterial::Normal: @@ -550,17 +575,21 @@ void CDriverGL3::setupPass(uint pass) case CMaterial::Cloud: setupCloudPass (pass); break; - - // All others materials do not require multi pass. - default: return; } + return true; } // *************************************************************************** void CDriverGL3::endMultiPass() { H_AUTO_OGL(CDriverGL3_endMultiPass) + +#ifdef GLSL + if( _CurrentMaterial->getDynMat() != NULL ) + return; +#endif + switch(_CurrentMaterialSupportedShader) { case CMaterial::LightMap: @@ -589,6 +618,77 @@ void CDriverGL3::endMultiPass() } } +bool CDriverGL3::setupDynMatPass( uint pass ) +{ +#ifdef GLSL + + if( !setupDynMatProgram( *_CurrentMaterial, pass ) ) + return false; + + CDynMaterial *m = _CurrentMaterial->getDynMat(); + SRenderPass *p = m->getPass( pass ); + + for( uint32 i = 0; i < p->count(); i++ ) + { + const SDynMaterialProp *prop = p->getProperty( i ); + int loc = nglGetUniformLocation( currentProgram->getProgramId(), prop->prop.c_str() ); + if( loc == -1 ) + continue; + + switch( prop->type ) + { + case SDynMaterialProp::Float: + setUniform1f( loc, prop->value.toFloat() ); + break; + + case SDynMaterialProp::Int: + setUniform1i( loc, prop->value.toInt() ); + break; + + case SDynMaterialProp::Uint: + setUniform1u( loc, prop->value.toUInt() ); + break; + + case SDynMaterialProp::Color: + case SDynMaterialProp::Vector4: + float v[ 4 ]; + prop->value.getVector4( v ); + setUniform4f( loc, v[ 0 ], v[ 1 ], v[ 2 ], v[ 3 ] ); + break; + + case SDynMaterialProp::Matrix4: + float m[ 16 ]; + prop->value.getMatrix4( m ); + setUniformMatrix4fv( loc, 1, false, m ); + break; + + case SDynMaterialProp::Texture: + break; + } + } + + ////////////////////////////////// Set up some standard uniforms ////////////////////////////////// + + int loc = -1; + loc = nglGetUniformLocation( currentProgram->getProgramId(), "mvpMatrix" ); + if( loc != -1 ) + { + CMatrix mat = _GLProjMat * _ModelViewMatrix; + setUniformMatrix4fv( loc, 1, false, mat.get() ); + } + + loc = nglGetUniformLocation( currentProgram->getProgramId(), "mvMatrix" ); + if( loc != -1 ) + { + setUniformMatrix4fv( loc, 1, false, _ModelViewMatrix.get() ); + } + + //////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif + return true; +} + void CDriverGL3::setupNormalPass() { const CMaterial &mat = *_CurrentMaterial; diff --git a/code/nel/src/3d/driver/OpenGL3/driver_opengl_program.cpp b/code/nel/src/3d/driver/OpenGL3/driver_opengl_program.cpp index 3c302db84..7766722a9 100644 --- a/code/nel/src/3d/driver/OpenGL3/driver_opengl_program.cpp +++ b/code/nel/src/3d/driver/OpenGL3/driver_opengl_program.cpp @@ -22,6 +22,9 @@ #include "driver_glsl_shader_generator.h" #include "driver_opengl_vertex_buffer_hard.h" #include "nel/3d/i_program_object.h" +#include "nel/3d/dynamic_material.h" +#include "nel/3d/usr_shader_manager.h" +#include "nel/3d/usr_shader_program.h" namespace { @@ -51,9 +54,6 @@ namespace NL3D if( !program->isLinked() ) return false; - // Release previous program - releaseProgram(); - nglUseProgram( program->getProgramId() ); GLenum error = glGetError(); @@ -148,11 +148,6 @@ namespace NL3D return true; } - static IProgram *vp; - static IProgram *pp; - static IProgramObject *p; - - void CDriverGL3::generateShaderDesc( CShaderDesc &desc, CMaterial &mat ) { desc.setShaderType( mat.getShader() ); @@ -216,8 +211,13 @@ namespace NL3D bool CDriverGL3::setupProgram( CMaterial &mat ) { + if( mat.getDynMat() != NULL ) + return true; + + IProgram *vp = NULL; + IProgram *pp = NULL; + IProgramObject *p = NULL; -#ifdef GLSL CShaderDesc desc; generateShaderDesc( desc, mat ); @@ -288,7 +288,65 @@ namespace NL3D setupUniforms( mat ); -#endif + return true; + } + + bool CDriverGL3::setupDynMatProgram( CMaterial& mat, uint pass ) + { + CDynMaterial *m = mat.getDynMat(); + const SRenderPass *rp = m->getPass( pass ); + std::string shaderRef; + rp->getShaderRef( shaderRef ); + + NL3D::CUsrShaderProgram prg; + + if( !usrShaderManager->getShader( shaderRef, &prg ) ) + return false; + + IProgramObject *p = createProgramObject(); + IProgram *vp = createVertexProgram(); + IProgram *pp = createPixelProgram(); + + std::string shaderSource; + std::string log; + prg.getVP( shaderSource ); + vp->shaderSource( shaderSource.c_str() ); + if( !vp->compile( log ) ) + { + delete vp; + delete pp; + delete p; + return false; + } + + prg.getFP( shaderSource ); + pp->shaderSource( shaderSource.c_str() ); + if( !pp->compile( log ) ) + { + delete vp; + delete pp; + delete p; + return false; + } + + p->attachVertexProgram( vp ); + p->attachPixelProgram( pp ); + + if( !p->link( log ) ) + { + delete p; + return false; + } + + if( !activeProgramObject( p ) ) + { + delete p; + return false; + } + + if( dynMatProgram != NULL ) + delete dynMatProgram; + dynMatProgram = p; return true; } @@ -484,15 +542,6 @@ namespace NL3D } -#endif - } - - void CDriverGL3::releaseProgram() - { - currentProgram = NULL; - -#ifndef GLSL - _VertexProgramEnabled = false; #endif } diff --git a/code/nel/src/3d/driver/OpenGL3/driver_opengl_vertex.cpp b/code/nel/src/3d/driver/OpenGL3/driver_opengl_vertex.cpp index 753aed6d8..e8cff02d5 100644 --- a/code/nel/src/3d/driver/OpenGL3/driver_opengl_vertex.cpp +++ b/code/nel/src/3d/driver/OpenGL3/driver_opengl_vertex.cpp @@ -229,7 +229,8 @@ bool CDriverGL3::renderLines(CMaterial& mat, uint32 firstIndex, uint32 nlines) for(uint pass=0;pass= material->count() ) + if( i >= material->getPassCount() ) return CRenderPassProxy( NULL ); else return CRenderPassProxy( material->getPass( i ) );