Lights and hardware vertex processing

Started by
11 comments, last by Kaloux 16 years, 2 months ago
Hi ! When I enable hardware vertex processing and use my own vertex shader, lights are no longer applied (models are no more self shadowed). Is there something I missed in the API ? Or am I obliged to make my own pixel shader, taking care of light calculations by myself ? What would be the use of D3DLIGHT9 then ? (I really miss a good tutorial on this subject. All I find is either too complex or too abstract) Thanks in advance.
Advertisement
enabling vertex processing means that you will have to replace the full working of the transform and lighting pipeline. That means you have to several things in shaders, including transformation, lighting and shadowing.

what i don't understand is that models are no more self shadowed? I haven't been following the t&l anymore lately, but in my memory self shadowing wasn't even supported in the t&l hardware.

in the documentation of DX9/10 (latest sdk), there's an article about replacing the existing T&L, but it requires a 'newer' video card with good shader support i think.
Well, by self shadowing, I meant normal darkening. In the real world, it's a kind of shadow :)

Anyway...
Sadly, you confirmed my thoughts. Do you know a place where I could find pre-build shaders that I could work on ?
If none, then I'd have just a question :
I'd have to pass all the lights in the pixel shader. As far as I know, you can't transfer a C++ struct directly into the shader program. So the solution would be to create several arrays in the pixel shader :

    // General    int    xLightType[MAX_LIGHT_NBR];    float3 xLightColor[MAX_LIGHT_NBR];    // Spot and point lights    float3 xLightPos[MAX_LIGHT_NBR];    float3 xLightAttenFactors[MAX_LIGHT_NBR];    float  xLightRange[MAX_LIGHT_NBR];    // Spot and directionnal lights    float3 xLightDirection[MAX_LIGHT_NBR];    // Spot lights    float2 xLightCones[MAX_LIGHT_NBR];    float  xLightFallof[MAX_LIGHT_NBR];


... and then update them in the main program when needed ?
I could also calculate everything in the main program and change the color of my vertice.
What'd be best ?
You mention both vertex and pixel shaders so it's not clear whether just vertex lighting would suffice.

You wouldn't need a pixel shader routine to do just vertex shading.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

The standard D3D fixed function lighting is per vertex, so you wouldn't need to write a pixel shader. You will need to add lighting to your vertex shader though.
Wow, awesome posts guys and well done on helping Kaloux,
Kaloux, at the very least, your vertex shader should transform the vertices to give them a position in world space. You can however then additionally specify a lighting model (light your vertices).

I hope this helps.
Take care.
Ok thanks for these infos, I didn't thought I could do it in the vertex shader !

I've tried using the arrays I described in my previous post and I just can't get it to work properly...
In fact, I use a "for" loop to iterate through my arrays and calculate lighting, but weird things are happening.

Here is my code, I'll explain what's wrong just after :

// Vertex shader input structurestruct VS_INPUT{	float4 Position   : POSITION;	float2 Texture    : TEXCOORD0;	float3 Normal     : NORMAL;};// Vertex shader output structurestruct VS_OUTPUT{	float4 Position   : POSITION;	float2 Texture    : TEXCOORD0;	float3 Normal     : TEXCOORD1;	float4 Color      : COLOR0;};// Global variablesfloat4x4 mWorldViewProj;/// LIGHTS// Light typesint LIGHT_POINT = 1;int LIGHT_SPOT = 2;int LIGHT_DIRECTIONAL = 3;// Generalint    mLightNbr;int    mLightType[128];float4 mLightColor[128];// Spot and point lightsfloat4 mLightPos[128];float4 mLightAttenFactors[128];float  mLightRange[128];// Spot and directionnal lightsfloat4 mLightDirection[128];// Spot lightsfloat  mLightConeIn[128];float  mLightConeOut[128];float  mLightFallof[128];float4 Light_PointDiffuse(float3 VertPos, float3 VertNorm, float3 LightPos,                          float4 LightColor, float4 LightAttenuation, float LightRange){	float3 LightDir = LightPos - VertPos;	float Dist = length(LightDir);	if (Dist < LightRange)	{		float DistAttn = saturate(1 / (LightAttenuation.x +                                               LightAttenuation.y * Dist +                                               LightAttenuation.z * Dist * Dist));									   		float AngleAttn = saturate(dot(VertNorm, LightDir));				return LightColor * DistAttn * AngleAttn;	}	else		return float4(1, 1, 1, 1);}// Name: Simple Vertex Shader// Type: Vertex shader// Desc: Vertex transformation and texture coord pass-through//VS_OUTPUT main( in VS_INPUT Input ){	VS_OUTPUT Output; //create an output vertex	float3 Position3D = Input.Position;	Output.Position = mul(Input.Position, mWorldViewProj); //apply vertex transformation	Output.Texture  = Input.Texture; //copy original texcoords.	Output.Normal = Input.Normal;	Output.Color[0] = 1.0f;	Output.Color[1] = 1.0f;	Output.Color[2] = 1.0f;	Output.Color[3] = 1.0f;		if (mLightNbr != 0)	{		for (int i = 0; i < mLightNbr; i++)		{			if (mLightType == 1) // Point light			{				Output.Color *= Light_PointDiffuse(Position3D, Input.Normal, mLightPos, mLightColor, mLightAttenFactors, mLightRange);			}		}	}	return Output; //return output vertex}


Maybe 128 is a bit too much :)
Anyway, if I use this shader, everything is plain black. However, if I replace :
Output.Color *= Light_PointDiffuse(Position3D, Input.Normal, mLightPos, mLightColor, mLightAttenFactors, mLightRange);

...by :
Output.Color *= Light_PointDiffuse(Position3D, Input.Normal, mLightPos[0], mLightColor[0], mLightAttenFactors[0], mLightRange[0]);

... it works !

I made some tests and checked that the loop is executed only once in both cases (I have only one light in my scene).
Am I doing something wrong with the loop ?

Something else that annoys me is that the following code doesn't work as expected :
if (mLightType == LIGHT_POINT)	...

That's why I replaced "LIGHT_POINT" by "1" in my code, and it worked. Strange...
128 is way too much, you're running out of constants. Try pulling it back to 3 or 4, work your way up from there.
but very nice progress!

Hi,

Actually you can use structs in HLSL (instead of those numerous arrays), and as far as I remember, they even map quite well to C++ structures. Need to verify that.

Good luck!

This topic is closed to new replies.

Advertisement