armory/blender/material/make_forward.py
2016-12-13 01:09:17 +01:00

478 lines
12 KiB
Python

import material.state as state
def node_by_type(ntype):
for n in state.nodes:
if n.type == ntype:
return n
def mesh(context_id):
# global parsed
global frag
global vert
# global first_basecol # Do not multiply vals first time
# global first_roughness
# global first_metallic
# parsed = [] # Compute node only onces
# first_basecol = True
# first_roughness = True
# first_metallic = True
con_mesh = state.data.add_context({ 'name': context_id, 'depth_write': True, 'compare_mode': 'less', 'cull_mode': 'clockwise' })
vert = con_mesh.vert()
frag = con_mesh.frag()
vert.add_out('vec3 wnormal')
vert.add_out('vec3 wposition')
vert.add_out('vec3 eyeDir')
vert.add_uniform('mat4 W', '_worldMatrix')
vert.add_uniform('mat4 N', '_normalMatrix')
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/brdf.glsl')
frag.add_include('../../Shaders/std/math.glsl')
frag.add_include('../../Shaders/std/shirr.glsl')
frag.add_uniform('vec3 lightColor', '_lampColor')
frag.add_uniform('vec3 lightDir', '_lampDirection')
frag.add_uniform('vec3 lightPos', '_lampPosition')
frag.add_uniform('int lightType', '_lampType')
frag.add_uniform('float shirr[27]', link='_envmapIrradiance', included=True)
frag.add_uniform('float envmapStrength', link='_envmapStrength')
frag.add_uniform('sampler2D senvmapRadiance', link='_envmapRadiance')
frag.add_uniform('sampler2D senvmapBrdf', link='_envmapBrdf')
frag.add_uniform('int envmapNumMipmaps', link='_envmapNumMipmaps')
frag.write('vec3 n = normalize(wnormal);')
frag.write('vec3 l = lightType == 0 ? lightDir : normalize(lightPos - wposition);')
frag.write('vec3 v = normalize(eyeDir);')
frag.write('vec3 h = normalize(v + l);')
frag.write('float dotNL = dot(n, l);')
frag.write('float dotNV = dot(n, v);')
frag.write('float dotNH = dot(n, h);')
frag.write('float dotVH = dot(v, h);')
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_uniform('sampler2D shadowMap', included=True)
frag.add_uniform('bool receiveShadow')
frag.add_uniform('float shadowsBias', '_lampShadowsBias')
frag.write('float visibility = 1.0;')
frag.write('if (receiveShadow && lampPos.w > 0.0) {')
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.tab -= 1
frag.write('}')
frag.add_uniform('float spotlightCutoff', '_spotlampCutoff')
frag.add_uniform('float spotlightExponent', '_spotlampExponent')
frag.write('if (lightType == 2) {')
frag.tab += 1
frag.write('float spotEffect = dot(lightDir, l);')
frag.write('if (spotEffect < spotlightCutoff) {')
frag.tab += 1
frag.write('spotEffect = smoothstep(spotlightCutoff - spotlightExponent, spotlightCutoff, spotEffect);')
frag.write('visibility *= spotEffect;')
frag.tab -= 1
frag.write('}')
frag.tab -= 1
frag.write('}')
frag.write('vec3 basecol;')
frag.write('float roughness;')
frag.write('float metallic;')
# frag.write('float occlussion;')
output_node = node_by_type('OUTPUT_MATERIAL')
if output_node != None:
parse_output(output_node)
frag.write('vec3 albedo = surfaceAlbedo(basecol, metallic);')
frag.write('vec3 f0 = surfaceF0(basecol, metallic);')
frag.write('vec3 direct = lambertDiffuseBRDF(albedo, dotNL);')
frag.write('direct += specularBRDF(f0, roughness, dotNL, dotNH, dotNV, dotVH);')
frag.write('vec3 indirect = (shIrradiance(n, 2.2) / PI) * albedo;')
frag.write('vec3 reflectionWorld = reflect(-v, n);')
frag.write('float lod = getMipFromRoughness(roughness, envmapNumMipmaps);')
frag.write('vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;')
frag.write('vec2 envBRDF = texture(senvmapBrdf, vec2(roughness, 1.0 - dotNV)).xy;')
frag.write('indirect += prefilteredColor * (f0 * envBRDF.x + envBRDF.y);')
frag.write('fragColor = vec4(direct * lightColor * visibility + indirect * envmapStrength, 1.0);')
return con_mesh
def parse_output(node):
out_basecol, out_roughness, out_metallic = parse_shader_input(node.inputs[0])
frag.write('basecol = {0};'.format(out_basecol))
frag.write('roughness = {0};'.format(out_roughness))
frag.write('metallic = {0};'.format(out_metallic))
def parse_shader_input(inp):
if inp.is_linked:
return parse_shader(inp.links[0].from_node)
else:
out_basecol = 'vec3(0.0)'
out_roughness = '0.0'
out_metallic = '0.0'
return out_basecol, out_roughness, out_metallic
def parse_shader(node):
if node.type == 'REROUTE':
return parse_shader(node.inputs[0].links[0].from_node)
elif node.type == 'MIX_SHADER':
fac = parse_float_input(node.inputs[0])
bc1, rough1, met1 = parse_shader_input(node.inputs[1])
bc2, rough2, met2 = parse_shader_input(node.inputs[2])
out_basecol = '({0} * (1.0 - {2}) + {1} * {2})'.format(bc1, bc2, fac)
out_roughness = '({0} * (1.0 - {2}) + {1} * {2})'.format(rough1, rough2, fac)
out_metallic = '({0} * (1.0 - {2}) + {1} * {2})'.format(met1, met2, fac)
elif node.type == 'ADD_SHADER':
pass
elif node.type == 'BSDF_DIFFUSE':
out_basecol = parse_color_input(node.inputs[0])
out_roughness = parse_float_input(node.inputs[1])
out_metallic = '0.0'
elif node.type == 'BSDF_GLOSSY':
out_basecol = parse_color_input(node.inputs[0])
out_roughness = parse_float_input(node.inputs[1])
out_metallic = '1.0'
elif node.type == 'AMBIENT_OCCLUSION':
pass
elif node.type == 'BSDF_ANISOTROPIC':
pass
elif node.type == 'EMISSION':
pass
elif node.type == 'BSDF_GLASS':
pass
elif node.type == 'BSDF_HAIR':
pass
elif node.type == 'HOLDOUT':
pass
elif node.type == 'BSDF_REFRACTION':
pass
elif node.type == 'SUBSURFACE_SCATTERING':
pass
elif node.type == 'BSDF_TOON':
pass
elif node.type == 'BSDF_TRANSLUCENT':
pass
elif node.type == 'BSDF_TRANSPARENT':
pass
elif node.type == 'BSDF_VELVET':
pass
elif node.type == 'VOLUME_ABSORPTION':
pass
elif node.type == 'VOLUME_SCATTER':
pass
elif node.type == 'GROUP' and node.node_tree.name.startswith('Armory PBR'):
pass
else:
out_basecol = 'vec3(0.0)'
out_roughness = '0.0'
out_metallic = '0.0'
return out_basecol, out_roughness, out_metallic
def parse_color_input(inp):
if inp.is_linked:
parse_color(inp.links[0].from_node)
else:
return vec3(inp.default_value)
def parse_color(node):
if node.type == 'REROUTE':
return parse_color(node.inputs[0].links[0].from_node)
elif node.type == 'ATTRIBUTE':
pass
elif node.type == 'RGB':
pass
elif node.type == 'TEX_BRICK':
pass
elif node.type == 'TEX_CHECKER':
pass
elif node.type == 'TEX_ENVIRONMENT':
pass
elif node.type == 'TEX_GRADIENT':
pass
elif node.type == 'TEX_IMAGE':
pass
elif node.type == 'TEX_MAGIC':
pass
elif node.type == 'TEX_MUSGRAVE':
pass
elif node.type == 'TEX_NOISE':
pass
elif node.type == 'TEX_POINTDENSITY':
pass
elif node.type == 'TEX_SKY':
pass
elif node.type == 'TEX_VORONOI':
pass
elif node.type == 'TEX_WAVE':
pass
elif node.type == 'BRIGHTCONTRAST':
pass
elif node.type == 'GAMMA':
pass
elif node.type == 'HUE_SAT':
pass
elif node.type == 'INVERT':
pass
elif node.type == 'MIX_RGB':
pass
elif node.type == 'CURVE_RGB':
pass
elif node.type == 'BLACKBODY':
pass
elif node.type == 'VALTORGB':
pass
elif node.type == 'COMBHSV':
pass
elif node.type == 'COMBRGB':
pass
elif node.type == 'WAVELENGTH':
pass
def parse_vector_input(inp):
if inp.is_linked:
return parse_vector(inp.links[0].from_node)
else:
return vec3(inp.default_value)
def parse_vector(node):
if node.type == 'REROUTE':
return parse_vector(node.inputs[0].links[0].from_node)
elif node.type == 'ATTRIBUTE':
pass
elif node.type == 'CAMERA':
pass
elif node.type == 'NEW_GEOMETRY':
pass
elif node.type == 'HAIR_INFO':
pass
elif node.type == 'OBJECT_INFO':
pass
elif node.type == 'PARTICLE_INFO':
pass
elif node.type == 'TANGENT':
pass
elif node.type == 'TEX_COORD':
pass
elif node.type == 'UVMAP':
pass
elif node.type == 'BUMP':
pass
elif node.type == 'MAPPING':
pass
elif node.type == 'NORMAL':
pass
elif node.type == 'NORMAL_MAP':
pass
elif node.type == 'CURVE_VEC':
pass
elif node.type == 'VECT_TRANSFORM':
pass
elif node.type == 'COMBXYZ':
pass
elif node.type == 'VECT_MATH':
pass
def parse_float_input(inp):
if inp.is_linked:
return parse_float(inp.links[0].from_node)
else:
return vec1(inp.default_value)
def parse_float(node):
if node.type == 'REROUTE':
return parse_float(node.inputs[0].links[0].from_node)
if node.type == 'ATTRIBUTE':
pass
elif node.type == 'CAMERA':
pass
elif node.type == 'FRESNEL':
pass
elif node.type == 'NEW_GEOMETRY':
pass
elif node.type == 'HAIR_INFO':
pass
elif node.type == 'LAYER_WEIGHT':
pass
elif node.type == 'LIGHT_PATH':
pass
elif node.type == 'OBJECT_INFO':
pass
elif node.type == 'PARTICLE_INFO':
pass
elif node.type == 'VALUE':
return vec1(node.outputs[0].default_value)
elif node.type == 'WIREFRAME':
pass
elif node.type == 'TEX_BRICK':
pass
elif node.type == 'TEX_CHECKER':
pass
elif node.type == 'TEX_GRADIENT':
pass
elif node.type == 'TEX_IMAGE':
pass
elif node.type == 'TEX_MAGIC':
pass
elif node.type == 'TEX_MUSGRAVE':
pass
elif node.type == 'TEX_NOISE':
pass
elif node.type == 'TEX_POINTDENSITY':
pass
elif node.type == 'TEX_VORONOI':
pass
elif node.type == 'TEX_WAVE':
pass
elif node.type == 'LIGHT_FALLOFF':
pass
elif node.type == 'NORMAL':
pass
elif node.type == 'VALTORGB':
pass
elif node.type == 'MATH':
pass
elif node.type == 'RGBTOBW':
pass
elif node.type == 'SEPHSV':
pass
elif node.type == 'SEPRGB':
pass
elif node.type == 'SEPXYZ':
pass
elif node.type == 'VECT_MATH':
pass
def vec1(v):
return str(v)
def vec2(v):
return 'vec2({0}, {1})'.format(v[0], v[1])
def vec3(v):
return 'vec3({0}, {1}, {2})'.format(v[0], v[1], v[2])
def vec4(v):
return 'vec4({0}, {1}, {2}, {3})'.format(v[0], v[1], v[2], v[3])
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.vert()
vert.add_uniform('mat4 LWVP', '_lampWorldViewProjectionMatrix')
vert.write('gl_Position = LWVP * vec4(pos, 1.0);')
frag = con_shadowmap.frag()
frag.write('fragColor = vec4(0.0);')
return con_shadowmap