Sign in to follow this  
Daniel Wilson

What to do with an attenuated light vector in my shader

Recommended Posts

Hi, I am working on implementing a subsurface scattering light shader and have it all coded I just need to debug. I have a question I cannot solve though, say I have the attenuated light vector that has come from the light, scattered as it enters the surface of the object, and now goes to the viewers eye. What would I do with this output vector for for a mesh that has a standard Blinn-Phong shader? The image has the vector I am talking about, vector [i]PC[/i]



[img]http://i.imgur.com/xiINE.png[/img]

In my normal lighting shader I have this:

[CODE]

float3 l = normalize(IN.light.xyz - IN.oPosition);
float3 v = normalize(IN.oPosition);

// compute diffuse and specular terms
float diff = saturate(dot(l,IN.normal));
float spec = saturate(dot(normalize(l-v),IN.normal));
spec = pow(spec, shine);
// attenuation factor
float att = saturate(dot(l, IN.normal));

// compute final color
float3 finalcolor;
finalcolor = ambient.xyz*color.xyz +
att*(color.xyz*diffuse.xyz*diff +
specular*spec);

return float4(finalcolor.xyz, 1.0);
[/CODE]

With no normal map or anything, how might I slot PC into this code. I'm thinking it would replace the view direction [i]v[/i] that I have. Someone else told me the *= it with the final colour, but that just produces weird rainbow type colours, and my light is white

Share this post


Link to post
Share on other sites
[quote name='shiqiu1105' timestamp='1341544575' post='4956198']
How do you implement the SSS effect?? it's an approximation?
[/quote]

It is a single scattering approximation, using cg. The paper is called subsurface texture mapping and is located [url="http://graphics.cs.ucf.edu/stm.pdf"]here[/url] . It uses a texture to encode depth in the rgba channels, where red is the first layer, alpha is the bottom layer etc. So light enters the mesh, becomes attenuated from this texture and lots of other calculations, then leaves afaik. So I'm not really sure what to do with the light that leaves then. My current guess is that it would replace the l vector in the above code (rather than subtracting the light pos from the pixel position).

Share this post


Link to post
Share on other sites
My theory now is that I could just multiply the final colour by the result. Anyone know if this is correct? My result may be wrong at the moment, its pretty blue so multiplying by the final colour is really removing most of the diffuse colour for a dark blue though....

Share this post


Link to post
Share on other sites
So I didn't quite figure this out yet because it's quite a complex shader. I would lke to implement this shader with a basic phong model. [img]http://takinginitiative.files.wordpress.com/2010/08/surface.jpg[/img]

Say I have this:

[source lang="cpp"] float3 BumpNormal = tex2D(nm, IN.texcoord)*2.0 - 1.0;
float4 amb = AmbientIntensity * ambient;
float4 diff = DiffuseIntensity * diffuse * saturate(dot(IN.worldLightDir,BumpNormal));

float3 R = normalize(2.0 * dot(BumpNormal, IN.worldLightDir) * BumpNormal - IN.worldLightDir);
float3 v = normalize(IN.eye);

float spec = pow(saturate(dot(R,v)), specularPower) * SpecularIntensity;

// compute final color
float4 color = tex2D(color_map,IN.texcoord);

float4 finalcolor = (amb + diff + spec) * color;[/source]

