Opens the Renderer's API, switch to using guava's Graph facilities.

develop
manu3d 2018-04-14 14:49:00 +02:00 committed by GitHub
commit 7c7edd128d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 476 additions and 278 deletions

View File

@ -16,6 +16,8 @@
package org.terasology.rendering.dag;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.util.Set;
import org.junit.Test;
import org.terasology.engine.SimpleUri;
@ -30,25 +32,22 @@ public class RenderTaskListGeneratorTest {
RenderTaskListGenerator renderTaskListGenerator = new RenderTaskListGenerator();
List<Node> orderedNodes = Lists.newArrayList();
Node alphaNode = new AlphaNode();
alphaNode.setUri(new SimpleUri("engine:alphaNode"));
Node alphaNode = new AlphaNode("alphaNode");
orderedNodes.add(alphaNode);
Node bravoNode = new BravoNode();
bravoNode.setUri(new SimpleUri("engine:bravoNode"));
Node bravoNode = new BravoNode("bravoNode");
orderedNodes.add(bravoNode);
Node charlieNode = new CharlieNode();
charlieNode.setUri(new SimpleUri("engine:charlieNode"));
Node charlieNode = new CharlieNode("charlieNode");
orderedNodes.add(charlieNode);
List<RenderPipelineTask> taskList = renderTaskListGenerator.generateFrom(orderedNodes);
assertEquals("----- engine:alphaNode (AlphaNode)", taskList.get(0).toString().trim()); // Strictly speaking we don't need
assertEquals("----- test:alphaNode (AlphaNode)", taskList.get(0).toString().trim()); // Strictly speaking we don't need
assertEquals("SetName: foo", taskList.get(1).toString().trim()); // trimming MarkerTask.toString(),
assertEquals("engine:alphaNode (AlphaNode)", taskList.get(2).toString().trim()); // resulting in "----- <NodeName>"
assertEquals("----- engine:bravoNode (BravoNode)", taskList.get(3).toString().trim()); // We just do it to avoid attracting
assertEquals("engine:bravoNode (BravoNode)", taskList.get(4).toString().trim()); // too much attention to it.
assertEquals("----- engine:charlieNode (CharlieNode)", taskList.get(5).toString().trim());
assertEquals("engine:charlieNode (CharlieNode)", taskList.get(6).toString().trim());
assertEquals("test:alphaNode (AlphaNode)", taskList.get(2).toString().trim()); // resulting in "----- <NodeName>"
assertEquals("----- test:bravoNode (BravoNode)", taskList.get(3).toString().trim()); // We just do it to avoid attracting
assertEquals("test:bravoNode (BravoNode)", taskList.get(4).toString().trim()); // too much attention to it.
assertEquals("----- test:charlieNode (CharlieNode)", taskList.get(5).toString().trim());
assertEquals("test:charlieNode (CharlieNode)", taskList.get(6).toString().trim());
assertEquals("SetName: bar", taskList.get(7).toString().trim());
}
@ -56,31 +55,27 @@ public class RenderTaskListGeneratorTest {
public void testReducePersistingStateChanges() {
RenderTaskListGenerator renderTaskListGenerator = new RenderTaskListGenerator();
List<Node> orderedNodes = Lists.newArrayList();
Node alphaNode = new AlphaNode();
alphaNode.setUri(new SimpleUri("engine:alphaNode"));
Node alphaNode = new AlphaNode("alphaNode");
orderedNodes.add(alphaNode);
Node bravoNode = new BravoNode();
bravoNode.setUri(new SimpleUri("engine:bravoNode"));
Node bravoNode = new BravoNode("bravoNode");
orderedNodes.add(bravoNode);
Node charlieNode = new CharlieNode();
charlieNode.setUri(new SimpleUri("engine:charlieNode"));
Node charlieNode = new CharlieNode("charlieNode");
orderedNodes.add(charlieNode);
Node deltaNode = new DeltaNode();
deltaNode.setUri(new SimpleUri("engine:deltaNode"));
Node deltaNode = new DeltaNode("deltaNode");
orderedNodes.add(deltaNode);
List<RenderPipelineTask> taskList = renderTaskListGenerator.generateFrom(orderedNodes);
assertEquals("----- engine:alphaNode (AlphaNode)", taskList.get(0).toString().trim());
assertEquals("----- test:alphaNode (AlphaNode)", taskList.get(0).toString().trim());
assertEquals("SetName: foo", taskList.get(1).toString().trim());
assertEquals("engine:alphaNode (AlphaNode)", taskList.get(2).toString().trim());
assertEquals("----- engine:bravoNode (BravoNode)", taskList.get(3).toString().trim());
assertEquals("engine:bravoNode (BravoNode)", taskList.get(4).toString().trim());
assertEquals("----- engine:charlieNode (CharlieNode)", taskList.get(5).toString().trim());
assertEquals("engine:charlieNode (CharlieNode)", taskList.get(6).toString().trim());
assertEquals("----- engine:deltaNode (DeltaNode)", taskList.get(7).toString().trim());
assertEquals("SetName: delta", taskList.get(8).toString().trim());
assertEquals("engine:deltaNode (DeltaNode)", taskList.get(9).toString().trim());
assertEquals("test:alphaNode (AlphaNode)", taskList.get(2).toString().trim());
assertEquals("----- test:bravoNode (BravoNode)", taskList.get(3).toString().trim());
assertEquals("test:bravoNode (BravoNode)", taskList.get(4).toString().trim());
assertEquals("----- test:charlieNode (CharlieNode)", taskList.get(5).toString().trim());
assertEquals("test:charlieNode (CharlieNode)", taskList.get(6).toString().trim());
assertEquals("----- test:deltaNode (DeltaNode)", taskList.get(7).toString().trim());
assertEquals("SetName: bar", taskList.get(8).toString().trim());
assertEquals("test:deltaNode (DeltaNode)", taskList.get(9).toString().trim());
assertEquals("SetName: bar", taskList.get(10).toString().trim());
}
@ -88,44 +83,85 @@ public class RenderTaskListGeneratorTest {
public void testReducePersistingStateChangesEcho() {
RenderTaskListGenerator renderTaskListGenerator = new RenderTaskListGenerator();
List<Node> orderedNodes = Lists.newArrayList();
Node alphaNode = new AlphaNode();
alphaNode.setUri(new SimpleUri("engine:alphaNode"));
Node alphaNode = new AlphaNode("alphaNode");
orderedNodes.add(alphaNode);
Node bravoNode = new BravoNode();
bravoNode.setUri(new SimpleUri("engine:bravoNode"));
Node bravoNode = new BravoNode("bravoNode");
orderedNodes.add(bravoNode);
Node echoNode = new EchoNode();
echoNode.setUri(new SimpleUri("engine:echoNode"));
Node echoNode = new EchoNode("echoNode");
orderedNodes.add(echoNode);
Node charlieNode = new CharlieNode();
charlieNode.setUri(new SimpleUri("engine:charlieNode"));
Node charlieNode = new CharlieNode("charlieNode");
orderedNodes.add(charlieNode);
Node deltaNode = new DeltaNode();
deltaNode.setUri(new SimpleUri("engine:deltaNode"));
Node deltaNode = new DeltaNode("deltaNode");
orderedNodes.add(deltaNode);
List<RenderPipelineTask> taskList = renderTaskListGenerator.generateFrom(orderedNodes);
assertEquals("----- engine:alphaNode (AlphaNode)", taskList.get(0).toString().trim());
assertEquals("----- test:alphaNode (AlphaNode)", taskList.get(0).toString().trim());
assertEquals("SetName: foo", taskList.get(1).toString().trim());
assertEquals("engine:alphaNode (AlphaNode)", taskList.get(2).toString().trim());
assertEquals("----- engine:bravoNode (BravoNode)", taskList.get(3).toString().trim());
assertEquals("engine:bravoNode (BravoNode)", taskList.get(4).toString().trim());
assertEquals("----- engine:echoNode (EchoNode)", taskList.get(5).toString().trim());
assertEquals("test:alphaNode (AlphaNode)", taskList.get(2).toString().trim());
assertEquals("----- test:bravoNode (BravoNode)", taskList.get(3).toString().trim());
assertEquals("test:bravoNode (BravoNode)", taskList.get(4).toString().trim());
assertEquals("----- test:echoNode (EchoNode)", taskList.get(5).toString().trim());
assertEquals("SetName: bar", taskList.get(6).toString().trim());
assertEquals("engine:echoNode (EchoNode)", taskList.get(7).toString().trim());
assertEquals("----- engine:charlieNode (CharlieNode)", taskList.get(8).toString().trim());
assertEquals("test:echoNode (EchoNode)", taskList.get(7).toString().trim());
assertEquals("----- test:charlieNode (CharlieNode)", taskList.get(8).toString().trim());
assertEquals("SetName: foo", taskList.get(9).toString().trim());
assertEquals("engine:charlieNode (CharlieNode)", taskList.get(10).toString().trim());
assertEquals("----- engine:deltaNode (DeltaNode)", taskList.get(11).toString().trim());
assertEquals("SetName: delta", taskList.get(12).toString().trim());
assertEquals("engine:deltaNode (DeltaNode)", taskList.get(13).toString().trim());
assertEquals("test:charlieNode (CharlieNode)", taskList.get(10).toString().trim());
assertEquals("----- test:deltaNode (DeltaNode)", taskList.get(11).toString().trim());
assertEquals("SetName: bar", taskList.get(12).toString().trim());
assertEquals("test:deltaNode (DeltaNode)", taskList.get(13).toString().trim());
assertEquals("SetName: bar", taskList.get(14).toString().trim());
}
@SuppressWarnings("static-access") // actual node classes are not meant to be static
private class AlphaNode extends AbstractNode {
AlphaNode() {
private abstract class DummyNode implements Node {
private SimpleUri nodeUri;
private Set<StateChange> desiredStateChanges = Sets.newLinkedHashSet();
private boolean enabled;
DummyNode(String nodeUri) {
this.nodeUri = new SimpleUri("test:" + nodeUri);
enabled = true;
}
@Override
public SimpleUri getUri() {
return nodeUri;
}
void addDesiredStateChange(StateChange stateChange) {
desiredStateChanges.add(stateChange);
}
@Override
public Set<StateChange> getDesiredStateChanges() {
return desiredStateChanges;
}
@Override
public boolean isEnabled() {
return enabled;
}
@Override
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Override
public void handleCommand(String command, String... arguments) { }
@Override
public void dispose() { }
@Override
public String toString() {
return String.format("%s (%s)", getUri(), this.getClass().getSimpleName());
}
}
private class AlphaNode extends DummyNode {
AlphaNode(String nodeUri) {
super(nodeUri);
addDesiredStateChange(new SetName("foo"));
}
@ -133,9 +169,9 @@ public class RenderTaskListGeneratorTest {
public void process() { }
}
@SuppressWarnings("static-access") // actual node classes are not meant to be static
private class BravoNode extends AbstractNode {
BravoNode() {
private class BravoNode extends DummyNode {
BravoNode(String nodeUri) {
super(nodeUri);
addDesiredStateChange(new SetName("foo"));
}
@ -143,9 +179,9 @@ public class RenderTaskListGeneratorTest {
public void process() { }
}
@SuppressWarnings("static-access") // actual node classes are not meant to be static
private class CharlieNode extends AbstractNode {
CharlieNode() {
private class CharlieNode extends DummyNode {
CharlieNode(String nodeUri) {
super(nodeUri);
addDesiredStateChange(new SetName("foo"));
}
@ -153,19 +189,20 @@ public class RenderTaskListGeneratorTest {
public void process() { }
}
@SuppressWarnings("static-access") // actual node classes are not meant to be static
private class DeltaNode extends AbstractNode {
DeltaNode() {
addDesiredStateChange(new SetName("delta"));
private class DeltaNode extends DummyNode {
DeltaNode(String nodeUri) {
super(nodeUri);
addDesiredStateChange(new SetName("bar"));
}
@Override
public void process() { }
}
@SuppressWarnings("static-access") // actual node classes are not meant to be static
private class EchoNode extends AbstractNode {
EchoNode() { }
private class EchoNode extends DummyNode {
EchoNode(String nodeUri) {
super(nodeUri);
}
@Override
public void process() { }

View File

@ -92,7 +92,7 @@ dependencies {
// Storage and networking
compile group: 'com.google.guava', name: 'guava', version: '19.0'
compile group: 'com.google.guava', name: 'guava', version: '23.0'
compile group: 'com.google.code.gson', name: 'gson', version: '2.6.2'
compile group: 'com.google.protobuf', name: 'protobuf-java', version: '2.6.1'
compile group: 'net.sf.trove4j', name: 'trove4j', version: '3.0.3'
@ -127,7 +127,7 @@ dependencies {
// Small-time 3rd party libs we've stored in our Artifactory for access
compile group: 'ec.util', name: 'MersenneTwister', version: '20'
compile group: 'org.eaxy', name: 'eaxy', version: '0.1'
// telemetry
compile (group: 'com.snowplowanalytics', name: 'snowplow-java-tracker', version :'0.8.0'){
exclude group:'org.slf4j',module:'slf4j-simple'
@ -185,7 +185,7 @@ task cacheReflections {
description = 'Caches reflection output to make regular startup faster. May go stale and need cleanup at times.'
inputs.files project.classes.outputs.files
dependsOn classes
doLast {
// Without the .mkdirs() we might hit a scenario where the classes dir doesn't exist yet
file(sourceSets.main.output.classesDir.toString()).mkdirs()
@ -194,7 +194,7 @@ task cacheReflections {
.setScanners(new TypeAnnotationsScanner(), new SubTypesScanner()))
reflections.save(sourceSets.main.output.classesDir.toString() + "/reflections.cache")
}
}
task cleanReflections(type: Delete) {

View File

@ -79,6 +79,10 @@ public final class ExternalApiWhitelist {
.add("sun.reflect")
.add("com.snowplowanalytics.snowplow.tracker.events")
.add("com.snowplowanalytics.snowplow.tracker.payload")
.add("org.lwjgl.opengl")
.add("org.lwjgl.opengl.GL11")
.add("org.lwjgl.opengl.GL12")
.add("org.lwjgl.opengl.GL13")
.build();
public static final Set<Class<?>> CLASSES = new ImmutableSet.Builder<Class<?>>()

View File

@ -26,6 +26,7 @@ import org.terasology.monitoring.PerformanceMonitor;
import org.terasology.rendering.assets.material.Material;
import org.terasology.rendering.cameras.Camera;
import org.terasology.rendering.cameras.SubmersibleCamera;
import org.terasology.rendering.dag.RenderGraph;
import org.terasology.rendering.world.viewDistance.ViewDistance;
import org.terasology.rendering.world.WorldRenderer;
import org.terasology.world.WorldProvider;
@ -192,6 +193,11 @@ public class HeadlessWorldRenderer implements WorldRenderer {
return "";
}
@Override
public RenderGraph getRenderGraph() {
return null;
}
/**
* Updates the list of chunks around the player.
*

View File

@ -20,7 +20,12 @@ import com.google.common.collect.Sets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.terasology.assets.ResourceUrn;
import org.terasology.context.Context;
import org.terasology.engine.SimpleUri;
import org.terasology.engine.module.ModuleManager;
import org.terasology.module.sandbox.API;
import org.terasology.naming.Name;
import org.terasology.registry.CoreRegistry;
import org.terasology.rendering.assets.material.Material;
import org.terasology.rendering.opengl.BaseFBOsManager;
import org.terasology.rendering.opengl.FBO;
@ -39,7 +44,14 @@ public abstract class AbstractNode implements Node {
private Set<StateChange> desiredStateChanges = Sets.newLinkedHashSet();
private Map<SimpleUri, BaseFBOsManager> fboUsages = Maps.newHashMap();
protected boolean enabled = true;
private SimpleUri nodeUri = null;
private final SimpleUri nodeUri;
protected AbstractNode(String nodeUri, Context context) {
ModuleManager moduleManager = context.get(ModuleManager.class);
Name providingModule = moduleManager.getEnvironment().getModuleProviding(this.getClass());
this.nodeUri = new SimpleUri(providingModule.toString() + ":" + nodeUri);
}
protected FBO requiresFBO(FBOConfig fboConfig, BaseFBOsManager fboManager) {
SimpleUri fboName = fboConfig.getName();
@ -99,15 +111,6 @@ public abstract class AbstractNode implements Node {
@Override
public void handleCommand(String command, String... arguments) { }
@Override
public void setUri(SimpleUri nodeUri) {
if (this.nodeUri == null) {
this.nodeUri = nodeUri;
} else {
throw new RuntimeException("Cannot set a Node's URI more than once!");
}
}
@Override
public SimpleUri getUri() {
return nodeUri;

View File

@ -32,7 +32,9 @@ public abstract class ConditionDependentNode extends AbstractNode implements Pro
protected WorldRenderer worldRenderer;
protected ConditionDependentNode(Context context) {
protected ConditionDependentNode(String nodeUri, Context context) {
super(nodeUri, context);
worldRenderer = context.get(WorldRenderer.class);
}

View File

@ -17,9 +17,8 @@ package org.terasology.rendering.dag;
//TODO: consider removing the word "Node" from the name of all Node implementations now that they are in the dag.nodes package.
import org.terasology.engine.SimpleUri;
import java.util.Set;
import org.terasology.engine.SimpleUri;
/**
* TODO: Add javadocs
@ -36,7 +35,5 @@ public interface Node extends RenderPipelineTask {
void handleCommand(String command, String... arguments);
void setUri(SimpleUri nodeUri);
SimpleUri getUri();
}

View File

@ -16,58 +16,56 @@
package org.terasology.rendering.dag;
import com.google.common.base.Preconditions;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.graph.GraphBuilder;
import com.google.common.graph.MutableGraph;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.terasology.engine.SimpleUri;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
/**
* TODO: Add javadocs
*/
public class RenderGraph {
private static final Logger logger = LoggerFactory.getLogger(RenderGraph.class);
private Map<SimpleUri, Node> nodeMap = Maps.newHashMap();
// TODO: Convert to biMap
private Multimap<Node, Node> edgeMap = HashMultimap.create();
private Multimap<Node, Node> reverseEdgeMap = HashMultimap.create();
private Map<SimpleUri, Node> nodeMap;
private MutableGraph<Node> graph;
public SimpleUri addNode(Node node, String suggestedUri) {
public RenderGraph() {
nodeMap = Maps.newHashMap();
graph = GraphBuilder.directed().build();
}
public void addNode(Node node) {
Preconditions.checkNotNull(node, "node cannot be null!");
Preconditions.checkNotNull(suggestedUri, "suggestedUri cannot be null!");
SimpleUri nodeUri = new SimpleUri("engine:" + suggestedUri);
SimpleUri nodeUri = node.getUri();
if (nodeMap.containsKey(nodeUri)) {
int i = 2;
while (nodeMap.containsKey(new SimpleUri(nodeUri.toString() + i))) {
i++;
}
nodeUri = new SimpleUri(nodeUri.toString() + i);
throw new RuntimeException("A node with uri " + nodeUri + " already exists!");
}
node.setUri(nodeUri);
nodeMap.put(nodeUri, node);
return nodeUri;
graph.addNode(node);
}
public Node removeNode(SimpleUri nodeUri) {
Preconditions.checkNotNull(nodeUri, "nodeUri cannot be null!");
if (edgeMap.containsKey(nodeUri)) {
throw new RuntimeException("The node you are trying to remove is still connected to other nodes in the graph!");
Node node = findNode(nodeUri);
if (node == null) {
throw new RuntimeException("Node removal failure: there is no '" + nodeUri + "' in the render graph!");
}
if (graph.adjacentNodes(node).size() != 0) {
throw new RuntimeException("Node removal failure: node '" + nodeUri + "' is still connected to other nodes in the render graph!");
}
nodeMap.remove(nodeUri);
return nodeMap.remove(nodeUri);
}
@ -81,10 +79,8 @@ public class RenderGraph {
return findNode(new SimpleUri(simpleUri));
}
public boolean connect(Node ... nodeList) {
boolean returnValue = true;
assert(nodeList.length > 1);
public void connect(Node ... nodeList) {
Preconditions.checkArgument(nodeList.length > 1, "Expected at least 2 nodes as arguments to connect() - found " + nodeList.length);
Node fromNode = null;
@ -92,28 +88,26 @@ public class RenderGraph {
Preconditions.checkNotNull(toNode, "toNode cannot be null!");
if (fromNode != null) {
boolean success = edgeMap.put(fromNode, toNode);
if (success) {
reverseEdgeMap.put(toNode, fromNode);
if (!graph.hasEdgeConnecting(fromNode, toNode)) {
graph.putEdge(fromNode, toNode);
} else {
logger.warn("Trying to connect two already connected nodes, " + fromNode.getClass() + " and " + toNode.getClass());
logger.warn("Trying to connect two already connected nodes, " + fromNode.getUri() + " and " + toNode.getUri());
}
returnValue = returnValue && success;
}
fromNode = toNode;
}
return returnValue;
}
public boolean disconnect(Node fromNode, Node toNode) {
public void disconnect(Node fromNode, Node toNode) {
Preconditions.checkNotNull(fromNode, "fromNode cannot be null!");
Preconditions.checkNotNull(toNode, "toNode cannot be null!");
reverseEdgeMap.remove(toNode, fromNode);
return edgeMap.remove(fromNode, toNode);
if (!graph.hasEdgeConnecting(fromNode, toNode)) {
logger.warn("Trying to disconnect two nodes that aren't connected, " + fromNode.getUri() + " and " + toNode.getUri());
}
graph.removeEdge(fromNode, toNode);
}
// TODO: Add `boolean isFullyFunctional(Node node)`
@ -131,15 +125,12 @@ public class RenderGraph {
List<Node> nodesToExamine = Lists.newArrayList();
int visitedNodes = 0;
// Calculate the in-degree for each node.
for (Entry<Node, Collection<Node>> nodeEdgeList : reverseEdgeMap.asMap().entrySet()) {
inDegreeMap.put(nodeEdgeList.getKey(), nodeEdgeList.getValue().size());
}
// Calculate the in-degree for each node, and mark all nodes with no incoming edges for examination.
for (Node node : graph.nodes()) {
int inDegree = graph.inDegree(node);
inDegreeMap.put(node, inDegree);
// Add the missing nodes that did not have any edges, and mark them for examination
for (Node node : nodeMap.values()) {
if (!inDegreeMap.containsKey(node)) {
inDegreeMap.put(node, 0);
if (inDegree == 0) {
nodesToExamine.add(node);
}
}
@ -147,7 +138,7 @@ public class RenderGraph {
while (!nodesToExamine.isEmpty()) {
Node currentNode = nodesToExamine.remove(0);
for (Node adjacentNode : edgeMap.get(currentNode)) {
for (Node adjacentNode : graph.successors(currentNode)) {
int updatedInDegree = inDegreeMap.get(adjacentNode) - 1;
inDegreeMap.put(adjacentNode, updatedInDegree);
@ -169,8 +160,10 @@ public class RenderGraph {
}
public void dispose() {
for (Node node : nodeMap.values()) {
graph.removeNode(node);
node.dispose();
}
nodeMap.clear();
edgeMap.clear();
reverseEdgeMap.clear();
}
}

View File

@ -84,7 +84,9 @@ public class AlphaRejectBlocksNode extends AbstractNode implements WireframeCapa
@Range(min = 0.0f, max = 0.50f)
private float parallaxScale = 0.05f;
public AlphaRejectBlocksNode(Context context) {
public AlphaRejectBlocksNode(String nodeUri, Context context) {
super(nodeUri, context);
renderQueues = context.get(RenderQueuesHelper.class);
worldProvider = context.get(WorldProvider.class);

View File

@ -96,8 +96,8 @@ public class AmbientOcclusionNode extends ConditionDependentNode {
private FloatBuffer ssaoSamples;
public AmbientOcclusionNode(Context context) {
super(context);
public AmbientOcclusionNode(String nodeUri, Context context) {
super(nodeUri, context);
activeCamera = worldRenderer.getActiveCamera();

View File

@ -43,7 +43,9 @@ import static org.terasology.rendering.opengl.OpenGLUtils.renderFullscreenQuad;
public class ApplyDeferredLightingNode extends AbstractNode {
private static final ResourceUrn DEFERRED_LIGHTING_MATERIAL_URN = new ResourceUrn("engine:prog.lightBufferPass");
public ApplyDeferredLightingNode(Context context) {
public ApplyDeferredLightingNode(String nodeUri, Context context) {
super(nodeUri, context);
DisplayResolutionDependentFBOs displayResolutionDependentFBOs = context.get(DisplayResolutionDependentFBOs.class);
SwappableFBO gBufferPair = displayResolutionDependentFBOs.getGBufferPair();

View File

@ -91,7 +91,9 @@ public class BackdropNode extends AbstractNode implements WireframeCapable {
@SuppressWarnings("FieldCanBeLocal")
private float turbidity;
public BackdropNode(Context context) {
public BackdropNode(String nodeUri, Context context) {
super(nodeUri, context);
backdropProvider = context.get(BackdropProvider.class);
worldRenderer = context.get(WorldRenderer.class);

View File

@ -97,7 +97,9 @@ public class BackdropReflectionNode extends AbstractNode {
*
* This method also requests the material using the "sky" shaders (vertex, fragment) to be enabled.
*/
public BackdropReflectionNode(Context context) {
public BackdropReflectionNode(String nodeUri, Context context) {
super(nodeUri, context);
backdropProvider = context.get(BackdropProvider.class);
SubmersibleCamera activeCamera = context.get(WorldRenderer.class).getActiveCamera();

View File

@ -43,8 +43,8 @@ public class BloomBlurNode extends BlurNode {
* @param inputFbo The input fbo, containing the image to be blurred.
* @param outputFbo The output fbo, to store the blurred image.
*/
public BloomBlurNode(Context context, FBO inputFbo, FBO outputFbo) {
super(context, inputFbo, outputFbo, BLUR_RADIUS);
public BloomBlurNode(String nodeUri, Context context, FBO inputFbo, FBO outputFbo) {
super(nodeUri, context, inputFbo, outputFbo, BLUR_RADIUS);
RenderingConfig renderingConfig = context.get(Config.class).getRendering();
requiresCondition(renderingConfig::isBloom);

View File

@ -48,8 +48,8 @@ public class BlurNode extends ConditionDependentNode {
* @param outputFbo The output fbo, to store the blurred image.
* @param blurRadius the blur radius: higher values cause higher blur. The shader's default is 16.0f.
*/
public BlurNode(Context context, FBO inputFbo, FBO outputFbo, float blurRadius) {
super(context);
public BlurNode(String nodeUri, Context context, FBO inputFbo, FBO outputFbo, float blurRadius) {
super(nodeUri, context);
this.blurRadius = blurRadius;

View File

@ -64,8 +64,8 @@ public class BlurredAmbientOcclusionNode extends ConditionDependentNode {
private FBO ssaoBlurredFbo;
public BlurredAmbientOcclusionNode(Context context) {
super(context);
public BlurredAmbientOcclusionNode(String nodeUri, Context context) {
super(nodeUri, context);
RenderingConfig renderingConfig = context.get(Config.class).getRendering();
renderingConfig.subscribe(RenderingConfig.SSAO, this);

View File

@ -15,6 +15,7 @@
*/
package org.terasology.rendering.dag.nodes;
import org.terasology.context.Context;
import org.terasology.rendering.dag.AbstractNode;
import org.terasology.rendering.dag.stateChanges.BindFbo;
import org.terasology.rendering.opengl.BaseFBOsManager;
@ -45,7 +46,8 @@ public class BufferClearingNode extends AbstractNode {
* Non GL_*_BIT values will be accepted but might eventually generate an opengl error.
* @throws IllegalArgumentException if fboConfig, fboManager are null and if clearingMask is zero.
*/
public BufferClearingNode(FBOConfig fboConfig, BaseFBOsManager fboManager, int clearingMask) {
public BufferClearingNode(String nodeUri, Context context, FBOConfig fboConfig, BaseFBOsManager fboManager, int clearingMask) {
super(nodeUri, context);
boolean argumentsAreValid = validateArguments(fboConfig, fboManager, clearingMask);
@ -58,7 +60,9 @@ public class BufferClearingNode extends AbstractNode {
}
}
public BufferClearingNode(FBO fbo, int clearingMask) {
public BufferClearingNode(String nodeUri, Context context, FBO fbo, int clearingMask) {
super(nodeUri, context);
boolean argumentsAreValid = validateArguments(fbo, clearingMask);
if (argumentsAreValid) {

View File

@ -83,7 +83,9 @@ public class DeferredMainLightNode extends AbstractNode {
@SuppressWarnings("FieldCanBeLocal")
private Vector3f mainLightInViewSpace = new Vector3f();
public DeferredMainLightNode(Context context) {
public DeferredMainLightNode(String nodeUri, Context context) {
super(nodeUri, context);
backdropProvider = context.get(BackdropProvider.class);
renderingConfig = context.get(Config.class).getRendering();
worldProvider = context.get(WorldProvider.class);

View File

@ -83,7 +83,9 @@ public class DeferredPointLightsNode extends AbstractNode {
@SuppressWarnings("FieldCanBeLocal")
private Vector3f activeCameraToLightSpace = new Vector3f();
public DeferredPointLightsNode(Context context) {
public DeferredPointLightsNode(String nodeUri, Context context) {
super(nodeUri, context);
renderingConfig = context.get(Config.class).getRendering();
worldProvider = context.get(WorldProvider.class);
entityManager = context.get(EntityManager.class);

View File

@ -40,9 +40,10 @@ public class DownSamplerForExposureNode extends DownSamplerNode {
public static final FBOConfig FBO_2X2_CONFIG = new FBOConfig(new SimpleUri("engine:fbo.2x2px"), 2, 2, FBO.Type.DEFAULT);
public static final FBOConfig FBO_1X1_CONFIG = new FBOConfig(new SimpleUri("engine:fbo.1x1px"), 1, 1, FBO.Type.DEFAULT);
public DownSamplerForExposureNode(Context context, FBOConfig inputFboConfig, BaseFBOsManager inputFboManager,
public DownSamplerForExposureNode(String nodeUri, Context context,
FBOConfig inputFboConfig, BaseFBOsManager inputFboManager,
FBOConfig outputFboConfig, BaseFBOsManager outputFboManager) {
super(context, inputFboConfig, inputFboManager, outputFboConfig, outputFboManager);
super(nodeUri, context, inputFboConfig, inputFboManager, outputFboConfig, outputFboManager);
RenderingConfig renderingConfig = context.get(Config.class).getRendering();
requiresCondition(renderingConfig::isEyeAdaptation);

View File

@ -50,9 +50,10 @@ public class DownSamplerNode extends ConditionDependentNode {
* @param outputFboConfig an FBOConfig instance describing the output FBO, to be retrieved from the FBO manager
* @param outputFboManager the FBO manager from which to retrieve the output FBO
*/
public DownSamplerNode(Context context, FBOConfig inputFboConfig, BaseFBOsManager inputFboManager,
public DownSamplerNode(String nodeUri, Context context,
FBOConfig inputFboConfig, BaseFBOsManager inputFboManager,
FBOConfig outputFboConfig, BaseFBOsManager outputFboManager) {
super(context);
super(nodeUri, context);
FBO inputFbo = requiresFBO(inputFboConfig, inputFboManager);
outputFbo = requiresFBO(outputFboConfig, outputFboManager);

View File

@ -87,7 +87,9 @@ public class FinalPostProcessingNode extends AbstractNode implements PropertyCha
private final int noiseTextureSize = 1024;
public FinalPostProcessingNode(Context context) {
public FinalPostProcessingNode(String nodeUri, Context context) {
super(nodeUri, context);
worldRenderer = context.get(WorldRenderer.class);
activeCamera = worldRenderer.getActiveCamera();
screenGrabber = context.get(ScreenGrabber.class);

View File

@ -45,8 +45,8 @@ public class HazeNode extends BlurNode {
* @param inputFbo The input fbo, containing the image to be blurred.
* @param outputFbo The output fbo, to store the blurred image.
*/
public HazeNode(Context context, FBO inputFbo, FBO outputFbo) {
super(context, inputFbo, outputFbo, BLUR_RADIUS);
public HazeNode(String nodeUri, Context context, FBO inputFbo, FBO outputFbo) {
super(nodeUri, context, inputFbo, outputFbo, BLUR_RADIUS);
renderingConfig = context.get(Config.class).getRendering();
requiresCondition(renderingConfig::isInscattering);

View File

@ -51,8 +51,8 @@ public class HighPassNode extends ConditionDependentNode {
private Material highPass;
public HighPassNode(Context context) {
super(context);
public HighPassNode(String nodeUri, Context context) {
super(nodeUri, context);
RenderingConfig renderingConfig = context.get(Config.class).getRendering();
renderingConfig.subscribe(RenderingConfig.BLOOM, this);

View File

@ -78,7 +78,9 @@ public class InitialPostProcessingNode extends AbstractNode implements PropertyC
@Range(min = 0.0f, max = 1.0f)
private float bloomFactor = 0.5f;
public InitialPostProcessingNode(Context context) {
public InitialPostProcessingNode(String nodeUri, Context context) {
super(nodeUri, context);
worldProvider = context.get(WorldProvider.class);
worldRenderer = context.get(WorldRenderer.class);

View File

@ -52,8 +52,8 @@ public class LateBlurNode extends BlurNode implements PropertyChangeListener {
* @param inputFbo The input fbo, containing the image to be blurred.
* @param outputFbo The output fbo, to store the blurred image.
*/
public LateBlurNode(Context context, FBO inputFbo, FBO outputFbo) {
super(context, inputFbo, outputFbo, 0); // note: blurRadius is 0.0 at this stage.
public LateBlurNode(String nodeUri, Context context, FBO inputFbo, FBO outputFbo) {
super(nodeUri, context, inputFbo, outputFbo, 0); // note: blurRadius is 0.0 at this stage.
renderingConfig = context.get(Config.class).getRendering();
requiresCondition(() -> renderingConfig.getBlurIntensity() != 0); // getBlurIntensity > 0 implies blur is enabled.

View File

@ -81,8 +81,8 @@ public class LightShaftsNode extends ConditionDependentNode {
@SuppressWarnings("FieldCanBeLocal")
private Vector4f sunPositionScreenSpace = new Vector4f();
public LightShaftsNode(Context context) {
super(context);
public LightShaftsNode(String nodeUri, Context context) {
super(nodeUri, context);
backdropProvider = context.get(BackdropProvider.class);
activeCamera = context.get(WorldRenderer.class).getActiveCamera();

View File

@ -83,7 +83,9 @@ public class OpaqueBlocksNode extends AbstractNode implements WireframeCapable,
@Range(min = 0.0f, max = 0.50f)
private float parallaxScale = 0.05f;
public OpaqueBlocksNode(Context context) {
public OpaqueBlocksNode(String nodeUri, Context context) {
super(nodeUri, context);
renderQueues = context.get(RenderQueuesHelper.class);
worldProvider = context.get(WorldProvider.class);

View File

@ -46,7 +46,9 @@ public class OpaqueObjectsNode extends AbstractNode implements WireframeCapable
private SetWireframe wireframeStateChange;
private EnableFaceCulling faceCullingStateChange;
public OpaqueObjectsNode(Context context) {
public OpaqueObjectsNode(String nodeUri, Context context) {
super(nodeUri, context);
componentSystemManager = context.get(ComponentSystemManager.class);
worldRenderer = context.get(WorldRenderer.class);

View File

@ -63,8 +63,8 @@ public class OutlineNode extends ConditionDependentNode {
@Range(min = 0.0f, max = 16.0f)
private float pixelOffsetY = 1.0f;
public OutlineNode(Context context) {
super(context);
public OutlineNode(String nodeUri, Context context) {
super(nodeUri, context);
activeCamera = worldRenderer.getActiveCamera();

View File

@ -55,8 +55,8 @@ public class OutputToHMDNode extends ConditionDependentNode {
* Constructs an instance of this node. Specifically, initialize the vrProvider and pass the frame buffer
* information for the vrProvider to use.
*/
public OutputToHMDNode(Context context) {
super(context);
public OutputToHMDNode(String nodeUri, Context context) {
super(nodeUri, context);
vrProvider = context.get(OpenVRProvider.class);
requiresCondition(() -> (context.get(Config.class).getRendering().isVrSupport() && vrProvider.isInitialized()));

View File

@ -45,8 +45,8 @@ public class OutputToScreenNode extends ConditionDependentNode {
private StateChange bindFbo;
public OutputToScreenNode(Context context) {
super(context);
public OutputToScreenNode(String nodeUri, Context context) {
super(nodeUri, context);
displayResolutionDependentFBOs = context.get(DisplayResolutionDependentFBOs.class);

View File

@ -47,7 +47,9 @@ public class OverlaysNode extends AbstractNode implements WireframeCapable {
private SetWireframe wireframeStateChange;
public OverlaysNode(Context context) {
public OverlaysNode(String nodeUri, Context context) {
super(nodeUri, context);
componentSystemManager = context.get(ComponentSystemManager.class);
worldRenderer = context.get(WorldRenderer.class);

View File

@ -104,7 +104,9 @@ public class PrePostCompositeNode extends AbstractNode implements PropertyChange
@Range(min = -0.1f, max = 0.1f)
private float volumetricFogHeightFalloff = -0.01f;
public PrePostCompositeNode(Context context) {
public PrePostCompositeNode(String nodeUri, Context context) {
super(nodeUri, context);
worldRenderer = context.get(WorldRenderer.class);
activeCamera = worldRenderer.getActiveCamera();

View File

@ -148,7 +148,9 @@ public class RefractiveReflectiveBlocksNode extends AbstractNode implements Prop
@SuppressWarnings("FieldCanBeLocal")
private Vector3f sunDirection;
public RefractiveReflectiveBlocksNode(Context context) {
public RefractiveReflectiveBlocksNode(String nodeUri, Context context) {
super(nodeUri, context);
renderQueues = context.get(RenderQueuesHelper.class);
backdropProvider = context.get(BackdropProvider.class);
worldProvider = context.get(WorldProvider.class);

View File

@ -73,8 +73,8 @@ public class ShadowMapNode extends ConditionDependentNode implements PropertyCha
private SubmersibleCamera activeCamera;
private float texelSize;
public ShadowMapNode(Context context) {
super(context);
public ShadowMapNode(String nodeUri, Context context) {
super(nodeUri, context);
renderQueues = context.get(RenderQueuesHelper.class);
backdropProvider = context.get(BackdropProvider.class);

View File

@ -50,7 +50,9 @@ import static org.lwjgl.opengl.GL11.GL_SRC_ALPHA;
public class SimpleBlendMaterialsNode extends AbstractNode {
private ComponentSystemManager componentSystemManager;
public SimpleBlendMaterialsNode(Context context) {
public SimpleBlendMaterialsNode(String nodeUri, Context context) {
super(nodeUri, context);
componentSystemManager = context.get(ComponentSystemManager.class);
Camera playerCamera = context.get(WorldRenderer.class).getActiveCamera();

View File

@ -60,7 +60,9 @@ public class ToneMappingNode extends AbstractNode {
@Range(min = 0.0f, max = 100.0f)
private float whitePoint = 9f;
public ToneMappingNode(Context context) {
public ToneMappingNode(String nodeUri, Context context) {
super(nodeUri, context);
screenGrabber = context.get(ScreenGrabber.class);
DisplayResolutionDependentFBOs displayResolutionDependentFBOs = context.get(DisplayResolutionDependentFBOs.class);

View File

@ -74,7 +74,9 @@ public class UpdateExposureNode extends AbstractNode {
private PBO writeOnlyPbo; // PBOs are 1x1 pixels buffers used to read GPU data back into the CPU.
// This data is then used in the context of eye adaptation.
public UpdateExposureNode(Context context) {
public UpdateExposureNode(String nodeUri, Context context) {
super(nodeUri, context);
backdropProvider = context.get(BackdropProvider.class);
screenGrabber = context.get(ScreenGrabber.class);

View File

@ -99,8 +99,8 @@ public class WorldReflectionNode extends ConditionDependentNode {
*
* This method also requests the material using the "chunk" shaders (vertex, fragment) to be enabled.
*/
public WorldReflectionNode(Context context) {
super(context);
public WorldReflectionNode(String nodeUri, Context context) {
super(nodeUri, context);
renderQueues = context.get(RenderQueuesHelper.class);
backdropProvider = context.get(BackdropProvider.class);

View File

@ -0,0 +1,20 @@
/*
* Copyright 2018 MovingBlocks
*
* 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.
*/
@API
package org.terasology.rendering.dag.nodes;
import org.terasology.module.sandbox.API;

View File

@ -0,0 +1,20 @@
/*
* Copyright 2018 MovingBlocks
*
* 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.
*/
@API
package org.terasology.rendering.dag;
import org.terasology.module.sandbox.API;

View File

@ -0,0 +1,20 @@
/*
* Copyright 2018 MovingBlocks
*
* 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.
*/
@API
package org.terasology.rendering.dag.stateChanges;
import org.terasology.module.sandbox.API;

View File

@ -0,0 +1,20 @@
/*
* Copyright 2018 MovingBlocks
*
* 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.
*/
@API
package org.terasology.rendering.opengl.fbms;
import org.terasology.module.sandbox.API;

View File

@ -0,0 +1,20 @@
/*
* Copyright 2018 MovingBlocks
*
* 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.
*/
@API
package org.terasology.rendering.opengl;
import org.terasology.module.sandbox.API;

View File

@ -17,9 +17,11 @@ package org.terasology.rendering.world;
import org.terasology.math.geom.Vector3f;
import org.terasology.math.geom.Vector3i;
import org.terasology.module.sandbox.API;
import org.terasology.rendering.assets.material.Material;
import org.terasology.rendering.cameras.Camera;
import org.terasology.rendering.cameras.SubmersibleCamera;
import org.terasology.rendering.dag.RenderGraph;
import org.terasology.rendering.world.viewDistance.ViewDistance;
/**
@ -33,6 +35,7 @@ import org.terasology.rendering.world.viewDistance.ViewDistance;
* If this is the first time you look into this interface, you might want to start with
* the update and render methods as they are central to a rendering implementation.
*/
@API
public interface WorldRenderer {
float BLOCK_LIGHT_POW = 0.96f;
float BLOCK_LIGHT_SUN_POW = 0.96f;
@ -218,4 +221,18 @@ public interface WorldRenderer {
*/
// TODO: transform this to return an object or a map. Consumers would then take care of formatting.
String getMetrics();
/***
* Returns the RenderGraph.
*
* This object is used by Engine and Modules to add/remove Nodes to/from the rendering process.
*
* Nodes encapsulate the rendering functionality of the renderer. A node might provide a basic rendering
* of the landscape, another might add deferred lighting to it while another might add tone mapping
* to the resulting 2d image. Arbitrary features and effects can be added or removed by adding or removing
* nodes to the graph and connecting them appropriately with other nodes.
*
* @return the RenderGraph containing the nodes used by the rendering process.
*/
RenderGraph getRenderGraph();
}

View File

@ -15,6 +15,7 @@
*/
package org.terasology.rendering.world;
import java.util.List;
import org.terasology.config.Config;
import org.terasology.config.RenderingConfig;
import org.terasology.context.Context;
@ -22,7 +23,6 @@ import org.terasology.engine.SimpleUri;
import org.terasology.engine.subsystem.DisplayDevice;
import org.terasology.engine.subsystem.lwjgl.GLBufferPool;
import org.terasology.engine.subsystem.lwjgl.LwjglGraphics;
import org.terasology.entitySystem.systems.RegisterSystem;
import org.terasology.logic.console.Console;
import org.terasology.logic.console.commandSystem.MethodCommand;
import org.terasology.logic.console.commandSystem.annotations.Command;
@ -86,9 +86,6 @@ import org.terasology.rendering.world.viewDistance.ViewDistance;
import org.terasology.utilities.Assets;
import org.terasology.world.WorldProvider;
import org.terasology.world.chunks.ChunkProvider;
import java.util.List;
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_CULL_FACE;
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
@ -119,14 +116,13 @@ import static org.terasology.rendering.opengl.ScalingFactors.QUARTER_SCALE;
* TODO: update this section to include new, relevant objects
* - a RenderableWorld instance, providing acceleration structures caching blocks requiring different rendering treatments<br/>
*/
@RegisterSystem
public final class WorldRendererImpl implements WorldRenderer {
/*
* Presumably, the eye height should be context.get(Config.class).getPlayer().getEyeHeight() above the ground plane.
* It's not, so for now, we use this factor to adjust for the disparity.
*/
private static final float GROUND_PLANE_HEIGHT_DISPARITY = -0.7f;
private static RenderGraph renderGraph = new RenderGraph(); // TODO: Try making this non-static
private RenderGraph renderGraph = new RenderGraph();
private boolean isFirstRenderingStageForCurrentFrame;
private final RenderQueuesHelper renderQueues;
@ -267,35 +263,34 @@ public final class WorldRendererImpl implements WorldRenderer {
addOutputNodes(renderGraph);
renderTaskListGenerator = new RenderTaskListGenerator();
List<Node> orderedNodes = renderGraph.getNodesInTopologicalOrder();
renderPipelineTaskList = renderTaskListGenerator.generateFrom(orderedNodes);
requestTaskListRefresh();
}
private void addGBufferClearingNodes(RenderGraph renderGraph) {
SwappableFBO gBufferPair = displayResolutionDependentFBOs.getGBufferPair();
BufferClearingNode lastUpdatedGBufferClearingNode = new BufferClearingNode(gBufferPair.getLastUpdatedFbo(), GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
renderGraph.addNode(lastUpdatedGBufferClearingNode, "lastUpdatedGBufferClearingNode");
BufferClearingNode lastUpdatedGBufferClearingNode = new BufferClearingNode("lastUpdatedGBufferClearingNode", context, gBufferPair.getLastUpdatedFbo(), GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
renderGraph.addNode(lastUpdatedGBufferClearingNode);
BufferClearingNode staleGBufferClearingNode = new BufferClearingNode(gBufferPair.getStaleFbo(), GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
renderGraph.addNode(staleGBufferClearingNode, "staleGBufferClearingNode");
BufferClearingNode staleGBufferClearingNode = new BufferClearingNode("staleGBufferClearingNode", context, gBufferPair.getStaleFbo(), GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
renderGraph.addNode(staleGBufferClearingNode);
}
private void addSkyNodes(RenderGraph renderGraph) {
Node backdropNode = new BackdropNode(context);
renderGraph.addNode(backdropNode, "backdropNode");
Node backdropNode = new BackdropNode("backdropNode", context);
renderGraph.addNode(backdropNode);
FBOConfig intermediateHazeConfig = new FBOConfig(HazeNode.INTERMEDIATE_HAZE_FBO_URI, ONE_16TH_SCALE, FBO.Type.DEFAULT);
FBO intermediateHazeFbo = displayResolutionDependentFBOs.request(intermediateHazeConfig);
HazeNode intermediateHazeNode = new HazeNode(context, displayResolutionDependentFBOs.getGBufferPair().getLastUpdatedFbo(), intermediateHazeFbo);
renderGraph.addNode(intermediateHazeNode, "intermediateHazeNode");
HazeNode intermediateHazeNode = new HazeNode("intermediateHazeNode", context, displayResolutionDependentFBOs.getGBufferPair().getLastUpdatedFbo(), intermediateHazeFbo);
renderGraph.addNode(intermediateHazeNode);
FBOConfig finalHazeConfig = new FBOConfig(HazeNode.FINAL_HAZE_FBO_URI, ONE_32TH_SCALE, FBO.Type.DEFAULT);
FBO finalHazeFbo = displayResolutionDependentFBOs.request(finalHazeConfig);
HazeNode finalHazeNode = new HazeNode(context, intermediateHazeFbo, finalHazeFbo);
renderGraph.addNode(finalHazeNode, "finalHazeNode");
HazeNode finalHazeNode = new HazeNode("finalHazeNode", context, intermediateHazeFbo, finalHazeFbo);
renderGraph.addNode(finalHazeNode);
Node lastUpdatedGBufferClearingNode = renderGraph.findNode("engine:lastUpdatedGBufferClearingNode");
renderGraph.connect(lastUpdatedGBufferClearingNode, backdropNode, intermediateHazeNode, finalHazeNode);
@ -313,20 +308,20 @@ public final class WorldRendererImpl implements WorldRenderer {
the haze-related nodes together. */
Node finalHazeNode = renderGraph.findNode("engine:finalHazeNode");
Node opaqueObjectsNode = new OpaqueObjectsNode(context);
renderGraph.addNode(opaqueObjectsNode, "opaqueObjectsNode");
Node opaqueObjectsNode = new OpaqueObjectsNode("opaqueObjectsNode", context);
renderGraph.addNode(opaqueObjectsNode);
renderGraph.connect(finalHazeNode, opaqueObjectsNode);
Node opaqueBlocksNode = new OpaqueBlocksNode(context);
renderGraph.addNode(opaqueBlocksNode, "opaqueBlocksNode");
Node opaqueBlocksNode = new OpaqueBlocksNode("opaqueBlocksNode", context);
renderGraph.addNode(opaqueBlocksNode);
renderGraph.connect(finalHazeNode, opaqueBlocksNode);
Node alphaRejectBlocksNode = new AlphaRejectBlocksNode(context);
renderGraph.addNode(alphaRejectBlocksNode, "alphaRejectBlocksNode");
Node alphaRejectBlocksNode = new AlphaRejectBlocksNode("alphaRejectBlocksNode", context);
renderGraph.addNode(alphaRejectBlocksNode);
renderGraph.connect(finalHazeNode, alphaRejectBlocksNode);
Node overlaysNode = new OverlaysNode(context);
renderGraph.addNode(overlaysNode, "overlaysNode");
Node overlaysNode = new OverlaysNode("overlaysNode", context);
renderGraph.addNode(overlaysNode);
renderGraph.connect(finalHazeNode, overlaysNode);
}
@ -338,29 +333,29 @@ public final class WorldRendererImpl implements WorldRenderer {
Node staleGBufferClearingNode = renderGraph.findNode("engine:staleGBufferClearingNode");
FBOConfig shadowMapConfig = new FBOConfig(ShadowMapNode.SHADOW_MAP_FBO_URI, FBO.Type.NO_COLOR).useDepthBuffer();
BufferClearingNode shadowMapClearingNode = new BufferClearingNode(shadowMapConfig, shadowMapResolutionDependentFBOs, GL_DEPTH_BUFFER_BIT);
renderGraph.addNode(shadowMapClearingNode, "shadowMapClearingNode");
BufferClearingNode shadowMapClearingNode = new BufferClearingNode("shadowMapClearingNode", context, shadowMapConfig, shadowMapResolutionDependentFBOs, GL_DEPTH_BUFFER_BIT);
renderGraph.addNode(shadowMapClearingNode);
shadowMapNode = new ShadowMapNode(context);
renderGraph.addNode(shadowMapNode, "shadowMapNode");
shadowMapNode = new ShadowMapNode("shadowMapNode", context);
renderGraph.addNode(shadowMapNode);
renderGraph.connect(shadowMapClearingNode, shadowMapNode);
Node deferredPointLightsNode = new DeferredPointLightsNode(context);
renderGraph.addNode(deferredPointLightsNode, "deferredPointLightsNode");
Node deferredPointLightsNode = new DeferredPointLightsNode("deferredPointLightsNode", context);
renderGraph.addNode(deferredPointLightsNode);
renderGraph.connect(opaqueObjectsNode, deferredPointLightsNode);
renderGraph.connect(opaqueBlocksNode, deferredPointLightsNode);
renderGraph.connect(alphaRejectBlocksNode, deferredPointLightsNode);
Node deferredMainLightNode = new DeferredMainLightNode(context);
renderGraph.addNode(deferredMainLightNode, "deferredMainLightNode");
Node deferredMainLightNode = new DeferredMainLightNode("deferredMainLightNode", context);
renderGraph.addNode(deferredMainLightNode);
renderGraph.connect(shadowMapNode, deferredMainLightNode);
renderGraph.connect(opaqueObjectsNode, deferredMainLightNode);
renderGraph.connect(opaqueBlocksNode, deferredMainLightNode);
renderGraph.connect(alphaRejectBlocksNode, deferredMainLightNode);
renderGraph.connect(deferredPointLightsNode, deferredMainLightNode);
Node applyDeferredLightingNode = new ApplyDeferredLightingNode(context);
renderGraph.addNode(applyDeferredLightingNode, "applyDeferredLightingNode");
Node applyDeferredLightingNode = new ApplyDeferredLightingNode("applyDeferredLightingNode", context);
renderGraph.addNode(applyDeferredLightingNode);
renderGraph.connect(deferredMainLightNode, applyDeferredLightingNode);
renderGraph.connect(deferredPointLightsNode, applyDeferredLightingNode);
renderGraph.connect(lastUpdatedGBufferClearingNode, applyDeferredLightingNode);
@ -373,44 +368,44 @@ public final class WorldRendererImpl implements WorldRenderer {
Node alphaRejectBlocksNode = renderGraph.findNode("engine:alphaRejectBlocksNode");
Node applyDeferredLightingNode = renderGraph.findNode("engine:applyDeferredLightingNode");
Node outlineNode = new OutlineNode(context);
renderGraph.addNode(outlineNode, "outlineNode");
Node outlineNode = new OutlineNode("outlineNode", context);
renderGraph.addNode(outlineNode);
renderGraph.connect(opaqueObjectsNode, outlineNode);
renderGraph.connect(opaqueBlocksNode, outlineNode);
renderGraph.connect(alphaRejectBlocksNode, outlineNode);
Node ambientOcclusionNode = new AmbientOcclusionNode(context);
renderGraph.addNode(ambientOcclusionNode, "ambientOcclusionNode");
Node ambientOcclusionNode = new AmbientOcclusionNode("ambientOcclusionNode", context);
renderGraph.addNode(ambientOcclusionNode);
renderGraph.connect(opaqueObjectsNode, ambientOcclusionNode);
renderGraph.connect(opaqueBlocksNode, ambientOcclusionNode);
renderGraph.connect(alphaRejectBlocksNode, ambientOcclusionNode);
// TODO: At this stage, it is unclear -why- this connection is required, we just know that it's required. Investigate.
renderGraph.connect(applyDeferredLightingNode, ambientOcclusionNode);
Node blurredAmbientOcclusionNode = new BlurredAmbientOcclusionNode(context);
renderGraph.addNode(blurredAmbientOcclusionNode, "blurredAmbientOcclusionNode");
Node blurredAmbientOcclusionNode = new BlurredAmbientOcclusionNode("blurredAmbientOcclusionNode", context);
renderGraph.addNode(blurredAmbientOcclusionNode);
renderGraph.connect(ambientOcclusionNode, blurredAmbientOcclusionNode);
}
private void addReflectionAndRefractionNodes(RenderGraph renderGraph) {
FBOConfig reflectedBufferConfig = new FBOConfig(BackdropReflectionNode.REFLECTED_FBO_URI, HALF_SCALE, FBO.Type.DEFAULT).useDepthBuffer();
BufferClearingNode reflectedBufferClearingNode = new BufferClearingNode(reflectedBufferConfig, displayResolutionDependentFBOs, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
renderGraph.addNode(reflectedBufferClearingNode, "reflectedBufferClearingNode");
BufferClearingNode reflectedBufferClearingNode = new BufferClearingNode("reflectedBufferClearingNode", context, reflectedBufferConfig, displayResolutionDependentFBOs, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
renderGraph.addNode(reflectedBufferClearingNode);
Node reflectedBackdropNode = new BackdropReflectionNode(context);
renderGraph.addNode(reflectedBackdropNode, "reflectedBackdropNode");
Node reflectedBackdropNode = new BackdropReflectionNode("reflectedBackdropNode", context);
renderGraph.addNode(reflectedBackdropNode);
Node worldReflectionNode = new WorldReflectionNode(context);
renderGraph.addNode(worldReflectionNode, "worldReflectionNode");
Node worldReflectionNode = new WorldReflectionNode("worldReflectionNode", context);
renderGraph.addNode(worldReflectionNode);
renderGraph.connect(reflectedBufferClearingNode, reflectedBackdropNode, worldReflectionNode);
FBOConfig reflectedRefractedBufferConfig = new FBOConfig(RefractiveReflectiveBlocksNode.REFRACTIVE_REFLECTIVE_FBO_URI, FULL_SCALE, FBO.Type.HDR).useNormalBuffer();
BufferClearingNode reflectedRefractedBufferClearingNode = new BufferClearingNode(reflectedRefractedBufferConfig, displayResolutionDependentFBOs, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
renderGraph.addNode(reflectedRefractedBufferClearingNode, "reflectedRefractedBufferClearingNode");
BufferClearingNode reflectedRefractedBufferClearingNode = new BufferClearingNode("reflectedRefractedBufferClearingNode", context, reflectedRefractedBufferConfig, displayResolutionDependentFBOs, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
renderGraph.addNode(reflectedRefractedBufferClearingNode);
Node chunksRefractiveReflectiveNode = new RefractiveReflectiveBlocksNode(context);
renderGraph.addNode(chunksRefractiveReflectiveNode, "chunksRefractiveReflectiveNode");
Node chunksRefractiveReflectiveNode = new RefractiveReflectiveBlocksNode("chunksRefractiveReflectiveNode", context);
renderGraph.addNode(chunksRefractiveReflectiveNode);
Node applyDeferredLightingNode = renderGraph.findNode("engine:applyDeferredLightingNode");
renderGraph.connect(reflectedRefractedBufferClearingNode, chunksRefractiveReflectiveNode);
@ -431,8 +426,8 @@ public final class WorldRendererImpl implements WorldRenderer {
Node outlineNode = renderGraph.findNode("engine:outlineNode");
Node blurredAmbientOcclusionNode = renderGraph.findNode("engine:blurredAmbientOcclusionNode");
Node prePostCompositeNode = new PrePostCompositeNode(context);
renderGraph.addNode(prePostCompositeNode, "prePostCompositeNode");
Node prePostCompositeNode = new PrePostCompositeNode("prePostCompositeNode", context);
renderGraph.addNode(prePostCompositeNode);
renderGraph.connect(overlaysNode, prePostCompositeNode);
renderGraph.connect(finalHazeNode, prePostCompositeNode);
renderGraph.connect(chunksRefractiveReflectiveNode, prePostCompositeNode);
@ -440,34 +435,34 @@ public final class WorldRendererImpl implements WorldRenderer {
renderGraph.connect(outlineNode, prePostCompositeNode);
renderGraph.connect(blurredAmbientOcclusionNode, prePostCompositeNode);
Node simpleBlendMaterialsNode = new SimpleBlendMaterialsNode(context);
renderGraph.addNode(simpleBlendMaterialsNode, "simpleBlendMaterialsNode");
Node simpleBlendMaterialsNode = new SimpleBlendMaterialsNode("simpleBlendMaterialsNode", context);
renderGraph.addNode(simpleBlendMaterialsNode);
renderGraph.connect(prePostCompositeNode, simpleBlendMaterialsNode);
}
private void addBloomNodes(RenderGraph renderGraph) {
// Bloom Effect: one high-pass filter and three blur passes
Node highPassNode = new HighPassNode(context);
renderGraph.addNode(highPassNode, "highPassNode");
Node highPassNode = new HighPassNode("highPassNode", context);
renderGraph.addNode(highPassNode);
FBOConfig halfScaleBloomConfig = new FBOConfig(BloomBlurNode.HALF_SCALE_FBO_URI, HALF_SCALE, FBO.Type.DEFAULT);
FBO halfScaleBloomFbo = displayResolutionDependentFBOs.request(halfScaleBloomConfig);
BloomBlurNode halfScaleBlurredBloomNode = new BloomBlurNode(context, displayResolutionDependentFBOs.get(HighPassNode.HIGH_PASS_FBO_URI), halfScaleBloomFbo);
renderGraph.addNode(halfScaleBlurredBloomNode, "halfScaleBlurredBloomNode");
BloomBlurNode halfScaleBlurredBloomNode = new BloomBlurNode("halfScaleBlurredBloomNode", context, displayResolutionDependentFBOs.get(HighPassNode.HIGH_PASS_FBO_URI), halfScaleBloomFbo);
renderGraph.addNode(halfScaleBlurredBloomNode);
FBOConfig quarterScaleBloomConfig = new FBOConfig(BloomBlurNode.QUARTER_SCALE_FBO_URI, QUARTER_SCALE, FBO.Type.DEFAULT);
FBO quarterScaleBloomFbo = displayResolutionDependentFBOs.request(quarterScaleBloomConfig);
BloomBlurNode quarterScaleBlurredBloomNode = new BloomBlurNode(context, halfScaleBloomFbo, quarterScaleBloomFbo);
renderGraph.addNode(quarterScaleBlurredBloomNode, "quarterScaleBlurredBloomNode");
BloomBlurNode quarterScaleBlurredBloomNode = new BloomBlurNode("quarterScaleBlurredBloomNode", context, halfScaleBloomFbo, quarterScaleBloomFbo);
renderGraph.addNode(quarterScaleBlurredBloomNode);
FBOConfig one8thScaleBloomConfig = new FBOConfig(BloomBlurNode.ONE_8TH_SCALE_FBO_URI, ONE_8TH_SCALE, FBO.Type.DEFAULT);
FBO one8thScaleBloomFbo = displayResolutionDependentFBOs.request(one8thScaleBloomConfig);
BloomBlurNode one8thScaleBlurredBloomNode = new BloomBlurNode(context, quarterScaleBloomFbo, one8thScaleBloomFbo);
renderGraph.addNode(one8thScaleBlurredBloomNode, "one8thScaleBlurredBloomNode");
BloomBlurNode one8thScaleBlurredBloomNode = new BloomBlurNode("one8thScaleBlurredBloomNode", context, quarterScaleBloomFbo, one8thScaleBloomFbo);
renderGraph.addNode(one8thScaleBlurredBloomNode);
Node simpleBlendMaterialsNode = renderGraph.findNode("engine:simpleBlendMaterialsNode");
renderGraph.connect(simpleBlendMaterialsNode, highPassNode, halfScaleBlurredBloomNode,
@ -476,23 +471,23 @@ public final class WorldRendererImpl implements WorldRenderer {
private void addExposureNodes(RenderGraph renderGraph) {
FBOConfig gBuffer2Config = displayResolutionDependentFBOs.getFboConfig(new SimpleUri("engine:fbo.gBuffer2")); // TODO: Remove the hard coded value here
DownSamplerForExposureNode exposureDownSamplerTo16pixels = new DownSamplerForExposureNode(context, gBuffer2Config, displayResolutionDependentFBOs, FBO_16X16_CONFIG, immutableFBOs);
renderGraph.addNode(exposureDownSamplerTo16pixels, "exposureDownSamplerTo16pixels");
DownSamplerForExposureNode exposureDownSamplerTo16pixels = new DownSamplerForExposureNode("exposureDownSamplerTo16pixels", context, gBuffer2Config, displayResolutionDependentFBOs, FBO_16X16_CONFIG, immutableFBOs);
renderGraph.addNode(exposureDownSamplerTo16pixels);
DownSamplerForExposureNode exposureDownSamplerTo8pixels = new DownSamplerForExposureNode(context, FBO_16X16_CONFIG, immutableFBOs, FBO_8X8_CONFIG, immutableFBOs);
renderGraph.addNode(exposureDownSamplerTo8pixels, "exposureDownSamplerTo8pixels");
DownSamplerForExposureNode exposureDownSamplerTo8pixels = new DownSamplerForExposureNode("exposureDownSamplerTo8pixels", context, FBO_16X16_CONFIG, immutableFBOs, FBO_8X8_CONFIG, immutableFBOs);
renderGraph.addNode(exposureDownSamplerTo8pixels);
DownSamplerForExposureNode exposureDownSamplerTo4pixels = new DownSamplerForExposureNode(context, FBO_8X8_CONFIG, immutableFBOs, FBO_4X4_CONFIG, immutableFBOs);
renderGraph.addNode(exposureDownSamplerTo4pixels, "exposureDownSamplerTo4pixels");
DownSamplerForExposureNode exposureDownSamplerTo4pixels = new DownSamplerForExposureNode("exposureDownSamplerTo4pixels", context, FBO_8X8_CONFIG, immutableFBOs, FBO_4X4_CONFIG, immutableFBOs);
renderGraph.addNode(exposureDownSamplerTo4pixels);
DownSamplerForExposureNode exposureDownSamplerTo2pixels = new DownSamplerForExposureNode(context, FBO_4X4_CONFIG, immutableFBOs, FBO_2X2_CONFIG, immutableFBOs);
renderGraph.addNode(exposureDownSamplerTo2pixels, "exposureDownSamplerTo2pixels");
DownSamplerForExposureNode exposureDownSamplerTo2pixels = new DownSamplerForExposureNode("exposureDownSamplerTo2pixels", context, FBO_4X4_CONFIG, immutableFBOs, FBO_2X2_CONFIG, immutableFBOs);
renderGraph.addNode(exposureDownSamplerTo2pixels);
DownSamplerForExposureNode exposureDownSamplerTo1pixel = new DownSamplerForExposureNode(context, FBO_2X2_CONFIG, immutableFBOs, FBO_1X1_CONFIG, immutableFBOs);
renderGraph.addNode(exposureDownSamplerTo1pixel, "exposureDownSamplerTo1pixel");
DownSamplerForExposureNode exposureDownSamplerTo1pixel = new DownSamplerForExposureNode("exposureDownSamplerTo1pixel", context, FBO_2X2_CONFIG, immutableFBOs, FBO_1X1_CONFIG, immutableFBOs);
renderGraph.addNode(exposureDownSamplerTo1pixel);
Node updateExposureNode = new UpdateExposureNode(context);
renderGraph.addNode(updateExposureNode, "updateExposureNode");
Node updateExposureNode = new UpdateExposureNode("updateExposureNode", context);
renderGraph.addNode(updateExposureNode);
Node simpleBlendMaterialsNode = renderGraph.findNode("engine:simpleBlendMaterialsNode");
renderGraph.connect(simpleBlendMaterialsNode, exposureDownSamplerTo16pixels, exposureDownSamplerTo8pixels,
@ -505,13 +500,13 @@ public final class WorldRendererImpl implements WorldRenderer {
Node one8thScaleBlurredBloomNode = renderGraph.findNode("engine:one8thScaleBlurredBloomNode");
// Light shafts
Node lightShaftsNode = new LightShaftsNode(context);
renderGraph.addNode(lightShaftsNode, "lightShaftsNode");
Node lightShaftsNode = new LightShaftsNode("lightShaftsNode", context);
renderGraph.addNode(lightShaftsNode);
renderGraph.connect(simpleBlendMaterialsNode, lightShaftsNode);
// Adding the bloom and light shafts to the gBuffer
Node initialPostProcessingNode = new InitialPostProcessingNode(context);
renderGraph.addNode(initialPostProcessingNode, "initialPostProcessingNode");
Node initialPostProcessingNode = new InitialPostProcessingNode("initialPostProcessingNode", context);
renderGraph.addNode(initialPostProcessingNode);
renderGraph.connect(lightShaftsNode, initialPostProcessingNode);
renderGraph.connect(one8thScaleBlurredBloomNode, initialPostProcessingNode);
}
@ -520,8 +515,8 @@ public final class WorldRendererImpl implements WorldRenderer {
Node initialPostProcessingNode = renderGraph.findNode("engine:initialPostProcessingNode");
Node updateExposureNode = renderGraph.findNode("engine:updateExposureNode");
Node toneMappingNode = new ToneMappingNode(context);
renderGraph.addNode(toneMappingNode, "toneMappingNode");
Node toneMappingNode = new ToneMappingNode("toneMappingNode", context);
renderGraph.addNode(toneMappingNode);
renderGraph.connect(updateExposureNode, toneMappingNode);
renderGraph.connect(initialPostProcessingNode, toneMappingNode);
@ -529,17 +524,17 @@ public final class WorldRendererImpl implements WorldRenderer {
FBOConfig firstLateBlurConfig = new FBOConfig(FIRST_LATE_BLUR_FBO_URI, HALF_SCALE, FBO.Type.DEFAULT);
FBO firstLateBlurFbo = displayResolutionDependentFBOs.request(firstLateBlurConfig);
LateBlurNode firstLateBlurNode = new LateBlurNode(context, displayResolutionDependentFBOs.get(ToneMappingNode.TONE_MAPPING_FBO_URI), firstLateBlurFbo);
renderGraph.addNode(firstLateBlurNode, "firstLateBlurNode");
LateBlurNode firstLateBlurNode = new LateBlurNode("firstLateBlurNode", context, displayResolutionDependentFBOs.get(ToneMappingNode.TONE_MAPPING_FBO_URI), firstLateBlurFbo);
renderGraph.addNode(firstLateBlurNode);
FBOConfig secondLateBlurConfig = new FBOConfig(SECOND_LATE_BLUR_FBO_URI, HALF_SCALE, FBO.Type.DEFAULT);
FBO secondLateBlurFbo = displayResolutionDependentFBOs.request(secondLateBlurConfig);
LateBlurNode secondLateBlurNode = new LateBlurNode(context, firstLateBlurFbo, secondLateBlurFbo);
renderGraph.addNode(secondLateBlurNode, "secondLateBlurNode");
LateBlurNode secondLateBlurNode = new LateBlurNode("secondLateBlurNode", context, firstLateBlurFbo, secondLateBlurFbo);
renderGraph.addNode(secondLateBlurNode);
Node finalPostProcessingNode = new FinalPostProcessingNode(context);
renderGraph.addNode(finalPostProcessingNode, "finalPostProcessingNode");
Node finalPostProcessingNode = new FinalPostProcessingNode("finalPostProcessingNode", context);
renderGraph.addNode(finalPostProcessingNode);
renderGraph.connect(toneMappingNode, firstLateBlurNode, secondLateBlurNode, finalPostProcessingNode);
}
@ -547,12 +542,12 @@ public final class WorldRendererImpl implements WorldRenderer {
private void addOutputNodes(RenderGraph renderGraph) {
Node finalPostProcessingNode = renderGraph.findNode("engine:finalPostProcessingNode");
Node outputToVRFrameBufferNode = new OutputToHMDNode(context);
renderGraph.addNode(outputToVRFrameBufferNode, "outputToVRFrameBufferNode");
Node outputToVRFrameBufferNode = new OutputToHMDNode("outputToVRFrameBufferNode", context);
renderGraph.addNode(outputToVRFrameBufferNode);
renderGraph.connect(finalPostProcessingNode, outputToVRFrameBufferNode);
Node outputToScreenNode = new OutputToScreenNode(context);
renderGraph.addNode(outputToScreenNode, "outputToScreenNode");
Node outputToScreenNode = new OutputToScreenNode("outputToScreenNode", context);
renderGraph.addNode(outputToScreenNode);
renderGraph.connect(finalPostProcessingNode, outputToScreenNode);
}
@ -638,7 +633,8 @@ public final class WorldRendererImpl implements WorldRenderer {
renderableWorld.queueVisibleChunks(isFirstRenderingStageForCurrentFrame);
if (requestedTaskListRefresh) {
renderTaskListGenerator.refresh();
List<Node> orderedNodes = renderGraph.getNodesInTopologicalOrder();
renderPipelineTaskList = renderTaskListGenerator.generateFrom(orderedNodes);
requestedTaskListRefresh = false;
}
}
@ -777,6 +773,11 @@ public final class WorldRendererImpl implements WorldRenderer {
return currentRenderingStage;
}
@Override
public RenderGraph getRenderGraph() {
return renderGraph;
}
/**
* Forces a recompilation of all shaders. This command, backed by Gestalt's monitoring feature,
* allows developers to hot-swap shaders for easy development.