Woops sorry, I've gotten so deep into this thing I'm just assuming the whole world knows what I mean by

p_omega_out . 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.

When I say

p_omega_out, 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

this map as the subsurface texture map.

[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 Lightfloat4 ambient : AMBIENT < string UIName = "Ambient Light Color"; string UIWidget = "Color";> = {0.7f,0.7f,0.7f,1.0f};// surface colorfloat4 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 = 1if(-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 - mfloat3 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 SSTMfloat4 thicknessLayersM = LayerThickness(m, umvm, sstm);//Compute the thickness of the layers at the point Kfloat3 K = m + (KM*-omega_in); //SWAPPED to go back up to Kfloat3 PK = K - p; //PK 0 first time round, p ad K are the samefloat2 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 thicknessesfloat4 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 - kfloat3 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 spacefloat num_samplesF = 50.0f;//Omega out is the view vector to the pointfloat3 omega_out = IN.eye; //The view vector in world space//L(P, Omega_out) The lighting contribution vector from point Pfloat3 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-1float3 m = p; //M starts of as the point p and increases in depthfloat theta = dot(IN.worldLightDir.xyz, omega_out);//The angle between the light vector and the eye vectorfloat currentLayer = 0;float3 reducedIntensity;float4 mScattering; //Check thisfloat4 currentLayerCoeffs_S, currentLayerCoeffs_T;float currentLayerCoeffs_g; //RGBA = S-T-g-Blankfloat3 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

here as well because it's not really displaying properly here.