Okay, first off, WHAT is a Material?
Materials are NOT:
A material, simply put, is a series of just FIVE instructions that tell DirectX how light should be handled on every VERTEX of the model (or group, since Materials can be applied to individual groups as well.) This may sound simple enough, but it will make ALL the difference in how your applications look. If you get a good understanding of materials, and learn how to use them, you can go from having a mediocre looking app, to a great looking app. So let’s start with how TV handles them.
First you’ve got 5 settings. I’ll put them in my personal order of importance. (ie, how often you’ll use them.)
Here are some settings to get the camera,box,sphere roughly in position
TV.GetCamera().SetPosition(2, 1, 0); TV.GetCamera().SetLookAt(0, 0, 4); box.CreateBox(1, 1, 1); box.SetPosition(-1, 0f, 4); sphere.CreateSphere(1,20,20); sphere.SetPosition(0, 0, 4);
| First, we create a couple of models to look at. I’m going to just make a sphere and a box.|
I’m not going to go through now to init the engine, load models, and render them. If you don’t know how to do that, then you have bigger problems than just your materials.
The first thing you notice is that they’re COMPLETELY white. “WHY!” This is actually done on purpose. With TV 6.5, the default material is 100% Ambient, with a slight emissive, and its own light, so you’ll actually be able to see SOMETHING right off the bat, and know if your model is loading properly quickly. We’re about to change all that. First thing, call this: Lights.SetGlobalAmbient 0, 0, 0 It’s difficult to explain at the moment, but due to a current glitch, it’s not being set to 0 by default. Just make things easier on yourself and call it first. We’ll come back to it later.
|Now... The second-first thing you want to do is change the lighting mode, so that the mesh will start listening to what YOU want it to do, instead of sticking with the TV Defaults. This is easily done by setting the mesh’s LightingMode (strangely enough.) Since you want to MANAGE the lighting on your meshes yourself, then guess what you want to set the lighting mode to? Mesh.SetLightingMode TV_LIGHTING_MANAGED“OH NOES!!! EVRTHNG WENT 2 TEH BLAK!!!!!” If your models have now turned black, this is a good thing. Black is beautiful. All this means is that you’re now managing your own lighting. And if you’re managing your own lighting, but you don’t actually have any LIGHTS, well, hrm, do you really gotta think about this?|
| So let’s stick a simple directional light into this scene, just to get us back to where we started. LightID = LightEngine.CreateDirectionalLight(Vector(-1, -1, 1), 1, 1, 1, “Arr”, 1)|
LightEngine.SetSpecularLighting True There’s several things I want you to notice here. First, the Y vector value is negative. With directional lights, always pretend that the light is located at 0,0,0, and the vector is what the light is “looking at.” So to make the light point downward, the Y has to be a negative value. Secondly, the specular is set to 1. This will come into play later. Might also be good to note that the color of this light is solid white, with the 1,1,1 color settings. Also, note that I’ve enabled specular lighting. Without this, none of your specular settings would take effect. IMO specular lighting makes good lighting great lighting when used correctly. Well, now we’re back at the white models. WTF? This is because the models STILL have the default material on them. Read above to see why the default material makes things white.
|For starters, if you’re going to manage your own light and materials, let’s do it right. The MaterialFactory’s .CreateMaterialQuick and .CreateLightMaterial are fine and dandy if you’re in a hurry, but for the most part, you want to do this stuff yourself. So let’s start with a standard material: matStd = MaterialFactory.CreateMaterial Then switch the mesh’s material to the one you just created: Mesh.SetMaterial matStd Hard stuff, huh? “OMGWHAT JAVIN?!? ITS STILL THE SAME!!!” Shut up and keep reading...|
| Okay, our biggest problem here is that by default, ALL of our settings are cranked up to maximum. For educational purposes, we’re going to go ahead and remove ALL of these settings, so we can tackle them one at a time: MaterialFactory.SetAmbient matStd, 0, 0, 0, 1|
MaterialFactory.SetDiffuse matStd, 0, 0, 0, 1
MaterialFactory.SetSpecular matStd, 0, 0, 0, 1
MaterialFactory.SetPower matStd, 0
MaterialFactory.SetEmissive matStd, 0, 0, 0, 1 Note that this is also the order we’re going to tackle these settings in. “OMGOMGZ@!!!” Yes, I know... It’s black. Your models are still there, but with no light settings on them, they aren’t visible against the black background.
|Your first setting is going to be your Ambient lighting. This is the amount of light that hits ALL parts of your model, regardless of what angle it is to the light. What’s more, it’s a percentage of ALL LIGHTS hitting the model. So if you have your ambient lighting set to 0.1 (10%) then one light will have the “dark side” of your model with 10% light hitting it. However, three lights will be 30% brighter on the dark side. Keep this in mind when designing your light schemes. Your Ambient lighting should almost always be a VERY low value. Let’s start with 10%: MaterialFactory.SetAmbient matStd, 0.1, 0.1, 01, 1 (Note that I always set the “alpha” to 1. This will be covered later.) You start to at least get an idea of the outline of your models.|
|Next, and one of the single most important values, is your “Diffuse.” Diffuse is the difference between your “dark” sides, and your “light” sides. The higher the diffuse, the lighter the light sides, and the darker the dark sides are. Diffuse should typically be quite high, and in very, very bright scenes (desert sunlight) you might even go higher than 100%. Those cases are rare, though. Let’s set our Diffuse to a nice, high value. Say, 80%: MaterialFactory.SetDiffuse matStd 0.8, 0.8, 0.8, 1 Take note of the lighting on the box in the background. Since lighting is PER VERTEX, the corners of the box apply to three different sides, giving an unrealistic look to the lighting. Keep this in mind when making things that should have “sharp” edges. You’ll have to unweld them, and make each “side” a different group for DirectX to correctly seperate them.|
|“OMGJAVIN ITS TEH PRETTAY KAN WE STOP NOW?!!?” No. Next is Specular lighting. This is how much “shine” a model has on it. Basically, it will take a certain percentage of your “diffused” bright light, and crank it up by THIS percentage. Most things (fruits, wood, even skin) has at least a SMALL amount of shine to it. More obvious things such as metal and glass have a huge amount of shine to them. MaterialFactory.SetSpecular matStd, 0.2, 0.2, 0.2, 1“OH NOES< ITS NOT TEH PRETTAY NEMORE!!!!!11” Keep in mind that your specular is highly influenced by the “Power” setting, which we currently have set to 0.|
|The “power” setting works kinda like a magnifying glass. It takes all that specular lighting you just doused your model with, and “concentrates” it based on how high the power setting is. Also, it doesn’t take a 0-1 value like the other settings, but you can be far more aggressive with it. So let’s crank this power up to give us a nice, single, shiny dot: MaterialFactory.SetPower matStd, 20 As you can see, this gives us a shiny “spot” on our sphere. Keep in mind that ALL of these effects are per-vertex, so the more vertecies you have, the “smoother” the effects look. Something like specular is best seen with a moving object. Take a look at my VehiclePhysics Demo to see a high specular value in action. The vehicle itself has these EXACT settings to get the shadowing/shine/etc.|
| Finally, let’s talk a moment about semi-invisible meshes. To put ANY kind of alpha on a mesh, there’s two things you have to do. We’re going to do them for the sphere, only: Mesh.SetAlphaTest True, 0|
Mesh.SetBlendingMode TV_BLEND_ALPHA First off, you tell TV that it needs to check the mesh whenever it goes through it’s alpha sorting, and that the lowest (0-255) alpha value it should pay attention to is 0 (giving you the full range from full alpha to no alpha). Second, set the mesh’s “blending mode.” Usually, this will be TV_BLEND_ALPHA. Every now and then, you’ll want to use a different blending mode for special effects. Now, let’s add some opacity to the material: MaterialFactory.SetOpacity matStd, 0.5 Just so you know what this does, remember all those alpha values on your Emissive/Ambient/Diffuse/Etc.? Well, most of them don’t do anything. That’s right, DirectX requires them, but then ignores them. Go Microsoft. The only one that DOES do anything is Diffuse. Changing the alpha of your diffuse is the EXACT same as calling .SetOpacity. So you could have just as easily called .SetDiffuse matStd, 0.8, 0.8, 0.8, 0.5 and gotten the EXACT same results.
Last, and usually least, is your Emissive settings. Emissive is the light that your mesh will “Emit” (no, this is not the same as creating a light. This “emitted” light doesn’t actually shine ON any other meshes). Emissive isn’t often used, but when it is, it’s usually for things such as lights, glowing eyeballs, etc. Typically, what you would do is create whatever portion of your model should glow (say, vehicle lights) as a seperate group. Then, when you want to “turn the light on” you would simply set the material of that group to one with full Emissive.
Other tricks with emissive materials would involve “pulsing” lights. You simply raise and lower the emissive value every frame creating a “pulse” look. With some fancy footwork, you can use emissive materials and a render surface to display GlowMaps. They have their uses, but they’re pretty rare.
Other tricks with Materials as a whole:
There’s a lot materials can do. Learn them well, and you’ll be able to get incredible effects without having to resort to expensive things such as pixel shaders. (Not saying that pixel shaders themselves aren’t useful, but that’s another tutorial all together.)