違いは何ですか? WebGL の sin で Math.sin と同じ結果を生成するにはどうすればよいですか?
編集: 頂点シェーダーにコードがいくつかあります (これはすべてのコードではありません)。これは、球の周りのフィボナッチ点を計算し、この新しいスポットに頂点を配置することになっています:
attribute float index;
float inc = 3.141592653589793238462643383279 * (3.0 - sqrt(5.0));
float off = 2.0 / 2500000;
float yy = index * off - 1.0 + (off / 2.0);
float rr = sqrt(1.0 - yy * yy);
float phi = index* inc;
vec3 fibPoint = vec3(cos(phi) * rr, yy, sin(phi) * rr);
これは機能しません。次のような厄介な頂点の場所が表示されます: http://i.imgur.com/Z1crisy.png
代わりに、CPU で javascript の Math.sin と Math.cos を使用して cos(phi) と sin(phi) を計算し、属性としてこれらをスローすると、次のようになります。
attribute float index;
attribute float sinphi;
attribute float cosphi;
float inc = 3.141592653589793238462643383279 * (3.0 - sqrt(5.0));
float off = 2.0 / 2500000;
float yy = index * off - 1.0 + (off / 2.0);
float rr = sqrt(1.0 - yy * yy);
float phi = index* inc;
vec3 fibPoint = vec3(cosphi * rr, yy, sinphi * rr);
次のような素晴らしいフィボナッチ分布を取得します: http://i.imgur.com/DeRoXkL.png
明らかに、GLSL と Javascript の cos/sin 関数に違いがあるようです。ファイは、「5476389.695241543」のようにかなり大きな数になる可能性があります。GLSL の精度には大きすぎるのではないでしょうか?
編集2:
vertexShader: [
"attribute float index;",
"attribute float cosphi;",
"attribute float sinphi;",
"attribute float displacementType;",
"uniform vec3 faceCorner;",
"uniform vec3 faceNormal;",
"uniform vec3 faceCenter;",
"varying vec2 vTexCoord;",
"void main()",
"{",
"vTexCoord = uv;",
// find fibonacci distribution of points on sphere
"float inc = 3.141592653589793238462643383279 * 0.7639320225002102;",
"float off = 0.0000008;",
"float yy = index* off - 1.0 + (off / 2.0);",
"float rr = sqrt(1.0 - yy * yy);",
"float phi = index* inc;",
"vec3 fibPoint = vec3(cos(phi) * rr * -1.0, yy, sin(phi) * rr * -1.0);",
// intersecting face
"vec3 normalizedFaceNormal = normalize(faceNormal);",
"float planeConstant = - dot(faceCorner, normalizedFaceNormal);",
"float denominator = dot(normalizedFaceNormal, fibPoint);",
"float distanceToPlane = - planeConstant / denominator;",
"vec3 intersectPoint = normalize(fibPoint) * distanceToPlane;",
"intersectPoint = faceCenter;",
// displacement
"float buildingRadius = 3.0;",
"vec3 newPosition = position;",
"vec3 cornerVec = normalize(faceCorner - intersectPoint) * buildingRadius;",
// ground vertices
"if(displacementType == 0.0){",
"newPosition = intersectPoint + cornerVec;",
"} else if(displacementType == 1.0){",
"newPosition = cross(cornerVec, normalizedFaceNormal);",
"newPosition = intersectPoint + newPosition;",
"} else if(displacementType == 2.0){",
"newPosition = intersectPoint - cornerVec;",
"} else if(displacementType == 3.0){",
"newPosition = cross(normalizedFaceNormal, cornerVec);",
"newPosition = intersectPoint + newPosition;",
"} else {",
// roof vertices
"vec3 corner0 = intersectPoint + cornerVec;",
"vec3 corner1 = intersectPoint + cross(cornerVec, normalizedFaceNormal);",
"float UVdistance = length(corner0 - corner1);",
"float buildingHeight = UVdistance * 2.0;",
"vec3 roofCentroid = intersectPoint + normalizedFaceNormal * (-buildingHeight);",
"if(displacementType == 4.0){",
"newPosition = roofCentroid + cornerVec;",
"} else if(displacementType == 5.0){",
"newPosition = cross(cornerVec, normalizedFaceNormal);",
"newPosition = roofCentroid + newPosition;",
"} else if(displacementType == 6.0){",
"newPosition = roofCentroid - cornerVec;",
"} else {",
"newPosition = cross(normalizedFaceNormal, cornerVec);",
"newPosition = roofCentroid + newPosition;",
"}",
"}",
"gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition.xyz, 1.0);",
"}"
].join("\n"),
「cos(phi)」と「sin(phi)」を属性である cosphi と sinphi に変更すると、javascript の Math.sin(phi) と Math.sin(phi) によって CPU で計算されます。 .cos(phi) の場合、コードは機能します。建物/立方体は無傷であるため、変位が機能し、建物/立方体が正しい距離ToPlaneで球の表面に配置されるため、交差が機能します。
gamedev.net の Cornstalks による回答:
数が多いことが問題です。頂点シェーダーが 32 ビット浮動小数点数で動作している場合、10 進数で 6 桁の精度しか得られません。5476389.695241543 から 6 桁の精度は 5476380.000000 です (6 桁以降はすべて切り捨てられます)。Pi は 3.14 までしかなく、sin/cos は周期的であるため、大きな数を使用しても、小さな数を使用するよりもメリットはありません (大きな数がラップアラウンドするため)。ただし、数値が非常に大きいため、[-pi、pi] (または [0, 2pi]) の範囲に正確にマッピングすることさえできません。基本的に、ラップアラウンドはすべての「上位」桁を破棄し、関連する下位桁のみを保持しますが、残念ながら、下位桁はすべてがらくたです。
要するに、そうです、それらの膨大な数はあなたを殺します.
ただし、JavaScript では、すべての浮動小数点数が 64 ビットであるため、10 進数で 15 桁の精度が得られます。つまり、JavaScript では 5476389.69524154 を実際に適切に表すことができるため、三角関数の計算は実際には正確です (JavaScript コードが頂点シェーダーと同じ大きな値を処理していると仮定します)。