首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用手写asm.js

用手写asm.js
EN

Stack Overflow用户
提问于 2013-07-21 23:27:00
回答 1查看 3.6K关注 0票数 14

我试图将asm.js注释添加到perlin噪声函数中:

代码语言:javascript
复制
"use strict";

// Ported from Stefan Gustavson's java implementation
// http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
// Read Stefan's excellent paper for details on how this code works.
//
// Sean McCullough banksean@gmail.com

function SimplexNoise(stdlib,foreign,heap) {
    "use asm";
    // heap should be at least 1024*4+12*3*4 bytes long
    var floor = stdlib.Math.floor,
        sqrt = stdlib.Math.sqrt,
        random = new stdlib.Float32Array(heap),
        buf = new stdlib.Int32Array(heap),
        F2 = 0.0, F3 = 0.0,
        G2 = 0.0, G3 = 0.0;
    F2 = (sqrt(3.0)-1.0)*0.5; F3 = 1.0/3.0;
    G2 = (3.0-sqrt(3.0))/6.0; G3 = 1.0/6.0;
    function init() {
        // before calling this function, set the first 256 floats in the heap to be random numbers between 0..1
        // the heap gets rewritten, but if you record the IV separately, the noise is reproducable
        for(var i=0; i<256; i++) {
            buf[i] = buf[i+256] = floor(random[i]*256.0) & 0xff;
            buf[i+512] = buf[i+512+256] = (buf[i] % 12) * 3 + 1024;
        }
        i = 1024;
        buf[i++] = 1;  buf[i++] = 1;  buf[i++] = 0;
        buf[i++] = -1; buf[i++] = 1;  buf[i++] = 0;
        buf[i++] = 1;  buf[i++] = -1; buf[i++] = 0;
        buf[i++] = -1; buf[i++] = -1; buf[i++] = 0;
        buf[i++] = 1;  buf[i++] = 0;  buf[i++] = 1;
        buf[i++] = -1; buf[i++] = 0;  buf[i++] = 1; 
        buf[i++] = 1;  buf[i++] = 0;  buf[i++] = -1;
        buf[i++] = -1; buf[i++] = 0;  buf[i++] = -1;
        buf[i++] = 0;  buf[i++] = 1;  buf[i++] = 1;
        buf[i++] = 0;  buf[i++] = -1; buf[i++] = 1;
        buf[i++] = 0;  buf[i++] = 1;  buf[i++] = -1;
        buf[i++] = 0;  buf[i++] = -1; buf[i++] = -1;
    }
    function noise2D(xin,yin) {
        xin = +xin; yin = +yin;
        var s = 0.0, i = 0, j = 0,
            t = 0.0,
            X0 = 0.0, Y0 = 0.0,
            x0 = 0.0, y0 = 0.0,
            i1 = 0, j1 = 0,
            x1 = 0.0, y1 = 0.0,
            x2 = 0.0, y2 = 0.0,
            ii = 0, jj = 0,
            gi0 = 0, gi1 = 0, gi2 = 0,
            t0 = 0.0, t1 = 0.0, t2 = 0.0,
            n0 = 0.0, n1 = 0.0, n2 = 0.0;
        // Skew the input space to determine which simplex cell we're in 
        s = (xin+yin)*F2; // Hairy factor for 2D 
        i = floor(xin+s); j = floor(yin+s);
        t = (i+j)*G2;
        X0 = i-t; Y0 = j-t; // Unskew the cell origin back to (x;y) space 
        x0 = xin-X0; y0 = yin-Y0; // The x;y distances from the cell origin 
        // For the 2D case; the simplex shape is an equilateral triangle. 
        // Determine which simplex we are in. 
        i1 = (x0>y0?1:0); j1 = (x0>y0?0:1); // Offsets for second (middle) corner of simplex in (i;j) coords 
        // A step of (1;0) in (i;j) means a step of (1-c;-c) in (x;y); and 
        // a step of (0;1) in (i;j) means a step of (-c;1-c) in (x;y); where 
        // c = (3-sqrt(3))/6 
        x1 = x0-i1+G2; y1 = y0-j1+G2; // Offsets for middle corner in (x;y) unskewed coords 
        x2 = x0-1+2*G2; y2 = y0-1+2*G2; // Offsets for last corner in (x;y) unskewed coords 
        // Work out the hashed gradient indices of the three simplex corners 
        ii = i & 255; jj = j & 255;
        gi0 = buf[ii+buf[jj]+512];
        gi1 = buf[ii+i1+buf[jj+j1]+512]; 
        gi2 = buf[ii+1+buf[jj+1]+512];
        // Calculate the contribution from the three corners 
        t0 = 0.5-x0*x0-y0*y0; t1 = 0.5-x1*x1-y1*y1; t2 = 0.5-x2*x2-y2*y2;
        n0 = t0<0.0? 0.0: t0*t0*t0*t0*(buf[gi0]*x0+buf[gi0+1]*y0);  // (x;y) of buf used for 2D gradient 
        n1 = t1<0.0? 0.0: t1*t1*t1*t1*(buf[gi1]*x1+buf[gi1+1]*y1);
        n2 = t2<0.0? 0.0: t2*t2*t2*t2*(buf[gi2]*x2+buf[gi2+1]*y2); 
        // Add contributions from each corner to get the final noise value. 
        // The result is scaled to return values in the interval [-1,1]. 
        return 70.0 * (n0 + n1 + n2);
    }
    return {
        init: init,
        noise2D: noise2D
    };
};

