2013-07-06 57 views
3

有什麼區別,以及如何讓WebGL的罪與Math.sin產生相同的結果?Javascript「Math.sin」和WebGL「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在COS(PHI)和sin(PHI)與JavaScript的Math.sin和Math.cos它們扔作爲一個屬性,像這樣:

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)」 和 「罪(PHI)」,以COSPHI和sinphi,這是屬性,在CPU上計算,通過JavaScript的Math.sin(phi)和Math.cos(phi),然後代碼工作。建築物/立方體完好無損,因此,由於建築物/立方體放置在球體表面並具有正確的distanceToPlane,所以位移工作和相交工程。

回答玉米稈上gamedev.net:

大數量是一個問題。如果您的頂點着色器與32位浮點數一起使用,那麼它只能提供6位精度的十進制數字。 5476389.695241543至6精度的十進制數字是5476380.000000(截斷6位數字後的所有內容)。因爲sin/cos是週期性的,所以Pi只有〜3.14和 ,使用大數不會給你任何 的好處,因爲使用較小的數字(因爲大數字只是 環繞)。但是,您的號碼非常大,以致於它們幾乎環繞着 以至於它們甚至不精確映射到[-pi,pi](或[0, 2pi])範圍。基本上,周圍的包裹扔掉所有的「高」 數字,並只保留相關的低位數,但不幸的是,對於 ,你所有的低位數都是垃圾,因爲你把所有6位精度數字放在被扔掉的數字上,而現在你所有的 低(但最重要的)數字都沒有意義。

總之,是的,那些巨大的數字會殺了你。

但是,在JavaScript中,所有浮點數都是64位,其中 會爲您提供15位精度的十進制數字。這意味着在JavaScript中,您實際上可以正確代表5476389,即 。69524154,因此您的trig 計算實際上是準確的(假設您的JavaScript代碼爲 ,處理的頂點着色器的值相同)。

+0

對於興趣,這裏的整個主題在上gamedev.net:http://www.gamedev.net/topic/645229-javascripts-%E2%80%9Cmathsinmathcos %E2%80%9D-and-webgls-%E2%80%9Csincos%E2%80%9D-give-different-results/ – Air

回答

0

有沒有區別sin表示sine function。請使用radians

轉換您可以使用

var angleInRadians = angleInDegrees * Math.PI/180; 
+0

指數來自哪裏?似乎它是空的,你試圖與它相乘 – raam86

+0

索引只是一個計數器的每個頂點,介於1和2500000之間,我將它們分組爲8,因此您在這些圖片上看到的一個立方體是8個具有相同索引的頂點,指數給出了斐波納契點。而且我不認爲它是空的,因爲它在第二個代碼片段中不爲空,並且它與我放入的索引相同。 – user2010496

+0

您的代碼不反映這個 – raam86