bate's blog

調べたこと実装したことなどを取りとめもなく書きます。

FXComposer超入門11

ディファードレンダリングとかディファードシェーディングとかいうやつをしてみる。


1.シーンに板と球とトーラスを追加する。
2.下の絵1のようになる。

3.[Effects]にある[DefaultEffect]と[Materials]にある[DefaultMaterial]を削除する。
4.[Effects]に空のCgFXを追加する。
5.下のコード1を追加したCgFXにコピペする。

/*

% Description of my shader.
% Second line of description for my shader.

keywords: material classic

date: YYMMDD

*/


//------------------------------------------
// Script
//------------------------------------------
float Script : STANDARDSGLOBAL
<
	string UIWidget = "none";
	string ScriptClass = "scene";
	string ScriptOrder = "standard";
	string ScriptOutput = "color";
	string Script = "Technique=DeferredRendering;";
> = 0.8;


//-------------------------------------------
// Global variable : Transform
//-------------------------------------------
float4x4 gWVP		: WorldViewProjection <string UIWidget="none";>;
float4x4 gWorld		: World <string UIWidget="none";>;
float4x4 gView		: View <string UIWidget="none";>;
float4x4 gProj		: Projection <string UIWidget="none";>;

//--------------------------------------------
// Global variable : Camera
//--------------------------------------------
float4 gCameraPosition : POSITION
<
	string UIWidget = "float";
	string UIName = "Camera Pos";
	string Object = "PerspectiveCamera";
	string Space = "World";
> = { 10, 10, 10, 1 };

//--------------------------------------------
// Global variable
//--------------------------------------------

// light info
#define LIGHT_NUM (3)

struct LightInfomation
{
	float4 WorldPosition;
	float4 Color;
};

LightInfomation gLight[LIGHT_NUM] =
{
	{ float4(0,0,30,1), float4(1,0,0,1) },
	{ float4(0,30,0,1), float4(0,1,0,1) },
	{ float4(30,0,0,1), float4(0,0,1,1) }
};

float4 ClearColor
<
	string UIWidget = "color";
	string UIName = "Clear Color";
> = { 0.0, 0.0, 0.0, 1.f };

float ClearDepth
<
	string UIWidget = "none";
> = 1.0;

float2 ViewportSize : VIEWPORTPIXELSIZE
<
	string UIWidget = "none";
	string UIName = "Screen Size";
>;


//--------------------------------------
// texture and sampler
//--------------------------------------

// Final Image
texture FinalScreen : RENDERCOLORTARGET
<
	float2 ViewPortRatio = { 1.0, 1.0};
	int MipLevels = 1;
	string Format = "X8R8G8B8";
	string UIWidget = "none";
>;

sampler2D FinalScreenSampler = sampler_state
{
	texture = <FinalScreen>;
	WrapS = ClampToEdge;
	WrapT = ClampToEdge;
	MinFilter = Linear;
	MagFilter = Linear;
};

// Final ZBuffer
texture FinalZBuffer : RENDERDEPTHSTENCILTARGET
<
	float2 ViewPortRatio = { 1.0, 1.0 };
	int MipLevels = 1;
	string Format = "D24S8";
	string UIWidget = "none";
>;

sampler2D FinalZBufferSampler = sampler_state
{
	texture = <FinalZBuffer>;
	WrapS = ClampToEdge;
	WrapT = ClampToEdge;
	MinFilter = Linear;
	MagFilter = Linear;
};

// Final Image
texture TemporaryScreen : RENDERCOLORTARGET
<
	float2 ViewPortRatio = { 1.0, 1.0};
	int MipLevels = 1;
	string Format = "X8R8G8B8";
	string UIWidget = "none";
>;

sampler2D TemporaryScreenSampler = sampler_state
{
	texture = <TemporaryScreen>;
	WrapS = ClampToEdge;
	WrapT = ClampToEdge;
	MinFilter = Linear;
	MagFilter = Linear;
};

// Position GBuffer
texture PositionGBuffer : RENDERCOLORTARGET
<
	float2 ViewPortRatio = { 1.0, 1.0};
	int MipLevels = 1;
	string Format = "X8R8G8B8";
	string UIWidget = "none";
>;

sampler2D PositionGBufferSampler = sampler_state
{
	texture = <PositionGBuffer>;
	WrapS = ClampToEdge;
	WrapT = ClampToEdge;
	MinFilter = Linear;
	MagFilter = Linear;
};

// Normal GBuffer
texture NormalGBuffer : RENDERCOLORTARGET
<
	float2 ViewPortRatio = { 1.0, 1.0};
	int MipLevels = 1;
	string Format = "X8R8G8B8";
	string UIWidget = "none";
