Ray-Box-Intersection like in the threejs example but withugly dashed edges. Maybe a problem with my FXAA shader?

I want to make ray box intersections like in the volumetric clouds example.
I’ve been struggling with an annoying problem for a long time. I made a snippet from my app. Here is the github link:

You can move with wasd, the arrow keys and space.

As you can see in the screenshot, my problem are the ugly white dashed edges. I just can’t figure out where it’s coming from and what I can do about it.

I have tried to reduce the app as much as possible in the hope of limiting the phenomenon.

The RayBox intersection can be found in the shader cloudsFS.js in the shader folder in resources. threejs is initialized in threejs-component.js and in the main the composer, renderer and camera are passed to cloud. There’s nothing that would be complicated in any way, but as I said, I just can’t figure out where these ugly lines are coming from. I reduced the shader a lot so that all the volume calculations are gone. With these, the dashed lines would also go up. I suspect there is a missing setting in the composer, because the ray-cube-intersection is very simple. I have the box from the volumetric clouds example

import {THREE, OrbitControls, RenderPass, ShaderPass, EffectComposer, CopyShader, FXAAShader, WebGL} from './three-defs.js';
import {entity} from "./entity.js";


export const threejs_component = (() => {

	class ThreeJSController extends entity.Component {
		constructor() {
			super();
		}

		InitEntity() {
    	
    		if (!WebGL.isWebGL2Available()) {
    			return false;
			}
	
			const canvas = document.createElement('canvas');
			const context = canvas.getContext('webgl2');
		
			this.threejs_ = new THREE.WebGLRenderer({ 
				canvas: canvas,
				context: context,
				antialias: true
			});
    	
			this.threejs_.outputEncoding = THREE.sRGBEncoding;
			this.threejs_.setPixelRatio(window.devicePixelRatio);
			this.threejs_.shadowMap.enabled = true;
			this.threejs_.shadowMap.type = THREE.PCFSoftShadowMap;
			this.threejs_.physicallyCorrectLights = true;
			this.threejs_.domElement.id = 'threejs';
				
			this.container = document.getElementById('container');
			this.threejs_.setSize(this.container.clientWidth, this.container.clientHeight);
			this.container.appendChild( this.threejs_.domElement );
	
			const aspect = this.container.clientWidth / this.container.clientHeight; 
			const fov = 50;
			const near = 1;
			const far = 1E6;
			this.camera_ = new THREE.PerspectiveCamera(fov, aspect, near, far);
			this.scene_ = new THREE.Scene();
			this.threejs_.setClearColor( 0x000000 );
						
			this.camera_.position.set(0, 0, 10000);
			
	
			this.fxaaPass = new ShaderPass( FXAAShader );

			var pixelRatio = this.threejs_.getPixelRatio();

			this.fxaaPass.material.uniforms[ 'resolution' ].value.x = 1 / ( this.container.clientWidth * pixelRatio );
			this.fxaaPass.material.uniforms[ 'resolution' ].value.y = 1 / ( this.container.clientHeight * pixelRatio );
					
			this.composer_ = new EffectComposer(this.threejs_);
			const renderPass = new RenderPass(this.scene_, this.camera_);
			this.composer_.addPass(renderPass);
			this.composer_.addPass(this.fxaaPass);
			
			
			this.resolution_ = new THREE.Vector2(); 
			this.threejs_.getDrawingBufferSize(this.resolution_);

			this.target_ = new THREE.WebGLRenderTarget(this.resolution_.x, this.resolution_.y);		
			this.target_.stencilBuffer = false;
			this.target_.depthBuffer = true;
			this.target_.depthTexture = new THREE.DepthTexture();
			this.target_.depthTexture.format = THREE.DepthFormat;
			this.target_.depthTexture.type = THREE.FloatType;		
			this.target_.depthTexture.minFilter = THREE.NearestFilter;
			this.target_.depthTexture.magFilter = THREE.NearestFilter;
	
	
			window.addEventListener('resize', () => {this.OnResize_();}, false);
		}//end init	
	

		Render() {

			this.threejs_.setRenderTarget(this.target_);
			this.threejs_.render(this.scene_, this.camera_);   
			this.threejs_.setRenderTarget( null );

			this.composer_.render();

		}

		Update(timeElapsed) {
			const player = this.FindEntity('player');
			if (!player) {
				return;
			}
			const pos = player._position; 

		}
     
		OnResize_() {
		
			let width, height;
		
			if(window.innerWidth > window.innerHeight){	
				width = 1.0 * window.innerWidth;
				height = 1.0 * window.innerHeight;				
			}		
			if(window.innerHeight > window.innerWidth){	
				width = 1.0 * window.innerWidth;
				height = 1.0 * window.innerHeight;				
			}
			
			this.camera_.aspect = width / height;
			this.camera_.updateProjectionMatrix();
    		
			this.threejs_.setSize(width, height);
		
			var pixelRatio = this.threejs_.getPixelRatio();

			this.fxaaPass.material.uniforms[ 'resolution' ].value.x = 1 / ( this.container.clientWidth * pixelRatio );
			this.fxaaPass.material.uniforms[ 'resolution' ].value.y = 1 / ( this.container.clientHeight * pixelRatio );
			
		}
  
  }//end class


  return {
      ThreeJSController: ThreeJSController,
  };
})();

