2016-12-20 14:15:09 +01:00
|
|
|
import bpy
|
2017-03-15 12:30:14 +01:00
|
|
|
import arm.make_utils as make_utils
|
2016-12-13 01:09:17 +01:00
|
|
|
|
|
|
|
class Shader:
|
|
|
|
|
2016-12-15 23:50:21 +01:00
|
|
|
def __init__(self, context, shader_type):
|
2016-12-13 01:09:17 +01:00
|
|
|
self.context = context
|
2016-12-15 23:50:21 +01:00
|
|
|
self.shader_type = shader_type
|
2016-12-13 01:09:17 +01:00
|
|
|
self.includes = []
|
|
|
|
self.ins = []
|
|
|
|
self.outs = []
|
|
|
|
self.uniforms = []
|
2016-12-13 20:06:23 +01:00
|
|
|
self.functions = {}
|
2016-12-13 01:09:17 +01:00
|
|
|
self.main = ''
|
2016-12-15 23:50:21 +01:00
|
|
|
self.main_pre = ''
|
2017-03-23 12:01:25 +01:00
|
|
|
self.main_header = ''
|
2017-02-18 20:18:38 +01:00
|
|
|
self.header = ''
|
2016-12-17 23:48:18 +01:00
|
|
|
self.write_pre = False
|
2017-10-06 19:44:10 +02:00
|
|
|
self.write_pre_header = False
|
2016-12-13 01:09:17 +01:00
|
|
|
self.tab = 1
|
2017-03-28 14:30:51 +02:00
|
|
|
self.vertex_structure_as_vsinput = True
|
2017-04-26 14:21:22 +02:00
|
|
|
self.lock = False
|
2016-12-13 01:09:17 +01:00
|
|
|
|
|
|
|
def add_include(self, s):
|
|
|
|
self.includes.append(s)
|
|
|
|
|
|
|
|
def add_in(self, s):
|
|
|
|
self.ins.append(s)
|
|
|
|
|
|
|
|
def add_out(self, s):
|
|
|
|
self.outs.append(s)
|
|
|
|
|
2016-12-21 00:51:04 +01:00
|
|
|
def add_uniform(self, s, link=None, included=False):
|
2016-12-13 01:09:17 +01:00
|
|
|
ar = s.split(' ')
|
2017-02-18 20:18:38 +01:00
|
|
|
# layout(RGBA8) image3D voxels
|
|
|
|
utype = ar[-2]
|
|
|
|
uname = ar[-1]
|
2017-08-03 14:01:04 +02:00
|
|
|
if utype.startswith('sampler') or utype.startswith('image') or utype.startswith('uimage'):
|
|
|
|
is_image = True if (utype.startswith('image') or utype.startswith('uimage')) else None
|
2017-02-18 20:18:38 +01:00
|
|
|
self.context.add_texture_unit(utype, uname, link=link, is_image=is_image)
|
2016-12-13 01:09:17 +01:00
|
|
|
else:
|
2017-02-07 11:50:21 +01:00
|
|
|
# Prefer vec4[] for d3d to avoid padding
|
2016-12-13 01:09:17 +01:00
|
|
|
if ar[0] == 'float' and '[' in ar[1]:
|
|
|
|
ar[0] = 'floats'
|
|
|
|
ar[1] = ar[1].split('[', 1)[0]
|
2017-02-07 11:50:21 +01:00
|
|
|
elif ar[0] == 'vec4' and '[' in ar[1]:
|
2017-04-12 13:25:09 +02:00
|
|
|
ar[0] = 'floats'
|
2017-02-07 11:50:21 +01:00
|
|
|
ar[1] = ar[1].split('[', 1)[0]
|
2016-12-13 01:09:17 +01:00
|
|
|
self.context.add_constant(ar[0], ar[1], link=link)
|
2016-12-15 23:50:21 +01:00
|
|
|
if included == False and s not in self.uniforms:
|
2016-12-13 01:09:17 +01:00
|
|
|
self.uniforms.append(s)
|
|
|
|
|
2016-12-13 20:06:23 +01:00
|
|
|
def add_function(self, s):
|
|
|
|
fname = s.split('(', 1)[0]
|
|
|
|
if fname in self.functions:
|
|
|
|
return
|
|
|
|
self.functions[fname] = s
|
|
|
|
|
2016-12-19 01:25:22 +01:00
|
|
|
def contains(self, s):
|
2017-09-09 13:46:32 +02:00
|
|
|
return (s in self.main or s in self.main_pre or s in self.main_header or s in self.ins)
|
2016-12-19 01:25:22 +01:00
|
|
|
|
2017-03-14 20:43:54 +01:00
|
|
|
def prepend(self, s):
|
2017-03-23 12:01:25 +01:00
|
|
|
self.main_pre = s + '\n' + self.main_pre
|
2017-03-14 20:43:54 +01:00
|
|
|
|
2016-12-13 01:09:17 +01:00
|
|
|
def write(self, s):
|
2017-04-26 14:21:22 +02:00
|
|
|
if self.lock:
|
|
|
|
return
|
2016-12-17 23:48:18 +01:00
|
|
|
if self.write_pre:
|
|
|
|
self.main_pre += '\t' * 1 + s + '\n'
|
2017-10-06 19:44:10 +02:00
|
|
|
elif self.write_pre_header:
|
|
|
|
self.main_header += '\t' * 1 + s + '\n'
|
2016-12-17 23:48:18 +01:00
|
|
|
else:
|
|
|
|
self.main += '\t' * self.tab + s + '\n'
|
2016-12-13 01:09:17 +01:00
|
|
|
|
2017-02-18 20:18:38 +01:00
|
|
|
def write_header(self, s):
|
|
|
|
self.header += s + '\n'
|
|
|
|
|
2017-03-23 12:01:25 +01:00
|
|
|
def write_main_header(self, s):
|
|
|
|
self.main_header += s + '\n'
|
|
|
|
|
2016-12-13 01:09:17 +01:00
|
|
|
def get(self):
|
2016-12-17 15:34:43 +01:00
|
|
|
s = '#version 450\n'
|
|
|
|
|
2017-02-18 20:18:38 +01:00
|
|
|
s += self.header
|
|
|
|
|
2016-12-20 14:15:09 +01:00
|
|
|
defs = make_utils.def_strings_to_array(bpy.data.worlds['Arm'].world_defs)
|
|
|
|
for a in defs:
|
|
|
|
s += '#define {0}\n'.format(a)
|
|
|
|
|
2016-12-17 15:34:43 +01:00
|
|
|
in_ext = ''
|
2016-12-20 14:15:09 +01:00
|
|
|
out_ext = ''
|
2016-12-17 15:34:43 +01:00
|
|
|
|
2017-03-28 14:30:51 +02:00
|
|
|
if self.shader_type == 'vert' and self.vertex_structure_as_vsinput: # Vertex structure as vertex shader input
|
2017-05-25 16:48:41 +02:00
|
|
|
vs = self.context.data['vertex_structure']
|
2016-12-15 23:50:21 +01:00
|
|
|
for e in vs:
|
|
|
|
self.add_in('vec' + str(e['size']) + ' ' + e['name'])
|
|
|
|
|
2016-12-17 15:34:43 +01:00
|
|
|
elif self.shader_type == 'tesc':
|
|
|
|
in_ext = '[]'
|
|
|
|
out_ext = '[]'
|
|
|
|
s += 'layout(vertices = 3) out;\n'
|
|
|
|
# Gen outs
|
|
|
|
for sin in self.ins:
|
2017-02-18 20:18:38 +01:00
|
|
|
ar = sin.rsplit(' ', 1) # vec3 wnormal
|
2016-12-17 15:34:43 +01:00
|
|
|
tc_s = 'tc_' + ar[1]
|
|
|
|
self.add_out(ar[0] + ' ' + tc_s)
|
|
|
|
# Pass data
|
|
|
|
self.write('{0}[gl_InvocationID] = {1}[gl_InvocationID];'.format(tc_s, ar[1]))
|
|
|
|
|
|
|
|
elif self.shader_type == 'tese':
|
|
|
|
in_ext = '[]'
|
|
|
|
s += 'layout(triangles, equal_spacing, ccw) in;\n'
|
|
|
|
|
2017-02-18 20:18:38 +01:00
|
|
|
elif self.shader_type == 'geom':
|
|
|
|
in_ext = '[]'
|
|
|
|
s += 'layout(triangles) in;\n'
|
|
|
|
s += 'layout(triangle_strip, max_vertices = 3) out;\n'
|
|
|
|
|
2016-12-13 01:09:17 +01:00
|
|
|
for a in self.includes:
|
|
|
|
s += '#include "' + a + '"\n'
|
|
|
|
for a in self.ins:
|
2016-12-17 15:34:43 +01:00
|
|
|
s += 'in {0}{1};\n'.format(a, in_ext)
|
2016-12-13 01:09:17 +01:00
|
|
|
for a in self.outs:
|
2016-12-17 15:34:43 +01:00
|
|
|
s += 'out {0}{1};\n'.format(a, out_ext)
|
2016-12-21 00:51:04 +01:00
|
|
|
for a in self.uniforms:
|
2016-12-13 01:09:17 +01:00
|
|
|
s += 'uniform ' + a + ';\n'
|
2016-12-13 20:06:23 +01:00
|
|
|
for f in self.functions:
|
|
|
|
s += self.functions[f]
|
2016-12-13 01:09:17 +01:00
|
|
|
s += 'void main() {\n'
|
2017-03-23 12:01:25 +01:00
|
|
|
s += self.main_header
|
2016-12-15 23:50:21 +01:00
|
|
|
s += self.main_pre
|
2016-12-13 01:09:17 +01:00
|
|
|
s += self.main
|
|
|
|
s += '}\n'
|
|
|
|
return s
|