postext-folio 0.52.2 → 0.52.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/pageFlip/constants.d.ts +28 -0
- package/dist/pageFlip/constants.d.ts.map +1 -0
- package/dist/pageFlip/constants.js +31 -0
- package/dist/pageFlip/constants.js.map +1 -0
- package/dist/pageFlip/leaf.d.ts +125 -0
- package/dist/pageFlip/leaf.d.ts.map +1 -0
- package/dist/pageFlip/leaf.js +327 -0
- package/dist/pageFlip/leaf.js.map +1 -0
- package/dist/pageFlip/materials.d.ts +176 -0
- package/dist/pageFlip/materials.d.ts.map +1 -0
- package/dist/pageFlip/materials.js +362 -0
- package/dist/pageFlip/materials.js.map +1 -0
- package/dist/pageFlip/occlusion.d.ts +44 -0
- package/dist/pageFlip/occlusion.d.ts.map +1 -0
- package/dist/pageFlip/occlusion.js +202 -0
- package/dist/pageFlip/occlusion.js.map +1 -0
- package/dist/pageFlip.d.ts +4 -73
- package/dist/pageFlip.d.ts.map +1 -1
- package/dist/pageFlip.js +20 -911
- package/dist/pageFlip.js.map +1 -1
- package/dist/pageFlipFlat/leaf.d.ts +79 -0
- package/dist/pageFlipFlat/leaf.d.ts.map +1 -0
- package/dist/pageFlipFlat/leaf.js +100 -0
- package/dist/pageFlipFlat/leaf.js.map +1 -0
- package/dist/pageFlipFlat/shaders.d.ts +30 -0
- package/dist/pageFlipFlat/shaders.d.ts.map +1 -0
- package/dist/pageFlipFlat/shaders.js +214 -0
- package/dist/pageFlipFlat/shaders.js.map +1 -0
- package/dist/pageFlipFlat.d.ts +1 -1
- package/dist/pageFlipFlat.d.ts.map +1 -1
- package/dist/pageFlipFlat.js +4 -310
- package/dist/pageFlipFlat.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { Texture, Vector2, Color, Vector4, Vector3, MeshPhysicalMaterial, MeshStandardMaterial } from 'three';
|
|
2
|
+
import type { FolioConfig } from 'postext';
|
|
3
|
+
import type { PaperSpec } from '../paper.js';
|
|
4
|
+
/** What lies behind the leaves in the air (#484): the scene drawn without
|
|
5
|
+
* the translucent leaves (colour, mipmapped, and depth), shared by every
|
|
6
|
+
* page. `uBehindSize`: the screen in device px; `uBehindClip`: the
|
|
7
|
+
* camera's near and far planes; `uBehindScale`: texels of that picture
|
|
8
|
+
* per book unit at a view depth of 1; `uBehindFloor`: how far (book
|
|
9
|
+
* units) the sheet's fibres spread even what touches it. */
|
|
10
|
+
export declare const behindUniforms: {
|
|
11
|
+
uBehind: {
|
|
12
|
+
value: Texture | null;
|
|
13
|
+
};
|
|
14
|
+
uBehindDepth: {
|
|
15
|
+
value: Texture | null;
|
|
16
|
+
};
|
|
17
|
+
uBehindOn: {
|
|
18
|
+
value: number;
|
|
19
|
+
};
|
|
20
|
+
uBehindSize: {
|
|
21
|
+
value: Vector2;
|
|
22
|
+
};
|
|
23
|
+
uBehindClip: {
|
|
24
|
+
value: Vector2;
|
|
25
|
+
};
|
|
26
|
+
uBehindScale: {
|
|
27
|
+
value: number;
|
|
28
|
+
};
|
|
29
|
+
uBehindFloor: {
|
|
30
|
+
value: number;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
type PageUniforms = {
|
|
34
|
+
uFront: {
|
|
35
|
+
value: Texture | null;
|
|
36
|
+
};
|
|
37
|
+
uBack: {
|
|
38
|
+
value: Texture | null;
|
|
39
|
+
};
|
|
40
|
+
uHasFront: {
|
|
41
|
+
value: number;
|
|
42
|
+
};
|
|
43
|
+
uHasBack: {
|
|
44
|
+
value: number;
|
|
45
|
+
};
|
|
46
|
+
uMirror: {
|
|
47
|
+
value: number;
|
|
48
|
+
};
|
|
49
|
+
uShowThrough: {
|
|
50
|
+
value: number;
|
|
51
|
+
};
|
|
52
|
+
/** The page lying under an open page (the next leaf's face under it)
|
|
53
|
+
* and how much of its print comes through (#484). */
|
|
54
|
+
uUnder: {
|
|
55
|
+
value: Texture | null;
|
|
56
|
+
};
|
|
57
|
+
uHasUnder: {
|
|
58
|
+
value: number;
|
|
59
|
+
};
|
|
60
|
+
uUnderK: {
|
|
61
|
+
value: number;
|
|
62
|
+
};
|
|
63
|
+
/** How much of the light behind a leaf in the air comes through it. */
|
|
64
|
+
uTransmit: {
|
|
65
|
+
value: number;
|
|
66
|
+
};
|
|
67
|
+
uPaper: {
|
|
68
|
+
value: Color;
|
|
69
|
+
};
|
|
70
|
+
/** 1 on the open pages: lifted leaves occlude them. A leaf in the air
|
|
71
|
+
* does not read that map (it holds the leaf itself, and its own roll
|
|
72
|
+
* would flicker it). */
|
|
73
|
+
uLeafOcc: {
|
|
74
|
+
value: number;
|
|
75
|
+
};
|
|
76
|
+
/** Paper closer above a point than this (px) does not occlude it: a
|
|
77
|
+
* leaf's own surface round a point is not a blocker. */
|
|
78
|
+
uOccBias: {
|
|
79
|
+
value: number;
|
|
80
|
+
};
|
|
81
|
+
/** The videos playing on the leaf's pages (#477, #507): the atlas their
|
|
82
|
+
* pictures are drawn into, one texel of it, how many there are and, for
|
|
83
|
+
* each, where it lies on its page (`origin`, `across`: xy, zw; see
|
|
84
|
+
* {@link PageVideoFrame}), its `down` and face (xy; z 1 front, 2
|
|
85
|
+
* back) and its slot in the atlas (fractions from its top left). */
|
|
86
|
+
uVideo: {
|
|
87
|
+
value: Texture | null;
|
|
88
|
+
};
|
|
89
|
+
uVidTexel: {
|
|
90
|
+
value: Vector2;
|
|
91
|
+
};
|
|
92
|
+
uVidCount: {
|
|
93
|
+
value: number;
|
|
94
|
+
};
|
|
95
|
+
uVidOA: {
|
|
96
|
+
value: Vector4[];
|
|
97
|
+
};
|
|
98
|
+
uVidDF: {
|
|
99
|
+
value: Vector4[];
|
|
100
|
+
};
|
|
101
|
+
uVidRect: {
|
|
102
|
+
value: Vector4[];
|
|
103
|
+
};
|
|
104
|
+
/** The leaves in the air as a gloss open page mirrors them (#483): the
|
|
105
|
+
* picture (drawn from the camera mirrored in the page's plane, so a
|
|
106
|
+
* point of the page finds what it mirrors at its own place on screen,
|
|
107
|
+
* turned left for right), whether it is on, and the size of the screen
|
|
108
|
+
* in device px. */
|
|
109
|
+
uReflection: {
|
|
110
|
+
value: Texture | null;
|
|
111
|
+
};
|
|
112
|
+
uReflectionOn: {
|
|
113
|
+
value: number;
|
|
114
|
+
};
|
|
115
|
+
uReflectionSize: {
|
|
116
|
+
value: Vector2;
|
|
117
|
+
};
|
|
118
|
+
/** The mirror plane's normal (world). */
|
|
119
|
+
uReflectionNormal: {
|
|
120
|
+
value: Vector3;
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
export type PageMaterial = MeshPhysicalMaterial & {
|
|
124
|
+
userData: {
|
|
125
|
+
uniforms: PageUniforms;
|
|
126
|
+
spec?: PaperSpec | null;
|
|
127
|
+
};
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* A page's material: three.js's physical (PBR) material lit by the
|
|
131
|
+
* environment and the key light, the printed page on each face, the
|
|
132
|
+
* paper's shade, finish (roughness, a clear coat on coated stock, a fibre
|
|
133
|
+
* sheen on uncoated) and relief (a normal map), and the print on the other
|
|
134
|
+
* side showing faintly through thin paper. Ambient light is cut by the
|
|
135
|
+
* gutter's occlusion (a vertex attribute, from the book's cross-section)
|
|
136
|
+
* and by lifted leaves nearby.
|
|
137
|
+
*/
|
|
138
|
+
export declare function pageMaterial(mirror: boolean, sign: number): PageMaterial;
|
|
139
|
+
/** The uniforms every page block's edge material shares: book units per
|
|
140
|
+
* mm, and how strongly the cut face is relieved (uncoated stock shows
|
|
141
|
+
* its fibres; a coated sheet is cut cleaner). */
|
|
142
|
+
export declare const edgeUniforms: {
|
|
143
|
+
uEdgeK: {
|
|
144
|
+
value: number;
|
|
145
|
+
};
|
|
146
|
+
uEdgeRelief: {
|
|
147
|
+
value: number;
|
|
148
|
+
};
|
|
149
|
+
};
|
|
150
|
+
/** The page block's edges: paper with a fine line between leaves (fading
|
|
151
|
+
* to their average where the lines are finer than a pixel), its cut face
|
|
152
|
+
* in relief. */
|
|
153
|
+
export declare function edgeMaterial(sign: number, bands?: {
|
|
154
|
+
lo: number;
|
|
155
|
+
hi: number;
|
|
156
|
+
color: Color;
|
|
157
|
+
}, paper?: Color): MeshStandardMaterial;
|
|
158
|
+
export declare const ease: (t: number) => number;
|
|
159
|
+
export declare const easeOut: (t: number) => number;
|
|
160
|
+
export declare const smooth: (a: number, b: number, x: number) => number;
|
|
161
|
+
/**
|
|
162
|
+
* The stock a publisher would print a book of `pages` pages on, when its
|
|
163
|
+
* settings name none: a long book goes on lighter paper, a very long one
|
|
164
|
+
* on bible paper (2,000 pages make a volume about 4.5 cm thick, not 11).
|
|
165
|
+
* Settings that name a stock, a grammage or a bulk are kept as they are.
|
|
166
|
+
*/
|
|
167
|
+
export declare function withStockForExtent(folio: FolioConfig | undefined, pages: number): FolioConfig | undefined;
|
|
168
|
+
/** The colour round the edge of a printed cover (its ground), averaged: the
|
|
169
|
+
* colour its boards and spine show when the book carries its own covers.
|
|
170
|
+
* Null when the image cannot be read. */
|
|
171
|
+
export declare function edgeColorOf(image: CanvasImageSource & {
|
|
172
|
+
width: number;
|
|
173
|
+
height: number;
|
|
174
|
+
}): Color | null;
|
|
175
|
+
export {};
|
|
176
|
+
//# sourceMappingURL=materials.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"materials.d.ts","sourceRoot":"","sources":["../../src/pageFlip/materials.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
// The materials of the book: what lies behind the leaves in the air, the
|
|
2
|
+
// page material, the cut face of a page block and the colour round a
|
|
3
|
+
// printed cover's edge, with the easing curves (#1276: split out of pageFlip.ts).
|
|
4
|
+
import { Vector2, Color, Vector4, Vector3, MeshPhysicalMaterial, DoubleSide, MeshStandardMaterial, SRGBColorSpace } from 'three';
|
|
5
|
+
import { MAX_PAGE_VIDEOS } from '../videoAtlas.js';
|
|
6
|
+
import { occlusionUniforms, BOOK_POS_PARS, BOOK_POS, keyShadowed, OCCLUSION, keySpecular } from './occlusion.js';
|
|
7
|
+
/** What lies behind the leaves in the air (#484): the scene drawn without
|
|
8
|
+
* the translucent leaves (colour, mipmapped, and depth), shared by every
|
|
9
|
+
* page. `uBehindSize`: the screen in device px; `uBehindClip`: the
|
|
10
|
+
* camera's near and far planes; `uBehindScale`: texels of that picture
|
|
11
|
+
* per book unit at a view depth of 1; `uBehindFloor`: how far (book
|
|
12
|
+
* units) the sheet's fibres spread even what touches it. */
|
|
13
|
+
export const behindUniforms = {
|
|
14
|
+
uBehind: { value: null },
|
|
15
|
+
uBehindDepth: { value: null },
|
|
16
|
+
uBehindOn: { value: 0 },
|
|
17
|
+
uBehindSize: { value: new Vector2(1, 1) },
|
|
18
|
+
uBehindClip: { value: new Vector2(1, 2) },
|
|
19
|
+
uBehindScale: { value: 1 },
|
|
20
|
+
uBehindFloor: { value: 1 },
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* A page's material: three.js's physical (PBR) material lit by the
|
|
24
|
+
* environment and the key light, the printed page on each face, the
|
|
25
|
+
* paper's shade, finish (roughness, a clear coat on coated stock, a fibre
|
|
26
|
+
* sheen on uncoated) and relief (a normal map), and the print on the other
|
|
27
|
+
* side showing faintly through thin paper. Ambient light is cut by the
|
|
28
|
+
* gutter's occlusion (a vertex attribute, from the book's cross-section)
|
|
29
|
+
* and by lifted leaves nearby.
|
|
30
|
+
*/
|
|
31
|
+
export function pageMaterial(mirror, sign) {
|
|
32
|
+
const m = new MeshPhysicalMaterial({ side: DoubleSide, roughness: 0.85 });
|
|
33
|
+
const uniforms = {
|
|
34
|
+
uFront: { value: null },
|
|
35
|
+
uBack: { value: null },
|
|
36
|
+
uHasFront: { value: 0 },
|
|
37
|
+
uHasBack: { value: 0 },
|
|
38
|
+
uMirror: { value: mirror ? 1 : 0 },
|
|
39
|
+
uShowThrough: { value: 0 },
|
|
40
|
+
uUnder: { value: null },
|
|
41
|
+
uHasUnder: { value: 0 },
|
|
42
|
+
uUnderK: { value: 0 },
|
|
43
|
+
uTransmit: { value: 0 },
|
|
44
|
+
uPaper: { value: new Color(1, 1, 1) },
|
|
45
|
+
uLeafOcc: { value: 0.45 },
|
|
46
|
+
uOccBias: { value: 6 },
|
|
47
|
+
uVideo: { value: null },
|
|
48
|
+
uVidTexel: { value: new Vector2(1, 1) },
|
|
49
|
+
uVidCount: { value: 0 },
|
|
50
|
+
uVidOA: { value: Array.from({ length: MAX_PAGE_VIDEOS }, () => new Vector4()) },
|
|
51
|
+
uVidDF: { value: Array.from({ length: MAX_PAGE_VIDEOS }, () => new Vector4()) },
|
|
52
|
+
uVidRect: { value: Array.from({ length: MAX_PAGE_VIDEOS }, () => new Vector4()) },
|
|
53
|
+
uReflection: { value: null },
|
|
54
|
+
uReflectionOn: { value: 0 },
|
|
55
|
+
uReflectionSize: { value: new Vector2(1, 1) },
|
|
56
|
+
uReflectionNormal: { value: new Vector3(0, 0, 1) },
|
|
57
|
+
};
|
|
58
|
+
m.userData.uniforms = uniforms;
|
|
59
|
+
m.onBeforeCompile = (shader) => {
|
|
60
|
+
Object.assign(shader.uniforms, occlusionUniforms, behindUniforms, uniforms, { uSign: { value: sign } });
|
|
61
|
+
shader.vertexShader = shader.vertexShader
|
|
62
|
+
.replace("#include <common>", `#include <common>
|
|
63
|
+
attribute float ao;
|
|
64
|
+
varying float vAo;
|
|
65
|
+
varying vec2 vPageUv;
|
|
66
|
+
${BOOK_POS_PARS}`)
|
|
67
|
+
.replace("#include <begin_vertex>", `#include <begin_vertex>
|
|
68
|
+
vAo = ao;
|
|
69
|
+
vPageUv = uv;
|
|
70
|
+
${BOOK_POS}`);
|
|
71
|
+
shader.fragmentShader = keyShadowed(shader.fragmentShader)
|
|
72
|
+
.replace("#include <common>", `#include <common>
|
|
73
|
+
uniform sampler2D uFront;
|
|
74
|
+
uniform sampler2D uBack;
|
|
75
|
+
uniform float uHasFront;
|
|
76
|
+
uniform float uHasBack;
|
|
77
|
+
uniform float uMirror;
|
|
78
|
+
uniform float uShowThrough;
|
|
79
|
+
uniform sampler2D uUnder;
|
|
80
|
+
uniform float uHasUnder;
|
|
81
|
+
uniform float uUnderK;
|
|
82
|
+
uniform float uTransmit;
|
|
83
|
+
uniform sampler2D uBehind;
|
|
84
|
+
uniform sampler2D uBehindDepth;
|
|
85
|
+
uniform float uBehindOn;
|
|
86
|
+
uniform vec2 uBehindSize;
|
|
87
|
+
uniform vec2 uBehindClip;
|
|
88
|
+
uniform float uBehindScale;
|
|
89
|
+
uniform float uBehindFloor;
|
|
90
|
+
// The print of both faces at this point: what light coming
|
|
91
|
+
// through the sheet passes on its way.
|
|
92
|
+
vec3 transInk = vec3(1.0);
|
|
93
|
+
uniform vec3 uPaper;
|
|
94
|
+
uniform float uLeafOcc;
|
|
95
|
+
uniform float uSign;
|
|
96
|
+
uniform sampler2D uVideo;
|
|
97
|
+
uniform vec2 uVidTexel;
|
|
98
|
+
uniform float uVidCount;
|
|
99
|
+
uniform vec4 uVidOA[${MAX_PAGE_VIDEOS}];
|
|
100
|
+
uniform vec4 uVidDF[${MAX_PAGE_VIDEOS}];
|
|
101
|
+
uniform vec4 uVidRect[${MAX_PAGE_VIDEOS}];
|
|
102
|
+
uniform sampler2D uReflection;
|
|
103
|
+
uniform float uReflectionOn;
|
|
104
|
+
uniform vec2 uReflectionSize;
|
|
105
|
+
uniform vec3 uReflectionNormal;
|
|
106
|
+
varying float vAo;
|
|
107
|
+
varying vec2 vPageUv;
|
|
108
|
+
varying vec3 vBookPos;
|
|
109
|
+
${OCCLUSION}`)
|
|
110
|
+
.replace("#include <map_fragment>", `{
|
|
111
|
+
// 0 no page, 1 its image, 2 blank paper; uv.x runs from the spine.
|
|
112
|
+
bool front = gl_FrontFacing;
|
|
113
|
+
float has = front ? uHasFront : uHasBack;
|
|
114
|
+
float u = uMirror > 0.5 ? 1.0 - vPageUv.x : vPageUv.x;
|
|
115
|
+
vec2 uvF = vec2(u, vPageUv.y);
|
|
116
|
+
vec2 uvB = vec2(1.0 - u, vPageUv.y);
|
|
117
|
+
vec3 ink = uPaper;
|
|
118
|
+
if (has > 0.5 && has < 1.5) ink = front ? texture2D(uFront, uvF).rgb : texture2D(uBack, uvB).rgb;
|
|
119
|
+
// The videos playing on this face, printed over their posters:
|
|
120
|
+
// the point of the page (from its top left corner) in each
|
|
121
|
+
// picture's own frame, which may lie turned on the page, then in
|
|
122
|
+
// its slot of the atlas (kept half a texel inside it, clear of
|
|
123
|
+
// the next slot).
|
|
124
|
+
vec2 tuv = front ? uvF : uvB;
|
|
125
|
+
for (int i = 0; i < ${MAX_PAGE_VIDEOS}; i++) {
|
|
126
|
+
if (float(i) >= uVidCount) break;
|
|
127
|
+
vec4 oa = uVidOA[i];
|
|
128
|
+
vec4 df = uVidDF[i];
|
|
129
|
+
if ((df.z < 1.5) != front) continue;
|
|
130
|
+
vec2 p = vec2(tuv.x, 1.0 - tuv.y) - oa.xy;
|
|
131
|
+
vec2 st = vec2(dot(p, oa.zw) / dot(oa.zw, oa.zw), dot(p, df.xy) / dot(df.xy, df.xy));
|
|
132
|
+
if (st.x >= 0.0 && st.x <= 1.0 && st.y >= 0.0 && st.y <= 1.0) {
|
|
133
|
+
vec4 r = uVidRect[i];
|
|
134
|
+
vec2 v = clamp(r.xy + st * r.zw, r.xy + 0.5 * uVidTexel, r.xy + r.zw - 0.5 * uVidTexel);
|
|
135
|
+
ink = texture2D(uVideo, vec2(v.x, 1.0 - v.y)).rgb;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// The other side's print, seen through the sheet (the same point
|
|
139
|
+
// of paper, so mirrored as it should be).
|
|
140
|
+
float other = front ? uHasBack : uHasFront;
|
|
141
|
+
vec3 through = vec3(1.0);
|
|
142
|
+
if ((uShowThrough > 0.0 || uTransmit > 0.0) && other > 0.5 && other < 1.5) {
|
|
143
|
+
through = front ? texture2D(uBack, uvB).rgb : texture2D(uFront, uvF).rgb;
|
|
144
|
+
}
|
|
145
|
+
transInk = ink * through;
|
|
146
|
+
if (uShowThrough > 0.0) ink *= mix(vec3(1.0), through, uShowThrough);
|
|
147
|
+
// The page lying under an open page: its print comes through the
|
|
148
|
+
// whole sheet (the fibres spread it by a fraction of a millimetre,
|
|
149
|
+
// finer than the page's own texels: a softer sample would blur
|
|
150
|
+
// a page seen small to grey).
|
|
151
|
+
if (uHasUnder > 0.5 && uUnderK > 0.0) {
|
|
152
|
+
vec3 under = texture2D(uUnder, front ? uvF : uvB).rgb;
|
|
153
|
+
ink *= mix(vec3(1.0), under, uUnderK);
|
|
154
|
+
}
|
|
155
|
+
diffuseColor.rgb *= ink;
|
|
156
|
+
}`)
|
|
157
|
+
.replace("#include <aomap_fragment>", `#include <aomap_fragment>
|
|
158
|
+
{
|
|
159
|
+
// A leaf's own roll counts among the leaves it is occluded by:
|
|
160
|
+
// held to what its open side would let in.
|
|
161
|
+
float occ = vAo * (1.0 - uLeafOcc * bookOcclusion(vBookPos, 1.0));
|
|
162
|
+
reflectedLight.indirectDiffuse *= occ;
|
|
163
|
+
reflectedLight.indirectSpecular *= mix(1.0, occ, 0.85);
|
|
164
|
+
}
|
|
165
|
+
// The reflection's ray, in book coordinates.
|
|
166
|
+
vec3 reflected = (vec4(reflect(-geometryViewDir, normal), 0.0) * viewMatrix).xyz;
|
|
167
|
+
reflected.x *= uSign;
|
|
168
|
+
// A mirrored leaf stands for what it hides itself.
|
|
169
|
+
${keySpecular("1.0 - 0.85 * (uReflectionOn > 0.5 ? 0.0 : reflectionOcclusion(vBookPos, reflected, 1.0))")}
|
|
170
|
+
#ifdef USE_CLEARCOAT
|
|
171
|
+
if (uReflectionOn > 0.5) {
|
|
172
|
+
// The leaves in the air, mirrored in a gloss page: where one is
|
|
173
|
+
// seen, it takes the place of the environment it hides, through
|
|
174
|
+
// the coating's Fresnel and the paper's own. A plane holds only
|
|
175
|
+
// where the page lies in it: the mirror fades up the gutter.
|
|
176
|
+
vec2 st = gl_FragCoord.xy / uReflectionSize;
|
|
177
|
+
vec4 seen = texture2D(uReflection, vec2(1.0 - st.x, st.y));
|
|
178
|
+
float lies = smoothstep(0.97, 0.995, abs(dot((vec4(normalize(vNormal), 0.0) * viewMatrix).xyz, uReflectionNormal)));
|
|
179
|
+
float a = seen.a * lies;
|
|
180
|
+
vec3 leaf = seen.rgb * lies;
|
|
181
|
+
clearcoatSpecularIndirect = clearcoatSpecularIndirect * (1.0 - a)
|
|
182
|
+
+ leaf * EnvironmentBRDF(geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness);
|
|
183
|
+
reflectedLight.indirectSpecular = reflectedLight.indirectSpecular * (1.0 - a)
|
|
184
|
+
+ leaf * EnvironmentBRDF(geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.roughness);
|
|
185
|
+
}
|
|
186
|
+
#endif
|
|
187
|
+
if (uBehindOn > 0.5 && uTransmit > 0.0) {
|
|
188
|
+
// Thin paper in the air lets through the light behind it (#484):
|
|
189
|
+
// what lies there on screen, seen through the print of both
|
|
190
|
+
// faces. The sheet scatters what it lets through about evenly
|
|
191
|
+
// (near Lambertian), so a thing a gap behind it is spread over
|
|
192
|
+
// about twice that gap: sharp where the leaf touches the page
|
|
193
|
+
// under it, a soft glow a few millimetres off. A page close
|
|
194
|
+
// under it is lit only through the leaf, so its print comes
|
|
195
|
+
// back at about half the leaf's transmittance (1 − opacity, as
|
|
196
|
+
// the open page shows the one under it); what lies further, out
|
|
197
|
+
// of the leaf's shade, at the whole of it. Stronger and sharper,
|
|
198
|
+
// the page under a leaf about to land read as lying over it
|
|
199
|
+
// (#492). What it lets through it does not reflect.
|
|
200
|
+
vec2 st = gl_FragCoord.xy / uBehindSize;
|
|
201
|
+
float depth = texture2D(uBehindDepth, st).x;
|
|
202
|
+
float zBehind = uBehindClip.x * uBehindClip.y / (uBehindClip.y - depth * (uBehindClip.y - uBehindClip.x));
|
|
203
|
+
float gap = max(0.0, zBehind - vViewPosition.z);
|
|
204
|
+
float spread = (uBehindFloor + 2.0 * gap) * uBehindScale / vViewPosition.z;
|
|
205
|
+
vec4 seen = textureLod(uBehind, st, log2(max(1.0, 2.0 * spread)));
|
|
206
|
+
float carried = uTransmit * mix(0.5, 1.0, smoothstep(0.0, 8.0 * uBehindFloor, gap));
|
|
207
|
+
float lost = carried * seen.a;
|
|
208
|
+
reflectedLight.directDiffuse *= 1.0 - lost;
|
|
209
|
+
reflectedLight.indirectDiffuse = reflectedLight.indirectDiffuse * (1.0 - lost) + carried * seen.rgb * transInk;
|
|
210
|
+
}`);
|
|
211
|
+
};
|
|
212
|
+
return m;
|
|
213
|
+
}
|
|
214
|
+
/** The uniforms every page block's edge material shares: book units per
|
|
215
|
+
* mm, and how strongly the cut face is relieved (uncoated stock shows
|
|
216
|
+
* its fibres; a coated sheet is cut cleaner). */
|
|
217
|
+
export const edgeUniforms = {
|
|
218
|
+
uEdgeK: { value: 1 },
|
|
219
|
+
uEdgeRelief: { value: 1 },
|
|
220
|
+
};
|
|
221
|
+
// The cut face of a page block, as a height field in mm over (leaf, mm
|
|
222
|
+
// along the cut): every leaf a rounded ridge standing a hair proud of or
|
|
223
|
+
// behind its neighbours (sheets are never quite in line), the sections
|
|
224
|
+
// and the bundles the knife took together a little out of line with the
|
|
225
|
+
// next, and the faint streaks the guillotine drags across the block. Each
|
|
226
|
+
// scale fades out where it is finer than a pixel, so the face never
|
|
227
|
+
// shimmers. The relief bends the normal (bump mapping from the screen-
|
|
228
|
+
// space derivatives of the field), so the face catches a grazing light.
|
|
229
|
+
const EDGE_RELIEF = /* glsl */ `
|
|
230
|
+
uniform float uEdgeK;
|
|
231
|
+
uniform float uEdgeRelief;
|
|
232
|
+
varying float vRun;
|
|
233
|
+
float eHash(float n) { return fract(sin(n * 127.1) * 43758.5453); }
|
|
234
|
+
float eHash2(vec2 p) { return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453); }
|
|
235
|
+
float eNoise(vec2 p) {
|
|
236
|
+
vec2 i = floor(p);
|
|
237
|
+
vec2 f = fract(p);
|
|
238
|
+
vec2 u = f * f * (3.0 - 2.0 * f);
|
|
239
|
+
return mix(mix(eHash2(i), eHash2(i + vec2(1.0, 0.0)), u.x), mix(eHash2(i + vec2(0.0, 1.0)), eHash2(i + vec2(1.0, 1.0)), u.x), u.y);
|
|
240
|
+
}
|
|
241
|
+
// fade: x = the leaves, y = the bundles, z = the fine knife marks.
|
|
242
|
+
float edgeHeight(vec2 lv, vec3 fade) {
|
|
243
|
+
float id = floor(lv.x);
|
|
244
|
+
float ridge = sin(fract(lv.x) * PI);
|
|
245
|
+
float proud = eHash(id) - 0.5 + 0.8 * (eNoise(vec2(id * 0.37, lv.y * 0.12)) - 0.5);
|
|
246
|
+
float leaf = (0.45 * ridge + proud) * 0.04 * fade.x;
|
|
247
|
+
float bundle = (eNoise(vec2(lv.x / 5.0, lv.y * 0.03)) - 0.5) * 0.12 * fade.y
|
|
248
|
+
+ (eNoise(vec2(lv.x / 24.0 + 7.0, lv.y * 0.02)) - 0.5) * 0.18;
|
|
249
|
+
float knife = (eNoise(vec2(lv.y * 0.7, lv.x / 90.0)) - 0.5) * 0.035
|
|
250
|
+
+ (eNoise(vec2(lv.y * 3.0, lv.x / 40.0)) - 0.5) * 0.006 * fade.z;
|
|
251
|
+
return leaf + bundle + knife;
|
|
252
|
+
}
|
|
253
|
+
vec3 edgeNormal(vec3 surfPos, vec3 n, vec2 dH, float faceDir) {
|
|
254
|
+
vec3 sx = dFdx(surfPos);
|
|
255
|
+
vec3 sy = dFdy(surfPos);
|
|
256
|
+
vec3 r1 = cross(sy, n);
|
|
257
|
+
vec3 r2 = cross(n, sx);
|
|
258
|
+
float det = dot(sx, r1) * faceDir;
|
|
259
|
+
vec3 grad = sign(det) * (dH.x * r1 + dH.y * r2);
|
|
260
|
+
return normalize(abs(det) * n - grad);
|
|
261
|
+
}
|
|
262
|
+
`;
|
|
263
|
+
/** The page block's edges: paper with a fine line between leaves (fading
|
|
264
|
+
* to their average where the lines are finer than a pixel), its cut face
|
|
265
|
+
* in relief. */
|
|
266
|
+
export function edgeMaterial(sign, bands, paper) {
|
|
267
|
+
const m = new MeshStandardMaterial({ side: DoubleSide, roughness: 0.92 });
|
|
268
|
+
if (paper)
|
|
269
|
+
m.color.copy(paper);
|
|
270
|
+
const band = { uBoardLo: { value: bands?.lo ?? -1 }, uBoardHi: { value: bands?.hi ?? 2 }, uBoardColor: { value: bands?.color ?? new Color(0, 0, 0) } };
|
|
271
|
+
m.onBeforeCompile = (shader) => {
|
|
272
|
+
Object.assign(shader.uniforms, occlusionUniforms, edgeUniforms, band, { uSign: { value: sign } });
|
|
273
|
+
shader.vertexShader = shader.vertexShader
|
|
274
|
+
.replace("#include <common>", `#include <common>\nattribute float layer;\nattribute float lambda;\nattribute float run;\nvarying float vLayer;\nvarying float vLambda;\nvarying float vRun;\n${BOOK_POS_PARS}`)
|
|
275
|
+
.replace("#include <begin_vertex>", `#include <begin_vertex>\nvLayer = layer;\nvLambda = lambda;\nvRun = run;\n${BOOK_POS}`);
|
|
276
|
+
shader.fragmentShader = keyShadowed(shader.fragmentShader)
|
|
277
|
+
.replace("#include <common>", `#include <common>\nuniform float uBoardLo;\nuniform float uBoardHi;\nuniform vec3 uBoardColor;\nvarying float vLayer;\nvarying float vLambda;\nvarying vec3 vBookPos;\n${OCCLUSION}\n${EDGE_RELIEF}`)
|
|
278
|
+
.replace("#include <normal_fragment_maps>", `{
|
|
279
|
+
vec2 lv = vec2(vLayer, vRun / uEdgeK);
|
|
280
|
+
vec2 dx = dFdx(lv);
|
|
281
|
+
vec2 dy = dFdy(lv);
|
|
282
|
+
float wl = fwidth(vLayer);
|
|
283
|
+
vec3 fade = vec3(
|
|
284
|
+
1.0 - smoothstep(0.3, 0.8, wl),
|
|
285
|
+
1.0 - smoothstep(2.0, 5.0, wl),
|
|
286
|
+
1.0 - smoothstep(0.05, 0.15, fwidth(lv.y))
|
|
287
|
+
);
|
|
288
|
+
float h0 = edgeHeight(lv, fade);
|
|
289
|
+
vec2 dH = vec2(edgeHeight(lv + dx, fade) - h0, edgeHeight(lv + dy, fade) - h0) * uEdgeK * uEdgeRelief;
|
|
290
|
+
if (vLambda >= uBoardLo && vLambda <= uBoardHi) normal = edgeNormal(-vViewPosition, normal, dH, faceDirection);
|
|
291
|
+
}`)
|
|
292
|
+
.replace("#include <map_fragment>", `{
|
|
293
|
+
float w = fwidth(vLayer);
|
|
294
|
+
float d = abs(fract(vLayer) - 0.5) * 2.0;
|
|
295
|
+
float line = smoothstep(0.55 - w, 0.95 + w, d);
|
|
296
|
+
float fine = clamp(w * 1.5, 0.0, 1.0);
|
|
297
|
+
diffuseColor.rgb *= 1.0 - mix(0.22 * line, 0.08, fine);
|
|
298
|
+
// The bundles' sheets are never quite one shade.
|
|
299
|
+
diffuseColor.rgb *= 1.0 + 0.06 * uEdgeRelief * (eNoise(vec2(vLayer / 9.0, 3.0)) - 0.5);
|
|
300
|
+
// A board lying in the block (the book's own cover) shows its
|
|
301
|
+
// own edge, not paper.
|
|
302
|
+
if (vLambda < uBoardLo || vLambda > uBoardHi) diffuseColor.rgb = uBoardColor;
|
|
303
|
+
}`)
|
|
304
|
+
.replace("#include <aomap_fragment>", "#include <aomap_fragment>\nreflectedLight.indirectDiffuse *= 1.0 - bookOcclusion(vBookPos, 0.0);");
|
|
305
|
+
};
|
|
306
|
+
return m;
|
|
307
|
+
}
|
|
308
|
+
export const ease = (t) => (t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2);
|
|
309
|
+
export const easeOut = (t) => 1 - Math.pow(1 - t, 3);
|
|
310
|
+
export const smooth = (a, b, x) => {
|
|
311
|
+
const t = Math.min(1, Math.max(0, (x - a) / (b - a)));
|
|
312
|
+
return t * t * (3 - 2 * t);
|
|
313
|
+
};
|
|
314
|
+
/**
|
|
315
|
+
* The stock a publisher would print a book of `pages` pages on, when its
|
|
316
|
+
* settings name none: a long book goes on lighter paper, a very long one
|
|
317
|
+
* on bible paper (2,000 pages make a volume about 4.5 cm thick, not 11).
|
|
318
|
+
* Settings that name a stock, a grammage or a bulk are kept as they are.
|
|
319
|
+
*/
|
|
320
|
+
export function withStockForExtent(folio, pages) {
|
|
321
|
+
const paper = folio?.paper;
|
|
322
|
+
if (paper?.type !== undefined || paper?.grammage !== undefined || paper?.bulk !== undefined)
|
|
323
|
+
return folio;
|
|
324
|
+
if (pages > 1000)
|
|
325
|
+
return { ...folio, paper: { ...paper, type: "bible" } };
|
|
326
|
+
if (pages > 600)
|
|
327
|
+
return { ...folio, paper: { ...paper, grammage: 70 } };
|
|
328
|
+
return folio;
|
|
329
|
+
}
|
|
330
|
+
/** The colour round the edge of a printed cover (its ground), averaged: the
|
|
331
|
+
* colour its boards and spine show when the book carries its own covers.
|
|
332
|
+
* Null when the image cannot be read. */
|
|
333
|
+
export function edgeColorOf(image) {
|
|
334
|
+
try {
|
|
335
|
+
const c = document.createElement("canvas");
|
|
336
|
+
c.width = c.height = 32;
|
|
337
|
+
const g = c.getContext("2d");
|
|
338
|
+
if (!g)
|
|
339
|
+
return null;
|
|
340
|
+
g.drawImage(image, 0, 0, 32, 32);
|
|
341
|
+
const d = g.getImageData(0, 0, 32, 32).data;
|
|
342
|
+
let r = 0;
|
|
343
|
+
let gr = 0;
|
|
344
|
+
let b = 0;
|
|
345
|
+
let n = 0;
|
|
346
|
+
for (let y = 0; y < 32; y++)
|
|
347
|
+
for (let x = 0; x < 32; x++) {
|
|
348
|
+
if (x > 1 && x < 30 && y > 1 && y < 30)
|
|
349
|
+
continue;
|
|
350
|
+
const i = (y * 32 + x) * 4;
|
|
351
|
+
r += d[i];
|
|
352
|
+
gr += d[i + 1];
|
|
353
|
+
b += d[i + 2];
|
|
354
|
+
n++;
|
|
355
|
+
}
|
|
356
|
+
return new Color().setRGB(r / n / 255, gr / n / 255, b / n / 255, SRGBColorSpace);
|
|
357
|
+
}
|
|
358
|
+
catch {
|
|
359
|
+
return null;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
//# sourceMappingURL=materials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"materials.js","sourceRoot":"","sources":["../../src/pageFlip/materials.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Texture, Vector4, BufferGeometry, Mesh, ShaderMaterial, MeshStandardMaterial } from 'three';
|
|
2
|
+
export declare const OCCLUSION = "\n uniform sampler2D uShadowMap;\n uniform vec4 uShadowBox;\n uniform float uShadowOn;\n uniform float uOccRadius;\n uniform float uOccBias;\n float casterAt(vec2 s, float channel) {\n vec2 uv = (s - uShadowBox.xy) / uShadowBox.zw;\n if (uv.x < 0.0 || uv.y < 0.0 || uv.x > 1.0 || uv.y > 1.0) return -1e4;\n vec4 t = texture2D(uShadowMap, uv);\n return (channel > 0.5 ? t.g : t.r) - 10.0;\n }\n // Horizon-based: in each of 8 directions, the highest paper seen from p\n // (as an elevation angle) hides that much of the sky: sin(horizon) of a\n // cosine-weighted slice.\n float bookOcclusion(vec3 p, float channel) {\n if (uShadowOn < 0.5) return 0.0;\n float spin = fract(sin(dot(gl_FragCoord.xy, vec2(12.9898, 78.233))) * 43758.5453);\n float occ = 0.0;\n for (int d = 0; d < 8; d++) {\n float a = (float(d) + spin) * 0.785398;\n vec2 dir = vec2(cos(a), sin(a));\n float horizon = 0.0;\n for (int i = 0; i < 4; i++) {\n float t = (float(i) + 0.25 + 0.5 * spin) / 4.0;\n float r = t * t * uOccRadius + 1.0;\n float h = casterAt(p.xy + r * dir, channel) - p.z - uOccBias;\n horizon = max(horizon, h / sqrt(h * h + r * r));\n }\n occ += horizon;\n }\n return occ / 8.0;\n }\n // How far the reflection seen at p runs under paper: its ray marched\n // out through the height map (a lifted leaf hides what it would mirror,\n // and so does the leaf's own roll over the inside of its curl). The\n // march starts a few px out, past the paper round p itself. Its steps\n // are shifted a little from pixel to pixel: at fixed steps the leaf's\n // outline was cut in at each of them, a row of teeth (#483).\n float reflectionOcclusion(vec3 p, vec3 r, float channel) {\n if (uShadowOn < 0.5) return 0.0;\n // Interleaved gradient noise: neighbours take evenly spread shifts.\n float spin = fract(52.9829189 * fract(dot(gl_FragCoord.xy, vec2(0.06711056, 0.00583715))));\n float hidden = 0.0;\n for (int i = 0; i < 8; i++) {\n float s = (float(i) + spin) / 8.0;\n float t = 6.0 + s * s * uOccRadius * 2.0;\n vec3 q = p + r * t;\n hidden = max(hidden, smoothstep(0.0, 4.0, casterAt(q.xy, channel) - q.z - uOccBias));\n }\n return hidden;\n }\n";
|
|
3
|
+
/** Declares the book position varying in a vertex shader and sets it:
|
|
4
|
+
* the world position with the mirror of a right-bound book undone. */
|
|
5
|
+
export declare const BOOK_POS_PARS = "uniform float uSign;\nvarying vec3 vBookPos;";
|
|
6
|
+
export declare const BOOK_POS = "vBookPos = (modelMatrix * vec4(transformed, 1.0)).xyz;\nvBookPos.x *= uSign;";
|
|
7
|
+
/** The occlusion uniforms every receiving material shares (same objects). */
|
|
8
|
+
export declare const occlusionUniforms: {
|
|
9
|
+
uShadowMap: {
|
|
10
|
+
value: Texture | null;
|
|
11
|
+
};
|
|
12
|
+
uShadowBox: {
|
|
13
|
+
value: Vector4;
|
|
14
|
+
};
|
|
15
|
+
uShadowOn: {
|
|
16
|
+
value: number;
|
|
17
|
+
};
|
|
18
|
+
uOccRadius: {
|
|
19
|
+
value: number;
|
|
20
|
+
};
|
|
21
|
+
uOccBias: {
|
|
22
|
+
value: number;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
/** How much of the environment's reflection the key's shadow takes away:
|
|
26
|
+
* the key stands where the environment's brightest emitter is, so what
|
|
27
|
+
* hides it from a point hides that emitter's reflection too. */
|
|
28
|
+
export declare function keySpecular(occlusion?: string): string;
|
|
29
|
+
/** Gives a material the key's shadow on its own plane. */
|
|
30
|
+
export declare function keyShadowed(fragmentShader: string): string;
|
|
31
|
+
/** A caster's own copy of a mesh's shape. The height map is drawn before
|
|
32
|
+
* the main view, and three.js uploads a geometry once per frame number,
|
|
33
|
+
* which the key's shadow pass at the end of the last main view had
|
|
34
|
+
* already taken: a caster sharing a leaf's geometry drew the leaf where
|
|
35
|
+
* it lay a frame before, and a leaf moving down was shaded by its own
|
|
36
|
+
* old self, moving up it was not (#488). */
|
|
37
|
+
export declare function casterGeometry(source: BufferGeometry): BufferGeometry;
|
|
38
|
+
/** Brings a caster's copy to its mesh's shape as laid out this frame. */
|
|
39
|
+
export declare function syncCaster(caster: Mesh, source: BufferGeometry): void;
|
|
40
|
+
export declare function casterMaterial(leaf: boolean): ShaderMaterial;
|
|
41
|
+
/** A standard material (the desk, the covers) with the book's occlusion
|
|
42
|
+
* on its ambient light. */
|
|
43
|
+
export declare function occluded<T extends MeshStandardMaterial>(m: T, sign: number): T;
|
|
44
|
+
//# sourceMappingURL=occlusion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"occlusion.d.ts","sourceRoot":"","sources":["../../src/pageFlip/occlusion.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAe,cAAc,EAAE,IAAI,EAAmB,cAAc,EAAsD,oBAAoB,EAAE,MAAM,OAAO,CAAC;AASvL,eAAO,MAAM,SAAS,+uEAoDrB,CAAC;AAEF;uEACuE;AACvE,eAAO,MAAM,aAAa,iDAAiD,CAAC;AAC5E,eAAO,MAAM,QAAQ,iFAAiF,CAAC;AAoBvG,6EAA6E;AAC7E,eAAO,MAAM,iBAAiB;;eACC,OAAO,GAAG,IAAI;;;;;;;;;;;;;;CAK5C,CAAC;AA4CF;;iEAEiE;AACjE,wBAAgB,WAAW,CAAC,SAAS,SAAQ,UAW5C;AAED,0DAA0D;AAC1D,wBAAgB,WAAW,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED;;;;;6CAK6C;AAC7C,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,cAAc,CAKrE;AAED,yEAAyE;AACzE,wBAAgB,UAAU,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,QAI9D;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,kBAc3C;AAED;4BAC4B;AAC5B,wBAAgB,QAAQ,CAAC,CAAC,SAAS,oBAAoB,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,CAc9E"}
|