question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Skinned Mesh producing faint artifact with SSAO Pass

See original GitHub issue

Description of the bug

Skinned meshes cause incorrect depth calculations, that affect the SSAO pass. I suspect that the problem might be possibly in three.js itself, but I can’t know for sure, as this artifact only appears with post-processing enabled. This is more pronounced with Skinned meshes, but I actually think that it’s a depth problem in general.

To Reproduce

Use a skinned mesh (doesn’t have to be playing an animation), and when inspecting the SSAO pass by setting the blend function mode to NORMAL, faint outlines of the base mesh can be visible.

Expected behavior

No faint outlines of the base mesh should be visible.

Screenshots

These two videos showcase well the outline issue.

https://user-images.githubusercontent.com/22790704/106307671-88b25f00-6257-11eb-969d-c3203c3b849f.mp4

https://user-images.githubusercontent.com/22790704/106307038-bea31380-6256-11eb-97a6-ce6deb8f2b4e.mp4

Library versions used

  • Three: 0.123.0
  • Post Processing: 6.20.1

Desktop

  • OS: Linux
  • Browser Firefox 85 and Chromium 88
  • Graphics hardware: AMD RX 480

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:12 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
veryprofessionaldodocommented, Feb 5, 2021

Thanks for the help, truly! I’ll test these monday morning, thank you once again!

1reaction
vanruesccommented, Feb 5, 2021

I think the chain should look more like this:

const renderPass = new RenderPass(scene, camera);
const customDepthPass = new CustomDepthPass();
const normalPass = new NormalPass();

const depthDownsamplingPass = new DepthDownsamplingPass({
	normalBuffer: normalPass.texture
});

const ssaoEffect = new SSAOEffect(camera, null, {
	normalDepthBuffer: depthDownsamplingPass.texture
});

const effectPass = new EffectPass(camera, ssaoEffect);

composer.addPass(renderPass);
composer.addPass(customDepthPass);
composer.addPass(normalPass);
composer.addPass(depthDownsamplingPass);
composer.addPass(effectPass);

depthDownsamplingPass.setDepthTexture(customDepthPass.texture, RGBADepthPacking);
effectPass.setDepthTexture(customDepthPass.texture, RGBADepthPacking);
CustomDepthMaterial (untested)

import { RGBADepthPacking, ShaderMaterial } from "three";

const depthVertexShader = `
#include <common>
#include <uv_pars_vertex>
#include <displacementmap_pars_vertex>
#include <morphtarget_pars_vertex>
#include <skinning_pars_vertex>
#include <clipping_planes_pars_vertex>

varying vec2 vHighPrecisionZW;

void main() {

	#include <uv_vertex>
	#include <skinbase_vertex>

	#ifdef USE_DISPLACEMENTMAP

		#include <beginnormal_vertex>
		#include <morphnormal_vertex>
		#include <skinnormal_vertex>

	#endif

	#include <begin_vertex>
	#include <morphtarget_vertex>
	#include <skinning_vertex>
	#include <displacementmap_vertex>
	#include <project_vertex>
	#include <clipping_planes_vertex>

	vHighPrecisionZW = gl_Position.zw;

}`;

const depthFragmentShader = `
#if DEPTH_PACKING == 3200

	uniform float opacity;

#endif

#include <common>
#include <packing>
#include <uv_pars_fragment>
#include <map_pars_fragment>
#include <alphamap_pars_fragment>
#include <clipping_planes_pars_fragment>

varying vec2 vHighPrecisionZW;

void main() {

	#include <clipping_planes_fragment>
	vec4 diffuseColor = vec4(1.0);

	#if DEPTH_PACKING == 3200

		diffuseColor.a = opacity;

	#endif

	#include <map_fragment>
	#include <alphamap_fragment>
	#include <alphatest_fragment>

	// Higher precision equivalent of gl_FragCoord.z.
	float fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;

	#if DEPTH_PACKING == 3200

		gl_FragColor = vec4(vec3(1.0 - fragCoordZ), opacity);

	#elif DEPTH_PACKING == 3201

		gl_FragColor = packDepthToRGBA(fragCoordZ);

	#endif

}`;

class CustomDepthMaterial extends ShaderMaterial {

	constructor(depthPacking = RGBADepthPacking) {

		super({

			type: "CustomDepthMaterial",

			defines: {
				DEPTH_PACKING: depthPacking.toFixed(0)
			},

			fragmentShader: depthFragmentShader,
			vertexShader: depthVertexShader

		});

	}

}

CustomDepthPass (untested)

import { RGBADepthPacking } from "three";
import { CustomDepthMaterial } from "./CustomDepthMaterial";

export class CustomDepthPass extends DepthPass {

	constructor(scene, camera, options) {

		super(scene, camera, options);

		this.renderPass.overrideMaterial = new CustomDepthMaterial({
			depthPacking: RGBADepthPacking
		});

	}

}

Read more comments on GitHub >

github_iconTop Results From Across the Web

Ambient Occlusion | Unreal Engine 4.27 Documentation
Screen Space Ambient Occlusion (SSAO) is an effect that approximates the attenuation of light due to occlusion. This is generally best used as...
Read more >
Chapter 12. High-Quality Ambient Occlusion - NVIDIA Developer
Ambient occlusion is a technique used in production to approximate the effect of environment ... Figure 12-1 Artifacts on a Sparsely Tessellated Mesh....
Read more >
Know your SSAO artifacts | IceFall Games - WordPress.com
I'm going to mainly discuss artifacts related to the sampling of points. Generally, for SSAO you use a number of randomly generated sample ......
Read more >
Vulkan: Strange black line artifact in SSAO when Half Size is ...
When SSAO quality is set to above "Low (Fast)" a weird line appears directly in the middle of the screen - it seems...
Read more >
Graphics – The Code Corsair
The simplest scheme generates random samples within the pixel, but there are better ways of producing fixed sequences of samples.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found