Add WebGL cloth and paper materials
This commit is contained in:
+283
-27
@@ -169,6 +169,8 @@ const rightTexture = new THREE.CanvasTexture(rightCanvas);
|
||||
texture.generateMipmaps = true;
|
||||
});
|
||||
const leatherTextures = createLeatherTextures();
|
||||
const spineClothTextures = createSpineClothTextures();
|
||||
const paperTextures = createHardcoverPaperTextures();
|
||||
|
||||
const materials = {
|
||||
leather: new THREE.MeshStandardMaterial({
|
||||
@@ -216,55 +218,80 @@ const materials = {
|
||||
side: THREE.DoubleSide
|
||||
}),
|
||||
pageBlock: new THREE.MeshStandardMaterial({
|
||||
color: 0xe3c98f,
|
||||
roughness: 0.82,
|
||||
color: 0xfffbef,
|
||||
map: paperTextures.color,
|
||||
normalMap: paperTextures.normal,
|
||||
normalScale: new THREE.Vector2(0.032, 0.032),
|
||||
roughnessMap: paperTextures.roughness,
|
||||
roughness: 0.88,
|
||||
metalness: 0,
|
||||
envMapIntensity: 0.08
|
||||
envMapIntensity: 0.06
|
||||
}),
|
||||
pageEdge: new THREE.MeshStandardMaterial({
|
||||
color: 0xc69f64,
|
||||
roughness: 0.92,
|
||||
color: 0xfff4cf,
|
||||
map: paperTextures.edge,
|
||||
normalMap: paperTextures.normal,
|
||||
normalScale: new THREE.Vector2(0.024, 0.024),
|
||||
roughnessMap: paperTextures.roughness,
|
||||
roughness: 0.94,
|
||||
metalness: 0,
|
||||
envMapIntensity: 0.08
|
||||
envMapIntensity: 0.05
|
||||
}),
|
||||
pageSurface: new THREE.MeshStandardMaterial({
|
||||
color: 0xf0c17a,
|
||||
roughness: 0.86,
|
||||
color: 0xfffbf0,
|
||||
map: paperTextures.color,
|
||||
normalMap: paperTextures.normal,
|
||||
normalScale: new THREE.Vector2(0.03, 0.03),
|
||||
roughnessMap: paperTextures.roughness,
|
||||
roughness: 0.9,
|
||||
metalness: 0,
|
||||
emissive: 0x1e1209,
|
||||
emissiveIntensity: 0.08,
|
||||
envMapIntensity: 0.04,
|
||||
emissive: 0x14110b,
|
||||
emissiveIntensity: 0.025,
|
||||
envMapIntensity: 0.035,
|
||||
side: THREE.DoubleSide
|
||||
}),
|
||||
leftPage: new THREE.MeshStandardMaterial({
|
||||
color: 0xffffff,
|
||||
map: leftTexture,
|
||||
roughness: 0.74,
|
||||
normalMap: paperTextures.normal,
|
||||
normalScale: new THREE.Vector2(0.025, 0.025),
|
||||
roughnessMap: paperTextures.roughness,
|
||||
roughness: 0.86,
|
||||
metalness: 0,
|
||||
emissive: 0x2d1e12,
|
||||
emissiveIntensity: 0.18,
|
||||
emissive: 0x11100c,
|
||||
emissiveIntensity: 0.035,
|
||||
side: THREE.DoubleSide
|
||||
}),
|
||||
rightPage: new THREE.MeshStandardMaterial({
|
||||
color: 0xffffff,
|
||||
map: rightTexture,
|
||||
roughness: 0.74,
|
||||
normalMap: paperTextures.normal,
|
||||
normalScale: new THREE.Vector2(0.025, 0.025),
|
||||
roughnessMap: paperTextures.roughness,
|
||||
roughness: 0.86,
|
||||
metalness: 0,
|
||||
emissive: 0x2d1e12,
|
||||
emissiveIntensity: 0.18,
|
||||
emissive: 0x11100c,
|
||||
emissiveIntensity: 0.035,
|
||||
side: THREE.DoubleSide
|
||||
}),
|
||||
spineCloth: new THREE.MeshStandardMaterial({
|
||||
color: 0x8e1d18,
|
||||
normalMap: leatherTextures.normal,
|
||||
normalScale: new THREE.Vector2(0.04, 0.04),
|
||||
roughnessMap: leatherTextures.roughness,
|
||||
roughness: 0.82,
|
||||
color: 0x6f0808,
|
||||
map: spineClothTextures.color,
|
||||
normalMap: spineClothTextures.normal,
|
||||
normalScale: new THREE.Vector2(0.075, 0.075),
|
||||
roughnessMap: spineClothTextures.roughness,
|
||||
roughness: 0.9,
|
||||
metalness: 0,
|
||||
envMapIntensity: 0.08,
|
||||
envMapIntensity: 0.045,
|
||||
side: THREE.DoubleSide
|
||||
})
|
||||
};
|
||||
materials.spineCloth.userData.isSpineCloth = true;
|
||||
configureHardcoverPaperMaterial(materials.pageBlock);
|
||||
configureHardcoverPaperMaterial(materials.pageEdge, { useEdgeMap: true });
|
||||
configureHardcoverPaperMaterial(materials.pageSurface);
|
||||
configureHardcoverPaperMaterial(materials.leftPage);
|
||||
configureHardcoverPaperMaterial(materials.rightPage);
|
||||
|
||||
configureBookShadowReceiver(materials.leather, 0.52);
|
||||
configureBookShadowReceiver(materials.hingeLeather, 0.36);
|
||||
@@ -393,7 +420,9 @@ function loadUtilityTexture(url) {
|
||||
}
|
||||
|
||||
function configureBookShadowReceiver(material, strength) {
|
||||
material.customProgramCacheKey = () => `book-shadow-receiver-${strength.toFixed(2)}`;
|
||||
const isSpineCloth = material.userData?.isSpineCloth === true;
|
||||
const isHardcoverPaper = material.userData?.isHardcoverPaper === true;
|
||||
material.customProgramCacheKey = () => `book-shadow-receiver-${strength.toFixed(2)}-${isSpineCloth ? 'spine-cloth-v1' : isHardcoverPaper ? 'hardcover-paper-v1' : 'plain'}`;
|
||||
material.onBeforeCompile = (shader) => {
|
||||
shader.uniforms.bookShadowMaps = { value: bookShadowTargets.map((target) => target.texture) };
|
||||
shader.uniforms.bookShadowMatrices = { value: bookShadowMatrices };
|
||||
@@ -403,7 +432,14 @@ function configureBookShadowReceiver(material, strength) {
|
||||
shader.vertexShader = shader.vertexShader
|
||||
.replace(
|
||||
'#include <common>',
|
||||
'#include <common>\nvarying vec3 vBookReceiverWorldPosition;'
|
||||
`#include <common>
|
||||
varying vec3 vBookReceiverWorldPosition;
|
||||
${isSpineCloth || isHardcoverPaper ? 'varying vec2 vBookSurfaceUv;' : ''}`
|
||||
)
|
||||
.replace(
|
||||
'#include <begin_vertex>',
|
||||
`${isSpineCloth || isHardcoverPaper ? 'vBookSurfaceUv = uv;' : ''}
|
||||
#include <begin_vertex>`
|
||||
)
|
||||
.replace(
|
||||
'#include <project_vertex>',
|
||||
@@ -419,6 +455,7 @@ function configureBookShadowReceiver(material, strength) {
|
||||
uniform vec2 bookShadowMapTexelSize;
|
||||
uniform float bookShadowReceiverStrength;
|
||||
varying vec3 vBookReceiverWorldPosition;
|
||||
${isSpineCloth || isHardcoverPaper ? 'varying vec2 vBookSurfaceUv;' : ''}
|
||||
|
||||
float bookReceiverUnpackRGBADepth(vec4 packedDepth) {
|
||||
const vec4 unpackFactors = vec4(
|
||||
@@ -485,11 +522,45 @@ function configureBookShadowReceiver(material, strength) {
|
||||
float shadow1 = bookReceiverSample1(bookShadowMatrices[1] * vec4(worldPosition, 1.0));
|
||||
float shadow2 = bookReceiverSample2(bookShadowMatrices[2] * vec4(worldPosition, 1.0));
|
||||
return clamp(max(max(shadow0, shadow1), shadow2), 0.0, 1.0);
|
||||
}
|
||||
|
||||
float spineClothThread(float coordinate, float frequency, float sharpness) {
|
||||
float wave = abs(fract(coordinate * frequency) - 0.5) * 2.0;
|
||||
return pow(1.0 - wave, sharpness);
|
||||
}
|
||||
|
||||
vec3 spineClothLight(vec2 uv, vec3 baseLight) {
|
||||
float warp = spineClothThread(uv.x + sin(uv.y * 18.0) * 0.002, 92.0, 2.4);
|
||||
float weft = spineClothThread(uv.y + sin(uv.x * 21.0) * 0.0016, 64.0, 2.1);
|
||||
float fineFiber = sin((uv.x * 420.0 + uv.y * 55.0) * 6.28318530718) *
|
||||
sin((uv.y * 380.0 - uv.x * 33.0) * 6.28318530718);
|
||||
float raisedThread = clamp(warp * 0.58 + weft * 0.44, 0.0, 1.0);
|
||||
float valley = clamp((1.0 - warp) * (1.0 - weft), 0.0, 1.0);
|
||||
vec3 threadTint = mix(vec3(0.55, 0.19, 0.16), vec3(1.18, 0.78, 0.58), raisedThread);
|
||||
float fiberShade = 0.9 + fineFiber * 0.035 - valley * 0.18;
|
||||
return baseLight * threadTint * fiberShade;
|
||||
}
|
||||
|
||||
float paperFiber(float coordinate, float frequency, float sharpness) {
|
||||
float wave = abs(fract(coordinate * frequency) - 0.5) * 2.0;
|
||||
return pow(1.0 - wave, sharpness);
|
||||
}
|
||||
|
||||
vec3 hardcoverPaperLight(vec2 uv, vec3 baseLight) {
|
||||
float laid = paperFiber(uv.y + sin(uv.x * 12.0) * 0.002, 88.0, 2.8);
|
||||
float chain = paperFiber(uv.x + sin(uv.y * 8.0) * 0.0015, 18.0, 1.6);
|
||||
float fleck = sin((uv.x * 241.0 + uv.y * 97.0) * 6.28318530718) *
|
||||
sin((uv.y * 211.0 - uv.x * 53.0) * 6.28318530718);
|
||||
float fiber = clamp(laid * 0.18 + chain * 0.1 + fleck * 0.025, -0.08, 0.24);
|
||||
vec3 paperTint = mix(vec3(0.92, 0.9, 0.82), vec3(1.12, 1.08, 0.96), clamp(0.58 + fiber, 0.0, 1.0));
|
||||
return baseLight * paperTint;
|
||||
}`
|
||||
)
|
||||
.replace(
|
||||
'#include <opaque_fragment>',
|
||||
`float bookReceiverShadow = bookReceiverShadowField(vBookReceiverWorldPosition) * bookShadowReceiverStrength;
|
||||
`${isSpineCloth ? 'outgoingLight = spineClothLight(vBookSurfaceUv, outgoingLight);' : ''}
|
||||
${isHardcoverPaper ? 'outgoingLight = hardcoverPaperLight(vBookSurfaceUv, outgoingLight);' : ''}
|
||||
float bookReceiverShadow = bookReceiverShadowField(vBookReceiverWorldPosition) * bookShadowReceiverStrength;
|
||||
outgoingLight *= mix(vec3(1.0), vec3(0.38, 0.29, 0.2), bookReceiverShadow);
|
||||
#include <opaque_fragment>`
|
||||
);
|
||||
@@ -1190,6 +1261,9 @@ function buildBook() {
|
||||
rightPage: materials.rightPage
|
||||
},
|
||||
configureMaterial(material, part) {
|
||||
if (part === 'pages') {
|
||||
configureHardcoverPaperMaterial(material, { useEdgeMap: material.map !== null });
|
||||
}
|
||||
const strength = part === 'spine'
|
||||
? 0.48
|
||||
: part === 'coverSpineBase'
|
||||
@@ -1208,6 +1282,18 @@ function buildBook() {
|
||||
book.add(proceduralBook.group);
|
||||
}
|
||||
|
||||
function configureHardcoverPaperMaterial(material, { useEdgeMap = false } = {}) {
|
||||
material.userData.isHardcoverPaper = true;
|
||||
if (!material.map) material.map = useEdgeMap ? paperTextures.edge : paperTextures.color;
|
||||
material.normalMap = paperTextures.normal;
|
||||
material.normalScale = material.normalScale ?? new THREE.Vector2(0.024, 0.024);
|
||||
material.roughnessMap = paperTextures.roughness;
|
||||
material.roughness = Math.max(material.roughness ?? 0.86, useEdgeMap ? 0.92 : 0.86);
|
||||
material.metalness = 0;
|
||||
material.envMapIntensity = Math.min(material.envMapIntensity ?? 0.05, 0.06);
|
||||
material.needsUpdate = true;
|
||||
}
|
||||
|
||||
function setReadingProgress(value) {
|
||||
const nextProgress = THREE.MathUtils.clamp(Number.parseFloat(value), 0, 1);
|
||||
if (!Number.isFinite(nextProgress)) return;
|
||||
@@ -1797,7 +1883,7 @@ function createPageCanvas(side) {
|
||||
canvas.width = pageTextureWidth;
|
||||
canvas.height = Math.round(pageTextureWidth * PROCEDURAL_BOOK.PAGE_DEPTH / PROCEDURAL_BOOK.PAGE_WIDTH);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.fillStyle = '#f5dfab';
|
||||
ctx.fillStyle = '#fffaf0';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
canvas.style.width = `${canvas.width}px`;
|
||||
canvas.style.height = `${canvas.height}px`;
|
||||
@@ -1928,6 +2014,176 @@ function createLeatherTextures() {
|
||||
return { color: colorTexture, normal: normalTexture, roughness: roughnessTexture };
|
||||
}
|
||||
|
||||
function createSpineClothTextures() {
|
||||
const size = 1024;
|
||||
const colorCanvas = document.createElement('canvas');
|
||||
const normalCanvas = document.createElement('canvas');
|
||||
const roughnessCanvas = document.createElement('canvas');
|
||||
colorCanvas.width = size;
|
||||
colorCanvas.height = size;
|
||||
normalCanvas.width = size;
|
||||
normalCanvas.height = size;
|
||||
roughnessCanvas.width = size;
|
||||
roughnessCanvas.height = size;
|
||||
const colorContext = colorCanvas.getContext('2d');
|
||||
const normalContext = normalCanvas.getContext('2d');
|
||||
const roughnessContext = roughnessCanvas.getContext('2d');
|
||||
const colorImage = colorContext.createImageData(size, size);
|
||||
const normalImage = normalContext.createImageData(size, size);
|
||||
const roughnessImage = roughnessContext.createImageData(size, size);
|
||||
const threadAt = (x, y) => {
|
||||
const nx = x / size;
|
||||
const ny = y / size;
|
||||
const warpPhase = nx * 112 + Math.sin(ny * 31.4159265359) * 0.025;
|
||||
const weftPhase = ny * 76 + Math.sin(nx * 25.1327412287) * 0.02;
|
||||
const warp = Math.pow(1 - Math.abs((warpPhase - Math.floor(warpPhase)) - 0.5) * 2, 2.2);
|
||||
const weft = Math.pow(1 - Math.abs((weftPhase - Math.floor(weftPhase)) - 0.5) * 2, 2.0);
|
||||
const fiber = Math.sin((nx * 430 + ny * 73) * 6.28318530718) * Math.sin((ny * 390 - nx * 41) * 6.28318530718);
|
||||
const nap = Math.sin((nx * 19 + ny * 7) * 6.28318530718);
|
||||
return warp * 0.46 + weft * 0.38 + fiber * 0.045 + nap * 0.055;
|
||||
};
|
||||
|
||||
for (let y = 0; y < size; y += 1) {
|
||||
for (let x = 0; x < size; x += 1) {
|
||||
const index = (y * size + x) * 4;
|
||||
const height = threadAt(x, y);
|
||||
const wornFiber = 0.86 + 0.1 * Math.sin((x * 0.019 + y * 0.037)) + 0.04 * Math.sin((x * 0.083 - y * 0.011));
|
||||
const threadGlow = THREE.MathUtils.clamp(0.58 + height * 0.46, 0, 1);
|
||||
colorImage.data[index] = Math.round(95 * threadGlow * wornFiber);
|
||||
colorImage.data[index + 1] = Math.round(10 * threadGlow * wornFiber);
|
||||
colorImage.data[index + 2] = Math.round(9 * (0.84 + height * 0.12));
|
||||
colorImage.data[index + 3] = 255;
|
||||
|
||||
const hLeft = threadAt((x - 1 + size) % size, y);
|
||||
const hRight = threadAt((x + 1) % size, y);
|
||||
const hDown = threadAt(x, (y - 1 + size) % size);
|
||||
const hUp = threadAt(x, (y + 1) % size);
|
||||
const normal = new THREE.Vector3((hLeft - hRight) * 5.4, (hDown - hUp) * 5.4, 1).normalize();
|
||||
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 + 2] = Math.round((normal.z * 0.5 + 0.5) * 255);
|
||||
normalImage.data[index + 3] = 255;
|
||||
|
||||
const fiberContrast = Math.abs(hLeft - hRight) + Math.abs(hDown - hUp);
|
||||
const roughness = THREE.MathUtils.clamp(0.84 + height * 0.07 + fiberContrast * 1.25, 0.62, 0.98);
|
||||
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);
|
||||
normalContext.putImageData(normalImage, 0, 0);
|
||||
roughnessContext.putImageData(roughnessImage, 0, 0);
|
||||
const colorTexture = new THREE.CanvasTexture(colorCanvas);
|
||||
const normalTexture = new THREE.CanvasTexture(normalCanvas);
|
||||
const roughnessTexture = new THREE.CanvasTexture(roughnessCanvas);
|
||||
[colorTexture, normalTexture, roughnessTexture].forEach((texture) => {
|
||||
texture.wrapS = THREE.RepeatWrapping;
|
||||
texture.wrapT = THREE.RepeatWrapping;
|
||||
texture.repeat.set(2.1, 4.4);
|
||||
texture.anisotropy = maxTextureAnisotropy;
|
||||
texture.minFilter = THREE.LinearMipmapLinearFilter;
|
||||
texture.magFilter = THREE.LinearFilter;
|
||||
texture.generateMipmaps = true;
|
||||
});
|
||||
colorTexture.colorSpace = THREE.SRGBColorSpace;
|
||||
normalTexture.colorSpace = THREE.NoColorSpace;
|
||||
roughnessTexture.colorSpace = THREE.NoColorSpace;
|
||||
return { color: colorTexture, normal: normalTexture, roughness: roughnessTexture };
|
||||
}
|
||||
|
||||
function createHardcoverPaperTextures() {
|
||||
const size = 1024;
|
||||
const colorCanvas = document.createElement('canvas');
|
||||
const edgeCanvas = document.createElement('canvas');
|
||||
const normalCanvas = document.createElement('canvas');
|
||||
const roughnessCanvas = document.createElement('canvas');
|
||||
[colorCanvas, edgeCanvas, normalCanvas, roughnessCanvas].forEach((canvas) => {
|
||||
canvas.width = size;
|
||||
canvas.height = size;
|
||||
});
|
||||
const colorContext = colorCanvas.getContext('2d');
|
||||
const edgeContext = edgeCanvas.getContext('2d');
|
||||
const normalContext = normalCanvas.getContext('2d');
|
||||
const roughnessContext = roughnessCanvas.getContext('2d');
|
||||
const colorImage = colorContext.createImageData(size, size);
|
||||
const edgeImage = edgeContext.createImageData(size, size);
|
||||
const normalImage = normalContext.createImageData(size, size);
|
||||
const roughnessImage = roughnessContext.createImageData(size, size);
|
||||
const fiberAt = (x, y) => {
|
||||
const nx = x / size;
|
||||
const ny = y / size;
|
||||
const laid = Math.sin((ny * 92 + Math.sin(nx * 25.1327412287) * 0.12) * 6.28318530718);
|
||||
const chain = Math.sin((nx * 18 + Math.sin(ny * 12.5663706144) * 0.06) * 6.28318530718);
|
||||
const pulpA = Math.sin((nx * 173 + ny * 67) * 6.28318530718);
|
||||
const pulpB = Math.sin((nx * 89 - ny * 131) * 6.28318530718);
|
||||
const fleck = Math.max(0, 0.5 - Math.abs(pulpA * pulpB));
|
||||
return laid * 0.08 + chain * 0.045 - fleck * 0.055;
|
||||
};
|
||||
|
||||
for (let y = 0; y < size; y += 1) {
|
||||
for (let x = 0; x < size; x += 1) {
|
||||
const index = (y * size + x) * 4;
|
||||
const fiber = fiberAt(x, y);
|
||||
const warmth = 0.97 + 0.018 * Math.sin(x * 0.017 + y * 0.003) + 0.012 * Math.sin(y * 0.041);
|
||||
const shade = THREE.MathUtils.clamp(0.975 + fiber, 0.88, 1.0);
|
||||
colorImage.data[index] = Math.round(255 * shade * warmth);
|
||||
colorImage.data[index + 1] = Math.round(251 * shade * warmth);
|
||||
colorImage.data[index + 2] = Math.round(235 * shade);
|
||||
colorImage.data[index + 3] = 255;
|
||||
|
||||
const line = y % 34 === 0 ? 0.72 : y % 34 === 1 ? 0.82 : 1;
|
||||
edgeImage.data[index] = Math.round(255 * shade * line);
|
||||
edgeImage.data[index + 1] = Math.round(244 * shade * line);
|
||||
edgeImage.data[index + 2] = Math.round(207 * shade * line);
|
||||
edgeImage.data[index + 3] = 255;
|
||||
|
||||
const hLeft = fiberAt((x - 1 + size) % size, y);
|
||||
const hRight = fiberAt((x + 1) % size, y);
|
||||
const hDown = fiberAt(x, (y - 1 + size) % size);
|
||||
const hUp = fiberAt(x, (y + 1) % size);
|
||||
const normal = new THREE.Vector3((hLeft - hRight) * 3.2, (hDown - hUp) * 3.2, 1).normalize();
|
||||
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 + 2] = Math.round((normal.z * 0.5 + 0.5) * 255);
|
||||
normalImage.data[index + 3] = 255;
|
||||
|
||||
const roughness = THREE.MathUtils.clamp(0.86 + Math.abs(fiber) * 0.5 + Math.abs(hLeft - hRight + hDown - hUp) * 1.2, 0.72, 0.98);
|
||||
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);
|
||||
edgeContext.putImageData(edgeImage, 0, 0);
|
||||
normalContext.putImageData(normalImage, 0, 0);
|
||||
roughnessContext.putImageData(roughnessImage, 0, 0);
|
||||
const colorTexture = new THREE.CanvasTexture(colorCanvas);
|
||||
const edgeTexture = new THREE.CanvasTexture(edgeCanvas);
|
||||
const normalTexture = new THREE.CanvasTexture(normalCanvas);
|
||||
const roughnessTexture = new THREE.CanvasTexture(roughnessCanvas);
|
||||
[colorTexture, edgeTexture, normalTexture, roughnessTexture].forEach((texture) => {
|
||||
texture.wrapS = THREE.RepeatWrapping;
|
||||
texture.wrapT = THREE.RepeatWrapping;
|
||||
texture.repeat.set(2.6, 3.4);
|
||||
texture.anisotropy = maxTextureAnisotropy;
|
||||
texture.minFilter = THREE.LinearMipmapLinearFilter;
|
||||
texture.magFilter = THREE.LinearFilter;
|
||||
texture.generateMipmaps = true;
|
||||
});
|
||||
colorTexture.colorSpace = THREE.SRGBColorSpace;
|
||||
edgeTexture.colorSpace = THREE.SRGBColorSpace;
|
||||
normalTexture.colorSpace = THREE.NoColorSpace;
|
||||
roughnessTexture.colorSpace = THREE.NoColorSpace;
|
||||
return { color: colorTexture, edge: edgeTexture, normal: normalTexture, roughness: roughnessTexture };
|
||||
}
|
||||
|
||||
function createRoomReflectionTexture() {
|
||||
const canvas = document.createElement('canvas');
|
||||
generatedTextureCanvases.roomReflection = canvas;
|
||||
|
||||
Reference in New Issue
Block a user