# Why can't I transform the light to the opposite direction in HLSL

9 replies to this topic

### #1jack33

New Member

• Members
• 5 posts

Posted 15 January 2006 - 01:56 PM

The following is my hlsl codes. When I set the 'lightDir' as { 1.0f, 0.0f, 0.0f }, I got a light from right. I want to try to make the light come from left, I set the 'lightDir' as { -1.0f, 0.0f, 0.0f }, but I got a totally black object. Why? And How can I reach my objective.

// diffuse.fx
float4x4 matWorldViewProj : WORLDVIEWPROJECTION;
float4x4 matWorld : WORLD;

struct VS_OUTPUT
{
float4 Pos : POSITION;
float3 Light : TEXCOORD0;
float3 Norm : TEXCOORD1;
};

VS_OUTPUT VS(float4 Pos : POSITION, float3 Normal : NORMAL)
{
VS_OUTPUT Out = (VS_OUTPUT)0;
float3 lightDir = { -1.0f, -1.0f, 0.0f };
Out.Pos = mul(Pos, matWorldViewProj); // transform Position
Out.Light = normalize(lightDir); // output light vector
Out.Norm = normalize(mul(Normal, matWorld)); // transform Normal and normalize it
return Out;
}

float4 PS(float3 Light: TEXCOORD0, float3 Norm : TEXCOORD1) : COLOR
{
float4 diffuse = { 1.0f, 1.0f, 1.0f, 1.0f};
float4 ambient = { 0.0, 0.1, 0.0, 1.0 };
return ambient + float4(diffuse.xyz * saturate(dot(Light, Norm)), 1.0f);
}

technique Diffuse
{
pass P0
{
}
}

### #2chot

New Member

• Members
• 28 posts

Posted 15 January 2006 - 10:52 PM

Not sure, but try replacing saturate(dot(Light, Norm)) with max(dot(Light, Norm), 0)

### #3jack33

New Member

• Members
• 5 posts

Posted 16 January 2006 - 04:03 AM

Thank you! But I tried another hlsl code, and it worked. It seems that ps_2_0 should be used. Do you have any idea about the significant difference here?

### #4chot

New Member

• Members
• 28 posts

Posted 16 January 2006 - 11:59 AM

No sorry, i've never used saturate.

### #5Axel

Valued Member

• Members
• 119 posts

Posted 17 January 2006 - 12:23 AM

saturate clamps to [0,1], max selects the larger value, so max(dot(Light, Norm),0) should give equal results to saturate(dot(Light,Norm)) if Light and Norm are normalized.

### #6Superfly Johnson

New Member

• Members
• 19 posts

Posted 19 January 2006 - 09:09 AM

// diffuse.fx
float4x4 matWorldViewProj : WORLDVIEWPROJECTION;
float4x4 matWorld : WORLD;

struct VS_OUTPUT
{
float4 Pos : POSITION;
float3 Light : TEXCOORD0;
float3 Norm : TEXCOORD1;
};

VS_OUTPUT VS(float4 Pos : POSITION, float3 Normal : NORMAL)
{
VS_OUTPUT Out;
float3 lightDir = { -1.0f, -1.0f, 0.0f };
Out.Pos = mul(Pos, matWorldViewProj); // transform Position
Out.Light = normalize(lightDir); // output light vector
Out.Norm = normalize(mul(Normal, (float3x3)matWorld)); // transform Normal and normalize it
return Out;
}

float4 PS(float3 Light: TEXCOORD0, float3 Norm : TEXCOORD1) : COLOR
{
float4 diffuse = { 1.0f, 1.0f, 1.0f, 1.0f};
float4 ambient = { 0.0, 0.1, 0.0, 1.0 };
return ambient + float4(diffuse.xyz * saturate(dot(Light, Norm)), 1.0f);
}

technique Diffuse
{
pass P0
{
}
}

Not sure if the change I made will make a difference, but I usually do that cast for float3's.

However, your problem is not with the saturate. It's with the most essential part of 3D graphics programming: The dot. Taken from MS's HLSL reference:

Quote

This intrinsic function is supported in the following (or above) shader versions:

vs_1_1 ps_2_0

So my advice is to work out colour per vertex and interpolate. Or just support better graphics cards ;)

As a side, I've always found dot() to work on PS1.1 - PS1.4. However, just as many people have said what you said too - it works on one side but not others.

### #7jack33

New Member

• Members
• 5 posts

Posted 19 January 2006 - 12:22 PM

Thank you very much! Your quote has much help to me. I had better use ps_2_0 whenever possible, right? :)

### #8Superfly Johnson

New Member

• Members
• 19 posts

Posted 19 January 2006 - 12:29 PM

ps_1_1 is not very useful these days.

I write a codepath for ps_1_4 as a minimum (R8500, gf4 series), but the bulk of my time is spent making ps_2_0 look nice. Problem is the number of instructions, doing parallax mapping, shadow mapping with attenuated spotlights and a specular component in ps_2_0 is tricky, so there's ps_2_x for that. :)

### #9.oisyn

DevMaster Staff

• Moderators
• 1842 posts

Posted 19 January 2006 - 12:44 PM

Superfly Johnson said:

I write a codepath for ps_1_4 as a minimum (R8500, gf4 series)

1.4 is ATi only (when it comes to pre 2.0 hardware), the GF4 family only goes to 1.3
-
Currently working on: the 3D engine for Tomb Raider.

### #10Superfly Johnson

New Member

• Members
• 19 posts

Posted 19 January 2006 - 12:53 PM

My mistake.

#### 1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users