[SOLVED] Shaders - How to Set values of struct array in HLSL from Application ?

Started by
10 comments, last by Chetanhl 13 years, 6 months ago
I have a following structure in my HLSL Shader -

struct DirectionalLights{	float3 revDirection;		float4 ambientColor : COLOR;	float4 diffuseColor : COLOR;	float4 specularColor : COLOR;};int numDirLights = 0;DirectionalLights dirLights[2];



How can i assign values to dirLights ???
I am using DX9 Effects framework.

Here the c++ code am using -

typedef struct chDirectionLight{	D3DXVECTOR3 direction;	float pad0;   //getting same error even after removing this optional variable	D3DXCOLOR ambientColor,diffuseColor,specularColor;	chDirectionLight()	{		pad0=0.0f;		direction = D3DXVECTOR3(0.0f,0.0f,0.0f);		diffuseColor=ambientColor=specularColor=D3DXCOLOR(0.0f,0.0f,0.0f,0.0f);	}}chDirectionLight,*LPChDirectionalLight;/////Later to set value I am using following call effect->SetValue(this->dirLightHandle,(void *)ptrDirLight,sizeof(chDirectionLight));



I am trying to set first member of array in above c++ code but it m getting - DirectX Reported Error: D3DERR_INVALIDCALL - Invalid

Please help me figure out how to do it correctly and also how we will assign values to 2nd member of dirLights array.



EDIT : I know how to set 2 elements togather using 2*sizeof(struct), but i want to know if there is some method to assign value to 2nd elemnt without bothering the first one. There is no option to set offset in ID3DXEFFECT::SetValue() Method.

EDIT 2: I am getting DirectX Reported Error: D3DERR_INVALIDCALL - Invalid call on this line :
effect->SetValue(this->dirLightHandle,(void *)ptrDirLight,sizeof(chDirectionLight));

[Edited by - Chetanhl on October 23, 2010 2:29:37 PM]

My Game Development Blog : chetanjags.wordpress.com

Advertisement
* You forgot the parameter pad0 in your shader code. Take a look.
* Maybe you have to pass numElements * sizeof (chDirectionLight) to the 3rd of ID3DXBaseEffect::SetValue() function.
There's no "hard", and "the impossible" takes just a little time.
Initially there wasn't any pad0 variable i added just becoz some random article on net (it's just on of search results i got while searching on google
) suggested to do so, as in HLSL float3 are saved as float4 in memory. I dunno if its correct but no matter if pad is there or not am getting same error message.

I know how to set 2 elements togather using 2*sizeof(struct), but i want to know if there is some method to assign value to 2nd elemnt without bothering the first one. There is no option to set offset in ID3DXEFFECT::SetValue() Method.

My Game Development Blog : chetanjags.wordpress.com

You need to use the pad var both in shader and application code, or you will get errors...
Already tried to include padding in both even thats not working.

Here's new code for HLSL Struct -

struct DirectionalLights{	float3 revDirection;	float pad0;		float4 ambientColor : COLOR;	float4 diffuseColor : COLOR;	float4 specularColor : COLOR;};




c++ Struct Code -

typedef struct chDirectionLight{	D3DXVECTOR3 direction;	float pad0;	D3DXCOLOR ambientColor,diffuseColor,specularColor;	chDirectionLight()	{		pad0=0.0f;		direction = D3DXVECTOR3(0.0f,0.0f,0.0f);		diffuseColor=ambientColor=specularColor=D3DXCOLOR(0.0f,0.0f,0.0f,0.0f);	}}chDirectionLight,*LPChDirectionalLight;


Still no luck geting same error.

My Game Development Blog : chetanjags.wordpress.com

In which line is the error thrown?
Here's that line -

effect->SetValue(this->dirLightHandle,(void *)ptrDirLight,sizeof(chDirectionLight));

My Game Development Blog : chetanjags.wordpress.com

Have you more information on that D3DERR_INVALIDCALL-Error (i.e. DirectX Debug Runtime output ) ?
This is choped of from my old project.
code:
const UINT MAX_ACTIVE_LIGHTS = 8; //...D3DXHANDLE    HNumLights;D3DXHANDLE    HLightPosition[MAX_ACTIVE_LIGHTS];D3DXHANDLE    HLightAmbient[MAX_ACTIVE_LIGHTS];D3DXHANDLE    HLightDiffuse[MAX_ACTIVE_LIGHTS];D3DXHANDLE    HLightSpecular[MAX_ACTIVE_LIGHTS];D3DXHANDLE    HLightRadius[MAX_ACTIVE_LIGHTS];...//and other attributes...D3DXHANDLE hLight = 0;UINT i  = 0;for(; i < MAX_ACTIVE_LIGHTS; ++i){	hLight = Effect->GetParameterElement("Lights", i);	if(0 == hLight)	{		...error		return false;	}	HLightPosition = Effect->GetParameterByName(hLight, "Position");	if(0 == HLightPosition)	{          ...error	    return false;	}	HLightAmbient = Effect->GetParameterByName(hLight, "Ambient");	if(0 == HLightAmbient)	{		return false;	}	HLightDiffuse = Effect->GetParameterByName(hLight, "Diffuse");	if(0 == HLightDiffuse)	{            ...error		return false;	}	HLightSpecular = Effect->GetParameterByName(hLight, "Specular");	if(0 == HLightSpecular)	{            ...error		return false;	}	HLightRadius = Effect->GetParameterByName(hLight, "Radius");	if(0 == HLightRadius)	{            ...error		return false;	}      ...//other attributes}...//then you set each value using handles


shader:
#define MAX_ACTIVE_LIGHTS 8int    NumLights;//num lights currently affecting this model...struct Light{	float3 Position;	float4 Ambient;	float4 Diffuse;	float4 Specular;	float  Radius;      ...//other attributes};Light Lights[MAX_ACTIVE_LIGHTS];...


hope it helps.
For the error you can pass an error buffer when creating your shader then any failures would be available in human readable form. You can also use fxc.exe as well, just ignore the 'main() not found' error since that is only required by fxc. Both methods will give you the line number and column of the error. I prefer the first since I log all of my errors in a text file.

******************************************************************************************
Youtube Channel

This topic is closed to new replies.

Advertisement