How to offset LineSegmentsGeometry in shader?

I am using LineSegmentsGeometry and LineMaterial. I want to offset the line in the shader (towards the camera, similar to how polygonOffset operates; note, polygonoffset doesn’t work for LineMaterial either)… I have tried the following:

this.material.isShaderMaterial = true;		//We need to set this so that the cameraPosition uniform is updated in the shader
		this.material.onBeforeCompile = function ( shader ) {
			shader.vertexShader = shader.vertexShader.replace(
				'#include <begin_vertex>',
				[
					'float myOffset = 0.0;',
					'myOffset = (vColor.r + vColor.g + vColor.b) < 3.0 ? 0.01 : 0.0;',
					'vec4 localPosition = vec4( position, 1.);',
					'vec4 worldPosition = modelMatrix * localPosition;',
					'vec3 look = myOffset * normalize( cameraPosition - vec3(worldPosition) );',
					'vec3 transformed = vec3( position ) + look;'
				].join( '\n' )
			);
			

		};

It doesn’t work. This has worked for other materials/meshes, but it seems the LineMaterial isn’t setup the same way… Any help on how to offset the lines in the shader towards the camera?

Hi!

There is no such line in the vertex shader of LineMaterial: three.js/examples/jsm/lines/LineMaterial.js at 7a5121685fe9c3c7c5d8d9c7ebb3887d5d023090 · mrdoob/three.js · GitHub

I need to somehow modify this:

vec2 offset = vec2( dir.y, - dir.x );
				// undo aspect ratio adjustment
				dir.x /= aspect;
				offset.x /= aspect;
				// sign flip
				if ( position.x < 0.0 ) offset *= - 1.0;
				// endcaps
				if ( position.y < 0.0 ) {
					offset += - dir;
				} else if ( position.y > 1.0 ) {
					offset += dir;
				}
				// adjust for linewidth
				offset *= linewidth;
				// adjust for clip-space to screen-space conversion // maybe resolution should be based on viewport ...
				offset /= resolution.y;
				// select end
				vec4 clip = ( position.y < 0.5 ) ? clipStart : clipEnd;
				// back to clip space
				offset *= clip.w;
				clip.xy += offset;

I tried to do this:

shader.vertexShader = shader.vertexShader.replace(
				'clip.xy += offset;',
				[
					'clip.xy += offset;',
					'',
					'float myOffset = 0.040;',
					'vec3 look = myOffset * normalize( cameraPosition - vec3(clip) );',
					'clip.xyz += look;'
				].join( '\n' )
			);

however, it is offsetting it in an unusual way.

Okay, I figured it out:

this.material.isShaderMaterial = true;		//We need to set this so that the cameraPosition uniform is updated in the shader
		this.material.onBeforeCompile = function ( shader ) {
			shader.vertexShader = shader.vertexShader.replace(
				'worldStart = start.xyz;',
				[
					'float myOffset = -0.040;',
					'vec3 look = myOffset * normalize( vec3( start ) );',
					'start.xyz += look.xyz;',
					'look = myOffset * normalize( vec3( end ) );',
					'end.xyz += look.xyz;',
					'',
					'worldStart = start.xyz;'
				].join( '\n' )
			);
			
		};
1 Like