Grozz

[HELP] MTA:SA Diffuse Lighting Shader

Recommended Posts

Hi! I just searched for lighting effects, and i found a shader for XNA. Its an Ambient and Diffuse lighting shader with Shadow Maps:

#define GENERATE_NORMALS
#include "mta-helper.fx"
//------------------------------------------------------------------------------
// File: BasicRender.fx
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------


//------------------------------------------------------------------------------
// Global variables
//------------------------------------------------------------------------------
float4 g_MaterialAmbientColor = {0.05f, 0.05f, 0.05f, 0.05f};      // Material's ambient color
float4 g_MaterialDiffuseColor = {0.75f, 0.75f, 0.75f, 0.75f};      // Material's diffuse color

float3 g_LightPos = {1000, 2000, 1000};					// Position of light
float3 g_LightDir = {0, 0, 0};					// Direction of light (temp)
float4x4 g_mLightView;				// View matrix of light
float4x4 g_mLightProj;				// Projection matrix of light

float4 g_LightDiffuse = {0.75f, 0.75f, 0.75f, 0.75f};			// Light's diffuse color
float4 g_LightAmbient = {0.05f, 0.05f, 0.05f, 0.05f};             // Light's ambient color

texture g_MeshTexture;              // Color texture for mesh
texture g_ShadowMapTexture;			// Shadow map texture for lighting

float4x4 g_mWorld;                  // World matrix for object
float3 g_CameraPos;				    // Camera position for scene View 
float4x4 g_mCameraView;				// Camera's view matrix
float4x4 g_mCameraProj;				// Projection matrix


//------------------------------------------------------------------------------
// Texture samplers
//------------------------------------------------------------------------------
sampler MeshTextureSampler = 
sampler_state
{
    Texture = (gTexture0);
    MipFilter = LINEAR;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
};
sampler ShadowMapSampler =
sampler_state
{
	Texture = <g_ShadowMapTexture>;
    MinFilter = POINT;
    MagFilter = POINT;
    MipFilter = POINT;
    AddressU = Clamp;
    AddressV = Clamp;
};

//------------------------------------------------------------------------------
// Vertex shader output structure
//------------------------------------------------------------------------------
struct VS_OUTPUT
{
    float4 Position   : POSITION0;   // vertex position 
    float2 TextureUV  : TEXCOORD0;  // vertex texture coords   
    float3 vNormal	  : TEXCOORD1;
    float4 vPos       : TEXCOORD2;  
};
struct PS_INPUT
{
    float2 TextureUV  : TEXCOORD0;  // vertex texture coords   
    float3 vNormal	  : TEXCOORD1;
    float4 vPos       : TEXCOORD2;  
};
struct VS_SHADOW_OUTPUT
{
	float4 Position : POSITION;
	float Depth : TEXCOORD0;
};
//------------------------------------------------------------------------------
// Utility function(s)
//------------------------------------------------------------------------------
float4x4 CreateLookAt(float3 gView, float3 gProjection, float3 up)
{
	float3 zaxis = normalize(gView - gProjection);
	float3 xaxis = normalize(cross(up, zaxis));
	float3 yaxis = cross(zaxis, xaxis);
	
	float4x4 view = { xaxis.x, yaxis.x, zaxis.x, 0,
		xaxis.y, yaxis.y, zaxis.y, 0,
		xaxis.z, yaxis.z, zaxis.z, 0,
		-dot(xaxis, gView), -dot(yaxis, gView),
		-dot(zaxis, gView), 1
	};

	return view;
}
float4 GetPositionFromLight(float4 position)
{
	float4x4 WorldViewProjection =
	 mul(mul(gWorld, gLightDiffuse), gLightDirection);
	return mul(position, WorldViewProjection);  
}
//------------------------------------------------------------------------------
// This shader computes rudimentary transform and lighting.
// The XNA VertexDeclaration of our models is PositionNormalTexture.
//------------------------------------------------------------------------------

VS_OUTPUT RenderShadowsVS(
     float3 position : POSITION,
     float3 normal : NORMAL,
     float2 vTexCoord0 : TEXCOORD0 )
{
     VS_OUTPUT Output;

     //generate the world-view-projection matrix
     float4x4 wvp = mul(mul(gWorld, gView), gProjection);
     
     //transform the input position to the output
     Output.Position = mul(float4(position, 1.0), wvp);

	 //transform the normal to world space
     Output.vNormal =  mul(normal, gWorld);
     
     //do not transform the position needed for the
     //shadow map determination
     Output.vPos = float4(position,1.0);
     
     //pass the texture coordinate as-is
	 Output.TextureUV = vTexCoord0;
    
     //return the output structure
     return Output;
}

