|
|
|
@ -25,6 +25,7 @@
|
|
|
|
|
|
|
|
|
|
#include "ogre_nif_loader.hpp"
|
|
|
|
|
|
|
|
|
|
#include <components/settings/settings.hpp>
|
|
|
|
|
|
|
|
|
|
typedef unsigned char ubyte;
|
|
|
|
|
|
|
|
|
@ -299,138 +300,136 @@ void NIFLoader::createMaterial(const String &name,
|
|
|
|
|
material->setSelfIllumination(emissive.array[0], emissive.array[1], emissive.array[2]);
|
|
|
|
|
material->setShininess(glossiness);
|
|
|
|
|
|
|
|
|
|
// Create shader for the material
|
|
|
|
|
// vertex
|
|
|
|
|
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
|
|
|
|
|
|
|
|
|
|
HighLevelGpuProgramPtr vertex;
|
|
|
|
|
if (mgr.getByName("main_vp").isNull())
|
|
|
|
|
if (Settings::Manager::getBool("shaders", "Objects"))
|
|
|
|
|
{
|
|
|
|
|
vertex = mgr.createProgram("main_vp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
|
|
|
|
"cg", GPT_VERTEX_PROGRAM);
|
|
|
|
|
vertex->setParameter("profiles", "vs_4_0 vs_2_x vp40 arbvp1");
|
|
|
|
|
vertex->setParameter("entry_point", "main_vp");
|
|
|
|
|
StringUtil::StrStreamType outStream;
|
|
|
|
|
outStream <<
|
|
|
|
|
"void main_vp( \n"
|
|
|
|
|
" float4 position : POSITION, \n"
|
|
|
|
|
" float4 normal : NORMAL, \n"
|
|
|
|
|
" float4 colour : COLOR, \n"
|
|
|
|
|
" in float2 uv : TEXCOORD0, \n"
|
|
|
|
|
" out float2 oUV : TEXCOORD0, \n"
|
|
|
|
|
" out float4 oPosition : POSITION, \n"
|
|
|
|
|
" out float4 oPositionObjSpace : TEXCOORD1, \n"
|
|
|
|
|
" out float4 oNormal : TEXCOORD2, \n"
|
|
|
|
|
" out float oFogValue : TEXCOORD3, \n"
|
|
|
|
|
" out float4 oVertexColour : TEXCOORD4, \n"
|
|
|
|
|
" uniform float4 fogParams, \n"
|
|
|
|
|
" uniform float4x4 worldViewProj \n"
|
|
|
|
|
") \n"
|
|
|
|
|
"{ \n"
|
|
|
|
|
" oVertexColour = colour; \n"
|
|
|
|
|
" oUV = uv; \n"
|
|
|
|
|
" oNormal = normal; \n"
|
|
|
|
|
" oPosition = mul( worldViewProj, position ); \n"
|
|
|
|
|
" oFogValue = saturate((oPosition.z - fogParams.y) * fogParams.w); \n"
|
|
|
|
|
" oPositionObjSpace = position; \n"
|
|
|
|
|
"}";
|
|
|
|
|
vertex->setSource(outStream.str());
|
|
|
|
|
vertex->load();
|
|
|
|
|
vertex->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
|
|
|
|
|
vertex->getDefaultParameters()->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
vertex = mgr.getByName("main_vp");
|
|
|
|
|
material->getTechnique(0)->getPass(0)->setVertexProgram(vertex->getName());
|
|
|
|
|
|
|
|
|
|
// the number of lights to support.
|
|
|
|
|
// when rendering an object, OGRE automatically picks the lights that are
|
|
|
|
|
// closest to the object being rendered. unfortunately this mechanism does
|
|
|
|
|
// not work perfectly for objects batched together (they will all use the same
|
|
|
|
|
// lights). to work around this, we are simply pushing the maximum number
|
|
|
|
|
// of lights here in order to minimize disappearing lights.
|
|
|
|
|
float num_lights;
|
|
|
|
|
if (GpuProgramManager::getSingleton().isSyntaxSupported("fp40") ||
|
|
|
|
|
GpuProgramManager::getSingleton().isSyntaxSupported("ps_4_0"))
|
|
|
|
|
num_lights = 8 /* 32 */;
|
|
|
|
|
else
|
|
|
|
|
num_lights = 8;
|
|
|
|
|
// Create shader for the material
|
|
|
|
|
// vertex
|
|
|
|
|
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
|
|
|
|
|
|
|
|
|
|
// fragment
|
|
|
|
|
HighLevelGpuProgramPtr fragment;
|
|
|
|
|
if (mgr.getByName("main_fp").isNull())
|
|
|
|
|
{
|
|
|
|
|
fragment = mgr.createProgram("main_fp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
|
|
|
|
"cg", GPT_FRAGMENT_PROGRAM);
|
|
|
|
|
fragment->setParameter("profiles", "ps_4_0 ps_2_x fp40 arbfp1");
|
|
|
|
|
fragment->setParameter("entry_point", "main_fp");
|
|
|
|
|
StringUtil::StrStreamType outStream;
|
|
|
|
|
outStream <<
|
|
|
|
|
"void main_fp( \n"
|
|
|
|
|
" in float2 uv : TEXCOORD0, \n"
|
|
|
|
|
" out float4 oColor : COLOR, \n"
|
|
|
|
|
" uniform sampler2D texture : TEXUNIT0, \n"
|
|
|
|
|
" float4 positionObjSpace : TEXCOORD1, \n"
|
|
|
|
|
" float4 normal : TEXCOORD2, \n"
|
|
|
|
|
" float fogValue : TEXCOORD3, \n"
|
|
|
|
|
" float4 vertexColour : TEXCOORD4, \n"
|
|
|
|
|
" uniform float4 fogColour, \n";
|
|
|
|
|
|
|
|
|
|
for (int i=0; i<num_lights; ++i)
|
|
|
|
|
HighLevelGpuProgramPtr vertex;
|
|
|
|
|
if (mgr.getByName("main_vp").isNull())
|
|
|
|
|
{
|
|
|
|
|
vertex = mgr.createProgram("main_vp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
|
|
|
|
"cg", GPT_VERTEX_PROGRAM);
|
|
|
|
|
vertex->setParameter("profiles", "vs_4_0 vs_2_x vp40 arbvp1");
|
|
|
|
|
vertex->setParameter("entry_point", "main_vp");
|
|
|
|
|
StringUtil::StrStreamType outStream;
|
|
|
|
|
outStream <<
|
|
|
|
|
" uniform float4 lightDiffuse"<<i<<", \n"
|
|
|
|
|
" uniform float4 lightPositionObjSpace"<<i<<", \n"
|
|
|
|
|
" uniform float4 lightAttenuation"<<i<<", \n";
|
|
|
|
|
"void main_vp( \n"
|
|
|
|
|
" float4 position : POSITION, \n"
|
|
|
|
|
" float4 normal : NORMAL, \n"
|
|
|
|
|
" float4 colour : COLOR, \n"
|
|
|
|
|
" in float2 uv : TEXCOORD0, \n"
|
|
|
|
|
" out float2 oUV : TEXCOORD0, \n"
|
|
|
|
|
" out float4 oPosition : POSITION, \n"
|
|
|
|
|
" out float4 oPositionObjSpace : TEXCOORD1, \n"
|
|
|
|
|
" out float4 oNormal : TEXCOORD2, \n"
|
|
|
|
|
" out float oFogValue : TEXCOORD3, \n"
|
|
|
|
|
" out float4 oVertexColour : TEXCOORD4, \n"
|
|
|
|
|
" uniform float4 fogParams, \n"
|
|
|
|
|
" uniform float4x4 worldViewProj \n"
|
|
|
|
|
") \n"
|
|
|
|
|
"{ \n"
|
|
|
|
|
" oVertexColour = colour; \n"
|
|
|
|
|
" oUV = uv; \n"
|
|
|
|
|
" oNormal = normal; \n"
|
|
|
|
|
" oPosition = mul( worldViewProj, position ); \n"
|
|
|
|
|
" oFogValue = saturate((oPosition.z - fogParams.y) * fogParams.w); \n"
|
|
|
|
|
" oPositionObjSpace = position; \n"
|
|
|
|
|
"}";
|
|
|
|
|
vertex->setSource(outStream.str());
|
|
|
|
|
vertex->load();
|
|
|
|
|
vertex->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
|
|
|
|
|
vertex->getDefaultParameters()->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS);
|
|
|
|
|
}
|
|
|
|
|
outStream <<
|
|
|
|
|
" uniform float4 lightAmbient, \n"
|
|
|
|
|
" uniform float4 ambient, \n"
|
|
|
|
|
" uniform float4 diffuse, \n"
|
|
|
|
|
" uniform float4 emissive \n"
|
|
|
|
|
") \n"
|
|
|
|
|
"{ \n"
|
|
|
|
|
" float4 tex = tex2D(texture, uv); \n"
|
|
|
|
|
" float d; \n"
|
|
|
|
|
" float attn; \n"
|
|
|
|
|
" float3 lightColour = float3(0, 0, 0); \n";
|
|
|
|
|
|
|
|
|
|
for (int i=0; i<num_lights; ++i)
|
|
|
|
|
else
|
|
|
|
|
vertex = mgr.getByName("main_vp");
|
|
|
|
|
material->getTechnique(0)->getPass(0)->setVertexProgram(vertex->getName());
|
|
|
|
|
|
|
|
|
|
// the number of lights to support.
|
|
|
|
|
// when rendering an object, OGRE automatically picks the lights that are
|
|
|
|
|
// closest to the object being rendered. unfortunately this mechanism does
|
|
|
|
|
// not work perfectly for objects batched together (they will all use the same
|
|
|
|
|
// lights). to work around this, we are simply pushing the maximum number
|
|
|
|
|
// of lights here in order to minimize disappearing lights.
|
|
|
|
|
int num_lights = Settings::Manager::getInt("num lights", "Objects");
|
|
|
|
|
|
|
|
|
|
// fragment
|
|
|
|
|
HighLevelGpuProgramPtr fragment;
|
|
|
|
|
if (mgr.getByName("main_fp").isNull())
|
|
|
|
|
{
|
|
|
|
|
fragment = mgr.createProgram("main_fp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
|
|
|
|
"cg", GPT_FRAGMENT_PROGRAM);
|
|
|
|
|
fragment->setParameter("profiles", "ps_4_0 ps_2_x fp40 arbfp1");
|
|
|
|
|
fragment->setParameter("entry_point", "main_fp");
|
|
|
|
|
StringUtil::StrStreamType outStream;
|
|
|
|
|
outStream <<
|
|
|
|
|
" float3 lightDir"<<i<<" = lightPositionObjSpace"<<i<<".xyz - (positionObjSpace.xyz * lightPositionObjSpace"<<i<<".w); \n"
|
|
|
|
|
|
|
|
|
|
// pre-multiply light color with attenuation factor
|
|
|
|
|
" d = length( lightDir"<<i<<" ); \n"
|
|
|
|
|
" attn = ( 1.0 / (( lightAttenuation"<<i<<".y ) + ( lightAttenuation"<<i<<".z * d ) + ( lightAttenuation"<<i<<".w * d * d ))); \n"
|
|
|
|
|
" lightDiffuse"<<i<<" *= attn; \n"
|
|
|
|
|
"void main_fp( \n"
|
|
|
|
|
" in float2 uv : TEXCOORD0, \n"
|
|
|
|
|
" out float4 oColor : COLOR, \n"
|
|
|
|
|
" uniform sampler2D texture : TEXUNIT0, \n"
|
|
|
|
|
" float4 positionObjSpace : TEXCOORD1, \n"
|
|
|
|
|
" float4 normal : TEXCOORD2, \n"
|
|
|
|
|
" float fogValue : TEXCOORD3, \n"
|
|
|
|
|
" float4 vertexColour : TEXCOORD4, \n"
|
|
|
|
|
" uniform float4 fogColour, \n";
|
|
|
|
|
|
|
|
|
|
for (int i=0; i<num_lights; ++i)
|
|
|
|
|
{
|
|
|
|
|
outStream <<
|
|
|
|
|
" uniform float4 lightDiffuse"<<i<<", \n"
|
|
|
|
|
" uniform float4 lightPositionObjSpace"<<i<<", \n"
|
|
|
|
|
" uniform float4 lightAttenuation"<<i<<", \n";
|
|
|
|
|
}
|
|
|
|
|
outStream <<
|
|
|
|
|
" uniform float4 lightAmbient, \n"
|
|
|
|
|
" uniform float4 ambient, \n"
|
|
|
|
|
" uniform float4 diffuse, \n"
|
|
|
|
|
" uniform float4 emissive \n"
|
|
|
|
|
") \n"
|
|
|
|
|
"{ \n"
|
|
|
|
|
" float4 tex = tex2D(texture, uv); \n"
|
|
|
|
|
" float d; \n"
|
|
|
|
|
" float attn; \n"
|
|
|
|
|
" float3 lightColour = float3(0, 0, 0); \n";
|
|
|
|
|
|
|
|
|
|
for (int i=0; i<num_lights; ++i)
|
|
|
|
|
{
|
|
|
|
|
outStream <<
|
|
|
|
|
" float3 lightDir"<<i<<" = lightPositionObjSpace"<<i<<".xyz - (positionObjSpace.xyz * lightPositionObjSpace"<<i<<".w); \n"
|
|
|
|
|
|
|
|
|
|
" lightColour.xyz += lit(dot(normalize(lightDir"<<i<<"), normalize(normal)), 0, 0).y * lightDiffuse"<<i<<".xyz;\n";
|
|
|
|
|
}
|
|
|
|
|
// pre-multiply light color with attenuation factor
|
|
|
|
|
" d = length( lightDir"<<i<<" ); \n"
|
|
|
|
|
" attn = ( 1.0 / (( lightAttenuation"<<i<<".y ) + ( lightAttenuation"<<i<<".z * d ) + ( lightAttenuation"<<i<<".w * d * d ))); \n"
|
|
|
|
|
" lightDiffuse"<<i<<" *= attn; \n"
|
|
|
|
|
|
|
|
|
|
outStream <<
|
|
|
|
|
" float3 lightingFinal = lightColour.xyz * diffuse.xyz * vertexColour.xyz + ambient.xyz * lightAmbient.xyz + emissive.xyz; \n"
|
|
|
|
|
" oColor.xyz = lerp(lightingFinal * tex.xyz, fogColour, fogValue); \n"
|
|
|
|
|
" oColor.a = tex.a * diffuse.a * vertexColour.a; \n"
|
|
|
|
|
"}";
|
|
|
|
|
fragment->setSource(outStream.str());
|
|
|
|
|
fragment->load();
|
|
|
|
|
" lightColour.xyz += lit(dot(normalize(lightDir"<<i<<"), normalize(normal)), 0, 0).y * lightDiffuse"<<i<<".xyz;\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i=0; i<num_lights; ++i)
|
|
|
|
|
{
|
|
|
|
|
fragment->getDefaultParameters()->setNamedAutoConstant("lightPositionObjSpace"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE, i);
|
|
|
|
|
fragment->getDefaultParameters()->setNamedAutoConstant("lightDiffuse"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR, i);
|
|
|
|
|
fragment->getDefaultParameters()->setNamedAutoConstant("lightAttenuation"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_ATTENUATION, i);
|
|
|
|
|
outStream <<
|
|
|
|
|
" float3 lightingFinal = lightColour.xyz * diffuse.xyz * vertexColour.xyz + ambient.xyz * lightAmbient.xyz + emissive.xyz; \n"
|
|
|
|
|
" oColor.xyz = lerp(lightingFinal * tex.xyz, fogColour, fogValue); \n"
|
|
|
|
|
" oColor.a = tex.a * diffuse.a * vertexColour.a; \n"
|
|
|
|
|
"}";
|
|
|
|
|
fragment->setSource(outStream.str());
|
|
|
|
|
fragment->load();
|
|
|
|
|
|
|
|
|
|
for (int i=0; i<num_lights; ++i)
|
|
|
|
|
{
|
|
|
|
|
fragment->getDefaultParameters()->setNamedAutoConstant("lightPositionObjSpace"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE, i);
|
|
|
|
|
fragment->getDefaultParameters()->setNamedAutoConstant("lightDiffuse"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR, i);
|
|
|
|
|
fragment->getDefaultParameters()->setNamedAutoConstant("lightAttenuation"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_ATTENUATION, i);
|
|
|
|
|
}
|
|
|
|
|
fragment->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
|
|
|
|
|
fragment->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR);
|
|
|
|
|
fragment->getDefaultParameters()->setNamedAutoConstant("ambient", GpuProgramParameters::ACT_SURFACE_AMBIENT_COLOUR);
|
|
|
|
|
fragment->getDefaultParameters()->setNamedAutoConstant("lightAmbient", GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR);
|
|
|
|
|
fragment->getDefaultParameters()->setNamedAutoConstant("fogColour", GpuProgramParameters::ACT_FOG_COLOUR);
|
|
|
|
|
}
|
|
|
|
|
fragment->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
|
|
|
|
|
fragment->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR);
|
|
|
|
|
fragment->getDefaultParameters()->setNamedAutoConstant("ambient", GpuProgramParameters::ACT_SURFACE_AMBIENT_COLOUR);
|
|
|
|
|
fragment->getDefaultParameters()->setNamedAutoConstant("lightAmbient", GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR);
|
|
|
|
|
fragment->getDefaultParameters()->setNamedAutoConstant("fogColour", GpuProgramParameters::ACT_FOG_COLOUR);
|
|
|
|
|
else
|
|
|
|
|
fragment = mgr.getByName("main_fp");
|
|
|
|
|
material->getTechnique(0)->getPass(0)->setFragmentProgram(fragment->getName());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
fragment = mgr.getByName("main_fp");
|
|
|
|
|
material->getTechnique(0)->getPass(0)->setFragmentProgram(fragment->getName());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Takes a name and adds a unique part to it. This is just used to
|
|
|
|
|