Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TSL Transpiler: GLSL -> TSL #26982

Merged
merged 50 commits into from
Oct 21, 2023
Merged

TSL Transpiler: GLSL -> TSL #26982

merged 50 commits into from
Oct 21, 2023

Conversation

sunag
Copy link
Collaborator

@sunag sunag commented Oct 16, 2023

Related issue: #24958 (comment)

Description

I started working on a Traspiler to speed up the migration of codes created in GLSL to TSL. This WIP is a very initial work, considering that the transpiler "engine" is ready, now it would be necessary to extend the syntax library following the logic already programmed.

The Transpiler is based on an AST, with Decoder and Encoder, thus allowing conversions to other formats in the future, not being a simple text replacement.

Syntax

const decoder = new GLSLDecoder();
const encoder = new TSLEncoder();

const transpiler = new Transpiler( decoder, encoder );

const tsl = transpiler.parse( glsl );

Example
https://raw.githack.com/sunag/three.js/dev-transpiler-tsl/examples/webgpu_tsl_transpiler.html

Tasks for this PR

  • Arithmetic operators
  • Partial function declaration
  • Partial variable declaration
  • Operator precedence
  • Groups
  • Return
  • Expression
  • Constant conversion
  • Auto chaining
  • Auto layout
  • Negate number
  • Negate boolean
  • Prefix increment and decrement
  • Conditional If/Else
  • Conditional Operators
  • Beautifier
  • For (Partial)
  • Keywords
  • Imports
  • Ternary
  • Revision

Maybe in other PR

  • Array accessor
  • Array
  • Texture, CubeTexture
  • Preserve comments and double lines

Soon

  • Uniforms, varying, more keywords, preprocessors, inout, switch etc

@sunag sunag added the TSL Three.js Shading Language label Oct 16, 2023
@sunag sunag added this to the r158 milestone Oct 16, 2023
@LeviPesin
Copy link
Contributor

I don't think we should place transpiler in the Nodes directory, maybe it can be just examples/jsm/transpiler/Files?
Maybe we could even integrate it with the Nodes Editor.

@sunag
Copy link
Collaborator Author

sunag commented Oct 19, 2023

I made a simple ShaderToyDecoder and ShaderToyNode to show some different use cases.

The example https://www.shadertoy.com/view/Mt2SzR worked just by copying and pasting.

With the Transpiler GLSL can work in both backends, example:

https://raw.githack.com/sunag/three.js/dev-transpiler-tsl/examples/webgpu_shadertoy.html

/cc @mrdoob

@sunag sunag changed the title TSL Transpiler: GLSL -> TSL - ( WIP ) TSL Transpiler: GLSL -> TSL Oct 20, 2023
@sunag
Copy link
Collaborator Author

sunag commented Oct 20, 2023

I put two complex shader with functions names repeated into a mix(), and everything work fine.

https://raw.githack.com/sunag/three.js/dev-transpiler-tsl/examples/webgpu_shadertoy.html

const shaderToy1Node = new ShaderToyNode();
shaderToy1Node.parse( example1Code );

const shaderToy2Node = new ShaderToyNode();
shaderToy2Node.parse( example2Code );

//

material.colorNode = oscSine( timerLocal( .3 ) ).mix( shaderToy1Node, shaderToy2Node );

@sunag sunag marked this pull request as ready for review October 20, 2023 21:44
@sunag sunag merged commit 328ec21 into mrdoob:dev Oct 21, 2023
18 checks passed
@@ -1087,6 +1104,18 @@ class NodeBuilder {

}

getPrimitiveType( type ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But we already have getComponentType for exactly the same task, no? /ping @sunag

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree! I will test it.

@@ -1141,6 +1170,15 @@ class NodeBuilder {

}

if ( fromTypeLength === 1 && toTypeLength > 1 && fromType[ 0 ] !== toType[ 0 ] ) { // fromType is float-like
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are the cases that don't work without this clause?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it done exclusively to make something like vec4( x ) output vec4( x ) instead of vec4( vec3( x ), 1.0 )? If so, I think this clause isn't needed, only the && fromTypeLength > 1 above is sufficient.

@@ -52,6 +52,7 @@ export default VarNode;

export const temp = nodeProxy( VarNode );

addNodeElement( 'temp', temp );
addNodeElement( 'temp', temp ); // @TODO: Will be removed in the future
addNodeElement( 'toVar', ( ...params ) => temp( ...params ).append() );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can rename this back to temp? It seems like better name and the behavior is almost unchanged (except that now it forces the variable to be generated immediately in the shader flow, if I understand correctly), so it will not be a so breaking change.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that the conversion variables used in the "chain" could have the prefix "to". It seems to sound more like the conversions we see in any other API, for example value.toVec3() instead of value.vec3() the same I see for value.toVar()

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really see "temping" a node as a conversion... I agree about toVec3, but for temp I still think this is the best name.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe createVar()?

I don't think temp is a bad name, it just seems like it wasn't clear that it declares a variable, I think doubts like this could be avoided.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that the name of this element should be short, because it is one of the most used ones. I also don't really think name toVar makes it significantly more understandable for someone who doesn't know what this element do...
In my opiniion temp is best both for being short and being understandable ("temping" a node creates a temp variable with it).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
TSL Three.js Shading Language
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants