@triforge/shader-core 0.1.0
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/README.md +90 -0
- package/dist/bundle.js +5578 -0
- package/dist/core/CompileContext.d.ts +60 -0
- package/dist/core/CompileContext.d.ts.map +1 -0
- package/dist/core/CompileContext.js +276 -0
- package/dist/core/InputNode.d.ts +11 -0
- package/dist/core/InputNode.d.ts.map +1 -0
- package/dist/core/InputNode.js +13 -0
- package/dist/core/InputSocket.d.ts +21 -0
- package/dist/core/InputSocket.d.ts.map +1 -0
- package/dist/core/InputSocket.js +23 -0
- package/dist/core/OutputNode.d.ts +30 -0
- package/dist/core/OutputNode.d.ts.map +1 -0
- package/dist/core/OutputNode.js +60 -0
- package/dist/core/OutputSocket.d.ts +18 -0
- package/dist/core/OutputSocket.d.ts.map +1 -0
- package/dist/core/OutputSocket.js +16 -0
- package/dist/core/ProcessNode.d.ts +8 -0
- package/dist/core/ProcessNode.d.ts.map +1 -0
- package/dist/core/ProcessNode.js +7 -0
- package/dist/core/ShaderConfig.d.ts +13 -0
- package/dist/core/ShaderConfig.d.ts.map +1 -0
- package/dist/core/ShaderConfig.js +11 -0
- package/dist/core/ShaderNode.d.ts +114 -0
- package/dist/core/ShaderNode.d.ts.map +1 -0
- package/dist/core/ShaderNode.js +156 -0
- package/dist/core/ShaderNodeError.d.ts +32 -0
- package/dist/core/ShaderNodeError.d.ts.map +1 -0
- package/dist/core/ShaderNodeError.js +61 -0
- package/dist/core/SocketType.d.ts +12 -0
- package/dist/core/SocketType.d.ts.map +1 -0
- package/dist/core/SocketType.js +7 -0
- package/dist/index.d.ts +164 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +108 -0
- package/dist/nodes/input/Attribute.d.ts +45 -0
- package/dist/nodes/input/Attribute.d.ts.map +1 -0
- package/dist/nodes/input/Attribute.js +58 -0
- package/dist/nodes/input/CameraData.d.ts +21 -0
- package/dist/nodes/input/CameraData.d.ts.map +1 -0
- package/dist/nodes/input/CameraData.js +33 -0
- package/dist/nodes/input/ColorAttribute.d.ts +28 -0
- package/dist/nodes/input/ColorAttribute.d.ts.map +1 -0
- package/dist/nodes/input/ColorAttribute.js +32 -0
- package/dist/nodes/input/Geometry.d.ts +23 -0
- package/dist/nodes/input/Geometry.d.ts.map +1 -0
- package/dist/nodes/input/Geometry.js +38 -0
- package/dist/nodes/input/HairInfo.d.ts +38 -0
- package/dist/nodes/input/HairInfo.d.ts.map +1 -0
- package/dist/nodes/input/HairInfo.js +50 -0
- package/dist/nodes/input/LayerWeight.d.ts +26 -0
- package/dist/nodes/input/LayerWeight.d.ts.map +1 -0
- package/dist/nodes/input/LayerWeight.js +35 -0
- package/dist/nodes/input/LightPath.d.ts +60 -0
- package/dist/nodes/input/LightPath.d.ts.map +1 -0
- package/dist/nodes/input/LightPath.js +112 -0
- package/dist/nodes/input/ObjectInfo.d.ts +22 -0
- package/dist/nodes/input/ObjectInfo.d.ts.map +1 -0
- package/dist/nodes/input/ObjectInfo.js +41 -0
- package/dist/nodes/input/OceanAttribute.d.ts +32 -0
- package/dist/nodes/input/OceanAttribute.d.ts.map +1 -0
- package/dist/nodes/input/OceanAttribute.js +38 -0
- package/dist/nodes/input/ParticleInfo.d.ts +31 -0
- package/dist/nodes/input/ParticleInfo.d.ts.map +1 -0
- package/dist/nodes/input/ParticleInfo.js +44 -0
- package/dist/nodes/input/RGB.d.ts +19 -0
- package/dist/nodes/input/RGB.d.ts.map +1 -0
- package/dist/nodes/input/RGB.js +23 -0
- package/dist/nodes/input/ScreenCamera.d.ts +37 -0
- package/dist/nodes/input/ScreenCamera.d.ts.map +1 -0
- package/dist/nodes/input/ScreenCamera.js +59 -0
- package/dist/nodes/input/Tangent.d.ts +21 -0
- package/dist/nodes/input/Tangent.d.ts.map +1 -0
- package/dist/nodes/input/Tangent.js +30 -0
- package/dist/nodes/input/TextureCoordinate.d.ts +17 -0
- package/dist/nodes/input/TextureCoordinate.d.ts.map +1 -0
- package/dist/nodes/input/TextureCoordinate.js +24 -0
- package/dist/nodes/input/UVMap.d.ts +20 -0
- package/dist/nodes/input/UVMap.d.ts.map +1 -0
- package/dist/nodes/input/UVMap.js +23 -0
- package/dist/nodes/input/Value.d.ts +19 -0
- package/dist/nodes/input/Value.d.ts.map +1 -0
- package/dist/nodes/input/Value.js +22 -0
- package/dist/nodes/input/Wireframe.d.ts +25 -0
- package/dist/nodes/input/Wireframe.d.ts.map +1 -0
- package/dist/nodes/input/Wireframe.js +30 -0
- package/dist/nodes/output/Displacement.d.ts +28 -0
- package/dist/nodes/output/Displacement.d.ts.map +1 -0
- package/dist/nodes/output/Displacement.js +34 -0
- package/dist/nodes/output/MaterialOutput.d.ts +43 -0
- package/dist/nodes/output/MaterialOutput.d.ts.map +1 -0
- package/dist/nodes/output/MaterialOutput.js +118 -0
- package/dist/nodes/output/ScreenOutput.d.ts +38 -0
- package/dist/nodes/output/ScreenOutput.d.ts.map +1 -0
- package/dist/nodes/output/ScreenOutput.js +88 -0
- package/dist/nodes/process/AddShader.d.ts +30 -0
- package/dist/nodes/process/AddShader.d.ts.map +1 -0
- package/dist/nodes/process/AddShader.js +36 -0
- package/dist/nodes/process/AnimatedNoiseTexture.d.ts +39 -0
- package/dist/nodes/process/AnimatedNoiseTexture.d.ts.map +1 -0
- package/dist/nodes/process/AnimatedNoiseTexture.js +93 -0
- package/dist/nodes/process/Blackbody.d.ts +29 -0
- package/dist/nodes/process/Blackbody.d.ts.map +1 -0
- package/dist/nodes/process/Blackbody.js +50 -0
- package/dist/nodes/process/BrickTexture.d.ts +36 -0
- package/dist/nodes/process/BrickTexture.d.ts.map +1 -0
- package/dist/nodes/process/BrickTexture.js +71 -0
- package/dist/nodes/process/BrightContrast.d.ts +30 -0
- package/dist/nodes/process/BrightContrast.d.ts.map +1 -0
- package/dist/nodes/process/BrightContrast.js +41 -0
- package/dist/nodes/process/Bump.d.ts +31 -0
- package/dist/nodes/process/Bump.d.ts.map +1 -0
- package/dist/nodes/process/Bump.js +65 -0
- package/dist/nodes/process/CheckerTexture.d.ts +30 -0
- package/dist/nodes/process/CheckerTexture.d.ts.map +1 -0
- package/dist/nodes/process/CheckerTexture.js +48 -0
- package/dist/nodes/process/Clamp.d.ts +32 -0
- package/dist/nodes/process/Clamp.d.ts.map +1 -0
- package/dist/nodes/process/Clamp.js +37 -0
- package/dist/nodes/process/ColorRamp.d.ts +28 -0
- package/dist/nodes/process/ColorRamp.d.ts.map +1 -0
- package/dist/nodes/process/ColorRamp.js +49 -0
- package/dist/nodes/process/CombineColor.d.ts +34 -0
- package/dist/nodes/process/CombineColor.d.ts.map +1 -0
- package/dist/nodes/process/CombineColor.js +69 -0
- package/dist/nodes/process/CombineRGB.d.ts +29 -0
- package/dist/nodes/process/CombineRGB.d.ts.map +1 -0
- package/dist/nodes/process/CombineRGB.js +33 -0
- package/dist/nodes/process/CombineXYZ.d.ts +29 -0
- package/dist/nodes/process/CombineXYZ.d.ts.map +1 -0
- package/dist/nodes/process/CombineXYZ.js +33 -0
- package/dist/nodes/process/DiffuseBSDF.d.ts +30 -0
- package/dist/nodes/process/DiffuseBSDF.d.ts.map +1 -0
- package/dist/nodes/process/DiffuseBSDF.js +43 -0
- package/dist/nodes/process/Emission.d.ts +30 -0
- package/dist/nodes/process/Emission.d.ts.map +1 -0
- package/dist/nodes/process/Emission.js +36 -0
- package/dist/nodes/process/EnvironmentTexture.d.ts +41 -0
- package/dist/nodes/process/EnvironmentTexture.d.ts.map +1 -0
- package/dist/nodes/process/EnvironmentTexture.js +65 -0
- package/dist/nodes/process/FloatCurve.d.ts +34 -0
- package/dist/nodes/process/FloatCurve.d.ts.map +1 -0
- package/dist/nodes/process/FloatCurve.js +46 -0
- package/dist/nodes/process/Fresnel.d.ts +36 -0
- package/dist/nodes/process/Fresnel.d.ts.map +1 -0
- package/dist/nodes/process/Fresnel.js +53 -0
- package/dist/nodes/process/Gamma.d.ts +29 -0
- package/dist/nodes/process/Gamma.d.ts.map +1 -0
- package/dist/nodes/process/Gamma.js +35 -0
- package/dist/nodes/process/GlassBSDF.d.ts +31 -0
- package/dist/nodes/process/GlassBSDF.d.ts.map +1 -0
- package/dist/nodes/process/GlassBSDF.js +51 -0
- package/dist/nodes/process/GlossyBSDF.d.ts +30 -0
- package/dist/nodes/process/GlossyBSDF.d.ts.map +1 -0
- package/dist/nodes/process/GlossyBSDF.js +50 -0
- package/dist/nodes/process/GradientTexture.d.ts +31 -0
- package/dist/nodes/process/GradientTexture.d.ts.map +1 -0
- package/dist/nodes/process/GradientTexture.js +49 -0
- package/dist/nodes/process/HashValue.d.ts +30 -0
- package/dist/nodes/process/HashValue.d.ts.map +1 -0
- package/dist/nodes/process/HashValue.js +34 -0
- package/dist/nodes/process/HueSaturationValue.d.ts +32 -0
- package/dist/nodes/process/HueSaturationValue.d.ts.map +1 -0
- package/dist/nodes/process/HueSaturationValue.js +58 -0
- package/dist/nodes/process/ImageTexture.d.ts +34 -0
- package/dist/nodes/process/ImageTexture.d.ts.map +1 -0
- package/dist/nodes/process/ImageTexture.js +53 -0
- package/dist/nodes/process/InvertColor.d.ts +29 -0
- package/dist/nodes/process/InvertColor.d.ts.map +1 -0
- package/dist/nodes/process/InvertColor.js +35 -0
- package/dist/nodes/process/MagicTexture.d.ts +30 -0
- package/dist/nodes/process/MagicTexture.d.ts.map +1 -0
- package/dist/nodes/process/MagicTexture.js +54 -0
- package/dist/nodes/process/MapRange.d.ts +38 -0
- package/dist/nodes/process/MapRange.d.ts.map +1 -0
- package/dist/nodes/process/MapRange.js +52 -0
- package/dist/nodes/process/Mapping.d.ts +37 -0
- package/dist/nodes/process/Mapping.d.ts.map +1 -0
- package/dist/nodes/process/Mapping.js +57 -0
- package/dist/nodes/process/Math.d.ts +40 -0
- package/dist/nodes/process/Math.d.ts.map +1 -0
- package/dist/nodes/process/Math.js +100 -0
- package/dist/nodes/process/MixRGB.d.ts +35 -0
- package/dist/nodes/process/MixRGB.d.ts.map +1 -0
- package/dist/nodes/process/MixRGB.js +63 -0
- package/dist/nodes/process/MixShader.d.ts +35 -0
- package/dist/nodes/process/MixShader.d.ts.map +1 -0
- package/dist/nodes/process/MixShader.js +47 -0
- package/dist/nodes/process/MusgraveTexture.d.ts +36 -0
- package/dist/nodes/process/MusgraveTexture.d.ts.map +1 -0
- package/dist/nodes/process/MusgraveTexture.js +70 -0
- package/dist/nodes/process/NoiseTexture.d.ts +31 -0
- package/dist/nodes/process/NoiseTexture.d.ts.map +1 -0
- package/dist/nodes/process/NoiseTexture.js +78 -0
- package/dist/nodes/process/Normal.d.ts +30 -0
- package/dist/nodes/process/Normal.d.ts.map +1 -0
- package/dist/nodes/process/Normal.js +38 -0
- package/dist/nodes/process/NormalMap.d.ts +34 -0
- package/dist/nodes/process/NormalMap.d.ts.map +1 -0
- package/dist/nodes/process/NormalMap.js +54 -0
- package/dist/nodes/process/PrincipledBSDF.d.ts +32 -0
- package/dist/nodes/process/PrincipledBSDF.d.ts.map +1 -0
- package/dist/nodes/process/PrincipledBSDF.js +75 -0
- package/dist/nodes/process/PrincipledHair.d.ts +63 -0
- package/dist/nodes/process/PrincipledHair.d.ts.map +1 -0
- package/dist/nodes/process/PrincipledHair.js +137 -0
- package/dist/nodes/process/PrincipledVolume.d.ts +37 -0
- package/dist/nodes/process/PrincipledVolume.d.ts.map +1 -0
- package/dist/nodes/process/PrincipledVolume.js +67 -0
- package/dist/nodes/process/RGBCurves.d.ts +45 -0
- package/dist/nodes/process/RGBCurves.d.ts.map +1 -0
- package/dist/nodes/process/RGBCurves.js +81 -0
- package/dist/nodes/process/RGBtoBW.d.ts +28 -0
- package/dist/nodes/process/RGBtoBW.d.ts.map +1 -0
- package/dist/nodes/process/RGBtoBW.js +31 -0
- package/dist/nodes/process/RefractionBSDF.d.ts +32 -0
- package/dist/nodes/process/RefractionBSDF.d.ts.map +1 -0
- package/dist/nodes/process/RefractionBSDF.js +46 -0
- package/dist/nodes/process/SchwarzschildMarch.d.ts +56 -0
- package/dist/nodes/process/SchwarzschildMarch.d.ts.map +1 -0
- package/dist/nodes/process/SchwarzschildMarch.js +306 -0
- package/dist/nodes/process/SeparateColor.d.ts +33 -0
- package/dist/nodes/process/SeparateColor.d.ts.map +1 -0
- package/dist/nodes/process/SeparateColor.js +79 -0
- package/dist/nodes/process/SeparateRGB.d.ts +27 -0
- package/dist/nodes/process/SeparateRGB.d.ts.map +1 -0
- package/dist/nodes/process/SeparateRGB.js +31 -0
- package/dist/nodes/process/SeparateXYZ.d.ts +27 -0
- package/dist/nodes/process/SeparateXYZ.d.ts.map +1 -0
- package/dist/nodes/process/SeparateXYZ.js +31 -0
- package/dist/nodes/process/ShaderScript.d.ts +95 -0
- package/dist/nodes/process/ShaderScript.d.ts.map +1 -0
- package/dist/nodes/process/ShaderScript.js +119 -0
- package/dist/nodes/process/ShaderToRGB.d.ts +28 -0
- package/dist/nodes/process/ShaderToRGB.d.ts.map +1 -0
- package/dist/nodes/process/ShaderToRGB.js +33 -0
- package/dist/nodes/process/SheenBSDF.d.ts +31 -0
- package/dist/nodes/process/SheenBSDF.d.ts.map +1 -0
- package/dist/nodes/process/SheenBSDF.js +49 -0
- package/dist/nodes/process/SpecularBSDF.d.ts +32 -0
- package/dist/nodes/process/SpecularBSDF.d.ts.map +1 -0
- package/dist/nodes/process/SpecularBSDF.js +54 -0
- package/dist/nodes/process/SubsurfaceScattering.d.ts +33 -0
- package/dist/nodes/process/SubsurfaceScattering.d.ts.map +1 -0
- package/dist/nodes/process/SubsurfaceScattering.js +46 -0
- package/dist/nodes/process/ToonBSDF.d.ts +31 -0
- package/dist/nodes/process/ToonBSDF.d.ts.map +1 -0
- package/dist/nodes/process/ToonBSDF.js +44 -0
- package/dist/nodes/process/TranslucentBSDF.d.ts +29 -0
- package/dist/nodes/process/TranslucentBSDF.d.ts.map +1 -0
- package/dist/nodes/process/TranslucentBSDF.js +39 -0
- package/dist/nodes/process/VectorCurves.d.ts +42 -0
- package/dist/nodes/process/VectorCurves.d.ts.map +1 -0
- package/dist/nodes/process/VectorCurves.js +71 -0
- package/dist/nodes/process/VectorMath.d.ts +38 -0
- package/dist/nodes/process/VectorMath.d.ts.map +1 -0
- package/dist/nodes/process/VectorMath.js +105 -0
- package/dist/nodes/process/VectorRotate.d.ts +34 -0
- package/dist/nodes/process/VectorRotate.d.ts.map +1 -0
- package/dist/nodes/process/VectorRotate.js +52 -0
- package/dist/nodes/process/VectorTransform.d.ts +36 -0
- package/dist/nodes/process/VectorTransform.d.ts.map +1 -0
- package/dist/nodes/process/VectorTransform.js +48 -0
- package/dist/nodes/process/VolumeAbsorption.d.ts +30 -0
- package/dist/nodes/process/VolumeAbsorption.d.ts.map +1 -0
- package/dist/nodes/process/VolumeAbsorption.js +36 -0
- package/dist/nodes/process/VolumeScatter.d.ts +31 -0
- package/dist/nodes/process/VolumeScatter.d.ts.map +1 -0
- package/dist/nodes/process/VolumeScatter.js +42 -0
- package/dist/nodes/process/VoronoiTexture.d.ts +38 -0
- package/dist/nodes/process/VoronoiTexture.d.ts.map +1 -0
- package/dist/nodes/process/VoronoiTexture.js +123 -0
- package/dist/nodes/process/WaveTexture.d.ts +39 -0
- package/dist/nodes/process/WaveTexture.d.ts.map +1 -0
- package/dist/nodes/process/WaveTexture.js +77 -0
- package/dist/nodes/process/Wavelength.d.ts +28 -0
- package/dist/nodes/process/Wavelength.d.ts.map +1 -0
- package/dist/nodes/process/Wavelength.js +43 -0
- package/dist/nodes/process/WhiteNoise.d.ts +27 -0
- package/dist/nodes/process/WhiteNoise.d.ts.map +1 -0
- package/dist/nodes/process/WhiteNoise.js +44 -0
- package/dist/nodes/shader/AmbientOcclusion.d.ts +47 -0
- package/dist/nodes/shader/AmbientOcclusion.d.ts.map +1 -0
- package/dist/nodes/shader/AmbientOcclusion.js +128 -0
- package/dist/nodes/shader/RayPortal.d.ts +57 -0
- package/dist/nodes/shader/RayPortal.d.ts.map +1 -0
- package/dist/nodes/shader/RayPortal.js +56 -0
- package/dist/shaders/color.d.ts +12 -0
- package/dist/shaders/color.d.ts.map +1 -0
- package/dist/shaders/color.js +42 -0
- package/dist/shaders/noise.d.ts +12 -0
- package/dist/shaders/noise.d.ts.map +1 -0
- package/dist/shaders/noise.js +70 -0
- package/dist/types/shader.d.ts +17 -0
- package/dist/types/shader.d.ts.map +1 -0
- package/dist/types/shader.js +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { ProcessNode } from '../../core/ProcessNode.js';
|
|
2
|
+
/**
|
|
3
|
+
* Principled BSDF — Blender "Principled BSDF" node equivalent.
|
|
4
|
+
*
|
|
5
|
+
* Inputs: baseColor, metallic, roughness, ior, alpha, normal
|
|
6
|
+
* Outputs: BSDF (shader)
|
|
7
|
+
*/
|
|
8
|
+
export class PrincipledBSDF extends ProcessNode {
|
|
9
|
+
get nodeType() { return 'PrincipledBSDF'; }
|
|
10
|
+
get metadata() {
|
|
11
|
+
return { label: 'Principled BSDF', category: 'Shader', color: '#336699', cost: 'medium', costNote: 'Schlick Fresnel + GGX — heavier on mobile.' };
|
|
12
|
+
}
|
|
13
|
+
constructor(inputs = {}) {
|
|
14
|
+
super('PrincipledBSDF');
|
|
15
|
+
this._inputs = this.createInputs(inputs, {
|
|
16
|
+
baseColor: ['color', '#ffffff'],
|
|
17
|
+
metallic: ['float', 0.0],
|
|
18
|
+
roughness: ['float', 0.5],
|
|
19
|
+
ior: ['float', 1.5],
|
|
20
|
+
alpha: ['float', 1.0],
|
|
21
|
+
normal: ['color', null],
|
|
22
|
+
});
|
|
23
|
+
this._outputs = this.createOutputs({ BSDF: 'shader' });
|
|
24
|
+
}
|
|
25
|
+
getInputSockets() { return this._inputs; }
|
|
26
|
+
getOutputSockets() { return this._outputs; }
|
|
27
|
+
compileDefs() { return this.glslFunction ?? PrincipledBSDF.glslFunction; }
|
|
28
|
+
compileCall(ctx) {
|
|
29
|
+
const normal = this._inputs.normal.isConnected()
|
|
30
|
+
? ctx.outputVar(this._inputs.normal.connection.node, this._inputs.normal.connection.name)
|
|
31
|
+
: 'normalize(vNormal)';
|
|
32
|
+
return `vec3 ${ctx.outputVar(this, 'BSDF')} = _st_principledBSDF(${ctx.resolveInput(this._inputs.baseColor)}, ${ctx.resolveInput(this._inputs.metallic)}, ${ctx.resolveInput(this._inputs.roughness)}, ${ctx.resolveInput(this._inputs.ior)}, ${ctx.resolveInput(this._inputs.alpha)}, ${normal});`;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
PrincipledBSDF.instanceSpecificDef = false;
|
|
36
|
+
PrincipledBSDF.glslFunction = `
|
|
37
|
+
// Set these on material.uniforms after compile()
|
|
38
|
+
#ifndef _ST_HAIR_LIGHT_UNIFORMS
|
|
39
|
+
#define _ST_HAIR_LIGHT_UNIFORMS
|
|
40
|
+
uniform vec3 uSunDirection;
|
|
41
|
+
uniform vec3 uSunColor;
|
|
42
|
+
uniform vec3 uAmbientColor;
|
|
43
|
+
#endif
|
|
44
|
+
|
|
45
|
+
vec3 _st_schlick(vec3 F0, float c) {
|
|
46
|
+
return F0 + (1.0 - F0) * pow(clamp(1.0 - c, 0.0, 1.0), 5.0);
|
|
47
|
+
}
|
|
48
|
+
float _st_ggx(float NdotH, float r) {
|
|
49
|
+
float a = r * r, a2 = a * a;
|
|
50
|
+
float d = (NdotH * NdotH) * (a2 - 1.0) + 1.0;
|
|
51
|
+
return a2 / max(3.14159 * d * d, 1e-7);
|
|
52
|
+
}
|
|
53
|
+
float _st_geo(float NdotX, float r) {
|
|
54
|
+
float k = (r + 1.0) * (r + 1.0) / 8.0;
|
|
55
|
+
return NdotX / max(NdotX * (1.0 - k) + k, 1e-7);
|
|
56
|
+
}
|
|
57
|
+
vec3 _st_principledBSDF(vec3 base, float metallic, float roughness, float ior, float alpha, vec3 N) {
|
|
58
|
+
vec3 V = normalize(cameraPosition - vPosition);
|
|
59
|
+
vec3 L = normalize(uSunDirection);
|
|
60
|
+
vec3 H = normalize(L + V);
|
|
61
|
+
float r = max(roughness, 0.04);
|
|
62
|
+
float NdotL = max(dot(N, L), 0.0);
|
|
63
|
+
float NdotV = max(dot(N, V), 1e-4);
|
|
64
|
+
float NdotH = max(dot(N, H), 0.0);
|
|
65
|
+
float HdotV = max(dot(H, V), 0.0);
|
|
66
|
+
float f0s = pow((1.0 - ior) / (1.0 + ior), 2.0);
|
|
67
|
+
vec3 F0 = mix(vec3(f0s), base, metallic);
|
|
68
|
+
vec3 F = _st_schlick(F0, HdotV);
|
|
69
|
+
float D = _st_ggx(NdotH, r);
|
|
70
|
+
float G = _st_geo(NdotL, r) * _st_geo(NdotV, r);
|
|
71
|
+
vec3 spec = (D * G * F) / max(4.0 * NdotV * NdotL, 1e-7);
|
|
72
|
+
vec3 kD = (1.0 - F) * (1.0 - metallic);
|
|
73
|
+
vec3 ambient = uAmbientColor * base;
|
|
74
|
+
return ambient + (kD * base / 3.14159 + spec * uSunColor) * NdotL;
|
|
75
|
+
}`;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { ProcessNode } from '../../core/ProcessNode.js';
|
|
2
|
+
import type { NodeMetadata } from '../../core/ShaderNode.js';
|
|
3
|
+
import type { CompileContext } from '../../core/CompileContext.js';
|
|
4
|
+
import type { OutputSocket } from '../../core/OutputSocket.js';
|
|
5
|
+
export interface PrincipledHairInputs {
|
|
6
|
+
/** Base hair color. Blender: Color. */
|
|
7
|
+
color?: OutputSocket | string;
|
|
8
|
+
/** Longitudinal roughness — scattering along the strand axis. Blender: Roughness. */
|
|
9
|
+
roughness?: OutputSocket | number;
|
|
10
|
+
/** Azimuthal roughness — scattering around the strand. Blender: Radial Roughness. */
|
|
11
|
+
radialRoughness?: OutputSocket | number;
|
|
12
|
+
/** Clear-coat specular intensity. Blender: Coat. */
|
|
13
|
+
coat?: OutputSocket | number;
|
|
14
|
+
/** Index of refraction — affects R-lobe highlight color. Blender: IOR. */
|
|
15
|
+
ior?: OutputSocket | number;
|
|
16
|
+
/** Longitudinal shift of specular lobes. Blender: Offset. */
|
|
17
|
+
offset?: OutputSocket | number;
|
|
18
|
+
/** Per-strand color variation amount [0,1]. Blender: Random Color. */
|
|
19
|
+
randomColor?: OutputSocket | number;
|
|
20
|
+
/** Per-strand roughness variation amount [0,1]. Blender: Random Roughness. */
|
|
21
|
+
randomRoughness?: OutputSocket | number;
|
|
22
|
+
/** Random seed input — connect HairInfo.Random for per-strand variation. */
|
|
23
|
+
random?: OutputSocket | number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Principled Hair BSDF — Blender "Principled Hair BSDF" node equivalent.
|
|
27
|
+
*
|
|
28
|
+
* Implements a Kajiya-Kay dual-lobe model suitable for real-time rendering:
|
|
29
|
+
* • Diffuse: sin(T, L) — angle between tangent and light
|
|
30
|
+
* • R lobe: primary specular highlight (white, sharp, IOR-tinted)
|
|
31
|
+
* • TRT lobe: secondary specular (colored, broader, offset in opposite direction)
|
|
32
|
+
* • Coat: clear-coat gloss on top
|
|
33
|
+
*
|
|
34
|
+
* Connect HairInfo.TangentNormal to the internal `tangent` socket and
|
|
35
|
+
* HairInfo.Random to `random` for correct per-strand behavior.
|
|
36
|
+
*
|
|
37
|
+
* Inputs: color, roughness, radialRoughness, coat, ior, offset,
|
|
38
|
+
* randomColor, randomRoughness, random, tangent
|
|
39
|
+
* Outputs: BSDF (shader)
|
|
40
|
+
*/
|
|
41
|
+
export declare class PrincipledHair extends ProcessNode {
|
|
42
|
+
get nodeType(): string;
|
|
43
|
+
static instanceSpecificDef: boolean;
|
|
44
|
+
get metadata(): NodeMetadata;
|
|
45
|
+
static glslFunction: string;
|
|
46
|
+
private readonly _inputs;
|
|
47
|
+
private readonly _outputs;
|
|
48
|
+
constructor(inputs?: PrincipledHairInputs);
|
|
49
|
+
getInputSockets(): Record<string, import("../../core/InputSocket.js").InputSocket<unknown>>;
|
|
50
|
+
getOutputSockets(): Record<string, OutputSocket>;
|
|
51
|
+
compileDefs(): string;
|
|
52
|
+
vertexInjections(): ({
|
|
53
|
+
attrName: string;
|
|
54
|
+
attrType: "vec3";
|
|
55
|
+
varyingName: string;
|
|
56
|
+
} | {
|
|
57
|
+
attrName: string;
|
|
58
|
+
attrType: "float";
|
|
59
|
+
varyingName: string;
|
|
60
|
+
})[];
|
|
61
|
+
compileCall(ctx: CompileContext): string;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=PrincipledHair.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PrincipledHair.d.ts","sourceRoot":"","sources":["../../../src/nodes/process/PrincipledHair.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAE9D,MAAM,WAAW,oBAAoB;IACnC,uCAAuC;IACvC,KAAK,CAAC,EAAa,YAAY,GAAG,MAAM,CAAA;IACxC,qFAAqF;IACrF,SAAS,CAAC,EAAS,YAAY,GAAG,MAAM,CAAA;IACxC,qFAAqF;IACrF,eAAe,CAAC,EAAG,YAAY,GAAG,MAAM,CAAA;IACxC,oDAAoD;IACpD,IAAI,CAAC,EAAc,YAAY,GAAG,MAAM,CAAA;IACxC,0EAA0E;IAC1E,GAAG,CAAC,EAAe,YAAY,GAAG,MAAM,CAAA;IACxC,6DAA6D;IAC7D,MAAM,CAAC,EAAY,YAAY,GAAG,MAAM,CAAA;IACxC,sEAAsE;IACtE,WAAW,CAAC,EAAO,YAAY,GAAG,MAAM,CAAA;IACxC,8EAA8E;IAC9E,eAAe,CAAC,EAAG,YAAY,GAAG,MAAM,CAAA;IACxC,4EAA4E;IAC5E,MAAM,CAAC,EAAY,YAAY,GAAG,MAAM,CAAA;CACzC;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,cAAe,SAAQ,WAAW;IAC7C,IAAI,QAAQ,WAA8B;IAC1C,MAAM,CAAC,mBAAmB,UAAQ;IAElC,IAAI,QAAQ,IAAI,YAAY,CAE3B;IAGD,MAAM,CAAC,YAAY,SAsEnB;IAEA,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2E;IACnG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmE;gBAEhF,MAAM,GAAE,oBAAyB;IAiB7C,eAAe;IACf,gBAAgB;IAChB,WAAW;IAGX,gBAAgB;;;;;;;;;IAOhB,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM;CAgBzC"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { ProcessNode } from '../../core/ProcessNode.js';
|
|
2
|
+
/**
|
|
3
|
+
* Principled Hair BSDF — Blender "Principled Hair BSDF" node equivalent.
|
|
4
|
+
*
|
|
5
|
+
* Implements a Kajiya-Kay dual-lobe model suitable for real-time rendering:
|
|
6
|
+
* • Diffuse: sin(T, L) — angle between tangent and light
|
|
7
|
+
* • R lobe: primary specular highlight (white, sharp, IOR-tinted)
|
|
8
|
+
* • TRT lobe: secondary specular (colored, broader, offset in opposite direction)
|
|
9
|
+
* • Coat: clear-coat gloss on top
|
|
10
|
+
*
|
|
11
|
+
* Connect HairInfo.TangentNormal to the internal `tangent` socket and
|
|
12
|
+
* HairInfo.Random to `random` for correct per-strand behavior.
|
|
13
|
+
*
|
|
14
|
+
* Inputs: color, roughness, radialRoughness, coat, ior, offset,
|
|
15
|
+
* randomColor, randomRoughness, random, tangent
|
|
16
|
+
* Outputs: BSDF (shader)
|
|
17
|
+
*/
|
|
18
|
+
export class PrincipledHair extends ProcessNode {
|
|
19
|
+
get nodeType() { return 'PrincipledHair'; }
|
|
20
|
+
get metadata() {
|
|
21
|
+
return { label: 'Principled Hair BSDF', category: 'Shader', color: '#5a3a1a', cost: 'medium' };
|
|
22
|
+
}
|
|
23
|
+
constructor(inputs = {}) {
|
|
24
|
+
super('PrincipledHair');
|
|
25
|
+
this._inputs = this.createInputs(inputs, {
|
|
26
|
+
color: ['color', inputs.color ?? '#8b6050'],
|
|
27
|
+
roughness: ['float', inputs.roughness ?? 0.3],
|
|
28
|
+
radialRoughness: ['float', inputs.radialRoughness ?? 0.5],
|
|
29
|
+
coat: ['float', inputs.coat ?? 0.2],
|
|
30
|
+
ior: ['float', inputs.ior ?? 1.55],
|
|
31
|
+
offset: ['float', inputs.offset ?? 0.04],
|
|
32
|
+
randomColor: ['float', inputs.randomColor ?? 0.1],
|
|
33
|
+
randomRoughness: ['float', inputs.randomRoughness ?? 0.0],
|
|
34
|
+
random: ['float', inputs.random ?? 0.0],
|
|
35
|
+
tangent: ['color', null],
|
|
36
|
+
});
|
|
37
|
+
this._outputs = this.createOutputs({ BSDF: 'shader' });
|
|
38
|
+
}
|
|
39
|
+
getInputSockets() { return this._inputs; }
|
|
40
|
+
getOutputSockets() { return this._outputs; }
|
|
41
|
+
compileDefs() { return PrincipledHair.glslFunction; }
|
|
42
|
+
// Ensure strandTangent is always available even without HairInfo in the graph
|
|
43
|
+
vertexInjections() {
|
|
44
|
+
return [
|
|
45
|
+
{ attrName: 'strandTangent', attrType: 'vec3', varyingName: 'vStrandTangent' },
|
|
46
|
+
{ attrName: 'strandRandom', attrType: 'float', varyingName: 'vStrandRandom' },
|
|
47
|
+
];
|
|
48
|
+
}
|
|
49
|
+
compileCall(ctx) {
|
|
50
|
+
const color = ctx.resolveInput(this._inputs.color);
|
|
51
|
+
const roughness = ctx.resolveInput(this._inputs.roughness);
|
|
52
|
+
const radialRoughness = ctx.resolveInput(this._inputs.radialRoughness);
|
|
53
|
+
const coat = ctx.resolveInput(this._inputs.coat);
|
|
54
|
+
const ior = ctx.resolveInput(this._inputs.ior);
|
|
55
|
+
const offset = ctx.resolveInput(this._inputs.offset);
|
|
56
|
+
const randomColor = ctx.resolveInput(this._inputs.randomColor);
|
|
57
|
+
const randomRoughness = ctx.resolveInput(this._inputs.randomRoughness);
|
|
58
|
+
const random = ctx.resolveInput(this._inputs.random);
|
|
59
|
+
const tangent = this._inputs.tangent.isConnected()
|
|
60
|
+
? ctx.outputVar(this._inputs.tangent.connection.node, this._inputs.tangent.connection.name)
|
|
61
|
+
: 'normalize(vStrandTangent)'; // fallback: read attribute directly if not connected
|
|
62
|
+
return `vec3 ${ctx.outputVar(this, 'BSDF')} = _st_principledHair(${color}, ${roughness}, ${radialRoughness}, ${coat}, ${ior}, ${offset}, ${randomColor}, ${randomRoughness}, ${random}, ${tangent});`;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
PrincipledHair.instanceSpecificDef = false;
|
|
66
|
+
// Light uniforms guarded by a #define so they survive alongside PrincipledBSDF in the same graph.
|
|
67
|
+
PrincipledHair.glslFunction = `
|
|
68
|
+
#ifndef _ST_HAIR_LIGHT_UNIFORMS
|
|
69
|
+
#define _ST_HAIR_LIGHT_UNIFORMS
|
|
70
|
+
uniform vec3 uSunDirection;
|
|
71
|
+
uniform vec3 uSunColor;
|
|
72
|
+
uniform vec3 uAmbientColor;
|
|
73
|
+
#endif
|
|
74
|
+
|
|
75
|
+
float _st_hairHash(float n) {
|
|
76
|
+
return fract(sin(n * 127.1 + 311.7) * 43758.5453);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Kajiya-Kay dual-lobe hair BSDF.
|
|
80
|
+
// T = strand tangent (unit, world space)
|
|
81
|
+
// R = primary specular exponent = 1 / (roughness^2)
|
|
82
|
+
// R2 = secondary specular exponent = 1 / (radialRoughness^2)
|
|
83
|
+
vec3 _st_principledHair(
|
|
84
|
+
vec3 color,
|
|
85
|
+
float roughness,
|
|
86
|
+
float radialRoughness,
|
|
87
|
+
float coat,
|
|
88
|
+
float ior,
|
|
89
|
+
float offset,
|
|
90
|
+
float randomColor,
|
|
91
|
+
float randomRoughness,
|
|
92
|
+
float rnd,
|
|
93
|
+
vec3 T
|
|
94
|
+
) {
|
|
95
|
+
// Per-strand variation
|
|
96
|
+
float rc = _st_hairHash(rnd * 1.3731 + 0.1);
|
|
97
|
+
float rr = _st_hairHash(rnd * 2.7183 + 0.2);
|
|
98
|
+
color = mix(color, color * (0.6 + 0.8 * rc), randomColor);
|
|
99
|
+
roughness = clamp(roughness + (rr - 0.5) * randomRoughness * 0.5, 0.02, 1.0);
|
|
100
|
+
|
|
101
|
+
vec3 V = normalize(cameraPosition - vPosition);
|
|
102
|
+
vec3 L = normalize(uSunDirection);
|
|
103
|
+
vec3 H = normalize(L + V);
|
|
104
|
+
vec3 N = normalize(vNormal);
|
|
105
|
+
|
|
106
|
+
// Kajiya-Kay diffuse: sin(angle T, L)
|
|
107
|
+
float cosT = dot(T, L);
|
|
108
|
+
float sinT = sqrt(max(1.0 - cosT * cosT, 0.0));
|
|
109
|
+
float diff = sinT * max(dot(N, L) * 0.5 + 0.5, 0.0); // wrap diffuse
|
|
110
|
+
|
|
111
|
+
// R lobe — primary specular, shifted by +offset along normal
|
|
112
|
+
float f0 = pow(clamp((1.0 - ior) / (1.0 + ior), 0.0, 1.0), 2.0);
|
|
113
|
+
vec3 T1 = normalize(T + offset * N);
|
|
114
|
+
float cosTH1 = dot(T1, H);
|
|
115
|
+
float sinTH1 = sqrt(max(1.0 - cosTH1 * cosTH1, 0.0));
|
|
116
|
+
float exp1 = max(1.0 / max(roughness * roughness, 0.001), 1.0);
|
|
117
|
+
float spec1 = pow(sinTH1, exp1);
|
|
118
|
+
vec3 F1 = vec3(f0) + (vec3(1.0) - vec3(f0)) * pow(1.0 - max(dot(H, V), 0.0), 5.0);
|
|
119
|
+
|
|
120
|
+
// TRT lobe — secondary specular, shifted by -2*offset, colored
|
|
121
|
+
vec3 T2 = normalize(T - 2.0 * offset * N);
|
|
122
|
+
float cosTH2 = dot(T2, H);
|
|
123
|
+
float sinTH2 = sqrt(max(1.0 - cosTH2 * cosTH2, 0.0));
|
|
124
|
+
float rr2 = clamp(radialRoughness, 0.02, 1.0);
|
|
125
|
+
float exp2 = max(1.0 / max(rr2 * rr2, 0.001), 1.0);
|
|
126
|
+
float spec2 = pow(sinTH2, exp2) * 0.25;
|
|
127
|
+
|
|
128
|
+
// Coat gloss
|
|
129
|
+
float cosTHc = dot(T, H);
|
|
130
|
+
float sinTHc = sqrt(max(1.0 - cosTHc * cosTHc, 0.0));
|
|
131
|
+
float coatSpec = pow(sinTHc, 128.0) * coat;
|
|
132
|
+
|
|
133
|
+
vec3 diffuse = color * (uSunColor * diff + uAmbientColor);
|
|
134
|
+
vec3 specular = uSunColor * (F1 * spec1 + vec3(coatSpec)) + color * uSunColor * spec2;
|
|
135
|
+
|
|
136
|
+
return diffuse + specular;
|
|
137
|
+
}`;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { ProcessNode } from '../../core/ProcessNode.js';
|
|
2
|
+
import type { NodeMetadata } from '../../core/ShaderNode.js';
|
|
3
|
+
import type { CompileContext } from '../../core/CompileContext.js';
|
|
4
|
+
import type { OutputSocket } from '../../core/OutputSocket.js';
|
|
5
|
+
export interface PrincipledVolumeInputs {
|
|
6
|
+
color?: OutputSocket | string;
|
|
7
|
+
density?: OutputSocket | number;
|
|
8
|
+
anisotropy?: OutputSocket | number;
|
|
9
|
+
absorptionColor?: OutputSocket | string;
|
|
10
|
+
emissionColor?: OutputSocket | string;
|
|
11
|
+
emissionStrength?: OutputSocket | number;
|
|
12
|
+
blackbodyIntensity?: OutputSocket | number;
|
|
13
|
+
temperature?: OutputSocket | number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Principled Volume — Blender "Principled Volume" shader node.
|
|
17
|
+
* Combines scatter, absorption, and emission into a single volume shader.
|
|
18
|
+
* Connect to MaterialOutput.volume.
|
|
19
|
+
*
|
|
20
|
+
* Inputs: color, density, anisotropy, absorptionColor, emissionColor,
|
|
21
|
+
* emissionStrength, blackbodyIntensity, temperature
|
|
22
|
+
* Outputs: Volume (shader)
|
|
23
|
+
*/
|
|
24
|
+
export declare class PrincipledVolume extends ProcessNode {
|
|
25
|
+
get nodeType(): string;
|
|
26
|
+
static instanceSpecificDef: boolean;
|
|
27
|
+
get metadata(): NodeMetadata;
|
|
28
|
+
static glslFunction: string;
|
|
29
|
+
private readonly _inputs;
|
|
30
|
+
private readonly _outputs;
|
|
31
|
+
constructor(inputs?: PrincipledVolumeInputs);
|
|
32
|
+
getInputSockets(): Record<string, import("../../core/InputSocket.js").InputSocket<unknown>>;
|
|
33
|
+
getOutputSockets(): Record<string, OutputSocket>;
|
|
34
|
+
compileDefs(): string;
|
|
35
|
+
compileCall(ctx: CompileContext): string;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=PrincipledVolume.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PrincipledVolume.d.ts","sourceRoot":"","sources":["../../../src/nodes/process/PrincipledVolume.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAE9D,MAAM,WAAW,sBAAsB;IACrC,KAAK,CAAC,EAAc,YAAY,GAAG,MAAM,CAAA;IACzC,OAAO,CAAC,EAAY,YAAY,GAAG,MAAM,CAAA;IACzC,UAAU,CAAC,EAAS,YAAY,GAAG,MAAM,CAAA;IACzC,eAAe,CAAC,EAAI,YAAY,GAAG,MAAM,CAAA;IACzC,aAAa,CAAC,EAAM,YAAY,GAAG,MAAM,CAAA;IACzC,gBAAgB,CAAC,EAAG,YAAY,GAAG,MAAM,CAAA;IACzC,kBAAkB,CAAC,EAAE,YAAY,GAAG,MAAM,CAAA;IAC1C,WAAW,CAAC,EAAQ,YAAY,GAAG,MAAM,CAAA;CAC1C;AAED;;;;;;;;GAQG;AACH,qBAAa,gBAAiB,SAAQ,WAAW;IAC/C,IAAI,QAAQ,WAAgC;IAC5C,MAAM,CAAC,mBAAmB,UAAQ;IAElC,IAAI,QAAQ,IAAI,YAAY,CAE3B;IAED,MAAM,CAAC,YAAY,SAqBnB;IAEA,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2E;IACnG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmE;gBAEhF,MAAM,GAAE,sBAA2B;IAe/C,eAAe;IACf,gBAAgB;IAChB,WAAW;IAEX,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM;CAWzC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { ProcessNode } from '../../core/ProcessNode.js';
|
|
2
|
+
/**
|
|
3
|
+
* Principled Volume — Blender "Principled Volume" shader node.
|
|
4
|
+
* Combines scatter, absorption, and emission into a single volume shader.
|
|
5
|
+
* Connect to MaterialOutput.volume.
|
|
6
|
+
*
|
|
7
|
+
* Inputs: color, density, anisotropy, absorptionColor, emissionColor,
|
|
8
|
+
* emissionStrength, blackbodyIntensity, temperature
|
|
9
|
+
* Outputs: Volume (shader)
|
|
10
|
+
*/
|
|
11
|
+
export class PrincipledVolume extends ProcessNode {
|
|
12
|
+
get nodeType() { return 'PrincipledVolume'; }
|
|
13
|
+
get metadata() {
|
|
14
|
+
return { label: 'Principled Volume', category: 'Shader', color: '#1a6688', cost: 'high' };
|
|
15
|
+
}
|
|
16
|
+
constructor(inputs = {}) {
|
|
17
|
+
super('PrincipledVolume');
|
|
18
|
+
this._inputs = this.createInputs(inputs, {
|
|
19
|
+
color: ['color', '#ffffff'],
|
|
20
|
+
density: ['float', inputs.density ?? 1.0],
|
|
21
|
+
anisotropy: ['float', inputs.anisotropy ?? 0.0],
|
|
22
|
+
absorptionColor: ['color', '#000000'],
|
|
23
|
+
emissionColor: ['color', '#000000'],
|
|
24
|
+
emissionStrength: ['float', inputs.emissionStrength ?? 0.0],
|
|
25
|
+
blackbodyIntensity: ['float', inputs.blackbodyIntensity ?? 0.0],
|
|
26
|
+
temperature: ['float', inputs.temperature ?? 1000.0],
|
|
27
|
+
});
|
|
28
|
+
this._outputs = this.createOutputs({ Volume: 'shader' });
|
|
29
|
+
}
|
|
30
|
+
getInputSockets() { return this._inputs; }
|
|
31
|
+
getOutputSockets() { return this._outputs; }
|
|
32
|
+
compileDefs() { return PrincipledVolume.glslFunction; }
|
|
33
|
+
compileCall(ctx) {
|
|
34
|
+
const color = ctx.resolveInput(this._inputs.color);
|
|
35
|
+
const density = ctx.resolveInput(this._inputs.density);
|
|
36
|
+
const anisotropy = ctx.resolveInput(this._inputs.anisotropy);
|
|
37
|
+
const absorptionColor = ctx.resolveInput(this._inputs.absorptionColor);
|
|
38
|
+
const emissionColor = ctx.resolveInput(this._inputs.emissionColor);
|
|
39
|
+
const emissionStrength = ctx.resolveInput(this._inputs.emissionStrength);
|
|
40
|
+
const blackbodyIntensity = ctx.resolveInput(this._inputs.blackbodyIntensity);
|
|
41
|
+
const temperature = ctx.resolveInput(this._inputs.temperature);
|
|
42
|
+
return `vec3 ${ctx.outputVar(this, 'Volume')} = _st_principledVolume(${color}, ${density}, ${anisotropy}, ${absorptionColor}, ${emissionColor}, ${emissionStrength}, ${blackbodyIntensity}, ${temperature});`;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
PrincipledVolume.instanceSpecificDef = false;
|
|
46
|
+
PrincipledVolume.glslFunction = `
|
|
47
|
+
vec3 _st_principledVolume(
|
|
48
|
+
vec3 scatterColor, float density,
|
|
49
|
+
float anisotropy, vec3 absorptionColor,
|
|
50
|
+
vec3 emissionColor, float emissionStrength,
|
|
51
|
+
float blackbodyIntensity, float temperature
|
|
52
|
+
) {
|
|
53
|
+
float g = clamp(anisotropy, -0.9999, 0.9999);
|
|
54
|
+
float g2 = g * g;
|
|
55
|
+
float phase = (1.0 - g2) / pow(1.0 + g2, 1.5);
|
|
56
|
+
|
|
57
|
+
vec3 scatter = scatterColor * density * phase;
|
|
58
|
+
vec3 absorption = absorptionColor * density;
|
|
59
|
+
vec3 emission = emissionColor * emissionStrength;
|
|
60
|
+
|
|
61
|
+
// Simplified blackbody tint: blend toward hot white at high temperature
|
|
62
|
+
float tNorm = clamp((temperature - 800.0) / 4200.0, 0.0, 1.0);
|
|
63
|
+
vec3 bb = mix(vec3(1.0, 0.2, 0.0), vec3(1.0, 0.95, 0.8), tNorm);
|
|
64
|
+
emission += bb * blackbodyIntensity * density;
|
|
65
|
+
|
|
66
|
+
return scatter + emission - absorption * 0.5;
|
|
67
|
+
}`;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ProcessNode } from '../../core/ProcessNode.js';
|
|
2
|
+
import type { NodeMetadata } from '../../core/ShaderNode.js';
|
|
3
|
+
import type { CompileContext } from '../../core/CompileContext.js';
|
|
4
|
+
import type { OutputSocket } from '../../core/OutputSocket.js';
|
|
5
|
+
/** A curve point [x, y] where both x and y are in [0, 1]. */
|
|
6
|
+
export type CurvePoint = [number, number];
|
|
7
|
+
export interface RGBCurvesInputs {
|
|
8
|
+
color?: OutputSocket | string;
|
|
9
|
+
fac?: OutputSocket | number;
|
|
10
|
+
/**
|
|
11
|
+
* Per-channel piecewise linear curve as [[x,y], ...] control points.
|
|
12
|
+
* Points are sorted by x automatically. Default = identity [[0,0],[1,1]].
|
|
13
|
+
*/
|
|
14
|
+
rPoints?: CurvePoint[];
|
|
15
|
+
gPoints?: CurvePoint[];
|
|
16
|
+
bPoints?: CurvePoint[];
|
|
17
|
+
/** Master curve applied after per-channel curves. Default = identity. */
|
|
18
|
+
masterPoints?: CurvePoint[];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* RGB Curves — Blender "RGB Curves" node equivalent.
|
|
22
|
+
* Full piecewise linear curve per channel (R, G, B) plus a master curve.
|
|
23
|
+
* Matches Blender's RGB Curves node exactly — arbitrary control points,
|
|
24
|
+
* piecewise linear interpolation between them.
|
|
25
|
+
*
|
|
26
|
+
* Inputs: color, fac
|
|
27
|
+
* Outputs: Color (color)
|
|
28
|
+
*/
|
|
29
|
+
export declare class RGBCurves extends ProcessNode {
|
|
30
|
+
get nodeType(): string;
|
|
31
|
+
static instanceSpecificDef: boolean;
|
|
32
|
+
get metadata(): NodeMetadata;
|
|
33
|
+
private readonly rPts;
|
|
34
|
+
private readonly gPts;
|
|
35
|
+
private readonly bPts;
|
|
36
|
+
private readonly mPts;
|
|
37
|
+
private readonly _inputs;
|
|
38
|
+
private readonly _outputs;
|
|
39
|
+
constructor(inputs?: RGBCurvesInputs);
|
|
40
|
+
getInputSockets(): Record<string, import("../../core/InputSocket.js").InputSocket<unknown>>;
|
|
41
|
+
getOutputSockets(): Record<string, OutputSocket>;
|
|
42
|
+
compileDefs(): string;
|
|
43
|
+
compileCall(ctx: CompileContext): string;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=RGBCurves.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RGBCurves.d.ts","sourceRoot":"","sources":["../../../src/nodes/process/RGBCurves.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAE9D,6DAA6D;AAC7D,MAAM,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAEzC,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAG,YAAY,GAAG,MAAM,CAAA;IAC9B,GAAG,CAAC,EAAK,YAAY,GAAG,MAAM,CAAA;IAC9B;;;OAGG;IACH,OAAO,CAAC,EAAE,UAAU,EAAE,CAAA;IACtB,OAAO,CAAC,EAAE,UAAU,EAAE,CAAA;IACtB,OAAO,CAAC,EAAE,UAAU,EAAE,CAAA;IACtB,yEAAyE;IACzE,YAAY,CAAC,EAAE,UAAU,EAAE,CAAA;CAC5B;AAED;;;;;;;;GAQG;AACH,qBAAa,SAAU,SAAQ,WAAW;IACxC,IAAI,QAAQ,WAAyB;IACrC,MAAM,CAAC,mBAAmB,UAAO;IAEjC,IAAI,QAAQ,IAAI,YAAY,CAE3B;IAED,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAc;IACnC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAc;IACnC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAc;IACnC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAc;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2E;IACnG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmE;gBAEhF,MAAM,GAAE,eAAoB;IAcxC,eAAe;IACf,gBAAgB;IAEhB,WAAW,IAAI,MAAM;IAUrB,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM;CAkBzC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { ProcessNode } from '../../core/ProcessNode.js';
|
|
2
|
+
/**
|
|
3
|
+
* RGB Curves — Blender "RGB Curves" node equivalent.
|
|
4
|
+
* Full piecewise linear curve per channel (R, G, B) plus a master curve.
|
|
5
|
+
* Matches Blender's RGB Curves node exactly — arbitrary control points,
|
|
6
|
+
* piecewise linear interpolation between them.
|
|
7
|
+
*
|
|
8
|
+
* Inputs: color, fac
|
|
9
|
+
* Outputs: Color (color)
|
|
10
|
+
*/
|
|
11
|
+
export class RGBCurves extends ProcessNode {
|
|
12
|
+
get nodeType() { return 'RGBCurves'; }
|
|
13
|
+
get metadata() {
|
|
14
|
+
return { label: 'RGB Curves', category: 'Color', color: '#633060', cost: 'low' };
|
|
15
|
+
}
|
|
16
|
+
constructor(inputs = {}) {
|
|
17
|
+
super('RGBCurves');
|
|
18
|
+
const identity = [[0, 0], [1, 1]];
|
|
19
|
+
this.rPts = sortPoints(inputs.rPoints ?? identity);
|
|
20
|
+
this.gPts = sortPoints(inputs.gPoints ?? identity);
|
|
21
|
+
this.bPts = sortPoints(inputs.bPoints ?? identity);
|
|
22
|
+
this.mPts = sortPoints(inputs.masterPoints ?? identity);
|
|
23
|
+
this._inputs = this.createInputs(inputs, {
|
|
24
|
+
color: ['color', '#ffffff'],
|
|
25
|
+
fac: ['float', inputs.fac ?? 1.0],
|
|
26
|
+
});
|
|
27
|
+
this._outputs = this.createOutputs({ Color: 'color' });
|
|
28
|
+
}
|
|
29
|
+
getInputSockets() { return this._inputs; }
|
|
30
|
+
getOutputSockets() { return this._outputs; }
|
|
31
|
+
compileDefs() {
|
|
32
|
+
// Emit one piecewise linear evaluator function per curve per instance
|
|
33
|
+
return [
|
|
34
|
+
buildCurveFn(`_rc_r_${this.id}`, this.rPts),
|
|
35
|
+
buildCurveFn(`_rc_g_${this.id}`, this.gPts),
|
|
36
|
+
buildCurveFn(`_rc_b_${this.id}`, this.bPts),
|
|
37
|
+
buildCurveFn(`_rc_m_${this.id}`, this.mPts),
|
|
38
|
+
].join('\n');
|
|
39
|
+
}
|
|
40
|
+
compileCall(ctx) {
|
|
41
|
+
const col = ctx.resolveInput(this._inputs.color);
|
|
42
|
+
const fac = ctx.resolveInput(this._inputs.fac);
|
|
43
|
+
const id = this.id;
|
|
44
|
+
const out = ctx.outputVar(this, 'Color');
|
|
45
|
+
return [
|
|
46
|
+
`vec3 _rc_${id} = ${col};`,
|
|
47
|
+
// Per-channel curves
|
|
48
|
+
`_rc_${id}.r = _rc_r_${id}(_rc_${id}.r);`,
|
|
49
|
+
`_rc_${id}.g = _rc_g_${id}(_rc_${id}.g);`,
|
|
50
|
+
`_rc_${id}.b = _rc_b_${id}(_rc_${id}.b);`,
|
|
51
|
+
// Master curve applied to each channel
|
|
52
|
+
`_rc_${id}.r = _rc_m_${id}(_rc_${id}.r);`,
|
|
53
|
+
`_rc_${id}.g = _rc_m_${id}(_rc_${id}.g);`,
|
|
54
|
+
`_rc_${id}.b = _rc_m_${id}(_rc_${id}.b);`,
|
|
55
|
+
`vec3 ${out} = mix(${col}, clamp(_rc_${id}, 0.0, 1.0), clamp(${fac}, 0.0, 1.0));`,
|
|
56
|
+
].join('\n ');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
RGBCurves.instanceSpecificDef = true;
|
|
60
|
+
// ── helpers ───────────────────────────────────────────────────────────────────
|
|
61
|
+
function sortPoints(pts) {
|
|
62
|
+
return [...pts].sort((a, b) => a[0] - b[0]);
|
|
63
|
+
}
|
|
64
|
+
function buildCurveFn(name, pts) {
|
|
65
|
+
// No array initializers — GLSL ES 1.00 doesn't support float[n](...) syntax.
|
|
66
|
+
// Generate a fully unrolled if/else chain with all values baked as literals.
|
|
67
|
+
const f = (n) => n.toFixed(5);
|
|
68
|
+
const clamps = `
|
|
69
|
+
if (t <= ${f(pts[0][0])}) return ${f(pts[0][1])};
|
|
70
|
+
if (t >= ${f(pts[pts.length - 1][0])}) return ${f(pts[pts.length - 1][1])};`;
|
|
71
|
+
const segments = pts.slice(0, -1).map((p, i) => {
|
|
72
|
+
const x0 = f(p[0]), y0 = f(p[1]);
|
|
73
|
+
const x1 = f(pts[i + 1][0]), y1 = f(pts[i + 1][1]);
|
|
74
|
+
return ` if (t <= ${x1}) return mix(${y0}, ${y1}, (t - ${x0}) / (${x1} - ${x0}));`;
|
|
75
|
+
}).join('\n');
|
|
76
|
+
return `
|
|
77
|
+
float ${name}(float t) {${clamps}
|
|
78
|
+
${segments}
|
|
79
|
+
return ${f(pts[pts.length - 1][1])};
|
|
80
|
+
}`;
|
|
81
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ProcessNode } from '../../core/ProcessNode.js';
|
|
2
|
+
import type { NodeMetadata } from '../../core/ShaderNode.js';
|
|
3
|
+
import type { CompileContext } from '../../core/CompileContext.js';
|
|
4
|
+
import type { OutputSocket } from '../../core/OutputSocket.js';
|
|
5
|
+
export interface RGBtoBWInputs {
|
|
6
|
+
color?: OutputSocket | string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* RGB to BW — Blender "RGB to BW" node equivalent.
|
|
10
|
+
* Converts a colour to a greyscale float using luminance weights.
|
|
11
|
+
*
|
|
12
|
+
* Inputs: color (color)
|
|
13
|
+
* Outputs: Val (float) — luminance value [0-1]
|
|
14
|
+
*/
|
|
15
|
+
export declare class RGBtoBW extends ProcessNode {
|
|
16
|
+
get nodeType(): string;
|
|
17
|
+
static instanceSpecificDef: boolean;
|
|
18
|
+
get metadata(): NodeMetadata;
|
|
19
|
+
static glslFunction: string;
|
|
20
|
+
private readonly _inputs;
|
|
21
|
+
private readonly _outputs;
|
|
22
|
+
constructor(inputs?: RGBtoBWInputs);
|
|
23
|
+
getInputSockets(): Record<string, import("../../core/InputSocket.js").InputSocket<unknown>>;
|
|
24
|
+
getOutputSockets(): Record<string, OutputSocket>;
|
|
25
|
+
compileDefs(): string;
|
|
26
|
+
compileCall(ctx: CompileContext): string;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=RGBtoBW.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RGBtoBW.d.ts","sourceRoot":"","sources":["../../../src/nodes/process/RGBtoBW.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAE9D,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,YAAY,GAAG,MAAM,CAAA;CAC9B;AAED;;;;;;GAMG;AACH,qBAAa,OAAQ,SAAQ,WAAW;IACtC,IAAI,QAAQ,WAAuB;IACnC,MAAM,CAAC,mBAAmB,UAAQ;IAElC,IAAI,QAAQ,IAAI,YAAY,CAE3B;IAED,MAAM,CAAC,YAAY,SAGnB;IAEA,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2E;IACnG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmE;gBAEhF,MAAM,GAAE,aAAkB;IAMtC,eAAe;IACf,gBAAgB;IAChB,WAAW;IAEX,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM;CAIzC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { ProcessNode } from '../../core/ProcessNode.js';
|
|
2
|
+
/**
|
|
3
|
+
* RGB to BW — Blender "RGB to BW" node equivalent.
|
|
4
|
+
* Converts a colour to a greyscale float using luminance weights.
|
|
5
|
+
*
|
|
6
|
+
* Inputs: color (color)
|
|
7
|
+
* Outputs: Val (float) — luminance value [0-1]
|
|
8
|
+
*/
|
|
9
|
+
export class RGBtoBW extends ProcessNode {
|
|
10
|
+
get nodeType() { return 'RGBtoBW'; }
|
|
11
|
+
get metadata() {
|
|
12
|
+
return { label: 'RGB to BW', category: 'Converter', color: '#4a3a6a', cost: 'low' };
|
|
13
|
+
}
|
|
14
|
+
constructor(inputs = {}) {
|
|
15
|
+
super('RGBtoBW');
|
|
16
|
+
this._inputs = this.createInputs(inputs, { color: ['color', '#ffffff'] });
|
|
17
|
+
this._outputs = this.createOutputs({ Val: 'float' });
|
|
18
|
+
}
|
|
19
|
+
getInputSockets() { return this._inputs; }
|
|
20
|
+
getOutputSockets() { return this._outputs; }
|
|
21
|
+
compileDefs() { return RGBtoBW.glslFunction; }
|
|
22
|
+
compileCall(ctx) {
|
|
23
|
+
const col = ctx.resolveInput(this._inputs.color);
|
|
24
|
+
return `float ${ctx.outputVar(this, 'Val')} = _st_rgbToBw(${col});`;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
RGBtoBW.instanceSpecificDef = false;
|
|
28
|
+
RGBtoBW.glslFunction = `
|
|
29
|
+
float _st_rgbToBw(vec3 col) {
|
|
30
|
+
return dot(col, vec3(0.2126, 0.7152, 0.0722));
|
|
31
|
+
}`;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ProcessNode } from '../../core/ProcessNode.js';
|
|
2
|
+
import type { NodeMetadata } from '../../core/ShaderNode.js';
|
|
3
|
+
import type { CompileContext } from '../../core/CompileContext.js';
|
|
4
|
+
import type { OutputSocket } from '../../core/OutputSocket.js';
|
|
5
|
+
export interface RefractionBSDFInputs {
|
|
6
|
+
color?: OutputSocket | string;
|
|
7
|
+
roughness?: OutputSocket | number;
|
|
8
|
+
ior?: OutputSocket | number;
|
|
9
|
+
normal?: OutputSocket;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Refraction BSDF — Blender "Refraction BSDF" node equivalent.
|
|
13
|
+
* Simulates light bending through a transparent medium.
|
|
14
|
+
* Approximated in real-time using a tinted transmission colour.
|
|
15
|
+
*
|
|
16
|
+
* Inputs: color, roughness, ior, normal
|
|
17
|
+
* Outputs: BSDF (shader)
|
|
18
|
+
*/
|
|
19
|
+
export declare class RefractionBSDF extends ProcessNode {
|
|
20
|
+
get nodeType(): string;
|
|
21
|
+
static instanceSpecificDef: boolean;
|
|
22
|
+
get metadata(): NodeMetadata;
|
|
23
|
+
static glslFunction: string;
|
|
24
|
+
private readonly _inputs;
|
|
25
|
+
private readonly _outputs;
|
|
26
|
+
constructor(inputs?: RefractionBSDFInputs);
|
|
27
|
+
getInputSockets(): Record<string, import("../../core/InputSocket.js").InputSocket<unknown>>;
|
|
28
|
+
getOutputSockets(): Record<string, OutputSocket>;
|
|
29
|
+
compileDefs(): string;
|
|
30
|
+
compileCall(ctx: CompileContext): string;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=RefractionBSDF.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RefractionBSDF.d.ts","sourceRoot":"","sources":["../../../src/nodes/process/RefractionBSDF.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAE9D,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,EAAM,YAAY,GAAG,MAAM,CAAA;IACjC,SAAS,CAAC,EAAE,YAAY,GAAG,MAAM,CAAA;IACjC,GAAG,CAAC,EAAQ,YAAY,GAAG,MAAM,CAAA;IACjC,MAAM,CAAC,EAAK,YAAY,CAAA;CACzB;AAED;;;;;;;GAOG;AACH,qBAAa,cAAe,SAAQ,WAAW;IAC7C,IAAI,QAAQ,WAA8B;IAC1C,MAAM,CAAC,mBAAmB,UAAQ;IAElC,IAAI,QAAQ,IAAI,YAAY,CAE3B;IAED,MAAM,CAAC,YAAY,SAOnB;IAEA,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2E;IACnG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmE;gBAEhF,MAAM,GAAE,oBAAyB;IAW7C,eAAe;IACf,gBAAgB;IAChB,WAAW;IAEX,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM;CASzC"}
|