我正在尝试为我的暂停菜单创建背景效果像这样。我当前的想法是在暂停时截取屏幕截图,保存它,打开它,对其进行高斯模糊,然后将其渲染到屏幕上并将菜单渲染在顶部。唯一的问题是我不知道如何有效地保存屏幕截图。
我尝试使用
batch.setColor(0,0,0,0.7f);
在背景上渲染褪色的图像,但它没有给我带来我正在寻找的模糊效果,而只是像我想象的那样提供色调。
非常感谢示例/文档。
编辑:找到此代码
package com.me.mygdxgame;
import java.awt.Point;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.PixelInterleavedSampleModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import com.badlogic.gdx.Application.ApplicationType;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.utils.ScreenUtils;
public class ScreenShot {
private static final int[] RGBA_OFFSETS = { 0, 1, 2, 3 };
private static final int[] RGB_OFFSETS = { 0, 1, 2 };
public static void saveScreenshot(String baseName) throws IOException {
File createTempFile = File.createTempFile(baseName, ".png");
saveScreenshot(createTempFile);
}
public static void saveScreenshot(File file) throws IOException {
saveScreenshot(file, false);
}
public static void saveScreenshot(File file, boolean hasAlpha) throws IOException {
if (Gdx.app.getType() == ApplicationType.Android)
return;
byte[] screenshotPixels = ScreenUtils.getFrameBufferPixels(true);
int width = Gdx.graphics.getWidth();
int height = Gdx.graphics.getHeight();
saveScreenshot(file, screenshotPixels, width, height, hasAlpha);
}
public static void saveScreenshot(File file, byte[] pixels, int width, int height, boolean hasAlpha) throws IOException {
DataBufferByte dataBuffer = new DataBufferByte(pixels, pixels.length);
PixelInterleavedSampleModel sampleModel = new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE, width, height, 4, 4 * width, getOffsets(hasAlpha));
WritableRaster raster = Raster.createWritableRaster(sampleModel, dataBuffer, new Point(0, 0));
BufferedImage img = new BufferedImage(getColorModel(hasAlpha), raster, false, null);
ImageIO.write(img, "png", file);
}
private static ColorModel getColorModel(boolean alpha) {
if (alpha)
return new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[] { 8, 8, 8, 8 }, true, false, ComponentColorModel.TRANSLUCENT, DataBuffer.TYPE_BYTE);
return new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[] { 8, 8, 8 }, false, false, ComponentColorModel.OPAQUE, DataBuffer.TYPE_BYTE);
}
private static int[] getOffsets(boolean alpha) {
if (alpha)
return RGBA_OFFSETS;
return RGB_OFFSETS;
}
}
但是当我尝试
saveScreenshot("output");
时它给了我这个错误(运行桌面版本,如果这有影响的话。还没有在android上测试过)
Exception in thread "LWJGL Application" com.badlogic.gdx.utils.GdxRuntimeException: java.awt.image.RasterFormatException: Incorrect scanline stride: 3200
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:111)
Caused by: java.awt.image.RasterFormatException: Incorrect scanline stride: 3200
错误行:
ImageIO.write(img, "png", file);
我参加聚会迟到了,但这正是您要找的:
https://github.com/mattdesl/lwjgl-basics/wiki/ShaderLesson5
使用着色器渲染到场缓冲区对象以创建模糊,然后将其从帧缓冲区绘制到屏幕上。
我为 libgdx 创建了自己的高斯模糊实现。也许这对某人有用。只需将以下类添加到您的项目中即可:
package com.mygdx.game;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Color;
import java.lang.Math;
class Blur {
private static double matrix [];
private static int radius;
public static void setMatrix(int radius, double sigma) {
Blur.matrix = new double[radius+1];
Blur.radius = radius;
for(int i=0; i<=radius; i++)
matrix[i] = gauss((double)i, sigma);
double sum = 0;
for(int i=-radius; i<=radius; i++)
sum += matrix[Math.abs(i)];
for(int i=0; i<=radius; i++)
matrix[i]/=sum;
}
private static double gauss(double x, double sigma) {
return 1/(sigma*Math.sqrt(2*Math.PI))*Math.exp(-(x*x)/(2*sigma*sigma));
}
public static Pixmap blur(Pixmap pixmap, boolean vertical) {
int width = pixmap.getWidth();
int height = pixmap.getHeight();
Pixmap result = new Pixmap(width,height,Format.RGBA8888);
for(int y=0; y<height; y++)
for(int x=0; x<width; x++){
float r=0,g=0,b=0,a=0;
for(int i=-radius; i<=radius; i++) {
int px=x, py=y;
if(vertical)
py=mirrorTheEdge(py+i,height);
else
px=mirrorTheEdge(px+i,width);
Color color = new Color(pixmap.getPixel(px,py));
float weight = (float)matrix[Math.abs(i)];
r+=color.r*weight;
g+=color.g*weight;
b+=color.b*weight;
a+=color.a*weight;
}
result.setColor(new Color(r,g,b,a));
result.drawPixel(x,y);
}
return result;
}
private static int mirrorTheEdge(int p, int limit) {
if(p<0)
p=p*-1-1;
if(p>=limit)
p=limit*2-p+1;
return p;
}
}
这是一个使用示例:
package com.mygdx.game;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.utils.ScreenUtils;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.files.FileHandle;
public class MyGdxGame extends ApplicationAdapter {
SpriteBatch batch;
Texture img;
@Override
public void create () {
batch = new SpriteBatch();
Pixmap pixmap = new Pixmap(new FileHandle("badlogic.jpg")); // Creating pixmap from file
Blur.setMatrix(15,7.5); // Setting the blur strength
pixmap = Blur.blur(pixmap,false); // Blurring the pixmap horizontally
pixmap = Blur.blur(pixmap,true); // Blurring the pixmap vertically
//pixmap = Blur.blur(Blur.blur(pixmap,false),true); // same in one line
img = new Texture(pixmap);
}
@Override
public void render () {
ScreenUtils.clear(1, 0, 0, 1);
batch.begin();
batch.draw(img, 0, 0);
batch.end();
}
@Override
public void dispose () {
batch.dispose();
img.dispose();
}
}
基本上,任何可以转换为像素图的东西都可以被模糊。要设置模糊强度,请使用 Blur.setMatrix(radius,sigma)。我不太明白,但这两个值越高,图像越模糊。如果您想对此进行优化,请记住半径越小越好。仅此而已。