All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.badlogic.gdx.graphics.g3d.decals.CameraGroupStrategy Maven / Gradle / Ivy

There is a newer version: 1.12.1
Show newest version
/*******************************************************************************
 * Copyright 2011 See AUTHORS file.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/

package com.badlogic.gdx.graphics.g3d.decals;

import java.util.Comparator;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Disposable;
import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.Pool;

/**
 * 

* Minimalistic grouping strategy that splits decals into opaque and transparent ones enabling and disabling blending as needed. * Opaque decals are rendered first (decal color is ignored in opacity check).
* Use this strategy only if the vast majority of your decals are opaque and the few transparent ones are unlikely to overlap. *

*

* Can produce invisible artifacts when transparent decals overlap each other. *

*

* Needs to be explicitly disposed as it might allocate a ShaderProgram when GLSL 2.0 is used. *

*

* States (* = any, EV = entry value - same as value before flush):
*

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
expectsexits on
glDepthMasktrueEV
GL_DEPTH_TESTenabledEV
glDepthFuncGL_LESS | GL_LEQUALEV
GL_BLENDdisabledEV | disabled
glBlendFunc**
GL_TEXTURE_2D*disabled
*

*/ public class CameraGroupStrategy implements GroupStrategy, Disposable { private static final int GROUP_OPAQUE = 0; private static final int GROUP_BLEND = 1; Pool> arrayPool = new Pool>(16) { @Override protected Array newObject () { return new Array(); } }; Array> usedArrays = new Array>(); ObjectMap> materialGroups = new ObjectMap>(); Camera camera; ShaderProgram shader; private final Comparator cameraSorter; public CameraGroupStrategy (Camera camera) { this.camera = camera; this.cameraSorter = new Comparator() { @Override public int compare (Decal o1, Decal o2) { float dist1 = CameraGroupStrategy.this.camera.position.dst(o1.position); float dist2 = CameraGroupStrategy.this.camera.position.dst(o2.position); return (int)Math.signum(dist2 - dist1); } }; createDefaultShader(); } public CameraGroupStrategy (Camera camera, Comparator sorter) { this.camera = camera; this.cameraSorter = sorter; createDefaultShader(); } public void setCamera (Camera camera) { this.camera = camera; } public Camera getCamera () { return camera; } @Override public int decideGroup (Decal decal) { return decal.getMaterial().isOpaque() ? GROUP_OPAQUE : GROUP_BLEND; } @Override public void beforeGroup (int group, Array contents) { if (group == GROUP_BLEND) { Gdx.gl.glEnable(GL20.GL_BLEND); contents.sort(cameraSorter); } else { for (int i = 0, n = contents.size; i < n; i++) { Decal decal = contents.get(i); Array materialGroup = materialGroups.get(decal.material); if (materialGroup == null) { materialGroup = arrayPool.obtain(); materialGroup.clear(); usedArrays.add(materialGroup); materialGroups.put(decal.material, materialGroup); } materialGroup.add(decal); } contents.clear(); for (Array materialGroup : materialGroups.values()) { contents.addAll(materialGroup); } materialGroups.clear(); arrayPool.freeAll(usedArrays); usedArrays.clear(); } } @Override public void afterGroup (int group) { if (group == GROUP_BLEND) { Gdx.gl.glDisable(GL20.GL_BLEND); } } @Override public void beforeGroups () { Gdx.gl.glEnable(GL20.GL_DEPTH_TEST); shader.bind(); shader.setUniformMatrix("u_projectionViewMatrix", camera.combined); shader.setUniformi("u_texture", 0); } @Override public void afterGroups () { Gdx.gl.glDisable(GL20.GL_DEPTH_TEST); } private void createDefaultShader () { String vertexShader = "attribute vec4 " + ShaderProgram.POSITION_ATTRIBUTE + ";\n" // + "attribute vec4 " + ShaderProgram.COLOR_ATTRIBUTE + ";\n" // + "attribute vec2 " + ShaderProgram.TEXCOORD_ATTRIBUTE + "0;\n" // + "uniform mat4 u_projectionViewMatrix;\n" // + "varying vec4 v_color;\n" // + "varying vec2 v_texCoords;\n" // + "\n" // + "void main()\n" // + "{\n" // + " v_color = " + ShaderProgram.COLOR_ATTRIBUTE + ";\n" // + " v_color.a = v_color.a * (255.0/254.0);\n" // + " v_texCoords = " + ShaderProgram.TEXCOORD_ATTRIBUTE + "0;\n" // + " gl_Position = u_projectionViewMatrix * " + ShaderProgram.POSITION_ATTRIBUTE + ";\n" // + "}\n"; String fragmentShader = "#ifdef GL_ES\n" // + "precision mediump float;\n" // + "#endif\n" // + "varying vec4 v_color;\n" // + "varying vec2 v_texCoords;\n" // + "uniform sampler2D u_texture;\n" // + "void main()\n"// + "{\n" // + " gl_FragColor = v_color * texture2D(u_texture, v_texCoords);\n" // + "}"; shader = new ShaderProgram(vertexShader, fragmentShader); if (!shader.isCompiled()) throw new IllegalArgumentException("couldn't compile shader: " + shader.getLog()); } @Override public ShaderProgram getGroupShader (int group) { return shader; } @Override public void dispose () { if (shader != null) shader.dispose(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy