dgcor / DGEngine

An implementation of the Diablo 1 game engine
Other
253 stars 29 forks source link

Fix lighting #33

Closed ghost closed 3 years ago

ghost commented 5 years ago

A new lighting implementation was added that uses shaders. An array is passed to the shader with the position of the light, intensity and radius (with the closest lights to the player). It's working well for just 1 light (the player's, which is always centered in the texture) but not for floor lights, such as the ones in D1's caves:

d1_lighting

The shader is loaded from ShaderManager.cpp - the Level shader levelText. and the primitives passed to it are set in Level.cpp's draw function:

    sf::RenderStates states(sf::RenderStates::Default);
    if (shader != nullptr)
    {
        states.shader = shader;
        shader->setUniform("elapsedTime", game.getTotalElapsedTime().asSeconds());
        if (hasMouseInside == true)
        {
            shader->setUniform("mousePosition", sf::Glsl::Vec2(
                (game.MousePositionf().x - surface.Position().x) /
                surface.Size().x,
                (game.MousePositionf().y - surface.Position().y) /
                surface.Size().y
            ));
        }
        shader->setUniform("textureSize", sf::Glsl::Vec2(
            surface.Size().x,
            surface.Size().y
        ));

        shader->setUniform("visibleRect", sf::Glsl::Vec4(
            surface.visibleRect.left,
            surface.visibleRect.top,
            surface.visibleRect.width,
            surface.visibleRect.height
        ));

        shader->setUniform("numberOfLights", (int)map.lightArray.size());
        shader->setUniformArray("lights", map.lightArray.data(), map.lightArray.size());
        shader->setUniform("defaultLight", ((float)map.getDefaultLight() / 255.f));
        shader->setUniform("radiusSize", (float)(std::max(map.MapSizef().x, map.MapSizef().y)));
    }
    surface.draw(target, states);

There must be something I'm missing. I can't get the lights to draw over the water.

PS: zoom kind of breaks light because of how it's drawn. try first to get it working on 100% zoom only.

grantramsay commented 5 years ago

Hey, I had a play round with this. Just inverting the y position seemed to work for me, IIRC opengl y coordinate is backwards to what you might think. E.g something like:

vec2 coord = vec2(gl_TexCoord[0].x, 1.0 - gl_TexCoord[0].y);
vec2 pixelPos = visibleRect.xy + (visibleRect.zw * coord);

(Also the new D2 textures look mint!)

ghost commented 5 years ago

Thanks, that's it. Visually, I could see it was something like this.

ghost commented 3 years ago

Fixed in last push. It's now using a simpler shader that has lighting in the alpha channel.