【发布时间】:2019-09-12 20:54:07
【问题描述】:
3D 物理模拟需要访问着色器中相邻顶点的位置和属性来计算顶点的新位置。 2D 版本有效,但在将解决方案移植到 3D 时遇到问题。翻转两个 3D 纹理似乎是正确的,为一个纹理输入一组 x、y 和 z 坐标,并获取包含相邻点的位置-速度-加速度数据的 vec4s,用于计算每个顶点的新位置和速度。 2D 版本使用带有帧缓冲区的 1 个绘图调用将所有生成的 gl_FragColors 保存到 sampler2D。我想使用帧缓冲区对 sampler3D 做同样的事情。但它看起来像在 3D 中使用帧缓冲区,我需要在第二个 3D 纹理的时候写一个 + 层,直到所有层都被保存。我对将顶点网格映射到纹理的相对 x、y、z 坐标以及如何将其单独保存到图层感到困惑。在 2D 版本中,写入帧缓冲区的 gl_FragColor 直接映射到画布的 2D x-y 坐标系,每个像素都是一个顶点。但我不明白如何确保将包含 3D 顶点位置速度数据的 gl_FragColor 写入纹理,以便它保持正确映射到 3D 顶点。
这适用于片段着色器中的 2D:
vec2 onePixel = vec2(1.0, 1.0)/u_textureSize;
vec4 currentState = texture2D(u_image, v_texCoord);
float fTotal = 0.0;
for (int i=-1;i<=1;i+=2){
for (int j=-1;j<=1;j+=2){
if (i == 0 && j == 0) continue;
vec2 neighborCoord = v_texCoord + vec2(onePixel.x*float(i), onePixel.y*float(j));
vec4 neighborState;
if (neighborCoord.x < 0.0 || neighborCoord.y < 0.0 || neighborCoord.x >= 1.0 || neighborCoord.y >= 1.0){
neighborState = vec4(0.0,0.0,0.0,1.0);
} else {
neighborState = texture2D(u_image, neighborCoord);
}
float deltaP = neighborState.r - currentState.r;
float deltaV = neighborState.g - currentState.g;
fTotal += u_kSpring*deltaP + u_dSpring*deltaV;
}
}
float acceleration = fTotal/u_mass;
float velocity = acceleration*u_dt + currentState.g;
float position = velocity*u_dt + currentState.r;
gl_FragColor = vec4(position,velocity,acceleration,1);
这是我在片段着色器中的 3D 尝试:#version 300 es
vec3 onePixel = vec3(1.0, 1.0, 1.0)/u_textureSize;
vec4 currentState = texture(u_image, v_texCoord);
float fTotal = 0.0;
for (int i=-1; i<=1; i++){
for (int j=-1; j<=1; j++){
for (int k=-1; k<=1; k++){
if (i == 0 && j == 0 && k == 0) continue;
vec3 neighborCoord = v_texCoord + vec3(onePixel.x*float(i), onePixel.y*float(j), onePixel.z*float(k));
vec4 neighborState;
if (neighborCoord.x < 0.0 || neighborCoord.y < 0.0 || neighborCoord.z < 0.0 || neighborCoord.x >= 1.0 || neighborCoord.y >= 1.0 || neighborCoord.z >= 1.0){
neighborState = vec4(0.0,0.0,0.0,1.0);
} else {
neighborState = texture(u_image, neighborCoord);
}
float deltaP = neighborState.r - currentState.r; //Distance from neighbor
float springDeltaLength = (deltaP - u_springOrigLength[counter]);
//Add the force on our point of interest from the current neighbor point. We'll be adding up to 26 of these together.
fTotal += u_kSpring[counter]*springDeltaLength;
}
}
}
float acceleration = fTotal/u_mass;
float velocity = acceleration*u_dt + currentState.g;
float position = velocity*u_dt + currentState.r;
gl_FragColor = vec4(position,velocity,acceleration,1);
写完之后,我继续阅读,发现帧缓冲区不会同时访问 sampler3D 的所有层进行写入。我需要以某种方式一次处理 1-4 层。我不确定如何做到这一点,以及确保 gl_FragColor 进入正确图层上的正确像素。
我在 SO 上找到了这个答案: Render to 3D texture webgl2 它演示了在帧缓冲区中一次写入多个图层,但我没有看到如何将其与片段着色器等同起来,从一个绘图调用,自动运行 1,000,000 次(100 x 100 x 100 ...(长度 x 宽度x height)),每次使用位置-速度-加速度数据填充 sampler3D 中的正确像素,然后我可以将其用于下一次迭代。
我还没有结果。我希望以编程方式制作第一个 sampler3D,用它生成新的顶点数据,保存在第二个 sampler3D 中,然后切换纹理并重复。
【问题讨论】:
标签: textures shader framebuffer webgl2