Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Most effiecient way to 'blit'?  (Read 3548 times)

0 Members and 1 Guest are viewing this topic.

zombiekiller222

  • Guest
Most effiecient way to 'blit'?
« on: August 31, 2011, 09:04:45 am »
Ok, I'm making a terrain generator. It is very slow due to how I blit. How could I possibly make it faster?


Code: [Select]

public static void ren ()
{
PerlinNoise perlinNoise = new PerlinNoise (-1);
double widthDivisor = 1 / (double)width;
double heightDivisor = 1 / (double)height;
for (uint i=0; i<width; i++) {
for (uint ii=0; ii<height; ii++) {
uint posx = i;
uint posy = ii;
// Note that the result from the noise function is in the range -1 to 1, but I want it in the range of 0 to 1
// that's the reason of the strange code
double v =
           // First octave
           (perlinNoise.Noise (2 * i * widthDivisor, 2 * ii * heightDivisor, -0.5) + 1) / 2 * 0.7 +
// Second octave
           (perlinNoise.Noise (4 * i * widthDivisor, 4 * ii * heightDivisor, 0) + 1) / 2 * 0.2 +
// Third octave
           (perlinNoise.Noise (8 * i * widthDivisor, 8 * ii * heightDivisor, +0.5) + 1) / 2 * 0.1;

v = Math.Min (1, Math.Max (0, v));
byte b = (byte)(v * 255);
byte r = b;
byte bl = b;
byte g = b;
Color col;
Color col2;
if (b < 110) {
while (posx>water.Width-1) {
posx -= water.Width - 1;
}
while (posy>water.Height-1) {
posy -= water.Height - 1;
}
col = water.GetPixel (posx, posy);
col2 = new Color (0, 0, 0);

} else if (b < 112) {
while (posx>desert.Width-1) {
posx -= desert.Width - 1;
}
while (posy>desert.Height-1) {
posy -= desert.Height - 1;
}
col = desert.GetPixel (posx, posy);
col2 = new Color (1, 0, 0);

} else if (b < 140) {
while (posx>grass.Width-1) {
posx -= grass.Width - 1;
}
while (posy>grass.Height-1) {
posy -= grass.Height - 1;
}
col = grass.GetPixel (posx, posy);
col2 = new Color (2, 0, 0);

} else {
while (posx>stone.Width-1) {
posx -= stone.Width - 1;
}
while (posy>stone.Height-1) {
posy -= stone.Height - 1;
}
col = stone.GetPixel (posx, posy);
col2 = new Color (3, 0, 0);

}
bitmap.SetPixel (i, ii, col);
data.SetPixel (i, ii, col2);
}
;
}


background.Image = bitmap;
perlinNoise = new PerlinNoise (-1);
Random gen = new Random ();
for (uint i=0; i<width; i++) {
for (uint ii=0; ii<height; ii++) {
uint posx = i;
uint posy = ii;
// Note that the result from the noise function is in the range -1 to 1, but I want it in the range of 0 to 1
// that's the reason of the strange code
double v =
           // First octave
           (perlinNoise.Noise (2 * i * widthDivisor, 2 * ii * heightDivisor, -0.5) + 1) / 2 * 0.7 +
// Second octave
           (perlinNoise.Noise (4 * i * widthDivisor, 4 * ii * heightDivisor, 0) + 1) / 2 * 0.2 +
// Third octave
           (perlinNoise.Noise (8 * i * widthDivisor, 8 * ii * heightDivisor, +0.5) + 1) / 2 * 0.1;

v = Math.Min (1, Math.Max (0, v));
byte b = (byte)(v * 255);
if (b > 130) {
if (data.GetPixel (i, ii).R != 0 && data.GetPixel (i, ii).R != 3 &&
data.GetPixel (i, ii).R != 1) {

if (gen.NextDouble () > 0) {

for (uint i2=0; i2<tree.Width; i2++) {
for (uint ii2=0; ii2<tree.Height; ii2++){
bitmap.SetPixel(i, ii, tree.GetPixel(i2, ii2));
}
}
}
}



Haikarainen

  • Guest
Most effiecient way to 'blit'?
« Reply #1 on: August 31, 2011, 09:20:13 am »
Dont get the language very much but. What are you doing? More minimal code?

Are you using Window.Draw(Sprite) at all?

zombiekiller222

  • Guest
Most effiecient way to 'blit'?
« Reply #2 on: August 31, 2011, 09:23:51 am »
I am trying to 'combine' two images into one. Basically I have a map for which I want to blit various trees and textures quickly and efficiently (onto the map, which is an image).

Currently for blitting I:

loop through pixels in image2
set that pixel as the pixel of image1

Haikarainen

  • Guest
Most effiecient way to 'blit'?
« Reply #3 on: August 31, 2011, 09:29:09 am »
Quote from: "zombiekiller222"
I am trying to 'combine' two images into one. Basically I have a map for which I want to blit various trees and textures quickly and efficiently (onto the map, which is an image).

Currently for blitting I:

loop through pixels in image2
set that pixel as the pixel of image1


http://sfml-dev.org/documentation/1.6/classsf_1_1Image.php#a408c40c8675363adfa96a8b9a9576bc2

Use that function, also, you should only do this once and then render the resulting image every frame.

zombiekiller222

  • Guest
Most effiecient way to 'blit'?
« Reply #4 on: August 31, 2011, 09:30:54 am »
Thanks, I thought that function was for creating another instance in memory with the exact same value :(

omeg

  • Jr. Member
  • **
  • Posts: 55
    • View Profile
    • http://omeg.pl/
Most effiecient way to 'blit'?
« Reply #5 on: August 31, 2011, 09:36:30 am »
Don't use SetPixel/GetPixel - they are always very slow. What you want is to change pixel data in memory and then set everything at once. SFML.Graphics.Image has a constructor that takes a byte array of pixel data, you want to use that. Here is an example from my GWEN.Net SFML renderer:
Code: [Select]
       // [omeg] added, pixelData is in RGBA format
        public override void LoadTextureRaw(Texture texture, byte[] pixelData)
        {
            if (null == texture) return;
            if (texture.RendererData != null) FreeTexture(texture);

            global::SFML.Graphics.Texture tex;
            Sprite sprite;

            try
            {
                var img = new Image((uint)texture.Width, (uint)texture.Height, pixelData); // SFML Image
                tex = new global::SFML.Graphics.Texture(img);
                tex.Smooth = true;
                sprite = new Sprite(tex);
                img.Dispose();
            }
            catch (LoadingFailedException)
            {
                texture.Failed = true;
                return;
            }

            texture.RendererData = sprite;
        }


and here an example of how to build raw pixel data:
Code: [Select]
           if (m_Texture == null)
            {
                byte[] pixelData = new byte[Width*Height*4];

                for (int x = 0; x < Width; x++)
                {
                    for (int y = 0; y < Height; y++)
                    {
                        Color c = GetColorAt(x, y);
                        pixelData[4*(x + y*Width)] = c.R;
                        pixelData[4*(x + y*Width) + 1] = c.G;
                        pixelData[4*(x + y*Width) + 2] = c.B;
                        pixelData[4*(x + y*Width) + 3] = c.A;
                    }
                }

                m_Texture = new Texture(skin.Renderer);
                m_Texture.Width = Width;
                m_Texture.Height = Height;
                m_Texture.LoadRaw(Width, Height, pixelData);
            }

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Most effiecient way to 'blit'?
« Reply #6 on: August 31, 2011, 09:42:54 am »
Don't use sf::Image until the final pixels are ready, use an array of sf::Uint8 (or sf::Color) it will be much faster.
Laurent Gomila - SFML developer

zombiekiller222

  • Guest
Most effiecient way to 'blit'?
« Reply #7 on: August 31, 2011, 10:04:16 am »
How would I do operations like copy on an array?

Btw, when I do.

image1.copy(image2)

The alpha is not copied, and all the places where there should be alpha are black.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Most effiecient way to 'blit'?
« Reply #8 on: August 31, 2011, 11:53:30 am »
There is a parameter applyAlpha. See the link posted by Haikarainen ;)
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

zombiekiller222

  • Guest
Most effiecient way to 'blit'?
« Reply #9 on: September 01, 2011, 05:00:28 am »
Actually there isn't. It's a bug in the .net binding of sfml (I think I posted this in the wrong forum section...). Laurent is supposedly going to fix this ASAP.