Adding custom shader
I'm trying to add fresnel shader to my mesh
I did not write the shader myself, I tried turning it into a string as it's what is required. The original uniforms were declared using new THREE.color('black') but I do not have access to the THREE functions it seems
<Mesh ref="box">
<TorusKnotGeometry :radius="1.5" :tube="0.625" :tubularSegments="300" :radialSegments="200" />
<LambertMaterial :color="'#0F161B'" />
<ShaderMaterial :props="{ uniforms: uniforms, vertexShader: vertex, fragmentShader: fragment }" />
</Mesh>
data() {
return {
header: 'varying vec3 vNN; varying vec3 vEye;',
fragmentHeader: 'uniform vec3 fresnelColor;',
vertex: `
mat4 LM = modelMatrix;
LM[2][3] = 0.0;
LM[3][0] = 0.0;
LM[3][1] = 0.0;
LM[3][2] = 0.0;
vec4 GN = LM * vec4(objectNormal.xyz, 1.0);
vNN = normalize(GN.xyz);
vEye = normalize(GN.xyz-cameraPosition);`
,
fragment: `
gl_FragColor = vec4( outgoingLight, diffuseColor.a );
gl_FragColor.rgb += ( 1.0 - -min(dot(vEye, normalize(vNN) ), 0.0) ) * fresnelColor;
`
,
uniforms: {
diffuse: '#ff0000',
fresnelColor: '#ff0000'
}
}
},
Error:
Error 0 - VALIDATE_STATUS false
Program Info Log: Vertex shader is not compiled.
The original setup I copied was using objects so it would return "string.replace is not a function"
Any idea how to do this ? Or a simpler way of adding fresnel ?
Original code
var material = THREE.extendMaterial(THREE.MeshStandardMaterial, {
// Will be prepended to vertex and fragment code
header: 'varying vec3 vNN; varying vec3 vEye;',
fragmentHeader: 'uniform vec3 fresnelColor;',
// Insert code lines by hinting at a existing
vertex: {
// Inserts the line after #include <fog_vertex>
'#include <fog_vertex>': `
mat4 LM = modelMatrix;
LM[2][3] = 0.0;
LM[3][0] = 0.0;
LM[3][1] = 0.0;
LM[3][2] = 0.0;
vec4 GN = LM * vec4(objectNormal.xyz, 1.0);
vNN = normalize(GN.xyz);
vEye = normalize(GN.xyz-cameraPosition);`
},
fragment: {
'gl_FragColor = vec4( outgoingLight, diffuseColor.a );' : `
gl_FragColor.rgb += ( 1.0 - -min(dot(vEye, normalize(vNN) ), 0.0) ) * fresnelColor;
`
},
// Uniforms (will be applied to existing or added)
uniforms: {
diffuse: new THREE.Color( 'black' ),
fresnelColor: new THREE.Color( 'blue' )
}
});
// mesh
mesh = new THREE.Mesh( geometry, material );
I see people accessing THREE.FresnelShader in this post https://discourse.threejs.org/t/material-with-emissionmap-and-fresnel-shader/6223 , but I can't find official three.js doc about it
Is there a way to directly use this somehow ?
You should create your own material component :
import { Color } from 'three'
import { StandardMaterial } from 'troisjs'
export default {
extends: StandardMaterial,
created() {
this.material.onBeforeCompile = (shader) => {
shader.uniforms.fresnelColor = { value: new Color(0x0000ff) }
shader.vertexShader = `
varying vec3 vNN;
varying vec3 vEye;
` + shader.vertexShader
shader.vertexShader = shader.vertexShader.replace(
'#include <fog_vertex>',
`
#include <fog_vertex>
mat4 LM = modelMatrix;
LM[2][3] = 0.0;
LM[3][0] = 0.0;
LM[3][1] = 0.0;
LM[3][2] = 0.0;
vec4 GN = LM * vec4(objectNormal.xyz, 1.0);
vNN = normalize(GN.xyz);
vEye = normalize(GN.xyz-cameraPosition);
`
)
shader.fragmentShader = `
uniform vec3 fresnelColor;
varying vec3 vNN;
varying vec3 vEye;
` + shader.fragmentShader
shader.fragmentShader = shader.fragmentShader.replace(
'#include <output_fragment>',
`
#include <output_fragment>
gl_FragColor.rgb += ( 1.0 - -min(dot(vEye, normalize(vNN) ), 0.0) ) * fresnelColor;
`
)
}
}
}
