2013-07-06 2 views
3

В чем разница, и как мне получить грех WebGL для получения того же результата, что и Math.sin?Разница между Javascript «Math.sin» и WebGL «sin»

EDIT: У меня есть код в моей вершинных шейдеров (это не весь код), который вычисляет точку Фибоначчи вокруг сферы и, как предполагается поместить вершину на новом месте:

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

Если я вместо вычислить соз (фи) и sin (PHI) на процессоре с Math.sin JavaScript и 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? Phi может стать довольно большим числом, например «5476389.695241543». Может быть, это слишком велико для точности GLSL?

EDIT 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"), 

Так что это один дает ошибочные позиции вершин, если я изменю "соз (фи)" и "грех (фи)" в cosphi и sinphi, которые являются атрибутами , рассчитанный на CPU, с помощью javascript's Math.sin (phi) и Math.cos (phi), тогда код работает. Здания/кубы неповреждены, поэтому перемещение работает и пересекающиеся работы, так как здания/кубы попадают на поверхность сферы с правильным расстоянием.

ОТВЕТ на кукурузные стебли на GameDev.net:

Большое число является проблемой. Если ваш вершинный шейдер работает с 32-битными поплавками , это дает вам только 6 десятичных цифр точности. 5476389.695241543 до 6 десятичных цифр точности - 5476380.000000 (усечение всего после 6 цифр). Pi - только ~ 3.14 и , так как sin/cos периодичны, используя большие числа, не дает вам никакого преимущества при использовании меньших чисел (потому что большие числа просто обертываются). Однако ваши цифры настолько велики, что они обертывают вокруг настолько, что они даже не точно отображают диапазон [-pi, pi] (или [0, 2pi]). В принципе, обертка вокруг выбрасывает все «высокие» цифры и сохраняет только самые низкие разряды, но, к сожалению, для вы все свои младшие разряды являются ненужными, потому что вы потратили все 6 своих цифр на те, которые выбрасываются , и теперь все ваши низкие (но самые важные) цифры не имеют смысла.

Короче говоря, эти огромные числа убьют вас.

Однако в JavaScript все числа с плавающей запятой являются 64-разрядными, что дает вам 15 десятичных цифр точности. Это означает, что в JavaScript вы действительно можете правильно представить 5476389.69524154, поэтому ваши триггеры на самом деле точны (если ваш код JavaScript обрабатывает те же большие значения, что и ваш шейдер вершин).

+0

Для интереса, вот весь поток над на GameDev.net: http://www.gamedev.net/topic/645229-javascripts-%E2%80%9Cmathsinmathcos % E2% 80% 9D-и-webgls-% E2% 80% 9Csincos% E2% 80% 9D-give-different-results/ – Air

ответ

0

Нет разницы sin обозначает sine function.

Убедитесь, что вы используете radians.

для преобразования вы можете использовать

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

Где находится индекс? Кажется, что это null, и вы пытаетесь умножить inc с ним. – raam86

+0

Индекс - это просто счетчик для каждой вершины, между 1 и 2500000, я группирую их на 8, поэтому один куб, который вы видите на этих изображениях, - это 8 вершин с одним и тем же индексом, index дает точку фибоначчи. И я не думаю, что это null, потому что он не является нулевым во втором кодере, и это тот же самый индекс, который я вставлял. – user2010496

+0

Ваш код не отражает это – raam86