SFML community forums
Help => Graphics => Topic started by: zombiekiller222 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?
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));
}
}
}
}
-
Dont get the language very much but. What are you doing? More minimal code?
Are you using Window.Draw(Sprite) at all?
-
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
-
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.
-
Thanks, I thought that function was for creating another instance in memory with the exact same value :(
-
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:
// [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:
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);
}
-
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.
-
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.
-
There is a parameter applyAlpha. See the link posted by Haikarainen ;)
-
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.