Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Корректировка положения света и нормалей для правильного освещения вращающегося куба в Delphi

Delphi , Графика и Игры , OpenGL

delphi and opengl: light is rotating with the cube

Оригинальный заголовок:

delphi and opengl: light is rotating with the cube

Описание проблемы (вопрос):

Вопрос был переведен, так что я не знаю, верно ли он орфографически. Я начал изучать 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);

glNormal3fv(@FrontNormal);

glVertex3fv(@FrontDownLeft);

glVertex3fv(@FrontDownRight);

glVertex3fv(@FrontUpRight);

glVertex3fv(@FrontUpLeft);

glEnd;

glBegin(GL_QUADS);

glNormal3fv(@LeftNormal);

glVertex3fv(@FrontDownLeft);

glVertex3fv(@FrontUpLeft);

glVertex3fv(@BackUpLeft);

glVertex3fv(@BackDownLeft);

glEnd;

glBegin(GL_QUADS);

glNormal3fv(@RightNormal);

glVertex3fv(@FrontDownRight);

glVertex3fv(@FrontUpRight);

glVertex3fv(@BackUpRight);

glVertex3fv(@BackDownRight);

glEnd;

glBegin(GL_QUADS);

glNormal3fv(@UpNormal);

glVertex3fv(@FrontUpRight);

glVertex3fv(@FrontUpLeft);

glVertex3fv(@BackUpLeft);

glVertex3fv(@BackUpRight);

glEnd;

glBegin(GL_QUADS);

glNormal3fv(@DownNormal);

glVertex3fv(@FrontDownRight);

glVertex3fv(@FrontDownLeft);

glVertex3fv(@BackDownLeft);

glVertex3fv(@BackDownRight);

glEnd;

glBegin(GL_QUADS);

glNormal3fv(@BackNormal);

glVertex3fv(@BackDownLeft);

glVertex3fv(@BackDownRight);

glVertex3fv(@BackUpRight);

glVertex3fv(@BackUpLeft);

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

Подтвержденный ответ:

Итак, я вижу несколько проблем в вашем коде.

Во-первых, ваши нормали некорректны. Измените их на следующее:

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. Обратите внимание на команду gluLookAt(), которая устанавливает вид от (-2, 3, -3) к (0, 0, 0). Установите 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 становится следующей.

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;

Примечание: Я добавил приватную форму FTransformLights, которая, если 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);

glNormal3fv(@FrontNormal);

glVertex3fv(@FrontDownLeft);

glVertex3fv(@FrontDownRight);

glVertex3fv(@FrontUpRight);

glVertex3fv(@FrontUpLeft);

glEnd;

glBegin(GL_QUADS);

glNormal3fv(@LeftNormal);

glVertex3fv(@FrontDownLeft);

glVertex3fv(@FrontUpLeft);

glVertex3fv(@BackUpLeft);

glVertex3fv(@BackDownLeft);

glEnd;

glBegin(GL_QUADS);

glNormal3fv(@RightNormal);

glVertex3fv(@FrontDownRight);

glVertex3fv(@FrontUpRight);

glVertex3fv(@BackUpRight);

glVertex3fv(@BackDownRight);

glEnd;

glBegin(GL_QUADS);

glNormal3fv(@UpNormal);

glVertex3fv(@FrontUpRight);

glVertex3fv(@FrontUpLeft);

glVertex3fv(@BackUpLeft);

glVertex3fv(@BackUpRight);

glEnd;

glBegin(GL_QUADS);

glNormal3fv(@DownNormal);

glVertex3fv(@FrontDownRight);

glVertex3fv(@FrontDownLeft);

glVertex3fv(@BackDownLeft);

glVertex3fv(@BackDownRight);

glEnd;

glBegin(GL_QUADS);

glNormal3fv(@BackNormal);

glVertex3fv(@BackDownLeft);

glVertex3fv(@BackDownRight);

glVertex3fv(@BackUpRight);

glVertex3fv(@BackUpLeft);

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

Создано по материалам из источника по ссылке.

В контексте данного фрагмента кода пользователь столкнулся с проблемой при использовании OpenGL и Delphi: при вращении куба свет также вращается вместе с ним, что не является желаемым поведением. Пользователь пытался изменить координаты света в каждом кад


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: OpenGL ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-02-05 19:07:17/0.0039801597595215/0