我希望我的片段着色器遍历一个序列化的四叉树。 当找到内部节点时,rg值被解释为相同纹理的索引。 蓝色值0表示内部节点。
在第一步中,使用提供的uv coords从位置0x0处的2x2子图像读取指针。 然后该指针用于访问相同纹理的另一个2x2部分。 但是,对于根节点的每个子节点,存在增加的偏移误差,导致错误的颜色。
这是我的着色器(对于调试porpusses,循环在一次迭代时被修复,因此只能访问四层树的两个级别。)
另外,为了调试,我确实在左上角的位置放了一个红色的2x2图像,右上角是绿色图像,左下角是蓝色,右下角是黄色。
生成的图像是这样的:
我完全无能为力。你们其中一个人可以想到这种情况发生的原因吗? 我检查所有坐标转换和计算3次它们都是正确的。
以下是着色器:
// virtual_image.fs
precision highp float;
uniform sampler2D t_atlas;
uniform sampler2D t_tree;
uniform vec2 gridpoolSize;
uniform vec2 atlasTileSize;
uniform vec2 atlasSize;
varying vec2 v_texcoord;
const float LEAF_MARKER = 1.0;
const float NODE_MARKER = 0.0;
const float CHANNEL_PERECISION = 255.0;
vec2 decode(const vec2 vec){
return vec * CHANNEL_PERECISION;
}
void main ()
{
vec4 oc = vec4(1); // output color
vec4 tColor = texture2D(t_tree, v_texcoord); // only for debuging
vec4 aColor = texture2D(t_atlas, v_texcoord); // only for debuging
// oc = mix(tColor, aColor, 0.5);
highp vec2 localCoord = v_texcoord;
// by convention the root node starts at [0,0]
// so we read the first pointer relative to that point
// we use the invertedGridpoolSize to convert the local coords in local coords of the first grid at [0,0]
highp vec3 pointer = texture2D(t_tree, localCoord / gridpoolSize).rgb;// pointer is correct at this point!
for(int i = 0 ; i < 1; i++) {
// divides the local coords into 4 quadrants
localCoord = fract(localCoord * 2.0); // localCoord is correct!
// branch
if(pointer.b <= NODE_MARKER + 0.1){
highp vec2 index = decode(pointer.rg);// index is correct!
highp vec2 absoluteCoord = (localCoord + index) / gridpoolSize;// absoluteCoord is correct!
// we have a inner node get next pointer and continue
pointer = texture2D(t_tree, absoluteCoord).rgb;
oc.rgb = pointer.rgb; // this point in the code introduces a growing offset, I don't know where this comes from. BUG LOCATION
//gl_FragColor = vec4(1,0,0,1);
} else {
if(pointer.b >= LEAF_MARKER - 0.1){
// we have a leaf
vec2 atlasCoord = ((decode(pointer.rg) * atlasTileSize) / atlasSize) + (localCoord * (atlasTileSize / atlasSize));
vec4 atlasColor = texture2D(t_atlas, atlasCoord);
//vec4 atlasCoordColor = vec4(atlasCoord,0,1);
//gl_FragColor = mix(atlasColor, vec4(localCoord, 0, 1), 1.0);
//gl_FragColor = vec4(localCoord, 0, 1);
oc = vec4(1,0,1,1);
} else {
// we have an empty cell
oc = vec4(1,0,1,1);
}
}
}
//oc.rgb = pointer;
//oc.rgb = oc.rgb * (255.0 / 20.0 );
gl_FragColor = oc;
}
有关如何将四叉树序列化为纹理的详细信息,请参阅本文:Octree Textures on the GPU
答案 0 :(得分:1)
事实证明这是一个四舍五入的问题。
解码功能中的代码必须更改为:
vec2 decode(const vec2 vec){
return floor(0.5 + (vec * CHANNEL_PERECISION))
}
值返回应该是int的索引,但是稍微小到5.99而不是6。