diff --git a/code/nel/include/nel/3d/i_program_object.h b/code/nel/include/nel/3d/i_program_object.h index 5b0c1dc71..2d892b00c 100644 --- a/code/nel/include/nel/3d/i_program_object.h +++ b/code/nel/include/nel/3d/i_program_object.h @@ -46,6 +46,10 @@ namespace NL3D Sampler2, Sampler3, AlphaTreshold, + FogStart, + FogEnd, + FogColor, + FogDensity, 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 bf0b1e6d2..5b23836ab 100644 --- a/code/nel/src/3d/driver/OpenGL3/driver_glsl_program.cpp +++ b/code/nel/src/3d/driver/OpenGL3/driver_glsl_program.cpp @@ -191,7 +191,11 @@ namespace NL3D "sampler1", "sampler2", "sampler3", - "alphaTreshold" + "alphaTreshold", + "fogStart", + "fogEnd", + "fogColor", + "fogDensity" }; 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 f87e69725..375f512ab 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 @@ -17,6 +17,7 @@ #include "sstream" #include "driver_glsl_shader_generator.h" #include "nel/3d/vertex_buffer.h" +#include "driver_opengl_shader_desc.h" namespace { @@ -285,12 +286,64 @@ namespace NL3D ss << "if( fragColor.a <= ( alphaTreshold - 0.0001 ) ) discard;" << std::endl; } + void CGLSLShaderGenerator::addFogUniform() + { + if( !desc->fogEnabled() ) + return; + + ss << "uniform float fogStart;" << std::endl; + ss << "uniform float fogEnd;" << std::endl; + ss << "uniform vec4 fogColor;" << std::endl; + + if( desc->getFogMode() == CShaderDesc::Linear ) + return; + + ss << "uniform float fogDensity;" << std::endl; + } + + void CGLSLShaderGenerator::addFogFunction() + { + if( !desc->fogEnabled() ) + return; + + switch( desc->getFogMode() ) + { + case CShaderDesc::Linear: + ss << "vec4 applyFog( vec4 col )" << std::endl; + ss << "{" << std::endl; + ss << "float z = ecPos.z / ecPos.w;" << std::endl; + ss << "z = abs( z );" << std::endl; + ss << "float fogFactor = ( fogEnd - z ) / ( fogEnd - fogStart );" << std::endl; + ss << "fogFactor = clamp( fogFactor, 0.0, 1.0 );" << std::endl; + ss << "vec4 fColor = mix( fogColor, col, fogFactor );" << std::endl; + ss << "return fColor;" << std::endl; + ss << "}" << std::endl; + ss << std::endl; + break; + } + } + + void CGLSLShaderGenerator::addFog() + { + ss << "fragColor = applyFog( fragColor );" << std::endl; + } + void CGLSLShaderGenerator::generateNormalVS() { + if( desc->fogEnabled() ) + { + ss << "uniform mat4 mvMatrix;" << std::endl; + ss << "smooth out vec4 ecPos;" << std::endl; + } + ss << std::endl; + ss << "void main( void )" << std::endl; ss << "{" << std::endl; ss << "gl_Position = mvpMatrix * " << "v" << attribNames[ 0 ] << ";" << std::endl; + if( desc->fogEnabled() ) + ss << "ecPos = mvMatrix * v" << attribNames[ 0 ] << ";" << std::endl; + for( int i = Weight; i < NumOffsets; i++ ) { if( hasFlag( vbFormat, vertexFlags[ i ] ) ) @@ -310,6 +363,8 @@ namespace NL3D ss << "uniform mat4 mvMatrix;" << std::endl; ss << "uniform mat4 texMatrix0;" << std::endl; ss << "smooth out vec3 cubeTexCoords;" << std::endl; + if( desc->fogEnabled() ) + ss << "smooth out vec4 ecPos;" << std::endl; ss << std::endl; ss << "vec3 ReflectionMap( const in vec3 eyePos, const in vec3 normal )" << std::endl; @@ -322,6 +377,7 @@ namespace NL3D ss << "void main( void )" << std::endl; ss << "{" << std::endl; ss << "vec4 eyePosition = mvMatrix * v" << attribNames[ 0 ] << ";" << std::endl; + ss << "ecPos = eyePosition;" << std::endl; ss << "vec3 ep = eyePosition.xyz / eyePosition.w;" << std::endl; ss << "vec3 n = vnormal.xyz;" << std::endl; ss << "cubeTexCoords = ReflectionMap( ep, n );" << std::endl; @@ -476,8 +532,15 @@ namespace NL3D addColor(); addConstants(); addAlphaTreshold(); + addFogUniform(); + + if( desc->fogEnabled() ) + ss << "smooth in vec4 ecPos;" << std::endl; ss << std::endl; + + if( desc->fogEnabled() ) + addFogFunction(); ss << "void main( void )" << std::endl; ss << "{" << std::endl; @@ -518,6 +581,9 @@ namespace NL3D ss << "fragColor = texel;" << std::endl; + if( desc->fogEnabled() ) + addFog(); + addAlphaTest(); ss << "}" << std::endl; @@ -886,8 +952,16 @@ namespace NL3D addAlphaTreshold(); + addFogUniform(); + + if( desc->fogEnabled() ) + ss << "smooth in vec4 ecPos;" << std::endl; + ss << std::endl; + if( desc->fogEnabled() ) + addFogFunction(); + ss << "void main( void )" << std::endl; ss << "{" << std::endl; @@ -924,7 +998,12 @@ namespace NL3D } ss << "fragColor = texel;" << std::endl; + + if( desc->fogEnabled() ) + addFog(); + addAlphaTest(); + ss << "}" << std::endl; ss << std::endl; } @@ -937,6 +1016,16 @@ namespace NL3D addDiffuse(); addAlphaTreshold(); + addFogUniform(); + + if( desc->fogEnabled() ) + ss << "smooth in vec4 ecPos;" << std::endl; + + ss << std::endl; + + if( desc->fogEnabled() ) + addFogFunction(); + ss << "void main( void )" << std::endl; ss << "{" << std::endl; ss << "vec4 texel0 = texture2D( sampler0, texCoord0 );" << std::endl; @@ -947,7 +1036,12 @@ namespace NL3D ss << "texel.rgb = texel1.rgb * texel.a + texel.rgb;" << std::endl; ss << "texel.a = texel1.a;" << std::endl; ss << "fragColor = texel;" << std::endl; + + if( desc->fogEnabled() ) + addFog(); + addAlphaTest(); + ss << "}" << std::endl; } 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 f4ad2893b..c0515a730 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 @@ -24,6 +24,7 @@ namespace NL3D { class CMaterial; + class CShaderDesc; class CGLSLShaderGenerator { @@ -37,14 +38,20 @@ namespace NL3D void setMaterial( CMaterial *mat ){ material = mat; } void setVBFormat( uint16 format ){ vbFormat = format; } + void setShaderDesc( CShaderDesc *d ){ desc = d; } private: void addDiffuse(); void addColor(); void addConstants(); + void addAlphaTreshold(); void addAlphaTest(); + void addFogUniform(); + void addFogFunction(); + void addFog(); + void generateNormalVS(); void generateSpecularVS(); @@ -72,6 +79,7 @@ namespace NL3D std::stringstream ss; uint16 vbFormat; CMaterial const *material; + CShaderDesc const *desc; }; } 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 205c6110f..3dddda680 100644 --- a/code/nel/src/3d/driver/OpenGL3/driver_opengl_program.cpp +++ b/code/nel/src/3d/driver/OpenGL3/driver_opengl_program.cpp @@ -168,6 +168,9 @@ namespace NL3D desc.setAlphaTest( mat.getAlphaTest() ); desc.setAlphaTestThreshold( mat.getAlphaTestThreshold() ); + + desc.setFog( fogEnabled() ); + desc.setFogMode( CShaderDesc::Linear ); } @@ -194,6 +197,7 @@ namespace NL3D shaderGenerator->reset(); shaderGenerator->setMaterial( &mat ); shaderGenerator->setVBFormat( _CurrentVertexBufferHard->VB->getVertexFormat() ); + shaderGenerator->setShaderDesc( &desc ); shaderGenerator->generateVS( vs ); shaderGenerator->generatePS( ps ); @@ -261,6 +265,36 @@ namespace NL3D setUniformMatrix4fv( mvpIndex, 1, false, mat.get() ); } + int mvIndex = currentProgram->getUniformIndex( IProgramObject::MVMatrix ); + if( mvIndex != -1 ) + { + setUniformMatrix4fv( mvIndex, 1, false, _ModelViewMatrix.get() ); + } + + int fogStartIdx = currentProgram->getUniformIndex( IProgramObject::FogStart ); + if( fogStartIdx != -1 ) + { + setUniform1f( fogStartIdx, getFogStart() ); + } + + int fogEndIdx = currentProgram->getUniformIndex( IProgramObject::FogEnd ); + if( fogEndIdx != -1 ) + { + setUniform1f( fogEndIdx, getFogEnd() ); + } + + int fogColorIdx = currentProgram->getUniformIndex( IProgramObject::FogColor ); + if( fogColorIdx != -1 ) + { + GLfloat glCol[ 4 ]; + CRGBA col = getFogColor(); + glCol[ 0 ] = col.R / 255.0f; + glCol[ 1 ] = col.G / 255.0f; + glCol[ 2 ] = col.B / 255.0f; + glCol[ 3 ] = col.A / 255.0f; + setUniform4f( fogColorIdx, glCol[ 0 ], glCol[ 1 ], glCol[ 2 ], glCol[ 3 ] ); + } + int colorIndex = currentProgram->getUniformIndex( IProgramObject::Color ); if( colorIndex != -1 ) { 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 c261a2713..fd6c7e8f1 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 @@ -28,6 +28,14 @@ namespace NL3D class CShaderDesc { public: + + enum TFogMode + { + Exponential, + Exponential2, + Linear + }; + CShaderDesc(){ for( int i = 0; i < MAX_TEXTURES; i++ ) texEnvMode[ i ] = 0; @@ -37,6 +45,7 @@ namespace NL3D vbFlags = 0; nlightmaps = 0; alphaTestTreshold = 0.5f; + fogMode = Exponential; } ~CShaderDesc(){ @@ -65,6 +74,12 @@ namespace NL3D return false; } + if( ( features & Fog ) != 0 ) + { + if( fogMode != o.fogMode ) + return false; + } + for( int i = 0; i < MAX_TEXTURES; i++ ) if( texEnvMode[ i ] != o.texEnvMode[ i ] ) return false; @@ -78,7 +93,8 @@ namespace NL3D void setProgram( IProgramObject *p ){ program = p; } void setNLightMaps( uint32 n ){ nlightmaps = n; } - void setAlphaTest( bool b ){ + void setAlphaTest( bool b ) + { if( b ) features |= AlphaTest; else @@ -87,6 +103,26 @@ namespace NL3D void setAlphaTestThreshold( float t ){ alphaTestTreshold = t; } + void setFog( bool b ) + { + if( b ) + features |= Fog; + else + features &= ~Fog; + } + + bool fogEnabled() const + { + if( ( features & Fog ) != 0 ) + return true; + else + return false; + } + + void setFogMode( TFogMode mode ){ fogMode = mode; } + + uint32 getFogMode() const{ return fogMode; } + IProgramObject* getProgram() const{ return program; } private: @@ -94,7 +130,8 @@ namespace NL3D enum TShaderFeatures { None = 0, - AlphaTest = 1 + AlphaTest = 1, + Fog = 2 }; uint32 features; @@ -103,6 +140,7 @@ namespace NL3D uint32 shaderType; uint32 nlightmaps; float alphaTestTreshold; + uint32 fogMode; 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 d028099bb..5cc8c11d5 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 @@ -465,6 +465,9 @@ namespace MaterialEditor setupCamera(); + driver->enableFog( true ); + driver->setupFog( 1.0f, 5.0f, NLMISC::CRGBA::White ); + return true; }