PDA

View Full Version : Very weird lighting problem



Brainer
17-05-2008, 07:20 AM
:arrow: System: Windows Vista, Pentium D 2.66GHz, GeForce 7600 GS
:arrow: Compiler/IDE: Delphi 2007 for Win32
:arrow: API: OpenGL

Hello all. :)

I have a very weird problem with lighting in my engine. I mean, I want to set up a sun light, but when I rotate the camera, the objects dissapear. Look at the screenshots.
Before camera rotation
http://i25.tinypic.com/iv8i2q.jpg
After camera rotation
http://i30.tinypic.com/5etuhf.jpg

Here's a bunch of code I use:
Rendering a triangle

glBegin(GL_TRIANGLES);
glNormal3f(0.0, 0.0, 1.0);
glVertex3f(-1.0, -1.0, 1.0);
glVertex3f(1.0, -1.0, 1.0);
glVertex3f(0.0, 1.0, 1.0);
glEnd();


Rendering order

Camera.Apply();
LightManager.ApplyLighting();
Scene.RenderScene();


The light I set up

with LightManager.AddLight() do
begin
LightType := ltDirectional;
Position := AffineVectorMake(0.0, 0.0, 1.0);
end;
LightManager.EnableLighting();


Lighting class

unit UBELight;

interface

uses
Classes, SysUtils,
// -- Headers --
dglOpenGL,
// -- Base Units --
VectorGeometry, VectorTypes,
// -- Engine Units --
UBELogger, UBEUtils;

type
{ .: TLightType :. }
TLightType = (ltSpot, ltPoint, ltDirectional);

{ .; TLightSource :. }
TLightSource = class(TObject)
private
{ Private declarations }
FEnabled: Boolean;
FSpotConstantAtt: Single;
FAmbient: TVector4f;
FLightType: TLightType;
FDiffuse: TVector4f;
FSpecular: TVector4f;
FSpotQuadraticAtt: Single;
FSpotLinearAtt: Single;
FSpotCutoff: Integer;
FSpotDirection: TAffineVector;
FPosition: TAffineVector;
FSpotExponent: Single;
FIndex: Cardinal;
public
{ Public declarations }
constructor Create(const AIndex: Cardinal);

procedure Assign(Source: TLightSource); virtual;

procedure LoadFromStream(S: TStream);
procedure SaveToStream(S: TStream);

property LightType: TLightType read FLightType write FLightType;

property Position: TAffineVector read FPosition write FPosition;
property Ambient: TVector4f read FAmbient write FAmbient;
property Diffuse: TVector4f read FDiffuse write FDiffuse;
property Specular: TVector4f read FSpecular write FSpecular;
//property Emission: TVector4f read FEmission write FEmission;

property SpotCutoff: Integer read FSpotCutoff write FSpotCutoff;
property SpotDirection: TAffineVector read FSpotDirection write FSpotDirection;
property SpotExponent: Single read FSpotExponent write FSpotExponent;

property SpotConstantAtt: Single read FSpotConstantAtt write FSpotConstantAtt;
property SpotLinearAtt: Single read FSpotLinearAtt write FSpotLinearAtt;
property SpotQuadraticAtt: Single read FSpotQuadraticAtt write FSpotQuadraticAtt;

property Index: Cardinal read FIndex;
property Enabled: Boolean read FEnabled write FEnabled;
end;

implementation

{ TLightSource }

procedure TLightSource.Assign(Source: TLightSource);
begin
if Assigned(Source) then
begin
FLightType := Source.LightType;

FPosition := Source.Position;
FAmbient := Source.Ambient;
FDiffuse := Source.Diffuse;
FSpecular := Source.Specular;

FSpotCutoff := Source.SpotCutoff;
FSpotDirection := Source.SpotDirection;
FSpotExponent := Source.SpotExponent;

FSpotConstantAtt := Source.SpotConstantAtt;
FSpotLinearAtt := Source.SpotLinearAtt;
FSpotQuadraticAtt := Source.SpotQuadraticAtt;

FEnabled := Source.Enabled;
end else
Log.Log('Source not assigned.', 'UBELight');
end;

constructor TLightSource.Create(const AIndex: Cardinal);
begin
inherited Create();

FLightType := ltSpot;

FPosition := AffineVectorMake(0.0, 0.0, 0.0);
FAmbient := VectorMake(0.0, 0.0, 0.0, 1.0);
FDiffuse := VectorMake(1.0, 1.0, 1.0, 1.0);
FSpecular := VectorMake(0.0, 0.0, 0.0, 1.0);

FSpotCutoff := 180;
FSpotDirection := AffineVectorMake(0.0, 0.0, -1.0);
FSpotExponent := 0.0;

FSpotConstantAtt := 1.0;
FSpotLinearAtt := 0.0;
FSpotQuadraticAtt := 0.0;

FIndex := AIndex;
FEnabled := True;
end;

procedure TLightSource.LoadFromStream(S: TStream);
begin
S.Read(FLightType, SizeOf(TLightType));

