MySpace


Oliver

Oliver Pavicevic


Last Updated: 4/5/2009

Send Message
Instant Message
Email to a Friend
Subscribe

Gender: Male
Status: Engaged
Age: 35
Sign: Gemini

City: Milano
Country: IT
Signup Date: 3/9/2006
Wednesday, March 29, 2006 12:26 PM

Current mood:  accomplished
Category: Games

Per rendere la iluminazione delle nuvole piu convincente avevo il bisogno di un HLSL shader capace di simulare il Subsurface Scattering. Questo shader e alla fine molto semplice. Un bel esempio come si possono ottenere effetti convincenti con poche risorse.

 

Il video: VIDEO DIVX

In order to render the illumination of clouds more convincing I had a need of an HLSL shader able to simulate the Subsurface Scattering.  This shader is quite simple.  A beautiful example how a convincing effects can be obtained with a little resources.

 

Here you can find a complete shader code in HLSL (this shader is Virtools ready, in other programs you will probably have to change some lines):

 

//Subsurface scattering shader by Oliver Pavicevic (olix@iol.it)

.r{}************ TWEAKABLES **************/

 

 

half4 surfColor : Diffuse = {1.0f, 1.0f, 1.0f, 1.0f};

texture colorTexture : Texture;

 

.r{}************* light info **************/

half3 light1Pos <string type="entity3d";> = {100.0f, 100.0f, 100.0f};

half4 light1Color = { 1.0f, 1.0f, 1.0f, 0.0f };

 

half4x4 wvp : WorldViewProjection < string UIWidget = "None"; >;

half4x4 worldI : WorldInverse < string UIWidget = "None"; >;

half4x4 viewInvTrans : ViewInverse < string UIWidget = "None"; >;

 

half attenuation1 <

string UIWidget = "slider";

float UIMin = 0;

float UIMax = 1000;

string UIName = "close attenuation";

> = 100;

half attenuation2 <

string UIWidget = "slider";

float UIMin = 0;

float UIMax = 128;

string UIName = "medium attenuation";

> = 10;

half attenuation3 <

string UIWidget = "slider";

float UIMin = 0;

float UIMax = 1;

string UIName = "far attenuation";

> = 0.3;

.r{}***************************************************/

.r{}********* HLSL SHADER FUNCTIONS *********************/

.r{}***************************************************/

// input from application

struct a2v {

half4 position : POSITION;

half2 texCoord : TEXCOORD0;

half3 tangent : TEXCOORD1;

half3 binormal : TEXCOORD2;

half3 normal : NORMAL;

};

// output to fragment program

struct v2f {

half4 position : POSITION;

half2 texCoord : TEXCOORD0;

half3 lightVec : TEXCOORD2;

};

// blinn lighting with lit function

half4 blinn2(half3 N,

half3 L,

half3 V,

uniform half4 diffuseColor,

uniform half4 specularColor,

uniform half shininess

)

{

half3 H = normalize(V L);

half4 lighting = lit(dot(L,N), dot(H,N),0);

return diffuseColor*lighting.y ;

}

.r{}*************************************/

.r{}**** VERTEX SHADER ******************/

.r{}*************************************/

v2f v(a2v In,

uniform half4x4 worldViewProj, // object to clip space

uniform half4x4 WorldIMatrix, //world to object space

uniform half4 lightPosition,

uniform half4x4 ViewInvTrans )

{

v2f Out;

// transform vertex position to homogeneous clip space

Out.position = mul(In.position, worldViewProj);

//pass texture coordinates

Out.texCoord = In.texCoord;

// compute the 3x3 tranform from tangent space to object space

half3x3 objTangentXf;

objTangentXf[0] = In.tangent.xyz;

objTangentXf[1] = In.binormal.xyz;

objTangentXf[2] = In.normal.xyz;

//put the world space light position in object space

half4 objSpaceLightPos = mul(lightPosition, WorldIMatrix);

half3 objLightVec = objSpaceLightPos.xyz - In.position.xyz;

// xform light vector from obj space to tangent space

Out.lightVec = mul(objTangentXf, objLightVec );

//compute the eye vector in world space and put it in object space

half4 objSpaceEyePos = mul(ViewInvTrans[3], WorldIMatrix);

 

return Out;

}

.r{}*************************************/

.r{}**** FRAGMENT PROGRAM ***************/

.r{}*************************************/

float4 f(v2f In,

uniform sampler2D colorTex,

uniform half4 diffuseColor,

uniform half4 light1Color,

uniform half attenuation1,

uniform half attenuation2,

uniform half attenuation3

) : COLOR

{

//fetch the diffuse map

half4 colorMap = tex2D(colorTex, In.texCoord.xy);

//calculate attenuation

half d = length(In.lightVec);

half attenuation = 1 / ((attenuation1) (attenuation2 * d) (attenuation3 * d * d));;

 

//Subsurface Scattering

half4 SS = (light1Color*1200) * blinn2(1, 0.02, 0, colorMap*diffuseColor, colorMap.a, 0) * attenuation;

return SS;

}

.r{}***************************************************/

.r{}********* SAMPLERS ********************************/

.r{}***************************************************/

sampler2D colorTextureSampler = sampler_state

{

Texture = ;

MinFilter = Linear;

MagFilter = Linear;

MipFilter = Linear;

};

 

 

.r{}***************************************************/

.r{}********* TECHNIQUES ******************************/

.r{}***************************************************/

technique Complete

{

pass envPass

{

VertexShader = compile vs_1_1 v(wvp,worldI,half4(light1Pos,1),viewInvTrans);

ZEnable = true;

ZWriteEnable = true;

//CullMode = CW;

PixelShader = compile ps_2_0 f(colorTextureSampler,surfColor,light1Color,attenuation1,attenuation2,attenuation3);

}

}

 

Patrick

 
Beautiful effect man, thanks for posting the shader code(although the syntax highlighting makes it look like a christmass tree :P)
 
Posted by Patrick on Thursday, March 30, 2006 - 11:46 AM
[Reply to this