>;

sampler2D NormalGBufferSampler = sampler_state
{
	texture = <NormalGBuffer>;
	WrapS = ClampToEdge;
	WrapT = ClampToEdge;
	MinFilter = Linear;
	MagFilter = Linear;
};

// Diffuse GBuffer
texture DiffuseGBuffer : RENDERCOLORTARGET
<
	float2 ViewPortRatio = { 1.0, 1.0};
	int MipLevels = 1;
	string Format = "X8R8G8B8";
	string UIWidget = "none";
>;

sampler2D DiffuseGBufferSampler = sampler_state
{
	texture = <DiffuseGBuffer>;
	WrapS = ClampToEdge;
	WrapT = ClampToEdge;
	MinFilter = Linear;
	MagFilter = Linear;
};

// Depth GBuffer
texture DepthGBuffer : RENDERDEPTHSTENCILTARGET
<
	float2 ViewPortRatio = { 1.0, 1.0};
	int MipLevels = 1;
	string Format = "D24S8";
	string UIWidget = "none";
>;

sampler2D DepthGBufferSampler = sampler_state
{
	texture = <DepthGBuffer>;
	WrapS = ClampToEdge;
	WrapT = ClampToEdge;
	MinFilter = Linear;
	MagFilter = Linear;
};



//--------------------------------------
// structure
//--------------------------------------

//-------------------------
// GBuffer

// input
struct GBufferInput
{
	float4 Position		: POSITION;
	float2 TexCoord		: TEXCOORD0;
	float3 Normal		: NORMAL;
};

// vertex to pixel
struct GBufferV2P
{
	float4 Position			: POSITION;
	float2 TexCoord			: TEXCOORD0;
	float4 ViewPosition		: TEXCOORD1;
	float3 ViewNormal		: TEXCOORD2;
	float4 DiffuseColor		: TEXCOORD3;
};

// output
struct GBufferOutput
{
	float4 Position			: COLOR0;
	float4 Normal			: COLOR1;
	float4 DiffuseAlbedo	: COLOR2;
};

//------------------------
// Lighting

// input
struct LightingInput
{
	float4 Position	: POSITION;
	float2 TexCoord	: TEXCOORD0;
};

// vertex to pixel
struct LightingV2P
{
	float4 Position	: POSITION;
	float2 TexCoord	: TEXCOORD0;
};

//------------------------
// make Screen

// input
struct ScreenInput
{
	float4 Position	: POSITION;
	float2 TexCoord	: TEXCOORD0;
};

// vertex to pixel
struct ScreenV2P
{
	float4 Position	: POSITION;
	float2 TexCoord	: TEXCOORD0;
};


//--------------------------------------
// GBuffer pass
//--------------------------------------
GBufferV2P GBufferVS(GBufferInput IN)
{
	GBufferV2P OUT = (GBufferV2P)0;
	
	float4 world_position = mul(gWorld, IN.Position);
	float4 view_position = mul(gView, world_position);
	float4 proj_position = mul(gProj, view_position);
	
	float3 world_normal = mul((float3x3)gWorld, IN.Normal);
	float3 view_normal = mul((float3x3)gView, world_normal);
	
	OUT.Position = proj_position;
	OUT.TexCoord = IN.TexCoord;
	OUT.ViewNormal = view_normal;
	OUT.ViewPosition = view_position;
	OUT.DiffuseColor = float4(1.0,1.0,1.0,1.0);
	
	return OUT;
}

GBufferOutput GBufferPS(GBufferV2P IN)
{
	GBufferOutput OUT = (GBufferOutput)0;
	
	//float depth = IN.ViewPosition.z/IN.ViewPosition.w;
	
	// convert from [-1,1] to [0,1]
	float3 normal = normalize( IN.ViewNormal ) * 0.5 + 0.5;
	
	OUT.Position = IN.ViewPosition;
	OUT.Normal = float4(normal, 1.0);
	OUT.DiffuseAlbedo = IN.DiffuseColor;
	
	return OUT;
}

//---------------------------------------
// Lighting pass
//---------------------------------------
LightingV2P LightingVS(LightingInput IN)
{
	LightingV2P OUT = (LightingV2P)0;
	OUT.Position = float4(IN.Position.xyz,1);
	OUT.TexCoord = float2(IN.TexCoord.xy);
	
	return OUT;
}

