def make(context_id, rpasses, shadowmap=False): is_disp = mat_utils.disp_linked(mat_state.output_node) vs = [{'name': 'pos', 'size': 3}] if is_disp: vs.append({'name': 'nor', 'size': 3}) con_depth = mat_state.data.add_context({ 'name': context_id, 'vertex_structure': vs, 'depth_write': True, 'compare_mode': 'less', 'cull_mode': 'clockwise', 'color_write_red': False, 'color_write_green': False, 'color_write_blue': False, 'color_write_alpha': False }) vert = con_depth.make_vert() frag = con_depth.make_frag() geom = None tesc = None tese = None vert.write_attrib('vec4 spos = vec4(pos, 1.0);') parse_opacity = 'translucent' in rpasses or mat_state.material.arm_discard if parse_opacity: frag.write('vec3 n;') # Discard at compile time frag.write('float dotNV;') frag.write('float opacity;') if con_depth.is_elem('bone'): make_skin.skin_pos(vert) if con_depth.is_elem('off'): vert.write('spos.xyz += off;') wrd = bpy.data.worlds['Arm'] if mat_state.material.arm_particle == 'gpu': make_particle.write(vert) if is_disp: rpdat = arm.utils.get_rp() if rpdat.arm_rp_displacement == 'Vertex': vert.add_uniform('mat4 W', '_worldMatrix') vert.add_uniform('mat3 N', '_normalMatrix') vert.write('vec3 wnormal = normalize(N * nor);') vert.write('vec3 wposition = vec4(W * spos).xyz;') cycles.parse(mat_state.nodes, con_depth, vert, frag, geom, tesc, tese, parse_surface=False, parse_opacity=parse_opacity) if con_depth.is_elem('tex'): vert.add_out('vec2 texCoord') ## vs only, remove out vert.write_attrib('texCoord = tex;') vert.write('wposition += wnormal * disp * 0.1;') if shadowmap: vert.add_uniform('mat4 LVP', '_lampViewProjectionMatrix') vert.write('gl_Position = LVP * vec4(wposition, 1.0);') else: vert.add_uniform('mat4 VP', '_viewProjectionMatrix') vert.write('gl_Position = VP * vec4(wposition, 1.0);') else: # Tessellation tesc = con_depth.make_tesc() tese = con_depth.make_tese() tesc.ins = vert.outs tese.ins = tesc.outs frag.ins = tese.outs vert.add_out('vec3 wposition') vert.add_out('vec3 wnormal') vert.add_uniform('mat4 W', '_worldMatrix') vert.add_uniform('mat3 N', '_normalMatrix') vert.write('wnormal = normalize(N * nor);') vert.write('wposition = vec4(W * spos).xyz;') make_tess.tesc_levels(tesc, rpdat.arm_tess_shadows_inner, rpdat.arm_tess_shadows_outer) make_tess.interpolate(tese, 'wposition', 3) make_tess.interpolate(tese, 'wnormal', 3, normalize=True) cycles.parse(mat_state.nodes, con_depth, vert, frag, geom, tesc, tese, parse_surface=False, parse_opacity=parse_opacity) if con_depth.is_elem('tex'): vert.add_out('vec2 texCoord') vert.write('texCoord = tex;') tese.write_pre = True make_tess.interpolate(tese, 'texCoord', 2, declare_out=frag.contains('texCoord')) tese.write_pre = False if con_depth.is_elem('tex1'): vert.add_out('vec2 texCoord1') vert.write('texCoord1 = tex1;') tese.write_pre = True make_tess.interpolate(tese, 'texCoord1', 2, declare_out=frag.contains('texCoord1')) tese.write_pre = False if con_depth.is_elem('col'): vert.add_out('vec3 vcolor') vert.write('vcolor = col;') tese.write_pre = True make_tess.interpolate(tese, 'vcolor', 3, declare_out=frag.contains('vcolor')) tese.write_pre = False if shadowmap: tese.add_uniform('mat4 LVP', '_lampViewProjectionMatrix') tese.write('wposition += wnormal * disp * 0.1;') tese.write('gl_Position = LVP * vec4(wposition, 1.0);') else: tese.add_uniform('mat4 VP', '_viewProjectionMatrix') tese.write('wposition += wnormal * disp * 0.1;') tese.write('gl_Position = VP * vec4(wposition, 1.0);') # No displacement else: frag.ins = vert.outs billboard = mat_state.material.arm_billboard if shadowmap: if billboard == 'spherical': vert.add_uniform('mat4 LWVP', '_lampWorldViewProjectionMatrixSphere') elif billboard == 'cylindrical': vert.add_uniform('mat4 LWVP', '_lampWorldViewProjectionMatrixCylinder') else: # off vert.add_uniform('mat4 LWVP', '_lampWorldViewProjectionMatrix') vert.write('gl_Position = LWVP * spos;') else: 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 parse_opacity: cycles.parse(mat_state.nodes, con_depth, vert, frag, geom, tesc, tese, parse_surface=False, parse_opacity=True) if con_depth.is_elem('tex'): vert.add_out('vec2 texCoord') if mat_state.material.arm_tilesheet_mat: vert.add_uniform('vec2 tilesheetOffset', '_tilesheetOffset') vert.write('texCoord = tex + tilesheetOffset;') else: vert.write('texCoord = tex;') if con_depth.is_elem('tex1'): vert.add_out('vec2 texCoord1') vert.write('texCoord1 = tex1;') if con_depth.is_elem('col'): vert.add_out('vec3 vcolor') vert.write('vcolor = col;') if parse_opacity: opac = mat_state.material.arm_discard_opacity_shadows frag.write('if (opacity < {0}) discard;'.format(opac)) make_mesh.make_finalize(con_depth) assets.vs_equal(con_depth, assets.shader_cons['depth_vert']) assets.fs_equal(con_depth, assets.shader_cons['depth_frag']) return con_depth
def make_mesh_pass(rpass): con = { 'name': rpass, 'depth_write': True, 'compare_mode': 'less', 'cull_mode': 'clockwise' } con_mesh = mat_state.data.add_context(con) mat_state.con_mesh = con_mesh mat = con_mesh.material wrd = bpy.data.worlds['Arm'] vert = con_mesh.make_vert() frag = con_mesh.make_frag() geom = None tesc = None tese = None vert.add_uniform('mat3 N', '_normalMatrix') vert.write_attrib('vec4 spos = vec4(pos.xyz, 1.0);') frag.ins = vert.outs frag.add_include('compiled.glsl') frag.add_uniform('vec3 sunDir', '_sunDirection') frag.add_uniform('vec3 sunCol', '_sunColor') frag.add_uniform('float envmapStrength', link='_envmapStrength') frag.write('float visibility = 1.0;') frag.write('float dotNL = max(dot(n, sunDir), 0.0);') is_shadows = '_ShadowMap' in wrd.world_defs if is_shadows: vert.add_out('vec4 lightPos') vert.add_uniform('mat4 LWVP', '_biasLightWorldViewProjectionMatrix') vert.write('lightPos = LWVP * spos;') frag.add_include('std/shadows.glsl') frag.add_uniform('sampler2DShadow shadowMap') frag.add_uniform('float shadowsBias', '_sunShadowsBias') frag.add_uniform('bool receiveShadow') frag.write('if (receiveShadow && lightPos.w > 0.0) {') frag.write('vec3 lPos = lightPos.xyz / lightPos.w;') frag.write('const vec2 smSize = shadowmapSize;') frag.write( 'visibility *= PCF(shadowMap, lPos.xy, lPos.z - shadowsBias, smSize);' ) frag.write('}') frag.write('vec3 basecol;') frag.write('float roughness;') frag.write('float metallic;') frag.write('float occlusion;') frag.write('float specular;') frag.write('float emission;') is_displacement = mat_utils.disp_linked(mat_state.output_node) arm_discard = mat_state.material.arm_discard if arm_discard: frag.write('float opacity;') cycles.parse(mat_state.nodes, con_mesh, vert, frag, geom, tesc, tese, parse_opacity=arm_discard, parse_displacement=is_displacement) if arm_discard: opac = mat_state.material.arm_discard_opacity frag.write('if (opacity < {0}) discard;'.format(opac)) if con_mesh.is_elem('tex'): vert.add_out('vec2 texCoord') vert.add_uniform('float texUnpack', link='_texUnpack') vert.write_attrib('texCoord = tex * texUnpack;') if con_mesh.is_elem('col'): vert.add_out('vec3 vcolor') vert.write_attrib('vcolor = col;') if con_mesh.is_elem('tang'): vert.add_out('mat3 TBN') make_attrib.write_norpos(con_mesh, vert, declare=True) vert.write('vec3 tangent = normalize(N * tang.xyz);') vert.write('vec3 bitangent = normalize(cross(wnormal, tangent));') vert.write('TBN = mat3(tangent, bitangent, wnormal);') else: vert.add_out('vec3 wnormal') make_attrib.write_norpos(con_mesh, vert) frag.write_attrib('vec3 n = normalize(wnormal);') frag.add_out('vec4 fragColor') frag.write( f'vec3 shade = basecol * {cycles.to_vec3(mat.arm_celshade_shade_color)};' ) s = mat.arm_celshade_shade_softness if s == 0.0: frag.write( 'vec3 direct = mix(shade, basecol, step(0.5, dotNL)) * visibility * sunCol;' ) else: frag.write( f'vec3 direct = mix(shade, basecol, smoothstep({0.5 - s}, {0.5 + s}, dotNL)) * visibility * sunCol;' ) frag.write('vec3 indirect = basecol * envmapStrength;') frag.write('fragColor = vec4(direct + indirect, 1.0);') if '_LDR' in wrd.world_defs: frag.write('fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2));') if is_displacement: vert.add_uniform('mat4 W', link='_worldMatrix') vert.add_uniform('mat4 VP', link='_viewProjectionMatrix') vert.write('vec4 wpos = W * spos;') vert.write('wpos.xyz += wnormal * disp * 0.1;') vert.write('gl_Position = VP * wpos;') else: make_attrib.write_vertpos(vert) assets.vs_equal(con_mesh, assets.shader_cons['mesh_vert']) make_finalize.make(con_mesh) return con_mesh
def make(context_id): con_decal = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'less', 'cull_mode': 'clockwise', 'blend_source': 'source_alpha', 'blend_destination': 'inverse_source_alpha', 'blend_operation': 'add', 'color_write_alpha': False }) vert = con_decal.make_vert() frag = con_decal.make_frag() geom = None tesc = None tese = None vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrix') vert.add_uniform('mat3 N', '_normalMatrix') vert.add_out('vec4 wvpposition') vert.add_out('vec3 wnormal') vert.write('wnormal = N * vec3(0.0, 0.0, 1.0);') vert.write('wvpposition = WVP * vec4(pos, 1.0);') vert.write('gl_Position = wvpposition;') frag.add_include('../../Shaders/compiled.glsl') frag.add_include('../../Shaders/std/gbuffer.glsl') frag.ins = vert.outs frag.add_uniform('sampler2D gbufferD') frag.add_uniform('mat4 invVP', '_inverseViewProjectionMatrix') frag.add_uniform('mat4 invW', '_inverseWorldMatrix') frag.add_uniform('vec3 eye', '_cameraPosition') frag.add_out('vec4[2] fragColor') frag.write_main_header(' vec3 n = normalize(wnormal);') frag.write_main_header(' vec2 screenPosition = wvpposition.xy / wvpposition.w;') frag.write_main_header(' vec2 depthCoord = screenPosition * 0.5 + 0.5;') frag.write_main_header(' float depth = texture(gbufferD, depthCoord).r * 2.0 - 1.0;') frag.write_main_header(' vec3 wpos = getPos2(invVP, depth, depthCoord);') frag.write_main_header(' vec4 mpos = invW * vec4(wpos, 1.0);') frag.write_main_header(' if (abs(mpos.x) > 1.0) discard;') frag.write_main_header(' if (abs(mpos.y) > 1.0) discard;') frag.write_main_header(' if (abs(mpos.z) > 1.0) discard;') frag.write_main_header(' vec3 vVec = normalize(eye - wpos);') frag.write_main_header(' vec2 texCoord = mpos.xy * 0.5 + 0.5;') frag.write('vec3 basecol;') frag.write('float roughness;') frag.write('float metallic;') frag.write('float occlusion;') cycles.parse(mat_state.nodes, con_decal, vert, frag, geom, tesc, tese, parse_opacity=False) 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);') if cycles.basecol_texname == '': frag.write('const float alpha = 1.0;') else: frag.write('const float alpha = {0}.a;'.format(cycles.basecol_texname)) frag.write('fragColor[0] = vec4(n.xy, packFloat(metallic, roughness), alpha);') frag.write('fragColor[1] = vec4(basecol.rgb, alpha);') return con_decal
def make_base(con_mesh, parse_opacity): global is_displacement global write_material_attribs global write_material_attribs_post global write_vertex_attribs vert = con_mesh.make_vert() frag = con_mesh.make_frag() geom = None tesc = None tese = None vert.add_uniform('mat3 N', '_normalMatrix') vert.write_main_header(' vec4 spos = vec4(pos, 1.0);') 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 tese.ins = tesc.outs frag.ins = tese.outs vert.add_uniform('mat4 W', '_worldMatrix') vert.add_out('vec3 wposition') vert.write('wposition = vec4(W * spos).xyz;') make_tess.tesc_levels(tesc, mat_state.material.arm_tess_inner, mat_state.material.arm_tess_outer) make_tess.interpolate(tese, 'wposition', 3, declare_out=True) make_tess.interpolate(tese, 'wnormal', 3, declare_out=True, normalize=True) # No displacement else: frag.ins = vert.outs if write_vertex_attribs != None: vattr_written = write_vertex_attribs(vert) frag.add_include('../../Shaders/compiled.glsl') written = False if write_material_attribs != None: written = write_material_attribs(con_mesh, frag) if written == False: frag.write('vec3 basecol;') frag.write('float roughness;') frag.write('float metallic;') frag.write('float occlusion;') if parse_opacity: frag.write('float opacity;') cycles.parse(mat_state.nodes, con_mesh, vert, frag, geom, tesc, tese, parse_opacity=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: if mat_state.material.arm_particle == 'gpu': make_particle.write_tilesheet(vert) else: vert.add_uniform('vec2 tilesheetOffset', '_tilesheetOffset') vert.write('texCoord = tex + tilesheetOffset;') else: vert.write('texCoord = tex;') if tese != None: # TODO: also includes texCoord1 tese.write_pre = True make_tess.interpolate(tese, 'texCoord', 2, declare_out=frag.contains('texCoord')) tese.write_pre = False if con_mesh.is_elem('tex1'): vert.add_out('vec2 texCoord1') vert.write('texCoord1 = tex1;') if tese != None: tese.write_pre = True make_tess.interpolate(tese, 'texCoord1', 2, declare_out=frag.contains('texCoord1')) tese.write_pre = False if con_mesh.is_elem('col'): vert.add_out('vec3 vcolor') vert.write('vcolor = col;') if tese != None: tese.write_pre = True make_tess.interpolate(tese, 'vcolor', 3, declare_out=frag.contains('vcolor')) tese.write_pre = False if con_mesh.is_elem('tang'): if tese != None: vert.add_out('vec3 wnormal') vert.add_out('vec3 wtangent') write_norpos(con_mesh, vert) vert.write('wtangent = normalize(N * tang);') tese.add_out('mat3 TBN') make_tess.interpolate(tese, 'wtangent', 3, normalize=True) tese.write('vec3 wbitangent = normalize(cross(wnormal, wtangent));') tese.write('TBN = mat3(wtangent, wbitangent, wnormal);') else: vert.add_out('mat3 TBN') write_norpos(con_mesh, vert, declare=True) vert.write('vec3 tangent = normalize(N * tang);') vert.write('vec3 bitangent = normalize(cross(wnormal, tangent));') vert.write('TBN = mat3(tangent, bitangent, wnormal);') else: vert.add_out('vec3 wnormal') write_norpos(con_mesh, vert) frag.prepend_header('vec3 n = normalize(wnormal);') 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 make_forward_mobile(con_mesh): wrd = bpy.data.worlds['Arm'] vert = con_mesh.make_vert() frag = con_mesh.make_frag() geom = None tesc = None tese = None vert.add_uniform('mat3 N', '_normalMatrix') vert.write_attrib('vec4 spos = vec4(pos, 1.0);') frag.ins = vert.outs vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrix') vert.add_uniform('mat4 W', '_worldMatrix') vert.add_out('vec3 wposition') vert.write_attrib('wposition = vec4(W * spos).xyz;') vert.write('gl_Position = WVP * spos;') frag.add_include('compiled.glsl') frag.write('vec3 basecol;') frag.write('float roughness;') frag.write('float metallic;') frag.write('float occlusion;') cycles.parse(mat_state.nodes, con_mesh, vert, frag, geom, tesc, tese, parse_opacity=False, parse_displacement=False) if con_mesh.is_elem('tex'): vert.add_out('vec2 texCoord') vert.write_attrib('texCoord = tex;') if con_mesh.is_elem('col'): vert.add_out('vec3 vcolor') vert.write('vcolor = col;') vert.add_out('vec3 wnormal') write_norpos(con_mesh, vert) frag.write_attrib('vec3 n = normalize(wnormal);') frag.add_include('std/math.glsl') frag.add_include('std/brdf.glsl') frag.add_uniform('vec3 lightColor', '_lampColor') frag.add_uniform('vec3 lightDir', '_lampDirection') frag.add_uniform('vec3 lightPos', '_lampPosition') frag.add_uniform('float envmapStrength', link='_envmapStrength') is_shadows = not '_NoShadows' in wrd.world_defs frag.write('float visibility = 1.0;') frag.write('float dotNL = max(dot(n, lightDir), 0.0);') if is_shadows: vert.add_out('vec4 lampPos') vert.add_uniform('mat4 LWVP', '_biasLampWorldViewProjectionMatrix') vert.write('lampPos = LWVP * spos;') frag.add_include('std/shadows.glsl') frag.add_uniform('sampler2D shadowMap') frag.add_uniform('float shadowsBias', '_lampShadowsBias') frag.write(' if (lampPos.w > 0.0) {') frag.write(' vec3 lPos = lampPos.xyz / lampPos.w;') frag.write(' const float texelSize = 1.0 / shadowmapSize.x;') frag.write(' visibility = 0.0;') # TODO: CSM frag.write( ' visibility += float(texture(shadowMap, lPos.xy).r + shadowsBias > lPos.z);' ) frag.write( ' visibility += float(texture(shadowMap, lPos.xy + vec2(texelSize, 0.0)).r + shadowsBias > lPos.z) * 0.5;' ) frag.write( ' visibility += float(texture(shadowMap, lPos.xy + vec2(-texelSize, 0.0)).r + shadowsBias > lPos.z) * 0.25;' ) frag.write( ' visibility += float(texture(shadowMap, lPos.xy + vec2(0.0, texelSize)).r + shadowsBias > lPos.z) * 0.5;' ) frag.write( ' visibility += float(texture(shadowMap, lPos.xy + vec2(0.0, -texelSize)).r + shadowsBias > lPos.z) * 0.25;' ) frag.write(' visibility /= 2.5;') frag.write(' visibility = max(visibility, 0.2);') # frag.write(' visibility = max(float(texture(shadowMap, lPos.xy).r + shadowsBias > lPos.z), 0.5);') frag.write(' }') frag.add_out('vec4 fragColor') blend = mat_state.material.arm_blending if blend: # frag.write('fragColor = vec4(basecol * visibility, 1.0);') frag.write('fragColor = vec4(basecol, 1.0);') return frag.write('vec3 direct = basecol * dotNL * lightColor;') # frag.write('direct += vec3(D_Approx(max(roughness, 0.3), dot(reflect(-vVec, n), lightDir)));') frag.write('direct *= attenuate(distance(wposition, lightPos));') if '_Irr' in wrd.world_defs: frag.add_include('std/shirr.glsl') frag.add_uniform('vec4 shirr[7]', link='_envmapIrradiance', included=True) env_str = 'shIrradiance(n)' else: env_str = '0.5' frag.write( 'fragColor = vec4(direct * visibility + basecol * {0} * envmapStrength, 1.0);' .format(env_str)) if '_LDR' in wrd.world_defs: frag.write('fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2));')
def make(context_id, rpasses, shadowmap=False): is_disp = mat_utils.disp_linked( mat_state.output_node) and mat_state.material.arm_tess_shadows vs = [{'name': 'pos', 'size': 3}] if is_disp: vs.append({'name': 'nor', 'size': 3}) con_depth = mat_state.data.add_context({ 'name': context_id, 'vertex_structure': vs, 'depth_write': True, 'compare_mode': 'less', 'cull_mode': 'clockwise', 'color_write_red': False, 'color_write_green': False, 'color_write_blue': False, 'color_write_alpha': False }) vert = con_depth.make_vert() frag = con_depth.make_frag() geom = None tesc = None tese = None gapi = arm.utils.get_gapi() if gapi == 'direct3d9': frag.add_out( 'vec4 fragColor' ) # Definition requred for d3d9 - pixel shader must minimally write all four components of COLOR0 vert.write_main_header('vec4 spos = vec4(pos, 1.0);') parse_opacity = 'translucent' in rpasses or mat_state.material.arm_discard if parse_opacity: frag.write('vec3 n;') # Discard at compile time frag.write('float dotNV;') frag.write('float opacity;') if con_depth.is_elem('bone'): make_skin.skin_pos(vert) if con_depth.is_elem('off'): vert.write('spos.xyz += off;') wrd = bpy.data.worlds['Arm'] if mat_state.material.arm_particle == 'gpu': make_particle.write(vert) if is_disp: tesc = con_depth.make_tesc() tese = con_depth.make_tese() tesc.ins = vert.outs tese.ins = tesc.outs frag.ins = tese.outs vert.add_out('vec3 wposition') vert.add_out('vec3 wnormal') vert.add_uniform('mat4 W', '_worldMatrix') vert.add_uniform('mat3 N', '_normalMatrix') vert.write('wnormal = normalize(N * nor);') vert.write('wposition = vec4(W * spos).xyz;') make_tess.tesc_levels(tesc, mat_state.material.arm_tess_shadows_inner, mat_state.material.arm_tess_shadows_outer) make_tess.interpolate(tese, 'wposition', 3) make_tess.interpolate(tese, 'wnormal', 3, normalize=True) cycles.parse(mat_state.nodes, con_depth, vert, frag, geom, tesc, tese, parse_surface=False, parse_opacity=parse_opacity) if con_depth.is_elem('tex'): vert.add_out('vec2 texCoord') vert.write('texCoord = tex;') tese.write_pre = True make_tess.interpolate(tese, 'texCoord', 2, declare_out=frag.contains('texCoord')) tese.write_pre = False if con_depth.is_elem('tex1'): vert.add_out('vec2 texCoord1') vert.write('texCoord1 = tex1;') tese.write_pre = True make_tess.interpolate(tese, 'texCoord1', 2, declare_out=frag.contains('texCoord1')) tese.write_pre = False if con_depth.is_elem('col'): vert.add_out('vec3 vcolor') vert.write('vcolor = col;') tese.write_pre = True make_tess.interpolate(tese, 'vcolor', 3, declare_out=frag.contains('vcolor')) tese.write_pre = False if shadowmap: tese.add_uniform('mat4 LVP', '_lampViewProjectionMatrix') tese.write('wposition += wnormal * disp * 0.2;') tese.write('gl_Position = LVP * vec4(wposition, 1.0);') else: tese.add_uniform('mat4 VP', '_viewProjectionMatrix') tese.write('wposition += wnormal * disp * 0.2;') tese.write('gl_Position = VP * vec4(wposition, 1.0);') # No displacement else: frag.ins = vert.outs billboard = mat_state.material.arm_billboard if shadowmap: if billboard == 'spherical': vert.add_uniform('mat4 LWVP', '_lampWorldViewProjectionMatrixSphere') elif billboard == 'cylindrical': vert.add_uniform('mat4 LWVP', '_lampWorldViewProjectionMatrixCylinder') else: # off vert.add_uniform('mat4 LWVP', '_lampWorldViewProjectionMatrix') vert.write('gl_Position = LWVP * spos;') else: 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 parse_opacity: cycles.parse(mat_state.nodes, con_depth, vert, frag, geom, tesc, tese, parse_surface=False, parse_opacity=True) if con_depth.is_elem('tex'): vert.add_out('vec2 texCoord') if mat_state.material.arm_tilesheet_mat: vert.add_uniform('vec2 tilesheetOffset', '_tilesheetOffset') vert.write('texCoord = tex + tilesheetOffset;') else: vert.write('texCoord = tex;') if con_depth.is_elem('tex1'): vert.add_out('vec2 texCoord1') vert.write('texCoord1 = tex1;') if con_depth.is_elem('col'): vert.add_out('vec3 vcolor') vert.write('vcolor = col;') # TODO: interleaved buffer has to match vertex structure of mesh context if not bpy.data.worlds['Arm'].arm_deinterleaved_buffers: con_depth.add_elem('nor', 3) if mat_state.con_mesh != None: if mat_state.con_mesh.is_elem('tex'): con_depth.add_elem('tex', 2) if mat_state.con_mesh.is_elem('tex1'): con_depth.add_elem('tex1', 2) if mat_state.con_mesh.is_elem('col'): con_depth.add_elem('col', 3) if mat_state.con_mesh.is_elem('tang'): con_depth.add_elem('tang', 4) # TODO: pass vbuf with proper struct if gapi.startswith('direct3d') and bpy.data.worlds[ 'Arm'].arm_deinterleaved_buffers == False: vert.write('vec3 t1 = nor; // TODO: Temp for d3d') if con_depth.is_elem('tex'): vert.write('vec2 t2 = tex; // TODO: Temp for d3d') if parse_opacity: opac = mat_state.material.arm_discard_opacity_shadows frag.write('if (opacity < {0}) discard;'.format(opac)) # frag.write('fragColor = vec4(0.0);') make_mesh.make_finalize(con_depth) return con_depth
def make_gi(context_id): con_voxel = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'always', 'cull_mode': 'none', 'color_write_red': False, 'color_write_green': False, 'color_write_blue': False, 'color_write_alpha': False, 'conservative_raster': True }) wrd = bpy.data.worlds['Arm'] is_shadows = not '_NoShadows' in wrd.world_defs vert = con_voxel.make_vert() frag = con_voxel.make_frag() geom = con_voxel.make_geom() tesc = None tese = None geom.ins = vert.outs frag.ins = geom.outs frag.add_include('../../Shaders/compiled.glsl') frag.add_include('../../Shaders/std/math.glsl') frag.add_include('../../Shaders/std/imageatomic.glsl') frag.write_header('#extension GL_ARB_shader_image_load_store : enable') rpdat = arm.utils.get_rp() if rpdat.rp_voxelgi_hdr: frag.add_uniform('layout(rgba16) image3D voxels') else: # frag.add_uniform('layout(rgba8) image3D voxels') frag.add_uniform('layout(r32ui) uimage3D voxels') frag.add_uniform('vec3 lightPos', '_lampPosition') frag.add_uniform('vec3 lightColor', '_lampColorVoxel') frag.add_uniform('int lightType', '_lampType') frag.add_uniform('vec3 lightDir', '_lampDirection') frag.write('if (abs(voxposition.z) > ' + rpdat.rp_voxelgi_resolution_z + ' || abs(voxposition.x) > 1 || abs(voxposition.y) > 1) return;') frag.write('vec3 wposition = voxposition * voxelgiHalfExtents;') if rpdat.arm_voxelgi_revoxelize and rpdat.arm_voxelgi_camera: frag.add_uniform('vec3 eyeSnap', '_cameraPositionSnap') frag.write('wposition += eyeSnap;') frag.write('float visibility = 1.0;') frag.write('vec3 lp = lightPos - wposition;') frag.write('vec3 l;') frag.write('if (lightType == 0) l = lightDir;') frag.write( 'else { l = normalize(lp); visibility *= attenuate(distance(wposition, lightPos)); }' ) frag.write('float dotNL = max(dot(wnormal, l), 0.0);') frag.write('if (dotNL == 0.0) return;') if is_shadows: frag.add_include('../../Shaders/std/shadows.glsl') frag.add_uniform('sampler2D shadowMap', included=True) frag.add_uniform('samplerCube shadowMapCube', included=True) frag.add_uniform('int lightShadow', '_lampCastShadow') frag.add_uniform('vec2 lightProj', '_lampPlaneProj') frag.add_uniform('float shadowsBias', '_lampShadowsBias') frag.write('if (lightShadow == 1 && lampPos.w > 0.0) {') frag.write(' vec3 lpos = lampPos.xyz / lampPos.w;') # frag.write(' if (lpos.x < 0.0 || lpos.y < 0.0 || lpos.x > 1.0 || lpos.y > 1.0) return;') # Note: shadowmap bound for sun lamp is tight behind the camera - can cause darkening no close surfaces frag.write( ' if (texture(shadowMap, lpos.xy).r < lpos.z - shadowsBias) visibility = 0.0;' ) # frag.write(' visibility = PCF(lpos.xy, lpos.z - shadowsBias);') frag.write('}') frag.write( 'else if (lightShadow == 2) visibility *= float(texture(shadowMapCube, -l).r + shadowsBias > lpToDepth(lp, lightProj));' ) # frag.write('if (lightType == 2) {') # frag.write(' float spotEffect = dot(lightDir, l);') # frag.write(' if (spotEffect < spotlightData.x) {') # frag.write(' visibility *= smoothstep(spotlightData.y, spotlightData.x, spotEffect);') # frag.write(' }') # frag.write('}') # 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));') # frag.write(' float ltcspec = ltcEvaluate(n, vVec, dotNV, wposition, invM, lampArea0, lampArea1, lampArea2, lampArea3);') # frag.write(' ltcspec *= texture(sltcMag, tuv).a;') # frag.write(' float ltcdiff = ltcEvaluate(n, vVec, dotNV, wposition, mat3(1.0), lampArea0, lampArea1, lampArea2, lampArea3);') # frag.write(' direct = albedo * ltcdiff + ltcspec;') # frag.write('}') # frag.write('else {') # frag.tab += 1 frag.write('vec3 basecol;') frag.write('float roughness;') # frag.write('float metallic;') # frag.write('float occlusion;') # parse_opacity = rpdat.arm_voxelgi_refraction if parse_opacity: frag.write('float opacity;') frag.write('float dotNV = 0.0;') cycles.parse(mat_state.nodes, con_voxel, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity, parse_displacement=False, basecol_only=True) # Voxelized particles particle = mat_state.material.arm_particle if particle == 'gpu': # make_particle.write(vert, particle_info=cycles.particle_info) frag.write_pre = True frag.write('const float p_index = 0;') frag.write('const float p_age = 0;') frag.write('const float p_lifetime = 0;') frag.write('const vec3 p_location = vec3(0);') frag.write('const float p_size = 0;') frag.write('const vec3 p_velocity = vec3(0);') frag.write('const vec3 p_angular_velocity = vec3(0);') frag.write_pre = False if not frag.contains('vec3 n ='): frag.write_pre = True frag.write('vec3 n;') frag.write_pre = False export_mpos = frag.contains( 'mposition') and not frag.contains('vec3 mposition') if export_mpos: vert.add_out('vec3 mpositionGeom') vert.write_pre = True vert.write('mpositionGeom = pos;') vert.write_pre = False vert.add_uniform('mat4 W', '_worldMatrix') vert.add_uniform('mat3 N', '_normalMatrix') vert.add_out('vec3 voxpositionGeom') vert.add_out('vec3 wnormalGeom') vert.add_include('../../Shaders/compiled.glsl') if con_voxel.is_elem('col'): vert.add_out('vec3 vcolorGeom') vert.write('vcolorGeom = col;') if con_voxel.is_elem('tex'): vert.add_out('vec2 texCoordGeom') vert.write('texCoordGeom = tex;') if rpdat.arm_voxelgi_revoxelize and rpdat.arm_voxelgi_camera: vert.add_uniform('vec3 eyeSnap', '_cameraPositionSnap') vert.write( 'voxpositionGeom = (vec3(W * vec4(pos, 1.0)) - eyeSnap) / voxelgiHalfExtents;' ) else: vert.write( 'voxpositionGeom = vec3(W * vec4(pos, 1.0)) / voxelgiHalfExtents;') vert.write('wnormalGeom = normalize(N * nor);') # vert.write('gl_Position = vec4(0.0, 0.0, 0.0, 1.0);') if is_shadows: vert.add_out('vec4 lampPosGeom') if '_CSM' in wrd.world_defs: vert.add_include('../../Shaders/compiled.glsl') vert.add_include('../../Shaders/std/shadows.glsl') vert.add_uniform('vec4 casData[shadowmapCascades * 4 + 4]', '_cascadeData', included=True) # TODO: Using second cascade vert.write( 'mat4 LWVP = mat4(casData[4 + 0], casData[4 + 1], casData[4 + 2], casData[4 + 3]);' ) else: vert.add_uniform('mat4 LWVP', '_biasLampWorldViewProjectionMatrix') vert.write('lampPosGeom = LWVP * vec4(pos, 1.0);') geom.add_out('vec3 voxposition') geom.add_out('vec3 wnormal') if is_shadows: geom.add_out('vec4 lampPos') if con_voxel.is_elem('col'): geom.add_out('vec3 vcolor') if con_voxel.is_elem('tex'): geom.add_out('vec2 texCoord') if export_mpos: geom.add_out('vec3 mposition') geom.write('const vec3 p1 = voxpositionGeom[1] - voxpositionGeom[0];') geom.write('const vec3 p2 = voxpositionGeom[2] - voxpositionGeom[0];') geom.write('const vec3 p = abs(cross(p1, p2));') geom.write('for (uint i = 0; i < 3; ++i) {') geom.write(' voxposition = voxpositionGeom[i];') geom.write(' wnormal = wnormalGeom[i];') if is_shadows: geom.write(' lampPos = lampPosGeom[i];') if con_voxel.is_elem('col'): geom.write(' vcolor = vcolorGeom[i];') if con_voxel.is_elem('tex'): geom.write(' texCoord = texCoordGeom[i];') if export_mpos: geom.write(' mposition = mpositionGeom[i];') geom.write(' if (p.z > p.x && p.z > p.y) {') geom.write( ' gl_Position = vec4(voxposition.x, voxposition.y, 0.0, 1.0);') geom.write(' }') geom.write(' else if (p.x > p.y && p.x > p.z) {') geom.write( ' gl_Position = vec4(voxposition.y, voxposition.z, 0.0, 1.0);') geom.write(' }') geom.write(' else {') geom.write( ' gl_Position = vec4(voxposition.x, voxposition.z, 0.0, 1.0);') geom.write(' }') geom.write(' EmitVertex();') geom.write('}') geom.write('EndPrimitive();') if cycles.emission_found: frag.write('vec3 color = basecol;') else: frag.write('vec3 color = basecol * visibility * lightColor * dotNL;') frag.write('vec3 voxel = voxposition * 0.5 + 0.5;') if rpdat.arm_voxelgi_emission: frag.write( 'color = min(color * 0.9, vec3(0.9)) + min(color / 200.0, 0.1);' ) # Higher range to allow emission frag.write('color = clamp(color, vec3(0.0), vec3(1.0));') if rpdat.rp_voxelgi_hdr: frag.write( 'imageStore(voxels, ivec3(voxelgiResolution * voxel), vec4(color, 1.0));' ) else: frag.write('uint val = convVec4ToRGBA8(vec4(color, 1.0) * 255);') frag.write( 'imageAtomicMax(voxels, ivec3(voxelgiResolution * voxel), val);') # frag.write('imageStore(voxels, ivec3(voxelgiResolution * voxel), vec4(color, 1.0));') # frag.write('imageAtomicRGBA8Avg(voxels, ivec3(voxelgiResolution * voxel), vec4(color, 1.0));') # frag.write('ivec3 coords = ivec3(voxelgiResolution * voxel);') # if parse_opacity: # frag.write('vec4 val = vec4(color, opacity);') # else: # frag.write('vec4 val = vec4(color, 1.0);') # frag.write('val *= 255.0;') # frag.write('uint newVal = encUnsignedNibble(convVec4ToRGBA8(val), 1);') # frag.write('uint prevStoredVal = 0;') # frag.write('uint currStoredVal;') # # frag.write('int counter = 0;') # # frag.write('while ((currStoredVal = imageAtomicCompSwap(voxels, coords, prevStoredVal, newVal)) != prevStoredVal && counter < 16) {') # frag.write('while ((currStoredVal = imageAtomicCompSwap(voxels, coords, prevStoredVal, newVal)) != prevStoredVal) {') # frag.write(' vec4 rval = convRGBA8ToVec4(currStoredVal & 0xFEFEFEFE);') # frag.write(' uint n = decUnsignedNibble(currStoredVal);') # frag.write(' rval = rval * n + val;') # frag.write(' rval /= ++n;') # frag.write(' rval = round(rval / 2) * 2;') # frag.write(' newVal = encUnsignedNibble(convVec4ToRGBA8(rval), n);') # frag.write(' prevStoredVal = currStoredVal;') # # frag.write(' counter++;') # frag.write('}') # frag.write('val.rgb *= 255.0f;') # frag.write('uint newVal = convVec4ToRGBA8(val);') # frag.write('uint prevStoredVal = 0;') # frag.write('uint curStoredVal;') # frag.write('while ((curStoredVal = imageAtomicCompSwap(voxels, coords, prevStoredVal, newVal)) != prevStoredVal) {') # frag.write(' prevStoredVal = curStoredVal;') # frag.write(' vec4 rval = convRGBA8ToVec4(curStoredVal);') # frag.write(' rval.xyz = (rval.xyz * rval.w);') # frag.write(' vec4 curValF = rval + val;') # frag.write(' curValF.xyz /= (curValF.w);') # frag.write(' newVal = convVec4ToRGBA8(curValF);') # frag.write('}') return con_voxel
def make_base(con_mesh, parse_opacity): global is_displacement global write_material_attribs global write_material_attribs_post global write_vertex_attribs wrd = bpy.data.worlds['Arm'] vert = con_mesh.make_vert() frag = con_mesh.make_frag() geom = None tesc = None tese = None vert.add_uniform('mat3 N', '_normalMatrix') vert.write_attrib('vec4 spos = vec4(pos.xyz, 1.0);') vattr_written = False rpdat = arm.utils.get_rp() is_displacement = mat_utils.disp_linked(mat_state.output_node) if is_displacement: if rpdat.arm_rp_displacement == 'Vertex': frag.ins = vert.outs else: # Tessellation tesc = con_mesh.make_tesc() tese = con_mesh.make_tese() tesc.ins = vert.outs tese.ins = tesc.outs frag.ins = tese.outs make_tess.tesc_levels(tesc, rpdat.arm_tess_mesh_inner, rpdat.arm_tess_mesh_outer) make_tess.interpolate(tese, 'wposition', 3, declare_out=True) make_tess.interpolate(tese, 'wnormal', 3, declare_out=True, normalize=True) # No displacement else: frag.ins = vert.outs if write_vertex_attribs != None: vattr_written = write_vertex_attribs(vert) frag.add_include('compiled.inc') written = False if write_material_attribs != None: written = write_material_attribs(con_mesh, frag) if written == False: frag.write('vec3 basecol;') frag.write('float roughness;') frag.write('float metallic;') frag.write('float occlusion;') frag.write('float specular;') if '_Emission' in wrd.world_defs: frag.write('float emission;') if parse_opacity: frag.write('float opacity;') cycles.parse(mat_state.nodes, con_mesh, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity) if write_material_attribs_post != None: write_material_attribs_post(con_mesh, frag) vert.add_out('vec3 wnormal') make_attrib.write_norpos(con_mesh, vert) frag.write_attrib('vec3 n = normalize(wnormal);') if not is_displacement and not vattr_written: make_attrib.write_vertpos(vert) make_attrib.write_tex_coords(con_mesh, vert, frag, tese) if con_mesh.is_elem('col'): vert.add_out('vec3 vcolor') vert.write_attrib('vcolor = col.rgb;') if tese is not None: tese.write_pre = True make_tess.interpolate(tese, 'vcolor', 3, declare_out=frag.contains('vcolor')) tese.write_pre = False if con_mesh.is_elem('tang'): if tese is not None: tese.add_out('mat3 TBN') tese.write_attrib( 'vec3 wbitangent = normalize(cross(wnormal, wtangent));') tese.write_attrib('TBN = mat3(wtangent, wbitangent, wnormal);') else: vert.add_out('mat3 TBN') vert.write_attrib('vec3 tangent = normalize(N * tang.xyz);') vert.write_attrib( 'vec3 bitangent = normalize(cross(wnormal, tangent));') vert.write_attrib('TBN = mat3(tangent, bitangent, wnormal);') if is_displacement: if rpdat.arm_rp_displacement == 'Vertex': sh = vert else: sh = tese if (con_mesh.is_elem('ipos')): vert.write('wposition = vec4(W * spos).xyz;') sh.add_uniform('mat4 VP', '_viewProjectionMatrix') sh.write('wposition += wnormal * disp;') sh.write('gl_Position = VP * vec4(wposition, 1.0);')
def make_mesh_pass(rpass): con = { 'name': rpass, 'depth_write': True, 'compare_mode': 'less', 'cull_mode': 'clockwise' } con_mesh = mat_state.data.add_context(con) mat_state.con_mesh = con_mesh wrd = bpy.data.worlds['Arm'] vert = con_mesh.make_vert() frag = con_mesh.make_frag() geom = None tesc = None tese = None vert.add_uniform('mat3 N', '_normalMatrix') vert.write_attrib('vec4 spos = vec4(pos, 1.0);') frag.ins = vert.outs frag.add_include('compiled.glsl') frag.add_uniform('vec3 lightDir', '_lampDirection') frag.add_uniform('vec3 lightColor', '_lampColor') frag.add_uniform('float envmapStrength', link='_envmapStrength') frag.write('float visibility = 1.0;') frag.write('float dotNL = max(dot(n, lightDir), 0.0);') is_shadows = not '_NoShadows' in wrd.world_defs if is_shadows: vert.add_out('vec4 lampPos') vert.add_uniform('mat4 LWVP', '_biasLampWorldViewProjectionMatrix') vert.write('lampPos = LWVP * spos;') frag.add_include('std/shadows.glsl') frag.add_uniform('sampler2D shadowMap') frag.add_uniform('float shadowsBias', '_lampShadowsBias') frag.add_uniform('bool receiveShadow') frag.write(' if (receiveShadow && lampPos.w > 0.0) {') frag.write(' vec3 lPos = lampPos.xyz / lampPos.w;') frag.write(' const vec2 smSize = shadowmapSize;') frag.write( ' visibility *= PCF(shadowMap, lPos.xy, lPos.z - shadowsBias, smSize);' ) # frag.write(' const float texelSize = 1.0 / shadowmapSize.x;') # frag.write(' visibility = 0.0;') # frag.write(' visibility += float(texture(shadowMap, lPos.xy).r + shadowsBias > lPos.z);') # frag.write(' visibility += float(texture(shadowMap, lPos.xy + vec2(texelSize, 0.0)).r + shadowsBias > lPos.z) * 0.5;') # frag.write(' visibility += float(texture(shadowMap, lPos.xy + vec2(-texelSize, 0.0)).r + shadowsBias > lPos.z) * 0.25;') # frag.write(' visibility += float(texture(shadowMap, lPos.xy + vec2(0.0, texelSize)).r + shadowsBias > lPos.z) * 0.5;') # frag.write(' visibility += float(texture(shadowMap, lPos.xy + vec2(0.0, -texelSize)).r + shadowsBias > lPos.z) * 0.25;') # frag.write(' visibility /= 2.5;') frag.write(' }') frag.write('vec3 basecol;') frag.write('float roughness;') frag.write('float metallic;') frag.write('float occlusion;') frag.write('float specular;') arm_discard = mat_state.material.arm_discard if arm_discard: frag.write('float opacity;') cycles.parse(mat_state.nodes, con_mesh, vert, frag, geom, tesc, tese, parse_opacity=arm_discard, parse_displacement=False) make_mesh.write_vertpos(vert) if arm_discard: opac = mat_state.material.arm_discard_opacity frag.write('if (opacity < {0}) discard;'.format(opac)) if con_mesh.is_elem('tex'): vert.add_out('vec2 texCoord') vert.write('texCoord = tex;') if con_mesh.is_elem('col'): vert.add_out('vec3 vcolor') vert.write('vcolor = col;') if con_mesh.is_elem('tang'): vert.add_out('mat3 TBN') make_mesh.write_norpos(con_mesh, vert, declare=True) vert.write('vec3 tangent = normalize(N * tang);') vert.write('vec3 bitangent = normalize(cross(wnormal, tangent));') vert.write('TBN = mat3(tangent, bitangent, wnormal);') else: vert.add_out('vec3 wnormal') make_mesh.write_norpos(con_mesh, vert) frag.write_attrib('vec3 n = normalize(wnormal);') frag.add_out('vec4 fragColor') frag.write( 'vec3 direct = basecol * step(0.5, dotNL) * visibility * lightColor;') frag.write('vec3 indirect = basecol * envmapStrength;') frag.write('fragColor = vec4(direct + indirect, 1.0);') if '_LDR' in wrd.world_defs: frag.write('fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2));') assets.vs_equal(con_mesh, assets.shader_cons['mesh_vert']) make_mesh.make_finalize(con_mesh) return con_mesh
def make_gi(context_id): con_voxel = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'always', 'cull_mode': 'none', 'color_write_red': False, 'color_write_green': False, 'color_write_blue': False, 'color_write_alpha': False, 'conservative_raster': True }) wrd = bpy.data.worlds['Arm'] if '_NoShadows' in wrd.world_defs: is_shadows = False else: is_shadows = True vert = con_voxel.make_vert() frag = con_voxel.make_frag() geom = con_voxel.make_geom() tesc = None tese = None geom.ins = vert.outs frag.ins = geom.outs frag.write('vec3 lp = lightPos - wposition * voxelgiDimensions;') frag.write('vec3 l = normalize(lp);') frag.write('float visibility = 1.0;') frag.add_include('../../Shaders/compiled.glsl') if is_shadows: frag.add_include('../../Shaders/std/shadows.glsl') frag.add_uniform('sampler2D shadowMap', included=True) frag.add_uniform('samplerCube shadowMapCube', included=True) frag.add_uniform('int lightShadow', '_lampCastShadow') frag.add_uniform('vec2 lightPlane', '_lampPlane') frag.add_uniform('float shadowsBias', '_lampShadowsBias') frag.write('if (lightShadow == 1 && lampPos.w > 0.0) {') frag.write(' vec3 lpos = lampPos.xyz / lampPos.w;') frag.write(' if (texture(shadowMap, lpos.xy).r < lpos.z - shadowsBias) visibility = 0.0;') frag.write('}') frag.write('else if (lightShadow == 2) visibility = float(texture(shadowMapCube, -l).r + shadowsBias > lpToDepth(lp, lightPlane));') else: frag.write('int lightShadow = 0;') frag.add_include('../../Shaders/std/math.glsl') frag.add_include('../../Shaders/std/imageatomic.glsl') frag.write_header('#extension GL_ARB_shader_image_load_store : enable') rpdat = arm.utils.get_rp() # if rpdat.rp_voxelgi_hdr: # frag.add_uniform('layout(RGBA16) image3D voxels') # else: # frag.add_uniform('layout(RGBA8) image3D voxels') frag.add_uniform('layout(r32ui) uimage3D voxels') frag.add_uniform('vec3 lightPos', '_lampPosition') frag.add_uniform('vec3 lightColor', '_lampColorVoxel') frag.write('if (!isInsideCube(wposition)) return;') frag.write('vec3 basecol;') frag.write('float roughness;') # frag.write('float metallic;') # frag.write('float occlusion;') # parse_opacity = rpdat.arm_voxelgi_refraction if parse_opacity: frag.write('float opacity;') frag.write_pre = True frag.write('mat3 TBN;') # TODO: discard, parse basecolor only frag.write_pre = False frag.write('float dotNV = 0.0;') frag.write('float dotNL = max(dot(wnormal, l), 0.0);') cycles.parse(mat_state.nodes, con_voxel, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity, parse_displacement=False) if not frag.contains('vec3 n ='): frag.write_pre = True frag.write('vec3 n;') frag.write_pre = False if rpdat.arm_voxelgi_camera: vert.add_uniform('vec3 eye', '_cameraPosition') vert.add_uniform('mat4 W', '_worldMatrix') vert.add_uniform('mat3 N', '_normalMatrix') vert.add_out('vec3 wpositionGeom') vert.add_out('vec3 wnormalGeom') vert.add_include('../../Shaders/compiled.glsl') if con_voxel.is_elem('tex'): vert.add_out('vec2 texCoordGeom') vert.write('texCoordGeom = tex;') if rpdat.arm_voxelgi_camera: vert.write('const float step = voxelgiDimensions / voxelgiResolution;') # TODO: Pass as uniform vert.write('vec3 eyeSnap = ivec3(eye / step) * step;') # TODO: Pass as uniform vert.write('wpositionGeom = (vec3(W * vec4(pos, 1.0)) - eyeSnap) / voxelgiDimensions;') else: vert.write('wpositionGeom = vec3(W * vec4(pos, 1.0)) / voxelgiDimensions;') vert.write('wnormalGeom = normalize(N * nor);') vert.write('gl_Position = vec4(0.0, 0.0, 0.0, 1.0);') if is_shadows: vert.add_out('vec4 lampPosGeom') vert.add_uniform('mat4 LWVP', '_biasLampWorldViewProjectionMatrix') vert.write('lampPosGeom = LWVP * vec4(pos, 1.0);') geom.add_out('vec3 wposition') geom.add_out('vec3 wnormal') if is_shadows: geom.add_out('vec4 lampPos') if con_voxel.is_elem('tex'): geom.add_out('vec2 texCoord') geom.write('const vec3 p1 = wpositionGeom[1] - wpositionGeom[0];') geom.write('const vec3 p2 = wpositionGeom[2] - wpositionGeom[0];') geom.write('const vec3 p = abs(cross(p1, p2));') geom.write('for (uint i = 0; i < 3; ++i) {') geom.write(' wposition = wpositionGeom[i];') geom.write(' wnormal = wnormalGeom[i];') if is_shadows: geom.write(' lampPos = lampPosGeom[i];') if con_voxel.is_elem('tex'): geom.write(' texCoord = texCoordGeom[i];') geom.write(' if (p.z > p.x && p.z > p.y) {') geom.write(' gl_Position = vec4(wposition.x, wposition.y, 0.0, 1.0);') geom.write(' }') geom.write(' else if (p.x > p.y && p.x > p.z) {') geom.write(' gl_Position = vec4(wposition.y, wposition.z, 0.0, 1.0);') geom.write(' }') geom.write(' else {') geom.write(' gl_Position = vec4(wposition.x, wposition.z, 0.0, 1.0);') geom.write(' }') geom.write(' EmitVertex();') geom.write('}') geom.write('EndPrimitive();') if cycles.emission_found: frag.write('vec3 color = basecol;') else: frag.write('vec3 color = basecol * visibility * lightColor * dotNL * attenuate(distance(wposition * voxelgiDimensions, lightPos));') frag.write('vec3 voxel = wposition * 0.5 + vec3(0.5);') if rpdat.arm_material_model == 'Cycles': frag.write('color = min(color * 0.9, vec3(0.9)) + min(color / 200.0, 0.1);') # Higher range to allow emission # if rpdat.rp_voxelgi_hdr: # frag.write('imageStore(voxels, ivec3(voxelgiResolution * voxel), vec4(color, 1.0));') # else: frag.write('color = clamp(color, vec3(0.0), vec3(1.0));') # frag.write('uint val = convVec4ToRGBA8(vec4(color, 1.0) * 255);') # frag.write('imageAtomicMax(voxels, ivec3(voxelgiResolution * voxel), val);') # frag.write('imageStore(voxels, ivec3(voxelgiResolution * voxel), vec4(color, 1.0));') # frag.write('imageAtomicRGBA8Avg(voxels, ivec3(voxelgiResolution * voxel), vec4(color, 1.0));') frag.write('ivec3 coords = ivec3(voxelgiResolution * voxel);') if parse_opacity: frag.write('vec4 val = vec4(color, opacity);') else: frag.write('vec4 val = vec4(color, 1.0);') frag.write('val *= 255.0;') frag.write('uint newVal = encUnsignedNibble(convVec4ToRGBA8(val), 1);') frag.write('uint prevStoredVal = 0;') frag.write('uint currStoredVal;') # frag.write('int counter = 0;') # frag.write('while ((currStoredVal = imageAtomicCompSwap(voxels, coords, prevStoredVal, newVal)) != prevStoredVal && counter < 16) {') frag.write('while ((currStoredVal = imageAtomicCompSwap(voxels, coords, prevStoredVal, newVal)) != prevStoredVal) {') frag.write(' vec4 rval = convRGBA8ToVec4(currStoredVal & 0xFEFEFEFE);') frag.write(' uint n = decUnsignedNibble(currStoredVal);') frag.write(' rval = rval * n + val;') frag.write(' rval /= ++n;') frag.write(' rval = round(rval / 2) * 2;') frag.write(' newVal = encUnsignedNibble(convVec4ToRGBA8(rval), n);') frag.write(' prevStoredVal = currStoredVal;') # frag.write(' counter++;') frag.write('}') # frag.write('val.rgb *= 255.0f;') # frag.write('uint newVal = convVec4ToRGBA8(val);') # frag.write('uint prevStoredVal = 0;') # frag.write('uint curStoredVal;') # frag.write('while ((curStoredVal = imageAtomicCompSwap(voxels, coords, prevStoredVal, newVal)) != prevStoredVal) {') # frag.write(' prevStoredVal = curStoredVal;') # frag.write(' vec4 rval = convRGBA8ToVec4(curStoredVal);') # frag.write(' rval.xyz = (rval.xyz * rval.w);') # frag.write(' vec4 curValF = rval + val;') # frag.write(' curValF.xyz /= (curValF.w);') # frag.write(' newVal = convVec4ToRGBA8(curValF);') # frag.write('}') return con_voxel
def make_base(con_mesh, parse_opacity): global is_displacement global write_material_attribs global write_material_attribs_post global write_vertex_attribs vert = con_mesh.make_vert() frag = con_mesh.make_frag() geom = None tesc = None tese = None 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 tesc = con_mesh.make_tesc() tese = con_mesh.make_tese() tesc.ins = vert.outs tese.ins = tesc.outs frag.ins = tese.outs vert.add_uniform('mat4 W', '_worldMatrix') vert.add_out('vec3 wposition') vert.write('wposition = vec4(W * spos).xyz;') const = {} const['name'] = 'tessLevel' const['vec2'] = [ mat_state.material.height_tess_inner, mat_state.material.height_tess_outer ] mat_state.bind_constants.append(const) tesc.add_uniform('vec2 tessLevel') 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) # 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: vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrix') vert.write('gl_Position = WVP * spos;') frag.add_include('../../Shaders/compiled.glsl') written = False if write_material_attribs != None: written = write_material_attribs(con_mesh, frag) if written == False: frag.write('vec3 basecol;') frag.write('float roughness;') frag.write('float metallic;') frag.write('float occlusion;') if parse_opacity: frag.write('float opacity;') cycles.parse(mat_state.nodes, con_mesh, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity) if write_material_attribs_post != None: write_material_attribs_post(con_mesh, frag) if con_mesh.is_elem('tex'): vert.add_out('vec2 texCoord') vert.write('texCoord = tex;') if tese != None: # TODO: also includes texCoord1 tese.write_pre = True make_tess.interpolate(tese, 'texCoord', 2, declare_out=frag.contains('texCoord')) tese.write_pre = False if con_mesh.is_elem('tex1'): vert.add_out('vec2 texCoord1') vert.write('texCoord1 = tex1;') if tese != None: tese.write_pre = True make_tess.interpolate(tese, 'texCoord1', 2, declare_out=frag.contains('texCoord1')) tese.write_pre = False if con_mesh.is_elem('col'): vert.add_out('vec3 vcolor') vert.write('vcolor = col;') if tese != None: tese.write_pre = True make_tess.interpolate(tese, 'vcolor', 3, declare_out=frag.contains('vcolor')) tese.write_pre = False if con_mesh.is_elem('tang'): if tese != None: vert.add_out('vec3 wnormal') vert.add_out('vec3 wtangent') write_norpos(con_mesh, vert) vert.write('wtangent = normalize(N * tang);') tese.add_out('mat3 TBN') make_tess.interpolate(tese, 'wtangent', 3, normalize=True) tese.write( 'vec3 wbitangent = normalize(cross(wnormal, wtangent));') tese.write('TBN = mat3(wtangent, wbitangent, wnormal);') else: vert.add_out('mat3 TBN') write_norpos(con_mesh, vert, declare=True) vert.write('vec3 tangent = normalize(N * tang);') vert.write('vec3 bitangent = normalize(cross(wnormal, tangent));') vert.write('TBN = mat3(tangent, bitangent, wnormal);') else: vert.add_out('vec3 wnormal') write_norpos(con_mesh, vert) frag.write_pre = True frag.write_main_header('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 make(context_id): con_voxel = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'always', 'cull_mode': 'none', 'color_write_red': False, 'color_write_green': False, 'color_write_blue': False, 'color_write_alpha': False, 'conservative_raster': True }) wrd = bpy.data.worlds['Arm'] if '_NoShadows' in wrd.world_defs: is_shadows = False else: is_shadows = True vert = con_voxel.make_vert() frag = con_voxel.make_frag() geom = con_voxel.make_geom() tesc = None tese = None geom.ins = vert.outs frag.ins = geom.outs frag.write('vec3 lp = lightPos - wposition * voxelgiDimensions.x;') frag.write('vec3 l = normalize(lp);') frag.write('float visibility = 1.0;') frag.add_include('../../Shaders/compiled.glsl') if is_shadows: frag.add_include('../../Shaders/std/shadows.glsl') frag.add_uniform('sampler2D shadowMap', included=True) frag.add_uniform('samplerCube shadowMapCube', included=True) frag.add_uniform('int lightShadow', '_lampCastShadow') frag.add_uniform('vec2 lightPlane', '_lampPlane') frag.add_uniform('float shadowsBias', '_lampShadowsBias') frag.write('if (lightShadow == 1 && lampPos.w > 0.0) {') frag.write(' vec3 lpos = lampPos.xyz / lampPos.w;') frag.write( ' if (texture(shadowMap, lpos.xy).r < lpos.z - shadowsBias) visibility = 0.0;' ) frag.write('}') frag.write( 'else if (lightShadow == 2) visibility = float(texture(shadowMapCube, -l).r + shadowsBias > lpToDepth(lp, lightPlane));' ) else: frag.write('int lightShadow = 0;') frag.add_include('../../Shaders/std/math.glsl') frag.write_header('#extension GL_ARB_shader_image_load_store : enable') frag.add_uniform('layout(RGBA8) image3D voxels') frag.add_uniform('vec3 lightPos', '_lampPosition') frag.add_uniform('vec3 lightColor', '_lampColor') frag.write('if (!isInsideCube(wposition)) return;') frag.write('vec3 basecol;') frag.write('float roughness;') # frag.write('float metallic;') # frag.write('float occlusion;') # # frag.write('float opacity;') # frag.write_pre = True frag.write('mat3 TBN;') # TODO: discard, parse basecolor only frag.write_pre = False frag.write('float dotNV = 0.0;') frag.write('float dotNL = max(dot(wnormal, l), 0.0);') cycles.parse(mat_state.nodes, con_voxel, vert, frag, geom, tesc, tese, parse_opacity=False, parse_displacement=False) vert.add_uniform('mat4 W', '_worldMatrix') vert.add_uniform('mat3 N', '_normalMatrix') vert.add_out('vec3 wpositionGeom') vert.add_out('vec3 wnormalGeom') vert.add_include('../../Shaders/compiled.glsl') if con_voxel.is_elem('tex'): vert.add_out('vec2 texCoordGeom') vert.write('texCoordGeom = tex;') vert.write( 'wpositionGeom = vec3(W * vec4(pos, 1.0)) / voxelgiDimensions.x;') vert.write('wnormalGeom = normalize(N * nor);') vert.write('gl_Position = vec4(0.0, 0.0, 0.0, 1.0);') if is_shadows: vert.add_out('vec4 lampPosGeom') vert.add_uniform('mat4 LWVP', '_biasLampWorldViewProjectionMatrix') vert.write('lampPosGeom = LWVP * vec4(pos, 1.0);') geom.add_out('vec3 wposition') geom.add_out('vec3 wnormal') if is_shadows: geom.add_out('vec4 lampPos') if con_voxel.is_elem('tex'): geom.add_out('vec2 texCoord') geom.write('const vec3 p1 = wpositionGeom[1] - wpositionGeom[0];') geom.write('const vec3 p2 = wpositionGeom[2] - wpositionGeom[0];') geom.write('const vec3 p = abs(cross(p1, p2));') geom.write('for (uint i = 0; i < 3; ++i) {') geom.write(' wposition = wpositionGeom[i];') geom.write(' wnormal = wnormalGeom[i];') if is_shadows: geom.write(' lampPos = lampPosGeom[i];') if con_voxel.is_elem('tex'): geom.write(' texCoord = texCoordGeom[i];') geom.write(' if (p.z > p.x && p.z > p.y) {') geom.write( ' gl_Position = vec4(wposition.x, wposition.y, 0.0, 1.0);') geom.write(' }') geom.write(' else if (p.x > p.y && p.x > p.z) {') geom.write( ' gl_Position = vec4(wposition.y, wposition.z, 0.0, 1.0);') geom.write(' }') geom.write(' else {') geom.write( ' gl_Position = vec4(wposition.x, wposition.z, 0.0, 1.0);') geom.write(' }') geom.write(' EmitVertex();') geom.write('}') geom.write('EndPrimitive();') frag.write('vec3 color;') frag.write( 'if (lightShadow > 0) color = basecol * visibility * lightColor * dotNL * attenuate(distance(wposition * voxelgiDimensions.x, lightPos));' ) frag.write('else color = (basecol - 1.0);' ) # Emission only when no lamp or shadowmap is present frag.write('vec3 voxel = wposition * 0.5 + vec3(0.5);') frag.write( 'imageStore(voxels, ivec3(voxelgiResolution * voxel), vec4(color, 1.0));' ) return con_voxel
def make_forward_mobile(con_mesh): wrd = bpy.data.worlds['Arm'] vert = con_mesh.make_vert() frag = con_mesh.make_frag() geom = None tesc = None tese = None vert.add_uniform('mat3 N', '_normalMatrix') vert.write_attrib('vec4 spos = vec4(pos, 1.0);') frag.ins = vert.outs write_vertpos(vert) frag.add_include('compiled.inc') frag.write('vec3 basecol;') frag.write('float roughness;') frag.write('float metallic;') frag.write('float occlusion;') frag.write('float specular;') arm_discard = mat_state.material.arm_discard blend = mat_state.material.arm_blending is_transluc = mat_utils.is_transluc(mat_state.material) parse_opacity = (blend and is_transluc) or arm_discard if parse_opacity: frag.write('float opacity;') cycles.parse(mat_state.nodes, con_mesh, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity, parse_displacement=False) if arm_discard: opac = mat_state.material.arm_discard_opacity frag.write('if (opacity < {0}) discard;'.format(opac)) if con_mesh.is_elem('tex'): vert.add_out('vec2 texCoord') if mat_state.material.arm_tilesheet_mat: vert.add_uniform('vec2 tilesheetOffset', '_tilesheetOffset') vert.write('texCoord = tex + tilesheetOffset;') else: vert.write('texCoord = tex;') if con_mesh.is_elem('col'): vert.add_out('vec3 vcolor') vert.write('vcolor = col;') if con_mesh.is_elem('tang'): vert.add_out('mat3 TBN') write_norpos(con_mesh, vert, declare=True) vert.write('vec3 tangent = normalize(N * tang);') vert.write('vec3 bitangent = normalize(cross(wnormal, tangent));') vert.write('TBN = mat3(tangent, bitangent, wnormal);') else: vert.add_out('vec3 wnormal') write_norpos(con_mesh, vert) frag.write_attrib('vec3 n = normalize(wnormal);') frag.add_include('std/math.glsl') frag.add_include('std/brdf.glsl') frag.add_out('vec4 fragColor') blend = mat_state.material.arm_blending if blend: if parse_opacity: frag.write('fragColor = vec4(basecol, opacity);') else: frag.write('fragColor = vec4(basecol, 1.0);') return is_shadows = '_ShadowMap' in wrd.world_defs frag.write('vec3 direct = vec3(0.0);') if '_Sun' in wrd.world_defs: frag.add_uniform('vec3 sunCol', '_sunColor') frag.add_uniform('vec3 sunDir', '_sunDirection') frag.write('float svisibility = 1.0;') frag.write('float sdotNL = max(dot(n, sunDir), 0.0);') if is_shadows: vert.add_out('vec4 lightPosition') vert.add_uniform('mat4 LWVP', '_biasLightWorldViewProjectionMatrix') vert.write('lightPosition = LWVP * spos;') frag.add_uniform('sampler2D shadowMap') frag.add_uniform('float shadowsBias', '_sunShadowsBias') frag.write('if (lightPosition.w > 0.0) {') frag.write(' vec3 lPos = lightPosition.xyz / lightPosition.w;') frag.write(' const float texelSize = 1.0 / shadowmapSize.x;') frag.write(' svisibility = 0.0;') frag.write(' svisibility += float(texture(shadowMap, lPos.xy).r + shadowsBias > lPos.z);') frag.write(' svisibility += float(texture(shadowMap, lPos.xy + vec2(texelSize, 0.0)).r + shadowsBias > lPos.z) * 0.5;') frag.write(' svisibility += float(texture(shadowMap, lPos.xy + vec2(-texelSize, 0.0)).r + shadowsBias > lPos.z) * 0.25;') frag.write(' svisibility += float(texture(shadowMap, lPos.xy + vec2(0.0, texelSize)).r + shadowsBias > lPos.z) * 0.5;') frag.write(' svisibility += float(texture(shadowMap, lPos.xy + vec2(0.0, -texelSize)).r + shadowsBias > lPos.z) * 0.25;') frag.write(' svisibility /= 2.5;') frag.write(' svisibility = max(svisibility, 0.2);') # frag.write(' svisibility = max(float(texture(shadowMap, lPos.xy).r + shadowsBias > lPos.z), 0.5);') frag.write('}') frag.write('direct += basecol * sdotNL * sunCol * svisibility;') if '_SinglePoint' in wrd.world_defs: frag.add_uniform('vec3 pointPos', '_pointPosition') frag.add_uniform('vec3 pointCol', '_pointColor') frag.write('float visibility = 1.0;') frag.write('float dotNL = max(dot(n, pointPos - wposition), 0.0);') if is_shadows: vert.add_out('vec4 lightPosition') vert.add_uniform('mat4 LWVP', '_biasLightWorldViewProjectionMatrix') vert.write('lightPosition = LWVP * spos;') frag.add_uniform('sampler2D shadowMap0') frag.add_uniform('float shadowsBias', '_lightShadowsBias') frag.write('if (lightPosition.w > 0.0) {') frag.write(' vec3 lPos = lightPosition.xyz / lightPosition.w;') frag.write(' const float texelSize = 1.0 / shadowmapSize.x;') frag.write(' visibility = 0.0;') frag.write(' visibility += float(texture(shadowMap0, lPos.xy).r + shadowsBias > lPos.z);') frag.write(' visibility += float(texture(shadowMap0, lPos.xy + vec2(texelSize, 0.0)).r + shadowsBias > lPos.z) * 0.5;') frag.write(' visibility += float(texture(shadowMap0, lPos.xy + vec2(-texelSize, 0.0)).r + shadowsBias > lPos.z) * 0.25;') frag.write(' visibility += float(texture(shadowMap0, lPos.xy + vec2(0.0, texelSize)).r + shadowsBias > lPos.z) * 0.5;') frag.write(' visibility += float(texture(shadowMap0, lPos.xy + vec2(0.0, -texelSize)).r + shadowsBias > lPos.z) * 0.25;') frag.write(' visibility /= 2.5;') frag.write(' visibility = max(visibility, 0.2);') frag.write('}') frag.write('direct += basecol * dotNL * pointCol * attenuate(distance(wposition, pointPos)) * visibility;') if '_Clusters' in wrd.world_defs: frag.add_include('std/light_mobile.glsl') frag.write('vec3 albedo = basecol;') frag.write('vec3 f0 = surfaceF0(basecol, metallic);') make_cluster.write(vert, frag) if '_Irr' in wrd.world_defs: frag.add_include('std/shirr.glsl') frag.add_uniform('vec4 shirr[7]', link='_envmapIrradiance', included=True) env_str = 'shIrradiance(n)' else: env_str = '0.5' frag.add_uniform('float envmapStrength', link='_envmapStrength') frag.write('fragColor = vec4(direct + basecol * {0} * envmapStrength, 1.0);'.format(env_str)) if '_LDR' in wrd.world_defs: frag.write('fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2));')
def make_forward_mobile(con_mesh): wrd = bpy.data.worlds['Arm'] vert = con_mesh.make_vert() frag = con_mesh.make_frag() geom = None tesc = None tese = None vert.add_uniform('mat3 N', '_normalMatrix') vert.write_attrib('vec4 spos = vec4(pos.xyz, 1.0);') frag.ins = vert.outs frag.add_include('compiled.inc') frag.write('vec3 basecol;') frag.write('float roughness;') frag.write('float metallic;') frag.write('float occlusion;') frag.write('float specular;') if '_Emission' in wrd.world_defs: frag.write('float emission;') arm_discard = mat_state.material.arm_discard blend = mat_state.material.arm_blending is_transluc = mat_utils.is_transluc(mat_state.material) parse_opacity = (blend and is_transluc) or arm_discard if parse_opacity: frag.write('float opacity;') cycles.parse(mat_state.nodes, con_mesh, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity, parse_displacement=False) if arm_discard: opac = mat_state.material.arm_discard_opacity frag.write('if (opacity < {0}) discard;'.format(opac)) make_attrib.write_tex_coords(con_mesh, vert, frag, tese) if con_mesh.is_elem('col'): vert.add_out('vec3 vcolor') vert.write('vcolor = col.rgb;') if con_mesh.is_elem('tang'): vert.add_out('mat3 TBN') make_attrib.write_norpos(con_mesh, vert, declare=True) vert.write('vec3 tangent = normalize(N * tang.xyz);') vert.write('vec3 bitangent = normalize(cross(wnormal, tangent));') vert.write('TBN = mat3(tangent, bitangent, wnormal);') else: vert.add_out('vec3 wnormal') make_attrib.write_norpos(con_mesh, vert) frag.write_attrib('vec3 n = normalize(wnormal);') make_attrib.write_vertpos(vert) frag.add_include('std/math.glsl') frag.add_include('std/brdf.glsl') frag.add_out('vec4 fragColor') blend = mat_state.material.arm_blending if blend: if parse_opacity: frag.write('fragColor = vec4(basecol, opacity);') else: frag.write('fragColor = vec4(basecol, 1.0);') return is_shadows = '_ShadowMap' in wrd.world_defs is_shadows_atlas = '_ShadowMapAtlas' in wrd.world_defs shadowmap_sun = 'shadowMap' if is_shadows_atlas: is_single_atlas = '_SingleAtlas' in wrd.world_defs shadowmap_sun = 'shadowMapAtlasSun' if not is_single_atlas else 'shadowMapAtlas' frag.add_uniform('vec2 smSizeUniform', '_shadowMapSize', included=True) frag.write('vec3 direct = vec3(0.0);') if '_Sun' in wrd.world_defs: frag.add_uniform('vec3 sunCol', '_sunColor') frag.add_uniform('vec3 sunDir', '_sunDirection') frag.write('float svisibility = 1.0;') frag.write('float sdotNL = max(dot(n, sunDir), 0.0);') if is_shadows: vert.add_out('vec4 lightPosition') vert.add_uniform('mat4 LWVP', '_biasLightWorldViewProjectionMatrixSun') vert.write('lightPosition = LWVP * spos;') frag.add_uniform('bool receiveShadow') frag.add_uniform(f'sampler2DShadow {shadowmap_sun}') frag.add_uniform('float shadowsBias', '_sunShadowsBias') frag.write('if (receiveShadow) {') if '_CSM' in wrd.world_defs: frag.add_include('std/shadows.glsl') frag.add_uniform('vec4 casData[shadowmapCascades * 4 + 4]', '_cascadeData', included=True) frag.add_uniform('vec3 eye', '_cameraPosition') frag.write( f'svisibility = shadowTestCascade({shadowmap_sun}, eye, wposition + n * shadowsBias * 10, shadowsBias);' ) else: frag.write('if (lightPosition.w > 0.0) {') frag.write( ' vec3 lPos = lightPosition.xyz / lightPosition.w;') if '_Legacy' in wrd.world_defs: frag.write( f' svisibility = float(texture({shadowmap_sun}, vec2(lPos.xy)).r > lPos.z - shadowsBias);' ) else: frag.write( f' svisibility = texture({shadowmap_sun}, vec3(lPos.xy, lPos.z - shadowsBias)).r;' ) frag.write('}') frag.write('}') # receiveShadow frag.write('direct += basecol * sdotNL * sunCol * svisibility;') if '_SinglePoint' in wrd.world_defs: frag.add_uniform('vec3 pointPos', '_pointPosition') frag.add_uniform('vec3 pointCol', '_pointColor') if '_Spot' in wrd.world_defs: frag.add_uniform('vec3 spotDir', link='_spotDirection') frag.add_uniform('vec3 spotRight', link='_spotRight') frag.add_uniform('vec4 spotData', link='_spotData') frag.write('float visibility = 1.0;') frag.write('vec3 ld = pointPos - wposition;') frag.write('vec3 l = normalize(ld);') frag.write('float dotNL = max(dot(n, l), 0.0);') if is_shadows: frag.add_uniform('bool receiveShadow') frag.add_uniform('float pointBias', link='_pointShadowsBias') frag.add_include('std/shadows.glsl') frag.write('if (receiveShadow) {') if '_Spot' in wrd.world_defs: vert.add_out('vec4 spotPosition') vert.add_uniform( 'mat4 LWVPSpotArray[1]', link='_biasLightWorldViewProjectionMatrixSpotArray') vert.write('spotPosition = LWVPSpotArray[0] * spos;') frag.add_uniform('sampler2DShadow shadowMapSpot[1]') frag.write('if (spotPosition.w > 0.0) {') frag.write( ' vec3 lPos = spotPosition.xyz / spotPosition.w;') if '_Legacy' in wrd.world_defs: frag.write( ' visibility = float(texture(shadowMapSpot[0], vec2(lPos.xy)).r > lPos.z - pointBias);' ) else: frag.write( ' visibility = texture(shadowMapSpot[0], vec3(lPos.xy, lPos.z - pointBias)).r;' ) frag.write('}') else: frag.add_uniform('vec2 lightProj', link='_lightPlaneProj') frag.add_uniform('samplerCubeShadow shadowMapPoint[1]') frag.write('const float s = shadowmapCubePcfSize;' ) # TODO: incorrect... frag.write( 'float compare = lpToDepth(ld, lightProj) - pointBias * 1.5;' ) frag.write('#ifdef _InvY') frag.write('l.y = -l.y;') frag.write('#endif') if '_Legacy' in wrd.world_defs: frag.write( 'visibility = float(texture(shadowMapPoint[0], vec3(-l + n * pointBias * 20)).r > compare);' ) else: frag.write( 'visibility = texture(shadowMapPoint[0], vec4(-l + n * pointBias * 20, compare)).r;' ) frag.write('}') # receiveShadow frag.write( 'direct += basecol * dotNL * pointCol * attenuate(distance(wposition, pointPos)) * visibility;' ) if '_Clusters' in wrd.world_defs: frag.add_include('std/light_mobile.glsl') frag.write('vec3 albedo = basecol;') frag.write('vec3 f0 = surfaceF0(basecol, metallic);') make_cluster.write(vert, frag) if '_Irr' in wrd.world_defs: frag.add_include('std/shirr.glsl') frag.add_uniform('vec4 shirr[7]', link='_envmapIrradiance') env_str = 'shIrradiance(n, shirr)' else: env_str = '0.5' frag.add_uniform('float envmapStrength', link='_envmapStrength') frag.write( 'fragColor = vec4(direct + basecol * {0} * envmapStrength, 1.0);'. format(env_str)) if '_LDR' in wrd.world_defs: frag.write('fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2));')
def make(context_id, rpasses): con_shadowmap = mat_state.data.add_context({ 'name': context_id, 'depth_write': True, 'compare_mode': 'less', 'cull_mode': 'clockwise', 'color_write_red': False, 'color_write_green': False, 'color_write_blue': False, 'color_write_alpha': False }) vert = con_shadowmap.make_vert() frag = con_shadowmap.make_frag() geom = None tesc = None tese = None # frag.add_out('vec4 fragColor') vert.write_main_header('vec4 spos = vec4(pos, 1.0);') # TODO: pass vbuf with proper struct vert.write('vec3 t1 = nor; // TODO: Temp for d3d') if mat_state.data.is_elem('tex'): vert.write('vec2 t2 = tex; // TODO: Temp for d3d') parse_opacity = 'translucent' in rpasses if parse_opacity: frag.write('vec3 n;') # Discard at compile time frag.write('float dotNV;') frag.write('float opacity;') if mat_state.data.is_elem('bone'): make_skin.skin_pos(vert) if mat_state.data.is_elem('off'): vert.write('spos.xyz += off;') if mat_utils.disp_linked( mat_state.output_node) and mat_state.material.height_tess_shadows: tesc = con_shadowmap.make_tesc() tese = con_shadowmap.make_tese() tesc.ins = vert.outs tese.ins = tesc.outs frag.ins = tese.outs vert.add_out('vec3 wposition') vert.add_out('vec3 wnormal') vert.add_uniform('mat4 W', '_worldMatrix') vert.add_uniform('mat3 N', '_normalMatrix') vert.write('wnormal = normalize(N * nor);') vert.write('wposition = vec4(W * spos).xyz;') const = {} const['name'] = 'tessLevel' const['vec2'] = [ mat_state.material.height_tess_shadows_inner, mat_state.material.height_tess_shadows_outer ] mat_state.bind_constants.append(const) tesc.add_uniform('vec2 tessLevel') make_tess.tesc_levels(tesc) make_tess.interpolate(tese, 'wposition', 3) make_tess.interpolate(tese, 'wnormal', 3, normalize=True) cycles.parse(mat_state.nodes, vert, frag, geom, tesc, tese, parse_surface=False, parse_opacity=parse_opacity) if mat_state.data.is_elem('tex'): vert.add_out('vec2 texCoord') vert.write('texCoord = tex;') tese.write_pre = True make_tess.interpolate(tese, 'texCoord', 2, declare_out=frag.contains('texCoord')) tese.write_pre = False if mat_state.data.is_elem('tex1'): vert.add_out('vec2 texCoord1') vert.write('texCoord1 = tex1;') tese.write_pre = True make_tess.interpolate(tese, 'texCoord1', 2, declare_out=frag.contains('texCoord1')) tese.write_pre = False if mat_state.data.is_elem('col'): vert.add_out('vec3 vcolor') vert.write('vcolor = col;') tese.write_pre = True make_tess.interpolate(tese, 'vcolor', 3, declare_out=frag.contains('vcolor')) tese.write_pre = False tese.add_uniform('mat4 LVP', '_lampViewProjectionMatrix') tese.write('wposition += wnormal * disp * 0.2;') tese.write('gl_Position = LVP * vec4(wposition, 1.0);') # No displacement else: frag.ins = vert.outs vert.add_uniform('mat4 LWVP', '_lampWorldViewProjectionMatrix') vert.write('gl_Position = LWVP * spos;') if parse_opacity: cycles.parse(mat_state.nodes, vert, frag, geom, tesc, tese, parse_surface=False, parse_opacity=True) if mat_state.data.is_elem('tex'): vert.add_out('vec2 texCoord') vert.write('texCoord = tex;') if mat_state.data.is_elem('tex1'): vert.add_out('vec2 texCoord1') vert.write('texCoord1 = tex1;') if mat_state.data.is_elem('col'): vert.add_out('vec3 vcolor') vert.write('vcolor = col;') if parse_opacity: frag.write('if (opacity < 0.5) discard;') # frag.write('fragColor = vec4(0.0);') make_mesh.make_finalize(con_shadowmap) return con_shadowmap
def make_forward_solid(con_mesh): wrd = bpy.data.worlds['Arm'] vert = con_mesh.make_vert() frag = con_mesh.make_frag() geom = None tesc = None tese = None for e in con_mesh.data['vertex_elements']: if e['name'] == 'nor': con_mesh.data['vertex_elements'].remove(e) break vert.write_attrib('vec4 spos = vec4(pos.xyz, 1.0);') frag.ins = vert.outs frag.add_include('compiled.inc') frag.write('vec3 basecol;') frag.write('float roughness;') frag.write('float metallic;') frag.write('float occlusion;') frag.write('float specular;') if '_Emission' in wrd.world_defs: frag.write('float emission;') arm_discard = mat_state.material.arm_discard blend = mat_state.material.arm_blending is_transluc = mat_utils.is_transluc(mat_state.material) parse_opacity = (blend and is_transluc) or arm_discard if parse_opacity: frag.write('float opacity;') cycles.parse(mat_state.nodes, con_mesh, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity, parse_displacement=False, basecol_only=True) if arm_discard: opac = mat_state.material.arm_discard_opacity frag.write('if (opacity < {0}) discard;'.format(opac)) if con_mesh.is_elem('tex'): vert.add_out('vec2 texCoord') vert.add_uniform('float texUnpack', link='_texUnpack') if mat_state.material.arm_tilesheet_flag: vert.add_uniform('vec2 tilesheetOffset', '_tilesheetOffset') vert.write('texCoord = tex * texUnpack + tilesheetOffset;') else: vert.write('texCoord = tex * texUnpack;') if con_mesh.is_elem('col'): vert.add_out('vec3 vcolor') vert.write('vcolor = col.rgb;') make_attrib.write_norpos(con_mesh, vert, write_nor=False) make_attrib.write_vertpos(vert) frag.add_out('vec4 fragColor') if blend and parse_opacity: frag.write('fragColor = vec4(basecol, opacity);') else: frag.write('fragColor = vec4(basecol, 1.0);') if '_LDR' in wrd.world_defs: frag.write('fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2));')
def make(context_id, rpasses, shadowmap=False): is_disp = mat_utils.disp_linked(mat_state.output_node) vs = [{'name': 'pos', 'data': 'short4norm'}] if is_disp: vs.append({'name': 'nor', 'data': 'short2norm'}) con_depth = mat_state.data.add_context({ 'name': context_id, 'vertex_elements': vs, 'depth_write': True, 'compare_mode': 'less', 'cull_mode': 'clockwise', 'color_writes_red': [False], 'color_writes_green': [False], 'color_writes_blue': [False], 'color_writes_alpha': [False] }) vert = con_depth.make_vert() frag = con_depth.make_frag() geom = None tesc = None tese = None vert.write_attrib('vec4 spos = vec4(pos.xyz, 1.0);') parse_opacity = 'translucent' in rpasses or mat_state.material.arm_discard parse_custom_particle = (cycles.node_by_name(mat_state.nodes, 'ArmCustomParticleNode') is not None) if parse_opacity: frag.write('float opacity;') if con_depth.is_elem('bone'): make_skin.skin_pos(vert) if (not is_disp and parse_custom_particle): cycles.parse(mat_state.nodes, con_depth, vert, frag, geom, tesc, tese, parse_surface=False, parse_opacity=parse_opacity) if con_depth.is_elem('ipos'): make_inst.inst_pos(con_depth, vert) rpdat = arm.utils.get_rp() if mat_state.material.arm_particle_flag and rpdat.arm_particles == 'On': make_particle.write(vert, shadowmap=shadowmap) if is_disp: if rpdat.arm_rp_displacement == 'Vertex': frag.ins = vert.outs vert.add_uniform('mat3 N', '_normalMatrix') vert.write('vec3 wnormal = normalize(N * vec3(nor.xy, pos.w));') if(con_depth.is_elem('ipos')): vert.write('wposition = vec4(W * spos).xyz;') if(con_depth.is_elem('irot')): vert.write('wnormal = transpose(inverse(mirot)) * wnormal;') cycles.parse(mat_state.nodes, con_depth, vert, frag, geom, tesc, tese, parse_surface=False, parse_opacity=parse_opacity) if con_depth.is_elem('tex'): vert.add_out('vec2 texCoord') ## vs only, remove out vert.add_uniform('float texUnpack', link='_texUnpack') vert.write_attrib('texCoord = tex * texUnpack;') if con_depth.is_elem('tex1'): vert.add_out('vec2 texCoord1') ## vs only, remove out vert.add_uniform('float texUnpack', link='_texUnpack') vert.write_attrib('texCoord1 = tex1 * texUnpack;') if con_depth.is_elem('col'): vert.add_out('vec3 vcolor') vert.write_attrib('vcolor = col.rgb;') vert.write('wposition += wnormal * disp;') if shadowmap: vert.add_uniform('mat4 LVP', '_lightViewProjectionMatrix') vert.write('gl_Position = LVP * vec4(wposition, 1.0);') else: vert.add_uniform('mat4 VP', '_viewProjectionMatrix') vert.write('gl_Position = VP * vec4(wposition, 1.0);') else: # Tessellation tesc = con_depth.make_tesc() tese = con_depth.make_tese() tesc.ins = vert.outs tese.ins = tesc.outs frag.ins = tese.outs vert.add_out('vec3 wnormal') vert.add_uniform('mat3 N', '_normalMatrix') vert.write('wnormal = normalize(N * vec3(nor.xy, pos.w));') make_tess.tesc_levels(tesc, rpdat.arm_tess_shadows_inner, rpdat.arm_tess_shadows_outer) make_tess.interpolate(tese, 'wposition', 3) make_tess.interpolate(tese, 'wnormal', 3, normalize=True) cycles.parse(mat_state.nodes, con_depth, vert, frag, geom, tesc, tese, parse_surface=False, parse_opacity=parse_opacity) if con_depth.is_elem('tex'): vert.add_out('vec2 texCoord') vert.add_uniform('float texUnpack', link='_texUnpack') vert.write('texCoord = tex * texUnpack;') tese.write_pre = True make_tess.interpolate(tese, 'texCoord', 2, declare_out=frag.contains('texCoord')) tese.write_pre = False if con_depth.is_elem('tex1'): vert.add_out('vec2 texCoord1') vert.write('texCoord1 = tex1;') tese.write_pre = True make_tess.interpolate(tese, 'texCoord1', 2, declare_out=frag.contains('texCoord1')) tese.write_pre = False if con_depth.is_elem('col'): vert.add_out('vec3 vcolor') vert.write('vcolor = col.rgb;') tese.write_pre = True make_tess.interpolate(tese, 'vcolor', 3, declare_out=frag.contains('vcolor')) tese.write_pre = False if shadowmap: tese.add_uniform('mat4 LVP', '_lightViewProjectionMatrix') tese.write('wposition += wnormal * disp;') tese.write('gl_Position = LVP * vec4(wposition, 1.0);') else: tese.add_uniform('mat4 VP', '_viewProjectionMatrix') tese.write('wposition += wnormal * disp;') tese.write('gl_Position = VP * vec4(wposition, 1.0);') # No displacement else: frag.ins = vert.outs billboard = mat_state.material.arm_billboard if shadowmap: if billboard == 'spherical': vert.add_uniform('mat4 LWVP', '_lightWorldViewProjectionMatrixSphere') elif billboard == 'cylindrical': vert.add_uniform('mat4 LWVP', '_lightWorldViewProjectionMatrixCylinder') else: # off vert.add_uniform('mat4 LWVP', '_lightWorldViewProjectionMatrix') vert.write('gl_Position = LWVP * spos;') else: 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 parse_opacity: if (not parse_custom_particle): cycles.parse(mat_state.nodes, con_depth, vert, frag, geom, tesc, tese, parse_surface=False, parse_opacity=True) if con_depth.is_elem('tex'): vert.add_out('vec2 texCoord') vert.add_uniform('float texUnpack', link='_texUnpack') if mat_state.material.arm_tilesheet_flag: vert.add_uniform('vec2 tilesheetOffset', '_tilesheetOffset') vert.write('texCoord = tex * texUnpack + tilesheetOffset;') else: vert.write('texCoord = tex * texUnpack;') if con_depth.is_elem('tex1'): vert.add_out('vec2 texCoord1') vert.write('texCoord1 = tex1;') if con_depth.is_elem('col'): vert.add_out('vec3 vcolor') vert.write('vcolor = col.rgb;') if parse_opacity: if mat_state.material.arm_discard: opac = mat_state.material.arm_discard_opacity_shadows else: opac = '1.0' frag.write('if (opacity < {0}) discard;'.format(opac)) make_finalize.make(con_depth) assets.vs_equal(con_depth, assets.shader_cons['depth_vert']) assets.fs_equal(con_depth, assets.shader_cons['depth_frag']) return con_depth
def make_base(con_mesh, parse_opacity): global is_displacement global write_material_attribs global write_material_attribs_post global write_vertex_attribs vert = con_mesh.make_vert() frag = con_mesh.make_frag() geom = None tesc = None tese = None vert.add_uniform('mat3 N', '_normalMatrix') vert.write_attrib(' vec4 spos = vec4(pos, 1.0);') vattr_written = False rpdat = arm.utils.get_rp() is_displacement = mat_utils.disp_linked(mat_state.output_node) if is_displacement: if rpdat.arm_rp_displacement == 'Vertex': frag.ins = vert.outs rid = rpdat.rp_renderer if rid == 'Deferred': vert.add_uniform('mat4 W', '_worldMatrix') vert.add_out('vec3 wposition') vert.write_attrib('wposition = vec4(W * spos).xyz;') else: # Tessellation tesc = con_mesh.make_tesc() tese = con_mesh.make_tese() tesc.ins = vert.outs tese.ins = tesc.outs frag.ins = tese.outs vert.add_uniform('mat4 W', '_worldMatrix') vert.add_out('vec3 wposition') vert.write_attrib('wposition = vec4(W * spos).xyz;') make_tess.tesc_levels(tesc, rpdat.arm_tess_mesh_inner, rpdat.arm_tess_mesh_outer) make_tess.interpolate(tese, 'wposition', 3, declare_out=True) make_tess.interpolate(tese, 'wnormal', 3, declare_out=True, normalize=True) # No displacement else: frag.ins = vert.outs if write_vertex_attribs != None: vattr_written = write_vertex_attribs(vert) frag.add_include('compiled.glsl') written = False if write_material_attribs != None: written = write_material_attribs(con_mesh, frag) if written == False: frag.write('vec3 basecol;') frag.write('float roughness;') frag.write('float metallic;') frag.write('float occlusion;') if parse_opacity: frag.write('float opacity;') cycles.parse(mat_state.nodes, con_mesh, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity) if write_material_attribs_post != None: write_material_attribs_post(con_mesh, frag) if not is_displacement and not vattr_written: write_vertpos(vert) if con_mesh.is_elem('tex'): vert.add_out('vec2 texCoord') if mat_state.material.arm_tilesheet_mat: if mat_state.material.arm_particle == 'gpu': make_particle.write_tilesheet(vert) else: vert.add_uniform('vec2 tilesheetOffset', '_tilesheetOffset') vert.write_attrib('texCoord = tex + tilesheetOffset;') else: vert.write_attrib('texCoord = tex;') if tese != None: tese.write_pre = True make_tess.interpolate(tese, 'texCoord', 2, declare_out=frag.contains('texCoord')) tese.write_pre = False if con_mesh.is_elem('tex1'): vert.add_out('vec2 texCoord1') vert.write('texCoord1 = tex1;') if tese != None: tese.write_pre = True make_tess.interpolate(tese, 'texCoord1', 2, declare_out=frag.contains('texCoord1')) tese.write_pre = False if con_mesh.is_elem('col'): vert.add_out('vec3 vcolor') vert.write('vcolor = col;') if tese != None: tese.write_pre = True make_tess.interpolate(tese, 'vcolor', 3, declare_out=frag.contains('vcolor')) tese.write_pre = False if con_mesh.is_elem('tang'): if tese != None: vert.add_out('vec3 wnormal') vert.add_out('vec3 wtangent') write_norpos(con_mesh, vert) vert.write('wtangent = normalize(N * tang);') tese.add_out('mat3 TBN') make_tess.interpolate(tese, 'wtangent', 3, normalize=True) tese.write( 'vec3 wbitangent = normalize(cross(wnormal, wtangent));') tese.write('TBN = mat3(wtangent, wbitangent, wnormal);') else: vert.add_out('mat3 TBN') write_norpos(con_mesh, vert, declare=True) vert.write('vec3 tangent = normalize(N * tang);') vert.write('vec3 bitangent = normalize(cross(wnormal, tangent));') vert.write('TBN = mat3(tangent, bitangent, wnormal);') else: vert.add_out('vec3 wnormal') write_norpos(con_mesh, vert) frag.write_attrib('vec3 n = normalize(wnormal);') if is_displacement: if rpdat.arm_rp_displacement == 'Vertex': sh = vert else: sh = tese sh.add_uniform('mat4 VP', '_viewProjectionMatrix') sh.write('wposition += wnormal * disp * 0.1;') sh.write('gl_Position = VP * vec4(wposition, 1.0);')
def make(context_id): vs = [{'name': 'pos', 'data': 'float3'}] con_decal = mat_state.data.add_context({ 'name': context_id, 'vertex_elements': vs, 'depth_write': False, 'compare_mode': 'less', 'cull_mode': 'clockwise', 'blend_source': 'source_alpha', 'blend_destination': 'inverse_source_alpha', 'blend_operation': 'add', 'color_writes_alpha': [False, False] }) vert = con_decal.make_vert() frag = con_decal.make_frag() geom = None tesc = None tese = None vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrix') vert.add_uniform('mat3 N', '_normalMatrix') vert.add_out('vec4 wvpposition') vert.add_out('vec3 wnormal') vert.write('wnormal = N * vec3(0.0, 0.0, 1.0);') vert.write('wvpposition = WVP * vec4(pos.xyz, 1.0);') vert.write('gl_Position = wvpposition;') frag.add_include('compiled.inc') frag.add_include('std/gbuffer.glsl') frag.ins = vert.outs frag.add_uniform('sampler2D gbufferD') frag.add_uniform('mat4 invVP', '_inverseViewProjectionMatrix') frag.add_uniform('mat4 invW', '_inverseWorldMatrix') frag.add_out('vec4 fragColor[2]') frag.write_attrib(' vec3 n = normalize(wnormal);') frag.write_attrib(' vec2 screenPosition = wvpposition.xy / wvpposition.w;') frag.write_attrib(' vec2 depthCoord = screenPosition * 0.5 + 0.5;') frag.write_attrib('#ifdef HLSL') frag.write_attrib(' depthCoord.y = 1.0 - depthCoord.y;') frag.write_attrib('#endif') frag.write_attrib(' float depth = texture(gbufferD, depthCoord).r * 2.0 - 1.0;') frag.write_attrib(' vec3 wpos = getPos2(invVP, depth, depthCoord);') frag.write_attrib(' vec4 mpos = invW * vec4(wpos, 1.0);') frag.write_attrib(' if (abs(mpos.x) > 1.0) discard;') frag.write_attrib(' if (abs(mpos.y) > 1.0) discard;') frag.write_attrib(' if (abs(mpos.z) > 1.0) discard;') frag.write_attrib(' vec2 texCoord = mpos.xy * 0.5 + 0.5;') frag.write('vec3 basecol;') frag.write('float roughness;') frag.write('float metallic;') frag.write('float occlusion;') frag.write('float specular;') frag.write('float opacity;') cycles.parse(mat_state.nodes, con_decal, vert, frag, geom, tesc, tese) 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);') frag.write('fragColor[0] = vec4(n.xy, packFloat(metallic, roughness), opacity);') frag.write('fragColor[1] = vec4(basecol.rgb, opacity);') make_finalize.make(con_decal) return con_decal
def make_rect(con_rect): wrd = bpy.data.worlds['Arm'] vert = con_rect.make_vert() frag = con_rect.make_frag() vert.vstruct_as_vsin = False # Rect structure is used instead vert.add_in('vec2 pos') vert.add_out('vec2 texCoordRect') vert.add_out('vec3 viewRay') vert.add_uniform('float materialID', link='_objectInfoMaterialIndex') vert.add_uniform('mat4 invVP', link='_inverseViewProjectionMatrix') vert.add_uniform('vec3 eye', link='_cameraPosition') vert.write('const vec2 madd = vec2(0.5, 0.5);') vert.write('texCoordRect = pos.xy * madd + madd;') vert.write('const float fstep = 1.0 / 16777216.0; // 24bit') # vert.write('const float fstep = 1.0 / 65536.0; // 16bit') vert.write( 'gl_Position = vec4(pos.xy, (materialID * fstep) * 2.0 - 1.0, 1.0);') vert.write('vec4 v = vec4(pos.xy, 1.0, 1.0);') vert.write('v = vec4(invVP * v);') vert.write('v.xyz /= v.w;') vert.write('viewRay = v.xyz - eye;') frag.ins = vert.outs frag.add_out('vec4 fragColor') frag.add_include('compiled.inc') frag.add_include('std/brdf.glsl') frag.add_include('std/math.glsl') frag.add_include('std/gbuffer.glsl') frag.add_include('std/shirr.glsl') frag.add_include('std/shadows.glsl') frag.add_uniform('sampler2D gbuffer0') frag.add_uniform('sampler2D gbuffer1') frag.add_uniform('sampler2D gbuffer2') frag.add_uniform('sampler2D gbufferD') frag.add_uniform('sampler2D ssaotex') frag.add_uniform('sampler2D shadowMap') frag.add_uniform('sampler2D shadowMapCube') frag.add_uniform('mat4 LWVP', link='_biasLightWorldViewProjectionMatrix') frag.add_uniform('vec3 eye', link='_cameraPosition') frag.add_uniform('vec3 eyeLook', link='_cameraLook') frag.add_uniform('vec3 lightPos', link='_lightPosition') frag.add_uniform('vec3 lightColor', link='_lightColor') frag.add_uniform('int lightShadow', link='_lightCastShadow') frag.add_uniform('vec2 lightProj', link='_lightPlaneProj') frag.add_uniform('float shadowsBias', link='_lightShadowsBias') # TODO: ifdef frag.add_uniform('float envmapStrength', link='_envmapStrength') frag.add_uniform('vec4 shirr[7]', link='_envmapIrradiance', included=True) frag.add_uniform('sampler2D senvmapRadiance', link='_envmapRadiance') frag.add_uniform('sampler2D senvmapBrdf', link='_envmapBrdf') frag.add_uniform('int envmapNumMipmaps', link='_envmapNumMipmaps') frag.write_pre = True frag.write('vec4 g0 = texture(gbuffer0, texCoordRect);') frag.write('vec4 g1 = texture(gbuffer1, texCoordRect);') frag.write('vec4 g2 = texture(gbuffer2, texCoordRect);') frag.write('float depth = texture(gbufferD, texCoordRect).r * 2.0 - 1.0;') frag.write('vec3 n;') frag.write('n.z = 1.0 - abs(g0.x) - abs(g0.y);') frag.write('n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy);') frag.write('n = normalize(n);') frag.write('vec2 texCoord = g0.zw;') frag.add_uniform('vec2 cameraProj', link='_cameraPlaneProj') frag.write( 'vec3 wposition = getPos(eye, eyeLook, viewRay, depth, cameraProj);') frag.write('vec3 vVec = normalize(eye - wposition);') frag.write_pre = False frag.write('float dotNV = dot(n, vVec);') frag.write('vec3 lp = lightPos - wposition;') frag.write('vec3 l = normalize(lp);') frag.write('float dotNL = max(dot(n, l), 0.0);') frag.write('vec3 h = normalize(vVec + l);') frag.write('float dotNH = dot(n, h);') frag.write('float dotVH = dot(vVec, h);') frag.write('float visibility = 1.0;') frag.write('vec3 basecol;') frag.write('float roughness;') frag.write('float metallic;') frag.write('float occlusion;') frag.write('float specular;') mat_state.texture_grad = True cycles.parse(mat_state.nodes, con_rect, vert, frag, None, None, None, parse_opacity=False, parse_displacement=False) mat_state.texture_grad = False frag.write('vec3 albedo = surfaceAlbedo(basecol, metallic);') frag.write('vec3 f0 = surfaceF0(basecol, metallic);') # Shadows frag.write('if (lightShadow == 1) {') frag.write(' vec4 lPos = LWVP * vec4(wposition, 1.0);') frag.write(' lPos.xyz /= lPos.w;') frag.write( ' if (lPos.x > 0.0 && lPos.y > 0.0 && lPos.x < 1.0 && lPos.y < 1.0) visibility = PCF(lPos.xy, lPos.z - shadowsBias);;' ) frag.write('}') frag.write('else if (lightShadow == 2) {') frag.write( ' visibility = PCFCube(shadowMapCube, lp, -l, shadowsBias, lightProj, n);' ) frag.write('}') frag.write('visibility *= attenuate(distance(wposition, lightPos));') frag.write( 'fragColor.rgb = lambertDiffuseBRDF(albedo, dotNL) + specularBRDF(f0, roughness, dotNL, dotNH, dotNV, dotVH) * specular;' ) frag.write('fragColor.rgb *= lightColor;') frag.write('fragColor.rgb *= visibility;') # Env frag.write( 'vec2 envBRDF = texture(senvmapBrdf, vec2(roughness, 1.0 - dotNV)).xy;' ) frag.write('vec3 envl = shIrradiance(n) / PI;') frag.write('vec3 reflectionWorld = reflect(-vVec, n);') frag.write('float lod = getMipFromRoughness(roughness, envmapNumMipmaps);') frag.write( 'vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;' ) frag.write('envl.rgb *= albedo;') frag.write('envl.rgb += prefilteredColor * (f0 * envBRDF.x + envBRDF.y);') frag.write('envl.rgb *= texture(ssaotex, texCoordRect).r;') frag.write('envl.rgb *= envmapStrength * occlusion;') frag.write('fragColor.rgb += envl;')
def make_gi(context_id): con_voxel = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'always', 'cull_mode': 'none', 'color_write_red': False, 'color_write_green': False, 'color_write_blue': False, 'color_write_alpha': False, 'conservative_raster': True }) wrd = bpy.data.worlds['Arm'] vert = con_voxel.make_vert() frag = con_voxel.make_frag() geom = con_voxel.make_geom() tesc = None tese = None geom.ins = vert.outs frag.ins = geom.outs frag.add_include('compiled.inc') frag.add_include('std/math.glsl') frag.add_include('std/imageatomic.glsl') frag.add_include('std/gbuffer.glsl') frag.write_header('#extension GL_ARB_shader_image_load_store : enable') rpdat = arm.utils.get_rp() frag.add_uniform('layout(r32ui) uimage3D voxels') frag.add_uniform('layout(r32ui) uimage3D voxelsNor') frag.write('if (abs(voxposition.z) > ' + rpdat.rp_voxelgi_resolution_z + ' || abs(voxposition.x) > 1 || abs(voxposition.y) > 1) return;') frag.write('vec3 wposition = voxposition * voxelgiHalfExtents;') if rpdat.arm_voxelgi_revoxelize and rpdat.arm_voxelgi_camera: frag.add_uniform('vec3 eyeSnap', '_cameraPositionSnap') frag.write('wposition += eyeSnap;') frag.write('vec3 basecol;') frag.write('float roughness;') # frag.write('float metallic;') # frag.write('float occlusion;') # frag.write('float specular;') # parse_opacity = rpdat.arm_voxelgi_refraction if parse_opacity: frag.write('float opacity;') frag.write('float dotNV = 0.0;') cycles.parse(mat_state.nodes, con_voxel, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity, parse_displacement=False, basecol_only=True) # Voxelized particles particle = mat_state.material.arm_particle_flag if particle and rpdat.arm_particles == 'GPU': # make_particle.write(vert, particle_info=cycles.particle_info) frag.write_pre = True frag.write('const float p_index = 0;') frag.write('const float p_age = 0;') frag.write('const float p_lifetime = 0;') frag.write('const vec3 p_location = vec3(0);') frag.write('const float p_size = 0;') frag.write('const vec3 p_velocity = vec3(0);') frag.write('const vec3 p_angular_velocity = vec3(0);') frag.write_pre = False if not frag.contains('vec3 n ='): frag.write_pre = True frag.write('vec3 n;') frag.write_pre = False export_mpos = frag.contains('mposition') and not frag.contains('vec3 mposition') if export_mpos: vert.add_out('vec3 mpositionGeom') vert.write_pre = True vert.write('mpositionGeom = pos;') vert.write_pre = False export_bpos = frag.contains('bposition') and not frag.contains('vec3 bposition') if export_bpos: vert.add_out('vec3 bpositionGeom') vert.add_uniform('vec3 dim', link='_dim') vert.add_uniform('vec3 hdim', link='_halfDim') vert.write_pre = True vert.write('bpositionGeom = (pos.xyz + hdim) / dim;') vert.write_pre = False vert.add_uniform('mat4 W', '_worldMatrix') vert.add_uniform('mat3 N', '_normalMatrix') vert.add_out('vec3 voxpositionGeom') vert.add_out('vec3 wnormalGeom') vert.add_include('compiled.inc') if con_voxel.is_elem('col'): vert.add_out('vec3 vcolorGeom') vert.write('vcolorGeom = col;') if con_voxel.is_elem('tex'): vert.add_out('vec2 texCoordGeom') vert.write('texCoordGeom = tex;') if rpdat.arm_voxelgi_revoxelize and rpdat.arm_voxelgi_camera: vert.add_uniform('vec3 eyeSnap', '_cameraPositionSnap') vert.write('voxpositionGeom = (vec3(W * vec4(pos, 1.0)) - eyeSnap) / voxelgiHalfExtents;') else: vert.write('voxpositionGeom = vec3(W * vec4(pos, 1.0)) / voxelgiHalfExtents;') vert.write('wnormalGeom = normalize(N * nor);') # vert.write('gl_Position = vec4(0.0, 0.0, 0.0, 1.0);') geom.add_out('vec3 voxposition') geom.add_out('vec3 wnormal') if con_voxel.is_elem('col'): geom.add_out('vec3 vcolor') if con_voxel.is_elem('tex'): geom.add_out('vec2 texCoord') if export_mpos: geom.add_out('vec3 mposition') if export_bpos: geom.add_out('vec3 bposition') geom.write('vec3 p1 = voxpositionGeom[1] - voxpositionGeom[0];') geom.write('vec3 p2 = voxpositionGeom[2] - voxpositionGeom[0];') geom.write('vec3 p = abs(cross(p1, p2));') geom.write('for (uint i = 0; i < 3; ++i) {') geom.write(' voxposition = voxpositionGeom[i];') geom.write(' wnormal = wnormalGeom[i];') if con_voxel.is_elem('col'): geom.write(' vcolor = vcolorGeom[i];') if con_voxel.is_elem('tex'): geom.write(' texCoord = texCoordGeom[i];') if export_mpos: geom.write(' mposition = mpositionGeom[i];') if export_bpos: geom.write(' bposition = bpositionGeom[i];') geom.write(' if (p.z > p.x && p.z > p.y) {') geom.write(' gl_Position = vec4(voxposition.x, voxposition.y, 0.0, 1.0);') geom.write(' }') geom.write(' else if (p.x > p.y && p.x > p.z) {') geom.write(' gl_Position = vec4(voxposition.y, voxposition.z, 0.0, 1.0);') geom.write(' }') geom.write(' else {') geom.write(' gl_Position = vec4(voxposition.x, voxposition.z, 0.0, 1.0);') geom.write(' }') geom.write(' EmitVertex();') geom.write('}') geom.write('EndPrimitive();') frag.write('vec3 voxel = voxposition * 0.5 + 0.5;') frag.write('uint val = convVec4ToRGBA8(vec4(basecol, 1.0) * 255);') frag.write('imageAtomicMax(voxels, ivec3(voxelgiResolution * voxel), val);') frag.write('val = encNor(wnormal);'); frag.write('imageAtomicMax(voxelsNor, ivec3(voxelgiResolution * voxel), val);') # frag.write('imageStore(voxels, ivec3(voxelgiResolution * voxel), vec4(color, 1.0));') # frag.write('imageAtomicRGBA8Avg(voxels, ivec3(voxelgiResolution * voxel), vec4(color, 1.0));') # frag.write('ivec3 coords = ivec3(voxelgiResolution * voxel);') # if parse_opacity: # frag.write('vec4 val = vec4(color, opacity);') # else: # frag.write('vec4 val = vec4(color, 1.0);') # frag.write('val *= 255.0;') # frag.write('uint newVal = encUnsignedNibble(convVec4ToRGBA8(val), 1);') # frag.write('uint prevStoredVal = 0;') # frag.write('uint currStoredVal;') # # frag.write('int counter = 0;') # # frag.write('while ((currStoredVal = imageAtomicCompSwap(voxels, coords, prevStoredVal, newVal)) != prevStoredVal && counter < 16) {') # frag.write('while ((currStoredVal = imageAtomicCompSwap(voxels, coords, prevStoredVal, newVal)) != prevStoredVal) {') # frag.write(' vec4 rval = convRGBA8ToVec4(currStoredVal & 0xFEFEFEFE);') # frag.write(' uint n = decUnsignedNibble(currStoredVal);') # frag.write(' rval = rval * n + val;') # frag.write(' rval /= ++n;') # frag.write(' rval = round(rval / 2) * 2;') # frag.write(' newVal = encUnsignedNibble(convVec4ToRGBA8(rval), n);') # frag.write(' prevStoredVal = currStoredVal;') # # frag.write(' counter++;') # frag.write('}') # frag.write('val.rgb *= 255.0f;') # frag.write('uint newVal = convVec4ToRGBA8(val);') # frag.write('uint prevStoredVal = 0;') # frag.write('uint curStoredVal;') # frag.write('while ((curStoredVal = imageAtomicCompSwap(voxels, coords, prevStoredVal, newVal)) != prevStoredVal) {') # frag.write(' prevStoredVal = curStoredVal;') # frag.write(' vec4 rval = convRGBA8ToVec4(curStoredVal);') # frag.write(' rval.xyz = (rval.xyz * rval.w);') # frag.write(' vec4 curValF = rval + val;') # frag.write(' curValF.xyz /= (curValF.w);') # frag.write(' newVal = convVec4ToRGBA8(curValF);') # frag.write('}') return con_voxel
def make_forward_restricted(con_mesh): wrd = bpy.data.worlds['Arm'] vert = con_mesh.make_vert() frag = con_mesh.make_frag() geom = None tesc = None tese = None vert.add_uniform('mat3 N', '_normalMatrix') vert.write_main_header('vec4 spos = vec4(pos, 1.0);') 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;') cycles.parse(mat_state.nodes, con_mesh, vert, frag, geom, tesc, tese, basecol_only=True, parse_opacity=False, parse_displacement=False) if con_mesh.is_elem('tex'): vert.add_out('vec2 texCoord') vert.write('texCoord = tex;') if con_mesh.is_elem('col'): vert.add_out('vec3 vcolor') vert.write('vcolor = col;') vert.add_out('vec3 wnormal') write_norpos(con_mesh, vert) frag.write_pre = True frag.write_main_header('vec3 n = normalize(wnormal);') frag.write_pre = False frag.add_uniform('vec3 lightColor', '_lampColor') frag.add_uniform('vec3 lightDir', '_lampDirection') frag.add_uniform('float envmapStrength', link='_envmapStrength') if '_NoShadows' in wrd.world_defs: is_shadows = False else: is_shadows = True frag.write('float visibility = 1.0;') frag.write('float dotNL = dot(n, lightDir);') if is_shadows: vert.add_out('vec4 lampPos') vert.add_uniform('mat4 LWVP', '_biasLampWorldViewProjectionMatrix') vert.write('lampPos = LWVP * spos;') frag.add_include('../../Shaders/std/shadows.glsl') frag.add_uniform('sampler2D shadowMap', included=True) frag.add_uniform('float shadowsBias', '_lampShadowsBias') frag.write(' if (lampPos.w > 0.0) {') frag.write(' vec3 lpos = lampPos.xyz / lampPos.w;') # frag.write(' visibility *= PCF(lpos.xy, lpos.z - shadowsBias);') frag.write(' const float texelSize = 1.0 / shadowmapSize.x;') frag.write(' visibility = 0.0;') frag.write( ' visibility += float(texture(shadowMap, lpos.xy).r + shadowsBias > lpos.z);' ) frag.write( ' visibility += float(texture(shadowMap, lpos.xy + vec2(texelSize, 0.0)).r + shadowsBias > lpos.z) * 0.5;' ) frag.write( ' visibility += float(texture(shadowMap, lpos.xy + vec2(-texelSize, 0.0)).r + shadowsBias > lpos.z) * 0.25;' ) frag.write( ' visibility += float(texture(shadowMap, lpos.xy + vec2(0.0, texelSize)).r + shadowsBias > lpos.z) * 0.5;' ) frag.write( ' visibility += float(texture(shadowMap, lpos.xy + vec2(0.0, -texelSize)).r + shadowsBias > lpos.z) * 0.25;' ) frag.write(' visibility /= 2.5;') frag.write(' visibility = max(visibility, 0.5);') # frag.write(' visibility = max(float(texture(shadowMap, lpos.xy).r + shadowsBias > lpos.z), 0.5);') frag.write(' }') frag.write('vec3 direct = basecol * max(dotNL, 0.1);') frag.add_out('vec4 fragColor') frag.write('fragColor = vec4(direct * lightColor * visibility, 1.0);') if '_LDR' in bpy.data.worlds['Arm'].rp_defs: frag.write('fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2));')
def make_gi(context_id): con_voxel = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'always', 'cull_mode': 'none', 'color_write_red': False, 'color_write_green': False, 'color_write_blue': False, 'color_write_alpha': False, 'conservative_raster': True }) wrd = bpy.data.worlds['Arm'] vert = con_voxel.make_vert() frag = con_voxel.make_frag() geom = con_voxel.make_geom() tesc = None tese = None geom.ins = vert.outs frag.ins = geom.outs frag.add_include('compiled.inc') frag.add_include('std/math.glsl') frag.add_include('std/imageatomic.glsl') frag.add_include('std/gbuffer.glsl') frag.write_header('#extension GL_ARB_shader_image_load_store : enable') rpdat = arm.utils.get_rp() if arm.utils.get_gapi() == 'direct3d11': for e in con_voxel.data['vertex_elements']: if e['name'] == 'nor': con_voxel.data['vertex_elements'].remove(e) break frag.add_uniform('layout(rgba8) writeonly image3D voxels') else: frag.add_uniform('layout(r32ui) uimage3D voxels') frag.write('if (abs(voxposition.z) > ' + rpdat.rp_voxelgi_resolution_z + ' || abs(voxposition.x) > 1 || abs(voxposition.y) > 1) return;') frag.write('vec3 wposition = voxposition * voxelgiHalfExtents;') if rpdat.arm_voxelgi_revoxelize and rpdat.arm_voxelgi_camera: frag.add_uniform('vec3 eyeSnap', '_cameraPositionSnap') frag.write('wposition += eyeSnap;') frag.write('vec3 basecol;') frag.write('float roughness;') # frag.write('float metallic;') # frag.write('float occlusion;') # frag.write('float specular;') # if '_Emission' in wrd.world_defs: frag.write('float emission;') # frag.write('float dotNV = 0.0;') cycles.parse(mat_state.nodes, con_voxel, vert, frag, geom, tesc, tese, parse_opacity=False, parse_displacement=False, basecol_only=True) # Voxelized particles particle = mat_state.material.arm_particle_flag if particle and rpdat.arm_particles == 'GPU': # make_particle.write(vert, particle_info=cycles.particle_info) frag.write_pre = True frag.write('const float p_index = 0;') frag.write('const float p_age = 0;') frag.write('const float p_lifetime = 0;') frag.write('const vec3 p_location = vec3(0);') frag.write('const float p_size = 0;') frag.write('const vec3 p_velocity = vec3(0);') frag.write('const vec3 p_angular_velocity = vec3(0);') frag.write_pre = False if not frag.contains('vec3 n ='): frag.write_pre = True frag.write('vec3 n;') frag.write_pre = False export_mpos = frag.contains( 'mposition') and not frag.contains('vec3 mposition') if export_mpos: vert.add_out('vec3 mpositionGeom') vert.write_pre = True vert.write('mpositionGeom = pos;') vert.write_pre = False export_bpos = frag.contains( 'bposition') and not frag.contains('vec3 bposition') if export_bpos: vert.add_out('vec3 bpositionGeom') vert.add_uniform('vec3 dim', link='_dim') vert.add_uniform('vec3 hdim', link='_halfDim') vert.write_pre = True vert.write('bpositionGeom = (pos.xyz + hdim) / dim;') vert.write_pre = False vert.add_uniform('mat4 W', '_worldMatrix') vert.add_out('vec3 voxpositionGeom') vert.add_include('compiled.inc') if con_voxel.is_elem('col'): vert.add_out('vec3 vcolorGeom') vert.write('vcolorGeom = col.rgb;') if con_voxel.is_elem('tex'): vert.add_out('vec2 texCoordGeom') vert.write('texCoordGeom = tex;') if rpdat.arm_voxelgi_revoxelize and rpdat.arm_voxelgi_camera: vert.add_uniform('vec3 eyeSnap', '_cameraPositionSnap') vert.write( 'voxpositionGeom = (vec3(W * vec4(pos.xyz, 1.0)) - eyeSnap) / voxelgiHalfExtents;' ) else: vert.write( 'voxpositionGeom = vec3(W * vec4(pos.xyz, 1.0)) / voxelgiHalfExtents;' ) vert.write('gl_Position = vec4(0.0, 0.0, 0.0, 1.0);') geom.add_out('vec3 voxposition') geom.add_out('vec4 lightPosition') if con_voxel.is_elem('col'): geom.add_out('vec3 vcolor') if con_voxel.is_elem('tex'): geom.add_out('vec2 texCoord') if export_mpos: geom.add_out('vec3 mposition') if export_bpos: geom.add_out('vec3 bposition') if arm.utils.get_gapi() == 'direct3d11': # No geom shader compiler for hlsl yet geom.noprocessing = True struct_input = 'struct SPIRV_Cross_Input {' struct_output = 'struct SPIRV_Cross_Output {' pos = 0 if export_bpos: struct_input += ' float3 bpositionGeom : TEXCOORD' + str(pos) + ';' struct_output += ' float3 bposition : TEXCOORD' + str(pos) + ';' pos += 1 struct_input += ' float3 lightPositionGeom : TEXCOORD' + str(pos) + ';' struct_output += ' float3 lightPosition : TEXCOORD' + str(pos) + ';' pos += 1 if export_mpos: struct_input += ' float3 mpositionGeom : TEXCOORD' + str(pos) + ';' struct_output += ' float3 mposition : TEXCOORD' + str(pos) + ';' pos += 1 if con_voxel.is_elem('tex'): struct_input += ' float2 texCoordGeom : TEXCOORD' + str(pos) + ';' struct_output += ' float2 texCoord : TEXCOORD' + str(pos) + ';' pos += 1 if con_voxel.is_elem('col'): struct_input += ' float3 vcolorGeom : TEXCOORD' + str(pos) + ';' struct_output += ' float3 vcolor : TEXCOORD' + str(pos) + ';' pos += 1 struct_input += ' float3 voxpositionGeom : TEXCOORD' + str(pos) + ';' struct_output += ' float3 voxposition : TEXCOORD' + str(pos) + ';' pos += 1 struct_input += ' float4 gl_Position : SV_POSITION; };' struct_output += ' float4 gl_Position : SV_POSITION; };' geom.write(struct_input) geom.write(struct_output) geom.write('[maxvertexcount(3)]') geom.write( 'void main(triangle SPIRV_Cross_Input stage_input[3], inout TriangleStream<SPIRV_Cross_Output> output) {' ) geom.write( ' float3 p1 = stage_input[1].voxpositionGeom.xyz - stage_input[0].voxpositionGeom.xyz;' ) geom.write( ' float3 p2 = stage_input[2].voxpositionGeom.xyz - stage_input[0].voxpositionGeom.xyz;' ) geom.write(' float3 p = abs(cross(p1, p2));') geom.write(' for (int i = 0; i < 3; ++i) {') geom.write(' SPIRV_Cross_Output stage_output;') geom.write( ' stage_output.voxposition = stage_input[i].voxpositionGeom;') geom.write( ' stage_output.lightPosition = stage_input[i].lightPositionGeom;' ) if con_voxel.is_elem('col'): geom.write(' stage_output.vcolor = stage_input[i].vcolorGeom;') if con_voxel.is_elem('tex'): geom.write( ' stage_output.texCoord = stage_input[i].texCoordGeom;') if export_mpos: geom.write( ' stage_output.mposition = stage_input[i].mpositionGeom;') if export_bpos: geom.write( ' stage_output.bposition = stage_input[i].bpositionGeom;') geom.write(' if (p.z > p.x && p.z > p.y) {') geom.write( ' stage_output.gl_Position = float4(stage_input[i].voxpositionGeom.x, stage_input[i].voxpositionGeom.y, 0.0, 1.0);' ) geom.write(' }') geom.write(' else if (p.x > p.y && p.x > p.z) {') geom.write( ' stage_output.gl_Position = float4(stage_input[i].voxpositionGeom.y, stage_input[i].voxpositionGeom.z, 0.0, 1.0);' ) geom.write(' }') geom.write(' else {') geom.write( ' stage_output.gl_Position = float4(stage_input[i].voxpositionGeom.x, stage_input[i].voxpositionGeom.z, 0.0, 1.0);' ) geom.write(' }') geom.write(' output.Append(stage_output);') geom.write(' }') geom.write('}') else: geom.write('vec3 p1 = voxpositionGeom[1] - voxpositionGeom[0];') geom.write('vec3 p2 = voxpositionGeom[2] - voxpositionGeom[0];') geom.write('vec3 p = abs(cross(p1, p2));') geom.write('for (uint i = 0; i < 3; ++i) {') geom.write(' voxposition = voxpositionGeom[i];') geom.write(' lightPosition = lightPositionGeom[i];') if con_voxel.is_elem('col'): geom.write(' vcolor = vcolorGeom[i];') if con_voxel.is_elem('tex'): geom.write(' texCoord = texCoordGeom[i];') if export_mpos: geom.write(' mposition = mpositionGeom[i];') if export_bpos: geom.write(' bposition = bpositionGeom[i];') geom.write(' if (p.z > p.x && p.z > p.y) {') geom.write( ' gl_Position = vec4(voxposition.x, voxposition.y, 0.0, 1.0);' ) geom.write(' }') geom.write(' else if (p.x > p.y && p.x > p.z) {') geom.write( ' gl_Position = vec4(voxposition.y, voxposition.z, 0.0, 1.0);' ) geom.write(' }') geom.write(' else {') geom.write( ' gl_Position = vec4(voxposition.x, voxposition.z, 0.0, 1.0);' ) geom.write(' }') geom.write(' EmitVertex();') geom.write('}') geom.write('EndPrimitive();') if '_Sun' in wrd.world_defs and '_ShadowMap' in wrd.world_defs: vert.add_out('vec4 lightPositionGeom') vert.add_uniform('mat4 LWVP', link='_biasLightWorldViewProjectionMatrix') vert.write('lightPositionGeom = LWVP * vec4(pos.xyz, 1.0);') frag.add_uniform('sampler2DShadow shadowMap') frag.add_uniform('float shadowsBias', link='_sunShadowsBias') frag.write('float visibility = 1.0;') if '_CSM' in wrd.world_defs: frag.add_include('std/shadows.glsl') frag.add_uniform('vec4 casData[shadowmapCascades * 4 + 4]', '_cascadeData', included=True) frag.add_uniform('vec3 eye', '_cameraPosition') frag.write( 'visibility = shadowTestCascade(shadowMap, eye, wposition, shadowsBias);' ) else: frag.write('if (lightPosition.w > 0.0) {') frag.write(' vec3 lPos = lightPosition.xyz / lightPosition.w;') frag.write( ' visibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).r;' ) frag.write('}') frag.add_uniform('vec3 sunCol', link="_sunColor") frag.write('basecol *= visibility * sunCol;') else: print( 'Armory Warning: Voxel GI requires sun light and enabled shadows') vert.add_out('vec4 lightPositionGeom') frag.write('basecol = vec3(0.0);') frag.write('vec3 voxel = voxposition * 0.5 + 0.5;') if arm.utils.get_gapi() == 'direct3d11': frag.write( 'imageStore(voxels, ivec3(voxelgiResolution * voxel), vec4(min(basecol, vec3(1.0)), 1.0));' ) else: frag.write( 'uint val = convVec4ToRGBA8(vec4(min(basecol, vec3(1.0)), 1.0));') frag.write( 'imageAtomicMax(voxels, ivec3(voxelgiResolution * voxel), val);') return con_voxel