1

我有这个通常为 8x8 大小的子像素纹理(此处为放大版:http: //i.imgur.com/w697DMO.png),我需要能够在 GLSL 中生成此纹理,而无需实际使用任何上传的着色器本身的纹理。我知道这是可能的,因为我已经看到对这样的纹理进行了类似的数学运算(http://www.reach3d.net/views.pdf),我只是不确定如何以相反的方式进行......换句话说,我需要生成在着色器中输出此纹理所需的数学运算。

编辑:我忘了提到我对生成数据的第二个要求。

过去我使用常规纹理时,在计算最终颜色之前还进行了其他操作,这需要将亚像素纹理在其中一个轴上上下移动(例如,纹理的第一行移动到如果我们“向上”移动,则底部)。例如,我有一个图像纹理,其中包含 8 或 9 个不同的部分(想想井字游戏布局),需要合成为单个图像,其中每个部分都放大到全屏大小并与不同的部分相乘(全屏,包裹)子像素纹理(如 8x8 或 3x9)。这将如何实现?

输入图像如下所示:http: //i.imgur.com/vzxI5tL.jpg

输出(仅使用前 8 个部分,具有 8x8 纹理)应如下所示:http: //i.imgur.com/YuIgSSu.jpg

4

1 回答 1

6

要着色的像素位置似乎是某些丢番图方程的根:

Red: y== x*3+1 mod 8
Gre: y== x*3+2 mod 8
Blu: y== x*3+3 mod 8

着色器将 avarying vec2 vTexCoord;作为输入。

您可以将纹理坐标预乘 8 并使用坐标的整数部分。(免责声明:不记得强制转换是否足以在 GLSL 中进行 float->int 转换。)

int a=(((int)vTexCoord.x)*3 - ((int)vTexCoord.y)) & 7;
glColor = vec4( (a==1)?1.0:0.0,
                (a==2)?1.0:0.0,
                (a==3)?1.0:0.0, 1.0);

编辑

对于 3x9 系统,必须检查红色像素的条件:

     F(x mod 3, y mod 9) == true iff (y=0;x=2), (y=3;x=1), (y=6;x=0)

这可以完全按原样编码:

 bool is_red = (y==0 && x==2) || (y==3 && x==1) || (y==6 && x==0);

但它也可以表示为:

 bool is_red   = (x*3-y == 0);  // and following the same logic
 bool is_green = (x*3-y == 1);
 bool is_blue  = (x*3-y == 2);

使用后面这些方程的完整片段着色器将是:

varying vec2 v_texCoord;
void main()
{
    float x = fract(v_texCoord.x * (1.0/3.0));
    float y = fract(v_texCoord.y * (1.0/9.0));
    int xmod3 = (int)(x*3.0);
    int ymod9 = (int)(y*9.0);
    int d = xmod3*3-ymod9;

    gl_FragColor = vec4((d==0)?1.0f:0.0f,
                        (d==1)?1.0f:0.0f,
                        (d==2)?1.0f:0.0f,
                        1.0f);
}

这是一个使用着色器版本 1.0 的 webgl jsfiddle版本,具有诸如无整数模、无逻辑与等限制;这是第二个版本

于 2013-01-28T07:08:07.680 回答