【问题标题】:Delphi OpenGL resizeDelphi OpenGL 调整大小
【发布时间】:2017-05-18 01:54:58
【问题描述】:

我有一个关于使用 Delphi 的 OpenGL 的问题。 我的目的是在表格中绘制一个 n 行 n 列的网格。我希望网格中的单元格像这张图片一样是方形的:

这是我用来创建这个网格的代码:

unit Main;

interface

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

type
  TfrmMain = class(TForm)
    PopupMenu: TPopupMenu;
    mnuDrawGrid: TMenuItem;
    procedure FormCreate(Sender: TObject);
    procedure mnuDrawGridClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormResize(Sender: TObject);
  private
    glDC: HDC;
    oldW: Integer;
    oldH: Integer;
    glContext: HGLRC;
    errorCode: GLenum;
    openGLReady: Boolean;
    procedure DisegnaLinea(const aX1, aY1, aX2, aY2: Double; aSpessore,
      aOffSet: Integer);
    procedure DisegnaTabellone(const aNumRighe, aNumColonne: SmallInt);
  public
    { Public declarations }
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.dfm}

{ Gestione form -------------------------------------------------------------- }

// OpenGL initialization
procedure TfrmMain.FormCreate(Sender: TObject);
var
  pfd: TPixelFormatDescriptor;
  formatIndex: Integer;
begin
  FillChar(pfd, SizeOf(pfd), 0);
  with pfd do
  begin
    nSize := SizeOf(pfd);
    nVersion := 1;
    dwFlags := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL;
    iPixelType := PFD_TYPE_RGBA;
    cColorBits := 24;
    cDepthBits := 32;
    iLayerType := PFD_MAIN_PLANE;
  end;
  glDC := GetDC(Handle);
  formatIndex := ChoosePixelFormat(glDC, @pfd);
  if formatIndex = 0 then
    raise Exception.Create('Choose pixel format failed ' + IntToStr(GetLastError));
  if not SetPixelFormat(glDC, formatIndex, @pfd) then
    raise Exception.Create('Set pixel forma failed ' + IntToStr(GetLastError));
  glContext := wglCreateContext(glDC);
  if not glContext = 0 then
    raise Exception.Create('Create context failed ' + IntToStr(GetLastError));
  if not wglMakeCurrent(glDC, glContext) then
    raise Exception.Create('Make current failsed ' + IntToStr(GetLastError));

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity;
  glOrtho(0.0, ClientWidth, 0.0, ClientHeight, 0.0, 1.0);

  oldW := ClientWidth;
  oldH := ClientHeight;

  openGLReady := True;
end;

// OpenGL destruction
procedure TfrmMain.FormDestroy(Sender: TObject);
begin
  wglMakeCurrent(Canvas.Handle, 0);
  wglDeleteContext(glContext);
end;

// Form resize
procedure TfrmMain.FormResize(Sender: TObject);
begin
  if not openGLReady then
    exit;
  glViewport(0, 0, ClientWidth, ClientHeight);
  errorCode := glGetError;
  if errorCode <> GL_NO_ERROR then
    raise Exception.Create('Form resize: ' + gluErrorString(errorCode));
  if (ClientWidth <> oldW) and (ClientHeight <> oldH) then
    DisegnaTabellone(10, 10);
  oldW := ClientWidth;
  oldH := ClientHeight;
end;


{ Gestione menu -------------------------------------------------------------- }

// Menu option grid drawing
procedure TfrmMain.mnuDrawGridClick(Sender: TObject);
begin
  DisegnaTabellone(10, 10);
end;



{ OpenGL --------------------------------------------------------------------- }

// Draw a line at aX1, aY1 to aX2, aY2 coordinates
procedure TfrmMain.DisegnaLinea(const aX1, aY1, aX2, aY2: Double; aSpessore,
  aOffSet: Integer);
begin
  glEnable(GL_LINE_SMOOTH);
  glLineWidth(aSpessore);
  glBegin(GL_LINES);
    glVertex2f(aX1, aY1);
    glVertex2f(aX2, aY2);
  glEnd;
end;

// Grid design
procedure TfrmMain.DisegnaTabellone(const aNumRighe, aNumColonne: SmallInt);
const
  vOffSet = 20;
var
  idx: SmallInt;
  pX: Double;
  pY: Double;
  incX: Double;
  incY: Double;
  hPos: Double;
  hWidth: Double;
  widthArea: Integer;
  heightArea: Integer;
  aspectRatio: Double;
begin
  glClearColor(1.0, 1.0, 1.0, 0.0);
  glClear(GL_COLOR_BUFFER_BIT);
  glColor3f(0.0, 0.0, 0.0);

  widthArea := ClientWidth;
  heightArea := ClientHeight;
  aspectRatio := widthArea / heightArea;

  pY := vOffSet / 2;
  incY := (heightArea - vOffSet) / aNumRighe;

  pX := (widthArea - aNumColonne * incY) / 2;
  hPos := pX;
  hWidth := hPos + aNumColonne * incY;
  incX := incY;

  // Draw vertical lines
  for idx := 0 to aNumColonne do begin
    DisegnaLinea(pX, vOffSet / 2, pX, heightArea - vOffSet / 2, 3, 0);
    pX := pX + incX;
  end;

   // Draw horizontal lines
  for idx := 0 to aNumRighe do begin
    DisegnaLinea(hPos, pY, hWidth, pY, 3, 0);
    pY := pY + incY;
  end;

  glFlush;
end;

end.

我在 FormCreate 事件中初始化像素格式描述,并创建了一个由弹出菜单调用的例程以绘制网格。在这个例程中,我进行相同的计算,因为我希望网格单元是正方形的,就像我说的那样。所以我取表单的高度 (ClientHeight) 并将它划分为我需要的行数:在这种情况下,10 加上一点偏移量,以便在表单的顶部和底部有一个边距。然后我计算一个完美正方形的网格宽度。它工作得很好,但是当我调整表单大小时问题就来了。 我的意图是根据表格尺寸绘制一个更小或更大的新网格,但这只是我的意图,因为网格没有保持正确的 aspet 比率并且以一种糟糕的方式绘制,如下图所示:

我不明白我的代码中的错误在哪里。我在 OpenGL 工作,有人可以帮帮我吗?

爱神

【问题讨论】:

  • 我建议使用调试器查看您使用DisegnaLinea() 绘制的极值

标签: delphi opengl


【解决方案1】:
  1. 尽管您在调整大小时设置了新的glViewport(),但您仍然使用不再相关的旧正交投影矩阵。
  2. 因此,在设置新视口之前,您只需要一个额外的glOrtho()
  3. OpenGL即时模式(glBegin()glEnd()glVertex()等)已经过时了近二十年;你真的不应该在 2017 年使用它。

【讨论】:

  • 非常感谢 hidefromkgb,不是它工作正常。如前所述,我是 OpenGL 的新手:我应该使用什么来代替 glBegin、glEnd 和 glVertex?我在一本旧书(1999 年)中找到了它们,但我在互联网上找不到更新的东西
  • @Eros,我推荐你to begin here。不幸的是,所有代码都是 C++,但只要归结为调用 GL 函数,就可以轻松移植到 Delphi。
  • hidefromkgb 引用了一个非常好的 Delphi 版本的教程,它们在这个 github 的存储库中:github.com/neslib/DelphiLearnOpenGL/wiki
猜你喜欢
  • 2014-11-16
  • 2023-03-23
  • 1970-01-01
  • 2018-11-05
  • 1970-01-01
  • 2014-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多