将OpenGL HQX着色器转换为LibGDX
我正在研究LibGDX的着色器,注意到有些属性只在LibGDX中使用 标准的顶点和片段着色器可以完美地工作,并应用到我的SpriteBatch中 当我尝试使用HQX着色器时,我会遇到很多错误 可能是因为我需要向着色器发送一些LibGDX相关变量,但我无法确定应该发送哪个 我想在有大屏幕的桌面上使用这些着色器,这样游戏在这些屏幕上看起来就一直很棒 我使用以下代码加载着色器:将OpenGL HQX着色器转换为LibGDX,libgdx,glsl,shader,Libgdx,Glsl,Shader,我正在研究LibGDX的着色器,注意到有些属性只在LibGDX中使用 标准的顶点和片段着色器可以完美地工作,并应用到我的SpriteBatch中 当我尝试使用HQX着色器时,我会遇到很多错误 可能是因为我需要向着色器发送一些LibGDX相关变量,但我无法确定应该发送哪个 我想在有大屏幕的桌面上使用这些着色器,这样游戏在这些屏幕上看起来就一直很棒 我使用以下代码加载着色器: 试试看{ shaderProgram=new shaderProgram(Gdx.files.internal(“verte
试试看{
shaderProgram=new shaderProgram(Gdx.files.internal(“vertex.glsl”).readString(),Gdx.files.internal(“fragment.glsl”).readString());
shaderProgram.pedantic=false;
System.out.println(“着色器日志:”);
System.out.println(shaderProgram.getLog());
}捕获(例外情况除外){}
着色器日志输出:
无错误。
提前感谢。这是一个后期处理着色器,因此您的流程应该如下所示:
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();
}
ShaderProgram.pedantic=false代码>加载任何内容之前的某个位置
现在需要一个大小合适的帧缓冲区。它的大小应该适合你的精灵像素完美(一个像素的纹理缩放到一个像素的世界)。大概是这样的:
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中不可用的内置变量):
然后在顶点着色器中,将gl\u位置
行更改为
gl_Position = a_position; //since we can't rely on built-in variables
出于同样的原因,将所有出现的gl_TexCoord
替换为v_TexCoord
在片段着色器中,要与OpenGL ES兼容,需要声明精度。您还需要声明相同的变量,因此将其添加到顶部:
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_texCoord[5];
与顶点着色器一样,将所有出现的gl_TexCoord
替换为v_TexCoord
。并将所有出现的rubyTexture
替换为u_纹理
,这是SpriteBatch使用的纹理名称
我想这就是一切。实际上我没有测试这个,我的内存已经用完了,但希望它能让你接近它。这是一个后处理着色器,所以你的流程应该是这样的:
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();
}
使用SpriteBatch的默认着色器以像素完美分辨率将场景绘制到FBO
使用放大着色器将FBO的纹理绘制到屏幕的帧缓冲区。如果修改着色器以匹配SpriteBatch使用的属性和制服,则可以使用SpriteBatch执行此操作。(也可以使用着色器期望的属性名称创建简单网格,但SpriteBatch可能是最简单的。)
首先,我们没有使用SpriteBatch的典型着色器,因此需要调用ShaderProgram.pedantic=false代码>加载任何内容之前的某个位置
现在需要一个大小合适的帧缓冲区。它的大小应该适合你的精灵像素完美(一个像素的纹理缩放到一个像素的世界)。大概是这样的:
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中不可用的内置变量):
然后在顶点着色器中,将gl\u位置
行更改为
gl_Position = a_position; //since we can't rely on built-in variables
出于同样的原因,将所有出现的gl_TexCoord
替换为v_TexCoord
在片段着色器中,要与OpenGL ES兼容,需要声明精度。您还需要声明相同的变量,因此将其添加到顶部:
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_texCoord[5];
与顶点着色器一样,将所有出现的gl_TexCoord
替换为v_TexCoord
。并将所有出现的rubyTexture
替换为u_纹理
,这是SpriteBatch使用的纹理名称
我想这就是一切。我并没有实际测试这个,我的记忆也快用完了,但希望它能让你接近它。你用它画得怎么样?您是在构建网格还是在使用SpriteBatch?我假设您使用的是帧缓冲区中的纹理?我使用的是batch.setShader(shaderProgram)代码>在我的render()方法中,使着色器应用于SpriteBatch,然后我绘制所有的纹理。您如何使用它进行绘制?您是在构建网格还是在使用SpriteBatch?我假设您使用的是帧缓冲区中的纹理?我使用的是batch.setShader(shaderProgram)代码>在我的render()方法中,使着色器应用于SpriteBatch,然后我绘制所有纹理谢谢你的帮助,我得到了这样的着色器,不再出现错误,但我得到的只是一个黑屏,你能测试它吗?假设