使用纹理进行数据处理

时间:2013-10-30 01:44:11

标签: opengl-es glsl webgl

我之前询问this question如何将数据数组传递给片段着色器以对地形进行着色,并建议我可以使用纹理的RGBA值。

我现在不知道如何弄清楚我如何使用yzw值。这是我的片段着色器代码:

vec4 data = texture2D(texture, vec2(verpos.x / 32.0, verpos.z / 32.0));
float blockID = data.x;
vec4 color;

if (blockID == 1.0) {
    color = vec4(0.28, 0.52, 0.05, 1.0);
}
else if (blockID == 2.0) {
    color = vec4(0.25, 0.46, 0.05, 1.0);
}
else if (blockID == 3.0) {
    color = vec4(0.27, 0.49, 0.05, 1.0);
}

gl_FragColor = color;

这样可以正常工作,但是你可以看到它只使用x - 坐标中的浮点数。如果它也使用yzw坐标,纹理大小可以减少到16x16而不是32x32(小四倍)。

这样做的目的是创建一个体素类型的地形,其中每个“块”在空间坐标中是1x1,并根据blockID着色。看起来像这样: enter image description here

在GLSL之外,这很简单,但是没有能力存储已计算出哪些块我发现这很困难。毫无疑问,我在思考问题,可以用一些简单的数学来完成。


修改
代码基于Wagner Patriota的回答:

vec2 pixel_of_target = vec2( verpos.xz * 32.0 - 0.5 ); // Assuming verpos.xz == uv_of_target ?

// For some reason mod() doesn't support integers so I have to convert it using int()
int X = int(mod(pixel_of_target.y, 2.0) * 2.0 + mod(pixel_of_target.x, 2.0));

// Gives the error "Index expression must be constant"
float blockID = data[ X ];

关于错误,我asked a question关于这个错误实际上导致我问这个错误。 :P
有任何想法吗?谢谢! :)

1 个答案:

答案 0 :(得分:2)

想法是取代:

float blockID = data.x;

通过

float blockID = data[ X ];

其中X是一个允许您从16x16数据图像中选择R,G,B或A的整数。

问题是如何根据你的UV来计算X

好的,你有一个目标图像(32x32)和数据图像(16x16)。我们这样做:

ivec pixel_of_target = ivec( uv_of_target * 32.0 - vec2( 0.5 ) ); // a trick!

将UV与纹理尺寸(在本例中为32)相乘,可以找到确切的像素。 -0.5是必要的,因为您正在尝试“从纹理中找到像素”。当然,纹理在“像素中心”之间具有内插值。你需要像素的确切中心......

您的pixel_of_targetivec(整数),您可以准确识别您的绘图位置!所以现在的事情是识别(基于你正在绘制的像素)你应该从16x16纹理中获得哪个通道。

int X = ( pixel_of_target.y % 2 ) * 2 + pixel_of_target.x % 2;
float blockID = data[ X ]; // party on!

上面的表达式允许您根据目标像素选取正确的索引X!在您的“数据纹理”上16x16将您的(R,G,B,A)映射到目标上每组4个像素的(左上角,右上角,左下角,右下角)(或者可能是上行角度 - 如果你愿意的话......你可以搞清楚)

<强>更新

因为您使用的是WebGL,所以应该更改一些细节。我做到了这一点并且有效。

vec2 pixel_of_target = vTextureCoord * 32.0 + vec2( 0.5 ); // the signal changed!
int _x = int( pixel_of_target.x );
int _y = int( pixel_of_target.y );
int X = mod( _y, 2 ) * 2 + mod( _x, 2 );

我用它进行测试:

if ( X == 0 )
    gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );
else if ( X == 1 )
    gl_FragColor = vec4( 0.0, 1.0, 0.0, 1.0 );
else if ( X == 2 )
    gl_FragColor = vec4( 0.0, 0.0, 1.0, 1.0 );
else if ( X == 3 )
    gl_FragColor = vec4( 1.0, 0.0, 1.0, 1.0 );

我的形象完美无缺:

Zoom

在这里,我用Photoshop看到像素的deatails。

PS1:因为我不熟悉WebGL,我无法在Chrome中运行WebGL,我尝试使用Firefox,而且我也没有找到mod()函数......所以我做了:

int mod( int a, int b )
{
    return a - int( floor( float( a ) / float( b ) ) * float( b ) );
}

PS2:我不知道为什么我必须总结vec2(0.5)而不是减去。 WebGL有点不同。它可能有这种转变。我不知道......它只是有效。