如何在 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];
但我不确定到底发生了什么,尤其是着色器编译错误。
这个问题以前有人问过,但是几年前在我的搜索中。答案总是使用纹理贴图,但我真正想做的是将星星表示为单个顶点 - 你可能认为我在用一种简单的方法来应对,但事实上,单点光源看起来相当不错和现实。但是我想用类似高斯模糊的东西来处理那个光点,在放大或更亮的星星时也给它多一点 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];
但我不确定到底发生了什么,尤其是着色器编译错误。