Skip to content

Commit

Permalink
🆕 feat: tangent space & spimle skybox
Browse files Browse the repository at this point in the history
  • Loading branch information
deepkolos committed Oct 4, 2023
1 parent 5a9d979 commit d8a83be
Show file tree
Hide file tree
Showing 18 changed files with 2,863 additions and 38 deletions.
2,575 changes: 2,575 additions & 0 deletions example/demo/demoSkybox.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions example/presets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -66,4 +67,5 @@ export const Presets = {
demoFlowMap,
demoImageFlip,
demoCartoonWater,
demoSkybox,
};
2 changes: 1 addition & 1 deletion src/compilers/ShaderGraphCompiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
55 changes: 55 additions & 0 deletions src/compilers/ShaderGraphFns.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { BiTangentVectorRC, NormalRC, TangentVectorRC } from '../components';
import { ShaderGraphCompiler } from './ShaderGraphCompiler';

export const initRandContext = (compiler: ShaderGraphCompiler) => {
Expand All @@ -8,3 +9,57 @@ return fract(sin(dot(seed, vec2<f32>(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<function, mat3x3f>, sgn: ptr<function, f32>) {
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,
};
}
};
4 changes: 4 additions & 0 deletions src/components/ShaderGraphComponents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ import {
ScreenRC,
SceneDepthRC,
SceneColorRC,
BiTangentVectorRC,
TangentVectorRC,
} from './input';
import {
AbsoluteRC,
Expand Down Expand Up @@ -268,4 +270,6 @@ export const initShaderGraphComponents = () => [
new SceneDepthRC(),
new SceneColorRC(),
new RefractRC(),
new TangentVectorRC(),
new BiTangentVectorRC(),
];
68 changes: 68 additions & 0 deletions src/components/input/geometry/BiTangentVectorRC.ts
Original file line number Diff line number Diff line change
@@ -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<ReteBiTangentVectorNode>): SGNodeOutput {
return { outputs: { out: BiTangentVectorRC.initBiTangentVectorContext(compiler, node.data.spaceValue) }, code: '' };
}
}
13 changes: 3 additions & 10 deletions src/components/input/geometry/NormalRC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -58,16 +56,11 @@ export class NormalRC extends RC {
const IT_ModelViewVar = TransformationMatrixRC.initMatrixContext(compiler, 'IT_ModelView');
code = `let ${vertVar} = mat3x3<f32>(${IT_ModelViewVar}[0].xyz, ${IT_ModelViewVar}[1].xyz, ${IT_ModelViewVar}[2].xyz) * (*normalOS);`;
} else {
code = `let ${vertVar} = vec3<f32>(0);`; // TODO
code = `let ${vertVar} = vec3<f32>(0, 0, 1);`; // TODO
}
compiler.setContext('vertShared', node, key, { varName: vertVar, code });
}
const varyingVar = compiler.setContext(
'varyings',
node,
key,
varName => `${varName}: vec3<f32>`,
);
const varyingVar = compiler.setContext('varyings', node, key, varName => `${varName}: vec3<f32>`);
const fragVar = compiler.setContext(
'fragShared',
node,
Expand Down
15 changes: 10 additions & 5 deletions src/components/input/geometry/PositionRC.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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) {
Expand All @@ -58,7 +63,7 @@ export class PositionRC extends RC {
const ModelViewVar = TransformationMatrixRC.initMatrixContext(compiler, 'ModelView');
code = `let ${vertVar} = (${ModelViewVar} * vec4<f32>(*positionOS, 1.0)).xyz;`;
} else {
code = `let ${vertVar} = vec3<f32>(0);`; // TODO
code = `let ${vertVar} = vec3<f32>(0,0,0);`; // tangent
}
compiler.setContext('vertShared', node, key, { varName: vertVar, code });
} else {
Expand Down
82 changes: 82 additions & 0 deletions src/components/input/geometry/TangentVectorRC.ts
Original file line number Diff line number Diff line change
@@ -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<typeof TransformationMatrixRC.initMatrixContext>['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<ReteTangentVectorNode>): SGNodeOutput {
return { outputs: { out: TangentVectorRC.initTangentVectorContext(compiler, node.data.spaceValue) }, code: '' };
}
}
26 changes: 22 additions & 4 deletions src/components/input/geometry/ViewDirectionRC.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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<ReteViewDirectionNode>): SGNodeOutput {
return { outputs: { out: ViewDirectionRC.initViewDirectionContext(compiler, node.data.spaceValue) }, code: '' };
return {
outputs: { out: ViewDirectionRC.initViewDirectionContext(compiler, node.data.spaceValue) },
code: '',
};
}
}
9 changes: 5 additions & 4 deletions src/components/input/geometry/ViewVectorRC.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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<f32>(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<ReteViewVectorNode>): SGNodeOutput {
Expand Down
Loading

0 comments on commit d8a83be

Please sign in to comment.