diff --git a/Engine/source/forest/glsl/windDeformationGLSL.cpp b/Engine/source/forest/glsl/windDeformationGLSL.cpp index 00502caa9..ae32b51f7 100644 --- a/Engine/source/forest/glsl/windDeformationGLSL.cpp +++ b/Engine/source/forest/glsl/windDeformationGLSL.cpp @@ -40,6 +40,9 @@ static void _onRegisterFeatures( GFXAdapterType type ) { + if ( type != OpenGL ) + return; + FEATUREMGR->registerFeature( MFT_WindEffect, new WindDeformationGLSL ); } @@ -83,29 +86,14 @@ void WindDeformationGLSL::processVert( Vector &componentList, // save constant space and reduce the memory copied to the // card. // - // This in particular helps when we're instancing. - // // .x = bend scale // .y = branch amplitude // .z = detail amplitude // .w = detail frequency // - Var *windParams; - if ( fd.features[MFT_UseInstancing] ) - { - ShaderConnector *vertStruct = dynamic_cast( componentList[C_VERT_STRUCT] ); - windParams = vertStruct->getElement( RT_TEXCOORD ); - windParams->setName( "inst_windParams" ); - windParams->setType( "vec4" ); - - mInstancingFormat->addElement( "windParams", GFXDeclType_Float4, windParams->constNum ); - } - else - { - windParams = new Var( "windParams", "vec4" ); + Var *windParams = new Var( "windParams", "vec4" ); windParams->uniform = true; windParams->constSortPos = cspPotentialPrimitive; - } // If we're instancing then we need to instance the wind direction // and speed as its unique for each tree instance. @@ -114,6 +102,7 @@ void WindDeformationGLSL::processVert( Vector &componentList, { ShaderConnector *vertStruct = dynamic_cast( componentList[C_VERT_STRUCT] ); windDirAndSpeed = vertStruct->getElement( RT_TEXCOORD ); + windDirAndSpeed->setStructName( "IN" ); windDirAndSpeed->setName( "inst_windDirAndSpeed" ); windDirAndSpeed->setType( "vec3" ); @@ -143,16 +132,31 @@ void WindDeformationGLSL::processVert( Vector &componentList, if ( !inPosition ) inPosition = (Var*)LangElement::find( "position" ); + // Copy the input position to the output first as + // the wind effects are conditional. + Var *outPosition = (Var*)LangElement::find( "inPosition" ); + if ( !outPosition ) + { + outPosition = new Var; + outPosition->setType( "vec3" ); + outPosition->setName( "inPosition" ); + meta->addStatement( new GenOp(" @ = @.xyz;\r\n", new DecOp( outPosition ), inPosition ) ); + } + // Get the incoming color data Var *inColor = (Var*)LangElement::find( "diffuse" ); + // Do a dynamic branch based on wind force. + if ( GFX->getPixelShaderVersion() >= 3.0f ) + meta->addStatement( new GenOp(" if ( any( bvec3(@) ) ) {\r\n", windDirAndSpeed ) ); + // Do the branch and detail bending first so that // it can work in pure object space of the tree. LangElement *effect = new GenOp( "windBranchBending( " - "@.xyz, " // vPos - "normalize( normal ), " // vNormal + "@, " // vPos + "normalize( IN_normal ), " // vNormal "@, " // fTime "@.z, " // fWindSpeed @@ -161,13 +165,13 @@ void WindDeformationGLSL::processVert( Vector &componentList, "@.y, " // fBranchAmp "@.r, " // fBranchAtten - "dot( @[3], vec4( 1.0 ) ), " // fDetailPhase + "dot( @[3], vec4(1) ), " // fDetailPhase "@.z, " // fDetailAmp "@.w, " // fDetailFreq - + "@.b )", // fEdgeAtten - inPosition, // vPos + outPosition, // vPos // vNormal accumTime, // fTime @@ -183,22 +187,15 @@ void WindDeformationGLSL::processVert( Vector &componentList, inColor ); // fEdgeAtten - Var *outPosition = (Var*)LangElement::find( "inPosition" ); - if ( outPosition ) - meta->addStatement( new GenOp( " @.xyz = @;\r\n", outPosition, effect, inPosition ) ); - else - { - outPosition = new Var; - outPosition->setType( "vec3" ); - outPosition->setName( "inPosition" ); - meta->addStatement( new GenOp(" vec3 inPosition = @;\r\n", effect, inPosition ) ); - } + meta->addStatement( new GenOp( " @ = @;\r\n", outPosition, effect ) ); // Now do the trunk bending. - effect = new GenOp( "windTrunkBending( @, @.xy, @.z * @.x )", - outPosition, windDirAndSpeed, outPosition, windParams ); + meta->addStatement( new GenOp(" @ = windTrunkBending( @, @.xy, @.z * @.x );\r\n", + outPosition, outPosition, windDirAndSpeed, outPosition, windParams ) ); - meta->addStatement( new GenOp(" @ = @;\r\n", outPosition, effect ) ); + // End the dynamic branch. + if ( GFX->getPixelShaderVersion() >= 3.0f ) + meta->addStatement( new GenOp(" } // [branch]\r\n" ) ); } ShaderFeatureConstHandles* WindDeformationGLSL::createConstHandles( GFXShader *shader, SimObject *userObject ) diff --git a/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.cpp b/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.cpp index 1da348f03..c5f85234a 100644 --- a/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.cpp +++ b/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.cpp @@ -35,16 +35,12 @@ void DeferredRTLightingFeatGLSL::processPixMacros( Vector ¯os, const MaterialFeatureData &fd ) { - /// TODO: This needs to be done via some sort of material - /// feature and not just allow all translucent elements to - /// read from the light prepass. - /* - if ( fd.features[MFT_IsTranslucent] ) + // Skip deferred features, and use forward shading instead + if ( fd.features[MFT_ForwardShading] ) { Parent::processPixMacros( macros, fd ); return; } - */ // Pull in the uncondition method for the light info buffer NamedTexTarget *texTarget = NamedTexTarget::find( AdvancedLightBinManager::smBufferName ); @@ -59,48 +55,42 @@ void DeferredRTLightingFeatGLSL::processPixMacros( Vector ¯o void DeferredRTLightingFeatGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { - /// TODO: This needs to be done via some sort of material - /// feature and not just allow all translucent elements to - /// read from the light prepass. - /* - if ( fd.features[MFT_IsTranslucent] ) + // Skip deferred features, and use forward shading instead + if ( fd.features[MFT_ForwardShading] ) { Parent::processVert( componentList, fd ); return; } - */ // Pass screen space position to pixel shader to compute a full screen buffer uv ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *ssPos = connectComp->getElement( RT_TEXCOORD ); ssPos->setName( "screenspacePos" ); + ssPos->setStructName( "OUT" ); ssPos->setType( "vec4" ); -// Var *outPosition = (Var*) LangElement::find( "hpos" ); -// AssertFatal( outPosition, "No hpos, ohnoes." ); + Var *outPosition = (Var*) LangElement::find( "gl_Position" ); + AssertFatal( outPosition, "No gl_Position, ohnoes." ); - output = new GenOp( " @ = gl_Position;\r\n", ssPos ); + output = new GenOp( " @ = @;\r\n", ssPos, outPosition ); } void DeferredRTLightingFeatGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { - /// TODO: This needs to be done via some sort of material - /// feature and not just allow all translucent elements to - /// read from the light prepass. - /* - if ( fd.features[MFT_IsTranslucent] ) + // Skip deferred features, and use forward shading instead + if ( fd.features[MFT_ForwardShading] ) { Parent::processPix( componentList, fd ); return; } - */ MultiLine *meta = new MultiLine; ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *ssPos = connectComp->getElement( RT_TEXCOORD ); ssPos->setName( "screenspacePos" ); + ssPos->setStructName( "IN" ); ssPos->setType( "vec4" ); Var *uvScene = new Var; @@ -108,18 +98,20 @@ void DeferredRTLightingFeatGLSL::processPix( Vector &component uvScene->setName( "uvScene" ); LangElement *uvSceneDecl = new DecOp( uvScene ); - Var *rtParams = (Var*) LangElement::find( "renderTargetParams" ); + String rtParamName = String::ToString( "rtParams%s", "lightInfoBuffer" ); + Var *rtParams = (Var*) LangElement::find( rtParamName ); if( !rtParams ) { rtParams = new Var; rtParams->setType( "vec4" ); - rtParams->setName( "renderTargetParams" ); + rtParams->setName( rtParamName ); rtParams->uniform = true; rtParams->constSortPos = cspPass; } meta->addStatement( new GenOp( " @ = @.xy / @.w;\r\n", uvSceneDecl, ssPos, ssPos ) ); // get the screen coord... its -1 to +1 meta->addStatement( new GenOp( " @ = ( @ + 1.0 ) / 2.0;\r\n", uvScene, uvScene ) ); // get the screen coord to 0 to 1 + meta->addStatement( new GenOp( " @.y = 1.0 - @.y;\r\n", uvScene, uvScene ) ); // flip the y axis meta->addStatement( new GenOp( " @ = ( @ * @.zw ) + @.xy;\r\n", uvScene, uvScene, rtParams, rtParams) ); // scale it down and offset it to the rt size Var *lightInfoSamp = new Var; @@ -134,36 +126,60 @@ void DeferredRTLightingFeatGLSL::processPix( Vector &component lightInfoBuffer->sampler = true; lightInfoBuffer->constNum = Var::getTexUnitNum(); // used as texture unit num here - String unconditionLightInfo = String::ToLower( AdvancedLightBinManager::smBufferName ) + "Uncondition"; - - meta->addStatement( new GenOp( " vec3 d_lightcolor;\r\n" ) ); - meta->addStatement( new GenOp( " float d_NL_Att;\r\n" ) ); - meta->addStatement( new GenOp( " float d_specular;\r\n" ) ); - meta->addStatement( new GenOp( avar( " %s(texture2D(@, @), d_lightcolor, d_NL_Att, d_specular);\r\n", unconditionLightInfo.c_str() ), - lightInfoBuffer, uvScene ) ); + // Declare the RTLighting variables in this feature, they will either be assigned + // in this feature, or in the tonemap/lightmap feature + Var *d_lightcolor = new Var( "d_lightcolor", "vec3" ); + meta->addStatement( new GenOp( " @;\r\n", new DecOp( d_lightcolor ) ) ); - Var *rtShading = new Var; - rtShading->setType( "vec4" ); - rtShading->setName( "rtShading" ); - LangElement *rtShadingDecl = new DecOp( rtShading ); - meta->addStatement( new GenOp( " @ = vec4( d_lightcolor, 1.0 );\r\n", rtShadingDecl ) ); + Var *d_NL_Att = new Var( "d_NL_Att", "float" ); + meta->addStatement( new GenOp( " @;\r\n", new DecOp( d_NL_Att ) ) ); + + Var *d_specular = new Var( "d_specular", "float" ); + meta->addStatement( new GenOp( " @;\r\n", new DecOp( d_specular ) ) ); + + + // Perform the uncondition here. + String unconditionLightInfo = String::ToLower( AdvancedLightBinManager::smBufferName ) + "Uncondition"; + meta->addStatement( new GenOp( avar( " %s(tex2D(@, @), @, @, @);\r\n", + unconditionLightInfo.c_str() ), lightInfoBuffer, uvScene, d_lightcolor, d_NL_Att, d_specular ) ); + + // If this has an interlaced pre-pass, do averaging here + if( fd.features[MFT_InterlacedPrePass] ) + { + Var *oneOverTargetSize = (Var*) LangElement::find( "oneOverTargetSize" ); + if( !oneOverTargetSize ) + { + oneOverTargetSize = new Var; + oneOverTargetSize->setType( "vec2" ); + oneOverTargetSize->setName( "oneOverTargetSize" ); + oneOverTargetSize->uniform = true; + oneOverTargetSize->constSortPos = cspPass; + } + + meta->addStatement( new GenOp( " float id_NL_Att, id_specular;\r\n float3 id_lightcolor;\r\n" ) ); + meta->addStatement( new GenOp( avar( " %s(tex2D(@, @ + float2(0.0, @.y)), id_lightcolor, id_NL_Att, id_specular);\r\n", + unconditionLightInfo.c_str() ), lightInfoBuffer, uvScene, oneOverTargetSize ) ); + + meta->addStatement( new GenOp(" @ = lerp(@, id_lightcolor, 0.5);\r\n", d_lightcolor, d_lightcolor ) ); + meta->addStatement( new GenOp(" @ = lerp(@, id_NL_Att, 0.5);\r\n", d_NL_Att, d_NL_Att ) ); + meta->addStatement( new GenOp(" @ = lerp(@, id_specular, 0.5);\r\n", d_specular, d_specular ) ); + } // This is kind of weak sauce - if( !fd.features[MFT_SubSurface] && !fd.features[MFT_ToneMap] && !fd.features[MFT_LightMap] ) - meta->addStatement( new GenOp( " @;\r\n", assignColor( rtShading, Material::Mul ) ) ); + if( !fd.features[MFT_VertLit] && !fd.features[MFT_ToneMap] && !fd.features[MFT_LightMap] && !fd.features[MFT_SubSurface] ) + meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "float4(@, 1.0)", d_lightcolor ), Material::Mul ) ) ); output = meta; } ShaderFeature::Resources DeferredRTLightingFeatGLSL::getResources( const MaterialFeatureData &fd ) { - /// TODO: This needs to be done via some sort of material - /// feature and not just allow all translucent elements to - /// read from the light prepass. - /* - if( fd.features[MFT_IsTranslucent] ) + // Skip deferred features, and use forward shading instead + if ( fd.features[MFT_ForwardShading] ) return Parent::getResources( fd ); - */ + + // HACK: See DeferredRTLightingFeatGLSL::setTexData. + mLastTexIndex = 0; Resources res; res.numTex = 1; @@ -176,21 +192,22 @@ void DeferredRTLightingFeatGLSL::setTexData( Material::StageData &stageDat, RenderPassData &passData, U32 &texIndex ) { - /// TODO: This needs to be done via some sort of material - /// feature and not just allow all translucent elements to - /// read from the light prepass. - /* - if( fd.features[MFT_IsTranslucent] ) + // Skip deferred features, and use forward shading instead + if ( fd.features[MFT_ForwardShading] ) { Parent::setTexData( stageDat, fd, passData, texIndex ); return; } - */ NamedTexTarget *texTarget = NamedTexTarget::find( AdvancedLightBinManager::smBufferName ); if( texTarget ) { - passData.mTexType[ texIndex ] = Material::TexTarget; + // HACK: We store this for use in DeferredRTLightingFeatGLSL::processPix() + // which cannot deduce the texture unit itself. + mLastTexIndex = texIndex; + + passData.mTexType[ texIndex ] = Material::TexTarget; + passData.mSamplerNames[ texIndex ]= "lightInfoBuffer"; passData.mTexSlot[ texIndex++ ].texTarget = texTarget; } } @@ -205,92 +222,31 @@ void DeferredBumpFeatGLSL::processVert( Vector &componentLis // to the pixel shader. MultiLine *meta = new MultiLine; - // setup texture space matrix - Var *texSpaceMat = (Var*) LangElement::find( "objToTangentSpace" ); - if( !texSpaceMat ) - { - LangElement * texSpaceSetup = setupTexSpaceMat( componentList, &texSpaceMat ); - meta->addStatement( texSpaceSetup ); - texSpaceMat = (Var*) LangElement::find( "objToTangentSpace" ); - } - - // turn obj->tangent into world->tangent - Var *worldToTangent = new Var; - worldToTangent->setType( "mat3" ); - worldToTangent->setName( "worldToTangent" ); - LangElement *worldToTangentDecl = new DecOp( worldToTangent ); - - // Get the world->obj transform - Var *worldToObj = new Var; - worldToObj->setType( "mat4" ); - worldToObj->setName( "worldToObj" ); - worldToObj->uniform = true; - worldToObj->constSortPos = cspPrimitive; - - Var *mat3Conversion = new Var; - mat3Conversion->setType( "mat3" ); - mat3Conversion->setName( "worldToObjMat3" ); - LangElement* mat3Lang = new DecOp(mat3Conversion); - meta->addStatement( new GenOp( " @ = mat3(@[0].xyz, @[1].xyz, @[2].xyz);\r\n ", mat3Lang, worldToObj, worldToObj, worldToObj) ); - - // assign world->tangent transform - meta->addStatement( new GenOp( " @ = @ * @;\r\n", worldToTangentDecl, texSpaceMat, mat3Conversion ) ); - - // send transform to pixel shader - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - - Var *worldToTangentR1 = connectComp->getElement( RT_TEXCOORD ); - worldToTangentR1->setName( "worldToTangentR1" ); - worldToTangentR1->setType( "vec3" ); - meta->addStatement( new GenOp( " @ = @[0];\r\n", worldToTangentR1, worldToTangent ) ); - - Var *worldToTangentR2 = connectComp->getElement( RT_TEXCOORD ); - worldToTangentR2->setName( "worldToTangentR2" ); - worldToTangentR2->setType( "vec3" ); - meta->addStatement( new GenOp( " @ = @[1];\r\n", worldToTangentR2, worldToTangent ) ); - - Var *worldToTangentR3 = connectComp->getElement( RT_TEXCOORD ); - worldToTangentR3->setName( "worldToTangentR3" ); - worldToTangentR3->setType( "vec3" ); - meta->addStatement( new GenOp( " @ = @[2];\r\n", worldToTangentR3, worldToTangent ) ); + // We need the view to tangent space transform in the pixel shader. + getOutViewToTangent( componentList, meta, fd ); // Make sure there are texcoords - if( !fd.features[MFT_DiffuseMap] ) + if( !fd.features[MFT_Parallax] && !fd.features[MFT_DiffuseMap] ) { - // find incoming texture var - Var *inTex = getVertTexCoord( "texCoord" ); + const bool useTexAnim = fd.features[MFT_TexAnim]; - // grab connector texcoord register - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - Var *outTex = connectComp->getElement( RT_TEXCOORD ); - outTex->setName( "outTexCoord" ); - outTex->setType( "vec2" ); - outTex->mapsToSampler = true; + getOutTexCoord( "texCoord", + "vec2", + true, + useTexAnim, + meta, + componentList ); - if( fd.features[MFT_TexAnim] ) - { - inTex->setType( "vec4" ); - - // create texture mat var - Var *texMat = new Var; - texMat->setType( "mat4" ); - texMat->setName( "texMat" ); - texMat->uniform = true; - texMat->constSortPos = cspPotentialPrimitive; - - meta->addStatement( new GenOp( " @ = @ * @;\r\n", outTex, texMat, inTex ) ); - } - else - { - // setup language elements to output incoming tex coords to output - meta->addStatement( new GenOp( " @ = @;\r\n", outTex, inTex ) ); - } + if ( fd.features.hasFeature( MFT_DetailNormalMap ) ) + addOutDetailTexCoord( componentList, + meta, + useTexAnim ); } output = meta; } else if ( fd.materialFeatures[MFT_NormalsOut] || - fd.features[MFT_IsTranslucent] || + fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] ) { Parent::processVert( componentList, fd ); @@ -312,52 +268,12 @@ void DeferredBumpFeatGLSL::processPix( Vector &componentList, { MultiLine *meta = new MultiLine; - // Pull the world->tangent transform from the vertex shader - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - - Var *worldToTangentR1 = connectComp->getElement( RT_TEXCOORD ); - worldToTangentR1->setName( "worldToTangentR1" ); - worldToTangentR1->setType( "vec3" ); - - Var *worldToTangentR2 = connectComp->getElement( RT_TEXCOORD ); - worldToTangentR2->setName( "worldToTangentR2" ); - worldToTangentR2->setType( "vec3" ); - - Var *worldToTangentR3 = connectComp->getElement( RT_TEXCOORD ); - worldToTangentR3->setName( "worldToTangentR3" ); - worldToTangentR3->setType( "vec3" ); - - Var *worldToTangent = new Var; - worldToTangent->setType( "mat3" ); - worldToTangent->setName( "worldToTangent" ); - LangElement *worldToTangentDecl = new DecOp( worldToTangent ); - - // Build world->tangent matrix - meta->addStatement( new GenOp( " @;\r\n", worldToTangentDecl ) ); - meta->addStatement( new GenOp( " @[0] = @;\r\n", worldToTangent, worldToTangentR1 ) ); - meta->addStatement( new GenOp( " @[1] = @;\r\n", worldToTangent, worldToTangentR2 ) ); - meta->addStatement( new GenOp( " @[2] = @;\r\n", worldToTangent, worldToTangentR3 ) ); + Var *viewToTangent = getInViewToTangent( componentList ); // create texture var - Var *bumpMap = new Var; - bumpMap->setType( "sampler2D" ); - bumpMap->setName( "bumpMap" ); - bumpMap->uniform = true; - bumpMap->sampler = true; - bumpMap->constNum = Var::getTexUnitNum(); // used as texture unit num here - - Var *texCoord = (Var*) LangElement::find( "outTexCoord" ); - if( !texCoord ) - { - // grab connector texcoord register - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - texCoord = connectComp->getElement( RT_TEXCOORD ); - texCoord->setName( "outTexCoord" ); - texCoord->setType( "vec2" ); - texCoord->mapsToSampler = true; - } - - LangElement * texOp = new GenOp( "texture2D(@, @)", bumpMap, texCoord ); + Var *bumpMap = getNormalMapTex(); + Var *texCoord = getInTexCoord( "texCoord", "vec2", true, componentList ); + LangElement *texOp = new GenOp( "tex2D(@, @)", bumpMap, texCoord ); // create bump normal Var *bumpNorm = new Var; @@ -367,56 +283,75 @@ void DeferredBumpFeatGLSL::processPix( Vector &componentList, LangElement *bumpNormDecl = new DecOp( bumpNorm ); meta->addStatement( expandNormalMap( texOp, bumpNormDecl, bumpNorm, fd ) ); + // If we have a detail normal map we add the xy coords of + // it to the base normal map. This gives us the effect we + // want with few instructions and minial artifacts. + if ( fd.features.hasFeature( MFT_DetailNormalMap ) ) + { + bumpMap = new Var; + bumpMap->setType( "sampler2D" ); + bumpMap->setName( "detailBumpMap" ); + bumpMap->uniform = true; + bumpMap->sampler = true; + bumpMap->constNum = Var::getTexUnitNum(); + + texCoord = getInTexCoord( "detCoord", "vec2", true, componentList ); + texOp = new GenOp( "tex2D(@, @)", bumpMap, texCoord ); + + Var *detailBump = new Var; + detailBump->setName( "detailBump" ); + detailBump->setType( "vec4" ); + meta->addStatement( expandNormalMap( texOp, new DecOp( detailBump ), detailBump, fd ) ); + + Var *detailBumpScale = new Var; + detailBumpScale->setType( "float" ); + detailBumpScale->setName( "detailBumpStrength" ); + detailBumpScale->uniform = true; + detailBumpScale->constSortPos = cspPass; + meta->addStatement( new GenOp( " @.xy += @.xy * @;\r\n", bumpNorm, detailBump, detailBumpScale ) ); + } + // This var is read from GBufferConditionerHLSL and // used in the prepass output. + // + // By using the 'half' type here we get a bunch of partial + // precision optimized code on further operations on the normal + // which helps alot on older Geforce cards. + // Var *gbNormal = new Var; gbNormal->setName( "gbNormal" ); - gbNormal->setType( "vec3" ); + gbNormal->setType( "half3" ); LangElement *gbNormalDecl = new DecOp( gbNormal ); // Normalize is done later... // Note: The reverse mul order is intentional. Affine matrix. - meta->addStatement( new GenOp( " @ = @.xyz * @;\r\n", gbNormalDecl, bumpNorm, worldToTangent ) ); + meta->addStatement( new GenOp( " @ = half3(tMul( @.xyz, @ ));\r\n", gbNormalDecl, bumpNorm, viewToTangent ) ); output = meta; return; } else if ( fd.materialFeatures[MFT_NormalsOut] || - fd.features[MFT_IsTranslucent] || + fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] ) { Parent::processPix( componentList, fd ); return; } - else if ( fd.features[MFT_PixSpecular] ) + else if ( fd.features[MFT_PixSpecular] && !fd.features[MFT_SpecularMap] ) { Var *bumpSample = (Var *)LangElement::find( "bumpSample" ); if( bumpSample == NULL ) { - Var *texCoord = (Var*) LangElement::find( "outTexCoord" ); - if( !texCoord ) - { - // grab connector texcoord register - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - texCoord = connectComp->getElement( RT_TEXCOORD ); - texCoord->setName( "outTexCoord" ); - texCoord->setType( "vec2" ); - texCoord->mapsToSampler = true; - } + Var *texCoord = getInTexCoord( "texCoord", "vec2", true, componentList ); - Var *bumpMap = new Var; - bumpMap->setType( "sampler2D" ); - bumpMap->setName( "bumpMap" ); - bumpMap->uniform = true; - bumpMap->sampler = true; - bumpMap->constNum = Var::getTexUnitNum(); // used as texture unit num here + Var *bumpMap = getNormalMapTex(); bumpSample = new Var; bumpSample->setType( "vec4" ); bumpSample->setName( "bumpSample" ); LangElement *bumpSampleDecl = new DecOp( bumpSample ); - output = new GenOp( " @ = texture2D(@, @);\r\n", bumpSampleDecl, bumpMap, texCoord ); + output = new GenOp( " @ = tex2D(@, @);\r\n", bumpSampleDecl, bumpMap, texCoord ); return; } } @@ -427,7 +362,7 @@ void DeferredBumpFeatGLSL::processPix( Vector &componentList, ShaderFeature::Resources DeferredBumpFeatGLSL::getResources( const MaterialFeatureData &fd ) { if ( fd.materialFeatures[MFT_NormalsOut] || - fd.features[MFT_IsTranslucent] || + fd.features[MFT_ForwardShading] || fd.features[MFT_Parallax] || !fd.features[MFT_RTLighting] ) return Parent::getResources( fd ); @@ -437,7 +372,16 @@ ShaderFeature::Resources DeferredBumpFeatGLSL::getResources( const MaterialFeatu { res.numTex = 1; res.numTexReg = 1; + + if ( fd.features[MFT_PrePassConditioner] && + fd.features.hasFeature( MFT_DetailNormalMap ) ) + { + res.numTex += 1; + if ( !fd.features.hasFeature( MFT_DetailMap ) ) + res.numTexReg += 1; + } } + return res; } @@ -447,21 +391,28 @@ void DeferredBumpFeatGLSL::setTexData( Material::StageData &stageDat, U32 &texIndex ) { if ( fd.materialFeatures[MFT_NormalsOut] || - fd.features[MFT_IsTranslucent] || + fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] ) { Parent::setTexData( stageDat, fd, passData, texIndex ); return; } - GFXTextureObject *normalMap = stageDat.getTex( MFT_NormalMap ); if ( !fd.features[MFT_Parallax] && !fd.features[MFT_SpecularMap] && ( fd.features[MFT_PrePassConditioner] || - fd.features[MFT_PixSpecular] ) && - normalMap ) + fd.features[MFT_PixSpecular] ) ) { passData.mTexType[ texIndex ] = Material::Bump; - passData.mTexSlot[ texIndex++ ].texObject = normalMap; + passData.mSamplerNames[ texIndex ] = "bumpMap"; + passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_NormalMap ); + + if ( fd.features[MFT_PrePassConditioner] && + fd.features.hasFeature( MFT_DetailNormalMap ) ) + { + passData.mTexType[ texIndex ] = Material::DetailBump; + passData.mSamplerNames[ texIndex ] = "detailBumpMap"; + passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_DetailNormalMap ); + } } } @@ -469,7 +420,7 @@ void DeferredBumpFeatGLSL::setTexData( Material::StageData &stageDat, void DeferredPixelSpecularGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { - if( fd.features[MFT_IsTranslucent] || !fd.features[MFT_RTLighting] ) + if( fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] ) { Parent::processVert( componentList, fd ); return; @@ -480,7 +431,7 @@ void DeferredPixelSpecularGLSL::processVert( Vector &component void DeferredPixelSpecularGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { - if( fd.features[MFT_IsTranslucent] || !fd.features[MFT_RTLighting] ) + if( fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] ) { Parent::processPix( componentList, fd ); return; @@ -523,19 +474,18 @@ void DeferredPixelSpecularGLSL::processPix( Vector &component specStrength->uniform = true; specStrength->constSortPos = cspPotentialPrimitive; - Var *constSpecPow = new Var; - constSpecPow->setType( "float" ); - constSpecPow->setName( "constantSpecularPower" ); - constSpecPow->uniform = true; - constSpecPow->constSortPos = cspPass; - Var *lightInfoSamp = (Var *)LangElement::find( "lightInfoSample" ); - AssertFatal( lightInfoSamp, "Something hosed the deferred features! Can't find lightInfoSample" ); + Var *d_specular = (Var*)LangElement::find( "d_specular" ); + Var *d_NL_Att = (Var*)LangElement::find( "d_NL_Att" ); + + AssertFatal( lightInfoSamp && d_specular && d_NL_Att, + "DeferredPixelSpecularGLSL::processPix - Something hosed the deferred features!" ); // (a^m)^n = a^(m*n) - meta->addStatement( new GenOp( " @ = pow(d_specular, ceil(@ / @)) * @;\r\n", specDecl, specPow, constSpecPow, specStrength ) ); + meta->addStatement( new GenOp( " @ = pow( abs(@), max((@ / AL_ConstantSpecularPower),1.0f)) * @;\r\n", + specDecl, d_specular, specPow, specStrength ) ); - LangElement *specMul = new GenOp( "@ * @", specCol, specular ); + LangElement *specMul = new GenOp( "float4( @.rgb, 0 ) * @", specCol, specular ); LangElement *final = specMul; // We we have a normal map then mask the specular @@ -545,14 +495,15 @@ void DeferredPixelSpecularGLSL::processPix( Vector &component final = new GenOp( "@ * @.a", final, bumpSample ); } - // add to color meta->addStatement( new GenOp( " @;\r\n", assignColor( final, Material::Add ) ) ); + // add to color + meta->addStatement( new GenOp( " @;\r\n", assignColor( final, Material::Add ) ) ); output = meta; } ShaderFeature::Resources DeferredPixelSpecularGLSL::getResources( const MaterialFeatureData &fd ) { - if( fd.features[MFT_IsTranslucent] || !fd.features[MFT_RTLighting] ) + if( fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] ) return Parent::getResources( fd ); Resources res; @@ -563,7 +514,7 @@ ShaderFeature::Resources DeferredPixelSpecularGLSL::getResources( const Material ShaderFeature::Resources DeferredMinnaertGLSL::getResources( const MaterialFeatureData &fd ) { Resources res; - if( !fd.features[MFT_IsTranslucent] && fd.features[MFT_RTLighting] ) + if( !fd.features[MFT_ForwardShading] && fd.features[MFT_RTLighting] ) { res.numTex = 1; res.numTexReg = 1; @@ -576,7 +527,7 @@ void DeferredMinnaertGLSL::setTexData( Material::StageData &stageDat, RenderPassData &passData, U32 &texIndex ) { - if( !fd.features[MFT_IsTranslucent] && fd.features[MFT_RTLighting] ) + if( !fd.features[MFT_ForwardShading] && fd.features[MFT_RTLighting] ) { NamedTexTarget *texTarget = NamedTexTarget::find(RenderPrePassMgr::BufferName); if ( texTarget ) @@ -590,7 +541,7 @@ void DeferredMinnaertGLSL::setTexData( Material::StageData &stageDat, void DeferredMinnaertGLSL::processPixMacros( Vector ¯os, const MaterialFeatureData &fd ) { - if( !fd.features[MFT_IsTranslucent] && fd.features[MFT_RTLighting] ) + if( !fd.features[MFT_ForwardShading] && fd.features[MFT_RTLighting] ) { // Pull in the uncondition method for the g buffer NamedTexTarget *texTarget = NamedTexTarget::find( RenderPrePassMgr::BufferName ); @@ -607,55 +558,24 @@ void DeferredMinnaertGLSL::processVert( Vector &componentLis const MaterialFeatureData &fd ) { // If there is no deferred information, bail on this feature - if( fd.features[MFT_IsTranslucent] || !fd.features[MFT_RTLighting] ) + if( fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] ) { output = NULL; return; } - // grab incoming vert position - Var *inVertPos = (Var*) LangElement::find( "position" ); - AssertFatal( inVertPos, "Something went bad with ShaderGen. The vertex position should be already defined." ); - - // grab output for gbuffer normal - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - Var *outWSEyeVec= connectComp->getElement( RT_TEXCOORD ); - outWSEyeVec->setName( "outWSViewVec" ); - outWSEyeVec->setType( "vec4" ); - - // create objToWorld variable - Var *objToWorld = (Var*) LangElement::find( "objTrans" ); - if( !objToWorld ) - { - objToWorld = new Var; - objToWorld->setType( "mat4x4" ); - objToWorld->setName( "objTrans" ); - objToWorld->uniform = true; - objToWorld->constSortPos = cspPrimitive; - } - - // Eye Pos world - Var *eyePosWorld = (Var*) LangElement::find( "eyePosWorld" ); - if( !eyePosWorld ) - { - eyePosWorld = new Var; - eyePosWorld->setType( "vec3" ); - eyePosWorld->setName( "eyePosWorld" ); - eyePosWorld->uniform = true; - eyePosWorld->constSortPos = cspPass; - } - - // Kick out the world-space normal - LangElement *statement = new GenOp( " @ = vec4(@, @) - vec4(@, 0.0);\r\n", - outWSEyeVec, objToWorld, inVertPos, eyePosWorld ); - output = statement; + // Make sure we pass the world space position to the + // pixel shader so we can calculate a view vector. + MultiLine *meta = new MultiLine; + addOutWsPosition( componentList, fd.features[MFT_UseInstancing], meta ); + output = meta; } void DeferredMinnaertGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { // If there is no deferred information, bail on this feature - if( fd.features[MFT_IsTranslucent] || !fd.features[MFT_RTLighting] ) + if( fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] ) { output = NULL; return; @@ -679,25 +599,19 @@ void DeferredMinnaertGLSL::processPix( Vector &componentList, Var *uvScene = (Var*) LangElement::find( "uvScene" ); AssertFatal(uvScene != NULL, "Unable to find UVScene, no RTLighting feature?"); - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - Var *wsViewVec = (Var*) LangElement::find( "wsPos" ); - if( !wsViewVec ) - { - wsViewVec = connectComp->getElement( RT_TEXCOORD ); - wsViewVec->setName( "outWSViewVec" ); - wsViewVec->setType( "vec4" ); - wsViewVec->mapsToSampler = false; - wsViewVec->uniform = false; - } + MultiLine *meta = new MultiLine; + + // Get the world space view vector. + Var *wsViewVec = getWsView( getInWsPosition( componentList ), meta ); String unconditionPrePassMethod = String::ToLower(RenderPrePassMgr::BufferName) + "Uncondition"; - MultiLine *meta = new MultiLine; - meta->addStatement( new GenOp( avar( " vec4 normalDepth = %s(texture2D(@, @));\r\n", unconditionPrePassMethod.c_str() ), prepassBuffer, uvScene ) ); - meta->addStatement( new GenOp( " vec3 worldViewVec = normalize(@.xyz / @.w);\r\n", wsViewVec, wsViewVec ) ); - meta->addStatement( new GenOp( " float vDotN = dot(normalDepth.xyz, worldViewVec);\r\n" ) ); - meta->addStatement( new GenOp( " float Minnaert = pow(d_NL_Att, @) * pow(vDotN, 1.0 - @);\r\n", minnaertConstant, minnaertConstant ) ); - meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "vec4(Minnaert, Minnaert, Minnaert, 1.0)" ), Material::Mul ) ) ); + Var *d_NL_Att = (Var*)LangElement::find( "d_NL_Att" ); + + meta->addStatement( new GenOp( avar( " float4 normalDepth = %s(@, @);\r\n", unconditionPrePassMethod.c_str() ), prepassBuffer, uvScene ) ); + meta->addStatement( new GenOp( " float vDotN = dot(normalDepth.xyz, @);\r\n", wsViewVec ) ); + meta->addStatement( new GenOp( " float Minnaert = pow( @, @) * pow(vDotN, 1.0 - @);\r\n", d_NL_Att, minnaertConstant, minnaertConstant ) ); + meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "float4(Minnaert, Minnaert, Minnaert, 1.0)" ), Material::Mul ) ) ); output = meta; } @@ -707,7 +621,7 @@ void DeferredSubSurfaceGLSL::processPix( Vector &componentLis const MaterialFeatureData &fd ) { // If there is no deferred information, bail on this feature - if( fd.features[MFT_IsTranslucent] || !fd.features[MFT_RTLighting] ) + if( fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] ) { output = NULL; return; @@ -719,12 +633,13 @@ void DeferredSubSurfaceGLSL::processPix( Vector &componentLis subSurfaceParams->uniform = true; subSurfaceParams->constSortPos = cspPotentialPrimitive; - Var *inColor = (Var*) LangElement::find( "rtShading" ); + Var *d_lightcolor = (Var*)LangElement::find( "d_lightcolor" ); + Var *d_NL_Att = (Var*)LangElement::find( "d_NL_Att" ); MultiLine *meta = new MultiLine; - meta->addStatement( new GenOp( " float subLamb = smoothstep(-@.a, 1.0, d_NL_Att) - smoothstep(0.0, 1.0, d_NL_Att);\r\n", subSurfaceParams ) ); + meta->addStatement( new GenOp( " float subLamb = smoothstep(-@.a, 1.0, @) - smoothstep(0.0, 1.0, @);\r\n", subSurfaceParams, d_NL_Att, d_NL_Att ) ); meta->addStatement( new GenOp( " subLamb = max(0.0, subLamb);\r\n" ) ); - meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "vec4(@.rgb + (subLamb * @.rgb), 1.0)", inColor, subSurfaceParams ), Material::Mul ) ) ); + meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "float4(@ + (subLamb * @.rgb), 1.0)", d_lightcolor, subSurfaceParams ), Material::Mul ) ) ); output = meta; } diff --git a/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.h b/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.h index fb37848a8..0e326de6a 100644 --- a/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.h +++ b/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.h @@ -30,13 +30,25 @@ class ConditionerMethodDependency; -/// Lights the pixel by sampling from the light prepass buffer. It will -/// fall back to default vertex lighting functionality if +/// Lights the pixel by sampling from the light prepass +/// buffer. It will fall back to forward lighting +/// functionality for non-deferred rendered surfaces. +/// +/// Also note that this feature is only used in the +/// forward rendering pass. It is not used during the +/// prepass step. +/// class DeferredRTLightingFeatGLSL : public RTLightingFeatGLSL { typedef RTLightingFeatGLSL Parent; +protected: + + /// @see DeferredRTLightingFeatHLSL::processPix() + U32 mLastTexIndex; + public: + virtual void processVert( Vector &componentList, const MaterialFeatureData &fd ); @@ -57,12 +69,12 @@ public: virtual String getName() { - return "Deferred RT Lighting Feature"; + return "Deferred RT Lighting"; } }; -/// Used to write the normals during the depth/normal prepass. +/// This is used during the class DeferredBumpFeatGLSL : public BumpFeatGLSL { typedef BumpFeatGLSL Parent; diff --git a/Engine/source/lighting/advanced/glsl/gBufferConditionerGLSL.cpp b/Engine/source/lighting/advanced/glsl/gBufferConditionerGLSL.cpp index fd3b27d85..17a98c969 100644 --- a/Engine/source/lighting/advanced/glsl/gBufferConditionerGLSL.cpp +++ b/Engine/source/lighting/advanced/glsl/gBufferConditionerGLSL.cpp @@ -27,9 +27,10 @@ #include "gfx/gfxStringEnumTranslate.h" #include "materials/materialFeatureTypes.h" #include "materials/materialFeatureData.h" +#include "shaderGen/GLSL/shaderFeatureGLSL.h" -GBufferConditionerGLSL::GBufferConditionerGLSL( const GFXFormat bufferFormat ) : +GBufferConditionerGLSL::GBufferConditionerGLSL( const GFXFormat bufferFormat, const NormalSpace nrmSpace ) : Parent( bufferFormat ) { // Figure out how we should store the normal data. These are the defaults. @@ -39,20 +40,18 @@ GBufferConditionerGLSL::GBufferConditionerGLSL( const GFXFormat bufferFormat ) : // Note: We clear to a depth 1 (the w component) so // that the unrendered parts of the scene end up // farthest to the camera. - + const NormalStorage &twoCmpNrmStorageType = ( nrmSpace == WorldSpace ? Spherical : LambertAzimuthal ); switch(bufferFormat) { case GFXFormatR8G8B8A8: - // TODO: Some kind of logic here. Spherical is better, but is more - // expensive. - mNormalStorageType = Spherical; + mNormalStorageType = twoCmpNrmStorageType; mBitsPerChannel = 8; break; case GFXFormatR16G16B16A16F: // Floating point buffers don't need to encode negative values mCanWriteNegativeValues = true; - mNormalStorageType = Spherical; + mNormalStorageType = twoCmpNrmStorageType; mBitsPerChannel = 16; break; @@ -61,7 +60,7 @@ GBufferConditionerGLSL::GBufferConditionerGLSL( const GFXFormat bufferFormat ) : // precision and high quality normals within a 64bit // buffer format. case GFXFormatR16G16B16A16: - mNormalStorageType = Spherical; + mNormalStorageType = twoCmpNrmStorageType; mBitsPerChannel = 16; break; @@ -83,34 +82,43 @@ GBufferConditionerGLSL::~GBufferConditionerGLSL() void GBufferConditionerGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { - output = NULL; + // If we have a normal map then that feature will + // take care of passing gbNormal to the pixel shader. + if ( fd.features[MFT_NormalMap] ) + return; - if( !fd.features[MFT_NormalMap] ) + MultiLine *meta = new MultiLine; + output = meta; + + // grab incoming vert normal + Var *inNormal = (Var*) LangElement::find( "normal" ); + AssertFatal( inNormal, "Something went bad with ShaderGen. The normal should be already defined." ); + + // grab output for gbuffer normal + ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); + Var *outNormal = connectComp->getElement( RT_TEXCOORD ); + outNormal->setName( "gbNormal" ); + outNormal->setStructName( "OUT" ); + outNormal->setType( "float3" ); + + if( !fd.features[MFT_ParticleNormal] ) { - // grab incoming vert normal - Var *inNormal = (Var*) LangElement::find( "normal" ); - AssertFatal( inNormal, "Something went bad with ShaderGen. The normal should be already defined." ); + // Kick out the view-space normal - // grab output for gbuffer normal - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - Var *outNormal = connectComp->getElement( RT_TEXCOORD ); - outNormal->setName( "gbNormal" ); - outNormal->setType( "vec3" ); + // TODO: Total hack because Conditioner is directly derived + // from ShaderFeature and not from ShaderFeatureGLSL. + NamedFeatureGLSL dummy( String::EmptyString ); + dummy.mInstancingFormat = mInstancingFormat; + Var *worldViewOnly = dummy.getWorldView( componentList, fd.features[MFT_UseInstancing], meta ); - // create objToWorld variable - Var *objToWorld = (Var*) LangElement::find( "objTrans" ); - if( !objToWorld ) - { - objToWorld = new Var; - objToWorld->setType( "mat4" ); - objToWorld->setName( "objTrans" ); - objToWorld->uniform = true; - objToWorld->constSortPos = cspPrimitive; - } - - // Kick out the world-space normal - LangElement *statement = new GenOp( " @ = vec3(@ * vec4(normalize(@), 0.0));\r\n", outNormal, objToWorld, inNormal ); - output = statement; + meta->addStatement( new GenOp(" @ = tMul(@, float4( normalize(@), 0.0 ) ).xyz;\r\n", + outNormal, worldViewOnly, inNormal ) ); + } + else + { + // Assume the particle normal generator has already put this in view space + // and normalized it + meta->addStatement( new GenOp( " @ = @;\r\n", outNormal, inNormal ) ); } } @@ -129,7 +137,8 @@ void GBufferConditionerGLSL::processPix( Vector &componentLis { gbNormal = connectComp->getElement( RT_TEXCOORD ); gbNormal->setName( "gbNormal" ); - gbNormal->setType( "vec3" ); + gbNormal->setStructName( "IN" ); + gbNormal->setType( "float3" ); gbNormal->mapsToSampler = false; gbNormal->uniform = false; } @@ -143,16 +152,45 @@ void GBufferConditionerGLSL::processPix( Vector &componentLis Var *unconditionedOut = new Var; - unconditionedOut->setType("vec4"); + unconditionedOut->setType("float4"); unconditionedOut->setName("normal_depth"); LangElement *outputDecl = new DecOp( unconditionedOut ); + // If we're doing prepass blending then we need + // to steal away the alpha channel before the + // conditioner stomps on it. + Var *alphaVal = NULL; + if ( fd.features[ MFT_IsTranslucentZWrite ] ) + { + alphaVal = new Var( "outAlpha", "float" ); + meta->addStatement( new GenOp( " @ = col.a; // MFT_IsTranslucentZWrite\r\n", new DecOp( alphaVal ) ) ); + } + + // If using interlaced normals, invert the normal + if(fd.features[MFT_InterlacedPrePass]) + { + // NOTE: Its safe to not call ShaderFeatureGLSL::addOutVpos() in the vertex + // shader as for SM 3.0 nothing is needed there. + Var *Vpos = (Var*) LangElement::find( "gl_Position" ); //Var *Vpos = ShaderFeatureGLSL::getInVpos( meta, componentList ); + + Var *iGBNormal = new Var( "interlacedGBNormal", "float3" ); + meta->addStatement(new GenOp(" @ = (frac(@.y * 0.5) < 0.1 ? reflect(@, float3(0.0, -1.0, 0.0)) : @);\r\n", new DecOp(iGBNormal), Vpos, gbNormal, gbNormal)); + gbNormal = iGBNormal; + } + // NOTE: We renormalize the normal here as they // will not stay normalized during interpolation. - meta->addStatement( new GenOp(" @ = @;", outputDecl, new GenOp( "vec4(normalize(@), @)", gbNormal, depth ) ) ); + meta->addStatement( new GenOp(" @ = @;", outputDecl, new GenOp( "float4(normalize(@), @)", gbNormal, depth ) ) ); meta->addStatement( assignOutput( unconditionedOut ) ); + // If we have an alpha var then we're doing prepass lerp blending. + if ( alphaVal ) + { + Var *outColor = (Var*)LangElement::find( getOutputTargetVarName( DefaultTarget ) ); + meta->addStatement( new GenOp( " @.ba = float2( 0, @ ); // MFT_IsTranslucentZWrite\r\n", outColor, alphaVal ) ); + } + output = meta; } @@ -180,7 +218,7 @@ Var* GBufferConditionerGLSL::printMethodHeader( MethodType methodType, const Str { Var *methodVar = new Var; methodVar->setName(methodName); - methodVar->setType("vec4"); + methodVar->setType("float4"); DecOp *methodDecl = new DecOp(methodVar); Var *prepassSampler = new Var; @@ -190,12 +228,12 @@ Var* GBufferConditionerGLSL::printMethodHeader( MethodType methodType, const Str Var *screenUV = new Var; screenUV->setName("screenUVVar"); - screenUV->setType("vec2"); + screenUV->setType("float2"); DecOp *screenUVDecl = new DecOp(screenUV); Var *bufferSample = new Var; bufferSample->setName("bufferSample"); - bufferSample->setType("vec4"); + bufferSample->setType("float4"); DecOp *bufferSampleDecl = new DecOp(bufferSample); meta->addStatement( new GenOp( "@(@, @)\r\n", methodDecl, prepassSamplerDecl, screenUVDecl ) ); @@ -204,9 +242,18 @@ Var* GBufferConditionerGLSL::printMethodHeader( MethodType methodType, const Str meta->addStatement( new GenOp( " // Sampler g-buffer\r\n" ) ); +#ifdef TORQUE_OS_XENON + meta->addStatement( new GenOp( " @;\r\n", bufferSampleDecl ) ); + meta->addStatement( new GenOp( " asm { tfetch2D @, @, @, MagFilter = point, MinFilter = point, MipFilter = point };\r\n", bufferSample, screenUV, prepassSampler ) ); +#else // The gbuffer has no mipmaps, so use tex2dlod when - // so that the shader compiler can optimize. - meta->addStatement( new GenOp( " @ = texture2DLod(@, @, 0.0);\r\n", bufferSampleDecl, prepassSampler, screenUV ) ); + // possible so that the shader compiler can optimize. + meta->addStatement( new GenOp( " #if TORQUE_SM >= 30\r\n" ) ); + meta->addStatement( new GenOp( " @ = tex2Dlod(@, float4(@,0,0));\r\n", bufferSampleDecl, prepassSampler, screenUV ) ); + meta->addStatement( new GenOp( " #else\r\n" ) ); + meta->addStatement( new GenOp( " @ = tex2D(@, @);\r\n", bufferSampleDecl, prepassSampler, screenUV ) ); + meta->addStatement( new GenOp( " #endif\r\n\r\n" ) ); +#endif // We don't use this way of passing var's around, so this should cause a crash // if something uses this improperly @@ -218,39 +265,67 @@ Var* GBufferConditionerGLSL::printMethodHeader( MethodType methodType, const Str GenOp* GBufferConditionerGLSL::_posnegEncode( GenOp *val ) { - return mCanWriteNegativeValues ? val : new GenOp("0.5 * (@ + 1.0)", val); + if(mNormalStorageType == LambertAzimuthal) + return mCanWriteNegativeValues ? val : new GenOp(avar("(%f * (@ + %f))", 1.0f/(M_SQRT2_F * 2.0f), M_SQRT2_F), val); + else + return mCanWriteNegativeValues ? val : new GenOp("(0.5 * (@ + 1.0))", val); } GenOp* GBufferConditionerGLSL::_posnegDecode( GenOp *val ) { - return mCanWriteNegativeValues ? val : new GenOp("@ * 2.0 - 1.0", val); + if(mNormalStorageType == LambertAzimuthal) + return mCanWriteNegativeValues ? val : new GenOp(avar("(@ * %f - %f)", M_SQRT2_F * 2.0f, M_SQRT2_F), val); + else + return mCanWriteNegativeValues ? val : new GenOp("(@ * 2.0 - 1.0)", val); } Var* GBufferConditionerGLSL::_conditionOutput( Var *unconditionedOutput, MultiLine *meta ) { Var *retVar = new Var; - retVar->setType("vec4"); + retVar->setType("float4"); retVar->setName("_gbConditionedOutput"); LangElement *outputDecl = new DecOp( retVar ); switch(mNormalStorageType) { case CartesianXYZ: - meta->addStatement( new GenOp( " // g-buffer conditioner: vec4(normal.xyz, depth)\r\n" ) ); - meta->addStatement( new GenOp( " @ = vec4(@, @.a);\r\n", outputDecl, + meta->addStatement( new GenOp( " // g-buffer conditioner: float4(normal.xyz, depth)\r\n" ) ); + meta->addStatement( new GenOp( " @ = float4(@, @.a);\r\n", outputDecl, _posnegEncode(new GenOp("@.xyz", unconditionedOutput)), unconditionedOutput ) ); break; case CartesianXY: - meta->addStatement( new GenOp( " // g-buffer conditioner: vec4(normal.xy, depth Hi + z-sign, depth Lo)\r\n" ) ); - meta->addStatement( new GenOp( " @ = vec4(@, @.a);", outputDecl, - _posnegEncode(new GenOp("vec3(@.xy, sign(@.z))", unconditionedOutput, unconditionedOutput)), unconditionedOutput ) ); + meta->addStatement( new GenOp( " // g-buffer conditioner: float4(normal.xy, depth Hi + z-sign, depth Lo)\r\n" ) ); + meta->addStatement( new GenOp( " @ = float4(@, @.a);", outputDecl, + _posnegEncode(new GenOp("float3(@.xy, sign(@.z))", unconditionedOutput, unconditionedOutput)), unconditionedOutput ) ); break; case Spherical: - meta->addStatement( new GenOp( " // g-buffer conditioner: vec4(normal.theta, normal.phi, depth Hi, depth Lo)\r\n" ) ); - meta->addStatement( new GenOp( " @ = vec4(@, 0.0, @.a);\r\n", outputDecl, - _posnegEncode(new GenOp("vec2(atan2(@.y, @.x) / 3.14159265358979323846f, @.z)", unconditionedOutput, unconditionedOutput, unconditionedOutput ) ), + meta->addStatement( new GenOp( " // g-buffer conditioner: float4(normal.theta, normal.phi, depth Hi, depth Lo)\r\n" ) ); + meta->addStatement( new GenOp( " @ = float4(@, 0.0, @.a);\r\n", outputDecl, + _posnegEncode(new GenOp("float2(atan2(@.y, @.x) / 3.14159265358979323846f, @.z)", unconditionedOutput, unconditionedOutput, unconditionedOutput ) ), + unconditionedOutput ) ); + + // HACK: This fixes the noise present when using a floating point + // gbuffer on Geforce cards and the "flat areas unlit" issues. + // + // We need work around atan2() above to fix this issue correctly + // without the extra overhead of this test. + // + meta->addStatement( new GenOp( " if ( abs( dot( @.xyz, float3( 0.0, 0.0, 1.0 ) ) ) > 0.999f ) @ = float4( 0, 1 * sign( @.z ), 0, @.a );\r\n", + unconditionedOutput, retVar, unconditionedOutput, unconditionedOutput ) ); + break; + + case LambertAzimuthal: + //http://en.wikipedia.org/wiki/Lambert_azimuthal_equal-area_projection + // + // Note we're casting to half to use partial precision + // sqrt which is much faster on older Geforces while + // still being acceptable for normals. + // + meta->addStatement( new GenOp( " // g-buffer conditioner: float4(normal.X, normal.Y, depth Hi, depth Lo)\r\n" ) ); + meta->addStatement( new GenOp( " @ = float4(@, 0.0, @.a);\r\n", outputDecl, + _posnegEncode(new GenOp("sqrt(half(2.0/(1.0 - @.y))) * half2(@.xz)", unconditionedOutput, unconditionedOutput)), unconditionedOutput ) ); break; } @@ -259,11 +334,10 @@ Var* GBufferConditionerGLSL::_conditionOutput( Var *unconditionedOutput, MultiLi if(mNormalStorageType != CartesianXYZ) { const U64 maxValPerChannel = 1 << mBitsPerChannel; - const U64 extraVal = (maxValPerChannel * maxValPerChannel - 1) - (maxValPerChannel - 1) * 2; meta->addStatement( new GenOp( " \r\n // Encode depth into hi/lo\r\n" ) ); - meta->addStatement( new GenOp( avar( " vec3 _tempDepth = fract(@.a * vec3(1.0, %llu.0, %llu.0));\r\n", maxValPerChannel - 1, extraVal ), + meta->addStatement( new GenOp( avar( " float2 _tempDepth = frac(@.a * float2(1.0, %llu.0));\r\n", maxValPerChannel - 1 ), unconditionedOutput ) ); - meta->addStatement( new GenOp( avar( " @.zw = _tempDepth.xy - _tempDepth.yz * vec2(1.0/%llu.0, 1.0/%llu.0);\r\n\r\n", maxValPerChannel - 1, maxValPerChannel - 1 ), + meta->addStatement( new GenOp( avar( " @.zw = _tempDepth.xy - _tempDepth.yy * float2(1.0/%llu.0, 0.0);\r\n\r\n", maxValPerChannel - 1 ), retVar ) ); } @@ -274,33 +348,43 @@ Var* GBufferConditionerGLSL::_conditionOutput( Var *unconditionedOutput, MultiLi Var* GBufferConditionerGLSL::_unconditionInput( Var *conditionedInput, MultiLine *meta ) { Var *retVar = new Var; - retVar->setType("vec4"); + retVar->setType("float4"); retVar->setName("_gbUnconditionedInput"); LangElement *outputDecl = new DecOp( retVar ); switch(mNormalStorageType) { case CartesianXYZ: - meta->addStatement( new GenOp( " // g-buffer unconditioner: vec4(normal.xyz, depth)\r\n" ) ); - meta->addStatement( new GenOp( " @ = vec4(@, @.a);\r\n", outputDecl, + meta->addStatement( new GenOp( " // g-buffer unconditioner: float4(normal.xyz, depth)\r\n" ) ); + meta->addStatement( new GenOp( " @ = float4(@, @.a);\r\n", outputDecl, _posnegDecode(new GenOp("@.xyz", conditionedInput)), conditionedInput ) ); break; case CartesianXY: - meta->addStatement( new GenOp( " // g-buffer unconditioner: vec4(normal.xy, depth Hi + z-sign, depth Lo)\r\n" ) ); - meta->addStatement( new GenOp( " @ = vec4(@, @.a);\r\n", outputDecl, + meta->addStatement( new GenOp( " // g-buffer unconditioner: float4(normal.xy, depth Hi + z-sign, depth Lo)\r\n" ) ); + meta->addStatement( new GenOp( " @ = float4(@, @.a);\r\n", outputDecl, _posnegDecode(new GenOp("@.xyz", conditionedInput)), conditionedInput ) ); meta->addStatement( new GenOp( " @.z *= sqrt(1.0 - dot(@.xy, @.xy));\r\n", retVar, retVar, retVar ) ); break; case Spherical: - meta->addStatement( new GenOp( " // g-buffer unconditioner: vec4(normal.theta, normal.phi, depth Hi, depth Lo)\r\n" ) ); - meta->addStatement( new GenOp( " vec2 spGPUAngles = @;\r\n", _posnegDecode(new GenOp("@.xy", conditionedInput)) ) ); - meta->addStatement( new GenOp( " vec2 sincosTheta;\r\n" ) ); - meta->addStatement( new GenOp( " sincosTheta.x = sin(spGPUAngles.x * 3.14159265358979323846);\r\n" ) ); - meta->addStatement( new GenOp( " sincosTheta.y = cos(spGPUAngles.x * 3.14159265358979323846);\r\n" ) ); - meta->addStatement( new GenOp( " vec2 sincosPhi = vec2(sqrt(1.0 - spGPUAngles.y * spGPUAngles.y), spGPUAngles.y);\r\n" ) ); - meta->addStatement( new GenOp( " @ = vec4(sincosTheta.y * sincosPhi.x, sincosTheta.x * sincosPhi.x, sincosPhi.y, @.a);\r\n", outputDecl, conditionedInput ) ); + meta->addStatement( new GenOp( " // g-buffer unconditioner: float4(normal.theta, normal.phi, depth Hi, depth Lo)\r\n" ) ); + meta->addStatement( new GenOp( " float2 spGPUAngles = @;\r\n", _posnegDecode(new GenOp("@.xy", conditionedInput)) ) ); + meta->addStatement( new GenOp( " float2 sincosTheta;\r\n" ) ); + meta->addStatement( new GenOp( " sincos(spGPUAngles.x * 3.14159265358979323846f, sincosTheta.x, sincosTheta.y);\r\n" ) ); + meta->addStatement( new GenOp( " float2 sincosPhi = float2(sqrt(1.0 - spGPUAngles.y * spGPUAngles.y), spGPUAngles.y);\r\n" ) ); + meta->addStatement( new GenOp( " @ = float4(sincosTheta.y * sincosPhi.x, sincosTheta.x * sincosPhi.x, sincosPhi.y, @.a);\r\n", outputDecl, conditionedInput ) ); + break; + + case LambertAzimuthal: + // Note we're casting to half to use partial precision + // sqrt which is much faster on older Geforces while + // still being acceptable for normals. + // + meta->addStatement( new GenOp( " // g-buffer unconditioner: float4(normal.X, normal.Y, depth Hi, depth Lo)\r\n" ) ); + meta->addStatement( new GenOp( " float2 _inpXY = @;\r\n", _posnegDecode(new GenOp("@.xy", conditionedInput)) ) ); + meta->addStatement( new GenOp( " float _xySQ = dot(_inpXY, _inpXY);\r\n" ) ); + meta->addStatement( new GenOp( " @ = float4( sqrt(half(1.0 - (_xySQ / 4.0))) * _inpXY, -1.0 + (_xySQ / 2.0), @.a).xzyw;\r\n", outputDecl, conditionedInput ) ); break; } @@ -309,7 +393,7 @@ Var* GBufferConditionerGLSL::_unconditionInput( Var *conditionedInput, MultiLine { const U64 maxValPerChannel = 1 << mBitsPerChannel; meta->addStatement( new GenOp( " \r\n // Decode depth\r\n" ) ); - meta->addStatement( new GenOp( avar( " @.w = dot( @.zw, vec2(1.0, 1.0/%llu.0));\r\n", maxValPerChannel - 1 ), + meta->addStatement( new GenOp( avar( " @.w = dot( @.zw, float2(1.0, 1.0/%llu.0));\r\n", maxValPerChannel - 1 ), retVar, conditionedInput ) ); } diff --git a/Engine/source/lighting/advanced/glsl/gBufferConditionerGLSL.h b/Engine/source/lighting/advanced/glsl/gBufferConditionerGLSL.h index 9e9364c88..640891824 100644 --- a/Engine/source/lighting/advanced/glsl/gBufferConditionerGLSL.h +++ b/Engine/source/lighting/advanced/glsl/gBufferConditionerGLSL.h @@ -42,6 +42,13 @@ public: CartesianXYZ, CartesianXY, Spherical, + LambertAzimuthal, + }; + + enum NormalSpace + { + WorldSpace, + ViewSpace, }; protected: @@ -52,7 +59,7 @@ protected: public: - GBufferConditionerGLSL( const GFXFormat bufferFormat ); + GBufferConditionerGLSL( const GFXFormat bufferFormat, const NormalSpace nrmSpace ); virtual ~GBufferConditionerGLSL(); diff --git a/Engine/source/shaderGen/GLSL/bumpGLSL.cpp b/Engine/source/shaderGen/GLSL/bumpGLSL.cpp index 737ddcbaf..1b1cd0437 100644 --- a/Engine/source/shaderGen/GLSL/bumpGLSL.cpp +++ b/Engine/source/shaderGen/GLSL/bumpGLSL.cpp @@ -64,14 +64,14 @@ void BumpFeatGLSL::processPix( Vector &componentList, output = meta; // Get the texture coord. - Var *texCoord = getInTexCoord( "out_texCoord", "vec2", true, componentList ); + Var *texCoord = getInTexCoord( "texCoord", "vec2", true, componentList ); // Sample the bumpmap. Var *bumpMap = getNormalMapTex(); - LangElement *texOp = NULL; //Handle atlased textures + // http://www.infinity-universe.com/Infinity/index.php?option=com_content&task=view&id=65&Itemid=47 if(fd.features[MFT_NormalMapAtlas]) { // This is a big block of code, so put a comment in the shader code @@ -79,52 +79,49 @@ void BumpFeatGLSL::processPix( Vector &componentList, Var *atlasedTex = new Var; atlasedTex->setName("atlasedBumpCoord"); - atlasedTex->setType("vec2"); + atlasedTex->setType( "vec2" ); LangElement *atDecl = new DecOp(atlasedTex); // Parameters of the texture atlas Var *atParams = new Var; - atParams->setType("vec4"); + atParams->setType( "float4" ); atParams->setName("bumpAtlasParams"); atParams->uniform = true; atParams->constSortPos = cspPotentialPrimitive; // Parameters of the texture (tile) this object is using in the atlas Var *tileParams = new Var; - tileParams->setType("vec4"); + tileParams->setType( "float4" ); tileParams->setName("bumpAtlasTileParams"); tileParams->uniform = true; tileParams->constSortPos = cspPotentialPrimitive; const bool is_sm3 = (GFX->getPixelShaderVersion() > 2.0f); - // getPixelShaderVersion() on Mac currently returns 2.0, - // or 3.0 if Advanced Lighting is enabled if(is_sm3) { // Figure out the mip level - meta->addStatement(new GenOp(" vec2 _dx_bump = dFdx(@ * @.z);\r\n", texCoord, atParams)); - meta->addStatement(new GenOp(" vec2 _dy_bump = dFdy(@ * @.z);\r\n", texCoord, atParams)); - meta->addStatement(new GenOp(" float mipLod_bump = 0.5 * log2(max(dot(_dx_bump, _dx_bump), dot(_dy_bump, _dy_bump)));\r\n")); - meta->addStatement(new GenOp(" mipLod_bump = clamp(mipLod_bump, 0.0, @.w);\r\n", atParams)); + meta->addStatement( new GenOp( " float2 _dx_bump = ddx(@ * @.z);\r\n", texCoord, atParams ) ); + meta->addStatement( new GenOp( " float2 _dy_bump = ddy(@ * @.z);\r\n", texCoord, atParams ) ); + meta->addStatement( new GenOp( " float mipLod_bump = 0.5 * log2(max(dot(_dx_bump, _dx_bump), dot(_dy_bump, _dy_bump)));\r\n")); + meta->addStatement( new GenOp( " mipLod_bump = clamp(mipLod_bump, 0.0, @.w);\r\n", atParams)); // And the size of the mip level meta->addStatement(new GenOp(" float mipPixSz_bump = pow(2.0, @.w - mipLod_bump);\r\n", atParams)); - meta->addStatement(new GenOp(" vec2 mipSz_bump = mipPixSz_bump / @.xy;\r\n", atParams)); + meta->addStatement( new GenOp( " float2 mipSz_bump = mipPixSz_bump / @.xy;\r\n", atParams ) ); } else { - meta->addStatement(new GenOp(" vec2 mipSz = float2(1.0, 1.0);\r\n")); + meta->addStatement(new GenOp(" float2 mipSz = float2(1.0, 1.0);\r\n")); } // Tiling mode - // TODO: Select wrap or clamp somehow if( true ) // Wrap - meta->addStatement(new GenOp(" @ = fract(@);\r\n", atDecl, texCoord)); + meta->addStatement( new GenOp( " @ = frac(@);\r\n", atDecl, texCoord ) ); else // Clamp meta->addStatement(new GenOp(" @ = saturate(@);\r\n", atDecl, texCoord)); // Finally scale/offset, and correct for filtering - meta->addStatement(new GenOp(" @ = @ * ((mipSz_bump * @.xy - 1.0) / mipSz_bump) + 0.5 / mipSz_bump + @.xy * @.xy;\r\n", + meta->addStatement( new GenOp( " @ = @ * ((mipSz_bump * @.xy - 1.0) / mipSz_bump) + 0.5 / mipSz_bump + @.xy * @.xy;\r\n", atlasedTex, atlasedTex, atParams, atParams, tileParams)); // Add a newline @@ -132,19 +129,19 @@ void BumpFeatGLSL::processPix( Vector &componentList, if(is_sm3) { - texOp = new GenOp( "texture2DLod(@, vec4(@, 0.0, mipLod_bump)", bumpMap, texCoord ); + texOp = new GenOp( "tex2Dlod(@, float4(@, 0.0, mipLod_bump))", bumpMap, texCoord ); } else { - texOp = new GenOp( "texture2D(@, @)", bumpMap, texCoord ); + texOp = new GenOp( "tex2D(@, @)", bumpMap, texCoord ); } } else { - texOp = new GenOp( "texture2D(@, @)", bumpMap, texCoord ); + texOp = new GenOp( "tex2D(@, @)", bumpMap, texCoord ); } - Var *bumpNorm = new Var( "bumpNormal", "vec4" ); + Var *bumpNorm = new Var( "bumpNormal", "float4" ); meta->addStatement( expandNormalMap( texOp, new DecOp( bumpNorm ), bumpNorm, fd ) ); // If we have a detail normal map we add the xy coords of @@ -160,11 +157,11 @@ void BumpFeatGLSL::processPix( Vector &componentList, bumpMap->constNum = Var::getTexUnitNum(); texCoord = getInTexCoord( "detCoord", "vec2", true, componentList ); - texOp = new GenOp( "texture2D(@, @)", bumpMap, texCoord ); + texOp = new GenOp( "tex2D(@, @)", bumpMap, texCoord ); Var *detailBump = new Var; detailBump->setName( "detailBump" ); - detailBump->setType( "vec4" ); + detailBump->setType( "float4" ); meta->addStatement( expandNormalMap( texOp, new DecOp( detailBump ), detailBump, fd ) ); Var *detailBumpScale = new Var; @@ -175,13 +172,11 @@ void BumpFeatGLSL::processPix( Vector &componentList, meta->addStatement( new GenOp( " @.xy += @.xy * @;\r\n", bumpNorm, detailBump, detailBumpScale ) ); } - // We transform it into world space by reversing the // multiplication by the worldToTanget transform. Var *wsNormal = new Var( "wsNormal", "vec3" ); Var *worldToTanget = getInWorldToTangent( componentList ); - meta->addStatement( new GenOp( " @ = normalize( vec3( @.xyz * @ ) );\r\n", new DecOp( wsNormal ), bumpNorm, worldToTanget ) ); - + meta->addStatement( new GenOp( " @ = normalize( tMul( @.xyz, @ ) );\r\n", new DecOp( wsNormal ), bumpNorm, worldToTanget ) ); } ShaderFeature::Resources BumpFeatGLSL::getResources( const MaterialFeatureData &fd ) @@ -227,20 +222,26 @@ void BumpFeatGLSL::setTexData( Material::StageData &stageDat, if ( fd.features[MFT_NormalMap] ) { passData.mTexType[ texIndex ] = Material::Bump; + passData.mSamplerNames[ texIndex ] = "bumpMap"; passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_NormalMap ); } - if ( fd.features[ MFT_DetailNormalMap ] ) { passData.mTexType[ texIndex ] = Material::DetailBump; + passData.mSamplerNames[ texIndex ] = "detailBumpMap"; passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_DetailNormalMap ); } } -// -Var* ParallaxFeatGLSL::_getUniformVar( const char *name, const char *type ) +ParallaxFeatGLSL::ParallaxFeatGLSL() + : mIncludeDep( "shaders/common/gl/torque.glsl" ) +{ + addDependency( &mIncludeDep ); +} + +Var* ParallaxFeatGLSL::_getUniformVar( const char *name, const char *type, ConstantSortPosition csp ) { Var *theVar = (Var*)LangElement::find( name ); if ( !theVar ) @@ -249,7 +250,7 @@ Var* ParallaxFeatGLSL::_getUniformVar( const char *name, const char *type ) theVar->setType( type ); theVar->setName( name ); theVar->uniform = true; - theVar->constSortPos = cspPass; + theVar->constSortPos = csp; } return theVar; @@ -259,13 +260,13 @@ void ParallaxFeatGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { AssertFatal( GFX->getPixelShaderVersion() >= 2.0, - "ParallaxFeatGLSL::processVert - We don't support SM 1.x!" ); + "ParallaxFeatGLSL::processVert - We don't support SM 1.x!" ); MultiLine *meta = new MultiLine; // Add the texture coords. getOutTexCoord( "texCoord", - "vec2", + "vec2", true, fd.features[MFT_TexAnim], meta, @@ -276,18 +277,36 @@ void ParallaxFeatGLSL::processVert( Vector &componentList, if ( !inPos ) inPos = (Var*)LangElement::find( "position" ); - // Get the object space eye position and the world - // to tangent transform. - Var *eyePos = _getUniformVar( "eyePos", "vec3" ); + // Get the object space eye position and the + // object to tangent space transform. + Var *eyePos = _getUniformVar( "eyePos", "vec3", cspPrimitive ); Var *objToTangentSpace = getOutObjToTangentSpace( componentList, meta, fd ); - // send transform to pixel shader + // Now send the negative view vector in tangent space to the pixel shader. ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - Var *outViewTS = connectComp->getElement( RT_TEXCOORD, 1 ); - outViewTS->setName( "outViewTS" ); - outViewTS->setType( "vec3" ); - meta->addStatement( new GenOp( " @ = ( @ - @.xyz ) * transpose( @ );\r\n", - outViewTS, inPos, eyePos, objToTangentSpace ) ); + Var *outNegViewTS = connectComp->getElement( RT_TEXCOORD ); + outNegViewTS->setName( "outNegViewTS" ); + outNegViewTS->setStructName( "OUT" ); + outNegViewTS->setType( "vec3" ); + meta->addStatement( new GenOp( " @ = tMul( @, float3( @.xyz - @ ) );\r\n", + outNegViewTS, objToTangentSpace, inPos, eyePos ) ); + + // TODO: I'm at a loss at why i need to flip the binormal/y coord + // to get a good view vector for parallax. Lighting works properly + // with the TS matrix as is... but parallax does not. + // + // Someone figure this out! + // + meta->addStatement( new GenOp( " @.y = -@.y;\r\n", outNegViewTS, outNegViewTS ) ); + + // If we have texture anim matrix the tangent + // space view vector may need to be rotated. + Var *texMat = (Var*)LangElement::find( "texMat" ); + if ( texMat ) + { + meta->addStatement( new GenOp( " @ = tMul(@, float4(@,0)).xyz;\r\n", + outNegViewTS, texMat, outNegViewTS ) ); + } output = meta; } @@ -296,7 +315,7 @@ void ParallaxFeatGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { AssertFatal( GFX->getPixelShaderVersion() >= 2.0, - "ParallaxFeatGLSL::processPix - We don't support SM 1.x!" ); + "ParallaxFeatGLSL::processPix - We don't support SM 1.x!" ); MultiLine *meta = new MultiLine; @@ -310,38 +329,28 @@ void ParallaxFeatGLSL::processPix( Vector &componentList, Var *negViewTS = (Var*)LangElement::find( "negViewTS" ); if ( !negViewTS ) { - Var *inViewTS = (Var*)LangElement::find( "outViewTS" ); - if ( !inViewTS ) + Var *inNegViewTS = (Var*)LangElement::find( "outNegViewTS" ); + if ( !inNegViewTS ) { - inViewTS = connectComp->getElement( RT_TEXCOORD, 1 ); - inViewTS->setName( "outViewTS" ); - inViewTS->setType( "vec3" ); + inNegViewTS = connectComp->getElement( RT_TEXCOORD ); + inNegViewTS->setName( "outNegViewTS" ); + inNegViewTS->setStructName( "IN" ); + inNegViewTS->setType( "vec3" ); } negViewTS = new Var( "negViewTS", "vec3" ); - meta->addStatement( new GenOp( " @ = -normalize( @ );\r\n", new DecOp( negViewTS ), inViewTS ) ); + meta->addStatement( new GenOp( " @ = normalize( @ );\r\n", new DecOp( negViewTS ), inNegViewTS ) ); } // Get the rest of our inputs. - Var *parallaxInfo = _getUniformVar( "parallaxInfo", "float" ); + Var *parallaxInfo = _getUniformVar( "parallaxInfo", "float", cspPotentialPrimitive ); Var *normalMap = getNormalMapTex(); - // Do 3 parallax samples to get acceptable - // quality without too much overhead. - Var *pdepth = findOrCreateLocal( "pdepth", "float", meta ); - Var *poffset = findOrCreateLocal( "poffset", "vec2", meta ); - meta->addStatement( new GenOp( " @ = texture2D( @, @.xy ).a;\r\n", pdepth, normalMap, texCoord ) ); - meta->addStatement( new GenOp( " @ = @.xy * ( @ * @ );\r\n", poffset, negViewTS, pdepth, parallaxInfo ) ); - - meta->addStatement( new GenOp( " @ = ( @ + texture2D( @, @.xy + @ ).a ) * 0.5;\r\n", pdepth, pdepth, normalMap, texCoord, poffset ) ); - meta->addStatement( new GenOp( " @ = @.xy * ( @ * @ );\r\n", poffset, negViewTS, pdepth, parallaxInfo ) ); - - meta->addStatement( new GenOp( " @ = ( @ + texture2D( @, @.xy + @ ).a ) * 0.5;\r\n", pdepth, pdepth, normalMap, texCoord, poffset ) ); - meta->addStatement( new GenOp( " @ = @.xy * ( @ * @ );\r\n", poffset, negViewTS, pdepth, parallaxInfo ) ); - - meta->addStatement( new GenOp( " @.xy += @;\r\n", texCoord, poffset ) ); + // Call the library function to do the rest. + meta->addStatement( new GenOp( " @.xy += parallaxOffset( @, @.xy, @, @ );\r\n", + texCoord, normalMap, texCoord, negViewTS, parallaxInfo ) ); - // TODO: Fix second UV. + // TODO: Fix second UV maybe? output = meta; } @@ -349,7 +358,7 @@ void ParallaxFeatGLSL::processPix( Vector &componentList, ShaderFeature::Resources ParallaxFeatGLSL::getResources( const MaterialFeatureData &fd ) { AssertFatal( GFX->getPixelShaderVersion() >= 2.0, - "ParallaxFeatGLSL::getResources - We don't support SM 1.x!" ); + "ParallaxFeatGLSL::getResources - We don't support SM 1.x!" ); Resources res; @@ -370,7 +379,7 @@ void ParallaxFeatGLSL::setTexData( Material::StageData &stageDat, U32 &texIndex ) { AssertFatal( GFX->getPixelShaderVersion() >= 2.0, - "ParallaxFeatGLSL::setTexData - We don't support SM 1.x!" ); + "ParallaxFeatGLSL::setTexData - We don't support SM 1.x!" ); GFXTextureObject *tex = stageDat.getTex( MFT_NormalMap ); if ( tex ) @@ -381,7 +390,6 @@ void ParallaxFeatGLSL::setTexData( Material::StageData &stageDat, } -// void NormalsOutFeatGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { @@ -397,6 +405,7 @@ void NormalsOutFeatGLSL::processVert( Vector &componentList, Var *outNormal = connectComp->getElement( RT_TEXCOORD ); outNormal->setName( "wsNormal" ); + outNormal->setStructName( "OUT" ); outNormal->setType( "vec3" ); outNormal->mapsToSampler = false; @@ -406,13 +415,13 @@ void NormalsOutFeatGLSL::processVert( Vector &componentList, { // Transform the normal to world space. Var *objTrans = getObjTrans( componentList, fd.features[MFT_UseInstancing], meta ); - meta->addStatement( new GenOp( " @ = @ * normalize( @ );\r\n", outNormal, objTrans, inNormal ) ); + meta->addStatement( new GenOp( " @ = tMul( @, normalize( vec4(@, 0.0) ) ).xyz;\r\n", outNormal, objTrans, inNormal ) ); } else { // If we don't have a vertex normal... just pass the // camera facing normal to the pixel shader. - meta->addStatement( new GenOp( " @ = vec3( 0.0, 0.0, 1.0 );\r\n", outNormal ) ); + meta->addStatement( new GenOp( " @ = float3( 0.0, 0.0, 1.0 );\r\n", outNormal ) ); } } @@ -428,20 +437,26 @@ void NormalsOutFeatGLSL::processPix( Vector &componentList, ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); wsNormal = connectComp->getElement( RT_TEXCOORD ); wsNormal->setName( "wsNormal" ); + wsNormal->setStructName( "IN" ); wsNormal->setType( "vec3" ); // If we loaded the normal its our resposibility // to normalize it... the interpolators won't. // - meta->addStatement( new GenOp( " @ = normalize( @ );\r\n", wsNormal, wsNormal ) ); + // Note we cast to half here to get partial precision + // optimized code which is an acceptable loss of + // precision for normals and performs much better + // on older Geforce cards. + // + meta->addStatement( new GenOp( " @ = normalize( half3( @ ) );\r\n", wsNormal, wsNormal ) ); } LangElement *normalOut; Var *outColor = (Var*)LangElement::find( "col" ); - if ( outColor ) - normalOut = new GenOp( "vec4( ( -@ + 1 ) * 0.5, @.a )", wsNormal, outColor ); + if ( outColor && !fd.features[MFT_AlphaTest] ) + normalOut = new GenOp( "float4( ( -@ + 1 ) * 0.5, @.a )", wsNormal, outColor ); else - normalOut = new GenOp( "vec4( ( -@ + 1 ) * 0.5, 1 )", wsNormal ); + normalOut = new GenOp( "float4( ( -@ + 1 ) * 0.5, 1 )", wsNormal ); meta->addStatement( new GenOp( " @;\r\n", assignColor( normalOut, Material::None ) ) ); diff --git a/Engine/source/shaderGen/GLSL/bumpGLSL.h b/Engine/source/shaderGen/GLSL/bumpGLSL.h index 899434f15..b37bb9099 100644 --- a/Engine/source/shaderGen/GLSL/bumpGLSL.h +++ b/Engine/source/shaderGen/GLSL/bumpGLSL.h @@ -26,6 +26,9 @@ #ifndef _SHADERGEN_GLSL_SHADERFEATUREGLSL_H_ #include "shaderGen/GLSL/shaderFeatureGLSL.h" #endif +#ifndef _LANG_ELEMENT_H_ +#include "shaderGen/langElement.h" +#endif struct RenderPassData; class MultiLine; @@ -50,7 +53,6 @@ public: const MaterialFeatureData &fd, RenderPassData &passData, U32 &texIndex ); - virtual String getName() { return "Bumpmap"; } }; @@ -62,10 +64,16 @@ class ParallaxFeatGLSL : public ShaderFeatureGLSL { protected: - static Var* _getUniformVar( const char *name, const char *type ); + static Var* _getUniformVar( const char *name, + const char *type, + ConstantSortPosition csp ); + + ShaderIncludeDependency mIncludeDep; public: + ParallaxFeatGLSL(); + // ShaderFeatureGLSL virtual void processVert( Vector &componentList, const MaterialFeatureData &fd ); @@ -80,7 +88,6 @@ public: }; - /// This feature is used to render normals to the /// diffuse target for imposter rendering. class NormalsOutFeatGLSL : public ShaderFeatureGLSL diff --git a/Engine/source/shaderGen/GLSL/depthGLSL.cpp b/Engine/source/shaderGen/GLSL/depthGLSL.cpp index 4c5f1b837..71bdbb96e 100644 --- a/Engine/source/shaderGen/GLSL/depthGLSL.cpp +++ b/Engine/source/shaderGen/GLSL/depthGLSL.cpp @@ -24,36 +24,36 @@ #include "shaderGen/GLSL/depthGLSL.h" #include "materials/materialFeatureTypes.h" +#include "materials/materialFeatureData.h" void EyeSpaceDepthOutGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { - - MultiLine *meta = new MultiLine; + MultiLine *meta = new MultiLine; output = meta; - // grab output + // grab output ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *outWSEyeVec = connectComp->getElement( RT_TEXCOORD ); - outWSEyeVec->setName( "outWSEyeVec" ); - - - // grab incoming vert position - Var *wsPosition = new Var( "depthPos", "vec3" ); + outWSEyeVec->setName( "wsEyeVec" ); + outWSEyeVec->setStructName( "OUT" ); + + // grab incoming vert position + Var *wsPosition = new Var( "depthPos", "float3" ); getWsPosition( componentList, fd.features[MFT_UseInstancing], meta, new DecOp( wsPosition ) ); Var *eyePos = (Var*)LangElement::find( "eyePosWorld" ); if( !eyePos ) { eyePos = new Var; - eyePos->setType("vec3"); + eyePos->setType("float3"); eyePos->setName("eyePosWorld"); eyePos->uniform = true; eyePos->constSortPos = cspPass; } -meta->addStatement( new GenOp( " @ = vec4( @.xyz - @, 1 );\r\n", outWSEyeVec, wsPosition, eyePos ) ); + meta->addStatement( new GenOp( " @ = float4( @.xyz - @, 1 );\r\n", outWSEyeVec, wsPosition, eyePos ) ); } void EyeSpaceDepthOutGLSL::processPix( Vector &componentList, @@ -64,14 +64,15 @@ void EyeSpaceDepthOutGLSL::processPix( Vector &componentList, // grab connector position ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *wsEyeVec = connectComp->getElement( RT_TEXCOORD ); - wsEyeVec->setName( "outWSEyeVec" ); - wsEyeVec->setType( "vec4" ); + wsEyeVec->setName( "wsEyeVec" ); + wsEyeVec->setStructName( "IN" ); + wsEyeVec->setType( "float4" ); wsEyeVec->mapsToSampler = false; wsEyeVec->uniform = false; // get shader constants Var *vEye = new Var; - vEye->setType("vec3"); + vEye->setType("float3"); vEye->setName("vEye"); vEye->uniform = true; vEye->constSortPos = cspPass; @@ -83,12 +84,27 @@ void EyeSpaceDepthOutGLSL::processPix( Vector &componentList, LangElement *depthOutDecl = new DecOp( depthOut ); + meta->addStatement( new GenOp( "#ifndef CUBE_SHADOW_MAP\r\n" ) ); meta->addStatement( new GenOp( " @ = dot(@, (@.xyz / @.w));\r\n", depthOutDecl, vEye, wsEyeVec, wsEyeVec ) ); + meta->addStatement( new GenOp( "#else\r\n" ) ); + + Var *farDist = (Var*)Var::find( "oneOverFarplane" ); + if ( !farDist ) + { + farDist = new Var; + farDist->setType("float4"); + farDist->setName("oneOverFarplane"); + farDist->uniform = true; + farDist->constSortPos = cspPass; + } + + meta->addStatement( new GenOp( " @ = length( @.xyz / @.w ) * @.x;\r\n", depthOutDecl, wsEyeVec, wsEyeVec, farDist ) ); + meta->addStatement( new GenOp( "#endif\r\n" ) ); // If there isn't an output conditioner for the pre-pass, than just write // out the depth to rgba and return. if( !fd.features[MFT_PrePassConditioner] ) - meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "vec4(@)", depthOut ), Material::None ) ) ); + meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "float4(float3(@),1)", depthOut ), Material::None ) ) ); output = meta; } @@ -111,11 +127,12 @@ void DepthOutGLSL::processVert( Vector &componentList, ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); // Grab the output vert. - Var *outPosition = (Var*)LangElement::find( "gl_Position" ); + Var *outPosition = (Var*)LangElement::find( "gl_Position" ); //hpos // Grab our output depth. Var *outDepth = connectComp->getElement( RT_TEXCOORD ); - outDepth->setName( "outDepth" ); + outDepth->setName( "depth" ); + outDepth->setStructName( "OUT" ); outDepth->setType( "float" ); output = new GenOp( " @ = @.z / @.w;\r\n", outDepth, outPosition, outPosition ); @@ -128,7 +145,8 @@ void DepthOutGLSL::processPix( Vector &componentList, // grab connector position Var *depthVar = connectComp->getElement( RT_TEXCOORD ); - depthVar->setName( "outDepth" ); + depthVar->setName( "depth" ); + depthVar->setStructName( "IN" ); depthVar->setType( "float" ); depthVar->mapsToSampler = false; depthVar->uniform = false; @@ -140,7 +158,7 @@ void DepthOutGLSL::processPix( Vector &componentList, depthOut->setName(getOutputVarName()); */ - LangElement *depthOut = new GenOp( "vec4( @, @ * @, 0, 1 )", depthVar, depthVar, depthVar ); + LangElement *depthOut = new GenOp( "float4( @, 0, 0, 1 )", depthVar ); output = new GenOp( " @;\r\n", assignColor( depthOut, Material::None ) ); } diff --git a/Engine/source/shaderGen/GLSL/depthGLSL.h b/Engine/source/shaderGen/GLSL/depthGLSL.h index 97cb62095..c92326415 100644 --- a/Engine/source/shaderGen/GLSL/depthGLSL.h +++ b/Engine/source/shaderGen/GLSL/depthGLSL.h @@ -54,7 +54,7 @@ public: virtual Resources getResources( const MaterialFeatureData &fd ); virtual String getName() { return "Depth (Out)"; } virtual Material::BlendOp getBlendOp() { return Material::None; } - virtual const char* getOutputVarName() const { return "outDepth"; } + virtual const char* getOutputVarName() const { return "IN_depth"; } }; #endif // _DEPTH_GLSL_H_ \ No newline at end of file diff --git a/Engine/source/shaderGen/GLSL/paraboloidGLSL.cpp b/Engine/source/shaderGen/GLSL/paraboloidGLSL.cpp index 373712c36..61e56d215 100644 --- a/Engine/source/shaderGen/GLSL/paraboloidGLSL.cpp +++ b/Engine/source/shaderGen/GLSL/paraboloidGLSL.cpp @@ -65,7 +65,7 @@ void ParaboloidVertTransformGLSL::processVert( Vector &compon // http://www.gamedev.net/reference/articles/article2308.asp // Swizzle z and y post-transform - meta->addStatement( new GenOp( " @ = vec4(@ * vec4(@.xyz,1)).xzyw;\r\n", outPosition, worldViewOnly, inPosition ) ); + meta->addStatement( new GenOp( " @ = tMul(@, float4(@.xyz,1)).xzyw;\r\n", outPosition, worldViewOnly, inPosition ) ); meta->addStatement( new GenOp( " float L = length(@.xyz);\r\n", outPosition ) ); if ( isSinglePass ) @@ -73,7 +73,8 @@ void ParaboloidVertTransformGLSL::processVert( Vector &compon // Flip the z in the back case Var *outIsBack = connectComp->getElement( RT_TEXCOORD ); outIsBack->setType( "float" ); - outIsBack->setName( "outIsBack" ); + outIsBack->setName( "isBack" ); + outIsBack->setStructName( "OUT" ); meta->addStatement( new GenOp( " bool isBack = @.z < 0.0;\r\n", outPosition ) ); meta->addStatement( new GenOp( " @ = isBack ? -1.0 : 1.0;\r\n", outIsBack ) ); @@ -94,15 +95,16 @@ void ParaboloidVertTransformGLSL::processVert( Vector &compon // TODO: If we change other shadow shaders to write out // linear depth, than fix this as well! // - // (L - 1.0)/(lightParams.x - 1.0); + // (L - zNear)/(lightParams.x - zNear); // meta->addStatement( new GenOp( " @.z = L / @.x;\r\n", outPosition, lightParams ) ); meta->addStatement( new GenOp( " @.w = 1.0;\r\n", outPosition ) ); // Pass unmodified to pixel shader to allow it to clip properly. Var *outPosXY = connectComp->getElement( RT_TEXCOORD ); - outPosXY->setType( "vec2" ); - outPosXY->setName( "outPosXY" ); + outPosXY->setType( "float2" ); + outPosXY->setName( "posXY" ); + outPosXY->setStructName( "OUT" ); meta->addStatement( new GenOp( " @ = @.xy;\r\n", outPosXY, outPosition ) ); // Scale and offset so it shows up in the atlas properly. @@ -136,16 +138,18 @@ void ParaboloidVertTransformGLSL::processPix( Vector &compon { // Cull things on the back side of the map. Var *isBack = connectComp->getElement( RT_TEXCOORD ); - isBack->setName( "outIsBack" ); + isBack->setName( "isBack" ); + isBack->setStructName( "IN" ); isBack->setType( "float" ); meta->addStatement( new GenOp( " if ( ( abs( @ ) - 0.999 ) < 0 ) discard;\r\n", isBack ) ); } // Cull pixels outside of the valid paraboloid. Var *posXY = connectComp->getElement( RT_TEXCOORD ); - posXY->setName( "outPosXY" ); - posXY->setType( "vec2" ); - meta->addStatement( new GenOp( " if ( ( 1.0 - length( @ ) ) < 0 ) discard;\r\n", posXY ) ); + posXY->setName( "posXY" ); + posXY->setStructName( "IN" ); + posXY->setType( "float2" ); + meta->addStatement( new GenOp( " clip( 1.0 - abs(@.x) );\r\n", posXY ) ); output = meta; } diff --git a/Engine/source/shaderGen/GLSL/pixSpecularGLSL.cpp b/Engine/source/shaderGen/GLSL/pixSpecularGLSL.cpp index ac313a103..4e34e2116 100644 --- a/Engine/source/shaderGen/GLSL/pixSpecularGLSL.cpp +++ b/Engine/source/shaderGen/GLSL/pixSpecularGLSL.cpp @@ -38,98 +38,35 @@ PixelSpecularGLSL::PixelSpecularGLSL() void PixelSpecularGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { - /* AssertFatal( fd.features[MFT_RTLighting], "PixelSpecularHLSL requires RTLighting to be enabled!" ); - MultiLine *meta = new MultiLine; - - // Get the eye world position. - Var *eyePos = (Var*)LangElement::find( "eyePosWorld" ); - if( !eyePos ) - { - eyePos = new Var; - eyePos->setType( "float3" ); - eyePos->setName( "eyePosWorld" ); - eyePos->uniform = true; - eyePos->constSortPos = cspPass; - } - - // Grab a register for passing the - // world space view vector. - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - Var *wsView = connectComp->getElement( RT_TEXCOORD ); - wsView->setName( "wsView" ); - wsView->setStructName( "OUT" ); - wsView->setType( "float3" ); - - // Get the input position. - Var *position = (Var*)LangElement::find( "inPosition" ); - if ( !position ) - position = (Var*)LangElement::find( "position" ); - - // Get the object to world transform. - Var *objTrans = (Var*) LangElement::find( "objTrans" ); - if ( !objTrans ) - { - objTrans = new Var; - objTrans->setType( "float4x4" ); - objTrans->setName( "objTrans" ); - objTrans->uniform = true; - objTrans->constSortPos = cspPrimitive; - } - - meta->addStatement( new GenOp( " @ = @ - mul( @, float4( @.xyz,1 ) ).xyz;\r\n", - wsView, eyePos, objTrans, position ) ); - - output = meta; - */ + // Nothing to do here... MFT_RTLighting should have + // taken care of passing everything to the pixel shader. } void PixelSpecularGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) -{ - /* +{ AssertFatal( fd.features[MFT_RTLighting], "PixelSpecularHLSL requires RTLighting to be enabled!" ); - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); + // RTLighting should have spit out the 4 specular + // powers for the 4 potential lights on this pass. + // + // This can sometimes be NULL if RTLighting skips out + // on us for lightmaps or missing normals. + Var *specular = (Var*)LangElement::find( "specular" ); + if ( !specular ) + return; MultiLine *meta = new MultiLine; - // Get the normal and light vectors from which the - // RTLighting feature should have already setup. - Var *wsNormal = (Var*)LangElement::find( "wsNormal" ); - Var *inLightVec = (Var*)LangElement::find( "inLightVec" ); - - // Grab the world space position to eye vector. - Var *wsView = connectComp->getElement( RT_TEXCOORD ); - wsView->setName( "wsView" ); - wsView->setStructName( "IN" ); - wsView->setType( "float3" ); - - // Get the specular power and color. - Var *specPow = new Var( "specularPower", "float" ); - specPow->uniform = true; - specPow->constSortPos = cspPass; - Var *specCol = (Var*)LangElement::find("specularColor"); - if(specCol == NULL) - { - specCol = new Var( "specularColor", "vec4" ); - specCol->uniform = true; - specCol->constSortPos = cspPass; - } - - // Calcuate the specular factor. - Var *specular = new Var( "specular", "float" ); - meta->addStatement( new GenOp( " @ = calcSpecular( -@, normalize( @ ), normalize( @ ), @ );\r\n", - new DecOp( specular ), inLightVec, wsNormal, wsView, specPow ) ); - - LangElement *specMul = new GenOp( "float4(@.rgb,0) * @", specCol, specular ); + LangElement *specMul = new GenOp( "@", specular ); LangElement *final = specMul; // mask out with lightmap if present - if( fd.features[MFT_LightMap] ) + if ( fd.features[MFT_LightMap] ) { LangElement *lmColor = NULL; @@ -141,37 +78,44 @@ void PixelSpecularGLSL::processPix( Vector &componentList, LangElement * lightMap = LangElement::find( "lightMap" ); LangElement * lmCoord = LangElement::find( "texCoord2" ); - lmColor = new GenOp( "tex2D(@, @)", lightMap, lmCoord ); + lmColor = new GenOp( "texture(@, @)", lightMap, lmCoord ); } - final = new GenOp( "@ * float4(@.rgb,0)", specMul, lmColor ); + final = new GenOp( "@ * vec4(@.rgb,0)", specMul, lmColor ); } - // We we have a normal map then mask the specular - if ( !fd.features[MFT_SpecularMap] && fd.features[MFT_NormalMap] ) + // If we have a normal map then mask the specular + if ( fd.features[MFT_SpecularMap] ) + { + Var *specularColor = (Var*)LangElement::find( "specularColor" ); + if (specularColor) + final = new GenOp( "@ * @", final, specularColor ); + } + else if ( fd.features[MFT_NormalMap] && !fd.features[MFT_IsDXTnm] ) { Var *bumpColor = (Var*)LangElement::find( "bumpNormal" ); final = new GenOp( "@ * @.a", final, bumpColor ); } - // Add the specular to the final color. - meta->addStatement( new GenOp( " @;\r\n", assignColor( final, Material::Add ) ) ); + // Add the specular to the final color. + // search for color var + Var *color = (Var*)LangElement::find( "col" ); + meta->addStatement( new GenOp( " @.rgb += ( @ ).rgb;\r\n", color, final ) ); output = meta; - */ } ShaderFeature::Resources PixelSpecularGLSL::getResources( const MaterialFeatureData &fd ) { Resources res; - res.numTexReg = 1; return res; } + void SpecularMapGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { // Get the texture coord. - Var *texCoord = getInTexCoord( "out_texCoord", "vec2", true, componentList ); + Var *texCoord = getInTexCoord( "texCoord", "vec2", true, componentList ); // create texture var Var *specularMap = new Var; @@ -180,7 +124,7 @@ void SpecularMapGLSL::processPix( Vector &componentList, const specularMap->uniform = true; specularMap->sampler = true; specularMap->constNum = Var::getTexUnitNum(); - LangElement *texOp = new GenOp( "texture2D(@, @)", specularMap, texCoord ); + LangElement *texOp = new GenOp( "texture(@, @)", specularMap, texCoord ); Var *specularColor = new Var( "specularColor", "vec4" ); @@ -203,6 +147,7 @@ void SpecularMapGLSL::setTexData( Material::StageData &stageDat, if ( tex ) { passData.mTexType[ texIndex ] = Material::Standard; + passData.mSamplerNames[ texIndex ] = "specularMap"; passData.mTexSlot[ texIndex++ ].texObject = tex; } } \ No newline at end of file diff --git a/Engine/source/shaderGen/GLSL/pixSpecularGLSL.h b/Engine/source/shaderGen/GLSL/pixSpecularGLSL.h index eb49b4504..2b7c92b95 100644 --- a/Engine/source/shaderGen/GLSL/pixSpecularGLSL.h +++ b/Engine/source/shaderGen/GLSL/pixSpecularGLSL.h @@ -53,7 +53,6 @@ public: } }; - /// A texture source for the PixSpecular feature class SpecularMapGLSL : public ShaderFeatureGLSL { @@ -75,5 +74,4 @@ public: } }; - -#endif // _PIXSPECULAR_GLSL_H_ \ No newline at end of file +#endif // _PIXSPECULAR_HLSL_H_ \ No newline at end of file diff --git a/Engine/source/shaderGen/GLSL/shaderCompGLSL.cpp b/Engine/source/shaderGen/GLSL/shaderCompGLSL.cpp index 7a476ff3b..faf5f92e1 100644 --- a/Engine/source/shaderGen/GLSL/shaderCompGLSL.cpp +++ b/Engine/source/shaderGen/GLSL/shaderCompGLSL.cpp @@ -38,7 +38,7 @@ Var * AppVertConnectorGLSL::getElement( RegisterType type, { Var *newVar = new Var; mElementList.push_back( newVar ); - newVar->setConnectName( "gl_Vertex" ); + newVar->setConnectName( "vPosition" ); return newVar; } @@ -46,28 +46,49 @@ Var * AppVertConnectorGLSL::getElement( RegisterType type, { Var *newVar = new Var; mElementList.push_back( newVar ); - newVar->setConnectName( "gl_Normal" ); + newVar->setConnectName( "vNormal" ); return newVar; } - + + case RT_BINORMAL: + { + Var *newVar = new Var; + mElementList.push_back( newVar ); + newVar->setConnectName( "vBinormal" ); + return newVar; + } case RT_COLOR: { Var *newVar = new Var; mElementList.push_back( newVar ); - newVar->setConnectName( "gl_Color" ); + newVar->setConnectName( "vColor" ); + return newVar; + } + + case RT_TANGENT: + { + Var *newVar = new Var; + mElementList.push_back( newVar ); + newVar->setConnectName( "vTangent" ); + return newVar; + } + + case RT_TANGENTW: + { + Var *newVar = new Var; + mElementList.push_back( newVar ); + newVar->setConnectName( "vTangentW" ); return newVar; } case RT_TEXCOORD: - case RT_BINORMAL: - case RT_TANGENT: { Var *newVar = new Var; mElementList.push_back( newVar ); char out[32]; - dSprintf( (char*)out, sizeof(out), "gl_MultiTexCoord%d", mCurTexElem ); + dSprintf( (char*)out, sizeof(out), "vTexCoord%d", mCurTexElem ); newVar->setConnectName( out ); newVar->constNum = mCurTexElem; newVar->arraySize = numElements; @@ -108,29 +129,55 @@ void AppVertConnectorGLSL::reset() mCurTexElem = 0; } -void AppVertConnectorGLSL::print( Stream &stream ) +void AppVertConnectorGLSL::print( Stream &stream, bool isVertexShader ) { - // print out elements + if(!isVertexShader) + return; + + U8 output[256]; + + // print struct + dSprintf( (char*)output, sizeof(output), "struct VertexData\r\n" ); + stream.write( dStrlen((char*)output), output ); + dSprintf( (char*)output, sizeof(output), "{\r\n" ); + stream.write( dStrlen((char*)output), output ); + for( U32 i=0; itype, "float")) - swizzle = "x"; - else if(!dStrcmp((const char*)var->type, "vec2")) - swizzle = "xy"; - else if(!dStrcmp((const char*)var->type, "vec3")) - swizzle = "xyz"; + + if( var->arraySize == 1) + { + dSprintf( (char*)output, sizeof(output), " %s %s;\r\n", var->type, (char*)var->name ); + stream.write( dStrlen((char*)output), output ); + } else - swizzle = "xyzw"; + { + dSprintf( (char*)output, sizeof(output), " %s %s[%d];\r\n", var->type, (char*)var->name, var->arraySize ); + stream.write( dStrlen((char*)output), output ); + } + } - // This is ugly. We use #defines to match user defined names with - // built in vars. There is no cleaner way to do this. - dSprintf( (char*)output, sizeof(output), "#define %s %s.%s\r\n", var->name, var->connectName, swizzle ); + dSprintf( (char*)output, sizeof(output), "} IN;\r\n\r\n" ); + stream.write( dStrlen((char*)output), output ); + // print in elements + for( U32 i=0; iarraySize; ++j) + { + const char *name = j == 0 ? var->connectName : avar("vTexCoord%d", var->constNum + j) ; + dSprintf( (char*)output, sizeof(output), "in %s %s;\r\n", var->type, name ); + stream.write( dStrlen((char*)output), output ); + } + + dSprintf( (char*)output, sizeof(output), "#define IN_%s IN.%s\r\n", var->name, var->name ); // TODO REMOVE stream.write( dStrlen((char*)output), output ); } + const char* newLine ="\r\n"; + stream.write( dStrlen((char*)newLine), newLine ); } Var * VertPixelConnectorGLSL::getElement( RegisterType type, @@ -140,14 +187,45 @@ Var * VertPixelConnectorGLSL::getElement( RegisterType type, switch( type ) { case RT_POSITION: + { + Var *newVar = new Var; + mElementList.push_back( newVar ); + newVar->setConnectName( "POSITION" ); + return newVar; + } + case RT_NORMAL: + { + Var *newVar = new Var; + mElementList.push_back( newVar ); + newVar->setConnectName( "NORMAL" ); + return newVar; + } + case RT_COLOR: { Var *newVar = new Var; mElementList.push_back( newVar ); + newVar->setConnectName( "COLOR" ); return newVar; } + /*case RT_BINORMAL: + { + Var *newVar = new Var; + mElementList.push_back( newVar ); + newVar->setConnectName( "BINORMAL" ); + return newVar; + } + + case RT_TANGENT: + { + Var *newVar = new Var; + mElementList.push_back( newVar ); + newVar->setConnectName( "TANGENT" ); + return newVar; + } */ + case RT_TEXCOORD: case RT_BINORMAL: case RT_TANGENT: @@ -155,6 +233,10 @@ Var * VertPixelConnectorGLSL::getElement( RegisterType type, Var *newVar = new Var; newVar->arraySize = numElements; + char out[32]; + dSprintf( (char*)out, sizeof(out), "TEXCOORD%d", mCurTexElem ); + newVar->setConnectName( out ); + if ( numRegisters != -1 ) mCurTexElem += numRegisters; else @@ -192,7 +274,7 @@ void VertPixelConnectorGLSL::reset() mCurTexElem = 0; } -void VertPixelConnectorGLSL::print( Stream &stream ) +void VertPixelConnectorGLSL::print( Stream &stream, bool isVerterShader ) { // print out elements for( U32 i=0; iarraySize <= 1) - dSprintf((char*)output, sizeof(output), "varying %s %s;\r\n", var->type, var->name); + dSprintf((char*)output, sizeof(output), "%s %s _%s_;\r\n", (isVerterShader ? "out" : "in"), var->type, var->connectName); else - dSprintf((char*)output, sizeof(output), "varying %s %s[%d];\r\n", var->type, var->name, var->arraySize); + dSprintf((char*)output, sizeof(output), "%s %s _%s_[%d];\r\n", (isVerterShader ? "out" : "in"),var->type, var->connectName, var->arraySize); stream.write( dStrlen((char*)output), output ); } + + printStructDefines(stream, !isVerterShader); } -void VertexParamsDefGLSL::print( Stream &stream ) +void VertPixelConnectorGLSL::printOnMain( Stream &stream, bool isVerterShader ) +{ + if(isVerterShader) + return; + + const char *newLine = "\r\n"; + const char *header = " //-------------------------\r\n"; + stream.write( dStrlen((char*)newLine), newLine ); + stream.write( dStrlen((char*)header), header ); + + // print out elements + for( U32 i=0; iname, "gl_Position")) + continue; + + dSprintf((char*)output, sizeof(output), " %s IN_%s = _%s_;\r\n", var->type, var->name, var->connectName); + + stream.write( dStrlen((char*)output), output ); + } + + stream.write( dStrlen((char*)header), header ); + stream.write( dStrlen((char*)newLine), newLine ); +} + + +void AppVertConnectorGLSL::printOnMain( Stream &stream, bool isVerterShader ) +{ + if(!isVerterShader) + return; + + const char *newLine = "\r\n"; + const char *header = " //-------------------------\r\n"; + stream.write( dStrlen((char*)newLine), newLine ); + stream.write( dStrlen((char*)header), header ); + + // print out elements + for( U32 i=0; iarraySize <= 1) + { + dSprintf((char*)output, sizeof(output), " IN.%s = %s;\r\n", var->name, var->connectName); + stream.write( dStrlen((char*)output), output ); + } + else + { + for(int j = 0; j < var->arraySize; ++j) + { + const char *name = j == 0 ? var->connectName : avar("vTexCoord%d", var->constNum + j) ; + dSprintf((char*)output, sizeof(output), " IN.%s[%d] = %s;\r\n", var->name, j, name ); + stream.write( dStrlen((char*)output), output ); + } + } + } + + stream.write( dStrlen((char*)header), header ); + stream.write( dStrlen((char*)newLine), newLine ); +} + + + + +Vector initDeprecadedDefines() +{ + Vector vec; + vec.push_back( "isBack"); + return vec; +} + +void VertPixelConnectorGLSL::printStructDefines( Stream &stream, bool in ) +{ + const char* connectionDir; + + if(in) + { + connectionDir = "IN"; + } + else + { + + connectionDir = "OUT"; + } + + static Vector deprecatedDefines = initDeprecadedDefines(); + + const char *newLine = "\r\n"; + const char *header = "// Struct defines\r\n"; + stream.write( dStrlen((char*)newLine), newLine ); + stream.write( dStrlen((char*)header), header ); + + // print out elements + for( U32 i=0; iname, "gl_Position")) + continue; + + if(!in) + { + dSprintf((char*)output, sizeof(output), "#define %s_%s _%s_\r\n", connectionDir, var->name, var->connectName); + stream.write( dStrlen((char*)output), output ); + } + + if( deprecatedDefines.contains((char*)var->name)) + continue; + + dSprintf((char*)output, sizeof(output), "#define %s %s_%s\r\n", var->name, connectionDir, var->name); + stream.write( dStrlen((char*)output), output ); + } + + stream.write( dStrlen((char*)newLine), newLine ); +} + +void VertexParamsDefGLSL::print( Stream &stream, bool isVerterShader ) { // find all the uniform variables and print them out for( U32 i=0; i(LangElement::elementList[i]); + if( var ) + { + if( var->uniform && !var->sampler) + { + U8 output[256]; + if(var->arraySize <= 1) + dSprintf((char*)output, sizeof(output), " %s %s = %s;\r\n", var->type, var->name, var->name); + else + dSprintf((char*)output, sizeof(output), " %s %s[%d] = %s;\r\n", var->type, var->name, var->arraySize, var->name); + + stream.write( dStrlen((char*)output), output ); + } + } + } } diff --git a/Engine/source/shaderGen/GLSL/shaderCompGLSL.h b/Engine/source/shaderGen/GLSL/shaderCompGLSL.h index 5b306c0c8..c00c70165 100644 --- a/Engine/source/shaderGen/GLSL/shaderCompGLSL.h +++ b/Engine/source/shaderGen/GLSL/shaderCompGLSL.h @@ -40,7 +40,9 @@ public: virtual void reset(); virtual void sortVars(); - virtual void print( Stream &stream ); + virtual void print( Stream &stream, bool isVerterShader ); + void printStructDefines( Stream &stream, bool in ); + virtual void printOnMain( Stream &stream, bool isVerterShader ); }; class AppVertConnectorGLSL : public ShaderConnector @@ -53,21 +55,22 @@ public: virtual void reset(); virtual void sortVars(); - virtual void print( Stream &stream ); + virtual void print( Stream &stream, bool isVerterShader ); + virtual void printOnMain( Stream &stream, bool isVerterShader ); }; class VertexParamsDefGLSL : public ParamsDef { public: - virtual void print( Stream &stream ); + virtual void print( Stream &stream, bool isVerterShader ); }; class PixelParamsDefGLSL : public ParamsDef { public: - virtual void print( Stream &stream ); + virtual void print( Stream &stream, bool isVerterShader ); }; #endif // _SHADERCOMP_GLSL_H_ \ No newline at end of file diff --git a/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp b/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp index 0e0c1ac46..c8942f454 100644 --- a/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp +++ b/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp @@ -41,26 +41,37 @@ LangElement * ShaderFeatureGLSL::setupTexSpaceMat( Vector &, / Var *B = (Var*) LangElement::find( "B" ); Var *T = (Var*) LangElement::find( "T" ); + Var *tangentW = (Var*) LangElement::find( "tangentW" ); + // setup matrix var *texSpaceMat = new Var; - (*texSpaceMat)->setType( "mat3" ); + (*texSpaceMat)->setType( "float3x3" ); (*texSpaceMat)->setName( "objToTangentSpace" ); MultiLine * meta = new MultiLine; + meta->addStatement( new GenOp( " @;\r\n", new DecOp( *texSpaceMat ) ) ); - // Recreate the binormal if we don't have one. - if ( !B ) + // Protect against missing normal and tangent. + if ( !N || !T ) { - B = new Var; - B->setType( "vec3" ); - B->setName( "B" ); - meta->addStatement( new GenOp( " @ = cross( @, normalize(@) );\r\n", new DecOp( B ), T, N ) ); + meta->addStatement( new GenOp( " tSetMatrixRow(@, 0, float3( 1, 0, 0 )); tSetMatrixRow(@, 1,float3( 0, 1, 0 )); tSetMatrixRow(@,2, float3( 0, 0, 1 ));\r\n", + *texSpaceMat, *texSpaceMat, *texSpaceMat ) ); + return meta; } - meta->addStatement( new GenOp( " @;\r\n", new DecOp( *texSpaceMat ) ) ); - meta->addStatement( new GenOp( " @[0] = vec3(@.x, @.x, normalize(@).x);\r\n", *texSpaceMat, T, B, N ) ); - meta->addStatement( new GenOp( " @[1] = vec3(@.y, @.y, normalize(@).y);\r\n", *texSpaceMat, T, B, N ) ); - meta->addStatement( new GenOp( " @[2] = vec3(@.z, @.z, normalize(@).z);\r\n", *texSpaceMat, T, B, N ) ); + meta->addStatement( new GenOp( " tSetMatrixRow(@, 0, @);\r\n", *texSpaceMat, T ) ); + if ( B ) + meta->addStatement( new GenOp( " tSetMatrixRow(@, 1, @);\r\n", *texSpaceMat, B ) ); + else + { + if(dStricmp((char*)T->type, "vec4") == 0) + meta->addStatement( new GenOp( " tSetMatrixRow(@, 1, cross( @, normalize(@) ) * @.w);\r\n", *texSpaceMat, T, N, T ) ); + else if(tangentW) + meta->addStatement( new GenOp( " tSetMatrixRow(@, 1, cross( @, normalize(@) ) * @);\r\n", *texSpaceMat, T, N, tangentW ) ); + else + meta->addStatement( new GenOp( " tSetMatrixRow(@, 1, cross( @, normalize(@) ));\r\n", *texSpaceMat, T, N ) ); + } + meta->addStatement( new GenOp( " tSetMatrixRow(@, 2, normalize(@));\r\n", *texSpaceMat, N ) ); return meta; } @@ -107,7 +118,7 @@ LangElement* ShaderFeatureGLSL::assignColor( LangElement *elem, case Material::LerpAlpha: if ( !lerpElem ) lerpElem = elem; - assign = new GenOp( "@.rgb = mix( @.rgb, (@).rgb, (@).a )", color, elem, color, lerpElem ); + assign = new GenOp( "@.rgb = lerp( @.rgb, (@).rgb, (@).a )", color, color, elem, lerpElem ); break; case Material::ToneMap: @@ -136,10 +147,19 @@ LangElement *ShaderFeatureGLSL::expandNormalMap( LangElement *sampleNormalOp, if ( fd.features.hasFeature( MFT_IsDXTnm, getProcessIndex() ) ) { + if ( fd.features[MFT_ImposterVert] ) + { + // The imposter system uses object space normals and + // encodes them with the z axis in the alpha component. + meta->addStatement( new GenOp( " @ = float4( normalize( @.xyw * 2.0 - 1.0 ), 0.0 ); // Obj DXTnm\r\n", normalDecl, sampleNormalOp ) ); + } + else + { // DXT Swizzle trick - meta->addStatement( new GenOp( " @ = vec4( @.ag * 2.0 - 1.0, 0.0, 0.0 ); // DXTnm\r\n", normalDecl, sampleNormalOp ) ); + meta->addStatement( new GenOp( " @ = float4( @.ag * 2.0 - 1.0, 0.0, 0.0 ); // DXTnm\r\n", normalDecl, sampleNormalOp ) ); meta->addStatement( new GenOp( " @.z = sqrt( 1.0 - dot( @.xy, @.xy ) ); // DXTnm\r\n", normalVar, normalVar, normalVar ) ); } + } else { meta->addStatement( new GenOp( " @ = @;\r\n", normalDecl, sampleNormalOp ) ); @@ -165,6 +185,18 @@ Var * ShaderFeatureGLSL::getVertTexCoord( const String &name ) inTex = dynamic_cast( LangElement::elementList[i] ); if ( inTex ) { + // NOTE: This used to do this check... + // + // dStrcmp( (char*)inTex->structName, "IN" ) + // + // ... to ensure that the var was from the input + // vertex structure, but this kept some features + // ( ie. imposter vert ) from decoding their own + // coords for other features to use. + // + // If we run into issues with collisions between + // IN vars and local vars we may need to revise. + break; } } @@ -201,7 +233,7 @@ Var* ShaderFeatureGLSL::getOutWorldToTangent( Vector &compon { // turn obj->tangent into world->tangent worldToTangent = new Var; - worldToTangent->setType( "mat3x3" ); + worldToTangent->setType( "float3x3" ); worldToTangent->setName( "worldToTangent" ); LangElement *worldToTangentDecl = new DecOp( worldToTangent ); @@ -211,16 +243,29 @@ Var* ShaderFeatureGLSL::getOutWorldToTangent( Vector &compon { worldToObj = new Var; worldToObj->setName( "worldToObj" ); - worldToObj->setType( "mat4x4" ); + + if ( fd.features[MFT_UseInstancing] ) + { + // We just use transpose to convert the 3x3 portion of + // the object transform to its inverse. + worldToObj->setType( "float3x3" ); + Var *objTrans = getObjTrans( componentList, true, meta ); + meta->addStatement( new GenOp( " @ = transpose( float3x3(@) ); // Instancing!\r\n", new DecOp( worldToObj ), objTrans ) ); + } + else + { + worldToObj->setType( "float4x4" ); worldToObj->uniform = true; worldToObj->constSortPos = cspPrimitive; } + } // assign world->tangent transform - meta->addStatement( new GenOp( " @ = @ * mat3x3( @[0].xyz, @[1].xyz, @[2].xyz );\r\n", worldToTangentDecl, texSpaceMat, worldToObj, worldToObj, worldToObj ) ); + meta->addStatement( new GenOp( " @ = tMul( @, float3x3(@) );\r\n", worldToTangentDecl, texSpaceMat, worldToObj ) ); } else { + // Assume particle normal generation has set this up in the proper space worldToTangent = texSpaceMat; } } @@ -230,13 +275,14 @@ Var* ShaderFeatureGLSL::getOutWorldToTangent( Vector &compon outWorldToTangent = connectComp->getElement( RT_TEXCOORD, 1, 3 ); outWorldToTangent->setName( "outWorldToTangent" ); - outWorldToTangent->setType( "mat3x3" ); + outWorldToTangent->setStructName( "OUT" ); + outWorldToTangent->setType( "float3x3" ); meta->addStatement( new GenOp( " @ = @;\r\n", outWorldToTangent, worldToTangent ) ); return outWorldToTangent; } -Var* ShaderFeatureGLSL::getOutViewToTangent( Vector &componentList, +Var* ShaderFeatureGLSL::getOutViewToTangent( Vector &componentList, MultiLine *meta, const MaterialFeatureData &fd ) { @@ -247,14 +293,14 @@ Var* ShaderFeatureGLSL::getOutViewToTangent( Vector &compone Var *viewToTangent = (Var*)LangElement::find( "viewToTangent" ); if ( !viewToTangent ) { + Var *texSpaceMat = getOutObjToTangentSpace( componentList, meta, fd ); if(!fd.features[MFT_ParticleNormal]) { - // turn obj->tangent into world->tangent viewToTangent = new Var; - viewToTangent->setType( "mat3" ); + viewToTangent->setType( "float3x3" ); viewToTangent->setName( "viewToTangent" ); LangElement *viewToTangentDecl = new DecOp( viewToTangent ); @@ -262,11 +308,7 @@ Var* ShaderFeatureGLSL::getOutViewToTangent( Vector &compone Var *viewToObj = getInvWorldView( componentList, fd.features[MFT_UseInstancing], meta ); // assign world->tangent transform - meta->addStatement( new GenOp( " mat3 mat3ViewToObj;\r\n" ) ); - meta->addStatement( new GenOp( " mat3ViewToObj[0] = @[0].xyz;\r\n", viewToObj ) ); - meta->addStatement( new GenOp( " mat3ViewToObj[1] = @[1].xyz;\r\n", viewToObj ) ); - meta->addStatement( new GenOp( " mat3ViewToObj[2] = @[2].xyz;\r\n", viewToObj ) ); - meta->addStatement( new GenOp( " @ = @ * mat3ViewToObj;\r\n", viewToTangentDecl, texSpaceMat ) ); + meta->addStatement( new GenOp( " @ = tMul( (@), float3x3(@) );\r\n", viewToTangentDecl, texSpaceMat, viewToObj ) ); } else { @@ -280,7 +322,8 @@ Var* ShaderFeatureGLSL::getOutViewToTangent( Vector &compone outViewToTangent = connectComp->getElement( RT_TEXCOORD, 1, 3 ); outViewToTangent->setName( "outViewToTangent" ); - outViewToTangent->setType( "mat3" ); + outViewToTangent->setStructName( "OUT" ); + outViewToTangent->setType( "float3x3" ); meta->addStatement( new GenOp( " @ = @;\r\n", outViewToTangent, viewToTangent ) ); return outViewToTangent; @@ -304,6 +347,7 @@ Var* ShaderFeatureGLSL::getOutTexCoord( const char *name, texCoord = connectComp->getElement( RT_TEXCOORD ); texCoord->setName( outTexName ); + texCoord->setStructName( "OUT" ); texCoord->setType( type ); texCoord->mapsToSampler = mapsToSampler; @@ -313,21 +357,21 @@ Var* ShaderFeatureGLSL::getOutTexCoord( const char *name, // create texture mat var Var *texMat = new Var; - texMat->setType( "mat4" ); + texMat->setType( "float4x4" ); texMat->setName( "texMat" ); texMat->uniform = true; texMat->constSortPos = cspPass; // Statement allows for casting of different types which // eliminates vector truncation problems. - String statement = String::ToString( " @ = %s(@ * @);\r\n", type ); + String statement = String::ToString( " @ = %s(tMul(@, @));\r\n", type ); meta->addStatement( new GenOp( statement , texCoord, texMat, inTex ) ); } else { // Statement allows for casting of different types which // eliminates vector truncation problems. - String statement = String::ToString( " @ = %s(@);\r\n", type ); + String statement = String::ToString( " @ = %s(@);\r\n", type ); meta->addStatement( new GenOp( statement, texCoord, inTex ) ); } } @@ -349,6 +393,7 @@ Var* ShaderFeatureGLSL::getInTexCoord( const char *name, ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); texCoord = connectComp->getElement( RT_TEXCOORD ); texCoord->setName( name ); + texCoord->setStructName( "IN" ); texCoord->setType( type ); texCoord->mapsToSampler = mapsToSampler; } @@ -359,15 +404,97 @@ Var* ShaderFeatureGLSL::getInTexCoord( const char *name, return texCoord; } +Var* ShaderFeatureGLSL::getInColor( const char *name, + const char *type, + Vector &componentList ) +{ + Var *inColor = (Var*)LangElement::find( name ); + if ( !inColor ) + { + ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); + inColor = connectComp->getElement( RT_COLOR ); + inColor->setName( name ); + inColor->setStructName( "IN" ); + inColor->setType( type ); + } + + AssertFatal( dStrcmp( type, (const char*)inColor->type ) == 0, + "ShaderFeatureGLSL::getInColor - Type mismatch!" ); + + return inColor; +} + +Var* ShaderFeatureGLSL::addOutVpos( MultiLine *meta, + Vector &componentList ) +{ + /* + // Nothing to do if we're on SM 3.0... we use the real vpos. + if ( GFX->getPixelShaderVersion() >= 3.0f ) + return NULL; + */ + + // For SM 2.x we need to generate the vpos in the vertex shader + // and pass it as a texture coord to the pixel shader. + + Var *outVpos = (Var*)LangElement::find( "outVpos" ); + if ( !outVpos ) + { + ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); + + outVpos = connectComp->getElement( RT_TEXCOORD ); + outVpos->setName( "outVpos" ); + outVpos->setStructName( "OUT" ); + outVpos->setType( "vec4" ); + outVpos->mapsToSampler = false; + + Var *outPosition = (Var*) LangElement::find( "gl_Position" ); + AssertFatal( outPosition, "ShaderFeatureGLSL::addOutVpos - Didn't find the output position." ); + + meta->addStatement( new GenOp( " @ = @;\r\n", outVpos, outPosition ) ); + } + + return outVpos; +} + +Var* ShaderFeatureGLSL::getInVpos( MultiLine *meta, + Vector &componentList ) +{ + Var *inVpos = (Var*)LangElement::find( "vpos" ); + if ( inVpos ) + return inVpos; + + ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); + /* + if ( GFX->getPixelShaderVersion() >= 3.0f ) + { + inVpos = connectComp->getElement( RT_VPOS ); + inVpos->setName( "vpos" ); + inVpos->setStructName( "IN" ); + inVpos->setType( "vec2" ); + return inVpos; + } + */ + inVpos = connectComp->getElement( RT_TEXCOORD ); + inVpos->setName( "inVpos" ); + inVpos->setStructName( "IN" ); + inVpos->setType( "vec4" ); + + Var *vpos = new Var( "vpos", "vec2" ); + meta->addStatement( new GenOp( " @ = @.xy / @.w;\r\n", new DecOp( vpos ), inVpos, inVpos ) ); + + return vpos; +} + Var* ShaderFeatureGLSL::getInWorldToTangent( Vector &componentList ) { - Var *worldToTangent = (Var*)LangElement::find( "outWorldToTangent" ); + Var *worldToTangent = (Var*)LangElement::find( "worldToTangent" ); if ( !worldToTangent ) { ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); worldToTangent = connectComp->getElement( RT_TEXCOORD, 1, 3 ); - worldToTangent->setName( "outWorldToTangent" ); - worldToTangent->setType( "mat3x3" ); + worldToTangent->setName( "worldToTangent" ); + worldToTangent->setStructName( "IN" ); + worldToTangent->setType( "float3x3" ); } return worldToTangent; @@ -375,13 +502,14 @@ Var* ShaderFeatureGLSL::getInWorldToTangent( Vector &component Var* ShaderFeatureGLSL::getInViewToTangent( Vector &componentList ) { - Var *viewToTangent = (Var*)LangElement::find( "outViewToTangent" ); + Var *viewToTangent = (Var*)LangElement::find( "viewToTangent" ); if ( !viewToTangent ) { ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); viewToTangent = connectComp->getElement( RT_TEXCOORD, 1, 3 ); - viewToTangent->setName( "outViewToTangent" ); - viewToTangent->setType( "mat3" ); + viewToTangent->setName( "viewToTangent" ); + viewToTangent->setStructName( "IN" ); + viewToTangent->setType( "float3x3" ); } return viewToTangent; @@ -403,16 +531,43 @@ Var* ShaderFeatureGLSL::getNormalMapTex() return normalMap; } -Var* ShaderFeatureGLSL::getObjTrans( Vector &componentList, +Var* ShaderFeatureGLSL::getObjTrans( Vector &componentList, bool useInstancing, MultiLine *meta ) { - Var *objTrans = (Var*) LangElement::find( "objTrans" ); if ( objTrans ) + Var *objTrans = (Var*)LangElement::find( "objTrans" ); + if ( objTrans ) return objTrans; - objTrans = new Var; objTrans->setType( "mat4x4" ); + + if ( useInstancing ) + { + ShaderConnector *vertStruct = dynamic_cast( componentList[C_VERT_STRUCT] ); + Var *instObjTrans = vertStruct->getElement( RT_TEXCOORD, 4, 4 ); + instObjTrans->setStructName( "IN" ); + instObjTrans->setName( "inst_objectTrans" ); + + mInstancingFormat->addElement( "objTrans", GFXDeclType_Float4, instObjTrans->constNum+0 ); + mInstancingFormat->addElement( "objTrans", GFXDeclType_Float4, instObjTrans->constNum+1 ); + mInstancingFormat->addElement( "objTrans", GFXDeclType_Float4, instObjTrans->constNum+2 ); + mInstancingFormat->addElement( "objTrans", GFXDeclType_Float4, instObjTrans->constNum+3 ); + + objTrans = new Var; + objTrans->setType( "mat4x4" ); + objTrans->setName( "objTrans" ); + meta->addStatement( new GenOp( " @ = mat4x4( // Instancing!\r\n", new DecOp( objTrans ), instObjTrans ) ); + meta->addStatement( new GenOp( " @[0],\r\n", instObjTrans ) ); + meta->addStatement( new GenOp( " @[1],\r\n", instObjTrans ) ); + meta->addStatement( new GenOp( " @[2],\r\n",instObjTrans ) ); + meta->addStatement( new GenOp( " @[3] );\r\n", instObjTrans ) ); + } + else + { + objTrans = new Var; + objTrans->setType( "float4x4" ); objTrans->setName( "objTrans" ); objTrans->uniform = true; objTrans->constSortPos = cspPrimitive; + } return objTrans; } @@ -425,12 +580,33 @@ Var* ShaderFeatureGLSL::getModelView( Vector &componentList, if ( modelview ) return modelview; - // create modelview variable + if ( useInstancing ) + { + Var *objTrans = getObjTrans( componentList, useInstancing, meta ); + + Var *viewProj = (Var*)LangElement::find( "viewProj" ); + if ( !viewProj ) + { + viewProj = new Var; + viewProj->setType( "float4x4" ); + viewProj->setName( "viewProj" ); + viewProj->uniform = true; + viewProj->constSortPos = cspPass; + } + modelview = new Var; - modelview->setType( "mat4" ); + modelview->setType( "float4x4" ); + modelview->setName( "modelview" ); + meta->addStatement( new GenOp( " @ = tMul( @, @ ); // Instancing!\r\n", new DecOp( modelview ), viewProj, objTrans ) ); + } + else + { + modelview = new Var; + modelview->setType( "float4x4" ); modelview->setName( "modelview" ); modelview->uniform = true; modelview->constSortPos = cspPrimitive; + } return modelview; } @@ -443,15 +619,39 @@ Var* ShaderFeatureGLSL::getWorldView( Vector &componentList, if ( worldView ) return worldView; + if ( useInstancing ) + { + Var *objTrans = getObjTrans( componentList, useInstancing, meta ); + + Var *worldToCamera = (Var*)LangElement::find( "worldToCamera" ); + if ( !worldToCamera ) + { + worldToCamera = new Var; + worldToCamera->setType( "float4x4" ); + worldToCamera->setName( "worldToCamera" ); + worldToCamera->uniform = true; + worldToCamera->constSortPos = cspPass; + } + + worldView = new Var; + worldView->setType( "float4x4" ); + worldView->setName( "worldViewOnly" ); + + meta->addStatement( new GenOp( " @ = tMul( @, @ ); // Instancing!\r\n", new DecOp( worldView ), worldToCamera, objTrans ) ); + } + else + { worldView = new Var; - worldView->setType( "mat4x4" ); + worldView->setType( "float4x4" ); worldView->setName( "worldViewOnly" ); worldView->uniform = true; worldView->constSortPos = cspPrimitive; + } return worldView; } + Var* ShaderFeatureGLSL::getInvWorldView( Vector &componentList, bool useInstancing, MultiLine *meta ) @@ -460,11 +660,27 @@ Var* ShaderFeatureGLSL::getInvWorldView( Vector &componentLis if ( viewToObj ) return viewToObj; + if ( useInstancing ) + { + Var *worldView = getWorldView( componentList, useInstancing, meta ); + + viewToObj = new Var; + viewToObj->setType( "float3x3" ); + viewToObj->setName( "viewToObj" ); + + // We just use transpose to convert the 3x3 portion + // of the world view transform into its inverse. + + meta->addStatement( new GenOp( " @ = transpose( float3x3(@) ); // Instancing!\r\n", new DecOp( viewToObj ), worldView ) ); + } + else + { viewToObj = new Var; - viewToObj->setType( "mat4" ); + viewToObj->setType( "float4x4" ); viewToObj->setName( "viewToObj" ); viewToObj->uniform = true; viewToObj->constSortPos = cspPrimitive; + } return viewToObj; } @@ -491,7 +707,7 @@ void ShaderFeatureGLSL::getWsPosition( Vector &componentList, Var *objTrans = getObjTrans( componentList, useInstancing, meta ); - meta->addStatement( new GenOp( " @ = ( @ * vec4( @.xyz, 1 ) ).xyz;\r\n", + meta->addStatement( new GenOp( " @ = tMul( @, float4( @.xyz, 1 ) ).xyz;\r\n", wsPosition, objTrans, inPosition ) ); } @@ -505,6 +721,7 @@ Var* ShaderFeatureGLSL::addOutWsPosition( Vector &componentLis ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); outWsPosition = connectComp->getElement( RT_TEXCOORD ); outWsPosition->setName( "outWsPosition" ); + outWsPosition->setStructName( "OUT" ); outWsPosition->setType( "vec3" ); outWsPosition->mapsToSampler = false; @@ -516,12 +733,13 @@ Var* ShaderFeatureGLSL::addOutWsPosition( Vector &componentLis Var* ShaderFeatureGLSL::getInWsPosition( Vector &componentList ) { - Var *wsPosition = (Var*)LangElement::find( "outWsPosition" ); + Var *wsPosition = (Var*)LangElement::find( "wsPosition" ); if ( !wsPosition ) { ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); wsPosition = connectComp->getElement( RT_TEXCOORD ); - wsPosition->setName( "outWsPosition" ); + wsPosition->setName( "wsPosition" ); + wsPosition->setStructName( "IN" ); wsPosition->setType( "vec3" ); } @@ -566,7 +784,7 @@ Var* ShaderFeatureGLSL::addOutDetailTexCoord( Vector &compon // create detail variable Var *detScale = new Var; - detScale->setType( "vec2" ); + detScale->setType( "vec2" ); detScale->setName( "detailScale" ); detScale->uniform = true; detScale->constSortPos = cspPotentialPrimitive; @@ -575,25 +793,26 @@ Var* ShaderFeatureGLSL::addOutDetailTexCoord( Vector &compon ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); outTex = connectComp->getElement( RT_TEXCOORD ); outTex->setName( "detCoord" ); - outTex->setType( "vec2" ); + outTex->setStructName( "OUT" ); + outTex->setType( "vec2" ); outTex->mapsToSampler = true; if ( useTexAnim ) { - inTex->setType( "vec4" ); + inTex->setType( "vec4" ); // Find or create the texture matrix. Var *texMat = (Var*)LangElement::find( "texMat" ); if ( !texMat ) { texMat = new Var; - texMat->setType( "mat4x4" ); + texMat->setType( "float4x4" ); texMat->setName( "texMat" ); texMat->uniform = true; texMat->constSortPos = cspPass; } - meta->addStatement( new GenOp( " @ = (@ * @) * @;\r\n", outTex, texMat, inTex, detScale ) ); + meta->addStatement( new GenOp( " @ = tMul(@, @) * @;\r\n", outTex, texMat, inTex, detScale ) ); } else { @@ -608,7 +827,7 @@ Var* ShaderFeatureGLSL::addOutDetailTexCoord( Vector &compon // Base Texture //**************************************************************************** -void DiffuseMapFeatGLSL::processVert( Vector &componentList, +void DiffuseMapFeatGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { MultiLine *meta = new MultiLine; @@ -625,7 +844,7 @@ void DiffuseMapFeatGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { // grab connector texcoord register - Var *inTex = getInTexCoord( "out_texCoord", "vec2", true, componentList ); + Var *inTex = getInTexCoord( "texCoord", "vec2", true, componentList ); // create texture var Var *diffuseMap = new Var; @@ -645,7 +864,7 @@ void DiffuseMapFeatGLSL::processPix( Vector &componentList, diffColor->setName( "diffuseColor" ); LangElement *colorDecl = new DecOp( diffColor ); - meta->addStatement( new GenOp( " @ = texture2D(@, @);\r\n", + meta->addStatement( new GenOp( " @ = tex2D(@, @);\r\n", colorDecl, diffuseMap, inTex ) ); @@ -662,19 +881,19 @@ void DiffuseMapFeatGLSL::processPix( Vector &componentList, Var *atlasedTex = new Var; atlasedTex->setName("atlasedTexCoord"); - atlasedTex->setType("float2"); + atlasedTex->setType("vec2"); LangElement *atDecl = new DecOp(atlasedTex); // Parameters of the texture atlas Var *atParams = new Var; - atParams->setType("float4"); + atParams->setType("vec4"); atParams->setName("diffuseAtlasParams"); atParams->uniform = true; atParams->constSortPos = cspPotentialPrimitive; // Parameters of the texture (tile) this object is using in the atlas Var *tileParams = new Var; - tileParams->setType("float4"); + tileParams->setType("vec4"); tileParams->setName("diffuseAtlasTileParams"); tileParams->uniform = true; tileParams->constSortPos = cspPotentialPrimitive; @@ -683,24 +902,24 @@ void DiffuseMapFeatGLSL::processPix( Vector &componentList, if(is_sm3) { // Figure out the mip level - meta->addStatement(new GenOp(" vec2 _dx = ddx(@ * @.z);\r\n", inTex, atParams)); - meta->addStatement(new GenOp(" vec2 _dy = ddy(@ * @.z);\r\n", inTex, atParams)); + meta->addStatement(new GenOp(" float2 _dx = ddx(@ * @.z);\r\n", inTex, atParams)); + meta->addStatement(new GenOp(" float2 _dy = ddy(@ * @.z);\r\n", inTex, atParams)); meta->addStatement(new GenOp(" float mipLod = 0.5 * log2(max(dot(_dx, _dx), dot(_dy, _dy)));\r\n")); meta->addStatement(new GenOp(" mipLod = clamp(mipLod, 0.0, @.w);\r\n", atParams)); // And the size of the mip level meta->addStatement(new GenOp(" float mipPixSz = pow(2.0, @.w - mipLod);\r\n", atParams)); - meta->addStatement(new GenOp(" vec2 mipSz = mipPixSz / @.xy;\r\n", atParams)); + meta->addStatement(new GenOp(" float2 mipSz = mipPixSz / @.xy;\r\n", atParams)); } else { - meta->addStatement(new GenOp(" vec2 mipSz = float2(1.0, 1.0);\r\n")); + meta->addStatement(new GenOp(" float2 mipSz = float2(1.0, 1.0);\r\n")); } // Tiling mode // TODO: Select wrap or clamp somehow if( true ) // Wrap - meta->addStatement(new GenOp(" @ = fract(@);\r\n", atDecl, inTex)); + meta->addStatement(new GenOp(" @ = frac(@);\r\n", atDecl, inTex)); else // Clamp meta->addStatement(new GenOp(" @ = saturate(@);\r\n", atDecl, inTex)); @@ -724,7 +943,7 @@ void DiffuseMapFeatGLSL::processPix( Vector &componentList, #ifdef DEBUG_ATLASED_UV_COORDS if(!fd.features[MFT_PrePassConditioner]) { - meta->addStatement(new GenOp(" @ = vec4(@.xy, mipLod / @.w, 1.0);\r\n", new DecOp(diffColor), inTex, atParams)); + meta->addStatement(new GenOp(" @ = float4(@.xy, mipLod / @.w, 1.0);\r\n", new DecOp(diffColor), inTex, atParams)); meta->addStatement(new GenOp(" @; return OUT;\r\n", assignColor(diffColor, Material::Mul))); return; } @@ -732,12 +951,12 @@ void DiffuseMapFeatGLSL::processPix( Vector &componentList, if(is_sm3) { - meta->addStatement(new GenOp( " @ = texture2Dlod(@, float4(@, 0.0, mipLod));\r\n", + meta->addStatement(new GenOp( " @ = tex2Dlod(@, float4(@, 0.0, mipLod));\r\n", new DecOp(diffColor), diffuseMap, inTex)); } else { - meta->addStatement(new GenOp( " @ = texture2D(@, @);\r\n", + meta->addStatement(new GenOp( " @ = tex2D(@, @);\r\n", new DecOp(diffColor), diffuseMap, inTex)); } @@ -745,7 +964,7 @@ void DiffuseMapFeatGLSL::processPix( Vector &componentList, } else { - LangElement *statement = new GenOp( "texture2D(@, @)", diffuseMap, inTex ); + LangElement *statement = new GenOp( "tex2D(@, @)", diffuseMap, inTex ); output = new GenOp( " @;\r\n", assignColor( statement, Material::Mul ) ); } @@ -767,7 +986,10 @@ void DiffuseMapFeatGLSL::setTexData( Material::StageData &stageDat, { GFXTextureObject *tex = stageDat.getTex( MFT_DiffuseMap ); if ( tex ) + { + passData.mSamplerNames[ texIndex ] = "diffuseMap"; passData.mTexSlot[ texIndex++ ].texObject = tex; + } } @@ -785,6 +1007,7 @@ void OverlayTexFeatGLSL::processVert( Vector &componentList, ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *outTex = connectComp->getElement( RT_TEXCOORD ); outTex->setName( "outTexCoord2" ); + outTex->setStructName( "OUT" ); outTex->setType( "vec2" ); outTex->mapsToSampler = true; @@ -797,13 +1020,13 @@ void OverlayTexFeatGLSL::processVert( Vector &componentList, if ( !texMat ) { texMat = new Var; - texMat->setType( "mat4x4" ); + texMat->setType( "float4x4" ); texMat->setName( "texMat" ); texMat->uniform = true; texMat->constSortPos = cspPass; } - output = new GenOp( " @ = @ * @;\r\n", outTex, texMat, inTex ); + output = new GenOp( " @ = tMul(@, @);\r\n", outTex, texMat, inTex ); return; } @@ -818,7 +1041,8 @@ void OverlayTexFeatGLSL::processPix( Vector &componentList, // grab connector texcoord register ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *inTex = connectComp->getElement( RT_TEXCOORD ); - inTex->setName( "outTexCoord2" ); + inTex->setName( "texCoord2" ); + inTex->setStructName( "IN" ); inTex->setType( "vec2" ); inTex->mapsToSampler = true; @@ -830,7 +1054,7 @@ void OverlayTexFeatGLSL::processPix( Vector &componentList, diffuseMap->sampler = true; diffuseMap->constNum = Var::getTexUnitNum(); // used as texture unit num here - LangElement *statement = new GenOp( "texture2D(@, @)", diffuseMap, inTex ); + LangElement *statement = new GenOp( "tex2D(@, @)", diffuseMap, inTex ); output = new GenOp( " @;\r\n", assignColor( statement, Material::LerpAlpha ) ); } @@ -899,6 +1123,7 @@ void DiffuseVertColorFeatureGLSL::processVert( Vector< ShaderComponent* >& comp AssertFatal( connectComp, "DiffuseVertColorFeatureGLSL::processVert - C_CONNECTOR is not a ShaderConnector" ); Var* outColor = connectComp->getElement( RT_COLOR ); outColor->setName( "vertColor" ); + outColor->setStructName( "OUT" ); outColor->setType( "vec4" ); output = new GenOp( " @ = @;\r\n", outColor, inColor ); @@ -917,6 +1142,7 @@ void DiffuseVertColorFeatureGLSL::processPix( Vector &compon AssertFatal( connectComp, "DiffuseVertColorFeatureGLSL::processVert - C_CONNECTOR is not a ShaderConnector" ); vertColor = connectComp->getElement( RT_COLOR ); vertColor->setName( "vertColor" ); + vertColor->setStructName( "IN" ); vertColor->setType( "vec4" ); } @@ -934,12 +1160,13 @@ void LightmapFeatGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { // grab tex register from incoming vert - Var *inTex = (Var*) LangElement::find( "texCoord2" ); + Var *inTex = getVertTexCoord( "texCoord2" ); // grab connector texcoord register ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *outTex = connectComp->getElement( RT_TEXCOORD ); - outTex->setName( "outTexCoord2" ); + outTex->setName( "texCoord2" ); + outTex->setStructName( "OUT" ); outTex->setType( "vec2" ); outTex->mapsToSampler = true; @@ -953,7 +1180,8 @@ void LightmapFeatGLSL::processPix( Vector &componentList, // grab connector texcoord register ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *inTex = connectComp->getElement( RT_TEXCOORD ); - inTex->setName( "outTexCoord2" ); + inTex->setName( "texCoord2" ); + inTex->setStructName( "IN" ); inTex->setType( "vec2" ); inTex->mapsToSampler = true; @@ -974,7 +1202,7 @@ void LightmapFeatGLSL::processPix( Vector &componentList, lmColor->setType( "vec4" ); LangElement *lmColorDecl = new DecOp( lmColor ); - output = new GenOp( " @ = texture2D(@, @);\r\n", lmColorDecl, lightMap, inTex ); + output = new GenOp( " @ = tex2D(@, @);\r\n", lmColorDecl, lightMap, inTex ); return; } @@ -995,21 +1223,27 @@ void LightmapFeatGLSL::processPix( Vector &componentList, // Lightmap has already been included in the advanced light bin, so // no need to do any sampling or anything if(bPreProcessedLighting) - statement = new GenOp( "vec4(@, 1.0)", inColor ); + statement = new GenOp( "float4(@, 1.0)", inColor ); else - statement = new GenOp( "texture2D(@, @) + vec4(@.rgb, 0.0)", lightMap, inTex, inColor ); + statement = new GenOp( "tex2D(@, @) + float4(@.rgb, 0.0)", lightMap, inTex, inColor ); } } - else - { - statement = new GenOp( "texture2D(@, @)", lightMap, inTex ); - } + + // If we still don't have it... then just sample the lightmap. + if ( !statement ) + statement = new GenOp( "tex2D(@, @)", lightMap, inTex ); // Assign to proper render target + MultiLine *meta = new MultiLine; if( fd.features[MFT_LightbufferMRT] ) - output = new GenOp( " @;\r\n", assignColor( statement, Material::None, NULL, ShaderFeature::RenderTarget1 ) ); + { + meta->addStatement( new GenOp( " @;\r\n", assignColor( statement, Material::None, NULL, ShaderFeature::RenderTarget1 ) ) ); + meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget1) ) ) ); + } else - output = new GenOp( " @;\r\n", assignColor( statement, Material::Mul ) ); + meta->addStatement( new GenOp( " @;\r\n", assignColor( statement, Material::Mul ) ) ); + + output = meta; } ShaderFeature::Resources LightmapFeatGLSL::getResources( const MaterialFeatureData &fd ) @@ -1027,6 +1261,7 @@ void LightmapFeatGLSL::setTexData( Material::StageData &stageDat, U32 &texIndex ) { GFXTextureObject *tex = stageDat.getTex( MFT_LightMap ); + passData.mSamplerNames[ texIndex ] = "lightMap"; if ( tex ) passData.mTexSlot[ texIndex++ ].texObject = tex; else @@ -1054,7 +1289,8 @@ void TonemapFeatGLSL::processVert( Vector &componentList, if ( inTex2 ) { Var *outTex2 = connectComp->getElement( RT_TEXCOORD ); - outTex2->setName( "toneMapCoord" ); + outTex2->setName( "texCoord2" ); + outTex2->setStructName( "OUT" ); outTex2->setType( "vec2" ); outTex2->mapsToSampler = true; @@ -1069,7 +1305,8 @@ void TonemapFeatGLSL::processPix( Vector &componentList, ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *inTex2 = connectComp->getElement( RT_TEXCOORD ); - inTex2->setName( "toneMapCoord" ); + inTex2->setName( "texCoord2" ); + inTex2->setStructName( "IN" ); inTex2->setType( "vec2" ); inTex2->mapsToSampler = true; @@ -1089,14 +1326,14 @@ void TonemapFeatGLSL::processPix( Vector &componentList, toneMapColor->setName( "toneMapColor" ); LangElement *toneMapColorDecl = new DecOp( toneMapColor ); - meta->addStatement( new GenOp( " @ = texture2D(@, @);\r\n", toneMapColorDecl, toneMap, inTex2 ) ); + meta->addStatement( new GenOp( " @ = tex2D(@, @);\r\n", toneMapColorDecl, toneMap, inTex2 ) ); // We do a different calculation if there is a diffuse map or not Material::BlendOp blendOp = Material::Mul; if ( fd.features[MFT_DiffuseMap] ) { // Reverse the tonemap - meta->addStatement( new GenOp( " @ = -1.0 * log(1.0 - @);\r\n", toneMapColor, toneMapColor ) ); + meta->addStatement( new GenOp( " @ = -1.0f * log(1.0f - @);\r\n", toneMapColor, toneMapColor ) ); // Re-tonemap with the current color factored in blendOp = Material::ToneMap; @@ -1126,7 +1363,10 @@ void TonemapFeatGLSL::processPix( Vector &componentList, // Assign to proper render target if( fd.features[MFT_LightbufferMRT] ) + { meta->addStatement( new GenOp( " @;\r\n", assignColor( toneMapColor, Material::None, NULL, ShaderFeature::RenderTarget1 ) ) ); + meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget1) ) ) ); + } else meta->addStatement( new GenOp( " @;\r\n", assignColor( toneMapColor, blendOp ) ) ); @@ -1151,6 +1391,7 @@ void TonemapFeatGLSL::setTexData( Material::StageData &stageDat, if ( tex ) { passData.mTexType[ texIndex ] = Material::ToneMapTex; + passData.mSamplerNames[ texIndex ] = "toneMap"; passData.mTexSlot[ texIndex++ ].texObject = tex; } } @@ -1194,6 +1435,7 @@ void VertLitGLSL::processVert( Vector &componentList, ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *outColor = connectComp->getElement( RT_COLOR ); outColor->setName( "vertColor" ); + outColor->setStructName( "OUT" ); outColor->setType( "vec4" ); output = new GenOp( " @ = @;\r\n", outColor, inColor ); @@ -1221,6 +1463,7 @@ void VertLitGLSL::processPix( Vector &componentList, AssertFatal( connectComp, "VertLitGLSL::processVert - C_CONNECTOR is not a ShaderConnector" ); vertColor = connectComp->getElement( RT_COLOR ); vertColor->setName( "vertColor" ); + vertColor->setStructName( "IN" ); vertColor->setType( "vec4" ); } @@ -1239,12 +1482,11 @@ void VertLitGLSL::processPix( Vector &componentList, LangElement *finalVertColorDecl = new DecOp( finalVertColor ); // Reverse the tonemap - meta->addStatement( new GenOp( " @ = -1.0 * log(1.0 - @);\r\n", finalVertColorDecl, vertColor ) ); + meta->addStatement( new GenOp( " @ = -1.0f * log(1.0f - @);\r\n", finalVertColorDecl, vertColor ) ); // Set the blend op to tonemap blendOp = Material::ToneMap; outColor = finalVertColor; - } // Add in the realtime lighting contribution, if applicable @@ -1253,7 +1495,6 @@ void VertLitGLSL::processPix( Vector &componentList, Var *rtLightingColor = (Var*) LangElement::find( "d_lightcolor" ); if(rtLightingColor != NULL) { - // Find out if RTLighting should be added or substituted bool bPreProcessedLighting = false; AdvancedLightBinManager *lightBin; if ( Sim::findObject( "AL_LightBinMgr", lightBin ) ) @@ -1263,15 +1504,18 @@ void VertLitGLSL::processPix( Vector &componentList, // the dynamic light buffer, and it already has the baked-vertex-color // included in it if(bPreProcessedLighting) - outColor = new GenOp( "vec4(@.rgb, 1.0)", rtLightingColor ); + outColor = new GenOp( "float4(@.rgb, 1.0)", rtLightingColor ); else - outColor = new GenOp( "vec4(@.rgb, 0.0) + @", rtLightingColor, outColor ); + outColor = new GenOp( "float4(@.rgb + @.rgb, 1.0)", rtLightingColor, outColor ); } } // Output the color if ( fd.features[MFT_LightbufferMRT] ) + { meta->addStatement( new GenOp( " @;\r\n", assignColor( outColor, Material::None, NULL, ShaderFeature::RenderTarget1 ) ) ); + meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget1) ) ) ); + } else meta->addStatement( new GenOp( " @;\r\n", assignColor( outColor, blendOp ) ) ); @@ -1283,7 +1527,6 @@ U32 VertLitGLSL::getOutputTargets( const MaterialFeatureData &fd ) const return fd.features[MFT_LightbufferMRT] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget; } - //**************************************************************************** // Detail map //**************************************************************************** @@ -1319,7 +1562,7 @@ void DetailFeatGLSL::processPix( Vector &componentList, // TODO: We could add a feature to toggle between this // and a simple multiplication with the detail map. - LangElement *statement = new GenOp( "( texture2D(@, @) * 2.0 ) - 1.0", detailMap, inTex ); + LangElement *statement = new GenOp( "( tex2D(@, @) * 2.0 ) - 1.0", detailMap, inTex ); output = new GenOp( " @;\r\n", assignColor( statement, Material::Add ) ); } @@ -1339,7 +1582,10 @@ void DetailFeatGLSL::setTexData( Material::StageData &stageDat, { GFXTextureObject *tex = stageDat.getTex( MFT_DetailMap ); if ( tex ) + { + passData.mSamplerNames[texIndex] = "detailMap"; passData.mTexSlot[ texIndex++ ].texObject = tex; + } } @@ -1347,6 +1593,17 @@ void DetailFeatGLSL::setTexData( Material::StageData &stageDat, // Vertex position //**************************************************************************** +void VertPositionGLSL::determineFeature( Material *material, + const GFXVertexFormat *vertexFormat, + U32 stageNum, + const FeatureType &type, + const FeatureSet &features, + MaterialFeatureData *outFeatureData ) +{ + // This feature is always on! + outFeatureData->features.addFeature( type ); +} + void VertPositionGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { @@ -1365,7 +1622,8 @@ void VertPositionGLSL::processVert( Vector &componentList, Var *modelview = getModelView( componentList, fd.features[MFT_UseInstancing], meta ); - meta->addStatement( new GenOp( " @ = @ * vec4(@.xyz,1);\r\n", outPosition, modelview, inPosition ) ); + meta->addStatement( new GenOp( " @ = tMul(@, float4(@.xyz,1));\r\n", + outPosition, modelview, inPosition ) ); output = meta; } @@ -1378,6 +1636,11 @@ void VertPositionGLSL::processVert( Vector &componentList, void ReflectCubeFeatGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { + // search for vert normal + Var *inNormal = (Var*) LangElement::find( "normal" ); + if ( !inNormal ) + return; + MultiLine * meta = new MultiLine; // If a base or bump tex is present in the material, but not in the @@ -1395,7 +1658,8 @@ void ReflectCubeFeatGLSL::processVert( Vector &componentList, // grab connector texcoord register ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *outTex = connectComp->getElement( RT_TEXCOORD ); - outTex->setName( "outTexCoord" ); + outTex->setName( "texCoord" ); + outTex->setStructName( "OUT" ); outTex->setType( "vec2" ); outTex->mapsToSampler = true; @@ -1405,54 +1669,60 @@ void ReflectCubeFeatGLSL::processVert( Vector &componentList, } // create cubeTrans - Var *cubeTrans = new Var; - cubeTrans->setType( "mat3" ); - cubeTrans->setName( "cubeTrans" ); - cubeTrans->uniform = true; - cubeTrans->constSortPos = cspPrimitive; - - // create cubeEye position - Var *cubeEyePos = new Var; - cubeEyePos->setType( "vec3" ); - cubeEyePos->setName( "cubeEyePos" ); - cubeEyePos->uniform = true; - cubeEyePos->constSortPos = cspPrimitive; - - // search for vert normal - Var *inNormal = (Var*) LangElement::find( "normal" ); + bool useInstancing = fd.features[MFT_UseInstancing]; + Var *cubeTrans = getObjTrans( componentList, useInstancing, meta ); // cube vert position Var * cubeVertPos = new Var; cubeVertPos->setName( "cubeVertPos" ); - cubeVertPos->setType( "vec3" ); + cubeVertPos->setType( "vec3" ); LangElement *cubeVertPosDecl = new DecOp( cubeVertPos ); - meta->addStatement( new GenOp( " @ = @ * @.xyz;\r\n", + meta->addStatement( new GenOp( " @ = tMul(mat3( @ ), @).xyz;\r\n", cubeVertPosDecl, cubeTrans, LangElement::find( "position" ) ) ); // cube normal Var * cubeNormal = new Var; cubeNormal->setName( "cubeNormal" ); - cubeNormal->setType( "vec3" ); + cubeNormal->setType( "vec3" ); LangElement *cubeNormDecl = new DecOp( cubeNormal ); - meta->addStatement( new GenOp( " @ = normalize( @ * normalize(@).xyz );\r\n", + meta->addStatement( new GenOp( " @ = ( tMul( (@), vec4(@, 0) ) ).xyz;\r\n", cubeNormDecl, cubeTrans, inNormal ) ); + // grab the eye position + Var *eyePos = (Var*)LangElement::find( "eyePosWorld" ); + if ( !eyePos ) + { + eyePos = new Var( "eyePosWorld", "vec3" ); + eyePos->uniform = true; + eyePos->constSortPos = cspPass; + } + + // cube position + Var * cubePos = new Var; + cubePos->setName( "cubePos" ); + cubePos->setType( "vec3" ); + LangElement *cubePosDecl = new DecOp( cubePos ); + + meta->addStatement( new GenOp( " @ = vec3( @[3][0], @[3][1], @[3][2] );\r\n", + cubePosDecl, cubeTrans, cubeTrans, cubeTrans ) ); + // eye to vert Var * eyeToVert = new Var; eyeToVert->setName( "eyeToVert" ); - eyeToVert->setType( "vec3" ); + eyeToVert->setType( "vec3" ); LangElement *e2vDecl = new DecOp( eyeToVert ); - meta->addStatement( new GenOp( " @ = @ - @;\r\n", - e2vDecl, cubeVertPos, cubeEyePos ) ); + meta->addStatement( new GenOp( " @ = @ - ( @ - @ );\r\n", + e2vDecl, cubeVertPos, eyePos, cubePos ) ); // grab connector texcoord register ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *reflectVec = connectComp->getElement( RT_TEXCOORD ); reflectVec->setName( "reflectVec" ); - reflectVec->setType( "vec3" ); + reflectVec->setStructName( "OUT" ); + reflectVec->setType( "vec3" ); reflectVec->mapsToSampler = true; meta->addStatement( new GenOp( " @ = reflect(@, @);\r\n", reflectVec, eyeToVert, cubeNormal ) ); @@ -1476,7 +1746,7 @@ void ReflectCubeFeatGLSL::processPix( Vector &componentList, fd.materialFeatures[MFT_NormalMap] ) { // grab connector texcoord register - Var *inTex = getInTexCoord( "outTexCoord", "vec2", true, componentList ); + Var *inTex = getInTexCoord( "texCoord", "vec2", true, componentList ); // create texture var Var *newMap = new Var; @@ -1494,7 +1764,7 @@ void ReflectCubeFeatGLSL::processPix( Vector &componentList, glossColor = color; - meta->addStatement( new GenOp( " @ = texture2D( @, @ );\r\n", colorDecl, newMap, inTex ) ); + meta->addStatement( new GenOp( " @ = tex2D( @, @ );\r\n", colorDecl, newMap, inTex ) ); } } else @@ -1508,12 +1778,13 @@ void ReflectCubeFeatGLSL::processPix( Vector &componentList, ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *reflectVec = connectComp->getElement( RT_TEXCOORD ); reflectVec->setName( "reflectVec" ); + reflectVec->setStructName( "IN" ); reflectVec->setType( "vec3" ); reflectVec->mapsToSampler = true; // create cubemap var Var *cubeMap = new Var; - cubeMap->setType( "samplerCube" ); + cubeMap->setType( "samplerCUBE" ); cubeMap->setName( "cubeMap" ); cubeMap->uniform = true; cubeMap->sampler = true; @@ -1527,7 +1798,7 @@ void ReflectCubeFeatGLSL::processPix( Vector &componentList, if ( fd.materialFeatures[MFT_RTLighting] ) attn =(Var*)LangElement::find("d_NL_Att"); - LangElement *texCube = new GenOp( "textureCube( @, @ )", cubeMap, reflectVec ); + LangElement *texCube = new GenOp( "texCUBE( @, @ )", cubeMap, reflectVec ); LangElement *lerpVal = NULL; Material::BlendOp blendOp = Material::LerpAlpha; @@ -1583,22 +1854,27 @@ void ReflectCubeFeatGLSL::setTexData( Material::StageData &stageDat, !passData.mFeatureData.features[MFT_NormalMap] ) { GFXTextureObject *tex = stageDat.getTex( MFT_DetailMap ); - if ( tex && - stageFeatures.features[MFT_DiffuseMap] ) + if ( tex && stageFeatures.features[MFT_DiffuseMap] ) + { + passData.mSamplerNames[ texIndex ] = "diffuseMap"; passData.mTexSlot[ texIndex++ ].texObject = tex; + } else { tex = stageDat.getTex( MFT_NormalMap ); - if ( tex && - stageFeatures.features[ MFT_NormalMap ] ) + if ( tex && stageFeatures.features[ MFT_NormalMap ] ) + { + passData.mSamplerNames[ texIndex ] = "bumpMap"; passData.mTexSlot[ texIndex++ ].texObject = tex; + } } } if( stageDat.getCubemap() ) { passData.mCubeMap = stageDat.getCubemap(); + passData.mSamplerNames[texIndex] = "cubeMap"; passData.mTexType[texIndex++] = Material::Cube; } else @@ -1606,6 +1882,7 @@ void ReflectCubeFeatGLSL::setTexData( Material::StageData &stageDat, if( stageFeatures.features[MFT_CubeMap] ) { // assuming here that it is a scenegraph cubemap + passData.mSamplerNames[texIndex] = "cubeMap"; passData.mTexType[texIndex++] = Material::SGCube; } } @@ -1639,18 +1916,17 @@ void RTLightingFeatGLSL::processVert( Vector &componentList, Var *eyePos = (Var*)LangElement::find( "eyePosWorld" ); if ( !eyePos ) { - eyePos = new Var( "eyePosWorld", "float3" ); + eyePos = new Var( "eyePosWorld", "vec3" ); eyePos->uniform = true; eyePos->constSortPos = cspPass; } - //TODO: should this be the same as "Find the incoming vertex normal" below? Var *inPosition = (Var*)LangElement::find( "position" ); Var *outNormal = connectComp->getElement( RT_TEXCOORD ); outNormal->setName( "wsNormal" ); outNormal->setStructName( "OUT" ); - outNormal->setType( "float3" ); + outNormal->setType( "vec3" ); outNormal->mapsToSampler = false; // Transform the normal to world space. @@ -1665,9 +1941,7 @@ void RTLightingFeatGLSL::processVert( Vector &componentList, } // Find the incoming vertex normal. - Var *inNormal = (Var*)LangElement::find( "inNormal" ); - if ( !inNormal ) - inNormal = (Var*)LangElement::find( "normal" ); + Var *inNormal = (Var*)LangElement::find( "normal" ); // Skip out on realtime lighting if we don't have a normal // or we're doing some sort of baked lighting. @@ -1675,29 +1949,25 @@ void RTLightingFeatGLSL::processVert( Vector &componentList, fd.features[MFT_LightMap] || fd.features[MFT_ToneMap] || fd.features[MFT_VertLit] ) - return; - - // Get the transform to world space. - Var *objTrans = getObjTrans( componentList, fd.features[MFT_UseInstancing], meta ); + return; // If there isn't a normal map then we need to pass // the world space normal to the pixel shader ourselves. if ( !fd.features[MFT_NormalMap] ) { Var *outNormal = connectComp->getElement( RT_TEXCOORD ); - outNormal->setName( "outWsNormal" ); + outNormal->setName( "wsNormal" ); + outNormal->setStructName( "OUT" ); outNormal->setType( "vec3" ); outNormal->mapsToSampler = false; + + // Get the transform to world space. + Var *objTrans = getObjTrans( componentList, fd.features[MFT_UseInstancing], meta ); // Transform the normal to world space. - meta->addStatement( new GenOp( " @ = ( @ * vec4( normalize( @ ), 0.0 ) ).xyz;\r\n", outNormal, objTrans, inNormal ) ); + meta->addStatement( new GenOp( " @ = tMul( @, float4( normalize( @ ), 0.0 ) ).xyz;\r\n", outNormal, objTrans, inNormal ) ); } - // Get the input position. - Var *inPosition = (Var*)LangElement::find( "inPosition" ); - if ( !inPosition ) - inPosition = (Var*)LangElement::find( "position" ); - addOutWsPosition( componentList, fd.features[MFT_UseInstancing], meta ); output = meta; @@ -1723,41 +1993,25 @@ void RTLightingFeatGLSL::processPix( Vector &componentList, Var *wsNormal = (Var*)LangElement::find( "wsNormal" ); if ( !wsNormal ) { - Var *outWsNormal = connectComp->getElement( RT_TEXCOORD ); - outWsNormal->setName( "outWsNormal" ); - outWsNormal->setType( "vec3" ); + wsNormal = connectComp->getElement( RT_TEXCOORD ); + wsNormal->setName( "wsNormal" ); + wsNormal->setStructName( "IN" ); + wsNormal->setType( "vec3" ); - wsNormal = new Var( "wsNormal", "vec3" ); - - // If we loaded the normal its our resposibility + // If we loaded the normal its our responsibility // to normalize it... the interpolators won't. - meta->addStatement( new GenOp( " @ = normalize( @ );\r\n", - new DecOp( wsNormal ), outWsNormal ) ); + // + // Note we cast to half here to get partial precision + // optimized code which is an acceptable loss of + // precision for normals and performs much better + // on older Geforce cards. + // + meta->addStatement( new GenOp( " @ = normalize( half3( @ ) );\r\n", wsNormal, wsNormal ) ); } - Var *wsPosition = getInWsPosition( componentList ); - - // If we have a specular feature then we need to - // get the world space view vector to pass to the - // lighting calculation. - Var *wsView = new Var( "wsView", "vec3" ); - if ( fd.features[MFT_PixSpecular] ) - { - Var *eyePos = (Var*)LangElement::find( "eyePosWorld" ); - if ( !eyePos ) - { - eyePos = new Var; - eyePos->setType( "vec3" ); - eyePos->setName( "eyePosWorld" ); - eyePos->uniform = true; - eyePos->constSortPos = cspPass; - } - - meta->addStatement( new GenOp( " @ = normalize( @ - @ );\r\n", - new DecOp( wsView ), eyePos, wsPosition ) ); - } - else - meta->addStatement( new GenOp( " @ = vec3( 0 );\r\n", new DecOp( wsView ) ) ); + // Now the wsPosition and wsView. + Var *wsPosition = getInWsPosition( componentList ); + Var *wsView = getWsView( wsPosition, meta ); // Create temporaries to hold results of lighting. Var *rtShading = new Var( "rtShading", "vec4" ); @@ -1765,18 +2019,66 @@ void RTLightingFeatGLSL::processPix( Vector &componentList, meta->addStatement( new GenOp( " @; @;\r\n", new DecOp( rtShading ), new DecOp( specular ) ) ); - // Calculate the diffuse shading and specular powers. - meta->addStatement( new GenOp( " compute4Lights( @, @, @, @, @ );\r\n", - wsView, wsPosition, wsNormal, rtShading, specular ) ); - // Look for a light mask generated from a previous // feature (this is done for BL terrain lightmaps). - Var *lightMask = (Var*)LangElement::find( "lightMask" ); - if ( lightMask ) - meta->addStatement( new GenOp( " @.rgb *= @;\r\n", rtShading, lightMask ) ); + LangElement *lightMask = LangElement::find( "lightMask" ); + if ( !lightMask ) + lightMask = new GenOp( "float4( 1, 1, 1, 1 )" ); + + // Get all the light constants. + Var *inLightPos = new Var( "inLightPos", "vec4" ); + inLightPos->uniform = true; + inLightPos->arraySize = 3; + inLightPos->constSortPos = cspPotentialPrimitive; + + Var *inLightInvRadiusSq = new Var( "inLightInvRadiusSq", "vec4" ); + inLightInvRadiusSq->uniform = true; + inLightInvRadiusSq->constSortPos = cspPotentialPrimitive; + + Var *inLightColor = new Var( "inLightColor", "vec4" ); + inLightColor->uniform = true; + inLightColor->arraySize = 4; + inLightColor->constSortPos = cspPotentialPrimitive; + + Var *inLightSpotDir = new Var( "inLightSpotDir", "vec4" ); + inLightSpotDir->uniform = true; + inLightSpotDir->arraySize = 3; + inLightSpotDir->constSortPos = cspPotentialPrimitive; + + Var *inLightSpotAngle = new Var( "inLightSpotAngle", "vec4" ); + inLightSpotAngle->uniform = true; + inLightSpotAngle->constSortPos = cspPotentialPrimitive; + + Var *lightSpotFalloff = new Var( "inLightSpotFalloff", "vec4" ); + lightSpotFalloff->uniform = true; + lightSpotFalloff->constSortPos = cspPotentialPrimitive; + + Var *specularPower = new Var( "specularPower", "float" ); + specularPower->uniform = true; + specularPower->constSortPos = cspPotentialPrimitive; + + Var *specularColor = (Var*)LangElement::find( "specularColor" ); + if ( !specularColor ) + { + specularColor = new Var( "specularColor", "vec4" ); + specularColor->uniform = true; + specularColor->constSortPos = cspPotentialPrimitive; + } + + Var *ambient = new Var( "ambient", "vec4" ); + ambient->uniform = true; + ambient->constSortPos = cspPass; + + // Calculate the diffuse shading and specular powers. + meta->addStatement( new GenOp( " compute4Lights( @, @, @, @,\r\n" + " @, @, @, @, @, @, @, @,\r\n" + " @, @ );\r\n", + wsView, wsPosition, wsNormal, lightMask, + inLightPos, inLightInvRadiusSq, inLightColor, inLightSpotDir, inLightSpotAngle, lightSpotFalloff, specularPower, specularColor, + rtShading, specular ) ); // Apply the lighting to the diffuse color. - LangElement *lighting = new GenOp( "vec4( @.rgb + ambient.rgb, 1 )", rtShading ); + LangElement *lighting = new GenOp( "float4( @.rgb + @.rgb, 1 )", rtShading, ambient ); meta->addStatement( new GenOp( " @;\r\n", assignColor( lighting, Material::Mul ) ) ); output = meta; } @@ -1844,6 +2146,7 @@ void FogFeatGLSL::processVert( Vector &componentList, ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *fogAmount = connectComp->getElement( RT_TEXCOORD ); fogAmount->setName( "fogAmount" ); + fogAmount->setStructName( "OUT" ); fogAmount->setType( "float" ); fogAmount->mapsToSampler = false; @@ -1891,6 +2194,7 @@ void FogFeatGLSL::processPix( Vector &componentList, ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); fogAmount = connectComp->getElement( RT_TEXCOORD ); fogAmount->setName( "fogAmount" ); + fogAmount->setStructName( "IN" ); fogAmount->setType( "float" ); } else @@ -1917,7 +2221,7 @@ void FogFeatGLSL::processPix( Vector &componentList, } // Lerp between the fog color and diffuse color. - LangElement *fogLerp = new GenOp( "mix( @.rgb, @.rgb, @ )", fogColor, color, fogAmount ); + LangElement *fogLerp = new GenOp( "lerp( @.rgb, @.rgb, @ )", fogColor, color, fogAmount ); meta->addStatement( new GenOp( " @.rgb = @;\r\n", color, fogLerp ) ); output = meta; @@ -1935,42 +2239,59 @@ ShaderFeature::Resources FogFeatGLSL::getResources( const MaterialFeatureData &f // Visibility //**************************************************************************** +VisibilityFeatGLSL::VisibilityFeatGLSL() + : mTorqueDep( "shaders/common/gl/torque.glsl" ) +{ + addDependency( &mTorqueDep ); +} + void VisibilityFeatGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { - // Pass screen space position to pixel shader to compute a full screen buffer uv - Var* ssPos = ( Var* ) LangElement::find( "screenspacePos" ); - if( !ssPos ) + MultiLine *meta = new MultiLine; + output = meta; + + if ( fd.features[ MFT_UseInstancing ] ) { - ShaderConnector* connectComp = dynamic_cast< ShaderConnector* >( componentList[C_CONNECTOR] ); - AssertFatal( connectComp, "VisibilityFeatGLSL::processVert - invalid ShaderConnector" ); + // We pass the visibility to the pixel shader via + // another output register. + // + // TODO: We should see if we can share this register + // with some other common instanced data. + // + ShaderConnector *conn = dynamic_cast( componentList[C_CONNECTOR] ); + Var *outVisibility = conn->getElement( RT_TEXCOORD ); + outVisibility->setStructName( "OUT" ); + outVisibility->setName( "visibility" ); + outVisibility->setType( "float" ); + + ShaderConnector *vertStruct = dynamic_cast( componentList[C_VERT_STRUCT] ); + Var *instVisibility = vertStruct->getElement( RT_TEXCOORD, 1 ); + instVisibility->setStructName( "IN" ); + instVisibility->setName( "inst_visibility" ); + instVisibility->setType( "float" ); + mInstancingFormat->addElement( "visibility", GFXDeclType_Float, instVisibility->constNum ); - Var* ssPos = connectComp->getElement( RT_TEXCOORD ); - ssPos->setName( "screenspacePos" ); - ssPos->setType( "vec4" ); - - Var* outPosition = ( Var* ) LangElement::find( "gl_Position" ); - AssertFatal( outPosition, "VisibilityFeatGLSL::processVert - No gl_Position" ); - - output = new GenOp( " @ = @;\r\n", ssPos, outPosition ); + meta->addStatement( new GenOp( " @ = @; // Instancing!\r\n", outVisibility, instVisibility ) ); } + + if ( fd.features[ MFT_IsTranslucent ] ) + return; + + addOutVpos( meta, componentList ); } void VisibilityFeatGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) -{ - // Look up output color. - - Var* color = ( Var* ) LangElement::find( "col" ); - if( !color ) +{ + // Get the visibility constant. + Var *visibility = NULL; + if ( fd.features[ MFT_UseInstancing ] ) + visibility = getInTexCoord( "visibility", "float", false, componentList ); + else { - output = NULL; - return; - } + visibility = (Var*)LangElement::find( "visibility" ); - Var* visibility = (Var*)LangElement::find( "visibility" ); - - // Create visibility var. if ( !visibility ) { visibility = new Var(); @@ -1979,94 +2300,36 @@ void VisibilityFeatGLSL::processPix( Vector &componentList, visibility->uniform = true; visibility->constSortPos = cspPotentialPrimitive; } - - Var* ssPos = ( Var* ) LangElement::find( "screenspacePos" ); - if( !ssPos ) - { - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - AssertFatal( connectComp, "VisibilityFeatGLSL::processPix - invalid ShaderConnector" ); - - ssPos = connectComp->getElement( RT_TEXCOORD ); - ssPos->setName( "screenspacePos" ); - ssPos->setType( "vec4" ); } MultiLine* meta = new MultiLine; output = meta; - //Compute final visibility from incoming visibility and strength of fade effects - Var *finalVisibility = new Var( "finalVisibility", "float" ); - meta->addStatement(new GenOp( " @ = @;\r\n", new DecOp( finalVisibility ), visibility ) ); - Var *imposterFade = (Var*) LangElement::find( "imposterFade" ); - if ( imposterFade ) - meta->addStatement( new GenOp( " @ *= @;\r\n", finalVisibility, imposterFade ) ); - Var *foliageFade = (Var*) LangElement::find( "foliageFade" ); - if ( foliageFade ) - meta->addStatement( new GenOp( " @ *= @;\r\n", finalVisibility, foliageFade ) ); - - if( !fd.features[ MFT_IsTranslucent ] ) + // Translucent objects do a simple alpha fade. + if ( fd.features[ MFT_IsTranslucent ] ) { - // Create fizzMap sampler. - - Var* fizzMap = ( Var* ) LangElement::find( "fizzMap" ); - if( !fizzMap ) - { - fizzMap = new Var; - fizzMap->setType( "sampler2D" ); - fizzMap->setName( "fizzMap" ); - fizzMap->uniform = true; - fizzMap->sampler = true; - fizzMap->constNum = Var::getTexUnitNum(); + Var *color = (Var*) LangElement::find( "col" ); + meta->addStatement( new GenOp( " @.a *= @;\r\n", color, visibility ) ); + return; } - // Create fizzScale uniform. - - Var* fizzScale = new Var; - fizzScale->setType( "float2" ); - fizzScale->setName( "fizzScale" ); - fizzScale->uniform = true; - fizzScale->constSortPos = cspPass; - - meta->addStatement( new GenOp( " float fizz = tex2D( @, (@.xy / @.w) * fizzScale ).r + 0.15;\r\n", fizzMap, ssPos, ssPos ) ); - meta->addStatement( new GenOp( " if( ( fizz * @ - 0.329 ) < 0.0 )\r\n" - " discard\r\n;", finalVisibility ) ); - } - else if( color ) - { - meta->addStatement( new GenOp( " @.w *= @;\r\n", color, finalVisibility ) ); - } + // Everything else does a fizzle. + Var *vPos = getInVpos( meta, componentList ); + meta->addStatement( new GenOp( " fizzle( @, @ );\r\n", vPos, visibility ) ); } ShaderFeature::Resources VisibilityFeatGLSL::getResources( const MaterialFeatureData &fd ) { Resources res; + // TODO: Fix for instancing. + if ( !fd.features[ MFT_IsTranslucent ] ) - { - res.numTex = 1; res.numTexReg = 1; - } return res; } -void VisibilityFeatGLSL::setTexData( Material::StageData &stageDat, - const MaterialFeatureData &fd, - RenderPassData &passData, - U32 &texIndex ) -{ - if ( !fd.features[ MFT_IsTranslucent ] ) - { - GFXTexHandle texHandle( "core/art/fizz_noise.dds", &GFXDefaultStaticDiffuseProfile, "VisibilityFeatHLSL_fizz_noise" ); - stageDat.setTex( MFT_Visibility, texHandle ); - - GFXTextureObject *tex = stageDat.getTex( MFT_Visibility ); - if ( tex ) - passData.mTexSlot[ texIndex++ ].texObject = tex; - } -} - - //**************************************************************************** // AlphaTest //**************************************************************************** @@ -2100,7 +2363,7 @@ void AlphaTestGLSL::processPix( Vector &componentList, alphaTestVal->constSortPos = cspPotentialPrimitive; // Do the clip. - output = new GenOp( " if ( ( @.a - @ ) < 0 ) discard;\r\n", color, alphaTestVal ); + output = new GenOp( " clip( @.a - @ );\r\n", color, alphaTestVal ); } @@ -2123,6 +2386,7 @@ void GlowMaskGLSL::processPix( Vector &componentList, output = new GenOp( " @.rgb = 0;\r\n", color ); } + //**************************************************************************** // RenderTargetZero //**************************************************************************** @@ -2140,10 +2404,11 @@ void RenderTargetZeroGLSL::processPix( Vector &componentList, //**************************************************************************** HDROutGLSL::HDROutGLSL() -: mTorqueDep( "shaders/common/gl/torque.glsl" ) + : mTorqueDep( "shaders/common/gl/torque.glsl" ) { addDependency( &mTorqueDep ); } + void HDROutGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { @@ -2153,7 +2418,6 @@ void HDROutGLSL::processPix( Vector &componentList, output = new GenOp( " @ = hdrEncode( @ );\r\n", color, color ); } - //**************************************************************************** // FoliageFeatureGLSL //**************************************************************************** @@ -2169,42 +2433,23 @@ FoliageFeatureGLSL::FoliageFeatureGLSL() void FoliageFeatureGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { - - MultiLine *meta = new MultiLine; - // Get the input variables we need. Var *inPosition = (Var*)LangElement::find( "inPosition" ); - if ( !inPosition ) { - // inPosition = (Var*)LangElement::find( "position" ); - inPosition = new Var( "inPosition", "vec3" ); - meta->addStatement( new GenOp( " @ = @;\n", new DecOp( inPosition ), (Var*)LangElement::find( "position" ) ) ); - } + if ( !inPosition ) + inPosition = (Var*)LangElement::find( "position" ); Var *inColor = (Var*)LangElement::find( "diffuse" ); - Var *outColor = new Var( "inDiffuse", "vec4" ); - meta->addStatement( new GenOp( " @ = @;\n", new DecOp( outColor ), inColor ) ); Var *inParams = (Var*)LangElement::find( "texCoord" ); - Var *outParams = getOutTexCoord( "texCoord", - "vec2", - true, - fd.features[MFT_TexAnim], - meta, - componentList ); - + MultiLine *meta = new MultiLine; // Declare the normal and tangent variables since they do not exist // in this vert type, but we do need to set them up for others. - Var *inNormal = (Var*)LangElement::find( "inNormal" ); - if ( !inNormal ) { - inNormal = new Var( "inNormal", "vec3" ); - meta->addStatement( new GenOp( " @ = @;\n", new DecOp( inNormal ), (Var*)LangElement::find( "normal" ) ) ); - } - //Var *normal = (Var*)LangElement::find( "normal" ); - AssertFatal( inNormal, "FoliageFeatureHLSL requires vert normal!" ); + Var *normal = (Var*)LangElement::find( "normal" ); + AssertFatal( normal, "FoliageFeatureGLSL requires vert normal!" ); Var *tangent = new Var; tangent->setType( "vec3" ); @@ -2216,6 +2461,7 @@ void FoliageFeatureGLSL::processVert( Vector &componentList, ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *fade = connectComp->getElement( RT_TEXCOORD ); fade->setName( "foliageFade" ); + fade->setStructName( "OUT" ); fade->setType( "float" ); // grab the eye position @@ -2227,12 +2473,11 @@ void FoliageFeatureGLSL::processVert( Vector &componentList, eyePos->constSortPos = cspPass; } - // All actual work is offloaded to this method. - meta->addStatement( new GenOp( " foliageProcessVert( @, @, @, @, @, @, @ );\r\n", inPosition, outColor, inParams, outParams, inNormal, tangent, eyePos ) ); + meta->addStatement( new GenOp( " foliageProcessVert( @, @, @, @, @, @ );\r\n", inPosition, inColor, inParams, normal, tangent, eyePos ) ); // Assign to foliageFade. InColor.a was set to the correct value inside foliageProcessVert. - meta->addStatement( new GenOp( " @ = @.a;\r\n", fade, outColor ) ); + meta->addStatement( new GenOp( " @ = @.a;\r\n", fade, inColor ) ); output = meta; } @@ -2244,7 +2489,26 @@ void FoliageFeatureGLSL::processPix( Vector &componentList, ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *fade = connectComp->getElement( RT_TEXCOORD ); fade->setName( "foliageFade" ); + fade->setStructName( "IN" ); fade->setType( "float" ); + + // Find / create visibility + Var *visibility = (Var*) LangElement::find( "visibility" ); + if ( !visibility ) + { + visibility = new Var(); + visibility->setType( "float" ); + visibility->setName( "visibility" ); + visibility->uniform = true; + visibility->constSortPos = cspPotentialPrimitive; + } + + MultiLine *meta = new MultiLine; + + // Multiply foliageFade into visibility. + meta->addStatement( new GenOp( " @ *= @;\r\n", visibility, fade ) ); + + output = meta; } void FoliageFeatureGLSL::determineFeature( Material *material, const GFXVertexFormat *vertexFormat, U32 stageNum, const FeatureType &type, const FeatureSet &features, MaterialFeatureData *outFeatureData ) @@ -2255,6 +2519,7 @@ void FoliageFeatureGLSL::determineFeature( Material *material, const GFXVertexFo outFeatureData->features.addFeature( type ); } + ShaderFeatureConstHandles* FoliageFeatureGLSL::createConstHandles( GFXShader *shader, SimObject *userObject ) { GroundCover *gcover = dynamic_cast< GroundCover* >( userObject ); @@ -2269,10 +2534,6 @@ ShaderFeatureConstHandles* FoliageFeatureGLSL::createConstHandles( GFXShader *sh } -//**************************************************************************** -// ParticleNormal -//**************************************************************************** - void ParticleNormalFeatureGLSL::processVert(Vector &componentList, const MaterialFeatureData &fd) { MultiLine *meta = new MultiLine; @@ -2292,7 +2553,7 @@ void ParticleNormalFeatureGLSL::processVert(Vector &componentL // screen because there is a discontinuity at (0, 1, 0) for gbuffer encoding. Do not // cause this value to be (0, -1, 0) or interlaced normals will be discontinuous. // [11/23/2009 Pat] - meta->addStatement(new GenOp(" @ = vec3(0.0, -0.97, 0.14);\r\n", new DecOp(normal))); + meta->addStatement(new GenOp(" @ = float3(0.0, -0.97, 0.14);\r\n", new DecOp(normal))); } Var *T = (Var*) LangElement::find( "T" ); @@ -2301,17 +2562,16 @@ void ParticleNormalFeatureGLSL::processVert(Vector &componentL T = new Var; T->setType( "vec3" ); T->setName( "T" ); - meta->addStatement(new GenOp(" @ = vec3(0.0, 0.0, -1.0);\r\n", new DecOp(T))); + meta->addStatement(new GenOp(" @ = float3(0.0, 0.0, -1.0);\r\n", new DecOp(T))); } } - //**************************************************************************** // ImposterVertFeatureGLSL //**************************************************************************** ImposterVertFeatureGLSL::ImposterVertFeatureGLSL() -: mDep( "shaders/common/gl/imposter.glsl" ) + : mDep( "shaders/common/gl/imposter.glsl" ) { addDependency( &mDep ); } @@ -2338,7 +2598,7 @@ void ImposterVertFeatureGLSL::processVert( Vector &component Var *imposterUVs = new Var; imposterUVs->setType( "vec4" ); imposterUVs->setName( "imposterUVs" ); - imposterUVs->arraySize = 64; // See imposter.hlsl + imposterUVs->arraySize = 64; // See imposter.glsl imposterUVs->uniform = true; imposterUVs->constSortPos = cspPotentialPrimitive; @@ -2362,15 +2622,15 @@ void ImposterVertFeatureGLSL::processVert( Vector &component meta->addStatement( new GenOp( " @;\r\n", new DecOp( outTexCoord ) ) ); Var *outWorldToTangent = new Var; - outWorldToTangent->setType( "mat3" ); + outWorldToTangent->setType( "float3x3" ); outWorldToTangent->setName( "worldToTangent" ); meta->addStatement( new GenOp( " @;\r\n", new DecOp( outWorldToTangent ) ) ); - //Var *outWorldToTangent = getOutWorldToTangent( componentList, meta, fd ); // Add imposterFade to the OUT structure. ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *outFade = connectComp->getElement( RT_TEXCOORD ); outFade->setName( "imposterFade" ); + outFade->setStructName( "OUT" ); outFade->setType( "float" ); // Assign OUT.imposterFade @@ -2410,7 +2670,7 @@ void ImposterVertFeatureGLSL::processVert( Vector &component // If we new viewToTangent... its the same as the // world to tangent for an imposter. Var *viewToTangent = new Var; - viewToTangent->setType( "mat3" ); + viewToTangent->setType( "float3x3" ); viewToTangent->setName( "viewToTangent" ); meta->addStatement( new GenOp( " @ = @;\r\n", new DecOp( viewToTangent ), outWorldToTangent ) ); } @@ -2418,14 +2678,13 @@ void ImposterVertFeatureGLSL::processVert( Vector &component void ImposterVertFeatureGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { - // Find / create IN.imposterFade ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *fade = connectComp->getElement( RT_TEXCOORD ); fade->setName( "imposterFade" ); + fade->setStructName( "IN" ); fade->setType( "float" ); - /* // Find / create visibility Var *visibility = (Var*) LangElement::find( "visibility" ); if ( !visibility ) @@ -2440,10 +2699,9 @@ void ImposterVertFeatureGLSL::processPix( Vector &componentLis MultiLine *meta = new MultiLine; // Multiply foliageFade into visibility. - //meta->addStatement( new GenOp( " @ *= @;\r\n", visibility, fade ) ); + meta->addStatement( new GenOp( " @ *= @;\r\n", visibility, fade ) ); output = meta; - */ } void ImposterVertFeatureGLSL::determineFeature( Material *material, @@ -2455,4 +2713,5 @@ void ImposterVertFeatureGLSL::determineFeature( Material *material, { if ( features.hasFeature( MFT_ImposterVert ) ) outFeatureData->features.addFeature( MFT_ImposterVert ); -} \ No newline at end of file +} + diff --git a/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.h b/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.h index 14af0300f..a0e831e93 100644 --- a/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.h +++ b/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.h @@ -25,9 +25,6 @@ #ifndef _SHADERFEATURE_H_ #include "shaderGen/shaderFeature.h" #endif -#ifndef _MATERIALFEATUREDATA_H_ - #include "materials/materialFeatureData.h" -#endif struct LangElement; struct MaterialFeatureData; @@ -54,13 +51,25 @@ public: bool mapsToSampler, Vector &componentList ); + static Var* getInColor( const char *name, + const char *type, + Vector &componentList ); + + /// + static Var* addOutVpos( MultiLine *meta, + Vector &componentList ); + + /// Returns the VPOS input register for the pixel shader. + static Var* getInVpos( MultiLine *meta, + Vector &componentList ); + /// Returns the "objToTangentSpace" transform or creates one if this /// is the first feature to need it. Var* getOutObjToTangentSpace( Vector &componentList, MultiLine *meta, const MaterialFeatureData &fd ); - /// Returns the existing output "worldToTangent" transform or + /// Returns the existing output "outWorldToTangent" transform or /// creates one if this is the first feature to need it. Var* getOutWorldToTangent( Vector &componentList, MultiLine *meta, @@ -70,7 +79,7 @@ public: /// adding it to the input connector if it doesn't exist. static Var* getInWorldToTangent( Vector &componentList ); - /// Returns the existing output "viewToTangent" transform or + /// Returns the existing output "outViewToTangent" transform or /// creates one if this is the first feature to need it. Var* getOutViewToTangent( Vector &componentList, MultiLine *meta, @@ -81,17 +90,16 @@ public: static Var* getInViewToTangent( Vector &componentList ); /// Calculates the world space position in the vertex shader and - /// assigns it to the passed language element. It does not pass /// it across the connector to the pixel shader. + /// assigns it to the passed language element. It does not pass + /// it across the connector to the pixel shader. /// @see addOutWsPosition void getWsPosition( Vector &componentList, - bool useInstancing, MultiLine *meta, LangElement *wsPosition ); /// Adds the "wsPosition" to the input connector if it doesn't exist. Var* addOutWsPosition( Vector &componentList, - bool useInstancing, MultiLine *meta ); @@ -129,7 +137,6 @@ public: bool useInstancing, MultiLine *meta ); - // ShaderFeature Var* getVertTexCoord( const String &name ); LangElement* setupTexSpaceMat( Vector &componentList, Var **texSpaceMat ); @@ -151,25 +158,27 @@ public: virtual String getName() { return mName; } }; - class RenderTargetZeroGLSL : public ShaderFeatureGLSL { -protected: ShaderFeature::OutputTarget mOutputTargetMask; +protected: + ShaderFeature::OutputTarget mOutputTargetMask; String mFeatureName; public: RenderTargetZeroGLSL( const ShaderFeature::OutputTarget target ) : mOutputTargetMask( target ) { - char buffer[256]; dSprintf(buffer, sizeof(buffer), "Render Target Output = 0.0, output mask %04b", mOutputTargetMask); - mFeatureName = buffer; } + char buffer[256]; + dSprintf(buffer, sizeof(buffer), "Render Target Output = 0.0, output mask %04b", mOutputTargetMask); + mFeatureName = buffer; + } virtual String getName() { return mFeatureName; } virtual void processPix( Vector &componentList, const MaterialFeatureData &fd ); - virtual U32 getOutputTargets( const MaterialFeatureData &fd ) const { return - mOutputTargetMask; } + + virtual U32 getOutputTargets( const MaterialFeatureData &fd ) const { return mOutputTargetMask; } }; @@ -190,11 +199,7 @@ public: U32 stageNum, const FeatureType &type, const FeatureSet &features, - MaterialFeatureData *outFeatureData ) - { - // This feature is always on! - outFeatureData->features.addFeature( type ); - } + MaterialFeatureData *outFeatureData ); }; @@ -297,7 +302,6 @@ public: } }; - /// Diffuse vertex color class DiffuseVertColorFeatureGLSL : public ShaderFeatureGLSL { @@ -316,7 +320,6 @@ public: } }; - /// Lightmap class LightmapFeatGLSL : public ShaderFeatureGLSL { @@ -491,7 +494,14 @@ public: /// Visibility class VisibilityFeatGLSL : public ShaderFeatureGLSL { +protected: + + ShaderIncludeDependency mTorqueDep; + public: + + VisibilityFeatGLSL(); + virtual void processVert( Vector &componentList, const MaterialFeatureData &fd ); @@ -500,11 +510,6 @@ public: virtual Resources getResources( const MaterialFeatureData &fd ); - virtual void setTexData( Material::StageData &stageDat, - const MaterialFeatureData &fd, - RenderPassData &passData, - U32 &texIndex ); - virtual Material::BlendOp getBlendOp() { return Material::None; } virtual String getName() @@ -547,10 +552,10 @@ public: } }; - /// This should be the final feature on most pixel shaders which /// encodes the color for the current HDR target format. -/// @see HDRPostFx/// @see LightManager +/// @see HDRPostFx +/// @see LightManager /// @see torque.glsl class HDROutGLSL : public ShaderFeatureGLSL { @@ -570,9 +575,9 @@ public: virtual String getName() { return "HDR Output"; } }; - /// -class FoliageFeatureGLSL : public ShaderFeatureGLSL{ +class FoliageFeatureGLSL : public ShaderFeatureGLSL +{ protected: ShaderIncludeDependency mDep; @@ -583,6 +588,7 @@ public: virtual void processVert( Vector &componentList, const MaterialFeatureData &fd ); + virtual void processPix( Vector &componentList, const MaterialFeatureData &fd ); @@ -597,11 +603,10 @@ public: const FeatureType &type, const FeatureSet &features, MaterialFeatureData *outFeatureData ); + virtual ShaderFeatureConstHandles* createConstHandles( GFXShader *shader, SimObject *userObject ); }; - -/// class ParticleNormalFeatureGLSL : public ShaderFeatureGLSL { public: @@ -616,6 +621,9 @@ public: }; + +/// Special feature for unpacking imposter verts. +/// @see RenderImposterMgr class ImposterVertFeatureGLSL : public ShaderFeatureGLSL { protected: @@ -623,9 +631,12 @@ protected: ShaderIncludeDependency mDep; public: - ImposterVertFeatureGLSL(); + + ImposterVertFeatureGLSL(); + virtual void processVert( Vector &componentList, const MaterialFeatureData &fd ); + virtual void processPix( Vector &componentList, const MaterialFeatureData &fd ); diff --git a/Engine/source/shaderGen/GLSL/shaderGenGLSL.cpp b/Engine/source/shaderGen/GLSL/shaderGenGLSL.cpp index ebbf2b3d8..f694b11e3 100644 --- a/Engine/source/shaderGen/GLSL/shaderGenGLSL.cpp +++ b/Engine/source/shaderGen/GLSL/shaderGenGLSL.cpp @@ -56,7 +56,9 @@ void ShaderGenPrinterGLSL::printMainComment( Stream& stream ) void ShaderGenPrinterGLSL::printVertexShaderCloser( Stream& stream ) { - const char *closer = "}\r\n"; + // We are render OpenGL upside down for use DX9 texture coords. + // Must be the last vertex feature. + const char *closer = " gl_Position.y *= -1;\r\n}\r\n"; stream.write( dStrlen(closer), closer ); } @@ -67,7 +69,7 @@ void ShaderGenPrinterGLSL::printPixelShaderOutputStruct( Stream& stream, const M void ShaderGenPrinterGLSL::printPixelShaderCloser( Stream& stream ) { - const char *closer = " gl_FragColor = col;\r\n}\r\n"; + const char *closer = " OUT_FragColor0 = col;\r\n}\r\n"; stream.write( dStrlen(closer), closer ); } @@ -124,6 +126,11 @@ ShaderComponent* ShaderGenComponentFactoryGLSL::createVertexInputConnector( cons var = vertComp->getElement( RT_TANGENT ); var->setName( "T" ); } + else if ( element.isSemantic( GFXSemantic::TANGENTW ) ) + { + var = vertComp->getElement( RT_TANGENTW ); + var->setName( "tangentW" ); + } else if ( element.isSemantic( GFXSemantic::BINORMAL ) ) { var = vertComp->getElement( RT_BINORMAL ); @@ -152,7 +159,7 @@ ShaderComponent* ShaderGenComponentFactoryGLSL::createVertexInputConnector( cons if ( !var ) continue; - var->setStructName( "" ); + var->setStructName( "IN" ); var->setType( typeToString( element.getType() ) ); } diff --git a/Engine/source/shaderGen/GLSL/shaderGenGLSLInit.cpp b/Engine/source/shaderGen/GLSL/shaderGenGLSLInit.cpp index 1318137bb..03634fa50 100644 --- a/Engine/source/shaderGen/GLSL/shaderGenGLSLInit.cpp +++ b/Engine/source/shaderGen/GLSL/shaderGenGLSLInit.cpp @@ -76,6 +76,8 @@ void _initShaderGenGLSL( ShaderGen *shaderGen ) FEATUREMGR->registerFeature( MFT_ParaboloidVertTransform, new ParaboloidVertTransformGLSL ); FEATUREMGR->registerFeature( MFT_IsSinglePassParaboloid, new NamedFeatureGLSL( "Single Pass Paraboloid" ) ); + FEATUREMGR->registerFeature( MFT_UseInstancing, new NamedFeatureGLSL( "Hardware Instancing" ) ); + FEATUREMGR->registerFeature( MFT_RenderTarget1_Zero, new RenderTargetZeroGLSL ( ShaderFeature::RenderTarget1 ) ); @@ -89,6 +91,10 @@ void _initShaderGenGLSL( ShaderGen *shaderGen ) FEATUREMGR->registerFeature( MFT_ImposterVert, new ImposterVertFeatureGLSL ); + //FEATUREMGR->registerFeature( MFT_LightbufferMRT, new NamedFeatureGLSL( "Lightbuffer MRT" ) ); + //FEATUREMGR->registerFeature( MFT_IsTranslucentZWrite, new NamedFeatureGLSL( "Translucent ZWrite" ) ); + //FEATUREMGR->registerFeature( MFT_InterlacedPrePass, new NamedFeatureGLSL( "Interlaced Pre Pass" ) ); + } MODULE_BEGIN( ShaderGenGLSL ) diff --git a/Engine/source/terrain/glsl/terrFeatureGLSL.cpp b/Engine/source/terrain/glsl/terrFeatureGLSL.cpp index c23d4d85d..63bc8cb60 100644 --- a/Engine/source/terrain/glsl/terrFeatureGLSL.cpp +++ b/Engine/source/terrain/glsl/terrFeatureGLSL.cpp @@ -30,22 +30,35 @@ #include "shaderGen/langElement.h" #include "shaderGen/shaderOp.h" #include "shaderGen/featureMgr.h" +#include "shaderGen/shaderGen.h" #include "core/module.h" +namespace +{ + void register_glsl_shader_features_for_terrain(GFXAdapterType type) + { + if(type != OpenGL) + return; + + FEATUREMGR->registerFeature( MFT_TerrainBaseMap, new TerrainBaseMapFeatGLSL ); + FEATUREMGR->registerFeature( MFT_TerrainParallaxMap, new NamedFeatureGLSL( "Terrain Parallax Texture" ) ); + FEATUREMGR->registerFeature( MFT_TerrainDetailMap, new TerrainDetailMapFeatGLSL ); + FEATUREMGR->registerFeature( MFT_TerrainNormalMap, new TerrainNormalMapFeatGLSL ); + FEATUREMGR->registerFeature( MFT_TerrainMacroMap, new TerrainMacroMapFeatGLSL ); + FEATUREMGR->registerFeature( MFT_TerrainLightMap, new TerrainLightMapFeatGLSL ); + FEATUREMGR->registerFeature( MFT_TerrainSideProject, new NamedFeatureGLSL( "Terrain Side Projection" ) ); + FEATUREMGR->registerFeature( MFT_TerrainAdditive, new TerrainAdditiveFeatGLSL ); + } + +}; MODULE_BEGIN( TerrainFeatGLSL ) - MODULE_INIT_AFTER( ShaderGenFeatureMgr ) + MODULE_INIT_AFTER( ShaderGen ) MODULE_INIT - { - FEATUREMGR->registerFeature( MFT_TerrainBaseMap, new TerrainBaseMapFeatGLSL ); - FEATUREMGR->registerFeature( MFT_TerrainParallaxMap, new TerrainParallaxMapFeatGLSL ); - FEATUREMGR->registerFeature( MFT_TerrainDetailMap, new TerrainDetailMapFeatGLSL ); - FEATUREMGR->registerFeature( MFT_TerrainNormalMap, new TerrainNormalMapFeatGLSL ); - FEATUREMGR->registerFeature( MFT_TerrainLightMap, new TerrainLightMapFeatGLSL ); - FEATUREMGR->registerFeature( MFT_TerrainSideProject, new NamedFeatureGLSL( "Terrain Side Projection" ) ); - FEATUREMGR->registerFeature( MFT_TerrainAdditive, new TerrainAdditiveFeatGLSL ); + { + SHADERGEN->getFeatureInitSignal().notify(®ister_glsl_shader_features_for_terrain); } MODULE_END; @@ -68,7 +81,7 @@ Var* TerrainFeatGLSL::_getUniformVar( const char *name, const char *type, Consta Var* TerrainFeatGLSL::_getInDetailCoord( Vector &componentList ) { - String name( String::ToString( "outDetCoord%d", getProcessIndex() ) ); + String name( String::ToString( "detCoord%d", getProcessIndex() ) ); Var *inDet = (Var*)LangElement::find( name ); if ( !inDet ) @@ -77,6 +90,7 @@ Var* TerrainFeatGLSL::_getInDetailCoord( Vector &componentList inDet = connectComp->getElement( RT_TEXCOORD ); inDet->setName( name ); + inDet->setStructName( "IN" ); inDet->setType( "vec4" ); inDet->mapsToSampler = true; } @@ -84,6 +98,25 @@ Var* TerrainFeatGLSL::_getInDetailCoord( Vector &componentList return inDet; } +Var* TerrainFeatGLSL::_getInMacroCoord( Vector &componentList ) +{ + String name( String::ToString( "macroCoord%d", getProcessIndex() ) ); + Var *inDet = (Var*)LangElement::find( name ); + + if ( !inDet ) + { + ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); + + inDet = connectComp->getElement( RT_TEXCOORD ); + inDet->setName( name ); + inDet->setStructName( "IN" ); + inDet->setType( "vec4" ); + inDet->mapsToSampler = true; + } + + return inDet; +} + Var* TerrainFeatGLSL::_getNormalMapTex() { String name( String::ToString( "normalMap%d", getProcessIndex() ) ); @@ -119,6 +152,24 @@ Var* TerrainFeatGLSL::_getDetailIdStrengthParallax() return detailInfo; } +Var* TerrainFeatGLSL::_getMacroIdStrengthParallax() +{ + String name( String::ToString( "macroIdStrengthParallax%d", getProcessIndex() ) ); + + Var *detailInfo = (Var*)LangElement::find( name ); + if ( !detailInfo ) + { + detailInfo = new Var; + detailInfo->setType( "vec3" ); + detailInfo->setName( name ); + detailInfo->uniform = true; + detailInfo->constSortPos = cspPotentialPrimitive; + } + + return detailInfo; +} + + void TerrainBaseMapFeatGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { @@ -146,7 +197,7 @@ void TerrainBaseMapFeatGLSL::processVert( Vector &componentLis // So instead i fixed this by flipping the base and detail // coord y scale to compensate when rendering. // - meta->addStatement( new GenOp( " @ = @.xyz * vec3( @, @, -@ );\r\n", + meta->addStatement( new GenOp( " @ = @.xyz * float3( @, @, -@ );\r\n", new DecOp( inTex ), inPos, oneOverTerrainSize, oneOverTerrainSize, oneOverTerrainSize ) ); } @@ -155,6 +206,7 @@ void TerrainBaseMapFeatGLSL::processVert( Vector &componentLis // Pass the texture coord to the pixel shader. Var *outTex = connectComp->getElement( RT_TEXCOORD ); outTex->setName( "outTexCoord" ); + outTex->setStructName( "OUT" ); outTex->setType( "vec3" ); outTex->mapsToSampler = true; meta->addStatement( new GenOp( " @.xy = @.xy;\r\n", outTex, inTex ) ); @@ -166,7 +218,7 @@ void TerrainBaseMapFeatGLSL::processVert( Vector &componentLis { Var *inNormal = (Var*)LangElement::find( "normal" ); meta->addStatement( - new GenOp( " @.z = pow( abs( dot( normalize( vec3( @.x, @.y, 0.0 ) ), vec3( 0, 1, 0 ) ) ), 10.0 );\r\n", + new GenOp( " @.z = pow( abs( dot( normalize( float3( @.x, @.y, 0 ) ), float3( 0, 1, 0 ) ) ), 10.0 );\r\n", outTex, inNormal, inNormal ) ); } else @@ -182,7 +234,7 @@ void TerrainBaseMapFeatGLSL::processVert( Vector &componentLis Var *inTangentZ = getVertTexCoord( "tcTangentZ" ); Var *inTanget = new Var( "T", "vec3" ); Var *squareSize = _getUniformVar( "squareSize", "float", cspPass ); - meta->addStatement( new GenOp( " @ = normalize( vec3( @, 0.0, @ ) );\r\n", + meta->addStatement( new GenOp( " @ = normalize( float3( @, 0, @ ) );\r\n", new DecOp( inTanget ), squareSize, inTangentZ ) ); } @@ -190,7 +242,7 @@ void TerrainBaseMapFeatGLSL::processPix( Vector &componentLis const MaterialFeatureData &fd ) { // grab connector texcoord register - Var *texCoord = getInTexCoord( "outTexCoord", "vec3", true, componentList ); + Var *texCoord = getInTexCoord( "texCoord", "vec3", true, componentList ); // We do nothing more if this is a prepass. if ( fd.features.hasFeature( MFT_PrePassConditioner ) ) @@ -209,7 +261,7 @@ void TerrainBaseMapFeatGLSL::processPix( Vector &componentLis Var *baseColor = new Var; baseColor->setType( "vec4" ); baseColor->setName( "baseColor" ); - meta->addStatement( new GenOp( " @ = texture2D( @, @.xy );\r\n", new DecOp( baseColor ), diffuseMap, texCoord ) ); + meta->addStatement( new GenOp( " @ = tex2D( @, @.xy );\r\n", new DecOp( baseColor ), diffuseMap, texCoord ) ); meta->addStatement( new GenOp( " @;\r\n", assignColor( baseColor, Material::Mul ) ) ); output = meta; @@ -228,8 +280,11 @@ ShaderFeature::Resources TerrainBaseMapFeatGLSL::getResources( const MaterialFea } TerrainDetailMapFeatGLSL::TerrainDetailMapFeatGLSL() - : mTerrainDep( "shaders/common/terrain/terrain.glsl" ) + : mTorqueDep( "shaders/common/gl/torque.glsl" ), + mTerrainDep( "shaders/common/terrain/terrain.glsl" ) + { + addDependency( &mTorqueDep ); addDependency( &mTerrainDep ); } @@ -238,13 +293,6 @@ void TerrainDetailMapFeatGLSL::processVert( Vector &component { const U32 detailIndex = getProcessIndex(); - - // If this is a prepass and we don't have a - // matching normal map... we have nothing to do. - if ( fd.features.hasFeature( MFT_PrePassConditioner ) && - !fd.features.hasFeature( MFT_TerrainNormalMap, detailIndex ) ) - return; - // Grab incoming texture coords... the base map feature // made sure this was created. Var *inTex = (Var*)LangElement::find( "texCoord" ); @@ -260,6 +308,26 @@ void TerrainDetailMapFeatGLSL::processVert( Vector &component MultiLine *meta = new MultiLine; + // If we have parallax mapping then make sure we've sent + // the negative view vector to the pixel shader. + if ( fd.features.hasFeature( MFT_TerrainParallaxMap ) && + !LangElement::find( "outNegViewTS" ) ) + { + // Get the object to tangent transform which + // will consume 3 output registers. + Var *objToTangentSpace = getOutObjToTangentSpace( componentList, meta, fd ); + + // Now use a single output register to send the negative + // view vector in tangent space to the pixel shader. + ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); + Var *outNegViewTS = connectComp->getElement( RT_TEXCOORD ); + outNegViewTS->setName( "outNegViewTS" ); + outNegViewTS->setStructName( "OUT" ); + outNegViewTS->setType( "vec3" ); + meta->addStatement( new GenOp( " @ = tMul( @, float3( @ - @.xyz ) );\r\n", + outNegViewTS, objToTangentSpace, eyePos, inPos ) ); + } + // Get the distance from the eye to this vertex. Var *dist = (Var*)LangElement::find( "dist" ); if ( !dist ) @@ -275,7 +343,8 @@ void TerrainDetailMapFeatGLSL::processVert( Vector &component // grab connector texcoord register ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *outTex = connectComp->getElement( RT_TEXCOORD ); - outTex->setName( String::ToString( "outDetCoord%d", detailIndex ) ); + outTex->setName( String::ToString( "detCoord%d", detailIndex ) ); + outTex->setStructName( "OUT" ); outTex->setType( "vec4" ); outTex->mapsToSampler = true; @@ -293,7 +362,7 @@ void TerrainDetailMapFeatGLSL::processVert( Vector &component // its scale is flipped to correct for the non negative y // in texCoord. // - // See TerrainBaseMapFeatHLSL::processVert(). + // See TerrainBaseMapFeatGLSL::processVert(). // meta->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex, inTex, detScaleAndFade ) ); @@ -308,17 +377,30 @@ void TerrainDetailMapFeatGLSL::processPix( Vector &component const MaterialFeatureData &fd ) { const U32 detailIndex = getProcessIndex(); + Var *inTex = getVertTexCoord( "texCoord" ); - // If this is a prepass and we don't have a - // matching normal map... we have nothing to do. - if ( fd.features.hasFeature( MFT_PrePassConditioner ) && - !fd.features.hasFeature( MFT_TerrainNormalMap, detailIndex ) ) - return; - - Var *inTex = getVertTexCoord( "outTexCoord" ); - MultiLine *meta = new MultiLine; + // We need the negative tangent space view vector + // as in parallax mapping we step towards the camera. + Var *negViewTS = (Var*)LangElement::find( "negViewTS" ); + if ( !negViewTS && + fd.features.hasFeature( MFT_TerrainParallaxMap ) ) + { + Var *inNegViewTS = (Var*)LangElement::find( "outNegViewTS" ); + if ( !inNegViewTS ) + { + ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); + inNegViewTS = connectComp->getElement( RT_TEXCOORD ); + inNegViewTS->setName( "outNegViewTS" ); + inNegViewTS->setStructName( "IN" ); + inNegViewTS->setType( "vec3" ); + } + + negViewTS = new Var( "negViewTS", "vec3" ); + meta->addStatement( new GenOp( " @ = normalize( @ );\r\n", new DecOp( negViewTS ), inNegViewTS ) ); + } + // Get the layer samples. Var *layerSample = (Var*)LangElement::find( "layerSample" ); if ( !layerSample ) @@ -336,7 +418,7 @@ void TerrainDetailMapFeatGLSL::processPix( Vector &component layerTex->constNum = Var::getTexUnitNum(); // Read the layer texture to get the samples. - meta->addStatement( new GenOp( " @ = round( texture2D( @, @.xy ) * 255.0f );\r\n", + meta->addStatement( new GenOp( " @ = round( tex2D( @, @.xy ) * 255.0f );\r\n", new DecOp( layerSample ), layerTex, inTex ) ); } @@ -372,17 +454,43 @@ void TerrainDetailMapFeatGLSL::processPix( Vector &component blendTotal = new Var; blendTotal->setName( "blendTotal" ); blendTotal->setType( "float" ); - meta->addStatement( new GenOp( " @ = 0.0;\r\n", new DecOp( blendTotal ) ) ); + meta->addStatement( new GenOp( " @ = 0;\r\n", new DecOp( blendTotal ) ) ); } // Add to the blend total. - meta->addStatement( new GenOp( " @ += @;\r\n", blendTotal, detailBlend ) ); - //meta->addStatement( new GenOp( " @ += @ * @.y * @.w;\r\n", - //blendTotal, detailBlend, detailInfo, inDet ) ); + meta->addStatement( new GenOp( " @ = max( @, @ );\r\n", blendTotal, blendTotal, detailBlend ) ); - // Nothing more to do for a detail texture in prepass. + // If we had a parallax feature... then factor in the parallax + // amount so that it fades out with the layer blending. + if ( fd.features.hasFeature( MFT_TerrainParallaxMap, detailIndex ) ) + { + // Get the rest of our inputs. + Var *normalMap = _getNormalMapTex(); + + // Call the library function to do the rest. + meta->addStatement( new GenOp( " @.xy += parallaxOffset( @, @.xy, @, @.z * @ );\r\n", + inDet, normalMap, inDet, negViewTS, detailInfo, detailBlend ) ); + } + + // If this is a prepass then we skip color. if ( fd.features.hasFeature( MFT_PrePassConditioner ) ) { + // Check to see if we have a gbuffer normal. + Var *gbNormal = (Var*)LangElement::find( "gbNormal" ); + + // If we have a gbuffer normal and we don't have a + // normal map feature then we need to lerp in a + // default normal else the normals below this layer + // will show thru. + if ( gbNormal && + !fd.features.hasFeature( MFT_TerrainNormalMap, detailIndex ) ) + { + Var *viewToTangent = getInViewToTangent( componentList ); + + meta->addStatement( new GenOp( " @ = lerp( @, tGetMatrix3Row(@, 2), min( @, @.w ) );\r\n", + gbNormal, gbNormal, viewToTangent, detailBlend, inDet ) ); + } + output = meta; return; } @@ -407,6 +515,7 @@ void TerrainDetailMapFeatGLSL::processPix( Vector &component // If we're using SM 3.0 then take advantage of // dynamic branching to skip layers per-pixel. + if ( GFX->getPixelShaderVersion() >= 3.0f ) meta->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend ) ); @@ -421,12 +530,12 @@ void TerrainDetailMapFeatGLSL::processPix( Vector &component // if ( fd.features.hasFeature( MFT_TerrainSideProject, detailIndex ) ) { - meta->addStatement( new GenOp( " @ = ( mix( texture2D( @, @.yz ), texture2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n", + meta->addStatement( new GenOp( " @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n", detailColor, detailMap, inDet, detailMap, inDet, inTex ) ); } else { - meta->addStatement( new GenOp( " @ = ( texture2D( @, @.xy ) * 2.0 ) - 1.0;\r\n", + meta->addStatement( new GenOp( " @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n", detailColor, detailMap, inDet ) ); } @@ -436,7 +545,7 @@ void TerrainDetailMapFeatGLSL::processPix( Vector &component Var *baseColor = (Var*)LangElement::find( "baseColor" ); Var *outColor = (Var*)LangElement::find( "col" ); - meta->addStatement( new GenOp( " @ = mix( @, @ + @, @ );\r\n", + meta->addStatement( new GenOp( " @ = lerp( @, @ + @, @ );\r\n", outColor, outColor, baseColor, detailColor, detailBlend ) ); meta->addStatement( new GenOp( " }\r\n" ) ); @@ -448,28 +557,293 @@ ShaderFeature::Resources TerrainDetailMapFeatGLSL::getResources( const MaterialF { Resources res; + if ( getProcessIndex() == 0 ) + { + // If this is the first detail pass then we + // samples from the layer tex. + res.numTex += 1; + + // If this material also does parallax then it + // will generate the negative view vector and the + // worldToTanget transform. + if ( fd.features.hasFeature( MFT_TerrainParallaxMap ) ) + res.numTexReg += 4; + } + + // If this isn't the prepass then we sample + // from the detail texture for diffuse coloring. + if ( !fd.features.hasFeature( MFT_PrePassConditioner ) ) + res.numTex += 1; + + // If we have parallax for this layer then we'll also + // be sampling the normal map for the parallax heightmap. + if ( fd.features.hasFeature( MFT_TerrainParallaxMap, getProcessIndex() ) ) + res.numTex += 1; + + // Finally we always send the detail texture + // coord to the pixel shader. + res.numTexReg += 1; + + return res; +} + + +TerrainMacroMapFeatGLSL::TerrainMacroMapFeatGLSL() + : mTorqueDep( "shaders/common/gl/torque.glsl" ), + mTerrainDep( "shaders/common/terrain/terrain.glsl" ) + +{ + addDependency( &mTorqueDep ); + addDependency( &mTerrainDep ); +} + + +void TerrainMacroMapFeatGLSL::processVert( Vector &componentList, + const MaterialFeatureData &fd ) +{ + const U32 detailIndex = getProcessIndex(); + + // Grab incoming texture coords... the base map feature + // made sure this was created. + Var *inTex = (Var*)LangElement::find( "texCoord" ); + AssertFatal( inTex, "The texture coord is missing!" ); + + // Grab the input position. + Var *inPos = (Var*)LangElement::find( "inPosition" ); + if ( !inPos ) + inPos = (Var*)LangElement::find( "position" ); + + // Get the object space eye position. + Var *eyePos = _getUniformVar( "eyePos", "vec3", cspPotentialPrimitive ); + + MultiLine *meta = new MultiLine; + + // Get the distance from the eye to this vertex. + Var *dist = (Var*)LangElement::find( "macroDist" ); + if ( !dist ) + { + dist = new Var; + dist->setType( "float" ); + dist->setName( "macroDist" ); + + meta->addStatement( new GenOp( " @ = distance( @.xyz, @ );\r\n", + new DecOp( dist ), inPos, eyePos ) ); + } + + // grab connector texcoord register + ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); + Var *outTex = connectComp->getElement( RT_TEXCOORD ); + outTex->setName( String::ToString( "macroCoord%d", detailIndex ) ); + outTex->setStructName( "OUT" ); + outTex->setType( "vec4" ); + outTex->mapsToSampler = true; + + // Get the detail scale and fade info. + Var *detScaleAndFade = new Var; + detScaleAndFade->setType( "vec4" ); + detScaleAndFade->setName( String::ToString( "macroScaleAndFade%d", detailIndex ) ); + detScaleAndFade->uniform = true; + detScaleAndFade->constSortPos = cspPotentialPrimitive; + + // Setup the detail coord. + meta->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex, inTex, detScaleAndFade ) ); + + // And sneak the detail fade thru the w detailCoord. + meta->addStatement( new GenOp( " @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n", + outTex, detScaleAndFade, dist, detScaleAndFade ) ); + + output = meta; +} + + +void TerrainMacroMapFeatGLSL::processPix( Vector &componentList, + const MaterialFeatureData &fd ) +{ + const U32 detailIndex = getProcessIndex(); + Var *inTex = getVertTexCoord( "texCoord" ); + + MultiLine *meta = new MultiLine; + + // We need the negative tangent space view vector + // as in parallax mapping we step towards the camera. + Var *negViewTS = (Var*)LangElement::find( "negViewTS" ); + if ( !negViewTS && + fd.features.hasFeature( MFT_TerrainParallaxMap ) ) + { + Var *inNegViewTS = (Var*)LangElement::find( "outNegViewTS" ); + if ( !inNegViewTS ) + { + ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); + inNegViewTS = connectComp->getElement( RT_TEXCOORD ); + inNegViewTS->setName( "outNegViewTS" ); + inNegViewTS->setStructName( "IN" ); + inNegViewTS->setType( "vec3" ); + } + + negViewTS = new Var( "negViewTS", "vec3" ); + meta->addStatement( new GenOp( " @ = normalize( @ );\r\n", new DecOp( negViewTS ), inNegViewTS ) ); + } + + // Get the layer samples. + Var *layerSample = (Var*)LangElement::find( "layerSample" ); + if ( !layerSample ) + { + layerSample = new Var; + layerSample->setType( "vec4" ); + layerSample->setName( "layerSample" ); + + // Get the layer texture var + Var *layerTex = new Var; + layerTex->setType( "sampler2D" ); + layerTex->setName( "macrolayerTex" ); + layerTex->uniform = true; + layerTex->sampler = true; + layerTex->constNum = Var::getTexUnitNum(); + + // Read the layer texture to get the samples. + meta->addStatement( new GenOp( " @ = round( tex2D( @, @.xy ) * 255.0f );\r\n", + new DecOp( layerSample ), layerTex, inTex ) ); + } + + Var *layerSize = (Var*)LangElement::find( "layerSize" ); + if ( !layerSize ) + { + layerSize = new Var; + layerSize->setType( "float" ); + layerSize->setName( "layerSize" ); + layerSize->uniform = true; + layerSize->constSortPos = cspPass; + } + + // Grab the incoming detail coord. + Var *inDet = _getInMacroCoord( componentList ); + + // Get the detail id. + Var *detailInfo = _getMacroIdStrengthParallax(); + + // Create the detail blend var. + Var *detailBlend = new Var; + detailBlend->setType( "float" ); + detailBlend->setName( String::ToString( "macroBlend%d", detailIndex ) ); + + // Calculate the blend for this detail texture. + meta->addStatement( new GenOp( " @ = calcBlend( @.x, @.xy, @, @ );\r\n", + new DecOp( detailBlend ), detailInfo, inTex, layerSize, layerSample ) ); + + // Get a var and accumulate the blend amount. + Var *blendTotal = (Var*)LangElement::find( "blendTotal" ); + if ( !blendTotal ) + { + blendTotal = new Var; + //blendTotal->setName( "blendTotal" ); + blendTotal->setName( "blendTotal" ); + blendTotal->setType( "float" ); + meta->addStatement( new GenOp( " @ = 0;\r\n", new DecOp( blendTotal ) ) ); + } + + // Add to the blend total. + meta->addStatement( new GenOp( " @ = max( @, @ );\r\n", blendTotal, blendTotal, detailBlend ) ); + + // If this is a prepass then we skip color. if ( fd.features.hasFeature( MFT_PrePassConditioner ) ) { - // If this is a prepass and we don't have a - // matching normal map... we use no resources. - if ( !fd.features.hasFeature( MFT_TerrainNormalMap, getProcessIndex() ) ) - return res; + // Check to see if we have a gbuffer normal. + Var *gbNormal = (Var*)LangElement::find( "gbNormal" ); - // If this is the first matching normal map then - // it also samples from the layer tex. - if ( !fd.features.hasFeature( MFT_TerrainNormalMap, getProcessIndex() - 1 ) ) - res.numTex += 1; + // If we have a gbuffer normal and we don't have a + // normal map feature then we need to lerp in a + // default normal else the normals below this layer + // will show thru. + if ( gbNormal && + !fd.features.hasFeature( MFT_TerrainNormalMap, detailIndex ) ) + { + Var *viewToTangent = getInViewToTangent( componentList ); + + meta->addStatement( new GenOp( " @ = lerp( @, tGetMatrix3Row(@, 2), min( @, @.w ) );\r\n", + gbNormal, gbNormal, viewToTangent, detailBlend, inDet ) ); + } + + output = meta; + return; + } + + Var *detailColor = (Var*)LangElement::find( "macroColor" ); + if ( !detailColor ) + { + detailColor = new Var; + detailColor->setType( "vec4" ); + detailColor->setName( "macroColor" ); + meta->addStatement( new GenOp( " @;\r\n", new DecOp( detailColor ) ) ); + } + + // Get the detail texture. + Var *detailMap = new Var; + detailMap->setType( "sampler2D" ); + detailMap->setName( String::ToString( "macroMap%d", detailIndex ) ); + detailMap->uniform = true; + detailMap->sampler = true; + detailMap->constNum = Var::getTexUnitNum(); // used as texture unit num here + + // If we're using SM 3.0 then take advantage of + // dynamic branching to skip layers per-pixel. + if ( GFX->getPixelShaderVersion() >= 3.0f ) + meta->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend ) ); + + meta->addStatement( new GenOp( " {\r\n" ) ); + + // Note that we're doing the standard greyscale detail + // map technique here which can darken and lighten the + // diffuse texture. + // + // We take two color samples and lerp between them for + // side projection layers... else a single sample. + // + if ( fd.features.hasFeature( MFT_TerrainSideProject, detailIndex ) ) + { + meta->addStatement( new GenOp( " @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n", + detailColor, detailMap, inDet, detailMap, inDet, inTex ) ); } else { - // If this is the first detail pass then it - // also samples from the layer tex. - if ( !fd.features.hasFeature( MFT_TerrainDetailMap, getProcessIndex() - 1 ) ) - res.numTex += 1; - - res.numTex += 1; + meta->addStatement( new GenOp( " @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n", + detailColor, detailMap, inDet ) ); } + meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n", + detailColor, detailInfo, inDet ) ); + + Var *baseColor = (Var*)LangElement::find( "baseColor" ); + Var *outColor = (Var*)LangElement::find( "col" ); + + meta->addStatement( new GenOp( " @ = lerp( @, @ + @, @ );\r\n", + outColor, outColor, outColor, detailColor, detailBlend ) ); + //outColor, outColor, baseColor, detailColor, detailBlend ) ); + + meta->addStatement( new GenOp( " }\r\n" ) ); + + output = meta; +} + + + +ShaderFeature::Resources TerrainMacroMapFeatGLSL::getResources( const MaterialFeatureData &fd ) +{ + Resources res; + + if ( getProcessIndex() == 0 ) + { + // If this is the first detail pass then we + // samples from the layer tex. + res.numTex += 1; + } + + // If this isn't the prepass then we sample + // from the detail texture for diffuse coloring. + if ( !fd.features.hasFeature( MFT_PrePassConditioner ) ) + res.numTex += 1; + + // Finally we always send the detail texture + // coord to the pixel shader. res.numTexReg += 1; return res; @@ -510,7 +884,7 @@ void TerrainNormalMapFeatGLSL::processPix( Vector &component gbNormal = new Var; gbNormal->setName( "gbNormal" ); gbNormal->setType( "vec3" ); - meta->addStatement( new GenOp( " @ = @[2];\r\n", new DecOp( gbNormal ), viewToTangent ) ); + meta->addStatement( new GenOp( " @ = tGetMatrix3Row(@, 2);\r\n", new DecOp( gbNormal ), viewToTangent ) ); } const U32 normalIndex = getProcessIndex(); @@ -520,7 +894,6 @@ void TerrainNormalMapFeatGLSL::processPix( Vector &component // If we're using SM 3.0 then take advantage of // dynamic branching to skip layers per-pixel. - if ( GFX->getPixelShaderVersion() >= 3.0f ) meta->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend ) ); @@ -531,7 +904,7 @@ void TerrainNormalMapFeatGLSL::processPix( Vector &component /// Get the texture coord. Var *inDet = _getInDetailCoord( componentList ); - Var *inTex = getVertTexCoord( "outTexCoord" ); + Var *inTex = getVertTexCoord( "texCoord" ); // Sample the normal map. // @@ -540,11 +913,11 @@ void TerrainNormalMapFeatGLSL::processPix( Vector &component LangElement *texOp; if ( fd.features.hasFeature( MFT_TerrainSideProject, normalIndex ) ) { - texOp = new GenOp( "mix( texture2D( @, @.yz ), texture2D( @, @.xz ), @.z )", + texOp = new GenOp( "lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z )", normalMap, inDet, normalMap, inDet, inTex ); } else - texOp = new GenOp( "texture2D(@, @.xy)", normalMap, inDet ); + texOp = new GenOp( "tex2D(@, @.xy)", normalMap, inDet ); // create bump normal Var *bumpNorm = new Var; @@ -556,7 +929,7 @@ void TerrainNormalMapFeatGLSL::processPix( Vector &component // Normalize is done later... // Note: The reverse mul order is intentional. Affine matrix. - meta->addStatement( new GenOp( " @ = mix( @, @.xyz * @, min( @, @.w ) );\r\n", + meta->addStatement( new GenOp( " @ = lerp( @, tMul( @.xyz, @ ), min( @, @.w ) );\r\n", gbNormal, gbNormal, bumpNorm, viewToTangent, detailBlend, inDet ) ); // End the conditional block. @@ -578,9 +951,11 @@ ShaderFeature::Resources TerrainNormalMapFeatGLSL::getResources( const MaterialF // We only need to process normals during the prepass. if ( fd.features.hasFeature( MFT_PrePassConditioner ) ) { - // If this is the first normal map then it - // will generate the worldToTanget transform. - if ( !fd.features.hasFeature( MFT_TerrainNormalMap, getProcessIndex() - 1 ) ) + // If this is the first normal map and there + // are no parallax features then we will + // generate the worldToTanget transform. + if ( !fd.features.hasFeature( MFT_TerrainParallaxMap ) && + ( getProcessIndex() == 0 || !fd.features.hasFeature( MFT_TerrainNormalMap, getProcessIndex() - 1 ) ) ) res.numTexReg = 3; res.numTex = 1; @@ -589,100 +964,11 @@ ShaderFeature::Resources TerrainNormalMapFeatGLSL::getResources( const MaterialF return res; } -TerrainParallaxMapFeatGLSL::TerrainParallaxMapFeatGLSL() - : mIncludeDep( "shaders/common/gl/torque.glsl" ) -{ - addDependency( &mIncludeDep ); -} - -void TerrainParallaxMapFeatGLSL::processVert( Vector &componentList, - const MaterialFeatureData &fd ) -{ - if ( LangElement::find( "outNegViewTS" ) ) - return; - - MultiLine *meta = new MultiLine; - - // Grab the input position. - Var *inPos = (Var*)LangElement::find( "inPosition" ); - if ( !inPos ) - inPos = (Var*)LangElement::find( "position" ); - - // Get the object space eye position and the - // object to tangent transform. - Var *eyePos = _getUniformVar( "eyePos", "vec3" , cspPotentialPrimitive ); - Var *objToTangentSpace = getOutObjToTangentSpace( componentList, meta,fd ); - - // Now send the negative view vector in tangent space to the pixel shader. - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - Var *outNegViewTS = connectComp->getElement( RT_TEXCOORD ); - outNegViewTS->setName( "outNegViewTS" ); - outNegViewTS->setType( "vec3" ); - meta->addStatement( new GenOp( " @ = @ * vec3( @ - @.xyz );\r\n", - outNegViewTS, objToTangentSpace, eyePos, inPos ) ); - - output = meta; -} - -void TerrainParallaxMapFeatGLSL::processPix( Vector &componentList, - const MaterialFeatureData &fd ) -{ - MultiLine *meta = new MultiLine; - - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - - // We need the negative tangent space view vector - // as in parallax mapping we step towards the camera. - Var *negViewTS = (Var*)LangElement::find( "negViewTS" ); - if ( !negViewTS ) - { - Var *inNegViewTS = (Var*)LangElement::find( "outNegViewTS" ); - if ( !inNegViewTS ) - { - inNegViewTS = connectComp->getElement( RT_TEXCOORD ); - inNegViewTS->setName( "outNegViewTS" ); - inNegViewTS->setType( "vec3" ); - } - - negViewTS = new Var( "negViewTS", "vec3" ); - meta->addStatement( new GenOp( " @ = normalize( @ );\r\n", new DecOp( negViewTS ), inNegViewTS ) ); - } - - // Get the rest of our inputs. - Var *detailInfo = _getDetailIdStrengthParallax(); - Var *normalMap = _getNormalMapTex(); - Var *texCoord = _getInDetailCoord( componentList ); - - // Call the library function to do the rest. - meta->addStatement( new GenOp( " @.xy += parallaxOffset( @, @.xy, @, @.z );\r\n", - texCoord, normalMap, texCoord, negViewTS, detailInfo ) ); - - output = meta; -} - -ShaderFeature::Resources TerrainParallaxMapFeatGLSL::getResources( const MaterialFeatureData &fd ) -{ - Resources res; - - // If this is the first parallax feature then - // it will generate the tangetEye vector and - // the worldToTanget transform. - if ( getProcessIndex() == 0 || !fd.features.hasFeature( MFT_TerrainParallaxMap, getProcessIndex() - 1 ) ) - res.numTexReg = 4; - - // If this isn't the prepass then we will - // be adding a normal map. - if ( !fd.features.hasFeature( MFT_PrePassConditioner ) ) - res.numTex = 1; - - return res; -} - void TerrainLightMapFeatGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { // grab connector texcoord register - Var *inTex = (Var*)LangElement::find( "outTexCoord" ); + Var *inTex = (Var*)LangElement::find( "texCoord" ); if ( !inTex ) return; @@ -694,13 +980,23 @@ void TerrainLightMapFeatGLSL::processPix( Vector &componentLis lightMap->sampler = true; lightMap->constNum = Var::getTexUnitNum(); - // Create a 'lightMask' value which is read by - // RTLighting to mask out the directional lighting. - Var *lightMask = new Var; - lightMask->setType( "vec3" ); - lightMask->setName( "lightMask" ); + MultiLine *meta = new MultiLine; - output = new GenOp( " @ = texture2D( @, @.xy ).rgb;\r\n", new DecOp( lightMask ), lightMap, inTex ); + // Find or create the lightMask value which is read by + // RTLighting to mask out the lights. + // + // The first light is always the sunlight so we apply + // the shadow mask to only the first channel. + // + Var *lightMask = (Var*)LangElement::find( "lightMask" ); + if ( !lightMask ) + { + lightMask = new Var( "lightMask", "vec4" ); + meta->addStatement( new GenOp( " @ = vec4(1);\r\n", new DecOp( lightMask ) ) ); + } + + meta->addStatement( new GenOp( " @[0] = tex2D( @, @.xy ).r;\r\n", lightMask, lightMap, inTex ) ); + output = meta; } ShaderFeature::Resources TerrainLightMapFeatGLSL::getResources( const MaterialFeatureData &fd ) @@ -721,7 +1017,7 @@ void TerrainAdditiveFeatGLSL::processPix( Vector &componentLis MultiLine *meta = new MultiLine; - meta->addStatement( new GenOp( " if ( @ - 0.0001 < 0.0 ) discard;\r\n", blendTotal ) ); + meta->addStatement( new GenOp( " clip( @ - 0.0001 );\r\n", blendTotal ) ); meta->addStatement( new GenOp( " @.a = @;\r\n", color, blendTotal ) ); output = meta; diff --git a/Engine/source/terrain/glsl/terrFeatureGLSL.h b/Engine/source/terrain/glsl/terrFeatureGLSL.h index c181ef493..790a8a342 100644 --- a/Engine/source/terrain/glsl/terrFeatureGLSL.h +++ b/Engine/source/terrain/glsl/terrFeatureGLSL.h @@ -30,6 +30,7 @@ #include "shaderGen/langElement.h" #endif + /// A shared base class for terrain features which /// includes some helper functions. class TerrainFeatGLSL : public ShaderFeatureGLSL @@ -38,14 +39,18 @@ protected: Var* _getInDetailCoord(Vector &componentList ); + Var* _getInMacroCoord(Vector &componentList ); + Var* _getNormalMapTex(); static Var* _getUniformVar( const char *name, const char *type, ConstantSortPosition csp ); Var* _getDetailIdStrengthParallax(); + Var* _getMacroIdStrengthParallax(); }; + class TerrainBaseMapFeatGLSL : public TerrainFeatGLSL { public: @@ -61,10 +66,12 @@ public: virtual String getName() { return "Terrain Base Texture"; } }; + class TerrainDetailMapFeatGLSL : public TerrainFeatGLSL { protected: + ShaderIncludeDependency mTorqueDep; ShaderIncludeDependency mTerrainDep; public: @@ -83,10 +90,17 @@ public: }; -class TerrainNormalMapFeatGLSL : public TerrainFeatGLSL +class TerrainMacroMapFeatGLSL : public TerrainFeatGLSL { +protected: + + ShaderIncludeDependency mTorqueDep; + ShaderIncludeDependency mTerrainDep; + public: + TerrainMacroMapFeatGLSL(); + virtual void processVert( Vector &componentList, const MaterialFeatureData &fd ); @@ -95,19 +109,14 @@ public: virtual Resources getResources( const MaterialFeatureData &fd ); - virtual String getName() { return "Terrain Normal Texture"; } + virtual String getName() { return "Terrain Macro Texture"; } }; -class TerrainParallaxMapFeatGLSL : public TerrainFeatGLSL + +class TerrainNormalMapFeatGLSL : public TerrainFeatGLSL { -protected: - - ShaderIncludeDependency mIncludeDep; - public: - TerrainParallaxMapFeatGLSL(); - virtual void processVert( Vector &componentList, const MaterialFeatureData &fd ); @@ -116,7 +125,7 @@ public: virtual Resources getResources( const MaterialFeatureData &fd ); - virtual String getName() { return "Terrain Parallax Texture"; } + virtual String getName() { return "Terrain Normal Texture"; } }; class TerrainLightMapFeatGLSL : public TerrainFeatGLSL