Also includes some unrelated tests Conflicts: jme3-core/src/main/java/com/jme3/renderer/RenderManager.java jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.javaexperimental^2^2
parent
49339497fa
commit
9d035f747a
@ -0,0 +1,96 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2015 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.material; |
||||||
|
|
||||||
|
import com.jme3.asset.AssetManager; |
||||||
|
import com.jme3.light.AmbientLight; |
||||||
|
import com.jme3.light.Light; |
||||||
|
import com.jme3.light.LightList; |
||||||
|
import com.jme3.math.ColorRGBA; |
||||||
|
import com.jme3.renderer.Caps; |
||||||
|
import com.jme3.renderer.RenderManager; |
||||||
|
import com.jme3.renderer.Renderer; |
||||||
|
import com.jme3.scene.Geometry; |
||||||
|
import com.jme3.scene.Mesh; |
||||||
|
import com.jme3.scene.instancing.InstancedGeometry; |
||||||
|
import com.jme3.shader.DefineList; |
||||||
|
import com.jme3.shader.Shader; |
||||||
|
import java.util.EnumSet; |
||||||
|
|
||||||
|
public class DefaultTechniqueDefLogic implements TechniqueDefLogic { |
||||||
|
|
||||||
|
protected final TechniqueDef techniqueDef; |
||||||
|
|
||||||
|
public DefaultTechniqueDefLogic(TechniqueDef techniqueDef) { |
||||||
|
this.techniqueDef = techniqueDef; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Shader makeCurrent(AssetManager assetManager, RenderManager renderManager, |
||||||
|
EnumSet<Caps> rendererCaps, DefineList defines) { |
||||||
|
return techniqueDef.getShader(assetManager, rendererCaps, defines); |
||||||
|
} |
||||||
|
|
||||||
|
public static void renderMeshFromGeometry(Renderer renderer, Geometry geom) { |
||||||
|
Mesh mesh = geom.getMesh(); |
||||||
|
int lodLevel = geom.getLodLevel(); |
||||||
|
if (geom instanceof InstancedGeometry) { |
||||||
|
InstancedGeometry instGeom = (InstancedGeometry) geom; |
||||||
|
renderer.renderMesh(mesh, lodLevel, instGeom.getActualNumInstances(), |
||||||
|
instGeom.getAllInstanceData()); |
||||||
|
} else { |
||||||
|
renderer.renderMesh(mesh, lodLevel, 1, null); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static ColorRGBA getAmbientColor(LightList lightList, boolean removeLights, ColorRGBA ambientLightColor) { |
||||||
|
ambientLightColor.set(0, 0, 0, 1); |
||||||
|
for (int j = 0; j < lightList.size(); j++) { |
||||||
|
Light l = lightList.get(j); |
||||||
|
if (l instanceof AmbientLight) { |
||||||
|
ambientLightColor.addLocal(l.getColor()); |
||||||
|
if (removeLights) { |
||||||
|
lightList.remove(l); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
ambientLightColor.a = 1.0f; |
||||||
|
return ambientLightColor; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights) { |
||||||
|
Renderer renderer = renderManager.getRenderer(); |
||||||
|
renderer.setShader(shader); |
||||||
|
renderMeshFromGeometry(renderer, geometry); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,176 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2015 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.material; |
||||||
|
|
||||||
|
import com.jme3.asset.AssetManager; |
||||||
|
import com.jme3.light.AmbientLight; |
||||||
|
import com.jme3.light.DirectionalLight; |
||||||
|
import com.jme3.light.Light; |
||||||
|
import com.jme3.light.LightList; |
||||||
|
import com.jme3.light.PointLight; |
||||||
|
import com.jme3.light.SpotLight; |
||||||
|
import com.jme3.math.ColorRGBA; |
||||||
|
import com.jme3.math.FastMath; |
||||||
|
import com.jme3.math.Quaternion; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.math.Vector4f; |
||||||
|
import com.jme3.renderer.Caps; |
||||||
|
import com.jme3.renderer.RenderManager; |
||||||
|
import com.jme3.renderer.Renderer; |
||||||
|
import com.jme3.scene.Geometry; |
||||||
|
import com.jme3.shader.DefineList; |
||||||
|
import com.jme3.shader.Shader; |
||||||
|
import com.jme3.shader.Uniform; |
||||||
|
import com.jme3.shader.VarType; |
||||||
|
import com.jme3.util.TempVars; |
||||||
|
import java.util.EnumSet; |
||||||
|
|
||||||
|
public final class MultiPassLightingLogic extends DefaultTechniqueDefLogic { |
||||||
|
|
||||||
|
private static final RenderState ADDITIVE_LIGHT = new RenderState(); |
||||||
|
private static final Quaternion NULL_DIR_LIGHT = new Quaternion(0, -1, 0, -1); |
||||||
|
|
||||||
|
private final ColorRGBA ambientLightColor = new ColorRGBA(0, 0, 0, 1); |
||||||
|
|
||||||
|
static { |
||||||
|
ADDITIVE_LIGHT.setBlendMode(RenderState.BlendMode.AlphaAdditive); |
||||||
|
ADDITIVE_LIGHT.setDepthWrite(false); |
||||||
|
} |
||||||
|
|
||||||
|
public MultiPassLightingLogic(TechniqueDef techniqueDef) { |
||||||
|
super(techniqueDef); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights) { |
||||||
|
Renderer r = renderManager.getRenderer(); |
||||||
|
Uniform lightDir = shader.getUniform("g_LightDirection"); |
||||||
|
Uniform lightColor = shader.getUniform("g_LightColor"); |
||||||
|
Uniform lightPos = shader.getUniform("g_LightPosition"); |
||||||
|
Uniform ambientColor = shader.getUniform("g_AmbientLightColor"); |
||||||
|
boolean isFirstLight = true; |
||||||
|
boolean isSecondLight = false; |
||||||
|
|
||||||
|
getAmbientColor(lights, false, ambientLightColor); |
||||||
|
|
||||||
|
for (int i = 0; i < lights.size(); i++) { |
||||||
|
Light l = lights.get(i); |
||||||
|
if (l instanceof AmbientLight) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
if (isFirstLight) { |
||||||
|
// set ambient color for first light only
|
||||||
|
ambientColor.setValue(VarType.Vector4, ambientLightColor); |
||||||
|
isFirstLight = false; |
||||||
|
isSecondLight = true; |
||||||
|
} else if (isSecondLight) { |
||||||
|
ambientColor.setValue(VarType.Vector4, ColorRGBA.Black); |
||||||
|
// apply additive blending for 2nd and future lights
|
||||||
|
r.applyRenderState(ADDITIVE_LIGHT); |
||||||
|
isSecondLight = false; |
||||||
|
} |
||||||
|
|
||||||
|
TempVars vars = TempVars.get(); |
||||||
|
Quaternion tmpLightDirection = vars.quat1; |
||||||
|
Quaternion tmpLightPosition = vars.quat2; |
||||||
|
ColorRGBA tmpLightColor = vars.color; |
||||||
|
Vector4f tmpVec = vars.vect4f1; |
||||||
|
|
||||||
|
ColorRGBA color = l.getColor(); |
||||||
|
tmpLightColor.set(color); |
||||||
|
tmpLightColor.a = l.getType().getId(); |
||||||
|
lightColor.setValue(VarType.Vector4, tmpLightColor); |
||||||
|
|
||||||
|
switch (l.getType()) { |
||||||
|
case Directional: |
||||||
|
DirectionalLight dl = (DirectionalLight) l; |
||||||
|
Vector3f dir = dl.getDirection(); |
||||||
|
//FIXME : there is an inconstency here due to backward
|
||||||
|
//compatibility of the lighting shader.
|
||||||
|
//The directional light direction is passed in the
|
||||||
|
//LightPosition uniform. The lighting shader needs to be
|
||||||
|
//reworked though in order to fix this.
|
||||||
|
tmpLightPosition.set(dir.getX(), dir.getY(), dir.getZ(), -1); |
||||||
|
lightPos.setValue(VarType.Vector4, tmpLightPosition); |
||||||
|
tmpLightDirection.set(0, 0, 0, 0); |
||||||
|
lightDir.setValue(VarType.Vector4, tmpLightDirection); |
||||||
|
break; |
||||||
|
case Point: |
||||||
|
PointLight pl = (PointLight) l; |
||||||
|
Vector3f pos = pl.getPosition(); |
||||||
|
float invRadius = pl.getInvRadius(); |
||||||
|
|
||||||
|
tmpLightPosition.set(pos.getX(), pos.getY(), pos.getZ(), invRadius); |
||||||
|
lightPos.setValue(VarType.Vector4, tmpLightPosition); |
||||||
|
tmpLightDirection.set(0, 0, 0, 0); |
||||||
|
lightDir.setValue(VarType.Vector4, tmpLightDirection); |
||||||
|
break; |
||||||
|
case Spot: |
||||||
|
SpotLight sl = (SpotLight) l; |
||||||
|
Vector3f pos2 = sl.getPosition(); |
||||||
|
Vector3f dir2 = sl.getDirection(); |
||||||
|
float invRange = sl.getInvSpotRange(); |
||||||
|
float spotAngleCos = sl.getPackedAngleCos(); |
||||||
|
|
||||||
|
tmpLightPosition.set(pos2.getX(), pos2.getY(), pos2.getZ(), invRange); |
||||||
|
lightPos.setValue(VarType.Vector4, tmpLightPosition); |
||||||
|
|
||||||
|
//We transform the spot direction in view space here to save 5 varying later in the lighting shader
|
||||||
|
//one vec4 less and a vec4 that becomes a vec3
|
||||||
|
//the downside is that spotAngleCos decoding happens now in the frag shader.
|
||||||
|
tmpVec.set(dir2.getX(), dir2.getY(), dir2.getZ(), 0); |
||||||
|
renderManager.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec); |
||||||
|
tmpLightDirection.set(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), spotAngleCos); |
||||||
|
|
||||||
|
lightDir.setValue(VarType.Vector4, tmpLightDirection); |
||||||
|
|
||||||
|
break; |
||||||
|
default: |
||||||
|
throw new UnsupportedOperationException("Unknown type of light: " + l.getType()); |
||||||
|
} |
||||||
|
vars.release(); |
||||||
|
r.setShader(shader); |
||||||
|
renderMeshFromGeometry(r, geometry); |
||||||
|
} |
||||||
|
|
||||||
|
if (isFirstLight) { |
||||||
|
// Either there are no lights at all, or only ambient lights.
|
||||||
|
// Render a dummy "normal light" so we can see the ambient color.
|
||||||
|
ambientColor.setValue(VarType.Vector4, getAmbientColor(lights, false, ambientLightColor)); |
||||||
|
lightColor.setValue(VarType.Vector4, ColorRGBA.BlackNoAlpha); |
||||||
|
lightPos.setValue(VarType.Vector4, NULL_DIR_LIGHT); |
||||||
|
r.setShader(shader); |
||||||
|
renderMeshFromGeometry(r, geometry); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,218 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2015 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.material; |
||||||
|
|
||||||
|
import com.jme3.asset.AssetManager; |
||||||
|
import com.jme3.light.DirectionalLight; |
||||||
|
import com.jme3.light.Light; |
||||||
|
import com.jme3.light.LightList; |
||||||
|
import com.jme3.light.PointLight; |
||||||
|
import com.jme3.light.SpotLight; |
||||||
|
import com.jme3.material.RenderState.BlendMode; |
||||||
|
import com.jme3.math.ColorRGBA; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.math.Vector4f; |
||||||
|
import com.jme3.renderer.Caps; |
||||||
|
import com.jme3.renderer.RenderManager; |
||||||
|
import com.jme3.renderer.Renderer; |
||||||
|
import com.jme3.scene.Geometry; |
||||||
|
import com.jme3.shader.DefineList; |
||||||
|
import com.jme3.shader.Shader; |
||||||
|
import com.jme3.shader.Uniform; |
||||||
|
import com.jme3.shader.VarType; |
||||||
|
import com.jme3.util.TempVars; |
||||||
|
import java.util.EnumSet; |
||||||
|
|
||||||
|
public final class SinglePassLightingLogic extends DefaultTechniqueDefLogic { |
||||||
|
|
||||||
|
private static final String DEFINE_SINGLE_PASS_LIGHTING = "SINGLE_PASS_LIGHTING"; |
||||||
|
private static final String DEFINE_NB_LIGHTS = "NB_LIGHTS"; |
||||||
|
private static final RenderState ADDITIVE_LIGHT = new RenderState(); |
||||||
|
|
||||||
|
private final ColorRGBA ambientLightColor = new ColorRGBA(0, 0, 0, 1); |
||||||
|
|
||||||
|
static { |
||||||
|
ADDITIVE_LIGHT.setBlendMode(BlendMode.AlphaAdditive); |
||||||
|
ADDITIVE_LIGHT.setDepthWrite(false); |
||||||
|
} |
||||||
|
|
||||||
|
private final int singlePassLightingDefineId; |
||||||
|
private final int nbLightsDefineId; |
||||||
|
|
||||||
|
public SinglePassLightingLogic(TechniqueDef techniqueDef) { |
||||||
|
super(techniqueDef); |
||||||
|
singlePassLightingDefineId = techniqueDef.addShaderUnmappedDefine(DEFINE_SINGLE_PASS_LIGHTING, VarType.Boolean); |
||||||
|
nbLightsDefineId = techniqueDef.addShaderUnmappedDefine(DEFINE_NB_LIGHTS, VarType.Int); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Shader makeCurrent(AssetManager assetManager, RenderManager renderManager, |
||||||
|
EnumSet<Caps> rendererCaps, DefineList defines) { |
||||||
|
defines.set(nbLightsDefineId, renderManager.getSinglePassLightBatchSize() * 3); |
||||||
|
defines.set(singlePassLightingDefineId, true); |
||||||
|
return super.makeCurrent(assetManager, renderManager, rendererCaps, defines); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Uploads the lights in the light list as two uniform arrays.<br/><br/> * |
||||||
|
* <p> |
||||||
|
* <code>uniform vec4 g_LightColor[numLights];</code><br/> //
|
||||||
|
* g_LightColor.rgb is the diffuse/specular color of the light.<br/> //
|
||||||
|
* g_Lightcolor.a is the type of light, 0 = Directional, 1 = Point, <br/> //
|
||||||
|
* 2 = Spot. <br/> <br/> |
||||||
|
* <code>uniform vec4 g_LightPosition[numLights];</code><br/> //
|
||||||
|
* g_LightPosition.xyz is the position of the light (for point lights)<br/> |
||||||
|
* // or the direction of the light (for directional lights).<br/> //
|
||||||
|
* g_LightPosition.w is the inverse radius (1/r) of the light (for |
||||||
|
* attenuation) <br/> </p> |
||||||
|
*/ |
||||||
|
protected int updateLightListUniforms(Shader shader, Geometry g, LightList lightList, int numLights, RenderManager rm, int startIndex) { |
||||||
|
if (numLights == 0) { // this shader does not do lighting, ignore.
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
Uniform lightData = shader.getUniform("g_LightData"); |
||||||
|
lightData.setVector4Length(numLights * 3);//8 lights * max 3
|
||||||
|
Uniform ambientColor = shader.getUniform("g_AmbientLightColor"); |
||||||
|
|
||||||
|
|
||||||
|
if (startIndex != 0) { |
||||||
|
// apply additive blending for 2nd and future passes
|
||||||
|
rm.getRenderer().applyRenderState(ADDITIVE_LIGHT); |
||||||
|
ambientColor.setValue(VarType.Vector4, ColorRGBA.Black); |
||||||
|
} else { |
||||||
|
ambientColor.setValue(VarType.Vector4, getAmbientColor(lightList, true, ambientLightColor)); |
||||||
|
} |
||||||
|
|
||||||
|
int lightDataIndex = 0; |
||||||
|
TempVars vars = TempVars.get(); |
||||||
|
Vector4f tmpVec = vars.vect4f1; |
||||||
|
int curIndex; |
||||||
|
int endIndex = numLights + startIndex; |
||||||
|
for (curIndex = startIndex; curIndex < endIndex && curIndex < lightList.size(); curIndex++) { |
||||||
|
|
||||||
|
|
||||||
|
Light l = lightList.get(curIndex); |
||||||
|
if(l.getType() == Light.Type.Ambient){ |
||||||
|
endIndex++; |
||||||
|
continue; |
||||||
|
} |
||||||
|
ColorRGBA color = l.getColor(); |
||||||
|
//Color
|
||||||
|
lightData.setVector4InArray(color.getRed(), |
||||||
|
color.getGreen(), |
||||||
|
color.getBlue(), |
||||||
|
l.getType().getId(), |
||||||
|
lightDataIndex); |
||||||
|
lightDataIndex++; |
||||||
|
|
||||||
|
switch (l.getType()) { |
||||||
|
case Directional: |
||||||
|
DirectionalLight dl = (DirectionalLight) l; |
||||||
|
Vector3f dir = dl.getDirection(); |
||||||
|
//Data directly sent in view space to avoid a matrix mult for each pixel
|
||||||
|
tmpVec.set(dir.getX(), dir.getY(), dir.getZ(), 0.0f); |
||||||
|
rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec); |
||||||
|
// tmpVec.divideLocal(tmpVec.w);
|
||||||
|
// tmpVec.normalizeLocal();
|
||||||
|
lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), -1, lightDataIndex); |
||||||
|
lightDataIndex++; |
||||||
|
//PADDING
|
||||||
|
lightData.setVector4InArray(0,0,0,0, lightDataIndex); |
||||||
|
lightDataIndex++; |
||||||
|
break; |
||||||
|
case Point: |
||||||
|
PointLight pl = (PointLight) l; |
||||||
|
Vector3f pos = pl.getPosition(); |
||||||
|
float invRadius = pl.getInvRadius(); |
||||||
|
tmpVec.set(pos.getX(), pos.getY(), pos.getZ(), 1.0f); |
||||||
|
rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec); |
||||||
|
//tmpVec.divideLocal(tmpVec.w);
|
||||||
|
lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), invRadius, lightDataIndex); |
||||||
|
lightDataIndex++; |
||||||
|
//PADDING
|
||||||
|
lightData.setVector4InArray(0,0,0,0, lightDataIndex); |
||||||
|
lightDataIndex++; |
||||||
|
break; |
||||||
|
case Spot: |
||||||
|
SpotLight sl = (SpotLight) l; |
||||||
|
Vector3f pos2 = sl.getPosition(); |
||||||
|
Vector3f dir2 = sl.getDirection(); |
||||||
|
float invRange = sl.getInvSpotRange(); |
||||||
|
float spotAngleCos = sl.getPackedAngleCos(); |
||||||
|
tmpVec.set(pos2.getX(), pos2.getY(), pos2.getZ(), 1.0f); |
||||||
|
rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec); |
||||||
|
// tmpVec.divideLocal(tmpVec.w);
|
||||||
|
lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), invRange, lightDataIndex); |
||||||
|
lightDataIndex++; |
||||||
|
|
||||||
|
//We transform the spot direction in view space here to save 5 varying later in the lighting shader
|
||||||
|
//one vec4 less and a vec4 that becomes a vec3
|
||||||
|
//the downside is that spotAngleCos decoding happens now in the frag shader.
|
||||||
|
tmpVec.set(dir2.getX(), dir2.getY(), dir2.getZ(), 0.0f); |
||||||
|
rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec); |
||||||
|
tmpVec.normalizeLocal(); |
||||||
|
lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), spotAngleCos, lightDataIndex); |
||||||
|
lightDataIndex++; |
||||||
|
break; |
||||||
|
default: |
||||||
|
throw new UnsupportedOperationException("Unknown type of light: " + l.getType()); |
||||||
|
} |
||||||
|
} |
||||||
|
vars.release(); |
||||||
|
//Padding of unsued buffer space
|
||||||
|
while(lightDataIndex < numLights * 3) { |
||||||
|
lightData.setVector4InArray(0f, 0f, 0f, 0f, lightDataIndex); |
||||||
|
lightDataIndex++; |
||||||
|
} |
||||||
|
return curIndex; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights) { |
||||||
|
int nbRenderedLights = 0; |
||||||
|
Renderer renderer = renderManager.getRenderer(); |
||||||
|
int batchSize = renderManager.getSinglePassLightBatchSize(); |
||||||
|
if (lights.size() == 0) { |
||||||
|
updateLightListUniforms(shader, geometry, lights, batchSize, renderManager, 0); |
||||||
|
renderer.setShader(shader); |
||||||
|
renderMeshFromGeometry(renderer, geometry); |
||||||
|
} else { |
||||||
|
while (nbRenderedLights < lights.size()) { |
||||||
|
nbRenderedLights = updateLightListUniforms(shader, geometry, lights, batchSize, renderManager, nbRenderedLights); |
||||||
|
renderer.setShader(shader); |
||||||
|
renderMeshFromGeometry(renderer, geometry); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,95 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2015 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.material; |
||||||
|
|
||||||
|
import com.jme3.asset.AssetManager; |
||||||
|
import com.jme3.light.LightList; |
||||||
|
import com.jme3.material.TechniqueDef.LightMode; |
||||||
|
import com.jme3.renderer.Caps; |
||||||
|
import com.jme3.renderer.RenderManager; |
||||||
|
import com.jme3.scene.Geometry; |
||||||
|
import com.jme3.shader.DefineList; |
||||||
|
import com.jme3.shader.Shader; |
||||||
|
import com.jme3.shader.Uniform; |
||||||
|
import com.jme3.shader.UniformBinding; |
||||||
|
import com.jme3.texture.Texture; |
||||||
|
import java.util.EnumSet; |
||||||
|
|
||||||
|
/** |
||||||
|
* <code>TechniqueDefLogic</code> is used to customize how |
||||||
|
* a material should be rendered. |
||||||
|
* |
||||||
|
* Typically used to implement {@link LightMode lighting modes}. |
||||||
|
* Implementations can register |
||||||
|
* {@link TechniqueDef#addShaderUnmappedDefine(java.lang.String) unmapped defines} |
||||||
|
* in their constructor and then later set them based on the geometry |
||||||
|
* or light environment being rendered. |
||||||
|
* |
||||||
|
* @author Kirill Vainer |
||||||
|
*/ |
||||||
|
public interface TechniqueDefLogic { |
||||||
|
|
||||||
|
/** |
||||||
|
* Determine the shader to use for the given geometry / material combination. |
||||||
|
* |
||||||
|
* @param assetManager The asset manager to use for loading shader source code, |
||||||
|
* shader nodes, and and lookup textures. |
||||||
|
* @param renderManager The render manager for which rendering is to be performed. |
||||||
|
* @param rendererCaps Renderer capabilities. The returned shader must |
||||||
|
* support these capabilities. |
||||||
|
* @param defines The define list used by the technique, any |
||||||
|
* {@link TechniqueDef#addShaderUnmappedDefine(java.lang.String) unmapped defines} |
||||||
|
* should be set here to change shader behavior. |
||||||
|
* |
||||||
|
* @return The shader to use for rendering. |
||||||
|
*/ |
||||||
|
public Shader makeCurrent(AssetManager assetManager, RenderManager renderManager, |
||||||
|
EnumSet<Caps> rendererCaps, DefineList defines); |
||||||
|
|
||||||
|
/** |
||||||
|
* Requests that the <code>TechniqueDefLogic</code> renders the given geometry. |
||||||
|
* |
||||||
|
* Fixed material functionality such as {@link RenderState}, |
||||||
|
* {@link MatParam material parameters}, and |
||||||
|
* {@link UniformBinding uniform bindings} |
||||||
|
* have already been applied by the material, however, |
||||||
|
* {@link RenderState}, {@link Uniform uniforms}, {@link Texture textures}, |
||||||
|
* can still be overriden. |
||||||
|
* |
||||||
|
* @param renderManager The render manager to perform the rendering against. |
||||||
|
* * @param shader The shader that was selected by this logic in |
||||||
|
* {@link #makeCurrent(com.jme3.asset.AssetManager, com.jme3.renderer.RenderManager, java.util.EnumSet, com.jme3.shader.DefineList)}. |
||||||
|
* @param geometry The geometry to render |
||||||
|
* @param lights Lights which influence the geometry. |
||||||
|
*/ |
||||||
|
public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights); |
||||||
|
} |
@ -1,201 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine |
|
||||||
* All rights reserved. |
|
||||||
* |
|
||||||
* Redistribution and use in source and binary forms, with or without |
|
||||||
* modification, are permitted provided that the following conditions are |
|
||||||
* met: |
|
||||||
* |
|
||||||
* * Redistributions of source code must retain the above copyright |
|
||||||
* notice, this list of conditions and the following disclaimer. |
|
||||||
* |
|
||||||
* * Redistributions in binary form must reproduce the above copyright |
|
||||||
* notice, this list of conditions and the following disclaimer in the |
|
||||||
* documentation and/or other materials provided with the distribution. |
|
||||||
* |
|
||||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
|
||||||
* may be used to endorse or promote products derived from this software |
|
||||||
* without specific prior written permission. |
|
||||||
* |
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
|
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
|
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
|
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
||||||
*/ |
|
||||||
package com.jme3.shader; |
|
||||||
|
|
||||||
import com.jme3.asset.AssetKey; |
|
||||||
import com.jme3.export.InputCapsule; |
|
||||||
import com.jme3.export.JmeExporter; |
|
||||||
import com.jme3.export.JmeImporter; |
|
||||||
import com.jme3.export.OutputCapsule; |
|
||||||
import java.io.IOException; |
|
||||||
import java.util.EnumMap; |
|
||||||
import java.util.Set; |
|
||||||
|
|
||||||
public class ShaderKey extends AssetKey<Shader> { |
|
||||||
|
|
||||||
protected EnumMap<Shader.ShaderType,String> shaderLanguage; |
|
||||||
protected EnumMap<Shader.ShaderType,String> shaderName; |
|
||||||
protected DefineList defines; |
|
||||||
protected int cachedHashedCode = 0; |
|
||||||
protected boolean usesShaderNodes = false; |
|
||||||
|
|
||||||
public ShaderKey(){ |
|
||||||
shaderLanguage=new EnumMap<Shader.ShaderType, String>(Shader.ShaderType.class); |
|
||||||
shaderName=new EnumMap<Shader.ShaderType, String>(Shader.ShaderType.class); |
|
||||||
} |
|
||||||
|
|
||||||
public ShaderKey(DefineList defines, EnumMap<Shader.ShaderType,String> shaderLanguage,EnumMap<Shader.ShaderType,String> shaderName){ |
|
||||||
super(""); |
|
||||||
this.name = reducePath(getShaderName(Shader.ShaderType.Vertex)); |
|
||||||
this.shaderLanguage=new EnumMap<Shader.ShaderType, String>(Shader.ShaderType.class); |
|
||||||
this.shaderName=new EnumMap<Shader.ShaderType, String>(Shader.ShaderType.class); |
|
||||||
this.defines = defines; |
|
||||||
for (Shader.ShaderType shaderType : shaderName.keySet()) { |
|
||||||
this.shaderName.put(shaderType,shaderName.get(shaderType)); |
|
||||||
this.shaderLanguage.put(shaderType,shaderLanguage.get(shaderType)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public ShaderKey clone() { |
|
||||||
ShaderKey clone = (ShaderKey) super.clone(); |
|
||||||
clone.cachedHashedCode = 0; |
|
||||||
clone.defines = defines.clone(); |
|
||||||
return clone; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public String toString(){ |
|
||||||
//todo:
|
|
||||||
return "V="+name+";"; |
|
||||||
} |
|
||||||
|
|
||||||
private final String getShaderName(Shader.ShaderType type) { |
|
||||||
if (shaderName == null) { |
|
||||||
return ""; |
|
||||||
} |
|
||||||
String shName = shaderName.get(type); |
|
||||||
return shName != null ? shName : ""; |
|
||||||
} |
|
||||||
|
|
||||||
//todo: make equals and hashCode work
|
|
||||||
@Override |
|
||||||
public boolean equals(Object obj) { |
|
||||||
final ShaderKey other = (ShaderKey) obj; |
|
||||||
if (name.equals(other.name) && getShaderName(Shader.ShaderType.Fragment).equals(other.getShaderName(Shader.ShaderType.Fragment))){ |
|
||||||
if (defines != null && other.defines != null) { |
|
||||||
return defines.equals(other.defines); |
|
||||||
} else if (defines != null || other.defines != null) { |
|
||||||
return false; |
|
||||||
} else { |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public int hashCode() { |
|
||||||
if (cachedHashedCode == 0) { |
|
||||||
int hash = 7; |
|
||||||
hash = 41 * hash + name.hashCode(); |
|
||||||
hash = 41 * hash + getShaderName(Shader.ShaderType.Fragment).hashCode(); |
|
||||||
hash = getShaderName(Shader.ShaderType.Geometry) == null ? hash : 41 * hash + getShaderName(Shader.ShaderType.Geometry).hashCode(); |
|
||||||
hash = getShaderName(Shader.ShaderType.TessellationControl) == null ? hash : 41 * hash + getShaderName(Shader.ShaderType.TessellationControl).hashCode(); |
|
||||||
hash = getShaderName(Shader.ShaderType.TessellationEvaluation) == null ? hash : 41 * hash + getShaderName(Shader.ShaderType.TessellationEvaluation).hashCode(); |
|
||||||
hash = 41 * hash + (defines != null ? defines.hashCode() : 0); |
|
||||||
cachedHashedCode = hash; |
|
||||||
} |
|
||||||
return cachedHashedCode; |
|
||||||
} |
|
||||||
|
|
||||||
public DefineList getDefines() { |
|
||||||
return defines; |
|
||||||
} |
|
||||||
|
|
||||||
public String getVertName(){ |
|
||||||
return getShaderName(Shader.ShaderType.Vertex); |
|
||||||
} |
|
||||||
|
|
||||||
public String getFragName() { |
|
||||||
return getShaderName(Shader.ShaderType.Fragment); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* @deprecated Use {@link #getVertexShaderLanguage() } instead. |
|
||||||
*/ |
|
||||||
@Deprecated |
|
||||||
public String getLanguage() { |
|
||||||
return shaderLanguage.get(Shader.ShaderType.Vertex); |
|
||||||
} |
|
||||||
|
|
||||||
public String getVertexShaderLanguage() { |
|
||||||
return shaderLanguage.get(Shader.ShaderType.Vertex); |
|
||||||
} |
|
||||||
|
|
||||||
public String getFragmentShaderLanguage() { |
|
||||||
return shaderLanguage.get(Shader.ShaderType.Vertex); |
|
||||||
} |
|
||||||
|
|
||||||
public boolean isUsesShaderNodes() { |
|
||||||
return usesShaderNodes; |
|
||||||
} |
|
||||||
|
|
||||||
public void setUsesShaderNodes(boolean usesShaderNodes) { |
|
||||||
this.usesShaderNodes = usesShaderNodes; |
|
||||||
} |
|
||||||
|
|
||||||
public Set<Shader.ShaderType> getUsedShaderPrograms(){ |
|
||||||
return shaderName.keySet(); |
|
||||||
} |
|
||||||
|
|
||||||
public String getShaderProgramLanguage(Shader.ShaderType shaderType){ |
|
||||||
return shaderLanguage.get(shaderType); |
|
||||||
} |
|
||||||
|
|
||||||
public String getShaderProgramName(Shader.ShaderType shaderType){ |
|
||||||
return getShaderName(shaderType); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void write(JmeExporter ex) throws IOException{ |
|
||||||
super.write(ex); |
|
||||||
OutputCapsule oc = ex.getCapsule(this); |
|
||||||
oc.write(shaderName.get(Shader.ShaderType.Fragment), "fragment_name", null); |
|
||||||
oc.write(shaderName.get(Shader.ShaderType.Geometry), "geometry_name", null); |
|
||||||
oc.write(shaderName.get(Shader.ShaderType.TessellationControl), "tessControl_name", null); |
|
||||||
oc.write(shaderName.get(Shader.ShaderType.TessellationEvaluation), "tessEval_name", null); |
|
||||||
oc.write(shaderLanguage.get(Shader.ShaderType.Vertex), "language", null); |
|
||||||
oc.write(shaderLanguage.get(Shader.ShaderType.Fragment), "frag_language", null); |
|
||||||
oc.write(shaderLanguage.get(Shader.ShaderType.Geometry), "geom_language", null); |
|
||||||
oc.write(shaderLanguage.get(Shader.ShaderType.TessellationControl), "tsctrl_language", null); |
|
||||||
oc.write(shaderLanguage.get(Shader.ShaderType.TessellationEvaluation), "tseval_language", null); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void read(JmeImporter im) throws IOException{ |
|
||||||
super.read(im); |
|
||||||
InputCapsule ic = im.getCapsule(this); |
|
||||||
shaderName.put(Shader.ShaderType.Vertex,name); |
|
||||||
shaderName.put(Shader.ShaderType.Fragment,ic.readString("fragment_name", null)); |
|
||||||
shaderName.put(Shader.ShaderType.Geometry,ic.readString("geometry_name", null)); |
|
||||||
shaderName.put(Shader.ShaderType.TessellationControl,ic.readString("tessControl_name", null)); |
|
||||||
shaderName.put(Shader.ShaderType.TessellationEvaluation,ic.readString("tessEval_name", null)); |
|
||||||
shaderLanguage.put(Shader.ShaderType.Vertex,ic.readString("language", null)); |
|
||||||
shaderLanguage.put(Shader.ShaderType.Fragment,ic.readString("frag_language", null)); |
|
||||||
shaderLanguage.put(Shader.ShaderType.Geometry,ic.readString("geom_language", null)); |
|
||||||
shaderLanguage.put(Shader.ShaderType.TessellationControl,ic.readString("tsctrl_language", null)); |
|
||||||
shaderLanguage.put(Shader.ShaderType.TessellationEvaluation,ic.readString("tseval_language", null)); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -0,0 +1,52 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2015 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.asset; |
||||||
|
|
||||||
|
import com.jme3.asset.plugins.ClasspathLocator; |
||||||
|
import com.jme3.shader.plugins.GLSLLoader; |
||||||
|
import com.jme3.system.JmeSystem; |
||||||
|
import com.jme3.system.MockJmeSystemDelegate; |
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
public class LoadShaderSourceTest { |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testLoadShaderSource() { |
||||||
|
JmeSystem.setSystemDelegate(new MockJmeSystemDelegate()); |
||||||
|
AssetManager assetManager = new DesktopAssetManager(); |
||||||
|
assetManager.registerLocator(null, ClasspathLocator.class); |
||||||
|
assetManager.registerLoader(GLSLLoader.class, "frag"); |
||||||
|
String showNormals = (String) assetManager.loadAsset("Common/MatDefs/Misc/ShowNormals.frag"); |
||||||
|
System.out.println(showNormals); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,342 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2015 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.renderer; |
||||||
|
|
||||||
|
import com.jme3.asset.AssetManager; |
||||||
|
import com.jme3.material.Material; |
||||||
|
import com.jme3.math.ColorRGBA; |
||||||
|
import com.jme3.renderer.queue.GeometryList; |
||||||
|
import com.jme3.renderer.queue.OpaqueComparator; |
||||||
|
import com.jme3.scene.Geometry; |
||||||
|
import com.jme3.scene.Mesh; |
||||||
|
import com.jme3.scene.shape.Box; |
||||||
|
import com.jme3.system.TestUtil; |
||||||
|
import com.jme3.texture.Image; |
||||||
|
import com.jme3.texture.Image.Format; |
||||||
|
import com.jme3.texture.Texture; |
||||||
|
import com.jme3.texture.Texture2D; |
||||||
|
import com.jme3.texture.image.ColorSpace; |
||||||
|
import com.jme3.util.BufferUtils; |
||||||
|
import java.nio.ByteBuffer; |
||||||
|
import java.util.HashSet; |
||||||
|
import java.util.Set; |
||||||
|
import org.junit.Before; |
||||||
|
import org.junit.Ignore; |
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
public class OpaqueComparatorTest { |
||||||
|
|
||||||
|
private final Mesh mesh = new Box(1,1,1); |
||||||
|
private Camera cam = new Camera(1, 1); |
||||||
|
private RenderManager renderManager; |
||||||
|
private AssetManager assetManager; |
||||||
|
private OpaqueComparator comparator = new OpaqueComparator(); |
||||||
|
|
||||||
|
@Before |
||||||
|
public void setUp() { |
||||||
|
assetManager = TestUtil.createAssetManager(); |
||||||
|
renderManager = TestUtil.createRenderManager(); |
||||||
|
comparator.setCamera(cam); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Given a correctly sorted list of materials, check if the |
||||||
|
* opaque comparator can sort a reversed list of them. |
||||||
|
* |
||||||
|
* Each material will be cloned so that none of them will be equal to each other |
||||||
|
* in reference, forcing the comparator to compare the material sort ID. |
||||||
|
* |
||||||
|
* E.g. for a list of materials A, B, C, the following list will be generated: |
||||||
|
* <pre>C, B, A, C, B, A, C, B, A</pre>, it should result in |
||||||
|
* <pre>A, A, A, B, B, B, C, C, C</pre>. |
||||||
|
* |
||||||
|
* @param materials The pre-sorted list of materials to check sorting for. |
||||||
|
*/ |
||||||
|
private void testSort(Material ... materials) { |
||||||
|
GeometryList gl = new GeometryList(comparator); |
||||||
|
for (int g = 0; g < 5; g++) { |
||||||
|
for (int i = materials.length - 1; i >= 0; i--) { |
||||||
|
Geometry geom = new Geometry("geom", mesh); |
||||||
|
Material clonedMaterial = materials[i].clone(); |
||||||
|
|
||||||
|
if (materials[i].getActiveTechnique() != null) { |
||||||
|
String techniqueName = materials[i].getActiveTechnique().getDef().getName(); |
||||||
|
clonedMaterial.selectTechnique(techniqueName, renderManager); |
||||||
|
} else { |
||||||
|
clonedMaterial.selectTechnique("Default", renderManager); |
||||||
|
} |
||||||
|
|
||||||
|
geom.setMaterial(clonedMaterial); |
||||||
|
gl.add(geom); |
||||||
|
} |
||||||
|
} |
||||||
|
gl.sort(); |
||||||
|
|
||||||
|
for (int i = 0; i < gl.size(); i++) { |
||||||
|
Material mat = gl.get(i).getMaterial(); |
||||||
|
String sortId = Integer.toHexString(mat.getSortId()).toUpperCase(); |
||||||
|
System.out.print(sortId + "\t"); |
||||||
|
System.out.println(mat); |
||||||
|
} |
||||||
|
|
||||||
|
Set<String> alreadySeen = new HashSet<String>(); |
||||||
|
Material current = null; |
||||||
|
for (int i = 0; i < gl.size(); i++) { |
||||||
|
Material mat = gl.get(i).getMaterial(); |
||||||
|
if (current == null) { |
||||||
|
current = mat; |
||||||
|
} else if (!current.getName().equals(mat.getName())) { |
||||||
|
assert !alreadySeen.contains(mat.getName()); |
||||||
|
alreadySeen.add(current.getName()); |
||||||
|
current = mat; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
for (int i = 0; i < materials.length; i++) { |
||||||
|
for (int g = 0; g < 5; g++) { |
||||||
|
int index = i * 5 + g; |
||||||
|
Material mat1 = gl.get(index).getMaterial(); |
||||||
|
Material mat2 = materials[i]; |
||||||
|
assert mat1.getName().equals(mat2.getName()) : |
||||||
|
mat1.getName() + " != " + mat2.getName() + " for index " + index; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testSortByMaterialDef() { |
||||||
|
Material lightingMat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md"); |
||||||
|
Material particleMat = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md"); |
||||||
|
Material unshadedMat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
||||||
|
Material skyMat = new Material(assetManager, "Common/MatDefs/Misc/Sky.j3md"); |
||||||
|
|
||||||
|
lightingMat.setName("MatLight"); |
||||||
|
particleMat.setName("MatParticle"); |
||||||
|
unshadedMat.setName("MatUnshaded"); |
||||||
|
skyMat.setName("MatSky"); |
||||||
|
testSort(skyMat, lightingMat, particleMat, unshadedMat); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testSortByTechnique() { |
||||||
|
Material lightingMatDefault = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md"); |
||||||
|
Material lightingPreShadow = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md"); |
||||||
|
Material lightingPostShadow = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md"); |
||||||
|
Material lightingMatPreNormalPass = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md"); |
||||||
|
Material lightingMatGBuf = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md"); |
||||||
|
Material lightingMatGlow = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md"); |
||||||
|
|
||||||
|
lightingMatDefault.setName("TechDefault"); |
||||||
|
lightingMatDefault.selectTechnique("Default", renderManager); |
||||||
|
|
||||||
|
lightingPostShadow.setName("TechPostShad"); |
||||||
|
lightingPostShadow.selectTechnique("PostShadow", renderManager); |
||||||
|
|
||||||
|
lightingPreShadow.setName("TechPreShad"); |
||||||
|
lightingPreShadow.selectTechnique("PreShadow", renderManager); |
||||||
|
|
||||||
|
lightingMatPreNormalPass.setName("TechNorm"); |
||||||
|
lightingMatPreNormalPass.selectTechnique("PreNormalPass", renderManager); |
||||||
|
|
||||||
|
lightingMatGBuf.setName("TechGBuf"); |
||||||
|
lightingMatGBuf.selectTechnique("GBuf", renderManager); |
||||||
|
|
||||||
|
lightingMatGlow.setName("TechGlow"); |
||||||
|
lightingMatGlow.selectTechnique("Glow", renderManager); |
||||||
|
|
||||||
|
testSort(lightingMatGlow, lightingPreShadow, lightingMatPreNormalPass, |
||||||
|
lightingMatDefault, lightingPostShadow, lightingMatGBuf); |
||||||
|
} |
||||||
|
|
||||||
|
@Test(expected = AssertionError.class) |
||||||
|
public void testNoSortByParam() { |
||||||
|
Material sameMat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
||||||
|
Material sameMat2 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
||||||
|
|
||||||
|
sameMat1.setName("MatRed"); |
||||||
|
sameMat1.setColor("Color", ColorRGBA.Red); |
||||||
|
|
||||||
|
sameMat2.setName("MatBlue"); |
||||||
|
sameMat2.setColor("Color", ColorRGBA.Blue); |
||||||
|
|
||||||
|
testSort(sameMat1, sameMat2); |
||||||
|
} |
||||||
|
|
||||||
|
private Texture createTexture(String name) { |
||||||
|
ByteBuffer bb = BufferUtils.createByteBuffer(3); |
||||||
|
Image image = new Image(Format.RGB8, 1, 1, bb, ColorSpace.sRGB); |
||||||
|
Texture2D texture = new Texture2D(image); |
||||||
|
texture.setName(name); |
||||||
|
return texture; |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testSortByTexture() { |
||||||
|
Material texture1Mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
||||||
|
Material texture2Mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
||||||
|
Material texture3Mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
||||||
|
|
||||||
|
Texture tex1 = createTexture("A"); |
||||||
|
tex1.getImage().setId(1); |
||||||
|
|
||||||
|
Texture tex2 = createTexture("B"); |
||||||
|
tex2.getImage().setId(2); |
||||||
|
|
||||||
|
Texture tex3 = createTexture("C"); |
||||||
|
tex3.getImage().setId(3); |
||||||
|
|
||||||
|
texture1Mat.setName("TexA"); |
||||||
|
texture1Mat.setTexture("ColorMap", tex1); |
||||||
|
|
||||||
|
texture2Mat.setName("TexB"); |
||||||
|
texture2Mat.setTexture("ColorMap", tex2); |
||||||
|
|
||||||
|
texture3Mat.setName("TexC"); |
||||||
|
texture3Mat.setTexture("ColorMap", tex3); |
||||||
|
|
||||||
|
testSort(texture1Mat, texture2Mat, texture3Mat); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testSortByShaderDefines() { |
||||||
|
Material lightingMat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md"); |
||||||
|
Material lightingMatVColor = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md"); |
||||||
|
Material lightingMatVLight = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md"); |
||||||
|
Material lightingMatTC = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md"); |
||||||
|
Material lightingMatVColorLight = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md"); |
||||||
|
Material lightingMatTCVColorLight = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md"); |
||||||
|
|
||||||
|
lightingMat.setName("DefNone"); |
||||||
|
|
||||||
|
lightingMatVColor.setName("DefVC"); |
||||||
|
lightingMatVColor.setBoolean("UseVertexColor", true); |
||||||
|
|
||||||
|
lightingMatVLight.setName("DefVL"); |
||||||
|
lightingMatVLight.setBoolean("VertexLighting", true); |
||||||
|
|
||||||
|
lightingMatTC.setName("DefTC"); |
||||||
|
lightingMatTC.setBoolean("SeparateTexCoord", true); |
||||||
|
|
||||||
|
lightingMatVColorLight.setName("DefVCVL"); |
||||||
|
lightingMatVColorLight.setBoolean("UseVertexColor", true); |
||||||
|
lightingMatVColorLight.setBoolean("VertexLighting", true); |
||||||
|
|
||||||
|
lightingMatTCVColorLight.setName("DefVCVLTC"); |
||||||
|
lightingMatTCVColorLight.setBoolean("UseVertexColor", true); |
||||||
|
lightingMatTCVColorLight.setBoolean("VertexLighting", true); |
||||||
|
lightingMatTCVColorLight.setBoolean("SeparateTexCoord", true); |
||||||
|
|
||||||
|
testSort(lightingMat, lightingMatVColor, lightingMatVLight, |
||||||
|
lightingMatVColorLight, lightingMatTC, lightingMatTCVColorLight); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testSortByAll() { |
||||||
|
Material matBase1 = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md"); |
||||||
|
Material matBase2 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
||||||
|
|
||||||
|
Texture texBase = createTexture("BASE"); |
||||||
|
texBase.getImage().setId(1); |
||||||
|
Texture tex1 = createTexture("1"); |
||||||
|
tex1.getImage().setId(2); |
||||||
|
Texture tex2 = createTexture("2"); |
||||||
|
tex2.getImage().setId(3); |
||||||
|
|
||||||
|
matBase1.setName("BASE"); |
||||||
|
matBase1.selectTechnique("Default", renderManager); |
||||||
|
matBase1.setBoolean("UseVertexColor", true); |
||||||
|
matBase1.setTexture("DiffuseMap", texBase); |
||||||
|
|
||||||
|
Material mat1100 = matBase1.clone(); |
||||||
|
mat1100.setName("1100"); |
||||||
|
mat1100.selectTechnique("PreShadow", renderManager); |
||||||
|
|
||||||
|
Material mat1101 = matBase1.clone(); |
||||||
|
mat1101.setName("1101"); |
||||||
|
mat1101.selectTechnique("PreShadow", renderManager); |
||||||
|
mat1101.setTexture("DiffuseMap", tex1); |
||||||
|
|
||||||
|
Material mat1102 = matBase1.clone(); |
||||||
|
mat1102.setName("1102"); |
||||||
|
mat1102.selectTechnique("PreShadow", renderManager); |
||||||
|
mat1102.setTexture("DiffuseMap", tex2); |
||||||
|
|
||||||
|
Material mat1110 = matBase1.clone(); |
||||||
|
mat1110.setName("1110"); |
||||||
|
mat1110.selectTechnique("PreShadow", renderManager); |
||||||
|
mat1110.setFloat("AlphaDiscardThreshold", 2f); |
||||||
|
|
||||||
|
Material mat1120 = matBase1.clone(); |
||||||
|
mat1120.setName("1120"); |
||||||
|
mat1120.selectTechnique("PreShadow", renderManager); |
||||||
|
mat1120.setBoolean("UseInstancing", true); |
||||||
|
|
||||||
|
Material mat1121 = matBase1.clone(); |
||||||
|
mat1121.setName("1121"); |
||||||
|
mat1121.selectTechnique("PreShadow", renderManager); |
||||||
|
mat1121.setBoolean("UseInstancing", true); |
||||||
|
mat1121.setTexture("DiffuseMap", tex1); |
||||||
|
|
||||||
|
Material mat1122 = matBase1.clone(); |
||||||
|
mat1122.setName("1122"); |
||||||
|
mat1122.selectTechnique("PreShadow", renderManager); |
||||||
|
mat1122.setBoolean("UseInstancing", true); |
||||||
|
mat1122.setTexture("DiffuseMap", tex2); |
||||||
|
|
||||||
|
Material mat1140 = matBase1.clone(); |
||||||
|
mat1140.setName("1140"); |
||||||
|
mat1140.selectTechnique("PreShadow", renderManager); |
||||||
|
mat1140.setFloat("AlphaDiscardThreshold", 2f); |
||||||
|
mat1140.setBoolean("UseInstancing", true); |
||||||
|
|
||||||
|
Material mat1200 = matBase1.clone(); |
||||||
|
mat1200.setName("1200"); |
||||||
|
mat1200.selectTechnique("PostShadow", renderManager); |
||||||
|
|
||||||
|
Material mat1210 = matBase1.clone(); |
||||||
|
mat1210.setName("1210"); |
||||||
|
mat1210.selectTechnique("PostShadow", renderManager); |
||||||
|
mat1210.setFloat("AlphaDiscardThreshold", 2f); |
||||||
|
|
||||||
|
Material mat1220 = matBase1.clone(); |
||||||
|
mat1220.setName("1220"); |
||||||
|
mat1220.selectTechnique("PostShadow", renderManager); |
||||||
|
mat1220.setBoolean("UseInstancing", true); |
||||||
|
|
||||||
|
Material mat2000 = matBase2.clone(); |
||||||
|
mat2000.setName("2000"); |
||||||
|
|
||||||
|
testSort(mat1100, mat1101, mat1102, mat1110, |
||||||
|
mat1120, mat1121, mat1122, mat1140, |
||||||
|
mat1200, mat1210, mat1220, mat2000); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,143 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2015 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.shader; |
||||||
|
|
||||||
|
import com.jme3.math.FastMath; |
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.List; |
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
public class DefineListTest { |
||||||
|
|
||||||
|
private List<String> defineNames; |
||||||
|
private List<VarType> defineTypes; |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testHashCollision() { |
||||||
|
DefineList dl1 = new DefineList(64); |
||||||
|
DefineList dl2 = new DefineList(64); |
||||||
|
|
||||||
|
// Try to cause a hash collision
|
||||||
|
// (since bit #32 is aliased to bit #1 in 32-bit ints)
|
||||||
|
dl1.set(0, 123); |
||||||
|
dl1.set(32, 0); |
||||||
|
|
||||||
|
dl2.set(32, 0); |
||||||
|
dl2.set(0, 123); |
||||||
|
|
||||||
|
assert dl1.hashCode() == dl2.hashCode(); |
||||||
|
assert dl1.equals(dl2); |
||||||
|
} |
||||||
|
|
||||||
|
private String generateSource(DefineList dl) { |
||||||
|
StringBuilder sb = new StringBuilder(); |
||||||
|
dl.generateSource(sb, defineNames, defineTypes); |
||||||
|
return sb.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testInitial() { |
||||||
|
DefineList dl = new DefineList(3); |
||||||
|
defineNames = Arrays.asList("A", "B", "C"); |
||||||
|
defineTypes = Arrays.asList(VarType.Boolean, VarType.Int, VarType.Float); |
||||||
|
|
||||||
|
assert dl.hashCode() == 0; |
||||||
|
assert generateSource(dl).equals(""); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testBooleanDefine() { |
||||||
|
DefineList dl = new DefineList(1); |
||||||
|
defineNames = Arrays.asList("BOOL_VAR"); |
||||||
|
defineTypes = Arrays.asList(VarType.Boolean); |
||||||
|
|
||||||
|
dl.set(0, true); |
||||||
|
assert dl.hashCode() == 1; |
||||||
|
assert generateSource(dl).equals("#define BOOL_VAR 1\n"); |
||||||
|
|
||||||
|
dl.set(0, false); |
||||||
|
assert dl.hashCode() == 0; |
||||||
|
assert generateSource(dl).equals(""); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testFloatDefine() { |
||||||
|
DefineList dl = new DefineList(1); |
||||||
|
defineNames = Arrays.asList("FLOAT_VAR"); |
||||||
|
defineTypes = Arrays.asList(VarType.Float); |
||||||
|
|
||||||
|
dl.set(0, 1f); |
||||||
|
assert dl.hashCode() == 1; |
||||||
|
assert generateSource(dl).equals("#define FLOAT_VAR 1.0\n"); |
||||||
|
|
||||||
|
dl.set(0, 0f); |
||||||
|
assert dl.hashCode() == 0; |
||||||
|
assert generateSource(dl).equals(""); |
||||||
|
|
||||||
|
dl.set(0, -1f); |
||||||
|
assert generateSource(dl).equals("#define FLOAT_VAR -1.0\n"); |
||||||
|
|
||||||
|
dl.set(0, FastMath.FLT_EPSILON); |
||||||
|
assert generateSource(dl).equals("#define FLOAT_VAR 1.1920929E-7\n"); |
||||||
|
|
||||||
|
dl.set(0, FastMath.PI); |
||||||
|
assert generateSource(dl).equals("#define FLOAT_VAR 3.1415927\n"); |
||||||
|
|
||||||
|
try { |
||||||
|
dl.set(0, Float.NaN); |
||||||
|
generateSource(dl); |
||||||
|
assert false; |
||||||
|
} catch (IllegalArgumentException ex) { } |
||||||
|
|
||||||
|
try { |
||||||
|
dl.set(0, Float.POSITIVE_INFINITY); |
||||||
|
generateSource(dl); |
||||||
|
assert false; |
||||||
|
} catch (IllegalArgumentException ex) { } |
||||||
|
|
||||||
|
try { |
||||||
|
dl.set(0, Float.NEGATIVE_INFINITY); |
||||||
|
generateSource(dl); |
||||||
|
assert false; |
||||||
|
} catch (IllegalArgumentException ex) { } |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testSourceGeneration() { |
||||||
|
DefineList dl = new DefineList(64); |
||||||
|
defineNames = Arrays.asList("BOOL_VAR", "INT_VAR", "FLOAT_VAR"); |
||||||
|
defineTypes = Arrays.asList(VarType.Boolean, VarType.Int, VarType.Float); |
||||||
|
dl.set(0, true); |
||||||
|
dl.set(1, -1); |
||||||
|
dl.set(2, Float.NaN); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,78 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2015 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.system; |
||||||
|
|
||||||
|
import com.jme3.audio.AudioRenderer; |
||||||
|
import java.io.IOException; |
||||||
|
import java.io.OutputStream; |
||||||
|
import java.net.URL; |
||||||
|
import java.nio.ByteBuffer; |
||||||
|
|
||||||
|
public class MockJmeSystemDelegate extends JmeSystemDelegate { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void writeImageFile(OutputStream outStream, String format, ByteBuffer imageData, int width, int height) throws IOException { |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void showErrorDialog(String message) { |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean showSettingsDialog(AppSettings sourceSettings, boolean loadFromRegistry) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public URL getPlatformAssetConfigURL() { |
||||||
|
return Thread.currentThread().getContextClassLoader().getResource("com/jme3/asset/General.cfg"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public JmeContext newContext(AppSettings settings, JmeContext.Type contextType) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public AudioRenderer newAudioRenderer(AppSettings settings) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void initialize(AppSettings settings) { |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void showSoftKeyboard(boolean show) { |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,55 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2015 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.system; |
||||||
|
|
||||||
|
import com.jme3.asset.AssetConfig; |
||||||
|
import com.jme3.asset.AssetManager; |
||||||
|
import com.jme3.asset.DesktopAssetManager; |
||||||
|
import com.jme3.renderer.RenderManager; |
||||||
|
import java.util.logging.Level; |
||||||
|
import java.util.logging.Logger; |
||||||
|
|
||||||
|
public class TestUtil { |
||||||
|
|
||||||
|
static { |
||||||
|
JmeSystem.setSystemDelegate(new MockJmeSystemDelegate()); |
||||||
|
} |
||||||
|
|
||||||
|
public static AssetManager createAssetManager() { |
||||||
|
Logger.getLogger(AssetConfig.class.getName()).setLevel(Level.OFF); |
||||||
|
return new DesktopAssetManager(true); |
||||||
|
} |
||||||
|
|
||||||
|
public static RenderManager createRenderManager() { |
||||||
|
return new RenderManager(new NullRenderer()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,50 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2015 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
|
||||||
|
import com.jme3.system.NativeLibraryLoader; |
||||||
|
import java.io.File; |
||||||
|
import java.util.Arrays; |
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* @author Kirill Vainer |
||||||
|
*/ |
||||||
|
public class LibraryLoaderTest { |
||||||
|
|
||||||
|
@Test |
||||||
|
public void whatever() { |
||||||
|
File[] nativeJars = NativeLibraryLoader.getJarsWithNatives(); |
||||||
|
System.out.println(Arrays.toString(nativeJars)); |
||||||
|
} |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue