Setting Shader Constants
by Aaron Leiby · in Torque Game Engine Advanced · 07/08/2006 (4:02 am) · 3 replies
I've just finished porting my fancy shader over from RenderMonkey to work with Torque. It's got a bunch of parameters which I initially setup in CustomMaterial::setShaderConstants by storing all the values in static variables, and filling them in using:
GFX->setPixelShaderConstF( PC_USERDEF1, (float*)&gBaseColor, 4 );
GFX->setPixelShaderConstF( PC_USERDEF2, (float*)&gBaseFalloff, 1 );
GFX->setPixelShaderConstF( PC_USERDEF3, (float*)&gBaseStrength, 1 );
etc.
Now, I want multiple CustomMaterials (those defined in TorqueScript) to use the same shader but different values for the parameters. Adding a bunch of data fields to CustomMaterial that are specific to this shader seems a bit heavy handed, so I thought I'd take advantage of Torque's dynamic data fields instead.
I created a map of my material's dynamic data fields to their respective consts:
gPCMap["BaseColor"] = PC_USERDEF1;
gPCMap["BaseFalloff"] = PC_USERDEF2;
gPCMap["BaseStrength"] = PC_USERDEF3;
etc.
Then iterate over the dynamic fields in CustomMaterial::setShaderConstants (instead of the hardcoded statics first mentioned):
SimFieldDictionaryIterator itr(getFieldDictionary());
SimFieldDictionary::Entry *entry;
while((entry = *itr) != NULL)
{
if (gPCMap.contains(entry->slotName))
{
ParseFloats(entry->value, data, size);
GFX->setPixelShaderConstF(gPCMap[entry->slotName], data, size);
}
++itr;
}
...where ParseFloats takes the string value and populates an array of floats 'data' and sets 'size' appropriately.
Stepping through this code, everything seems to be getting set exactly as expected, however things no longer render correctly.
Now here's my question: Do the consts need to be set the same for every instance of CustomMaterial? Because in this case, I'm now only setting them for the CustomMaterials that use my shader, and not for any others -- whereas previously, because they were hardcoded using static data, they were getting set for every single CustomMaterial.
I'm sure this will probably make more sense after a good night's rest, but I figured I'd get it out there in the meantime in case anyone had any insight. I seem to be missing some key piece of info. (I'm also new to Torque, so there may also be better ways to take advantage of TorqueScript in these situations -- there seems like there should be a simpler way to map semantics/parameters from TorqueScript to hlsl already, beyond hardcoding them in C++).
GFX->setPixelShaderConstF( PC_USERDEF1, (float*)&gBaseColor, 4 );
GFX->setPixelShaderConstF( PC_USERDEF2, (float*)&gBaseFalloff, 1 );
GFX->setPixelShaderConstF( PC_USERDEF3, (float*)&gBaseStrength, 1 );
etc.
Now, I want multiple CustomMaterials (those defined in TorqueScript) to use the same shader but different values for the parameters. Adding a bunch of data fields to CustomMaterial that are specific to this shader seems a bit heavy handed, so I thought I'd take advantage of Torque's dynamic data fields instead.
I created a map of my material's dynamic data fields to their respective consts:
gPCMap["BaseColor"] = PC_USERDEF1;
gPCMap["BaseFalloff"] = PC_USERDEF2;
gPCMap["BaseStrength"] = PC_USERDEF3;
etc.
Then iterate over the dynamic fields in CustomMaterial::setShaderConstants (instead of the hardcoded statics first mentioned):
SimFieldDictionaryIterator itr(getFieldDictionary());
SimFieldDictionary::Entry *entry;
while((entry = *itr) != NULL)
{
if (gPCMap.contains(entry->slotName))
{
ParseFloats(entry->value, data, size);
GFX->setPixelShaderConstF(gPCMap[entry->slotName], data, size);
}
++itr;
}
...where ParseFloats takes the string value and populates an array of floats 'data' and sets 'size' appropriately.
Stepping through this code, everything seems to be getting set exactly as expected, however things no longer render correctly.
Now here's my question: Do the consts need to be set the same for every instance of CustomMaterial? Because in this case, I'm now only setting them for the CustomMaterials that use my shader, and not for any others -- whereas previously, because they were hardcoded using static data, they were getting set for every single CustomMaterial.
I'm sure this will probably make more sense after a good night's rest, but I figured I'd get it out there in the meantime in case anyone had any insight. I seem to be missing some key piece of info. (I'm also new to Torque, so there may also be better ways to take advantage of TorqueScript in these situations -- there seems like there should be a simpler way to map semantics/parameters from TorqueScript to hlsl already, beyond hardcoding them in C++).
#2
07/09/2006 (12:36 pm)
Turns out I misunderstood the size parameter for setPixelShaderConstF. I was thinking it was number of floats, when it's actually number of four float vectors. With that change, things now work as expected.
#3
07/10/2006 (12:47 pm)
If you are setting a lot of shader constants for a particular CustomMaterial, you should create a new derived class from CustomMaterial and use that instead. Then you can set up more complex interaction between your material and your shader. You don't want to set up a situation where CustomMaterial is sending a ton of data to shaders that will never use it.
Torque Owner Bobby Leighton
Imagn' Games