WebGL在逐像素操作中使用库的速度要快得多吗?

时间:2017-04-14 09:26:41

标签: javascript html5-canvas webgl pixi.js

Hello Internet!

使用代码来制作可能很酷但无用的东西是我的爱好。

但随着我越来越多,我想做更复杂的事情,我认为 2d画布上下文已经不够了。

所以这导致我

这个问题:

使用一些像Pixi.js这样的WebGL 2d库会更快地逐像素操作吗?

我知道这似乎是一个愚蠢的问题,答案可能很明显,但对我来说并非如此。

我知道如果想要制作游戏,我会获得巨大的框架改进,但让我试着给你一个我计划创建的例子:

这是我的一个愚蠢"项目的片段"

代码是完全意大利面条,我没有费心去整理,但你可以全屏运行它,你可能会知道我计划创建什么。



var width = 800;
var height = 400;
var canvas = document.getElementById("canv");
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext("2d");

ctx.fillStyle = "#000000";
ctx.fillRect(0, 0, width, height);

var imageData = ctx.getImageData(0, 0, width, height);
var data = imageData.data;

var input = "Math.tan((y - height/2) / (x - width/2))*(180/Math.PI)";
var calc;

function inputChanged(inp) {
  var x, y, i;
  try {
    eval("calc = function(x, y, i){ return " + inp.value + " }");
    inp.style.cssText = "border: 2px solid green";
    document.getElementById("errorLog").innerHTML = "";
    draw();
  } catch (e) {
    inp.style.cssText = "border: 2px solid red";
    document.getElementById("errorLog").innerHTML = e;
  }
}

function przyklad(str) {
  var polecenieElement = document.getElementById("polecenie");
  polecenieElement.value = str;
  inputChanged(polecenieElement);
}

function draw() {
  for (var index = 0; index < data.length; index += 4) {
    var i = index / 4;
    var y = Math.floor(i / width);
    var x = i - y * width;
    var equation = calc(x, y, i);
    var clr = hsl2rgb(equation, 100, 50);
    data[index] = clr.r;
    data[index + 1] = clr.g;
    data[index + 2] = clr.b;
    data[index + 3] = 255;
  }

  ctx.putImageData(imageData, 0, 0);
}

function getColor(number) {
  var n = number % 510;
  return n > 255 ? (255 - (n - 255)) : n;
}

function hsl2rgb(h, s, l) {
  h = h % 360;
  var m1, m2, hue;
  var r, g, b
  s /= 100;
  l /= 100;
  if (s == 0)
    r = g = b = (l * 255);
  else {
    if (l <= 0.5)
      m2 = l * (s + 1);
    else
      m2 = l + s - l * s;
    m1 = l * 2 - m2;
    hue = h / 360;
    r = HueToRgb(m1, m2, hue + 1 / 3);
    g = HueToRgb(m1, m2, hue);
    b = HueToRgb(m1, m2, hue - 1 / 3);
  }
  return {
    r: r,
    g: g,
    b: b
  };
}

function HueToRgb(m1, m2, hue) {
  var v;
  if (hue < 0)
    hue += 1;
  else if (hue > 1)
    hue -= 1;
  if (6 * hue < 1)
    v = m1 + (m2 - m1) * hue * 6;
  else if (2 * hue < 1)
    v = m2;
  else if (3 * hue < 2)
    v = m1 + (m2 - m1) * (2 / 3 - hue) * 6;
  else
    v = m1;
  return 255 * v;
}
&#13;
#canv {
  border: 1px solid black;
}

#polecenie {
  width: 400;
}

.przyklad {
  background-color: #ddd;
  margin-top: 5px;
  border: 1px solid black;
  width: 400;
}

