【问题标题】:How to draw dynamic 2D grid that adjusts according to camera zoom: OpenGL如何绘制根据相机缩放调整的动态 2D 网格:OpenGL
【发布时间】:2020-10-08 01:01:03
【问题描述】:

所以我的问题与标题所述完全一样。我不是在寻找具体的代码示例,只是关于任何首选方法的一些想法/指南。

在我的 2D 游戏引擎中,我喜欢有一个表示一定数量像素(例如 32x32 像素)的网格。我特别希望能够定义世界空间中每个网格的宽度和高度,在所有线条上具有一致的笔划宽度,并且能够根据相机缩放调整图块大小。

我过去尝试过几种不同的方法来绘制这个网格:

  1. 我尝试的第一件事是使用自定义着色器来绘制网格。我在网上找到了一些代码,这些代码使用了一些我不理解的概念,只是在 2D 平面上绘制网格。这种方法的问题是我不知道如何在我的游戏世界中控制确切的大小,也不了解它是如何工作的。

  2. 我的第二种方法是使用我的调试绘图工具。我编写了一套函数,允许我在世界空间中添加不同笔划宽度的线条,我通过为每一帧的每一行动态生成四边形来实现这一点。然后我可以画一堆线,给我一个网格。

  3. 我的第三种方法是绘制一堆四边形,并使用自定义着色器为它们提供轮廓。然后我只画了一堆带有黑色轮廓的白色四边形,呈现出网格的外观。

有人有更好的解决方案吗?在我所有的方法中,我也从未尝试过根据相机的缩放级别动态调整网格。因此,对于这些方法是否是典型解决方案或是否有更好的解决方案的任何想法将不胜感激。另外,如果您对如何将这些方法扩展到 3D 空间有任何想法,这也不错,我似乎找不到在世界空间中绘制的线条上获得统一笔触宽度的好方法。

我的引擎目前也在使用 Opengl 和 C++ 进行编码,所以我主要关心如何使用现代 opengl 来实现这一点,而不是立即模式。

这是我想要实现的目标的图像:

编辑: 我主要关心渲染技术。你使用几个四边形吗?一个平面和一个复杂的着色器?或者你对每条线使用一个四边形?还是完全不同的东西?

这是我的尝试之一,作为我试图实现的外观和感觉的另一个参考。我只是忍不住认为必须有比我尝试过的方法更好的方法。

【问题讨论】:

    标签: c++ opengl graphics 2d gridlines


    【解决方案1】:

    不管渲染方法如何 首先你必须计算网格。我是这样做的:

    1. 在世界坐标中获取屏幕的 AABB (x0,y0,x1,y1)

      最好是有一个 3x3 矩阵,累积所有从世界坐标转换到 GL 屏幕空间的变换:

       vec2 world,screen;
       mat3 w2s;
       screen = w2s*world;
      

      要获得 AABB,我们需要将相反的屏幕角转换为世界:

       mat3 s2w;
       s2w = inverse(w2s);
       world = s2w*screen;
      

      因此,只需将(+/-1,+/-1) 的所有 4 种组合转换为世界并记住最小和最大 x,y (AABB) 让我们称它们为 (x0,y0,x1,y1) 这个矩阵对于鼠标交互也特别有用,因为它会转换鼠标(如果已转换屏幕坐标)转换为世界坐标,您可以使用它进行编辑、选择...

    2. 网格大小gx

      从 AABB 计算网格大小。简单地说,如果您的网格是某个世界单位大小的基数(例如 10),那么只需简单的网格正方形有多大。为简单起见,我将只做单轴(使用 2 个轴中的最小值或单独做两个轴):

      // let consider x0=-50, x1=+180 
      gx = log10(x1-x0); // bigest power of 10 to fit inside gx = 2.3617278360175928788677771122512
      gx = floor(gx-1); // round down and use 10 times smaller grid
      gx = pow(10,gx);  // your grid size in world coordinates gx=10
      
    3. 网格起始位置

      只需将x0,y0gx,gy... 再次对齐一个轴即可:

      x0 = floor(x0/gx)-1
      x0*= gx
      
    4. 渲染

      简单地从x0 循环到x1,逐步gx 并渲染线条...当我一步一步经过gx/10 并在之前渲染一个点或不太亮/粗的线条时,我通常还会再通过一次gx 步骤线。

    【讨论】:

    • 您好,谢谢您的回答!我的问题可能应该更具体一些,但我主要关心如何渲染网格。我从来没有在计算网格线的位置时遇到太多麻烦,当你说在最后一步只渲染一个点时,你是怎么做到的?通过一个完成所有 4 个步骤的着色器?或者你是在画一堆四边形之类的东西来代表一个点?
    • @GabeAmbrosio 对于基本的低级东西我使用旧的 GL api,因为新的不可靠......如果你需要速度,那么最好的方法是让 VBO 带有一组点并将其渲染为GL_POINTS ... 使用单个 QUAD 覆盖屏幕并从片段着色器渲染大量图元通常要慢得多
    • @GabeAmbrosio 如果你有统一的平铺贴图,那么是的,使用着色器和纹理图集 + 贴图作为纹理是最好的方法...
    • 如果您指的是旧 GL api 的 OpenGL 3,我也使用它,如果您指的是即时模式,我会避免使用它,因为我想使用GPU 用于所有绘图例程,而立即模式在这方面没有帮助。如果我要使用GL_POINTS,它将需要更多的计算 CPU 端来生成足够的点来制作一条好看的线,我认为绘制代表线的四边形会做得更好,因为它每个只需要 4 个点'线'。我目前没有使用纹理,但我考虑过使用平铺纹理。
    • @GabeAmbrosio GL_POINTS 用于点,GL_LINES 用于线......我的网格看起来像this
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多