Archived

This topic is now archived and is closed to further replies.

Lighting/Color changing.

This topic is 5124 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've figured out I wanted to make a change to my 2D D3D8.1 "engine". Currently it uses lit, untransformed vertices, which works good. However, I have this diffuse color component in my flexible vertex format, but I'm not happy with the way it sits there. Right now I generate vertices during loading time and use them later, which means I can't do color effects without creating a huge amount of vertices with different colour values. To solve this problem I've spent my evening searching in the DirectX documentation for different methods I might use to dynamically light my sprites. So far I've come up with a couple of promising alternatives: 1. There is a SetTextureStage() function of the IDirect3DDevice8 interface. What confuses me about this thing though are those D3DTSS_COLOROP and D3DTSS_COLORARG1 & 2 arguments, and their poorly explained use. Could anyone explain what how these work? 2. Additionally vertex shaders seem to be an option, but isn't that really a bit of an overkill? I mean, I just want to change the diffuse color of a vertex/triangle/vertex buffer (any of these suffice). Besides I won't get my new computer until a few weeks, and my TNT2 probably cannot handle any vertex shader. 3. The IDirect3DDevice8 inteface also has a SetMaterial() function. Now that seems nice, but how is it used? As you can see I'm not too keen to try all those methods myself. I'm lazy enough to beg for help, because I'm more interested to start working on the game mechanics rather than to spend another month reading up on these topics. If you need any more information to give me advice, please ask and I'll supply you with an answer. EDIT: Removed "2D" from the title to lure more Direct3D users here. [edited by - Unwise owl on November 30, 2003 4:51:43 PM]

Share this post


Link to post
Share on other sites
The best and easiest way to do what you're asking is to use the SetMaterial function you found. It's not terribly complicated to use. It only takes one argument: a pointer to a D3DMATERIAL9 structure that you fill in with the values you want.

If you're using Visual Studio 6.0 or higher, you can take a look at the code produced by the DirectX Wizard for rendering a single triangle (or a teapot for that matter). Your basic code would look like this:


// Create a yellow material
D3DMATERIAL9 yellowMaterial;
yellowMaterial.Diffuse.r = 1.0f;
yellowMaterial.Diffuse.g = 1.0f;

m_pd3dDevice->SetMaterial( &yellowMaterial );
m_pd3dDevice->SetStreamSource( ...... );
m_pd3dDevice->DrawPrimitive(.....)

Hope this helps,
neneboricua

[edited by - neneboricua19 on November 30, 2003 8:06:50 PM]

Share this post


Link to post
Share on other sites
Apparently since I use *lit* vertices without normals this method won't work, and I don't feel I want to start generating normals now just for this. Correct me if I'm wrong though (I'll still be testing this within the nearest hour).

To "the Clown": Yes but I have one question then, will it affect the speed of rendering in any way? It probably will, but to what extent?

[edited by - Unwise owl on December 1, 2003 1:58:01 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by Unwise owl
Apparently since I use *lit* vertices without normals this method won't work, and I don't feel I want to start generating normals now just for this. Correct me if I'm wrong though (I'll still be testing this within the nearest hour).

To "the Clown": Yes but I have one question then, will it affect the speed of rendering in any way? It probably will, but to what extent?

[edited by - Unwise owl on December 1, 2003 1:58:01 PM]

Ok, that's right. Materials need normals cuz they're part of the lighting calculations D3D uses. I'm not sure but you may run into the same issue if you try to use SetTextureStageState to do this.

Vertex shaders will definately work, but like you say, it's a bit of overkill. Since you're shader wouldn't be so long though, you could probably still use it on a TNT2. It will get emulated in software but if there aren't many 2D quad's you're rendering, then it might be ok.

The next best way to do it then would be to have normals directly out from your 2D quads. Then all you need to do is have a white directional light pointing straight at the quads. You can then change the materials to your heart's content. As far as speed goes, I don't think there would be much of a performance hit. The actual math to calculate diffuse lighting from a directional light and material color is very small. The TNT2 has hardware transformation & lighting so it shouldn't be bad at all.

Since this is 2D, your quads will have normals pointing straight out of the screen. All of your quads will have the same normal (0, 0, -1). Then you have one directional light that you can set up during initialization:

D3DLIGHT9 light;
light.Type = D3DLIGHT_DIRECTIONAL;
light.Diffuse.r = light.Diffuse.g = light.Diffuse.b = light.Diffuse.a = 1.0f;
light.Direction = D3DXVECTOR3( 0.0f, 0.0f, 1.0f );
m_pd3dDevice->SetLight( 0, &light );
m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );

Now you can set any material you want during rendering.

neneboricua

[edited by - neneboricua19 on December 1, 2003 3:00:30 PM]

Share this post


Link to post
Share on other sites
I solved it! (At least for now.) It took 20 minutes to change the engine once I figured what to do.

(Removed what I wrote here since it made no sense at all.)

EDIT: Actually diffuse isn't working (no change I think), probably it's because of the vertex normals, or they can't be generated because it's 2D . However the current ambient lighting capabilities seem enough, since I can set the ambient property in both the material and on a global scale in the SetRenderState() function.

[edited by - Unwise owl on December 1, 2003 3:27:22 PM]

Share this post


Link to post
Share on other sites
OK, now I have a new problem. It seems alpha blending doesn't work together with lighting. My mouse cursor that rendered fine previously with alpha blending, doesn't appear now unless I turn off alpha blending again. Why can this be?

My current render states are these:
g_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
g_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
g_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);

[edited by - Unwise owl on December 1, 2003 3:42:45 PM]

Share this post


Link to post
Share on other sites