Archived

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

Tagamoga

Lights

Recommended Posts

Hello. I am trying to turn on lights in my scene. Until now I have one triangle - yes for me it is GREAT *g* - With one blue, red and yellow corner and it rotates raound his Y-Axis... Until now I was using, untransformed Vertexes with Color. And the rotation was made by changing the WorldMatrix. Now I added Vertex normals. Still everything was working fine. Then I added one Material for the whole scene... ~g~ yes, it is still only one triangle... Everything was still working fine.. Here my Material Code: D3DMATERIAL8 Material; ZeroMemory(&Material, sizeof(D3DMATERIAL8)); Material.Diffuse.r = 1.0f; Material.Diffuse.g = 1.0f; Material.Diffuse.b = 1.0f; Material.Diffuse.a = 1.0f; Material.Ambient.r = 1.0f; Material.Ambient.g = 1.0f; Material.Ambient.b = 1.0f; Material.Ambient.a = 1.0f; g_pDevice->SetMaterial(&Material); The fact that my triangle has still his great bright colors and is still visible, and still rotates... I added one single Light... My Code: D3DLIGHT8 Light; ZeroMemory(&Light, sizeof(D3DLIGHT8)); Light.Type = D3DLIGHT_POINT; Light.Diffuse.r = 1.0f; Light.Diffuse.g = 1.0f; Light.Diffuse.b = 1.0f; Light.Position = D3DXVECTOR3(0,0,-9); Light.Range = 10.0f; g_pDevice->SetLight(0,&Light); g_pDevice->LightEnable(0,TRUE); g_pDevice->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_XRGB( 100, 100, 100 ) ); But now my great triangle is ugly.... sometime it has still a blue corner... but the oder are pale grey... and the blue color ist switching on and off... I thought, that the light would enlight the Middle of my beautifull triangle, but now.... what did I wrong? Can somebody explain me, how to set up lights correct? *g* Yes I know that is much stuff, but a beginning would be great... almost as great as my bright coloured single spinning traingle.... *smile* Taggi

Share this post


Link to post
Share on other sites
D3DLIGHT8 Light;
ZeroMemory(&Light, sizeof(D3DLIGHT8));
Light.Type = D3DLIGHT_POINT;
Light.Diffuse.r = Light.Ambient.r = 1.0f;
Light.Diffuse.g = Light.Ambient.g = 1.0f;
Light.Diffuse.b = Light.Ambient.b = 1.0f;
Light.Diffuse.a = Light.Ambient.a = 1.0f;
Light.Position = D3DXVECTOR3(0.0f, 0.0f, -9.0f);
Light.Range = 50.0f; // Needs to reach vertices, not plane
Light.Attenuation1 = 1.0f;

See if that works.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
With respect to the gray color: By default the diffuse material color comes from the vertex diffuse color. The ambient material, by contrast, comes from the material settings.

So what''s happening right now is that global ambient (100,100,100) is being multiplied by material ambient (1.0, 1.0, 1.0) and added it on to the diffuse lighting -- giving you grayish colors.

What you probably want in this situation is for the material ambient to come from the vertices, so set D3DRS_AMBIENTMATERIALSOURCE to D3DMCS_COLOR1.

I think you''ll find that the material diffuse color that you''re setting has no effect -- because again, by default it comes from the vertex, not the material settings.

And one other point: lighting is calculated only at the vertices and interpolated across the face of the triangle. You''re not going to see the interior of the triangle illuminated as I think you are expecting to. I would start with a sphere (D3DXCreateSphere). That will give you a better lighting than a single triangle can.

Share this post


Link to post
Share on other sites
Hey, Anonymous...

That is a great hint! Thanks!
I did not really understand your explanatation - my english is horrible -, but it works...

I am almost there... but I have still a little problem... The vertex, that is "backwards" looses always its color... and gains it back, when, another vertex rotates behind it. Then the first vertex gains its Color back and the second one looses it... does somebody know why?

And yes the light reaches all vertices

Taggi

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Lighting is complicated. :-) One thing that might help you understand how things work is Rich Thomson''s lighting demo:

http://www.xmission.com/~legalize/book/snippets/index.html#13

Share this post


Link to post
Share on other sites
another thought:

I have turned my triangle red in all corners... so I recognized, that, though it is rotating, one vertex (this one in front) is totaly red, and the other one (this one in the back) is black. Even though they are spinging araound, this red is not getting darker, when the triangle is rotating... suddenly both vertices are changing colors - that is when both are parallel to the surface -

