Opengl es 对数据使用纹理

Opengl es 对数据使用纹理,opengl-es,glsl,webgl,Opengl Es,Glsl,Webgl,我之前问过如何将数据数组传递给片段着色器以对地形着色,有人建议我可以使用纹理的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); } e

我之前问过如何将数据数组传递给片段着色器以对地形着色,有人建议我可以使用纹理的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,并基于块ID着色。看起来像这样:

在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 ];
关于这个错误,我之前提到过,这实际上导致我问这个问题P

有什么想法吗?谢谢!:)

我们的想法是取代:

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是必需的,因为您正在尝试“从纹理中查找像素”。当然,纹理在“像素中心”之间有插值。你需要精确的像素中心

目标的
像素ivec
(整数),您可以准确地识别您正在绘制的位置!因此,现在的问题是确定(基于您正在绘制的像素)应该从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 );
我的形象非常好:

在这里,我用Photoshop来查看像素的细节

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有点不同。它可能有这种转变。我不知道。。。它很管用。

非常好!但是,indexTable[n]==n,对于所使用的范围,是?英雄联盟我用不同的算法重新制作了它。。。我忘了换这个零件了!谢谢,我会修复它的Hanks Wagner Patriota,但是您的代码有一些问题:(这可能是因为我使用的是WebGL而不是OpenGL。首先,它不能识别
ivec
,但
ivec2
可以工作,模运算符(%)似乎不受支持,但我可以使用
mod(x,y)
来代替,我得到了错误“索引表达式必须是常量”对于数组的使用。我已将编辑过的代码添加到我的问题中。如果您能看看我是否做了任何错误/愚蠢的事情,我将不胜感激。再次感谢!我不擅长WebGL,但我做了一些对我有用的事情。我将更新答案!谢谢!:D现在工作得很好。正如您所知,我是WebGL/GLSL的新手,所以说真的我很感谢你花时间来帮助我。是的,mod()函数很奇怪。只喜欢浮点数。
int mod( int a, int b )
{
    return a - int( floor( float( a ) / float( b ) ) * float( b ) );
}