Shader help?
by Cosmic Logic · in Torque X 2D · 11/27/2009 (5:48 am) · 11 replies
Hey,
So I'm trying my hand at working with shaders.
I just found some source code for a colour swap shader. So far so good I think. I'm just not sure how to add that shader effect to... well something.
Looks like the easy way is to just make my own SimpleMaterial (as per this post) with the new effect stuff. The only trouble I'm having is how do you work that material in to the game?
In TXB I've got all of my resources, but in the XML it's all loaded as simplematerial.
I've (rather cave-manlike) just changing the material to a new instance of my custom material in a component's onregister and, well things kind of hit the fan.
How do I convert all of my TXB materials into this new custom material with the custom effect?
So I'm trying my hand at working with shaders.
I just found some source code for a colour swap shader. So far so good I think. I'm just not sure how to add that shader effect to... well something.
Looks like the easy way is to just make my own SimpleMaterial (as per this post) with the new effect stuff. The only trouble I'm having is how do you work that material in to the game?
In TXB I've got all of my resources, but in the XML it's all loaded as simplematerial.
I've (rather cave-manlike) just changing the material to a new instance of my custom material in a component's onregister and, well things kind of hit the fan.
How do I convert all of my TXB materials into this new custom material with the custom effect?
#2
All I get are black boxes that are floating around and other objects that don't even have the component turn in to black boxes. But only while certain animations are running. If I move around the black boxes flicker what they should be and become boxes.
My question is, what things do I have to pass to the material to make it proper? Do I need to specify things such as cell frames and image to use as the texture like the XML has? Or can I just set the new material and all of that stuff carries over? If it doesn't then do I have to pretty much make a copy of each material that I want to have that effect?
PS:
I used the shader from the bottom of this XNA post: Here.
And used this code for my material (keeping in mind I have no idea what I'm doing. I pretty much threw this together grasping at straws. There is little in the ways of shader tutorials):
I would also like to point out that the animatedsprite that I'm working with can use any of 14 different materials at any given time for different animations, not just the one.
11/28/2009 (4:07 am)
Well,All I get are black boxes that are floating around and other objects that don't even have the component turn in to black boxes. But only while certain animations are running. If I move around the black boxes flicker what they should be and become boxes.
My question is, what things do I have to pass to the material to make it proper? Do I need to specify things such as cell frames and image to use as the texture like the XML has? Or can I just set the new material and all of that stuff carries over? If it doesn't then do I have to pretty much make a copy of each material that I want to have that effect?
PS:
I used the shader from the bottom of this XNA post: Here.
And used this code for my material (keeping in mind I have no idea what I'm doing. I pretty much threw this together grasping at straws. There is little in the ways of shader tutorials):
class JerseyMaterial : SimpleMaterial {
public JerseyMaterial() {
EffectFilename = "data/effects/JerseyColour";
}
protected override string _SetupEffect(SceneRenderState srs, MaterialInstanceData materialData) {
base._SetupEffect(srs, materialData);
Effect.Instance.Parameters["TargetColor"].SetValue(new Vector3(1,1,1));
return "colorSwap";
}
}I would also like to point out that the animatedsprite that I'm working with can use any of 14 different materials at any given time for different animations, not just the one.
#3
Looks like I'm barking up the right tree this time.
Turns out the shader is just broken and I'll have to either write a good one or find a better one.
I just added a
to my TorqueSceneData.cs, manually changed all of my SimpleMaterial in the XML file to JerseyMaterial and it works with the tint shader from the link in my original post.
I may find a way to do it without this roundabout way eventually so I don't have to change my level data every time I run TXB, but for now it works.
11/28/2009 (5:42 am)
Aha!Looks like I'm barking up the right tree this time.
Turns out the shader is just broken and I'll have to either write a good one or find a better one.
I just added a
_defaultTypeMap.Add("JerseyMaterial", typeof(JerseyMaterial));to my TorqueSceneData.cs, manually changed all of my SimpleMaterial in the XML file to JerseyMaterial and it works with the tint shader from the link in my original post.
I may find a way to do it without this roundabout way eventually so I don't have to change my level data every time I run TXB, but for now it works.
#4
Something to bear in mind though is that animated sprites do not reference a material directly - they reference an animation data instance, which in turn references a material. You don't have to mess around with cell dividers and the like, just replacing the with something extending SimpleMaterial will work fine. BUT, if you change the material on an animation data instance then any object using that animation data will use that material too.
So if you want identical animation data being used with different materials (different tints) then you need to either create multiple identical versions of the animation data in TXB (one for each required tint) or clone the animation data at runtime, at the same time as you set the new material in component's on OnRegister.
11/28/2009 (9:48 am)
It should work fine setting a new material instance in OnRegister of a component. Test it out with static sprites first as that is the simplest case. Once it is working with static sprites it will also work with animated sprites.Something to bear in mind though is that animated sprites do not reference a material directly - they reference an animation data instance, which in turn references a material. You don't have to mess around with cell dividers and the like, just replacing the with something extending SimpleMaterial will work fine. BUT, if you change the material on an animation data instance then any object using that animation data will use that material too.
So if you want identical animation data being used with different materials (different tints) then you need to either create multiple identical versions of the animation data in TXB (one for each required tint) or clone the animation data at runtime, at the same time as you set the new material in component's on OnRegister.
#5
Using a component to change the material is a pretty cool idea. I have a question about how you did the OnRegister. When you are creating the new material are you also copying all the old material's properties, like in this example where I copy TextureFilename:
Or are you doing something else like reflection to copy all the properties automatically? Or am I just missing a different approach?
Thanks,
John
12/03/2009 (1:10 am)
Duncan,Using a component to change the material is a pretty cool idea. I have a question about how you did the OnRegister. When you are creating the new material are you also copying all the old material's properties, like in this example where I copy TextureFilename:
T2DStaticSprite sprite = owner as T2DStaticSprite; SimpleMaterial oldmaterial = sprite.Material as SimpleMaterial; TintMaterial newmaterial = new TintMaterial(); newmaterial.TextureFilename = oldmaterial.TextureFilename; sprite.Material = newmaterial;
Or are you doing something else like reflection to copy all the properties automatically? Or am I just missing a different approach?
Thanks,
John
#6
12/03/2009 (7:52 am)
You should make sure that owner is really a T2DStaticSprite. In case of AnimatedSprite, ParticleEffect and Scroller the material is access differently. Also copy the TextureDivider and properties like ColorBlended, Additive, ...
#7
Also: what Christian said.
12/03/2009 (12:12 pm)
@John: I just create a new instance of my custom material. You only need to set the material properties that are relevant to your custom material - so I'd only set the texture filename if I needed that to be set.Also: what Christian said.
#8
02/18/2010 (3:58 pm)
Duncan can you provide an example of the code you used to achieve your component based shader modifier?
#9
In onRegister() do something like this:
It's really as simple as just creating an instance of the custom material and setting it on the object. And set any parameters the custom material has, such as the texture to use, and so on.
02/18/2010 (7:07 pm)
Once you've created your custom material that uses the custom shader (see previous posts in this thread and on the forums), then you just create a custom component type that will set it up on the object the component is attached to.In onRegister() do something like this:
T2DStaticSprite _sprite = (owner as T2DStaticSprite); _material = new MyCustomMaterial(); _material.TextureFilename = (_sprite.Material as SimpleMaterial).TextureFilename; _sprite.Material = _material; _material.CustomParameter1 = ..... _material.CustomParameter2 = .....
It's really as simple as just creating an instance of the custom material and setting it on the object. And set any parameters the custom material has, such as the texture to use, and so on.
#10
(I'm completely new to TorqueX - haven't worked with an engine so complex before, so it's like being thrown in the deep end at the moment :) )
02/19/2010 (10:52 am)
Ok, I have tried this and I think I have it working, but how do you apply this kind of thing to a T2DAnimatedSprite? T2DAnimatedSprite doesn't have the Material property of StaticSprite? :S(I'm completely new to TorqueX - haven't worked with an engine so complex before, so it's like being thrown in the deep end at the moment :) )
#11
02/19/2010 (11:32 am)
MyAnimatedSprite.AnimationData.Material
Torque Owner Duncan Colvin
When I create a new custom material I also create a companion component that I can attach to an object in TXB and that component will set the object's material to an instance of my custom material at runtime (the component also provides TXB access to any parameters that I want to expose for the material/effect). I've not had any problems doing it that way.
What exactly is happening when things hit the fan in this instance?