Sign in to follow this  

Package my effect in DX

This topic is 2834 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I would like to create a effect class in DX, but I don't know how to set parameters quickly acrodding their names.And I must use D3DXHANDLE. In XNA: expEffect.Parameters["Projection"].SetValue(camera.ProjectionMatrix); That's what I want above... What I mean is that how to associate D3DXHANDLE and patameters and just transfer data into shader from theri names when rendering.

Share this post


Link to post
Share on other sites
You can pass a string instead of a D3DXHANDLE if you want.

effect->SetVector("LightColor", &lightColor);

You can also retrieve handles and cache them.

// During initialization
lightColorHandle = effect->GetParameterByName(NULL, "LightColor");

// During runtime
effect->SetVector(lightColorHandle, &lightColor);

Share this post


Link to post
Share on other sites
After packaging my shader class,I pass them looks like below:

Shader g_shader;
D3DXMATRIX world;
g_shader->setParemeters("gWorld",&world);


But I must search for the handleWorld by chars "gWorld",that's ineffective.
How do I avoid the search?

Share this post


Link to post
Share on other sites
MJP showed you how to do it above - you basically ask for the handle with the character based name, which returns a handle object. Then you can use the handle from that point onward to set the objects.

Share this post


Link to post
Share on other sites
As MJP said:
effect->SetVector("LightColor", &lightColor);
that's ineffective also,and that's why I use D3DXHANDLE.

struct Handle
{
char* name;
D3DXHANDLE handle;
}handle[MAX_NUM];

void MyShader::addParemeters(char* _p)
{
handle[i].name = _p;
handle[i].handle= effect->GetParameterByName(NULL, _p);
totalOfPar++;
}

void MyShader::setParemeters(char* _p, D3DXMATRIX* _m)
{
for(i=0;i<totalOfPar;i++)
{
if(strcmp(handle[i].name,_p))
effect->SetVector(handle[i].handle, &_m);
}
}


How can I avoid the "for" Circulation or the search?


Share this post


Link to post
Share on other sites
EDIT: sorry, I misread what you have written. So you want to set all parameters with a single call, is that the idea? If so, I think you would need to use DX10 or DX11 to use constant buffers. It sounds like you are using DX9, so I'm not sure there is a solution for that...

Share this post


Link to post
Share on other sites
Actually, you can set multiple adjacent constants with a single call in D3D9 as well. Set*ShaderConstants* methods have a parameter specifying how many registers you want to set.

You'd have to figure out the offsets of the variables and put your parameters in a structure that is perfectly equivalent to the register layout that you define in HLSL. The ID3DXConstantTable object can be used to calculate the registers corresponding to given variables. Note that the Effect framework already does this for you. And since the constant tables are static after the effect creation, it is very fast to access variables by handle anyway.

You can also force your HLSL variables to use particular registers, so you don't have to do the lookup from the host program. The syntax for a constant is as follows:


float4 example : register(c0); //variable "example" uses constant register 0.
float2 anotherExample: register (c1); //you get the idea...
...


Then you could set both of these with a single call to Set*ShaderConstantsF, since they are adjacent in the register layout.

In D3D9, you have to use separate registers for vertex and pixel shaders since the API doesn't have the notion of unified pipeline architecture. Also, integer, float and bool registers have their own logical banks. And finally, there is only one bank of constant registers per the three datatypes per shader stage. This is in contrast to D3D10 and up, where there is several general-purpose constant buffers that can store any datatype.

Share this post


Link to post
Share on other sites
Quote:
Original post by Jason Z
EDIT: sorry, I misread what you have written. So you want to set all parameters with a single call, is that the idea? If so, I think you would need to use DX10 or DX11 to use constant buffers. It sounds like you are using DX9, so I'm not sure there is a solution for that...


Thanks for JZ's reminder,I haven't learnt DX10 11 ,I must study hard..

Share this post


Link to post
Share on other sites
Quote:
Original post by Nik02
Actually, you can set multiple adjacent constants with a single call in D3D9 as well. Set*ShaderConstants* methods have a parameter specifying how many registers you want to set.

You'd have to figure out the offsets of the variables and put your parameters in a structure that is perfectly equivalent to the register layout that you define in HLSL. The ID3DXConstantTable object can be used to calculate the registers corresponding to given variables. Note that the Effect framework already does this for you. And since the constant tables are static after the effect creation, it is very fast to access variables by handle anyway.

You can also force your HLSL variables to use particular registers, so you don't have to do the lookup from the host program. The syntax for a constant is as follows:


float4 example : register(c0); //variable "example" uses constant register 0.
float2 anotherExample: register (c1); //you get the idea...
...



Then you could set both of these with a single call to Set*ShaderConstantsF, since they are adjacent in the register layout.

In D3D9, you have to use separate registers for vertex and pixel shaders since the API doesn't have the notion of unified pipeline architecture. Also, integer, float and bool registers have their own logical banks. And finally, there is only one bank of constant registers per the three datatypes per shader stage. This is in contrast to D3D10 and up, where there is several general-purpose constant buffers that can store any datatype.


Very helpful ! thank you very much! 谢谢 呵呵

Share this post


Link to post
Share on other sites
I forgot to mention: Since you're using the Effect system, you might want to use ID3DXEffect::SetRawValue. It effectively wraps Set*ShaderConstantsF, and you can give it the handle (or name) of the first variable to establish the first destination register.

Share this post


Link to post
Share on other sites

This topic is 2834 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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

Sign in to follow this