Particle Info material node
This commit is contained in:
parent
1ed22ad646
commit
cdb1525566
|
@ -19,6 +19,7 @@ import arm.material.cycles_state as c_state
|
|||
|
||||
basecol_texname = ''
|
||||
emission_found = False
|
||||
particle_info = None # Particle info export
|
||||
|
||||
def parse(nodes, con, vert, frag, geom, tesc, tese, parse_surface=True, parse_opacity=True, parse_displacement=True, basecol_only=False):
|
||||
output_node = node_by_type(nodes, 'OUTPUT_MATERIAL')
|
||||
|
@ -43,6 +44,7 @@ def parse_output(node, _con, _vert, _frag, _geom, _tesc, _tese, _parse_surface,
|
|||
global parse_teximage_vector
|
||||
global basecol_texname
|
||||
global emission_found
|
||||
global particle_info
|
||||
con = _con
|
||||
vert = _vert
|
||||
frag = _frag
|
||||
|
@ -56,6 +58,14 @@ def parse_output(node, _con, _vert, _frag, _geom, _tesc, _tese, _parse_surface,
|
|||
parse_teximage_vector = True
|
||||
basecol_texname = ''
|
||||
emission_found = False
|
||||
particle_info = {}
|
||||
particle_info['index'] = False
|
||||
particle_info['age'] = False
|
||||
particle_info['lifetime'] = False
|
||||
particle_info['location'] = False
|
||||
particle_info['size'] = False
|
||||
particle_info['velocity'] = False
|
||||
particle_info['angular_velocity'] = False
|
||||
|
||||
# Surface
|
||||
if parse_surface or parse_opacity:
|
||||
|
@ -716,6 +726,7 @@ def texture_store(node, tex, tex_name, to_linear=False):
|
|||
return tex_store
|
||||
|
||||
def parse_vector(node, socket):
|
||||
global particle_info
|
||||
|
||||
if node.type == 'GROUP':
|
||||
return parse_group(node, socket)
|
||||
|
@ -764,10 +775,13 @@ def parse_vector(node, socket):
|
|||
|
||||
elif node.type == 'PARTICLE_INFO':
|
||||
if socket == node.outputs[3]: # Location
|
||||
return 'vec3(0.0)'
|
||||
particle_info['location'] = True
|
||||
return 'p_location' if c_state.mat_get_material().arm_particle == 'gpu' else 'vec3(0.0)'
|
||||
elif socket == node.outputs[5]: # Velocity
|
||||
return 'vec3(0.0)'
|
||||
particle_info['velocity'] = True
|
||||
return 'p_velocity' if c_state.mat_get_material().arm_particle == 'gpu' else 'vec3(0.0)'
|
||||
elif socket == node.outputs[6]: # Angular Velocity
|
||||
particle_info['angular_velocity'] = True
|
||||
return 'vec3(0.0)'
|
||||
|
||||
elif node.type == 'TANGENT':
|
||||
|
@ -919,6 +933,7 @@ def parse_value_input(inp):
|
|||
return tovec1(inp.default_value)
|
||||
|
||||
def parse_value(node, socket):
|
||||
global particle_info
|
||||
|
||||
if node.type == 'GROUP':
|
||||
if node.node_tree.name.startswith('Armory PBR'):
|
||||
|
@ -1011,13 +1026,17 @@ def parse_value(node, socket):
|
|||
|
||||
elif node.type == 'PARTICLE_INFO':
|
||||
if socket == node.outputs[0]: # Index
|
||||
return '0.0'
|
||||
particle_info['index'] = True
|
||||
return 'p_index' if c_state.mat_get_material().arm_particle == 'gpu' else '0.0'
|
||||
elif socket == node.outputs[1]: # Age
|
||||
return '0.0'
|
||||
particle_info['age'] = True
|
||||
return 'p_age' if c_state.mat_get_material().arm_particle == 'gpu' else '0.0'
|
||||
elif socket == node.outputs[2]: # Lifetime
|
||||
return '0.0'
|
||||
particle_info['lifetime'] = True
|
||||
return 'p_lifetime' if c_state.mat_get_material().arm_particle == 'gpu' else '0.0'
|
||||
elif socket == node.outputs[4]: # Size
|
||||
return '0.0'
|
||||
particle_info['size'] = True
|
||||
return '1.0'
|
||||
|
||||
elif node.type == 'VALUE':
|
||||
return tovec1(node.outputs[0].default_value)
|
||||
|
|
|
@ -111,8 +111,9 @@ def make_base(con_mesh, parse_opacity):
|
|||
vert.add_uniform('mat3 N', '_normalMatrix')
|
||||
vert.write_main_header('vec4 spos = vec4(pos, 1.0);')
|
||||
|
||||
if mat_utils.disp_linked(mat_state.output_node):
|
||||
is_displacement = True
|
||||
vattr_written = False
|
||||
is_displacement = mat_utils.disp_linked(mat_state.output_node)
|
||||
if is_displacement:
|
||||
tesc = con_mesh.make_tesc()
|
||||
tese = con_mesh.make_tese()
|
||||
tesc.ins = vert.outs
|
||||
|
@ -127,36 +128,9 @@ def make_base(con_mesh, parse_opacity):
|
|||
make_tess.interpolate(tese, 'wnormal', 3, declare_out=True, normalize=True)
|
||||
# No displacement
|
||||
else:
|
||||
is_displacement = False
|
||||
frag.ins = vert.outs
|
||||
written = False
|
||||
if write_vertex_attribs != None:
|
||||
written = write_vertex_attribs(vert)
|
||||
if written == False:
|
||||
billboard = mat_state.material.arm_billboard
|
||||
particle = mat_state.material.arm_particle
|
||||
wrd = bpy.data.worlds['Arm']
|
||||
# Particles
|
||||
if particle != 'off':
|
||||
if particle == 'gpu':
|
||||
make_particle.write(vert)
|
||||
# Billboards
|
||||
if billboard == 'spherical':
|
||||
vert.add_uniform('mat4 WV', '_worldViewMatrix')
|
||||
vert.add_uniform('mat4 P', '_projectionMatrix')
|
||||
vert.write('gl_Position = P * (WV * vec4(0.0, 0.0, spos.z, 1.0) + vec4(spos.x, spos.y, 0.0, 0.0));')
|
||||
else:
|
||||
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrix')
|
||||
vert.write('gl_Position = WVP * spos;')
|
||||
else:
|
||||
# Billboards
|
||||
if billboard == 'spherical':
|
||||
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrixSphere')
|
||||
elif billboard == 'cylindrical':
|
||||
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrixCylinder')
|
||||
else: # off
|
||||
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrix')
|
||||
vert.write('gl_Position = WVP * spos;')
|
||||
vattr_written = write_vertex_attribs(vert)
|
||||
|
||||
frag.add_include('../../Shaders/compiled.glsl')
|
||||
|
||||
|
@ -174,6 +148,32 @@ def make_base(con_mesh, parse_opacity):
|
|||
if write_material_attribs_post != None:
|
||||
write_material_attribs_post(con_mesh, frag)
|
||||
|
||||
if not is_displacement and not vattr_written:
|
||||
billboard = mat_state.material.arm_billboard
|
||||
particle = mat_state.material.arm_particle
|
||||
wrd = bpy.data.worlds['Arm']
|
||||
# Particles
|
||||
if particle != 'off':
|
||||
if particle == 'gpu':
|
||||
make_particle.write(vert, particle_info=cycles.particle_info)
|
||||
# Billboards
|
||||
if billboard == 'spherical':
|
||||
vert.add_uniform('mat4 WV', '_worldViewMatrix')
|
||||
vert.add_uniform('mat4 P', '_projectionMatrix')
|
||||
vert.write('gl_Position = P * (WV * vec4(0.0, 0.0, spos.z, 1.0) + vec4(spos.x, spos.y, 0.0, 0.0));')
|
||||
else:
|
||||
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrix')
|
||||
vert.write('gl_Position = WVP * spos;')
|
||||
else:
|
||||
# Billboards
|
||||
if billboard == 'spherical':
|
||||
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrixSphere')
|
||||
elif billboard == 'cylindrical':
|
||||
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrixCylinder')
|
||||
else: # off
|
||||
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrix')
|
||||
vert.write('gl_Position = WVP * spos;')
|
||||
|
||||
if con_mesh.is_elem('tex'):
|
||||
vert.add_out('vec2 texCoord')
|
||||
if mat_state.material.arm_tilesheet_mat:
|
||||
|
@ -501,8 +501,8 @@ def make_forward(con_mesh):
|
|||
# frag.write('fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2));')
|
||||
|
||||
# Particle opacity
|
||||
# if mat_state.material.arm_particle == 'gpu':
|
||||
# frag.write('fragColor.rgb *= popac;')
|
||||
if mat_state.material.arm_particle == 'gpu' and mat_state.material.arm_particle_fade:
|
||||
frag.write('fragColor.rgb *= p_fade;')
|
||||
|
||||
def make_forward_base(con_mesh, parse_opacity=False):
|
||||
wrd = bpy.data.worlds['Arm']
|
||||
|
|
|
@ -1,50 +1,82 @@
|
|||
|
||||
def write(vert):
|
||||
import arm.material.mat_state as mat_state
|
||||
|
||||
def write(vert, particle_info=None):
|
||||
|
||||
# Outs
|
||||
out_index = True if particle_info != None and particle_info['index'] else False
|
||||
out_age = True if particle_info != None and particle_info['age'] else False
|
||||
out_lifetime = True if particle_info != None and particle_info['lifetime'] else False
|
||||
out_location = True if particle_info != None and particle_info['location'] else False
|
||||
out_size = True if particle_info != None and particle_info['size'] else False
|
||||
out_velocity = True if particle_info != None and particle_info['velocity'] else False
|
||||
out_angular_velocity = True if particle_info != None and particle_info['angular_velocity'] else False
|
||||
|
||||
vert.add_uniform('mat4 pd', '_particleData')
|
||||
|
||||
str_tex_hash = "float fhash(float n) { return fract(sin(n) * 43758.5453); }"
|
||||
vert.add_function(str_tex_hash)
|
||||
|
||||
# var ptime = (count - p.i) * spawnRate;
|
||||
vert.write('float ptime = (pd[0][0] - gl_InstanceID) * pd[0][1];')
|
||||
# ptime -= ptime * fhash(i) * r.lifetime_random;
|
||||
vert.write('ptime -= ptime * fhash(gl_InstanceID) * pd[2][3];')
|
||||
prep = 'float '
|
||||
if out_age:
|
||||
prep = ''
|
||||
vert.add_out('float p_age')
|
||||
# var p_age = (count - p.i) * spawnRate;
|
||||
vert.write(prep + 'p_age = (pd[0][0] - gl_InstanceID) * pd[0][1];')
|
||||
# p_age -= p_age * fhash(i) * r.lifetime_random;
|
||||
vert.write('p_age -= p_age * fhash(gl_InstanceID) * pd[2][3];')
|
||||
|
||||
# lifetime
|
||||
prep = 'float '
|
||||
if out_lifetime:
|
||||
prep = ''
|
||||
vert.add_out('float p_lifetime')
|
||||
vert.write(prep + 'p_lifetime = pd[0][2];')
|
||||
# todo: properly discard
|
||||
vert.write('if (gl_InstanceID > pd[0][0] || ptime < 0 || ptime > pd[0][2]) { spos.x = spos.y = spos.z = -99999; }')
|
||||
vert.write('if (gl_InstanceID > pd[0][0] || p_age < 0 || p_age > p_lifetime) { spos.x = spos.y = spos.z = -99999; }')
|
||||
|
||||
vert.write('ptime /= 2;')
|
||||
vert.write('p_age /= 2;')
|
||||
|
||||
# object_align_factor / 2 + gxyz
|
||||
vert.write('vec3 ppos = vec3(pd[1][0], pd[1][1], pd[1][2]);')
|
||||
prep = 'vec3 '
|
||||
if out_velocity:
|
||||
prep = ''
|
||||
vert.add_out('vec3 p_velocity')
|
||||
vert.write(prep + 'p_velocity = vec3(pd[1][0], pd[1][1], pd[1][2]);')
|
||||
|
||||
vert.write('p_velocity.x += fhash(gl_InstanceID) * pd[1][3] - pd[1][3] / 2;')
|
||||
vert.write('p_velocity.y += fhash(gl_InstanceID + pd[0][3]) * pd[1][3] - pd[1][3] / 2;')
|
||||
vert.write('p_velocity.z += fhash(gl_InstanceID + 2 * pd[0][3]) * pd[1][3] - pd[1][3] / 2;')
|
||||
|
||||
# factor_random = pd[1][3]
|
||||
# p.i = gl_InstanceID
|
||||
# particles.length = pd[0][3]
|
||||
vert.write('ppos.x += fhash(gl_InstanceID) * pd[1][3] - pd[1][3] / 2;')
|
||||
vert.write('ppos.y += fhash(gl_InstanceID + pd[0][3]) * pd[1][3] - pd[1][3] / 2;')
|
||||
vert.write('ppos.z += fhash(gl_InstanceID + 2 * pd[0][3]) * pd[1][3] - pd[1][3] / 2;')
|
||||
|
||||
# gxyz
|
||||
vert.write('ppos.x += (pd[2][0] * ptime) / 5;')
|
||||
vert.write('ppos.y += (pd[2][1] * ptime) / 5;')
|
||||
vert.write('ppos.z += (pd[2][2] * ptime) / 5;')
|
||||
vert.write('p_velocity.x += (pd[2][0] * p_age) / 5;')
|
||||
vert.write('p_velocity.y += (pd[2][1] * p_age) / 5;')
|
||||
vert.write('p_velocity.z += (pd[2][2] * p_age) / 5;')
|
||||
|
||||
vert.write('ppos.x *= ptime;')
|
||||
vert.write('ppos.y *= ptime;')
|
||||
vert.write('ppos.z *= ptime;')
|
||||
prep = 'vec3 '
|
||||
if out_location:
|
||||
prep = ''
|
||||
vert.add_out('vec3 p_location')
|
||||
vert.write(prep + 'p_location = p_velocity * p_age;')
|
||||
|
||||
vert.write('spos.xyz += ppos;')
|
||||
vert.write('spos.xyz += p_location;')
|
||||
|
||||
# Particle opacity
|
||||
# vert.add_out('float popac')
|
||||
# vert.write('popac = sin(min((ptime / 2) * 3.141592, 3.141592));')
|
||||
# Particle fade
|
||||
if mat_state.material.arm_particle == 'gpu' and mat_state.material.arm_particle_fade:
|
||||
vert.add_out('float p_fade')
|
||||
vert.write('p_fade = sin(min((p_age / 2) * 3.141592, 3.141592));')
|
||||
|
||||
if out_index:
|
||||
vert.add_out('float p_index');
|
||||
vert.write('p_index = gl_InstanceID;')
|
||||
|
||||
def write_tilesheet(vert):
|
||||
# tilesx, tilesy, framerate - pd[3][0], pd[3][1], pd[3][2]
|
||||
vert.write('int frame = int((ptime / 2) / pd[3][2]);')
|
||||
vert.write('int frame = int((p_age / 2) / pd[3][2]);')
|
||||
vert.write('int tx = frame % int(pd[3][0]);')
|
||||
vert.write('int ty = int(frame / pd[3][0]);')
|
||||
vert.write('vec2 tilesheetOffset = vec2(tx * (1 / pd[3][0]), ty * (1 / pd[3][1]));')
|
||||
|
|
|
@ -295,6 +295,7 @@ def init_properties():
|
|||
('gpu', 'GPU', 'GPU'),
|
||||
('cpu', 'CPU', 'CPU')],
|
||||
name="Particle", default='off', description="Use this material for particle system rendering", update=assets.invalidate_shader_cache)
|
||||
bpy.types.Material.arm_particle_fade = bpy.props.BoolProperty(name="Particle Fade", description="Fade particles in and out", default=False)
|
||||
bpy.types.Material.arm_tilesheet_mat = bpy.props.BoolProperty(name="Tilesheet", description="Generate tilesheet shaders", default=False)
|
||||
bpy.types.Material.arm_blending = bpy.props.BoolProperty(name="Blending", description="Enable additive blending", default=False)
|
||||
# For scene
|
||||
|
|
|
@ -270,6 +270,8 @@ class MaterialPropsPanel(bpy.types.Panel):
|
|||
layout.prop(mat, 'arm_skip_context')
|
||||
layout.prop(mat, 'arm_billboard')
|
||||
layout.prop(mat, 'arm_particle')
|
||||
if mat.arm_particle == 'gpu':
|
||||
layout.prop(mat, 'arm_particle_fade')
|
||||
row = layout.row()
|
||||
row.prop(mat, 'arm_tilesheet_mat')
|
||||
row.prop(mat, 'arm_blending')
|
||||
|
|
Loading…
Reference in a new issue