Fur Shader New

From GameStudio Wiki

Jump to: navigation, search

FIXME!!

Fur Shader for Directx9 (vs 1.1 ,ps 1.4) - tested on terrains


As discussed in this thread, URL, the old fur shader on this Wiki doesn't work with DirectX9, with great help from ello and others, here's a new fur shader. It extrudes the model vertices 5 times along the normal and renders the pixels using an alpha-mapped texture. Requires two textures that get multiplied together and one red channel texture that specifies the alpha value.

In my case I wanted to use a fur shader for a terrain, so I will explain it using a terrain. To make sure everyone will be able to implement it, i've written it in a more tutorial way, I hope it's not chaotic, anyways just follow the steps below;

1)Add this to your project's MAIN function

include <terrainshdrFUR.wdl>; // in this wdl, which we are going to make next, are all the functions for the shader

load_fur_fx(); // put this in your game's MAIN function, it'll call a function in the wdl mentioned earlier, and loads the shader

Ok, I like to keep things organised so I've put those shaderrelated code in a new wdl; Put this in a new wdl file, and save as for example terrainshdrFUR.wdl ;) terrainshdrFUR.wdl Code:

// terrainshdrFUR.wdl
// the next three textures are a bit mixed-up name-wise, maybe I'll change this later

bmap bmp_fur=<fur.tga>;  //the furmap, choose a name you like
bmap bmp_base=<tropical_tex.tga>;  // your terrain's basic skin
bmap bmp_color=<fur2.tga>;    //

// Next are the functions for the basic setup, define the materials
function mtl_fur_init
{
    // first_shell_brightness, you may want to experiment with these value a lot
    mtl.skill1=float(0.00006);          
    mtl.skill2=float(0.000005); // brightness_increment
    bmap_to_mipmap(mtl.skin1);
}

//Define the skins's material this way;
material mtl_fur 
{
        event=mtl_fur_init;
        skin1=bmp_fur; // skin1 is the fur texture
        skin2=bmp_base; //skin2 is the noise texture
        skin3=bmp_color;//skin3 is the actual skin of in my case the terrain
        effect = <terrainshdrFUR.fx>; //this points to another file, but I'll come to that later
}

//this is the actual function that starts loading the shader, 
// don't forget to call it in your MAIN function
function load_fur_fx() 
{
    //checks if your system is at least capable of handling 
    //vertex shader (vs) 1.1 and pixel shader (ps) 1.1 or higher versions
    if (d3d_shaderversion >= 1111)
    {
	effect_load(mtl_fur,"terrainshdrFUR.fx");
	return;
    } else {
	exit;
    }
}

//attach this action to your model or terrain for the fur effect
action fur 
{
        my.skill41=float(0.6); // shell_distance
        my.skill43=float(10);   // fur_u_scale
        my.skill44=float(10);   // fur_v_scale
        my.material=mtl_fur;
}

Next thing to do is put the next lines of code in a new file and save it as 'terrainshdrFUR.fx'

TerrainshdrFUR.fx Code:

  float4x4 matWorldViewProj;
  
  // This is the Vertex shader, most info comes from GameStudio and DirectX
  // except for the (shell) offset value which is specified in the various
  // passes later on
  // All it does is move the vertex position along the triangle normal
  void mainVS(in float4 position:POSITION,
         in float4 normal:NORMAL,
         in float2 texCoord:TEXCOORD0,
         out float4 pos:POSITION,
         out float4 nrm:COLOR0,
         out float2 oT0:TEXCOORD0,
       uniform float offset  )
  {
              //scale vertexposition in normals direction
	      position.xyz+=normal.xyz*offset/100;
              // from world pos to screen pos
	      pos=mul(position,matWorldViewProj);
	      nrm=normal;
	      oT0=texCoord*1;               //this is the amount of tiling of the fur texture
  }

//Define the material skins which we use;
texture mtlSkin1;
sampler basemap = sampler_state
{
	texture=(mtlSkin1);
};

texture mtlSkin2;
sampler noiseMap=sampler_state
{
	texture=(mtlSkin2);
};

texture mtlSkin3;
sampler furmap = sampler_state
{
	texture=(mtlSkin3);
};


// Next the main pixel shader. nrm & texcoord come from the Vertex Shader, 
// alpha is set in the function calls later on
float4 mainPS(
          in float4 nrm:COLOR0,
          in float2 texCoord:TEXCOORD0,
       uniform float alpha) : COLOR
{
	float4 base=tex2D(basemap,texCoord); //mtlskin1 sampler
        float4 fur=tex2D(furmap,texCoord); //mtlskin2 sampler
	float4 result=fur*base; //this is for color fur

        // use Red channel in noisemap texture to modulate transparency
	float4 noise=tex2D(noiseMap,texCoord);
        result.a=alpha*noise.r; 
	return noise;
}

// Through these passes, the amount of fur-layers are determined, 
// the more passes, the less fps (and even a changing effect, too much contrast)
technique test1
{
	pass p0
	{
		VertexShader=compile vs_1_1 mainVS(1); // 1% offset
		PixelShader=compile ps_1_4 mainPS(1);  // 1% transparency
	}
        //fur part:
	pass p0
	{
		CullMode=0;
		AlphaBlendEnable=1;
		BlendOp=1;
		srcBlend=3; // '1/2/3' play with these values to see what it does
		destBlend=7; // '3/5/7/9/11' just play with these numbers a bitrenderstates
		VertexShader=compile vs_1_1 mainVS(301.9); // 300 % offset
		PixelShader=compile ps_1_4 mainPS(300.9);  // 300 % alpha
	}
	pass p0
	{
        AlphaBlendEnable=1;
	destBlend=13;
	VertexShader=compile vs_1_1 mainVS(101);
	PixelShader=compile ps_1_4 mainPS(100.9);
	}
	pass p0
	{
	AlphaBlendEnable=1;
	destBlend=11; //7/9
	srcBlend=3;
	VertexShader=compile vs_1_1 mainVS(91);
	PixelShader=compile ps_1_4 mainPS(80.9);
	}
	pass p0
	{
	AlphaBlendEnable=1;
	destBlend=7;
 	VertexShader=compile vs_1_1 mainVS(200);
	PixelShader=compile ps_1_4 mainPS(99.9);
	}
}

Written by: Erik Franken aka PHeMoX 5/8/05 ---I guess someone couldn't stand the chaos ;) Thanks for making it more organised!---

Personal tools