看起来这应该很简单,但是使用点精灵的部分纹理我遇到了很多困难。我已经广泛搜索并提出了各种答案,但这些都没有解决我遇到的具体问题。
到目前为止我学到了什么:
以下是我正在努力实现的目标
我在哪里:
代码:
顶点着色器
uniform mat4 Projection;
uniform mat4 Modelview;
uniform float PointSize;
attribute vec4 Position;
attribute vec2 TextureCoordIn;
varying vec2 TextureCoord;
void main(void)
{
gl_Position = Projection * Modelview * Position;
TextureCoord = TextureCoordIn;
gl_PointSize = PointSize;
}
片段着色器
varying mediump vec2 TextureCoord;
uniform sampler2D Sampler;
void main(void)
{
// Using my TextureCoord just draws a grey square, so
// I'm likely generating texture coords that texture2D doesn't like.
gl_FragColor = texture2D(Sampler, TextureCoord);
// Using gl_PointCoord just draws my whole sprite map
// gl_FragColor = texture2D(Sampler, gl_PointCoord);
}
我坚持的内容:
gl_PointCoord
变量。 gl_PointCoord
最初包含哪些内容?为什么?它从何处获取数据?答案 0 :(得分:10)
我的一位同事帮助解决了问题。事实证明,诀窍是利用点的大小(以OpenGL单位)和精灵的大小(纹理单位,(0..1))结合一点矢量数学,只渲染部分精灵表到每个点上。
顶点着色器
uniform mat4 Projection;
uniform mat4 Modelview;
// The radius of the point in OpenGL units, eg: "20.0"
uniform float PointSize;
// The size of the sprite being rendered. My sprites are square
// so I'm just passing in a float. For non-square sprites pass in
// the width and height as a vec2.
uniform float TextureCoordPointSize;
attribute vec4 Position;
attribute vec4 ObjectCenter;
// The top left corner of a given sprite in the sprite-sheet
attribute vec2 TextureCoordIn;
varying vec2 TextureCoord;
varying vec2 TextureSize;
void main(void)
{
gl_Position = Projection * Modelview * Position;
TextureCoord = TextureCoordIn;
TextureSize = vec2(TextureCoordPointSize, TextureCoordPointSize);
// This is optional, it is a quick and dirty way to make the points stay the same
// size on the screen regardless of distance.
gl_PointSize = PointSize / Position.w;
}
片段着色器
varying mediump vec2 TextureCoord;
varying mediump vec2 TextureSize;
uniform sampler2D Sampler;
void main(void)
{
// This is where the magic happens. Combine all three factors to render
// just a portion of the sprite-sheet for this point
mediump vec2 realTexCoord = TextureCoord + (gl_PointCoord * TextureSize);
mediump vec4 fragColor = texture2D(Sampler, realTexCoord);
// Optional, emulate GL_ALPHA_TEST to use transparent images with
// point sprites without worrying about z-order.
// see: http://stackoverflow.com/a/5985195/806988
if(fragColor.a == 0.0){
discard;
}
gl_FragColor = fragColor;
}
答案 1 :(得分:4)
点精灵由单个位置组成。因此,任何“变化”值实际上都不会变化,因为它们之间没有内插。
gl_PointCoord
是vec2
值,其中XY值介于[0,1]之间。它们代表了该点的位置。 (0,0)是该点的左下角,(1,1)是右上角。
因此,您希望将(0,0)映射到精灵的左下角,将(1,1)映射到右上角。要做到这一点,你需要知道某些事情:精灵的大小(假设它们都是相同的大小),纹理的大小(因为纹理获取函数采用规范化纹理坐标,而不是像素位置),以及< em>当前正在渲染精灵。
后者可以通过varying
设置。它可以是一个值,它作为顶点数据传递到顶点着色器中的varying
。
使用它加上精灵的大小来确定纹理中为此精灵提取数据的位置。获得要使用的纹素坐标后,将它们除以纹理大小以生成标准化纹理坐标。
在任何情况下,无论名称如何,精灵点都不适用于精灵渲染。使用四边形/三角形会更容易,因为您可以更确切地确定所有位置的确切位置。