Problem with shaders for DirectGui elements

Hello! I am trying to write some shaders for the frame/background of a DirectButton, but the shader affects both the frame and the text in the element. Is there a good way to only apply the shader to the frame without affecting other parts of the gui?

Here is the code that I have been using this far:

import panda3d.core as p3d
from direct.gui import DirectGui
button = DirectGui.DirectButton(
    text='button',
    frameTexture="models/maps/circle.png",
    relief=DGG.FLAT,
    scale=0.8
)
shader = p3d.Shader.load(p3d.Shader.SL_GLSL,
                         vertex="frame.vert",
                         fragment="frame.frag")
button.setShader(shader)

Vertex shader:

#version 150

uniform mat4 p3d_ModelViewProjectionMatrix;

in vec4 p3d_Vertex;
in vec2 p3d_MultiTexCoord0;

out vec2 texcoord;

void main() {
    gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex;
    texcoord = p3d_MultiTexCoord0;
}

Fragment shader. Just trying to apply some transform to the texture messes up the text.

#version 150

uniform sampler2D p3d_Texture0;

in vec2 texcoord;

out vec4 p3d_FragColor;

void main() {
    vec2 coord = texcoord + vec2(0.1);  //Works fine without this line
    vec4 color = texture(p3d_Texture0, coord);

    p3d_FragColor = color;
}

Hmm…

There should be a way of accessing the specific node associated with the backing geometry, but I don’t seem to be finding it right now.

Failing that, however, you could always just disable the shader on the text.

Specifically, it should be possible to access the node associated with the text via the “component” method, requesting the “text” components (where “” is a number associated with the GUI-state related to that text).

For a DirectButton, then, which has four possible GUI-states (normal, rollover, disabled, and clicked), that means accessing “text0”, “text1”, “text2”, and “text3”.

Once you have those text-objects, just call “setShaderOff(1)” on them. (The “1” gives the setting a higher priority than the default, allowing it to override settings that don’t have a higher-still priority. I’m not sure that it’s called for here, but I include it just in case.)

Something like this:

textObj0 = myDirectButton.component("text0")
textObj0.setShaderOff(1)

Text in Panda is, I believe, just geometry with a texture applied that depicts the various characters of the text. As a result, applying a texture-adjustment may well throw this font-texture out of alignment.

Thank you!

That did indeed fix it. I should have thought about that…

1 Like

DirectGui is rather strange…

However this should work for applying a shader to the frame and no other components of the button for all four states:

button.setShader(shader)
for node in button.stateNodePath:
    node.setShader(shader)
    for child in node.children:
        child.setShaderOff(1)