gen2brain / raylib-go

Go bindings for raylib, a simple and easy-to-use library to enjoy videogames programming.
zlib License
1.55k stars 159 forks source link

Shader does not render correctly until rl.DrawGrid(0, 1.0) is called once #326

Closed Gishblade closed 4 months ago

Gishblade commented 9 months ago

I've noticed a weird issue where my shader does not work correctly until rl.DrawGrid(0, 1.0) is called at least once (it does not need to be called every frame)

Video of Bug: https://www.youtube.com/watch?v=lKa4bVZqznE

I suspect it is related to how textures get loaded in the shader.

My rendering loop is

for !rl.WindowShouldClose() {
        startThing += stepSize
        rl.BeginDrawing()
        {
            rl.ClearBackground(rl.RayWhite)
            rl.BeginMode3D(camera)
            {
                if frameCount == 100 {
                    rl.DrawGrid(0, 1.0)
                }
                if modelCase == 2 {
                    rl.SetShaderValueTexture(shader, primaryShaderLocation, texture)
                    rl.SetShaderValueTexture(shader, dfLocation, linework)
                }
                for i := 0; i < numThingsToSpawn; i++ {
                    sin := float32(math.Sin(startThing+float64(i)*fnMult)) * float32(radGrowth) * float32(i)
                    cos := float32(math.Cos(startThing+float64(i)*fnMult)) * float32(radGrowth) * float32(i)
                    if sin == cos && sin != cos && maxHeight == 30 {
                        break
                    }
                    rl.DrawModel(model, rl.Vector3{X: cos, Z: sin, Y: maxHeight - float32(i)*(maxHeight/float32(numThingsToSpawn))}, 1.0, rl.White)
                }
            }
            rl.EndMode3D()
            rl.DrawFPS(20, 20)
        }
        rl.EndDrawing()
        frameCount++
        if frameCount >= frameTarget {
            break
        }
    }

when modelCase != 2 it does not use my shader at all, and code works as expected (even when not calling rl.DrawGrid(0, 1.0).

My custom shader is

#version 330

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

// Input uniform values
uniform sampler2D texture0;
uniform sampler2D distance_field;
uniform sampler2D overwrite_tex;

uniform float divider = 0.5;

out vec4 finalColor;

void main()
{
//    float smoothing = 1.0 / 38.0;
    float smoothing = 1.0 / 18.0;
    float center = 0.65;
    vec4 color = texture(overwrite_tex, fragTexCoord);
    // Place fragment code here.
    float df_alpha = texture(distance_field, fragTexCoord).a;
    if (df_alpha == 0) {
        finalColor = color;
    } else {
        float dfv = df_alpha / 2.0 + 0.5;
        float sstep = smoothstep(center - smoothing, center + smoothing, dfv);
//        float sstep = 0.0;
        finalColor = (1.0 - sstep) * color + sstep * vec4(0.0, 0.0, 0.0, 1.0);
    }
}

Importantly, if I change

vec4 color = texture(overwrite_tex, fragTexCoord);
....
float sstep = smoothstep(center - smoothing, center + smoothing, dfv);

to

vec4 color = texture(texture0, fragTexCoord);
....
float sstep = 0.0;

It renders the models original texture (what is being passed by texture0) just fine.

So the issue seems to be that it does not load the

uniform sampler2D distance_field;
uniform sampler2D overwrite_tex;

arguments correctly until after rl.DrawGrid(0, 1.0) is called for some reason.

Gishblade commented 9 months ago

Oh, and important to note that this bug is present for versions v4.5.0 and v5.0.0 of this binding.

github.com/gen2brain/raylib-go/raylib v0.0.0-20230511170620-d84e4cc82f8d // indirect - version 4.5.0 github.com/gen2brain/raylib-go/raylib v0.0.0-20231123174446-48309e2407b7 // indirect - version 5.0.0.

Unsure if it is an issue with the bindings or raylib.

JupiterRider commented 9 months ago

@Gishblade Maybe you are missing a rl.Begin and rl.End?

Gishblade commented 9 months ago

I've got the Begin/End for both BeginDrawing and BeginMode3D.

I don't think there's a third one needed?

gen2brain commented 6 months ago

Is this an issue with just the Go bindings or Raylib in general?

JupiterRider commented 4 months ago
// Draw a grid centered at (0, 0, 0)
void DrawGrid(int slices, float spacing)
{
    int halfSlices = slices/2;

    rlBegin(RL_LINES);
        for (int i = -halfSlices; i <= halfSlices; i++)
        {
            if (i == 0)
            {
                rlColor3f(0.5f, 0.5f, 0.5f);
                rlColor3f(0.5f, 0.5f, 0.5f);
                rlColor3f(0.5f, 0.5f, 0.5f);
                rlColor3f(0.5f, 0.5f, 0.5f);
            }
            else
            {
                rlColor3f(0.75f, 0.75f, 0.75f);
                rlColor3f(0.75f, 0.75f, 0.75f);
                rlColor3f(0.75f, 0.75f, 0.75f);
                rlColor3f(0.75f, 0.75f, 0.75f);
            }

            rlVertex3f((float)i*spacing, 0.0f, (float)-halfSlices*spacing);
            rlVertex3f((float)i*spacing, 0.0f, (float)halfSlices*spacing);

            rlVertex3f((float)-halfSlices*spacing, 0.0f, (float)i*spacing);
            rlVertex3f((float)halfSlices*spacing, 0.0f, (float)i*spacing);
        }
    rlEnd();
}

@Gishblade I think you missed a Begin() and End(), which is the Go call for rlBegin and rlEnd. This is what DrawGrid does internally as well.

@gen2brain Think this issue can be closed then.

Gishblade commented 4 months ago

oh, so in my case raylib needs

rl.Begin() rl.BeginDrawing() rl.BeginMode3D()

to render correctly, and the examples mostly get away without explicitly calling rl.Begin() because they happen to call DrawGrid() which calls into rl.Begin()

?

Gishblade commented 4 months ago

Is it intended for users to call rlBegin() themselves?

I don't see a Begin() method in the cheetsheet (just BeginDrawing, BeginMode2D, BeginMode3D, etc.) suggesting it's supposed to be for internal use?

JupiterRider commented 4 months ago

rlBegin() is part of rlgl. rlgl is a low level API for OpenGL. It's meant to be used by advanced users.