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

Add Haze Pass #41

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 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
64 changes: 58 additions & 6 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ import {Axes} from "./axes.js";
import {Rect} from "./rect.js";
import {Colors} from "./colors.js";
import {Coords} from "./coords.js";
import {DepthShader} from "./shaders/depth_shader.js";
import {EventTracker} from "./event_tracker.js";
import {Extruder} from "./extruder.js";
import {FetchQueue} from "./fetch_queue.js";
import {Ground} from "./ground.js";
import {HazeShader} from "./shaders/haze_shader.js";
import {Settings} from "./settings.js";
import {SkyBox} from "./skybox.js";
import {Util} from "./util.js";
Expand Down Expand Up @@ -85,6 +87,8 @@ class App {
this.infoDetailsClose = document.getElementById("info-details-close");
this.infoDetailsDisplayed = false;

this.urlParams = new URLSearchParams(window.location.search);
Copy link
Member

Choose a reason for hiding this comment

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

Would you mind moving the new url params into main.js so they're handled the same as the current url params (the pattern is that the url params are parsed in main.js and loaded into an "options" object which is passed to the App construtor).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Much cleaner, done.


// map whose keys are bbox strings, value is an object giving details about the corresponding data tile
this.bBoxStringToSceneTileDetails = {
// "-74.002,40.742,-74.001,40.743": {
Expand Down Expand Up @@ -693,22 +697,67 @@ class App {

this.scene.add(this.camera);

this.composer = new THREE.EffectComposer(this.renderer);
// Set up render target for holding depth information.
Copy link
Member

Choose a reason for hiding this comment

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

It'd be great to make all the new composers/passes conditional on a url param, so if it's not enabled, the behavior/rendering is unchanged from before. This will make it easier to deploy this new feature while we experiment with and tweak it, without changing the current user experience. (At the moment it looks to me like there is a bit of a haze effect, or maybe it's just the antialising, I'm not sure, even if the new haze & depth params aren't present in the url. Also, eventually we might want different haze settings for birds-eye vs street-level views. In any case, if we can make it so that none of this is enabled, and the user sees the same result as before, unless they add special url params, then we can go ahead and deploy it and start experimenting with it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good note, I'll work on that. I think the current "haze" when the haze feature is disabled actually comes from the softening of the edges with the antialising from a previous merge, but I'll double check that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think the fuzziness is from the screen I captured it on, which has a lower resolution. I've taken another screenshot (attached) with all the new features disabled (which is the default). Certainly looks less fuzzy now I think.

Screen Shot 2021-04-23 at 14 07 14

this.depthRenderTarget = new THREE.WebGLRenderTarget( this.container.offsetWidth, this.container.offsetHeight );
this.depthRenderTarget.texture.format = THREE.RGBFormat;
this.depthRenderTarget.texture.minFilter = THREE.NearestFilter;
this.depthRenderTarget.texture.magFilter = THREE.NearestFilter;
this.depthRenderTarget.texture.generateMipmaps = false;
this.depthRenderTarget.stencilBuffer = false;
this.depthRenderTarget.depthBuffer = true;
this.depthRenderTarget.depthTexture = new THREE.DepthTexture();
this.depthRenderTarget.depthTexture.type = THREE.UnsignedShortType;

// Composer for preprocessing.
this.composerPreprocess = new THREE.EffectComposer(this.renderer, this.depthRenderTarget);
this.renderPass = new THREE.RenderPass(this.scene, this.camera);
this.composer.addPass(this.renderPass);
this.composerPreprocess.addPass(this.renderPass);

// Set up copy pass. Copies into write buffer, which can be used in calculating depth in this.depthPass.
this.copyPass = new THREE.ShaderPass(THREE.CopyShader);
this.composerPreprocess.addPass(this.copyPass);

// Render to screen.
var renderTargetParameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBuffer: false };
this.screenRenderTarget = new THREE.WebGLRenderTarget( this.container.offsetWidth, this.container.offsetHeight, renderTargetParameters );

// Composer for rendering to the screen.
this.composerFinal = new THREE.EffectComposer(this.renderer, this.screenRenderTarget);
const renderPass = new THREE.RenderPass(this.scene, this.camera );
this.composerFinal.addPass(renderPass)

// Set up outline pass.
this.outlinePass = new THREE.OutlinePass(new THREE.Vector2(this.container.offsetWidth, this.container.offsetHeight), this.scene, this.camera);
this.outlinePass.edgeStrength = 5.0;
this.outlinePass.edgeGlow = 0.5;
this.outlinePass.edgeThickness = 2.0;
this.composer.addPass(this.outlinePass);
this.composerFinal.addPass(this.outlinePass);

// Set up antialiasing.
// Set up antialiasing pass.
this.fxaaPass = new THREE.ShaderPass(THREE.FXAAShader);
const pixelRatio = this.renderer.getPixelRatio();
this.fxaaPass.material.uniforms['resolution'].value.x = 1 / (this.container.offsetWidth * pixelRatio);
this.fxaaPass.material.uniforms['resolution'].value.y = 1 / (this.container.offsetHeight * pixelRatio);
this.composer.addPass(this.fxaaPass);
this.composerFinal.addPass(this.fxaaPass);

// Render depth pass if the user has enabled debug
// and `depth=true` is in the URL parameters.
if (this.debug && this.urlParams.get('depth')=='true') {
this.depthPass = new THREE.ShaderPass( DepthShader );
this.depthPass.uniforms['tDepth'].value = this.depthRenderTarget.depthTexture;
this.depthPass.needsSwap = true;
this.depthPass.renderToScreen = true;
this.composerFinal.addPass(this.depthPass);
}

// Render haze pass if `haze=true` is in the URL parameters.
if (this.urlParams.get('haze')=='true') {
this.hazePass = new THREE.ShaderPass( HazeShader );
this.hazePass.uniforms['tDepth'].value = this.depthRenderTarget.depthTexture;
this.hazePass.needsSwap = true;
this.hazePass.renderToScreen = true;
this.composerFinal.addPass(this.hazePass);
}

if (this.debug) {
this.axes = Axes.axes3D({
Expand Down Expand Up @@ -977,7 +1026,10 @@ class App {
requestAnimationFrame(() => {
this.renderRequested = false;
// this.renderer.render( this.scene, this.camera );
this.composer.render();

this.composerPreprocess.render();
this.composerFinal.render();

//console.log([window.performance.memory.totalJSHeapSize, window.performance.memory.usedJSHeapSize]);
});
}
Expand Down
59 changes: 59 additions & 0 deletions shaders/depth_shader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
var DepthShader = {

uniforms: {

'tDepth': { value: null }

},

vertexShader: [

'varying vec2 vUv;',

'void main() {',

' vUv = uv;',

' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',

'}'

].join( '\n' ),

fragmentShader: [

'#include <common>',

'#include <packing>',

'uniform sampler2D tDepth;',

'varying vec2 vUv;',

'float readDepth( sampler2D depthSampler, vec2 coord ) {',

' float cameraFar = 100.0;',

' float fragCoordZ = texture2D( depthSampler, coord ).x;',

' float viewZ = perspectiveDepthToViewZ( fragCoordZ, 1.0, cameraFar );',

' return viewZToOrthographicDepth( viewZ, 1.0, cameraFar );',

'}',

'void main() {',

' float depth = readDepth( tDepth, vUv );',

' gl_FragColor.rgb = 1.0 - vec3( depth );',

' gl_FragColor.a = 1.0;',

'}'

].join( '\n' )

};

export {DepthShader};
67 changes: 67 additions & 0 deletions shaders/haze_shader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
var HazeShader = {

uniforms: {

'tDepth': { value: null },

'tDiffuse': { value: null },

},

vertexShader: [

'varying vec2 vUv;',

'void main() {',

' vUv = uv;',

' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',

'}'

].join( '\n' ),

fragmentShader: [

'#include <common>',

'#include <packing>',

'uniform sampler2D tDepth;',

'uniform sampler2D tDiffuse;',

'varying vec2 vUv;',

'float readDepth( sampler2D depthSampler, vec2 coord ) {',

' float cameraFar = 200.0;',

' float fragCoordZ = texture2D( depthSampler, coord ).x;',

' float viewZ = perspectiveDepthToViewZ( fragCoordZ, 1.0, cameraFar );',

' return viewZToOrthographicDepth( viewZ, 1.0, cameraFar );',

'}',

'void main() {',

' float depth = readDepth( tDepth, vUv );',

' vec4 color = texture2D( tDiffuse, vUv );',

' vec4 haze = vec4( 0.9, 0.8, 0.8, 1.0);',

' float intensity = depth * 0.6;',

' gl_FragColor = mix(color, haze, intensity);',

'}'

].join( '\n' )

};

export {HazeShader};