【问题标题】:Procedural GL textures程序 GL 纹理
【发布时间】:2017-04-19 14:38:08
【问题描述】:

背景

我正在使用 python/pyglet 创建程序生成的地形。 我正在用 pyglet 对屏幕上的每个 x 和 y 坐标运行一个 lambda 函数,然后用我想要的颜色绘制该像素。

这不是很理想。

我怀疑有一种方法可以创建一个矩形对象并告诉 GL 引擎在其上渲染纹理,给 GL 引擎一个 lambda 函数,该函数将返回颜色以换取 x 和 y 坐标.

伪 pyglet 示例

def get_color(pos):
    x, y = pos
    color = x * y % 255
    return [color, color, color]


width = 1680
height = 1024

win = window.Window(fullscreen=False, vsync=True, width=width, height=height)

glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluOrtho2D(0, win.width, 0, win.height)
glTextureMapper(get_color)
win.clear()

points = [0, 0, width, 0, width, height, 0, height]
pyglet.graphics.draw(int(len(points) / 2), GL_QUADS, ('v2f', points))

TLDR 问题

如何使用 lambda 函数为多边形着色?这是着色器吗?

Pyglet 示例是首选,但欢迎使用任何语言的示例

【问题讨论】:

  • OpenGL 不使用多边形,只使用三角形(以及线和点)。像素的颜色在定义图元(三角形、线或点)的顶点之间进行插值。如果您想要每个像素的功能,那么最好使用着色器。如果您已经计算了每个像素的颜色,那么纹理可能很有用。我最好的建议是遵循一些关于现代 OpenGL (ver >= 3.x) 的教程或书籍

标签: python opengl textures shader pyglet


【解决方案1】:

这可能不是一个完整的答案,但可能会让你更进一步。
另外请记住,我从来没有对纹理进行过足够奇怪的工作。

您可以做的是为任何一组四边形创建一个纹理组,并将它们添加到一个批次中。因为我不完全确定您为什么需要 lambda 函数?

class TextureGroup(pyglet.graphics.Group):
    def set_state(self):
        glEnable(texture.target)
        glBindTexture(texture.target, texture.id)

    def unset_state(self):
        glDisable(texture.target)

vertice_mem = {}

batch = pyglet.graphics.Batch()
texture_group = TextureGroup()
vertice_list = batch.add(2, pyglet.gl.GL_QUADS, None, ('v2f', points))
vertice_mem[(x,y)] = vertex_list

这是一种优化纹理添加到特定面的方式,并将这些面添加到批处理中,从而更快、更动态地渲染它们。

如果您需要更新顶点,您可以随时访问 vertice_list.vertices 并更改该特定面的 x,y 对。

您可以使用自定义组“动态”创建某些纹理,或者在这种情况下预渲染某些纹理,您可以将它们缝合在一起以创建“程序”纹理。

@Ripi2 所说的也是一个很好的提示,请阅读程序内存映射的工作原理及其实际情况。您在沙盒游戏中看到的大多数图形实际上都是巧妙地重复使用纹理来创建按需图形的错觉。

最后也是最后一个提示是,您很可能需要研究着色器,它们是迄今为止通过操纵和创建纹理中的湍流来自动生成“纹理”的最快方法,否则将对您的系统造成沉重负担因为您需要以某种方式迭代像素区域。

但同样,这不是我的经验领域——只是多年来收集到的同路人的点点滴滴的信息。

【讨论】:

  • 感谢您的回答,即使它没有过多地回答我的问题,但它在主题上也有一些好处。
【解决方案2】:

严格来说,OpenGL 无法绘制矩形(四边形),但您始终可以使用两个角之间的对角线来绘制两个三角形。 (拐角之间的插值可能存在一些差异,但它们可能不会影响到您。)

虽然我很迂腐,但您并不是在为 像素 着色,而是在为 3D 地形对象表面上的点着色。 (我假设您希望地形在从任何角度或距离观看时都保持相同的颜色。)

好的,我希望这是真正的答案。您的程序地形生成着色是否只完成一次,还是会动态更改?

如果您只创建一次地形并为其着色,请使用纹理贴图。您需要学习如何在地形的角落分配纹理坐标(TL;DR:它们将是 (0.0,0.0), (1.0,0.0), (1.0,1.0), (0.0, 1.0) )以及如何使用 glTexImage2D 将图像传输到 GPU。

纹理贴图只是 2D 光栅图像。 Pyglet 应该能够为您处理这个问题,如果不是 Pillow 或 Python Imaging Library 包的话。

如果你想让地形动态改变颜色,你需要一个片段着色器,这是一个用 OpenGL 着色语言编写的小函数,每次绘制地形时都会执行。由于 OpenGL 的工作方式,您还必须编写一个顶点着色器来处理 3D 坐标变换。

与纹理贴图方法相比,这意味着更多的思考和编码。但是现在 OpenGL(或 DirectX,或 RenderMan,...)中的所有内容都是使用着色器完成的,所以您不妨开始学习。着色器可让您进行任何类型的程序建模和动画,而不仅仅是颜色。例如,您可以动态生成地形高度和颜色。

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 2010-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-19
    • 2016-10-05
    • 1970-01-01
    相关资源
    最近更新 更多