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

Author Topic: Drawing a "flashlight texture" around mouse position?  (Read 7295 times)

0 Members and 1 Guest are viewing this topic.

wh1t3crayon

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
Drawing a "flashlight texture" around mouse position?
« on: October 22, 2014, 06:33:28 am »
I'm working on a project for class and I'm trying to design a maze, and the mouse will be your character, but the character has a limited sight distance so I want only the surrounding 50-100 pixels to be drawn from the point of the cursor. Are there any tutorials somebody can point me to/is this even possible?

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Drawing a "flashlight texture" around mouse position?
« Reply #1 on: October 22, 2014, 07:59:51 am »
I can think of at least a few ways of doing it.  You could use a black texture with a hole and draw that over everything.  You could draw everything to a rendertexture then use a shader that takes the cursor position as input and darkens everything that's too far away from it.  There's probably also some way of doing this with blend modes.

My personal impression is that for "lighting" effects like this, shaders tend to be the best way to go.  There is a tutorial on SFML shaders, and although it obviously won't cover this exact example, writing a fragment shader that takes a point as input and darkens each pixel based on the distance from it should be fairly straightforward.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Re: Drawing a "flashlight texture" around mouse position?
« Reply #2 on: October 22, 2014, 08:26:51 am »
I've once written a small example for such a thing. You can find it here and it will look something like this:



Code-wise it's not the best example and as Ixrec the "right way" would be a shader, but if you've no idea how something like this works, my example might give you some basic idea. ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Mario

  • SFML Team
  • Hero Member
  • *****
  • Posts: 879
    • View Profile
Re: Drawing a "flashlight texture" around mouse position?
« Reply #3 on: October 22, 2014, 08:47:12 am »
It really depends on the minimum requirements you'd like to accept. Right now SFML doesn't support shaders on mobile platforms, while they're available everywhere else.

First, I'd create a render texture big enough to hold your flashlight only. You don't have to render the whole screen/scene if you won't see it anyway. Render the part visible to that texture using an appropriate view.

Clear the screen to black and draw your flashlight area to the correct position. You're now also able to simply use `sf::Sprite::setColor()` to modify the color every frame to create some kind of flicker (in case you'd like to achieve some kind of torch like effect).

I'd only use the shader approach if you'd like to do more than one light source and/or complex shadows.

wh1t3crayon

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
Re: Drawing a "flashlight texture" around mouse position?
« Reply #4 on: October 22, 2014, 02:37:32 pm »
It really depends on the minimum requirements you'd like to accept. Right now SFML doesn't support shaders on mobile platforms, while they're available everywhere else.

First, I'd create a render texture big enough to hold your flashlight only. You don't have to render the whole screen/scene if you won't see it anyway. Render the part visible to that texture using an appropriate view.

Clear the screen to black and draw your flashlight area to the correct position. You're now also able to simply use `sf::Sprite::setColor()` to modify the color every frame to create some kind of flicker (in case you'd like to achieve some kind of torch like effect).

I'd only use the shader approach if you'd like to do more than one light source and/or complex shadows.

Render Texture sounds like the way to go here because it's a pretty crude application. It's my first time working with a RenderTexture, so I'm a little confused. The documentation says that it is used for off-screen drawing, but if I understand you, then you say to use it as the portion of the screen that is being displayed?

Also how do I make the render texture circular? Would I need to use an algorithim that makes the corners of the rectangles black or is there an easier way?
« Last Edit: October 22, 2014, 02:46:04 pm by wh1t3crayon »

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Drawing a "flashlight texture" around mouse position?
« Reply #5 on: October 22, 2014, 07:54:25 pm »
Render Texture sounds like the way to go here because it's a pretty crude application. It's my first time working with a RenderTexture, so I'm a little confused. The documentation says that it is used for off-screen drawing, but if I understand you, then you say to use it as the portion of the screen that is being displayed?

Also how do I make the render texture circular? Would I need to use an algorithim that makes the corners of the rectangles black or is there an easier way?

Yes, it is used for off-screen drawing, and one common use of off-screen drawing is to get an intermediate result that you can then draw to the screen later.  So if you wanted a 100x100 pixel square flashlight, just make a 100x100 rendertexture, set the right sf::View on it, draw everything, then draw the result onto a certain region of your actual window.

For getting it circular, you'll have to incorporate one of the other methods.  The simplest is probably using a 100x100 image that's black except for a transparent circle.

wh1t3crayon

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
Re: Drawing a "flashlight texture" around mouse position?
« Reply #6 on: October 22, 2014, 09:13:17 pm »
Render Texture sounds like the way to go here because it's a pretty crude application. It's my first time working with a RenderTexture, so I'm a little confused. The documentation says that it is used for off-screen drawing, but if I understand you, then you say to use it as the portion of the screen that is being displayed?

Also how do I make the render texture circular? Would I need to use an algorithim that makes the corners of the rectangles black or is there an easier way?

