- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这是一个小项目,用于测试 NME 在不同版本(Windows c++、Flash)下的像素级操作性能。
它使用 BitmapData.setPixel
逐个修改像素(每帧 320x240)。 C++ 构建运行在 22 FPS ,而 闪存构建运行在 ~100 FPS 左右。与闪存相比,C++ 构建的性能大幅下降的原因是什么?如何使用 C++ 构建改进代码以获得更高的 FPS?
Mandelbrot.hx
import nme.display.Sprite;
import nme.display.Bitmap;
import nme.display.BitmapData;
import nme.text.TextField;
import nme.events.Event;
import nme.events.TimerEvent;
import nme.utils.Timer;
import nme.geom.Matrix;
import nme.geom.Rectangle;
import nme.utils.ByteArray;
class Mandelbrot
{
public static function main() : Void
{
new Mandelbrot();
}
public var pixels:Array<Array<Int>>;
public var colorModifier:Int;
private var bitmapData:BitmapData;
private var bigBitmapData:BitmapData;
private var fps:TextField;
private var width:Int;
private var height:Int;
private var matrix:Matrix;
public function new()
{
width = 320; //Std.int(flash.Lib.current.stage.stageWidth/2);
height = 240; //Std.int(flash.Lib.current.stage.stageHeight/2);
var scale:Float = 2;//flash.Lib.current.stage.stageWidth/width;
matrix = new Matrix();
matrix.scale(scale, scale);
var setBitmap:Bitmap = new Bitmap();
bitmapData = new BitmapData( width , height , false , 0x000000 );
bigBitmapData = new BitmapData( nme.Lib.current.stage.stageWidth , nme.Lib.current.stage.stageHeight , false , 0x000000 );
setBitmap.bitmapData = bigBitmapData;
nme.Lib.current.addChild( setBitmap );
var maxIterations:Int = 128;
pixels = new Array();
var beforeTime = nme.Lib.getTimer();
var xtemp;
var iteration;
var x0:Float = 0;
var y0:Float = 0;
for(ix in 0...width) {
pixels[ix] = new Array();
for(iy in 0...height) {
x0 = 0;
y0 = 0;
iteration = 128;
while ( x0*x0 + y0*y0 <= 4 && iteration > 0 )
{
xtemp = x0*x0 - y0*y0 + (ix-14*5000)/50000;
y0 = 2*x0*y0 + (iy-(height/0.6))/50000;
x0 = xtemp;
iteration--;
}
pixels[ix][iy] = iteration;
}
}
var afterTime = nme.Lib.getTimer();
var tf = new TextField();
tf.width = 400;
tf.text = "Generating fractal took "+(afterTime-beforeTime)+" ms";
nme.Lib.current.addChild(tf);
fps = new TextField();
fps.width = 400;
fps.y = 10;
fps.text = "FPS: ";
nme.Lib.current.addChild(fps);
colorModifier = 2;
var timer:haxe.Timer = new haxe.Timer(10);
runLoop();
timer.run = runLoop;
}
public function runLoop() {
var r:Int=0, b:Int=0, g:Int=0;
var pixel:Int = 0;
var beforeTime = nme.Lib.getTimer();
for(iy in 0...height) {
for(ix in 0...width) {
pixel = pixels[ix][iy];
r = pixel + colorModifier;
g = pixel + colorModifier + r;
b = pixel + colorModifier + g;
bitmapData.setPixel(ix, iy, (r<<16 | g<<8 | b));
}
}
bigBitmapData.draw(bitmapData, matrix, null, null, null, false);
var afterTime = nme.Lib.getTimer();
fps.text = "FPS: "+Math.round(1000/(afterTime-beforeTime));
colorModifier += 2;
if(colorModifier > 65530)
colorModifier = 0;
}
}
<?xml version="1.0" encoding="utf-8"?>
<project>
<app
file="Mandelbrot.hx"
title="Mandelbrot sample"
package="org.haxe.nme.mandelbrot"
version="1.0.0"
company="nme"
main="Mandelbrot"
/>
<window
width="640"
height="480"
orientation="landscape"
fps="60"
background="0xffffff"
resizeable="true"
hardware="true"
/>
<classpath name="." />
<haxelib name="nme" />
<ndll name="std" />
<ndll name="regexp" />
<ndll name="zlib" />
<ndll name="nme" haxelib="nme" />
<setenv name="SHOW_CONSOLE"/>
</project>
最佳答案
查看 nme.Memory
API。这个想法是创建一个具有正确大小的 ByteArray
(或从 BitmapData
获取),选择它作为当前虚拟内存空间并直接操作其字节。
使用 Flash,您将获得大约 10 倍的速度提升,并且使用 CPP 目标也应该更快。 不要忘记在 Release 模式下编译 否则方法内联将被禁用并且性能会受到很大影响。
基本用法示例(未经测试的代码):
var rect:Rectangle = bitmapData.rect;
// 32bits integer = 4 bytes
var size:Int = bitmapData.width * bitmapData.height * 4;
// The virtual memory space we'll use
var pixels:ByteArray = new ByteArray();
// CPP does not support setting the length property directly
#if (cpp) pixels.setLength(size);
#else pixels.length = size; #end
// Select the memory space (call it once, not every frame)
Memory.select(pixels);
// And in your loop set your color
// Color is in BGRA mode, nme.Memory can only be used in little endian mode.
Memory.setI32((y * width + x) * 4, color);
// When you're done, render the BitmapData
// (don't forget to reset the ByteArray position)
pixels.position = 0;
bitmapData.setPixels(rect, pixels);
ByteArray
,因为您还需要存储迭代计数。可以在主循环中优化嵌套循环,并且可以避免大量额外的索引/地址计算:
// Note the size * 2 !
// First part of the ByteArray will be used to store the iteration count,
// the second part to draw the pixels.
#if (cpp) pixels.setLength(size * 2);
#else pixels.length = size * 2; #end
Memory.select(pixels);
// First loop storing iteration count
for (iy in 0...height)
{
for (ix in 0...width)
{
// ... do some stuff ...
Memory.setI32((iy * width + ix) << 2, iteration);
}
}
// In your runLoop :
for (i in 0...(height * width))
{
// Get the iteration count
var pixel:Int = Memory.getI32(i << 2);
r = pixel + colorModifier;
g = pixel + colorModifier + r;
b = pixel + colorModifier + g;
// Note that we're writing the pixel in the second part of our ByteArray
Memory.setI32(size + (i << 2), r | g << 8 | b << 16);
}
// Sets the position to the second part of our ByteArray
pixels.position = size;
bitmapData.setPixels(rect, pixels);
getVector()
类中的
setVector()
/
BitmapData
。但它确实没有那么快。
关于Haxe 和 NME : fastest method for per pixel bitmap manipulation,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10157787/
我一直在研究这段代码,但我找不到问题所在。该程序确实可以编译并运行,但最终出现 fatal error 。 程序读取文件并收集数字以计算总数(将它们转换为 float 后)。然后它读取文件并显示小于
我是计算机科学的新手,最近上了一节课。我正在努力解决这个问题,尽管我知道按位运算,但我还是不太明白 问题图片: 我可以有一个明确的解释吗? 最佳答案 答案:B 解释: 使用德摩根定律 (https:/
我发现了这个问题, 编写一个不使用乘法返回给定整数 n 的平方的函数。 对此的解决方法是 public static int sq(int n){ int i = n;
我在某处听说使用 XOR 是不可逆的(他们谈到了加密),但我不明白这是什么意思? AFAIK 即使使用 OR 操作,您也无法找出两个位中的哪一个是 1。请知道这意味着什么的人可以向我解释一下吗? 谢谢
由于一些原始研究和需要为其开发工具,我想出了一些新的,我希望能更好/更快地执行某些数学运算。 Atm 我正在研究伪代码,将它们发布在网站上,以回答已经提出的问题。 然而,在我这样做之前,我想尽可能地优
我经常遇到使用位运算符来做快速、简单和优雅的事情的人。我想学习一些有用的技巧。有哪些最有用的按位运算符案例? 最佳答案 恒定时间 2-幂运算: x = 1 << n; // x = pow(2, n)
我们需要为我的计算机体系结构类编写一个模拟IEEE浮点数除法的程序。我几乎已经做到了,但是我认为查看程序在APL中的样子会很有趣,但是据我所知,没有(简单的)方法可以在APL中进行按位运算(按位和/或
我正在寻找具有以下特征的按位运算序列以下属性: | 00 01 10 11 ---|--------------- 00 | 00 01 | 01 01 10 | 00 01 00
我有一系列位标志,其顺序类似于 {none=0x00, puppies=0x01, kittens=0x02, cute=0x04, funny=0x08, scary=0x10} 等等。 每当用户进
我正在尝试有效地执行以下任务: INPUT VALUE: 01101011 MASK: 00110010 MASK RESULT: --10--1- AGGREGATED: 00000
我需要一种快速的方法来计算位向量的索引间隔的设置位数。例如,给定 10000100100011000 和索引区间 [2, 5],返回值为 2。索引从右边的 0 开始。我有很多疑问要以这种方式完成。分别
我有以下表达式来计算奇偶校验位: AB0E 异或 73C9 异或 D46A 异或 06E3 这将如何评估?是吗: (((AB0E XOR 73C9) XOR D46A) XOR 06E3) 或者是:
我需要对 7 位值进行任意重新排序(是的,我知道我应该使用表格)并且想知道是否有任何技巧可以做到这一点。 例子: // -> // the naive way out = (0x020 &
假设我有这两个数字: x = 0xB7 y = 0xD9 它们的二进制表示是: x = 1011 0111 y = 1101 1001 现在我想在给定点交叉(GA),比如从位置 4 开始。 预期的结果
我想知道是否有办法使用按位运算符屏蔽 int 值列表,并使用该掩码来知道 int 值是否是掩码中的值之一。 即如果我有值 129 和 17,如何计算一个掩码,告诉我一个 int 值是否在掩码中对应(如
我需要使用卡片外的字节码验证器来验证Java Card程序(盖帽文件)。 我已经手动修改了cap文件中的信息,并且我想验证新的cap文件是否类型正确。 我尝试使用com.sun.javacard.sc
我正在尝试找到实现此目标的正确方法的方法: 想象一下,我们有一组位集,如下所示: 00100 00101 10000 00010 10001 我想测试一下,哪些位在所有位集中仅设置了一次。在该示例中,
我不完全理解这种计算奇偶校验位的算法。 有人可以详细解释一下吗? 以下代码摘自《黑客的喜悦》一书: int parity(unsigned x) { unsigned y; y = x ^
我有一个任意 8 位二进制 数字,例如,11101101 我必须交换所有的位,如: 交换前:11-10-11-01交换后:11-01-11-10 我在面试中被问到这个问题! 最佳答案 在伪代码中: x
在我的国际象棋引擎中,它使用位板来表示棋盘的状态,一次生成一大块伪合法移动,结果是位板。例如: 棋子: 稍后一点位板魔法: 最后的位板只是一大块可能的 Action 。引擎通常如何获取此位板并从中生成
我是一名优秀的程序员,十分优秀!