VS_SHADOW_OUTPUT RenderShadowMapVS(float4 vPos: POSITION)
{
	VS_SHADOW_OUTPUT Out;
	Out.Position = GetPositionFromLight(vPos); 
	// Depth is Z/W.  This is returned by the pixel shader.
	// Subtracting from 1 gives us more precision in floating point.
	Out.Depth.x = 1-(Out.Position.z/Out.Position.w);	
	return Out;
}

//------------------------------------------------------------------------------
// Pixel shader output structure
//------------------------------------------------------------------------------
struct PS_OUTPUT
{
    float4 RGBColor : COLOR0;  // Pixel color    
};


//------------------------------------------------------------------------------
// This shader outputs the pixel's color by modulating the texture's
//       color with diffuse material color
//------------------------------------------------------------------------------

PS_OUTPUT RenderShadowsPS( PS_INPUT In ) 
{ 
    PS_OUTPUT Output;
    
    // Standard lighting equation
    float4 vTotalLightDiffuse = float4(0.1f,0.1f,0.1f,0.1f);
    float3 lightDir = normalize(g_LightPos+In.vPos);  // direction of light
    vTotalLightDiffuse += g_LightDiffuse * max(0,dot(In.vNormal, lightDir)); 
    vTotalLightDiffuse.a = 0.5f;
	// Now, consult the ShadowMap to see if we're in shadow
    float4 lightingPosition 
		= GetPositionFromLight(In.vPos);// Get our position on the shadow map
   
    // Get the shadow map depth value for this pixel   
    float2 ShadowTexC = 
		0.5 * lightingPosition.xy / lightingPosition.w + float2( 0.5, 0.5 );
    ShadowTexC.y = 1.0f - ShadowTexC.y;

    float shadowdepth = tex2D(ShadowMapSampler, ShadowTexC).r;    
    
    // Check our value against the depth value
    float ourdepth = 1 + (lightingPosition.z / lightingPosition.w);
    
    // Check the shadowdepth against the depth of this pixel
    // a fudge factor is added to account for floating-point error
	if (shadowdepth-0.03 > ourdepth)
	{
	    // we're in shadow, cut the light
		vTotalLightDiffuse = float4(0,0,0,1);
	};

    Output.RGBColor = tex2D(MeshTextureSampler, In.TextureUV) * 
		(vTotalLightDiffuse + g_LightAmbient);
        
    return Output;
    
}
PS_OUTPUT DiffuseOnlyPS(VS_OUTPUT In) : COLOR
{
	 PS_OUTPUT Output;
     //calculate per-pixel diffuse
     float3 directionToLight = normalize(g_LightPos - In.vPos);
     float diffuseIntensity = saturate( dot(directionToLight, In.vNormal));
     float4 diffuse = g_LightDiffuse * diffuseIntensity;
     
     float4 color = diffuse + g_LightAmbient;
     color.a = 0.0;
     
     Output.RGBColor = tex2D(MeshTextureSampler, In.TextureUV) * color;
     
     return Output;
}
PS_OUTPUT TextureOnlyPS(float2 TextureUV  : TEXCOORD0) : COLOR
{
     PS_OUTPUT Output;
     Output.RGBColor = tex2D(MeshTextureSampler, TextureUV);
     
     return Output;
}
float4 RenderShadowMapPS( VS_SHADOW_OUTPUT In ) : COLOR
{ 
	// The depth is Z divided by W. We return
	// this value entirely in a 32-bit red channel
	// using SurfaceFormat.Single.  This preserves the
	// floating-point data for finer detail.
    return float4(In.Depth.x,0,0,1);
}
//------------------------------------------------------------------------------
// Renders scene to render target
//------------------------------------------------------------------------------
technique TextureRender
{
	pass P0
	{
        VertexShader = compile vs_2_0 RenderShadowsVS();
        PixelShader  = compile ps_2_0 TextureOnlyPS(); 
		
	}
	pass P1
	{
        VertexShader = compile vs_2_0 RenderShadowsVS();
        PixelShader  = compile ps_2_0 RenderShadowsPS(); 
	}
	pass P2
	{
		// These render states are necessary to get a shadow map.
		// You should consider resetting CullMode and AlphaBlendEnable
		// before you render your main scene.	
		CullMode = CW;
		ZEnable = TRUE;
		ZWriteEnable = TRUE;
		AlphaBlendEnable = TRUE;
		
        VertexShader = compile vs_2_0 RenderShadowMapVS();
        PixelShader  = compile ps_2_0 RenderShadowMapPS();
	
	}
}

This is not the original .fx file, i configured it for MTA. The diffuse and the ambient light works correctly, but not generating shadows. Any Idea?

Share this post


Link to post

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

  • Recently Browsing   0 members

    No registered users viewing this page.