Sign in to follow this  

Specularity implementation

This topic is 3848 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

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

Share this post


Link to post
Share on other sites
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..

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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.)

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
I don't know GL, but some quick googling, while not completely conclusive, looks like GL_SHININESS should be the same as power.

I would expect the falloff in the highlight. Specular is based on a reflection, not just the normal. Imagine you're looking at straight at a flat quad, centered. While all the normals will point exactly along Z back at the camera, the reflection vectors will not. The pixel in the middle of the screen will reflect straight back, while the ones towards the edge will reflect at an angle.

-------------
| | |
| | |
V V V
normals all point same way.



-------------
.
. .
. REFLECTION (varying vector at each point on the polygon)
CAM

The result here is that on a flat wall you'll only see a highlight near where the reflection and light direction are the same.

D3DRS_LOCALVIEWER can be used to change how the reflection is calculated. They suggest changing it when using ortho projection, which may give you the result you're expecting. I'm not really sure what exactly it does.

Share this post


Link to post
Share on other sites
Thanks for the confirmation on the GL_SHININESS parameter. I also thought it was the same thing from the documentation, but it doesn't seem to behave the same way.

As for the falloff, I'm not sure I agree with your derivation. Here are my thoughts:

1) Your example of using a a quad being looked straight on is good, so let's stick to that.

2) If my light is directional - not a point light - then every point on the quad will receive light at the same angle. And the agle with the normal is the same for all points on the quad. If I'm using an orthogonal projection, where in the x-y plane the viewer is is imaterial, so the quad should shine equally on all points. Of course, if I change the angle of the incident light, the specularity will change, but it should change equally for all points, so all pixels on the quad should have the same intensity.

I'll try to set something up for this example to test this out. Like I said, you suggested a simple it great example to test this out.

amtri

Share this post


Link to post
Share on other sites
Namethatnobodyelsetook,

You were right! The way I was thinking implied that LOCALVIEWER was set to off, which I had not set. Once I did set LOCALVIEWER to off, then everything started behaving as I expected.

Thanks!

amtri

Share this post


Link to post
Share on other sites

This topic is 3848 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this