在调整窗口大小时移动灯光着色器

时间:2017-01-27 18:23:11

标签: c++ glsl sfml

我一直在努力制作一个小小的着色器。 它完美地工作,我的意思是,光线应该按照预期的方式消失,它是围绕着我的角色移动的一个圆圈。 只有当调整大小事件不存在时,它才可能是完美的。

当SFML调整窗口大小时,它会扩大所有内容,但是会以一种奇怪的方式。它扩大了所有但着色器。 我试图调整窗口大小(我喜欢调整像素图形游戏的大小,我觉得它最漂亮。所以我不想阻止调整大小的事件。)

这是我的着色器:

with open ('dict_output.csv', 'r') as f:
    reader = csv.reader(f)
    columns = next(reader)

#Strips white space in header
    columns = [h.strip() for h in columns]


#reader = csv.DictReader(f, fieldnames=columns)
    for row in reader:
        print(row)

    con = sqlite3.connect("city_spec.db")
    cursor = con.cursor()

#Inserts data from csv into table in sql database.
    query = 'insert into MyTable({0}) values ({1})'
    query = query.format(','.join(columns), ','.join('?' * len(columns)))
    print(query)
    cursor = con.cursor()
    for row in reader:
        cursor.execute(query, row)
#cursor.commit()

    con.commit()

    con.close()

所以,问题是,我的窗口显示为1280 x 736(适合32x32纹理),我有一个1920 x 1080显示器。当我放大窗口以适应1920 x 1080(包括标题栏)时,整个事情正确调整大小,一切都很好,但着色器现在是1920x1080(减去标题栏)。因此着色器需要不同的坐标(假设x = 32,y = 0,对于着色器,x = 48 y = 0)。

所以我想知道,是否可以用整个窗口放大着色器?我应该使用类似事件吗?

感谢您的回答^^

编辑:这是一些照片: Before 所以这是在它调整大小之前的浅色着色器(它到处都是黑暗但在播放器上,就像它应该的那样)。 After然后我调整窗口大小,播放器不移动,纹理适合整个窗口,但光线移动。

所以,为了正确解释,当我调整窗口大小时,我希望所有东西都适合窗口,所以它充满了纹理,但是当我这样做时,给我的着色器的坐标是在调整大小之前的坐标,如果我移动它就好像我没有调整窗口大小一样,所以光线再也不会出现在我的播放器上了。

我不确定它更清楚,但我尽力了。

EDIT2:这是调用着色器的代码:

    uniform vec3 light;

void main(void) {
    float distance = sqrt(pow(gl_FragCoord.x - light.x, 2) + pow(gl_FragCoord.y - light.y, 2));
    float alpha = 1.;

    if (distance <= light.z) {
        alpha = (1.0 / light.z) * distance;
    }
    gl_FragColor = vec4(0., 0., 0., alpha);

}

1 个答案:

答案 0 :(得分:1)

您显示的代码片段实际上只更新着色器坐标(从快速一瞥看起来很好)。这个错误最有可能发生在您实际绘制的地方。

我会使用一种完全不同的方法,因为一旦你渲染了多个东西,其他光源等,你的着色器方法可能会变得相当乏味。

因此我建议你渲染一个光照贴图到渲染纹理(基本上就像“黑色=没有光,颜色=那种颜色的光”)。

我没有试图解释文本中的所有内容,而是编写了一个快速评论的示例程序,它将在屏幕上绘制一个窗口并在背景图像上移动一些光源(我使用了SFML着色器示例附带的那个) ):

Screenshot of the example code in action

除了在启动路径中有一个名为“background.jpg”的文件之外,没有任何要求。

随意复制此代码或将其用作灵感。请记住,这不是优化的,只是快速编辑以显示一般的想法。

#include <SFML/Graphics.hpp>
#include <vector>
#include <cmath>

const float PI = 3.1415f;

struct Light
{
    sf::Vector2f position;
    sf::Color color;
    float radius;
};

int main()
{
    // Let's setup a window
    sf::RenderWindow window(sf::VideoMode(640, 480), "SFML Lights");
    window.setVerticalSyncEnabled(false);
    window.setFramerateLimit(60);

    // Create something simple to draw
    sf::Texture texture;
    texture.loadFromFile("background.jpg");
    sf::Sprite background(texture);

    // Setup everything for the lightmap
    sf::RenderTexture lightmapTex;
    // We're using a 512x512 render texture for max. compatibility
    // On modern hardware it could match the window resolution of course
    lightmapTex.create(512, 512);
    sf::Sprite lightmap(lightmapTex.getTexture());
    // Scale the sprite to fill the window
    lightmap.setScale(640 / 512.f, 480 / 512.f);
    // Set the lightmap's view to the same as the window
    lightmapTex.setView(window.getDefaultView());

    // Drawable helper to draw lights
    // We'll just have to adjust the first vertex's color to tint it
    sf::VertexArray light(sf::PrimitiveType::TriangleFan);
    light.append({sf::Vector2f(0, 0), sf::Color::White});
    // This is inaccurate, but for demo purposes…
    // This could be more elaborate to allow better graduation etc.
    for (float i = 0; i  <= 2 * PI; i += PI * .125f)
        light.append({sf::Vector2f(std::sin(i), std::cos(i)), sf::Color::Transparent});

    // Setup some lights
    std::vector<Light> lights;
    lights.push_back({sf::Vector2f(50.f, 50.f), sf::Color::White, 100.f });
    lights.push_back({sf::Vector2f(350.f, 150.f), sf::Color::Red, 150.f });
    lights.push_back({sf::Vector2f(150.f, 250.f), sf::Color::Yellow, 200.f });
    lights.push_back({sf::Vector2f(250.f, 450.f), sf::Color::Cyan, 100.f });

    // RenderStates helper to transform and draw lights
    sf::RenderStates rs(sf::BlendAdd);

    while (window.isOpen()) {
        sf::Event event;
        while (window.pollEvent(event)) {
            switch (event.type) {
                case sf::Event::Closed:
                    window.close();
                    break;
            }
        }

        bool flip = false; // simple toggle to animate differently

        // Draw the light map
        lightmapTex.clear(sf::Color::Black);
        for(Light &l : lights)
        {
            // Apply all light attributes and render it

            // Reset the transformation
            rs.transform = sf::Transform::Identity;

            // Move the light
            rs.transform.translate(l.position);

            // And scale it (this could be animated to create flicker)
            rs.transform.scale(l.radius, l.radius);

            // Adjust the light color (first vertex)
            light[0].color = l.color;

            // Draw the light
            lightmapTex.draw(light, rs);

            // To make things a bit more interesting
            // We're moving the lights
            l.position.x += flip ? 2 : -2;
            flip = !flip;
            if (l.position.x > 640)
                l.position.x -= 640;
            else if (l.position.x < 0)
                l.position.x += 640;
        }
        lightmapTex.display();

        window.clear(sf::Color::White);
        // Draw the background / game
        window.draw(background);
        // Draw the lightmap
        window.draw(lightmap, sf::BlendMultiply);
        window.display();
    }
}