首页 文章

计算3D地形的正确纹理坐标

提问于
浏览
2

使用纹理,我正在尝试将数据传递给我的着色器,因此它知道每个片段应该是什么颜色 . 我正在尝试使用8位整数创建体素类型的地形(Minecraft样式体素),每个RGBA值是着色器上指定的不同颜色 . 值1可能是绿色,2可能是棕色 .

如果我的数学是正确的,那么2048 x 2048大小的纹理就是体素地形数据所需的确切大小:

2048 x 2048大小纹理= 4194304像素 . 一次装入8 x 8 = 64“块” . 块中的32 x 32 x 256 = 262144个体素 . 64 x 262144 = 16777216体素 .

对于纹理中的每个像素,我可以使用RGBA作为单独的值,因此将其除以4 :(因此,每个体素为1个字节,因为值小于200,所以很好 . )

16777216/4 = 4194304像素 .

也就是说,我无法获得正确的纹理坐标来表示3D地形 . 这是我目前的代码,适用于平面飞机:

片段着色器:

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

void main() {
    // divide by 4096 because we're using the same pixel twice in each axis
    vec4 data = texture2D(uSampler, vec2(verpos.x / 4096.0, verpos.z / 4096.0));

    vec2 pixel_of_target = verpos.xz;
    int _x = int( pixel_of_target.x );
    int _y = int( pixel_of_target.y );
    int X = modint( _y, 2 ) * 2 + modint( _x, 2 );

    vec4 colorthing;
    float blockID;

    if (X == 0) blockID = data.x;
    else if (X == 1) blockID = data.y;
    else if (X == 2) blockID = data.z;
    else if (X == 3) blockID = data.w;

    if (blockID == 1.0) gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );
    else if (blockID == 2.0) gl_FragColor = vec4( 0.0, 1.0, 0.0, 1.0 );
    else if (blockID == 3.0) gl_FragColor = vec4( 0.0, 0.0, 1.0, 1.0 );
    else if (blockID == 4.0) gl_FragColor = vec4( 1.0, 0.0, 1.0, 1.0 );
}

所以基本上我的纹理是包含我的3D数据切片的2D Map ,我需要修改这个代码,以便计算正确的坐标 . 谁知道我会怎么做?

2 回答

  • 0

    假设您的纹理将在8x8网格中包含64个地形切片,则以下查找应该有效:

    vec2 texCoord = vec2((verpos.x / 8.0 +   mod(verpos.y, 8.0)) / 4096.0,
                         (verpos.x / 8.0 + floor(verpos.y / 8.0)) / 4096.0));
    vec4 data = texture2D(uSampler, texCoord);
    ... Rest of your shader as above
    

    然后,您的纹理应包含高度为0的地形的完整2D切片,然后在高度为1的切片旁边,直到最右侧位置的高度为7 . 在下一行是高度8-15等等 .

    话虽如此,您通常应该尝试避免使用着色器代码中的 if ,因为它会大大减慢着色器处理速度 . 如果webGL支持数组(据我所知),您可以将所有颜色存储在数组中并执行数组查找而不是 if -chain

  • 0

    纹理坐标应该是

    vec4 data = texture2D(uSampler, vec2(verpos.x / (4 * 2048.0), verpos.z / 2048.0));
    

    然后将给出要读取的字节

    int index = (verpos.x/2048) % 4;
    
    if index == 0 pick data.r, if 1 data.g, if 2 data.b and so on...
    

相关问题