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

Author Topic: Creating Large Number Of Stars Efficiently  (Read 6579 times)

0 Members and 1 Guest are viewing this topic.

azoundria

  • Newbie
  • *
  • Posts: 11
    • View Profile
    • Email
Creating Large Number Of Stars Efficiently
« on: January 03, 2014, 10:15:23 pm »
I'm hoping to create a background which is randomized with lots of stars for a space-themed game. The stars all move in the same direction at the same time to simulate motion. There will be a lot of them, and I'd really like to create an efficient system.

I want it randomized, so it's not the same graphic over and over. What is the most efficient way to do this?

Do I want to create an array of star objects, similar to this code which doesn't work:

Quote
sf::CircleShape stars[] = sf::CircleShape[500];

Or is it recommended to do something more fancy, such as creating a random Image on the fly which is then moved in one piece?

krzat

  • Full Member
  • ***
  • Posts: 107
    • View Profile
Re: Creating Large Number Of Stars Efficiently
« Reply #1 on: January 03, 2014, 10:47:21 pm »
« Last Edit: January 03, 2014, 10:49:23 pm by krzat »
SFML.Utils - useful extensions for SFML.Net

azoundria

  • Newbie
  • *
  • Posts: 11
    • View Profile
    • Email
Re: Creating Large Number Of Stars Efficiently
« Reply #2 on: January 03, 2014, 11:38:26 pm »
I thought that this may be faster.

It still takes about a second to load the texture now with just 2500 stars in 1000x1000. I'm wondering if there is a faster way to set pixels...

void buildStarTexture (sf::RenderTexture* texture)
{
        sf::CircleShape star(1, 4);
        int i;
       
        if (!texture->create(STAR_TEXTURE_WIDTH, STAR_TEXTURE_HEIGHT))
        {
                // error...
        }
        texture->clear();
        star.setFillColor(sf::Color::Yellow);
        for (i = 0; i < STAR_TEXTURE_YELLOW; i ++) {
                star.setPosition(rand() % STAR_TEXTURE_WIDTH, rand() % STAR_TEXTURE_HEIGHT);
                texture->draw(star);
        }
        star.setFillColor(sf::Color::White);
        for (i = 0; i < STAR_TEXTURE_WHITE; i ++) {
                star.setPosition(rand() % STAR_TEXTURE_WIDTH, rand() % STAR_TEXTURE_HEIGHT);
                texture->draw(star);
        }
        texture->display();
}

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Creating Large Number Of Stars Efficiently
« Reply #3 on: January 04, 2014, 08:37:19 am »
A vertex array of points will be by far the most efficient solution. You can read the corresponding tutorial.
Laurent Gomila - SFML developer

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Re: Creating Large Number Of Stars Efficiently
« Reply #4 on: January 04, 2014, 09:37:49 am »
As Laurent said: vertex array

From there you could use shaders for glowing or other effects of the stars. Motion would be achieved by translating each vertex.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

krzat

  • Full Member
  • ***
  • Posts: 107
    • View Profile
Re: Creating Large Number Of Stars Efficiently
« Reply #5 on: January 04, 2014, 03:11:50 pm »
My guess is that you are using CircleShape with like thousand of vertices. Try with sprite.

I had similiar solution and it worked well: http://i.imgur.com/j610h.png
SFML.Utils - useful extensions for SFML.Net

azoundria

  • Newbie
  • *
  • Posts: 11
    • View Profile
    • Email
Re: Creating Large Number Of Stars Efficiently
« Reply #6 on: January 05, 2014, 02:15:45 am »
Okay I've made 30,000 beautiful pixelated stars using a VertexArray.

I'd now like to make them not pixelated, and more like shining stars.

I tried to apply a blur shader which Laurent made here:
https://github.com/SFML/SFML/blob/master/examples/shader/resources/blur.frag

However it seems to make the stars invisible. I modified the last line to 'gl_FragColor = gl_Color' and everything showed up okay.

Next, I did a simple test to make each pixel purple. 'gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);'

So, it seems that I can only control the single individual pixel, and in order to make the stars more realistic, I obviously would have to brighten the surrounding pixels somewhat. Is this possible with shaders and how would I go about doing it?
« Last Edit: January 05, 2014, 02:17:56 am by azoundria »

azoundria

  • Newbie
  • *
  • Posts: 11
    • View Profile
    • Email
Re: Creating Large Number Of Stars Efficiently
« Reply #7 on: January 05, 2014, 03:30:31 am »
I'm doing another attempt, this time using the sf::TrianglesFan to create gradient triangles in a circle around the central star. Here's the code:

        sf::VertexArray examplestar(sf::TrianglesFan, 8);
        buildStarExample(&examplestar, &window);

void buildStarExample (sf::VertexArray* star, sf::RenderWindow* window)
{
        int width = (int)(window->getSize().x);
        int height = (int)(window->getSize().y);
        float size = 30.f;

        sf::Vector2f center = sf::Vector2f
                                ((float)(rand() % width),
                                (float)(rand() % height));
        ((*star)[0]).position = center;
        std::cout << center.x << " - " << center.y << std::endl;
        ((*star)[0]).color = sf::Color((rand()%64)+192, (rand()%64)+192, rand()%256, 255);

        unsigned int i;
        for (i = 0; i < star->getVertexCount(); i ++) {
                float angle = ((float)(i) / (float)(star->getVertexCount()) * 360.f) * 3.14f / 180.f;
                ((*star)[i]).position = center + sf::Vector2f(
                        (float)(std::cos(angle) * size),
                        (float)(std::sin(angle) * size)
                );
                ((*star)[i]).color = ((*star)[0]).color;
                //((*star)[i]).color.a = 0;
        }
}

