armory/blender/armmaterial/make_mesh.py

368 lines
15 KiB
Python
Raw Normal View History

2016-12-19 01:25:22 +01:00
import bpy
import make_state as state
2017-03-15 10:37:09 +01:00
import armmaterial.mat_state as mat_state
import armmaterial.mat_utils as mat_utils
import armmaterial.cycles as cycles
import armmaterial.make_skin as make_skin
import armmaterial.make_tess as make_tess
2016-12-19 01:25:22 +01:00
import armutils
import assets
2017-03-14 20:43:54 +01:00
is_displacement = False
2016-12-20 00:39:18 +01:00
2017-03-14 20:43:54 +01:00
def make(context_id, rid):
2016-12-20 00:39:18 +01:00
con_mesh = mat_state.data.add_context({ 'name': context_id, 'depth_write': True, 'compare_mode': 'less', 'cull_mode': 'clockwise' })
2016-12-19 01:25:22 +01:00
if rid == 'forward':
2016-12-20 00:39:18 +01:00
make_forward(con_mesh)
2016-12-19 01:25:22 +01:00
elif rid == 'deferred':
2016-12-20 00:39:18 +01:00
make_deferred(con_mesh)
2016-12-19 01:25:22 +01:00
2016-12-20 00:39:18 +01:00
return con_mesh
2016-12-19 01:25:22 +01:00
2017-03-14 20:43:54 +01:00
def make_finalize(con_mesh):
vert = con_mesh.vert
frag = con_mesh.frag
geom = con_mesh.geom
tesc = con_mesh.tesc
tese = con_mesh.tese
# Additional values referenced in cycles
if frag.contains('dotNV') and not frag.contains('float dotNV'):
frag.prepend('float dotNV = max(dot(n, vVec), 0.0);')
if frag.contains('vVec') and not frag.contains('vec3 vVec'):
if is_displacement:
tese.add_out('vec3 eyeDir')
tese.add_uniform('vec3 eye', '_cameraPosition')
tese.write('eyeDir = eye - wposition;')
else:
vert.add_out('vec3 eyeDir')
vert.add_uniform('vec3 eye', '_cameraPosition')
vert.write('eyeDir = eye - wposition;')
frag.prepend('vec3 vVec = normalize(eyeDir);')
if frag.contains('wposition') and not frag.contains('vec3 wposition'):
if not is_displacement: # Displacement always outputs wposition
vert.add_uniform('mat4 W', '_worldMatrix')
vert.add_out('vec3 wposition')
vert.write('wposition = vec4(W * spos).xyz;')
2016-12-21 00:51:04 +01:00
def make_base(con_mesh, parse_opacity):
2017-03-14 20:43:54 +01:00
global is_displacement
2016-12-19 01:25:22 +01:00
vert = con_mesh.make_vert()
2016-12-21 00:51:04 +01:00
frag = con_mesh.make_frag()
2016-12-19 01:25:22 +01:00
geom = None
tesc = None
tese = None
2017-03-11 01:50:47 +01:00
vert.add_uniform('mat3 N', '_normalMatrix')
2016-12-19 01:25:22 +01:00
vert.write_pre = True
vert.write('vec4 spos = vec4(pos, 1.0);')
vert.write_pre = False
if mat_utils.disp_linked(mat_state.output_node):
2017-03-14 20:43:54 +01:00
is_displacement = True
2016-12-19 01:25:22 +01:00
tesc = con_mesh.make_tesc()
tese = con_mesh.make_tese()
tesc.ins = vert.outs
tese.ins = tesc.outs
frag.ins = tese.outs
2017-03-14 20:43:54 +01:00
vert.add_uniform('mat4 W', '_worldMatrix')
vert.add_out('vec3 wposition')
vert.write('wposition = vec4(W * spos).xyz;')
2016-12-19 01:25:22 +01:00
const = {}
2017-03-12 17:29:22 +01:00
const['name'] = 'tessLevel'
const['float'] = [mat_state.material.height_tess_inner, mat_state.material.height_tess_outer]
2017-03-14 20:43:54 +01:00
mat_state.bind_constants.append(const)
2017-03-12 17:29:22 +01:00
tesc.add_uniform('vec2 tessLevel')
2016-12-20 00:39:18 +01:00
make_tess.tesc_levels(tesc)
make_tess.interpolate(tese, 'wposition', 3, declare_out=True)
make_tess.interpolate(tese, 'wnormal', 3, declare_out=True, normalize=True)
2016-12-19 01:25:22 +01:00
# No displacement
else:
2017-03-14 20:43:54 +01:00
is_displacement = False
2016-12-19 01:25:22 +01:00
frag.ins = vert.outs
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrix')
vert.write('gl_Position = WVP * spos;')
frag.add_include('../../Shaders/compiled.glsl')
frag.write('vec3 basecol;')
frag.write('float roughness;')
frag.write('float metallic;')
frag.write('float occlusion;')
2016-12-20 00:39:18 +01:00
if parse_opacity:
frag.write('float opacity;')
2016-12-19 01:25:22 +01:00
2016-12-20 00:39:18 +01:00
cycles.parse(mat_state.nodes, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity)
2016-12-19 01:25:22 +01:00
if mat_state.data.is_elem('tex'):
vert.add_out('vec2 texCoord')
vert.write('texCoord = tex;')
if tese != None:
# TODO: also includes texCoord1
tese.write_pre = True
2016-12-20 00:39:18 +01:00
make_tess.interpolate(tese, 'texCoord', 2, declare_out=frag.contains('texCoord'))
2016-12-19 01:25:22 +01:00
tese.write_pre = False
if mat_state.data.is_elem('tex1'):
vert.add_out('vec2 texCoord1')
vert.write('texCoord1 = tex1;')
if tese != None:
tese.write_pre = True
2016-12-20 00:39:18 +01:00
make_tess.interpolate(tese, 'texCoord1', 2, declare_out=frag.contains('texCoord1'))
2016-12-19 01:25:22 +01:00
tese.write_pre = False
if mat_state.data.is_elem('col'):
vert.add_out('vec3 vcolor')
vert.write('vcolor = col;')
if tese != None:
tese.write_pre = True
2016-12-20 00:39:18 +01:00
make_tess.interpolate(tese, 'vcolor', 3, declare_out=frag.contains('vcolor'))
2016-12-19 01:25:22 +01:00
tese.write_pre = False
2017-03-02 10:15:22 +01:00
if mat_state.data.is_elem('tang'):
2016-12-19 01:25:22 +01:00
if tese != None:
vert.add_out('vec3 wnormal')
vert.add_out('vec3 wtangent')
write_norpos(vert)
2017-03-11 01:50:47 +01:00
vert.write('wtangent = normalize(N * tang);')
2016-12-19 01:25:22 +01:00
tese.add_out('mat3 TBN')
2016-12-20 00:39:18 +01:00
make_tess.interpolate(tese, 'wtangent', 3, normalize=True)
2016-12-19 01:25:22 +01:00
tese.write('vec3 wbitangent = normalize(cross(wnormal, wtangent));')
tese.write('TBN = mat3(wtangent, wbitangent, wnormal);')
else:
vert.add_out('mat3 TBN')
write_norpos(vert, declare=True)
2017-03-11 01:50:47 +01:00
vert.write('vec3 tangent = normalize(N * tang);')
2016-12-19 01:25:22 +01:00
vert.write('vec3 bitangent = normalize(cross(wnormal, tangent));')
vert.write('TBN = mat3(tangent, bitangent, wnormal);')
else:
vert.add_out('vec3 wnormal')
write_norpos(vert)
frag.write_pre = True
frag.write('vec3 n = normalize(wnormal);')
frag.write_pre = False
if tese != None:
tese.add_uniform('mat4 VP', '_viewProjectionMatrix')
# TODO: Sample disp at neightbour points to calc normal
tese.write('wposition += wnormal * disp * 0.2;')
tese.write('gl_Position = VP * vec4(wposition, 1.0);')
def write_norpos(vert, declare=False):
prep = ''
if declare:
prep = 'vec3 '
vert.write_pre = True
if mat_state.data.is_elem('bone'):
make_skin.skin_pos(vert)
2017-03-11 01:50:47 +01:00
vert.write(prep + 'wnormal = normalize(N * (nor + 2.0 * cross(skinA.xyz, cross(skinA.xyz, nor) + skinA.w * nor)));')
2016-12-19 01:25:22 +01:00
else:
2017-03-11 01:50:47 +01:00
vert.write(prep + 'wnormal = normalize(N * nor);')
2016-12-21 00:51:04 +01:00
if mat_state.data.is_elem('off'):
vert.write('spos.xyz += off;')
2016-12-19 01:25:22 +01:00
vert.write_pre = False
2016-12-20 00:39:18 +01:00
def make_deferred(con_mesh):
2016-12-21 00:51:04 +01:00
wrd = bpy.data.worlds['Arm']
make_base(con_mesh, parse_opacity=False)
2016-12-19 01:25:22 +01:00
2016-12-20 00:39:18 +01:00
frag = con_mesh.frag
2016-12-21 00:51:04 +01:00
vert = con_mesh.vert
2017-01-08 13:21:54 +01:00
tese = con_mesh.tese
2016-12-21 00:51:04 +01:00
2017-01-14 12:44:43 +01:00
if '_Veloc' in wrd.rp_defs:
2016-12-21 00:51:04 +01:00
frag.add_out('vec4[3] fragColor')
2017-01-08 13:21:54 +01:00
if tese == None:
vert.add_uniform('mat4 prevWVP', link='_prevWorldViewProjectionMatrix')
vert.add_out('vec4 wvpposition')
vert.add_out('vec4 prevwvpposition')
vert.write('wvpposition = gl_Position;')
vert.write('prevwvpposition = prevWVP * spos;')
else:
vert.add_uniform('mat4 prevW', link='_prevWorldMatrix')
vert.add_out('vec3 prevwposition')
vert.write('prevwposition = vec4(prevW * spos).xyz;')
tese.add_out('vec4 wvpposition')
tese.add_out('vec4 prevwvpposition')
tese.add_uniform('mat4 prevVP', '_prevViewProjectionMatrix')
tese.write('wvpposition = gl_Position;')
make_tess.interpolate(tese, 'prevwposition', 3)
tese.write('prevwvpposition = prevVP * vec4(prevwposition, 1.0);')
2016-12-21 00:51:04 +01:00
else:
frag.add_out('vec4[2] fragColor')
# Pack gbuffer
2016-12-20 00:39:18 +01:00
frag.add_include('../../Shaders/std/gbuffer.glsl')
frag.write('n /= (abs(n.x) + abs(n.y) + abs(n.z));')
frag.write('n.xy = n.z >= 0.0 ? n.xy : octahedronWrap(n.xy);')
2017-03-11 01:50:47 +01:00
# TODO: store_depth
# frag.write('fragColor[0] = vec4(n.xy, packFloat(metallic, roughness), 1.0 - gl_FragCoord.z);')
frag.write('fragColor[0] = vec4(n.xy, packFloat(metallic, roughness), occlusion);')
frag.write('fragColor[1] = vec4(basecol.rgb, 0.0);')
2016-12-19 01:25:22 +01:00
2017-01-14 12:44:43 +01:00
if '_Veloc' in wrd.rp_defs:
2016-12-21 00:51:04 +01:00
frag.write('vec2 posa = (wvpposition.xy / wvpposition.w) * 0.5 + 0.5;')
frag.write('vec2 posb = (prevwvpposition.xy / prevwvpposition.w) * 0.5 + 0.5;')
frag.write('fragColor[2].rg = vec2(posa - posb);')
2016-12-20 00:39:18 +01:00
return con_mesh
2016-12-19 01:25:22 +01:00
2016-12-21 00:51:04 +01:00
def make_forward(con_mesh):
make_forward_base(con_mesh)
2016-12-21 19:15:51 +01:00
frag = con_mesh.frag
2016-12-21 00:51:04 +01:00
frag.add_out('vec4 fragColor')
frag.write('fragColor = vec4(direct * lightColor * visibility + indirect * occlusion * envmapStrength, 1.0);')
2017-01-14 12:44:43 +01:00
if '_LDR' in bpy.data.worlds['Arm'].rp_defs:
2017-01-16 15:26:57 +01:00
frag.write('fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2));')
2016-12-21 00:51:04 +01:00
def make_forward_base(con_mesh, parse_opacity=False):
wrd = bpy.data.worlds['Arm']
make_base(con_mesh, parse_opacity=parse_opacity)
2016-12-20 00:39:18 +01:00
vert = con_mesh.vert
frag = con_mesh.frag
tese = con_mesh.tese
2016-12-19 01:25:22 +01:00
2017-03-14 20:43:54 +01:00
if is_displacement:
tese.add_out('vec3 eyeDir')
tese.add_uniform('vec3 eye', '_cameraPosition')
tese.write('eyeDir = eye - wposition;')
else:
vert.add_out('vec3 wposition')
vert.add_uniform('mat4 W', '_worldMatrix')
vert.write('wposition = vec4(W * spos).xyz;')
vert.add_out('vec3 eyeDir')
vert.add_uniform('vec3 eye', '_cameraPosition')
vert.write('eyeDir = eye - wposition;')
frag.write('vec3 vVec = normalize(eyeDir);')
frag.write('float dotNV = max(dot(n, vVec), 0.0);')
2016-12-19 01:25:22 +01:00
frag.add_include('../../Shaders/std/brdf.glsl')
frag.add_include('../../Shaders/std/math.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')
2017-03-12 17:29:22 +01:00
frag.add_uniform('vec2 spotlightData', '_spotlampData') # cutoff, cutoff - exponent
2016-12-19 01:25:22 +01:00
frag.add_uniform('float envmapStrength', link='_envmapStrength')
2017-01-23 20:41:45 +01:00
if '_Irr' in wrd.world_defs:
frag.add_include('../../Shaders/std/shirr.glsl')
2017-02-07 11:50:21 +01:00
frag.add_uniform('vec4 shirr[7]', link='_envmapIrradiance', included=True)
2017-01-23 20:41:45 +01:00
if '_Rad' in wrd.world_defs:
frag.add_uniform('sampler2D senvmapRadiance', link='_envmapRadiance')
frag.add_uniform('sampler2D senvmapBrdf', link='_envmapBrdf')
frag.add_uniform('int envmapNumMipmaps', link='_envmapNumMipmaps')
2016-12-20 00:39:18 +01:00
2017-01-23 00:48:59 +01:00
if '_NoShadows' in wrd.world_defs:
is_shadows = False
else:
is_shadows = True
2016-12-20 00:39:18 +01:00
if '_PCSS' in wrd.world_defs:
is_pcss = True
else:
is_pcss = False
2016-12-19 01:25:22 +01:00
frag.write('float visibility = 1.0;')
2017-03-02 10:15:22 +01:00
frag.write('vec3 l;')
frag.write('if (lightType == 0) l = lightDir;')
frag.write('else { l = normalize(lightPos - wposition); visibility *= attenuate(distance(wposition, lightPos)); }')
2017-03-14 20:43:54 +01:00
frag.write('vec3 h = normalize(vVec + l);')
2017-03-02 10:15:22 +01:00
frag.write('float dotNL = dot(n, l);')
frag.write('float dotNH = dot(n, h);')
2017-03-14 20:43:54 +01:00
frag.write('float dotVH = dot(vVec, h);')
2017-03-02 10:15:22 +01:00
2017-01-23 00:48:59 +01:00
if is_shadows:
if tese != None:
tese.add_out('vec4 lampPos')
2017-02-28 14:13:50 +01:00
tese.add_uniform('mat4 LVP', '_biasLampViewProjectionMatrix')
2017-01-23 00:48:59 +01:00
tese.write('lampPos = LVP * vec4(wposition, 1.0);')
else:
vert.add_out('vec4 lampPos')
2017-02-28 14:13:50 +01:00
vert.add_uniform('mat4 LWVP', '_biasLampWorldViewProjectionMatrix')
2017-01-23 00:48:59 +01:00
vert.write('lampPos = LWVP * spos;')
if is_pcss:
frag.add_include('../../Shaders/std/shadows_pcss.glsl')
frag.add_uniform('sampler2D snoise', link='_noise64', included=True)
frag.add_uniform('float lampSizeUV', link='_lampSizeUV', included=True)
else:
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('if (receiveShadow && lampPos.w > 0.0) {')
frag.tab += 1
frag.write('vec3 lpos = lampPos.xyz / lampPos.w;')
2017-03-02 10:15:22 +01:00
# frag.write('float bias = clamp(shadowsBias * 1.0 * tan(acos(clamp(dotNL, 0.0, 1.0))), 0.0, 0.01);')
2017-01-23 00:48:59 +01:00
if is_pcss:
2017-03-04 16:46:39 +01:00
frag.write('visibility *= PCSS(lpos.xy, lpos.z - shadowsBias);')
2017-01-23 00:48:59 +01:00
else:
2017-03-04 16:46:39 +01:00
frag.write('visibility *= PCF(lpos.xy, lpos.z - shadowsBias);')
2017-01-23 00:48:59 +01:00
frag.tab -= 1
frag.write('}')
2016-12-19 01:25:22 +01:00
frag.write('if (lightType == 2) {')
2017-03-03 14:36:01 +01:00
frag.write(' float spotEffect = dot(lightDir, l);')
2017-03-11 01:50:47 +01:00
frag.write(' if (spotEffect < spotlightData.x) {')
frag.write(' visibility *= smoothstep(spotlightData.y, spotlightData.x, spotEffect);')
2017-03-03 14:36:01 +01:00
frag.write(' }')
2016-12-19 01:25:22 +01:00
frag.write('}')
frag.write('vec3 albedo = surfaceAlbedo(basecol, metallic);')
frag.write('vec3 f0 = surfaceF0(basecol, metallic);')
2017-03-03 14:36:01 +01:00
frag.write('vec3 direct;')
if '_PolyLight' in wrd.world_defs:
frag.add_include('../../Shaders/std/ltc.glsl')
frag.add_uniform('sampler2D sltcMat', link='_ltcMat')
frag.add_uniform('sampler2D sltcMag', link='_ltcMag')
frag.add_uniform('vec3 lampArea0', link='_lampArea0')
frag.add_uniform('vec3 lampArea1', link='_lampArea1')
frag.add_uniform('vec3 lampArea2', link='_lampArea2')
frag.add_uniform('vec3 lampArea3', link='_lampArea3')
frag.write('if (lightType == 3) {')
frag.write(' float theta = acos(dotNV);')
frag.write(' vec2 tuv = vec2(roughness, theta / (0.5 * PI));')
frag.write(' tuv = tuv * LUT_SCALE + LUT_BIAS;')
frag.write(' vec4 t = texture(sltcMat, tuv);')
frag.write(' mat3 invM = mat3(vec3(1.0, 0.0, t.y), vec3(0.0, t.z, 0.0), vec3(t.w, 0.0, t.x));')
2017-03-14 20:43:54 +01:00
frag.write(' float ltcspec = ltcEvaluate(n, vVec, dotNV, wposition, invM, lampArea0, lampArea1, lampArea2, lampArea3);')
2017-03-03 14:36:01 +01:00
frag.write(' ltcspec *= texture(sltcMag, tuv).a;')
2017-03-14 20:43:54 +01:00
frag.write(' float ltcdiff = ltcEvaluate(n, vVec, dotNV, wposition, mat3(1.0), lampArea0, lampArea1, lampArea2, lampArea3);')
2017-03-03 14:36:01 +01:00
frag.write(' direct = albedo * ltcdiff + ltcspec;')
frag.write('}')
frag.write('else {')
frag.tab += 1
frag.write('direct = lambertDiffuseBRDF(albedo, dotNL);')
2016-12-19 01:25:22 +01:00
frag.write('direct += specularBRDF(f0, roughness, dotNL, dotNH, dotNV, dotVH);')
2017-03-03 14:36:01 +01:00
if '_PolyLight' in wrd.world_defs:
frag.write('}')
frag.tab -= 1
2017-01-23 20:41:45 +01:00
if '_Irr' in wrd.world_defs:
frag.write('vec3 indirect = (shIrradiance(n, 2.2) / PI) * albedo;')
if '_Rad' in wrd.world_defs:
2017-03-14 20:43:54 +01:00
frag.write('vec3 reflectionWorld = reflect(-vVec, n);')
2017-01-23 20:41:45 +01:00
frag.write('float lod = getMipFromRoughness(roughness, envmapNumMipmaps);')
frag.write('vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;')
if '_EnvLDR' in wrd.world_defs:
frag.write('prefilteredColor = pow(prefilteredColor, vec3(2.2));')
frag.write('vec2 envBRDF = texture(senvmapBrdf, vec2(roughness, 1.0 - dotNV)).xy;')
frag.write('indirect += prefilteredColor * (f0 * envBRDF.x + envBRDF.y);')
else:
frag.write('vec3 indirect = albedo;')