Yes, it is used for off-screen drawing, and one common use of off-screen drawing is to get an intermediate result that you can then draw to the screen later.  So if you wanted a 100x100 pixel square flashlight, just make a 100x100 rendertexture, set the right sf::View on it, draw everything, then draw the result onto a certain region of your actual window.

For getting it circular, you'll have to incorporate one of the other methods.  The simplest is probably using a 100x100 image that's black except for a transparent circle.

Ok I think I get it. What do you mean by "right sf::View", as opposed to what else? And is there pseudocode you can give as a quick demonstration?

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Drawing a "flashlight texture" around mouse position?
« Reply #7 on: October 22, 2014, 09:22:07 pm »
Basically, I'm assuming you would want your 100x100 flashlight to not always show the same {0,0,100,100} square region of the game world that would get drawn by default.  If you instead want the flashlight to show the {100,100,200,200} region instead, you'll have to move the render texture's view 100 pixels down and 100 pixels to the right before you draw() everything onto it.

For details and code, just read the view tutorial: http://sfml-dev.org/tutorials/2.1/graphics-view.php

wh1t3crayon

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
Re: Drawing a "flashlight texture" around mouse position?
« Reply #8 on: October 23, 2014, 05:27:54 am »
Basically, I'm assuming you would want your 100x100 flashlight to not always show the same {0,0,100,100} square region of the game world that would get drawn by default.  If you instead want the flashlight to show the {100,100,200,200} region instead, you'll have to move the render texture's view 100 pixels down and 100 pixels to the right before you draw() everything onto it.

For details and code, just read the view tutorial: http://sfml-dev.org/tutorials/2.1/graphics-view.php

Ok, so use sf::View to set the area for the RenderTexture, that makes sense. And I meant pseudocode for the drawing of the full window vs the drawing of the RenderTexture. I'll post what my idea of doing this would be so you can evaluate just how incorrect it is:
sf::RenderWindow window;
window.clear(sf::Color::Black);
        window.draw(everythingThatExistsInWindow);
        sf::View view;
        view.setCenter(mousePosition);
        sf::RenderTexture renderText;
        renderText.setView(view);
        renderText.display();

Does that make sense, or do I have the concept wrong?

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Drawing a "flashlight texture" around mouse position?
« Reply #9 on: October 23, 2014, 07:34:54 am »

wh1t3crayon

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
Re: Drawing a "flashlight texture" around mouse position?
« Reply #10 on: October 23, 2014, 02:44:54 pm »
Ok I tried that, but I'm getting a weird bug. Tiny white dots appear near where my mouse is, and they aren't cleared everytime, rather they stay on screen. Here is the code for drawing:
void Engine::Process(){
        while(window.pollEvent(event)){
                if(event.type == (sf::Event::Closed)){
                        window.close();
                }
        }
        sf::Vector2f mousePos(sf::Mouse::getPosition());
//sf::View
        view.setCenter(mousePos);
}

void Engine::Render(){
//sf::RenderWindow
        window.clear(sf::Color::Black);
//sf::RenderTexture
        flashlight.clear(sf::Color::Black);
//comment the setView() out, program works fine
        flashlight.setView(view);
        flashlight.draw(board.GetWalls()[0].GetWallShape());
    flashlight.draw(board.GetTexts()[0].GetText());
        const sf::Texture &texture = flashlight.getTexture();
        sf::Sprite sprite(texture);
        window.draw(sprite);
        window.display();
}

I'm confused as to why this isn't working, but it did work (displayed only the top left 75 * 75 pixels) without setting the RenderTexture's view.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Re: Drawing a "flashlight texture" around mouse position?
« Reply #11 on: October 23, 2014, 03:25:56 pm »
You never call display() on your render texture.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

wh1t3crayon

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
Re: Drawing a "flashlight texture" around mouse position?
« Reply #12 on: October 23, 2014, 05:18:44 pm »
Adding flashlight.display() before window.display() doesn't change anything. It's weird though, because the program will draw whatever my mouse is near (where the sf::View is), and draws it in the top left corner (the sf::RenderTexture is there, but I want the rendertexture to be following the mouse).

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
AW: Drawing a "flashlight texture" around mouse position?
« Reply #13 on: October 23, 2014, 07:01:04 pm »
As far as I can tell you're using the view wrong. Check again the official tutorial (and/or my old one on the wiki).

I'm not sure if you've just missed it, but I already linked my "flashlight" example. It too uses a render texture. Once you understand that it should be easy to apply the view stuff.

Mixing two problems will mostly complicate things, so it might be best to focus on ond task at once. ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

wh1t3crayon

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
Re: Drawing a "flashlight texture" around mouse position?
« Reply #14 on: October 24, 2014, 02:40:21 pm »
As far as I can tell you're using the view wrong.
Look, deja vu.  ;) Your tutorial helps, but it fails to show how to draw objects inside the flashlight texture. You just set its fill color, but I want sprites from the window to be drawn inside the area.