My FXAAShader doesn’t work either. I installed it as shown in the example. But what I do differently is to mount my own shader. I do that in the module. I access the threejs composer to add my own shader with addPass. Maybe I don’t understand the composer chain well enough

import {entity} from './entity.js';
import {THREE, ShaderPass, FXAAShader} from './three-defs.js';
import {cloud_model} from './cloud-model.js';
import { cloudsVS } from "../resources/shader/cloudsVS.js";
import { cloudsFS } from "../resources/shader/cloudsFS.js";



export const clouds = (() => {

	class Clouds extends entity.Component {
		constructor(params){
			super();
			this.Init(params);
		}	
	
		Init(params){
			this.params_ = params;
	
			let source = this.params_.threejs;
		
			const clouds = "./resources/textures/clouds/clouds_2.jpg";
			const cloudmodel = new cloud_model.CloudModel({
				renderer: source.threejs_,
				clouds: clouds
			});

			this.sunDir = new THREE.Vector3(-1, 0, 0.5);
			this.sunDir.normalize();
			this.sunDist = 200E9;
			this.sunPos = this.sunDir.multiplyScalar(this.sunDist);
			
			let uniform = {			
				tDiffuse: { value: null },
				tDepth: { value: null },
				planetRadius: { value: 6350 },
				cloudsInnerRadius: { value: 6356 },
				cloudsOuterRadius: { value: 6371 },		
				oceanRadius: { value: null },
				cameraNear: { value: source.camera_.near },
				cameraFar: { value: source.camera_.far },
				cameraPos: { value: source.camera_.position },
				cameraForward: { value: null },
				inverseProjection: { value: null },
				inverseView: { value: null },
				planetPos: { value: null },
				sunColor: { value: null },
				sunPos: { value: this.sunPos },
				cloud: { value: cloudmodel.cloud},   
				worley: { value: cloudmodel.worley},   
				weather: { value: cloudmodel.weather},
			};

			this.clouds = new THREE.RawShaderMaterial({
				glslVersion: THREE.GLSL3,
				uniforms: uniform,
				vertexShader: cloudsVS,
				fragmentShader: cloudsFS,
			});			

			source.composer_.addPass(new ShaderPass(this.clouds));		
		}
		
		
	
		Update(_) {
		
			let source = this.params_.threejs;
			const forward = new THREE.Vector3();
			source.camera_.getWorldDirection(forward);
			
			this.clouds.uniforms.tDepth.value = source.target_.depthTexture;
			this.clouds.uniforms.planetPos.value = new THREE.Vector3(0, 0, 0);
			this.clouds.uniforms.cameraForward.value = forward;
			this.clouds.uniforms.inverseProjection.value = source.camera_.projectionMatrixInverse;
			this.clouds.uniforms.inverseView.value = source.camera_.matrixWorld;
			this.clouds.uniforms.cameraNear.value = source.camera_.near;
			this.clouds.uniforms.cameraFar.value = source.camera_.far;
			this.clouds.uniforms.cameraPos.value = source.camera_.position;
			this.clouds.uniforms.sunColor.value = new THREE.Vector3(1.0, 1.0, 1.0);	
			this.clouds.uniforms.sunPos.value = this.sunPos;	
			this.clouds.uniformsNeedUpdate = true;	
				
		}//end Update
	
	}


return {
	Clouds: Clouds
}

})();

OK, solved.

In the cloudsFS shader in the function sampleWeather I have a threshold if(weatherMap.r < 0.1) if I set this threshold to 0.5 then it looks fine. However, I also filter away a little more everywhere but ok. I still don’t understand why everything suddenly becomes fine from a threshold value of 0.4. I had dated this to 0.1 because that seemed enough to me.

It is not yet clear to me why this suddenly becomes good with a threshold value of 0.4. Seems I run into some accuracy overrun of the GPU. Well, solution found and something learned

1 Like