Jump to content
  • Advertisement
Sign in to follow this  
CatmanFS

OpenGL Strange lighting issues

This topic is 2143 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 was working with a default picker for creating light objects. You would type something like:

 

LIGHT light0(AMBIENT);

 

and it would create an ambient light based off of preset values, and handle the rest of the code elsewhere.

 

The problem is when I was changing up the input variables for the lightfv( GL_AMBIENCE, float* ambience)

I ran into a problem.

 

The scene lighting would only work if the viewing position was somewhere near the origin. It didn't make sence. I messed with attenuation, trying to lower it, raise, it, remove it completely, and it didnt seem to have an effect on this issue.

 

Light just stops working once the camera moves more than just a few units from the origin.

 

Now if you know of this to be some sort of aspect of OpenGL and I'm just missing a line of code somewhere, let me know. if we're not so lucky keep reading for a few samples of the code and a the details of when this started happening.

 

 

Now the code for the light is something liek this

 

class LIGHT

{

 

vector3 pos;

color ambience;

color diffuse;

color specular

 

float shine;

float attenuation;

 

LIGHT(LIGHT_PRESET);

void Enable()

void Update()

 

};

 

I'm using a color code like this:

 

struct color

{

      float r, g, b, a;

      void Set(float, float, float);

      float* pFloat(); // this returns an array of 4 numbers like the ones the light needs as input

};

 

float* color::pFloat()

{

       float floater[] = {r, g, b, a};

      return floater;

};

 

the vector code for light positioning works similarly

 

struct vector3

{

     float x, y, z;

     void Set(float, float, float);

     float* pFloat();

};

 

float* color:pFloat()

{

       float floater[] = {x, y, z};

       return floater;

};

 

 

And the light takes those values as such

 

   glLightfv(ID, GL_POSITION, position.pFloat());
   glLightfv(ID, GL_DIFFUSE, diffuse.pFloat());   
   glLightfv(ID, GL_AMBIENT, ambient.pFloat()); 

 

The picker works, there was no problem there, but when I tried to change from setting the color values from this:

 

color[0] = .5;

color[1] = .2;

color[2] = .7;

 

position[0] = 10;

position[1] = 15;

position[0] = 10;

 

to something better like this

 

color.Set(.5, .2, .7);

position.Set(10, 15, 10);

 

The structs for color and position have functions to easily set themselves, and also produce the float* number array that openGl likes to use for it's light and position color values.

 

I got this working, and I've used this concept many times, but I ran into this other lighting problem that I just don't understand.

 

At first it seemed like it wasn't getting the correct positional values and just placing the lights at some far distance place,

then i noticed that it was placing them directly at the center, inside the test object I'm using to work with the lighting.

 

I output the values that would be directly sent into the openGl position input, and found them to be fine.

 

Does anyone have any idea why this is happening?

 

Share this post


Link to post
Share on other sites
Advertisement

I don't know if it is related to your problem or not, but if this is C++ code then your pFloat() functions are wrong. You are returning the address of a local array which becomes invalid as soon as the function has returned, so you are passing an invalid pointer to OpenGL. You should fix that whether it is related to your lighting problem or not.

Share this post


Link to post
Share on other sites

and also produce the float* number array that openGl likes to use for it's light and position color values.

Except that it does so by taking the address of a temporary.
 
It should be:
float* vector3::pFloat() {
    return reinterpret_cast<float *>(this);
}
Same with colors.

Also, one of the many reasons you should never touch fixed-function OpenGL is because it pre-multiplies light positions (for one) with the model-view matrix when you set them, forcing you to update them carefully (set the model-view matrix to identity first) each frame.


L. Spiro Edited by L. Spiro

Share this post


Link to post
Share on other sites

I changed the update light code to this:

 

    float amb[] = {5, 5, 5};
    glLightfv(light->ID, GL_POSITION, amb );

 

and excluded this:
    //glLightfv(light->ID, GL_POSITION, light->position.pFloat());

 

and it works. The problem is that I need to pull the info from the *light that the update function uses as input

 

is there something wrong with using:

 

UpdateLight( LIGHT *light)

 

and the pulling the info using:

 

light->position.pFloat();   // pFloat() returns a pointer to an array of { x, y, z} stored in the vector3

 

Could be that since it uses a pointer to the light struct, and then a pointer to the vector3 struct that somehow the actual data struct gets lost.

I'm still confused as to why the light only works near the origin with this implementation.

 

Any thoughts?

Share this post


Link to post
Share on other sites

Ahah you saved my life. I'm still a little confused about the matrix multiplying the light positions.

 

Right now, the UpdateAllLights() happens after the modelview matrix has been established.

 

Where would you reccomend that this be placed?

Share this post


Link to post
Share on other sites

is there something wrong with using:
 
UpdateLight( LIGHT *light)
 
and the pulling the info using:
 
light->position.pFloat();   // pFloat() returns a pointer to an array of { x, y, z} stored in the vector3

Yes there is something wrong with it. Brother Bob and I both just told you you are returning an address of a temporary.
Meaning you are not returning a pointer to a valid vector3, you are returning a pointer to garbage. The value to which it points is on the stack and will be overwritten on every function call, possibly even on function exit (it is undefined data on exit so the compiler can do anything it wants).
Make a method and pass the return value as a pointer of type GLfloat. Fill in the values on that pointer and return. Your method of overloading operators simply does not work.


Where would you reccomend that this be placed?

Somewhere just prior to rendering with a given camera.


L. Spiro

Share this post


Link to post
Share on other sites

I had started typing that before you had replied. Thanks again for the help. The reinterpret cast thing is new to me. I've been doing all of that manually, and it's been a real pain. Most of the C++  books I have are >10 years old, and they don't go into alot of detail about stuff like that. Mostly strings and array pointers. I'll do a little research into the methods of overloading operators and such. Thanks again for the help.

 

Got another question. i've got 3 lights, with ambient and diffuse values set around .8 -> .9 and the scene is very dark looking. There's light, but it's not really like the lighting I'm used to. I tried to bump the ambient values up to 10 and it didn't seem to have an effect. Any ideas?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!