将 OpenGL HQX 着色器转换为 LibGDX
Convert OpenGL HQX shader to LibGDX
我正在研究 LibGDX 的着色器,并注意到有些属性仅在 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.
提前致谢。
这是一个 post 处理着色器,因此您的流程应该是这样的:
使用 SpriteBatch 的默认着色器以像素完美分辨率将场景绘制到 FBO。
使用放大着色器将 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();
}
您还需要对着色器进行一些更改,以便它可以与 OpenGL ES 一起使用,并且因为 SpriteBatch 是针对特定属性和统一名称连接的:
在你的顶点着色器的顶部,添加它来定义你的顶点属性和变量(你的链接着色器不需要它,因为它依赖于 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
出于同样的原因,将所有出现的 gl_TexCoord
替换为 v_texCoord
。
片段着色器中,为了兼容OpenGL ES,需要声明精度。您还需要声明相同的 varying,因此将其添加到顶部:
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_texCoord[5];
与顶点着色器一样,将所有出现的 gl_TexCoord
替换为 v_texCoord
。并将所有出现的 rubyTexture
替换为 u_texture
,这是 SpriteBatch 使用的纹理名称。
我想这就是一切。我并没有真正测试过这个,我的记忆已经消失了,但希望它能让你接近。
我正在研究 LibGDX 的着色器,并注意到有些属性仅在 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.
提前致谢。
这是一个 post 处理着色器,因此您的流程应该是这样的:
使用 SpriteBatch 的默认着色器以像素完美分辨率将场景绘制到 FBO。
使用放大着色器将 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();
}
您还需要对着色器进行一些更改,以便它可以与 OpenGL ES 一起使用,并且因为 SpriteBatch 是针对特定属性和统一名称连接的:
在你的顶点着色器的顶部,添加它来定义你的顶点属性和变量(你的链接着色器不需要它,因为它依赖于 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
出于同样的原因,将所有出现的 gl_TexCoord
替换为 v_texCoord
。
片段着色器中,为了兼容OpenGL ES,需要声明精度。您还需要声明相同的 varying,因此将其添加到顶部:
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_texCoord[5];
与顶点着色器一样,将所有出现的 gl_TexCoord
替换为 v_texCoord
。并将所有出现的 rubyTexture
替换为 u_texture
,这是 SpriteBatch 使用的纹理名称。
我想这就是一切。我并没有真正测试过这个,我的记忆已经消失了,但希望它能让你接近。