Specularity implementation

Started by
11 comments, last by amtri 16 years, 10 months ago
Hello, I'm trying to add specularity to my scenes, but they are not coming out as I expected. The code is rather big, but the important calls I'm making are as follows: device->SetRenderState(D3DRS_SPECULARMATERIALSOURCE,D3DMCS_MATERIAL); device->SetRenderState(D3DRS_SPECULARENABLE,TRUE); Then I add a POINT light. I have the following parameters to *play* with: light.Specular.[rgba] material.Specular.[rgba] material.Power However, no matter how I change these parameters, nothing seems to change the specularity's appearance. I was looking for a very bright white highlight, but even if I set material.Specular.[rgba] to zero (all components), I still see the same specularity effect. Does anybody know how I can control the specularity to provide for a very strong highlight? Thanks. amtri
Advertisement
I believe that the fixed function specular highlights are calculated per vertex so the poly count could be a problem if it is too low.Also an issue could be the distance between the object being lit and the point light,the SDK docs say the distance between them should be "relatively large".Hope this helps..
Best Regards,Radu
RayTracer,

I'm not sure this is the problem. Although I know that comparing OpenGL to Direct3D is very much implementation dependent or, in other words, comparing apples and oranges, I do have the same equivalent code already written in OpenGL on the same geometry, same everything else, and I can get the result I want in OpenGL.

That's why I'm wondering whether there's some obscure flag I'm not familiar with in Direct3D, or some default value that needs to be changed somewhere in order to accomplish this.

Thanks.
The following steps are required for specular lighting (correct me if i'm wrong)
:

- create a material
- set material specular properties (color ,power)
- create a light
- set light properties (color ,direction ,type,falloff,attenuation,range and specular properties)
- set the light
- enable light
- set D3DRS_SPECULARENABLE to TRUE
- set material
- set D3DRS_SPECULARMATERIALSOURCE to D3DMCS_MATERIAL
- draw

Are you following all these steps?

Best Regards,Radu
D3DRS_LOCALVIEWER is another specular related option.
Specular is going to be more affected by non-unit vectors than diffuse lighting, so D3DRS_NORMALIZENORMALS may be useful too.

When your color is all 0, I'd expect you to see no specularity. The highlight amount is multiplied by the light's specular color and material's specular color. If any one of them is 0, you should get no specular. Your original post is implying that you're seeing some effect, even when the color is set to black. To me that means you're never actually setting the material, or the material is being overwritten somewhere else before rendering.

All of this no longer applies if you're using a vertex shader, which we're assuming you aren't.

Does your point light diffuse color affect the object correctly? If so, that would imply you're setting up the light fine (ie: attenuation, range, etc.)
I AM using a vertex shader (at least I believe I am).

My geometry is all defined with D3DFVF_DIFFUSE|D3DFVF_XYZ|D3DFVF_NORMAL. Sometimes I also have texture coordinates, and sometimes I use D3DFVF_XYZRHW instead of D3DFVF_XYZ.

I do NOT have D3DFVF_SPECULAR added anywhere, relying instead on using the material through the call

device->SetRenderState(D3DRS_SPECULARMATERIALSOURCE,D3DMCS_MATERIAL);

Then I set the material.Specular.[rgba] to 1.0 on every component. The light is set with light.Specular.[rgba] to some color.

I just ran some tests. It turns out that I get the same result whether SPECULAREABLE is TRUE or FALSE. So, obviously, specularity is not present.

You don't need D3DFVF_SPECULAR for normal geometry unless you want color values per vertex.

D3DFVF_XYZRHW is for pre-transformed geometry. It will skip all transforms, lighting, fogging, vertex shaders, etc and go straight to the rasterizer and pixel shader. If you want specular on pre-transformed geometry, it will need D3DFVF_SPECULAR.

If you are using a vertex shader (note: SetVertexShader with an FVF code in DX8 doesn't count as a shader), then it's completely different.

When using a shader, material settings, light settings, and many render states are completely ignored. You must handle lighting yourself, in your shader. You must create variables to hold your light and material data in the shader. You must include math to calculate the amount of light, you must manually apply the specular power, and manually mix with material and light colors. You must have your app setup the material and light variables for the shader, rather than using the normal calls for the fixed pipeline.

I think in OpenGL they provide a way to refer to the OpenGL light states in the shader. In D3D you must handle this all yourself.
I'm only using pre-transformed geometry in special circumstances. For example, if I need to add a thickness to my lines, with z-buffering, then I pre-transform to screen coordinates, and make the line thicker replicating the line one pixel up or to the right, depending on the line's inclination. Most of the time it is not pretransformed.

So I'm not using a vertex shader. That's good.

Maybe my issue is the definition of the light itself. I've changed it to a directional light, as it's easier to debug with.

Thanks.
Radu,

My apologies for the delay in replying. I AM following all the steps you mentioned above.

amtri
I have an update, although I'm not entirely clear. The issue is material.Power.

My past experience with specularity came from OpenGL, from GL_SHININESS which, according to the documentation I've seen, stands for the power in an identical formula as that presented in the Direct3D documentation.

I finally can see some specularity, but I have 2 issues if somebody could help me:

1) Is GL_SHININESS the same as material.Power? I thought this was the case, but it turns out that in order to see the specularity band I had to set the material.Power much SMALLER than what I used in GL_SHININESS. I would like to know how they correlate to each other.

2) Now the tough part:

- I'm using an orthogonal projection, so there's no distortion coming from perspective.
- I'm drawing a perfect cylinder with uniform color
- I'm using a directional light
- According to the formulas for specularity, and given the fact that along a "vertical geodesic (i.e., perpendicular to the circular base)" on the cylinder all normals are identical, I would expect the effect of the specularity to be the same along these lines. But that's not the case: the specularity is stronger at one end of the cylinder then on the other end.

Any thoughts on this?

Thanks.

This topic is closed to new replies.

Advertisement