Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[rlgl] Custom shaders called with rlLoadDrawQuad() cannot fetch data from texture uniforms. #4568

Open
mikeemm opened this issue Dec 2, 2024 · 4 comments
Labels
help needed - please! I need help with this issue

Comments

@mikeemm
Copy link
Contributor

mikeemm commented Dec 2, 2024

Issue description

TL;DR: Shaders made with rlLoadDrawQuad() can't seem to reliably access sampler2D uniforms via texture or texelFetch.

In my program I render a 3D scene into a RenderTexture. I then call rlLoadDrawQuad with a custom shader to load the previous texture, filter it and render to another RenderTexture, which I then output to the screen. However, it seems rlLoadDrawQuad cannot access uniform texture data when it is being called after BeginTextureMode(); removing that and outputting directly into the screen fixes this, but then I can't do further operations with that RenderTexture.

However, when attempting to create a small code sample to share here, I couldn't get rlLoadDrawQuad() to load a texture at all, even when outputting directly to the screen. Everything else in the shaders work correctly, the uniform location is found and the texture coordinates display fine onscreen, but all shader data is black no matter what texture it tries to access despite the image being loaded. I'm not sure where the problem is at this point to be honest.

Environment

Desktop (GLFW)
Windows 10 64-bit
GPU NVIDIA GeForce RTX 3050 Laptop GPU/PCIe/SSE2
OpenGL: 3.3.0 NVIDIA 537.13
GLSL: 3.30 NVIDIA via Cg compiler

Code Example

The code below should output whatever image you load up as example.png, but instead draws blank.

main.c:

#include "raylib.h"
#include "rlgl.h"

int main()
{
    InitWindow(1600, 900, "Test");

    Texture testTexture = LoadTexture("example.png");
    Shader testShader = LoadShader("rendertexture_VP.glsl", "rendertexture_FP.glsl");
    
    SetTargetFPS(60);
    while (!WindowShouldClose())
    {
        BeginDrawing();
            ClearBackground(BLACK);
            int loc = GetShaderLocation(testShader, "source");
            SetShaderValueTexture(testShader, loc, testTexture);
            rlEnableShader(testShader.id);
            rlLoadDrawQuad();
            rlDisableShader();
        EndDrawing();
    }

    CloseWindow();
}

rendertexture_VP.glsl:

#version 330

layout (location = 0) in vec3 vertexPosition;
layout (location = 1) in vec2 vertexTexCoord;

out vec2 fragTexCoord;

void main()
{
    fragTexCoord = vertexTexCoord;
    gl_Position = vec4(vertexPosition, 1.0f);
}

rendertexture_FP.glsl:

#version 330

in vec2 fragTexCoord;

uniform sampler2D source;

out vec4 finalColor;

void main()
{
    vec3 texColor = texture(source, fragTexCoord).xyz;
    finalColor = vec4(texColor, 1.0f);
}
@raysan5
Copy link
Owner

raysan5 commented Dec 2, 2024

@mikeemm Considering you are using rlgl, you should use rlSetShader(unsigned int id, int *locs) to enable shader locations, or do the process manually.

Note that rlgl is a lower level API, just a thin layer over OpenGL, but still has some custom functionality.

@raysan5 raysan5 closed this as completed Dec 2, 2024
@mikeemm
Copy link
Contributor Author

mikeemm commented Dec 3, 2024

@raysan5 I tried that before, and neither rlSetShader() nor BeginShaderMode() (which just calls rlSetShader() internally) worked. Adding either of these in the example I provided does not fix the issue for me, as the shader still refuses to access the texture. Please don't close this issue quite yet.

@raysan5 raysan5 reopened this Dec 3, 2024
@raysan5
Copy link
Owner

raysan5 commented Dec 3, 2024

@mikeemm Ok, reopening it.

@raysan5 raysan5 added the help needed - please! I need help with this issue label Dec 3, 2024
@raysan5 raysan5 changed the title [rlgl] Custom shaders called with rlLoadDrawQuad() cannot fetch data from texture uniforms. [rlgl] Custom shaders called with rlLoadDrawQuad() cannot fetch data from texture uniforms. Dec 3, 2024
@mikeemm
Copy link
Contributor Author

mikeemm commented Dec 4, 2024

Turns out before you set the sampler uniform you have to bind the texture using rlEnableTexture(); I assume this worked at first in my personal project because at some point during the rendering phase something in my code already bound the texture and left it bound.

However, the other reason this doesn't work is because SetShaderValueTexture() calls rlSetUniformSampler(), which calls glUniform1i(locIndex, 1 + i). This assumes that there was already one texture bound at texture unit 0 before binding the one you'd actually want to use; again, I assume this worked for me at first because a previous operation left a texture bound on unit 0 without adding its id to the RLGL state. Using SetShaderValue() instead with an explicit texture unit solves this.

So this doesn't work:

BeginDrawing();
    rlEnableTexture(testTexture.id);
    int texLoc = GetShaderLocation(testShader, "source");
    SetShaderValueTexture(testShader, texLoc, testTexture);
    rlLoadDrawQuad();
    rlDisableShader();
EndDrawing();

But this does:

BeginDrawing();
    rlEnableTexture(testTexture.id);
    int texUnit = 0;
    int texLoc = GetShaderLocation(testShader, "source");
    SetShaderValue(testShader, texLoc, &texUnit, SHADER_UNIFORM_SAMPLER2D);
    rlLoadDrawQuad();
    rlDisableShader();
EndDrawing();

This behavior must be intentional so that it works together with other drawing functions, which seem to set a default texture to texture unit 0 - my question is, where and why is this texture added? It seems incoherent that SetShaderValueTexture() would work or not depending on where in the program it was being used, with no way to know whether it would work until runtime. Is the reasoning for this behavior already documented somewhere perhaps?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help needed - please! I need help with this issue
Projects
None yet
Development

No branches or pull requests

2 participants