float4 LightingPS(LightingV2P IN) : COLOR0
{
	float3 view_position = tex2D( PositionGBufferSampler, IN.TexCoord).rgb;
	float3 view_normal = float3(0,0,0);
	
	float4 normal = tex2D( NormalGBufferSampler, IN.TexCoord );
	// convert from [0,1] to [-1,1]
	view_normal = normal.rgb * 2.0 - 1.0;
	float4(view_normal,1);
	
	float4 depth = tex2D( DepthGBufferSampler, IN.TexCoord );
	
	float4 color = float4(0,0,0,0);
	float3 view_camera_pos = mul((float3x3)gView, gCameraPosition.xyz);
	float3 eye_direction = normalize( view_camera_pos - view_position );
	float4 diffuse = tex2D( DiffuseGBufferSampler, IN.TexCoord );
	
	for(int i = 0; i < LIGHT_NUM; ++i)
	{
		float3 light_direction = mul((float3x3)gView,gLight[i].WorldPosition.xyz) - view_position;
		float3 L = normalize( light_direction );
		float attenuation = 1.f/length( light_direction );
		//color.rgb += attenuation * gLight[i].Color.rgb * diffuse.rgb * max( dot( L, world_normal ), 0 );
		color.rgb += gLight[i].Color.rgb * diffuse.rgb * max( dot( L, view_normal ), 0 );
		color.a = 1.0;
	}
	
	return color;
}


//---------------------------------------
// make Screen
//---------------------------------------
ScreenV2P ScreenVS(ScreenInput IN)
{
	ScreenV2P OUT = (ScreenV2P)0;
	OUT.Position = float4(IN.Position.xyz,1);
	OUT.TexCoord = float2(IN.TexCoord.xy);
	
	return OUT;
}

float4 ScreenPS(ScreenV2P IN) : COLOR0
{
	return tex2D(TemporaryScreenSampler, IN.TexCoord);
}


//----------------------------------------
// Deferred Rendering technique
//----------------------------------------
technique DeferredRendering
<
	string Script =
		"RenderColorTarget0=FinalScreen;"
		"RenderColorTarget1=;"
		"RenderColorTarget2=;"
		"RenderDepthStencilTarget=FinalZBuffer;"
			"ClearSetColor=ClearColor;"
			"ClearSetDepth=ClearDepth;"
			"Clear=Color;"
			"Clear=Depth;"
			"ScriptExternal=color;"
		"Pass=GBuffer;"
		"Pass=Lighting;"
		"Pass=Screen";
>
{
	pass GBuffer
	<
		string Script =
			"RenderColorTarget0=PositionGBuffer;"
			"RenderColorTarget1=NormalGBuffer;"
			"RenderColorTarget2=DiffuseGBuffer;"
			"RenderDepthStencilTarget=DepthGBuffer;"
			"ClearSetColor=ClearColor;"
			"ClearSetDepth=ClearDepth;"
			"Clear=Color;"
			"Clear=Depth;"
			"Draw=Geometry;";
	>
	{
		CullFaceEnable = true;
		ZEnable = true;
		ZWriteEnable = true;
		DepthTestEnable = true;
		DepthFunc = Less;
		DepthMask = true;
		BlendEnable = false;
		VertexProgram = compile vp40 GBufferVS();
		FragmentProgram = compile fp40 GBufferPS();
	}
	pass Lighting
	<
		string Script =
			"RenderColorTarget0=TemporaryScreen;"
			"RenderColorTarget1=;"
			"RenderColorTarget2=;"
			"RenderDepthStencilTarget=;"
			"ClearSetColor=ClearColor;"
			"ClearSetDepth=ClearDepth;"
			"Clear=Color;"
			"Clear=Depth;"
			"Draw=Buffer";
	>
	{
		ZEnable = false;
		DepthTestEnable = false;
		DepthMask = false;
		ZWriteEnable = false;
		CullFaceEnable = false;
		BlendEnable = false;
		DepthFunc = LEqual;
		
		VertexProgram = compile vp40 LightingVS();
		FragmentProgram = compile fp40 LightingPS();
	}
	
	pass Screen
	<
		string Script =
			"RenderColorTarget0=;"
			"RenderColorTarget1=;"
			"RenderColorTarget2=;"
			"RenderDepthStencilTarget=;"
			"ClearSetColor=ClearColor;"
			"ClearSetDepth=ClearDepth;"
			"Clear=Color;"
			"Clear=Depth;"
			"Draw=Buffer";
	>
	{
		ZEnable = false;
		DepthTestEnable = false;
		DepthMask = false;
		ZWriteEnable = false;
		CullFaceEnable = false;
		BlendEnable = false;
		DepthFunc = LEqual;
		
		VertexProgram = compile vp40 ScreenVS();
		FragmentProgram = compile fp40 ScreenPS();
	}
}

6.下の絵2のようになることを確認する。

7.おしまい。