Repe [T3DU] Update - 31f26d171bba0355ce2a77031e3aad4c64dbc7e9

This commit is contained in:
2026-09-04 10:46:13 -07:00
parent c915312901
commit 0460b9d587
482 changed files with 27797 additions and 3226 deletions

View File

@ -37,7 +37,7 @@ def parse_attribute(node: bpy.types.ShaderNodeAttribute, out_socket: bpy.types.N
return c.cast_value('time', from_type='float', to_type=out_type)
# UV maps (higher priority) and vertex colors
if node.attribute_type == 'GEOMETRY':
if node.attribute_type == 'GEOMETRY' and state.context == ParserContext.OBJECT:
# Alpha output. Leenkx doesn't support vertex colors with alpha
# values yet and UV maps don't have an alpha channel
@ -159,7 +159,7 @@ def parse_geometry(node: bpy.types.ShaderNodeNewGeometry, out_socket: bpy.types.
# True Normal
elif out_socket == node.outputs[3]:
state.dxdy_varying_input_value = True
return 'n' if state.curshader.shader_type == 'frag' else 'wnormal'
return 'normalize(cross(dFdy(wposition), dFdx(wposition)))' if state.curshader.shader_type == 'frag' else 'wnormal'
# Incoming
elif out_socket == node.outputs[4]:
state.dxdy_varying_input_value = True
@ -173,10 +173,18 @@ def parse_geometry(node: bpy.types.ShaderNodeNewGeometry, out_socket: bpy.types.
return '(1.0 - float(gl_FrontFacing))' if state.context == ParserContext.OBJECT else '0.0'
# Pointiness
elif out_socket == node.outputs[7]:
return '0.0'
state.dxdy_varying_input_value = True
if state.curshader.shader_type == 'frag':
return 'length(cross(n, normalize(cross(dFdy(wposition), dFdx(wposition)))))'
else:
return '0.0'
# Random Per Island
elif out_socket == node.outputs[8]:
return '0.0'
state.dxdy_varying_input_value = True
if state.curshader.shader_type == 'frag':
return '((sin(mposition.x * 5.12 + sin(mposition.y * 8.63)) * sin(mposition.y * 6.41 + sin(mposition.z * 9.15)) * sin(mposition.z * 7.34 + sin(mposition.x * 4.82))) * 0.5 + 0.5)'
else:
return '0.0'
def parse_hairinfo(node: bpy.types.ShaderNodeHairInfo, out_socket: bpy.types.NodeSocket, state: ParserState) -> Union[floatstr, vec3str]:
@ -196,7 +204,8 @@ def parse_objectinfo(node: bpy.types.ShaderNodeObjectInfo, out_socket: bpy.types
if out_socket == node.outputs[0]:
if state.context == ParserContext.WORLD:
return c.to_vec3((0.0, 0.0, 0.0))
return 'wposition'
state.curshader.add_uniform('mat4 W', link='_worldMatrix')
return 'vec3(W[3][0], W[3][1], W[3][2])'
# Color
elif out_socket == node.outputs[1]:
@ -207,15 +216,35 @@ def parse_objectinfo(node: bpy.types.ShaderNodeObjectInfo, out_socket: bpy.types
return c.to_vec3((0.0, 0.0, 0.0))
return c.to_vec3([background_node.inputs[1].default_value] * 3)
# TODO: Implement object color in Iron
# state.curshader.add_uniform('vec3 objectInfoColor', link='_objectInfoColor')
# return 'objectInfoColor'
return c.to_vec3((1.0, 1.0, 1.0))
if mat_state.uses_instancing:
state.vert.add_out(f'vec3 irandc')
state.frag.add_in(f'vec3 irandc')
state.vert.write("irandc = vec3(" \
"fract(sin(fract(sin(gl_InstanceID) * 43758.5453) * 12.9898 + 78.233) * 43758.5453), " \
"fract(sin(fract(sin(gl_InstanceID) * 43758.5453) * 39.3456 + 12.123) * 43758.5453), " \
"fract(sin(fract(sin(gl_InstanceID) * 43758.5453) * 78.2330 + 45.678) * 43758.5453)" \
");"
)
return 'irandc'
state.curshader.add_uniform('float objRandom', link='_objectInfoRandom')
return "vec3(" \
"fract(sin(objRandom * 12.9898 + 78.233) * 43758.5453), " \
"fract(sin(objRandom * 39.3456 + 12.123) * 43758.5453), " \
"fract(sin(objRandom * 78.2330 + 45.678) * 43758.5453)" \
")"
#return c.to_vec3((1.0, 1.0, 1.0))
# Alpha
elif out_socket == node.outputs[2]:
# TODO, see color output above
return '0.0'
if mat_state.uses_instancing:
state.vert.add_out(f'float iranda')
state.frag.add_in(f'float iranda')
state.vert.write("iranda = fract(sin(fract(sin(gl_InstanceID) * 43758.5453) * 12.9898) * 43758.5453);")
return 'iranda'
state.curshader.add_uniform('float objAlphaRandom', link='_objectInfoRandom')
return 'fract(sin(objAlphaRandom * 12.9898) * 43758.5453)'
# Object Index
elif out_socket == node.outputs[3]:
@ -316,7 +345,8 @@ def parse_texcoord(node: bpy.types.ShaderNodeTexCoord, out_socket: bpy.types.Nod
state.dxdy_varying_input_value = True
return 'mposition'
elif out_socket == node.outputs[4]: # Camera
return 'vec3(0.0)' # 'vposition'
state.curshader.add_uniform('mat4 V', link='_viewMatrix')
return '(V * vec4(wposition, 1.0)).xyz'
elif out_socket == node.outputs[5]: # Window
# TODO: Don't use gl_FragCoord here, it uses different axes on different graphics APIs
state.frag.add_uniform('vec2 screenSize', link='_screenSize')
@ -326,7 +356,8 @@ def parse_texcoord(node: bpy.types.ShaderNodeTexCoord, out_socket: bpy.types.Nod
if state.context == ParserContext.WORLD:
state.dxdy_varying_input_value = True
return 'n'
return 'vec3(0.0)'
state.curshader.add_uniform('vec3 cameraPos', link='_cameraPosition')
return 'reflect(normalize(wposition - cameraPos), n)'
def parse_uvmap(node: bpy.types.ShaderNodeUVMap, out_socket: bpy.types.NodeSocket, state: ParserState) -> vec3str:
@ -352,10 +383,11 @@ def parse_uvmap(node: bpy.types.ShaderNodeUVMap, out_socket: bpy.types.NodeSocke
def parse_fresnel(node: bpy.types.ShaderNodeFresnel, out_socket: bpy.types.NodeSocket, state: ParserState) -> floatstr:
state.curshader.add_function(c_functions.str_fresnel)
ior = c.parse_value_input(node.inputs[0])
if node.inputs[1].is_linked:
dotnv = 'dot({0}, vVec)'.format(c.parse_vector_input(node.inputs[1]))
dotnv = 'clamp(dot({0}, vVec), 0.0, 1.0)'.format(c.parse_vector_input(node.inputs[1]))
else:
dotnv = 'dotNV'
dotnv = 'clamp(dotNV, 0.0, 1.0)'
state.dxdy_varying_input_value = True
return 'fresnel({0}, {1})'.format(ior, dotnv)
@ -363,20 +395,24 @@ def parse_fresnel(node: bpy.types.ShaderNodeFresnel, out_socket: bpy.types.NodeS
def parse_layerweight(node: bpy.types.ShaderNodeLayerWeight, out_socket: bpy.types.NodeSocket, state: ParserState) -> floatstr:
blend = c.parse_value_input(node.inputs[0])
if node.inputs[1].is_linked:
dotnv = 'dot({0}, vVec)'.format(c.parse_vector_input(node.inputs[1]))
dotnv = 'clamp(dot({0}, vVec), 0.0, 1.0)'.format(c.parse_vector_input(node.inputs[1]))
else:
dotnv = 'dotNV'
dotnv = 'clamp(dotNV, 0.0, 1.0)'
state.dxdy_varying_input_value = True
# Fresnel
if out_socket == node.outputs[0]:
state.curshader.add_function(c_functions.str_fresnel)
return 'fresnel(1.0 / (1.0 - {0}), {1})'.format(blend, dotnv)
return 'fresnel((1.0 + sqrt(clamp({0}, 0.0, 0.99))) / max(1.0 - sqrt(clamp({0}, 0.0, 0.99)), 1e-5), {1})'.format(blend, dotnv)
# Facing
elif out_socket == node.outputs[1]:
return '(1.0 - pow({0}, ({1} < 0.5) ? 2.0 * {1} : 0.5 / (1.0 - {1})))'.format(dotnv, blend)
return '({0} < 0.5) ? 1.0 - pow({1}, 2.0 * {0}) : 1.0 - pow({1}, 0.5 / max(1.0 - {0}, 1e-5))'.format(blend, dotnv)
return '0.0'
def parse_lightpath(node: bpy.types.ShaderNodeLightPath, out_socket: bpy.types.NodeSocket, state: ParserState) -> floatstr: