2016-04-15 44 views
1

我正在使用LibGDX的着色器,并注意到有一些属性仅在LibGDX中使用。将OpenGL HQX着色器转换为LibGDX

https://github.com/libgdx/libgdx/wiki/Shaders的标准顶点和片段着色器工作完美,并得到应用到我的SpriteBatch。

当我尝试使用像https://github.com/SupSuper/OpenXcom/blob/master/bin/common/Shaders/HQ2x.OpenGL.shader这样的HQX着色器时,出现很多错误。

可能因为我需要发送一些LibGDX因变量给着色器,但我找不到应该是哪个。

我想在大屏幕的台式机上使用这些着色器,以便游戏在这些屏幕上保持优美。

我用这个代码加载着色器:

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) { }

着色器登录输出: No errors.

预先感谢。

+0

你最近怎么画?你构建了一个Mesh还是使用SpriteBatch?我假设你正在使用FrameBuffer的纹理? – Tenfour04

+0

我使用'batch.setShader(shaderProgram);'在我的render()方法中让着色器应用于SpriteBatch,然后绘制我的所有纹理 – ryanrio95

回答

0

这是一个后期处理着色器,让你流应该是这样的:

  1. 使用SpriteBatch的默认渲染在像素分辨率的完美画出场景的FBO。

  2. 使用向上缩放着色器将FBO的纹理绘制到屏幕的帧缓冲区。如果修改着色器以匹配SpriteBatch使用的属性和制服,则可以使用SpriteBatch执行此操作。 (你可以在交替产生与着色器预计属性名称的简单的网格,但SpriteBatch可能是最简单的。)

首先,我们不使用典型的着色器SpriteBatch,所以你需要调用ShaderProgram.pedantic = false;在加载任何东西前的某个地方

现在你需要一个合适大小的FrameBuffer。它的大小应该使你的精灵像素完美(纹理的一个像素可以缩放到世界的一个像素)。像这样:

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(); 
} 

然后,你可以画到帧缓冲区,就好像它是你的屏幕。之后,您将画框缓冲区的纹理绘制到屏幕上。

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(); 
} 

还有你需要对你的shader所以它会用OpenGL ES工作的一些变化,因为SpriteBatch是有线特定属性和统一的名称:

你的顶点着色器的顶部,添加此定义你的顶点属性和varyings(其中已连结的着色器并不需要,因为它依靠内置不可用在GL ES变量):

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

然后在顶点着色器,将gl_Position行更改为

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

v_texCoord出于同样的原因更换的gl_TexCoord所有出现。

在片段着色器中,为了与OpenGL ES兼容,您需要声明精度。您还需要声明相同的变化,所以这增加了顶部:

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

与顶点着色器,具有v_texCoord取代的gl_TexCoord所有出现。并且还将所有出现的rubyTexture替换为u_texture,这是SpriteBatch使用的纹理名称。

我认为这就是一切。我实际上并没有测试这个,而我正在脱离记忆,但希望它能让你接近。

+0

感谢您的帮助,我获得了像这样的着色器http: //pastebin.com/88rmNgVf并且不再有任何错误,但是我得到的只是一个黑屏,你能测试它吗? – ryanrio95

+0

假设您按照我的方式将四边形绘制到屏幕上,您需要从着色器中移除“u_projTrans”,或者将SpriteBatch的投影矩阵设置为标识。这是我最初看到的唯一问题。 – Tenfour04

+0

着色器现在正在工作,但除了整个屏幕变得阴影之外,纹理仍然彼此分开,也许这是由于TiledMapRenderer。整个目的是在屏幕上呈现的所有东西都需要一个纹理,我设法做到这一点,而且纹理需要着色器。我认为这是因为TiledMap会被跳过。 – ryanrio95