Custom StandardMaterial

I want to use the draw edges method from How to render geometry edges? - Questions - three.js forum (threejs.org) but I also need to support AmbientLight, DirectionalLight, PointLight and SpotLight. How can I mix these shaders?

Hi!
What result do you want to achieve? Any explanatory or reference pic?

image

This cube has the StandardMaterial because it needs to be flat shaded, the cube is white and the scene have a directional light.

image

This is the same cube with ambient light instead of directional.

I’d like both have the edges visible.

For some ideas, have a look at this post: Detecting objects which can camera see - #10 by prisoner849
MeshBasicMaterial + .onBeforeCompile

The shader of here doesn’t work because of some of my cubes are scaled.

The problem of MeshBasicMaterial + .onBeforeCompile is that I use both MeshBasicMaterial and MeshStandardMaterial in other places that I don’t want to show the edges.

Do you use instancing?

You can use a uniform, for example, a boolean one, for enable/disable box’s edges :thinking:

Do you use instancing?

Yes.

You can use a uniform, for example, a boolean one, for enable/disable box’s edges :thinking:

I guess this would solve, I gonna check it now.

I tried the following, but it didn’t work:

new MeshStandardMaterial({
	color: new Color().getHex(),
	flatShading: true,
	defines: { MY_EDGES: true },
	onBeforeCompile: (shader) => {
		shader.vertexShader = `
			attribute vec3 instData;
			${shader.vertexShader}
	  	`.replace(
			`#include <begin_vertex>`,
			`
				#include <begin_vertex>
			
				#ifdef MY_EDGES
					float aStep = instData.z;
					float halfStep = aStep * 0.5;
					float angle = mod(atan(instData.y, instData.x) + PI2, PI2);
					float radius = length(instData.xy);
							
					float currAngle = angle - halfStep + (aStep * position.x);
					transformed.x = cos(currAngle) * (radius - position.z) - instData.x;
					transformed.z = sin(currAngle) * (radius - position.z) - instData.y;
				#endif
			`
		);

		shader.fragmentShader = `
			float edgeFactor(vec2 p) {
				vec2 grid = abs(fract(p - 0.5) - 0.5) / fwidth(p);
				return min(grid.x, grid.y);
			}
			${shader.fragmentShader}
		`.replace(
			`vec4 diffuseColor = vec4( diffuse, opacity );`,
			`
				#ifdef MY_EDGES
					vec3 c = mix(vec3(0), diffuse, clamp(edgeFactor(vUv), 0., 1.));
					vec4 diffuseColor = vec4(c, opacity);
				#else
					vec4 diffuseColor = vec4(diffuse, opacity);
				#endif
			`
		);
	}
})

I meant a uniform, not a define.

I meant a uniform, not a define.

Oh, my mistake.

With uniforms it is having a strange behavior.

new MeshStandardMaterial({
	color: 0xffffff,
	flatShading: true,
	onBeforeCompile: (shader) => {
		shader.uniforms.edges = { value: true };

		shader.vertexShader = `
			uniform bool edges;
			attribute vec3 instData;
			${shader.vertexShader}
	  	`.replace(
			`#include <begin_vertex>`,
			`
				#include <begin_vertex>
						
				if (edges) {
					float aStep = instData.z;
					float halfStep = aStep * 0.5;
					float angle = mod(atan(instData.y, instData.x) + PI2, PI2);
					float radius = length(instData.xy);
							
					float currAngle = angle - halfStep + (aStep * position.x);
					transformed.x = cos(currAngle) * (radius - position.z) - instData.x;
					transformed.z = sin(currAngle) * (radius - position.z) - instData.y;
				}
			`
		);

		shader.fragmentShader = `
			uniform bool edges;

			float edgeFactor(vec2 p) {
				vec2 grid = abs(fract(p - 0.5) - 0.5) / fwidth(p);
				return min(grid.x, grid.y);
			}
			${shader.fragmentShader}
		`.replace(
			`vec4 diffuseColor = vec4( diffuse, opacity );`,
			`
				vec4 diffuseColor;

				if (edges) {
					vec3 c = mix(vec3(0), diffuse, clamp(edgeFactor(gl_PointCoord), 0., 1.));
					diffuseColor = vec4(c, opacity);
				} else {
					diffuseColor = vec4(diffuse, opacity);
				}
			`
		);
	}
})

image

I also tried to replace gl_PointCoord by vUv and by vUV, but both didn’t compile.

(I’m using a instanced mesh of box geometries)

Oh, wait, I thought you want to implement that approach for edges: How to render geometry edges? - #7 by prisoner849

1 Like