Created
February 24, 2021 21:55
-
-
Save WinterAlexander/4e9984bef3c5b54888b6c23be27a03a9 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package net.jumpai.world.objects.background; | |
| import com.badlogic.gdx.Gdx; | |
| import com.badlogic.gdx.graphics.GL20; | |
| import com.badlogic.gdx.graphics.OrthographicCamera; | |
| import com.badlogic.gdx.graphics.Pixmap.Format; | |
| import com.badlogic.gdx.graphics.Texture; | |
| import com.badlogic.gdx.graphics.g2d.TextureRegion; | |
| import com.badlogic.gdx.graphics.glutils.FrameBuffer; | |
| import com.badlogic.gdx.graphics.glutils.ShaderProgram; | |
| import com.badlogic.gdx.math.Vector2; | |
| import com.badlogic.gdx.utils.Array; | |
| import com.badlogic.gdx.utils.ObjectMap; | |
| import net.jumpai.render.JumpaiAssets; | |
| import net.jumpai.render.RenderScreen; | |
| import net.jumpai.render.assetprovider.texture.background.BackgroundProvider; | |
| import net.jumpai.world.World; | |
| import net.jumpai.world.biome.BiomeMaskGenerator; | |
| import net.jumpai.world.biome.BiomeType; | |
| import net.jumpai.world.camera.WorldCamera; | |
| import net.jumpai.world.component.render.InitRenderer; | |
| import net.jumpai.world.component.render.RenderPriority; | |
| import net.jumpai.world.component.render.WorldRenderPriority; | |
| import static com.badlogic.gdx.graphics.GL20.GL_ONE; | |
| import static com.badlogic.gdx.graphics.GL20.GL_ONE_MINUS_SRC_ALPHA; | |
| import static com.badlogic.gdx.graphics.GL20.GL_SRC_ALPHA; | |
| import static com.badlogic.gdx.graphics.GL20.GL_TEXTURE0; | |
| import static net.jumpai.util.Validation.ensureNotNull; | |
| import static net.jumpai.util.math.MathUtil.negMod; | |
| import static net.jumpai.world.JumpaiWorld.WORLD_WIDTH; | |
| /** | |
| * Renderer for background in world | |
| * <p> | |
| * Created on 2018-03-25. | |
| * | |
| * @author Alexander Winter | |
| */ | |
| public class BackgroundRenderer extends InitRenderer | |
| { | |
| private static final int BG_WIDTH = 4416; | |
| private static final int BG_HEIGHT = 2484; | |
| private static final int BIOME_MASK_UNIT = 5; | |
| protected final World world; | |
| private BackgroundType backgroundType; | |
| private final ObjectMap<BiomeType, Texture> backgrounds = new ObjectMap<>(); | |
| private final ObjectMap<BiomeType, TextureRegion> staticBackgrounds = new ObjectMap<>(); | |
| private final ObjectMap<BiomeType, Array<TextureRegion>> layers = new ObjectMap<>(); | |
| private final ObjectMap<BiomeType, FrameBuffer> fbos = new ObjectMap<>(); | |
| private boolean changedBackground; | |
| private ShaderProgram shader; | |
| private Texture white; | |
| private final Vector2 tmpSize = new Vector2(); | |
| private int lastWidth = -1; | |
| private OrthographicCamera cam; | |
| public BackgroundRenderer(World world, BackgroundType type) | |
| { | |
| ensureNotNull(world, "world"); | |
| ensureNotNull(type, "type"); | |
| this.world = world; | |
| this.backgroundType = type; | |
| changedBackground = true; | |
| } | |
| @Override | |
| protected void init(RenderScreen screen) | |
| { | |
| shader = JumpaiAssets.BACKGROUND_BIOME_SHADER.resolve(screen.getAssets()); | |
| white = JumpaiAssets.WHITE_PIXEL.resolve(screen.getAssets()); | |
| } | |
| @Override | |
| public void prepare(RenderScreen screen) | |
| { | |
| super.prepare(screen); | |
| boolean firstTime = changedBackground; | |
| if(changedBackground) | |
| { | |
| for(BiomeType biome : BiomeType.values()) | |
| staticBackgrounds.put(biome, JumpaiAssets.MOUNTAINS_BACKGROUND | |
| .get(biome) | |
| .getStaticLayer() | |
| .resolve(screen.getAssets())); | |
| for(BiomeType biome : BiomeType.values()) | |
| { | |
| BackgroundLayerDisposition disposition = backgroundType.getDisposition(biome); | |
| BackgroundProvider provider = disposition.getBackgroundProvider(); | |
| Array<TextureRegion> layerArr = new Array<>(disposition.getAssetCount()); | |
| if(disposition.hasForeground()) | |
| layerArr.add(provider.getForeground().resolve(screen.getAssets())); | |
| for(int i = 0; i < disposition.getMidLayerCount(); i++) | |
| layerArr.add(provider.getMidLayers()[i].resolve(screen.getAssets())); | |
| layerArr.add(provider.getBackground().resolve(screen.getAssets())); | |
| if(disposition.hasClouds()) | |
| layerArr.add(provider.getClouds().resolve(screen.getAssets())); | |
| layers.put(biome, layerArr); | |
| } | |
| changedBackground = false; | |
| } | |
| if(screen.useParallax() && firstTime) | |
| { | |
| if(fbos.size == 0 || lastWidth != (int)screen.getScreenSize().x) | |
| { | |
| lastWidth = (int)screen.getScreenSize().x; | |
| for(FrameBuffer fbo : fbos.values()) | |
| fbo.dispose(); | |
| fbos.clear(); | |
| for(BiomeType biomeType : BiomeType.values()) | |
| fbos.put(biomeType, new FrameBuffer(Format.RGBA8888, (int)screen.getScreenSize().x, (int)screen.getScreenSize().y, false)); | |
| } | |
| if(cam == null) | |
| { | |
| cam = new OrthographicCamera(); | |
| cam.setToOrtho(true, BG_WIDTH, BG_HEIGHT); | |
| cam.position.set(BG_WIDTH, BG_HEIGHT, 0f).scl(0.5f); | |
| cam.update(); | |
| } | |
| screen.getBatch().setProjectionMatrix(cam.combined); | |
| for(BiomeType biome : BiomeType.values()) | |
| { | |
| FrameBuffer fbo = fbos.get(biome); | |
| BackgroundLayerDisposition dispo = backgroundType.getDisposition(biome); | |
| Array<TextureRegion> layerArr = layers.get(biome); | |
| float scale = (float)BG_WIDTH / staticBackgrounds.get(biome).getRegionWidth(); | |
| fbo.begin(); | |
| Gdx.gl.glClearColor(0f, 0f, 0f, 0f); | |
| Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); | |
| screen.getBatch().begin(); | |
| screen.getBatch().enableBlending(); | |
| screen.getBatch().setBlendFunctionSeparate(GL_SRC_ALPHA, | |
| GL_ONE_MINUS_SRC_ALPHA, | |
| GL_ONE, | |
| GL_ONE_MINUS_SRC_ALPHA); | |
| screen.getBatch().draw(white, | |
| 0f, | |
| 0f, | |
| BG_WIDTH, | |
| BG_HEIGHT); | |
| screen.getBatch().flush(); | |
| screen.getBatch().draw(white, | |
| 0f, | |
| 0f, | |
| BG_WIDTH, | |
| BG_HEIGHT); | |
| if(dispo.hasClouds()) | |
| { | |
| int position = (int)(world.getFrameId() % BG_WIDTH); | |
| TextureRegion clouds = layerArr.get(dispo.getCloudsIndex()); | |
| screen.getBatch().draw(clouds, position, BG_HEIGHT - clouds.getRegionHeight() * scale, BG_WIDTH, clouds.getRegionHeight() * scale); | |
| screen.getBatch().draw(clouds, position - BG_WIDTH, BG_HEIGHT - clouds.getRegionHeight() * scale, BG_WIDTH, clouds.getRegionHeight() * scale); | |
| } | |
| TextureRegion bgRegion = layerArr.get(dispo.getBackgroundIndex()); | |
| screen.getBatch().draw(bgRegion, | |
| 0f, | |
| BG_HEIGHT - bgRegion.getRegionHeight() * scale, | |
| BG_WIDTH, | |
| bgRegion.getRegionHeight() * scale); | |
| int dragIndex = dispo.hasForeground() ? 1 : 0; | |
| float pos = -world.getCamera().getActualPosition().x / WORLD_WIDTH; | |
| for(int midLayer = dispo.getMidLayerCount() - 1; midLayer >= 0; midLayer--) | |
| { | |
| float layerPos = pos * dispo.getLayerDrag(dragIndex + midLayer); | |
| int position = (int)(negMod(layerPos, 1f) * BG_WIDTH); | |
| boolean flip = negMod(layerPos, 2f) < 1f; | |
| TextureRegion region = layerArr.get(dispo.getMidStartIndex() + midLayer); | |
| screen.getBatch().draw(region, | |
| position, 0, | |
| BG_WIDTH / 2, BG_HEIGHT / 2, | |
| BG_WIDTH, region.getRegionHeight() * scale, | |
| flip ? -1f : 1f, 1f, | |
| 0f); | |
| screen.getBatch().draw(layerArr.get(dispo.getMidStartIndex() + midLayer), | |
| position - BG_WIDTH, 0, | |
| BG_WIDTH / 2, BG_HEIGHT / 2, | |
| BG_WIDTH, region.getRegionHeight() * scale, | |
| flip ? 1f : -1f, 1f, | |
| 0f); | |
| } | |
| if(dispo.hasForeground()) | |
| { | |
| float layerPos = pos * dispo.getLayerDrag(0); | |
| int position = (int)(negMod(layerPos, 1f) * BG_WIDTH); | |
| boolean flip = negMod(layerPos, 2f) < 1f; | |
| TextureRegion region = layerArr.get(dispo.getForegroundIndex()); | |
| screen.getBatch().draw(region, | |
| position, 0, | |
| BG_WIDTH / 2, BG_HEIGHT / 2, | |
| BG_WIDTH, region.getRegionHeight() * scale, | |
| flip ? -1f : 1f, 1f, | |
| 0f); | |
| screen.getBatch().draw(layerArr.get(dispo.getForegroundIndex()), | |
| position - BG_WIDTH, 0, | |
| BG_WIDTH / 2, BG_HEIGHT / 2, | |
| BG_WIDTH, region.getRegionHeight() * scale, | |
| flip ? 1f : -1f, 1f, | |
| 0f); | |
| } | |
| screen.getBatch().end(); | |
| fbo.end(); | |
| screen.getBatch().setBlendFunction(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
| backgrounds.put(biome, fbo.getColorBufferTexture()); | |
| } | |
| } | |
| } | |
| @Override | |
| public void render(RenderScreen screen) | |
| { | |
| WorldCamera cam = world.getCamera(); | |
| BiomeMaskGenerator gen = world.getBiomeMaskGenerator(); | |
| screen.getBatch().setShader(shader); | |
| shader.setUniformi("u_biomeMask", BIOME_MASK_UNIT); | |
| shader.setUniformf("u_offset", gen.getMaskOffset()); | |
| shader.setUniformf("u_scale", gen.getMaskScale()); | |
| int dst = screen.getBatch().getBlendDstFunc(); | |
| int src = screen.getBatch().getBlendSrcFunc(); | |
| screen.getBatch().setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE); | |
| for(BiomeType biome : BiomeType.values()) | |
| { | |
| gen.getMask(biome).bind(BIOME_MASK_UNIT); | |
| Gdx.gl.glActiveTexture(GL_TEXTURE0); | |
| Vector2 pos = cam.getLogicalPosition(); | |
| tmpSize.set(cam.getViewSize()).scl(cam.getLogicalZoom()); | |
| if(screen.useParallax()) | |
| screen.getBatch().draw(backgrounds.get(biome), | |
| pos.x - tmpSize.x / 2, | |
| pos.y - tmpSize.y / 2, | |
| tmpSize.x, | |
| tmpSize.y); | |
| else | |
| screen.getBatch().draw(staticBackgrounds.get(biome), | |
| pos.x - tmpSize.x / 2, | |
| pos.y - tmpSize.y / 2, | |
| tmpSize.x, | |
| tmpSize.y); | |
| screen.getBatch().flush(); | |
| } | |
| screen.getBatch().setShader(null); | |
| screen.getBatch().setBlendFunction(src, dst); | |
| } | |
| @Override | |
| public RenderPriority getRenderPriority() | |
| { | |
| return WorldRenderPriority.BACKGROUND; | |
| } | |
| public BackgroundType getBackgroundType() | |
| { | |
| return backgroundType; | |
| } | |
| public void setBackgroundType(BackgroundType backgroundType) | |
| { | |
| if(this.backgroundType == backgroundType) | |
| return; | |
| this.backgroundType = backgroundType; | |
| changedBackground = true; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment