如何在GLSL着色器内有效地生成这个简单的重复纹理?

bpa*_*ker 1 opengl math shader image-processing glsl

我有这个子像素纹理,通常是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

Aki*_*nen 6

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

Red: y== x*3+1 mod 8
Gre: y== x*3+2 mod 8
Blu: y== x*3+3 mod 8
Run Code Online (Sandbox Code Playgroud)

着色器获得varying 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);
Run Code Online (Sandbox Code Playgroud)

编辑

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

     F(x mod 3, y mod 9) == true iff (y=0;x=2), (y=3;x=1), (y=6;x=0)
Run Code Online (Sandbox Code Playgroud)

这可以完全按原样编码:

 bool is_red = (y==0 && x==2) || (y==3 && x==1) || (y==6 && x==0);
Run Code Online (Sandbox Code Playgroud)

但它也可以表示为:

 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);
Run Code Online (Sandbox Code Playgroud)

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

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);
}
Run Code Online (Sandbox Code Playgroud)

这是一个webgl jsfiddle版本,使用着色器版本1.0,但没有整数模数,没有逻辑和; 这是第二个版本.