我正在尝试使用GPU进行布料模拟,但在不同硬件上遇到了一些问题。我使用threejs作为框架,但我认为这与我遇到的问题无关。
基本上,我上传一个矩阵和该矩阵的逆矩阵,以便将点从局部坐标转换为世界坐标系,对世界坐标系中的点进行一些数学计算(如碰撞检测),然后将它们转换回局部坐标系。当我在笔记本电脑上使用浮点纹理时,这非常有效,但是我注意到我的手机上存在一些奇怪的伪影。
经过一些调试,我将问题缩小到两个问题。两者都与十进制精度有关。由于约束(和约束期间的精度问题)而导致顶点崩溃,并且在使用矩阵乘法和逆矩阵时失去精度。
我相信问题与精度有关,因为如果我使用浮点纹理,则在我的计算机上可以正常工作,但是如果我使用半精度,我会遇到相同的问题。我的手机支持浮点纹理,这是我感到困惑的原因之一。我将问题缩小,以便所有布料模拟都被禁用,如果我在计算机上使用半精度纹理运行应用程序,没有重力但有转换和逆转,则平面会以奇怪的方式闪烁。
如果禁用转换和逆变,则看起来正常。
我已经想不出如何处理这个问题,也不确定是否正确。我相信半精度纹理具有有限的十进制精度,但我不明白为什么这会导致我的问题,因为它只应影响着色器的输出,而不是着色器中正在进行的数学运算。
着色器的代码如下:
基本上,我上传一个矩阵和该矩阵的逆矩阵,以便将点从局部坐标转换为世界坐标系,对世界坐标系中的点进行一些数学计算(如碰撞检测),然后将它们转换回局部坐标系。当我在笔记本电脑上使用浮点纹理时,这非常有效,但是我注意到我的手机上存在一些奇怪的伪影。
经过一些调试,我将问题缩小到两个问题。两者都与十进制精度有关。由于约束(和约束期间的精度问题)而导致顶点崩溃,并且在使用矩阵乘法和逆矩阵时失去精度。
我相信问题与精度有关,因为如果我使用浮点纹理,则在我的计算机上可以正常工作,但是如果我使用半精度,我会遇到相同的问题。我的手机支持浮点纹理,这是我感到困惑的原因之一。我将问题缩小,以便所有布料模拟都被禁用,如果我在计算机上使用半精度纹理运行应用程序,没有重力但有转换和逆转,则平面会以奇怪的方式闪烁。
如果禁用转换和逆变,则看起来正常。
我已经想不出如何处理这个问题,也不确定是否正确。我相信半精度纹理具有有限的十进制精度,但我不明白为什么这会导致我的问题,因为它只应影响着色器的输出,而不是着色器中正在进行的数学运算。
着色器的代码如下:
' vec2 cellSize = 1.0 / res;',
' vec4 pos = texture2D(vertexPositions, vuv.xy );',
' vec2 newUV;',
' if(type == 0.0){',
' float px = floor(vuv.x * res.x );',
' float spacingx = px- (2.0 * floor(px/2.0));',
' float py = floor(vuv.y * res.y );',
' float spacingy = py- (2.0 * floor(py/2.0));',
' float total = spacingx + spacingy;',
' total = total- (2.0 * floor(total/2.0));',
' if(total == 0.0){',
' newUV = vuv + (direction * cellSize);',
' }',
' else{',
' newUV = vuv - (direction * cellSize);',
' }',
' }',
' if(type == 1.0){',
' float px = floor(vuv.x * res.x );',
' float spacingx = px- (2.0 * floor(px/2.0));',
' float total = spacingx;',
' if(total == 0.0){',
' newUV = vuv + (direction * cellSize);',
' }',
' else{',
' newUV = vuv - (direction * cellSize);',
' }',
' }',
' vec4 totalDisplacement = vec4(0.0);',
' if(newUV.x > 0.0 && newUV.x < 1.0 && newUV.y > 0.0 && newUV.y < 1.0){ ',
' vec4 posOld = texture2D(vertexPositionsStart, vuv);' ,
' vec4 posOld2 = texture2D(vertexPositionsStart, newUV);' ,
' float targetDistance = length(posOld - posOld2);',
' vec4 newPos = texture2D(vertexPositions, newUV);',
' float dx = pos.x - newPos.x;',
' float dy = pos.y - newPos.y;',
' float dz = pos.z - newPos.z;',
' float distance = sqrt(dx * dx + dy * dy + dz * dz);',
' float difference = targetDistance- distance;',
' float percent = difference / distance / 2.0;',
' float offsetX = dx * percent * rigid;',
' float offsetY = dy * percent * rigid;',
' float offsetZ = dz * percent * rigid;',
' totalDisplacement.x += offsetX;',
' totalDisplacement.y += offsetY;',
' totalDisplacement.z += offsetZ;',
' }',
' }',
' }',
' pos += totalDisplacement;',
' if( vuv.x > 1.0 - cellSize.x && topConstrain == 1 ){',
' pos =transformation * texture2D(vertexPositionsStart, vuv.xy );',
' }',
' if( vuv.x < cellSize.x && bottomConstrain == 1 ){',
' pos =transformation * texture2D(vertexPositionsStart, vuv.xy );',
' }',
' if( vuv.y < cellSize.y && leftConstrain == 1 ){',
' pos =transformation * texture2D(vertexPositionsStart, vuv.xy );',
' }',
' if( vuv.y > 1.0 - cellSize.y && rightConstrain == 1 ){',
' pos =transformation * texture2D(vertexPositionsStart, vuv.xy );',
' }',
' gl_FragColor = vec4( pos.xyz , 1.0 );',