视差背景平铺不完美 [英] Parallax background tiled imperfectly
问题描述
我的视差背景图像有些问题.我在下面嵌入了一个GIF,以显示问题所在:(1)纹理边缘有一条黑色的闪烁线;(2)运动不流畅(这不是由于GIF的帧频太小).我还为ScrollableImage
类添加了短代码,这是实现视差的核心.我怀疑问题可能是由于setScrollOffset
方法内部的模运算造成的,但是不是那样的,现在我没有主意了.我应该如何解决这个问题?
I have some problems with my parallax background images. I embedded a GIF below that shows the problems: (1) there's a black flickering line at the edge of the texture and (2) the movement is not smooth (and this isn't due to the GIF's small frame rate). I also added the short code for my ScrollableImage
class, which is at the heart of how I implemented parallax. I suspected the problem might be due to the modulo operation inside the setScrollOffset
method, but that wasn't it and now I'm out of ideas. What should I try to fix this problem?
public class ScrollableImage extends Widget {
private TextureRegion region;
private float scrollOffset = 0.0f;
public ScrollableImage(TextureRegion region) {
this.region = region;
}
@Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
float w = region.getRegionWidth();
float h = region.getRegionHeight();
float scale = getHeight() / h;
float scaledWidth = w * scale;
float scaledHeight = h * scale;
float scaledOffset = scrollOffset * scale;
Color color = getColor();
batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
for (float x = getX() - scaledOffset; x < getX() + getWidth(); x += scaledWidth) {
batch.draw(region, x, getY(), scaledWidth, scaledHeight);
}
}
public float getScrollOffset() {
return scrollOffset;
}
public void setScrollOffset(float value) {
scrollOffset = Math.max(0, value % (float)region.getRegionWidth());
}
}
推荐答案
我设法解决了该问题.万一将来有人遇到类似的问题,这就是我所做的.有了以前给我带来问题的解决方案,我从软件中平铺了背景(我有一个for循环,该循环多次绘制纹理);我现在所做的,最有效的是使用OpenGL的GL_REPEAT
,它将使用硬件(GPU)来重复纹理.这是我的代码:
I managed to fix the problem. In case someone runs into similar problems in the future, here's what I did. With the solution that gave me problems before, I was tiling the background from software (I had a for loop the was drawing the texture multiple times); what I did now and which works great is the use OpenGL's GL_REPEAT
, which will use the hardware (the GPU) to repeat the texture. Here's my code:
public class ParallaxWidget extends Widget implements Disposable {
private static final int LAYER_COUNT = 2;
private Texture[] textures = new Texture[LAYER_COUNT];
private float[] scrollFactors = new float[LAYER_COUNT];
private float[] scrollAmounts = new float[LAYER_COUNT];
public ParallaxWidget(String path0, float factor0, String path1, float factor1) {
scrollFactors[0] = factor0;
scrollFactors[1] = factor1;
scrollAmounts[0] = 0.0f;
scrollAmounts[1] = 0.0f;
textures[0] = new Texture(Gdx.files.internal(path0));
textures[1] = new Texture(Gdx.files.internal(path1));
textures[0].setWrap(TextureWrap.Repeat, TextureWrap.ClampToEdge);
textures[1].setWrap(TextureWrap.Repeat, TextureWrap.ClampToEdge);
}
@Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
Color color = getColor();
batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
for (int i = 0; i < LAYER_COUNT; ++i) {
drawLayer(batch, i);
}
}
@Override
public void dispose() {
for (Texture texture : textures) {
texture.dispose();
}
}
public void updateScroll(float value) {
for (int i = 0; i < LAYER_COUNT; ++i) {
scrollAmounts[i] = value * scrollFactors[i];
}
}
private void drawLayer(Batch batch, int index) {
float x = getX();
float y = getY();
float w = getWidth();
float h = getHeight();
float th = textures[index].getHeight();
float tw = textures[index].getWidth() * h / th;
float u = scrollAmounts[index] / tw;
float v = 1.0f;
float u2 = u + (w / tw);
float v2 = 0.0f;
batch.draw(textures[index], x, y, w, h, u, v, u2, v2);
}
}
这篇关于视差背景平铺不完美的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!