/**
* Copyright 2012 Jason Sorensen (sorensenj@smert.net)
*
* 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 net.smert.frameworkgl.opengl.renderable.shared;
import java.util.Iterator;
import java.util.Map;
import net.smert.frameworkgl.opengl.GL;
import net.smert.frameworkgl.opengl.Texture;
import net.smert.frameworkgl.opengl.TextureType;
import net.smert.frameworkgl.opengl.constants.TextureTargets;
import net.smert.frameworkgl.opengl.constants.TextureUnit;
import net.smert.frameworkgl.opengl.mesh.Segment;
import net.smert.frameworkgl.opengl.mesh.SegmentMaterial;
import net.smert.frameworkgl.opengl.renderable.Renderable;
import net.smert.frameworkgl.utils.HashMapIntInt;
/**
*
* @author Jason Sorensen <sorensenj@smert.net>
*/
public class TextureBindState {
private int activeTextureUnit;
private int maxModelTextureUnits;
private int maxModelTextureUnitsWithTextureFlag;
private int maxShaderTextureUnits;
private int maxTextureUnits;
private final HashMapIntInt textureUnitToTextureID;
public TextureBindState() {
maxModelTextureUnits = 8;
maxModelTextureUnitsWithTextureFlag = 4; // Must be less than maxModelTextureUnits
maxShaderTextureUnits = 8;
maxTextureUnits = 16;
textureUnitToTextureID = new HashMapIntInt();
reset();
}
private void setActiveTexture(int textureUnit) {
if (activeTextureUnit == textureUnit) {
return;
}
activeTextureUnit = textureUnit;
GL.textureHelper.activeTexture(textureUnit);
}
private void setBindTexture(Texture texture) {
int textureID = texture.getTextureID();
int activeTextureID = textureUnitToTextureID.get(activeTextureUnit);
if (activeTextureID == textureID) {
return;
}
boolean flagChanged = false;
textureUnitToTextureID.put(activeTextureUnit, textureID);
if ((activeTextureUnit >= TextureUnit.TEXTURE0)
&& (activeTextureUnit < (TextureUnit.TEXTURE0 + maxModelTextureUnitsWithTextureFlag))) {
flagChanged = true;
}
int textureTarget = texture.getTextureTarget();
switch (textureTarget) {
case TextureTargets.TEXTURE_2D:
GL.textureHelper.setTextureTarget2D();
break;
case TextureTargets.TEXTURE_3D:
GL.textureHelper.setTextureTarget3D();
break;
case TextureTargets.TEXTURE_CUBE_MAP:
GL.textureHelper.setTextureTargetCubeMap();
break;
}
GL.textureHelper.bind(textureID);
if (flagChanged) {
if (textureID != 0) {
Renderable.shaderBindState.sendUniformTextureFlag(1f);
} else {
Renderable.shaderBindState.sendUniformTextureFlag(0f);
}
}
}
public void bindTexture(int textureUnit, Texture texture) {
setActiveTexture(textureUnit);
if (texture == null) {
unbindCurrent();
return;
}
setBindTexture(texture);
}
public void bindTexture(TextureType textureType, String textureFilename) {
int textureUnit = Renderable.shaderBindState.getTextureUnit(textureType);
int uniqueTextureID = Renderable.texturePool.getUniqueID(textureFilename);
Texture texture = Renderable.texturePool.get(uniqueTextureID);
bindTexture(textureUnit, texture);
}
public void bindTexture0(Texture texture) {
bindTexture(TextureUnit.TEXTURE0, texture);
}
public void bindTexture1(Texture texture) {
bindTexture(TextureUnit.TEXTURE1, texture);
}
public void bindTexture2(Texture texture) {
bindTexture(TextureUnit.TEXTURE2, texture);
}
public void bindTexture3(Texture texture) {
bindTexture(TextureUnit.TEXTURE3, texture);
}
public void bindTexture4(Texture texture) {
bindTexture(TextureUnit.TEXTURE4, texture);
}
public void bindTexture5(Texture texture) {
bindTexture(TextureUnit.TEXTURE5, texture);
}
public void bindTexture6(Texture texture) {
bindTexture(TextureUnit.TEXTURE6, texture);
}
public void bindTexture7(Texture texture) {
bindTexture(TextureUnit.TEXTURE7, texture);
}
public void bindTexture8(Texture texture) {
bindTexture(TextureUnit.TEXTURE8, texture);
}
public void bindTexture9(Texture texture) {
bindTexture(TextureUnit.TEXTURE9, texture);
}
public void bindTexture10(Texture texture) {
bindTexture(TextureUnit.TEXTURE10, texture);
}
public void bindTexture11(Texture texture) {
bindTexture(TextureUnit.TEXTURE11, texture);
}
public void bindTexture12(Texture texture) {
bindTexture(TextureUnit.TEXTURE12, texture);
}
public void bindTexture13(Texture texture) {
bindTexture(TextureUnit.TEXTURE13, texture);
}
public void bindTexture14(Texture texture) {
bindTexture(TextureUnit.TEXTURE14, texture);
}
public void bindTexture15(Texture texture) {
bindTexture(TextureUnit.TEXTURE15, texture);
}
public void bindTextures(Segment segment) {
SegmentMaterial material = segment.getMaterial();
if ((material == null) || material.getTextures().isEmpty()) {
unbindModel();
return;
}
Iterator<Map.Entry<TextureType, String>> iterator = material.getTextures().entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<TextureType, String> entry = iterator.next();
bindTexture(entry.getKey(), entry.getValue());
}
}
public int getMaxModelTextureUnits() {
return maxModelTextureUnits;
}
public void setMaxModelTextureUnits(int maxModelTextureUnits) {
this.maxModelTextureUnits = maxModelTextureUnits;
}
public int getMaxModelTextureUnitsWithTextureFlag() {
return maxModelTextureUnitsWithTextureFlag;
}
public void setMaxModelTextureUnitsWithTextureFlag(int maxModelTextureUnitsWithTextureFlag) {
this.maxModelTextureUnitsWithTextureFlag = maxModelTextureUnitsWithTextureFlag;
}
public int getMaxShaderTextureUnits() {
return maxShaderTextureUnits;
}
public void setMaxShaderTextureUnits(int maxShaderTextureUnits) {
this.maxShaderTextureUnits = maxShaderTextureUnits;
}
public int getMaxTextureUnits() {
return maxTextureUnits;
}
public void setMaxTextureUnits(int maxTextureUnits) {
this.maxTextureUnits = maxTextureUnits;
}
public final void reset() {
activeTextureUnit = -1;
}
public void unbindAll() {
for (int i = 0; i < maxTextureUnits; i++) {
bindTexture(TextureUnit.TEXTURE0 + i, null);
}
}
public void unbindAllForce() {
for (int i = 0; i < maxTextureUnits; i++) {
bindTexture(TextureUnit.TEXTURE0 + i, null);
GL.textureHelper.unbind();
}
}
public void unbindCurrent() {
int activeTextureID = textureUnitToTextureID.get(activeTextureUnit);
// Null key early out or if the active texture ID is already zero
if ((activeTextureID == HashMapIntInt.NOT_FOUND) || (activeTextureID == 0)) {
return;
}
// Active texture ID has changed
textureUnitToTextureID.put(activeTextureUnit, 0);
if ((activeTextureUnit >= TextureUnit.TEXTURE0)
&& (activeTextureUnit < (TextureUnit.TEXTURE0 + maxModelTextureUnitsWithTextureFlag))) {
Renderable.shaderBindState.sendUniformTextureFlag(0f);
}
// Unbind all texture targets
GL.textureHelper.setTextureTarget2D();
GL.textureHelper.unbind();
GL.textureHelper.setTextureTarget3D();
GL.textureHelper.unbind();
GL.textureHelper.setTextureTargetCubeMap();
GL.textureHelper.unbind();
}
public void unbindModel() {
for (int i = 0; i < maxModelTextureUnits; i++) {
bindTexture(TextureUnit.TEXTURE0 + i, null);
}
}
public void unbindModelForce() {
for (int i = 0; i < maxModelTextureUnits; i++) {
bindTexture(TextureUnit.TEXTURE0 + i, null);
GL.textureHelper.unbind();
}
}
public void unbindShader() {
for (int i = maxModelTextureUnits; i < maxShaderTextureUnits; i++) {
bindTexture(TextureUnit.TEXTURE0 + i, null);
}
}
public void unbindShaderForce() {
for (int i = maxModelTextureUnits; i < maxShaderTextureUnits; i++) {
bindTexture(TextureUnit.TEXTURE0 + i, null);
GL.textureHelper.unbind();
}
}
}