Upgrade scene to have light manager

This commit is contained in:
Retera 2020-09-27 02:58:04 -04:00
parent 59d350dd9e
commit b0b0745af9
5 changed files with 91 additions and 4 deletions

View File

@ -317,4 +317,8 @@ public abstract class Scene {
return -Float.compare(o2.depth, o1.depth);
}
}
public SceneLightManager getLightManager() {
return this.lightManager;
}
}

View File

@ -12,6 +12,7 @@ import com.etheller.warsmash.viewer5.Texture;
import com.etheller.warsmash.viewer5.gl.DataTexture;
import com.etheller.warsmash.viewer5.gl.WebGL;
import com.etheller.warsmash.viewer5.handlers.w3x.DynamicShadowManager;
import com.etheller.warsmash.viewer5.handlers.w3x.W3xSceneLightManager;
public class BatchGroup extends GenericGroup {
@ -36,6 +37,7 @@ public class BatchGroup extends GenericGroup {
final WebGL webGL = viewer.webGL;
final boolean isExtended = this.isExtended;
final ShaderProgram shader;
final W3xSceneLightManager lightManager = (W3xSceneLightManager) scene.getLightManager();
if (isExtended) {
if (DynamicShadowManager.IS_SHADOW_MAPPING) {
@ -59,6 +61,11 @@ public class BatchGroup extends GenericGroup {
shader.setUniformMatrix("u_mvp", mvp);
final DataTexture boneTexture = instance.boneTexture;
final DataTexture unitLightsTexture = lightManager.getUnitLightsTexture();
unitLightsTexture.bind(16);
shader.setUniformi("u_lightTexture", 16);
shader.setUniformf("u_lightCount", unitLightsTexture.getHeight());
// Instances of models with no bones don't have a bone texture.
if (boneTexture != null) {

View File

@ -13,14 +13,18 @@ public class LightInstance implements UpdatableObject, SceneLightInstance {
protected final Light light;
private boolean visible;
private boolean loadedInScene;
private final MdxComplexInstance instance;
public LightInstance(final MdxComplexInstance instance, final Light light) {
this.instance = instance;
this.node = instance.nodes[light.index];
this.light = light;
}
public void bind(final int offset, final FloatBuffer floatBuffer, final int sequence, final int frame,
final int counter) {
public void bind(final int offset, final FloatBuffer floatBuffer) {
final int sequence = this.instance.sequence;
final int frame = this.instance.frame;
final int counter = this.instance.counter;
this.light.getAttenuationStart(scalarHeap, sequence, frame, counter);
final float attenuationStart = scalarHeap[0];
this.light.getAttenuationEnd(scalarHeap, sequence, frame, counter);

View File

@ -1,5 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.List;
@ -10,13 +13,19 @@ import com.etheller.warsmash.viewer5.handlers.mdx.LightInstance;
public class W3xSceneLightManager implements SceneLightManager {
public final List<LightInstance> lights;
private FloatBuffer lightDataCopyHeap;
private final DataTexture unitLightsTexture;
private final DataTexture terrainLightsTexture;
private final War3MapViewer viewer;
private int terrainLightCount;
private int unitLightCount;
public W3xSceneLightManager(final War3MapViewer viewer) {
this.viewer = viewer;
this.lights = new ArrayList<>();
this.unitLightsTexture = new DataTexture(viewer.gl, 4, 4, 1);
this.terrainLightsTexture = new DataTexture(viewer.gl, 4, 4, 1);
this.lightDataCopyHeap = ByteBuffer.allocateDirect(16 * 1 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
}
@Override
@ -24,6 +33,7 @@ public class W3xSceneLightManager implements SceneLightManager {
// TODO redesign to avoid cast
final LightInstance mdxLight = (LightInstance) lightInstance;
this.lights.add(mdxLight);
rebind();
}
@Override
@ -31,5 +41,67 @@ public class W3xSceneLightManager implements SceneLightManager {
// TODO redesign to avoid cast
final LightInstance mdxLight = (LightInstance) lightInstance;
this.lights.remove(mdxLight);
rebind();
}
private void rebind() {
final int numberOfLights = this.lights.size() + 1;
final int bytesNeeded = numberOfLights * 4 * 16;
if (bytesNeeded > (this.lightDataCopyHeap.capacity() * 4)) {
this.lightDataCopyHeap = ByteBuffer.allocateDirect(bytesNeeded).order(ByteOrder.nativeOrder())
.asFloatBuffer();
}
this.unitLightCount = 0;
this.lightDataCopyHeap.clear();
int offset = 0;
if (this.viewer.dncUnit != null) {
if (!this.viewer.dncUnit.lights.isEmpty()) {
this.viewer.dncUnit.lights.get(0).bind(0, this.lightDataCopyHeap);
offset += 16;
this.unitLightCount++;
}
}
for (final LightInstance light : this.lights) {
light.bind(offset, this.lightDataCopyHeap);
offset += 16;
this.unitLightCount++;
}
this.lightDataCopyHeap.flip();
this.unitLightsTexture.bindAndUpdate(this.lightDataCopyHeap, 16, this.unitLightCount);
this.terrainLightCount = 0;
this.lightDataCopyHeap.clear();
offset = 0;
if (this.viewer.dncTerrain != null) {
if (!this.viewer.dncTerrain.lights.isEmpty()) {
this.viewer.dncTerrain.lights.get(0).bind(0, this.lightDataCopyHeap);
offset += 16;
this.terrainLightCount++;
}
}
for (final LightInstance light : this.lights) {
light.bind(offset, this.lightDataCopyHeap);
offset += 16;
this.terrainLightCount++;
}
this.lightDataCopyHeap.flip();
this.terrainLightsTexture.bindAndUpdate(this.lightDataCopyHeap, 16, this.terrainLightCount);
}
public DataTexture getUnitLightsTexture() {
return this.unitLightsTexture;
}
public int getUnitLightCount() {
return this.unitLightCount;
}
public DataTexture getTerrainLightsTexture() {
return this.terrainLightsTexture;
}
public int getTerrainLightCount() {
return this.terrainLightCount;
}
}

View File

@ -156,8 +156,8 @@ public class War3MapViewer extends ModelViewer {
public DataTable miscData;
private DataTable unitGlobalStrings;
private MdxComplexInstance confirmationInstance;
private MdxComplexInstance dncUnit;
private MdxComplexInstance dncTerrain;
public MdxComplexInstance dncUnit;
public MdxComplexInstance dncTerrain;
public CSimulation simulation;
private float updateTime;