diff --git a/code/nel/include/nel/3d/i_program_object.h b/code/nel/include/nel/3d/i_program_object.h index 2d892b00c..e70d655a5 100644 --- a/code/nel/include/nel/3d/i_program_object.h +++ b/code/nel/include/nel/3d/i_program_object.h @@ -50,6 +50,22 @@ namespace NL3D FogEnd, FogColor, FogDensity, + Light0Dir, + Light1Dir, + Light2Dir, + Light3Dir, + Light4Dir, + Light5Dir, + Light6Dir, + Light7Dir, + Light0Col, + Light1Col, + Light2Col, + Light3Col, + Light4Col, + Light5Col, + Light6Col, + Light7Col, NUM_UNIFORMS }; diff --git a/code/nel/src/3d/driver/OpenGL3/driver_glsl_program.cpp b/code/nel/src/3d/driver/OpenGL3/driver_glsl_program.cpp index 5b23836ab..f9b79f98a 100644 --- a/code/nel/src/3d/driver/OpenGL3/driver_glsl_program.cpp +++ b/code/nel/src/3d/driver/OpenGL3/driver_glsl_program.cpp @@ -195,7 +195,23 @@ namespace NL3D "fogStart", "fogEnd", "fogColor", - "fogDensity" + "fogDensity", + "light0Dir", + "light1Dir", + "light2Dir", + "light3Dir", + "light4Dir", + "light5Dir", + "light6Dir", + "light7Dir", + "light0Col", + "light1Col", + "light2Col", + "light3Col", + "light4Col", + "light5Col", + "light6Col", + "light7Col", }; void CGLSLProgram::cacheUniformIndices() diff --git a/code/nel/src/3d/driver/OpenGL3/driver_glsl_shader_generator.cpp b/code/nel/src/3d/driver/OpenGL3/driver_glsl_shader_generator.cpp index 375f512ab..d955a5f76 100644 --- a/code/nel/src/3d/driver/OpenGL3/driver_glsl_shader_generator.cpp +++ b/code/nel/src/3d/driver/OpenGL3/driver_glsl_shader_generator.cpp @@ -328,17 +328,173 @@ namespace NL3D ss << "fragColor = applyFog( fragColor );" << std::endl; } + + /////////////////////////////////////////////////////////// Lights //////////////////////////////////////////////////////////////////// + + void CGLSLShaderGenerator::addLightUniformsVS() + { + for( int i = 0; i < SHADER_MAX_LIGHTS; i++ ) + { + switch( desc->getLight( i ) ) + { + case CShaderDesc::Nolight: + continue; + break; + + case CShaderDesc::Directional: + ss << "uniform vec3 light" << i << "Dir;" << std::endl; + break; + } + } + } + + void CGLSLShaderGenerator::addLightUniformsFS() + { + for( int i = 0; i < SHADER_MAX_LIGHTS; i++ ) + { + switch( desc->getLight( i ) ) + { + case CShaderDesc::Nolight: + continue; + break; + + case CShaderDesc::Directional: + ss << "uniform vec4 light" << i << "Col;" << std::endl; + break; + } + } + + } + + void CGLSLShaderGenerator::addLightOutsVS() + { + for( int i = 0; i < SHADER_MAX_LIGHTS; i++ ) + { + switch( desc->getLight( i ) ) + { + case CShaderDesc::Nolight: + continue; + break; + + case CShaderDesc::Directional: + ss << "smooth out float intensity" << i << ";" << std::endl; + break; + } + } + } + + void CGLSLShaderGenerator::addLightInsFS() + { + for( int i = 0; i < SHADER_MAX_LIGHTS; i++ ) + { + switch( desc->getLight( i ) ) + { + case CShaderDesc::Nolight: + continue; + break; + + case CShaderDesc::Directional: + ss << "smooth in float intensity" << i << ";" << std::endl; + break; + } + } + } + + void CGLSLShaderGenerator::addDirectionalFunctionVS( int num ) + { + ss << "float getIntensity" << num << "( void )" << std::endl; + ss << "{" << std::endl; + ss << "mat3 nmat;" << std::endl; + ss << "nmat[ 0 ] = mvMatrix[ 0 ].xyz;" << std::endl; + ss << "nmat[ 1 ] = mvMatrix[ 1 ].xyz;" << std::endl; + ss << "nmat[ 2 ] = mvMatrix[ 2 ].xyz;" << std::endl; + ss << "nmat = inverse( nmat );" << std::endl; + ss << "nmat = transpose( nmat );" << std::endl; + ss << "vec3 normal3 = vnormal.xyz / vnormal.w;" << std::endl; + ss << "normal3 = nmat * normal3;" << std::endl; + ss << "float angle = dot( normalize( light" << num << "Dir ), normal3 );" << std::endl; + ss << "angle = max( 0.0, angle );" << std::endl; + ss << "return angle;" << std::endl; + ss << "}" << std::endl; + ss << std::endl; + } + + void CGLSLShaderGenerator::addLightsFunctionVS() + { + for( int i = 0; i < SHADER_MAX_LIGHTS; i++ ) + { + switch( desc->getLight( i ) ) + { + case CShaderDesc::Nolight: + continue; + break; + + case CShaderDesc::Directional: + addDirectionalFunctionVS( i ); + break; + } + } + } + + void CGLSLShaderGenerator::addLightsFunctionFS() + { + ss << "vec4 applyLights( vec4 col )" << std::endl; + ss << "{" << std::endl; + ss << "col = col * intensity0 * light0Col;" << std::endl; + ss << "return col;" << std::endl; + ss << "}" << std::endl; + } + + void CGLSLShaderGenerator::addLightsVS() + { + for( int i = 0; i < SHADER_MAX_LIGHTS; i++ ) + { + switch( desc->getLight( i ) ) + { + case CShaderDesc::Nolight: + continue; + break; + + case CShaderDesc::Directional: + ss << "intensity" << i << " = getIntensity" << i << "();" << std::endl; + break; + } + } + } + + void CGLSLShaderGenerator::addLightsFS() + { + ss << "fragColor = applyLights( fragColor );" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void CGLSLShaderGenerator::generateNormalVS() { - if( desc->fogEnabled() ) + if( desc->fogEnabled() || desc->lightingEnabled() ) { ss << "uniform mat4 mvMatrix;" << std::endl; - ss << "smooth out vec4 ecPos;" << std::endl; } + if( desc->fogEnabled() ) + ss << "smooth out vec4 ecPos;" << std::endl; ss << std::endl; + if( desc->lightingEnabled() ) + { + addLightUniformsVS(); + addLightOutsVS(); + ss << std::endl; + + addLightsFunctionVS(); + ss << std::endl; + } + ss << "void main( void )" << std::endl; ss << "{" << std::endl; + + if( desc->lightingEnabled() ) + addLightsVS(); + ss << "gl_Position = mvpMatrix * " << "v" << attribNames[ 0 ] << ";" << std::endl; if( desc->fogEnabled() ) @@ -539,6 +695,16 @@ namespace NL3D ss << std::endl; + if( desc->lightingEnabled() ) + { + addLightUniformsFS(); + addLightInsFS(); + ss << std::endl; + + addLightsFunctionFS(); + ss << std::endl; + } + if( desc->fogEnabled() ) addFogFunction(); @@ -581,6 +747,9 @@ namespace NL3D ss << "fragColor = texel;" << std::endl; + if( desc->lightingEnabled() ) + addLightsFS(); + if( desc->fogEnabled() ) addFog(); diff --git a/code/nel/src/3d/driver/OpenGL3/driver_glsl_shader_generator.h b/code/nel/src/3d/driver/OpenGL3/driver_glsl_shader_generator.h index c0515a730..60aaba81e 100644 --- a/code/nel/src/3d/driver/OpenGL3/driver_glsl_shader_generator.h +++ b/code/nel/src/3d/driver/OpenGL3/driver_glsl_shader_generator.h @@ -52,6 +52,18 @@ namespace NL3D void addFogFunction(); void addFog(); + //////////////////////////// Lights /////////////////////////// + void addLightUniformsVS(); + void addLightUniformsFS(); + void addLightOutsVS(); + void addLightInsFS(); + void addDirectionalFunctionVS( int num ); + void addLightsFunctionVS(); + void addLightsFunctionFS(); + void addLightsVS(); + void addLightsFS(); + ////////////////////////////////////////////////////////////// + void generateNormalVS(); void generateSpecularVS(); diff --git a/code/nel/src/3d/driver/OpenGL3/driver_opengl.h b/code/nel/src/3d/driver/OpenGL3/driver_opengl.h index eae913fe7..2beb74a96 100644 --- a/code/nel/src/3d/driver/OpenGL3/driver_opengl.h +++ b/code/nel/src/3d/driver/OpenGL3/driver_opengl.h @@ -1278,6 +1278,7 @@ private: int getUniformLocation( const char *name ); void setUniform1f( uint index, float f ); + void setUniform3f( uint index, float f1, float f2, float f3 ); void setUniform4f( uint index, float f1, float f2, float f3, float f4 ); void setUniform1i( uint index, int i ); void setUniform4i( uint index, int i1, int i2, int i3, int i4 ); 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 eade84bd8..14efeb284 100644 --- a/code/nel/src/3d/driver/OpenGL3/driver_opengl_material.cpp +++ b/code/nel/src/3d/driver/OpenGL3/driver_opengl_material.cpp @@ -432,7 +432,7 @@ bool CDriverGL3::setupMaterial(CMaterial& mat) //===================== // Light Part. -#ifndef GLSL + _DriverGLStates.enableLighting(mat.getFlags()&IDRV_MAT_LIGHTING); if(mat.getFlags()&IDRV_MAT_LIGHTING) { @@ -442,18 +442,19 @@ bool CDriverGL3::setupMaterial(CMaterial& mat) _DriverGLStates.setSpecular(pShader->PackedSpecular, pShader->Specular); _DriverGLStates.setShininess(mat.getShininess()); _DriverGLStates.setVertexColorLighted(mat.isLightedVertexColor ()); + } else { +#ifndef GLSL // Color unlit part. CRGBA col= mat.getColor(); glColor4ub(col.R, col.G, col.B, col.A); +#endif _DriverGLStates.setVertexColorLighted(false); } -#endif - // Fog Part. //================= 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 3dddda680..0b071a6d8 100644 --- a/code/nel/src/3d/driver/OpenGL3/driver_opengl_program.cpp +++ b/code/nel/src/3d/driver/OpenGL3/driver_opengl_program.cpp @@ -96,6 +96,11 @@ namespace NL3D nglUniform1f( index, f ); } + void CDriverGL3::setUniform3f( uint index, float f1, float f2, float f3 ) + { + nglUniform3f( index, f1, f2, f3 ); + } + void CDriverGL3::setUniform4f( uint index, float f1, float f2, float f3, float f4 ) { nglUniform4f( index, f1, f2, f3, f4 ); @@ -160,17 +165,52 @@ namespace NL3D if( mat.getShader() == CMaterial::Normal ) { - for( i = 0; i < MAX_TEXTURES; i++ ) + int maxTextures = std::min( int( SHADER_MAX_TEXTURES ), int( IDRV_MAT_MAXTEXTURES ) ); + for( i = 0; i < maxTextures; i++ ) { desc.setTexEnvMode( i, mat.getTexEnvMode( i ) ); } } - desc.setAlphaTest( mat.getAlphaTest() ); - desc.setAlphaTestThreshold( mat.getAlphaTestThreshold() ); + if( mat.getAlphaTest() ) + { + desc.setAlphaTest( true ); + desc.setAlphaTestThreshold( mat.getAlphaTestThreshold() ); + } + + if( fogEnabled() ) + { + desc.setFog( true ); + desc.setFogMode( CShaderDesc::Linear ); + } + + int maxLights = std::min( int( SHADER_MAX_LIGHTS ), int( MaxLight ) ); + bool enableLights = false; + for( int i = 0; i < maxLights; i++ ) + { + if( !_UserLightEnable[ i ] ) + continue; + + enableLights = true; + + switch( _LightMode[ i ] ) + { + case CLight::DirectionalLight: + desc.setLight( i, CShaderDesc::Directional ); + break; + + case CLight::PointLight: + desc.setLight( i, CShaderDesc::Point ); + break; + + case CLight::SpotLight: + desc.setLight( i, CShaderDesc::Spot ); + break; + } + + } - desc.setFog( fogEnabled() ); - desc.setFogMode( CShaderDesc::Linear ); + desc.setLighting( enableLights ); } @@ -253,6 +293,13 @@ namespace NL3D return true; } + + struct LightData + { + float direction[ 3 ]; + float color[ 4 ]; + }; + void CDriverGL3::setupUniforms( CMaterial& mat ) { @@ -322,6 +369,37 @@ namespace NL3D } + int maxLights = std::min( int( MaxLight ), int( SHADER_MAX_LIGHTS ) ); + for( int i = 0; i < maxLights; i++ ) + { + if( !_UserLightEnable[ i ] ) + continue; + + ////////////////// Temporary insanity /////////////////////////////// + if( _LightMode[ i ] != CLight::DirectionalLight ) + continue; + ////////////////////////////////////////////////////////////////////// + + LightData d; + d.direction[ 0 ] = _WorldLightDirection[ i ].x; + d.direction[ 1 ] = _WorldLightDirection[ i ].y; + d.direction[ 2 ] = _WorldLightDirection[ i ].z; + + int ld = currentProgram->getUniformIndex( IProgramObject::EUniform( IProgramObject::Light0Dir + i ) ); + if( ld != -1 ) + { + setUniform3f( ld, d.direction[ 0 ], d.direction[ 1 ], d.direction[ 2 ] ); + } + + int lc = currentProgram->getUniformIndex( IProgramObject::EUniform( IProgramObject::Light0Col + i ) ); + if( lc != -1 ) + { + setUniform4f( lc, 1.0f, 1.0f, 1.0f, 1.0f ); + } + + } + + // Lightmaps have special constants if( mat.getShader() != CMaterial::LightMap ) { diff --git a/code/nel/src/3d/driver/OpenGL3/driver_opengl_shader_desc.h b/code/nel/src/3d/driver/OpenGL3/driver_opengl_shader_desc.h index fd6c7e8f1..3f5a5c565 100644 --- a/code/nel/src/3d/driver/OpenGL3/driver_opengl_shader_desc.h +++ b/code/nel/src/3d/driver/OpenGL3/driver_opengl_shader_desc.h @@ -19,7 +19,8 @@ #include "nel/misc/types_nl.h" -#define MAX_TEXTURES 4 +#define SHADER_MAX_TEXTURES 4 +#define SHADER_MAX_LIGHTS 8 namespace NL3D { @@ -28,6 +29,20 @@ namespace NL3D class CShaderDesc { public: + + enum TShaderType + { + Normal, + Bump_unused, + UserColor, + LightMap, + Specular, + Caustics_unused, + PerPixelLighting, + PerPixelNoSpecular, + Cloud, + Water + }; enum TFogMode { @@ -36,16 +51,28 @@ namespace NL3D Linear }; + enum TLightMode + { + Nolight, + Directional, + Point, + Spot + }; + CShaderDesc(){ - for( int i = 0; i < MAX_TEXTURES; i++ ) + for( int i = 0; i < SHADER_MAX_TEXTURES; i++ ) texEnvMode[ i ] = 0; + + for( int i = 0; i < SHADER_MAX_LIGHTS; i++ ) + lightMode[ i ] = Nolight; + features = None; - shaderType = 0; + shaderType = Normal; program = NULL; vbFlags = 0; nlightmaps = 0; alphaTestTreshold = 0.5f; - fogMode = Exponential; + fogMode = Linear; } ~CShaderDesc(){ @@ -74,15 +101,25 @@ namespace NL3D return false; } - if( ( features & Fog ) != 0 ) + if( fogEnabled() ) { if( fogMode != o.fogMode ) return false; } - for( int i = 0; i < MAX_TEXTURES; i++ ) - if( texEnvMode[ i ] != o.texEnvMode[ i ] ) - return false; + if( shaderType == Normal ) + { + for( int i = 0; i < SHADER_MAX_TEXTURES; i++ ) + if( texEnvMode[ i ] != o.texEnvMode[ i ] ) + return false; + } + + if( lightingEnabled() ) + { + for( int i = 0; i < SHADER_MAX_LIGHTS; i++ ) + if( lightMode[ i ] != o.lightMode[ i ] ) + return false; + } return true; } @@ -123,6 +160,29 @@ namespace NL3D uint32 getFogMode() const{ return fogMode; } + void setLighting( bool b ) + { + if( b ) + features |= Lighting; + else + features &= ~Lighting; + } + + bool lightingEnabled() const + { + if( ( features & Lighting ) != 0 ) + return true; + else + return false; + } + + void setLight( int idx, TLightMode mode ) + { + lightMode[ idx ] = mode; + } + + TLightMode getLight( int idx ) const{ return lightMode[ idx ]; } + IProgramObject* getProgram() const{ return program; } private: @@ -131,16 +191,18 @@ namespace NL3D { None = 0, AlphaTest = 1, - Fog = 2 + Fog = 2, + Lighting = 4 }; uint32 features; - uint32 texEnvMode[ MAX_TEXTURES ]; + uint32 texEnvMode[ SHADER_MAX_TEXTURES ]; uint32 vbFlags; uint32 shaderType; uint32 nlightmaps; float alphaTestTreshold; uint32 fogMode; + TLightMode lightMode[ SHADER_MAX_LIGHTS ]; IProgramObject *program; }; diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/material_editor/nel3d_interface.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/material_editor/nel3d_interface.cpp index 5cc8c11d5..9ed79257a 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/material_editor/nel3d_interface.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/material_editor/nel3d_interface.cpp @@ -24,6 +24,7 @@ #include "nel/3d/scene_user.h" #include "nel/3d/u_camera.h" #include "nel/3d/u_instance.h" +#include "nel/3d/u_light.h" #include "nel/3d/u_3d_mouse_listener.h" #include "nel/3d/i_program.h" #include "nel/3d/i_program_object.h" @@ -405,6 +406,25 @@ namespace MaterialEditor driver->setDisplay( (nlWindow)wnd, NL3D::UDriver::CMode( w, h, 32 ) ); scene = driver->createScene( true ); + + + driver->enableFog( true ); + driver->setupFog( 1.0f, 5.0f, NLMISC::CRGBA::White ); + + NL3D::ULight *l = NL3D::ULight::createLight(); + + l->setMode( NL3D::ULight::DirectionalLight ); + l->setDirection( NLMISC::CVector( -100.0f, 100.0f, 100.0f ) ); + l->setAmbiant( NLMISC::CRGBA::White ); + driver->setLight( 0, *l ); + driver->enableLight( 0, true ); + + delete l; + l = NULL; + + scene->enableLightingSystem( false ); + + mouseListener = driver->create3dMouseListener(); mouseListener->setMouseMode( NL3D::U3dMouseListener::nelStyle ); } @@ -464,10 +484,7 @@ namespace MaterialEditor subMatId = 0; setupCamera(); - - driver->enableFog( true ); - driver->setupFog( 1.0f, 5.0f, NLMISC::CRGBA::White ); - + return true; }