-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLeonModel.gltf
1 lines (1 loc) · 125 KB
/
LeonModel.gltf
1
{"buffers":[{"uri":"data:application/octet-stream;base64,AAAMwgAAtMEAAAxCAAAMQgAAtMEAAAxCAAAMQgAAPkIAAAxCAAAMwgAAPkIAAAxCAAAMwgAAtMEAAAzCAAAMQgAAtMEAAAzCAAAMQgAAPkIAAAzCAAAMwgAAPkIAAAzCAAABAAIAAAACAAMAAQAFAAYAAQAGAAIABQAEAAcABQAHAAYABAAAAAMABAADAAcAAwACAAYAAwAGAAcABAAFAAEABAABAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAIAAAAAAAACAPwAAAIAAAAAAAACAPwAAAIAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAgAAAgD8AAAAAAAAAgAAAgD8AAAAAAAAAgAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAA7AXRvuwF0b7sBVE/q6oqP6uqKr+rqqo+7AXRPuwF0T7sBVE/7AXRvuwF0b7sBVE/7AXRPuwF0T7sBVE/q6oqv6uqKj+rqqo+q6oqP6uqKr+rqqo+7AXRPuwF0b7sBVG/q6oqP6uqKj+rqqq+q6oqP6uqKr+rqqo+q6oqP6uqKj+rqqq+7AXRPuwF0T7sBVE/7AXRPuwF0b7sBVG/q6oqv6uqKr+rqqq+7AXRvuwF0T7sBVG/7AXRPuwF0b7sBVG/7AXRvuwF0T7sBVG/q6oqP6uqKj+rqqq+q6oqv6uqKr+rqqq+7AXRvuwF0b7sBVE/q6oqv6uqKj+rqqo+q6oqv6uqKr+rqqq+q6oqv6uqKj+rqqo+7AXRvuwF0T7sBVG/q6oqv6uqKj+rqqo+7AXRPuwF0T7sBVE/q6oqP6uqKj+rqqq+q6oqv6uqKj+rqqo+q6oqP6uqKj+rqqq+7AXRvuwF0T7sBVG/q6oqv6uqKr+rqqq+7AXRPuwF0b7sBVG/q6oqP6uqKr+rqqo+q6oqv6uqKr+rqqq+q6oqP6uqKr+rqqo+7AXRvuwF0b7sBVE/","byteLength":1032},{"uri":"data:application/octet-stream;base64,AACgwAAAoMAAAKBAAACgQAAAoMAAAKBAAACgQAAAoEAAAKBAAACgwAAAoEAAAKBAAACgwAAAoMAAAKDAAACgQAAAoMAAAKDAAACgQAAAoEAAAKDAAACgwAAAoEAAAKDAAAABAAIAAAACAAMAAQAFAAYAAQAGAAIABQAEAAcABQAHAAYABAAAAAMABAADAAcAAwACAAYAAwAGAAcABAAFAAEABAABAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAIAAAAAAAACAPwAAAIAAAAAAAACAPwAAAIAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAgAAAgD8AAAAAAAAAgAAAgD8AAAAAAAAAgAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAA7AXRvuwF0b7sBVE/q6oqP6uqKr+rqqo+7AXRPuwF0T7sBVE/7AXRvuwF0b7sBVE/7AXRPuwF0T7sBVE/q6oqv6uqKj+rqqo+q6oqP6uqKr+rqqo+7AXRPuwF0b7sBVG/q6oqP6uqKj+rqqq+q6oqP6uqKr+rqqo+q6oqP6uqKj+rqqq+7AXRPuwF0T7sBVE/7AXRPuwF0b7sBVG/q6oqv6uqKr+rqqq+7AXRvuwF0T7sBVG/7AXRPuwF0b7sBVG/7AXRvuwF0T7sBVG/q6oqP6uqKj+rqqq+q6oqv6uqKr+rqqq+7AXRvuwF0b7sBVE/q6oqv6uqKj+rqqo+q6oqv6uqKr+rqqq+q6oqv6uqKj+rqqo+7AXRvuwF0T7sBVG/q6oqv6uqKj+rqqo+7AXRPuwF0T7sBVE/q6oqP6uqKj+rqqq+q6oqv6uqKj+rqqo+q6oqP6uqKj+rqqq+7AXRvuwF0T7sBVG/q6oqv6uqKr+rqqq+7AXRPuwF0b7sBVG/q6oqP6uqKr+rqqo+q6oqv6uqKr+rqqq+q6oqP6uqKr+rqqo+7AXRvuwF0b7sBVE/","byteLength":1032},{"uri":"data:application/octet-stream;base64,AACgwAAAoMAAAKBAAACgQAAAoMAAAKBAAACgQAAAoEAAAKBAAACgwAAAoEAAAKBAAACgwAAAoMAAAKDAAACgQAAAoMAAAKDAAACgQAAAoEAAAKDAAACgwAAAoEAAAKDAAAABAAIAAAACAAMAAQAFAAYAAQAGAAIABQAEAAcABQAHAAYABAAAAAMABAADAAcAAwACAAYAAwAGAAcABAAFAAEABAABAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAIAAAAAAAACAPwAAAIAAAAAAAACAPwAAAIAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAgAAAgD8AAAAAAAAAgAAAgD8AAAAAAAAAgAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAA7AXRvuwF0b7sBVE/q6oqP6uqKr+rqqo+7AXRPuwF0T7sBVE/7AXRvuwF0b7sBVE/7AXRPuwF0T7sBVE/q6oqv6uqKj+rqqo+q6oqP6uqKr+rqqo+7AXRPuwF0b7sBVG/q6oqP6uqKj+rqqq+q6oqP6uqKr+rqqo+q6oqP6uqKj+rqqq+7AXRPuwF0T7sBVE/7AXRPuwF0b7sBVG/q6oqv6uqKr+rqqq+7AXRvuwF0T7sBVG/7AXRPuwF0b7sBVG/7AXRvuwF0T7sBVG/q6oqP6uqKj+rqqq+q6oqv6uqKr+rqqq+7AXRvuwF0b7sBVE/q6oqv6uqKj+rqqo+q6oqv6uqKr+rqqq+q6oqv6uqKj+rqqo+7AXRvuwF0T7sBVG/q6oqv6uqKj+rqqo+7AXRPuwF0T7sBVE/q6oqP6uqKj+rqqq+q6oqv6uqKj+rqqo+q6oqP6uqKj+rqqq+7AXRvuwF0T7sBVG/q6oqv6uqKr+rqqq+7AXRPuwF0b7sBVG/q6oqP6uqKr+rqqo+q6oqv6uqKr+rqqq+q6oqP6uqKr+rqqo+7AXRvuwF0b7sBVE/","byteLength":1032},{"uri":"data:application/octet-stream;base64,AAAgwQAAoMAAAKBAAAAgQQAAoMAAAKBAAAAgQQAAoEAAAKBAAAAgwQAAoEAAAKBAAAAgwQAAoMAAAKDAAAAgQQAAoMAAAKDAAAAgQQAAoEAAAKDAAAAgwQAAoEAAAKDAAAABAAIAAAACAAMAAQAFAAYAAQAGAAIABQAEAAcABQAHAAYABAAAAAMABAADAAcAAwACAAYAAwAGAAcABAAFAAEABAABAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAIAAAAAAAACAPwAAAIAAAAAAAACAPwAAAIAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAgAAAgD8AAAAAAAAAgAAAgD8AAAAAAAAAgAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAA7AXRvuwF0b7sBVE/q6oqP6uqKr+rqqo+7AXRPuwF0T7sBVE/7AXRvuwF0b7sBVE/7AXRPuwF0T7sBVE/q6oqv6uqKj+rqqo+q6oqP6uqKr+rqqo+7AXRPuwF0b7sBVG/q6oqP6uqKj+rqqq+q6oqP6uqKr+rqqo+q6oqP6uqKj+rqqq+7AXRPuwF0T7sBVE/7AXRPuwF0b7sBVG/q6oqv6uqKr+rqqq+7AXRvuwF0T7sBVG/7AXRPuwF0b7sBVG/7AXRvuwF0T7sBVG/q6oqP6uqKj+rqqq+q6oqv6uqKr+rqqq+7AXRvuwF0b7sBVE/q6oqv6uqKj+rqqo+q6oqv6uqKr+rqqq+q6oqv6uqKj+rqqo+7AXRvuwF0T7sBVG/q6oqv6uqKj+rqqo+7AXRPuwF0T7sBVE/q6oqP6uqKj+rqqq+q6oqv6uqKj+rqqo+q6oqP6uqKj+rqqq+7AXRvuwF0T7sBVG/q6oqv6uqKr+rqqq+7AXRPuwF0b7sBVG/q6oqP6uqKr+rqqo+q6oqv6uqKr+rqqq+q6oqP6uqKr+rqqo+7AXRvuwF0b7sBVE/","byteLength":1032},{"uri":"data:application/octet-stream;base64,AABwwQAAoMAAAHBBAABwQQAAoMAAAHBBAABwQQAADEIAAHBBAABwwQAADEIAAHBBAABwwQAAoMAAAHDBAABwQQAAoMAAAHDBAABwQQAADEIAAHDBAABwwQAADEIAAHDBAAABAAIAAAACAAMAAQAFAAYAAQAGAAIABQAEAAcABQAHAAYABAAAAAMABAADAAcAAwACAAYAAwAGAAcABAAFAAEABAABAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAIAAAAAAAACAPwAAAIAAAAAAAACAPwAAAIAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAgAAAgD8AAAAAAAAAgAAAgD8AAAAAAAAAgAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAA7AXRvuwF0b7sBVE/q6oqP6uqKr+rqqo+7AXRPuwF0T7sBVE/7AXRvuwF0b7sBVE/7AXRPuwF0T7sBVE/q6oqv6uqKj+rqqo+q6oqP6uqKr+rqqo+7AXRPuwF0b7sBVG/q6oqP6uqKj+rqqq+q6oqP6uqKr+rqqo+q6oqP6uqKj+rqqq+7AXRPuwF0T7sBVE/7AXRPuwF0b7sBVG/q6oqv6uqKr+rqqq+7AXRvuwF0T7sBVG/7AXRPuwF0b7sBVG/7AXRvuwF0T7sBVG/q6oqP6uqKj+rqqq+q6oqv6uqKr+rqqq+7AXRvuwF0b7sBVE/q6oqv6uqKj+rqqo+q6oqv6uqKr+rqqq+q6oqv6uqKj+rqqo+7AXRvuwF0T7sBVG/q6oqv6uqKj+rqqo+7AXRPuwF0T7sBVE/q6oqP6uqKj+rqqq+q6oqv6uqKj+rqqo+q6oqP6uqKj+rqqq+7AXRvuwF0T7sBVG/q6oqv6uqKr+rqqq+7AXRPuwF0b7sBVG/q6oqP6uqKr+rqqo+q6oqv6uqKr+rqqq+q6oqP6uqKr+rqqo+7AXRvuwF0b7sBVE/","byteLength":1032},{"uri":"data:application/octet-stream;base64,AABwwQAAoMAAAHBBAABwQQAAoMAAAHBBAABwQQAADEIAAHBBAABwwQAADEIAAHBBAABwwQAAoMAAAHDBAABwQQAAoMAAAHDBAABwQQAADEIAAHDBAABwwQAADEIAAHDBAAABAAIAAAACAAMAAQAFAAYAAQAGAAIABQAEAAcABQAHAAYABAAAAAMABAADAAcAAwACAAYAAwAGAAcABAAFAAEABAABAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAIAAAAAAAACAPwAAAIAAAAAAAACAPwAAAIAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAgAAAgD8AAAAAAAAAgAAAgD8AAAAAAAAAgAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAA7AXRvuwF0b7sBVE/q6oqP6uqKr+rqqo+7AXRPuwF0T7sBVE/7AXRvuwF0b7sBVE/7AXRPuwF0T7sBVE/q6oqv6uqKj+rqqo+q6oqP6uqKr+rqqo+7AXRPuwF0b7sBVG/q6oqP6uqKj+rqqq+q6oqP6uqKr+rqqo+q6oqP6uqKj+rqqq+7AXRPuwF0T7sBVE/7AXRPuwF0b7sBVG/q6oqv6uqKr+rqqq+7AXRvuwF0T7sBVG/7AXRPuwF0b7sBVG/7AXRvuwF0T7sBVG/q6oqP6uqKj+rqqq+q6oqv6uqKr+rqqq+7AXRvuwF0b7sBVE/q6oqv6uqKj+rqqo+q6oqv6uqKr+rqqq+q6oqv6uqKj+rqqo+7AXRvuwF0T7sBVG/q6oqv6uqKj+rqqo+7AXRPuwF0T7sBVE/q6oqP6uqKj+rqqq+q6oqv6uqKj+rqqo+q6oqP6uqKj+rqqq+7AXRvuwF0T7sBVG/q6oqv6uqKr+rqqq+7AXRPuwF0b7sBVG/q6oqP6uqKr+rqqo+q6oqv6uqKr+rqqq+q6oqP6uqKr+rqqo+7AXRvuwF0b7sBVE/","byteLength":1032},{"uri":"data:application/octet-stream;base64,AABIwgAADMIAAMhCAABIQgAADMIAAMhCAABIQgAADEIAAMhCAABIwgAADEIAAMhCAABIwgAADMIAAMjCAABIQgAADMIAAMjCAABIQgAADEIAAMjCAABIwgAADEIAAMjCAAABAAIAAAACAAMAAQAFAAYAAQAGAAIABQAEAAcABQAHAAYABAAAAAMABAADAAcAAwACAAYAAwAGAAcABAAFAAEABAABAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAIAAAAAAAACAPwAAAIAAAAAAAACAPwAAAIAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAgAAAgD8AAAAAAAAAgAAAgD8AAAAAAAAAgAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAA7AXRvuwF0b7sBVE/q6oqP6uqKr+rqqo+7AXRPuwF0T7sBVE/7AXRvuwF0b7sBVE/7AXRPuwF0T7sBVE/q6oqv6uqKj+rqqo+q6oqP6uqKr+rqqo+7AXRPuwF0b7sBVG/q6oqP6uqKj+rqqq+q6oqP6uqKr+rqqo+q6oqP6uqKj+rqqq+7AXRPuwF0T7sBVE/7AXRPuwF0b7sBVG/q6oqv6uqKr+rqqq+7AXRvuwF0T7sBVG/7AXRPuwF0b7sBVG/7AXRvuwF0T7sBVG/q6oqP6uqKj+rqqq+q6oqv6uqKr+rqqq+7AXRvuwF0b7sBVE/q6oqv6uqKj+rqqo+q6oqv6uqKr+rqqq+q6oqv6uqKj+rqqo+7AXRvuwF0T7sBVG/q6oqv6uqKj+rqqo+7AXRPuwF0T7sBVE/q6oqP6uqKj+rqqq+q6oqv6uqKj+rqqo+q6oqP6uqKj+rqqq+7AXRvuwF0T7sBVG/q6oqv6uqKr+rqqq+7AXRPuwF0b7sBVG/q6oqP6uqKr+rqqo+q6oqv6uqKr+rqqq+q6oqP6uqKr+rqqo+7AXRvuwF0b7sBVE/","byteLength":1032},{"uri":"data:application/octet-stream;base64,AAA4wQAADMIAAEhBAAA4QQAADMIAAEhBAAA4QQAAoEAAAEhBAAA4wQAAoEAAAEhBAAA4wQAADMIAAEjBAAA4QQAADMIAAEjBAAA4QQAAoEAAAEjBAAA4wQAAoEAAAEjBAAABAAIAAAACAAMAAQAFAAYAAQAGAAIABQAEAAcABQAHAAYABAAAAAMABAADAAcAAwACAAYAAwAGAAcABAAFAAEABAABAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAIAAAAAAAACAPwAAAIAAAAAAAACAPwAAAIAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAgAAAgD8AAAAAAAAAgAAAgD8AAAAAAAAAgAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAA7AXRvuwF0b7sBVE/q6oqP6uqKr+rqqo+7AXRPuwF0T7sBVE/7AXRvuwF0b7sBVE/7AXRPuwF0T7sBVE/q6oqv6uqKj+rqqo+q6oqP6uqKr+rqqo+7AXRPuwF0b7sBVG/q6oqP6uqKj+rqqq+q6oqP6uqKr+rqqo+q6oqP6uqKj+rqqq+7AXRPuwF0T7sBVE/7AXRPuwF0b7sBVG/q6oqv6uqKr+rqqq+7AXRvuwF0T7sBVG/7AXRPuwF0b7sBVG/7AXRvuwF0T7sBVG/q6oqP6uqKj+rqqq+q6oqv6uqKr+rqqq+7AXRvuwF0b7sBVE/q6oqv6uqKj+rqqo+q6oqv6uqKr+rqqq+q6oqv6uqKj+rqqo+7AXRvuwF0T7sBVG/q6oqv6uqKj+rqqo+7AXRPuwF0T7sBVE/q6oqP6uqKj+rqqq+q6oqv6uqKj+rqqo+q6oqP6uqKj+rqqq+7AXRvuwF0T7sBVG/q6oqv6uqKr+rqqq+7AXRPuwF0b7sBVG/q6oqP6uqKr+rqqo+q6oqv6uqKr+rqqq+q6oqP6uqKr+rqqo+7AXRvuwF0b7sBVE/","byteLength":1032},{"uri":"data:application/octet-stream;base64,AAA4wQAADMIAAEhBAAA4QQAADMIAAEhBAAA4QQAAoEAAAEhBAAA4wQAAoEAAAEhBAAA4wQAADMIAAEjBAAA4QQAADMIAAEjBAAA4QQAAoEAAAEjBAAA4wQAAoEAAAEjBAAABAAIAAAACAAMAAQAFAAYAAQAGAAIABQAEAAcABQAHAAYABAAAAAMABAADAAcAAwACAAYAAwAGAAcABAAFAAEABAABAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAIAAAAAAAACAPwAAAIAAAAAAAACAPwAAAIAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAgAAAgD8AAAAAAAAAgAAAgD8AAAAAAAAAgAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAA7AXRvuwF0b7sBVE/q6oqP6uqKr+rqqo+7AXRPuwF0T7sBVE/7AXRvuwF0b7sBVE/7AXRPuwF0T7sBVE/q6oqv6uqKj+rqqo+q6oqP6uqKr+rqqo+7AXRPuwF0b7sBVG/q6oqP6uqKj+rqqq+q6oqP6uqKr+rqqo+q6oqP6uqKj+rqqq+7AXRPuwF0T7sBVE/7AXRPuwF0b7sBVG/q6oqv6uqKr+rqqq+7AXRvuwF0T7sBVG/7AXRPuwF0b7sBVG/7AXRvuwF0T7sBVG/q6oqP6uqKj+rqqq+q6oqv6uqKr+rqqq+7AXRvuwF0b7sBVE/q6oqv6uqKj+rqqo+q6oqv6uqKr+rqqq+q6oqv6uqKj+rqqo+7AXRvuwF0T7sBVG/q6oqv6uqKj+rqqo+7AXRPuwF0T7sBVE/q6oqP6uqKj+rqqq+q6oqv6uqKj+rqqo+q6oqP6uqKj+rqqq+7AXRvuwF0T7sBVG/q6oqv6uqKr+rqqq+7AXRPuwF0b7sBVG/q6oqP6uqKr+rqqo+q6oqv6uqKr+rqqq+q6oqP6uqKr+rqqo+7AXRvuwF0b7sBVE/","byteLength":1032},{"uri":"data:application/octet-stream;base64,AAA4wQAADMIAAEhBAAA4QQAADMIAAEhBAAA4QQAAoEAAAEhBAAA4wQAAoEAAAEhBAAA4wQAADMIAAEjBAAA4QQAADMIAAEjBAAA4QQAAoEAAAEjBAAA4wQAAoEAAAEjBAAABAAIAAAACAAMAAQAFAAYAAQAGAAIABQAEAAcABQAHAAYABAAAAAMABAADAAcAAwACAAYAAwAGAAcABAAFAAEABAABAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAIAAAAAAAACAPwAAAIAAAAAAAACAPwAAAIAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAgAAAgD8AAAAAAAAAgAAAgD8AAAAAAAAAgAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAA7AXRvuwF0b7sBVE/q6oqP6uqKr+rqqo+7AXRPuwF0T7sBVE/7AXRvuwF0b7sBVE/7AXRPuwF0T7sBVE/q6oqv6uqKj+rqqo+q6oqP6uqKr+rqqo+7AXRPuwF0b7sBVG/q6oqP6uqKj+rqqq+q6oqP6uqKr+rqqo+q6oqP6uqKj+rqqq+7AXRPuwF0T7sBVE/7AXRPuwF0b7sBVG/q6oqv6uqKr+rqqq+7AXRvuwF0T7sBVG/7AXRPuwF0b7sBVG/7AXRvuwF0T7sBVG/q6oqP6uqKj+rqqq+q6oqv6uqKr+rqqq+7AXRvuwF0b7sBVE/q6oqv6uqKj+rqqo+q6oqv6uqKr+rqqq+q6oqv6uqKj+rqqo+7AXRvuwF0T7sBVG/q6oqv6uqKj+rqqo+7AXRPuwF0T7sBVE/q6oqP6uqKj+rqqq+q6oqv6uqKj+rqqo+q6oqP6uqKj+rqqq+7AXRvuwF0T7sBVG/q6oqv6uqKr+rqqq+7AXRPuwF0b7sBVG/q6oqP6uqKr+rqqo+q6oqv6uqKr+rqqq+q6oqP6uqKr+rqqo+7AXRvuwF0b7sBVE/","byteLength":1032},{"uri":"data:application/octet-stream;base64,AAA4wQAADMIAAEhBAAA4QQAADMIAAEhBAAA4QQAAoEAAAEhBAAA4wQAAoEAAAEhBAAA4wQAADMIAAEjBAAA4QQAADMIAAEjBAAA4QQAAoEAAAEjBAAA4wQAAoEAAAEjBAAABAAIAAAACAAMAAQAFAAYAAQAGAAIABQAEAAcABQAHAAYABAAAAAMABAADAAcAAwACAAYAAwAGAAcABAAFAAEABAABAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAIAAAAAAAACAPwAAAIAAAAAAAACAPwAAAIAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAgAAAgD8AAAAAAAAAgAAAgD8AAAAAAAAAgAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAA7AXRvuwF0b7sBVE/q6oqP6uqKr+rqqo+7AXRPuwF0T7sBVE/7AXRvuwF0b7sBVE/7AXRPuwF0T7sBVE/q6oqv6uqKj+rqqo+q6oqP6uqKr+rqqo+7AXRPuwF0b7sBVG/q6oqP6uqKj+rqqq+q6oqP6uqKr+rqqo+q6oqP6uqKj+rqqq+7AXRPuwF0T7sBVE/7AXRPuwF0b7sBVG/q6oqv6uqKr+rqqq+7AXRvuwF0T7sBVG/7AXRPuwF0b7sBVG/7AXRvuwF0T7sBVG/q6oqP6uqKj+rqqq+q6oqv6uqKr+rqqq+7AXRvuwF0b7sBVE/q6oqv6uqKj+rqqo+q6oqv6uqKr+rqqq+q6oqv6uqKj+rqqo+7AXRvuwF0T7sBVG/q6oqv6uqKj+rqqo+7AXRPuwF0T7sBVE/q6oqP6uqKj+rqqq+q6oqv6uqKj+rqqo+q6oqP6uqKj+rqqq+7AXRvuwF0T7sBVG/q6oqv6uqKr+rqqq+7AXRPuwF0b7sBVG/q6oqP6uqKr+rqqo+q6oqv6uqKr+rqqq+q6oqP6uqKr+rqqo+7AXRvuwF0b7sBVE/","byteLength":1032}],"bufferViews":[{"buffer":0,"byteOffset":0,"byteLength":96,"target":34962},{"buffer":0,"byteOffset":168,"byteLength":432,"target":34962},{"buffer":0,"byteOffset":600,"byteLength":432,"target":34962},{"buffer":0,"byteOffset":96,"byteLength":72,"target":34963},{"buffer":1,"byteOffset":0,"byteLength":96,"target":34962},{"buffer":1,"byteOffset":168,"byteLength":432,"target":34962},{"buffer":1,"byteOffset":600,"byteLength":432,"target":34962},{"buffer":1,"byteOffset":96,"byteLength":72,"target":34963},{"buffer":2,"byteOffset":0,"byteLength":96,"target":34962},{"buffer":2,"byteOffset":168,"byteLength":432,"target":34962},{"buffer":2,"byteOffset":600,"byteLength":432,"target":34962},{"buffer":2,"byteOffset":96,"byteLength":72,"target":34963},{"buffer":3,"byteOffset":0,"byteLength":96,"target":34962},{"buffer":3,"byteOffset":168,"byteLength":432,"target":34962},{"buffer":3,"byteOffset":600,"byteLength":432,"target":34962},{"buffer":3,"byteOffset":96,"byteLength":72,"target":34963},{"buffer":4,"byteOffset":0,"byteLength":96,"target":34962},{"buffer":4,"byteOffset":168,"byteLength":432,"target":34962},{"buffer":4,"byteOffset":600,"byteLength":432,"target":34962},{"buffer":4,"byteOffset":96,"byteLength":72,"target":34963},{"buffer":5,"byteOffset":0,"byteLength":96,"target":34962},{"buffer":5,"byteOffset":168,"byteLength":432,"target":34962},{"buffer":5,"byteOffset":600,"byteLength":432,"target":34962},{"buffer":5,"byteOffset":96,"byteLength":72,"target":34963},{"buffer":6,"byteOffset":0,"byteLength":96,"target":34962},{"buffer":6,"byteOffset":168,"byteLength":432,"target":34962},{"buffer":6,"byteOffset":600,"byteLength":432,"target":34962},{"buffer":6,"byteOffset":96,"byteLength":72,"target":34963},{"buffer":7,"byteOffset":0,"byteLength":96,"target":34962},{"buffer":7,"byteOffset":168,"byteLength":432,"target":34962},{"buffer":7,"byteOffset":600,"byteLength":432,"target":34962},{"buffer":7,"byteOffset":96,"byteLength":72,"target":34963},{"buffer":8,"byteOffset":0,"byteLength":96,"target":34962},{"buffer":8,"byteOffset":168,"byteLength":432,"target":34962},{"buffer":8,"byteOffset":600,"byteLength":432,"target":34962},{"buffer":8,"byteOffset":96,"byteLength":72,"target":34963},{"buffer":9,"byteOffset":0,"byteLength":96,"target":34962},{"buffer":9,"byteOffset":168,"byteLength":432,"target":34962},{"buffer":9,"byteOffset":600,"byteLength":432,"target":34962},{"buffer":9,"byteOffset":96,"byteLength":72,"target":34963},{"buffer":10,"byteOffset":0,"byteLength":96,"target":34962},{"buffer":10,"byteOffset":168,"byteLength":432,"target":34962},{"buffer":10,"byteOffset":600,"byteLength":432,"target":34962},{"buffer":10,"byteOffset":96,"byteLength":72,"target":34963}],"accessors":[{"bufferView":0,"byteOffset":0,"componentType":5126,"count":8,"type":"VEC3","max":[],"min":[]},{"bufferView":1,"byteOffset":0,"componentType":5126,"count":36,"type":"VEC3","max":[],"min":[]},{"bufferView":2,"byteOffset":0,"componentType":5126,"count":36,"type":"VEC3","max":[],"min":[]},{"bufferView":3,"byteOffset":0,"componentType":5123,"count":36,"type":"SCALAR","max":[],"min":[]},{"bufferView":4,"byteOffset":0,"componentType":5126,"count":8,"type":"VEC3","max":[],"min":[]},{"bufferView":5,"byteOffset":0,"componentType":5126,"count":36,"type":"VEC3","max":[],"min":[]},{"bufferView":6,"byteOffset":0,"componentType":5126,"count":36,"type":"VEC3","max":[],"min":[]},{"bufferView":7,"byteOffset":0,"componentType":5123,"count":36,"type":"SCALAR","max":[],"min":[]},{"bufferView":8,"byteOffset":0,"componentType":5126,"count":8,"type":"VEC3","max":[],"min":[]},{"bufferView":9,"byteOffset":0,"componentType":5126,"count":36,"type":"VEC3","max":[],"min":[]},{"bufferView":10,"byteOffset":0,"componentType":5126,"count":36,"type":"VEC3","max":[],"min":[]},{"bufferView":11,"byteOffset":0,"componentType":5123,"count":36,"type":"SCALAR","max":[],"min":[]},{"bufferView":12,"byteOffset":0,"componentType":5126,"count":8,"type":"VEC3","max":[],"min":[]},{"bufferView":13,"byteOffset":0,"componentType":5126,"count":36,"type":"VEC3","max":[],"min":[]},{"bufferView":14,"byteOffset":0,"componentType":5126,"count":36,"type":"VEC3","max":[],"min":[]},{"bufferView":15,"byteOffset":0,"componentType":5123,"count":36,"type":"SCALAR","max":[],"min":[]},{"bufferView":16,"byteOffset":0,"componentType":5126,"count":8,"type":"VEC3","max":[],"min":[]},{"bufferView":17,"byteOffset":0,"componentType":5126,"count":36,"type":"VEC3","max":[],"min":[]},{"bufferView":18,"byteOffset":0,"componentType":5126,"count":36,"type":"VEC3","max":[],"min":[]},{"bufferView":19,"byteOffset":0,"componentType":5123,"count":36,"type":"SCALAR","max":[],"min":[]},{"bufferView":20,"byteOffset":0,"componentType":5126,"count":8,"type":"VEC3","max":[],"min":[]},{"bufferView":21,"byteOffset":0,"componentType":5126,"count":36,"type":"VEC3","max":[],"min":[]},{"bufferView":22,"byteOffset":0,"componentType":5126,"count":36,"type":"VEC3","max":[],"min":[]},{"bufferView":23,"byteOffset":0,"componentType":5123,"count":36,"type":"SCALAR","max":[],"min":[]},{"bufferView":24,"byteOffset":0,"componentType":5126,"count":8,"type":"VEC3","max":[],"min":[]},{"bufferView":25,"byteOffset":0,"componentType":5126,"count":36,"type":"VEC3","max":[],"min":[]},{"bufferView":26,"byteOffset":0,"componentType":5126,"count":36,"type":"VEC3","max":[],"min":[]},{"bufferView":27,"byteOffset":0,"componentType":5123,"count":36,"type":"SCALAR","max":[],"min":[]},{"bufferView":28,"byteOffset":0,"componentType":5126,"count":8,"type":"VEC3","max":[],"min":[]},{"bufferView":29,"byteOffset":0,"componentType":5126,"count":36,"type":"VEC3","max":[],"min":[]},{"bufferView":30,"byteOffset":0,"componentType":5126,"count":36,"type":"VEC3","max":[],"min":[]},{"bufferView":31,"byteOffset":0,"componentType":5123,"count":36,"type":"SCALAR","max":[],"min":[]},{"bufferView":32,"byteOffset":0,"componentType":5126,"count":8,"type":"VEC3","max":[],"min":[]},{"bufferView":33,"byteOffset":0,"componentType":5126,"count":36,"type":"VEC3","max":[],"min":[]},{"bufferView":34,"byteOffset":0,"componentType":5126,"count":36,"type":"VEC3","max":[],"min":[]},{"bufferView":35,"byteOffset":0,"componentType":5123,"count":36,"type":"SCALAR","max":[],"min":[]},{"bufferView":36,"byteOffset":0,"componentType":5126,"count":8,"type":"VEC3","max":[],"min":[]},{"bufferView":37,"byteOffset":0,"componentType":5126,"count":36,"type":"VEC3","max":[],"min":[]},{"bufferView":38,"byteOffset":0,"componentType":5126,"count":36,"type":"VEC3","max":[],"min":[]},{"bufferView":39,"byteOffset":0,"componentType":5123,"count":36,"type":"SCALAR","max":[],"min":[]},{"bufferView":40,"byteOffset":0,"componentType":5126,"count":8,"type":"VEC3","max":[],"min":[]},{"bufferView":41,"byteOffset":0,"componentType":5126,"count":36,"type":"VEC3","max":[],"min":[]},{"bufferView":42,"byteOffset":0,"componentType":5126,"count":36,"type":"VEC3","max":[],"min":[]},{"bufferView":43,"byteOffset":0,"componentType":5123,"count":36,"type":"SCALAR","max":[],"min":[]}],"samplers":[],"images":[],"textures":[],"materials":[{"type":"Basic Material","name":"head","vertexShader":"\n#define PI 3.1415926535897932384626433832795\nattribute vec4 a_position;\n\nuniform mat4 u_worldMatrix;\nuniform mat4 u_viewMatrix;\nuniform vec4 u_color;\n\nvarying vec4 v_color;\n\nvoid main() { \n gl_Position = u_viewMatrix * u_worldMatrix * a_position;\n v_color = u_color;\n}\n","fragmentShader":"\nprecision highp float;\nvarying vec4 v_color;\n\nvoid main() {\n gl_FragColor = v_color / 255.0;\n}\n","uniforms":{"color":[205,127,50,255]}},{"type":"Phong Material","name":"head-phong","vertexShader":"\nprecision mediump float;\n\nattribute vec3 a_position;\nattribute vec3 a_faceNormal;\nattribute vec3 a_vertexNormal;\nattribute vec2 a_displacementUV;\nattribute vec2 a_diffuseUV;\nattribute vec2 a_specularUV;\nattribute vec2 a_normalUV;\nattribute vec3 a_tangent;\nattribute vec3 a_bitangent;\n\nuniform mat4 u_worldMatrix;\nuniform mat4 u_viewMatrix;\nuniform sampler2D u_displacementMap;\nuniform float u_displacementScale;\nuniform float u_displacementBias;\n\nvarying vec3 normalSurface;\nvarying vec3 vertexPosition;\nvarying vec2 diffuseUV;\nvarying vec2 specularUV;\nvarying mat3 v_tbn;\nvarying vec2 v_texcoord;\nvarying vec3 v_pos;\n\nvoid main() {\n vec4 displacement = texture2D(u_displacementMap, a_displacementUV);\n\n vec4 displacementVector = normalize(vec4(a_vertexNormal.xyz, 0.0)) * (displacement.r * u_displacementScale + u_displacementBias);\n\n vec4 vertexPosition4 = u_worldMatrix * (vec4(a_position, 1.0) + displacementVector);\n vertexPosition = vec3(vertexPosition4) / vertexPosition4.w;\n normalSurface = (u_viewMatrix * u_worldMatrix * vec4(a_faceNormal, 1.0)).xyz;\n diffuseUV = a_diffuseUV;\n specularUV = a_specularUV;\n \n vec3 T = normalize(vec3(u_worldMatrix * vec4(a_tangent, 0.0)));\n vec3 B = normalize(vec3(u_worldMatrix * vec4(a_bitangent, 0.0)));\n \n vec3 normalTemp = cross(a_tangent, a_bitangent);\n vec3 N = normalize(vec3(u_worldMatrix * vec4(normalTemp, 0.0)));\n\n v_tbn = mat3(T, B, N);\n v_texcoord = a_normalUV;\n v_pos = a_position;\n \n gl_Position = u_viewMatrix * vertexPosition4;\n}\n","fragmentShader":"\nprecision mediump float;\n\n// Tecture sampler\nuniform sampler2D u_diffuseMap;\nuniform sampler2D u_specularMap;\nuniform sampler2D u_normalMap;\nuniform bool u_hasNormalMap;\nuniform float u_hasDiffuseMap;\nuniform float u_hasSpecularMap;\n\n// Material uniform\nuniform float u_shininess;\nuniform vec4 u_ambientColor;\nuniform vec4 u_diffuseColor;\nuniform vec4 u_specularColor;\n\n// Light uniform\nuniform int u_numLights;\n\n// Light properties\nuniform float u_lightType_0;\nuniform vec3 u_lightPosition_0;\nuniform vec4 u_lightColor_0;\nuniform vec4 u_lightAmbient_0;\nuniform vec4 u_lightDiffuse_0;\nuniform vec4 u_lightSpecular_0;\nuniform vec3 u_lightTarget_0;\nuniform float u_lightConstant_0;\nuniform float u_lightLinear_0;\nuniform float u_lightQuadratic_0;\n\nuniform float u_lightType_1;\nuniform vec3 u_lightPosition_1;\nuniform vec4 u_lightColor_1;\nuniform vec4 u_lightAmbient_1;\nuniform vec4 u_lightDiffuse_1;\nuniform vec4 u_lightSpecular_1;\nuniform vec3 u_lightTarget_1;\nuniform float u_lightConstant_1;\nuniform float u_lightLinear_1;\nuniform float u_lightQuadratic_1;\n\nuniform float u_mode;\n\nvarying vec3 normalSurface;\nvarying vec3 vertexPosition;\nvarying vec2 diffuseUV;\nvarying vec2 specularUV;\n\nvarying mat3 v_tbn;\nvarying vec2 v_texcoord;\n\nvoid main() {\n vec3 N;\n \n if (u_hasNormalMap) {\n N = texture2D(u_normalMap, v_texcoord).rgb;\n N = N * 2.0 - 1.0;\n N = normalize(v_tbn * N);\n } else {\n N = normalize(normalSurface);\n }\n \n vec3 finalAmbient = vec3(0.0);\n vec3 finalDiffuse = vec3(0.0);\n vec3 finalSpecular = vec3(0.0);\n\n // Convert colors from 0-255 to 0-1\n vec3 ambientColor = u_ambientColor.rgb / 255.0;\n vec3 diffuseColor = u_diffuseColor.rgb / 255.0;\n vec3 specularColor = u_specularColor.rgb / 255.0;\n\n for (int i = 0; i < 2; i++) {\n vec3 L;\n if (i == 0 && u_lightType_0 == 0.0) {\n // Directional Light\n L = normalize(u_lightTarget_0 - vertexPosition);\n } else if (i == 1 && u_lightType_1 == 0.0) {\n // Directional Light\n L = normalize(u_lightTarget_1 - vertexPosition);\n } else if (i == 0 && u_lightType_0 == 1.0) {\n // Point Light\n L = normalize(u_lightPosition_0 - vertexPosition);\n } else {\n // Point Light\n L = normalize(u_lightPosition_1 - vertexPosition);\n }\n\n vec3 lightAmbient = (i == 0) ? (u_lightAmbient_0.rgb / 255.0) : (u_lightAmbient_1.rgb / 255.0);\n vec3 lightDiffuse = (i == 0) ? (u_lightDiffuse_0.rgb / 255.0) : (u_lightDiffuse_1.rgb / 255.0);\n vec3 lightSpecular = (i == 0) ? (u_lightSpecular_0.rgb / 255.0) : (u_lightSpecular_1.rgb / 255.0);\n\n // Lambert's cosine law\n float lambertian = max(dot(N, L), 0.0);\n float specular = 0.0;\n if (lambertian > 0.0) {\n vec3 R = reflect(-L, N); // Reflected light vector\n vec3 V = normalize(-vertexPosition); // Vector to viewer\n \n // Compute the specular term\n float specAngle = max(dot(R, V), 0.0);\n specular = pow(specAngle, u_shininess);\n }\n\n // Directional light calculation\n vec3 directionalAmbient = lightAmbient * ambientColor;\n vec3 directionalDiffuse = lightDiffuse * lambertian * diffuseColor;\n vec3 directionalSpecular = lightSpecular * specular * specularColor;\n\n // Point light calculation 1\n float distance1 = length(u_lightPosition_0 - vertexPosition);\n float attenuation1 = 1.0 / (u_lightConstant_0 + u_lightLinear_0 * distance1 + u_lightQuadratic_0 * distance1 * distance1);\n\n vec3 pointAmbient1 = attenuation1 * lightAmbient * ambientColor;\n vec3 pointDiffuse1 = attenuation1 * lightDiffuse * lambertian * diffuseColor;\n vec3 pointSpecular1 = attenuation1 * lightSpecular * specular * specularColor;\n\n // Point light calculation 2\n float distance2 = length(u_lightPosition_1 - vertexPosition);\n float attenuation2 = 1.0 / (u_lightConstant_1 + u_lightLinear_1 * distance2 + u_lightQuadratic_1 * distance2 * distance2);\n\n vec3 pointAmbient2 = attenuation2 * lightAmbient * ambientColor;\n vec3 pointDiffuse2 = attenuation2 * lightDiffuse * lambertian * diffuseColor;\n vec3 pointSpecular2 = attenuation2 * lightSpecular * specular * specularColor;\n\n // Processing by u_mode\n // Mode 1 : 1st Directional, 2nd Point\n if (u_mode == 1.0) {\n if (i == 0) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n } else if (i == 1) {\n finalAmbient += pointAmbient2;\n finalDiffuse += pointDiffuse2;\n finalSpecular += pointSpecular2;\n }\n }\n // Mode 2 : 1st Point, 2nd Directional\n else if (u_mode == 2.0) {\n if (i == 0) {\n finalAmbient += pointAmbient1;\n finalDiffuse += pointDiffuse1;\n finalSpecular += pointSpecular1;\n } else if (i == 1) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n }\n }\n // Mode 3 : 1st Directional, 2nd None\n else if (u_mode == 3.0 && i == 0) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n }\n // Mode 4 : 1st Point, 2nd None\n else if (u_mode == 4.0) {\n finalAmbient += pointAmbient1;\n finalDiffuse += pointAmbient1;\n finalSpecular += pointAmbient1;\n }\n }\n\n // Using texture sampler\n vec3 fixedDiffuse = finalDiffuse;\n if (u_hasDiffuseMap == 1.0) {\n fixedDiffuse = fixedDiffuse * texture2D(u_diffuseMap, diffuseUV).rgb;\n }\n\n vec3 fixedSpecular = finalSpecular;\n\n if (u_hasSpecularMap == 1.0) {\n fixedSpecular = finalSpecular * texture2D(u_specularMap, specularUV).rgb;\n }\n\n vec3 finalColor = finalAmbient + fixedDiffuse + fixedSpecular;\n gl_FragColor = vec4(finalColor, 1.0);\n \n}\n","uniforms":{"ambientColor":[205,127,50,255],"diffuseColor":[205,127,50,255],"specularColor":[255,255,255,255],"shininess":60,"diffuseMaps":[],"normalMaps":[],"displacementMaps":[],"specularMaps":[],"diffuseMap":-1,"normalMap":-1,"displacementMap":-1,"specularMap":-1}},{"type":"Basic Material","name":"eye","vertexShader":"\n#define PI 3.1415926535897932384626433832795\nattribute vec4 a_position;\n\nuniform mat4 u_worldMatrix;\nuniform mat4 u_viewMatrix;\nuniform vec4 u_color;\n\nvarying vec4 v_color;\n\nvoid main() { \n gl_Position = u_viewMatrix * u_worldMatrix * a_position;\n v_color = u_color;\n}\n","fragmentShader":"\nprecision highp float;\nvarying vec4 v_color;\n\nvoid main() {\n gl_FragColor = v_color / 255.0;\n}\n","uniforms":{"color":[0,0,0,255]}},{"type":"Phong Material","name":"eye-phong","vertexShader":"\nprecision mediump float;\n\nattribute vec3 a_position;\nattribute vec3 a_faceNormal;\nattribute vec3 a_vertexNormal;\nattribute vec2 a_displacementUV;\nattribute vec2 a_diffuseUV;\nattribute vec2 a_specularUV;\nattribute vec2 a_normalUV;\nattribute vec3 a_tangent;\nattribute vec3 a_bitangent;\n\nuniform mat4 u_worldMatrix;\nuniform mat4 u_viewMatrix;\nuniform sampler2D u_displacementMap;\nuniform float u_displacementScale;\nuniform float u_displacementBias;\n\nvarying vec3 normalSurface;\nvarying vec3 vertexPosition;\nvarying vec2 diffuseUV;\nvarying vec2 specularUV;\nvarying mat3 v_tbn;\nvarying vec2 v_texcoord;\nvarying vec3 v_pos;\n\nvoid main() {\n vec4 displacement = texture2D(u_displacementMap, a_displacementUV);\n\n vec4 displacementVector = normalize(vec4(a_vertexNormal.xyz, 0.0)) * (displacement.r * u_displacementScale + u_displacementBias);\n\n vec4 vertexPosition4 = u_worldMatrix * (vec4(a_position, 1.0) + displacementVector);\n vertexPosition = vec3(vertexPosition4) / vertexPosition4.w;\n normalSurface = (u_viewMatrix * u_worldMatrix * vec4(a_faceNormal, 1.0)).xyz;\n diffuseUV = a_diffuseUV;\n specularUV = a_specularUV;\n \n vec3 T = normalize(vec3(u_worldMatrix * vec4(a_tangent, 0.0)));\n vec3 B = normalize(vec3(u_worldMatrix * vec4(a_bitangent, 0.0)));\n \n vec3 normalTemp = cross(a_tangent, a_bitangent);\n vec3 N = normalize(vec3(u_worldMatrix * vec4(normalTemp, 0.0)));\n\n v_tbn = mat3(T, B, N);\n v_texcoord = a_normalUV;\n v_pos = a_position;\n \n gl_Position = u_viewMatrix * vertexPosition4;\n}\n","fragmentShader":"\nprecision mediump float;\n\n// Tecture sampler\nuniform sampler2D u_diffuseMap;\nuniform sampler2D u_specularMap;\nuniform sampler2D u_normalMap;\nuniform bool u_hasNormalMap;\nuniform float u_hasDiffuseMap;\nuniform float u_hasSpecularMap;\n\n// Material uniform\nuniform float u_shininess;\nuniform vec4 u_ambientColor;\nuniform vec4 u_diffuseColor;\nuniform vec4 u_specularColor;\n\n// Light uniform\nuniform int u_numLights;\n\n// Light properties\nuniform float u_lightType_0;\nuniform vec3 u_lightPosition_0;\nuniform vec4 u_lightColor_0;\nuniform vec4 u_lightAmbient_0;\nuniform vec4 u_lightDiffuse_0;\nuniform vec4 u_lightSpecular_0;\nuniform vec3 u_lightTarget_0;\nuniform float u_lightConstant_0;\nuniform float u_lightLinear_0;\nuniform float u_lightQuadratic_0;\n\nuniform float u_lightType_1;\nuniform vec3 u_lightPosition_1;\nuniform vec4 u_lightColor_1;\nuniform vec4 u_lightAmbient_1;\nuniform vec4 u_lightDiffuse_1;\nuniform vec4 u_lightSpecular_1;\nuniform vec3 u_lightTarget_1;\nuniform float u_lightConstant_1;\nuniform float u_lightLinear_1;\nuniform float u_lightQuadratic_1;\n\nuniform float u_mode;\n\nvarying vec3 normalSurface;\nvarying vec3 vertexPosition;\nvarying vec2 diffuseUV;\nvarying vec2 specularUV;\n\nvarying mat3 v_tbn;\nvarying vec2 v_texcoord;\n\nvoid main() {\n vec3 N;\n \n if (u_hasNormalMap) {\n N = texture2D(u_normalMap, v_texcoord).rgb;\n N = N * 2.0 - 1.0;\n N = normalize(v_tbn * N);\n } else {\n N = normalize(normalSurface);\n }\n \n vec3 finalAmbient = vec3(0.0);\n vec3 finalDiffuse = vec3(0.0);\n vec3 finalSpecular = vec3(0.0);\n\n // Convert colors from 0-255 to 0-1\n vec3 ambientColor = u_ambientColor.rgb / 255.0;\n vec3 diffuseColor = u_diffuseColor.rgb / 255.0;\n vec3 specularColor = u_specularColor.rgb / 255.0;\n\n for (int i = 0; i < 2; i++) {\n vec3 L;\n if (i == 0 && u_lightType_0 == 0.0) {\n // Directional Light\n L = normalize(u_lightTarget_0 - vertexPosition);\n } else if (i == 1 && u_lightType_1 == 0.0) {\n // Directional Light\n L = normalize(u_lightTarget_1 - vertexPosition);\n } else if (i == 0 && u_lightType_0 == 1.0) {\n // Point Light\n L = normalize(u_lightPosition_0 - vertexPosition);\n } else {\n // Point Light\n L = normalize(u_lightPosition_1 - vertexPosition);\n }\n\n vec3 lightAmbient = (i == 0) ? (u_lightAmbient_0.rgb / 255.0) : (u_lightAmbient_1.rgb / 255.0);\n vec3 lightDiffuse = (i == 0) ? (u_lightDiffuse_0.rgb / 255.0) : (u_lightDiffuse_1.rgb / 255.0);\n vec3 lightSpecular = (i == 0) ? (u_lightSpecular_0.rgb / 255.0) : (u_lightSpecular_1.rgb / 255.0);\n\n // Lambert's cosine law\n float lambertian = max(dot(N, L), 0.0);\n float specular = 0.0;\n if (lambertian > 0.0) {\n vec3 R = reflect(-L, N); // Reflected light vector\n vec3 V = normalize(-vertexPosition); // Vector to viewer\n \n // Compute the specular term\n float specAngle = max(dot(R, V), 0.0);\n specular = pow(specAngle, u_shininess);\n }\n\n // Directional light calculation\n vec3 directionalAmbient = lightAmbient * ambientColor;\n vec3 directionalDiffuse = lightDiffuse * lambertian * diffuseColor;\n vec3 directionalSpecular = lightSpecular * specular * specularColor;\n\n // Point light calculation 1\n float distance1 = length(u_lightPosition_0 - vertexPosition);\n float attenuation1 = 1.0 / (u_lightConstant_0 + u_lightLinear_0 * distance1 + u_lightQuadratic_0 * distance1 * distance1);\n\n vec3 pointAmbient1 = attenuation1 * lightAmbient * ambientColor;\n vec3 pointDiffuse1 = attenuation1 * lightDiffuse * lambertian * diffuseColor;\n vec3 pointSpecular1 = attenuation1 * lightSpecular * specular * specularColor;\n\n // Point light calculation 2\n float distance2 = length(u_lightPosition_1 - vertexPosition);\n float attenuation2 = 1.0 / (u_lightConstant_1 + u_lightLinear_1 * distance2 + u_lightQuadratic_1 * distance2 * distance2);\n\n vec3 pointAmbient2 = attenuation2 * lightAmbient * ambientColor;\n vec3 pointDiffuse2 = attenuation2 * lightDiffuse * lambertian * diffuseColor;\n vec3 pointSpecular2 = attenuation2 * lightSpecular * specular * specularColor;\n\n // Processing by u_mode\n // Mode 1 : 1st Directional, 2nd Point\n if (u_mode == 1.0) {\n if (i == 0) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n } else if (i == 1) {\n finalAmbient += pointAmbient2;\n finalDiffuse += pointDiffuse2;\n finalSpecular += pointSpecular2;\n }\n }\n // Mode 2 : 1st Point, 2nd Directional\n else if (u_mode == 2.0) {\n if (i == 0) {\n finalAmbient += pointAmbient1;\n finalDiffuse += pointDiffuse1;\n finalSpecular += pointSpecular1;\n } else if (i == 1) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n }\n }\n // Mode 3 : 1st Directional, 2nd None\n else if (u_mode == 3.0 && i == 0) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n }\n // Mode 4 : 1st Point, 2nd None\n else if (u_mode == 4.0) {\n finalAmbient += pointAmbient1;\n finalDiffuse += pointAmbient1;\n finalSpecular += pointAmbient1;\n }\n }\n\n // Using texture sampler\n vec3 fixedDiffuse = finalDiffuse;\n if (u_hasDiffuseMap == 1.0) {\n fixedDiffuse = fixedDiffuse * texture2D(u_diffuseMap, diffuseUV).rgb;\n }\n\n vec3 fixedSpecular = finalSpecular;\n\n if (u_hasSpecularMap == 1.0) {\n fixedSpecular = finalSpecular * texture2D(u_specularMap, specularUV).rgb;\n }\n\n vec3 finalColor = finalAmbient + fixedDiffuse + fixedSpecular;\n gl_FragColor = vec4(finalColor, 1.0);\n \n}\n","uniforms":{"ambientColor":[0,0,0,255],"diffuseColor":[0,0,0,255],"specularColor":[255,255,255,255],"shininess":60,"diffuseMaps":[],"normalMaps":[],"displacementMaps":[],"specularMaps":[],"diffuseMap":-1,"normalMap":-1,"displacementMap":-1,"specularMap":-1}},{"type":"Basic Material","name":"eye","vertexShader":"\n#define PI 3.1415926535897932384626433832795\nattribute vec4 a_position;\n\nuniform mat4 u_worldMatrix;\nuniform mat4 u_viewMatrix;\nuniform vec4 u_color;\n\nvarying vec4 v_color;\n\nvoid main() { \n gl_Position = u_viewMatrix * u_worldMatrix * a_position;\n v_color = u_color;\n}\n","fragmentShader":"\nprecision highp float;\nvarying vec4 v_color;\n\nvoid main() {\n gl_FragColor = v_color / 255.0;\n}\n","uniforms":{"color":[0,0,0,255]}},{"type":"Phong Material","name":"eye-phong","vertexShader":"\nprecision mediump float;\n\nattribute vec3 a_position;\nattribute vec3 a_faceNormal;\nattribute vec3 a_vertexNormal;\nattribute vec2 a_displacementUV;\nattribute vec2 a_diffuseUV;\nattribute vec2 a_specularUV;\nattribute vec2 a_normalUV;\nattribute vec3 a_tangent;\nattribute vec3 a_bitangent;\n\nuniform mat4 u_worldMatrix;\nuniform mat4 u_viewMatrix;\nuniform sampler2D u_displacementMap;\nuniform float u_displacementScale;\nuniform float u_displacementBias;\n\nvarying vec3 normalSurface;\nvarying vec3 vertexPosition;\nvarying vec2 diffuseUV;\nvarying vec2 specularUV;\nvarying mat3 v_tbn;\nvarying vec2 v_texcoord;\nvarying vec3 v_pos;\n\nvoid main() {\n vec4 displacement = texture2D(u_displacementMap, a_displacementUV);\n\n vec4 displacementVector = normalize(vec4(a_vertexNormal.xyz, 0.0)) * (displacement.r * u_displacementScale + u_displacementBias);\n\n vec4 vertexPosition4 = u_worldMatrix * (vec4(a_position, 1.0) + displacementVector);\n vertexPosition = vec3(vertexPosition4) / vertexPosition4.w;\n normalSurface = (u_viewMatrix * u_worldMatrix * vec4(a_faceNormal, 1.0)).xyz;\n diffuseUV = a_diffuseUV;\n specularUV = a_specularUV;\n \n vec3 T = normalize(vec3(u_worldMatrix * vec4(a_tangent, 0.0)));\n vec3 B = normalize(vec3(u_worldMatrix * vec4(a_bitangent, 0.0)));\n \n vec3 normalTemp = cross(a_tangent, a_bitangent);\n vec3 N = normalize(vec3(u_worldMatrix * vec4(normalTemp, 0.0)));\n\n v_tbn = mat3(T, B, N);\n v_texcoord = a_normalUV;\n v_pos = a_position;\n \n gl_Position = u_viewMatrix * vertexPosition4;\n}\n","fragmentShader":"\nprecision mediump float;\n\n// Tecture sampler\nuniform sampler2D u_diffuseMap;\nuniform sampler2D u_specularMap;\nuniform sampler2D u_normalMap;\nuniform bool u_hasNormalMap;\nuniform float u_hasDiffuseMap;\nuniform float u_hasSpecularMap;\n\n// Material uniform\nuniform float u_shininess;\nuniform vec4 u_ambientColor;\nuniform vec4 u_diffuseColor;\nuniform vec4 u_specularColor;\n\n// Light uniform\nuniform int u_numLights;\n\n// Light properties\nuniform float u_lightType_0;\nuniform vec3 u_lightPosition_0;\nuniform vec4 u_lightColor_0;\nuniform vec4 u_lightAmbient_0;\nuniform vec4 u_lightDiffuse_0;\nuniform vec4 u_lightSpecular_0;\nuniform vec3 u_lightTarget_0;\nuniform float u_lightConstant_0;\nuniform float u_lightLinear_0;\nuniform float u_lightQuadratic_0;\n\nuniform float u_lightType_1;\nuniform vec3 u_lightPosition_1;\nuniform vec4 u_lightColor_1;\nuniform vec4 u_lightAmbient_1;\nuniform vec4 u_lightDiffuse_1;\nuniform vec4 u_lightSpecular_1;\nuniform vec3 u_lightTarget_1;\nuniform float u_lightConstant_1;\nuniform float u_lightLinear_1;\nuniform float u_lightQuadratic_1;\n\nuniform float u_mode;\n\nvarying vec3 normalSurface;\nvarying vec3 vertexPosition;\nvarying vec2 diffuseUV;\nvarying vec2 specularUV;\n\nvarying mat3 v_tbn;\nvarying vec2 v_texcoord;\n\nvoid main() {\n vec3 N;\n \n if (u_hasNormalMap) {\n N = texture2D(u_normalMap, v_texcoord).rgb;\n N = N * 2.0 - 1.0;\n N = normalize(v_tbn * N);\n } else {\n N = normalize(normalSurface);\n }\n \n vec3 finalAmbient = vec3(0.0);\n vec3 finalDiffuse = vec3(0.0);\n vec3 finalSpecular = vec3(0.0);\n\n // Convert colors from 0-255 to 0-1\n vec3 ambientColor = u_ambientColor.rgb / 255.0;\n vec3 diffuseColor = u_diffuseColor.rgb / 255.0;\n vec3 specularColor = u_specularColor.rgb / 255.0;\n\n for (int i = 0; i < 2; i++) {\n vec3 L;\n if (i == 0 && u_lightType_0 == 0.0) {\n // Directional Light\n L = normalize(u_lightTarget_0 - vertexPosition);\n } else if (i == 1 && u_lightType_1 == 0.0) {\n // Directional Light\n L = normalize(u_lightTarget_1 - vertexPosition);\n } else if (i == 0 && u_lightType_0 == 1.0) {\n // Point Light\n L = normalize(u_lightPosition_0 - vertexPosition);\n } else {\n // Point Light\n L = normalize(u_lightPosition_1 - vertexPosition);\n }\n\n vec3 lightAmbient = (i == 0) ? (u_lightAmbient_0.rgb / 255.0) : (u_lightAmbient_1.rgb / 255.0);\n vec3 lightDiffuse = (i == 0) ? (u_lightDiffuse_0.rgb / 255.0) : (u_lightDiffuse_1.rgb / 255.0);\n vec3 lightSpecular = (i == 0) ? (u_lightSpecular_0.rgb / 255.0) : (u_lightSpecular_1.rgb / 255.0);\n\n // Lambert's cosine law\n float lambertian = max(dot(N, L), 0.0);\n float specular = 0.0;\n if (lambertian > 0.0) {\n vec3 R = reflect(-L, N); // Reflected light vector\n vec3 V = normalize(-vertexPosition); // Vector to viewer\n \n // Compute the specular term\n float specAngle = max(dot(R, V), 0.0);\n specular = pow(specAngle, u_shininess);\n }\n\n // Directional light calculation\n vec3 directionalAmbient = lightAmbient * ambientColor;\n vec3 directionalDiffuse = lightDiffuse * lambertian * diffuseColor;\n vec3 directionalSpecular = lightSpecular * specular * specularColor;\n\n // Point light calculation 1\n float distance1 = length(u_lightPosition_0 - vertexPosition);\n float attenuation1 = 1.0 / (u_lightConstant_0 + u_lightLinear_0 * distance1 + u_lightQuadratic_0 * distance1 * distance1);\n\n vec3 pointAmbient1 = attenuation1 * lightAmbient * ambientColor;\n vec3 pointDiffuse1 = attenuation1 * lightDiffuse * lambertian * diffuseColor;\n vec3 pointSpecular1 = attenuation1 * lightSpecular * specular * specularColor;\n\n // Point light calculation 2\n float distance2 = length(u_lightPosition_1 - vertexPosition);\n float attenuation2 = 1.0 / (u_lightConstant_1 + u_lightLinear_1 * distance2 + u_lightQuadratic_1 * distance2 * distance2);\n\n vec3 pointAmbient2 = attenuation2 * lightAmbient * ambientColor;\n vec3 pointDiffuse2 = attenuation2 * lightDiffuse * lambertian * diffuseColor;\n vec3 pointSpecular2 = attenuation2 * lightSpecular * specular * specularColor;\n\n // Processing by u_mode\n // Mode 1 : 1st Directional, 2nd Point\n if (u_mode == 1.0) {\n if (i == 0) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n } else if (i == 1) {\n finalAmbient += pointAmbient2;\n finalDiffuse += pointDiffuse2;\n finalSpecular += pointSpecular2;\n }\n }\n // Mode 2 : 1st Point, 2nd Directional\n else if (u_mode == 2.0) {\n if (i == 0) {\n finalAmbient += pointAmbient1;\n finalDiffuse += pointDiffuse1;\n finalSpecular += pointSpecular1;\n } else if (i == 1) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n }\n }\n // Mode 3 : 1st Directional, 2nd None\n else if (u_mode == 3.0 && i == 0) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n }\n // Mode 4 : 1st Point, 2nd None\n else if (u_mode == 4.0) {\n finalAmbient += pointAmbient1;\n finalDiffuse += pointAmbient1;\n finalSpecular += pointAmbient1;\n }\n }\n\n // Using texture sampler\n vec3 fixedDiffuse = finalDiffuse;\n if (u_hasDiffuseMap == 1.0) {\n fixedDiffuse = fixedDiffuse * texture2D(u_diffuseMap, diffuseUV).rgb;\n }\n\n vec3 fixedSpecular = finalSpecular;\n\n if (u_hasSpecularMap == 1.0) {\n fixedSpecular = finalSpecular * texture2D(u_specularMap, specularUV).rgb;\n }\n\n vec3 finalColor = finalAmbient + fixedDiffuse + fixedSpecular;\n gl_FragColor = vec4(finalColor, 1.0);\n \n}\n","uniforms":{"ambientColor":[0,0,0,255],"diffuseColor":[0,0,0,255],"specularColor":[255,255,255,255],"shininess":60,"diffuseMaps":[],"normalMaps":[],"displacementMaps":[],"specularMaps":[],"diffuseMap":-1,"normalMap":-1,"displacementMap":-1,"specularMap":-1}},{"type":"Basic Material","name":"mouth","vertexShader":"\n#define PI 3.1415926535897932384626433832795\nattribute vec4 a_position;\n\nuniform mat4 u_worldMatrix;\nuniform mat4 u_viewMatrix;\nuniform vec4 u_color;\n\nvarying vec4 v_color;\n\nvoid main() { \n gl_Position = u_viewMatrix * u_worldMatrix * a_position;\n v_color = u_color;\n}\n","fragmentShader":"\nprecision highp float;\nvarying vec4 v_color;\n\nvoid main() {\n gl_FragColor = v_color / 255.0;\n}\n","uniforms":{"color":[0,0,0,255]}},{"type":"Phong Material","name":"mouth-phong","vertexShader":"\nprecision mediump float;\n\nattribute vec3 a_position;\nattribute vec3 a_faceNormal;\nattribute vec3 a_vertexNormal;\nattribute vec2 a_displacementUV;\nattribute vec2 a_diffuseUV;\nattribute vec2 a_specularUV;\nattribute vec2 a_normalUV;\nattribute vec3 a_tangent;\nattribute vec3 a_bitangent;\n\nuniform mat4 u_worldMatrix;\nuniform mat4 u_viewMatrix;\nuniform sampler2D u_displacementMap;\nuniform float u_displacementScale;\nuniform float u_displacementBias;\n\nvarying vec3 normalSurface;\nvarying vec3 vertexPosition;\nvarying vec2 diffuseUV;\nvarying vec2 specularUV;\nvarying mat3 v_tbn;\nvarying vec2 v_texcoord;\nvarying vec3 v_pos;\n\nvoid main() {\n vec4 displacement = texture2D(u_displacementMap, a_displacementUV);\n\n vec4 displacementVector = normalize(vec4(a_vertexNormal.xyz, 0.0)) * (displacement.r * u_displacementScale + u_displacementBias);\n\n vec4 vertexPosition4 = u_worldMatrix * (vec4(a_position, 1.0) + displacementVector);\n vertexPosition = vec3(vertexPosition4) / vertexPosition4.w;\n normalSurface = (u_viewMatrix * u_worldMatrix * vec4(a_faceNormal, 1.0)).xyz;\n diffuseUV = a_diffuseUV;\n specularUV = a_specularUV;\n \n vec3 T = normalize(vec3(u_worldMatrix * vec4(a_tangent, 0.0)));\n vec3 B = normalize(vec3(u_worldMatrix * vec4(a_bitangent, 0.0)));\n \n vec3 normalTemp = cross(a_tangent, a_bitangent);\n vec3 N = normalize(vec3(u_worldMatrix * vec4(normalTemp, 0.0)));\n\n v_tbn = mat3(T, B, N);\n v_texcoord = a_normalUV;\n v_pos = a_position;\n \n gl_Position = u_viewMatrix * vertexPosition4;\n}\n","fragmentShader":"\nprecision mediump float;\n\n// Tecture sampler\nuniform sampler2D u_diffuseMap;\nuniform sampler2D u_specularMap;\nuniform sampler2D u_normalMap;\nuniform bool u_hasNormalMap;\nuniform float u_hasDiffuseMap;\nuniform float u_hasSpecularMap;\n\n// Material uniform\nuniform float u_shininess;\nuniform vec4 u_ambientColor;\nuniform vec4 u_diffuseColor;\nuniform vec4 u_specularColor;\n\n// Light uniform\nuniform int u_numLights;\n\n// Light properties\nuniform float u_lightType_0;\nuniform vec3 u_lightPosition_0;\nuniform vec4 u_lightColor_0;\nuniform vec4 u_lightAmbient_0;\nuniform vec4 u_lightDiffuse_0;\nuniform vec4 u_lightSpecular_0;\nuniform vec3 u_lightTarget_0;\nuniform float u_lightConstant_0;\nuniform float u_lightLinear_0;\nuniform float u_lightQuadratic_0;\n\nuniform float u_lightType_1;\nuniform vec3 u_lightPosition_1;\nuniform vec4 u_lightColor_1;\nuniform vec4 u_lightAmbient_1;\nuniform vec4 u_lightDiffuse_1;\nuniform vec4 u_lightSpecular_1;\nuniform vec3 u_lightTarget_1;\nuniform float u_lightConstant_1;\nuniform float u_lightLinear_1;\nuniform float u_lightQuadratic_1;\n\nuniform float u_mode;\n\nvarying vec3 normalSurface;\nvarying vec3 vertexPosition;\nvarying vec2 diffuseUV;\nvarying vec2 specularUV;\n\nvarying mat3 v_tbn;\nvarying vec2 v_texcoord;\n\nvoid main() {\n vec3 N;\n \n if (u_hasNormalMap) {\n N = texture2D(u_normalMap, v_texcoord).rgb;\n N = N * 2.0 - 1.0;\n N = normalize(v_tbn * N);\n } else {\n N = normalize(normalSurface);\n }\n \n vec3 finalAmbient = vec3(0.0);\n vec3 finalDiffuse = vec3(0.0);\n vec3 finalSpecular = vec3(0.0);\n\n // Convert colors from 0-255 to 0-1\n vec3 ambientColor = u_ambientColor.rgb / 255.0;\n vec3 diffuseColor = u_diffuseColor.rgb / 255.0;\n vec3 specularColor = u_specularColor.rgb / 255.0;\n\n for (int i = 0; i < 2; i++) {\n vec3 L;\n if (i == 0 && u_lightType_0 == 0.0) {\n // Directional Light\n L = normalize(u_lightTarget_0 - vertexPosition);\n } else if (i == 1 && u_lightType_1 == 0.0) {\n // Directional Light\n L = normalize(u_lightTarget_1 - vertexPosition);\n } else if (i == 0 && u_lightType_0 == 1.0) {\n // Point Light\n L = normalize(u_lightPosition_0 - vertexPosition);\n } else {\n // Point Light\n L = normalize(u_lightPosition_1 - vertexPosition);\n }\n\n vec3 lightAmbient = (i == 0) ? (u_lightAmbient_0.rgb / 255.0) : (u_lightAmbient_1.rgb / 255.0);\n vec3 lightDiffuse = (i == 0) ? (u_lightDiffuse_0.rgb / 255.0) : (u_lightDiffuse_1.rgb / 255.0);\n vec3 lightSpecular = (i == 0) ? (u_lightSpecular_0.rgb / 255.0) : (u_lightSpecular_1.rgb / 255.0);\n\n // Lambert's cosine law\n float lambertian = max(dot(N, L), 0.0);\n float specular = 0.0;\n if (lambertian > 0.0) {\n vec3 R = reflect(-L, N); // Reflected light vector\n vec3 V = normalize(-vertexPosition); // Vector to viewer\n \n // Compute the specular term\n float specAngle = max(dot(R, V), 0.0);\n specular = pow(specAngle, u_shininess);\n }\n\n // Directional light calculation\n vec3 directionalAmbient = lightAmbient * ambientColor;\n vec3 directionalDiffuse = lightDiffuse * lambertian * diffuseColor;\n vec3 directionalSpecular = lightSpecular * specular * specularColor;\n\n // Point light calculation 1\n float distance1 = length(u_lightPosition_0 - vertexPosition);\n float attenuation1 = 1.0 / (u_lightConstant_0 + u_lightLinear_0 * distance1 + u_lightQuadratic_0 * distance1 * distance1);\n\n vec3 pointAmbient1 = attenuation1 * lightAmbient * ambientColor;\n vec3 pointDiffuse1 = attenuation1 * lightDiffuse * lambertian * diffuseColor;\n vec3 pointSpecular1 = attenuation1 * lightSpecular * specular * specularColor;\n\n // Point light calculation 2\n float distance2 = length(u_lightPosition_1 - vertexPosition);\n float attenuation2 = 1.0 / (u_lightConstant_1 + u_lightLinear_1 * distance2 + u_lightQuadratic_1 * distance2 * distance2);\n\n vec3 pointAmbient2 = attenuation2 * lightAmbient * ambientColor;\n vec3 pointDiffuse2 = attenuation2 * lightDiffuse * lambertian * diffuseColor;\n vec3 pointSpecular2 = attenuation2 * lightSpecular * specular * specularColor;\n\n // Processing by u_mode\n // Mode 1 : 1st Directional, 2nd Point\n if (u_mode == 1.0) {\n if (i == 0) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n } else if (i == 1) {\n finalAmbient += pointAmbient2;\n finalDiffuse += pointDiffuse2;\n finalSpecular += pointSpecular2;\n }\n }\n // Mode 2 : 1st Point, 2nd Directional\n else if (u_mode == 2.0) {\n if (i == 0) {\n finalAmbient += pointAmbient1;\n finalDiffuse += pointDiffuse1;\n finalSpecular += pointSpecular1;\n } else if (i == 1) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n }\n }\n // Mode 3 : 1st Directional, 2nd None\n else if (u_mode == 3.0 && i == 0) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n }\n // Mode 4 : 1st Point, 2nd None\n else if (u_mode == 4.0) {\n finalAmbient += pointAmbient1;\n finalDiffuse += pointAmbient1;\n finalSpecular += pointAmbient1;\n }\n }\n\n // Using texture sampler\n vec3 fixedDiffuse = finalDiffuse;\n if (u_hasDiffuseMap == 1.0) {\n fixedDiffuse = fixedDiffuse * texture2D(u_diffuseMap, diffuseUV).rgb;\n }\n\n vec3 fixedSpecular = finalSpecular;\n\n if (u_hasSpecularMap == 1.0) {\n fixedSpecular = finalSpecular * texture2D(u_specularMap, specularUV).rgb;\n }\n\n vec3 finalColor = finalAmbient + fixedDiffuse + fixedSpecular;\n gl_FragColor = vec4(finalColor, 1.0);\n \n}\n","uniforms":{"ambientColor":[0,0,0,255],"diffuseColor":[0,0,0,255],"specularColor":[255,255,255,255],"shininess":60,"diffuseMaps":[],"normalMaps":[],"displacementMaps":[],"specularMaps":[],"diffuseMap":-1,"normalMap":-1,"displacementMap":-1,"specularMap":-1}},{"type":"Basic Material","name":"ear","vertexShader":"\n#define PI 3.1415926535897932384626433832795\nattribute vec4 a_position;\n\nuniform mat4 u_worldMatrix;\nuniform mat4 u_viewMatrix;\nuniform vec4 u_color;\n\nvarying vec4 v_color;\n\nvoid main() { \n gl_Position = u_viewMatrix * u_worldMatrix * a_position;\n v_color = u_color;\n}\n","fragmentShader":"\nprecision highp float;\nvarying vec4 v_color;\n\nvoid main() {\n gl_FragColor = v_color / 255.0;\n}\n","uniforms":{"color":[72,60,50,255]}},{"type":"Phong Material","name":"ear-phong","vertexShader":"\nprecision mediump float;\n\nattribute vec3 a_position;\nattribute vec3 a_faceNormal;\nattribute vec3 a_vertexNormal;\nattribute vec2 a_displacementUV;\nattribute vec2 a_diffuseUV;\nattribute vec2 a_specularUV;\nattribute vec2 a_normalUV;\nattribute vec3 a_tangent;\nattribute vec3 a_bitangent;\n\nuniform mat4 u_worldMatrix;\nuniform mat4 u_viewMatrix;\nuniform sampler2D u_displacementMap;\nuniform float u_displacementScale;\nuniform float u_displacementBias;\n\nvarying vec3 normalSurface;\nvarying vec3 vertexPosition;\nvarying vec2 diffuseUV;\nvarying vec2 specularUV;\nvarying mat3 v_tbn;\nvarying vec2 v_texcoord;\nvarying vec3 v_pos;\n\nvoid main() {\n vec4 displacement = texture2D(u_displacementMap, a_displacementUV);\n\n vec4 displacementVector = normalize(vec4(a_vertexNormal.xyz, 0.0)) * (displacement.r * u_displacementScale + u_displacementBias);\n\n vec4 vertexPosition4 = u_worldMatrix * (vec4(a_position, 1.0) + displacementVector);\n vertexPosition = vec3(vertexPosition4) / vertexPosition4.w;\n normalSurface = (u_viewMatrix * u_worldMatrix * vec4(a_faceNormal, 1.0)).xyz;\n diffuseUV = a_diffuseUV;\n specularUV = a_specularUV;\n \n vec3 T = normalize(vec3(u_worldMatrix * vec4(a_tangent, 0.0)));\n vec3 B = normalize(vec3(u_worldMatrix * vec4(a_bitangent, 0.0)));\n \n vec3 normalTemp = cross(a_tangent, a_bitangent);\n vec3 N = normalize(vec3(u_worldMatrix * vec4(normalTemp, 0.0)));\n\n v_tbn = mat3(T, B, N);\n v_texcoord = a_normalUV;\n v_pos = a_position;\n \n gl_Position = u_viewMatrix * vertexPosition4;\n}\n","fragmentShader":"\nprecision mediump float;\n\n// Tecture sampler\nuniform sampler2D u_diffuseMap;\nuniform sampler2D u_specularMap;\nuniform sampler2D u_normalMap;\nuniform bool u_hasNormalMap;\nuniform float u_hasDiffuseMap;\nuniform float u_hasSpecularMap;\n\n// Material uniform\nuniform float u_shininess;\nuniform vec4 u_ambientColor;\nuniform vec4 u_diffuseColor;\nuniform vec4 u_specularColor;\n\n// Light uniform\nuniform int u_numLights;\n\n// Light properties\nuniform float u_lightType_0;\nuniform vec3 u_lightPosition_0;\nuniform vec4 u_lightColor_0;\nuniform vec4 u_lightAmbient_0;\nuniform vec4 u_lightDiffuse_0;\nuniform vec4 u_lightSpecular_0;\nuniform vec3 u_lightTarget_0;\nuniform float u_lightConstant_0;\nuniform float u_lightLinear_0;\nuniform float u_lightQuadratic_0;\n\nuniform float u_lightType_1;\nuniform vec3 u_lightPosition_1;\nuniform vec4 u_lightColor_1;\nuniform vec4 u_lightAmbient_1;\nuniform vec4 u_lightDiffuse_1;\nuniform vec4 u_lightSpecular_1;\nuniform vec3 u_lightTarget_1;\nuniform float u_lightConstant_1;\nuniform float u_lightLinear_1;\nuniform float u_lightQuadratic_1;\n\nuniform float u_mode;\n\nvarying vec3 normalSurface;\nvarying vec3 vertexPosition;\nvarying vec2 diffuseUV;\nvarying vec2 specularUV;\n\nvarying mat3 v_tbn;\nvarying vec2 v_texcoord;\n\nvoid main() {\n vec3 N;\n \n if (u_hasNormalMap) {\n N = texture2D(u_normalMap, v_texcoord).rgb;\n N = N * 2.0 - 1.0;\n N = normalize(v_tbn * N);\n } else {\n N = normalize(normalSurface);\n }\n \n vec3 finalAmbient = vec3(0.0);\n vec3 finalDiffuse = vec3(0.0);\n vec3 finalSpecular = vec3(0.0);\n\n // Convert colors from 0-255 to 0-1\n vec3 ambientColor = u_ambientColor.rgb / 255.0;\n vec3 diffuseColor = u_diffuseColor.rgb / 255.0;\n vec3 specularColor = u_specularColor.rgb / 255.0;\n\n for (int i = 0; i < 2; i++) {\n vec3 L;\n if (i == 0 && u_lightType_0 == 0.0) {\n // Directional Light\n L = normalize(u_lightTarget_0 - vertexPosition);\n } else if (i == 1 && u_lightType_1 == 0.0) {\n // Directional Light\n L = normalize(u_lightTarget_1 - vertexPosition);\n } else if (i == 0 && u_lightType_0 == 1.0) {\n // Point Light\n L = normalize(u_lightPosition_0 - vertexPosition);\n } else {\n // Point Light\n L = normalize(u_lightPosition_1 - vertexPosition);\n }\n\n vec3 lightAmbient = (i == 0) ? (u_lightAmbient_0.rgb / 255.0) : (u_lightAmbient_1.rgb / 255.0);\n vec3 lightDiffuse = (i == 0) ? (u_lightDiffuse_0.rgb / 255.0) : (u_lightDiffuse_1.rgb / 255.0);\n vec3 lightSpecular = (i == 0) ? (u_lightSpecular_0.rgb / 255.0) : (u_lightSpecular_1.rgb / 255.0);\n\n // Lambert's cosine law\n float lambertian = max(dot(N, L), 0.0);\n float specular = 0.0;\n if (lambertian > 0.0) {\n vec3 R = reflect(-L, N); // Reflected light vector\n vec3 V = normalize(-vertexPosition); // Vector to viewer\n \n // Compute the specular term\n float specAngle = max(dot(R, V), 0.0);\n specular = pow(specAngle, u_shininess);\n }\n\n // Directional light calculation\n vec3 directionalAmbient = lightAmbient * ambientColor;\n vec3 directionalDiffuse = lightDiffuse * lambertian * diffuseColor;\n vec3 directionalSpecular = lightSpecular * specular * specularColor;\n\n // Point light calculation 1\n float distance1 = length(u_lightPosition_0 - vertexPosition);\n float attenuation1 = 1.0 / (u_lightConstant_0 + u_lightLinear_0 * distance1 + u_lightQuadratic_0 * distance1 * distance1);\n\n vec3 pointAmbient1 = attenuation1 * lightAmbient * ambientColor;\n vec3 pointDiffuse1 = attenuation1 * lightDiffuse * lambertian * diffuseColor;\n vec3 pointSpecular1 = attenuation1 * lightSpecular * specular * specularColor;\n\n // Point light calculation 2\n float distance2 = length(u_lightPosition_1 - vertexPosition);\n float attenuation2 = 1.0 / (u_lightConstant_1 + u_lightLinear_1 * distance2 + u_lightQuadratic_1 * distance2 * distance2);\n\n vec3 pointAmbient2 = attenuation2 * lightAmbient * ambientColor;\n vec3 pointDiffuse2 = attenuation2 * lightDiffuse * lambertian * diffuseColor;\n vec3 pointSpecular2 = attenuation2 * lightSpecular * specular * specularColor;\n\n // Processing by u_mode\n // Mode 1 : 1st Directional, 2nd Point\n if (u_mode == 1.0) {\n if (i == 0) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n } else if (i == 1) {\n finalAmbient += pointAmbient2;\n finalDiffuse += pointDiffuse2;\n finalSpecular += pointSpecular2;\n }\n }\n // Mode 2 : 1st Point, 2nd Directional\n else if (u_mode == 2.0) {\n if (i == 0) {\n finalAmbient += pointAmbient1;\n finalDiffuse += pointDiffuse1;\n finalSpecular += pointSpecular1;\n } else if (i == 1) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n }\n }\n // Mode 3 : 1st Directional, 2nd None\n else if (u_mode == 3.0 && i == 0) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n }\n // Mode 4 : 1st Point, 2nd None\n else if (u_mode == 4.0) {\n finalAmbient += pointAmbient1;\n finalDiffuse += pointAmbient1;\n finalSpecular += pointAmbient1;\n }\n }\n\n // Using texture sampler\n vec3 fixedDiffuse = finalDiffuse;\n if (u_hasDiffuseMap == 1.0) {\n fixedDiffuse = fixedDiffuse * texture2D(u_diffuseMap, diffuseUV).rgb;\n }\n\n vec3 fixedSpecular = finalSpecular;\n\n if (u_hasSpecularMap == 1.0) {\n fixedSpecular = finalSpecular * texture2D(u_specularMap, specularUV).rgb;\n }\n\n vec3 finalColor = finalAmbient + fixedDiffuse + fixedSpecular;\n gl_FragColor = vec4(finalColor, 1.0);\n \n}\n","uniforms":{"ambientColor":[72,60,50,255],"diffuseColor":[72,60,50,255],"specularColor":[255,255,255,255],"shininess":60,"diffuseMaps":[],"normalMaps":[],"displacementMaps":[],"specularMaps":[],"diffuseMap":-1,"normalMap":-1,"displacementMap":-1,"specularMap":-1}},{"type":"Basic Material","name":"ear","vertexShader":"\n#define PI 3.1415926535897932384626433832795\nattribute vec4 a_position;\n\nuniform mat4 u_worldMatrix;\nuniform mat4 u_viewMatrix;\nuniform vec4 u_color;\n\nvarying vec4 v_color;\n\nvoid main() { \n gl_Position = u_viewMatrix * u_worldMatrix * a_position;\n v_color = u_color;\n}\n","fragmentShader":"\nprecision highp float;\nvarying vec4 v_color;\n\nvoid main() {\n gl_FragColor = v_color / 255.0;\n}\n","uniforms":{"color":[72,60,50,255]}},{"type":"Phong Material","name":"ear-phong","vertexShader":"\nprecision mediump float;\n\nattribute vec3 a_position;\nattribute vec3 a_faceNormal;\nattribute vec3 a_vertexNormal;\nattribute vec2 a_displacementUV;\nattribute vec2 a_diffuseUV;\nattribute vec2 a_specularUV;\nattribute vec2 a_normalUV;\nattribute vec3 a_tangent;\nattribute vec3 a_bitangent;\n\nuniform mat4 u_worldMatrix;\nuniform mat4 u_viewMatrix;\nuniform sampler2D u_displacementMap;\nuniform float u_displacementScale;\nuniform float u_displacementBias;\n\nvarying vec3 normalSurface;\nvarying vec3 vertexPosition;\nvarying vec2 diffuseUV;\nvarying vec2 specularUV;\nvarying mat3 v_tbn;\nvarying vec2 v_texcoord;\nvarying vec3 v_pos;\n\nvoid main() {\n vec4 displacement = texture2D(u_displacementMap, a_displacementUV);\n\n vec4 displacementVector = normalize(vec4(a_vertexNormal.xyz, 0.0)) * (displacement.r * u_displacementScale + u_displacementBias);\n\n vec4 vertexPosition4 = u_worldMatrix * (vec4(a_position, 1.0) + displacementVector);\n vertexPosition = vec3(vertexPosition4) / vertexPosition4.w;\n normalSurface = (u_viewMatrix * u_worldMatrix * vec4(a_faceNormal, 1.0)).xyz;\n diffuseUV = a_diffuseUV;\n specularUV = a_specularUV;\n \n vec3 T = normalize(vec3(u_worldMatrix * vec4(a_tangent, 0.0)));\n vec3 B = normalize(vec3(u_worldMatrix * vec4(a_bitangent, 0.0)));\n \n vec3 normalTemp = cross(a_tangent, a_bitangent);\n vec3 N = normalize(vec3(u_worldMatrix * vec4(normalTemp, 0.0)));\n\n v_tbn = mat3(T, B, N);\n v_texcoord = a_normalUV;\n v_pos = a_position;\n \n gl_Position = u_viewMatrix * vertexPosition4;\n}\n","fragmentShader":"\nprecision mediump float;\n\n// Tecture sampler\nuniform sampler2D u_diffuseMap;\nuniform sampler2D u_specularMap;\nuniform sampler2D u_normalMap;\nuniform bool u_hasNormalMap;\nuniform float u_hasDiffuseMap;\nuniform float u_hasSpecularMap;\n\n// Material uniform\nuniform float u_shininess;\nuniform vec4 u_ambientColor;\nuniform vec4 u_diffuseColor;\nuniform vec4 u_specularColor;\n\n// Light uniform\nuniform int u_numLights;\n\n// Light properties\nuniform float u_lightType_0;\nuniform vec3 u_lightPosition_0;\nuniform vec4 u_lightColor_0;\nuniform vec4 u_lightAmbient_0;\nuniform vec4 u_lightDiffuse_0;\nuniform vec4 u_lightSpecular_0;\nuniform vec3 u_lightTarget_0;\nuniform float u_lightConstant_0;\nuniform float u_lightLinear_0;\nuniform float u_lightQuadratic_0;\n\nuniform float u_lightType_1;\nuniform vec3 u_lightPosition_1;\nuniform vec4 u_lightColor_1;\nuniform vec4 u_lightAmbient_1;\nuniform vec4 u_lightDiffuse_1;\nuniform vec4 u_lightSpecular_1;\nuniform vec3 u_lightTarget_1;\nuniform float u_lightConstant_1;\nuniform float u_lightLinear_1;\nuniform float u_lightQuadratic_1;\n\nuniform float u_mode;\n\nvarying vec3 normalSurface;\nvarying vec3 vertexPosition;\nvarying vec2 diffuseUV;\nvarying vec2 specularUV;\n\nvarying mat3 v_tbn;\nvarying vec2 v_texcoord;\n\nvoid main() {\n vec3 N;\n \n if (u_hasNormalMap) {\n N = texture2D(u_normalMap, v_texcoord).rgb;\n N = N * 2.0 - 1.0;\n N = normalize(v_tbn * N);\n } else {\n N = normalize(normalSurface);\n }\n \n vec3 finalAmbient = vec3(0.0);\n vec3 finalDiffuse = vec3(0.0);\n vec3 finalSpecular = vec3(0.0);\n\n // Convert colors from 0-255 to 0-1\n vec3 ambientColor = u_ambientColor.rgb / 255.0;\n vec3 diffuseColor = u_diffuseColor.rgb / 255.0;\n vec3 specularColor = u_specularColor.rgb / 255.0;\n\n for (int i = 0; i < 2; i++) {\n vec3 L;\n if (i == 0 && u_lightType_0 == 0.0) {\n // Directional Light\n L = normalize(u_lightTarget_0 - vertexPosition);\n } else if (i == 1 && u_lightType_1 == 0.0) {\n // Directional Light\n L = normalize(u_lightTarget_1 - vertexPosition);\n } else if (i == 0 && u_lightType_0 == 1.0) {\n // Point Light\n L = normalize(u_lightPosition_0 - vertexPosition);\n } else {\n // Point Light\n L = normalize(u_lightPosition_1 - vertexPosition);\n }\n\n vec3 lightAmbient = (i == 0) ? (u_lightAmbient_0.rgb / 255.0) : (u_lightAmbient_1.rgb / 255.0);\n vec3 lightDiffuse = (i == 0) ? (u_lightDiffuse_0.rgb / 255.0) : (u_lightDiffuse_1.rgb / 255.0);\n vec3 lightSpecular = (i == 0) ? (u_lightSpecular_0.rgb / 255.0) : (u_lightSpecular_1.rgb / 255.0);\n\n // Lambert's cosine law\n float lambertian = max(dot(N, L), 0.0);\n float specular = 0.0;\n if (lambertian > 0.0) {\n vec3 R = reflect(-L, N); // Reflected light vector\n vec3 V = normalize(-vertexPosition); // Vector to viewer\n \n // Compute the specular term\n float specAngle = max(dot(R, V), 0.0);\n specular = pow(specAngle, u_shininess);\n }\n\n // Directional light calculation\n vec3 directionalAmbient = lightAmbient * ambientColor;\n vec3 directionalDiffuse = lightDiffuse * lambertian * diffuseColor;\n vec3 directionalSpecular = lightSpecular * specular * specularColor;\n\n // Point light calculation 1\n float distance1 = length(u_lightPosition_0 - vertexPosition);\n float attenuation1 = 1.0 / (u_lightConstant_0 + u_lightLinear_0 * distance1 + u_lightQuadratic_0 * distance1 * distance1);\n\n vec3 pointAmbient1 = attenuation1 * lightAmbient * ambientColor;\n vec3 pointDiffuse1 = attenuation1 * lightDiffuse * lambertian * diffuseColor;\n vec3 pointSpecular1 = attenuation1 * lightSpecular * specular * specularColor;\n\n // Point light calculation 2\n float distance2 = length(u_lightPosition_1 - vertexPosition);\n float attenuation2 = 1.0 / (u_lightConstant_1 + u_lightLinear_1 * distance2 + u_lightQuadratic_1 * distance2 * distance2);\n\n vec3 pointAmbient2 = attenuation2 * lightAmbient * ambientColor;\n vec3 pointDiffuse2 = attenuation2 * lightDiffuse * lambertian * diffuseColor;\n vec3 pointSpecular2 = attenuation2 * lightSpecular * specular * specularColor;\n\n // Processing by u_mode\n // Mode 1 : 1st Directional, 2nd Point\n if (u_mode == 1.0) {\n if (i == 0) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n } else if (i == 1) {\n finalAmbient += pointAmbient2;\n finalDiffuse += pointDiffuse2;\n finalSpecular += pointSpecular2;\n }\n }\n // Mode 2 : 1st Point, 2nd Directional\n else if (u_mode == 2.0) {\n if (i == 0) {\n finalAmbient += pointAmbient1;\n finalDiffuse += pointDiffuse1;\n finalSpecular += pointSpecular1;\n } else if (i == 1) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n }\n }\n // Mode 3 : 1st Directional, 2nd None\n else if (u_mode == 3.0 && i == 0) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n }\n // Mode 4 : 1st Point, 2nd None\n else if (u_mode == 4.0) {\n finalAmbient += pointAmbient1;\n finalDiffuse += pointAmbient1;\n finalSpecular += pointAmbient1;\n }\n }\n\n // Using texture sampler\n vec3 fixedDiffuse = finalDiffuse;\n if (u_hasDiffuseMap == 1.0) {\n fixedDiffuse = fixedDiffuse * texture2D(u_diffuseMap, diffuseUV).rgb;\n }\n\n vec3 fixedSpecular = finalSpecular;\n\n if (u_hasSpecularMap == 1.0) {\n fixedSpecular = finalSpecular * texture2D(u_specularMap, specularUV).rgb;\n }\n\n vec3 finalColor = finalAmbient + fixedDiffuse + fixedSpecular;\n gl_FragColor = vec4(finalColor, 1.0);\n \n}\n","uniforms":{"ambientColor":[72,60,50,255],"diffuseColor":[72,60,50,255],"specularColor":[255,255,255,255],"shininess":60,"diffuseMaps":[],"normalMaps":[],"displacementMaps":[],"specularMaps":[],"diffuseMap":-1,"normalMap":-1,"displacementMap":-1,"specularMap":-1}},{"type":"Basic Material","name":"body","vertexShader":"\n#define PI 3.1415926535897932384626433832795\nattribute vec4 a_position;\n\nuniform mat4 u_worldMatrix;\nuniform mat4 u_viewMatrix;\nuniform vec4 u_color;\n\nvarying vec4 v_color;\n\nvoid main() { \n gl_Position = u_viewMatrix * u_worldMatrix * a_position;\n v_color = u_color;\n}\n","fragmentShader":"\nprecision highp float;\nvarying vec4 v_color;\n\nvoid main() {\n gl_FragColor = v_color / 255.0;\n}\n","uniforms":{"color":[102,61,20,255]}},{"type":"Phong Material","name":"body-phong","vertexShader":"\nprecision mediump float;\n\nattribute vec3 a_position;\nattribute vec3 a_faceNormal;\nattribute vec3 a_vertexNormal;\nattribute vec2 a_displacementUV;\nattribute vec2 a_diffuseUV;\nattribute vec2 a_specularUV;\nattribute vec2 a_normalUV;\nattribute vec3 a_tangent;\nattribute vec3 a_bitangent;\n\nuniform mat4 u_worldMatrix;\nuniform mat4 u_viewMatrix;\nuniform sampler2D u_displacementMap;\nuniform float u_displacementScale;\nuniform float u_displacementBias;\n\nvarying vec3 normalSurface;\nvarying vec3 vertexPosition;\nvarying vec2 diffuseUV;\nvarying vec2 specularUV;\nvarying mat3 v_tbn;\nvarying vec2 v_texcoord;\nvarying vec3 v_pos;\n\nvoid main() {\n vec4 displacement = texture2D(u_displacementMap, a_displacementUV);\n\n vec4 displacementVector = normalize(vec4(a_vertexNormal.xyz, 0.0)) * (displacement.r * u_displacementScale + u_displacementBias);\n\n vec4 vertexPosition4 = u_worldMatrix * (vec4(a_position, 1.0) + displacementVector);\n vertexPosition = vec3(vertexPosition4) / vertexPosition4.w;\n normalSurface = (u_viewMatrix * u_worldMatrix * vec4(a_faceNormal, 1.0)).xyz;\n diffuseUV = a_diffuseUV;\n specularUV = a_specularUV;\n \n vec3 T = normalize(vec3(u_worldMatrix * vec4(a_tangent, 0.0)));\n vec3 B = normalize(vec3(u_worldMatrix * vec4(a_bitangent, 0.0)));\n \n vec3 normalTemp = cross(a_tangent, a_bitangent);\n vec3 N = normalize(vec3(u_worldMatrix * vec4(normalTemp, 0.0)));\n\n v_tbn = mat3(T, B, N);\n v_texcoord = a_normalUV;\n v_pos = a_position;\n \n gl_Position = u_viewMatrix * vertexPosition4;\n}\n","fragmentShader":"\nprecision mediump float;\n\n// Tecture sampler\nuniform sampler2D u_diffuseMap;\nuniform sampler2D u_specularMap;\nuniform sampler2D u_normalMap;\nuniform bool u_hasNormalMap;\nuniform float u_hasDiffuseMap;\nuniform float u_hasSpecularMap;\n\n// Material uniform\nuniform float u_shininess;\nuniform vec4 u_ambientColor;\nuniform vec4 u_diffuseColor;\nuniform vec4 u_specularColor;\n\n// Light uniform\nuniform int u_numLights;\n\n// Light properties\nuniform float u_lightType_0;\nuniform vec3 u_lightPosition_0;\nuniform vec4 u_lightColor_0;\nuniform vec4 u_lightAmbient_0;\nuniform vec4 u_lightDiffuse_0;\nuniform vec4 u_lightSpecular_0;\nuniform vec3 u_lightTarget_0;\nuniform float u_lightConstant_0;\nuniform float u_lightLinear_0;\nuniform float u_lightQuadratic_0;\n\nuniform float u_lightType_1;\nuniform vec3 u_lightPosition_1;\nuniform vec4 u_lightColor_1;\nuniform vec4 u_lightAmbient_1;\nuniform vec4 u_lightDiffuse_1;\nuniform vec4 u_lightSpecular_1;\nuniform vec3 u_lightTarget_1;\nuniform float u_lightConstant_1;\nuniform float u_lightLinear_1;\nuniform float u_lightQuadratic_1;\n\nuniform float u_mode;\n\nvarying vec3 normalSurface;\nvarying vec3 vertexPosition;\nvarying vec2 diffuseUV;\nvarying vec2 specularUV;\n\nvarying mat3 v_tbn;\nvarying vec2 v_texcoord;\n\nvoid main() {\n vec3 N;\n \n if (u_hasNormalMap) {\n N = texture2D(u_normalMap, v_texcoord).rgb;\n N = N * 2.0 - 1.0;\n N = normalize(v_tbn * N);\n } else {\n N = normalize(normalSurface);\n }\n \n vec3 finalAmbient = vec3(0.0);\n vec3 finalDiffuse = vec3(0.0);\n vec3 finalSpecular = vec3(0.0);\n\n // Convert colors from 0-255 to 0-1\n vec3 ambientColor = u_ambientColor.rgb / 255.0;\n vec3 diffuseColor = u_diffuseColor.rgb / 255.0;\n vec3 specularColor = u_specularColor.rgb / 255.0;\n\n for (int i = 0; i < 2; i++) {\n vec3 L;\n if (i == 0 && u_lightType_0 == 0.0) {\n // Directional Light\n L = normalize(u_lightTarget_0 - vertexPosition);\n } else if (i == 1 && u_lightType_1 == 0.0) {\n // Directional Light\n L = normalize(u_lightTarget_1 - vertexPosition);\n } else if (i == 0 && u_lightType_0 == 1.0) {\n // Point Light\n L = normalize(u_lightPosition_0 - vertexPosition);\n } else {\n // Point Light\n L = normalize(u_lightPosition_1 - vertexPosition);\n }\n\n vec3 lightAmbient = (i == 0) ? (u_lightAmbient_0.rgb / 255.0) : (u_lightAmbient_1.rgb / 255.0);\n vec3 lightDiffuse = (i == 0) ? (u_lightDiffuse_0.rgb / 255.0) : (u_lightDiffuse_1.rgb / 255.0);\n vec3 lightSpecular = (i == 0) ? (u_lightSpecular_0.rgb / 255.0) : (u_lightSpecular_1.rgb / 255.0);\n\n // Lambert's cosine law\n float lambertian = max(dot(N, L), 0.0);\n float specular = 0.0;\n if (lambertian > 0.0) {\n vec3 R = reflect(-L, N); // Reflected light vector\n vec3 V = normalize(-vertexPosition); // Vector to viewer\n \n // Compute the specular term\n float specAngle = max(dot(R, V), 0.0);\n specular = pow(specAngle, u_shininess);\n }\n\n // Directional light calculation\n vec3 directionalAmbient = lightAmbient * ambientColor;\n vec3 directionalDiffuse = lightDiffuse * lambertian * diffuseColor;\n vec3 directionalSpecular = lightSpecular * specular * specularColor;\n\n // Point light calculation 1\n float distance1 = length(u_lightPosition_0 - vertexPosition);\n float attenuation1 = 1.0 / (u_lightConstant_0 + u_lightLinear_0 * distance1 + u_lightQuadratic_0 * distance1 * distance1);\n\n vec3 pointAmbient1 = attenuation1 * lightAmbient * ambientColor;\n vec3 pointDiffuse1 = attenuation1 * lightDiffuse * lambertian * diffuseColor;\n vec3 pointSpecular1 = attenuation1 * lightSpecular * specular * specularColor;\n\n // Point light calculation 2\n float distance2 = length(u_lightPosition_1 - vertexPosition);\n float attenuation2 = 1.0 / (u_lightConstant_1 + u_lightLinear_1 * distance2 + u_lightQuadratic_1 * distance2 * distance2);\n\n vec3 pointAmbient2 = attenuation2 * lightAmbient * ambientColor;\n vec3 pointDiffuse2 = attenuation2 * lightDiffuse * lambertian * diffuseColor;\n vec3 pointSpecular2 = attenuation2 * lightSpecular * specular * specularColor;\n\n // Processing by u_mode\n // Mode 1 : 1st Directional, 2nd Point\n if (u_mode == 1.0) {\n if (i == 0) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n } else if (i == 1) {\n finalAmbient += pointAmbient2;\n finalDiffuse += pointDiffuse2;\n finalSpecular += pointSpecular2;\n }\n }\n // Mode 2 : 1st Point, 2nd Directional\n else if (u_mode == 2.0) {\n if (i == 0) {\n finalAmbient += pointAmbient1;\n finalDiffuse += pointDiffuse1;\n finalSpecular += pointSpecular1;\n } else if (i == 1) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n }\n }\n // Mode 3 : 1st Directional, 2nd None\n else if (u_mode == 3.0 && i == 0) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n }\n // Mode 4 : 1st Point, 2nd None\n else if (u_mode == 4.0) {\n finalAmbient += pointAmbient1;\n finalDiffuse += pointAmbient1;\n finalSpecular += pointAmbient1;\n }\n }\n\n // Using texture sampler\n vec3 fixedDiffuse = finalDiffuse;\n if (u_hasDiffuseMap == 1.0) {\n fixedDiffuse = fixedDiffuse * texture2D(u_diffuseMap, diffuseUV).rgb;\n }\n\n vec3 fixedSpecular = finalSpecular;\n\n if (u_hasSpecularMap == 1.0) {\n fixedSpecular = finalSpecular * texture2D(u_specularMap, specularUV).rgb;\n }\n\n vec3 finalColor = finalAmbient + fixedDiffuse + fixedSpecular;\n gl_FragColor = vec4(finalColor, 1.0);\n \n}\n","uniforms":{"ambientColor":[102,61,20,255],"diffuseColor":[102,61,20,255],"specularColor":[255,255,255,255],"shininess":60,"diffuseMaps":[],"normalMaps":[],"displacementMaps":[],"specularMaps":[],"diffuseMap":-1,"normalMap":-1,"displacementMap":-1,"specularMap":-1}},{"type":"Basic Material","name":"leg","vertexShader":"\n#define PI 3.1415926535897932384626433832795\nattribute vec4 a_position;\n\nuniform mat4 u_worldMatrix;\nuniform mat4 u_viewMatrix;\nuniform vec4 u_color;\n\nvarying vec4 v_color;\n\nvoid main() { \n gl_Position = u_viewMatrix * u_worldMatrix * a_position;\n v_color = u_color;\n}\n","fragmentShader":"\nprecision highp float;\nvarying vec4 v_color;\n\nvoid main() {\n gl_FragColor = v_color / 255.0;\n}\n","uniforms":{"color":[184,115,51,255]}},{"type":"Phong Material","name":"leg-phong","vertexShader":"\nprecision mediump float;\n\nattribute vec3 a_position;\nattribute vec3 a_faceNormal;\nattribute vec3 a_vertexNormal;\nattribute vec2 a_displacementUV;\nattribute vec2 a_diffuseUV;\nattribute vec2 a_specularUV;\nattribute vec2 a_normalUV;\nattribute vec3 a_tangent;\nattribute vec3 a_bitangent;\n\nuniform mat4 u_worldMatrix;\nuniform mat4 u_viewMatrix;\nuniform sampler2D u_displacementMap;\nuniform float u_displacementScale;\nuniform float u_displacementBias;\n\nvarying vec3 normalSurface;\nvarying vec3 vertexPosition;\nvarying vec2 diffuseUV;\nvarying vec2 specularUV;\nvarying mat3 v_tbn;\nvarying vec2 v_texcoord;\nvarying vec3 v_pos;\n\nvoid main() {\n vec4 displacement = texture2D(u_displacementMap, a_displacementUV);\n\n vec4 displacementVector = normalize(vec4(a_vertexNormal.xyz, 0.0)) * (displacement.r * u_displacementScale + u_displacementBias);\n\n vec4 vertexPosition4 = u_worldMatrix * (vec4(a_position, 1.0) + displacementVector);\n vertexPosition = vec3(vertexPosition4) / vertexPosition4.w;\n normalSurface = (u_viewMatrix * u_worldMatrix * vec4(a_faceNormal, 1.0)).xyz;\n diffuseUV = a_diffuseUV;\n specularUV = a_specularUV;\n \n vec3 T = normalize(vec3(u_worldMatrix * vec4(a_tangent, 0.0)));\n vec3 B = normalize(vec3(u_worldMatrix * vec4(a_bitangent, 0.0)));\n \n vec3 normalTemp = cross(a_tangent, a_bitangent);\n vec3 N = normalize(vec3(u_worldMatrix * vec4(normalTemp, 0.0)));\n\n v_tbn = mat3(T, B, N);\n v_texcoord = a_normalUV;\n v_pos = a_position;\n \n gl_Position = u_viewMatrix * vertexPosition4;\n}\n","fragmentShader":"\nprecision mediump float;\n\n// Tecture sampler\nuniform sampler2D u_diffuseMap;\nuniform sampler2D u_specularMap;\nuniform sampler2D u_normalMap;\nuniform bool u_hasNormalMap;\nuniform float u_hasDiffuseMap;\nuniform float u_hasSpecularMap;\n\n// Material uniform\nuniform float u_shininess;\nuniform vec4 u_ambientColor;\nuniform vec4 u_diffuseColor;\nuniform vec4 u_specularColor;\n\n// Light uniform\nuniform int u_numLights;\n\n// Light properties\nuniform float u_lightType_0;\nuniform vec3 u_lightPosition_0;\nuniform vec4 u_lightColor_0;\nuniform vec4 u_lightAmbient_0;\nuniform vec4 u_lightDiffuse_0;\nuniform vec4 u_lightSpecular_0;\nuniform vec3 u_lightTarget_0;\nuniform float u_lightConstant_0;\nuniform float u_lightLinear_0;\nuniform float u_lightQuadratic_0;\n\nuniform float u_lightType_1;\nuniform vec3 u_lightPosition_1;\nuniform vec4 u_lightColor_1;\nuniform vec4 u_lightAmbient_1;\nuniform vec4 u_lightDiffuse_1;\nuniform vec4 u_lightSpecular_1;\nuniform vec3 u_lightTarget_1;\nuniform float u_lightConstant_1;\nuniform float u_lightLinear_1;\nuniform float u_lightQuadratic_1;\n\nuniform float u_mode;\n\nvarying vec3 normalSurface;\nvarying vec3 vertexPosition;\nvarying vec2 diffuseUV;\nvarying vec2 specularUV;\n\nvarying mat3 v_tbn;\nvarying vec2 v_texcoord;\n\nvoid main() {\n vec3 N;\n \n if (u_hasNormalMap) {\n N = texture2D(u_normalMap, v_texcoord).rgb;\n N = N * 2.0 - 1.0;\n N = normalize(v_tbn * N);\n } else {\n N = normalize(normalSurface);\n }\n \n vec3 finalAmbient = vec3(0.0);\n vec3 finalDiffuse = vec3(0.0);\n vec3 finalSpecular = vec3(0.0);\n\n // Convert colors from 0-255 to 0-1\n vec3 ambientColor = u_ambientColor.rgb / 255.0;\n vec3 diffuseColor = u_diffuseColor.rgb / 255.0;\n vec3 specularColor = u_specularColor.rgb / 255.0;\n\n for (int i = 0; i < 2; i++) {\n vec3 L;\n if (i == 0 && u_lightType_0 == 0.0) {\n // Directional Light\n L = normalize(u_lightTarget_0 - vertexPosition);\n } else if (i == 1 && u_lightType_1 == 0.0) {\n // Directional Light\n L = normalize(u_lightTarget_1 - vertexPosition);\n } else if (i == 0 && u_lightType_0 == 1.0) {\n // Point Light\n L = normalize(u_lightPosition_0 - vertexPosition);\n } else {\n // Point Light\n L = normalize(u_lightPosition_1 - vertexPosition);\n }\n\n vec3 lightAmbient = (i == 0) ? (u_lightAmbient_0.rgb / 255.0) : (u_lightAmbient_1.rgb / 255.0);\n vec3 lightDiffuse = (i == 0) ? (u_lightDiffuse_0.rgb / 255.0) : (u_lightDiffuse_1.rgb / 255.0);\n vec3 lightSpecular = (i == 0) ? (u_lightSpecular_0.rgb / 255.0) : (u_lightSpecular_1.rgb / 255.0);\n\n // Lambert's cosine law\n float lambertian = max(dot(N, L), 0.0);\n float specular = 0.0;\n if (lambertian > 0.0) {\n vec3 R = reflect(-L, N); // Reflected light vector\n vec3 V = normalize(-vertexPosition); // Vector to viewer\n \n // Compute the specular term\n float specAngle = max(dot(R, V), 0.0);\n specular = pow(specAngle, u_shininess);\n }\n\n // Directional light calculation\n vec3 directionalAmbient = lightAmbient * ambientColor;\n vec3 directionalDiffuse = lightDiffuse * lambertian * diffuseColor;\n vec3 directionalSpecular = lightSpecular * specular * specularColor;\n\n // Point light calculation 1\n float distance1 = length(u_lightPosition_0 - vertexPosition);\n float attenuation1 = 1.0 / (u_lightConstant_0 + u_lightLinear_0 * distance1 + u_lightQuadratic_0 * distance1 * distance1);\n\n vec3 pointAmbient1 = attenuation1 * lightAmbient * ambientColor;\n vec3 pointDiffuse1 = attenuation1 * lightDiffuse * lambertian * diffuseColor;\n vec3 pointSpecular1 = attenuation1 * lightSpecular * specular * specularColor;\n\n // Point light calculation 2\n float distance2 = length(u_lightPosition_1 - vertexPosition);\n float attenuation2 = 1.0 / (u_lightConstant_1 + u_lightLinear_1 * distance2 + u_lightQuadratic_1 * distance2 * distance2);\n\n vec3 pointAmbient2 = attenuation2 * lightAmbient * ambientColor;\n vec3 pointDiffuse2 = attenuation2 * lightDiffuse * lambertian * diffuseColor;\n vec3 pointSpecular2 = attenuation2 * lightSpecular * specular * specularColor;\n\n // Processing by u_mode\n // Mode 1 : 1st Directional, 2nd Point\n if (u_mode == 1.0) {\n if (i == 0) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n } else if (i == 1) {\n finalAmbient += pointAmbient2;\n finalDiffuse += pointDiffuse2;\n finalSpecular += pointSpecular2;\n }\n }\n // Mode 2 : 1st Point, 2nd Directional\n else if (u_mode == 2.0) {\n if (i == 0) {\n finalAmbient += pointAmbient1;\n finalDiffuse += pointDiffuse1;\n finalSpecular += pointSpecular1;\n } else if (i == 1) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n }\n }\n // Mode 3 : 1st Directional, 2nd None\n else if (u_mode == 3.0 && i == 0) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n }\n // Mode 4 : 1st Point, 2nd None\n else if (u_mode == 4.0) {\n finalAmbient += pointAmbient1;\n finalDiffuse += pointAmbient1;\n finalSpecular += pointAmbient1;\n }\n }\n\n // Using texture sampler\n vec3 fixedDiffuse = finalDiffuse;\n if (u_hasDiffuseMap == 1.0) {\n fixedDiffuse = fixedDiffuse * texture2D(u_diffuseMap, diffuseUV).rgb;\n }\n\n vec3 fixedSpecular = finalSpecular;\n\n if (u_hasSpecularMap == 1.0) {\n fixedSpecular = finalSpecular * texture2D(u_specularMap, specularUV).rgb;\n }\n\n vec3 finalColor = finalAmbient + fixedDiffuse + fixedSpecular;\n gl_FragColor = vec4(finalColor, 1.0);\n \n}\n","uniforms":{"ambientColor":[184,115,51,255],"diffuseColor":[184,115,51,255],"specularColor":[255,255,255,255],"shininess":60,"diffuseMaps":[],"normalMaps":[],"displacementMaps":[],"specularMaps":[],"diffuseMap":-1,"normalMap":-1,"displacementMap":-1,"specularMap":-1}},{"type":"Basic Material","name":"leg","vertexShader":"\n#define PI 3.1415926535897932384626433832795\nattribute vec4 a_position;\n\nuniform mat4 u_worldMatrix;\nuniform mat4 u_viewMatrix;\nuniform vec4 u_color;\n\nvarying vec4 v_color;\n\nvoid main() { \n gl_Position = u_viewMatrix * u_worldMatrix * a_position;\n v_color = u_color;\n}\n","fragmentShader":"\nprecision highp float;\nvarying vec4 v_color;\n\nvoid main() {\n gl_FragColor = v_color / 255.0;\n}\n","uniforms":{"color":[184,115,51,255]}},{"type":"Phong Material","name":"leg-phong","vertexShader":"\nprecision mediump float;\n\nattribute vec3 a_position;\nattribute vec3 a_faceNormal;\nattribute vec3 a_vertexNormal;\nattribute vec2 a_displacementUV;\nattribute vec2 a_diffuseUV;\nattribute vec2 a_specularUV;\nattribute vec2 a_normalUV;\nattribute vec3 a_tangent;\nattribute vec3 a_bitangent;\n\nuniform mat4 u_worldMatrix;\nuniform mat4 u_viewMatrix;\nuniform sampler2D u_displacementMap;\nuniform float u_displacementScale;\nuniform float u_displacementBias;\n\nvarying vec3 normalSurface;\nvarying vec3 vertexPosition;\nvarying vec2 diffuseUV;\nvarying vec2 specularUV;\nvarying mat3 v_tbn;\nvarying vec2 v_texcoord;\nvarying vec3 v_pos;\n\nvoid main() {\n vec4 displacement = texture2D(u_displacementMap, a_displacementUV);\n\n vec4 displacementVector = normalize(vec4(a_vertexNormal.xyz, 0.0)) * (displacement.r * u_displacementScale + u_displacementBias);\n\n vec4 vertexPosition4 = u_worldMatrix * (vec4(a_position, 1.0) + displacementVector);\n vertexPosition = vec3(vertexPosition4) / vertexPosition4.w;\n normalSurface = (u_viewMatrix * u_worldMatrix * vec4(a_faceNormal, 1.0)).xyz;\n diffuseUV = a_diffuseUV;\n specularUV = a_specularUV;\n \n vec3 T = normalize(vec3(u_worldMatrix * vec4(a_tangent, 0.0)));\n vec3 B = normalize(vec3(u_worldMatrix * vec4(a_bitangent, 0.0)));\n \n vec3 normalTemp = cross(a_tangent, a_bitangent);\n vec3 N = normalize(vec3(u_worldMatrix * vec4(normalTemp, 0.0)));\n\n v_tbn = mat3(T, B, N);\n v_texcoord = a_normalUV;\n v_pos = a_position;\n \n gl_Position = u_viewMatrix * vertexPosition4;\n}\n","fragmentShader":"\nprecision mediump float;\n\n// Tecture sampler\nuniform sampler2D u_diffuseMap;\nuniform sampler2D u_specularMap;\nuniform sampler2D u_normalMap;\nuniform bool u_hasNormalMap;\nuniform float u_hasDiffuseMap;\nuniform float u_hasSpecularMap;\n\n// Material uniform\nuniform float u_shininess;\nuniform vec4 u_ambientColor;\nuniform vec4 u_diffuseColor;\nuniform vec4 u_specularColor;\n\n// Light uniform\nuniform int u_numLights;\n\n// Light properties\nuniform float u_lightType_0;\nuniform vec3 u_lightPosition_0;\nuniform vec4 u_lightColor_0;\nuniform vec4 u_lightAmbient_0;\nuniform vec4 u_lightDiffuse_0;\nuniform vec4 u_lightSpecular_0;\nuniform vec3 u_lightTarget_0;\nuniform float u_lightConstant_0;\nuniform float u_lightLinear_0;\nuniform float u_lightQuadratic_0;\n\nuniform float u_lightType_1;\nuniform vec3 u_lightPosition_1;\nuniform vec4 u_lightColor_1;\nuniform vec4 u_lightAmbient_1;\nuniform vec4 u_lightDiffuse_1;\nuniform vec4 u_lightSpecular_1;\nuniform vec3 u_lightTarget_1;\nuniform float u_lightConstant_1;\nuniform float u_lightLinear_1;\nuniform float u_lightQuadratic_1;\n\nuniform float u_mode;\n\nvarying vec3 normalSurface;\nvarying vec3 vertexPosition;\nvarying vec2 diffuseUV;\nvarying vec2 specularUV;\n\nvarying mat3 v_tbn;\nvarying vec2 v_texcoord;\n\nvoid main() {\n vec3 N;\n \n if (u_hasNormalMap) {\n N = texture2D(u_normalMap, v_texcoord).rgb;\n N = N * 2.0 - 1.0;\n N = normalize(v_tbn * N);\n } else {\n N = normalize(normalSurface);\n }\n \n vec3 finalAmbient = vec3(0.0);\n vec3 finalDiffuse = vec3(0.0);\n vec3 finalSpecular = vec3(0.0);\n\n // Convert colors from 0-255 to 0-1\n vec3 ambientColor = u_ambientColor.rgb / 255.0;\n vec3 diffuseColor = u_diffuseColor.rgb / 255.0;\n vec3 specularColor = u_specularColor.rgb / 255.0;\n\n for (int i = 0; i < 2; i++) {\n vec3 L;\n if (i == 0 && u_lightType_0 == 0.0) {\n // Directional Light\n L = normalize(u_lightTarget_0 - vertexPosition);\n } else if (i == 1 && u_lightType_1 == 0.0) {\n // Directional Light\n L = normalize(u_lightTarget_1 - vertexPosition);\n } else if (i == 0 && u_lightType_0 == 1.0) {\n // Point Light\n L = normalize(u_lightPosition_0 - vertexPosition);\n } else {\n // Point Light\n L = normalize(u_lightPosition_1 - vertexPosition);\n }\n\n vec3 lightAmbient = (i == 0) ? (u_lightAmbient_0.rgb / 255.0) : (u_lightAmbient_1.rgb / 255.0);\n vec3 lightDiffuse = (i == 0) ? (u_lightDiffuse_0.rgb / 255.0) : (u_lightDiffuse_1.rgb / 255.0);\n vec3 lightSpecular = (i == 0) ? (u_lightSpecular_0.rgb / 255.0) : (u_lightSpecular_1.rgb / 255.0);\n\n // Lambert's cosine law\n float lambertian = max(dot(N, L), 0.0);\n float specular = 0.0;\n if (lambertian > 0.0) {\n vec3 R = reflect(-L, N); // Reflected light vector\n vec3 V = normalize(-vertexPosition); // Vector to viewer\n \n // Compute the specular term\n float specAngle = max(dot(R, V), 0.0);\n specular = pow(specAngle, u_shininess);\n }\n\n // Directional light calculation\n vec3 directionalAmbient = lightAmbient * ambientColor;\n vec3 directionalDiffuse = lightDiffuse * lambertian * diffuseColor;\n vec3 directionalSpecular = lightSpecular * specular * specularColor;\n\n // Point light calculation 1\n float distance1 = length(u_lightPosition_0 - vertexPosition);\n float attenuation1 = 1.0 / (u_lightConstant_0 + u_lightLinear_0 * distance1 + u_lightQuadratic_0 * distance1 * distance1);\n\n vec3 pointAmbient1 = attenuation1 * lightAmbient * ambientColor;\n vec3 pointDiffuse1 = attenuation1 * lightDiffuse * lambertian * diffuseColor;\n vec3 pointSpecular1 = attenuation1 * lightSpecular * specular * specularColor;\n\n // Point light calculation 2\n float distance2 = length(u_lightPosition_1 - vertexPosition);\n float attenuation2 = 1.0 / (u_lightConstant_1 + u_lightLinear_1 * distance2 + u_lightQuadratic_1 * distance2 * distance2);\n\n vec3 pointAmbient2 = attenuation2 * lightAmbient * ambientColor;\n vec3 pointDiffuse2 = attenuation2 * lightDiffuse * lambertian * diffuseColor;\n vec3 pointSpecular2 = attenuation2 * lightSpecular * specular * specularColor;\n\n // Processing by u_mode\n // Mode 1 : 1st Directional, 2nd Point\n if (u_mode == 1.0) {\n if (i == 0) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n } else if (i == 1) {\n finalAmbient += pointAmbient2;\n finalDiffuse += pointDiffuse2;\n finalSpecular += pointSpecular2;\n }\n }\n // Mode 2 : 1st Point, 2nd Directional\n else if (u_mode == 2.0) {\n if (i == 0) {\n finalAmbient += pointAmbient1;\n finalDiffuse += pointDiffuse1;\n finalSpecular += pointSpecular1;\n } else if (i == 1) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n }\n }\n // Mode 3 : 1st Directional, 2nd None\n else if (u_mode == 3.0 && i == 0) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n }\n // Mode 4 : 1st Point, 2nd None\n else if (u_mode == 4.0) {\n finalAmbient += pointAmbient1;\n finalDiffuse += pointAmbient1;\n finalSpecular += pointAmbient1;\n }\n }\n\n // Using texture sampler\n vec3 fixedDiffuse = finalDiffuse;\n if (u_hasDiffuseMap == 1.0) {\n fixedDiffuse = fixedDiffuse * texture2D(u_diffuseMap, diffuseUV).rgb;\n }\n\n vec3 fixedSpecular = finalSpecular;\n\n if (u_hasSpecularMap == 1.0) {\n fixedSpecular = finalSpecular * texture2D(u_specularMap, specularUV).rgb;\n }\n\n vec3 finalColor = finalAmbient + fixedDiffuse + fixedSpecular;\n gl_FragColor = vec4(finalColor, 1.0);\n \n}\n","uniforms":{"ambientColor":[184,115,51,255],"diffuseColor":[184,115,51,255],"specularColor":[255,255,255,255],"shininess":60,"diffuseMaps":[],"normalMaps":[],"displacementMaps":[],"specularMaps":[],"diffuseMap":-1,"normalMap":-1,"displacementMap":-1,"specularMap":-1}},{"type":"Basic Material","name":"leg","vertexShader":"\n#define PI 3.1415926535897932384626433832795\nattribute vec4 a_position;\n\nuniform mat4 u_worldMatrix;\nuniform mat4 u_viewMatrix;\nuniform vec4 u_color;\n\nvarying vec4 v_color;\n\nvoid main() { \n gl_Position = u_viewMatrix * u_worldMatrix * a_position;\n v_color = u_color;\n}\n","fragmentShader":"\nprecision highp float;\nvarying vec4 v_color;\n\nvoid main() {\n gl_FragColor = v_color / 255.0;\n}\n","uniforms":{"color":[184,115,51,255]}},{"type":"Phong Material","name":"leg-phong","vertexShader":"\nprecision mediump float;\n\nattribute vec3 a_position;\nattribute vec3 a_faceNormal;\nattribute vec3 a_vertexNormal;\nattribute vec2 a_displacementUV;\nattribute vec2 a_diffuseUV;\nattribute vec2 a_specularUV;\nattribute vec2 a_normalUV;\nattribute vec3 a_tangent;\nattribute vec3 a_bitangent;\n\nuniform mat4 u_worldMatrix;\nuniform mat4 u_viewMatrix;\nuniform sampler2D u_displacementMap;\nuniform float u_displacementScale;\nuniform float u_displacementBias;\n\nvarying vec3 normalSurface;\nvarying vec3 vertexPosition;\nvarying vec2 diffuseUV;\nvarying vec2 specularUV;\nvarying mat3 v_tbn;\nvarying vec2 v_texcoord;\nvarying vec3 v_pos;\n\nvoid main() {\n vec4 displacement = texture2D(u_displacementMap, a_displacementUV);\n\n vec4 displacementVector = normalize(vec4(a_vertexNormal.xyz, 0.0)) * (displacement.r * u_displacementScale + u_displacementBias);\n\n vec4 vertexPosition4 = u_worldMatrix * (vec4(a_position, 1.0) + displacementVector);\n vertexPosition = vec3(vertexPosition4) / vertexPosition4.w;\n normalSurface = (u_viewMatrix * u_worldMatrix * vec4(a_faceNormal, 1.0)).xyz;\n diffuseUV = a_diffuseUV;\n specularUV = a_specularUV;\n \n vec3 T = normalize(vec3(u_worldMatrix * vec4(a_tangent, 0.0)));\n vec3 B = normalize(vec3(u_worldMatrix * vec4(a_bitangent, 0.0)));\n \n vec3 normalTemp = cross(a_tangent, a_bitangent);\n vec3 N = normalize(vec3(u_worldMatrix * vec4(normalTemp, 0.0)));\n\n v_tbn = mat3(T, B, N);\n v_texcoord = a_normalUV;\n v_pos = a_position;\n \n gl_Position = u_viewMatrix * vertexPosition4;\n}\n","fragmentShader":"\nprecision mediump float;\n\n// Tecture sampler\nuniform sampler2D u_diffuseMap;\nuniform sampler2D u_specularMap;\nuniform sampler2D u_normalMap;\nuniform bool u_hasNormalMap;\nuniform float u_hasDiffuseMap;\nuniform float u_hasSpecularMap;\n\n// Material uniform\nuniform float u_shininess;\nuniform vec4 u_ambientColor;\nuniform vec4 u_diffuseColor;\nuniform vec4 u_specularColor;\n\n// Light uniform\nuniform int u_numLights;\n\n// Light properties\nuniform float u_lightType_0;\nuniform vec3 u_lightPosition_0;\nuniform vec4 u_lightColor_0;\nuniform vec4 u_lightAmbient_0;\nuniform vec4 u_lightDiffuse_0;\nuniform vec4 u_lightSpecular_0;\nuniform vec3 u_lightTarget_0;\nuniform float u_lightConstant_0;\nuniform float u_lightLinear_0;\nuniform float u_lightQuadratic_0;\n\nuniform float u_lightType_1;\nuniform vec3 u_lightPosition_1;\nuniform vec4 u_lightColor_1;\nuniform vec4 u_lightAmbient_1;\nuniform vec4 u_lightDiffuse_1;\nuniform vec4 u_lightSpecular_1;\nuniform vec3 u_lightTarget_1;\nuniform float u_lightConstant_1;\nuniform float u_lightLinear_1;\nuniform float u_lightQuadratic_1;\n\nuniform float u_mode;\n\nvarying vec3 normalSurface;\nvarying vec3 vertexPosition;\nvarying vec2 diffuseUV;\nvarying vec2 specularUV;\n\nvarying mat3 v_tbn;\nvarying vec2 v_texcoord;\n\nvoid main() {\n vec3 N;\n \n if (u_hasNormalMap) {\n N = texture2D(u_normalMap, v_texcoord).rgb;\n N = N * 2.0 - 1.0;\n N = normalize(v_tbn * N);\n } else {\n N = normalize(normalSurface);\n }\n \n vec3 finalAmbient = vec3(0.0);\n vec3 finalDiffuse = vec3(0.0);\n vec3 finalSpecular = vec3(0.0);\n\n // Convert colors from 0-255 to 0-1\n vec3 ambientColor = u_ambientColor.rgb / 255.0;\n vec3 diffuseColor = u_diffuseColor.rgb / 255.0;\n vec3 specularColor = u_specularColor.rgb / 255.0;\n\n for (int i = 0; i < 2; i++) {\n vec3 L;\n if (i == 0 && u_lightType_0 == 0.0) {\n // Directional Light\n L = normalize(u_lightTarget_0 - vertexPosition);\n } else if (i == 1 && u_lightType_1 == 0.0) {\n // Directional Light\n L = normalize(u_lightTarget_1 - vertexPosition);\n } else if (i == 0 && u_lightType_0 == 1.0) {\n // Point Light\n L = normalize(u_lightPosition_0 - vertexPosition);\n } else {\n // Point Light\n L = normalize(u_lightPosition_1 - vertexPosition);\n }\n\n vec3 lightAmbient = (i == 0) ? (u_lightAmbient_0.rgb / 255.0) : (u_lightAmbient_1.rgb / 255.0);\n vec3 lightDiffuse = (i == 0) ? (u_lightDiffuse_0.rgb / 255.0) : (u_lightDiffuse_1.rgb / 255.0);\n vec3 lightSpecular = (i == 0) ? (u_lightSpecular_0.rgb / 255.0) : (u_lightSpecular_1.rgb / 255.0);\n\n // Lambert's cosine law\n float lambertian = max(dot(N, L), 0.0);\n float specular = 0.0;\n if (lambertian > 0.0) {\n vec3 R = reflect(-L, N); // Reflected light vector\n vec3 V = normalize(-vertexPosition); // Vector to viewer\n \n // Compute the specular term\n float specAngle = max(dot(R, V), 0.0);\n specular = pow(specAngle, u_shininess);\n }\n\n // Directional light calculation\n vec3 directionalAmbient = lightAmbient * ambientColor;\n vec3 directionalDiffuse = lightDiffuse * lambertian * diffuseColor;\n vec3 directionalSpecular = lightSpecular * specular * specularColor;\n\n // Point light calculation 1\n float distance1 = length(u_lightPosition_0 - vertexPosition);\n float attenuation1 = 1.0 / (u_lightConstant_0 + u_lightLinear_0 * distance1 + u_lightQuadratic_0 * distance1 * distance1);\n\n vec3 pointAmbient1 = attenuation1 * lightAmbient * ambientColor;\n vec3 pointDiffuse1 = attenuation1 * lightDiffuse * lambertian * diffuseColor;\n vec3 pointSpecular1 = attenuation1 * lightSpecular * specular * specularColor;\n\n // Point light calculation 2\n float distance2 = length(u_lightPosition_1 - vertexPosition);\n float attenuation2 = 1.0 / (u_lightConstant_1 + u_lightLinear_1 * distance2 + u_lightQuadratic_1 * distance2 * distance2);\n\n vec3 pointAmbient2 = attenuation2 * lightAmbient * ambientColor;\n vec3 pointDiffuse2 = attenuation2 * lightDiffuse * lambertian * diffuseColor;\n vec3 pointSpecular2 = attenuation2 * lightSpecular * specular * specularColor;\n\n // Processing by u_mode\n // Mode 1 : 1st Directional, 2nd Point\n if (u_mode == 1.0) {\n if (i == 0) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n } else if (i == 1) {\n finalAmbient += pointAmbient2;\n finalDiffuse += pointDiffuse2;\n finalSpecular += pointSpecular2;\n }\n }\n // Mode 2 : 1st Point, 2nd Directional\n else if (u_mode == 2.0) {\n if (i == 0) {\n finalAmbient += pointAmbient1;\n finalDiffuse += pointDiffuse1;\n finalSpecular += pointSpecular1;\n } else if (i == 1) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n }\n }\n // Mode 3 : 1st Directional, 2nd None\n else if (u_mode == 3.0 && i == 0) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n }\n // Mode 4 : 1st Point, 2nd None\n else if (u_mode == 4.0) {\n finalAmbient += pointAmbient1;\n finalDiffuse += pointAmbient1;\n finalSpecular += pointAmbient1;\n }\n }\n\n // Using texture sampler\n vec3 fixedDiffuse = finalDiffuse;\n if (u_hasDiffuseMap == 1.0) {\n fixedDiffuse = fixedDiffuse * texture2D(u_diffuseMap, diffuseUV).rgb;\n }\n\n vec3 fixedSpecular = finalSpecular;\n\n if (u_hasSpecularMap == 1.0) {\n fixedSpecular = finalSpecular * texture2D(u_specularMap, specularUV).rgb;\n }\n\n vec3 finalColor = finalAmbient + fixedDiffuse + fixedSpecular;\n gl_FragColor = vec4(finalColor, 1.0);\n \n}\n","uniforms":{"ambientColor":[184,115,51,255],"diffuseColor":[184,115,51,255],"specularColor":[255,255,255,255],"shininess":60,"diffuseMaps":[],"normalMaps":[],"displacementMaps":[],"specularMaps":[],"diffuseMap":-1,"normalMap":-1,"displacementMap":-1,"specularMap":-1}},{"type":"Basic Material","name":"leg","vertexShader":"\n#define PI 3.1415926535897932384626433832795\nattribute vec4 a_position;\n\nuniform mat4 u_worldMatrix;\nuniform mat4 u_viewMatrix;\nuniform vec4 u_color;\n\nvarying vec4 v_color;\n\nvoid main() { \n gl_Position = u_viewMatrix * u_worldMatrix * a_position;\n v_color = u_color;\n}\n","fragmentShader":"\nprecision highp float;\nvarying vec4 v_color;\n\nvoid main() {\n gl_FragColor = v_color / 255.0;\n}\n","uniforms":{"color":[184,115,51,255]}},{"type":"Phong Material","name":"leg-phong","vertexShader":"\nprecision mediump float;\n\nattribute vec3 a_position;\nattribute vec3 a_faceNormal;\nattribute vec3 a_vertexNormal;\nattribute vec2 a_displacementUV;\nattribute vec2 a_diffuseUV;\nattribute vec2 a_specularUV;\nattribute vec2 a_normalUV;\nattribute vec3 a_tangent;\nattribute vec3 a_bitangent;\n\nuniform mat4 u_worldMatrix;\nuniform mat4 u_viewMatrix;\nuniform sampler2D u_displacementMap;\nuniform float u_displacementScale;\nuniform float u_displacementBias;\n\nvarying vec3 normalSurface;\nvarying vec3 vertexPosition;\nvarying vec2 diffuseUV;\nvarying vec2 specularUV;\nvarying mat3 v_tbn;\nvarying vec2 v_texcoord;\nvarying vec3 v_pos;\n\nvoid main() {\n vec4 displacement = texture2D(u_displacementMap, a_displacementUV);\n\n vec4 displacementVector = normalize(vec4(a_vertexNormal.xyz, 0.0)) * (displacement.r * u_displacementScale + u_displacementBias);\n\n vec4 vertexPosition4 = u_worldMatrix * (vec4(a_position, 1.0) + displacementVector);\n vertexPosition = vec3(vertexPosition4) / vertexPosition4.w;\n normalSurface = (u_viewMatrix * u_worldMatrix * vec4(a_faceNormal, 1.0)).xyz;\n diffuseUV = a_diffuseUV;\n specularUV = a_specularUV;\n \n vec3 T = normalize(vec3(u_worldMatrix * vec4(a_tangent, 0.0)));\n vec3 B = normalize(vec3(u_worldMatrix * vec4(a_bitangent, 0.0)));\n \n vec3 normalTemp = cross(a_tangent, a_bitangent);\n vec3 N = normalize(vec3(u_worldMatrix * vec4(normalTemp, 0.0)));\n\n v_tbn = mat3(T, B, N);\n v_texcoord = a_normalUV;\n v_pos = a_position;\n \n gl_Position = u_viewMatrix * vertexPosition4;\n}\n","fragmentShader":"\nprecision mediump float;\n\n// Tecture sampler\nuniform sampler2D u_diffuseMap;\nuniform sampler2D u_specularMap;\nuniform sampler2D u_normalMap;\nuniform bool u_hasNormalMap;\nuniform float u_hasDiffuseMap;\nuniform float u_hasSpecularMap;\n\n// Material uniform\nuniform float u_shininess;\nuniform vec4 u_ambientColor;\nuniform vec4 u_diffuseColor;\nuniform vec4 u_specularColor;\n\n// Light uniform\nuniform int u_numLights;\n\n// Light properties\nuniform float u_lightType_0;\nuniform vec3 u_lightPosition_0;\nuniform vec4 u_lightColor_0;\nuniform vec4 u_lightAmbient_0;\nuniform vec4 u_lightDiffuse_0;\nuniform vec4 u_lightSpecular_0;\nuniform vec3 u_lightTarget_0;\nuniform float u_lightConstant_0;\nuniform float u_lightLinear_0;\nuniform float u_lightQuadratic_0;\n\nuniform float u_lightType_1;\nuniform vec3 u_lightPosition_1;\nuniform vec4 u_lightColor_1;\nuniform vec4 u_lightAmbient_1;\nuniform vec4 u_lightDiffuse_1;\nuniform vec4 u_lightSpecular_1;\nuniform vec3 u_lightTarget_1;\nuniform float u_lightConstant_1;\nuniform float u_lightLinear_1;\nuniform float u_lightQuadratic_1;\n\nuniform float u_mode;\n\nvarying vec3 normalSurface;\nvarying vec3 vertexPosition;\nvarying vec2 diffuseUV;\nvarying vec2 specularUV;\n\nvarying mat3 v_tbn;\nvarying vec2 v_texcoord;\n\nvoid main() {\n vec3 N;\n \n if (u_hasNormalMap) {\n N = texture2D(u_normalMap, v_texcoord).rgb;\n N = N * 2.0 - 1.0;\n N = normalize(v_tbn * N);\n } else {\n N = normalize(normalSurface);\n }\n \n vec3 finalAmbient = vec3(0.0);\n vec3 finalDiffuse = vec3(0.0);\n vec3 finalSpecular = vec3(0.0);\n\n // Convert colors from 0-255 to 0-1\n vec3 ambientColor = u_ambientColor.rgb / 255.0;\n vec3 diffuseColor = u_diffuseColor.rgb / 255.0;\n vec3 specularColor = u_specularColor.rgb / 255.0;\n\n for (int i = 0; i < 2; i++) {\n vec3 L;\n if (i == 0 && u_lightType_0 == 0.0) {\n // Directional Light\n L = normalize(u_lightTarget_0 - vertexPosition);\n } else if (i == 1 && u_lightType_1 == 0.0) {\n // Directional Light\n L = normalize(u_lightTarget_1 - vertexPosition);\n } else if (i == 0 && u_lightType_0 == 1.0) {\n // Point Light\n L = normalize(u_lightPosition_0 - vertexPosition);\n } else {\n // Point Light\n L = normalize(u_lightPosition_1 - vertexPosition);\n }\n\n vec3 lightAmbient = (i == 0) ? (u_lightAmbient_0.rgb / 255.0) : (u_lightAmbient_1.rgb / 255.0);\n vec3 lightDiffuse = (i == 0) ? (u_lightDiffuse_0.rgb / 255.0) : (u_lightDiffuse_1.rgb / 255.0);\n vec3 lightSpecular = (i == 0) ? (u_lightSpecular_0.rgb / 255.0) : (u_lightSpecular_1.rgb / 255.0);\n\n // Lambert's cosine law\n float lambertian = max(dot(N, L), 0.0);\n float specular = 0.0;\n if (lambertian > 0.0) {\n vec3 R = reflect(-L, N); // Reflected light vector\n vec3 V = normalize(-vertexPosition); // Vector to viewer\n \n // Compute the specular term\n float specAngle = max(dot(R, V), 0.0);\n specular = pow(specAngle, u_shininess);\n }\n\n // Directional light calculation\n vec3 directionalAmbient = lightAmbient * ambientColor;\n vec3 directionalDiffuse = lightDiffuse * lambertian * diffuseColor;\n vec3 directionalSpecular = lightSpecular * specular * specularColor;\n\n // Point light calculation 1\n float distance1 = length(u_lightPosition_0 - vertexPosition);\n float attenuation1 = 1.0 / (u_lightConstant_0 + u_lightLinear_0 * distance1 + u_lightQuadratic_0 * distance1 * distance1);\n\n vec3 pointAmbient1 = attenuation1 * lightAmbient * ambientColor;\n vec3 pointDiffuse1 = attenuation1 * lightDiffuse * lambertian * diffuseColor;\n vec3 pointSpecular1 = attenuation1 * lightSpecular * specular * specularColor;\n\n // Point light calculation 2\n float distance2 = length(u_lightPosition_1 - vertexPosition);\n float attenuation2 = 1.0 / (u_lightConstant_1 + u_lightLinear_1 * distance2 + u_lightQuadratic_1 * distance2 * distance2);\n\n vec3 pointAmbient2 = attenuation2 * lightAmbient * ambientColor;\n vec3 pointDiffuse2 = attenuation2 * lightDiffuse * lambertian * diffuseColor;\n vec3 pointSpecular2 = attenuation2 * lightSpecular * specular * specularColor;\n\n // Processing by u_mode\n // Mode 1 : 1st Directional, 2nd Point\n if (u_mode == 1.0) {\n if (i == 0) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n } else if (i == 1) {\n finalAmbient += pointAmbient2;\n finalDiffuse += pointDiffuse2;\n finalSpecular += pointSpecular2;\n }\n }\n // Mode 2 : 1st Point, 2nd Directional\n else if (u_mode == 2.0) {\n if (i == 0) {\n finalAmbient += pointAmbient1;\n finalDiffuse += pointDiffuse1;\n finalSpecular += pointSpecular1;\n } else if (i == 1) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n }\n }\n // Mode 3 : 1st Directional, 2nd None\n else if (u_mode == 3.0 && i == 0) {\n finalAmbient += directionalAmbient;\n finalDiffuse += directionalDiffuse;\n finalSpecular += directionalSpecular;\n }\n // Mode 4 : 1st Point, 2nd None\n else if (u_mode == 4.0) {\n finalAmbient += pointAmbient1;\n finalDiffuse += pointAmbient1;\n finalSpecular += pointAmbient1;\n }\n }\n\n // Using texture sampler\n vec3 fixedDiffuse = finalDiffuse;\n if (u_hasDiffuseMap == 1.0) {\n fixedDiffuse = fixedDiffuse * texture2D(u_diffuseMap, diffuseUV).rgb;\n }\n\n vec3 fixedSpecular = finalSpecular;\n\n if (u_hasSpecularMap == 1.0) {\n fixedSpecular = finalSpecular * texture2D(u_specularMap, specularUV).rgb;\n }\n\n vec3 finalColor = finalAmbient + fixedDiffuse + fixedSpecular;\n gl_FragColor = vec4(finalColor, 1.0);\n \n}\n","uniforms":{"ambientColor":[184,115,51,255],"diffuseColor":[184,115,51,255],"specularColor":[255,255,255,255],"shininess":60,"diffuseMaps":[],"normalMaps":[],"displacementMaps":[],"specularMaps":[],"diffuseMap":-1,"normalMap":-1,"displacementMap":-1,"specularMap":-1}}],"meshes":[{"primitives":[{"attributes":{"POSITION":0,"FACE_NORMAL":1,"VERTEX_NORMAL":2},"basicMaterial":0,"phongMaterial":1,"indices":3}]},{"primitives":[{"attributes":{"POSITION":4,"FACE_NORMAL":5,"VERTEX_NORMAL":6},"basicMaterial":2,"phongMaterial":3,"indices":7}]},{"primitives":[{"attributes":{"POSITION":8,"FACE_NORMAL":9,"VERTEX_NORMAL":10},"basicMaterial":4,"phongMaterial":5,"indices":11}]},{"primitives":[{"attributes":{"POSITION":12,"FACE_NORMAL":13,"VERTEX_NORMAL":14},"basicMaterial":6,"phongMaterial":7,"indices":15}]},{"primitives":[{"attributes":{"POSITION":16,"FACE_NORMAL":17,"VERTEX_NORMAL":18},"basicMaterial":8,"phongMaterial":9,"indices":19}]},{"primitives":[{"attributes":{"POSITION":20,"FACE_NORMAL":21,"VERTEX_NORMAL":22},"basicMaterial":10,"phongMaterial":11,"indices":23}]},{"primitives":[{"attributes":{"POSITION":24,"FACE_NORMAL":25,"VERTEX_NORMAL":26},"basicMaterial":12,"phongMaterial":13,"indices":27}]},{"primitives":[{"attributes":{"POSITION":28,"FACE_NORMAL":29,"VERTEX_NORMAL":30},"basicMaterial":14,"phongMaterial":15,"indices":31}]},{"primitives":[{"attributes":{"POSITION":32,"FACE_NORMAL":33,"VERTEX_NORMAL":34},"basicMaterial":16,"phongMaterial":17,"indices":35}]},{"primitives":[{"attributes":{"POSITION":36,"FACE_NORMAL":37,"VERTEX_NORMAL":38},"basicMaterial":18,"phongMaterial":19,"indices":39}]},{"primitives":[{"attributes":{"POSITION":40,"FACE_NORMAL":41,"VERTEX_NORMAL":42},"basicMaterial":20,"phongMaterial":21,"indices":43}]}],"cameras":[],"lights":[],"nodes":[{"id":"7a1219ad-85fe-49d6-986e-2387b7c65225","name":"Dog","translation":[0,-10,0],"rotation":[0.24999999999999997,0.24999999999999997,0.06698729810778066,0.9330127018922194],"scale":[0.5,0.5,0.5],"children":[1,7,8,9,10,11]},{"id":"4c402c1c-36b8-46bb-ab70-5492c149b032","name":"Head","translation":[0,20,120],"rotation":[0,0,0,1],"scale":[1,1,1],"children":[2,3,4,5,6],"mesh":0},{"id":"0ae877f8-2b01-47ba-afef-d0956badd6f8","name":"Left Eye","translation":[-15,30,35],"rotation":[0,0,0,1],"scale":[1,1,1],"children":[],"mesh":1},{"id":"9a9667b3-deaf-46a2-8c9e-5b603e0e77ac","name":"Right Eye","translation":[15,30,35],"rotation":[0,0,0,1],"scale":[1,1,1],"children":[],"mesh":2},{"id":"3fffaa45-f804-4bc3-9e52-7cc5b7c2268e","name":"Mouth","translation":[0,0,35],"rotation":[0,0,0,1],"scale":[1,1,1],"children":[],"mesh":3},{"id":"c8a036e2-f7d8-44ba-8698-e4c6209a8685","name":"Left Ear","translation":[-20,50,20],"rotation":[0,0,0,1],"scale":[1,1,1],"children":[],"mesh":4},{"id":"9079b8df-fd92-493c-a763-1e01702005ea","name":"Right Ear","translation":[20,50,20],"rotation":[0,0,0,1],"scale":[1,1,1],"children":[],"mesh":5},{"id":"dde4c993-1923-4241-a845-61b9d8c3fc66","name":"Body","translation":[0,0,0],"rotation":[0,0,0,1],"scale":[1,1,1],"children":[],"mesh":6},{"id":"052d3e0c-48f2-4210-abc5-bb5adce0def2","name":"Left Front Leg","translation":[-35,-30,70],"rotation":[0,0,0,1],"scale":[1,1,1],"children":[],"mesh":7},{"id":"a7de7964-b5c4-45a6-b359-270110529ae3","name":"Right Front Leg","translation":[35,-30,70],"rotation":[0,0,0,1],"scale":[1,1,1],"children":[],"mesh":8},{"id":"89135880-6bd2-49f9-84d6-8b4e35d85500","name":"Left Back Leg","translation":[-35,-30,-60],"rotation":[0,0,0,1],"scale":[1,1,1],"children":[],"mesh":9},{"id":"68be08e3-ed3b-4552-ac7f-ddcfca2540bc","name":"Right Back Leg","translation":[35,-30,-60],"rotation":[0,0,0,1],"scale":[1,1,1],"children":[],"mesh":10}],"scenes":[{"nodes":[0,1,2,3,4,5,6,7,8,9,10,11],"activeCamera":-1,"activeLight":[-1]}],"animations":[{"name":"walk and greet","frames":[{"nodeKeyframePairs":[{"node":8,"keyframe":{"rotation":[0,0,0]}},{"node":9,"keyframe":{"rotation":[0,0,0]}},{"node":11,"keyframe":{"rotation":[0,0,0]}},{"node":10,"keyframe":{"rotation":[0,0,0]}},{"node":2,"keyframe":{}},{"node":3,"keyframe":{}},{"node":5,"keyframe":{}},{"node":6,"keyframe":{}}]},{"nodeKeyframePairs":[{"node":8,"keyframe":{"rotation":[15,0,0]}},{"node":9,"keyframe":{"rotation":[-15,0,0]}},{"node":11,"keyframe":{"rotation":[15,0,0]}},{"node":10,"keyframe":{"rotation":[-15,0,0]}},{"node":2,"keyframe":{}},{"node":3,"keyframe":{}},{"node":5,"keyframe":{}},{"node":6,"keyframe":{}}]},{"nodeKeyframePairs":[{"node":8,"keyframe":{"rotation":[0,0,0]}},{"node":9,"keyframe":{"rotation":[0,0,0]}},{"node":11,"keyframe":{"rotation":[0,0,0]}},{"node":10,"keyframe":{"rotation":[0,0,0]}},{"node":2,"keyframe":{}},{"node":3,"keyframe":{}},{"node":5,"keyframe":{}},{"node":6,"keyframe":{}}]},{"nodeKeyframePairs":[{"node":8,"keyframe":{"rotation":[-15,0,0]}},{"node":9,"keyframe":{"rotation":[15,0,0]}},{"node":11,"keyframe":{"rotation":[-15,0,0]}},{"node":10,"keyframe":{"rotation":[15,0,0]}},{"node":2,"keyframe":{}},{"node":3,"keyframe":{}},{"node":5,"keyframe":{}},{"node":6,"keyframe":{}}]},{"nodeKeyframePairs":[{"node":8,"keyframe":{"rotation":[0,0,0]}},{"node":9,"keyframe":{"rotation":[0,0,0]}},{"node":11,"keyframe":{"rotation":[0,0,0]}},{"node":10,"keyframe":{"rotation":[0,0,0]}},{"node":2,"keyframe":{}},{"node":3,"keyframe":{}},{"node":5,"keyframe":{}},{"node":6,"keyframe":{}}]},{"nodeKeyframePairs":[{"node":8,"keyframe":{}},{"node":9,"keyframe":{}},{"node":11,"keyframe":{}},{"node":10,"keyframe":{}},{"node":2,"keyframe":{"scale":[1,0.5,1]}},{"node":3,"keyframe":{"scale":[1,0.5,1]}},{"node":5,"keyframe":{"rotation":[0,0,5]}},{"node":6,"keyframe":{"rotation":[0,0,-5]}}]},{"nodeKeyframePairs":[{"node":8,"keyframe":{}},{"node":9,"keyframe":{}},{"node":11,"keyframe":{}},{"node":10,"keyframe":{}},{"node":2,"keyframe":{"scale":[1,0,1]}},{"node":3,"keyframe":{"scale":[1,0,1]}},{"node":5,"keyframe":{"rotation":[0,0,15]}},{"node":6,"keyframe":{"rotation":[0,0,-15]}}]},{"nodeKeyframePairs":[{"node":8,"keyframe":{}},{"node":9,"keyframe":{}},{"node":11,"keyframe":{}},{"node":10,"keyframe":{}},{"node":2,"keyframe":{"scale":[1,0.5,1]}},{"node":3,"keyframe":{"scale":[1,0.5,1]}},{"node":5,"keyframe":{"rotation":[0,0,5]}},{"node":6,"keyframe":{"rotation":[0,0,-5]}}]},{"nodeKeyframePairs":[{"node":8,"keyframe":{}},{"node":9,"keyframe":{}},{"node":11,"keyframe":{}},{"node":10,"keyframe":{}},{"node":2,"keyframe":{"scale":[1,1,1]}},{"node":3,"keyframe":{"scale":[1,1,1]}},{"node":5,"keyframe":{"rotation":[0,0,0]}},{"node":6,"keyframe":{"rotation":[0,0,0]}}]},{"nodeKeyframePairs":[{"node":8,"keyframe":{}},{"node":9,"keyframe":{}},{"node":11,"keyframe":{}},{"node":10,"keyframe":{}},{"node":2,"keyframe":{"scale":[1,0.5,1]}},{"node":3,"keyframe":{"scale":[1,0.5,1]}},{"node":5,"keyframe":{"rotation":[0,0,5]}},{"node":6,"keyframe":{"rotation":[0,0,-5]}}]},{"nodeKeyframePairs":[{"node":8,"keyframe":{}},{"node":9,"keyframe":{}},{"node":11,"keyframe":{}},{"node":10,"keyframe":{}},{"node":2,"keyframe":{"scale":[1,0,1]}},{"node":3,"keyframe":{"scale":[1,0,1]}},{"node":5,"keyframe":{"rotation":[0,0,15]}},{"node":6,"keyframe":{"rotation":[0,0,-15]}}]},{"nodeKeyframePairs":[{"node":8,"keyframe":{}},{"node":9,"keyframe":{}},{"node":11,"keyframe":{}},{"node":10,"keyframe":{}},{"node":2,"keyframe":{"scale":[1,0.5,1]}},{"node":3,"keyframe":{"scale":[1,0.5,1]}},{"node":5,"keyframe":{"rotation":[0,0,5]}},{"node":6,"keyframe":{"rotation":[0,0,-5]}}]},{"nodeKeyframePairs":[{"node":8,"keyframe":{}},{"node":9,"keyframe":{}},{"node":11,"keyframe":{}},{"node":10,"keyframe":{}},{"node":2,"keyframe":{"scale":[1,1,1]}},{"node":3,"keyframe":{"scale":[1,1,1]}},{"node":5,"keyframe":{"rotation":[0,0,0]}},{"node":6,"keyframe":{"rotation":[0,0,0]}}]}]}],"scene":0}