delphi和opengl:灯光随立方体旋转
这个问题是由译者写的,所以我不知道它的拼写是否正确。 我开始学习Opengl,遇到了以下问题:当我旋转立方体时,光线也会旋转。我试图改变每一帧中光线的坐标,但没用。 告诉我:出了什么问题。 如果没有麻烦,可能会导致修改版本 代码:delphi和opengl:灯光随立方体旋转,delphi,opengl,rotation,lighting,Delphi,Opengl,Rotation,Lighting,这个问题是由译者写的,所以我不知道它的拼写是否正确。 我开始学习Opengl,遇到了以下问题:当我旋转立方体时,光线也会旋转。我试图改变每一帧中光线的坐标,但没用。 告诉我:出了什么问题。 如果没有麻烦,可能会导致修改版本 代码: 德格洛佩格尔:我发现有两件事不对劲 第一:你的法线不一致。改为 FrontNormal: TGLvectorf3=(0,0,1); BackNormal: TGLvectorf3 =(0,0,-1); LeftNormal: TGLvectorf3 =(1,0,0);
德格洛佩格尔:我发现有两件事不对劲 第一:你的法线不一致。改为
FrontNormal: TGLvectorf3=(0,0,1);
BackNormal: TGLvectorf3 =(0,0,-1);
LeftNormal: TGLvectorf3 =(1,0,0);
RightNormal: TGLvectorf3=(-1,0,0);
UpNormal: TGLvectorf3 =(0,-1,0);
DownNormal: TGLvectorf3 =(0,1,0);
第二:在GL_投影矩阵中变换立方体。GL_投影矩阵应仅包含设置投影所需的内容
立方体和灯光应通过GL_MODELVIEW矩阵进行变换
只有当窗口大小改变时,投影才会改变,因此,它可以进入FormResize事件
procedure TForm2.FormResize(Sender: TObject);
var tmpBool:boolean;
begin
glViewport(0,0,ClientWidth,ClientHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
gluPerspective(45.0,ClientWidth/ClientHeight,NearClipping,FarClipping);
idleHandler(Sender, tmpBool);
end;
可以在SetupGL proc中设置GL_模型视图矩阵。
请注意gluLookAt()命令,该命令设置从(-2,3,-3)到(0,0,0)的视图。设置gluLookAt(0,3,-3,0,0,0,1,0);有一个“正面”的观点
procedure TForm2.SetupGL;
begin
glClearColor(0.3,0.4,0.7,0.0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_SMOOTH);
glDepthFunc(GL_LEQUAL);
glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity;
gluLookAt(-2, 3, -3, 0,0,0, 0,1,0);
uzglLightEnable;
LightPos[0]:=0;
LightPos[1]:=0;
LightPos[2]:=1;
LightPos[3]:=1;
end;
渲染过程变为
procedure TForm2.Render;
var i:integer;
begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glPushMatrix;
glRotatef(XRot,1,0,0);
uzglCube;
if FTransformLights then
begin
glLightfv(GL_LIGHT0, GL_POSITION,@LightPos);
glPopMatrix;
end
else
begin
glPopMatrix;
glLightfv(GL_LIGHT0, GL_POSITION,@LightPos);
end;
SwapBuffers(dc);
XRot:=XRot+1;
end;
注意:我添加了一个私有形式变量ftTransformLights,如果为true,则会随立方体旋转灯光,否则在GL_MODELVIEW矩阵“弹出”回其原始状态(标识)后,灯光在变换时不会旋转
我添加了“x”键来切换灯光是否旋转。
下面是完整的修改列表。希望这能解决问题
unit MainUnit;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs,dglOpenGL;
type
TFMainForm = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormResize(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormKeyPress(Sender: TObject; var Key: Char);
private
FTransformLights:Boolean;
procedure SetupGL;
procedure uzglLightEnable;
procedure IdleHandler(Sender : TObject; var Done : Boolean);
public
procedure Render;
end;
var
FMainForm: TFMainForm;
dc:hdc;
hrc:hglrc;
XRot,YRot,ZRot:Single;
LightPos:TGLArrayf4;
BlueArray:TGLArrayf4;
GreenArray:TGLArrayf4;
myTex: glUint;
FrontNormal: TGLvectorf3=(0,0,1);
BackNormal: TGLvectorf3 =(0,0,-1);
LeftNormal: TGLvectorf3 =(1,0,0);
RightNormal: TGLvectorf3=(-1,0,0);
UpNormal: TGLvectorf3 =(0,-1,0);
DownNormal: TGLvectorf3 =(0,1,0);
FrontDownLeft :TGLvectorf3 = (-1,-1,-1);
FrontDownRight:TGLvectorf3 = (1,-1,-1);
FrontUpLeft :TGLvectorf3 = (-1,1,-1);
FrontUpRight :TGLvectorf3 = (1,1,-1);
BackDownLeft :TGLvectorf3 = (-1,-1,1);
BackDownRight:TGLvectorf3 = (1,-1,1);
BackUpLeft :TGLvectorf3 = (-1,1,1);
BackUpRight :TGLvectorf3 = (1,1,1);
const
NearClipping = 0.1;
FarClipping = 200;
procedure uzglTriangle(x1,y1,z1,x2,y2,z2,x3,y3,z3:single);
procedure uzglCube;
implementation
{$R *.dfm}
procedure uzglTriangle(x1,y1,z1,x2,y2,z2,x3,y3,z3:single);
begin
glBegin(GL_TRIANGLES);
glColor3f(0.3,0,0);glVertex3f(x1,y1,z1);
glColor3f(0.25,1,0);glVertex3f(x2,y2,z2);
glColor3f(0.7,0,1);glVertex3f(x3,y3,z3);
glEnd;
end;
procedure uzglCube;
begin
glBegin(GL_QUADS);
// Beginning of front
glNormal3fv(@FrontNormal);
glVertex3fv(@FrontDownLeft);
glVertex3fv(@FrontDownRight);
glVertex3fv(@FrontUpRight);
glVertex3fv(@FrontUpLeft);
// End of front
glEnd;
glBegin(GL_QUADS);
// Beginning of left
glNormal3fv(@LeftNormal);
glVertex3fv(@FrontDownLeft);
glVertex3fv(@FrontUpLeft);
glVertex3fv(@BackUpLeft);
glVertex3fv(@BackDownLeft);
// End of left
glEnd;
glBegin(GL_QUADS);
// Beginning of right
glNormal3fv(@RightNormal);
glVertex3fv(@FrontDownRight);
glVertex3fv(@FrontUpRight);
glVertex3fv(@BackUpRight);
glVertex3fv(@BackDownRight);
// End of right
glEnd;
glBegin(GL_QUADS);
// Beginning of up
glNormal3fv(@UpNormal);
glVertex3fv(@FrontUpRight);
glVertex3fv(@FrontUpLeft);
glVertex3fv(@BackUpLeft);
glVertex3fv(@BackUpRight);
// End of up
glEnd;
glBegin(GL_QUADS);
// Beginning of down
glNormal3fv(@DownNormal);
glVertex3fv(@FrontDownRight);
glVertex3fv(@FrontDownLeft);
glVertex3fv(@BackDownLeft);
glVertex3fv(@BackDownRight);
// End of down
glEnd;
glBegin(GL_QUADS);
// Beginning of back
glNormal3fv(@BackNormal);
glVertex3fv(@BackDownLeft);
glVertex3fv(@BackDownRight);
glVertex3fv(@BackUpRight);
glVertex3fv(@BackUpLeft);
// End of back
glEnd;
end;
procedure TFMainForm.SetupGL;
begin
glClearColor(0.3,0.4,0.7,0.0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_SMOOTH);
glDepthFunc(GL_LEQUAL);
glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity;
gluLookAt(-2, 3, -3, 0,0,0, 0,1,0);
uzglLightEnable;
LightPos[0]:=0;
LightPos[1]:=0;
LightPos[2]:=1;
LightPos[3]:=1;
end;
procedure TFMainForm.uzglLightEnable;
begin
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
end;
procedure TFMainForm.Render;
begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glPushMatrix;
glRotatef(XRot,1,0,0);
uzglCube;
if FTransformLights then
begin
glLightfv(GL_LIGHT0, GL_POSITION,@LightPos);
glPopMatrix;
end
else
begin
glPopMatrix;
glLightfv(GL_LIGHT0, GL_POSITION,@LightPos);
end;
SwapBuffers(dc);
XRot:=XRot+1;
end;
procedure TFMainForm.IdleHandler(Sender : TObject; var Done : Boolean);
begin
Render;
Sleep(25);
Done:=false;
end;
procedure TFMainForm.FormCreate(Sender: TObject);
begin
dc:=GetDC(Handle);
if not InitOpenGL then
begin
ShowMessage('????????... ????????????? ???????????');
Application.Terminate;
end;
hrc:=CreateRenderingContext (dc,
[opDoubleBuffered],
32,
24,
8,
0,
0,
0);
ActivateRenderingContext(dc,hrc);
FTransformLights:=false;
SetupGL;
Application.OnIdle:=IdleHandler;
FMainForm.OnResize(self);
end;
procedure TFMainForm.FormResize(Sender: TObject);
var tmpBool:boolean;
begin
glViewport(0,0,ClientWidth,ClientHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
gluPerspective(45.0,ClientWidth/ClientHeight,NearClipping,FarClipping);
idleHandler(Sender, tmpBool);
end;
procedure TFMainForm.FormDestroy(Sender: TObject);
begin
DeactivateRenderingContext;
DestroyRenderingContext(hrc);
ReleaseDC(Handle,dc);
end;
procedure TFMainForm.FormKeyPress(Sender: TObject; var Key: Char);
begin
case key of
'q':LightPos[0]:=LightPos[0]+0.1;
'a':LightPos[0]:=LightPos[0]-0.1;
'w':LightPos[1]:=LightPos[1]+0.1;
's':LightPos[1]:=LightPos[1]-0.1;
'e':LightPos[2]:=LightPos[2]+0.1;
'd':LightPos[2]:=LightPos[2]-0.1;
'x':FTransformLights:=NOT FTransformLights;
end;
end;
end.
我发现有两件事不对劲 第一:你的法线不一致。改为
FrontNormal: TGLvectorf3=(0,0,1);
BackNormal: TGLvectorf3 =(0,0,-1);
LeftNormal: TGLvectorf3 =(1,0,0);
RightNormal: TGLvectorf3=(-1,0,0);
UpNormal: TGLvectorf3 =(0,-1,0);
DownNormal: TGLvectorf3 =(0,1,0);
第二:在GL_投影矩阵中变换立方体。GL_投影矩阵应仅包含设置投影所需的内容
立方体和灯光应通过GL_MODELVIEW矩阵进行变换
只有当窗口大小改变时,投影才会改变,因此,它可以进入FormResize事件
procedure TForm2.FormResize(Sender: TObject);
var tmpBool:boolean;
begin
glViewport(0,0,ClientWidth,ClientHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
gluPerspective(45.0,ClientWidth/ClientHeight,NearClipping,FarClipping);
idleHandler(Sender, tmpBool);
end;
可以在SetupGL proc中设置GL_模型视图矩阵。
请注意gluLookAt()命令,该命令设置从(-2,3,-3)到(0,0,0)的视图。设置gluLookAt(0,3,-3,0,0,0,1,0);有一个“正面”的观点
procedure TForm2.SetupGL;
begin
glClearColor(0.3,0.4,0.7,0.0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_SMOOTH);
glDepthFunc(GL_LEQUAL);
glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity;
gluLookAt(-2, 3, -3, 0,0,0, 0,1,0);
uzglLightEnable;
LightPos[0]:=0;
LightPos[1]:=0;
LightPos[2]:=1;
LightPos[3]:=1;
end;
渲染过程变为
procedure TForm2.Render;
var i:integer;
begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glPushMatrix;
glRotatef(XRot,1,0,0);
uzglCube;
if FTransformLights then
begin
glLightfv(GL_LIGHT0, GL_POSITION,@LightPos);
glPopMatrix;
end
else
begin
glPopMatrix;
glLightfv(GL_LIGHT0, GL_POSITION,@LightPos);
end;
SwapBuffers(dc);
XRot:=XRot+1;
end;
注意:我添加了一个私有形式变量ftTransformLights,如果为true,则会随立方体旋转灯光,否则在GL_MODELVIEW矩阵“弹出”回其原始状态(标识)后,灯光在变换时不会旋转
我添加了“x”键来切换灯光是否旋转。
下面是完整的修改列表。希望这能解决问题
unit MainUnit;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs,dglOpenGL;
type
TFMainForm = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormResize(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormKeyPress(Sender: TObject; var Key: Char);
private
FTransformLights:Boolean;
procedure SetupGL;
procedure uzglLightEnable;
procedure IdleHandler(Sender : TObject; var Done : Boolean);
public
procedure Render;
end;
var
FMainForm: TFMainForm;
dc:hdc;
hrc:hglrc;
XRot,YRot,ZRot:Single;
LightPos:TGLArrayf4;
BlueArray:TGLArrayf4;
GreenArray:TGLArrayf4;
myTex: glUint;
FrontNormal: TGLvectorf3=(0,0,1);
BackNormal: TGLvectorf3 =(0,0,-1);
LeftNormal: TGLvectorf3 =(1,0,0);
RightNormal: TGLvectorf3=(-1,0,0);
UpNormal: TGLvectorf3 =(0,-1,0);
DownNormal: TGLvectorf3 =(0,1,0);
FrontDownLeft :TGLvectorf3 = (-1,-1,-1);
FrontDownRight:TGLvectorf3 = (1,-1,-1);
FrontUpLeft :TGLvectorf3 = (-1,1,-1);
FrontUpRight :TGLvectorf3 = (1,1,-1);
BackDownLeft :TGLvectorf3 = (-1,-1,1);
BackDownRight:TGLvectorf3 = (1,-1,1);
BackUpLeft :TGLvectorf3 = (-1,1,1);
BackUpRight :TGLvectorf3 = (1,1,1);
const
NearClipping = 0.1;
FarClipping = 200;
procedure uzglTriangle(x1,y1,z1,x2,y2,z2,x3,y3,z3:single);
procedure uzglCube;
implementation
{$R *.dfm}
procedure uzglTriangle(x1,y1,z1,x2,y2,z2,x3,y3,z3:single);
begin
glBegin(GL_TRIANGLES);
glColor3f(0.3,0,0);glVertex3f(x1,y1,z1);
glColor3f(0.25,1,0);glVertex3f(x2,y2,z2);
glColor3f(0.7,0,1);glVertex3f(x3,y3,z3);
glEnd;
end;
procedure uzglCube;
begin
glBegin(GL_QUADS);
// Beginning of front
glNormal3fv(@FrontNormal);
glVertex3fv(@FrontDownLeft);
glVertex3fv(@FrontDownRight);
glVertex3fv(@FrontUpRight);
glVertex3fv(@FrontUpLeft);
// End of front
glEnd;
glBegin(GL_QUADS);
// Beginning of left
glNormal3fv(@LeftNormal);
glVertex3fv(@FrontDownLeft);
glVertex3fv(@FrontUpLeft);
glVertex3fv(@BackUpLeft);
glVertex3fv(@BackDownLeft);
// End of left
glEnd;
glBegin(GL_QUADS);
// Beginning of right
glNormal3fv(@RightNormal);
glVertex3fv(@FrontDownRight);
glVertex3fv(@FrontUpRight);
glVertex3fv(@BackUpRight);
glVertex3fv(@BackDownRight);
// End of right
glEnd;
glBegin(GL_QUADS);
// Beginning of up
glNormal3fv(@UpNormal);
glVertex3fv(@FrontUpRight);
glVertex3fv(@FrontUpLeft);
glVertex3fv(@BackUpLeft);
glVertex3fv(@BackUpRight);
// End of up
glEnd;
glBegin(GL_QUADS);
// Beginning of down
glNormal3fv(@DownNormal);
glVertex3fv(@FrontDownRight);
glVertex3fv(@FrontDownLeft);
glVertex3fv(@BackDownLeft);
glVertex3fv(@BackDownRight);
// End of down
glEnd;
glBegin(GL_QUADS);
// Beginning of back
glNormal3fv(@BackNormal);
glVertex3fv(@BackDownLeft);
glVertex3fv(@BackDownRight);
glVertex3fv(@BackUpRight);
glVertex3fv(@BackUpLeft);
// End of back
glEnd;
end;
procedure TFMainForm.SetupGL;
begin
glClearColor(0.3,0.4,0.7,0.0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_SMOOTH);
glDepthFunc(GL_LEQUAL);
glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity;
gluLookAt(-2, 3, -3, 0,0,0, 0,1,0);
uzglLightEnable;
LightPos[0]:=0;
LightPos[1]:=0;
LightPos[2]:=1;
LightPos[3]:=1;
end;
procedure TFMainForm.uzglLightEnable;
begin
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
end;
procedure TFMainForm.Render;
begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glPushMatrix;
glRotatef(XRot,1,0,0);
uzglCube;
if FTransformLights then
begin
glLightfv(GL_LIGHT0, GL_POSITION,@LightPos);
glPopMatrix;
end
else
begin
glPopMatrix;
glLightfv(GL_LIGHT0, GL_POSITION,@LightPos);
end;
SwapBuffers(dc);
XRot:=XRot+1;
end;
procedure TFMainForm.IdleHandler(Sender : TObject; var Done : Boolean);
begin
Render;
Sleep(25);
Done:=false;
end;
procedure TFMainForm.FormCreate(Sender: TObject);
begin
dc:=GetDC(Handle);
if not InitOpenGL then
begin
ShowMessage('????????... ????????????? ???????????');
Application.Terminate;
end;
hrc:=CreateRenderingContext (dc,
[opDoubleBuffered],
32,
24,
8,
0,
0,
0);
ActivateRenderingContext(dc,hrc);
FTransformLights:=false;
SetupGL;
Application.OnIdle:=IdleHandler;
FMainForm.OnResize(self);
end;
procedure TFMainForm.FormResize(Sender: TObject);
var tmpBool:boolean;
begin
glViewport(0,0,ClientWidth,ClientHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
gluPerspective(45.0,ClientWidth/ClientHeight,NearClipping,FarClipping);
idleHandler(Sender, tmpBool);
end;
procedure TFMainForm.FormDestroy(Sender: TObject);
begin
DeactivateRenderingContext;
DestroyRenderingContext(hrc);
ReleaseDC(Handle,dc);
end;
procedure TFMainForm.FormKeyPress(Sender: TObject; var Key: Char);
begin
case key of
'q':LightPos[0]:=LightPos[0]+0.1;
'a':LightPos[0]:=LightPos[0]-0.1;
'w':LightPos[1]:=LightPos[1]+0.1;
's':LightPos[1]:=LightPos[1]-0.1;
'e':LightPos[2]:=LightPos[2]+0.1;
'd':LightPos[2]:=LightPos[2]-0.1;
'x':FTransformLights:=NOT FTransformLights;
end;
end;
end.