Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
delphi和opengl:灯光随立方体旋转_Delphi_Opengl_Rotation_Lighting - Fatal编程技术网

delphi和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);

这个问题是由译者写的,所以我不知道它的拼写是否正确。 我开始学习Opengl,遇到了以下问题:当我旋转立方体时,光线也会旋转。我试图改变每一帧中光线的坐标,但没用。 告诉我:出了什么问题。 如果没有麻烦,可能会导致修改版本

代码:


德格洛佩格尔:

我发现有两件事不对劲

第一:你的法线不一致。改为

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.