Improve WebGL leather material
This commit is contained in:
+53
-26
@@ -175,40 +175,44 @@ const materials = {
|
|||||||
color: 0x25130b,
|
color: 0x25130b,
|
||||||
map: leatherTextures.color,
|
map: leatherTextures.color,
|
||||||
normalMap: leatherTextures.normal,
|
normalMap: leatherTextures.normal,
|
||||||
normalScale: new THREE.Vector2(0.055, 0.055),
|
normalScale: new THREE.Vector2(0.07, 0.07),
|
||||||
roughness: 0.72,
|
roughnessMap: leatherTextures.roughness,
|
||||||
|
roughness: 0.78,
|
||||||
metalness: 0.02,
|
metalness: 0.02,
|
||||||
envMapIntensity: 0.08,
|
envMapIntensity: 0.1,
|
||||||
side: THREE.DoubleSide
|
side: THREE.DoubleSide
|
||||||
}),
|
}),
|
||||||
hingeLeather: new THREE.MeshStandardMaterial({
|
hingeLeather: new THREE.MeshStandardMaterial({
|
||||||
color: 0x32180c,
|
color: 0x32180c,
|
||||||
map: leatherTextures.color,
|
map: leatherTextures.color,
|
||||||
normalMap: leatherTextures.normal,
|
normalMap: leatherTextures.normal,
|
||||||
normalScale: new THREE.Vector2(0.048, 0.048),
|
normalScale: new THREE.Vector2(0.062, 0.062),
|
||||||
roughness: 0.78,
|
roughnessMap: leatherTextures.roughness,
|
||||||
|
roughness: 0.82,
|
||||||
metalness: 0.015,
|
metalness: 0.015,
|
||||||
envMapIntensity: 0.06,
|
envMapIntensity: 0.08,
|
||||||
side: THREE.DoubleSide
|
side: THREE.DoubleSide
|
||||||
}),
|
}),
|
||||||
spineBaseLeather: new THREE.MeshStandardMaterial({
|
spineBaseLeather: new THREE.MeshStandardMaterial({
|
||||||
color: 0x2a1209,
|
color: 0x2a1209,
|
||||||
map: leatherTextures.color,
|
map: leatherTextures.color,
|
||||||
normalMap: leatherTextures.normal,
|
normalMap: leatherTextures.normal,
|
||||||
normalScale: new THREE.Vector2(0.042, 0.042),
|
normalScale: new THREE.Vector2(0.055, 0.055),
|
||||||
roughness: 0.82,
|
roughnessMap: leatherTextures.roughness,
|
||||||
|
roughness: 0.86,
|
||||||
metalness: 0.01,
|
metalness: 0.01,
|
||||||
envMapIntensity: 0.04,
|
envMapIntensity: 0.06,
|
||||||
side: THREE.DoubleSide
|
side: THREE.DoubleSide
|
||||||
}),
|
}),
|
||||||
coverEdge: new THREE.MeshStandardMaterial({
|
coverEdge: new THREE.MeshStandardMaterial({
|
||||||
color: 0x5b351b,
|
color: 0x5b351b,
|
||||||
map: leatherTextures.color,
|
map: leatherTextures.color,
|
||||||
normalMap: leatherTextures.normal,
|
normalMap: leatherTextures.normal,
|
||||||
normalScale: new THREE.Vector2(0.052, 0.052),
|
normalScale: new THREE.Vector2(0.068, 0.068),
|
||||||
roughness: 0.76,
|
roughnessMap: leatherTextures.roughness,
|
||||||
|
roughness: 0.8,
|
||||||
metalness: 0.015,
|
metalness: 0.015,
|
||||||
envMapIntensity: 0.05,
|
envMapIntensity: 0.07,
|
||||||
side: THREE.DoubleSide
|
side: THREE.DoubleSide
|
||||||
}),
|
}),
|
||||||
pageBlock: new THREE.MeshStandardMaterial({
|
pageBlock: new THREE.MeshStandardMaterial({
|
||||||
@@ -252,6 +256,9 @@ const materials = {
|
|||||||
}),
|
}),
|
||||||
spineCloth: new THREE.MeshStandardMaterial({
|
spineCloth: new THREE.MeshStandardMaterial({
|
||||||
color: 0x8e1d18,
|
color: 0x8e1d18,
|
||||||
|
normalMap: leatherTextures.normal,
|
||||||
|
normalScale: new THREE.Vector2(0.04, 0.04),
|
||||||
|
roughnessMap: leatherTextures.roughness,
|
||||||
roughness: 0.82,
|
roughness: 0.82,
|
||||||
metalness: 0,
|
metalness: 0,
|
||||||
envMapIntensity: 0.08,
|
envMapIntensity: 0.08,
|
||||||
@@ -1840,22 +1847,31 @@ function createLeatherTextures() {
|
|||||||
const size = 1024;
|
const size = 1024;
|
||||||
const colorCanvas = document.createElement('canvas');
|
const colorCanvas = document.createElement('canvas');
|
||||||
const normalCanvas = document.createElement('canvas');
|
const normalCanvas = document.createElement('canvas');
|
||||||
|
const roughnessCanvas = document.createElement('canvas');
|
||||||
colorCanvas.width = size;
|
colorCanvas.width = size;
|
||||||
colorCanvas.height = size;
|
colorCanvas.height = size;
|
||||||
normalCanvas.width = size;
|
normalCanvas.width = size;
|
||||||
normalCanvas.height = size;
|
normalCanvas.height = size;
|
||||||
|
roughnessCanvas.width = size;
|
||||||
|
roughnessCanvas.height = size;
|
||||||
const colorContext = colorCanvas.getContext('2d');
|
const colorContext = colorCanvas.getContext('2d');
|
||||||
const normalContext = normalCanvas.getContext('2d');
|
const normalContext = normalCanvas.getContext('2d');
|
||||||
|
const roughnessContext = roughnessCanvas.getContext('2d');
|
||||||
const colorImage = colorContext.createImageData(size, size);
|
const colorImage = colorContext.createImageData(size, size);
|
||||||
const normalImage = normalContext.createImageData(size, size);
|
const normalImage = normalContext.createImageData(size, size);
|
||||||
|
const roughnessImage = roughnessContext.createImageData(size, size);
|
||||||
const heightAt = (x, y) => {
|
const heightAt = (x, y) => {
|
||||||
const nx = x / size;
|
const nx = x / size;
|
||||||
const ny = y / size;
|
const ny = y / size;
|
||||||
const longGrain = Math.sin((nx * 18 + Math.sin(ny * 18.8495559215) * 0.24) * 6.28318530718);
|
const longGrain = Math.sin((nx * 24 + Math.sin(ny * 31.4159265359) * 0.18) * 6.28318530718);
|
||||||
const crossGrain = Math.sin((ny * 42 + Math.sin(nx * 12.5663706144) * 0.16) * 6.28318530718);
|
const secondaryGrain = Math.sin((nx * 63 + ny * 9 + Math.sin(ny * 50.2654824574) * 0.1) * 6.28318530718);
|
||||||
const poreA = Math.sin((nx * 91 + ny * 37) * 6.28318530718);
|
const crossGrain = Math.sin((ny * 39 + Math.sin(nx * 18.8495559215) * 0.12) * 6.28318530718);
|
||||||
const poreB = Math.sin((nx * 47 - ny * 83) * 6.28318530718);
|
const poreA = Math.sin((nx * 137 + ny * 71) * 6.28318530718);
|
||||||
return longGrain * 0.34 + crossGrain * 0.22 + poreA * poreB * 0.16;
|
const poreB = Math.sin((nx * 97 - ny * 113) * 6.28318530718);
|
||||||
|
const pebble = Math.sin((nx * 181 + Math.sin(ny * 25.1327412287) * 0.22) * 6.28318530718) *
|
||||||
|
Math.sin((ny * 167 + Math.sin(nx * 37.6991118431) * 0.18) * 6.28318530718);
|
||||||
|
const pit = Math.max(0, 0.58 - Math.abs(poreA * poreB));
|
||||||
|
return longGrain * 0.22 + secondaryGrain * 0.16 + crossGrain * 0.1 + pebble * 0.18 - pit * 0.24;
|
||||||
};
|
};
|
||||||
|
|
||||||
for (let y = 0; y < size; y += 1) {
|
for (let y = 0; y < size; y += 1) {
|
||||||
@@ -1863,34 +1879,44 @@ function createLeatherTextures() {
|
|||||||
const wrappedX = (x + size) % size;
|
const wrappedX = (x + size) % size;
|
||||||
const wrappedY = (y + size) % size;
|
const wrappedY = (y + size) % size;
|
||||||
const height = heightAt(wrappedX, wrappedY);
|
const height = heightAt(wrappedX, wrappedY);
|
||||||
const grain = THREE.MathUtils.clamp(0.54 + height * 0.22, 0, 1);
|
const grain = THREE.MathUtils.clamp(0.58 + height * 0.24, 0, 1);
|
||||||
const warm = 0.82 + 0.18 * Math.sin((x * 0.07 + y * 0.013));
|
const warm = 0.86 + 0.1 * Math.sin((x * 0.045 + y * 0.011)) + 0.04 * Math.sin((x * 0.009 - y * 0.031));
|
||||||
const index = (y * size + x) * 4;
|
const index = (y * size + x) * 4;
|
||||||
colorImage.data[index] = Math.round(132 * grain * warm);
|
colorImage.data[index] = Math.round(118 * grain * warm);
|
||||||
colorImage.data[index + 1] = Math.round(66 * grain * warm);
|
colorImage.data[index + 1] = Math.round(54 * grain * warm);
|
||||||
colorImage.data[index + 2] = Math.round(29 * grain);
|
colorImage.data[index + 2] = Math.round(22 * grain);
|
||||||
colorImage.data[index + 3] = 255;
|
colorImage.data[index + 3] = 255;
|
||||||
|
|
||||||
const hLeft = heightAt((x - 1 + size) % size, wrappedY);
|
const hLeft = heightAt((x - 1 + size) % size, wrappedY);
|
||||||
const hRight = heightAt((x + 1) % size, wrappedY);
|
const hRight = heightAt((x + 1) % size, wrappedY);
|
||||||
const hDown = heightAt(wrappedX, (y - 1 + size) % size);
|
const hDown = heightAt(wrappedX, (y - 1 + size) % size);
|
||||||
const hUp = heightAt(wrappedX, (y + 1) % size);
|
const hUp = heightAt(wrappedX, (y + 1) % size);
|
||||||
const normal = new THREE.Vector3((hLeft - hRight) * 2.8, (hDown - hUp) * 2.8, 1).normalize();
|
const normal = new THREE.Vector3((hLeft - hRight) * 4.1, (hDown - hUp) * 4.1, 1).normalize();
|
||||||
normalImage.data[index] = Math.round((normal.x * 0.5 + 0.5) * 255);
|
normalImage.data[index] = Math.round((normal.x * 0.5 + 0.5) * 255);
|
||||||
normalImage.data[index + 1] = Math.round((normal.y * 0.5 + 0.5) * 255);
|
normalImage.data[index + 1] = Math.round((normal.y * 0.5 + 0.5) * 255);
|
||||||
normalImage.data[index + 2] = Math.round((normal.z * 0.5 + 0.5) * 255);
|
normalImage.data[index + 2] = Math.round((normal.z * 0.5 + 0.5) * 255);
|
||||||
normalImage.data[index + 3] = 255;
|
normalImage.data[index + 3] = 255;
|
||||||
|
|
||||||
|
const fiberContrast = Math.abs(hLeft - hRight) + Math.abs(hDown - hUp);
|
||||||
|
const roughness = THREE.MathUtils.clamp(0.76 + height * 0.1 + fiberContrast * 1.4, 0.5, 0.96);
|
||||||
|
const roughnessByte = Math.round(roughness * 255);
|
||||||
|
roughnessImage.data[index] = roughnessByte;
|
||||||
|
roughnessImage.data[index + 1] = roughnessByte;
|
||||||
|
roughnessImage.data[index + 2] = roughnessByte;
|
||||||
|
roughnessImage.data[index + 3] = 255;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
colorContext.putImageData(colorImage, 0, 0);
|
colorContext.putImageData(colorImage, 0, 0);
|
||||||
normalContext.putImageData(normalImage, 0, 0);
|
normalContext.putImageData(normalImage, 0, 0);
|
||||||
|
roughnessContext.putImageData(roughnessImage, 0, 0);
|
||||||
const colorTexture = new THREE.CanvasTexture(colorCanvas);
|
const colorTexture = new THREE.CanvasTexture(colorCanvas);
|
||||||
const normalTexture = new THREE.CanvasTexture(normalCanvas);
|
const normalTexture = new THREE.CanvasTexture(normalCanvas);
|
||||||
[colorTexture, normalTexture].forEach((texture) => {
|
const roughnessTexture = new THREE.CanvasTexture(roughnessCanvas);
|
||||||
|
[colorTexture, normalTexture, roughnessTexture].forEach((texture) => {
|
||||||
texture.wrapS = THREE.RepeatWrapping;
|
texture.wrapS = THREE.RepeatWrapping;
|
||||||
texture.wrapT = THREE.RepeatWrapping;
|
texture.wrapT = THREE.RepeatWrapping;
|
||||||
texture.repeat.set(2.5, 1.6);
|
texture.repeat.set(3.6, 2.2);
|
||||||
texture.anisotropy = maxTextureAnisotropy;
|
texture.anisotropy = maxTextureAnisotropy;
|
||||||
texture.minFilter = THREE.LinearMipmapLinearFilter;
|
texture.minFilter = THREE.LinearMipmapLinearFilter;
|
||||||
texture.magFilter = THREE.LinearFilter;
|
texture.magFilter = THREE.LinearFilter;
|
||||||
@@ -1898,7 +1924,8 @@ function createLeatherTextures() {
|
|||||||
});
|
});
|
||||||
colorTexture.colorSpace = THREE.SRGBColorSpace;
|
colorTexture.colorSpace = THREE.SRGBColorSpace;
|
||||||
normalTexture.colorSpace = THREE.NoColorSpace;
|
normalTexture.colorSpace = THREE.NoColorSpace;
|
||||||
return { color: colorTexture, normal: normalTexture };
|
roughnessTexture.colorSpace = THREE.NoColorSpace;
|
||||||
|
return { color: colorTexture, normal: normalTexture, roughness: roughnessTexture };
|
||||||
}
|
}
|
||||||
|
|
||||||
function createRoomReflectionTexture() {
|
function createRoomReflectionTexture() {
|
||||||
|
|||||||
Reference in New Issue
Block a user