I though that they are getting darker and brighter, when they are rotating... I though each frame the colors for the vertices are calculated and changing... why are they switching suddently, instead of having nuances of red?

Taggi

P.S.:
I hope you can understand my english .

Share this post


Link to post
Share on other sites
You must enable colored vertices, and say where the colors come from, ie: material or vertex diffuse or vertex specular.

// Enable vertex colors
m_d3dDevice->SetRenderState(D3DRS_COLORVERTEX, TRUE);
// Diffuse comes from vertex diffuse
m_d3dDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
// Specular, ambient, and emissive come from material
m_d3dDevice->SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL);
m_d3dDevice->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
m_d3dDevice->SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL);

You must also ensure the light is attenuated properly. D3Ds lighting sucks. You want a light that fades from full to zero over it''s range, which cannot be done without a shader. The attenuation formula is based on three attenuation values.

Light.Attenuation0 = 1;
Light.Attenuation1 = 1/Light.Range;
Light.Attenuation2 = 1/Light.Range/Light.Range;

A0 - Constant attenuation
A1 - Linear attenuation (times distance)
A2 - Quadratic attenuation (time distance squared)
D - Distance from vertex to light

The light color value is then multiplied by this formula:
A = 1 / (A0 + D*A1 + D^2*A2)

So, at distance 0, you want the light to be full bright:
A = 1 / (1+0+0)
A = 1 / 1

And you want the light to fade with distance. At full range, using the values above, your light will be 1/3 as bright.
A = 1 / (1+1+1)
A = 1 / 3

Change Attenuation2 to 2/Light.Range/Light.Range and you''ll get an attenuation at full range of 1/4.
A = 1 / (1+1+2)
A = 1 / 4

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
D3Ds lighting sucks. You want a light that fades from full to zero over it''s range, which cannot be done without a shader.


OpenGL uses the same attenuation formula. In practice it is not commonly a problem since you can set up a range and attenuation where the atten is close enough to 0 at range that it doesn''t matter. Jim''s suggestion is a very good one for getting started with lighting: Attenuation1 = 1, thus removing the possibility of an attenuation that''s too extreme.

The OP had problems with taking ambient from the material and should leave it at D3DMCS_COLOR1.

Tagamoga, I don''t know what it is that you''re seeing but again I think it would help if you work with something like a sphere rather than a triangle, and spend some time with the lighting demo I pointed you to.

Share this post


Link to post
Share on other sites
quote:
Original post by Namethatnobodyelsetook
D3Ds lighting sucks. You want a light that fades from full to zero over it''s range, which cannot be done without a shader.


This doesn''t suck - it''s more physically correct. A real light doesn''t have an actual range. There is some (small) amount of light at any distance. AP''s answer is the best - if you want, create values that make it very close to zero at the range.

I''m not sure, but I believe that D3D uses the range parameter for rough optimization. It is not part of the lighting equation.

Author, "Real Time Rendering Tricks and Techniques in DirectX", "Focus on Curves and Surfaces"

Share this post


Link to post
Share on other sites
quote:
I''m not sure, but I believe that D3D uses the range parameter for rough optimization. It is not part of the lighting equation.


Both, really. If light distance > range, attenuation is 0. In these cases the lighting calculations can bypass ambient, diffuse, and specular and just do emissive. Actually global ambient is added in as well, but not light ambient.

(BTW, I''m the Anonymous Poster in this thread. I decided it''s time I finally registered. :-) )

Share this post


Link to post
Share on other sites
Namethatnobodyelsetook now it is great! Now I have what I want, but I have to set
g_pDevice->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE,D3DMCS_COLOR1);

instead of

g_pDevice->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);

because otherwise my vertexcolors are gone.

Donavon Keithley I have run your Demoprogramm, but there are so many possibilities, that I still need help.
I am still "testing", playing or do experiments with DirectX, so it will take really much time, until I will generate spheres or anything that is more complex than a triangle.. *smile* I need time...

Well... until now, I have got everything worked fine, by myself, but lights are *&@!§$&*. I have to understand them and this can take a long time...

Tanks for all your help. I think some thinks are now clearer. For other I will ask again.. *smile*

Taggi

Share this post


Link to post
Share on other sites
Taggi,

Like I said, lighting is complicated. :-) You just have to take it a step at a time.

You can create a sphere with something like this:

ID3DXMesh* pMesh;
...
pMesh = D3DXCreateSphere(pDevice, 1, 32, 16, &pMesh, NULL);

And to render it:

pMesh->DrawSubset(0);

It''s not very hard, and if you''re learning lighting I think it''s well worth it.

Good luck!

Share this post


Link to post
Share on other sites