Advancing new material builder
This commit is contained in:
parent
924e187f9a
commit
19777385e5
Binary file not shown.
|
@ -1648,7 +1648,8 @@ class ArmoryExporter:
|
|||
na['size'] = 3
|
||||
na['values'] = ndata
|
||||
om['vertex_arrays'].append(na)
|
||||
if num_uv_layers > 0:
|
||||
|
||||
if self.get_export_uvs(exportMesh) == True and num_uv_layers > 0:
|
||||
ta = {}
|
||||
ta['attrib'] = "texcoord"
|
||||
ta['size'] = 2
|
||||
|
@ -1660,7 +1661,8 @@ class ArmoryExporter:
|
|||
ta1['size'] = 2
|
||||
ta1['values'] = t1data
|
||||
om['vertex_arrays'].append(ta1)
|
||||
if num_colors > 0:
|
||||
|
||||
if self.get_export_vcols(exportMesh) == True and num_colors > 0:
|
||||
ca = {}
|
||||
ca['attrib'] = "color"
|
||||
ca['size'] = 3
|
||||
|
@ -1707,7 +1709,7 @@ class ArmoryExporter:
|
|||
om['index_arrays'].append(ia)
|
||||
|
||||
# Make tangents
|
||||
if (self.get_export_tangents(exportMesh) == True and num_uv_layers > 0):
|
||||
if self.get_export_tangents(exportMesh) == True and num_uv_layers > 0:
|
||||
tana = {}
|
||||
tana['attrib'] = "tangent"
|
||||
tana['size'] = 3
|
||||
|
@ -1864,7 +1866,7 @@ class ArmoryExporter:
|
|||
|
||||
# Write the color array if it exists.
|
||||
colorCount = len(exportMesh.tessface_vertex_colors)
|
||||
if (colorCount > 0):
|
||||
if self.get_export_vcols(exportMesh) == True and colorCount > 0:
|
||||
ca = {}
|
||||
ca['attrib'] = "color"
|
||||
ca['size'] = 3
|
||||
|
@ -1873,7 +1875,7 @@ class ArmoryExporter:
|
|||
|
||||
# Write the texcoord arrays.
|
||||
texcoordCount = len(exportMesh.tessface_uv_textures)
|
||||
if (texcoordCount > 0):
|
||||
if self.get_export_uvs(exportMesh) == True and texcoordCount > 0:
|
||||
ta = {}
|
||||
ta['attrib'] = "texcoord"
|
||||
ta['size'] = 2
|
||||
|
@ -1931,16 +1933,16 @@ class ArmoryExporter:
|
|||
|
||||
# bpy.data.meshes.remove(morphMesh)
|
||||
|
||||
# Write the index arrays.
|
||||
# Write the index arrays
|
||||
om['index_arrays'] = []
|
||||
|
||||
maxMaterialIndex = 0
|
||||
for i in range(len(material_table)):
|
||||
index = material_table[i]
|
||||
if (index > maxMaterialIndex):
|
||||
if index > maxMaterialIndex:
|
||||
maxMaterialIndex = index
|
||||
|
||||
if (maxMaterialIndex == 0):
|
||||
if maxMaterialIndex == 0:
|
||||
# There is only one material, so write a single index array.
|
||||
ia = {}
|
||||
ia['size'] = 3
|
||||
|
@ -1970,7 +1972,7 @@ class ArmoryExporter:
|
|||
om['index_arrays'].append(ia)
|
||||
|
||||
# Export tangents
|
||||
if (self.get_export_tangents(exportMesh) == True and len(exportMesh.uv_textures) > 0):
|
||||
if self.get_export_tangents(exportMesh) == True and len(exportMesh.uv_textures) > 0:
|
||||
tana = {}
|
||||
tana['attrib'] = "tangent"
|
||||
tana['size'] = 3
|
||||
|
@ -2135,7 +2137,29 @@ class ArmoryExporter:
|
|||
if wrd.arm_material_level == 'Restricted':
|
||||
self.post_export_material(material, o)
|
||||
else:
|
||||
make_material_full.parse(material, o)
|
||||
sd = make_material_full.parse(material, o)
|
||||
|
||||
uv_export = False
|
||||
tan_export = False
|
||||
vcol_export = False
|
||||
for elem in sd['vertex_structure']:
|
||||
if elem['name'] == 'tan':
|
||||
tan_export = True
|
||||
elif elem['name'] == 'tex':
|
||||
uv_export = True
|
||||
elif elem['name'] == 'col':
|
||||
vcol_export = True
|
||||
|
||||
if (material.export_tangents != tan_export) or \
|
||||
(material.export_uvs != uv_export) or \
|
||||
(material.export_vcols != vcol_export):
|
||||
|
||||
material.export_uvs = uv_export
|
||||
material.export_vcols = vcol_export
|
||||
material.export_tangents = tan_export
|
||||
mat_users = self.materialToObjectDict[material]
|
||||
for ob in mat_users:
|
||||
ob.data.mesh_cached = False
|
||||
|
||||
self.output['material_datas'].append(o)
|
||||
|
||||
|
@ -2399,6 +2423,18 @@ class ArmoryExporter:
|
|||
return True
|
||||
return False
|
||||
|
||||
def get_export_vcols(self, mesh):
|
||||
for m in mesh.materials:
|
||||
if m != None and m.export_vcols == True:
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_export_uvs(self, mesh):
|
||||
for m in mesh.materials:
|
||||
if m != None and m.export_uvs == True:
|
||||
return True
|
||||
return False
|
||||
|
||||
def object_process_instancing(self, bobject, refs):
|
||||
is_instanced = False
|
||||
instance_offsets = None
|
||||
|
@ -2925,7 +2961,6 @@ class ArmoryExporter:
|
|||
# Delete mesh caches
|
||||
for ob in mat_users:
|
||||
ob.data.mesh_cached = False
|
||||
break
|
||||
|
||||
# Process defs and append datas
|
||||
if material.override_shader == False:
|
||||
|
|
115
blender/material/functions.py
Normal file
115
blender/material/functions.py
Normal file
|
@ -0,0 +1,115 @@
|
|||
str_tex_checker = """vec3 tex_checker(const vec3 co, const vec3 col1, const vec3 col2, const float scale) {
|
||||
vec3 p = co * scale;
|
||||
// Prevent precision issues on unit coordinates
|
||||
//p.x = (p.x + 0.000001) * 0.999999;
|
||||
//p.y = (p.y + 0.000001) * 0.999999;
|
||||
//p.z = (p.z + 0.000001) * 0.999999;
|
||||
float xi = abs(floor(p.x));
|
||||
float yi = abs(floor(p.y));
|
||||
float zi = abs(floor(p.z));
|
||||
bool check = ((mod(xi, 2.0) == mod(yi, 2.0)) == bool(mod(zi, 2.0)));
|
||||
return check ? col1 : col2;
|
||||
}
|
||||
"""
|
||||
|
||||
# Created by inigo quilez - iq/2013
|
||||
# License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
|
||||
str_tex_voronoi = """//vec3 hash(vec3 x) {
|
||||
//return texture(snoise, (x.xy + vec2(3.0, 1.0) * x.z + 0.5) / 64.0, -100.0).xyz;
|
||||
//x = vec3(dot(x, vec3(127.1, 311.7, 74.7)),
|
||||
// dot(x, vec3(269.5, 183.3, 246.1)),
|
||||
// dot(x, vec3(113.5, 271.9, 124.6)));
|
||||
//return fract(sin(x) * 43758.5453123);
|
||||
//}
|
||||
vec4 tex_voronoi(const vec3 x) {
|
||||
vec3 xx = x / 3.0; // Match cycles
|
||||
vec3 p = floor(xx);
|
||||
vec3 f = fract(xx);
|
||||
float id = 0.0;
|
||||
float res = 100.0;
|
||||
for (int k = -1; k <= 1; k++)
|
||||
for (int j = -1; j <= 1; j++)
|
||||
for (int i = -1; i <= 1; i++) {
|
||||
vec3 b = vec3(float(i), float(j), float(k));
|
||||
vec3 pb = p + b;
|
||||
//vec3 r = vec3(b) - f + texture(snoise, (pb.xy + vec2(3.0, 1.0) * pb.z + 0.5) / 64.0, -100.0).xyz; // No bias in tese
|
||||
vec3 r = vec3(b) - f + texture(snoise, (pb.xy + vec2(3.0, 1.0) * pb.z + 0.5) / 64.0).xyz;
|
||||
//vec3 r = vec3(b) - f + hash(p + b);
|
||||
float d = dot(r, r);
|
||||
if (d < res) {
|
||||
id = dot(p + b, vec3(1.0, 57.0, 113.0));
|
||||
res = d;
|
||||
}
|
||||
}
|
||||
vec3 col = 0.5 + 0.5 * cos(id * 0.35 + vec3(0.0, 1.0, 2.0));
|
||||
return vec4(col, sqrt(res));
|
||||
}
|
||||
"""
|
||||
|
||||
# str_tex_noise = """
|
||||
# float tex_noise_f(const vec3 x) {
|
||||
# vec3 p = floor(x);
|
||||
# vec3 f = fract(x);
|
||||
# f = f * f * (3.0 - 2.0 * f);
|
||||
# vec2 uv = (p.xy + vec2(37.0, 17.0) * p.z) + f.xy;
|
||||
# vec2 rg = texture(snoisea, (uv + 0.5) / 64.0, -100.0).yx;
|
||||
# return mix(rg.x, rg.y, f.z);
|
||||
# }
|
||||
# float tex_noise(vec3 q) {
|
||||
# //return fract(sin(dot(q.xy, vec2(12.9898,78.233))) * 43758.5453);
|
||||
# q *= 2.0; // Match to Cycles
|
||||
# const mat3 m = mat3(0.00, 0.80, 0.60, -0.80, 0.36, -0.48, -0.60, -0.48, 0.64);
|
||||
# float f = 0.5000 * tex_noise_f(q); q = m * q * 2.01;
|
||||
# f += 0.2500 * tex_noise_f(q); q = m * q * 2.02;
|
||||
# f += 0.1250 * tex_noise_f(q); q = m * q * 2.03;
|
||||
# f += 0.0625 * tex_noise_f(q); q = m * q * 2.01;
|
||||
# return pow(f, 3.0);
|
||||
# }
|
||||
# """
|
||||
# Created by Nikita Miropolskiy, nikat/2013
|
||||
# Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
|
||||
str_tex_noise = """
|
||||
vec3 random3(vec3 c) {
|
||||
// Might not be precise on lowp floats
|
||||
float j = 4096.0 * sin(dot(c, vec3(17.0, 59.4, 15.0)));
|
||||
vec3 r;
|
||||
r.z = fract(512.0 * j);
|
||||
j *= 0.125;
|
||||
r.x = fract(512.0 * j);
|
||||
j *= 0.125;
|
||||
r.y = fract(512.0 * j);
|
||||
return r - 0.5;
|
||||
}
|
||||
float tex_noise_f(vec3 p) {
|
||||
const float F3 = 0.3333333;
|
||||
const float G3 = 0.1666667;
|
||||
vec3 s = floor(p + dot(p, vec3(F3)));
|
||||
vec3 x = p - s + dot(s, vec3(G3));
|
||||
vec3 e = step(vec3(0.0), x - x.yzx);
|
||||
vec3 i1 = e*(1.0 - e.zxy);
|
||||
vec3 i2 = 1.0 - e.zxy*(1.0 - e);
|
||||
vec3 x1 = x - i1 + G3;
|
||||
vec3 x2 = x - i2 + 2.0*G3;
|
||||
vec3 x3 = x - 1.0 + 3.0*G3;
|
||||
vec4 w, d;
|
||||
w.x = dot(x, x);
|
||||
w.y = dot(x1, x1);
|
||||
w.z = dot(x2, x2);
|
||||
w.w = dot(x3, x3);
|
||||
w = max(0.6 - w, 0.0);
|
||||
d.x = dot(random3(s), x);
|
||||
d.y = dot(random3(s + i1), x1);
|
||||
d.z = dot(random3(s + i2), x2);
|
||||
d.w = dot(random3(s + 1.0), x3);
|
||||
w *= w;
|
||||
w *= w;
|
||||
d *= w;
|
||||
return clamp(dot(d, vec4(52.0)), 0.0, 1.0);
|
||||
}
|
||||
float tex_noise(vec3 p) {
|
||||
return 0.5333333 * tex_noise_f(p)
|
||||
+ 0.2666667 * tex_noise_f(2.0 * p)
|
||||
+ 0.1333333 * tex_noise_f(4.0 * p)
|
||||
+ 0.0666667 * tex_noise_f(8.0 * p);
|
||||
}
|
||||
"""
|
|
@ -61,6 +61,8 @@ def parse(material, mat_data):
|
|||
assets.add_shader_data(shader_data_path)
|
||||
mat_data['shader'] = shader_data_name + '/' + shader_data_name
|
||||
|
||||
return state.data.sd
|
||||
|
||||
def make_mat_context(name):
|
||||
c = {}
|
||||
c['name'] = name
|
||||
|
|
|
@ -18,124 +18,9 @@ import armutils
|
|||
import assets
|
||||
import material.make_texture as make_texture
|
||||
import material.mat_state as mat_state
|
||||
import material.functions
|
||||
import make_state as state
|
||||
|
||||
str_tex_checker = """vec3 tex_checker(const vec3 co, const vec3 col1, const vec3 col2, const float scale) {
|
||||
vec3 p = co * scale;
|
||||
// Prevent precision issues on unit coordinates
|
||||
//p.x = (p.x + 0.000001) * 0.999999;
|
||||
//p.y = (p.y + 0.000001) * 0.999999;
|
||||
//p.z = (p.z + 0.000001) * 0.999999;
|
||||
float xi = abs(floor(p.x));
|
||||
float yi = abs(floor(p.y));
|
||||
float zi = abs(floor(p.z));
|
||||
bool check = ((mod(xi, 2.0) == mod(yi, 2.0)) == bool(mod(zi, 2.0)));
|
||||
return check ? col1 : col2;
|
||||
}
|
||||
"""
|
||||
|
||||
# Created by inigo quilez - iq/2013
|
||||
# License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
|
||||
str_tex_voronoi = """//vec3 hash(vec3 x) {
|
||||
//return texture(snoise, (x.xy + vec2(3.0, 1.0) * x.z + 0.5) / 64.0, -100.0).xyz;
|
||||
//x = vec3(dot(x, vec3(127.1, 311.7, 74.7)),
|
||||
// dot(x, vec3(269.5, 183.3, 246.1)),
|
||||
// dot(x, vec3(113.5, 271.9, 124.6)));
|
||||
//return fract(sin(x) * 43758.5453123);
|
||||
//}
|
||||
vec4 tex_voronoi(const vec3 x) {
|
||||
vec3 xx = x / 3.0; // Match cycles
|
||||
vec3 p = floor(xx);
|
||||
vec3 f = fract(xx);
|
||||
float id = 0.0;
|
||||
float res = 100.0;
|
||||
for (int k = -1; k <= 1; k++)
|
||||
for (int j = -1; j <= 1; j++)
|
||||
for (int i = -1; i <= 1; i++) {
|
||||
vec3 b = vec3(float(i), float(j), float(k));
|
||||
vec3 pb = p + b;
|
||||
//vec3 r = vec3(b) - f + texture(snoise, (pb.xy + vec2(3.0, 1.0) * pb.z + 0.5) / 64.0, -100.0).xyz; // No bias in tese
|
||||
vec3 r = vec3(b) - f + texture(snoise, (pb.xy + vec2(3.0, 1.0) * pb.z + 0.5) / 64.0).xyz;
|
||||
//vec3 r = vec3(b) - f + hash(p + b);
|
||||
float d = dot(r, r);
|
||||
if (d < res) {
|
||||
id = dot(p + b, vec3(1.0, 57.0, 113.0));
|
||||
res = d;
|
||||
}
|
||||
}
|
||||
vec3 col = 0.5 + 0.5 * cos(id * 0.35 + vec3(0.0, 1.0, 2.0));
|
||||
return vec4(col, sqrt(res));
|
||||
}
|
||||
"""
|
||||
|
||||
# str_tex_noise = """
|
||||
# float tex_noise_f(const vec3 x) {
|
||||
# vec3 p = floor(x);
|
||||
# vec3 f = fract(x);
|
||||
# f = f * f * (3.0 - 2.0 * f);
|
||||
# vec2 uv = (p.xy + vec2(37.0, 17.0) * p.z) + f.xy;
|
||||
# vec2 rg = texture(snoisea, (uv + 0.5) / 64.0, -100.0).yx;
|
||||
# return mix(rg.x, rg.y, f.z);
|
||||
# }
|
||||
# float tex_noise(vec3 q) {
|
||||
# //return fract(sin(dot(q.xy, vec2(12.9898,78.233))) * 43758.5453);
|
||||
# q *= 2.0; // Match to Cycles
|
||||
# const mat3 m = mat3(0.00, 0.80, 0.60, -0.80, 0.36, -0.48, -0.60, -0.48, 0.64);
|
||||
# float f = 0.5000 * tex_noise_f(q); q = m * q * 2.01;
|
||||
# f += 0.2500 * tex_noise_f(q); q = m * q * 2.02;
|
||||
# f += 0.1250 * tex_noise_f(q); q = m * q * 2.03;
|
||||
# f += 0.0625 * tex_noise_f(q); q = m * q * 2.01;
|
||||
# return pow(f, 3.0);
|
||||
# }
|
||||
# """
|
||||
# Created by Nikita Miropolskiy, nikat/2013
|
||||
# Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
|
||||
str_tex_noise = """
|
||||
vec3 random3(vec3 c) {
|
||||
// Might not be precise on lowp floats
|
||||
float j = 4096.0 * sin(dot(c, vec3(17.0, 59.4, 15.0)));
|
||||
vec3 r;
|
||||
r.z = fract(512.0 * j);
|
||||
j *= 0.125;
|
||||
r.x = fract(512.0 * j);
|
||||
j *= 0.125;
|
||||
r.y = fract(512.0 * j);
|
||||
return r - 0.5;
|
||||
}
|
||||
float tex_noise_f(vec3 p) {
|
||||
const float F3 = 0.3333333;
|
||||
const float G3 = 0.1666667;
|
||||
vec3 s = floor(p + dot(p, vec3(F3)));
|
||||
vec3 x = p - s + dot(s, vec3(G3));
|
||||
vec3 e = step(vec3(0.0), x - x.yzx);
|
||||
vec3 i1 = e*(1.0 - e.zxy);
|
||||
vec3 i2 = 1.0 - e.zxy*(1.0 - e);
|
||||
vec3 x1 = x - i1 + G3;
|
||||
vec3 x2 = x - i2 + 2.0*G3;
|
||||
vec3 x3 = x - 1.0 + 3.0*G3;
|
||||
vec4 w, d;
|
||||
w.x = dot(x, x);
|
||||
w.y = dot(x1, x1);
|
||||
w.z = dot(x2, x2);
|
||||
w.w = dot(x3, x3);
|
||||
w = max(0.6 - w, 0.0);
|
||||
d.x = dot(random3(s), x);
|
||||
d.y = dot(random3(s + i1), x1);
|
||||
d.z = dot(random3(s + i2), x2);
|
||||
d.w = dot(random3(s + 1.0), x3);
|
||||
w *= w;
|
||||
w *= w;
|
||||
d *= w;
|
||||
return clamp(dot(d, vec4(52.0)), 0.0, 1.0);
|
||||
}
|
||||
float tex_noise(vec3 p) {
|
||||
return 0.5333333 * tex_noise_f(p)
|
||||
+ 0.2666667 * tex_noise_f(2.0 * p)
|
||||
+ 0.1333333 * tex_noise_f(4.0 * p)
|
||||
+ 0.0666667 * tex_noise_f(8.0 * p);
|
||||
}
|
||||
"""
|
||||
|
||||
def parse(nodes, vert, frag, geom, tesc, tese, parse_surface=True):
|
||||
output_node = node_by_type(nodes, 'OUTPUT_MATERIAL')
|
||||
if output_node != None:
|
||||
|
@ -151,8 +36,6 @@ def parse_output(node, _vert, _frag, _geom, _tesc, _tese, parse_surface):
|
|||
global geom
|
||||
global tesc
|
||||
global tese
|
||||
global str_tex_checker
|
||||
global str_tex_voronoi
|
||||
vert = _vert
|
||||
frag = _frag
|
||||
geom = _geom
|
||||
|
@ -176,7 +59,7 @@ def parse_output(node, _vert, _frag, _geom, _tesc, _tese, parse_surface):
|
|||
# parse_volume_input(node.inputs[1])
|
||||
|
||||
# Displacement
|
||||
if armutils.tess_enabled(state.target) and node.inputs[2].is_linked:
|
||||
if armutils.tess_enabled(state.target) and node.inputs[2].is_linked and tese != None:
|
||||
parsed = []
|
||||
parents = []
|
||||
normal_written = False
|
||||
|
@ -231,8 +114,10 @@ def parse_shader_input(inp):
|
|||
|
||||
def write_normal(inp):
|
||||
if inp.is_linked:
|
||||
curshader.write('n = {0};'.format(parse_vector_input(inp)))
|
||||
normal_written = True
|
||||
normal_res = parse_vector_input(inp)
|
||||
if normal_res != None:
|
||||
curshader.write('n = {0};'.format(normal_res))
|
||||
normal_written = True
|
||||
|
||||
def parse_shader(node, socket):
|
||||
out_basecol = 'vec3(0.8)'
|
||||
|
@ -242,7 +127,11 @@ def parse_shader(node, socket):
|
|||
|
||||
if node.type == 'GROUP':
|
||||
if node.node_tree.name.startswith('Armory PBR'):
|
||||
pass
|
||||
out_basecol = parse_vector_input(node.inputs[0])
|
||||
out_roughness = parse_value_input(node.inputs[3])
|
||||
out_metallic = parse_value_input(node.inputs[5])
|
||||
out_occlusion = parse_value_input(node.inputs[1])
|
||||
parse_normal_map_color_input(node.inputs[6])
|
||||
else:
|
||||
return parse_group(node, socket)
|
||||
|
||||
|
@ -361,12 +250,18 @@ def write_result(l):
|
|||
parsed.append(res_var)
|
||||
if st == 'RGB' or st == 'RGBA':
|
||||
res = parse_rgb(l.from_node, l.from_socket)
|
||||
if res == None:
|
||||
return None
|
||||
curshader.write('vec3 {0} = {1};'.format(res_var, res))
|
||||
elif st == 'VECTOR':
|
||||
res = parse_vector(l.from_node, l.from_socket)
|
||||
if res == None:
|
||||
return None
|
||||
curshader.write('vec3 {0} = {1};'.format(res_var, res))
|
||||
elif st == 'VALUE':
|
||||
res = parse_value(l.from_node, l.from_socket)
|
||||
if res == None:
|
||||
return None
|
||||
curshader.write('float {0} = {1};'.format(res_var, res))
|
||||
return res_var
|
||||
|
||||
|
@ -398,8 +293,10 @@ def parse_rgb(node, socket):
|
|||
return parse_input_group(node, socket)
|
||||
|
||||
elif node.type == 'ATTRIBUTE':
|
||||
# Vcols
|
||||
pass
|
||||
# Vcols only for now
|
||||
# node.attribute_name
|
||||
mat_state.data.add_elem('col', 3)
|
||||
return 'color'
|
||||
|
||||
elif node.type == 'RGB':
|
||||
return tovec3(socket.default_value)
|
||||
|
@ -409,7 +306,7 @@ def parse_rgb(node, socket):
|
|||
return tovec3([0.0, 0.0, 0.0])
|
||||
|
||||
elif node.type == 'TEX_CHECKER':
|
||||
curshader.add_function(str_tex_checker)
|
||||
curshader.add_function(functions.str_tex_checker)
|
||||
if node.inputs[0].is_linked:
|
||||
co = parse_vector_input(node.inputs[0])
|
||||
else:
|
||||
|
@ -462,7 +359,7 @@ def parse_rgb(node, socket):
|
|||
|
||||
elif node.type == 'TEX_MUSGRAVE':
|
||||
# Fall back to noise
|
||||
curshader.add_function(str_tex_noise)
|
||||
curshader.add_function(functions.str_tex_noise)
|
||||
if node.inputs[0].is_linked:
|
||||
co = parse_vector_input(node.inputs[0])
|
||||
else:
|
||||
|
@ -473,7 +370,7 @@ def parse_rgb(node, socket):
|
|||
return 'vec3(tex_noise_f({0} * {1}))'.format(co, scale)
|
||||
|
||||
elif node.type == 'TEX_NOISE':
|
||||
curshader.add_function(str_tex_noise)
|
||||
curshader.add_function(functions.str_tex_noise)
|
||||
if node.inputs[0].is_linked:
|
||||
co = parse_vector_input(node.inputs[0])
|
||||
else:
|
||||
|
@ -493,7 +390,7 @@ def parse_rgb(node, socket):
|
|||
return tovec3([0.0, 0.0, 0.0])
|
||||
|
||||
elif node.type == 'TEX_VORONOI':
|
||||
curshader.add_function(str_tex_voronoi)
|
||||
curshader.add_function(functions.str_tex_voronoi)
|
||||
assets.add(armutils.get_sdk_path() + '/armory/Assets/' + 'noise64.png')
|
||||
assets.add_embedded_data('noise64.png')
|
||||
curshader.add_uniform('sampler2D snoise', link='_noise64')
|
||||
|
@ -731,7 +628,7 @@ def parse_vector(node, socket):
|
|||
# height = parse_value_input(node.inputs[2])
|
||||
# nor = parse_vector_input(node.inputs[3])
|
||||
# Sample height around the normal and compute normal
|
||||
return 'wnormal'
|
||||
return 'n'
|
||||
|
||||
elif node.type == 'MAPPING':
|
||||
# vector = parse_vector_input(node.inputs[0])
|
||||
|
@ -748,8 +645,8 @@ def parse_vector(node, socket):
|
|||
#space = node.space
|
||||
#map = node.uv_map
|
||||
# strength = parse_value_input(node.inputs[0])
|
||||
# color = parse_vector_input(node.inputs[1])
|
||||
return 'vec3(0.0)'
|
||||
parse_normal_map_color_input(node.inputs[1]) # Color
|
||||
return None
|
||||
|
||||
elif node.type == 'CURVE_VEC':
|
||||
# fac = parse_value_input(node.inputs[0])
|
||||
|
@ -786,6 +683,15 @@ def parse_vector(node, socket):
|
|||
elif op == 'NORMALIZE':
|
||||
return 'normalize({0})'.format(vec1)
|
||||
|
||||
def parse_normal_map_color_input(inp):
|
||||
if inp.is_linked == False:
|
||||
return
|
||||
frag.write_pre = True
|
||||
frag.write('vec3 n = ({0}) * 2.0 - 1.0;'.format(parse_vector_input(inp)))
|
||||
frag.write('n = normalize(TBN * normalize(n));')
|
||||
mat_state.data.add_elem('tan', 3)
|
||||
frag.write_pre = False
|
||||
|
||||
def parse_value_input(inp):
|
||||
if inp.is_linked:
|
||||
l = inp.links[0]
|
||||
|
@ -805,7 +711,14 @@ def parse_value_input(inp):
|
|||
def parse_value(node, socket):
|
||||
|
||||
if node.type == 'GROUP':
|
||||
return parse_group(node, socket)
|
||||
if node.node_tree.name.startswith('Armory PBR'):
|
||||
# Displacement
|
||||
if socket == node.outputs[1]:
|
||||
return parse_value_input(node.inputs[10])
|
||||
else:
|
||||
return None
|
||||
else:
|
||||
return parse_group(node, socket)
|
||||
|
||||
elif node.type == 'GROUP_INPUT':
|
||||
return parse_input_group(node, socket)
|
||||
|
@ -907,7 +820,7 @@ def parse_value(node, socket):
|
|||
|
||||
elif node.type == 'TEX_CHECKER':
|
||||
# TODO: do not recompute when color socket is also connected
|
||||
curshader.add_function(str_tex_checker)
|
||||
curshader.add_function(functions.str_tex_checker)
|
||||
if node.inputs[0].is_linked:
|
||||
co = parse_vector_input(node.inputs[0])
|
||||
else:
|
||||
|
@ -928,7 +841,7 @@ def parse_value(node, socket):
|
|||
|
||||
elif node.type == 'TEX_MUSGRAVE':
|
||||
# Fall back to noise
|
||||
curshader.add_function(str_tex_noise)
|
||||
curshader.add_function(functions.str_tex_noise)
|
||||
if node.inputs[0].is_linked:
|
||||
co = parse_vector_input(node.inputs[0])
|
||||
else:
|
||||
|
@ -939,7 +852,7 @@ def parse_value(node, socket):
|
|||
return 'tex_noise_f({0} * {1})'.format(co, scale)
|
||||
|
||||
elif node.type == 'TEX_NOISE':
|
||||
curshader.add_function(str_tex_noise)
|
||||
curshader.add_function(functions.str_tex_noise)
|
||||
if node.inputs[0].is_linked:
|
||||
co = parse_vector_input(node.inputs[0])
|
||||
else:
|
||||
|
@ -953,7 +866,7 @@ def parse_value(node, socket):
|
|||
return '0.0'
|
||||
|
||||
elif node.type == 'TEX_VORONOI':
|
||||
curshader.add_function(str_tex_voronoi)
|
||||
curshader.add_function(functions.str_tex_voronoi)
|
||||
assets.add(armutils.get_sdk_path() + '/armory/Assets/' + 'noise64.png')
|
||||
assets.add_embedded_data('noise64.png')
|
||||
curshader.add_uniform('sampler2D snoise', link='_noise64')
|
||||
|
|
|
@ -15,7 +15,15 @@ def mesh(context_id):
|
|||
# Displacement linked
|
||||
tess_enabled = armutils.tess_enabled(state.target)
|
||||
output_node = make_cycles.node_by_type(mat_state.nodes, 'OUTPUT_MATERIAL')
|
||||
if tess_enabled and output_node != None and output_node.inputs[2].is_linked:
|
||||
if output_node == None:
|
||||
return None
|
||||
|
||||
if output_node.inputs[2].is_linked:
|
||||
l = output_node.inputs[2].links[0]
|
||||
if l.from_node.type == 'GROUP' and l.from_node.node_tree.name.startswith('Armory PBR') and l.from_node.inputs[10].is_linked == False:
|
||||
tess_enabled = False
|
||||
|
||||
if tess_enabled and output_node.inputs[2].is_linked:
|
||||
tesc = con_mesh.make_tesc()
|
||||
tese = con_mesh.make_tese()
|
||||
tesc.ins = vert.outs
|
||||
|
@ -23,11 +31,8 @@ def mesh(context_id):
|
|||
frag.ins = tese.outs
|
||||
|
||||
vert.add_out('vec3 wposition')
|
||||
vert.add_out('vec3 wnormal')
|
||||
vert.add_uniform('mat4 W', '_worldMatrix')
|
||||
vert.add_uniform('mat4 N', '_normalMatrix')
|
||||
vert.write('vec4 spos = vec4(pos, 1.0);')
|
||||
vert.write('wnormal = normalize(mat3(N) * nor);')
|
||||
vert.write('wposition = vec4(W * spos).xyz;')
|
||||
|
||||
const = {}
|
||||
|
@ -54,10 +59,9 @@ def mesh(context_id):
|
|||
tese.write('vec3 n2 = gl_TessCoord.z * tc_wnormal[2];')
|
||||
tese.write('wnormal = normalize(n0 + n1 + n2);')
|
||||
|
||||
# No displacement
|
||||
# No displacement
|
||||
else:
|
||||
frag.ins = vert.outs
|
||||
vert.add_out('vec3 wnormal')
|
||||
vert.add_out('vec3 wposition')
|
||||
vert.add_out('vec3 eyeDir')
|
||||
vert.add_uniform('mat4 W', '_worldMatrix')
|
||||
|
@ -65,14 +69,12 @@ def mesh(context_id):
|
|||
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrix')
|
||||
vert.add_uniform('vec3 eye', '_cameraPosition')
|
||||
vert.write('vec4 spos = vec4(pos, 1.0);')
|
||||
vert.write('wnormal = normalize(mat3(N) * nor);')
|
||||
vert.write('wposition = vec4(W * spos).xyz;')
|
||||
vert.write('eyeDir = eye - wposition;')
|
||||
vert.write('gl_Position = WVP * spos;')
|
||||
|
||||
frag.add_include('../../Shaders/compiled.glsl')
|
||||
frag.add_include('../../Shaders/std/gbuffer.glsl')
|
||||
frag.write('vec3 n = normalize(wnormal);')
|
||||
frag.write('vec3 v = normalize(eyeDir);')
|
||||
# frag.write('float dotNV = dot(n, v);')
|
||||
frag.write('float dotNV = max(dot(n, v), 0.0);')
|
||||
|
@ -89,17 +91,62 @@ def mesh(context_id):
|
|||
vert.write('texCoord = tex;')
|
||||
|
||||
if tese != None:
|
||||
if 'texCoord' in frag.main:
|
||||
if 'texCoord' in frag.main or 'texCoord' in frag.main_pre:
|
||||
tese.add_out('vec2 texCoord')
|
||||
tese.write_pre('vec2 tc0 = gl_TessCoord.x * tc_texCoord[0];')
|
||||
tese.write_pre('vec2 tc1 = gl_TessCoord.y * tc_texCoord[1];')
|
||||
tese.write_pre('vec2 tc2 = gl_TessCoord.z * tc_texCoord[2];')
|
||||
tese.write_pre('texCoord = tc0 + tc1 + tc2;')
|
||||
elif 'texCoord' in tese.main:
|
||||
tese.write_pre('vec2 tc0 = gl_TessCoord.x * tc_texCoord[0];')
|
||||
tese.write_pre('vec2 tc1 = gl_TessCoord.y * tc_texCoord[1];')
|
||||
tese.write_pre('vec2 tc2 = gl_TessCoord.z * tc_texCoord[2];')
|
||||
tese.write_pre('vec2 texCoord = tc0 + tc1 + tc2;')
|
||||
tese.write_pre = True
|
||||
tese.write('vec2 tc0 = gl_TessCoord.x * tc_texCoord[0];')
|
||||
tese.write('vec2 tc1 = gl_TessCoord.y * tc_texCoord[1];')
|
||||
tese.write('vec2 tc2 = gl_TessCoord.z * tc_texCoord[2];')
|
||||
tese.write('texCoord = tc0 + tc1 + tc2;')
|
||||
tese.write_pre = False
|
||||
elif 'texCoord' in tese.main or 'texCoord' in tese.main_pre:
|
||||
tese.write_pre = True
|
||||
tese.write('vec2 tc0 = gl_TessCoord.x * tc_texCoord[0];')
|
||||
tese.write('vec2 tc1 = gl_TessCoord.y * tc_texCoord[1];')
|
||||
tese.write('vec2 tc2 = gl_TessCoord.z * tc_texCoord[2];')
|
||||
tese.write('vec2 texCoord = tc0 + tc1 + tc2;')
|
||||
tese.write_pre = False
|
||||
|
||||
if mat_state.data.is_elem('col'):
|
||||
vert.add_out('vec3 color')
|
||||
vert.write('color = col;')
|
||||
|
||||
if tese != None:
|
||||
tese.add_out('vec3 color')
|
||||
tese.write('vec3 col0 = gl_TessCoord.x * tc_color[0];')
|
||||
tese.write('vec3 col1 = gl_TessCoord.y * tc_color[1];')
|
||||
tese.write('vec3 col2 = gl_TessCoord.z * tc_color[2];')
|
||||
tese.write('color = col0 + col1 + col2;')
|
||||
|
||||
if mat_state.data.is_elem('tan'):
|
||||
|
||||
if tese != None:
|
||||
vert.add_out('vec3 wnormal')
|
||||
vert.add_out('vec3 wtangent')
|
||||
vert.add_uniform('mat4 N', '_normalMatrix')
|
||||
vert.write('wnormal = normalize(mat3(N) * nor);')
|
||||
vert.write('wtangent = normalize(mat3(N) * tan);')
|
||||
tese.add_out('mat3 TBN')
|
||||
tese.write('vec3 tan0 = gl_TessCoord.x * tc_wtangent[0];')
|
||||
tese.write('vec3 tan1 = gl_TessCoord.y * tc_wtangent[1];')
|
||||
tese.write('vec3 tan2 = gl_TessCoord.z * tc_wtangent[2];')
|
||||
tese.write('vec3 wtangent = normalize(tan0 + tan1 + tan2);')
|
||||
tese.write('vec3 wbitangent = normalize(cross(wnormal, wtangent));')
|
||||
tese.write('TBN = mat3(wtangent, wbitangent, wnormal);')
|
||||
else:
|
||||
vert.add_out('mat3 TBN')
|
||||
vert.add_uniform('mat4 N', '_normalMatrix')
|
||||
vert.write('vec3 wnormal = normalize(mat3(N) * nor);')
|
||||
vert.write('vec3 tangent = normalize(mat3(N) * tan);')
|
||||
vert.write('vec3 bitangent = normalize(cross(wnormal, tangent));')
|
||||
vert.write('TBN = mat3(tangent, bitangent, wnormal);')
|
||||
else:
|
||||
vert.add_uniform('mat4 N', '_normalMatrix')
|
||||
vert.add_out('vec3 wnormal')
|
||||
vert.write('wnormal = normalize(mat3(N) * nor);')
|
||||
frag.write_pre = True
|
||||
frag.write('vec3 n = normalize(wnormal);')
|
||||
frag.write_pre = False
|
||||
|
||||
if tese != None:
|
||||
tese.add_uniform('mat4 VP', '_viewProjectionMatrix')
|
||||
|
@ -129,7 +176,16 @@ def shadows(context_id):
|
|||
# Displacement linked
|
||||
tess_enabled = armutils.tess_enabled(state.target)
|
||||
tess_enabled_shadow = mat_state.material.height_tess_shadows
|
||||
|
||||
output_node = make_cycles.node_by_type(mat_state.nodes, 'OUTPUT_MATERIAL')
|
||||
if output_node == None:
|
||||
return None
|
||||
|
||||
if output_node.inputs[2].is_linked:
|
||||
l = output_node.inputs[2].links[0]
|
||||
if l.from_node.type == 'GROUP' and l.from_node.node_tree.name.startswith('Armory PBR') and l.from_node.inputs[10].is_linked == False:
|
||||
tess_enabled = False
|
||||
|
||||
if tess_enabled and tess_enabled_shadow and output_node != None and output_node.inputs[2].is_linked:
|
||||
tesc = con_shadowmap.make_tesc()
|
||||
tese = con_shadowmap.make_tese()
|
||||
|
@ -172,10 +228,12 @@ def shadows(context_id):
|
|||
if tese != None and 'texCoord' in tese.main:
|
||||
vert.add_out('vec2 texCoord')
|
||||
vert.write('texCoord = tex;')
|
||||
tese.write_pre('vec2 tc0 = gl_TessCoord.x * tc_texCoord[0];')
|
||||
tese.write_pre('vec2 tc1 = gl_TessCoord.y * tc_texCoord[1];')
|
||||
tese.write_pre('vec2 tc2 = gl_TessCoord.z * tc_texCoord[2];')
|
||||
tese.write_pre('vec2 texCoord = tc0 + tc1 + tc2;')
|
||||
tese.write_pre = True
|
||||
tese.write('vec2 tc0 = gl_TessCoord.x * tc_texCoord[0];')
|
||||
tese.write('vec2 tc1 = gl_TessCoord.y * tc_texCoord[1];')
|
||||
tese.write('vec2 tc2 = gl_TessCoord.z * tc_texCoord[2];')
|
||||
tese.write('vec2 texCoord = tc0 + tc1 + tc2;')
|
||||
tese.write_pre = False
|
||||
|
||||
tese.add_uniform('mat4 LVP', '_lampViewProjectionMatrix')
|
||||
# tese.add_uniform('mat4 LWVP', '_lampWorldViewProjectionMatrix')
|
||||
|
|
|
@ -1,13 +1,25 @@
|
|||
import bpy
|
||||
import material.mat_state as state
|
||||
import material.make_cycles as make_cycles
|
||||
import armutils
|
||||
import assets
|
||||
|
||||
def mesh(context_id):
|
||||
wrd = bpy.data.worlds['Arm']
|
||||
if '_PCSS' in wrd.world_defs:
|
||||
is_pcss = True
|
||||
else:
|
||||
is_pcss = False
|
||||
|
||||
|
||||
con_mesh = state.data.add_context({ 'name': context_id, 'depth_write': True, 'compare_mode': 'less', 'cull_mode': 'clockwise' })
|
||||
|
||||
vert = con_mesh.make_vert()
|
||||
frag = con_mesh.make_frag()
|
||||
geom = None
|
||||
tesc = None
|
||||
tese = None
|
||||
|
||||
frag.ins = vert.outs
|
||||
|
||||
vert.add_out('vec3 wnormal')
|
||||
|
@ -49,10 +61,12 @@ def mesh(context_id):
|
|||
vert.add_out('vec4 lampPos')
|
||||
vert.add_uniform('mat4 LWVP', '_lampWorldViewProjectionMatrix')
|
||||
vert.write('lampPos = LWVP * spos;')
|
||||
frag.add_include('../../Shaders/std/shadows.glsl')
|
||||
# frag.add_include('../../Shaders/std/shadows_pcss.glsl')
|
||||
if is_pcss:
|
||||
frag.add_include('../../Shaders/std/shadows_pcss.glsl')
|
||||
frag.add_uniform('sampler2D snoise', link='_noise64', included=True)
|
||||
else:
|
||||
frag.add_include('../../Shaders/std/shadows.glsl')
|
||||
frag.add_uniform('sampler2D shadowMap', included=True)
|
||||
# frag.add_uniform('sampler2D snoise', link='_noise64', included=True)
|
||||
frag.add_uniform('float lampSizeUV', link='_lampSizeUV', included=True)
|
||||
frag.add_uniform('bool receiveShadow')
|
||||
frag.add_uniform('float shadowsBias', '_lampShadowsBias')
|
||||
|
@ -61,8 +75,10 @@ def mesh(context_id):
|
|||
frag.tab += 1
|
||||
frag.write('vec3 lpos = lampPos.xyz / lampPos.w;')
|
||||
frag.write('lpos.xy = lpos.xy * 0.5 + 0.5;')
|
||||
frag.write('visibility = PCF(lpos.xy, lpos.z - shadowsBias);')
|
||||
# frag.write('visibility = PCSS(lpos.xy, lpos.z - shadowsBias);')
|
||||
if is_pcss:
|
||||
frag.write('visibility = PCSS(lpos.xy, lpos.z - shadowsBias);')
|
||||
else:
|
||||
frag.write('visibility = PCF(lpos.xy, lpos.z - shadowsBias);')
|
||||
frag.tab -= 1
|
||||
frag.write('}')
|
||||
|
||||
|
@ -85,7 +101,7 @@ def mesh(context_id):
|
|||
frag.write('float metallic;')
|
||||
frag.write('float occlusion;')
|
||||
|
||||
make_cycles.parse(state.nodes, vert, frag)
|
||||
make_cycles.parse(state.nodes, vert, frag, geom, tesc, tese)
|
||||
|
||||
frag.write('vec3 albedo = surfaceAlbedo(basecol, metallic);')
|
||||
frag.write('vec3 f0 = surfaceF0(basecol, metallic);')
|
||||
|
@ -107,10 +123,14 @@ def shadows(context_id):
|
|||
con_shadowmap = state.data.add_context({ 'name': context_id, 'depth_write': True, 'compare_mode': 'less', 'cull_mode': 'clockwise' })
|
||||
|
||||
vert = con_shadowmap.make_vert()
|
||||
frag = con_shadowmap.make_frag()
|
||||
geom = None
|
||||
tesc = None
|
||||
tese = None
|
||||
|
||||
vert.add_uniform('mat4 LWVP', '_lampWorldViewProjectionMatrix')
|
||||
vert.write('gl_Position = LWVP * vec4(pos, 1.0);')
|
||||
|
||||
frag = con_shadowmap.make_frag()
|
||||
frag.write('fragColor = vec4(0.0);')
|
||||
|
||||
return con_shadowmap
|
||||
|
|
|
@ -11,6 +11,7 @@ class Shader:
|
|||
self.functions = {}
|
||||
self.main = ''
|
||||
self.main_pre = ''
|
||||
self.write_pre = False
|
||||
self.tab = 1
|
||||
|
||||
def add_include(self, s):
|
||||
|
@ -40,11 +41,11 @@ class Shader:
|
|||
return
|
||||
self.functions[fname] = s
|
||||
|
||||
def write_pre(self, s):
|
||||
self.main_pre += '\t' * 1 + s + '\n'
|
||||
|
||||
def write(self, s):
|
||||
self.main += '\t' * self.tab + s + '\n'
|
||||
if self.write_pre:
|
||||
self.main_pre += '\t' * 1 + s + '\n'
|
||||
else:
|
||||
self.main += '\t' * self.tab + s + '\n'
|
||||
|
||||
def write_tesc_levels(self):
|
||||
self.write('if (gl_InvocationID == 0) {')
|
||||
|
|
|
@ -23,6 +23,12 @@ class ShaderData:
|
|||
return True
|
||||
return False
|
||||
|
||||
def get_elem(self, name):
|
||||
for elem in self.sd['vertex_structure']:
|
||||
if elem['name'] == name:
|
||||
return elem
|
||||
return None
|
||||
|
||||
def add_context(self, props):
|
||||
con = ShaderContext(self.material, self.sd, props)
|
||||
if con not in self.sd['contexts']:
|
||||
|
@ -30,6 +36,15 @@ class ShaderData:
|
|||
return con
|
||||
|
||||
def get(self):
|
||||
# TODO: temporary, Sort vertex data
|
||||
for sd in self.data['shader_datas']:
|
||||
vs = []
|
||||
ar = ['pos', 'nor', 'tex', 'col', 'tan', 'bone', 'weight', 'off']
|
||||
for ename in ar:
|
||||
elem = self.get_elem(ename)
|
||||
if elem != None:
|
||||
vs.append(elem)
|
||||
sd['vertex_structure'] = vs
|
||||
return self.data
|
||||
|
||||
class ShaderContext:
|
||||
|
|
|
@ -330,6 +330,8 @@ def init_properties():
|
|||
bpy.types.Material.override_shader_context = bpy.props.BoolProperty(name="Override Context", default=False)
|
||||
bpy.types.Material.override_shader_context_name = bpy.props.StringProperty(name="Name", default='')
|
||||
bpy.types.Material.stencil_mask = bpy.props.IntProperty(name="Stencil Mask", default=0)
|
||||
bpy.types.Material.export_uvs = bpy.props.BoolProperty(name="Export UVs", default=False)
|
||||
bpy.types.Material.export_vcols = bpy.props.BoolProperty(name="Export VCols", default=False)
|
||||
bpy.types.Material.export_tangents = bpy.props.BoolProperty(name="Export Tangents", default=False)
|
||||
bpy.types.Material.skip_context = bpy.props.StringProperty(name="Skip Context", default='')
|
||||
bpy.types.Material.overlay = bpy.props.BoolProperty(name="X-Ray", default=False)
|
||||
|
|
Loading…
Reference in a new issue