2016-04-15 8 views
1

Ich kam zu Shaders für LibGDX und bemerkte, dass es einige Attribute gibt, die nur in LibGDX verwendet werden.Convert OpenGL HQX Shader zu LibGDX

Die Standard-Vertex- und Fragment-Shader von https://github.com/libgdx/libgdx/wiki/Shaders funktionieren perfekt und werden auf meinen SpriteBatch angewendet.

Wenn ich versuche, einen HQX-Shader wie https://github.com/SupSuper/OpenXcom/blob/master/bin/common/Shaders/HQ2x.OpenGL.shader zu verwenden, bekomme ich eine Menge Fehler.

Wahrscheinlich, weil ich einige libGDX abhängige Variablen an den Shader senden muss, aber ich kann nicht herausfinden, was das sein sollte.

Ich möchte diese Shader auf Desktops mit großen Bildschirmen verwenden, damit das Spiel auf diesen Bildschirmen gut aussieht.

habe ich diesen Code den Shader zu laden:

try { shaderProgram = new ShaderProgram(Gdx.files.internal("vertex.glsl").readString(), Gdx.files.internal("fragment.glsl").readString()); shaderProgram.pedantic = false; System.out.println("Shader Log:"); System.out.println(shaderProgram.getLog()); } catch(Exception ex) { }

Die Shader Log-Ausgänge: No errors.

Vielen Dank im Voraus.

+0

Wie zeichnest du damit? Haben Sie ein Mesh erstellt oder verwenden Sie SpriteBatch? Ich nehme an, Sie verwenden die Textur von einem FrameBuffer? – Tenfour04

+0

Ich benutze 'batch.setShader (shaderProgram);' in meiner render() Methode, so dass die Shader auf den SpriteBatch angewendet werden, dann zeichne ich alle meine Texturen – ryanrio95

Antwort

0

Dies ist ein Post-Processing-Shader, so dass Ihre Strömung so gehen sollte:

  1. Zeichnen Sie Ihre Szene mit einem FBO in Pixel mit perfekter Auflösung Spritebatch-Standard Shader.

  2. Zeichnen Sie die FBO-Textur mit dem Upscaling-Shader auf den Bildpuffer des Bildschirms. Sie können dies mit SpriteBatch tun, wenn Sie den Shader so ändern, dass er den Attributen und Uniformen entspricht, die SpriteBatch verwendet. (Sie können alternativ ein einfaches Gitter mit den Attributnamen erstellen, die der Shader erwartet, aber Spritebatch ist wahrscheinlich am einfachsten.)

Zunächst einmal sind wir ein typisches Shader mit Spritebatch nicht verwenden, so dass Sie ShaderProgram.pedantic = false; anrufen müssen Irgendwo bevor man etwas lädt.

Jetzt benötigen Sie einen FrameBuffer in der richtigen Größe. Es sollte so dimensioniert sein, dass Ihre Sprites pixelgenau sind (ein Pixel der Textur skaliert zu einem Pixel der Welt). So etwas wie das:

public void resize (int width, int height){ 
    float ratio = (float)width/(float) height; 
    int gameWidth = (int)(GAME_HEIGHT/ratio); 
    boolean needNewFrameBuffer = false; 
    if (frameBuffer != null && (frameBuffer.getWidth() != gameWidth || frameBuffer.getHeight() != GAME_HEIGHT)){ 
     frameBuffer.dispose(); 
     needNewFrameBuffer = true; 
    } 
    if (frameBuffer == null || needNewFrameBuffer) 
     frameBuffer = new FrameBuffer(Format.RGBA8888, gameWidth, GAME_HEIGHT); 

    camera.viewportWidth = gameWidth; 
    camera.viewportHeight = GAME_HEIGHT; 
    camera.update(); 
} 

Dann können Sie auf den Bildspeicher zeichnen, als ob es Ihr Bildschirm ist. Danach zeichnen Sie die Textur des Bildspeichers auf den Bildschirm.

public void render(){ 
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); 

    frameBuffer.begin(); 
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); 

    batch.setProjectionMatrix(camera.combined); 
    batch.setShader(null); //use default shader 
    batch.begin(); 
    //draw your game 
    batch.end(); 

    frameBuffer.end(); 

    batch.setShader(upscaleShader); 
    batch.begin(); 
    upscaleShader.setUniformf("rubyTextureSize", frameBuffer.getWidth(), frameBuffer.getHeight());//this is the uniform in your shader. I assume it's wanting the scene size in pixels 
    batch.draw(frameBuffer.getColorBufferTexture(), -1, 1, 2, -2); //full screen quad for no projection matrix, with Y flipped as needed for frame buffer textures 
    batch.end(); 
} 

Es gibt auch einige Änderungen, die Sie benötigen, um Ihre Shader zu machen, damit es mit OpenGL ES funktionieren wird, und weil Spritebatch für spezifisches Attribut und einheitliche Namen verdrahtet:

An der Spitze des Vertex-Shader fügen sie diese Ihre Vertex-Attribute und varyings (die verknüpften Shader muss nicht, weil es auf integrierte Variablen ist verlassen, die in GL eS nicht verfügbar sind) zu definieren:

attribute vec4 a_position; 
attribute vec2 a_texCoord; 
varying vec2 v_texCoord[5]; 

Dann in der Vertex-Shader, Ändern Sie die gl_Position Zeile zu

gl_Position = a_position; //since we can't rely on built-in variables 

und ersetzen alle Vorkommen von gl_TexCoord mit v_texCoord aus dem gleichen Grund.

Im Fragment-Shader müssen Sie, um mit OpenGL ES kompatibel zu sein, die Genauigkeit deklarieren. Sie müssen auch die gleiche Variation, so fügen Sie diese nach oben erklären:

#ifdef GL_ES 
precision mediump float; 
#endif 
varying vec2 v_texCoord[5]; 

Wie bei den Vertex-Shader, ersetzen Sie alle Vorkommen von gl_TexCoord mit v_texCoord. Und ersetzen Sie auch alle Vorkommen von rubyTexture durch u_texture, das ist der Texturname, den SpriteBatch verwendet.

Ich denke, das ist alles. Ich habe das nicht wirklich getestet und ich gehe aus dem Gedächtnis, aber hoffentlich kommt es dir nahe.

+0

Danke für deine Hilfe, ich habe meine Shader wie dieses http: //pastebin.com/88rmNgVf und bekomme keinen Fehler mehr, aber alles, was ich bekomme, ist ein schwarzer Bildschirm, kannst du es testen? – ryanrio95

+0

Angenommen, Sie haben meinen Weg verfolgt, den Quad auf den Bildschirm zu zeichnen, müssen Sie entweder den 'u_projTrans' aus Ihrem Shader entfernen oder die Projektionsmatrix des SpriteBatch auf Identität setzen. Das ist das einzige Problem, das ich zuerst sehe. – Tenfour04

+0

Der Shader funktioniert jetzt, obwohl die Texturen immer noch schattiert sind, außer dass der gesamte Bildschirm schattiert wird, vielleicht liegt das an dem TiledMapRenderer. Der ganze Zweck ist, dass alles, was auf dem Bildschirm gerendert wird, eine Textur sein muss, ich habe es geschafft, und dann braucht diese Textur einen Shader. Ich denke es ist, weil die TiledMap übersprungen wird. – ryanrio95