Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backdrop and Skybands Nodes for DAG #2362

Merged
merged 7 commits into from
Jun 22, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions engine/src/main/java/org/terasology/rendering/dag/BackdropNode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* Copyright 2016 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.
*/
package org.terasology.rendering.dag;

import org.terasology.config.Config;
import org.terasology.config.RenderingDebugConfig;
import org.terasology.monitoring.PerformanceMonitor;
import org.terasology.registry.In;
import org.terasology.rendering.backdrop.BackdropRenderer;
import org.terasology.rendering.cameras.Camera;
import org.terasology.rendering.opengl.FBO;
import org.terasology.rendering.opengl.FrameBuffersManager;
import org.terasology.rendering.world.WorldRenderer;
import static org.terasology.rendering.opengl.OpenGLUtils.bindDisplay;
import static org.terasology.rendering.opengl.OpenGLUtils.disableWireframeIf;
import static org.terasology.rendering.opengl.OpenGLUtils.enableWireframeIf;
import static org.terasology.rendering.opengl.OpenGLUtils.setRenderBufferMask;
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_STENCIL_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.glClear;


/**
* TODO: Diagram of this node
*/
public class BackdropNode implements Node {

@In
private Config config;

@In
private BackdropRenderer backdropRenderer;

@In
private WorldRenderer worldRenderer;

@In
private FrameBuffersManager frameBuffersManager;

private RenderingDebugConfig renderingDebugConfig;
private Camera playerCamera;
private FBO sceneOpaque;

@Override
public void initialise() {
renderingDebugConfig = config.getRendering().getDebug();
playerCamera = worldRenderer.getActiveCamera();
}

@Override
public void process() {
PerformanceMonitor.startActivity("rendering/backdrop");
enableWireframeIf(renderingDebugConfig.isWireframe());

sceneOpaque = frameBuffersManager.getFBO("sceneOpaque");

initialClearing();

sceneOpaque.bind();
setRenderBufferMask(sceneOpaque, true, true, true);

playerCamera.lookThroughNormalized();
/**
* Sets the state to render the Backdrop. At this stage the backdrop is the SkySphere
* plus the SkyBands passes.
*
* The backdrop is the only rendering that has three state-changing methods.
* This is due to the SkySphere requiring a state and the SkyBands requiring a slightly
* different one.
*/
setRenderBufferMask(sceneOpaque, true, false, false);
backdropRenderer.render(playerCamera);

disableWireframeIf(renderingDebugConfig.isWireframe());
PerformanceMonitor.endActivity();
}

/**
* Initial clearing of a couple of important Frame Buffers. Then binds back the Display.
*/
// It's unclear why these buffers need to be cleared while all the others don't...
private void initialClearing() {
FBO sceneReflectiveRefractive = frameBuffersManager.getFBO("sceneReflectiveRefractive");
sceneOpaque.bind();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
sceneReflectiveRefractive.bind();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
bindDisplay();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/
package org.terasology.rendering.dag;

import org.lwjgl.opengl.GL11;

import org.terasology.config.Config;
import org.terasology.config.RenderingConfig;
import org.terasology.math.TeraMath;
Expand All @@ -33,8 +33,13 @@
import org.terasology.rendering.world.RenderableWorld;
import org.terasology.rendering.world.WorldRenderer;
import org.terasology.rendering.world.WorldRendererImpl;
import static org.lwjgl.opengl.GL11.*;
import static org.terasology.rendering.opengl.OpenGLUtils.*;
import org.lwjgl.opengl.GL11;
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;
import static org.lwjgl.opengl.GL11.glClear;
import static org.terasology.rendering.opengl.OpenGLUtils.bindDisplay;
import static org.terasology.rendering.opengl.OpenGLUtils.setViewportToSizeOf;


/**
Expand Down Expand Up @@ -69,7 +74,6 @@ public class ShadowMapNode implements Node {
private RenderingConfig renderingConfig;
private Camera playerCamera;


@Override
public void initialise() {
this.playerCamera = worldRenderer.getActiveCamera();
Expand All @@ -81,7 +85,7 @@ public void initialise() {

@Override
public void process() {
this.shadowMap = frameBuffersManager.getFBO("sceneShadowMap");
shadowMap = frameBuffersManager.getFBO("sceneShadowMap");
positionShadowMapCamera();

// TODO: find an elegant way to fetch isFirstRenderingStageForCurrentFrame
Expand All @@ -90,7 +94,7 @@ public void process() {
return;
}

PerformanceMonitor.startActivity("Render World (Shadow Map)");
PerformanceMonitor.startActivity("rendering/shadowmap");
// preRenderSetupSceneShadowMap
shadowMap.bind();
setViewportToSizeOf(shadowMap);
Expand Down
114 changes: 114 additions & 0 deletions engine/src/main/java/org/terasology/rendering/dag/SkyBandsNode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* Copyright 2016 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.
*/
package org.terasology.rendering.dag;

import org.terasology.config.Config;
import org.terasology.config.RenderingConfig;
import org.terasology.config.RenderingDebugConfig;
import org.terasology.monitoring.PerformanceMonitor;
import org.terasology.registry.In;
import org.terasology.rendering.assets.material.Material;
import org.terasology.rendering.cameras.Camera;
import org.terasology.rendering.opengl.FBO;
import org.terasology.rendering.opengl.FrameBuffersManager;
import org.terasology.rendering.world.WorldRenderer;
import static org.terasology.rendering.opengl.OpenGLUtils.bindDisplay;
import static org.terasology.rendering.opengl.OpenGLUtils.setViewportToSizeOf;
import static org.terasology.rendering.opengl.OpenGLUtils.disableWireframeIf;
import static org.terasology.rendering.opengl.OpenGLUtils.enableWireframeIf;
import static org.terasology.rendering.opengl.OpenGLUtils.renderFullscreenQuad;
import static org.terasology.rendering.opengl.OpenGLUtils.setRenderBufferMask;
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.glClear;


/**
* TODO: Diagram of this node
* TODO: Separate this node into multiple SkyBandNode's
*/
public class SkyBandsNode implements Node {

@In
private Config config;

@In
private WorldRenderer worldRenderer;

@In
private FrameBuffersManager frameBuffersManager;

private RenderingConfig renderingConfig;
private Material blurShader;
private FBO sceneOpaque;
private FBO sceneSkyBand0;
private RenderingDebugConfig renderingDebugConfig;
private Camera playerCamera;

@Override
public void initialise() {
renderingConfig = config.getRendering();
renderingDebugConfig = renderingConfig.getDebug();
blurShader = worldRenderer.getMaterial("engine:prog.blur");
playerCamera = worldRenderer.getActiveCamera();
}

@Override
public void process() {
PerformanceMonitor.startActivity("rendering/skybands");
enableWireframeIf(renderingDebugConfig.isWireframe());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please enable AND disable wireframe in all nodes that were originally between the enableWireframeIf/disableWireframeIf statements in the WorldRendererImpl.render method. So, each of those nodes will need its own enable/disable pair. This of course has a small performance hit but we'll eventually solve it with state management.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you mean these two nodes also need a disableWireframeIf statement at the end of process() method? Should changed states for a certain node in OpenGL be reverted and left for our state management?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • The answer to the first question is yes.
  • OpenGL state changes shouldn't be touched at this stage. I was very, very tempted of touching some in the SkyBands node but I decided not to suggest it so that we can continue focusing on wrapping things.
  • PerformanceMonitor is not an opengl thing so I don't mind touching it. The content of every process() method of every node should really be bracketed by startActivity()/endActivity() as a rule.


sceneOpaque = frameBuffersManager.getFBO("sceneOpaque");

setRenderBufferMask(sceneOpaque, true, true, true);
if (renderingConfig.isInscattering()) {
sceneSkyBand0 = frameBuffersManager.getFBO("sceneSkyBand0");
FBO sceneSkyBand1 = frameBuffersManager.getFBO("sceneSkyBand1");

generateSkyBand(sceneSkyBand0);
generateSkyBand(sceneSkyBand1);
}

sceneOpaque.bind();

playerCamera.lookThrough();
disableWireframeIf(renderingDebugConfig.isWireframe());
PerformanceMonitor.endActivity();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good coding choice to clarify what would otherwise be hard to understand. However I'd solve the problem by having Performance Monitor statements at the beginning and end of each node. This is a change from what we have now, grouping together a number of rendering steps within the same activity. My vision is to group together activities by using hierarchical activity names instead. I.e. you could name the activity in the BackdropNode "rendering/backdrop" and the other "rendering/backdrop/skybands". It will be up to DebugOverlay to group these together if the user wishes it. Let me know if this is clear enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean like:

PerformanceMonitor.startActivity("rendering/backdrop") // Executed inside Backdrop
...
PerformanceMonitor.startActivity("rendering/backdrop/skybands") // Executed inside SkyBand node
... 
PerformanceMonitor.endActivity("rendering/backdrop/skybands") // Executed inside SkyBand 

PerformanceMonitor.endActivity("rendering/backdrop") // Executed not inside SkyBand, but inside Backdrop

But the activity backdrop (rendering/backdrop) in total is going to include measurements from rendering/backdrop/skybands right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding the activity statements: correct. Just remember endActivity() takes no parameter. Which won't be a problem now that start/end are closer to each other.

Regarding your question: ideally, but only in a DebugOverlay. And initially I don't mind if it isn't. If the DebugOverlay is ordered alphabetically for example, related nodes will be listed near each other anyway.

There could be an argument for naming rendering/backdrop more specifically. Or perhaps naming rendering/backdrop/skybands to rendering/skybands instead. In fact, I would prefer it that way. I am not convinced that the skybands should be grouped with the backdrop. If I remember correctly the generate some distant haze that gets overimposed on the world rendering. So, they are atmospheric effects on the world, not on the sky.

So, I'd suggest rendering/backdrop and rendering/skybands for the time being.

}

private void generateSkyBand(FBO skyBand) {
blurShader.enable();
blurShader.setFloat("radius", 8.0f, true);
blurShader.setFloat2("texelSize", 1.0f / skyBand.width(), 1.0f / skyBand.height(), true);

if (skyBand == sceneSkyBand0) {
sceneOpaque.bindTexture();
} else {
sceneSkyBand0.bindTexture();
}

skyBand.bind();
setRenderBufferMask(skyBand, true, false, false);

setViewportToSizeOf(skyBand);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // TODO: verify this is necessary

renderFullscreenQuad();

bindDisplay(); // TODO: verify this is necessary
setViewportToSizeOf(sceneOpaque); // TODO: verify this is necessary
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.glClear;
import static org.terasology.rendering.opengl.OpenGLUtils.*;
import static org.terasology.rendering.opengl.OpenGLUtils.bindDisplay;
import static org.terasology.rendering.opengl.OpenGLUtils.setViewportToSizeOf;

/**
* Diagram of this node can be viewed from:
Expand All @@ -61,6 +62,8 @@ public class WorldReflectionNode implements Node {
private Camera playerCamera;
private Material chunkShader;
private RenderingConfig renderingConfig;
private FBO sceneReflected;
private FBO sceneOpaque;

@Override
public void initialise() {
Expand All @@ -71,9 +74,9 @@ public void initialise() {

@Override
public void process() {
PerformanceMonitor.startActivity("Render World (Reflection)");
FBO sceneReflected = frameBuffersManager.getFBO("sceneReflected");
FBO sceneOpaque = frameBuffersManager.getFBO("sceneOpaque");
PerformanceMonitor.startActivity("rendering/worldreflection");
sceneReflected = frameBuffersManager.getFBO("sceneReflected");
sceneOpaque = frameBuffersManager.getFBO("sceneOpaque");

sceneReflected.bind();
setViewportToSizeOf(sceneReflected);
Expand Down
Loading