|
6 | 6 |
|
7 | 7 | import * as constants from '../core/constants'; |
8 | 8 | import { getStrokeDefs } from '../webgl/enums'; |
9 | | -import { DataType } from '../strands/ir_types.js'; |
| 9 | +import { DataType, INSTANCE_ID_VARYING_NAME } from '../strands/ir_types.js'; |
10 | 10 |
|
11 | 11 | import { colorVertexShader, colorFragmentShader } from './shaders/color'; |
12 | 12 | import { lineVertexShader, lineFragmentShader} from './shaders/line'; |
@@ -2651,6 +2651,50 @@ ${hookUniformFields}} |
2651 | 2651 | } |
2652 | 2652 | } |
2653 | 2653 |
|
| 2654 | + // Handle instanceID varying for fragment access |
| 2655 | + if (shader.hooks.instanceIDVarying) { |
| 2656 | + const { name, declaration, source, interpolation } = shader.hooks.instanceIDVarying; |
| 2657 | + const nextLocIndex = this._getNextAvailableLocation(preMain, shaderType); |
| 2658 | + const interpAttr = interpolation ? ` @interpolate(${interpolation})` : ''; |
| 2659 | + const [varName, varType] = declaration.split(':').map(s => s.trim()); |
| 2660 | + const structMember = `@location(${nextLocIndex})${interpAttr} ${declaration},`; |
| 2661 | + |
| 2662 | + if (shaderType === 'vertex') { |
| 2663 | + // Inject into VertexOutput struct |
| 2664 | + preMain = preMain.replace( |
| 2665 | + /struct\s+VertexOutput\s+\{([^}]*)\}/, |
| 2666 | + (match, body) => `struct VertexOutput {${body}\n${structMember}}` |
| 2667 | + ); |
| 2668 | + // Add private global |
| 2669 | + preMain += `var<private> ${declaration};\n`; |
| 2670 | + // Assign from built-in instanceID at start of main() |
| 2671 | + postMain = `\n ${varName} = ${source};\n` + postMain; |
| 2672 | + // Copy to output struct before return |
| 2673 | + const returnMatch = postMain.match(/return\s+(\w+)\s*;/); |
| 2674 | + if (returnMatch) { |
| 2675 | + const outputVarName = returnMatch[1]; |
| 2676 | + postMain = postMain.replace( |
| 2677 | + /(return\s+\w+\s*;)/g, |
| 2678 | + `${outputVarName}.${varName} = ${varName};\n $1` |
| 2679 | + ); |
| 2680 | + } |
| 2681 | + } else if (shaderType === 'fragment') { |
| 2682 | + // Inject into FragmentInput struct |
| 2683 | + preMain = preMain.replace( |
| 2684 | + /struct\s+FragmentInput\s+\{([^}]*)\}/, |
| 2685 | + (match, body) => `struct FragmentInput {${body}\n${structMember}}` |
| 2686 | + ); |
| 2687 | + // Add private global |
| 2688 | + preMain += `var<private> ${declaration};\n`; |
| 2689 | + // Initialize from input struct at start of main() |
| 2690 | + const inputMatch = main.match(/fn main\s*\((\w+):\s*\w+\)/); |
| 2691 | + if (inputMatch) { |
| 2692 | + const inputVarName = inputMatch[1]; |
| 2693 | + postMain = `\n ${varName} = ${inputVarName}.${varName};\n` + postMain; |
| 2694 | + } |
| 2695 | + } |
| 2696 | + } |
| 2697 | + |
2654 | 2698 | let hooks = ''; |
2655 | 2699 | let defines = ''; |
2656 | 2700 | if (shader.hooks.declarations) { |
|
0 commit comments