forked from LeenkxTeam/LNXSDK
Group Nodes, Shaders, Textures, Displacement
This commit is contained in:
@ -28,7 +28,7 @@ def parse_curvevec(node: bpy.types.ShaderNodeVectorCurve, out_socket: bpy.types.
|
||||
fac = c.get_value_input(node, ['Fac'])
|
||||
vec = c.get_vector_input(node, ['Vector'])
|
||||
curves = node.mapping.curves
|
||||
name = c.node_name(node.name)
|
||||
name = c.node_uid(node)
|
||||
|
||||
res_x = c.vector_curve(name + '0', vec + '.x', curves[0].points)
|
||||
res_y = c.vector_curve(name + '1', vec + '.y', curves[1].points)
|
||||
@ -47,33 +47,39 @@ def parse_bump(node: bpy.types.ShaderNodeBump, out_socket: bpy.types.NodeSocket,
|
||||
# Interpolation strength
|
||||
strength = c.get_value_input(node, ['Strength'])
|
||||
distance = c.get_value_input(node, ['Distance'])
|
||||
filter_width = c.get_value_input(node, ['Filter Width']) if 'Filter Width' in node.inputs else '1.0'
|
||||
height = c.get_value_input(node, ['Height'])
|
||||
|
||||
prev_pass = state.current_pass
|
||||
prev_scale = state.dxdy_scale
|
||||
state.dxdy_scale = filter_width
|
||||
state.current_pass = ParserPass.DX_SCREEN_SPACE
|
||||
height_dx = c.get_value_input(node, ['Height'])
|
||||
state.current_pass = ParserPass.DY_SCREEN_SPACE
|
||||
height_dy = c.get_value_input(node, ['Height'])
|
||||
state.current_pass = ParserPass.REGULAR
|
||||
state.current_pass = prev_pass
|
||||
state.dxdy_scale = prev_scale
|
||||
|
||||
nor = c.get_vector_input(node, ['Normal']) if node.inputs['Normal'].is_linked else 'n'
|
||||
|
||||
if height_dx != height or height_dy != height:
|
||||
tangent = f'{c.dfdx_fine("wposition")} + {nor} * (({height_dx} - {height}) * {distance})'
|
||||
bitangent = f'{c.dfdy_fine("wposition")} + {nor} * (({height_dy} - {height}) * {distance})'
|
||||
|
||||
# Cross-product operand order, dFdy is flipped on d3d11
|
||||
bitangent_first = utils.get_gapi() == 'direct3d11'
|
||||
|
||||
if node.invert:
|
||||
bitangent_first = not bitangent_first
|
||||
|
||||
if bitangent_first:
|
||||
# We need to normalize twice, once for the correct "weight" of the strength,
|
||||
# once for having a normalized output vector (lerping vectors does not preserve magnitude)
|
||||
res = f'normalize(mix({nor}, normalize(cross({bitangent}, {tangent})), {strength}))'
|
||||
else:
|
||||
res = f'normalize(mix({nor}, normalize(cross({tangent}, {bitangent})), {strength}))'
|
||||
|
||||
name = c.node_uid(node)
|
||||
if '__' in name:
|
||||
name = name.replace('_', '_x')
|
||||
sfx = state.get_parser_pass_suffix()
|
||||
invert = '-1.0' if node.invert else '1.0'
|
||||
w = state.curshader.write
|
||||
w(f'vec3 {name}_N{sfx} = normalize({nor});')
|
||||
w(f'float {name}_dist{sfx} = ({distance}) * (gl_FrontFacing ? {invert} : -({invert}));')
|
||||
w(f'vec3 {name}_dPdx{sfx} = {c.dfdx_fine("wposition")};')
|
||||
w(f'vec3 {name}_dPdy{sfx} = {c.dfdy_fine("wposition")};')
|
||||
w(f'vec3 {name}_Rx{sfx} = cross({name}_dPdy{sfx}, {name}_N{sfx});')
|
||||
w(f'vec3 {name}_Ry{sfx} = cross({name}_N{sfx}, {name}_dPdx{sfx});')
|
||||
w(f'float {name}_det{sfx} = dot({name}_dPdx{sfx}, {name}_Rx{sfx});')
|
||||
w(f'vec2 {name}_dHd{sfx} = vec2({height_dx}, {height_dy}) - vec2({height});')
|
||||
w(f'vec3 {name}_surfgrad{sfx} = {name}_dHd{sfx}.x * {name}_Rx{sfx} + {name}_dHd{sfx}.y * {name}_Ry{sfx};')
|
||||
w(f'vec3 {name}_res{sfx} = normalize(({filter_width}) * abs({name}_det{sfx}) * {name}_N{sfx} - {name}_dist{sfx} * sign({name}_det{sfx}) * {name}_surfgrad{sfx});')
|
||||
res = f'normalize(mix({name}_N{sfx}, {name}_res{sfx}, max({strength}, 0.0)))'
|
||||
else:
|
||||
res = nor
|
||||
|
||||
@ -96,7 +102,7 @@ def parse_mapping(node: bpy.types.ShaderNodeMapping, out_socket: bpy.types.NodeS
|
||||
out = f"({out} - {location})"
|
||||
|
||||
if input_rotation.is_linked or any(v != 0.0 for v in input_rotation.default_value):
|
||||
var_name = c.node_name(node.name) + "_rotation" + state.get_parser_pass_suffix()
|
||||
var_name = c.node_uid(node) + "_rotation" + state.get_parser_pass_suffix()
|
||||
state.curshader.write(f"mat3 {var_name}X = mat3(1.0, 0.0, 0.0, 0.0, cos({rotation}.x), sin({rotation}.x), 0.0, -sin({rotation}.x), cos({rotation}.x));")
|
||||
state.curshader.write(f"mat3 {var_name}Y = mat3(cos({rotation}.y), 0.0, -sin({rotation}.y), 0.0, 1.0, 0.0, sin({rotation}.y), 0.0, cos({rotation}.y));")
|
||||
state.curshader.write(f"mat3 {var_name}Z = mat3(cos({rotation}.z), sin({rotation}.z), 0.0, -sin({rotation}.z), cos({rotation}.z), 0.0, 0.0, 0.0, 1.0);")
|
||||
@ -110,7 +116,7 @@ def parse_mapping(node: bpy.types.ShaderNodeMapping, out_socket: bpy.types.NodeS
|
||||
out = f"({out} * {scale})"
|
||||
|
||||
if input_rotation.is_linked or any(v != 0.0 for v in input_rotation.default_value):
|
||||
var_name = c.node_name(node.name) + "_rotation" + state.get_parser_pass_suffix()
|
||||
var_name = c.node_uid(node) + "_rotation" + state.get_parser_pass_suffix()
|
||||
state.curshader.write(f"mat3 {var_name}X = mat3(1.0, 0.0, 0.0, 0.0, cos({rotation}.x), -sin({rotation}.x), 0.0, sin({rotation}.x), cos({rotation}.x));")
|
||||
state.curshader.write(f"mat3 {var_name}Y = mat3(cos({rotation}.y), 0.0, sin({rotation}.y), 0.0, 1.0, 0.0, -sin({rotation}.y), 0.0, cos({rotation}.y));")
|
||||
state.curshader.write(f"mat3 {var_name}Z = mat3(cos({rotation}.z), -sin({rotation}.z), 0.0, sin({rotation}.z), cos({rotation}.z), 0.0, 0.0, 0.0, 1.0);")
|
||||
@ -203,7 +209,8 @@ def parse_displacement(node: bpy.types.ShaderNodeDisplacement, out_socket: bpy.t
|
||||
nor = 'wnormal'
|
||||
|
||||
if node.space == 'OBJECT':
|
||||
nor = f'(inverse(mat3(W)) * {nor})'
|
||||
state.curshader.add_uniform('mat4 W', link='_worldMatrix')
|
||||
nor = f'(transpose(mat3(W)) * {nor})'
|
||||
|
||||
disp = f'normalize({nor}) * (vec3({height}) - vec3({midlevel})) * {scale}'
|
||||
|
||||
@ -221,12 +228,14 @@ def parse_vector_displacement(node: bpy.types.ShaderNodeVectorDisplacement, out_
|
||||
offset = f'(({vector} - vec3({midlevel})) * {scale})'
|
||||
|
||||
if node.space == 'TANGENT':
|
||||
state.curshader.add_uniform('mat4 W', link='_worldMatrix')
|
||||
t_obj = 'normalize(inverse(mat3(W)) * wtangent)'
|
||||
n_obj = 'normalize(inverse(mat3(W)) * wnormal)'
|
||||
n_obj = 'normalize(transpose(mat3(W)) * wnormal)'
|
||||
b_obj = f'normalize(cross({n_obj}, {t_obj}))'
|
||||
disp = f'({t_obj} * {offset}.x + {n_obj} * {offset}.y + {b_obj} * {offset}.z)'
|
||||
disp = f'({t_obj} * {offset}.x + {b_obj} * {offset}.y + {n_obj} * {offset}.z)'
|
||||
return f'(vec4(W * vec4({disp}, 0.0)).xyz)'
|
||||
elif node.space == 'OBJECT':
|
||||
state.curshader.add_uniform('mat4 W', link='_worldMatrix')
|
||||
return f'(vec4(W * vec4({offset}, 0.0)).xyz)'
|
||||
else:
|
||||
return offset
|
||||
@ -262,3 +271,9 @@ def parse_vectorrotate(node: bpy.types.ShaderNodeVectorRotate, out_socket: bpy.t
|
||||
return f'vec3( euler_to_mat3({rot_val}) * ({input_vector} - {input_center}) + {input_center})'
|
||||
|
||||
return f'vec3(0.0, 0.0, 0.0)'
|
||||
|
||||
|
||||
def parse_bevel(node: bpy.types.ShaderNodeBevel, out_socket: bpy.types.NodeSocket, state: ParserState) -> vec3str:
|
||||
if node.inputs['Normal'].is_linked:
|
||||
return c.get_vector_input(node, ['Normal'])
|
||||
return 'n' if state.curshader.shader_type == 'frag' else 'wnormal'
|
||||
|
||||
Reference in New Issue
Block a user