如何在 iOS OpenGL ES 2.0 中绘制星星

How to draw a star in iOS OpenGL ES 2.0

这个问题以前有人问过,但是几年前在我的搜索中。答案总是使用纹理贴图,但我真正想做的是将星星表示为单个顶点 - 你可能认为我在用一种简单的方法来应对,但事实上,单点光源看起来相当不错和现实。但是我想用类似高斯模糊的东西来处理那个光点,在放大或更亮的星星时也给它多一点 body 。我打算对高斯模糊图像进行纹理贴图,但如果我理解正确,我将不得不用 4 个顶点绘制每颗星。也许不是那么困难,但如果我只能处理一个顶点,我不想去那里。 vertex-shader 会这样做吗? GLKBaseEffects 能让我到达那里吗?有什么建议吗?

谢谢。

您可以使用点精灵。

绘图调用

您使用包含星星图像的纹理,并使用典型设置绑定纹理,将其绑定到着色器中的采样器制服等。

您为每颗星绘制一个顶点,将 GL_POINTS 作为原始类型作为第一个参数传递给 glDrawArrays()/glDrawElements()。不需要纹理坐标。

顶点着色器

在顶点着色器中,您像往常一样变换顶点,并设置内置 gl_PointSize 变量:

uniform float PointSize;
attribute vec4 Position;

void main() {
    gl_Position = ...;  // Transform Position attribute;
    gl_PointSize = PointSize;
}

例如,我使用统一的点大小,这意味着所有的星星都具有相同的大小。根据需要的效果,您还可以根据距离计算大小,或者使用额外的顶点属性为每个星指定不同的大小。

片段着色器

在片段着色器中,您现在可以访问内置的 gl_PointCoord 变量来获取片段在点精灵中的相对坐标。如果你的点精灵是一个简单的纹理图像,你可以直接使用它作为纹理坐标。

uniform sampler2D SpriteTex;

void main() {
    gl_FragColor = texture2D(SpriteTex, gl_PointCoord);
}

额外Material

我在这里回答了一个有点类似的问题:Render large circular points in modern OpenGL。由于它是用于桌面 OpenGL,而不是用于纹理精灵,所以这似乎值得单独回答。但是有些步骤是共享的,可能会在其他答案中进行更详细的解释。

我一直忙于自学和尝试,但我得到了奇怪的结果。它似乎适用于顶点变换 - 因为我看到点在屏幕上移出 - 但点大小和颜色没有受到影响。颜色似乎是某种默认的黄色,顶点之间有一些阴影。

同样困扰我的是,我在顶点着色器的内置函数中收到错误消息。以下是 vertex/fragment 代码和错误消息:

#Vertex shader
precision mediump float;
precision lowp int;

attribute float Pointsize;

varying vec4 color_out;

void main()
{
    gl_PointSize = Pointsize;
    gl_Position = gl_ModelViewMatrix * gl_Vertex;
    color_out = vec4(0.0, 1.0, 0.0, 1.0); // output only green for test
}

#Fragment shader
precision mediump float;
precision lowp int;

varying vec4        color_out;

void main()
{
    gl_FragColor = color_out;
}

错误信息如下:

错误:0:24:使用了未声明的标识符 'gl_ModelViewMatrix' 错误:0:24:使用未声明的标识符 'gl_Vertex' 错误:一个或多个附加着色器未成功编译

似乎转换是从我使用 GLKBaseEffects 的 iOS 代码传递的,例如以下几行:

self.effect.transform.modelviewMatrix = modelViewMatrix;

[self.effect prepareToDraw];

但我不确定到底发生了什么,尤其是着色器编译错误。