iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 28
0
自我挑戰組

寫遊戲初體驗系列 第 28

Day 28 Particle System 4

  • 分享至 

  • xImage
  •  

Particle System Render

在寫 Render code 之前我們先來寫 Shader 吧

vertex shader:

#version 330 core
layout (location = 0) in vec4 vertex; // <vec2 position, vec2 texCoords>

out vec2 TexCoords;
out vec4 ParticleColor;

uniform mat4 transform;
uniform mat4 projection;
uniform vec4 color;
uniform float scale;

void main()
{
    TexCoords = vertex.zw;
    ParticleColor = color;
    gl_Position = projection * transform * vec4((vertex.xy), 0.0, 1.0);
}

fragment shader

#version 330 core
in vec2 TexCoords;
in vec4 ParticleColor;
out vec4 color;

uniform sampler2D sprite;

void main()
{
    color = (texture(sprite, TexCoords) * ParticleColor);
}

以上的 Shader 應該都很簡單清楚,都跟之前的差不多

Render 的 code

void EmitterSystem::render(entt::registry &registry) {
    auto group = registry.view<TransformComponent, EmitterComponent>();

    for (auto entity : group) {
        auto &transform = registry.get<TransformComponent>(entity);
        auto &emitter = registry.get<EmitterComponent>(entity);

        glBlendFunc(GL_SRC_ALPHA, GL_ONE);
        shader -> bind();
        for (auto &particles : emitter.particles) {
            if(particles.life > 0.f) {
                shader->setFloat2("offset", particles.pos);
                shader->setFloat4("color", particles.currentColor);

                glm::mat4 trans(1.f);

                trans = glm::translate(trans, glm::vec3(particles.pos.x, particles.pos.y, 1.0f));
                trans = glm::rotate(trans, glm::radians(particles.angle), glm::vec3(0.f, 0.f, 1.f));
                trans = glm::scale(trans, glm::vec3(particles.currentSize ,particles.currentSize,1.0f));
                shader->setMat4("transform", trans);

                emitter.texture->bind();
                vertexArray->bind();
                glDrawArrays(GL_TRIANGLES, 0, 6);
                vertexArray->unbind();
            }
        }
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    }
} // End EmitterSystem::render()

我們整個的遊戲流程大概會是這樣

void Game::Init() {

    ResourceManager::loadShader("ptShader.glsl", "ptfShader.glsl", "particle");

    auto& particleShader = ResourceManager::getShader("particle");
    particleShader->bind();
    particleShader->setInt("sprite", 0);
    particleShader->setMat4("projection", projection);

    ResourceManager::loadTexture("particle.png", "particle");
    
    particleSystem.init(ResourceManager::getShader("particle"));
}

void Game::ProcessInput() {

  if(sf::Keyboard::isKeyPressed(sf::Keyboard::Q)) {

        std::ifstream is("Fire.json");
        std::string str((std::istreambuf_iterator<char>(is)), std::istreambuf_iterator<char>());
        std::stringstream oos(str);

        cereal::JSONInputArchive ar(oos);

        EmitterData data;
        ar(data);

        auto emit = registry.create();
        registry.emplace<TransformComponent>(emit, glm::vec2(sf::Mouse::getPosition(window_).x, sf::Mouse::getPosition(window_).y), glm::vec2(100.f, 100.f));
        registry.emplace<EmitterComponent>(emit, ResourceManager::getTexture("5"), data);
        registry.emplace<TagComponent>(emit);

        emitterSystem.initEmitter(registry, emit);
        
    }
}


void Game::Update(float) {

    particleSystem.update(registry, dt);
}

void Game::Render() {

    particleSystem.render(registry);
}

這樣就完成了!


上一篇
Day 27 Particle System 3
下一篇
Day 29
系列文
寫遊戲初體驗30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言