Refine WebGL paper and spine materials
This commit is contained in:
@@ -370,18 +370,23 @@ function addSimulatedStackBodies(group, context, model) {
|
||||
}
|
||||
|
||||
function createStackBodyMaterials(context, model, side, isSinglePage = false) {
|
||||
const baseColor = side < 0 ? '#d8c7a4' : '#e7d6b4';
|
||||
const lineColor = '#9a8058';
|
||||
const layerTexture = createStackLayerTexture(context, model.bundleCount, baseColor, lineColor);
|
||||
const baseColor = side < 0 ? '#fff1c8' : '#fff7d7';
|
||||
const lineColor = '#c39a4b';
|
||||
const layerTextures = createStackLayerTextures(context, model.bundleCount, baseColor, lineColor);
|
||||
const surface = new THREE.MeshStandardMaterial({
|
||||
map: layerTexture,
|
||||
roughness: 0.84,
|
||||
map: layerTextures.color,
|
||||
normalMap: layerTextures.normal,
|
||||
normalScale: new THREE.Vector2(0.034, 0.034),
|
||||
roughnessMap: layerTextures.roughness,
|
||||
roughness: 0.88,
|
||||
metalness: 0,
|
||||
envMapIntensity: 0.08,
|
||||
envMapIntensity: 0.06,
|
||||
side: THREE.DoubleSide
|
||||
});
|
||||
const edge = surface.clone();
|
||||
edge.map = layerTexture;
|
||||
edge.map = layerTextures.color;
|
||||
edge.normalMap = layerTextures.normal;
|
||||
edge.roughnessMap = layerTextures.roughness;
|
||||
const bottom = context.materials.pageTop.clone();
|
||||
const top = side < 0 && context.materials.leftPage
|
||||
? context.materials.leftPage
|
||||
@@ -401,33 +406,97 @@ function createStackBodyMaterials(context, model, side, isSinglePage = false) {
|
||||
return [surface, edge, bottom, top, context.materials.spine];
|
||||
}
|
||||
|
||||
function createStackLayerTexture(context, bundleCount, baseColor, lineColor) {
|
||||
function createStackLayerTextures(context, bundleCount, baseColor, lineColor) {
|
||||
const canvas = document.createElement('canvas');
|
||||
const normalCanvas = document.createElement('canvas');
|
||||
const roughnessCanvas = document.createElement('canvas');
|
||||
canvas.width = 2048;
|
||||
canvas.height = 1024;
|
||||
normalCanvas.width = canvas.width;
|
||||
normalCanvas.height = canvas.height;
|
||||
roughnessCanvas.width = canvas.width;
|
||||
roughnessCanvas.height = canvas.height;
|
||||
const context2d = canvas.getContext('2d');
|
||||
const normalContext = normalCanvas.getContext('2d');
|
||||
const roughnessContext = roughnessCanvas.getContext('2d');
|
||||
context2d.fillStyle = baseColor;
|
||||
context2d.fillRect(0, 0, canvas.width, canvas.height);
|
||||
context2d.strokeStyle = lineColor;
|
||||
context2d.globalAlpha = 0.95;
|
||||
context2d.lineWidth = 4.2;
|
||||
context2d.lineCap = 'square';
|
||||
for (let row = 0; row < bundleCount; row += 1) {
|
||||
const v = bundleCount <= 1 ? 0.5 : row / (bundleCount - 1);
|
||||
normalContext.fillStyle = 'rgb(128, 128, 255)';
|
||||
normalContext.fillRect(0, 0, normalCanvas.width, normalCanvas.height);
|
||||
roughnessContext.fillStyle = 'rgb(224, 224, 224)';
|
||||
roughnessContext.fillRect(0, 0, roughnessCanvas.width, roughnessCanvas.height);
|
||||
|
||||
const irregular = (seed) => {
|
||||
const value = Math.sin(seed * 12.9898 + 78.233) * 43758.5453;
|
||||
return value - Math.floor(value);
|
||||
};
|
||||
const drawLayerLine = (v, alpha, width, normalStrength) => {
|
||||
const y = (1 - v) * canvas.height;
|
||||
context2d.beginPath();
|
||||
context2d.moveTo(-8, y);
|
||||
context2d.lineTo(canvas.width + 8, y);
|
||||
context2d.strokeStyle = lineColor;
|
||||
context2d.globalAlpha = alpha;
|
||||
context2d.lineWidth = width;
|
||||
context2d.lineCap = 'square';
|
||||
context2d.stroke();
|
||||
|
||||
normalContext.beginPath();
|
||||
normalContext.moveTo(-8, y);
|
||||
normalContext.lineTo(normalCanvas.width + 8, y);
|
||||
const normalByte = Math.round(128 + normalStrength * 68);
|
||||
normalContext.strokeStyle = `rgb(128, ${normalByte}, 255)`;
|
||||
normalContext.globalAlpha = Math.min(1, alpha * 0.85);
|
||||
normalContext.lineWidth = Math.max(1, width * 0.72);
|
||||
normalContext.stroke();
|
||||
|
||||
roughnessContext.beginPath();
|
||||
roughnessContext.moveTo(-8, y);
|
||||
roughnessContext.lineTo(roughnessCanvas.width + 8, y);
|
||||
const roughnessByte = Math.round(218 + alpha * 28);
|
||||
roughnessContext.strokeStyle = `rgb(${roughnessByte}, ${roughnessByte}, ${roughnessByte})`;
|
||||
roughnessContext.globalAlpha = Math.min(1, alpha * 0.72);
|
||||
roughnessContext.lineWidth = Math.max(1, width * 0.8);
|
||||
roughnessContext.stroke();
|
||||
};
|
||||
|
||||
for (let row = 0; row < bundleCount; row += 1) {
|
||||
const rowV = bundleCount <= 1 ? 0.5 : row / (bundleCount - 1);
|
||||
const rowAccent = 0.5 + irregular(row + 0.37) * 0.28;
|
||||
drawLayerLine(rowV, rowAccent, 2.6 + irregular(row + 2.13) * 0.8, 0.58);
|
||||
if (row >= bundleCount - 1) continue;
|
||||
const nextV = (row + 1) / Math.max(1, bundleCount - 1);
|
||||
const interval = nextV - rowV;
|
||||
const microLines = 12;
|
||||
for (let sub = 1; sub < microLines; sub += 1) {
|
||||
const seed = row * 17.0 + sub * 3.0;
|
||||
const t = THREE.MathUtils.clamp((sub + (irregular(seed) - 0.5) * 0.22) / microLines, 0.04, 0.96);
|
||||
const v = rowV + interval * t;
|
||||
const alpha = 0.3 + irregular(seed + 1.91) * 0.24;
|
||||
const width = 1.05 + irregular(seed + 5.47) * 1.05;
|
||||
drawLayerLine(v, alpha, width, 0.34 + irregular(seed + 9.17) * 0.26);
|
||||
}
|
||||
}
|
||||
const texture = new THREE.CanvasTexture(canvas);
|
||||
texture.colorSpace = THREE.SRGBColorSpace;
|
||||
texture.anisotropy = context.maxAnisotropy;
|
||||
texture.minFilter = THREE.LinearMipmapLinearFilter;
|
||||
texture.magFilter = THREE.LinearFilter;
|
||||
texture.generateMipmaps = true;
|
||||
texture.needsUpdate = true;
|
||||
return texture;
|
||||
context2d.globalAlpha = 1;
|
||||
normalContext.globalAlpha = 1;
|
||||
roughnessContext.globalAlpha = 1;
|
||||
|
||||
const colorTexture = new THREE.CanvasTexture(canvas);
|
||||
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.anisotropy = context.maxAnisotropy;
|
||||
texture.minFilter = THREE.LinearMipmapLinearFilter;
|
||||
texture.magFilter = THREE.LinearFilter;
|
||||
texture.generateMipmaps = true;
|
||||
texture.needsUpdate = true;
|
||||
});
|
||||
colorTexture.colorSpace = THREE.SRGBColorSpace;
|
||||
normalTexture.colorSpace = THREE.NoColorSpace;
|
||||
roughnessTexture.colorSpace = THREE.NoColorSpace;
|
||||
return { color: colorTexture, normal: normalTexture, roughness: roughnessTexture };
|
||||
}
|
||||
|
||||
function createLoftedLineBody(model, lines, depth) {
|
||||
|
||||
Reference in New Issue
Block a user