use of com.jme3.light.LightProbe in project jmonkeyengine by jMonkeyEngine.
the class SinglePassAndImageBasedLightingLogic method updateLightListUniforms.
/**
* 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, int lastTexUnit) {
if (numLights == 0) {
// this shader does not do lighting, ignore.
return 0;
}
Uniform lightData = shader.getUniform("g_LightData");
//8 lights * max 3
lightData.setVector4Length(numLights * 3);
Uniform ambientColor = shader.getUniform("g_AmbientLightColor");
Uniform lightProbeData = shader.getUniform("g_LightProbeData");
lightProbeData.setVector4Length(1);
Uniform lightProbeIrrMap = shader.getUniform("g_IrradianceMap");
Uniform lightProbePemMap = shader.getUniform("g_PrefEnvMap");
lightProbe = null;
if (startIndex != 0) {
// apply additive blending for 2nd and future passes
rm.getRenderer().applyRenderState(ADDITIVE_LIGHT);
ambientColor.setValue(VarType.Vector4, ColorRGBA.Black);
} else {
lightProbe = extractIndirectLights(lightList, true);
ambientColor.setValue(VarType.Vector4, ambientLightColor);
}
//If there is a lightProbe in the list we force it's render on the first pass
if (lightProbe != null) {
BoundingSphere s = (BoundingSphere) lightProbe.getBounds();
lightProbeData.setVector4InArray(lightProbe.getPosition().x, lightProbe.getPosition().y, lightProbe.getPosition().z, 1f / s.getRadius(), 0);
//assigning new texture indexes
int irrUnit = lastTexUnit++;
int pemUnit = lastTexUnit++;
rm.getRenderer().setTexture(irrUnit, lightProbe.getIrradianceMap());
lightProbeIrrMap.setValue(VarType.Int, irrUnit);
rm.getRenderer().setTexture(pemUnit, lightProbe.getPrefilteredEnvMap());
lightProbePemMap.setValue(VarType.Int, pemUnit);
} else {
//Disable IBL for this pass
lightProbeData.setVector4InArray(0, 0, 0, -1, 0);
}
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();
if (l.getType() != Light.Type.Probe) {
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);
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);
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);
lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), invRange, lightDataIndex);
lightDataIndex++;
tmpVec.set(dir2.getX(), dir2.getY(), dir2.getZ(), 0.0f);
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;
}
use of com.jme3.light.LightProbe in project jmonkeyengine by jMonkeyEngine.
the class LightsDebugState method cleanProbes.
private void cleanProbes() {
if (probes.size() != probeMapping.size()) {
for (LightProbe probe : probeMapping.keySet()) {
if (!probes.contains(probe)) {
garbage.add(probe);
}
}
for (LightProbe probe : garbage) {
probeMapping.remove(probe);
}
garbage.clear();
probes.clear();
}
}
use of com.jme3.light.LightProbe in project jmonkeyengine by jMonkeyEngine.
the class LightProbeFactory method makeProbe.
/**
* Creates a LightProbe with the giver EnvironmentCamera in the given scene.
*
* Note that this is an assynchronous process that will run on multiple threads.
* The process is thread safe.
* The created lightProbe will only be marked as ready when the rendering process is done.
*
* The JobProgressListener will be notified of the progress of the generation.
* Note that you can also use a {@link JobProgressAdapter}.
*
* @see LightProbe
* @see EnvironmentCamera
* @see JobProgressListener
* @param envCam the EnvironmentCamera
* @param scene the Scene
* @param listener the listener of the genration progress.
* @return the created LightProbe
*/
public static LightProbe makeProbe(final EnvironmentCamera envCam, Spatial scene, final JobProgressListener<LightProbe> listener) {
final LightProbe probe = new LightProbe();
probe.setPosition(envCam.getPosition());
probe.setIrradianceMap(EnvMapUtils.createIrradianceMap(envCam.getSize(), envCam.getImageFormat()));
probe.setPrefilteredMap(EnvMapUtils.createPrefilteredEnvMap(envCam.getSize(), envCam.getImageFormat()));
envCam.snapshot(scene, new JobProgressAdapter<TextureCubeMap>() {
@Override
public void done(TextureCubeMap map) {
generatePbrMaps(map, probe, envCam.getApplication(), listener);
}
});
return probe;
}
use of com.jme3.light.LightProbe in project jmonkeyengine by jMonkeyEngine.
the class LightProbeFactory method generatePbrMaps.
/**
* Internally called to generate the maps.
* This method will spawn 7 thread (one for the IrradianceMap, and one for each face of the prefiltered env map).
* Those threads will be executed in a ScheduledThreadPoolExecutor that will be shutdown when the genration is done.
*
* @param envMap the raw env map rendered by the env camera
* @param probe the LigthProbe to generate maps for
* @param app the Application
* @param listener a progress listener. (can be null if no progress reporting is needed)
*/
private static void generatePbrMaps(TextureCubeMap envMap, final LightProbe probe, Application app, final JobProgressListener<LightProbe> listener) {
IrradianceMapGenerator irrMapGenerator;
PrefilteredEnvMapFaceGenerator[] pemGenerators = new PrefilteredEnvMapFaceGenerator[6];
final JobState jobState = new JobState(new ScheduledThreadPoolExecutor(7));
irrMapGenerator = new IrradianceMapGenerator(app, new JobListener(listener, jobState, probe, 6));
int size = envMap.getImage().getWidth();
irrMapGenerator.setGenerationParam(EnvMapUtils.duplicateCubeMap(envMap), size, EnvMapUtils.FixSeamsMethod.Wrap, probe.getIrradianceMap());
jobState.executor.execute(irrMapGenerator);
for (int i = 0; i < pemGenerators.length; i++) {
pemGenerators[i] = new PrefilteredEnvMapFaceGenerator(app, i, new JobListener(listener, jobState, probe, i));
pemGenerators[i].setGenerationParam(EnvMapUtils.duplicateCubeMap(envMap), size, EnvMapUtils.FixSeamsMethod.Wrap, probe.getPrefilteredEnvMap());
jobState.executor.execute(pemGenerators[i]);
}
}
use of com.jme3.light.LightProbe in project jmonkeyengine by jMonkeyEngine.
the class LightProbeBlendingProcessor method computeBlendFactors.
private float computeBlendFactors(List<BlendFactor> blendFactors) {
float sumBlendFactors = 0;
for (Spatial scene : viewPort.getScenes()) {
for (Light light : scene.getWorldLightList()) {
if (light.getType() == Light.Type.Probe) {
LightProbe p = (LightProbe) light;
TempVars vars = TempVars.get();
boolean intersect = p.intersectsFrustum(viewPort.getCamera(), vars);
vars.release();
//check if the probe is inside the camera frustum
if (intersect) {
//is the poi inside the bounds of this probe
if (poi.getWorldBound().intersects(p.getBounds())) {
//computing the distance as we need it to check if th epoi in in the inner radius and later to compute the weight
float outerRadius = ((BoundingSphere) p.getBounds()).getRadius();
float innerRadius = outerRadius * 0.5f;
float distance = p.getBounds().getCenter().distance(poi.getWorldTranslation());
// if the poi in inside the inner range of this probe, then this probe is the only one that matters.
if (distance < innerRadius) {
blendFactors.clear();
blendFactors.add(new BlendFactor(p, 1.0f));
return 1.0f;
}
//else we need to compute the weight of this probe and collect it for blending
float ndf = (distance - innerRadius) / (outerRadius - innerRadius);
sumBlendFactors += ndf;
blendFactors.add(new BlendFactor(p, ndf));
}
}
}
}
}
return sumBlendFactors;
}
Aggregations