gpt4 book ai didi

javascript - Javascript "Math.sin"和 WebGL“sin”之间的区别

转载 作者:太空宇宙 更新时间:2023-11-04 13:21:05 30 4
gpt4 key购买 nike

有什么区别,如何让 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

如果我使用 javascript 的 Math.sin 和 Math.cos 在 CPU 上计算 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 函数似乎存在一些差异? Phi 可以变成相当大的数字,例如“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.cos(phi),那么代码就可以工作了。建筑物/立方体是完好无损的,因此由于建筑物/立方体放置在球体表面,因此位移和相交工作,具有正确的距离ToPlane。

Gamedev.net 上 Cornstalks 的回答:

The big number is an issue. If your vertex shader is working with 32-bit floats, that only gives you 6 decimal digits of precision. 5476389.695241543 to 6 decimal digits of precision is 5476380.000000 (truncating everything after the 6 digits). Pi is only ~3.14, and since sin/cos are periodic, using large numbers doesn't give you any benefit over using smaller numbers (because the large numbers just wrap around). However, your numbers are so large that they wrap around so much that they don't even precisely map to the [-pi, pi] (or [0, 2pi]) range. Basically, the wrapping around throws away all the "high" digits and only keeps the relevant low digits, but unfortunately for you all your low digits are junk because you spent all 6 of your precision digits on the ones that get thrown away, and now all your low (but most important) digits are meaningless.

In short, yes, those huge numbers will kill you.

However, in JavaScript, all floating point numbers are 64-bit, which gives you 15 decimal digits of precision. That means in JavaScript you can actually properly represent 5476389.69524154, so your trig calculations are actually accurate (assuming your JavaScript code is processing the same large values that your vertex shader is).

最佳答案

没有区别sin表示sine function .

确保您使用的是 radians .

转换你可以使用

var angleInRadians = angleInDegrees * Math.PI / 180;

关于javascript - Javascript "Math.sin"和 WebGL“sin”之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17498353/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com