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

Author Topic: [SOLVED] Lightmap Shader + scrolling screen  (Read 2337 times)

0 Members and 1 Guest are viewing this topic.

bradgate

  • Newbie
  • *
  • Posts: 7
    • View Profile
[SOLVED] Lightmap Shader + scrolling screen
« on: July 10, 2018, 03:41:03 pm »
Hello,

I am attempting to implement my first lighting shader using a lightmap for some spotlights by rendering to a render texture and then blending this render texture over the game world for and additional amibent lighting effect, which is working nicely. (I am using SFML.Net)

The problem i'm having is with my scrolling View. When the view scrolls, the lights remain rendered in the same position and scrolling with the view, rather than being rendered in their original position.

My spotlights are sprites which remain in the same position throughout, which leads me to the conclusion that the issue lies with either the render texture used as the lightmap or the shader itself.

Any help would be greatly appreciated, this is one of my first attempts at lighting techniques, so i'm at a loss.

I'm using the standard passthrough vertex shader, so i don't specify one in my Shader instance.

my lighting fragment shader:

uniform sampler2D texture;
uniform sampler2D lightmap;

uniform vec4 ambient;
uniform vec2 resolution;

void main()
{
        vec4 diffuse = texture2D(texture, gl_TexCoord[0].xy);
        vec2 lightcoord = (gl_FragCoord.xy / resolution.xy);
        vec4 light = texture2D(lightmap, lightcoord);

        vec4 ambientLight = ambient;

        //ambientLight.a is used as intensity to pass through as vec4
        vec3 ambientColour = ambientLight.rgb * ambientLight.a;
        vec3 intensity = ambientColour + light.rgb;

        vec3 result = diffuse.rgb * intensity;

    gl_FragColor = vec4(result, diffuse.a);
}

Rendering:
public class RenderSystem : IDisposable
    {
        private readonly RenderWindow _window;
        public View View { get; }
        private RenderTexture _renderTexture;
        private Sprite _lightmap;

        public RenderStates States { get; set; }

        public RenderSystem(RenderWindow window, IUiLayer uiLayer)
        {
            _window = window;
            _renderTexture = new RenderTexture(_window.Size.X, _window.Size.Y);
            _lightmap = new Sprite(_renderTexture.Texture);

            UiLayer = uiLayer;
            View = new View((Vector2f)_window.Size / 2, (Vector2f)_window.Size);
        }

        public void RenderLights(IEnumerable<Sprite> lights)
        {
            _renderTexture.Clear(Color.Transparent);
            foreach (var light in lights)
            {
                _renderTexture.Draw(light);
            }
            _renderTexture.Display();

            States.Shader.SetUniform("lightmap", _renderTexture.Texture);
        }

        public void RenderDrawable(Drawable drawable)
        {
            _window.Draw(drawable, States);
        }
}
 

Render Method in my game loop:

public void Render()
{
    RenderSystem.RenderDrawable(_levelSprite);
    RenderSystem.RenderLights(_lights);

    foreach(Sprite gameObject in _gameObjects)
    {
        RenderSystem.RenderDrawable(gameObject);
    }
}
 

Initialisation of RenderSystem.States pre-gameloop:
public void Initialise()
{
    //Sig: Shader.FromString(string vertexShader, string geometryShader, string fragmentShader);
    Shader shader = Shader.FromString(null, File.ReadAllText("lighting.frag"), null);
    RenderSystem.States = new RenderStates(shader);
    RenderSystem.States.Shader.SetUniform("ambient", new Vec4(161, 93, 30, 167));
    RenderSystem.States.Shader.SetUniform("resolution", new Vec2(640, 480));
}
 
« Last Edit: July 13, 2018, 05:49:17 pm by bradgate »

verdog

  • Newbie
  • *
  • Posts: 25
    • View Profile
    • Email
Re: Lightmap Shader + scrolling screen
« Reply #1 on: July 12, 2018, 03:54:19 pm »
I'm inexperienced with shaders, so I apologize if I've overlooked something, but is it because the light sources are calculating the mask from their position and not taking the screen position into account?

That is, the lights are calculating the correct mask, but they're rendering to the texture as if the screen hasn't moved, and then you render the texture on top of the moved screen?

bradgate

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: Lightmap Shader + scrolling screen
« Reply #2 on: July 12, 2018, 05:40:50 pm »
Hi Verdog,

Thanks for your reply, it seems that is exactly what's happening, i'm just unsure how to correct the shader to take into account the original position of the light sources, or is this something that would be done as part of the main program and not in the shader?

verdog

  • Newbie
  • *
  • Posts: 25
    • View Profile
    • Email
Re: Lightmap Shader + scrolling screen
« Reply #3 on: July 12, 2018, 08:09:45 pm »
If it were me, I think I would try making adjustments before the shader (but again, I don't know much about shaders...).

In your RenderLights function, you could try internally adjusting the position of the lights before rendering them. So if your screen has moved 64 pixels to the right, you should internally move the lights 64 pixels to the left before rendering them (at least that's how I'd do it)

Not sure if that will work, but it was my first thought.

edit: Actually, now that I think of it, I'm not so sure that will work. I think you need to move the lightmap texture before applying the shader instead?

bradgate

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: Lightmap Shader + scrolling screen
« Reply #4 on: July 13, 2018, 09:55:46 am »
I figured it out, it turned out to be quite an easy solution.

I actually missed a line from the code that i posted which has probably confused the situation, my actual game object rendering method is:

public void RenderDrawable(Drawable drawable)
{
    _window.SetView(View);// this is the line that was missing from my original post.
    _window.Draw(drawable, States);
}

Now the solution was to set this same view on the lightmap render texture:

public void RenderLights(IEnumerable<Sprite> lights)
{
    _renderTexture.Clear(Color.Transparent);

    //adding this resulted in the light sources rendering to their original position
    //when scrolling
    _renderTexture.SetView(View);

    foreach (var light in lights)
    {
        _renderTexture.Draw(light);
    }
    _renderTexture.Display();

    States.Shader.SetUniform("lightmap", _renderTexture.Texture);
}

Thanks for your suggestion verdog, it led me to attempt this, although to be completely honest, i'm not exactly sure why this works, since it is the view that is scrolling. I would've thought the lightmap would've scrolled with it.

I appreciate you taking the time to help  :)

verdog

  • Newbie
  • *
  • Posts: 25
    • View Profile
    • Email
Re: Lightmap Shader + scrolling screen
« Reply #5 on: July 13, 2018, 03:14:25 pm »
Glad you got it working!

I think this works because the window's view and the texture's view are separate things. When you set the window's view, it doesn't change the texture's view, which caused it to render in the wrong position. When you changed both the window and the texture's view, they both move together.