#!/usr/bin/python3
# Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
# All rights reserved.
# Code licensed under the BSD License.
# http://www.anki3d.org/LICENSE
import os
import argparse
# Template
template_xml = """
vert
%vertInputs%
frag
%fragInputs%
"""
# Input type
INPUT_NONE = 0
INPUT_TEXTURE = 1
INPUT_CONST = 2
INPUT_VALUE = 3 # non-const
INPUT_COUNT = 4
# Variables
DIFFUSE = 0
SPECULAR = 1
ROUGHNESS = 2
METALLIC = 3
NORMAL = 4
EMISSION = 5
SUBSURFACE = 6
HEIGHT = 7
VARIABLE_COUNT = 8
allowed_permutations = [
[INPUT_TEXTURE, INPUT_CONST],
[INPUT_TEXTURE, INPUT_CONST],
[INPUT_TEXTURE, INPUT_CONST],
[INPUT_TEXTURE, INPUT_CONST],
[INPUT_TEXTURE, INPUT_NONE],
[INPUT_TEXTURE, INPUT_CONST],
[INPUT_CONST],
[INPUT_NONE, INPUT_TEXTURE]]
def parse_commandline():
""" Parse the command line arguments """
parser = argparse.ArgumentParser(description = "Create shader program permutations",
formatter_class = argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("-o", "--output-dir", required = True, help = "specify the output directory")
args = parser.parse_args()
return args.output_dir
def spin_wheel(wheel):
""" Spin the wheel """
done = False
start = VARIABLE_COUNT - 1
while True:
if start == -1:
done = True
break
wheel[start] += 1
if wheel[start] >= INPUT_COUNT:
wheel[start] = INPUT_NONE
start = start - 1
else:
break
return done
def mutate(wheel):
""" Create the mutation's source """
parallax = wheel[HEIGHT] == INPUT_TEXTURE
# Vert input & source
if parallax:
vert_inputs = """ mat4mvp
mat3normalMat0
mat4modelViewMat0
"""
vert_src = """#if COLOR
positionUvNormalTangent(mvp, normalMat);
parallax(vodelViewMat);
#else
ANKI_WRITE_POSITION(mvp * vec4(in_position, 1.0));
#endif
"""
else:
vert_inputs = """ mat4mvp
mat3normalMat0
"""
vert_src = """#if COLOR
positionUvNormalTangent(mvp, normalMat);
#else
ANKI_WRITE_POSITION(mvp * vec4(in_position, 1.0));
#endif
"""
# Frag inputs & source & filename
frag_ins = ""
frag_src = "#if COLOR\n"
fname = "ms_"
if parallax:
frag_ins += "\t\t\t\tfloatheightMapScale10\n"
frag_src += "vec2 uv = computeTextureCoordParallax(heightTex, in_uv, heightMapScale);\n"
else:
frag_src += "vec2 uv = in_uv;\n"
if wheel[DIFFUSE] == INPUT_TEXTURE:
frag_ins += "\t\t\t\tsampler2DdiffTex0\n"
frag_src += "vec3 diffColor = texture(diffTex, uv).rgb;\n"
fname += "difft_"
elif wheel[DIFFUSE] == INPUT_CONST:
frag_ins += "\t\t\t\tvec3diffColor10\n"
fname += "diffc_"
else:
assert 0
if wheel[SPECULAR] == INPUT_TEXTURE:
frag_ins += "\t\t\t\tsampler2DspecTex0\n"
frag_src += "vec3 specColor = texture(specTex, uv).rgb;\n"
fname += "spect_"
elif wheel[SPECULAR] == INPUT_CONST:
frag_ins += "\t\t\t\tvec3specColor10\n"
fname += "specc_"
else:
assert 0
if wheel[ROUGHNESS] == INPUT_TEXTURE:
frag_ins += "\t\t\t\tsampler2DroughnessTex0\n"
frag_src += "float roughness = texture(roughnessTex, uv).r;\n"
fname += "rought_"
elif wheel[ROUGHNESS] == INPUT_CONST:
frag_ins += "\t\t\t\tfloatroughness10\n"
fname += "roughc_"
else:
assert 0
if wheel[METALLIC] == INPUT_TEXTURE:
frag_ins += "\t\t\t\tsampler2DmetallicTex0\n"
frag_src += "float metallic = texture(metallicTex, uv).r;\n"
fname += "metalt_"
elif wheel[METALLIC] == INPUT_CONST:
frag_ins += "\t\t\t\tfloatmetallic10\n"
fname += "metalc_"
else:
assert 0
if wheel[NORMAL] == INPUT_TEXTURE:
frag_ins += "\t\t\t\tsampler2DnormalTex0\n"
frag_src += "vec3 normal = readNormalFromTexture(normalTex, uv);\n"
fname += "normalt_"
elif wheel[NORMAL] == INPUT_NONE:
frag_src += "vec3 normal = in_normal;\n"
fname += "normal0_"
else:
assert 0
if wheel[EMISSION] == INPUT_TEXTURE:
frag_ins += "\t\t\t\tsampler2DemissionTex0\n"
frag_src += "vec3 emission = texture(emissionTex, uv).rgb;\n"
fname += "emist_"
elif wheel[EMISSION] == INPUT_CONST:
frag_ins += "\t\t\t\tvec3emission10\n"
fname += "emisc_"
else:
assert 0
if wheel[SUBSURFACE] == INPUT_CONST:
frag_ins += "\t\t\t\tfloatsubsurface10\n"
fname += "subsc_"
else:
assert 0
if wheel[HEIGHT] == INPUT_NONE:
# nothing
fname += "par0"
elif wheel[HEIGHT] == INPUT_TEXTURE:
frag_ins += "\t\t\t\tsampler2DheightTex0\n"
fname += "par1"
else:
assert 0
frag_src += "writeRts(diffColor, normal, specColor, roughness, subsurface, emission, metallic);\n"
frag_src += "#endif\n"
xml = template_xml
xml = xml.replace("%vertInputs%", vert_inputs)
xml = xml.replace("%vertSrc%", vert_src)
xml = xml.replace("%fragInputs%", frag_ins)
xml = xml.replace("%fragSrc%", frag_src)
return (xml, fname)
def main():
""" Main function """
out_dir = parse_commandline()
wheel = [INPUT_NONE, INPUT_NONE, INPUT_NONE, INPUT_NONE, INPUT_NONE, INPUT_NONE, INPUT_NONE, INPUT_NONE]
while(not spin_wheel(wheel)):
if wheel[DIFFUSE] in allowed_permutations[DIFFUSE] \
and wheel[SPECULAR] in allowed_permutations[SPECULAR] \
and wheel[ROUGHNESS] in allowed_permutations[ROUGHNESS] \
and wheel[METALLIC] in allowed_permutations[METALLIC] \
and wheel[NORMAL] in allowed_permutations[NORMAL] \
and wheel[EMISSION] in allowed_permutations[EMISSION] \
and wheel[SUBSURFACE] in allowed_permutations[SUBSURFACE] \
and wheel[HEIGHT] in allowed_permutations[HEIGHT]:
(xml, fname) = mutate(wheel)
file = open(fname + ".ankiprog", "w")
file.write(xml)
if __name__ == "__main__":
main()