@driftengine/core 4.8.3 → 4.8.5
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/CHANGELOG.json +82 -0
- package/README.md +1 -1
- package/dist/build/shaderComments.js +0 -0
- package/dist/geometry/meshConcat.js +2 -0
- package/dist/index.d.ts +10 -4
- package/dist/index.js +16 -1
- package/dist/math/scalar.js +1 -1
- package/dist/render/anisotropicLobe.d.ts +7 -0
- package/dist/render/anisotropicLobe.js +33 -0
- package/dist/render/backend/api.d.ts +41 -4
- package/dist/render/backend/select.js +8 -0
- package/dist/render/backend/webgl2/clothTextures.d.ts +27 -0
- package/dist/render/backend/webgl2/clothTextures.js +93 -0
- package/dist/render/backend/webgl2/renderer.d.ts +136 -3
- package/dist/render/backend/webgl2/renderer.js +604 -63
- package/dist/render/backend/webgl2/skinScatter.d.ts +50 -0
- package/dist/render/backend/webgl2/skinScatter.js +256 -0
- package/dist/render/backend/webgpu/buffers.d.ts +25 -11
- package/dist/render/backend/webgpu/buffers.js +98 -49
- package/dist/render/backend/webgpu/clothSolvePack.d.ts +27 -0
- package/dist/render/backend/webgpu/clothSolvePack.js +129 -0
- package/dist/render/backend/webgpu/clothTextures.d.ts +68 -0
- package/dist/render/backend/webgpu/clothTextures.js +145 -0
- package/dist/render/backend/webgpu/compressedUpload.d.ts +18 -0
- package/dist/render/backend/webgpu/compressedUpload.js +38 -0
- package/dist/render/backend/webgpu/computeHost.d.ts +21 -0
- package/dist/render/backend/webgpu/computeHost.js +5 -0
- package/dist/render/backend/webgpu/depthPass.d.ts +16 -6
- package/dist/render/backend/webgpu/depthPass.js +39 -9
- package/dist/render/backend/webgpu/drawCommand.js +6 -2
- package/dist/render/backend/webgpu/flatPass.d.ts +38 -4
- package/dist/render/backend/webgpu/flatPass.js +109 -12
- package/dist/render/backend/webgpu/gpuSkinnedCloth.d.ts +74 -0
- package/dist/render/backend/webgpu/gpuSkinnedCloth.js +452 -0
- package/dist/render/backend/webgpu/motionPass.d.ts +20 -0
- package/dist/render/backend/webgpu/motionPass.js +106 -9
- package/dist/render/backend/webgpu/postPass.d.ts +3 -1
- package/dist/render/backend/webgpu/postPass.js +6 -3
- package/dist/render/backend/webgpu/renderer.d.ts +113 -5
- package/dist/render/backend/webgpu/renderer.js +498 -48
- package/dist/render/backend/webgpu/shaders/clothSolve.wgsl.d.ts +33 -0
- package/dist/render/backend/webgpu/shaders/clothSolve.wgsl.js +469 -0
- package/dist/render/backend/webgpu/skinScatterPass.d.ts +51 -0
- package/dist/render/backend/webgpu/skinScatterPass.js +253 -0
- package/dist/render/backend/webgpu/surfaceTexturePass.d.ts +4 -1
- package/dist/render/backend/webgpu/surfaceTexturePass.js +37 -12
- package/dist/render/clothBindingData.d.ts +41 -0
- package/dist/render/clothBindingData.js +72 -0
- package/dist/render/clothPlacement.d.ts +25 -0
- package/dist/render/clothPlacement.js +85 -0
- package/dist/render/compressedSource.d.ts +66 -0
- package/dist/render/compressedSource.js +138 -0
- package/dist/render/cutoutCaster.d.ts +2 -0
- package/dist/render/cutoutCaster.js +2 -0
- package/dist/render/cutoutDither.d.ts +51 -0
- package/dist/render/cutoutDither.js +90 -0
- package/dist/render/eyeRefraction.d.ts +35 -0
- package/dist/render/eyeRefraction.js +40 -0
- package/dist/render/glCompressed.d.ts +27 -0
- package/dist/render/glCompressed.js +53 -0
- package/dist/render/hairLobes.d.ts +70 -0
- package/dist/render/hairLobes.js +120 -0
- package/dist/render/lightBudget.d.ts +22 -0
- package/dist/render/lightBudget.js +22 -0
- package/dist/render/mesh.d.ts +7 -0
- package/dist/render/mesh.js +24 -0
- package/dist/render/recon/motionVectors.d.ts +4 -2
- package/dist/render/recon/motionVectors.js +6 -3
- package/dist/render/renderQuality.d.ts +20 -0
- package/dist/render/renderQuality.js +5 -0
- package/dist/render/rendererHarness.js +4 -0
- package/dist/render/sceneTarget.d.ts +12 -0
- package/dist/render/sceneTarget.js +14 -0
- package/dist/render/shaders/clothBinding.d.ts +22 -0
- package/dist/render/shaders/clothBinding.js +80 -0
- package/dist/render/shaders/depth.js +42 -6
- package/dist/render/shaders/flat/anisotropic.d.ts +15 -0
- package/dist/render/shaders/flat/anisotropic.js +68 -0
- package/dist/render/shaders/flat/eye.d.ts +1 -0
- package/dist/render/shaders/flat/eye.js +81 -0
- package/dist/render/shaders/flat/hair.d.ts +1 -0
- package/dist/render/shaders/flat/hair.js +101 -0
- package/dist/render/shaders/flat/index.js +36 -2
- package/dist/render/shaders/flat/main.d.ts +1 -1
- package/dist/render/shaders/flat/main.js +113 -17
- package/dist/render/shaders/flat/models.d.ts +14 -0
- package/dist/render/shaders/flat/models.js +273 -0
- package/dist/render/shaders/flat/preamble.js +26 -24
- package/dist/render/shaders/flat/skin.d.ts +1 -0
- package/dist/render/shaders/flat/skin.js +114 -0
- package/dist/render/shaders/generated/depth.wgsl.d.ts +38 -16
- package/dist/render/shaders/generated/depth.wgsl.js +38 -16
- package/dist/render/shaders/generated/flat.wgsl.d.ts +1790 -1704
- package/dist/render/shaders/generated/flat.wgsl.js +1828 -1742
- package/dist/render/shaders/generated/skinBlur.wgsl.d.ts +48 -0
- package/dist/render/shaders/generated/skinBlur.wgsl.js +54 -0
- package/dist/render/shaders/recon/motion.wgsl.d.ts +1 -1
- package/dist/render/shaders/recon/motion.wgsl.js +102 -0
- package/dist/render/shaders/skinBlur.d.ts +1 -0
- package/dist/render/shaders/skinBlur.js +103 -0
- package/dist/render/shaders/skinning.d.ts +3 -1
- package/dist/render/shaders/skinning.js +31 -4
- package/dist/render/shadowCasters.d.ts +13 -1
- package/dist/render/skinBlur.d.ts +41 -0
- package/dist/render/skinBlur.js +49 -0
- package/dist/render/skinScatter.d.ts +67 -0
- package/dist/render/skinScatter.js +80 -0
- package/dist/render/skinnedClothRun.d.ts +26 -0
- package/dist/render/skinnedClothRun.js +84 -0
- package/dist/render/surfaceModel.d.ts +129 -0
- package/dist/render/surfaceModel.js +152 -0
- package/dist/render/surfaceTexture.d.ts +44 -4
- package/dist/render/surfaceTexture.js +60 -46
- package/dist/render/vertexDefaults.js +7 -0
- package/package.json +6 -6
- package/src/build/shaderComments.ts +0 -0
- package/src/geometry/meshConcat.ts +2 -0
- package/src/index.ts +40 -1
- package/src/math/scalar.ts +1 -1
- package/src/render/anisotropicLobe.ts +41 -0
- package/src/render/backend/api.ts +52 -3
- package/src/render/backend/select.ts +8 -0
- package/src/render/backend/webgl2/clothTextures.ts +120 -0
- package/src/render/backend/webgl2/renderer.ts +693 -64
- package/src/render/backend/webgl2/skinScatter.ts +309 -0
- package/src/render/backend/webgpu/buffers.ts +137 -63
- package/src/render/backend/webgpu/clothSolvePack.ts +161 -0
- package/src/render/backend/webgpu/clothTextures.ts +194 -0
- package/src/render/backend/webgpu/compressedUpload.ts +65 -0
- package/src/render/backend/webgpu/computeHost.ts +25 -0
- package/src/render/backend/webgpu/depthPass.ts +39 -7
- package/src/render/backend/webgpu/drawCommand.ts +6 -2
- package/src/render/backend/webgpu/flatPass.ts +145 -7
- package/src/render/backend/webgpu/gpuSkinnedCloth.ts +502 -0
- package/src/render/backend/webgpu/motionPass.ts +128 -9
- package/src/render/backend/webgpu/postPass.ts +5 -1
- package/src/render/backend/webgpu/renderer.ts +663 -43
- package/src/render/backend/webgpu/shaders/clothSolve.wgsl.ts +470 -0
- package/src/render/backend/webgpu/skinScatterPass.ts +309 -0
- package/src/render/backend/webgpu/surfaceTexturePass.ts +42 -12
- package/src/render/clothBindingData.ts +89 -0
- package/src/render/clothPlacement.ts +114 -0
- package/src/render/compressedSource.ts +198 -0
- package/src/render/cutoutCaster.ts +5 -0
- package/src/render/cutoutDither.ts +99 -0
- package/src/render/eyeRefraction.ts +72 -0
- package/src/render/glCompressed.ts +86 -0
- package/src/render/hairLobes.ts +188 -0
- package/src/render/lightBudget.ts +25 -0
- package/src/render/mesh.ts +23 -0
- package/src/render/recon/motionVectors.ts +6 -3
- package/src/render/renderQuality.ts +28 -0
- package/src/render/rendererHarness.ts +4 -0
- package/src/render/sceneTarget.ts +21 -0
- package/src/render/shaders/clothBinding.ts +81 -0
- package/src/render/shaders/depth.ts +42 -6
- package/src/render/shaders/flat/anisotropic.ts +68 -0
- package/src/render/shaders/flat/eye.ts +82 -0
- package/src/render/shaders/flat/hair.ts +102 -0
- package/src/render/shaders/flat/index.ts +36 -2
- package/src/render/shaders/flat/main.ts +113 -17
- package/src/render/shaders/flat/models.ts +286 -0
- package/src/render/shaders/flat/preamble.ts +26 -24
- package/src/render/shaders/flat/skin.ts +116 -0
- package/src/render/shaders/generated/depth.wgsl.ts +38 -16
- package/src/render/shaders/generated/flat.wgsl.ts +1828 -1742
- package/src/render/shaders/generated/skinBlur.wgsl.ts +56 -0
- package/src/render/shaders/recon/motion.wgsl.ts +102 -0
- package/src/render/shaders/skinBlur.ts +105 -0
- package/src/render/shaders/skinning.ts +31 -4
- package/src/render/shadowCasters.ts +13 -0
- package/src/render/skinBlur.ts +53 -0
- package/src/render/skinScatter.ts +92 -0
- package/src/render/skinnedClothRun.ts +128 -0
- package/src/render/surfaceModel.ts +274 -0
- package/src/render/surfaceTexture.ts +123 -63
- package/src/render/vertexDefaults.ts +7 -0
- package/dist/math/exact.d.ts +0 -76
- package/dist/math/exact.js +0 -327
- package/src/math/exact.ts +0 -340
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The eye model in GLSL: `eyeRefraction.ts` is the refraction's arithmetic, and its tests hold it
|
|
3
|
+
* to no shift head-on, the refracted crossing at 30°, a bounded shift edge-on and the map-less iris.
|
|
4
|
+
*
|
|
5
|
+
* **The iris is moved before any map is read** (`modelSurfaceAt`), by how far the eye's ray crosses
|
|
6
|
+
* the iris plane after the cornea bends it, so the whole iris — colour, relief, the model's own
|
|
7
|
+
* channels — moves as one. The crossing is turned into texture coordinates by the tangent frame and
|
|
8
|
+
* by how many of them a metre spans here, which the screen's derivatives say: so it is in uniform
|
|
9
|
+
* control flow, as `modelSurfaceAt` is. **What it gives up** is an anisotropic mapping — a texture
|
|
10
|
+
* stretched one way more than the other moves by the average of the two.
|
|
11
|
+
*
|
|
12
|
+
* **The model map**: red is the iris (1 inside), green the cornea's height above the iris plane as a
|
|
13
|
+
* share of `irisDepth`. Without one, the iris is a disc of `irisRadius` about the texture's centre
|
|
14
|
+
* and the height is `irisDepth` throughout.
|
|
15
|
+
*
|
|
16
|
+
* **Lit as an eye is**: the iris by a normal mirrored about the axis — concave where the cornea is
|
|
17
|
+
* convex, so light pools on the side away from it — and the sclera by the surface's own; and over
|
|
18
|
+
* both, the cornea's highlight, normalised GGX at `corneaRoughness` with the Fresnel of index 1.336,
|
|
19
|
+
* in lamp units like skin's. The environment is reflected at the cornea's split-sum share.
|
|
20
|
+
*/
|
|
21
|
+
import { CORNEA_F0, EYE_MIN_DESCENT } from '../../eyeRefraction.js';
|
|
22
|
+
export const EYE_GLSL = /* glsl */ `
|
|
23
|
+
const float CORNEA_F0 = ${CORNEA_F0.toFixed(9)};
|
|
24
|
+
const float EYE_MIN_DESCENT = ${EYE_MIN_DESCENT.toFixed(4)};
|
|
25
|
+
|
|
26
|
+
/* How much of this texel is iris, gathered with the surface. */
|
|
27
|
+
float eIris;
|
|
28
|
+
|
|
29
|
+
/** Where the iris is without a map: a disc of the model's radius about the centre, a soft limbus. */
|
|
30
|
+
float eyeIrisDisc(vec2 uv) {
|
|
31
|
+
float r = length(uv - 0.5);
|
|
32
|
+
return 1.0 - smoothstep(uModelParams[0].x - 0.01, uModelParams[0].x + 0.01, r);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** The iris's texture coordinate, moved by the cornea: \`eyeRefraction.ts\`. Before any map is read. */
|
|
36
|
+
vec3 eyeRefract(vec3 at) {
|
|
37
|
+
vec3 n = normalize(vNormal);
|
|
38
|
+
vec3 axis = uModelParams[1].xyz;
|
|
39
|
+
vec4 map = texture(uModelMap, at);
|
|
40
|
+
bool mapped = uModelParams[1].w > 0.0;
|
|
41
|
+
float iris = mapped ? map.r : eyeIrisDisc(at.xy);
|
|
42
|
+
float height = uModelParams[0].y * (mapped ? map.g : 1.0);
|
|
43
|
+
vec3 ray = refract(-normalize(uCameraPos - vWorldPos), n, 1.0 / uModelParams[0].z);
|
|
44
|
+
float descent = max(-dot(ray, axis), EYE_MIN_DESCENT);
|
|
45
|
+
vec3 travel = ray * (height / descent);
|
|
46
|
+
vec3 across = travel - axis * dot(travel, axis);
|
|
47
|
+
mat3 frame = tangentFrame(n, vWorldPos, vUv.xy, vTangent, vHasTangents);
|
|
48
|
+
/* How many texture coordinates a metre spans here, from the screen's two derivatives. */
|
|
49
|
+
float perMetre = length(fwidth(vUv.xy)) / max(length(fwidth(vWorldPos)), 1e-9);
|
|
50
|
+
vec2 shift = vec2(dot(across, frame[0]), dot(across, frame[1])) * (perMetre * iris);
|
|
51
|
+
return vec3(at.xy + shift, at.z);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
void eyeSurface(vec3 at) {
|
|
55
|
+
eIris = uModelParams[1].w > 0.0 ? mMap.r : eyeIrisDisc(at.xy);
|
|
56
|
+
mRoughness = uModelParams[0].w;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
void eyeLight(vec3 l, float sourceRadius, float dist) {
|
|
60
|
+
vec3 axis = uModelParams[1].xyz;
|
|
61
|
+
/* The iris is concave where the cornea over it is convex: the surface's normal mirrored about the axis. */
|
|
62
|
+
vec3 irisNormal = normalize(2.0 * dot(mNormal, axis) * axis - mNormal);
|
|
63
|
+
vec3 lit = normalize(mix(mNormal, irisNormal, eIris));
|
|
64
|
+
mDiffuse = mAlbedo * max(dot(lit, l), 0.0) * (1.0 - mMetal);
|
|
65
|
+
|
|
66
|
+
float ndl = max(dot(mNormal, l), 0.0);
|
|
67
|
+
vec3 h = normalize(l + mToEye);
|
|
68
|
+
float ndh = max(dot(mNormal, h), 0.0);
|
|
69
|
+
float ndv = max(dot(mNormal, mToEye), 1e-4);
|
|
70
|
+
float grow = sourceRadius / max(2.0 * dist, 1e-3);
|
|
71
|
+
float alpha = min(max(mRoughness * mRoughness, MIN_LOBE_ALPHA) + grow, 1.0);
|
|
72
|
+
float f = CORNEA_F0 + (1.0 - CORNEA_F0) * pow(1.0 - max(dot(mToEye, h), 0.0), 5.0);
|
|
73
|
+
mSpecular = vec3(3.14159265 * f * smithMasking(ndl, ndv, alpha) * ggxLobe(ndh, alpha) * ndl);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** The environment at the cornea's Fresnel, by the split sum's share at its own roughness. */
|
|
77
|
+
float eyeReflectance() {
|
|
78
|
+
vec2 dfg = envBrdfApprox(max(dot(mNormal, mToEye), 0.0), uModelParams[0].w);
|
|
79
|
+
return CORNEA_F0 * dfg.x + dfg.y;
|
|
80
|
+
}
|
|
81
|
+
`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const HAIR_GLSL: string;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The hair model in GLSL: `hairLobes.ts` is the same arithmetic, and its tests hold the lobes to
|
|
3
|
+
* their tilted peaks, the transmitted lobe to the backlight, the sum to what a white strand
|
|
4
|
+
* receives, and every term to a finite answer where the geometry degenerates.
|
|
5
|
+
*
|
|
6
|
+
* **The strand is the tangent, root to tip.** The model map's green turns each strand's tilt by up
|
|
7
|
+
* to half of it either way (0.5 is none) and its blue is occlusion, which the sky, DriftLight and
|
|
8
|
+
* the environment's reflection take and the lamps do not — their shadows are theirs to cast. The
|
|
9
|
+
* red is not read: a colour from root to tip is the albedo map's to carry.
|
|
10
|
+
*
|
|
11
|
+
* **The environment** is the reflected lobe's: mirrored about a normal turned toward the eye across
|
|
12
|
+
* the strand, which is the cone R lies on, at the strand's own Fresnel — the lobe integrates to it
|
|
13
|
+
* over every direction of arrival. **What it gives up** is the two transmitted lobes against the
|
|
14
|
+
* sky, which a head of hair lit from behind by an open sky would show as a rim; the lamps carry
|
|
15
|
+
* them.
|
|
16
|
+
*/
|
|
17
|
+
import { HAIR_F0, HAIR_MIN_BETA, HAIR_SCATTER_SPHERE } from '../../hairLobes.js';
|
|
18
|
+
export const HAIR_GLSL = /* glsl */ `
|
|
19
|
+
const float HAIR_F0 = ${HAIR_F0.toFixed(9)};
|
|
20
|
+
const float HAIR_MIN_BETA = ${HAIR_MIN_BETA.toFixed(3)};
|
|
21
|
+
const float HAIR_SCATTER_SPHERE = ${HAIR_SCATTER_SPHERE.toFixed(3)};
|
|
22
|
+
|
|
23
|
+
/* This texel's tilt, gathered once with the surface. */
|
|
24
|
+
float hShift;
|
|
25
|
+
|
|
26
|
+
void hairSurface() {
|
|
27
|
+
hShift = uModelParams[0].x * (0.5 + mMap.g);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** A longitudinal lobe: a normalised Gaussian of width \`beta\` at \`x\` from its centre. */
|
|
31
|
+
float hairLongitudinal(float beta, float x) {
|
|
32
|
+
return exp(-0.5 * x * x / (beta * beta)) / (2.5066283 * beta);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
float hairFresnel(float cosine) {
|
|
36
|
+
float c = 1.0 - clamp(cosine, 0.0, 1.0);
|
|
37
|
+
return HAIR_F0 + (1.0 - HAIR_F0) * c * c * c * c * c;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** The normal turned toward the eye across the strand: the scatter's and the environment's. */
|
|
41
|
+
vec3 hairAcross() {
|
|
42
|
+
vec3 across = mToEye - mTangent * dot(mTangent, mToEye);
|
|
43
|
+
float length2 = dot(across, across);
|
|
44
|
+
return length2 > 1e-8 ? across * inversesqrt(length2) : mNormal;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
void hairLight(vec3 l, float sourceRadius, float dist) {
|
|
48
|
+
vec3 t = mTangent;
|
|
49
|
+
float sinI = clamp(dot(t, l), -1.0, 1.0);
|
|
50
|
+
float sinO = clamp(dot(t, mToEye), -1.0, 1.0);
|
|
51
|
+
/* Floored for the half angle's limit, whose single-precision cosine is negative: hairLobes.ts. */
|
|
52
|
+
float cosD = max(cos(0.5 * abs(asin(sinO) - asin(sinI))), 1e-3);
|
|
53
|
+
vec3 lp = l - sinI * t;
|
|
54
|
+
vec3 vp = mToEye - sinO * t;
|
|
55
|
+
float cosPhi = dot(lp, vp) * inversesqrt(dot(lp, lp) * dot(vp, vp) + 1e-4);
|
|
56
|
+
float cosHalfPhi = sqrt(clamp(0.5 + 0.5 * cosPhi, 0.0, 1.0));
|
|
57
|
+
float beta = max(mRoughness * mRoughness, HAIR_MIN_BETA);
|
|
58
|
+
float grow = sourceRadius / max(2.0 * dist, 1e-3);
|
|
59
|
+
float x = sinI + sinO;
|
|
60
|
+
|
|
61
|
+
float r = hairLongitudinal(beta + grow, x + 2.0 * hShift) * 0.25 * cosHalfPhi
|
|
62
|
+
* hairFresnel(sqrt(clamp(0.5 + 0.5 * dot(l, mToEye), 0.0, 1.0)));
|
|
63
|
+
|
|
64
|
+
float a = 1.0 / (1.19 / cosD + 0.36 * cosD);
|
|
65
|
+
float h = cosHalfPhi * (1.0 + a * (0.6 - 0.8 * cosPhi));
|
|
66
|
+
float fTT = hairFresnel(cosD * sqrt(clamp(1.0 - h * h, 0.0, 1.0)));
|
|
67
|
+
float tt = hairLongitudinal(0.5 * beta + grow, x - hShift) * exp(-3.65 * cosPhi - 3.98)
|
|
68
|
+
* (1.0 - fTT) * (1.0 - fTT) * uModelParams[0].z;
|
|
69
|
+
float ttPower = 0.5 * sqrt(clamp(1.0 - h * h * a * a, 0.0, 1.0)) / cosD;
|
|
70
|
+
|
|
71
|
+
float fTRT = hairFresnel(0.5 * cosD);
|
|
72
|
+
float trt = hairLongitudinal(2.0 * beta + grow, x - 3.0 * hShift) * exp(17.0 * cosPhi - 16.78)
|
|
73
|
+
* (1.0 - fTRT) * (1.0 - fTRT) * fTRT;
|
|
74
|
+
|
|
75
|
+
/* Above zero, so pow never takes the logarithm of nothing: hairLobes.ts. */
|
|
76
|
+
vec3 fibre = max(mAlbedo, vec3(1e-4));
|
|
77
|
+
/* π: the published lobes are per unit irradiance, and a lamp here is π of that. */
|
|
78
|
+
mSpecular = 3.14159265 * (vec3(r) + tt * pow(fibre, vec3(ttPower)) + trt * pow(fibre, vec3(0.8 / cosD)));
|
|
79
|
+
float wrapped = clamp((dot(hairAcross(), l) + 1.0) * 0.25, 0.0, 1.0);
|
|
80
|
+
mDiffuse = sqrt(mAlbedo) * uModelParams[0].y * mix(wrapped, 1.0 - abs(sinI), 0.33);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* A shadow on the scatter: light that reaches a strand in another's shadow has passed through
|
|
85
|
+
* hair to get there, so a penumbra deepens toward the fibre's own hue.
|
|
86
|
+
*/
|
|
87
|
+
vec3 hairShade(float shadow) {
|
|
88
|
+
vec3 hue = mAlbedo / max(dot(mAlbedo, vec3(0.2126, 0.7152, 0.0722)), 1e-4);
|
|
89
|
+
return shadow * pow(max(hue, vec3(1e-4)), vec3(1.0 - shadow));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Light from every side, through the scatter term: \`HAIR_SCATTER_SPHERE\` says why that number. */
|
|
93
|
+
vec3 hairAround(vec3 light) {
|
|
94
|
+
return sqrt(mAlbedo) * (uModelParams[0].y * HAIR_SCATTER_SPHERE * mMap.b) * light;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** The reflected lobe's share of the environment: its Fresnel, which is what it integrates to. */
|
|
98
|
+
float hairReflectance() {
|
|
99
|
+
return hairFresnel(dot(hairAcross(), mToEye)) * mMap.b;
|
|
100
|
+
}
|
|
101
|
+
`;
|
|
@@ -3,15 +3,18 @@ import { OCTAHEDRAL_GLSL } from '../octahedral.js';
|
|
|
3
3
|
import { PROBEGRID_GLSL } from './probeGrid.js';
|
|
4
4
|
import { TANGENT_FRAME_GLSL } from '../tangentFrame.js';
|
|
5
5
|
import { CUTOUT_COVERAGE_GLSL } from '../cutoutCoverage.js';
|
|
6
|
+
import { CUTOUT_DITHER_GLSL } from '../../cutoutDither.js';
|
|
6
7
|
import { preambleGlsl } from './preamble.js';
|
|
7
8
|
import { LOBES_GLSL } from './lobes.js';
|
|
8
9
|
import { POINTSHADOW_GLSL } from './pointShadow.js';
|
|
9
10
|
import { DIRECTIONALSHADOW_GLSL } from './directionalShadow.js';
|
|
10
11
|
import { glassTintGlsl, litSwitchesGlsl } from './glassTint.js';
|
|
11
12
|
import { MORPH_GLSL } from '../morph.js';
|
|
13
|
+
import { CLOTH_BINDING_GLSL } from '../clothBinding.js';
|
|
12
14
|
import { SKINNING_GLSL } from '../skinning.js';
|
|
13
15
|
import { SURFACE_GLSL } from './surface.js';
|
|
14
16
|
import { MAIN_GLSL } from './main.js';
|
|
17
|
+
import { MODELS_GLSL } from './models.js';
|
|
15
18
|
import { DRIFT_LIGHT_GLSL } from './driftLight.js';
|
|
16
19
|
import { SURFACE_EFFECTS_GLSL } from './surfaceEffects.js';
|
|
17
20
|
import { CHANNEL_ATTRIBUTE, CHANNEL_BEND } from '../vertexChannel.js';
|
|
@@ -144,6 +147,10 @@ ${CHANNEL_BEND}
|
|
|
144
147
|
#if MORPHED
|
|
145
148
|
${MORPH_GLSL}
|
|
146
149
|
#endif
|
|
150
|
+
#if SKINNED
|
|
151
|
+
/* Samplers and a constant alone, so no field of the vertex block moves. See clothBinding.ts. */
|
|
152
|
+
${CLOTH_BINDING_GLSL}
|
|
153
|
+
#endif
|
|
147
154
|
|
|
148
155
|
out vec3 vNormal;
|
|
149
156
|
out vec3 vColor;
|
|
@@ -217,9 +224,11 @@ void main() {
|
|
|
217
224
|
mat4 skin = skinMatrix();
|
|
218
225
|
vec4 local = skin * vec4(basePosition, 1.0);
|
|
219
226
|
vec3 localNormal = mat3(skin) * aNormal;
|
|
227
|
+
vec3 localTangent = mat3(skin) * aTangent.xyz;
|
|
220
228
|
#else
|
|
221
229
|
vec4 local = vec4(basePosition, 1.0);
|
|
222
230
|
vec3 localNormal = aNormal;
|
|
231
|
+
vec3 localTangent = aTangent.xyz;
|
|
223
232
|
#endif
|
|
224
233
|
#if INSTANCED
|
|
225
234
|
mat4 model = mat4(aInstanceModel0, aInstanceModel1, aInstanceModel2, aInstanceModel3);
|
|
@@ -240,9 +249,31 @@ void main() {
|
|
|
240
249
|
vec3 bent = channelBend(world.xyz, aChannel.x);
|
|
241
250
|
#endif
|
|
242
251
|
world = vec4(bent, world.w);
|
|
243
|
-
vWorldPos = world.xyz;
|
|
244
252
|
// Rotation/translation-only models (our case): mat3 is a valid normal matrix.
|
|
245
253
|
vec3 worldNormal = mat3(model) * localNormal;
|
|
254
|
+
/*
|
|
255
|
+
* **The tangent turns as the normal does**, because the fragment stage crosses it with the
|
|
256
|
+
* world-space normal to build its frame. It went out in the mesh's own space until 4.8.4, which
|
|
257
|
+
* is world space only for a mesh that is moved and never turned: a turned or skinned mesh lit its
|
|
258
|
+
* normal map, and anything reading a direction along its surface, from the wrong side.
|
|
259
|
+
*/
|
|
260
|
+
vec3 worldTangent = mat3(model) * localTangent;
|
|
261
|
+
#if SKINNED
|
|
262
|
+
/*
|
|
263
|
+
* **Toward the cloth, after the skeleton and the bend.** The simulation already swings with the
|
|
264
|
+
* wind it was given, so the bend moves only the skinned part; the weight painted per vertex says
|
|
265
|
+
* how much of the cloth's place and turn the vertex takes. See clothBinding.ts.
|
|
266
|
+
*/
|
|
267
|
+
if (CLOTH_BOUND) {
|
|
268
|
+
vec3 clothPosition;
|
|
269
|
+
mat3 turn;
|
|
270
|
+
float follow = clothPlace(clothPosition, turn);
|
|
271
|
+
world = vec4(mix(world.xyz, clothPosition, follow), world.w);
|
|
272
|
+
worldNormal = normalize(mix(worldNormal, turn * aNormal, follow));
|
|
273
|
+
worldTangent = mix(worldTangent, turn * aTangent.xyz, follow);
|
|
274
|
+
}
|
|
275
|
+
#endif
|
|
276
|
+
vWorldPos = world.xyz;
|
|
246
277
|
vNormal = worldNormal;
|
|
247
278
|
vLightPos = uLightViewProj * world;
|
|
248
279
|
vColor = aColor * tint;
|
|
@@ -253,7 +284,7 @@ void main() {
|
|
|
253
284
|
vRoughness = aRoughness;
|
|
254
285
|
vGrain = aGrain;
|
|
255
286
|
vRelief = aRelief;
|
|
256
|
-
vTangent = aTangent;
|
|
287
|
+
vTangent = vec4(worldTangent, aTangent.w);
|
|
257
288
|
#if INSTANCED
|
|
258
289
|
/* No channel on this path; the neutral values are what every mesh read before it existed. */
|
|
259
290
|
vSkyDirect = 1.0;
|
|
@@ -397,8 +428,11 @@ export function flatFrag(options) {
|
|
|
397
428
|
TANGENT_FRAME_GLSL,
|
|
398
429
|
/* Unconditional for the same reason, and called only where a cutoff was asked for. */
|
|
399
430
|
CUTOUT_COVERAGE_GLSL,
|
|
431
|
+
CUTOUT_DITHER_GLSL,
|
|
400
432
|
DRIFT_LIGHT_GLSL,
|
|
401
433
|
SURFACE_EFFECTS_GLSL,
|
|
434
|
+
/* Depth zero and after the tangent frame and the lobes it calls; see models.ts. */
|
|
435
|
+
MODELS_GLSL,
|
|
402
436
|
MAIN_GLSL,
|
|
403
437
|
].join('\n'), {
|
|
404
438
|
POINT_SHADOWS: options.pointShadows,
|