0 votes

Hi, I have some custom particle shaders that work with Particles2D when I run the game from the editor, but once I export the game to a release build, they stop emitting or doing anything.

I am running Godot on 3.2.2-stable for both my exports and editor, and doing all of this on Windows.

Is there some box I have tick in order to get drivers working for custom particle shaders on the exported project? Or is my shader code failing for whatever reason only upon export.

Any suggestions on how to fix would be great.

Let me dump my shader code below, although I don't think there is anything wrong with it:

shader_type particles;

// particle firing stuff
uniform float spread;
uniform float firing_angle;
uniform int amount;
uniform float speed;

// obstacle texture stuff
uniform sampler2D obstacle_tex : hint_black;
uniform int block_sz;
uniform vec2 tex_origin;

vec2 ang2vec(float a) {
    return vec2(cos(a), sin(a));

mat4 rotationMatrix(vec3 axis, float angle)
    axis = normalize(axis);
    float s = sin(angle);
    float c = cos(angle);
    float oc = 1.0 - c;

    mat4 resm;
    resm[0] = vec4(oc * axis.x * axis.x + c, oc * axis.x * axis.y + axis.z * s, oc * axis.z * axis.x - axis.y * s, 0.0);
    resm[1] = vec4(oc * axis.x * axis.y - axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z + axis.x * s, 0.0);
    resm[2] = vec4(oc * axis.z * axis.x + axis.y * s, oc * axis.y * axis.z - axis.x * s, oc * axis.z * axis.z + c, 0.0);
    resm[3] = vec4(0.0, 0.0, 0.0, 1.0);

    return resm;

void vertex()
    // collision found later
    // v_found_obstacle = uintBitsToFloat(0);
    COLOR.a = 1.0;

    // reset
    if (RESTART) {
        // translate because of non-local coords
        // rotate based on firing_angle
        TRANSFORM *= rotationMatrix(vec3(0.0, 0.0, 1.0), firing_angle);
        // start moving
        float increment = spread / float(amount);
        float idx_angle = ((float(INDEX) - float(amount)/2.0) * increment) + firing_angle;
        vec2 firing_direction = ang2vec(idx_angle);
        VELOCITY.xy = firing_direction * speed;
    } else {
        // check if inside square next frame
        // get pos
        ivec2 world_pos;
        world_pos.x = int(TRANSFORM[3].x) + int(VELOCITY.x * DELTA);
        world_pos.y = int(TRANSFORM[3].y) + int(VELOCITY.y * DELTA);

        // get byte
        ivec2 obst_pos_st = (world_pos / block_sz) - ivec2(int(tex_origin.x), int(tex_origin.y));
        vec4 texel = texelFetch(obstacle_tex, obst_pos_st, 0);
        bool non_obstacle = floatBitsToUint(texel.r) != uint(0x00);
        // check result
        if (non_obstacle) {
            // stop moving
            ACTIVE = false;
enter code here
in Engine by (283 points)

1 Answer

0 votes
Best answer

I had two issues:
1) I was not exporting the .json files I was using for meta data in my shader. That was fixed by adding *.json to non-resource files when exported.

2) Checking if a file exists via File.new().file_exists(path) doesn't work with image resources after exporting the game, because they get shuffled around in the pack. Issue is documented here: File.file_exists() doesn't take remappings after resource conversion into account

by (283 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.