LoadVectorFromStream(FPosition, S);
LoadVectorFromStream(FAmbient, S);
LoadVectorFromStream(FDiffuse, S);
LoadVectorFromStream(FSpecular, S);

S.Read(FSpotCutoff, SizeOf(Integer));
LoadVectorFromStream(FSpotDirection, S);
S.Read(FSpotExponent, SizeOf(Single));

S.Read(FSpotConstantAtt, SizeOf(Single));
S.Read(FSpotLinearAtt, SizeOf(Single));
S.Read(FSpotQuadraticAtt, SizeOf(Single));

S.Read(FIndex, SizeOf(Cardinal));
S.Read(FEnabled, SizeOf(Boolean));
end;

procedure TLightSource.SaveToStream(S: TStream);
begin
S.Write(FLightType, SizeOf(TLightType));

SaveVectorToStream(FPosition, S);
SaveVectorToStream(FAmbient, S);
SaveVectorToStream(FDiffuse, S);
SaveVectorToStream(FSpecular, S);

S.Write(FSpotCutoff, SizeOf(Integer));
SaveVectorToStream(FSpotDirection, S);
S.Write(FSpotExponent, SizeOf(Single));

S.Write(FSpotConstantAtt, SizeOf(Single));
S.Write(FSpotLinearAtt, SizeOf(Single));
S.Write(FSpotQuadraticAtt, SizeOf(Single));

S.Write(FIndex, SizeOf(Cardinal));
S.Write(FEnabled, SizeOf(Boolean));
end;

{ ... }
procedure TLightManager.ApplyLighting;
var
V: TVector4f;
I: Integer;
begin
glPushMatrix();
glLoadIdentity();

for I := 0 to FList.Count -1 do
with TLightSource(FList.Items[I]) do
begin
V[0] := Position[0];
V[1] := Position[1];
V[2] := Position[2];

case LightType of
ltSpot:
begin
V[3] := 1.0;
glLightfv(GL_LIGHT0 + I, GL_POSITION, @V);
glLightfv(GL_LIGHT0 + I, GL_AMBIENT, @Ambient);
glLightfv(GL_LIGHT0 + I, GL_DIFFUSE, @Diffuse);
glLightfv(GL_LIGHT0 + I, GL_SPECULAR, @Specular);

glLightf(GL_LIGHT0 + I, GL_SPOT_CUTOFF, SpotCutoff);
glLightf(GL_LIGHT0 + I, GL_SPOT_EXPONENT, SpotExponent);
glLightfv(GL_LIGHT0 + I, GL_SPOT_DIRECTION, @SpotDirection);

glLightf(GL_LIGHT0 + I, GL_CONSTANT_ATTENUATION, SpotConstantAtt);
glLightf(GL_LIGHT0 + I, GL_LINEAR_ATTENUATION, SpotLinearAtt);
glLightf(GL_LIGHT0 + I, GL_QUADRATIC_ATTENUATION, SpotQuadraticAtt);
end;
ltPoint:
begin
V[3] := 1.0;
glLightfv(GL_LIGHT0 + I, GL_POSITION, @V);
glLightfv(GL_LIGHT0 + I, GL_AMBIENT, @Ambient);
glLightfv(GL_LIGHT0 + I, GL_DIFFUSE, @Diffuse);
glLightfv(GL_LIGHT0 + I, GL_SPECULAR, @Specular);
glLightf(GL_LIGHT0 + I, GL_LINEAR_ATTENUATION, SpotLinearAtt);

glLightf(GL_LIGHT0 + I, GL_SPOT_CUTOFF, SpotCutoff);
end;
ltDirectional:
begin
V[3] := 0.0;
glLightfv(GL_LIGHT0 + I, GL_POSITION, @V);
glLightfv(GL_LIGHT0 + I, GL_DIFFUSE, @Diffuse);
end;
end;
end;

glPopMatrix();
end;


The second triangle is a child of the larger one. Please notice that the child is not lit. What is the problem?

Thanks in advance. :)

JernejL
17-05-2008, 08:53 AM
It looks as if you transform the light source in some errorenous manner.

NecroDOME
17-05-2008, 09:49 AM
this sometimes has to do with moving the light of geometry instead of the camera itself. I didn't look trough your code, but I think this is the problem. Matrix problem. Check those.

User137
17-05-2008, 12:35 PM
What happens if you take out glPushMatrix(); glLoadIdentity(); glPopMatrix(); from TLightManager.ApplyLighting; ? I guess it's the same thing NecroDome and Delfi say.

Also something that can make faces black is if it is considered single sided, as this will ignore lighting calculation on backside. I think some glMaterial or related functions solve that (some GL_FRONT_AND_BACK thing...). Normally every model face should be 1 sided anyway with glEnable(GL_CULL_FACE).

Brainer
17-05-2008, 04:02 PM
Also something that can make faces black is if it is considered single sided, as this will ignore lighting calculation on backside. I think some glMaterial or related functions solve that (some GL_FRONT_AND_BACK thing...). Normally every model face should be 1 sided anyway with glEnable(GL_CULL_FACE).
Yip, that solves the problem. I tried my code on a cube and everything worked properly. Thanks a lot. :)