Firefox Javascript错误控制台只说:

警告: TypeError: asm.js类型错误: asm.js必须以返回导出语句结束源文件: perlin_simplex.js行:9

我已经搜索了错误可能是什么的帮助,只找到了https://github.com/zbjornson/human-asmjs,这通常是非常有用的,但在这种特殊情况下没有帮助。

我出什么问题了?这个perlin噪声函数是如何由人类来实现的呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-07-22 03:28:22

问题在于以下几行:

代码语言:javascript
复制
F2 = (sqrt(3.0)-1.0)*0.5; F3 = 1.0/3.0;
G2 = (3.0-sqrt(3.0))/6.0; G3 = 1.0/6.0;

在asm.js模块的顶层范围内只允许声明。不允许在顶级作用域中定义变量。

根据等级库,您只能将文字值赋值给全局变量(以及其他导入语句)。因此,您也不能执行以下操作,因为F2F3G2G3没有分配文字值:

代码语言:javascript
复制
var floor = stdlib.Math.floor,
    sqrt = stdlib.Math.sqrt,
    random = new stdlib.Float32Array(heap),
    buf = new stdlib.Int32Array(heap),
    F2 = (sqrt(3.0)-1.0)*0.5, F3 = 1.0/3.0,
    G2 = (3.0-sqrt(3.0))/6.0, G3 = 1.0/6.0;

因此,您需要将F2F3G2G3的定义移到函数中(可能是init函数)。因此,您的代码应该如下所示:

代码语言:javascript
复制
function SimplexNoise(stdlib,foreign,heap) {
    "use asm";

    var floor = stdlib.Math.floor,
        sqrt = stdlib.Math.sqrt,
        random = new stdlib.Float32Array(heap),
        buf = new stdlib.Int32Array(heap),
        F2 = 0.0, F3 = 0.0,
        G2 = 0.0, G3 = 0.0;

    function init() {
        F2 = (sqrt(3.0)-1.0)*0.5; F3 = 1.0/3.0;
        G2 = (3.0-sqrt(3.0))/6.0; G3 = 1.0/6.0;
        // rest of init
    }

    function noise2D(xin,yin) {
        // function body
    }

    return {
        init: init,
        noise2D: noise2D
    };
};

人工asm.js确实告诉了您这个问题,但它们给出了数组的示例,而不是简单的变量:

请注意,不能在函数之外修改这些类型化数组:

代码语言:javascript
复制
function MyModule(stdlib, foreign, heap) {
  var arr = new stdlib.Int8Array(heap);
  arr[0] = 1; // "asm.js must end with a return export statement"
  // ...
}

相反,可以这样做:

代码语言:javascript
复制
function MyModule(stdlib, foreign, heap) {
  var arr = new stdlib.Int8Array(heap);
  function init() {
    arr[0] = 1;
  }

  return {
    init: init
  };
}

这就对了。asm.js不是很痛吗?

票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17778006

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档