From d8a83be24e2551551f52e1cf41216d3d30a64f9f Mon Sep 17 00:00:00 2001 From: deepkolos Date: Wed, 4 Oct 2023 10:45:04 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=86=95=20feat:=20tangent=20space=20&=20sp?= =?UTF-8?q?imle=20skybox?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/demo/demoSkybox.json | 2575 +++++++++++++++++ example/presets.ts | 2 + src/compilers/ShaderGraphCompiler.ts | 2 +- src/compilers/ShaderGraphFns.ts | 55 + src/components/ShaderGraphComponents.ts | 4 + .../input/geometry/BiTangentVectorRC.ts | 68 + src/components/input/geometry/NormalRC.ts | 13 +- src/components/input/geometry/PositionRC.ts | 15 +- .../input/geometry/TangentVectorRC.ts | 82 + .../input/geometry/ViewDirectionRC.ts | 26 +- src/components/input/geometry/ViewVectorRC.ts | 9 +- src/components/input/geometry/index.ts | 4 +- .../input/texture/SampleTexture2DRC.ts | 1 + src/components/math/vector/TransformRC.ts | 22 +- src/editors/ShaderGraphTypes.ts | 4 + src/materials/WebGPURenderer.ts | 12 +- src/templates/Unlit.ts | 5 +- src/types.ts | 2 +- 18 files changed, 2863 insertions(+), 38 deletions(-) create mode 100644 example/demo/demoSkybox.json create mode 100644 src/components/input/geometry/BiTangentVectorRC.ts create mode 100644 src/components/input/geometry/TangentVectorRC.ts diff --git a/example/demo/demoSkybox.json b/example/demo/demoSkybox.json new file mode 100644 index 0000000..5c9aa05 --- /dev/null +++ b/example/demo/demoSkybox.json @@ -0,0 +1,2575 @@ +{ + "id": "", + "nodes": { + "147": { + "id": 147, + "data": { + "vertValue": 0, + "vertValueType": "vertex", + "expanded": true + }, + "inputs": { + "vert": { + "connections": [ + { + "node": 148, + "output": "vert", + "data": { + "fixed": true + } + } + ] + } + }, + "outputs": {}, + "blocks": [ + { + "id": 151, + "data": { + "baseColorValue": [ + 0, + 0, + 0 + ], + "baseColorValueType": "vec3", + "expanded": true + }, + "inputs": { + "baseColor": { + "connections": [ + { + "node": 356961, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": {}, + "blocks": [], + "position": [ + 0, + 0 + ], + "name": "BaseColorBlock", + "contextId": 147 + } + ], + "position": [ + 2241.508885143782, + 1470.9068661428537 + ], + "name": "Fragment" + }, + "148": { + "id": 148, + "data": { + "vertValue": 0, + "vertValueType": "vertex", + "expanded": true + }, + "inputs": {}, + "outputs": { + "vert": { + "connections": [ + { + "node": 147, + "input": "vert", + "data": { + "fixed": true + } + } + ] + } + }, + "blocks": [ + { + "id": 149, + "data": { + "positionValue": [ + 0, + 0, + 0 + ], + "positionValueType": "vec3", + "expanded": true + }, + "inputs": { + "position": { + "connections": [] + } + }, + "outputs": {}, + "blocks": [], + "position": [ + 0, + 0 + ], + "name": "PositionBlock", + "contextId": 148 + }, + { + "id": 150, + "data": { + "normalValue": [ + 0, + 0, + 0 + ], + "normalValueType": "vec3", + "expanded": true + }, + "inputs": { + "normal": { + "connections": [] + } + }, + "outputs": {}, + "blocks": [], + "position": [ + 0, + 0 + ], + "name": "NormalBlock", + "contextId": 148 + } + ], + "position": [ + 2241.508885143782, + 1270.9068661428537 + ], + "name": "Vertex" + }, + "152": { + "id": 152, + "data": { + "outValue": [ + 0, + 0, + 0 + ], + "outValueType": "vec3", + "spaceValue": "world", + "spaceValueType": "string", + "exposed": true, + "expanded": true, + "previewType": "3d" + }, + "inputs": {}, + "outputs": { + "out": { + "connections": [ + { + "node": 159, + "input": "in", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -1472.7402298291613, + 326.73531264511945 + ], + "name": "Position" + }, + "159": { + "id": 159, + "data": { + "inValue": [ + 0, + 0, + 0 + ], + "inValueType": "vec3", + "outValue": [ + 0, + 0, + 0 + ], + "outValueType": "vec3", + "expanded": true + }, + "inputs": { + "in": { + "connections": [ + { + "node": 152, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 172, + "input": "in", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -1264.3363125443238, + 328.1453145222903 + ], + "name": "Normalize" + }, + "172": { + "id": 172, + "data": { + "inValue": [ + 0, + 0, + 0 + ], + "inValueType": "vec3", + "rValue": 0, + "rValueType": "float", + "gValue": 0, + "gValueType": "float", + "bValue": 0, + "bValueType": "float", + "aValue": 0, + "aValueType": "float", + "expanded": false + }, + "inputs": { + "in": { + "connections": [ + { + "node": 159, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "r": { + "connections": [] + }, + "g": { + "connections": [ + { + "node": 185, + "input": "a", + "data": {} + } + ] + }, + "b": { + "connections": [] + }, + "a": { + "connections": [] + } + }, + "blocks": [], + "position": [ + -1067.616351053166, + 324.90160481586804 + ], + "name": "Split" + }, + "185": { + "id": 185, + "data": { + "aValue": 0, + "aValueType": "float", + "bValue": 0, + "bValueType": "float", + "outValue": 0, + "outValueType": "float", + "expanded": true + }, + "inputs": { + "a": { + "connections": [ + { + "node": 172, + "output": "g", + "data": {} + } + ] + }, + "b": { + "connections": [ + { + "node": 210, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 223, + "input": "in", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -877.129584088421, + 330.05676375445995 + ], + "name": "Add" + }, + "210": { + "id": 210, + "data": { + "outValue": 0, + "outValueType": "float", + "outValueName": "GroundOffset", + "exposed": true, + "expanded": true + }, + "inputs": {}, + "outputs": { + "out": { + "connections": [ + { + "node": 185, + "input": "b", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -1093.7382676284737, + 429.2968556622477 + ], + "name": "Parameter" + }, + "223": { + "id": 223, + "data": { + "inValue": 0, + "inValueType": "float", + "outValue": 0, + "outValueType": "float", + "expanded": true + }, + "inputs": { + "in": { + "connections": [ + { + "node": 185, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 248, + "input": "a", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -681.7749476445182, + 333.8051356623584 + ], + "name": "Saturate" + }, + "248": { + "id": 248, + "data": { + "aValue": 0, + "aValueType": "float", + "bValue": 0, + "bValueType": "float", + "outValue": 0, + "outValueType": "float", + "expanded": true + }, + "inputs": { + "a": { + "connections": [ + { + "node": 223, + "output": "out", + "data": {} + } + ] + }, + "b": { + "connections": [ + { + "node": 289, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 310, + "input": "t", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -449.1538489295969, + 339.1537058118883 + ], + "name": "Power" + }, + "289": { + "id": 289, + "data": { + "outValue": "1", + "outValueType": "float", + "outValueName": "AtomsphereThinkness", + "exposed": true, + "expanded": true + }, + "inputs": {}, + "outputs": { + "out": { + "connections": [ + { + "node": 248, + "input": "b", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -741.2528612437022, + 451.80087952532676 + ], + "name": "Parameter" + }, + "310": { + "id": 310, + "data": { + "aValue": [ + 0, + 0, + 0 + ], + "aValueType": "vec3", + "bValue": [ + 0, + 0, + 0 + ], + "bValueType": "vec3", + "tValue": [ + 0, + 0, + 0 + ], + "tValueType": "vec3", + "outValue": [ + 0, + 0, + 0 + ], + "outValueType": "vec3", + "expanded": true, + "preview": true, + "previewType": "3d" + }, + "inputs": { + "a": { + "connections": [ + { + "node": 384, + "output": "out", + "data": {} + } + ] + }, + "b": { + "connections": [ + { + "node": 371, + "output": "out", + "data": {} + } + ] + }, + "t": { + "connections": [ + { + "node": 248, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 10757, + "input": "base", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -259.2632922718328, + 221.69787921931498 + ], + "name": "Lerp" + }, + "371": { + "id": 371, + "data": { + "outValue": [ + 0.2, + 0.9411764705882353, + 0.9294117647058824 + ], + "outValueType": "vec3", + "outValueName": "TopColor", + "exposed": true, + "expanded": true + }, + "inputs": {}, + "outputs": { + "out": { + "connections": [ + { + "node": 310, + "input": "b", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -511.6618807287235, + 279.40941779854217 + ], + "name": "Parameter" + }, + "384": { + "id": 384, + "data": { + "outValue": [ + 0.7137254901960784, + 0.8745098039215686, + 0.9254901960784314 + ], + "outValueType": "vec3", + "outValueName": "BottomColor", + "exposed": true, + "expanded": true + }, + "inputs": {}, + "outputs": { + "out": { + "connections": [ + { + "node": 310, + "input": "a", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -539.6469865210921, + 235.91235965512965 + ], + "name": "Parameter" + }, + "411": { + "id": 411, + "data": { + "outValue": [ + 0, + 0, + 0 + ], + "outValueType": "vec3", + "spaceValue": "world", + "spaceValueType": "string", + "exposed": true, + "expanded": true, + "previewType": "3d" + }, + "inputs": {}, + "outputs": { + "out": { + "connections": [ + { + "node": 440, + "input": "in", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -1605.7607358314485, + 993.6586730847184 + ], + "name": "Position" + }, + "440": { + "id": 440, + "data": { + "inValue": [ + 0, + 0, + 0 + ], + "inValueType": "vec3", + "outValue": [ + 0, + 0, + 0 + ], + "outValueType": "vec3", + "expanded": true + }, + "inputs": { + "in": { + "connections": [ + { + "node": 411, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 522, + "input": "a", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -1408.6370601717585, + 996.4764100697053 + ], + "name": "Normalize" + }, + "505": { + "id": 505, + "data": { + "outValue": [ + 0, + 0.5, + -0.89 + ], + "outValueType": "vec3", + "outValueName": "SubPosition", + "exposed": true, + "expanded": true + }, + "inputs": {}, + "outputs": { + "out": { + "connections": [ + { + "node": 522, + "input": "b", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -1413.7638522107745, + 1107.112877883221 + ], + "name": "Parameter" + }, + "522": { + "id": 522, + "data": { + "aValue": [ + 0, + 0, + 0 + ], + "aValueType": "vec3", + "bValue": [ + 0, + 0, + 0 + ], + "bValueType": "vec3", + "outValue": 0, + "outValueType": "float", + "expanded": true + }, + "inputs": { + "a": { + "connections": [ + { + "node": 440, + "output": "out", + "data": {} + } + ] + }, + "b": { + "connections": [ + { + "node": 505, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 595, + "input": "edge", + "data": {} + }, + { + "node": 717, + "input": "edge2", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -1198.3891135553208, + 997.688493439787 + ], + "name": "Distance" + }, + "595": { + "id": 595, + "data": { + "edgeValue": 0, + "edgeValueType": "float", + "inValue": 0, + "inValueType": "float", + "outValue": 0, + "outValueType": "float", + "expanded": true, + "preview": false, + "previewType": "3d" + }, + "inputs": { + "edge": { + "connections": [ + { + "node": 522, + "output": "out", + "data": {} + } + ] + }, + "in": { + "connections": [ + { + "node": 676, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 8610, + "input": "a", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -893.9572148050576, + 1097.373838188076 + ], + "name": "Step" + }, + "676": { + "id": 676, + "data": { + "outValue": "0.1", + "outValueType": "float", + "outValueName": "SunSize", + "exposed": true, + "expanded": true + }, + "inputs": {}, + "outputs": { + "out": { + "connections": [ + { + "node": 595, + "input": "in", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -1049.6209930850262, + 1176.6580699600227 + ], + "name": "Parameter" + }, + "717": { + "id": 717, + "data": { + "edge1Value": 0, + "edge1ValueType": "float", + "edge2Value": 0, + "edge2ValueType": "float", + "inValue": 0, + "inValueType": "float", + "outValue": 0, + "outValueType": "float", + "expanded": true, + "preview": false, + "previewType": "3d" + }, + "inputs": { + "edge1": { + "connections": [] + }, + "edge2": { + "connections": [ + { + "node": 522, + "output": "out", + "data": {} + } + ] + }, + "in": { + "connections": [ + { + "node": 806, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 8464, + "input": "a", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -900.6980067255176, + 707.7760957283742 + ], + "name": "Smoothstep" + }, + "806": { + "id": 806, + "data": { + "outValue": 0.07, + "outValueType": "float", + "outValueName": "SunHoloSize", + "exposed": true, + "expanded": true + }, + "inputs": {}, + "outputs": { + "out": { + "connections": [ + { + "node": 717, + "input": "in", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -1119.6551102225274, + 819.4427726865229 + ], + "name": "Parameter" + }, + "8464": { + "id": 8464, + "data": { + "aValue": 0, + "aValueType": "float", + "bValue": 0, + "bValueType": "float", + "outValue": 0, + "outValueType": "float", + "expanded": true, + "preview": true, + "previewType": "3d" + }, + "inputs": { + "a": { + "connections": [ + { + "node": 717, + "output": "out", + "data": {} + } + ] + }, + "b": { + "connections": [ + { + "node": 8561, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 10757, + "input": "opacity", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -442.5892409244455, + 706.3264122183971 + ], + "name": "Power" + }, + "8561": { + "id": 8561, + "data": { + "outValue": "1", + "outValueType": "float", + "outValueName": "SunHaloThickness", + "exposed": true, + "expanded": true + }, + "inputs": {}, + "outputs": { + "out": { + "connections": [ + { + "node": 8464, + "input": "b", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -694.1589082073467, + 786.5526427783662 + ], + "name": "Parameter" + }, + "8610": { + "id": 8610, + "data": { + "aValue": [ + 0, + 0, + 0 + ], + "aValueType": "vec3", + "bValue": [ + 0, + 0, + 0 + ], + "bValueType": "vec3", + "outValue": [ + 0, + 0, + 0 + ], + "outValueType": "vec3", + "expanded": true, + "preview": true, + "previewType": "3d" + }, + "inputs": { + "a": { + "connections": [ + { + "node": 595, + "output": "out", + "data": {} + } + ] + }, + "b": { + "connections": [ + { + "node": 8715, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 10272, + "input": "b", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -441.9998471663323, + 1096.7897442687415 + ], + "name": "Multiply" + }, + "8715": { + "id": 8715, + "data": { + "outValue": [ + 0.9568627450980393, + 0.8392156862745098, + 0.08235294117647059 + ], + "outValueType": "vec3", + "outValueName": "SunColor", + "exposed": true, + "expanded": true + }, + "inputs": {}, + "outputs": { + "out": { + "connections": [ + { + "node": 8610, + "input": "b", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -645.4782691488189, + 1172.2821693544258 + ], + "name": "Parameter" + }, + "9011": { + "id": 9011, + "data": { + "outValue": [ + 0.8862745098039215, + 0.9490196078431372, + 0.4117647058823529 + ], + "outValueType": "vec3", + "outValueName": "SunHoloColor", + "exposed": true, + "expanded": true + }, + "inputs": {}, + "outputs": { + "out": { + "connections": [ + { + "node": 10272, + "input": "a", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -200.1467992787082, + 817.4504897508884 + ], + "name": "Parameter" + }, + "10272": { + "id": 10272, + "data": { + "aValue": [ + 0, + 0, + 0 + ], + "aValueType": "vec3", + "bValue": [ + 0, + 0, + 0 + ], + "bValueType": "vec3", + "outValue": [ + 0, + 0, + 0 + ], + "outValueType": "vec3", + "expanded": true, + "preview": true, + "previewType": "3d" + }, + "inputs": { + "a": { + "connections": [ + { + "node": 9011, + "output": "out", + "data": {} + } + ] + }, + "b": { + "connections": [ + { + "node": 8610, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 10757, + "input": "blend", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + 10.940575165498906, + 777.2563904941757 + ], + "name": "Add" + }, + "10757": { + "id": 10757, + "data": { + "baseValue": [ + 0, + 0, + 0 + ], + "baseValueType": "vec3", + "blendValue": [ + 0, + 0, + 0 + ], + "blendValueType": "vec3", + "opacityValue": 0, + "opacityValueType": "float", + "modeValue": "Overwrite", + "modeValueType": "string", + "outValue": [ + 0, + 0, + 0 + ], + "outValueType": "vec3", + "expanded": true, + "preview": true, + "previewType": "3d" + }, + "inputs": { + "base": { + "connections": [ + { + "node": 310, + "output": "out", + "data": {} + } + ] + }, + "blend": { + "connections": [ + { + "node": 10272, + "output": "out", + "data": {} + } + ] + }, + "opacity": { + "connections": [ + { + "node": 8464, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 356961, + "input": "a", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + 493.68867559576097, + 603.5022913504628 + ], + "name": "Blend" + }, + "59976": { + "id": 59976, + "data": { + "outValue": [ + 0, + 0, + 0 + ], + "outValueType": "vec3", + "spaceValue": "world", + "spaceValueType": "string", + "exposed": true, + "expanded": true, + "previewType": "3d" + }, + "inputs": {}, + "outputs": { + "out": { + "connections": [ + { + "node": 59977, + "input": "in", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -1661.8018052563698, + 2270.132709053705 + ], + "name": "Position" + }, + "59977": { + "id": 59977, + "data": { + "inValue": [ + 0, + 0, + 0 + ], + "inValueType": "vec3", + "outValue": [ + 0, + 0, + 0 + ], + "outValueType": "vec3", + "expanded": true + }, + "inputs": { + "in": { + "connections": [ + { + "node": 59976, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 60047, + "input": "in", + "data": {} + }, + { + "node": 60692, + "input": "b", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -1464.6781295966798, + 2272.950446038692 + ], + "name": "Normalize" + }, + "60047": { + "id": 60047, + "data": { + "inValue": [ + 0, + 0, + 0 + ], + "inValueType": "vec3", + "rValue": 0, + "rValueType": "float", + "gValue": 0, + "gValueType": "float", + "bValue": 0, + "bValueType": "float", + "aValue": 0, + "aValueType": "float", + "expanded": false + }, + "inputs": { + "in": { + "connections": [ + { + "node": 59977, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "r": { + "connections": [] + }, + "g": { + "connections": [ + { + "node": 60150, + "input": "b", + "data": {} + } + ] + }, + "b": { + "connections": [] + }, + "a": { + "connections": [] + } + }, + "blocks": [], + "position": [ + -1249.7298717176566, + 2274.4530981468406 + ], + "name": "Split" + }, + "60150": { + "id": 60150, + "data": { + "aValue": "1", + "aValueType": "float", + "bValue": 2, + "bValueType": "float", + "outValue": 0, + "outValueType": "float", + "expanded": true, + "preview": false, + "previewType": "3d" + }, + "inputs": { + "a": { + "connections": [ + { + "node": 60367, + "output": "out", + "data": {} + } + ] + }, + "b": { + "connections": [ + { + "node": 60047, + "output": "g", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 60692, + "input": "a", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -1050.8613694221924, + 2227.5488293595636 + ], + "name": "Divide" + }, + "60367": { + "id": 60367, + "data": { + "outValue": "1", + "outValueType": "float", + "outValueName": "CloudHeight", + "exposed": true, + "expanded": true + }, + "inputs": {}, + "outputs": { + "out": { + "connections": [ + { + "node": 60150, + "input": "a", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -1273.6205939182992, + 2213.5661033240804 + ], + "name": "Parameter" + }, + "60692": { + "id": 60692, + "data": { + "aValue": [ + 0, + 0, + 0 + ], + "aValueType": "vec3", + "bValue": [ + 0, + 0, + 0 + ], + "bValueType": "vec3", + "outValue": [ + 0, + 0, + 0 + ], + "outValueType": "vec3", + "expanded": true, + "preview": true, + "previewType": "3d" + }, + "inputs": { + "a": { + "connections": [ + { + "node": 60150, + "output": "out", + "data": {} + } + ] + }, + "b": { + "connections": [ + { + "node": 59977, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 60959, + "input": "in", + "data": {} + }, + { + "node": 90133, + "input": "a", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -801.1055029075059, + 2235.4593342046333 + ], + "name": "Multiply" + }, + "60959": { + "id": 60959, + "data": { + "inValue": [ + 0, + 0, + 0 + ], + "inValueType": "vec3", + "rValue": 0, + "rValueType": "float", + "gValue": 0, + "gValueType": "float", + "bValue": 0, + "bValueType": "float", + "aValue": 0, + "aValueType": "float", + "expanded": false + }, + "inputs": { + "in": { + "connections": [ + { + "node": 60692, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "r": { + "connections": [ + { + "node": 61074, + "input": "x", + "data": {} + } + ] + }, + "g": { + "connections": [] + }, + "b": { + "connections": [ + { + "node": 61074, + "input": "y", + "data": {} + } + ] + }, + "a": { + "connections": [] + } + }, + "blocks": [], + "position": [ + -535.7448843881929, + 2233.9021218056487 + ], + "name": "Split" + }, + "61074": { + "id": 61074, + "data": { + "xValue": 0, + "xValueType": "float", + "yValue": 0, + "yValueType": "float", + "outValue": [ + 0, + 0 + ], + "outValueType": "vec2", + "expanded": true + }, + "inputs": { + "x": { + "connections": [ + { + "node": 60959, + "output": "r", + "data": {} + } + ] + }, + "y": { + "connections": [ + { + "node": 60959, + "output": "b", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 76946, + "input": "a", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -353.4536846520396, + 2233.3717095818415 + ], + "name": "Vector 2" + }, + "61464": { + "id": 61464, + "data": { + "uvValue": "UV0", + "uvValueType": "vec2", + "scaleValue": 500, + "scaleValueType": "float", + "outValue": 0, + "outValueType": "float", + "expanded": true, + "preview": true, + "previewType": "3d" + }, + "inputs": { + "uv": { + "connections": [ + { + "node": 77327, + "output": "out", + "data": {} + } + ] + }, + "scale": { + "connections": [ + { + "node": 61585, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 117076, + "input": "b", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + 612.6863196434796, + 2224.331858165557 + ], + "name": "SimpleNoise" + }, + "61585": { + "id": 61585, + "data": { + "outValue": "37.08", + "outValueType": "float", + "outValueName": "CloudScale", + "exposed": true, + "expanded": true + }, + "inputs": {}, + "outputs": { + "out": { + "connections": [ + { + "node": 61464, + "input": "scale", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + 414.0924320265601, + 2296.418791959852 + ], + "name": "Parameter" + }, + "76946": { + "id": 76946, + "data": { + "aValue": [ + 0, + 0 + ], + "aValueType": "vec2", + "bValue": [ + 0, + 0 + ], + "bValueType": "vec2", + "outValue": [ + 0, + 0 + ], + "outValueType": "vec2", + "expanded": true + }, + "inputs": { + "a": { + "connections": [ + { + "node": 61074, + "output": "out", + "data": {} + } + ] + }, + "b": { + "connections": [ + { + "node": 77157, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 77327, + "input": "a", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + 39.164802594687984, + 2228.669349534971 + ], + "name": "Multiply" + }, + "77157": { + "id": 77157, + "data": { + "outValue": [ + "1", + "1" + ], + "outValueType": "vec2", + "outValueName": "CloudTiling", + "exposed": true, + "expanded": true + }, + "inputs": {}, + "outputs": { + "out": { + "connections": [ + { + "node": 76946, + "input": "b", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -186.4753107326282, + 2306.954025356107 + ], + "name": "Parameter" + }, + "77284": { + "id": 77284, + "data": { + "outValue": [ + 0.2, + 3.26 + ], + "outValueType": "vec2", + "outValueName": "CloudOffset", + "exposed": true, + "expanded": true + }, + "inputs": {}, + "outputs": { + "out": { + "connections": [ + { + "node": 77327, + "input": "b", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + 28.291669224122103, + 2375.0929956109258 + ], + "name": "Parameter" + }, + "77327": { + "id": 77327, + "data": { + "aValue": [ + 0, + 0 + ], + "aValueType": "vec2", + "bValue": [ + 0, + 0 + ], + "bValueType": "vec2", + "outValue": [ + 0, + 0 + ], + "outValueType": "vec2", + "expanded": true + }, + "inputs": { + "a": { + "connections": [ + { + "node": 76946, + "output": "out", + "data": {} + } + ] + }, + "b": { + "connections": [ + { + "node": 77284, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 61464, + "input": "uv", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + 260.1792691896751, + 2226.7962233186267 + ], + "name": "Add" + }, + "90133": { + "id": 90133, + "data": { + "aValue": [ + 0, + 0, + 0 + ], + "aValueType": "vec3", + "bValue": [ + 0, + 0, + 0 + ], + "bValueType": "vec3", + "outValue": 0, + "outValueType": "float", + "expanded": true, + "preview": true, + "previewType": "3d" + }, + "inputs": { + "a": { + "connections": [ + { + "node": 60692, + "output": "out", + "data": {} + } + ] + }, + "b": { + "connections": [] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 90549, + "input": "in", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -165.8446293473811, + 1898.2594235781746 + ], + "name": "Distance" + }, + "90502": { + "id": 90502, + "data": { + "outValue": 4.5, + "outValueType": "float", + "outValueName": "CloudFadeDistance", + "exposed": true, + "expanded": true + }, + "inputs": {}, + "outputs": { + "out": { + "connections": [ + { + "node": 90549, + "input": "edge2", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + -240.00403845034603, + 1817.4831059516553 + ], + "name": "Parameter" + }, + "90549": { + "id": 90549, + "data": { + "edge1Value": 0, + "edge1ValueType": "float", + "edge2Value": 0, + "edge2ValueType": "float", + "inValue": 0, + "inValueType": "float", + "outValue": 0, + "outValueType": "float", + "expanded": true, + "preview": true, + "previewType": "3d" + }, + "inputs": { + "edge1": { + "connections": [] + }, + "edge2": { + "connections": [ + { + "node": 90502, + "output": "out", + "data": {} + } + ] + }, + "in": { + "connections": [ + { + "node": 90133, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 91222, + "input": "in", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + 57.40547154293875, + 1735.947272603184 + ], + "name": "Smoothstep" + }, + "91222": { + "id": 91222, + "data": { + "inValue": 0, + "inValueType": "float", + "outValue": 0, + "outValueType": "float", + "expanded": true, + "preview": true, + "previewType": "3d" + }, + "inputs": { + "in": { + "connections": [ + { + "node": 90549, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 117076, + "input": "a", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + 397.5207371550854, + 1789.265293700164 + ], + "name": "OneMinus" + }, + "117076": { + "id": 117076, + "data": { + "aValue": 0, + "aValueType": "float", + "bValue": 0, + "bValueType": "float", + "outValue": 0, + "outValueType": "float", + "expanded": true, + "preview": true, + "previewType": "3d" + }, + "inputs": { + "a": { + "connections": [ + { + "node": 91222, + "output": "out", + "data": {} + } + ] + }, + "b": { + "connections": [ + { + "node": 61464, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 244344, + "input": "in", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + 954.1936435964458, + 1850.3102274421592 + ], + "name": "Multiply" + }, + "243801": { + "id": 243801, + "data": { + "aValue": 0, + "aValueType": "float", + "bValue": 0, + "bValueType": "float", + "outValue": 0, + "outValueType": "float", + "expanded": true + }, + "inputs": { + "a": { + "connections": [ + { + "node": 244072, + "output": "out", + "data": {} + } + ] + }, + "b": { + "connections": [ + { + "node": 244127, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 244344, + "input": "edge2", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + 1219.8621152000903, + 1659.2016419727086 + ], + "name": "Add" + }, + "244072": { + "id": 244072, + "data": { + "outValue": 0.35, + "outValueType": "float", + "outValueName": "CloudThreshold", + "exposed": true, + "expanded": true + }, + "inputs": {}, + "outputs": { + "out": { + "connections": [ + { + "node": 243801, + "input": "a", + "data": {} + }, + { + "node": 244344, + "input": "edge1", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + 969.6456830392959, + 1683.9824334709274 + ], + "name": "Parameter" + }, + "244127": { + "id": 244127, + "data": { + "outValue": 0.39, + "outValueType": "float", + "outValueName": "CloudFade", + "exposed": true, + "expanded": true + }, + "inputs": {}, + "outputs": { + "out": { + "connections": [ + { + "node": 243801, + "input": "b", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + 999.2052336935591, + 1740.6460873215785 + ], + "name": "Parameter" + }, + "244344": { + "id": 244344, + "data": { + "edge1Value": 0, + "edge1ValueType": "float", + "edge2Value": 0, + "edge2ValueType": "float", + "inValue": 0, + "inValueType": "float", + "outValue": 0, + "outValueType": "float", + "expanded": true, + "preview": true, + "previewType": "3d" + }, + "inputs": { + "edge1": { + "connections": [ + { + "node": 244072, + "output": "out", + "data": {} + } + ] + }, + "edge2": { + "connections": [ + { + "node": 243801, + "output": "out", + "data": {} + } + ] + }, + "in": { + "connections": [ + { + "node": 117076, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 356961, + "input": "b", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + 1444.2177780723239, + 1846.033275222732 + ], + "name": "Smoothstep" + }, + "356961": { + "id": 356961, + "data": { + "aValue": [ + 0, + 0, + 0 + ], + "aValueType": "vec3", + "bValue": [ + 0, + 0, + 0 + ], + "bValueType": "vec3", + "outValue": [ + 0, + 0, + 0 + ], + "outValueType": "vec3", + "expanded": true, + "preview": true, + "previewType": "3d" + }, + "inputs": { + "a": { + "connections": [ + { + "node": 10757, + "output": "out", + "data": {} + } + ] + }, + "b": { + "connections": [ + { + "node": 244344, + "output": "out", + "data": {} + } + ] + } + }, + "outputs": { + "out": { + "connections": [ + { + "node": 151, + "input": "baseColor", + "data": {} + } + ] + } + }, + "blocks": [], + "position": [ + 1789.0149925919538, + 1393.2942062248994 + ], + "name": "Add" + } + }, + "UIState": { + "showMainPreview": true, + "showBlackBoard": true, + "showInspector": true + }, + "type": "ShaderGraph", + "version": "", + "setting": { + "template": "unlit", + "precision": "single", + "allowMaterialOverride": false, + "surfaceType": "opaque", + "blendingMode": "alpha", + "renderFace": "front", + "depthWrite": "auto", + "depthTest": "l equal", + "alphaClipping": false, + "castShadows": true, + "clearCoat": false + }, + "parameters": [ + { + "name": "GroundOffset", + "type": "float", + "defalutValue": 0, + "exposed": true + }, + { + "name": "AtomsphereThinkness", + "type": "float", + "defalutValue": "1", + "exposed": true + }, + { + "name": "TopColor", + "type": "vec3", + "defalutValue": [ + 0.2, + 0.9411764705882353, + 0.9294117647058824 + ], + "exposed": true, + "typeEdit": "color" + }, + { + "name": "BottomColor", + "type": "vec3", + "defalutValue": [ + 0.7137254901960784, + 0.8745098039215686, + 0.9254901960784314 + ], + "exposed": true, + "typeEdit": "color" + }, + { + "name": "SubPosition", + "type": "vec3", + "defalutValue": [ + 0, + 0.5, + -0.89 + ], + "exposed": true + }, + { + "name": "SunSize", + "type": "float", + "defalutValue": "0.1", + "exposed": true + }, + { + "name": "SunHoloSize", + "type": "float", + "defalutValue": 0.07, + "exposed": true + }, + { + "name": "SunHaloThickness", + "type": "float", + "defalutValue": "1", + "exposed": true + }, + { + "name": "SunColor", + "type": "vec3", + "defalutValue": [ + 0.9568627450980393, + 0.8392156862745098, + 0.08235294117647059 + ], + "exposed": true, + "typeEdit": "color" + }, + { + "name": "SunHoloColor", + "type": "vec3", + "defalutValue": [ + 0.8862745098039215, + 0.9490196078431372, + 0.4117647058823529 + ], + "exposed": true, + "typeEdit": "color" + }, + { + "name": "CloudHeight", + "type": "float", + "defalutValue": "1", + "exposed": true + }, + { + "name": "CloudScale", + "type": "float", + "defalutValue": "37.08", + "exposed": true + }, + { + "name": "CloudTiling", + "type": "vec2", + "defalutValue": [ + "1", + "1" + ], + "exposed": true + }, + { + "name": "CloudOffset", + "type": "vec2", + "defalutValue": [ + 0.2, + 3.26 + ], + "exposed": true + }, + { + "name": "CloudFadeDistance", + "type": "float", + "defalutValue": 4.5, + "exposed": true + }, + { + "name": "CloudThreshold", + "type": "float", + "defalutValue": 0.35, + "exposed": true + }, + { + "name": "CloudFade", + "type": "float", + "defalutValue": 0.39, + "exposed": true + } + ] +} \ No newline at end of file diff --git a/example/presets.ts b/example/presets.ts index 67cb989..aa44c6b 100644 --- a/example/presets.ts +++ b/example/presets.ts @@ -31,6 +31,7 @@ import demoFlowMapSubGraph from './demo/demoFlowMapSubGraph.json'; import demoFlowMap from './demo/demoFlowMap.json'; import demoImageFlip from './demo/demoImageFlip.json'; import demoCartoonWater from './demo/demoCartoonWater'; +import demoSkybox from './demo/demoSkybox.json'; export const Presets = { devCompile, @@ -66,4 +67,5 @@ export const Presets = { demoFlowMap, demoImageFlip, demoCartoonWater, + demoSkybox, }; \ No newline at end of file diff --git a/src/compilers/ShaderGraphCompiler.ts b/src/compilers/ShaderGraphCompiler.ts index d63f70b..2d3ddd1 100644 --- a/src/compilers/ShaderGraphCompiler.ts +++ b/src/compilers/ShaderGraphCompiler.ts @@ -553,7 +553,7 @@ ${code}`; const colorOut = (await BaseColorBlock.prototype.compileSG.call(null, this, baseColorData))!; const fragOut = (await FragmentRC.prototype.compileSG.call(null, this, fragNodeData))!; delete graphData.nodes[baseColorData.id]; - + debugger; const fragBody = this.prependFragSharedCode(fragOut.code + '\n ' + colorOut.code); fragCode = this.compileHeadCode(fragBody, 'frag') + SGTemplates.unlit.frag(fragBody); vertBody += this.getAutoVaryingsCode(fragCode); diff --git a/src/compilers/ShaderGraphFns.ts b/src/compilers/ShaderGraphFns.ts index a7d1054..418c4d9 100644 --- a/src/compilers/ShaderGraphFns.ts +++ b/src/compilers/ShaderGraphFns.ts @@ -1,3 +1,4 @@ +import { BiTangentVectorRC, NormalRC, TangentVectorRC } from '../components'; import { ShaderGraphCompiler } from './ShaderGraphCompiler'; export const initRandContext = (compiler: ShaderGraphCompiler) => { @@ -8,3 +9,57 @@ return fract(sin(dot(seed, vec2(12.9898, 78.233))) * 43758.5453); }`; return compiler.setContext('defines', node, 'fn', codeFn); }; + +export const initTBNContext = (compiler: ShaderGraphCompiler, space: 'world' = 'world') => { + const node = { name: 'TBNMat3', data: {} } as any; + + if (space === 'world') { + const bitangentWS = BiTangentVectorRC.initBiTangentVectorContext(compiler, 'world'); + const tangentWS = TangentVectorRC.initTangentVectorContext(compiler, 'world'); + const normalWS = NormalRC.initNormalContext(compiler, 'world'); + // 原见TransformWorldToTangent + const codeFn = (varName: string) => /* wgsl */ ` +fn ${varName}(tangentToWorld: mat3x3f, matTBN_I_T: ptr, sgn: ptr) { + let tangentToWorld_T = transpose(tangentToWorld); + let row0 = tangentToWorld_T[0]; + let row1 = tangentToWorld_T[1]; + let row2 = tangentToWorld_T[2]; + let col0 = cross(row1, row2); + let col1 = cross(row2, row0); + let col2 = cross(row0, row1); + let determinant = dot(row0, col0); + *sgn = -step(determinant, 0) * 2.0 + 1.0; // determinant<0.0 ? (-1.0) : 1.0; + *matTBN_I_T = transpose(mat3x3f(col0, col1, col2)); +}`; + + const fnVar = compiler.setContext('defines', node, 'get_TBN_IT_sgn', codeFn); + const TangentToWorldFn = (varName: string) => + /* wgsl */ `let ${varName} = transpose(mat3x3f(${tangentWS}, ${bitangentWS}, ${normalWS}));`; + const TBN_TangentToWorld_ITFn = (varName: string) => + /* wgsl */ `var ${varName}: mat3x3f; var ${varName}_sgn: f32; ${fnVar}(transpose(mat3x3f(${tangentWS}, ${bitangentWS}, ${normalWS})), &${varName}, &${varName}_sgn);`; + const vert_TBN_TangentToWorld = compiler.setContext('vertShared', node, 'TangentToWorld', TangentToWorldFn); + const vert_TBN_TangentToWorld_IT = compiler.setContext('vertShared', node, 'TBN_TangentToWorld_IT', TBN_TangentToWorld_ITFn); + const vert_TBN_TangentToWorld_sgn = vert_TBN_TangentToWorld_IT + '_sgn'; + const frag_TBN_TangentToWorld = compiler.setContext('fragShared', node, 'TangentToWorld', TangentToWorldFn); + const frag_TBN_TangentToWorld_IT = compiler.setContext('fragShared', node, 'TBN_TangentToWorld_IT', TBN_TangentToWorld_ITFn); + const frag_TBN_TangentToWorld_sgn = frag_TBN_TangentToWorld_IT + '_sgn'; + const def_TBN_TangentToWorld = compiler.setVarNameMap(node, 'TBN_TangentToWorld_def', vert_TBN_TangentToWorld, frag_TBN_TangentToWorld); + const def_TBN_TangentToWorld_IT = compiler.setVarNameMap( + node, + 'TBN_TangentToWorld_IT_def', + vert_TBN_TangentToWorld_IT, + frag_TBN_TangentToWorld_IT, + ); + const def_TBN_TangentToWorld_IT_sgn = compiler.setVarNameMap( + node, + 'TBN_TangentToWorld_sgn_def', + vert_TBN_TangentToWorld_sgn, + frag_TBN_TangentToWorld_sgn, + ); + return { + TBN: def_TBN_TangentToWorld, + TBN_IT: def_TBN_TangentToWorld_IT, + TBN_IT_sgn: def_TBN_TangentToWorld_IT_sgn, + }; + } +}; diff --git a/src/components/ShaderGraphComponents.ts b/src/components/ShaderGraphComponents.ts index b620760..d5591c4 100644 --- a/src/components/ShaderGraphComponents.ts +++ b/src/components/ShaderGraphComponents.ts @@ -45,6 +45,8 @@ import { ScreenRC, SceneDepthRC, SceneColorRC, + BiTangentVectorRC, + TangentVectorRC, } from './input'; import { AbsoluteRC, @@ -268,4 +270,6 @@ export const initShaderGraphComponents = () => [ new SceneDepthRC(), new SceneColorRC(), new RefractRC(), + new TangentVectorRC(), + new BiTangentVectorRC(), ]; diff --git a/src/components/input/geometry/BiTangentVectorRC.ts b/src/components/input/geometry/BiTangentVectorRC.ts new file mode 100644 index 0000000..4165542 --- /dev/null +++ b/src/components/input/geometry/BiTangentVectorRC.ts @@ -0,0 +1,68 @@ +import { ShaderGraphCompiler, SGNodeOutput } from '../../../compilers'; +import { SGNodeData } from '../../../editors'; +import { Sockets } from '../../../sockets'; +import { ExtendReteNode, ValueType, Rete, SpaceValue, SpaceSuffixMap } from '../../../types'; +import { NodeView, SelectControl } from '../../../view'; +import { RC } from '../../ReteComponent'; +import { TransformationMatrixRC } from '../matrix'; +import { NormalRC } from './NormalRC'; +import { TangentVectorRC } from './TangentVectorRC'; + +export type ReteBiTangentVectorNode = ExtendReteNode< + 'BiTangentVector', + { + outValue: number[]; + outValueType: ValueType.vec3; + spaceValue: SpaceValue; + } +>; + +export class BiTangentVectorRC extends RC { + static Name = 'BiTangentVector'; + constructor() { + super(BiTangentVectorRC.Name); + this.data.component = NodeView; + } + + initNode(node: ReteBiTangentVectorNode) { + const { data, meta } = node; + node.initValueType('out', [0, 0, 0], ValueType.vec3); + node.initValueType('space', 'world', ValueType.string); + data.exposed ??= true; + data.preview ??= true; + data.expanded ??= true; + data.previewType ??= '3d'; + meta.category = 'input/geometry'; + meta.previewDisabled = false; + meta.label = 'BiTangent Vector'; + } + + async builder(node: ReteBiTangentVectorNode) { + this.initNode(node); + const out = new Rete.Output('out', 'Out', Sockets.vec3); + node.addOutput(out).addControl(new SelectControl('space', node, 'Space', ['object', 'view', 'world', 'tangent'], false)); + } + + static initBiTangentVectorContext(compiler: ShaderGraphCompiler, space: SpaceValue) { + if (space === 'tangent') return 'vec3(0, 1, 0)'; + + const node = { name: 'BiTangent', data: {} } as any; + const suffix = SpaceSuffixMap[space]; + const key = 'bitangent' + suffix; + const vertVar = key; + const normalSameSpace = NormalRC.initNormalContext(compiler, space); + const tangentSameSpace = TangentVectorRC.initTangentVectorContext(compiler, space); + const tangentOS = TangentVectorRC.initTangentVectorContext(compiler, 'object'); + const code = `let ${vertVar} = cross(${normalSameSpace}, ${tangentSameSpace}.xyz) * ${tangentOS}.w;`; + compiler.setContext('vertShared', node, key, { varName: vertVar, code }); + const varyingVar = compiler.setContext('varyings', node, key, varName => `${varName}: vec3f`); + const fragVar = compiler.setContext('fragShared', node, key, varName => `let ${varName} = normalize(${varyingVar});`); + const defVar = compiler.setVarNameMap(node, key + '_def', vertVar, fragVar); + compiler.setAutoVaryings(node, key, varyingVar, vertVar); + return defVar; + } + + compileSG(compiler: ShaderGraphCompiler, node: SGNodeData): SGNodeOutput { + return { outputs: { out: BiTangentVectorRC.initBiTangentVectorContext(compiler, node.data.spaceValue) }, code: '' }; + } +} diff --git a/src/components/input/geometry/NormalRC.ts b/src/components/input/geometry/NormalRC.ts index c8caf5d..2688e67 100644 --- a/src/components/input/geometry/NormalRC.ts +++ b/src/components/input/geometry/NormalRC.ts @@ -38,9 +38,7 @@ export class NormalRC extends RC { const out = new Rete.Output('out', 'Out', Sockets.vec3); node .addOutput(out) - .addControl( - new SelectControl('space', node, 'Space', ['object', 'view', 'world', 'tangent'], false), - ); + .addControl(new SelectControl('space', node, 'Space', ['object', 'view', 'world', 'tangent'], false)); } static initNormalContext(compiler: ShaderGraphCompiler, space: SpaceValue) { @@ -58,16 +56,11 @@ export class NormalRC extends RC { const IT_ModelViewVar = TransformationMatrixRC.initMatrixContext(compiler, 'IT_ModelView'); code = `let ${vertVar} = mat3x3(${IT_ModelViewVar}[0].xyz, ${IT_ModelViewVar}[1].xyz, ${IT_ModelViewVar}[2].xyz) * (*normalOS);`; } else { - code = `let ${vertVar} = vec3(0);`; // TODO + code = `let ${vertVar} = vec3(0, 0, 1);`; // TODO } compiler.setContext('vertShared', node, key, { varName: vertVar, code }); } - const varyingVar = compiler.setContext( - 'varyings', - node, - key, - varName => `${varName}: vec3`, - ); + const varyingVar = compiler.setContext('varyings', node, key, varName => `${varName}: vec3`); const fragVar = compiler.setContext( 'fragShared', node, diff --git a/src/components/input/geometry/PositionRC.ts b/src/components/input/geometry/PositionRC.ts index 02adc3e..25d8df5 100644 --- a/src/components/input/geometry/PositionRC.ts +++ b/src/components/input/geometry/PositionRC.ts @@ -1,7 +1,14 @@ import { ShaderGraphCompiler, SGNodeOutput } from '../../../compilers'; import { SGNodeData } from '../../../editors'; import { Sockets } from '../../../sockets'; -import { ExtendReteNode, ValueType, Rete, SpaceValue, SpaceSuffixMap } from '../../../types'; +import { + ExtendReteNode, + ValueType, + Rete, + SpaceValue, + SpaceSuffixMap, + SpaceOptions, +} from '../../../types'; import { NodeView, SelectControl } from '../../../view'; import { RC } from '../../ReteComponent'; import { TransformationMatrixRC } from '../matrix'; @@ -38,9 +45,7 @@ export class PositionRC extends RC { const out = new Rete.Output('out', 'Out', Sockets.vec3); node .addOutput(out) - .addControl( - new SelectControl('space', node, 'Space', ['object', 'view', 'world', 'tangent'], false), - ); + .addControl(new SelectControl('space', node, 'Space', SpaceOptions as any, false)); } static initPositionContext(compiler: ShaderGraphCompiler, space: SpaceValue) { @@ -58,7 +63,7 @@ export class PositionRC extends RC { const ModelViewVar = TransformationMatrixRC.initMatrixContext(compiler, 'ModelView'); code = `let ${vertVar} = (${ModelViewVar} * vec4(*positionOS, 1.0)).xyz;`; } else { - code = `let ${vertVar} = vec3(0);`; // TODO + code = `let ${vertVar} = vec3(0,0,0);`; // tangent } compiler.setContext('vertShared', node, key, { varName: vertVar, code }); } else { diff --git a/src/components/input/geometry/TangentVectorRC.ts b/src/components/input/geometry/TangentVectorRC.ts new file mode 100644 index 0000000..69cb9c4 --- /dev/null +++ b/src/components/input/geometry/TangentVectorRC.ts @@ -0,0 +1,82 @@ +import { ShaderGraphCompiler, SGNodeOutput } from '../../../compilers'; +import { SGNodeData } from '../../../editors'; +import { Sockets } from '../../../sockets'; +import { ExtendReteNode, ValueType, Rete, SpaceValue, SpaceSuffixMap } from '../../../types'; +import { NodeView, SelectControl } from '../../../view'; +import { RC } from '../../ReteComponent'; +import { TransformationMatrixRC } from '../matrix/TransformationMatrixRC'; +import { NormalRC } from './NormalRC'; + +export type ReteTangentVectorNode = ExtendReteNode< + 'TangentVector', + { + outValue: number[]; + outValueType: ValueType.vec3; + spaceValue: SpaceValue; + } +>; + +export class TangentVectorRC extends RC { + static Name = 'TangentVector'; + constructor() { + super(TangentVectorRC.Name); + this.data.component = NodeView; + } + + initNode(node: ReteTangentVectorNode) { + const { data, meta } = node; + node.initValueType('out', [0, 0, 0], ValueType.vec3); + node.initValueType('space', 'world', ValueType.string); + data.exposed ??= true; + data.preview ??= true; + data.expanded ??= true; + data.previewType ??= '3d'; + meta.category = 'input/geometry'; + meta.previewDisabled = false; + meta.label = 'Tangent Vector'; + } + + async builder(node: ReteTangentVectorNode) { + this.initNode(node); + const out = new Rete.Output('out', 'Out', Sockets.vec3); + node.addOutput(out).addControl(new SelectControl('space', node, 'Space', ['object', 'view', 'world', 'tangent'], false)); + } + + static initTangentVectorContext(compiler: ShaderGraphCompiler, space: SpaceValue) { + if (space === 'tangent') return 'vec3(1, 0, 0)'; + + const node = { name: 'Tangent', data: {} } as any; + const suffix = SpaceSuffixMap[space]; + const key = 'tangent' + suffix; + let vertVar = key; + const Mat = (type: Parameters['1']) => + TransformationMatrixRC.initMatrixContext(compiler, type); + if (space === 'object') { + vertVar = '(*tangentOS)'; + compiler.setContext('attributes', node, key, { + varName: 'tangentOS', + code: ``, + }); + const varyingVar = compiler.setContext('varyings', node, key, varName => `${varName}: vec4f`); + const fragVar = compiler.setContext('fragShared', node, key, varName => `let ${varName} = normalize(${varyingVar}.xyz);`); + const defVar = compiler.setVarNameMap(node, key + '_def', vertVar, fragVar); + compiler.setAutoVaryings(node, key, varyingVar, vertVar); + return defVar; + } else { + let code: string; + const tangentOS = TangentVectorRC.initTangentVectorContext(compiler, 'object'); + const matrix = Mat(space === 'view' ? 'ModelView' : 'Model'); + code = `let ${vertVar} = mat3x3f(${matrix}[0].xyz, ${matrix}[1].xyz, ${matrix}[2].xyz) * ${tangentOS}.xyz;`; + compiler.setContext('vertShared', node, key, { varName: vertVar, code }); + const varyingVar = compiler.setContext('varyings', node, key, varName => `${varName}: vec3f`); + const fragVar = compiler.setContext('fragShared', node, key, varName => `let ${varName} = normalize(${varyingVar});`); + const defVar = compiler.setVarNameMap(node, key + '_def', vertVar, fragVar); + compiler.setAutoVaryings(node, key, varyingVar, vertVar); + return defVar; + } + } + + compileSG(compiler: ShaderGraphCompiler, node: SGNodeData): SGNodeOutput { + return { outputs: { out: TangentVectorRC.initTangentVectorContext(compiler, node.data.spaceValue) }, code: '' }; + } +} diff --git a/src/components/input/geometry/ViewDirectionRC.ts b/src/components/input/geometry/ViewDirectionRC.ts index adb9835..27ad33b 100644 --- a/src/components/input/geometry/ViewDirectionRC.ts +++ b/src/components/input/geometry/ViewDirectionRC.ts @@ -1,4 +1,4 @@ -import { ShaderGraphCompiler, SGNodeOutput } from '../../../compilers'; +import { ShaderGraphCompiler, SGNodeOutput, initTBNContext } from '../../../compilers'; import { SGNodeData } from '../../../editors'; import { Sockets } from '../../../sockets'; import { ExtendReteNode, ValueType, Rete, SpaceValue, SpaceSuffixMap } from '../../../types'; @@ -37,21 +37,39 @@ export class ViewDirectionRC extends RC { async builder(node: ReteViewDirectionNode) { this.initNode(node); const out = new Rete.Output('out', 'Out', Sockets.vec3); - node.addOutput(out).addControl(new SelectControl('space', node, 'Space', ['object', 'view', 'world', 'tangent'], false)); + node + .addOutput(out) + .addControl( + new SelectControl('space', node, 'Space', ['object', 'view', 'world', 'tangent'], false), + ); } static initViewDirectionContext(compiler: ShaderGraphCompiler, space: SpaceValue) { const node = { name: ViewDirectionRC.Name, data: {} } as any; const suffix = SpaceSuffixMap[space]; const key = 'viewDir' + suffix; + + if (space === 'tangent') { + const viewVectorVar = ViewVectorRC.initViewVectorContext(compiler, 'world'); + const { TBN_IT, TBN_IT_sgn } = initTBNContext(compiler, 'world')!; + const codeFn = (varName: string) => + `let ${varName} = normalize(${TBN_IT_sgn} * (${TBN_IT} * ${viewVectorVar}));`; + const vertVar = compiler.setContext('vertShared', node, key, codeFn); + const fragVar = compiler.setContext('fragShared', node, key, codeFn); + return compiler.setVarNameMap(node, key + '_def', vertVar, fragVar); + } + const viewVectorVar = ViewVectorRC.initViewVectorContext(compiler, space); const codeFn = (varName: string) => `let ${varName} = normalize(${viewVectorVar});`; const vertVar = compiler.setContext('vertShared', node, key, codeFn); const fragVar = compiler.setContext('fragShared', node, key, codeFn); - return compiler.setVarNameMap(node, key, vertVar, fragVar); + return compiler.setVarNameMap(node, key + '_def', vertVar, fragVar); } compileSG(compiler: ShaderGraphCompiler, node: SGNodeData): SGNodeOutput { - return { outputs: { out: ViewDirectionRC.initViewDirectionContext(compiler, node.data.spaceValue) }, code: '' }; + return { + outputs: { out: ViewDirectionRC.initViewDirectionContext(compiler, node.data.spaceValue) }, + code: '', + }; } } diff --git a/src/components/input/geometry/ViewVectorRC.ts b/src/components/input/geometry/ViewVectorRC.ts index d40282a..d249b1a 100644 --- a/src/components/input/geometry/ViewVectorRC.ts +++ b/src/components/input/geometry/ViewVectorRC.ts @@ -1,4 +1,4 @@ -import { ShaderGraphCompiler, SGNodeOutput } from '../../../compilers'; +import { ShaderGraphCompiler, SGNodeOutput, initTBNContext } from '../../../compilers'; import { SGNodeData } from '../../../editors'; import { Sockets } from '../../../sockets'; import { ExtendReteNode, ValueType, Rete, SpaceValue, SpaceSuffixMap } from '../../../types'; @@ -67,13 +67,14 @@ export class ViewVectorRC extends RC { vertVar = compiler.setContext('vertShared', node, key, codeFn); fragVar = compiler.setContext('fragShared', node, key, codeFn); } else { - // TODO - const codeFn = (varName: string) => `let ${varName} = vec3(0);`; + const viewVectorVar = ViewVectorRC.initViewVectorContext(compiler, 'world'); + const { TBN_IT, TBN_IT_sgn } = initTBNContext(compiler, 'world')!; + const codeFn = (varName: string) => `let ${varName} = ${TBN_IT_sgn} * (${TBN_IT} * ${viewVectorVar});`; vertVar = compiler.setContext('vertShared', node, key, codeFn); fragVar = compiler.setContext('fragShared', node, key, codeFn); } - return compiler.setVarNameMap(node, key, vertVar, fragVar); + return compiler.setVarNameMap(node, key + '_def', vertVar, fragVar); } compileSG(compiler: ShaderGraphCompiler, node: SGNodeData): SGNodeOutput { diff --git a/src/components/input/geometry/index.ts b/src/components/input/geometry/index.ts index 38182f8..90ef785 100644 --- a/src/components/input/geometry/index.ts +++ b/src/components/input/geometry/index.ts @@ -3,4 +3,6 @@ export * from './NormalRC'; export * from './PositionRC'; export * from './ViewVectorRC'; export * from './ViewDirectionRC'; -export * from './ScreenPositionRC'; \ No newline at end of file +export * from './ScreenPositionRC'; +export * from './TangentVectorRC'; +export * from './BiTangentVectorRC'; \ No newline at end of file diff --git a/src/components/input/texture/SampleTexture2DRC.ts b/src/components/input/texture/SampleTexture2DRC.ts index e892b97..e292c0a 100644 --- a/src/components/input/texture/SampleTexture2DRC.ts +++ b/src/components/input/texture/SampleTexture2DRC.ts @@ -49,6 +49,7 @@ export class SampleTexture2DRC extends RC { node.initValueType('type', 'default', ValueType.string); node.initValueType('space', 'object', ValueType.string); data.expanded ??= true; + data.preview ??= true; meta.previewDisabled = false; meta.category = 'input/texture'; diff --git a/src/components/math/vector/TransformRC.ts b/src/components/math/vector/TransformRC.ts index 6651fe0..77ce31b 100644 --- a/src/components/math/vector/TransformRC.ts +++ b/src/components/math/vector/TransformRC.ts @@ -2,7 +2,7 @@ import { NodeView, DynamicControl, SelectControl, SelectDualControl } from '../. import { Sockets } from '../../../sockets'; import { ArrayElement, ExtendReteNode, Rete, ValueType } from '../../../types'; import { RC } from '../../ReteComponent'; -import { ShaderGraphCompiler, SGNodeOutput } from '../../../compilers'; +import { ShaderGraphCompiler, SGNodeOutput, initTBNContext } from '../../../compilers'; import { SGNodeData } from '../../../editors'; import { TransformationMatrixRC } from '../../input'; @@ -68,48 +68,54 @@ export class TransformRC extends RC { // space 相同直接转发inVar即可 if (inSpace === outSpace) return { outputs: { out: inVar }, code: '' }; - const outVar = compiler.getOutVarName(node, 'out', 'transform'); + const outVar = compiler.getOutVarName(node, 'out', combine); const typeClass = compiler.getTypeClass(node.data.outValueType); const Mat = (type: Parameters['1']) => TransformationMatrixRC.initMatrixContext(compiler, type); const w = node.data.typeValue === 'position' ? '1.0' : '0.0'; const vec4Var = `vec4(${inVar}, ${w})`; - - // TODO tangent + const { TBN, TBN_IT, TBN_IT_sgn } = initTBNContext(compiler, 'world')!; let varCode = `${typeClass}(0)`; if (combine === 'object_to_world') { varCode = `${Mat('Model')} * ${vec4Var}`; } if (combine === 'object_to_view') { - varCode = `${Mat('I_View')} * ${Mat('Model')} * ${vec4Var}`; + varCode = `${Mat('ModelView')} * ${vec4Var}`; } if (combine === 'object_to_tangent') { + const model = Mat('Model'); + varCode = `normalize(${TBN_IT_sgn} * (${TBN_IT} * (mat3x3f(${model}[0].xyz, ${model}[1].xyz, ${model}[2].xyz) * ${vec4Var}.xyz)))`; } if (combine === 'world_to_object') { varCode = `${Mat('I_Model')} * ${vec4Var}`; } if (combine === 'world_to_view') { - varCode = `${Mat('I_View')} * ${vec4Var}`; + varCode = `${Mat('View')} * ${vec4Var}`; } if (combine === 'world_to_tangent') { + varCode = `normalize(${TBN_IT_sgn} * (${TBN_IT} * ${vec4Var}.xyz))`; } if (combine === 'view_to_object') { - varCode = `${Mat('I_Model')} * ${Mat('View')} * ${vec4Var}`; + varCode = `${Mat('I_ModelView')} * ${vec4Var}`; } if (combine === 'view_to_world') { - varCode = `${Mat('View')} * ${vec4Var}`; + varCode = `${Mat('I_View')} * ${vec4Var}`; } if (combine === 'view_to_tangent') { + varCode = `normalize(${TBN_IT_sgn} * (${TBN_IT} * (${Mat('View')} * vec4(${vec4Var}.xyz, 1.)).xyz))`; } if (combine === 'tangent_to_object') { + varCode = `${Mat('I_Model')} * vec4(${vec4Var}.xyz * ${TBN}, ${w})`; } if (combine === 'tangent_to_world') { + varCode = `vec4(${vec4Var}.xyz * ${TBN}, ${w})`; } if (combine === 'tangent_to_view') { + varCode = `${Mat('I_View')} * vec4(${vec4Var}.xyz * ${TBN}, ${w})`; } return { diff --git a/src/editors/ShaderGraphTypes.ts b/src/editors/ShaderGraphTypes.ts index e6584e1..65616ce 100644 --- a/src/editors/ShaderGraphTypes.ts +++ b/src/editors/ShaderGraphTypes.ts @@ -145,6 +145,8 @@ import { ReteSceneColorNode, ReteSceneDepthNode, ReteRefractNode, + ReteTangentVectorNode, + ReteBiTangentVectorNode, } from '../components'; import { NodeData } from '../rete/core/data'; import { Rete, ParameterData, GraphData } from '../types'; @@ -194,6 +196,8 @@ export type SGNodes = | ReteViewVectorNode | ReteViewDirectionNode | ReteScreenPositionNode + | ReteTangentVectorNode + | ReteBiTangentVectorNode // input/matrix | ReteTransformationMatrixNode | ReteMatrix4x4Node diff --git a/src/materials/WebGPURenderer.ts b/src/materials/WebGPURenderer.ts index 72f6a9b..033a66f 100644 --- a/src/materials/WebGPURenderer.ts +++ b/src/materials/WebGPURenderer.ts @@ -42,6 +42,7 @@ export interface GPUGeometry { position?: GPUBuffer; uv?: GPUBuffer; normal?: GPUBuffer; + tangent?: GPUBuffer; index?: GPUBuffer; } @@ -180,7 +181,8 @@ export class WebGPURenderer { const gpuMaterial = material.userData as GPUMaterial; if (!gpuGeometry.position) { - (['position', 'normal', 'uv'] as const).forEach(name => { + geometry.computeTangents(); + (['position', 'normal', 'uv', 'tangent'] as const).forEach(name => { const attribute = geometry.getAttribute(name); let bufferAttribute = attribute as BufferAttribute; if (attribute instanceof InterleavedBuffer) { @@ -317,7 +319,7 @@ export class WebGPURenderer { vertex: { module: vsm, entryPoint: 'main', - // position uv normal + // position uv normal tangent buffers: [ { arrayStride: 4 * 3, @@ -331,6 +333,10 @@ export class WebGPURenderer { arrayStride: 4 * 3, attributes: [{ shaderLocation: 2, offset: 0, format: 'float32x3' }], }, + { + arrayStride: 4 * 4, + attributes: [{ shaderLocation: 3, offset: 0, format: 'float32x4' }], + }, ], }, fragment: { @@ -424,6 +430,7 @@ export class WebGPURenderer { passEncoder.setVertexBuffer(0, gpuGeometry.position!); passEncoder.setVertexBuffer(1, gpuGeometry.uv!); passEncoder.setVertexBuffer(2, gpuGeometry.normal!); + passEncoder.setVertexBuffer(3, gpuGeometry.tangent!); if (gpuGeometry.index) { passEncoder.drawIndexed(geometry.index!.count); } else { @@ -573,6 +580,7 @@ export function disposeGeometry(geometry: BufferGeometry) { gpuGeometry.index?.destroy(); gpuGeometry.normal?.destroy(); gpuGeometry.position?.destroy(); + gpuGeometry.tangent?.destroy(); gpuGeometry.uv?.destroy(); } diff --git a/src/templates/Unlit.ts b/src/templates/Unlit.ts index 9183d0a..bc54f18 100644 --- a/src/templates/Unlit.ts +++ b/src/templates/Unlit.ts @@ -2,7 +2,7 @@ export const UnlitSGTemplate = Object.freeze({ vert: (body: string) => /* wgsl */ `fn sg_vert( positionOS: ptr>, normalOS: ptr>, - tangentOS: ptr>, + tangentOS: ptr>, v: ptr, uv: vec2 ) { @@ -27,11 +27,12 @@ fn main( @location(0) position: vec3, @location(1) uv: vec2, @location(2) normal: vec3, + @location(3) tangent: vec4, ) -> Varying { var v: Varying; var sg_position = vec3(position); var sg_normal = vec3(normal); - var sg_tangent = vec3(0); + var sg_tangent = tangent; sg_vert(&sg_position, &sg_normal, &sg_tangent, &v, uv); v.position = u.sg_Matrix_Proj * u.sg_Matrix_ModelView * vec4(sg_position, 1.0); diff --git a/src/types.ts b/src/types.ts index 52b124a..0ad16f9 100644 --- a/src/types.ts +++ b/src/types.ts @@ -181,7 +181,7 @@ export interface ParameterData { export type AssetValue = { id: string; label: string } | undefined; // TODO support tangent -export const SpaceOptions = ['object', 'view', 'world'] as const; +export const SpaceOptions = ['object', 'view', 'world', 'tangent'] as const; export type SpaceValue = ArrayElement; // TODO support UV123 export const UVOptions = ['UV0'] as const;