Package com.badlogic.gdx.graphics.g3d.decals

Source Code of com.badlogic.gdx.graphics.g3d.decals.CameraGroupStrategy

/*******************************************************************************
* 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.GL10;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.Pool;

/** <p>
* 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).<br/>
* Use this strategy only if the vast majority of your decals are opaque and the few transparent ones are unlikely to overlap.
* </p>
* <p>
* Can produce invisible artifacts when transparent decals overlap each other.
* </p>
* <p>
* States (* = any, EV = entry value - same as value before flush):<br/>
* <table>
* <tr>
* <td></td>
* <td>expects</td>
* <td>exits on</td>
* </tr>
* <tr>
* <td>glDepthMask</td>
* <td>true</td>
* <td>EV</td>
* </tr>
* <tr>
* <td>GL_DEPTH_TEST</td>
* <td>enabled</td>
* <td>EV</td>
* </tr>
* <tr>
* <td>glDepthFunc</td>
* <td>GL_LESS | GL_LEQUAL</td>
* <td>EV</td>
* </tr>
* <tr>
* <td>GL_BLEND</td>
* <td>disabled</td>
* <td>EV | disabled</td>
* </tr>
* <tr>
* <td>glBlendFunc</td>
* <td>*</td>
* <td>*</td>
* </tr>
* <tr>
* <td>GL_TEXTURE_2D</td>
* <td>*</td>
* <td>disabled</td>
* </tr>
* </table>
* </p> */
public class CameraGroupStrategy implements GroupStrategy {
  private static final int GROUP_OPAQUE = 0;
  private static final int GROUP_BLEND = 1;

  Pool<Array<Decal>> arrayPool = new Pool<Array<Decal>>(16) {
    @Override
    protected Array<Decal> newObject () {
      return new Array<Decal>();
    }
  };
  Array<Array<Decal>> usedArrays = new Array<Array<Decal>>();
  ObjectMap<DecalMaterial, Array<Decal>> materialGroups = new ObjectMap<DecalMaterial, Array<Decal>>();

  Camera camera;
  ShaderProgram shader;
  private final Comparator<Decal> cameraSorter = new Comparator<Decal>() {
    @Override
    public int compare (Decal o1, Decal o2) {
      float dist1 = camera.position.dst2(o1.position);
      float dist2 = camera.position.dst2(o2.position);
      return (int)Math.signum(dist2 - dist1);
    }
  };

  public CameraGroupStrategy (Camera camera) {
    this.camera = camera;
    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<Decal> contents) {
    if (group == GROUP_BLEND) {
      Gdx.gl.glEnable(GL10.GL_BLEND);
      contents.sort(cameraSorter);
    } else {
      for (int i = 0, n = contents.size; i < n; i++) {
        Decal decal = contents.get(i);
        Array<Decal> 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<Decal> materialGroup : materialGroups.values()) {
        contents.addAll(materialGroup);
      }

      materialGroups.clear();
      arrayPool.free(usedArrays);
      usedArrays.clear();
    }
  }

  @Override
  public void afterGroup (int group) {
    if (group == GROUP_BLEND) {
      Gdx.gl.glDisable(GL10.GL_BLEND);
    }
  }

  @Override
  public void beforeGroups () {
    Gdx.gl.glEnable(GL10.GL_DEPTH_TEST);
    if (shader != null) {
      shader.begin();
      shader.setUniformMatrix("u_projectionViewMatrix", camera.combined);
      shader.setUniformi("u_texture", 0);
    } else {
      Gdx.gl.glEnable(GL10.GL_TEXTURE_2D);
      Gdx.gl10.glMatrixMode(GL10.GL_PROJECTION);
      Gdx.gl10.glLoadMatrixf(camera.projection.val, 0);
      Gdx.gl10.glMatrixMode(GL10.GL_MODELVIEW);
      Gdx.gl10.glLoadMatrixf(camera.view.val, 0);
    }
  }

  @Override
  public void afterGroups () {
    if (shader != null) {
      shader.end();
    }
    Gdx.gl.glDisable(GL10.GL_TEXTURE_2D);
    Gdx.gl.glDisable(GL10.GL_DEPTH_TEST);
  }

  private void createDefaultShader () {
    if (Gdx.graphics.isGL20Available()) {
      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_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() == false) throw new IllegalArgumentException("couldn't compile shader: " + shader.getLog());
    }
  }

  @Override
  public ShaderProgram getGroupShader (int group) {
    return shader;
  }
}
TOP

Related Classes of com.badlogic.gdx.graphics.g3d.decals.CameraGroupStrategy

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.