@damienmortini/three
Version:
113 lines (103 loc) • 3.99 kB
JavaScript
import LightShader from '@damienmortini/core/shader/LightShader.js';
import PBRShader from '@damienmortini/core/shader/PBRShader.js';
import RayShader from '@damienmortini/core/shader/RayShader.js';
import { Color, ShaderChunk, Vector3 } from '../../../three/src/Three.js';
import THREEShaderMaterial from './THREEShaderMaterial.js';
export default class THREEPBRMaterial extends THREEShaderMaterial {
constructor({
webgl2 = true,
vertexChunks = [],
fragmentChunks = [],
uniforms = {},
pbrDiffuseLightFromRay = (uniforms.envMap
? `
vec4 texel = ${webgl2 ? 'textureLod' : 'textureCubeLodEXT'}(envMap, ray.direction, roughness * ${Math.log2(uniforms.envMap.image.width).toFixed(1)});
return texel.rgb;
`
: undefined),
pbrReflectionFromRay = (uniforms.envMap
? `
vec4 texel = ${webgl2 ? 'textureLod' : 'textureCubeLodEXT'}(envMap, ray.direction, roughness * ${Math.log2(uniforms.envMap.image.width).toFixed(1)});
return texel.rgb;
`
: undefined),
...options
} = {}) {
super({
lights: !!uniforms.light,
uniforms: {
baseColor: new Color('#ffffff'),
metalness: 0,
roughness: 0,
opacity: 1,
light: {
intensity: 0,
color: new Color('#ffffff'),
position: new Vector3(),
direction: new Vector3(),
},
...uniforms,
},
vertex: `
void main() {
}
`,
vertexChunks: [
['start', `
${options.skinning ? '#include <skinning_pars_vertex>' : ''}
varying vec3 vPosition;
varying vec3 vNormal;
varying vec2 vUv;
varying vec3 vWorldPosition;
varying vec3 vViewDirection;
`],
['main', `
vec3 pbrPosition = position;
vec3 pbrNormal = normal;
${options.skinning ? ShaderChunk.skinbase_vertex : ''}
${options.skinning ? ShaderChunk.skinnormal_vertex.replace(/objectNormal/g, 'pbrNormal') : ''}
${options.skinning ? ShaderChunk.skinning_vertex.replace(/transformed/g, 'pbrPosition') : ''}
`],
['end', `
vec3 pbrWorldPosition = (modelMatrix * vec4(pbrPosition, 1.)).xyz;
gl_Position = projectionMatrix * viewMatrix * vec4(pbrWorldPosition, 1.);
vWorldPosition = pbrWorldPosition;
vViewDirection = normalize(pbrWorldPosition - cameraPosition);
vPosition = pbrPosition;
vNormal = normalize(mat3(modelMatrix) * pbrNormal);
vUv = uv;
`],
...vertexChunks,
],
fragmentChunks: [
['start', `
${LightShader.Light}
${RayShader.Ray}
${PBRShader.MetallicRoughnessMaterial}
uniform vec3 baseColor;
uniform float metalness;
uniform float roughness;
uniform float opacity;
uniform Light light;
${uniforms.envMap ? 'uniform samplerCube envMap;' : ''}
${uniforms.map ? 'uniform sampler2D map;' : ''}
varying vec3 vNormal;
varying vec3 vPosition;
varying vec2 vUv;
varying vec3 vWorldPosition;
varying vec3 vViewDirection;
${PBRShader.computePBRColor({ pbrReflectionFromRay, pbrDiffuseLightFromRay })}
`],
['main', `
${uniforms.map ? 'vec4 mapTexel = texture2D(map, vUv);' : ''}
vec4 pbrColor = computePBRColor(vViewDirection, light, vPosition, vNormal, MetallicRoughnessMaterial(vec4(${uniforms.map ? 'baseColor * pow(mapTexel.rgb, vec3(2.2))' : 'baseColor'}, ${uniforms.map ? 'opacity * mapTexel.a' : 'opacity'}), metalness, roughness));
`],
['end', `
gl_FragColor = pbrColor;
`],
...fragmentChunks,
],
...options,
});
}
}