Using shaders with light attenuation with Ofusion [SOLVED]

Evak

04-10-2007 06:40:14

After the excellent results I got in my shader and 2 lights thread.

http://www.kineticrealities.com/3lights.jpg

I was wondering whether Ofusion supports param_named_auto atten0 light_attenuation 0

I saw that shaderFX supports inverse and inverse squared with decay as an optional global setting for your light sources in your shader material.

I'm currently working on giving my game Aerial Antics a graphics overhaul, including adding an attenuated light for the rocket pack. Is it possible to use Ofusion and get attenuation settings for each light in your scene?.

Lioric

04-10-2007 16:06:53

The auto parameter light attenuation is supported ("LIGHT_ATTENUATION" in the shader parameter editor)

This constant parameter has the form (in the shader):

Vector4(range, constant, linear, cuadratic)

If in your example, the parameter is named "atten0", you can access the light attenuation values with:

atten0.x (range, float type)
atten0.y (constant, float type)
atten0.z (linear, float ype)
atten0.w (cuadratic, float type)

I will review what values shaderFX uses for this

What shaderFX node is, that generates this parameter?

Evak

04-10-2007 16:56:18

Hi lioric, I looked into it some more and there is an attenuation node, seems like the easiest way to control the range is via the decay settings in the material.

which was what I was playing with, but its not attenuation. I just found the attenuation node in the groups node section.

THe shaderFX help says that you cant use the attenuation node with the standard material node, which handles attenuation automaticly. I'll see if I can get attenuation working here, and then post a simple diffuse color shader with working attenuation on here.

Evak

04-10-2007 20:09:56

Hmm, starting to think that maybe decay and attenuation are considered the same thing in ShaderFX.

Here's what a basic shaderFX HLSL .FX shader looks like with the standard materials decay enabled. This shader has decay set to inverse with a range of 100.

float decayScale
<

> = 145.0;


/************** light info **************/

float3 light1Pos : POSITION
<

> = {100.0f, 100.0f, 100.0f};

//----------------------------------

float4 light1Color : LIGHTCOLOR
<

> = { 1.0f, 1.0f, 1.0f, 1.0f};

//----------------------------------

float4x4 wvp : WorldViewProjection < string UIType = "None"; >;
float4x4 worldI : WorldInverse < string UIType = "None"; >;
float4x4 worldIT : WorldInverseTranspose < string UIType = "None"; >;
float4x4 viewInv : ViewInverse < string UIType = "None"; >;
float4x4 world : World < string UIType = "None"; >;

// input from application
struct a2v {
float4 position : POSITION;
float3 tangent : TANGENT;
float3 binormal : BINORMAL;
float3 normal : NORMAL;


};

// output to fragment program
struct v2f {
float4 position : POSITION;
float3 lightVec : TEXCOORD0;


};

//Diffuse and Specular Pass Vertex Shader
v2f v(a2v In, uniform float3 lightPosition)
{
v2f Out = (v2f)0;
Out.position = mul(In.position, wvp); //transform vert position to homogeneous clip space
//this code was added by the standard material
float3x3 objTangentXf; //build object to tangent space transform matrix
objTangentXf[0] = In.tangent;
objTangentXf[1] = -In.binormal;
objTangentXf[2] = In.normal;
//this code was added by the standard material
float3 osLPos = mul(lightPosition, worldI); //put world space light position in object space
float3 osLVec = osLPos.xyz - In.position.xyz; //object space light vector
Out.lightVec = mul(objTangentXf, osLVec); //tangent space light vector passed out
return Out;
}

//Diffuse and Specular Pass Pixel Shader
float4 f(v2f In, uniform float4 lightColor) : COLOR
{
float3 ret = float3(0,0,0);
float3 L = normalize(In.lightVec); //creating the light vector

float3 DiffuseColor = float3(0.858824f, 0.180392f, 0.180392f );
float3 input2 = DiffuseColor;

float3 N = float3(0.0, 0.0, 1.0); //the Normal socket was empty - using default value
float3 diffuseColor = input2; //using the Diffuse Color socket
float diffuse = saturate(dot(N,L)); //calculate the diffuse
diffuseColor *= diffuse; //the resulting diffuse color
ret += diffuseColor; //add diffuse light to final color
float d = length(In.lightVec); //measure the length of the light vector
float attenuation = (1 / d) * decayScale; //linear light decay
ret *= attenuation; //multiply by the light decay
ret *= lightColor; //multiply by the color of the light
float4 done = float4(ret, 1);
return done;


I posted on the shaderFX forum asking about attenuation, I may be getting confused, but I was under the impression that decay and attenuation were not the same thing, and that I should be able to adjust the lights attenuation in max and see the effect on the shader material.

Evak

05-10-2007 05:42:30

I got a response regarding attenuation in ShaderFX, doesn't look too promising :(.

ShaderFX currently only has light decay as option.
Inside max you cannot read any data from the light other then position and color.
So setting the near/far attenuation of a light object in the max scene will not end up in the shader.

I really wish it could though, but there is no access to those light properties from within a shader.
Sounds wierd, but max has to specifically pass things into a shader from objects in the scene and it simply does not pass attenuation settings.

So with ShaderFX we added a decay setting for the material to give you at least 'something'.
However it does the same decay/attenuation for every light.
So if your material has 3 lights, all 3 get the same decay.

That maybe something we could improve on in the future where we give you a seperate decay value for each of the lights.

The only way to do this now would be to use a advanced material and do your own decay (base on light position) I think.
(Though you may run into some limitations there too, I would have to try to be sure)

There is room for improvement in this part of the system for sure.

Lioric

05-10-2007 16:23:41

You can get any light data as you need, that is why in the exported scene the light attenuation form the max light is available (or for advanced control we provide a custom light attenuation parameters)

Probably they are using a different method

In any case, if you use the LIGHT_ATTENUATION auto parameter, you will get the complete attenuation parameters for each light in your shader

Evak

05-10-2007 17:09:50

Is there an easy way to add LIGHT_ATTENUATION auto parameter?

I'll add it to my .program file and do some research see if I can find anything easy for me to figure it out from :)

Lioric

09-10-2007 16:08:35

In your shader parameter list (in the shader source file) add the parameter uniform float4 lightAtten (or name the parameter what you need)



returnValue shaderProgramName(a2v In, uniform float4 lightAtten, ... ) {

// shader code

float range = lightAtten.x;
float constant = lightAtten.y;
float linear = lightAtten.z;
float cuadratic = lightAtten.w;

// Use the light attenuation values as you need

}



In your .program file (shader definition file) you add the default value (LIGHT_ATTENUATION), as you noted in your previous post, in the default parameters section you add the "param_named_auto lightAtten light_attenuation 0"

Evak

13-10-2007 05:18:21

thanks for the tips lioric, our coder has spent a large chunk of the day and found what seems to be a simple way to add it.

we found an easy way to get shaderFX shaders to work with max far attenuation in ofusion :)

had to put param_named_auto lightAtten light_attenuation 0" into the fragment shader definition.

put uniform float4 lightAtten parameter from the list of Vertex Program parameters and place it in the Fragment Program parameters

just had to

Replace: ( In the fragment program )

ret*= lightColor;

with

// ADDED - attenuation term -
float d = length( In.lightVec );
float4 attn = ( 1.0 / (( lightAtten.y ) + ( lightAtten.z * d ) + ( lightAtten.w * d * d ))*60 );

ret *= lightColor*attn;


With the auto light position, auto light color, and auto light attenuation definitions in my ogre material, all the lights data is now read automaticly up to the max number of simultanious dynamic lights permitted in my material.



Might come in handy for other shaderFX ogre users.