2013-07-13 5 views
0

질문이 번역자에 의해 작성되었으므로 필자는 정형 적으로 올바른지 잘 모릅니다. OpenGL을 배우기 시작하면서 다음과 같은 문제가 발생했습니다. 큐브를 회전 시키면 빛도 회전합니다. 모든 프레임에서 빛의 좌표를 변경하려했지만 도움이되지 않았습니다. 말해주십시오 : 무엇이 잘못 됐습니까. 문제가 아니라면 수정 된 버전이 될 수 있습니다.델파이와 OpenGL : 빛이 큐브와 함께 회전 함

코드 :

unit MainUnit; 

interface 

uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,  Vcl.Graphics, 
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs,dglOpenGL,dglut; 

type 
    TFMainForm = class(TForm) 
    procedure FormCreate(Sender: TObject); 
    procedure FormResize(Sender: TObject); 
    procedure FormDestroy(Sender: TObject); 
    procedure FormKeyPress(Sender: TObject; var Key: Char); 
    private 

    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); 
    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; 
var i:integer; 
begin 
    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity; 
    gluPerspective(45.0,ClientWidth/ClientHeight,NearClipping,FarClipping); 
    glTranslatef(0,0,-5); 

    glPushMatrix; 
    glRotatef(XRot,1,0,0); 
    uzglCube; 
    glPopMatrix; 

    glLightfv(GL_LIGHT0, GL_POSITION,@LightPos); 

    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); 
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); 
glMatrixMode(GL_MODELVIEW); 
glLoadIdentity; 

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; 
end; 
end; 

end. 

dglOpenGL : http://wiki.delphigl.com/index.php/dglOpenGL.pas/en

답변

6

내가 틀려서 몇 가지를 발견 할 수 있습니다.

첫째로 : 귀하의 법선이 일치하지 않습니다.

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_PROJECTION 매트릭스에서 입방체를 변형하고 있습니다. GL_PROJECTION 행렬에는 투영법을 설정하는 데 필요한 요소 만 포함되어야합니다.

큐브 & 큐브는 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; 

GL_MODELVIEW 매트릭스는 SetupGL proc에서 설정할 수 있습니다. 뷰를 (-2,3, -3)에서 (0,0,0)으로 설정하는 gluLookAt() 명령에 주목하십시오. gluLookAt (0, 3, -3, 0,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; 

Render Proc가됩니다.

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; 

참고 : 나는 그들이 변환됩니다으로 GL_MODELVIEW 매트릭스는 원래의 뒷면에 '펑'후 그렇지 않으면 빛이 회전하지 않는 경우는 true하면 큐브 빛을 회전하는 개인 양식 변수 FTransformLights을 추가 한 상태 (신분).

나는 '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. 
+0

답장을 보내 주셔서 감사합니다. 이제 내 프로그램은 훌륭하게 작동합니다. – proggamer12