2016-04-09 9 views
2

Ich habe von diesem Artikel wie beschrieben mit Distanzfeld Schriftart experimentiert: https://github.com/libgdx/libgdx/wiki/Distance-field-fontsLibgdx - Benutzerdefinierte Shader für TEXTBUTTON Schriftart

Alles funktioniert gut, wenn ich die Schrift nur bin Rendering, aber wenn ich versuche, den Shader zu verwenden Auf einem TextButton wird die Schaltfläche nur weiß, weil es den Shader auf die gesamte Schaltfläche und nicht nur den Text anwendet. Ich habe mich umgesehen, aber ich kann keine Informationen darüber finden, wie man den Shader nur für den Text einer TextButton ändert, also frage ich hier; Wie wende ich einen Cutom-Shader nur an das Text-Rendering eines TextButton an?

Init-Code:

textShader = new ShaderProgram(Gdx.files.internal("graphics/shaders/font/font.vert"), 
      Gdx.files.internal("graphics/shaders/font/font.frag")); 
//exact same shaders as linked article 
stage = new Stage(); 
stage.getBatch().setShader(textShader); 
//Setting the shader for the stage will set the shader for everything in the stage, 
//like my labels/buttons etc. This works fine for my labels as they are plain text, 
//but my buttons become completely white. 

init the rest of my labels, buttons, batches etc... 

Render-Code:

Gdx.gl.glClearColor(0, 0, 0, 1); 
Gdx.gl.glClear(GL_COLOR_BUFFER_BIT); 

render background/other stuff... 

stage.act(delta); 
stage.draw(); 

Fragment-Shader:

#ifdef GL_ES 
precision mediump float; 
#endif 

uniform sampler2D u_texture; 

varying vec4 v_color; 
varying vec2 v_texCoord; 

const float c_width = 0.5; 
const float c_edge = 0.1; 

const vec2 c_offset = vec2(0); 

const float c_borderWidth = 0.5; 
const float c_borderEdge = 0.5; 

const vec3 c_color = vec3(0.7, 0.3, 0.1); 
const vec3 c_outlineColor = vec3(0.3); 

void main() { 
    float distance = 1.0 - texture(u_texture, v_texCoord).a; 
    float alpha = 1.0 - smoothstep(c_width, c_width + c_edge, distance); 

    float distance2 = 1.0 - texture(u_texture, v_texCoord + c_offset).a; 
    float outlineAlpha = 1.0 - smoothstep(c_borderWidth, c_borderWidth + c_borderEdge, distance2); 

    float overallAlpha = alpha + (1.0 - alpha) * outlineAlpha; 
    vec3 overallColour = mix(c_outlineColor, c_color, alpha/overallAlpha); 

    gl_FragColor = vec4(overallColour, overallAlpha); 
} 

Vertex-Shader:

uniform mat4 u_projTrans; 

attribute vec4 a_position; 
attribute vec2 a_texCoord0; 
attribute vec4 a_color; 

varying vec4 v_color; 
varying vec2 v_texCoord; 

void main() { 
    gl_Position = u_projTrans * a_position; 
    v_texCoord = a_texCoord0; 
    v_color = a_color; 
} 
+0

können wir Ihren Code bitte sehen? –

+0

Ich habe einen Code hinzugefügt. Ich sollte auch beachten, dass der Text auf den TextButtons in Ordnung ist, es ist nur der Hintergrund der Tasten, die versauen. – Charanor

Antwort

3

Der Entfernungsfeld-Shader kann andere Objekte nicht normal darstellen. Um es in scene2D zu verwenden, müssen Sie beim Zeichnen von Labels nur vorübergehend zu diesem Shader wechseln. Daher müssen Sie eine Unterklasse von Label erstellen, die den Shader austauschen kann. Vielleicht so etwas wie:

public class CustomShaderLabel extends Label { 
    private ShaderProgram shader; 
    public CustomShaderLabel(CharSequence text, Skin skin) { 
     super(text, skin); 
    } 

    public CustomShaderLabel(CharSequence text, Skin skin, String styleName) { 
     super(text, skin, styleName); 
    } 

    public CustomShaderLabel(CharSequence text, Skin skin, String fontName, Color color) { 
     super(text, skin, fontName, color); 
    } 

    public CustomShaderLabel(CharSequence text, Skin skin, String fontName, String colorName) { 
     super(text, skin, fontName, colorName); 
    } 

    public CustomShaderLabel(CharSequence text, LabelStyle style) { 
     super(text, style); 
    } 

    public ShaderProgram getShader() { 
     return shader; 
    } 

    public void setShader(ShaderProgram shader) { 
     this.shader = shader; 
    } 

    public void draw (Batch batch, float parentAlpha) { 
     if (shader != null) batch.setShader(shader); 
     super.draw(batch, parentAlpha); 
     if (shader != null) batch.setShader(null); 
    } 
} 

Beachten Sie, dass diese zusätzliche Charge Wallungen verursachen wird, wo immer es Labels, die ein Problem werden könnte, wenn Sie eine komplizierte Hierarchie mit vielen Etiketten.

Da TextButton den benutzerdefinierten Label-Typ nicht kennt, müssen Sie entweder einen Standard-Button verwenden und ein Label hinzufügen oder die meisten TextButton-Klassen kopieren und einfügen, um Ihre eigene Version zu erstellen (Sie können TextButton.TextButtonStyles verwenden, um Ihr Label innerhalb der Schaltfläche zu formatieren.

+0

Das funktioniert, aber jetzt habe ich das Problem, dass meine Etiketten meine Aktionen nicht verwenden (sie verblassen nicht/fadeOut/ändern ihre Alpha). Irgendeine Lösungsmöglichkeit? – Charanor

+0

Wenn Sie den Shader von diesem Link verwenden, ersetzen Alpha in der letzten Zeile mit alpha * v_color.a – Tenfour04

+1

Ich verwende nicht den gleichen Shader, aber ich habe stattdessen overallAlpha * v_color.a in meinem Code, und es hat funktioniert. Vielen Dank! – Charanor

Verwandte Themen