At the moment, it's a solid octagon shape. The moment I uncomment the line '((*star)).color.a = 0;', the whole star disappears. I expect the center to be solid, and the edges transparent. Why is it not fading to transparent?

G.

  • Hero Member
  • *****
  • Posts: 1593
    • View Profile
Re: Creating Large Number Of Stars Efficiently
« Reply #8 on: January 05, 2014, 11:07:20 am »
If ((*star)[0]) is your center then ((*star)[i]) is also your center when i = 0
(and it's not the center anymore anyway, because you change its position 3 lines before :p )

When you tried the bluring shader, you were drawing your stars to a RenderTexture (with no shader), and then drawing the RenderTexture to the window while applying the shader ?
« Last Edit: January 05, 2014, 11:09:10 am by G. »

azoundria

  • Newbie
  • *
  • Posts: 11
    • View Profile
    • Email
Re: Creating Large Number Of Stars Efficiently
« Reply #9 on: January 05, 2014, 10:43:49 pm »
Thanks for your help with that error.

At the moment, the blur shader doesn't appear to be having any effect. I know it is loading because the whole screen turned purple when I tested.

However, when I restore it to the normal shader code, the screen appears unchanged.

uniform sampler2D texture;
uniform float blur_radius;

void main()
{
    vec2 offx = vec2(blur_radius, 0.0);
    vec2 offy = vec2(0.0, blur_radius);

    vec4 pixel = texture2D(texture, gl_TexCoord[0].xy) * 4.0 +
                 texture2D(texture, gl_TexCoord[0].xy - offx) * 2.0 +
                 texture2D(texture, gl_TexCoord[0].xy + offx) * 2.0 +
                 texture2D(texture, gl_TexCoord[0].xy - offy) * 2.0 +
                 texture2D(texture, gl_TexCoord[0].xy + offy) * 2.0 +
                 texture2D(texture, gl_TexCoord[0].xy - offx - offy) * 1.0 +
                 texture2D(texture, gl_TexCoord[0].xy - offx + offy) * 1.0 +
                 texture2D(texture, gl_TexCoord[0].xy + offx - offy) * 1.0 +
                 texture2D(texture, gl_TexCoord[0].xy + offx + offy) * 1.0;

    gl_FragColor = gl_Color * (pixel / 16.0);
}

I tried manually filling in the blur_radius, in case I had to fill that in. I tried both 4.0 and 1.0. I notice no difference to the screen except strange random horizontal and vertical lines all the way across the screen, the same colour as some of the stars.

I also tried to change the code a bit like this to see if that would do anything:

  vec4 pixel = texture2D(texture, gl_TexCoord[0].xy) * 0.0 +
               texture2D(texture, gl_TexCoord[0].xy - offx) * 2.5 +
               texture2D(texture, gl_TexCoord[0].xy + offx) * 2.5 +
               texture2D(texture, gl_TexCoord[0].xy - offy) * 2.5 +
               texture2D(texture, gl_TexCoord[0].xy + offy) * 2.5 +
               texture2D(texture, gl_TexCoord[0].xy - offx - offy) * 1.5 +
               texture2D(texture, gl_TexCoord[0].xy - offx + offy) * 1.5 +
               texture2D(texture, gl_TexCoord[0].xy + offx - offy) * 1.5 +
               texture2D(texture, gl_TexCoord[0].xy + offx + offy) * 1.5;

Here is the code:

        sf::Shader blur;
        if (sf::Shader::isAvailable())
        {
                if (!blur.loadFromFile("blur.frag", sf::Shader::Fragment))
                {
                        std::cout << "Could Not Load Blur Shader!" <<std::endl;
                }
        }
        else
        {
                std::cout << "Error! Shaders Not Supported!" <<std::endl;
        }
        sf::RenderTexture blurtexture;
        if (!blurtexture.create(sf::VideoMode::getDesktopMode().width, sf::VideoMode::getDesktopMode().height))
        {
                std::cout << "Error Creating BlurTexture!" << std::endl;
        }

                blurtexture.clear(sf::Color::Black);
                blurtexture.draw(smallstars);
                for (i = 0; i < LARGESTAR_COUNT; i ++) {
                        blurtexture.draw(largestars[i]);
                }
                blurtexture.display();
                sf::Sprite blursprite(blurtexture.getTexture());

        window.clear(sf::Color::Black);
        window.draw(blursprite, &blur);
        window.display();

the_mean_marine

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: Creating Large Number Of Stars Efficiently
« Reply #10 on: January 06, 2014, 12:07:00 pm »
I believe that your problem here is that gl_TexCoord[0] is not initialised by OpenGL; you have to set the value of this variable yourself. It's is set in the vertex shader for the example you're copying from. The relevant line of code is:

gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;

This code is done in the vertex shader as it only needs to be computed for each vertex and then the fragment shader uses a linearly interpolated value of this to get the texel coordinates. You need to set this in the vertex shader as the fragment shader does not have access to gl_MultiTexCoord0.

Also I'm not sure what your end use case is but there are shaders that can draw a background of stars without having to deal with the vertices which given the large number required for a convincing space-y background may be a better option for you.

You can find one such example here: https://www.shadertoy.com/view/4dfGDM