Search code examples
c++glslshaderfragment-shaderraylib

Object not moving according to mouse position when using shaders in raylib


I'm creating a few glowing particles in raylib using shaders and the particles are supposed to move along with the mouse but when compiling it gets stuck to the bottom left corner and the particles dont move.

How it Looks

The c++ code

#include <raylib.h>
#include <vector>


const int W = 400;
const int H = 400;

std::vector<Vector2> particle;

float remap(float value, float low1, float high1, float low2, float high2) {
    return low2 + (value - low1) * (high2 - low2) / (high1 - low1);
}

int main() {
    SetConfigFlags( FLAG_WINDOW_RESIZABLE );
    InitWindow(W, H, "FireWorks");

    Shader shader = LoadShader("../assets/vert.glsl", "../assets/frag.glsl");
    Texture2D texture = LoadTextureFromImage(GenImageColor(W, H, BLUE));

    int resolLoc = GetShaderLocation(shader, "resolution");
    int particleLoc = GetShaderLocation(shader, "particle");
    int particleCountLoc = GetShaderLocation(shader, "particleCount");

    float res[2] = {(float)W, (float)H};
    SetShaderValue(shader, resolLoc, res, SHADER_UNIFORM_VEC2);

    SetTargetFPS(60);

    while (!WindowShouldClose()) {
        BeginDrawing();
        ClearBackground(BLACK);

        particle.push_back(Vector2{(float)GetMouseX(), (float)GetMouseY()});
        int removeCount = 1;

        for (int i = 0; i < removeCount; i++) {
            if (particle.size() == 0) break;

            if (particle.size() > 30) {
                particle.erase(particle.begin() + i);
            }
        }

        BeginShaderMode(shader);

        float particles[30][2];

        for ( int i = 0; i < particle.size(); i++) {
            particles[i][0] = remap(particle[i].x, 0, W, 0.0, 1.0);
            particles[i][1] = remap(particle[i].y, 0, H, 1.0, 0.0);
        }

        int pSize = particle.size();

        SetShaderValue(shader, particleCountLoc, &pSize, SHADER_UNIFORM_INT);
        SetShaderValue(shader, particleLoc, particles, SHADER_UNIFORM_VEC2);

        DrawTextureRec(texture, (Rectangle) { 0, 0, (float)texture.width, (float) -texture.height }, (Vector2) { 0, 0}, RAYWHITE);
        DrawRectangle(0, 0, W, H, BLACK);

        EndShaderMode();
        EndDrawing();
    }

    UnloadTexture(texture);
    UnloadShader(shader);
    CloseWindow();

    return 0;
}

The Vertex Shader

#version 330

// Input vertex attributes
in vec3 vertexPosition;
in vec2 vertexTexCoord;
in vec3 vertexNormal;
in vec4 vertexColor;

// Input uniform values
uniform mat4 mvp;

// Output vertex attributes (to fragment shader)
out vec2 fragTexCoord;
out vec4 fragColor;

// NOTE: Add here your custom variables 

void main()
{
    // Send vertex attributes to fragment shader
    fragTexCoord = vertexTexCoord;
    fragColor = vertexColor;
    
    // Calculate final vertex position
    gl_Position = mvp * vec4(vertexPosition, 1.0);
}

The Fragment Shader

#version 330

// Input vertex attributes (from vertex shader)
in vec2 fragTexCoord;
in vec4 fragColor;

// Input uniform values
uniform sampler2D texture0;
uniform vec4 colDiffuse;

// Output fragment color
out vec4 finalColor;

// NOTE: Add here your custom variables

uniform vec2 resolution;
uniform int particleCount;
uniform vec2 particle[30];

void main() {
    // Texel color fetching from texture sampler
    vec4 texelColor = texture(texture0, fragTexCoord);
    
    vec2 st = gl_FragCoord.xy / resolution.xy;

    float r = 0.0;
    float g = 0.0;
    float b = 0.0;

    for (int i = 0; i < 30; i++) {
        if (i < particleCount) {
            vec2 particlePos = particle[i];

            float value = float(i) / distance(st, particlePos.xy) * 0.00015;  

            g += value * 0.5;
            b += value;
        }
    }
    
    finalColor = vec4(r, g, b, 1.0) * texelColor * colDiffuse;
}

The JS version of the code (which works) is here.

If you could point me in the right direction it'd be great.


Solution

  • The uniform particle is of type vec2[30]. An uniform array can needs to be set with SetShaderValueV instead of SetShaderValue:

    SetShaderValue(shader, particleLoc, particles, SHADER_UNIFORM_VEC2);

    SetShaderValueV(shader, particleLoc, particles[0], SHADER_UNIFORM_VEC2, 30);