.przyklad:hover {
  background-color: #888;
}
&#13;
<body onload="inputChanged(document.getElementById('polecenie'));">
  <canvas id="canv"></canvas><br><br>
  <b>AVAILABLE VARIABLES: </b><br>
  <b>x, y</b> - X, Y coordinates of current pixel.<br>
  <b>i</b> - index of current pixel.<br>
  <b>width, height</b> - canvas width & height;<br><br> Rotation of hsl color in point (x,y) = <input id="polecenie" type="text" value="Math.tan((y - height/2) / (x - width/2))*(180/Math.PI)" oninput="inputChanged(this);"></input>
  <br><br><b id="errorLog" style="color: red;"></b><br> Cool examples:
  <div class="przyklad" onclick="przyklad(this.innerText);">Math.atan2((y - height/2),(x - width/2))*(180/Math.PI)</div>
  <div class="przyklad" onclick="przyklad(this.innerText);">Math.tan((y - height/2) / (x - width/2))*(180/Math.PI)</div>
  <div class="przyklad" onclick="przyklad(this.innerText);">Math.asin((y - height/2) / (x - width/2))*(180/Math.PI)</div>
  <div class="przyklad" onclick="przyklad(this.innerText);">x * y</div>
  <div class="przyklad" onclick="przyklad(this.innerText);">(width*height)/x*y;</div>
  <div class="przyklad" onclick="przyklad(this.innerText);">Math.random()*360</div>
  <div class="przyklad" onclick="przyklad(this.innerText);">Math.sqrt((x - width/2)*(x - width/2) + (y - height/2)*(y-height/2)) > 150 ? 100: Math.sqrt((x - width/2)*(x - width/2) + (y - height/2)*(y-height/2));</div>
  <div class="przyklad" onclick="przyklad(this.innerText);">((height*width) / (x+y)) + x%50</div>
  <div class="przyklad" onclick="przyklad(this.innerText);">Math.random()*30+((x
    < width/2.3 && y <=height/1.86) ? ((((y-6) % 35 < 18 && x % 45 < 20)&&(((y-6) % 35> 5 && x % 45 > 5))) ? i%3 == 0 ? 0 : (i%2 == 0 ? 240 : 120) : (i%3 == 200 ? 0 : (y%2 == 0 ? 240 : 280))) : (y % (height/6.5)
      < (height/(13)) ? i%3==0 ? 0 : (i%2==0 ? 240 : 0) : i%3==0 ? 0 : (x%2==0 ? 120 : 240)))</div>
</body>
&#13;
&#13;
&#13;

所以...?

是否值得为这类应用程序使用某种库?

fps是否值得花时间学习API?

另外作为一个附带问题:

有人可以向我推荐一些东西(某些书或网站),在那里我可以学习如何让我的代码变得干净整洁吗?

谢谢!

2 个答案:

答案 0 :(得分:1)

这实际上取决于Pixel by Pixel操作的含义。

我会说pixi.js本身对逐像素操作无能为力。这不是重点。另一方面,在您尝试匹配webgl can do

的情况下,使用WebGL进行逐像素操作应该更快

至于你的愚蠢的项目,这些看起来就像在https://glslsandbox.comhttps://shadertoy.com

上完成的事情一样

答案 1 :(得分:1)

我个人从未成为任何形式的JS库和框架的粉丝。这并不是说它们很糟糕,但是库涵盖了所有解决方案,它们往往会进行大量的审查,有些只是充满了糟糕的代码。这意味着需要运行许多额外的代码(以及一些不太好的代码),这会影响性能。

对于初学者,库提供了快速解决方案,但可能导致变得依赖于库。这意味着您不会学习可能使您处于劣势的基础API。

使用库的最佳方法是打开它并将其设置为appart。删除不会使用的内容,更改结构和功能以满足您的需求。通过这种方式,您可以根据需要优化库,了解它的结构,并了解如何通过库示例有效地使用浏览器的API(如果它是一个很好的库)

至于性能,如果你是一名经验丰富的编码员并且能够很好地理解javascript,那么请避免使用该库(但之后你就会知道),因为你将直接使用API​​获得更多性能。

如果您是中型编码员,请使用该库作为模板。如果你是初学者,那么你应该考虑你想要什么,学习如何使用浏览器的API或抽象出来并集中精力构建你的应用程序,而不要过分担心性能。