R and V are purely directional vectors right? So my attenuated light vector must represent a [i]direction [/i]and the [i]intensity [/i]of the light that is returned to the [i]viewer [/i]I think. In the above code the only thing that strikes me as close to this is the calculation of the diffuse value. Ignoring the bump map (I don't need bumped normals), does anyone know if it would be wrong to have:
[source lang="cpp"]float4 diff = DiffuseIntensity * diffuse * p_omega_out;[/source]
Where [font=courier new,courier,monospace]p_omega_out[/font] is the attenuated light intensity/direction? I think my vector needs to go from the pixel to the viewer, would this vector do that?!

Share this post


Link to post
Share on other sites
Specular lighting is light that reflects off the surface, without entering the material at all, so your SSS code definately shouldn't modulate the specular contribution.

Diffuse lighting is light that refracts into the object, bounces around inside, and later re-emerges. In standard lighting models, we use the simplification that the diffuse exit points are all located at the entry point ([i]there is no movement inside the material[/i]).

SSS expands this by making the diffuse model more advanced -- instead of just using a constant diffuse colour, you use your chosen technique ([i]a multi-layered texture, in your case[/i]) to calculate the colouration of the diffuse light, and to calculate how far inside the material the diffuse light travels before re-emerging ([i]which has a blurring effect on the diffuse light[/i]).
[hr]
Regarding attenuation: standard lighting will calculate the attenuation from the light-source to the material (from S to K in your original diagram), which affects the amount of light that reaches the surface in the first place (before it's split into diffuse-refraction/specular-reflection). In standard blinn-phong, internal diffuse attenuation is specified by a constant value: your "diffuse colour".
When you extend this with SSS, the "diffuse colour" is instead calculated by the internal attenuation from K to M, and M to P -- the details of that specified by your chosen technique.

Share this post


Link to post
Share on other sites
[quote name='Hodgman' timestamp='1344267403' post='4966697']
In standard blinn-phong, internal diffuse attenuation is specified by a constant value: your "diffuse colour".
When you extend this with SSS, the "diffuse colour" is instead calculated by the internal attenuation from K to M, and M to P -- the details of that specified by your chosen technique
[/quote]

Ah okay this is interesting thank you. You see the paper assumes you just know what to do with the output vector that has been attenuated from K-M-P. So theoretically it should be okay to use it in place of a hard coded "diffuse" value I did have, e.g.:
[source lang="cpp"]float4 diff = DiffuseIntensity * p_omega_out * saturate(dot(IN.worldLightDir,BumpNormal));[/source]
At the moment if I output p_omega_out as a colour, the result is some pretty blurry bands of colour, so hopefully it won't damage the rest of the colour too much. (I'll post a screen cap in a few mins). Thanks [img]http://public.gamedev.net//public/style_emoticons/default/cool.png[/img]

Share this post


Link to post
Share on other sites
Okay so the [font=courier new,courier,monospace]p_omega_out[/font] value looks like this as a colour:
[img]http://img27.imageshack.us/img27/7017/56461905.png[/img]

Applied to a simple plane. I'm not sure whether or not that's the correct output for it but that's what I have at the moment. If I slot it in to my phong normal mapped plane, I get this:
[img]http://img4.imageshack.us/img4/5800/93060286.png[/img]

Which is pretty but obviously isn't right! So is [font=courier new,courier,monospace]p_omega_out[/font] wrong, or am I just putting it in the wrong place!? Here is the final part of the code for reference but the only change is the inclusion of the new attenuated vector:
[source lang="cpp"] float3 BumpNormal = tex2D(nm, IN.texcoord)*2.0 - 1.0;
float4 amb = AmbientIntensity * ambient;
float4 diff = DiffuseIntensity * float4(p_omega_out, 1) * saturate(dot(IN.tangentSpaceLightDir,BumpNormal));

float3 R = normalize(2.0 * dot(BumpNormal, IN.tangentSpaceLightDir) * BumpNormal - IN.tangentSpaceLightDir);
float3 v = normalize(IN.tangentSpaceEye);

float spec = pow(saturate(dot(R,v)), specularPower) * SpecularIntensity;

// compute final color
float4 color = tex2D(color_map,IN.texcoord);

float4 finalcolor = (amb + diff + spec) * color;

return finalcolor;[/source]

Share this post


Link to post
Share on other sites
[quote name='Daniel Wilson' timestamp='1344274285' post='4966724']
You see the paper assumes you just know what to do with the output vector that has been attenuated from K-M-P.
[/quote]I'm having a hard time following any of your posts in this thread, because "attenuated light vector" doesn't seems like the right terminology for what you're trying to describe.

Also, I have no idea what p_omega_out is, or where those magic colours come from.
i.e. with the information given, I can't possibly help. Note my previous post was just general advice barely connected to your posts because of this.

Perhaps you should just post your full SSS shader code, and the input textures?

Share this post


Link to post
Share on other sites
Woops sorry, I've gotten so deep into this thing I'm just assuming the whole world knows what I mean by [font=courier new,courier,monospace]p_omega_out[/font] [img]http://public.gamedev.net//public/style_emoticons/default/biggrin.png[/img]. I appreciate the help and even general advice is very useful. Here is another screen from the paper which should be looked at with the image from the first post.
[img]http://img824.imageshack.us/img824/3552/capturepjd.png[/img]
When I say [font=courier new,courier,monospace]p_omega_out[/font], I mean the vector from the pixel P to the viewer.

Here is the fx composer file I have at the moment, it's rather large and based off of the algorithms in the paper which you would probably need to read in full to make sense of so I won't ask you to do that! I am applying [url="http://img441.imageshack.us/img441/1986/sstm2.png"]this map as the subsurface texture map[/url].

[source lang="java"]/*****************************************************************/
/*** HOST APPLICATION IDENTIFIERS ********************************/
/*** Potentially predefined by varying host environments *********/
/*****************************************************************/

// #define _XSI_ /* predefined when running in XSI */
// #define TORQUE /* predefined in TGEA 1.7 and up */
// #define _3DSMAX_ /* predefined in 3DS Max */
#ifdef _3DSMAX_
int ParamID = 0x0003; /* Used by Max to select the correct parser */
#endif /* _3DSMAX_ */
#ifdef _XSI_
#define Main Static /* Technique name used for export to XNA */
#endif /* _XSI_ */

#ifndef FXCOMPOSER_VERSION /* for very old versions */
#define FXCOMPOSER_VERSION 180
#endif /* FXCOMPOSER_VERSION */

#ifndef DIRECT3D_VERSION
#define DIRECT3D_VERSION 0x900
#endif /* DIRECT3D_VERSION */

#define FLIP_TEXTURE_Y /* Different in OpenGL & DirectX */

/*****************************************************************/
/*** EFFECT-SPECIFIC CODE BEGINS HERE ****************************/
/*****************************************************************/

/******* Lighting Macros *******/
/** To use "Object-Space" lighting definitions, change these two macros: **/
#define LIGHT_COORDS "World"
// #define OBJECT_SPACE_LIGHTS /* Define if LIGHT_COORDS is "Object" */

/**** UNTWEAKABLES: Hidden & Automatically-Tracked Parameters **********/

// transform object vertices to world-space:
float4x4 gWorldXf : World < string UIWidget="None"; >;
// transform object vertices to view space and project them in perspective:
float4x4 gWvpXf : WorldViewProjection < string UIWidget="None"; >;

// Ambient Light
float4 ambient : AMBIENT <
string UIName = "Ambient Light Color";
string UIWidget = "Color";
> = {0.7f,0.7f,0.7f,1.0f};

// surface color
float4 diffuse : DIFFUSE <
string UIName = "Diffuse Color";
string UIWidget = "Color";
> = {0.9f,0.9f,0.9f,1.0f};

float4 specular <
string UIName = "Specular Color";
string UIWidget = "color";
> = {0.75,0.75,0.75,1};

float specularPower <
string UIName = "Phong Exponent";
string UIWidget = "slider";
float UIMin = 1.0f;
float UIStep = 4;
float UIMax = 256.0f;
> = 8.0;

/*********** TEXTURES ***************/

texture gColorTexture : DIFFUSE <
string ResourceName = "grey.jpg";
string UIName = "Color Texture";
string ResourceType = "2D";
>;

sampler2D cm = sampler_state {
Texture = <gColorTexture>;
#if DIRECT3D_VERSION >= 0xa00
Filter = MIN_MAG_MIP_LINEAR;
#else /* DIRECT3D_VERSION < 0xa00 */
MinFilter = Linear;
MipFilter = Linear;
MagFilter = Linear;
#endif /* DIRECT3D_VERSION */
AddressU = Wrap;
AddressV = Wrap;
};

texture gReliefTexture <
string ResourceName = "SSTM.png";
string UIName = "SSTM";
string ResourceType = "2D";
>;

sampler2D sstm = sampler_state {
Texture = <gReliefTexture>;
#if DIRECT3D_VERSION >= 0xa00
Filter = MIN_MAG_MIP_LINEAR;
#else /* DIRECT3D_VERSION < 0xa00 */
MinFilter = Linear;
MipFilter = Linear;
MagFilter = Linear;
#endif /* DIRECT3D_VERSION */
AddressU = Wrap;
AddressV = Wrap;
};

texture gNormalTexture : NORMAL <
string ResourceName = "grey.jpg";
string UIName = "Normal Texture";
string ResourceType = "2D";
>;

sampler2D nm = sampler_state {
Texture = <gNormalTexture>;
#if DIRECT3D_VERSION >= 0xa00
Filter = MIN_MAG_MIP_LINEAR;
#else /* DIRECT3D_VERSION < 0xa00 */
MinFilter = Linear;
MipFilter = Linear;
MagFilter = Linear;
#endif /* DIRECT3D_VERSION */
AddressU = Wrap;
AddressV = Wrap;
};

texture gMatrixTex <
string ResourceName = "grey.jpg";
string UIName = "Matrix Texture";
string ResourceType = "1D";
>;

sampler1D matrix_tex = sampler_state {
Texture = <gMatrixTex>;
};
float3x3 matTangent;
float3 worldEyePos : CAMERAPOSITION;
static const float AmbientIntensity = 1.0f; // The intensity of the ambient light.
static const float DiffuseIntensity = 1.0f; // The intensity of the diffuse light.
static const float SpecularIntensity = 1.0f; // The intensity of the specular light.

/********** CONNECTOR STRUCTURES *****************/

struct a2v //Application to a vertex
{
float4 pos : POSITION0;
float3 normal : NORMAL;
float4 tangent : TANGENT0;
float4 binormal : BINORMAL0;
float2 texcoord : TEXCOORD0;
float3 NSp : TEXCOORD1;
};

struct v2f //Vertex to a fragment (vertex output)
{
float4 hpos : POSITION0; //For rasterizer (not available in fragment shader, but must be written to)
float2 texcoord : TEXCOORD0;
float3 oNSp : TEXCOORD1;
float4 tangent : TEXCOORD2;
float3 eye : TEXCOORD3;
float3 worldLightDir : TEXCOORD4;
float4 binormal : TEXCOORD5;
float3 normal : TEXCOORD6;
float3 oPosition : TEXCOORD7;
float3 tangentSpaceEye : TEXCOORD8;
float3 tangentSpaceLightDir : TEXCOORD9;
};

struct outPixel
{
float4 colour : COLOR0;
};

/*** SHADER FUNCTIONS **********************************************/

v2f view_spaceVS(a2v IN,
uniform float4x4 WorldXf,
uniform float4x4 WvpXf
) {
// invert matrixes for FX Composer
WvpXf = transpose(WvpXf);
WorldXf = transpose(WorldXf);

v2f OUT = (v2f)0;
// vertex position in homogeneous clip space
OUT.hpos=mul(WvpXf, IN.pos);

OUT.texcoord = IN.texcoord;

// View vector in world space
float3 worldPos = mul(WorldXf, IN.pos).xyz;
OUT.eye = normalize(worldEyePos - worldPos); //Vertex to the eye (as opposed to incident eye->vert)

// Directional light so just normalize once
OUT.worldLightDir = normalize(float3(0, -1, 0));
// Planar approximation in world space
float4 N = float4(0, 1, 0, 0);
float4 B = float4(0, 0, 1, 0);
float4 T = float4(1, 0, 0, 0);
OUT.oNSp = mul(WorldXf, N);
//Position in world space
OUT.oPosition = worldPos;
//T, B, N in world space
OUT.normal = mul(WorldXf, N);
OUT.tangent = mul(WorldXf, T);
OUT.binormal = mul(WorldXf, B);

matTangent[0] = OUT.tangent;
matTangent[1] = OUT.binormal;
matTangent[2] = OUT.normal;

OUT.tangentSpaceEye = normalize(mul(OUT.eye, matTangent));
OUT.tangentSpaceLightDir = normalize(mul(-OUT.worldLightDir, matTangent));
return OUT;
}

//--------------------------
float4 color_mapping(v2f IN,
in float3 p_omega_out,
in float4 ambient,
in float4 diffuse,
in float4 specular,
in float specularPower,
in sampler2D color_map : register(s0),
in sampler2D sstm : register(s1),
in sampler2D nm : register(s3)
)
{
float3 BumpNormal = tex2D(nm, IN.texcoord)*2.0 - 1.0;
float4 amb = AmbientIntensity * ambient;
float4 diff = DiffuseIntensity * float4(p_omega_out, 1) * saturate(dot(IN.tangentSpaceLightDir,BumpNormal));

float3 R = normalize(2.0 * dot(BumpNormal, IN.tangentSpaceLightDir) * BumpNormal - IN.tangentSpaceLightDir);
float3 v = normalize(IN.tangentSpaceEye);

float spec = pow(saturate(dot(R,v)), specularPower) * SpecularIntensity;

// compute final color
float4 color = tex2D(color_map,IN.texcoord);

float4 finalcolor = (amb + diff + spec) * color;

//Remove this line to display p_omega_out with the diffuse and normal map
//-----------------------------------
finalcolor = float4(p_omega_out, 1.0);
//-----------------------------------

return finalcolor;
}

//--------------------------
float FindLayer(in float depthM,
in float2 umvm,
in sampler2D sstm : register(s1)
)
{
float4 ss_val = tex2Dlod(sstm, float4(umvm.x, umvm.y, 0, 1));
float layer = 0;

//Check red first, if depth is < red, layer = 0
//If and only if depth is greater than red, check if depth < green -> layer = 1
if(-depthM > ss_val.x)
{
if(-depthM > ss_val.y)
{
layer = 1;

if(-depthM > ss_val.z)
{
layer = 2;
}
}
}
//if(depthM > ss_val.w){layer = 3;}

return layer;
}
//--------------------------
float4 LayerThickness(in float3 m,
in float2 umvm,
in sampler2D sstm : register(s1)
)
{
float4 ss_val = tex2Dlod(sstm, float4(umvm.x, umvm.y, 0, 1));
return ss_val/4.0; //Divided by 4 because (1,0,0,0) = 1/4 red, (1, 1, 1, 1) = 0.25 + 0.25 + 0.25 + 0.25 = the full depth of 1
}
//--------------------------
float3 ReducedIntensity(in float3 p,
in float3 m,
in float3 lightdir,
in sampler2D sstm : register(s1),
in float3 normal,
in float2 umvm,
in float i,
in float3 PM_max,
in float2 upvp,
in float4 tangent,
in float4 binormal,
in float3 NSp,
in float3 diffuse,
in float num_samplesF
)
{
//L_ri(M, Omega_in)
float3 finalLightVector = float3(0, 0, 0);
float AttenuationKM = 1.0;
//Obtain a planar surface approximation for the current m depth [light and m in view space]
//light position - m
float3 omega_in = normalize(float3(0, 1, 0) - m);

float3 Nm = ((i*normal)+((num_samplesF - i)*NSp))/num_samplesF;
float3 Pm = ((i*PM_max) + ((num_samplesF - i)*p))/num_samplesF;
//Nm = normalize(Nm);
//Pm = normalize(Pm);

float cosTheta = cos(dot(Nm, omega_in));
//Calculate the distance ||KM||
float KM = length(dot((Pm*m),Nm))/cosTheta;
//Compute the thickness of the layers at the point M, lookup SSTM
float4 thicknessLayersM = LayerThickness(m, umvm, sstm);
//Compute the thickness of the layers at the point K
float3 K = m + (KM*-omega_in); //SWAPPED to go back up to K
float3 PK = K - p; //PK 0 first time round, p ad K are the same
float2 ukvk = (0,0);
ukvk.x = upvp.x + dot(PK, tangent.xyz);
ukvk.y = upvp.y + dot(PK, binormal.xyz);
//ukvk = normalize(ukvk);
float4 thicknessLayersK = LayerThickness(K, ukvk, sstm);
//Average thicknesses
float4 thicknessAverage = 0.5*(thicknessLayersM + thicknessLayersK);

float sigmaX = ((thicknessLayersM.x - thicknessLayersK.x)/2.0)/cosTheta;
float sigmaY = ((thicknessLayersM.y - thicknessLayersK.y)/2.0)/cosTheta;
float sigmaZ = ((thicknessLayersM.z - thicknessLayersK.z)/2.0)/cosTheta;
float sigmaW = ((thicknessLayersM.w - thicknessLayersK.w)/2.0)/cosTheta;
float sigmaTotal = sigmaX+sigmaY+sigmaZ+sigmaW;

float d1,d2,d3,d4;
d1 = min(KM - sigmaTotal, thicknessAverage.x/cosTheta);
d2 = min(KM - sigmaTotal, thicknessAverage.y/cosTheta);
d3 = min(KM - sigmaTotal, thicknessAverage.z/cosTheta);
d4 = min(KM - sigmaTotal, thicknessAverage.w/cosTheta);
//Calculate the attenuation along KM:
float att_1, att_2, att_3, att_4;
att_1 = exp(-2.6 * d1);
att_2 = exp(-6.6 * d2);
att_3 = exp(-1.5 * d3);
att_4 = exp(-1.0 * d4); //TODO: Make not HARD CODED! [img]http://public.gamedev.net//public/style_emoticons/default/ohmy.png[/img]
AttenuationKM = att_1*att_2*att_3*att_4;
//Estimate the reduced intensity, light position - k
float3 omega_in_k = float3(0, 1, 0) - K;
finalLightVector = omega_in_k*AttenuationKM;

return finalLightVector;
}
//--------------------------
float PhaseFunction(float g, float theta)
{
float pTheta = (1.0-(g*g))/4.0*3.14*(1.0+g*cos(theta))*(1.0+g*cos(theta));
return pTheta;
}
//--------------------------

/************ PIXEL SHADER ******************/

float4 pixel_shader(v2f IN,
uniform float specularPower,
uniform float4 ambient,
uniform float4 diffuse,
uniform float4 specular,
uniform sampler2D cm, //diffuse color map
uniform sampler2D sstm, //Subsurface Texture
uniform sampler1D matrix_tex, //Floating Point texture containing scattering coefficients
uniform sampler2D nm //Normal map, not needed
) : COLOR0
{
float3 p = IN.oPosition; //The pixel position in world space
float num_samplesF = 50.0f;
//Omega out is the view vector to the point
float3 omega_out = IN.eye; //The view vector in world space

//L(P, Omega_out) The lighting contribution vector from point P
float3 p_omega_out = float3(0,0,0);
float AttenuationPM = 1.0;
float Depth_max = 1.0;
float3 M_max = p - ((Depth_max/dot(IN.oNSp, omega_out))*omega_out);
float3 PM_max = M_max - p;
float3 PMstep = PM_max/num_samplesF;
float tan = dot(PM_max, IN.tangent.xyz);
float bi = dot(PM_max, IN.binormal.xyz);
float2 dsdt = float2(tan, bi); //normalize(IN.eye.xy);
float2 texCoordStep = float2(dsdt.x/num_samplesF, dsdt.y/num_samplesF);
float2 umvm = IN.texcoord.xy;
float depthM = 0;
float depthStep = dot(PMstep, IN.normal); //This needs to be a value between 0-1

float3 m = p; //M starts of as the point p and increases in depth

float theta = dot(IN.worldLightDir.xyz, omega_out);//The angle between the light vector and the eye vector
float currentLayer = 0;
float3 reducedIntensity;
float4 mScattering; //Check this
float4 currentLayerCoeffs_S, currentLayerCoeffs_T;
float currentLayerCoeffs_g; //RGBA = S-T-g-Blank
float3 myTest;

for(int i = 0; i < num_samplesF; i++)
{
float iF = i;
//Point M localization
currentLayer = FindLayer(depthM, umvm, sstm); //Returns a value between 0 and 3
//Estimate the reduced intensity - L_ri(M, omega_in)
reducedIntensity = ReducedIntensity(p, m, IN.worldLightDir.xyz, sstm, IN.normal.xyz, umvm,
iF, PM_max, IN.texcoord, IN.tangent, IN.binormal, IN.oNSp, diffuse, num_samplesF); //IMPLICIT CAST
//Estimate the single scattering at point M:
float3 coeffsPixel = float3(currentLayer/16.0, ((currentLayer+4.0)/16.0), ((currentLayer+8.0)/16.0)); //16 pixels in tex, divide by 16 for 0-1 tex space
currentLayerCoeffs_S = tex1Dlod(matrix_tex, float4(coeffsPixel.r, 0, 0, 1)); //0-3rd pixel
currentLayerCoeffs_T = tex1Dlod(matrix_tex, float4(coeffsPixel.g, 0, 0, 1)); //4-7th pixel range
currentLayerCoeffs_g = tex1Dlod(matrix_tex, float4(coeffsPixel.b, 0, 0, 1)); //8-11th pixel range -- only r component of this texel used

mScattering = currentLayerCoeffs_S * float4(reducedIntensity, 1.0) * PhaseFunction(currentLayerCoeffs_g.x, theta); //L_ri(M, omega_out)
//Attenuate the scattered radiance along PM and add the contribution of point M

p_omega_out += float3(mScattering * AttenuationPM * -PMstep);
//Move to the next sample M and compute its tex coords and attenuation
umvm.x += texCoordStep.x;
umvm.y += texCoordStep.y;
depthM += depthStep;
m += PMstep;
AttenuationPM *= exp(-currentLayerCoeffs_T*length(PMstep));
}
return color_mapping(IN, p_omega_out, ambient, diffuse, specular, specularPower, cm, sstm, nm);
}

///////////////////////////////////////
/// TECHNIQUES ////////////////////////
///////////////////////////////////////

technique SSTM <
string Script = "Pass=p0;";
> {
pass p0 <
string Script = "Draw=geometry;";
> {
VertexShader = compile vs_3_0 view_spaceVS(gWorldXf, gWvpXf);
ZEnable = true;
ZWriteEnable = true;
ZFunc = LessEqual;
AlphaBlendEnable = false;
CullMode = None;
PixelShader = compile ps_3_0 pixel_shader(
specularPower,
ambient,
diffuse,
specular,
cm,
sstm,
matrix_tex,
nm);
}
}
[/source]

The file is attached [url="https://dl.dropbox.com/u/4305049/SSTM.fx"]here[/url] as well because it's not really displaying properly here.

Share this post


Link to post
Share on other sites
Yeah should've mentioned that too sorry, I am certain that data is correct. This shader is actually being used in Ogre, and it's easy to generate the texture in Ogre and the output is virtually identical to fx composer. Each rgba component in the floating point texture just holds a preset scattering coefficient value taken from this table:
[img]http://img17.imageshack.us/img17/765/capturexv.png[/img]

Share this post


Link to post
Share on other sites
So I've been working on this a while longer, and the only real conclusion I have come up with is the colour values must be wrong. I thought for a while maybe they were right and I was not doing the correct thing with the result. I was given the good advice that:
[quote]The scattered radiance should be added to the phong radiance component because
the phong model computes the radiance at the surface only, the scattered radiance is
just more radiance coming from under the surface, to the eye. [/quote] So hopefully that might help some future googlers, now if if I could just work out the correct values to begin with! I knew the colours were too trippy [img]http://public.gamedev.net//public/style_emoticons/default/rolleyes.gif[/img]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this