Dual quaternion skinning, mirrors.
This commit is contained in:
parent
8e3c2e0c74
commit
f3554b4de8
BIN
Assets/hosek/hosek_radiance.hdr
Normal file
BIN
Assets/hosek/hosek_radiance.hdr
Normal file
Binary file not shown.
BIN
Assets/hosek/hosek_radiance_0.hdr
Normal file
BIN
Assets/hosek/hosek_radiance_0.hdr
Normal file
Binary file not shown.
BIN
Assets/hosek/hosek_radiance_1.hdr
Normal file
BIN
Assets/hosek/hosek_radiance_1.hdr
Normal file
Binary file not shown.
BIN
Assets/hosek/hosek_radiance_2.hdr
Normal file
BIN
Assets/hosek/hosek_radiance_2.hdr
Normal file
Binary file not shown.
BIN
Assets/hosek/hosek_radiance_3.hdr
Normal file
BIN
Assets/hosek/hosek_radiance_3.hdr
Normal file
Binary file not shown.
BIN
Assets/hosek/hosek_radiance_4.hdr
Normal file
BIN
Assets/hosek/hosek_radiance_4.hdr
Normal file
Binary file not shown.
BIN
Assets/hosek/hosek_radiance_5.hdr
Normal file
BIN
Assets/hosek/hosek_radiance_5.hdr
Normal file
Binary file not shown.
BIN
Assets/hosek/hosek_radiance_6.hdr
Normal file
BIN
Assets/hosek/hosek_radiance_6.hdr
Normal file
Binary file not shown.
BIN
Assets/hosek/hosek_radiance_7.hdr
Normal file
BIN
Assets/hosek/hosek_radiance_7.hdr
Normal file
Binary file not shown.
|
@ -1,3 +0,0 @@
|
|||
package armory;
|
||||
|
||||
typedef Root = iron.Root;
|
|
@ -1,53 +1,3 @@
|
|||
package armory;
|
||||
|
||||
import iron.App;
|
||||
import iron.Root;
|
||||
import iron.object.Object;
|
||||
import iron.object.CameraObject;
|
||||
import iron.data.SceneFormat;
|
||||
import iron.data.Data;
|
||||
import armory.trait.internal.PhysicsWorld;
|
||||
|
||||
class Scene {
|
||||
|
||||
var cam:CameraObject;
|
||||
|
||||
public static var physics:PhysicsWorld;
|
||||
|
||||
public function new(sceneName:String) {
|
||||
|
||||
// Startup scene
|
||||
var sceneObject = Root.addScene(sceneName);
|
||||
|
||||
if (Root.cameras.length == 0) {
|
||||
trace('No camera found for scene "$sceneName"!');
|
||||
return;
|
||||
}
|
||||
cam = Root.cameras[0];
|
||||
|
||||
// Attach world to camera for now
|
||||
var raw:TSceneFormat = Data.getSceneRaw(sceneName);
|
||||
cam.world = Data.getWorld(sceneName, raw.world_ref);
|
||||
|
||||
// Physics
|
||||
physics = new PhysicsWorld(raw.gravity);
|
||||
sceneObject.addTrait(physics);
|
||||
|
||||
App.notifyOnRender(render);
|
||||
|
||||
// Experimental scene reloading
|
||||
// App.notifyOnUpdate(function() {
|
||||
// if (iron.sys.Input.released) {
|
||||
// // kha.Assets.loadBlob(sceneName + '_arm', function(b:kha.Blob) {
|
||||
// iron.App.reset();
|
||||
// iron.data.Data.clearSceneData();
|
||||
// new iron.App(armory.Root);
|
||||
// // });
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
function render(g:kha.graphics4.Graphics) {
|
||||
cam.renderFrame(g, Root.root, Root.lamps);
|
||||
}
|
||||
}
|
||||
typedef Scene = iron.Scene;
|
||||
|
|
|
@ -17,7 +17,7 @@ class PickerNode extends Node {
|
|||
}
|
||||
|
||||
function init() {
|
||||
target = iron.Root.root.getChild(property0);
|
||||
target = iron.Scene.active.getChild(property0);
|
||||
}
|
||||
|
||||
public static function create(_property0:String):PickerNode {
|
||||
|
|
|
@ -128,7 +128,7 @@ class HosekWilkie {
|
|||
|
||||
// Extract direction from lamp
|
||||
// var mat = iron.data.Data.getMaterial("World_material", "World_material").data;
|
||||
// var lamp = iron.Root.lamps[0];
|
||||
// var lamp = iron.Scene.active.lamps[0];
|
||||
// var ltr = lamp.transform;
|
||||
// var lf = ltr.matrix.look2();
|
||||
// lamp.data.data.strength = 3.3 - Math.abs(ltr.absy()) / 45;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package armory.trait;
|
||||
|
||||
import iron.Trait;
|
||||
import iron.Root;
|
||||
import iron.sys.Input;
|
||||
import iron.object.CameraObject;
|
||||
import iron.math.Vec4;
|
||||
|
@ -24,7 +23,7 @@ class ArcBallCamera extends Trait {
|
|||
}
|
||||
|
||||
function init() {
|
||||
camera = Root.cameras[0];
|
||||
camera = cast(object, CameraObject);
|
||||
|
||||
var r = camera.transform.rot;
|
||||
var q = new Quat(r.x, r.y, r.z, r.w);
|
||||
|
|
|
@ -36,7 +36,7 @@ class FirstPersonController extends Trait {
|
|||
function init() {
|
||||
transform = object.transform;
|
||||
body = object.getTrait(RigidBody);
|
||||
camera = iron.Root.cameras[0];
|
||||
camera = cast(object, CameraObject);
|
||||
}
|
||||
|
||||
function onDown(key: kha.Key, char: String) {
|
||||
|
|
23
Sources/armory/trait/MirrorTexture.hx
Normal file
23
Sources/armory/trait/MirrorTexture.hx
Normal file
|
@ -0,0 +1,23 @@
|
|||
package armory.trait;
|
||||
|
||||
import iron.Trait;
|
||||
import iron.object.MeshObject;
|
||||
|
||||
class MirrorTexture extends Trait {
|
||||
|
||||
var cameraName:String;
|
||||
|
||||
public function new(cameraName:String) {
|
||||
super();
|
||||
|
||||
this.cameraName = cameraName;
|
||||
notifyOnInit(init);
|
||||
}
|
||||
|
||||
function init() {
|
||||
var image = iron.Scene.active.getCamera(cameraName).data.mirror;
|
||||
|
||||
var o = cast(object, iron.object.MeshObject);
|
||||
o.materials[0].contexts[0].textures[0] = image; // Override diffuse texture
|
||||
}
|
||||
}
|
|
@ -31,7 +31,7 @@ class PhysicsDrag extends Trait {
|
|||
}
|
||||
|
||||
function init() {
|
||||
physics = armory.Scene.physics;
|
||||
physics = armory.trait.internal.PhysicsWorld.active;
|
||||
}
|
||||
|
||||
function update() {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package armory.trait;
|
||||
|
||||
import iron.Trait;
|
||||
import iron.Root;
|
||||
|
||||
class SceneInstance extends Trait {
|
||||
|
||||
|
@ -9,7 +8,7 @@ class SceneInstance extends Trait {
|
|||
super();
|
||||
|
||||
notifyOnInit(function() {
|
||||
Root.addScene(sceneName, object);
|
||||
iron.Scene.active.addScene(sceneName, object);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,12 +67,12 @@ class VehicleBody extends Trait {
|
|||
}
|
||||
|
||||
function init() {
|
||||
physics = armory.Scene.physics;
|
||||
physics = armory.trait.internal.PhysicsWorld.active;
|
||||
transform = object.transform;
|
||||
camera = iron.Root.cameras[0];
|
||||
camera = iron.Scene.active.camera;
|
||||
|
||||
for (n in wheelNames) {
|
||||
wheels.push(iron.Root.root.getChild(n));
|
||||
wheels.push(iron.Scene.active.root.getChild(n));
|
||||
}
|
||||
|
||||
var rightIndex = 0;
|
||||
|
|
|
@ -2,7 +2,6 @@ package armory.trait;
|
|||
|
||||
import kha.Key;
|
||||
import iron.Trait;
|
||||
import iron.Root;
|
||||
import iron.sys.Input;
|
||||
import iron.sys.Time;
|
||||
import iron.object.CameraObject;
|
||||
|
@ -39,7 +38,7 @@ class WalkNavigation extends Trait {
|
|||
}
|
||||
|
||||
function init() {
|
||||
camera = Root.cameras[0];
|
||||
camera = cast(object, CameraObject);
|
||||
}
|
||||
|
||||
function update() {
|
||||
|
|
|
@ -11,8 +11,9 @@ class Animation extends Trait {
|
|||
var speeds:Array<Float>;
|
||||
var loops:Array<Bool>;
|
||||
var reflects:Array<Bool>;
|
||||
static var maxBones:Int;
|
||||
|
||||
public function new(startTrack:String, names:Array<String>, starts:Array<Int>, ends:Array<Int>, speeds:Array<Float>, loops:Array<Bool>, reflects:Array<Bool>) {
|
||||
public function new(startTrack:String, names:Array<String>, starts:Array<Int>, ends:Array<Int>, speeds:Array<Float>, loops:Array<Bool>, reflects:Array<Bool>, _maxBones:Int) {
|
||||
super();
|
||||
|
||||
this.startTrack = startTrack;
|
||||
|
@ -22,13 +23,14 @@ class Animation extends Trait {
|
|||
this.speeds = speeds;
|
||||
this.loops = loops;
|
||||
this.reflects = reflects;
|
||||
maxBones = _maxBones;
|
||||
|
||||
notifyOnAdd(add);
|
||||
notifyOnUpdate(update);
|
||||
}
|
||||
|
||||
function add() {
|
||||
object.setupAnimation(startTrack, names, starts, ends, speeds, loops, reflects);
|
||||
object.setupAnimation(startTrack, names, starts, ends, speeds, loops, reflects, maxBones);
|
||||
}
|
||||
|
||||
function update() {
|
||||
|
|
|
@ -77,7 +77,7 @@ class Console extends Trait {
|
|||
}
|
||||
ui.separator();
|
||||
if (ui.node(Id.node(), "Inspector", 0, false)) {
|
||||
for (o in iron.Root.meshes) {
|
||||
for (o in iron.Scene.active.meshes) {
|
||||
ui.text(o.name + " (" + Std.int(o.transform.absx() * 100) / 100 + ", " + Std.int(o.transform.absy() * 100) / 100 + ", " + Std.int(o.transform.absz() * 100) / 100 + ")");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ class JSScriptAPI {
|
|||
class JSScriptAPI {
|
||||
|
||||
public static var App = iron.App;
|
||||
public static var Root = iron.Root;
|
||||
public static var Scene = iron.Scene;
|
||||
public static var Time = iron.sys.Time;
|
||||
public static var Object = iron.object.Object;
|
||||
public static var Data = iron.data.Data;
|
||||
|
|
|
@ -3,7 +3,6 @@ package armory.trait.internal;
|
|||
import iron.math.Mat4;
|
||||
import iron.math.Vec4;
|
||||
import iron.Trait;
|
||||
import iron.Root;
|
||||
import iron.object.Transform;
|
||||
import iron.object.MeshObject;
|
||||
import iron.data.Data;
|
||||
|
@ -83,7 +82,7 @@ class PathTracer extends Trait {
|
|||
transformMap = new Map();
|
||||
var sphereNum = 0;
|
||||
var cubeNum = 0;
|
||||
for (n in Root.meshes) {
|
||||
for (n in iron.Scene.active.meshes) {
|
||||
if (n.name.split(".")[0] == "Sphere") {
|
||||
context.raw.bind_constants.push(
|
||||
{
|
||||
|
@ -144,7 +143,7 @@ class PathTracer extends Trait {
|
|||
}
|
||||
|
||||
function update() {
|
||||
var camera = Root.cameras[0];
|
||||
var camera = iron.Scene.active.camera;
|
||||
var eye = camera.transform.loc;
|
||||
|
||||
// var jitter = Mat4.identity();
|
||||
|
|
|
@ -19,6 +19,8 @@ class ContactPair {
|
|||
|
||||
class PhysicsWorld extends Trait {
|
||||
|
||||
public static var active:PhysicsWorld;
|
||||
|
||||
#if (!WITH_PHYSICS)
|
||||
public function new(gravity:Array<Float> = null) { super(); }
|
||||
#else
|
||||
|
@ -39,6 +41,8 @@ class PhysicsWorld extends Trait {
|
|||
public function new(gravity:Array<Float> = null) {
|
||||
super();
|
||||
|
||||
active = this;
|
||||
|
||||
rbMap = new Map();
|
||||
|
||||
//var min = BtVector3.create(-100, -100, -100);
|
||||
|
@ -172,12 +176,12 @@ class PhysicsWorld extends Trait {
|
|||
}
|
||||
|
||||
public function getRayFrom():BtVector3Pointer {
|
||||
var camera = iron.Root.cameras[0];
|
||||
var camera = iron.Scene.active.camera;
|
||||
return BtVector3.create(camera.transform.loc.x, camera.transform.loc.y, camera.transform.loc.z);
|
||||
}
|
||||
|
||||
public function getRayTo(inputX:Float, inputY:Float):BtVector3Pointer {
|
||||
var camera = iron.Root.cameras[0];
|
||||
var camera = iron.Scene.active.camera;
|
||||
var start = new Vec4();
|
||||
var end = new Vec4();
|
||||
RayCaster.getDirection(start, end, inputX, inputY, camera);
|
||||
|
|
|
@ -52,7 +52,7 @@ class RigidBody extends Trait {
|
|||
|
||||
public function init() {
|
||||
transform = object.transform;
|
||||
physics = armory.Scene.physics;
|
||||
physics = armory.trait.internal.PhysicsWorld.active;
|
||||
|
||||
if (bodyCreated) return;
|
||||
bodyCreated = true;
|
||||
|
|
Binary file not shown.
|
@ -561,7 +561,7 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
|
||||
return unifiedVertexArray
|
||||
|
||||
def ExportBone(self, armature, bone, scene, o):
|
||||
def ExportBone(self, armature, bone, scene, o, action):
|
||||
bobjectRef = self.bobjectArray.get(bone)
|
||||
|
||||
if (bobjectRef):
|
||||
|
@ -572,12 +572,12 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
#if (name != ""):
|
||||
# o.name = name
|
||||
|
||||
self.ExportBoneTransform(armature, bone, scene, o)
|
||||
self.ExportBoneTransform(armature, bone, scene, o, action)
|
||||
|
||||
o['objects'] = [] # TODO
|
||||
for subbobject in bone.children:
|
||||
so = {}
|
||||
self.ExportBone(armature, subbobject, scene, so)
|
||||
self.ExportBone(armature, subbobject, scene, so, action)
|
||||
o['objects'].append(so)
|
||||
|
||||
# Export any ordinary objects that are parented to this bone
|
||||
|
@ -634,15 +634,28 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
|
||||
scene.frame_set(currentFrame, currentSubframe)
|
||||
|
||||
def ExportBoneSampledAnimation(self, poseBone, scene, o):
|
||||
def get_action_framerange(self, action):
|
||||
# TODO: experimental
|
||||
begin_frame = int(action.frame_range[0])
|
||||
end_frame = int(action.frame_range[1])
|
||||
if self.beginFrame > begin_frame: # Cap frames to timeline bounds
|
||||
begin_frame = self.beginFrame
|
||||
if self.endFrame > end_frame:
|
||||
end_frame = self.endFrame
|
||||
return begin_frame, end_frame
|
||||
|
||||
def ExportBoneSampledAnimation(self, poseBone, scene, o, action):
|
||||
# This function exports bone animation as full 4x4 matrices for each frame.
|
||||
currentFrame = scene.frame_current
|
||||
currentSubframe = scene.frame_subframe
|
||||
|
||||
# Frame range
|
||||
begin_frame, end_frame = self.get_action_framerange(action)
|
||||
|
||||
animationFlag = False
|
||||
m1 = poseBone.matrix.copy()
|
||||
|
||||
for i in range(self.beginFrame, self.endFrame):
|
||||
for i in range(begin_frame, end_frame):
|
||||
scene.frame_set(i)
|
||||
m2 = poseBone.matrix
|
||||
if (ArmoryExporter.MatricesDifferent(m1, m2)):
|
||||
|
@ -656,28 +669,28 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
tracko['time'] = {}
|
||||
tracko['time']['values'] = []
|
||||
|
||||
for i in range(self.beginFrame, self.endFrame):
|
||||
tracko['time']['values'].append(((i - self.beginFrame) * self.frameTime))
|
||||
for i in range(begin_frame, end_frame):
|
||||
tracko['time']['values'].append(((i - begin_frame) * self.frameTime))
|
||||
|
||||
tracko['time']['values'].append((self.endFrame * self.frameTime))
|
||||
tracko['time']['values'].append((end_frame * self.frameTime))
|
||||
|
||||
tracko['value'] = {}
|
||||
tracko['value']['values'] = []
|
||||
|
||||
parent = poseBone.parent
|
||||
if (parent):
|
||||
for i in range(self.beginFrame, self.endFrame):
|
||||
for i in range(begin_frame, end_frame):
|
||||
scene.frame_set(i)
|
||||
tracko['value']['values'].append(self.WriteMatrix(parent.matrix.inverted() * poseBone.matrix))
|
||||
|
||||
scene.frame_set(self.endFrame)
|
||||
scene.frame_set(end_frame)
|
||||
tracko['value']['values'].append(self.WriteMatrix(parent.matrix.inverted() * poseBone.matrix))
|
||||
else:
|
||||
for i in range(self.beginFrame, self.endFrame):
|
||||
for i in range(begin_frame, end_frame):
|
||||
scene.frame_set(i)
|
||||
tracko['value']['values'].append(self.WriteMatrix(poseBone.matrix))
|
||||
|
||||
scene.frame_set(self.endFrame)
|
||||
scene.frame_set(end_frame)
|
||||
tracko['value']['values'].append(self.WriteMatrix(poseBone.matrix))
|
||||
o['animation']['tracks'] = [tracko]
|
||||
|
||||
|
@ -1325,7 +1338,7 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
# If an object is used as a bone, then we force its type to be a bone.
|
||||
boneRef[1]["objectType"] = kNodeTypeBone
|
||||
|
||||
def ExportBoneTransform(self, armature, bone, scene, o):
|
||||
def ExportBoneTransform(self, armature, bone, scene, o, action):
|
||||
curveArray = self.CollectBoneAnimation(armature, bone.name)
|
||||
animation = ((len(curveArray) != 0) or (ArmoryExporter.sampleAnimationFlag))
|
||||
|
||||
|
@ -1341,7 +1354,6 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
if (parentPoseBone):
|
||||
transform = parentPoseBone.matrix.inverted() * transform
|
||||
|
||||
|
||||
o['transform'] = {}
|
||||
|
||||
#if (animation):
|
||||
|
@ -1350,7 +1362,7 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
o['transform']['values'] = self.WriteMatrix(transform)
|
||||
|
||||
if ((animation) and (poseBone)):
|
||||
self.ExportBoneSampledAnimation(poseBone, scene, o)
|
||||
self.ExportBoneSampledAnimation(poseBone, scene, o, action)
|
||||
|
||||
def ExportMaterialRef(self, material, index, o):
|
||||
if material == None:
|
||||
|
@ -1475,7 +1487,7 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
self.ExportObjectTransform(bobject, scene, o)
|
||||
|
||||
# Viewport Camera - overwrite active camera matrix with viewport matrix
|
||||
if type == kNodeTypeCamera and bpy.data.worlds[0].ArmPlayViewportCamera:
|
||||
if type == kNodeTypeCamera and bpy.data.worlds[0].ArmPlayViewportCamera and bobject.name == self.scene.camera.name:
|
||||
viewport_matrix = self.get_viewport_view_matrix()
|
||||
if viewport_matrix != None:
|
||||
o['transform']['values'] = self.WriteMatrix(viewport_matrix.inverted())
|
||||
|
@ -1483,29 +1495,41 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
o['local_transform_only'] = True
|
||||
|
||||
if (bobject.type == "ARMATURE"):
|
||||
skeleton = bobject.data # Armature data
|
||||
if (skeleton):
|
||||
armatureid = utils.safe_filename(skeleton.name)
|
||||
o['bones_ref'] = 'bones_' + armatureid
|
||||
armdata = bobject.data # Armature data
|
||||
if (armdata):
|
||||
# Reference start action
|
||||
if bobject.edit_actions_prop:
|
||||
action = bpy.data.actions[bobject.start_action_name_prop]
|
||||
else: # Use default
|
||||
action = bobject.animation_data.action
|
||||
armatureid = utils.safe_filename(armdata.name)
|
||||
o['bones_ref'] = 'bones_' + armatureid + '_' + action.name
|
||||
|
||||
# TODO: use option_mesh_per_file
|
||||
fp = self.get_meshes_file_path(o['bones_ref'])
|
||||
assets.add(fp)
|
||||
# Write bones
|
||||
if armdata.edit_actions:
|
||||
export_actions = []
|
||||
for t in my_actiontraitlist:
|
||||
export_actions.append(t.name)
|
||||
else: # Use default
|
||||
export_actions = [action]
|
||||
|
||||
if bobject.data.armature_cached == False or not os.path.exists(fp):
|
||||
bones = []
|
||||
for bone in skeleton.bones:
|
||||
if (not bone.parent):
|
||||
boneo = {}
|
||||
self.ExportBone(bobject, bone, scene, boneo)
|
||||
#o.objects.append(boneo)
|
||||
bones.append(boneo)
|
||||
|
||||
# Save bones separately
|
||||
bones_obj = {}
|
||||
bones_obj['objects'] = bones
|
||||
utils.write_arm(fp, bones_obj)
|
||||
bobject.data.armature_cached = True
|
||||
for action in export_actions:
|
||||
armdata.animation_data.action = action
|
||||
fp = self.get_meshes_file_path('bones_' + armatureid + '_' + action.name)
|
||||
assets.add(fp)
|
||||
if armdata.armature_cached == False or not os.path.exists(fp):
|
||||
bones = []
|
||||
for bone in armdata.bones:
|
||||
if (not bone.parent):
|
||||
boneo = {}
|
||||
self.ExportBone(bobject, bone, scene, boneo, action)
|
||||
#o.objects.append(boneo)
|
||||
bones.append(boneo)
|
||||
# Save bones separately
|
||||
bones_obj = {}
|
||||
bones_obj['objects'] = bones
|
||||
utils.write_arm(fp, bones_obj)
|
||||
armdata.armature_cached = True
|
||||
|
||||
if (parento == None):
|
||||
self.output['objects'].append(o)
|
||||
|
@ -1544,9 +1568,6 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
boneArray = armature.data.bones
|
||||
boneCount = len(boneArray)
|
||||
|
||||
#self.IndentWrite(B"ref\t\t\t// ")
|
||||
#self.WriteInt(boneCount)
|
||||
|
||||
for i in range(boneCount):
|
||||
boneRef = self.FindNode(boneArray[i].name)
|
||||
if (boneRef):
|
||||
|
@ -1554,16 +1575,12 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
else:
|
||||
oskel['bone_ref_array'].append("null")
|
||||
|
||||
# Write the bind pose transform array.
|
||||
# Write the bind pose transform array
|
||||
oskel['transforms'] = []
|
||||
|
||||
#self.IndentWrite(B"float[16]\t// ")
|
||||
#self.WriteInt(boneCount)
|
||||
|
||||
for i in range(boneCount):
|
||||
oskel['transforms'].append(self.WriteMatrix(armature.matrix_world * boneArray[i].matrix_local))
|
||||
|
||||
# Export the per-vertex bone influence data.
|
||||
# Export the per-vertex bone influence data
|
||||
groupRemap = []
|
||||
|
||||
for group in bobject.vertex_groups:
|
||||
|
@ -2149,8 +2166,23 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
o['type'] = 'perspective'
|
||||
else:
|
||||
o['type'] = 'orthographic'
|
||||
|
||||
if objref.is_mirror:
|
||||
o['is_mirror'] = True
|
||||
o['mirror_resolution_x'] = int(objref.mirror_resolution_x)
|
||||
o['mirror_resolution_y'] = int(objref.mirror_resolution_y)
|
||||
|
||||
o['frustum_culling'] = objref.frustum_culling
|
||||
o['pipeline'] = objref.pipeline_path + '/' + objref.pipeline_path # Same file name and id
|
||||
|
||||
self.cb_export_camera(objref, o)
|
||||
if 'Background' in bpy.data.worlds[0].node_tree.nodes: # TODO: parse node tree
|
||||
background_node = bpy.data.worlds[0].node_tree.nodes['Background']
|
||||
col = background_node.inputs[0].default_value
|
||||
strength = background_node.inputs[1].default_value
|
||||
o['clear_color'] = [col[0] * strength, col[1] * strength, col[2] * strength, col[3]]
|
||||
else:
|
||||
o['clear_color'] = [0.0, 0.0, 0.0, 1.0]
|
||||
|
||||
self.output['camera_datas'].append(o)
|
||||
|
||||
def ExportSpeaker(self, objectRef):
|
||||
|
@ -2286,14 +2318,14 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
|
||||
self.output = {}
|
||||
|
||||
scene = context.scene
|
||||
originalFrame = scene.frame_current
|
||||
originalSubframe = scene.frame_subframe
|
||||
self.scene = context.scene
|
||||
originalFrame = self.scene.frame_current
|
||||
originalSubframe = self.scene.frame_subframe
|
||||
self.restoreFrame = False
|
||||
|
||||
self.beginFrame = scene.frame_start
|
||||
self.endFrame = scene.frame_end
|
||||
self.frameTime = 1.0 / (scene.render.fps_base * scene.render.fps)
|
||||
self.beginFrame = self.scene.frame_start
|
||||
self.endFrame = self.scene.frame_end
|
||||
self.frameTime = 1.0 / (self.scene.render.fps_base * self.scene.render.fps)
|
||||
|
||||
self.bobjectArray = {}
|
||||
self.meshArray = {}
|
||||
|
@ -2322,18 +2354,21 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
|
||||
self.cb_preprocess()
|
||||
|
||||
for bobject in scene.objects:
|
||||
for bobject in self.scene.objects:
|
||||
if (not bobject.parent):
|
||||
self.ProcessBObject(bobject)
|
||||
|
||||
self.ProcessSkinnedMeshes()
|
||||
|
||||
self.output['name'] = self.scene.name
|
||||
self.output['objects'] = []
|
||||
for object in scene.objects:
|
||||
for object in self.scene.objects:
|
||||
if (not object.parent):
|
||||
self.ExportObject(object, scene)
|
||||
self.ExportObject(object, self.scene)
|
||||
|
||||
if not ArmoryExporter.option_mesh_only:
|
||||
self.output['camera_ref'] = self.scene.camera.name
|
||||
|
||||
self.output['material_datas'] = []
|
||||
self.ExportMaterials()
|
||||
|
||||
|
@ -2342,16 +2377,16 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
|
||||
self.output['world_datas'] = []
|
||||
self.ExportWorlds()
|
||||
self.output['world_ref'] = scene.world.name
|
||||
self.output['world_ref'] = self.scene.world.name
|
||||
|
||||
self.output['gravity'] = [scene.gravity[0], scene.gravity[1], scene.gravity[2]]
|
||||
self.output['gravity'] = [self.scene.gravity[0], self.scene.gravity[1], self.scene.gravity[2]]
|
||||
|
||||
self.ExportObjects(scene)
|
||||
self.ExportObjects(self.scene)
|
||||
|
||||
self.cb_postprocess()
|
||||
|
||||
if (self.restoreFrame):
|
||||
scene.frame_set(originalFrame, originalSubframe)
|
||||
self.scene.frame_set(originalFrame, originalSubframe)
|
||||
|
||||
# Write .arm
|
||||
utils.write_arm(self.filepath, self.output)
|
||||
|
@ -2471,7 +2506,6 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
break
|
||||
|
||||
def cb_export_object(self, bobject, o, type):
|
||||
#return
|
||||
# Export traits
|
||||
o['traits'] = []
|
||||
for t in bobject.my_traitlist:
|
||||
|
@ -2481,24 +2515,6 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
if t.type_prop == 'Logic Nodes' and t.nodes_name_prop != '':
|
||||
x['type'] = 'Script'
|
||||
x['class_name'] = bpy.data.worlds[0].ArmProjectPackage + '.node.' + utils.safe_filename(t.nodes_name_prop)
|
||||
elif t.type_prop == 'Animation':
|
||||
x['type'] = 'Script'
|
||||
x['class_name'] = 'armory.trait.internal.Animation'
|
||||
names = []
|
||||
starts = []
|
||||
ends = []
|
||||
speeds = []
|
||||
loops = []
|
||||
reflects = []
|
||||
for at in t.my_animationtraitlist:
|
||||
if at.enabled_prop:
|
||||
names.append(at.name)
|
||||
starts.append(at.start_prop)
|
||||
ends.append(at.end_prop)
|
||||
speeds.append(at.speed_prop)
|
||||
loops.append(at.loop_prop)
|
||||
reflects.append(at.reflect_prop)
|
||||
x['parameters'] = [t.start_track_name_prop, names, starts, ends, speeds, loops, reflects]
|
||||
elif t.type_prop == 'JS Script' or t.type_prop == 'Python Script':
|
||||
x['type'] = 'Script'
|
||||
x['class_name'] = 'armory.trait.internal.JSScript'
|
||||
|
@ -2551,7 +2567,37 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
x['parameters'] = []
|
||||
for pt in t.my_paramstraitlist: # Append parameters
|
||||
x['parameters'].append(ast.literal_eval(pt.name))
|
||||
|
||||
o['traits'].append(x)
|
||||
|
||||
# Animation trait
|
||||
if self.is_bone_animation_enabled(bobject) or self.is_object_animation_enabled(bobject):
|
||||
x = {}
|
||||
x['type'] = 'Script'
|
||||
x['class_name'] = 'armory.trait.internal.Animation'
|
||||
if len(bobject.my_cliptraitlist) > 0:
|
||||
# Edit clips enabled
|
||||
names = []
|
||||
starts = []
|
||||
ends = []
|
||||
speeds = []
|
||||
loops = []
|
||||
reflects = []
|
||||
for at in bobject.my_cliptraitlist:
|
||||
if at.enabled_prop:
|
||||
names.append(at.name)
|
||||
starts.append(at.start_prop)
|
||||
ends.append(at.end_prop)
|
||||
speeds.append(at.speed_prop)
|
||||
loops.append(at.loop_prop)
|
||||
reflects.append(at.reflect_prop)
|
||||
x['parameters'] = [bobject.start_track_name_prop, names, starts, ends, speeds, loops, reflects, bpy.data.worlds[0].generate_gpu_skin_max_bones]
|
||||
else:
|
||||
# Export default clip, taking full action
|
||||
if self.is_bone_animation_enabled(bobject):
|
||||
begin_frame, end_frame = self.get_action_framerange(bobject.parent.animation_data.action)
|
||||
else:
|
||||
begin_frame, end_frame = self.get_action_framerange(bobject.animation_data.action)
|
||||
x['parameters'] = ['default', ['default'], [begin_frame], [end_frame], [1.0], [True], [False], bpy.data.worlds[0].generate_gpu_skin_max_bones]
|
||||
o['traits'].append(x)
|
||||
|
||||
# Rigid body trait
|
||||
|
@ -2592,8 +2638,8 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
console_trait['class_name'] = 'armory.trait.internal.Console'
|
||||
console_trait['parameters'] = []
|
||||
o['traits'].append(console_trait)
|
||||
# Viewport camera enabled, attach navigation if enabled
|
||||
if bpy.data.worlds[0].ArmPlayViewportCamera and bpy.data.worlds[0].ArmPlayViewportNavigation == 'Walk':
|
||||
# Viewport camera enabled, attach navigation to active camera if enabled
|
||||
if bobject.name == self.scene.camera.name and bpy.data.worlds[0].ArmPlayViewportCamera and bpy.data.worlds[0].ArmPlayViewportNavigation == 'Walk':
|
||||
navigation_trait = {}
|
||||
navigation_trait['type'] = 'Script'
|
||||
navigation_trait['class_name'] = 'armory.trait.WalkNavigation'
|
||||
|
@ -2613,23 +2659,20 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
self.materialToObjectDict[mat] = [bobject]
|
||||
self.materialToGameObjectDict[mat] = [o]
|
||||
|
||||
def cb_export_camera(self, object, o):
|
||||
#return
|
||||
o['frustum_culling'] = object.frustum_culling
|
||||
o['pipeline'] = object.pipeline_path + '/' + object.pipeline_path # Same file name and id
|
||||
|
||||
if 'Background' in bpy.data.worlds[0].node_tree.nodes: # TODO: parse node tree
|
||||
background_node = bpy.data.worlds[0].node_tree.nodes['Background']
|
||||
col = background_node.inputs[0].default_value
|
||||
strength = background_node.inputs[1].default_value
|
||||
o['clear_color'] = [col[0] * strength, col[1] * strength, col[2] * strength, col[3]]
|
||||
else:
|
||||
o['clear_color'] = [0.0, 0.0, 0.0, 1.0]
|
||||
def is_object_animation_enabled(self, bobject):
|
||||
# Checks if animation is present and enabled
|
||||
if bobject.object_animation_enabled == False or bobject.type == 'ARMATURE' or bobject.type == 'BONE':
|
||||
return False
|
||||
if bobject.animation_data and bobject.animation_data.action:
|
||||
return True
|
||||
return False
|
||||
|
||||
def find_anim_trait(self, ob):
|
||||
# Checks if animation trait is attached
|
||||
for t in ob.my_traitlist:
|
||||
if t.type_prop == 'Animation' and t.enabled_prop == True:
|
||||
def is_bone_animation_enabled(self, bobject):
|
||||
# Checks if animation is present and enabled for parented armature
|
||||
if bobject.parent and bobject.parent.type == 'ARMATURE':
|
||||
if bobject.parent.bone_animation_enabled == False:
|
||||
return False
|
||||
if bobject.parent.animation_data and bobject.parent.animation_data.action:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
@ -2733,7 +2776,7 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
if ob.instanced_children or len(ob.particle_systems) > 0:
|
||||
defs.append('_Instancing')
|
||||
# GPU Skinning
|
||||
if ob.find_armature() and self.find_anim_trait(ob) and bpy.data.worlds[0].generate_gpu_skin == True:
|
||||
if ob.find_armature() and self.is_bone_animation_enabled(ob) and bpy.data.worlds[0].generate_gpu_skin == True:
|
||||
defs.append('_Skinning')
|
||||
# Billboarding
|
||||
if len(ob.constraints) > 0 and ob.constraints[0].target != None and \
|
||||
|
@ -2762,13 +2805,20 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
# Main probe
|
||||
world_generate_radiance = False
|
||||
defs = bpy.data.worlds[0].world_defs
|
||||
if '_EnvTex' in defs: # Radiance only for texture
|
||||
world_generate_radiance = bpy.data.worlds[0].generate_radiance
|
||||
generate_irradiance = True #'_EnvTex' in defs or '_EnvSky' in defs or '_EnvCon' in defs
|
||||
envtex = bpy.data.cameras[0].world_envtex_name.rsplit('.', 1)[0]
|
||||
irrtex = bpy.data.cameras[0].world_envtex_name.rsplit('.', 1)[0]
|
||||
radtex = irrtex
|
||||
|
||||
# Radiance
|
||||
if '_EnvTex' in defs:
|
||||
world_generate_radiance = bpy.data.worlds[0].generate_radiance
|
||||
elif '_EnvSky' in defs and bpy.data.worlds[0].generate_radiance_sky:
|
||||
world_generate_radiance = bpy.data.worlds[0].generate_radiance
|
||||
radtex = 'hosek'
|
||||
|
||||
num_mips = bpy.data.cameras[0].world_envtex_num_mips
|
||||
strength = bpy.data.cameras[0].world_envtex_strength
|
||||
po = self.make_probe('world', envtex, num_mips, strength, 1.0, [0, 0, 0], [0, 0, 0], world_generate_radiance, generate_irradiance)
|
||||
po = self.make_probe('world', irrtex, radtex, num_mips, strength, 1.0, [0, 0, 0], [0, 0, 0], world_generate_radiance, generate_irradiance)
|
||||
o['probes'].append(po)
|
||||
|
||||
if '_EnvSky' in defs:
|
||||
|
@ -2793,17 +2843,17 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
texture_path = '//' + cam.probe_texture
|
||||
cam.probe_num_mips = write_probes.write_probes(texture_path, disable_hdr, cam.probe_num_mips, generate_radiance=generate_radiance)
|
||||
base_name = cam.probe_texture.rsplit('.', 1)[0]
|
||||
po = self.make_probe(cam.name, base_name, cam.probe_num_mips, cam.probe_strength, cam.probe_blending, volume, volume_center, generate_radiance, generate_irradiance)
|
||||
po = self.make_probe(cam.name, base_name, base_name, cam.probe_num_mips, cam.probe_strength, cam.probe_blending, volume, volume_center, generate_radiance, generate_irradiance)
|
||||
o['probes'].append(po)
|
||||
|
||||
def make_probe(self, id, envtex, mipmaps, strength, blending, volume, volume_center, generate_radiance, generate_irradiance):
|
||||
def make_probe(self, id, irrtex, radtex, mipmaps, strength, blending, volume, volume_center, generate_radiance, generate_irradiance):
|
||||
po = {}
|
||||
po['name'] = id
|
||||
if generate_radiance:
|
||||
po['radiance'] = envtex + '_radiance'
|
||||
po['radiance'] = radtex + '_radiance'
|
||||
po['radiance_mipmaps'] = mipmaps
|
||||
if generate_irradiance:
|
||||
po['irradiance'] = envtex + '_irradiance'
|
||||
po['irradiance'] = irrtex + '_irradiance'
|
||||
else:
|
||||
po['irradiance'] = '' # No irradiance data, fallback to default at runtime
|
||||
po['strength'] = strength
|
||||
|
|
|
@ -796,13 +796,19 @@ def buildNodeTrees(shader_references, asset_references, assets_path):
|
|||
# Always include
|
||||
buildNodeTrees.linked_assets.append(buildNodeTrees.assets_path + 'brdf.png')
|
||||
|
||||
# Export selected pipeline
|
||||
node_group = bpy.data.node_groups[bpy.data.cameras[0].pipeline_path]
|
||||
buildNodeTree(node_group, shader_references, asset_references)
|
||||
# Export pipeline for each camera
|
||||
parsed_paths = []
|
||||
for cam in bpy.data.cameras:
|
||||
# if cam.game_export
|
||||
if cam.pipeline_path not in parsed_paths:
|
||||
node_group = bpy.data.node_groups[cam.pipeline_path]
|
||||
buildNodeTree(cam, node_group, shader_references, asset_references)
|
||||
parsed_paths.append(cam.pipeline_path)
|
||||
|
||||
return buildNodeTrees.linked_assets
|
||||
|
||||
def buildNodeTree(node_group, shader_references, asset_references):
|
||||
def buildNodeTree(cam, node_group, shader_references, asset_references):
|
||||
buildNodeTree.cam = cam
|
||||
output = {}
|
||||
dat = {}
|
||||
output['pipeline_datas'] = [dat]
|
||||
|
@ -817,8 +823,8 @@ def buildNodeTree(node_group, shader_references, asset_references):
|
|||
dat['name'] = node_group_name
|
||||
|
||||
# Store main context names
|
||||
dat['mesh_context'] = bpy.data.cameras[0].mesh_context
|
||||
dat['shadows_context'] = bpy.data.cameras[0].shadows_context
|
||||
dat['mesh_context'] = buildNodeTree.cam.mesh_context
|
||||
dat['shadows_context'] = buildNodeTree.cam.shadows_context
|
||||
|
||||
dat['render_targets'], dat['depth_buffers'] = preprocess_pipeline(rn, node_group)
|
||||
dat['stages'] = []
|
||||
|
@ -878,7 +884,7 @@ def make_draw_meshes(stage, node_group, node):
|
|||
# Context
|
||||
context = node.inputs[1].default_value
|
||||
# Store shadowmap size
|
||||
if context == bpy.data.cameras[0].shadows_context:
|
||||
if context == buildNodeTree.cam.shadows_context:
|
||||
bpy.data.worlds[0].shadowmap_size = buildNode.last_set_target_w
|
||||
stage['params'].append(context)
|
||||
# Order
|
||||
|
@ -889,7 +895,7 @@ def make_draw_decals(stage, node_group, node, shader_references, asset_reference
|
|||
stage['command'] = 'draw_decals'
|
||||
context = node.inputs[1].default_value
|
||||
stage['params'].append(context) # Context
|
||||
bpy.data.cameras[0].last_decal_context = context
|
||||
buildNodeTree.cam.last_decal_context = context
|
||||
|
||||
def make_bind_target(stage, node_group, node, constant_name, currentNode=None, target_index=1):
|
||||
if currentNode == None:
|
||||
|
@ -985,7 +991,7 @@ def make_draw_compositor(stage, node_group, node, shader_references, asset_refer
|
|||
if wrd.generate_fog:
|
||||
compositor_defs += '_CompoFog'
|
||||
compo_pos = True
|
||||
if bpy.data.cameras[0].cycles.aperture_size > 0.0:
|
||||
if buildNodeTree.cam.cycles.aperture_size > 0.0:
|
||||
compositor_defs += '_CompoDOF'
|
||||
compo_depth = True
|
||||
if compo_pos:
|
||||
|
@ -1186,7 +1192,7 @@ def buildNode(stages, node, node_group, shader_references, asset_references):
|
|||
stencil_val = None
|
||||
if node.inputs[1].default_value == True:
|
||||
if node.inputs[2].is_linked: # Assume background color node is linked
|
||||
color_val = bpy.data.cameras[0].world_envtex_color
|
||||
color_val = buildNodeTree.cam.world_envtex_color
|
||||
else:
|
||||
color_val = node.inputs[2].default_value
|
||||
if node.inputs[3].default_value == True:
|
||||
|
@ -1237,7 +1243,7 @@ def buildNode(stages, node, node_group, shader_references, asset_references):
|
|||
make_set_target(stage, node_group, node)
|
||||
stages.append(stage)
|
||||
# Bind targets
|
||||
if node.inputs[2].is_linked or node.inputs[3].is_linked:
|
||||
if node.inputs[2].is_linked or node.inputs[3].is_linked or node.inputs[4].is_linked:
|
||||
stage = {}
|
||||
stage['params'] = []
|
||||
buildNode.last_bind_target = stage
|
||||
|
@ -1390,14 +1396,14 @@ def get_root_node(node_group):
|
|||
for n in node_group.nodes:
|
||||
if n.bl_idname == 'BeginNodeType':
|
||||
# Store contexts
|
||||
bpy.data.cameras[0].pipeline_id = n.inputs[0].default_value
|
||||
buildNodeTree.cam.pipeline_id = n.inputs[0].default_value
|
||||
mesh_contexts = n.inputs[1].default_value.split(',')
|
||||
bpy.data.cameras[0].mesh_context = mesh_contexts[0]
|
||||
buildNodeTree.cam.mesh_context = mesh_contexts[0]
|
||||
if len(mesh_contexts) > 1:
|
||||
bpy.data.cameras[0].mesh_context_empty = mesh_contexts[1]
|
||||
bpy.data.cameras[0].shadows_context = n.inputs[2].default_value
|
||||
bpy.data.cameras[0].translucent_context = n.inputs[3].default_value
|
||||
bpy.data.cameras[0].overlay_context = n.inputs[4].default_value
|
||||
buildNodeTree.cam.mesh_context_empty = mesh_contexts[1]
|
||||
buildNodeTree.cam.shadows_context = n.inputs[2].default_value
|
||||
buildNodeTree.cam.translucent_context = n.inputs[3].default_value
|
||||
buildNodeTree.cam.overlay_context = n.inputs[4].default_value
|
||||
if n.inputs[5].default_value == False: # No HDR space lighting, append def
|
||||
bpy.data.worlds[0].world_defs += '_LDR'
|
||||
rn = findNodeByLinkFrom(node_group, n, n.outputs[0])
|
||||
|
@ -1408,16 +1414,16 @@ def preprocess_pipeline(root_node, node_group):
|
|||
render_targets = []
|
||||
depth_buffers = []
|
||||
preprocess_pipeline.velocity_def_added = False
|
||||
bpy.data.cameras[0].pipeline_passes = ''
|
||||
buildNodeTree.cam.pipeline_passes = ''
|
||||
traverse_pipeline(root_node, node_group, render_targets, depth_buffers)
|
||||
return render_targets, depth_buffers
|
||||
|
||||
def traverse_pipeline(node, node_group, render_targets, depth_buffers):
|
||||
# Gather linked draw geometry contexts
|
||||
if node.bl_idname == 'DrawMeshesNodeType':
|
||||
if bpy.data.cameras[0].pipeline_passes != '':
|
||||
bpy.data.cameras[0].pipeline_passes += '_' # Separator
|
||||
bpy.data.cameras[0].pipeline_passes += node.inputs[1].default_value
|
||||
if buildNodeTree.cam.pipeline_passes != '':
|
||||
buildNodeTree.cam.pipeline_passes += '_' # Separator
|
||||
buildNodeTree.cam.pipeline_passes += node.inputs[1].default_value
|
||||
|
||||
# Gather defs from linked nodes
|
||||
if node.bl_idname == 'TAAPassNodeType' or node.bl_idname == 'MotionBlurVelocityPassNodeType' or node.bl_idname == 'SSAOReprojectPassNodeType':
|
||||
|
|
|
@ -77,6 +77,10 @@ def buildNodeTree(world_name, node_group):
|
|||
if wrd.generate_shadows == False:
|
||||
wrd.world_defs += '_NoShadows'
|
||||
|
||||
# Percentage closer soft shadows
|
||||
if wrd.generate_pcss:
|
||||
wrd.world_defs += '_PCSS'
|
||||
|
||||
# Enable probes
|
||||
for cam in bpy.data.cameras:
|
||||
if cam.is_probe:
|
||||
|
@ -166,7 +170,7 @@ def parse_color(node_group, node, context, envmap_strength_const):
|
|||
# Append LDR define
|
||||
if disable_hdr:
|
||||
bpy.data.worlds[0].world_defs += '_EnvLDR'
|
||||
# Append radiance degine
|
||||
# Append radiance define
|
||||
if generate_radiance:
|
||||
bpy.data.worlds[0].world_defs += '_Rad'
|
||||
|
||||
|
@ -191,5 +195,18 @@ def parse_color(node_group, node, context, envmap_strength_const):
|
|||
|
||||
write_probes.write_sky_irradiance(base_name)
|
||||
|
||||
# Radiance
|
||||
if bpy.data.worlds[0].generate_radiance_sky and bpy.data.worlds[0].generate_radiance:
|
||||
bpy.data.worlds[0].world_defs += '_Rad'
|
||||
|
||||
user_preferences = bpy.context.user_preferences
|
||||
addon_prefs = user_preferences.addons['armory'].preferences
|
||||
sdk_path = addon_prefs.sdk_path
|
||||
assets.add(sdk_path + 'armory/Assets/hosek/hosek_radiance.hdr')
|
||||
for i in range(0, 8):
|
||||
assets.add(sdk_path + 'armory/Assets/hosek/hosek_radiance_' + str(i) + '.hdr')
|
||||
|
||||
bpy.data.cameras[0].world_envtex_num_mips = 8
|
||||
|
||||
# Adjust strength to match Cycles
|
||||
envmap_strength_const['float'] *= 0.25
|
||||
|
|
107
blender/props.py
107
blender/props.py
|
@ -5,6 +5,8 @@ import json
|
|||
import nodes_renderpath
|
||||
from bpy.types import Menu, Panel, UIList
|
||||
from bpy.props import *
|
||||
from traits_clip import *
|
||||
from traits_action import *
|
||||
import utils
|
||||
|
||||
def on_scene_update(context):
|
||||
|
@ -15,10 +17,6 @@ def on_scene_update(context):
|
|||
elif edit_obj.type == 'ARMATURE':
|
||||
edit_obj.data.armature_cached = False
|
||||
|
||||
for text in bpy.data.texts:
|
||||
if text.is_updated:
|
||||
print('ASDASDASDASDASD')
|
||||
|
||||
def invalidate_shader_cache(self, context):
|
||||
# compiled.glsl changed, recompile all shaders next time
|
||||
fp = utils.get_fp()
|
||||
|
@ -91,6 +89,16 @@ def initProperties():
|
|||
bpy.types.Object.override_material_name = bpy.props.StringProperty(name="Name", default="")
|
||||
bpy.types.Object.game_export = bpy.props.BoolProperty(name="Export", default=True)
|
||||
bpy.types.Object.spawn = bpy.props.BoolProperty(name="Spawn", description="Auto-add this object when creating scene", default=True)
|
||||
# - Clips
|
||||
bpy.types.Object.bone_animation_enabled = bpy.props.BoolProperty(name="Bone Animation", default=True)
|
||||
bpy.types.Object.object_animation_enabled = bpy.props.BoolProperty(name="Object Animation", default=True)
|
||||
bpy.types.Object.edit_tracks_prop = bpy.props.BoolProperty(name="Edit Clips", description="A name for this item", default=False)
|
||||
bpy.types.Object.start_track_name_prop = bpy.props.StringProperty(name="Start Track", description="A name for this item", default="")
|
||||
bpy.types.Object.my_cliptraitlist = bpy.props.CollectionProperty(type=ListClipTraitItem)
|
||||
bpy.types.Object.cliptraitlist_index = bpy.props.IntProperty(name="Index for my_list", default=0)
|
||||
# - Actions
|
||||
bpy.types.Object.edit_actions_prop = bpy.props.BoolProperty(name="Edit Actions", description="A name for this item", default=False)
|
||||
bpy.types.Object.start_action_name_prop = bpy.props.StringProperty(name="Start Action", description="A name for this item", default="")
|
||||
# For mesh
|
||||
bpy.types.Mesh.mesh_cached = bpy.props.BoolProperty(name="Mesh Cached", default=False)
|
||||
bpy.types.Mesh.mesh_cached_verts = bpy.props.IntProperty(name="Last Verts", default=0)
|
||||
|
@ -99,6 +107,10 @@ def initProperties():
|
|||
bpy.types.Curve.static_usage = bpy.props.BoolProperty(name="Static Usage", default=True)
|
||||
# For armature
|
||||
bpy.types.Armature.armature_cached = bpy.props.BoolProperty(name="Armature Cached", default=False)
|
||||
# Actions
|
||||
bpy.types.Armature.edit_actions = bpy.props.BoolProperty(name="Edit Actions", default=False)
|
||||
bpy.types.Armature.my_actiontraitlist = bpy.props.CollectionProperty(type=ListActionTraitItem)
|
||||
bpy.types.Armature.actiontraitlist_index = bpy.props.IntProperty(name="Index for my_list", default=0)
|
||||
# For camera
|
||||
bpy.types.Camera.frustum_culling = bpy.props.BoolProperty(name="Frustum Culling", default=True)
|
||||
bpy.types.Camera.pipeline_path = bpy.props.StringProperty(name="Render Path", default="deferred_path")
|
||||
|
@ -117,6 +129,9 @@ def initProperties():
|
|||
bpy.types.Camera.probe_volume = bpy.props.StringProperty(name="Volume", default="")
|
||||
bpy.types.Camera.probe_strength = bpy.props.FloatProperty(name="Strength", default=1.0)
|
||||
bpy.types.Camera.probe_blending = bpy.props.FloatProperty(name="Blending", default=0.0)
|
||||
bpy.types.Camera.is_mirror = bpy.props.BoolProperty(name="Mirror", default=False)
|
||||
bpy.types.Camera.mirror_resolution_x = bpy.props.FloatProperty(name="X", default=512.0)
|
||||
bpy.types.Camera.mirror_resolution_y = bpy.props.FloatProperty(name="Y", default=256.0)
|
||||
# TODO: move to world
|
||||
bpy.types.Camera.world_envtex_name = bpy.props.StringProperty(name="Environment Texture", default='')
|
||||
bpy.types.Camera.world_envtex_num_mips = bpy.props.IntProperty(name="Number of mips", default=0)
|
||||
|
@ -127,7 +142,8 @@ def initProperties():
|
|||
bpy.types.Camera.world_envtex_ground_albedo = bpy.props.FloatProperty(name="Ground Albedo", default=0.0)
|
||||
bpy.types.Camera.last_decal_context = bpy.props.StringProperty(name="Decal Context", default='')
|
||||
bpy.types.World.world_defs = bpy.props.StringProperty(name="World Shader Defs", default='')
|
||||
bpy.types.World.generate_radiance = bpy.props.BoolProperty(name="Radiance Probes", default=True, update=invalidate_shader_cache)
|
||||
bpy.types.World.generate_radiance = bpy.props.BoolProperty(name="Probe Radiance", default=True, update=invalidate_shader_cache)
|
||||
bpy.types.World.generate_radiance_sky = bpy.props.BoolProperty(name="Sky Radiance", default=False, update=invalidate_shader_cache)
|
||||
bpy.types.World.generate_clouds = bpy.props.BoolProperty(name="Clouds", default=False, update=invalidate_shader_cache)
|
||||
bpy.types.World.generate_clouds_density = bpy.props.FloatProperty(name="Density", default=0.5, min=0.0, max=10.0, update=invalidate_shader_cache)
|
||||
bpy.types.World.generate_clouds_size = bpy.props.FloatProperty(name="Size", default=1.0, min=0.0, max=10.0, update=invalidate_shader_cache)
|
||||
|
@ -167,6 +183,8 @@ def initProperties():
|
|||
bpy.types.World.generate_ssr_falloff_exp = bpy.props.FloatProperty(name="Falloff Exp", default=5.0, update=invalidate_shader_cache)
|
||||
bpy.types.World.generate_ssr_jitter = bpy.props.FloatProperty(name="Jitter", default=0.6, update=invalidate_shader_cache)
|
||||
bpy.types.World.generate_ssr_texture_scale = bpy.props.FloatProperty(name="Texture Scale", default=0.5, min=0.0, max=1.0, update=invalidate_shader_cache)
|
||||
bpy.types.World.generate_pcss = bpy.props.BoolProperty(name="PCSS", description="Percentage Closer Soft Shadows", default=False, update=invalidate_shader_cache)
|
||||
# Compositor
|
||||
bpy.types.World.generate_letterbox = bpy.props.BoolProperty(name="Letterbox", default=False, update=invalidate_shader_cache)
|
||||
bpy.types.World.generate_letterbox_size = bpy.props.FloatProperty(name="Size", default=0.1, update=invalidate_shader_cache)
|
||||
bpy.types.World.generate_grain = bpy.props.BoolProperty(name="Film Grain", default=False, update=invalidate_shader_cache)
|
||||
|
@ -175,6 +193,7 @@ def initProperties():
|
|||
bpy.types.World.generate_fog_color = bpy.props.FloatVectorProperty(name="Color", size=3, subtype='COLOR', default=[0.5, 0.6, 0.7], update=invalidate_shader_cache)
|
||||
bpy.types.World.generate_fog_amounta = bpy.props.FloatProperty(name="Amount A", default=0.25, update=invalidate_shader_cache)
|
||||
bpy.types.World.generate_fog_amountb = bpy.props.FloatProperty(name="Amount B", default=0.5, update=invalidate_shader_cache)
|
||||
# Skin
|
||||
bpy.types.World.generate_gpu_skin = bpy.props.BoolProperty(name="GPU Skinning", default=True, update=invalidate_shader_cache)
|
||||
bpy.types.World.generate_gpu_skin_max_bones = bpy.props.IntProperty(name="Max Bones", default=50, min=1, max=84, update=invalidate_shader_cache)
|
||||
# For material
|
||||
|
@ -246,6 +265,47 @@ class ObjectPropsPanel(bpy.types.Panel):
|
|||
if obj.override_material:
|
||||
layout.prop(obj, 'override_material_name')
|
||||
|
||||
if obj.type == 'ARMATURE':
|
||||
layout.prop(obj, 'bone_animation_enabled')
|
||||
if obj.bone_animation_enabled:
|
||||
layout.prop(obj, 'edit_actions_prop')
|
||||
if obj.edit_actions_prop:
|
||||
layout.prop_search(obj, "start_action_name_prop", obj.data, "my_actiontraitlist", "Start Action")
|
||||
else:
|
||||
layout.prop(obj, 'object_animation_enabled')
|
||||
|
||||
if (obj.type == 'ARMATURE' and obj.bone_animation_enabled) or (obj.type != 'ARMATURE' and obj.object_animation_enabled):
|
||||
layout.prop(obj, 'edit_tracks_prop')
|
||||
if obj.edit_tracks_prop:
|
||||
layout.prop_search(obj, "start_track_name_prop", obj, "my_cliptraitlist", "Start Clip")
|
||||
# Tracks list
|
||||
layout.label("Clips")
|
||||
animrow = layout.row()
|
||||
animrows = 2
|
||||
if len(obj.my_cliptraitlist) > 1:
|
||||
animrows = 4
|
||||
|
||||
row = layout.row()
|
||||
row.template_list("MY_UL_ClipTraitList", "The_List", obj, "my_cliptraitlist", obj, "cliptraitlist_index", rows=animrows)
|
||||
|
||||
col = row.column(align=True)
|
||||
col.operator("my_cliptraitlist.new_item", icon='ZOOMIN', text="")
|
||||
col.operator("my_cliptraitlist.delete_item", icon='ZOOMOUT', text="")
|
||||
|
||||
if len(obj.my_cliptraitlist) > 1:
|
||||
col.separator()
|
||||
col.operator("my_cliptraitlist.move_item", icon='TRIA_UP', text="").direction = 'UP'
|
||||
col.operator("my_cliptraitlist.move_item", icon='TRIA_DOWN', text="").direction = 'DOWN'
|
||||
|
||||
if obj.cliptraitlist_index >= 0 and len(obj.my_cliptraitlist) > 0:
|
||||
animitem = obj.my_cliptraitlist[obj.cliptraitlist_index]
|
||||
row = layout.row()
|
||||
row.prop(animitem, "start_prop")
|
||||
row.prop(animitem, "end_prop")
|
||||
layout.prop(animitem, "speed_prop")
|
||||
layout.prop(animitem, "loop_prop")
|
||||
layout.prop(animitem, "reflect_prop")
|
||||
|
||||
# Menu in modifiers region
|
||||
class ModifiersPropsPanel(bpy.types.Panel):
|
||||
bl_label = "Armory Props"
|
||||
|
@ -281,6 +341,11 @@ class DataPropsPanel(bpy.types.Panel):
|
|||
layout.prop_search(obj.data, "probe_volume", bpy.data, "objects")
|
||||
layout.prop(obj.data, 'probe_strength')
|
||||
layout.prop(obj.data, 'probe_blending')
|
||||
layout.prop(obj.data, 'is_mirror')
|
||||
if obj.data.is_mirror == True:
|
||||
layout.label('Resolution')
|
||||
layout.prop(obj.data, 'mirror_resolution_x')
|
||||
layout.prop(obj.data, 'mirror_resolution_y')
|
||||
layout.prop(obj.data, 'frustum_culling')
|
||||
layout.prop_search(obj.data, "pipeline_path", bpy.data, "node_groups")
|
||||
layout.operator("arm.reimport_paths_menu")
|
||||
|
@ -292,6 +357,33 @@ class DataPropsPanel(bpy.types.Panel):
|
|||
layout.prop(obj.data, 'lamp_clip_end')
|
||||
layout.prop(obj.data, 'lamp_fov')
|
||||
layout.prop(obj.data, 'lamp_shadows_bias')
|
||||
elif obj.type == 'ARMATURE':
|
||||
layout.prop(obj.data, 'edit_actions')
|
||||
if obj.data.edit_actions:
|
||||
# Actions list
|
||||
layout.label("Actions")
|
||||
animrow = layout.row()
|
||||
animrows = 2
|
||||
if len(obj.data.my_actiontraitlist) > 1:
|
||||
animrows = 4
|
||||
|
||||
row = layout.row()
|
||||
row.template_list("MY_UL_ActionTraitList", "The_List", obj.data, "my_actiontraitlist", obj.data, "actiontraitlist_index", rows=animrows)
|
||||
|
||||
col = row.column(align=True)
|
||||
col.operator("my_actiontraitlist.new_item", icon='ZOOMIN', text="")
|
||||
col.operator("my_actiontraitlist.delete_item", icon='ZOOMOUT', text="")
|
||||
|
||||
if len(obj.data.my_actiontraitlist) > 1:
|
||||
col.separator()
|
||||
col.operator("my_actiontraitlist.move_item", icon='TRIA_UP', text="").direction = 'UP'
|
||||
col.operator("my_actiontraitlist.move_item", icon='TRIA_DOWN', text="").direction = 'DOWN'
|
||||
|
||||
if obj.data.actiontraitlist_index >= 0 and len(obj.data.my_actiontraitlist) > 0:
|
||||
item = obj.data.my_actiontraitlist[obj.data.actiontraitlist_index]
|
||||
item.name = item.action_name_prop
|
||||
row = layout.row()
|
||||
row.prop_search(item, "action_name_prop", bpy.data, "actions", "Action")
|
||||
|
||||
class ScenePropsPanel(bpy.types.Panel):
|
||||
bl_label = "Armory Props"
|
||||
|
@ -379,6 +471,8 @@ class WorldPropsPanel(bpy.types.Panel):
|
|||
wrd = bpy.context.world
|
||||
layout.prop(wrd, 'generate_shadows')
|
||||
layout.prop(wrd, 'generate_radiance')
|
||||
if wrd.generate_radiance:
|
||||
layout.prop(wrd, 'generate_radiance_sky')
|
||||
layout.prop(wrd, 'generate_clouds')
|
||||
if wrd.generate_clouds:
|
||||
layout.prop(wrd, 'generate_clouds_density')
|
||||
|
@ -409,7 +503,8 @@ class WorldPropsPanel(bpy.types.Panel):
|
|||
layout.prop(wrd, 'generate_ssr_falloff_exp')
|
||||
layout.prop(wrd, 'generate_ssr_jitter')
|
||||
layout.prop(wrd, 'generate_ssr_texture_scale')
|
||||
|
||||
layout.prop(wrd, 'generate_pcss')
|
||||
|
||||
layout.label('Compositor')
|
||||
layout.prop(wrd, 'generate_letterbox')
|
||||
if wrd.generate_letterbox:
|
||||
|
|
|
@ -3,20 +3,22 @@ import nodes_logic
|
|||
import nodes_renderpath
|
||||
import nodes_world
|
||||
import exporter
|
||||
import traits_animation
|
||||
import traits_action
|
||||
import traits_clip
|
||||
import traits_params
|
||||
import traits
|
||||
import props
|
||||
import lib.drop_to_ground
|
||||
|
||||
def register():
|
||||
traits_action.register()
|
||||
traits_clip.register()
|
||||
props.register()
|
||||
project.register()
|
||||
nodes_logic.register()
|
||||
nodes_renderpath.register()
|
||||
nodes_world.register()
|
||||
exporter.register()
|
||||
traits_animation.register()
|
||||
traits_params.register()
|
||||
traits.register()
|
||||
lib.drop_to_ground.register()
|
||||
|
@ -27,8 +29,9 @@ def unregister():
|
|||
nodes_renderpath.unregister()
|
||||
nodes_world.unregister()
|
||||
exporter.unregister()
|
||||
traits_animation.unregister()
|
||||
traits_params.unregister()
|
||||
traits.unregister()
|
||||
props.unregister()
|
||||
traits_action.unregister()
|
||||
traits_clip.unregister()
|
||||
lib.drop_to_ground.unregister()
|
||||
|
|
|
@ -2,7 +2,6 @@ import shutil
|
|||
import bpy
|
||||
import os
|
||||
import json
|
||||
from traits_animation import *
|
||||
from traits_params import *
|
||||
from bpy.types import Menu, Panel, UIList
|
||||
from bpy.props import *
|
||||
|
@ -27,15 +26,14 @@ class ListTraitItem(bpy.types.PropertyGroup):
|
|||
('Python Script', 'Python Script', 'Python Script'),
|
||||
('JS Script', 'JS Script', 'JS Script'),
|
||||
('Bundled Script', 'Bundled Script', 'Bundled Script'),
|
||||
('Logic Nodes', 'Logic Nodes', 'Logic Nodes'),
|
||||
('Animation', 'Animation', 'Animation')
|
||||
('Logic Nodes', 'Logic Nodes', 'Logic Nodes')
|
||||
],
|
||||
name = "Type")
|
||||
|
||||
data_prop = bpy.props.StringProperty(
|
||||
name="Data",
|
||||
description="A name for this item",
|
||||
default="")
|
||||
# data_prop = bpy.props.StringProperty(
|
||||
# name="Data",
|
||||
# description="A name for this item",
|
||||
# default="")
|
||||
|
||||
class_name_prop = bpy.props.StringProperty(
|
||||
name="Class",
|
||||
|
@ -52,17 +50,9 @@ class ListTraitItem(bpy.types.PropertyGroup):
|
|||
description="A name for this item",
|
||||
default="")
|
||||
|
||||
start_track_name_prop = bpy.props.StringProperty(
|
||||
name="Start Track",
|
||||
description="A name for this item",
|
||||
default="")
|
||||
|
||||
my_paramstraitlist = bpy.props.CollectionProperty(type=ListParamsTraitItem)
|
||||
paramstraitlist_index = bpy.props.IntProperty(name="Index for my_list", default=0)
|
||||
|
||||
my_animationtraitlist = bpy.props.CollectionProperty(type=ListAnimationTraitItem)
|
||||
animationtraitlist_index = bpy.props.IntProperty(name="Index for my_list", default=0)
|
||||
|
||||
class MY_UL_TraitList(bpy.types.UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
|
||||
# We could write some code to decide which icon to use here...
|
||||
|
@ -71,7 +61,7 @@ class MY_UL_TraitList(bpy.types.UIList):
|
|||
# Make sure your code supports all 3 layout types
|
||||
if self.layout_type in {'DEFAULT', 'COMPACT'}:
|
||||
layout.prop(item, "enabled_prop")
|
||||
layout.label(item.name, icon = custom_icon)
|
||||
layout.label(item.name, icon=custom_icon)
|
||||
|
||||
elif self.layout_type in {'GRID'}:
|
||||
layout.alignment = 'CENTER'
|
||||
|
@ -239,7 +229,7 @@ class ToolsTraitsPanel(bpy.types.Panel):
|
|||
col.operator("my_traitlist.move_item", icon='TRIA_DOWN', text="").direction = 'DOWN'
|
||||
|
||||
if obj.traitlist_index >= 0 and len(obj.my_traitlist) > 0:
|
||||
item = obj.my_traitlist[obj.traitlist_index]
|
||||
item = obj.my_traitlist[obj.traitlist_index]
|
||||
# Default props
|
||||
row = layout.row()
|
||||
row.prop(item, "type_prop")
|
||||
|
@ -299,40 +289,6 @@ class ToolsTraitsPanel(bpy.types.Panel):
|
|||
row = layout.row()
|
||||
row.prop_search(item, "nodes_name_prop", bpy.data, "node_groups", "Tree")
|
||||
|
||||
# Animation
|
||||
elif item.type_prop == 'Animation':
|
||||
item.name = item.type_prop
|
||||
row = layout.row()
|
||||
row.prop_search(item, "start_track_name_prop", item, "my_animationtraitlist", "Start Track")
|
||||
# Tracks list
|
||||
layout.label("Tracks")
|
||||
animrow = layout.row()
|
||||
animrows = 2
|
||||
if len(item.my_animationtraitlist) > 1:
|
||||
animrows = 4
|
||||
|
||||
row = layout.row()
|
||||
row.template_list("MY_UL_AnimationTraitList", "The_List", item, "my_animationtraitlist", item, "animationtraitlist_index", rows=animrows)
|
||||
|
||||
col = row.column(align=True)
|
||||
col.operator("my_animationtraitlist.new_item", icon='ZOOMIN', text="")
|
||||
col.operator("my_animationtraitlist.delete_item", icon='ZOOMOUT', text="")
|
||||
|
||||
if len(item.my_animationtraitlist) > 1:
|
||||
col.separator()
|
||||
col.operator("my_animationtraitlist.move_item", icon='TRIA_UP', text="").direction = 'UP'
|
||||
col.operator("my_animationtraitlist.move_item", icon='TRIA_DOWN', text="").direction = 'DOWN'
|
||||
|
||||
if item.animationtraitlist_index >= 0 and len(item.my_animationtraitlist) > 0:
|
||||
animitem = item.my_animationtraitlist[item.animationtraitlist_index]
|
||||
|
||||
row = layout.row()
|
||||
row.prop(animitem, "start_prop")
|
||||
row.prop(animitem, "end_prop")
|
||||
layout.prop(animitem, "speed_prop")
|
||||
layout.prop(animitem, "loop_prop")
|
||||
layout.prop(animitem, "reflect_prop")
|
||||
|
||||
# Registration
|
||||
def register():
|
||||
bpy.utils.register_module(__name__)
|
||||
|
|
131
blender/traits_action.py
Executable file
131
blender/traits_action.py
Executable file
|
@ -0,0 +1,131 @@
|
|||
import shutil
|
||||
import bpy
|
||||
import os
|
||||
import json
|
||||
from bpy.types import Menu, Panel, UIList
|
||||
from bpy.props import *
|
||||
|
||||
class ListActionTraitItem(bpy.types.PropertyGroup):
|
||||
# Group of properties representing an item in the list
|
||||
name = bpy.props.StringProperty(
|
||||
name="Name",
|
||||
description="A name for this item",
|
||||
default="")
|
||||
|
||||
enabled_prop = bpy.props.BoolProperty(
|
||||
name="",
|
||||
description="A name for this item",
|
||||
default=True)
|
||||
|
||||
action_name_prop = bpy.props.StringProperty(
|
||||
name="Action",
|
||||
description="A name for this item",
|
||||
default="")
|
||||
|
||||
class MY_UL_ActionTraitList(bpy.types.UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
|
||||
# We could write some code to decide which icon to use here...
|
||||
custom_icon = 'OBJECT_DATAMODE'
|
||||
|
||||
# Make sure your code supports all 3 layout types
|
||||
if self.layout_type in {'DEFAULT', 'COMPACT'}:
|
||||
layout.prop(item, "enabled_prop")
|
||||
layout.label(item.name, icon=custom_icon)
|
||||
# layout.prop(item, "name", text="", emboss=False, icon=custom_icon)
|
||||
|
||||
elif self.layout_type in {'GRID'}:
|
||||
layout.alignment = 'CENTER'
|
||||
layout.label("", icon = custom_icon)
|
||||
|
||||
class LIST_OT_ActionTraitNewItem(bpy.types.Operator):
|
||||
# Add a new item to the list
|
||||
bl_idname = "my_actiontraitlist.new_item"
|
||||
bl_label = "Add a new item"
|
||||
|
||||
def execute(self, context):
|
||||
trait = context.object.data
|
||||
trait.my_actiontraitlist.add()
|
||||
trait.actiontraitlist_index = len(trait.my_actiontraitlist) - 1
|
||||
return{'FINISHED'}
|
||||
|
||||
|
||||
class LIST_OT_ActionTraitDeleteItem(bpy.types.Operator):
|
||||
# Delete the selected item from the list
|
||||
bl_idname = "my_actiontraitlist.delete_item"
|
||||
bl_label = "Deletes an item"
|
||||
|
||||
@classmethod
|
||||
def poll(self, context):
|
||||
""" Enable if there's something in the list """
|
||||
trait = context.object.data
|
||||
return len(trait.my_actiontraitlist) > 0
|
||||
|
||||
def execute(self, context):
|
||||
trait = context.object.data
|
||||
list = trait.my_actiontraitlist
|
||||
index = trait.actiontraitlist_index
|
||||
|
||||
list.remove(index)
|
||||
|
||||
if index > 0:
|
||||
index = index - 1
|
||||
|
||||
trait.actiontraitlist_index = index
|
||||
return{'FINISHED'}
|
||||
|
||||
|
||||
class LIST_OT_ActionTraitMoveItem(bpy.types.Operator):
|
||||
# Move an item in the list
|
||||
bl_idname = "my_actiontraitlist.move_item"
|
||||
bl_label = "Move an item in the list"
|
||||
direction = bpy.props.EnumProperty(
|
||||
items=(
|
||||
('UP', 'Up', ""),
|
||||
('DOWN', 'Down', ""),))
|
||||
|
||||
@classmethod
|
||||
def poll(self, context):
|
||||
""" Enable if there's something in the list. """
|
||||
trait = context.object.data
|
||||
return len(trait.my_actiontraitlist) > 0
|
||||
|
||||
|
||||
def move_index(self):
|
||||
# Move index of an item render queue while clamping it
|
||||
trait = context.object.data
|
||||
index = trait.actiontraitlist_index
|
||||
list_length = len(trait.my_actiontraitlist) - 1
|
||||
new_index = 0
|
||||
|
||||
if self.direction == 'UP':
|
||||
new_index = index - 1
|
||||
elif self.direction == 'DOWN':
|
||||
new_index = index + 1
|
||||
|
||||
new_index = max(0, min(new_index, list_length))
|
||||
index = new_index
|
||||
|
||||
|
||||
def execute(self, context):
|
||||
trait = context.object.data
|
||||
list = trait.my_actiontraitlist
|
||||
index = trait.actiontraitlist_index
|
||||
|
||||
if self.direction == 'DOWN':
|
||||
neighbor = index + 1
|
||||
#queue.move(index,neighbor)
|
||||
self.move_index()
|
||||
|
||||
elif self.direction == 'UP':
|
||||
neighbor = index - 1
|
||||
#queue.move(neighbor, index)
|
||||
self.move_index()
|
||||
else:
|
||||
return{'CANCELLED'}
|
||||
return{'FINISHED'}
|
||||
|
||||
def register():
|
||||
bpy.utils.register_module(__name__)
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_module(__name__)
|
|
@ -5,7 +5,7 @@ import json
|
|||
from bpy.types import Menu, Panel, UIList
|
||||
from bpy.props import *
|
||||
|
||||
class ListAnimationTraitItem(bpy.types.PropertyGroup):
|
||||
class ListClipTraitItem(bpy.types.PropertyGroup):
|
||||
# Group of properties representing an item in the list
|
||||
name = bpy.props.StringProperty(
|
||||
name="Name",
|
||||
|
@ -43,7 +43,7 @@ class ListAnimationTraitItem(bpy.types.PropertyGroup):
|
|||
default=False)
|
||||
|
||||
|
||||
class MY_UL_AnimationTraitList(bpy.types.UIList):
|
||||
class MY_UL_ClipTraitList(bpy.types.UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
|
||||
# We could write some code to decide which icon to use here...
|
||||
custom_icon = 'OBJECT_DATAMODE'
|
||||
|
@ -58,46 +58,46 @@ class MY_UL_AnimationTraitList(bpy.types.UIList):
|
|||
layout.alignment = 'CENTER'
|
||||
layout.label("", icon = custom_icon)
|
||||
|
||||
class LIST_OT_AnimationTraitNewItem(bpy.types.Operator):
|
||||
class LIST_OT_ClipTraitNewItem(bpy.types.Operator):
|
||||
# Add a new item to the list
|
||||
bl_idname = "my_animationtraitlist.new_item"
|
||||
bl_idname = "my_cliptraitlist.new_item"
|
||||
bl_label = "Add a new item"
|
||||
|
||||
def execute(self, context):
|
||||
trait = context.object.my_traitlist[context.object.traitlist_index]
|
||||
trait.my_animationtraitlist.add()
|
||||
trait.animationtraitlist_index = len(trait.my_animationtraitlist) - 1
|
||||
trait = context.object
|
||||
trait.my_cliptraitlist.add()
|
||||
trait.cliptraitlist_index = len(trait.my_cliptraitlist) - 1
|
||||
return{'FINISHED'}
|
||||
|
||||
|
||||
class LIST_OT_AnimationTraitDeleteItem(bpy.types.Operator):
|
||||
class LIST_OT_ClipTraitDeleteItem(bpy.types.Operator):
|
||||
# Delete the selected item from the list
|
||||
bl_idname = "my_animationtraitlist.delete_item"
|
||||
bl_idname = "my_cliptraitlist.delete_item"
|
||||
bl_label = "Deletes an item"
|
||||
|
||||
@classmethod
|
||||
def poll(self, context):
|
||||
""" Enable if there's something in the list """
|
||||
trait = context.object.my_traitlist[context.object.traitlist_index]
|
||||
return len(trait.my_animationtraitlist) > 0
|
||||
trait = context.object
|
||||
return len(trait.my_cliptraitlist) > 0
|
||||
|
||||
def execute(self, context):
|
||||
trait = context.object.my_traitlist[context.object.traitlist_index]
|
||||
list = trait.my_animationtraitlist
|
||||
index = trait.animationtraitlist_index
|
||||
trait = context.object
|
||||
list = trait.my_cliptraitlist
|
||||
index = trait.cliptraitlist_index
|
||||
|
||||
list.remove(index)
|
||||
|
||||
if index > 0:
|
||||
index = index - 1
|
||||
|
||||
trait.animationtraitlist_index = index
|
||||
trait.cliptraitlist_index = index
|
||||
return{'FINISHED'}
|
||||
|
||||
|
||||
class LIST_OT_AnimationTraitMoveItem(bpy.types.Operator):
|
||||
class LIST_OT_ClipTraitMoveItem(bpy.types.Operator):
|
||||
# Move an item in the list
|
||||
bl_idname = "my_animationtraitlist.move_item"
|
||||
bl_idname = "my_cliptraitlist.move_item"
|
||||
bl_label = "Move an item in the list"
|
||||
direction = bpy.props.EnumProperty(
|
||||
items=(
|
||||
|
@ -107,15 +107,15 @@ class LIST_OT_AnimationTraitMoveItem(bpy.types.Operator):
|
|||
@classmethod
|
||||
def poll(self, context):
|
||||
""" Enable if there's something in the list. """
|
||||
trait = context.object.my_traitlist[context.object.traitlist_index]
|
||||
return len(trait.my_animationtraitlist) > 0
|
||||
trait = context.object
|
||||
return len(trait.my_cliptraitlist) > 0
|
||||
|
||||
|
||||
def move_index(self):
|
||||
# Move index of an item render queue while clamping it
|
||||
trait = context.object.my_traitlist[context.object.traitlist_index]
|
||||
index = trait.animationtraitlist_index
|
||||
list_length = len(trait.my_animationtraitlist) - 1
|
||||
trait = context.object
|
||||
index = trait.cliptraitlist_index
|
||||
list_length = len(trait.my_cliptraitlist) - 1
|
||||
new_index = 0
|
||||
|
||||
if self.direction == 'UP':
|
||||
|
@ -128,9 +128,9 @@ class LIST_OT_AnimationTraitMoveItem(bpy.types.Operator):
|
|||
|
||||
|
||||
def execute(self, context):
|
||||
trait = context.object.my_traitlist[context.object.traitlist_index]
|
||||
list = trait.my_animationtraitlist
|
||||
index = trait.animationtraitlist_index
|
||||
trait = context.object
|
||||
list = trait.my_cliptraitlist
|
||||
index = trait.cliptraitlist_index
|
||||
|
||||
if self.direction == 'DOWN':
|
||||
neighbor = index + 1
|
|
@ -123,7 +123,12 @@ class Main {
|
|||
f.write("""
|
||||
kha.System.init({title: projectName, width: projectWidth, height: projectHeight, samplesPerPixel: projectSamplesPerPixel}, function() {
|
||||
iron.App.init(function() {
|
||||
new armory.Scene(projectScene);
|
||||
var raw = iron.data.Data.getSceneRaw(projectScene);
|
||||
var scene = iron.Scene.create(raw);
|
||||
scene.addTrait(new armory.trait.internal.PhysicsWorld(raw.gravity));
|
||||
iron.App.notifyOnRender(function(g:kha.graphics4.Graphics) {
|
||||
iron.Scene.active.renderFrame(g);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -8,240 +8,244 @@ import utils
|
|||
import assets
|
||||
|
||||
def add_irr_assets(output_file_irr):
|
||||
assets.add(output_file_irr + '.arm')
|
||||
assets.add(output_file_irr + '.arm')
|
||||
|
||||
def add_rad_assets(output_file_rad, rad_format, num_mips):
|
||||
assets.add(output_file_rad + '.' + rad_format)
|
||||
for i in range(0, num_mips):
|
||||
assets.add(output_file_rad + '_' + str(i) + '.' + rad_format)
|
||||
assets.add(output_file_rad + '.' + rad_format)
|
||||
for i in range(0, num_mips):
|
||||
assets.add(output_file_rad + '_' + str(i) + '.' + rad_format)
|
||||
|
||||
# Generate probes from environment map
|
||||
def write_probes(image_filepath, disable_hdr, cached_num_mips, generate_radiance=True):
|
||||
if not os.path.exists('build/compiled/Assets/envmaps'):
|
||||
os.makedirs('build/compiled/Assets/envmaps')
|
||||
|
||||
base_name = image_filepath.rsplit('/', 1)[1].rsplit('.', 1)[0] # Extract file name without extension
|
||||
|
||||
# Assets to be generated
|
||||
output_file_irr = 'build/compiled/Assets/envmaps/' + base_name + '_irradiance'
|
||||
if generate_radiance:
|
||||
output_file_rad = 'build/compiled/Assets/envmaps/' + base_name + '_radiance'
|
||||
rad_format = 'jpg' if disable_hdr else 'hdr'
|
||||
if not os.path.exists('build/compiled/Assets/envmaps'):
|
||||
os.makedirs('build/compiled/Assets/envmaps')
|
||||
|
||||
base_name = image_filepath.rsplit('/', 1)[1].rsplit('.', 1)[0] # Extract file name without extension
|
||||
|
||||
# Assets to be generated
|
||||
output_file_irr = 'build/compiled/Assets/envmaps/' + base_name + '_irradiance'
|
||||
if generate_radiance:
|
||||
output_file_rad = 'build/compiled/Assets/envmaps/' + base_name + '_radiance'
|
||||
rad_format = 'jpg' if disable_hdr else 'hdr'
|
||||
|
||||
# Assume irradiance has to exist
|
||||
if os.path.exists('build/compiled/Assets/envmaps/' + base_name + '_irradiance.arm'):
|
||||
# Cached assets
|
||||
add_irr_assets(output_file_irr)
|
||||
if generate_radiance:
|
||||
add_rad_assets(output_file_rad, rad_format, cached_num_mips)
|
||||
return cached_num_mips
|
||||
|
||||
# Get paths
|
||||
user_preferences = bpy.context.user_preferences
|
||||
addon_prefs = user_preferences.addons['armory'].preferences
|
||||
sdk_path = addon_prefs.sdk_path
|
||||
# Assume irradiance has to exist
|
||||
if os.path.exists('build/compiled/Assets/envmaps/' + base_name + '_irradiance.arm'):
|
||||
# Cached assets
|
||||
add_irr_assets(output_file_irr)
|
||||
if generate_radiance:
|
||||
add_rad_assets(output_file_rad, rad_format, cached_num_mips)
|
||||
return cached_num_mips
|
||||
|
||||
# Get paths
|
||||
user_preferences = bpy.context.user_preferences
|
||||
addon_prefs = user_preferences.addons['armory'].preferences
|
||||
sdk_path = addon_prefs.sdk_path
|
||||
|
||||
if utils.get_os() == 'win':
|
||||
cmft_path = sdk_path + '/armory/tools/cmft/cmft.exe'
|
||||
kraffiti_path = sdk_path + '/kode_studio/KodeStudio-win32/resources/app/extensions/kha/Kha/Kore/Tools/kraffiti/kraffiti.exe'
|
||||
elif utils.get_os() == 'mac':
|
||||
cmft_path = sdk_path + '/armory/tools/cmft/cmft-osx'
|
||||
kraffiti_path = sdk_path + '/kode_studio/"Kode Studio.app"/Contents/Resources/app/extensions/kha/Kha/Kore/Tools/kraffiti/kraffiti-osx'
|
||||
else:
|
||||
cmft_path = sdk_path + '/armory/tools/cmft/cmft-linux64'
|
||||
kraffiti_path = sdk_path + '/kode_studio/KodeStudio-linux64/resources/app/extensions/kha/Kha/Kore/Tools/kraffiti/kraffiti-linux64'
|
||||
|
||||
generated_files = []
|
||||
output_gama_numerator = '1.0' if disable_hdr else '2.2'
|
||||
input_file = utils.get_fp() + image_filepath #'Assets/' + image_name
|
||||
|
||||
# Get input size
|
||||
output = subprocess.check_output([ \
|
||||
kraffiti_path + \
|
||||
' from=' + input_file + \
|
||||
' donothing'], shell=True)
|
||||
# #%ix%i
|
||||
image_w = str(output).split("'")[1]
|
||||
image_w = image_w[1:]
|
||||
image_w = image_w.split('x')[0]
|
||||
image_w = int(image_w)
|
||||
image_h = image_w / 2
|
||||
|
||||
# 4096 = 256 face - 6 mips - 1024 latlong
|
||||
# 2048 = 128 face - 5 mips - 512 latlong
|
||||
# 1024 = 64 face - 4 mips
|
||||
# 512 = 32 face - 3 mips
|
||||
# 256 = 16 face - 2 mips
|
||||
# 128 = 8 face - 1 mip
|
||||
mip_count = 1
|
||||
num = 128
|
||||
while num < image_w:
|
||||
num *= 2
|
||||
mip_count += 1
|
||||
if utils.get_os() == 'win':
|
||||
cmft_path = sdk_path + '/armory/tools/cmft/cmft.exe'
|
||||
kraffiti_path = sdk_path + '/kode_studio/KodeStudio-win32/resources/app/extensions/kha/Kha/Kore/Tools/kraffiti/kraffiti.exe'
|
||||
elif utils.get_os() == 'mac':
|
||||
cmft_path = sdk_path + '/armory/tools/cmft/cmft-osx'
|
||||
kraffiti_path = sdk_path + '/kode_studio/"Kode Studio.app"/Contents/Resources/app/extensions/kha/Kha/Kore/Tools/kraffiti/kraffiti-osx'
|
||||
else:
|
||||
cmft_path = sdk_path + '/armory/tools/cmft/cmft-linux64'
|
||||
kraffiti_path = sdk_path + '/kode_studio/KodeStudio-linux64/resources/app/extensions/kha/Kha/Kore/Tools/kraffiti/kraffiti-linux64'
|
||||
|
||||
generated_files = []
|
||||
output_gama_numerator = '1.0' if disable_hdr else '2.2'
|
||||
input_file = utils.get_fp() + image_filepath #'Assets/' + image_name
|
||||
|
||||
# Get input size
|
||||
output = subprocess.check_output([ \
|
||||
kraffiti_path + \
|
||||
' from=' + input_file + \
|
||||
' donothing'], shell=True)
|
||||
# #%ix%i
|
||||
image_w = str(output).split("'")[1]
|
||||
image_w = image_w[1:]
|
||||
image_w = image_w.split('x')[0]
|
||||
image_w = int(image_w)
|
||||
image_h = image_w / 2
|
||||
|
||||
# 4096 = 256 face - 6 mips - 1024 latlong
|
||||
# 2048 = 128 face - 5 mips - 512 latlong
|
||||
# 1024 = 64 face - 4 mips
|
||||
# 512 = 32 face - 3 mips
|
||||
# 256 = 16 face - 2 mips
|
||||
# 128 = 8 face - 1 mip
|
||||
mip_count = 1
|
||||
num = 128
|
||||
while num < image_w:
|
||||
num *= 2
|
||||
mip_count += 1
|
||||
|
||||
face_size = image_w / 16
|
||||
src_face_size = str(face_size)
|
||||
dst_face_size = str(face_size)
|
||||
|
||||
# Generate irradiance
|
||||
gama_options = ''
|
||||
if disable_hdr:
|
||||
gama_options = \
|
||||
' --inputGammaNumerator 2.2' + \
|
||||
' --inputGammaDenominator 1.0' + \
|
||||
' --outputGammaNumerator 1.0' + \
|
||||
' --outputGammaDenominator ' + output_gama_numerator
|
||||
|
||||
# Irradiance spherical harmonics
|
||||
subprocess.call([ \
|
||||
cmft_path + \
|
||||
' --input ' + input_file + \
|
||||
' --filter shcoeffs' + \
|
||||
#gama_options + \
|
||||
' --outputNum 1' + \
|
||||
' --output0 ' + output_file_irr], shell=True)
|
||||
|
||||
sh_to_json(output_file_irr)
|
||||
# Non cached assets
|
||||
add_irr_assets(output_file_irr)
|
||||
|
||||
# Mip-mapped radiance image
|
||||
if generate_radiance == False:
|
||||
return cached_num_mips
|
||||
face_size = image_w / 16
|
||||
src_face_size = str(face_size)
|
||||
dst_face_size = str(face_size)
|
||||
|
||||
# Generate irradiance
|
||||
gama_options = ''
|
||||
if disable_hdr:
|
||||
gama_options = \
|
||||
' --inputGammaNumerator 2.2' + \
|
||||
' --inputGammaDenominator 1.0' + \
|
||||
' --outputGammaNumerator 1.0' + \
|
||||
' --outputGammaDenominator ' + output_gama_numerator
|
||||
|
||||
# Irradiance spherical harmonics
|
||||
subprocess.call([ \
|
||||
cmft_path + \
|
||||
' --input ' + input_file + \
|
||||
' --filter shcoeffs' + \
|
||||
#gama_options + \
|
||||
' --outputNum 1' + \
|
||||
' --output0 ' + output_file_irr], shell=True)
|
||||
|
||||
sh_to_json(output_file_irr)
|
||||
# Non cached assets
|
||||
add_irr_assets(output_file_irr)
|
||||
|
||||
# Mip-mapped radiance image
|
||||
if generate_radiance == False:
|
||||
return cached_num_mips
|
||||
|
||||
output = subprocess.check_output([ \
|
||||
kraffiti_path + \
|
||||
' from=' + input_file + \
|
||||
' to=' + output_file_rad + '.' + rad_format + \
|
||||
' format=' + rad_format + \
|
||||
' scale=0.5'], shell=True)
|
||||
output = subprocess.check_output([ \
|
||||
kraffiti_path + \
|
||||
' from=' + input_file + \
|
||||
' to=' + output_file_rad + '.' + rad_format + \
|
||||
' format=' + rad_format + \
|
||||
' scale=0.5'], shell=True)
|
||||
|
||||
subprocess.call([ \
|
||||
cmft_path + \
|
||||
' --input ' + input_file + \
|
||||
' --filter radiance' + \
|
||||
' --dstFaceSize ' + dst_face_size + \
|
||||
' --srcFaceSize ' + src_face_size + \
|
||||
' --excludeBase false' + \
|
||||
' --mipCount ' + str(mip_count) + \
|
||||
' --glossScale 7' + \
|
||||
' --glossBias 3' + \
|
||||
' --lightingModel blinnbrdf' + \
|
||||
' --edgeFixup none' + \
|
||||
' --numCpuProcessingThreads 4' + \
|
||||
' --useOpenCL true' + \
|
||||
' --clVendor anyGpuVendor' + \
|
||||
' --deviceType gpu' + \
|
||||
' --deviceIndex 0' + \
|
||||
' --generateMipChain false' + \
|
||||
' --inputGammaNumerator 2.2' + \
|
||||
' --inputGammaDenominator 1.0' + \
|
||||
' --outputGammaNumerator 1.0' + \
|
||||
' --outputGammaDenominator ' + output_gama_numerator + \
|
||||
' --outputNum 1' + \
|
||||
' --output0 ' + output_file_rad + \
|
||||
' --output0params hdr,rgbe,latlong'], shell=True)
|
||||
|
||||
# Remove size extensions in file name
|
||||
mip_w = int(face_size * 4)
|
||||
mip_h = int(face_size * 2)
|
||||
mip_base = output_file_rad + '_'
|
||||
mip_num = 0
|
||||
while mip_w >= 32:
|
||||
mip_name = mip_base + str(mip_num)
|
||||
os.rename(
|
||||
mip_name + '_' + str(mip_w) + 'x' + str(mip_h) + '.hdr',
|
||||
mip_name + '.hdr')
|
||||
mip_w = int(mip_w / 2)
|
||||
mip_h = int(mip_h / 2)
|
||||
mip_num += 1
|
||||
subprocess.call([ \
|
||||
cmft_path + \
|
||||
' --input ' + input_file + \
|
||||
' --filter radiance' + \
|
||||
' --dstFaceSize ' + dst_face_size + \
|
||||
' --srcFaceSize ' + src_face_size + \
|
||||
' --excludeBase false' + \
|
||||
' --mipCount ' + str(mip_count) + \
|
||||
' --glossScale 7' + \
|
||||
' --glossBias 3' + \
|
||||
' --lightingModel blinnbrdf' + \
|
||||
' --edgeFixup none' + \
|
||||
' --numCpuProcessingThreads 4' + \
|
||||
' --useOpenCL true' + \
|
||||
' --clVendor anyGpuVendor' + \
|
||||
' --deviceType gpu' + \
|
||||
' --deviceIndex 0' + \
|
||||
' --generateMipChain false' + \
|
||||
' --inputGammaNumerator 2.2' + \
|
||||
' --inputGammaDenominator 1.0' + \
|
||||
' --outputGammaNumerator 1.0' + \
|
||||
' --outputGammaDenominator ' + output_gama_numerator + \
|
||||
' --outputNum 1' + \
|
||||
' --output0 ' + output_file_rad + \
|
||||
' --output0params hdr,rgbe,latlong'], shell=True)
|
||||
|
||||
# Remove size extensions in file name
|
||||
mip_w = int(face_size * 4)
|
||||
mip_h = int(face_size * 2)
|
||||
mip_base = output_file_rad + '_'
|
||||
mip_num = 0
|
||||
while mip_w >= 32:
|
||||
mip_name = mip_base + str(mip_num)
|
||||
os.rename(
|
||||
mip_name + '_' + str(mip_w) + 'x' + str(mip_h) + '.hdr',
|
||||
mip_name + '.hdr')
|
||||
mip_w = int(mip_w / 2)
|
||||
mip_h = int(mip_h / 2)
|
||||
mip_num += 1
|
||||
|
||||
# Append mips
|
||||
for i in range(0, mip_count):
|
||||
generated_files.append(output_file_rad + '_' + str(i))
|
||||
|
||||
# Convert to jpgs
|
||||
if disable_hdr is True:
|
||||
for f in generated_files:
|
||||
subprocess.call([ \
|
||||
kraffiti_path + \
|
||||
' from=' + f + '.hdr' + \
|
||||
' to=' + f + '.jpg' + \
|
||||
' format=jpg'], shell=True)
|
||||
os.remove(f + '.hdr')
|
||||
|
||||
# Scale from (32x16 to 1x1>
|
||||
for i in range (0, 5):
|
||||
last = generated_files[-1]
|
||||
out = output_file_rad + '_' + str(mip_count + i)
|
||||
subprocess.call([ \
|
||||
kraffiti_path + \
|
||||
' from=' + last + '.' + rad_format + \
|
||||
' to=' + out + '.' + rad_format + \
|
||||
' scale=0.5' + \
|
||||
' format=' + rad_format], shell=True)
|
||||
generated_files.append(out)
|
||||
|
||||
mip_count += 5
|
||||
# Append mips
|
||||
for i in range(0, mip_count):
|
||||
generated_files.append(output_file_rad + '_' + str(i))
|
||||
|
||||
# Convert to jpgs
|
||||
if disable_hdr is True:
|
||||
for f in generated_files:
|
||||
subprocess.call([ \
|
||||
kraffiti_path + \
|
||||
' from=' + f + '.hdr' + \
|
||||
' to=' + f + '.jpg' + \
|
||||
' format=jpg'], shell=True)
|
||||
os.remove(f + '.hdr')
|
||||
|
||||
# Scale from (32x16 to 1x1>
|
||||
for i in range (0, 5):
|
||||
last = generated_files[-1]
|
||||
out = output_file_rad + '_' + str(mip_count + i)
|
||||
subprocess.call([ \
|
||||
kraffiti_path + \
|
||||
' from=' + last + '.' + rad_format + \
|
||||
' to=' + out + '.' + rad_format + \
|
||||
' scale=0.5' + \
|
||||
' format=' + rad_format], shell=True)
|
||||
generated_files.append(out)
|
||||
|
||||
mip_count += 5
|
||||
|
||||
# Non cached assets
|
||||
add_rad_assets(output_file_rad, rad_format, mip_count)
|
||||
# Non cached assets
|
||||
add_rad_assets(output_file_rad, rad_format, mip_count)
|
||||
|
||||
return mip_count
|
||||
return mip_count
|
||||
|
||||
# Parse sh coefs produced by cmft into json array
|
||||
def sh_to_json(sh_file):
|
||||
sh_lines = open(sh_file + '.c').read().splitlines()
|
||||
band0_line = sh_lines[5]
|
||||
band1_line = sh_lines[6]
|
||||
band2_line = sh_lines[7]
|
||||
|
||||
irradiance_floats = []
|
||||
parse_band_floats(irradiance_floats, band0_line)
|
||||
parse_band_floats(irradiance_floats, band1_line)
|
||||
parse_band_floats(irradiance_floats, band2_line)
|
||||
|
||||
sh_json = {}
|
||||
sh_json['irradiance'] = irradiance_floats
|
||||
utils.write_arm(sh_file + '.arm', sh_json)
|
||||
|
||||
# Clean up .c
|
||||
os.remove(sh_file + '.c')
|
||||
sh_lines = open(sh_file + '.c').read().splitlines()
|
||||
band0_line = sh_lines[5]
|
||||
band1_line = sh_lines[6]
|
||||
band2_line = sh_lines[7]
|
||||
|
||||
irradiance_floats = []
|
||||
parse_band_floats(irradiance_floats, band0_line)
|
||||
parse_band_floats(irradiance_floats, band1_line)
|
||||
parse_band_floats(irradiance_floats, band2_line)
|
||||
|
||||
sh_json = {}
|
||||
sh_json['irradiance'] = irradiance_floats
|
||||
utils.write_arm(sh_file + '.arm', sh_json)
|
||||
|
||||
# Clean up .c
|
||||
os.remove(sh_file + '.c')
|
||||
|
||||
def parse_band_floats(irradiance_floats, band_line):
|
||||
string_floats = re.findall(r'[-+]?\d*\.\d+|\d+', band_line)
|
||||
string_floats = string_floats[1:] # Remove 'Band 0/1/2' number
|
||||
for s in string_floats:
|
||||
irradiance_floats.append(float(s))
|
||||
string_floats = re.findall(r'[-+]?\d*\.\d+|\d+', band_line)
|
||||
string_floats = string_floats[1:] # Remove 'Band 0/1/2' number
|
||||
for s in string_floats:
|
||||
irradiance_floats.append(float(s))
|
||||
|
||||
def write_sky_irradiance(base_name):
|
||||
# Predefined fake spherical harmonics for now
|
||||
irradiance_floats = [1.0281457342829743,1.1617608778901902,1.3886220898440544,-0.13044863139637752,-0.2794659158733846,-0.5736106907295643,0.04065421813873111,0.0434367391348577,0.03567450494792305,0.10964557605577738,0.1129839085793664,0.11261660812141877,-0.08271974283263238,-0.08068091195339556,-0.06432614970480094,-0.12517787967665814,-0.11638582546310804,-0.09743696224655113,0.20068697715947176,0.2158788783296805,0.2109374396869599,0.19636637427150455,0.19445523113118082,0.17825330699680575,0.31440860839538637,0.33041120060402407,0.30867788630062676]
|
||||
|
||||
if not os.path.exists('build/compiled/Assets/envmaps'):
|
||||
os.makedirs('build/compiled/Assets/envmaps')
|
||||
|
||||
output_file = 'build/compiled/Assets/envmaps/' + base_name + '_irradiance'
|
||||
|
||||
sh_json = {}
|
||||
sh_json['irradiance'] = irradiance_floats
|
||||
utils.write_arm(output_file + '.arm', sh_json)
|
||||
# Predefined fake spherical harmonics for now
|
||||
irradiance_floats = [1.0281457342829743,1.1617608778901902,1.3886220898440544,-0.13044863139637752,-0.2794659158733846,-0.5736106907295643,0.04065421813873111,0.0434367391348577,0.03567450494792305,0.10964557605577738,0.1129839085793664,0.11261660812141877,-0.08271974283263238,-0.08068091195339556,-0.06432614970480094,-0.12517787967665814,-0.11638582546310804,-0.09743696224655113,0.20068697715947176,0.2158788783296805,0.2109374396869599,0.19636637427150455,0.19445523113118082,0.17825330699680575,0.31440860839538637,0.33041120060402407,0.30867788630062676]
|
||||
# Hosek
|
||||
# irradiance_floats = [1.5519331988822218,2.3352207154503266,2.997277451988076,0.2673894962434794,0.4305630474135794,0.11331825259716752,-0.04453633521758638,-0.038753175134160295,-0.021302768541875794,0.00055858020486499,0.000371654770334503,0.000126606145406403,-0.000135708721978705,-0.000787399554583089,-0.001550090690860059,0.021947399048903773,0.05453650591711572,0.08783641266630278,0.17053593578630663,0.14734127083304463,0.07775404698816404,-2.6924363189795e-05,-7.9350169701934e-05,-7.559914435231e-05,0.27035455385870993,0.23122918445556914,0.12158817295211832]
|
||||
# for i in range(0, len(irradiance_floats)):
|
||||
# irradiance_floats[i] /= 2;
|
||||
|
||||
assets.add(output_file + '.arm')
|
||||
if not os.path.exists('build/compiled/Assets/envmaps'):
|
||||
os.makedirs('build/compiled/Assets/envmaps')
|
||||
|
||||
output_file = 'build/compiled/Assets/envmaps/' + base_name + '_irradiance'
|
||||
|
||||
sh_json = {}
|
||||
sh_json['irradiance'] = irradiance_floats
|
||||
utils.write_arm(output_file + '.arm', sh_json)
|
||||
|
||||
assets.add(output_file + '.arm')
|
||||
|
||||
def write_color_irradiance(base_name, col):
|
||||
# Constant color
|
||||
irradiance_floats = [col[0], col[1], col[2]]
|
||||
for i in range(0, 24):
|
||||
irradiance_floats.append(0.0)
|
||||
|
||||
if not os.path.exists('build/compiled/Assets/envmaps'):
|
||||
os.makedirs('build/compiled/Assets/envmaps')
|
||||
|
||||
output_file = 'build/compiled/Assets/envmaps/' + base_name + '_irradiance'
|
||||
|
||||
sh_json = {}
|
||||
sh_json['irradiance'] = irradiance_floats
|
||||
utils.write_arm(output_file + '.arm', sh_json)
|
||||
# Constant color
|
||||
irradiance_floats = [col[0], col[1], col[2]]
|
||||
for i in range(0, 24):
|
||||
irradiance_floats.append(0.0)
|
||||
|
||||
if not os.path.exists('build/compiled/Assets/envmaps'):
|
||||
os.makedirs('build/compiled/Assets/envmaps')
|
||||
|
||||
output_file = 'build/compiled/Assets/envmaps/' + base_name + '_irradiance'
|
||||
|
||||
sh_json = {}
|
||||
sh_json['irradiance'] = irradiance_floats
|
||||
utils.write_arm(output_file + '.arm', sh_json)
|
||||
|
||||
assets.add(output_file + '.arm')
|
||||
assets.add(output_file + '.arm')
|
||||
|
|
|
@ -22,7 +22,7 @@ vec2 unpackFloat(float f) {
|
|||
|
||||
void main() {
|
||||
vec2 tc = texCoord * ssrTextureScale;
|
||||
float roughness = unpackFloat(texture(gbuffer0, texCoord).b).x;
|
||||
float roughness = unpackFloat(texture(gbuffer0, texCoord).b).y;
|
||||
if (roughness == 0.0) {
|
||||
outColor = texture(tex, tc);
|
||||
// outColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
|
|
|
@ -60,17 +60,19 @@ vec3 getPos(float depth) {
|
|||
// const vec3 compoFogColor = vec3(0.5, 0.6, 0.7);
|
||||
// const float compoFogAmountA = 1.0; // b = 0.01
|
||||
// const float compoFogAmountB = 1.0; // c = 0.1
|
||||
vec3 applyFog(vec3 rgb, // original color of the pixel
|
||||
float distance, // camera to point distance
|
||||
vec3 rayOri, // camera position
|
||||
vec3 rayDir) { // camera to point vector
|
||||
float fogAmount = compoFogAmountB * exp(-rayOri.y * compoFogAmountA) * (1.0 - exp(-distance * rayDir.y * compoFogAmountA)) / rayDir.y;
|
||||
return mix(rgb, compoFogColor, fogAmount);
|
||||
}
|
||||
// vec3 applyFog(vec3 rgb, float distance) {
|
||||
// float fogAmount = 1.0 - exp(-distance * compoFogAmountA);
|
||||
// return mix(rgb, compoFogColor, fogAmount);
|
||||
// vec3 applyFog(vec3 rgb, // original color of the pixel
|
||||
// float distance, // camera to point distance
|
||||
// vec3 rayOri, // camera position
|
||||
// vec3 rayDir) { // camera to point vector
|
||||
// float fogAmount = compoFogAmountB * exp(-rayOri.y * compoFogAmountA) * (1.0 - exp(-distance * rayDir.y * compoFogAmountA)) / rayDir.y;
|
||||
// return mix(rgb, compoFogColor, fogAmount);
|
||||
// }
|
||||
vec3 applyFog(vec3 rgb, float distance) {
|
||||
// float fogAmount = 1.0 - exp(-distance * compoFogAmountA);
|
||||
float fogAmount = 1.0 - exp(-distance * 0.0055);
|
||||
return mix(rgb, vec3(0.4, 0.7, 0.2), fogAmount);
|
||||
// return mix(rgb, compoFogColor, fogAmount);
|
||||
}
|
||||
#endif
|
||||
|
||||
float vignette() {
|
||||
|
@ -78,10 +80,11 @@ float vignette() {
|
|||
// dist = smoothstep(vignout + (fstop / vignfade), vignin + (fstop / vignfade), dist);
|
||||
// return clamp(dist, 0.0, 1.0);
|
||||
// vignetting from iq
|
||||
return 0.4 + 0.6 * pow(16.0 * texCoord.x * texCoord.y * (1.0 - texCoord.x) * (1.0 - texCoord.y), 0.2);
|
||||
// return 0.4 + 0.6 * pow(16.0 * texCoord.x * texCoord.y * (1.0 - texCoord.x) * (1.0 - texCoord.y), 0.2);
|
||||
return 0.3 + 0.7 * pow(16.0 * texCoord.x * texCoord.y * (1.0 - texCoord.x) * (1.0 - texCoord.y), 0.2);
|
||||
}
|
||||
|
||||
#ifdef _CompoDOF
|
||||
// #ifdef _CompoDOF
|
||||
vec3 sampleBox(float size) {
|
||||
vec3 color = vec3(texture(tex, vec2(texCoord.x - size, texCoord.y - size)).rgb) * 0.075;
|
||||
color += texture(tex, vec2(texCoord.x, texCoord.y - size)).rgb * 0.1;
|
||||
|
@ -94,7 +97,7 @@ vec3 sampleBox(float size) {
|
|||
color += texture(tex, vec2(texCoord.x + size, texCoord.y + size)).rgb * 0.075;
|
||||
return color;
|
||||
}
|
||||
#endif
|
||||
// #endif
|
||||
|
||||
float linearize(float depth) {
|
||||
return -cameraPlane.y * cameraPlane.x / (depth * (cameraPlane.y - cameraPlane.x) - cameraPlane.y);
|
||||
|
@ -232,19 +235,25 @@ void main() {
|
|||
#endif
|
||||
|
||||
#ifdef _CompoDOF
|
||||
float linDepth = linearize(depth);
|
||||
float blur_amount = abs(linDepth - compoDOFDistance) / cameraPlane.y;
|
||||
blur_amount = clamp(blur_amount, 0.0, 1.0);
|
||||
float blurSize = compoDOFSize * 10000.0 * blur_amount;
|
||||
vec3 blurredColor = 0.75 * sampleBox(blurSize * 0.5) + 0.25 * sampleBox(blurSize * 1.0);
|
||||
col.rgb *= (1.0 - blur_amount) + blurredColor * blur_amount;
|
||||
if (depth < 1.0) {
|
||||
float linDepth = linearize(depth);
|
||||
float blur_amount = abs(linDepth - compoDOFDistance) / cameraPlane.y;
|
||||
// float blur_amount = abs(linDepth - 4.0);
|
||||
float blurSize = compoDOFSize * blur_amount;
|
||||
// float blurSize = 0.0005 * blur_amount;
|
||||
col.rgb = 0.75 * sampleBox(blurSize * 0.5) + 0.25 * sampleBox(blurSize * 1.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _CompoFog
|
||||
vec3 pos = getPos(depth);
|
||||
float dist = distance(pos, eye);
|
||||
vec3 eyedir = eyeLook;// normalize(eye + pos);
|
||||
col.rgb = applyFog(col.rgb, dist, eye, eyedir);
|
||||
// if (depth < 1.0) {
|
||||
// vec3 pos = getPos(depth);
|
||||
// float dist = distance(pos, eye);
|
||||
float dist = linearize(depth);
|
||||
// vec3 eyedir = eyeLook;// normalize(eye + pos);
|
||||
// col.rgb = applyFog(col.rgb, dist, eye, eyedir);
|
||||
col.rgb = applyFog(col.rgb, dist);
|
||||
// }
|
||||
#endif
|
||||
|
||||
#ifdef _CompoGlare
|
||||
|
|
|
@ -48,7 +48,7 @@ void main() {
|
|||
|
||||
// vec3 p = getPos(depth);
|
||||
// vec3 baseColor = g1.rgb;
|
||||
// vec2 roughmet = unpackFloat(g1.a);
|
||||
// float roughness = roughmet.x;
|
||||
// float metalness = roughmet.y;
|
||||
// vec2 metrough = unpackFloat(g1.a);
|
||||
// float metalness = metrough.x;
|
||||
// float roughness = metrough.y;
|
||||
}
|
||||
|
|
|
@ -31,54 +31,73 @@ in vec3 nor;
|
|||
|
||||
uniform mat4 LWVP;
|
||||
#ifdef _Skinning
|
||||
uniform float skinBones[skinMaxBones * 12];
|
||||
uniform float skinBones[skinMaxBones * 8];
|
||||
#endif
|
||||
|
||||
// out vec4 position;
|
||||
|
||||
#ifdef _Skinning
|
||||
mat4 getBoneMat(const int boneIndex) {
|
||||
vec4 v0 = vec4(skinBones[boneIndex * 12 + 0],
|
||||
skinBones[boneIndex * 12 + 1],
|
||||
skinBones[boneIndex * 12 + 2],
|
||||
skinBones[boneIndex * 12 + 3]);
|
||||
vec4 v1 = vec4(skinBones[boneIndex * 12 + 4],
|
||||
skinBones[boneIndex * 12 + 5],
|
||||
skinBones[boneIndex * 12 + 6],
|
||||
skinBones[boneIndex * 12 + 7]);
|
||||
vec4 v2 = vec4(skinBones[boneIndex * 12 + 8],
|
||||
skinBones[boneIndex * 12 + 9],
|
||||
skinBones[boneIndex * 12 + 10],
|
||||
skinBones[boneIndex * 12 + 11]);
|
||||
return mat4(v0.x, v0.y, v0.z, v0.w,
|
||||
v1.x, v1.y, v1.z, v1.w,
|
||||
v2.x, v2.y, v2.z, v2.w,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
mat4 getSkinningMat() {
|
||||
return weight.x * getBoneMat(int(bone.x)) +
|
||||
weight.y * getBoneMat(int(bone.y)) +
|
||||
weight.z * getBoneMat(int(bone.z)) +
|
||||
weight.w * getBoneMat(int(bone.w));
|
||||
}
|
||||
|
||||
mat3 getSkinningMatVec(const mat4 skinningMat) {
|
||||
return mat3(skinningMat[0].xyz, skinningMat[1].xyz, skinningMat[2].xyz);
|
||||
void getSkinningDualQuat(vec4 weights, out vec4 A, inout vec4 B) {
|
||||
// Retrieve the real and dual part of the dual-quaternions
|
||||
mat4 matA, matB;
|
||||
matA[0][0] = skinBones[int(bone.x) * 8 + 0];
|
||||
matA[0][1] = skinBones[int(bone.x) * 8 + 1];
|
||||
matA[0][2] = skinBones[int(bone.x) * 8 + 2];
|
||||
matA[0][3] = skinBones[int(bone.x) * 8 + 3];
|
||||
matB[0][0] = skinBones[int(bone.x) * 8 + 4];
|
||||
matB[0][1] = skinBones[int(bone.x) * 8 + 5];
|
||||
matB[0][2] = skinBones[int(bone.x) * 8 + 6];
|
||||
matB[0][3] = skinBones[int(bone.x) * 8 + 7];
|
||||
matA[1][0] = skinBones[int(bone.y) * 8 + 0];
|
||||
matA[1][1] = skinBones[int(bone.y) * 8 + 1];
|
||||
matA[1][2] = skinBones[int(bone.y) * 8 + 2];
|
||||
matA[1][3] = skinBones[int(bone.y) * 8 + 3];
|
||||
matB[1][0] = skinBones[int(bone.y) * 8 + 4];
|
||||
matB[1][1] = skinBones[int(bone.y) * 8 + 5];
|
||||
matB[1][2] = skinBones[int(bone.y) * 8 + 6];
|
||||
matB[1][3] = skinBones[int(bone.y) * 8 + 7];
|
||||
matA[2][0] = skinBones[int(bone.z) * 8 + 0];
|
||||
matA[2][1] = skinBones[int(bone.z) * 8 + 1];
|
||||
matA[2][2] = skinBones[int(bone.z) * 8 + 2];
|
||||
matA[2][3] = skinBones[int(bone.z) * 8 + 3];
|
||||
matB[2][0] = skinBones[int(bone.z) * 8 + 4];
|
||||
matB[2][1] = skinBones[int(bone.z) * 8 + 5];
|
||||
matB[2][2] = skinBones[int(bone.z) * 8 + 6];
|
||||
matB[2][3] = skinBones[int(bone.z) * 8 + 7];
|
||||
matA[3][0] = skinBones[int(bone.w) * 8 + 0];
|
||||
matA[3][1] = skinBones[int(bone.w) * 8 + 1];
|
||||
matA[3][2] = skinBones[int(bone.w) * 8 + 2];
|
||||
matA[3][3] = skinBones[int(bone.w) * 8 + 3];
|
||||
matB[3][0] = skinBones[int(bone.w) * 8 + 4];
|
||||
matB[3][1] = skinBones[int(bone.w) * 8 + 5];
|
||||
matB[3][2] = skinBones[int(bone.w) * 8 + 6];
|
||||
matB[3][3] = skinBones[int(bone.w) * 8 + 7];
|
||||
// Handles antipodality by sticking joints in the same neighbourhood
|
||||
// weights.xyz *= sign(matA[3] * mat3x4(matA)).xyz;
|
||||
weights.xyz *= sign(matA[3] * matA).xyz;
|
||||
// Apply weights
|
||||
A = matA * weights; // Real part
|
||||
B = matB * weights; // Dual part
|
||||
// Normalize
|
||||
float invNormA = 1.0 / length(A);
|
||||
A *= invNormA;
|
||||
B *= invNormA;
|
||||
}
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
#ifdef _Instancing
|
||||
#ifdef _Instancing
|
||||
vec4 sPos = (vec4(pos + off, 1.0));
|
||||
#else
|
||||
vec4 sPos = (vec4(pos, 1.0));
|
||||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
mat4 skinningMat = getSkinningMat();
|
||||
mat3 skinningMatVec = getSkinningMatVec(skinningMat);
|
||||
sPos = sPos * skinningMat;
|
||||
vec4 skinA;
|
||||
vec4 skinB;
|
||||
getSkinningDualQuat(weight, skinA, skinB);
|
||||
sPos.xyz += 2.0 * cross(skinA.xyz, cross(skinA.xyz, sPos.xyz) + skinA.w * sPos.xyz); // Rotate
|
||||
sPos.xyz += 2.0 * (skinA.w * skinB.xyz - skinB.w * skinA.xyz + cross(skinA.xyz, skinB.xyz)); // Translate
|
||||
#endif
|
||||
|
||||
gl_Position = LWVP * sPos;
|
||||
|
|
|
@ -77,8 +77,8 @@ in vec4 matColor;
|
|||
#endif
|
||||
|
||||
float packFloat(float f1, float f2) {
|
||||
int index = int(f1 * 1000);
|
||||
float alpha = f2 == 0.0 ? f2 : (f2 - 0.0001);
|
||||
float index = floor(f1 * 1000.0); // Temporary
|
||||
float alpha = clamp(f2, 0.0, 1.0 - 0.001);
|
||||
return index + alpha;
|
||||
}
|
||||
|
||||
|
@ -179,7 +179,7 @@ float parallaxShadow(vec3 L, vec2 initialTexCoord, float initialHeight) {
|
|||
// ...
|
||||
|
||||
// Shadowing factor should be 1 if there were no points under the surface
|
||||
if(numSamplesUnderSurface < 1) shadowMultiplier = 1;
|
||||
if (numSamplesUnderSurface < 1) shadowMultiplier = 1;
|
||||
else shadowMultiplier = 1.0 - shadowMultiplier;
|
||||
}
|
||||
return shadowMultiplier;
|
||||
|
@ -259,9 +259,9 @@ void main() {
|
|||
}
|
||||
if (dist > 0) mask_probe = 0;
|
||||
}
|
||||
outColor[0] = vec4(n.xy, packFloat(roughness, metalness), mask_probe);
|
||||
outColor[0] = vec4(n.xy, packFloat(metalness, roughness), mask_probe);
|
||||
#else
|
||||
outColor[0] = vec4(n.xy, packFloat(roughness, metalness), mask);
|
||||
outColor[0] = vec4(n.xy, packFloat(metalness, roughness), mask);
|
||||
#endif
|
||||
outColor[1] = vec4(baseColor.rgb, occ);
|
||||
|
||||
|
|
|
@ -45,7 +45,8 @@ uniform vec4 albedo_color;
|
|||
uniform mat4 W;
|
||||
#endif
|
||||
#ifdef _Skinning
|
||||
uniform float skinBones[skinMaxBones * 12]; // Default to 50
|
||||
// uniform float skinBones[skinMaxBones * 12]; // Defaults to 50
|
||||
uniform float skinBones[skinMaxBones * 8]; // Dual quat
|
||||
#endif
|
||||
#ifdef _Probes
|
||||
uniform mat4 W; // TODO: Conflicts with _HeightTex
|
||||
|
@ -78,60 +79,79 @@ out vec4 matColor;
|
|||
#ifdef _Skinning
|
||||
// Geometric Skinning with Approximate Dual Quaternion Blending, Kavan
|
||||
// Based on https://github.com/tcoppex/aer-engine/blob/master/demos/aura/data/shaders/Skinning.glsl
|
||||
// void getSkinningDualQuat(vec4 weights, inout vec3 v, inout vec3 n) {
|
||||
// // Retrieve the real and dual part of the dual-quaternions
|
||||
// mat4 matA, matB;
|
||||
// vec4 indices = vec4(2.0) * bone;
|
||||
// matA[0] = skinBones[int(indices.x) + 0];
|
||||
// matB[0] = skinBones[int(indices.x) + 1];
|
||||
// matA[1] = skinBones[int(indices.y) + 0];
|
||||
// matB[1] = skinBones[int(indices.y) + 1];
|
||||
// matA[2] = skinBones[int(indices.z) + 0];
|
||||
// matB[2] = skinBones[int(indices.z) + 1];
|
||||
// matA[3] = skinBones[int(indices.w) + 0];
|
||||
// matB[3] = skinBones[int(indices.w) + 1];
|
||||
// // Handles antipodality by sticking joints in the same neighbourhood
|
||||
// weights.xyz *= sign(matA[3] * mat3x4(matA));
|
||||
// // Apply weights
|
||||
// vec4 A = matA * weights; // Real part
|
||||
// vec4 B = matB * weights; // Dual part
|
||||
// // Normalize
|
||||
// float invNormA = 1.0 / length(A);
|
||||
// A *= invNormA;
|
||||
// B *= invNormA;
|
||||
// // Position
|
||||
// v += 2.0 * cross(A.xyz, cross(A.xyz, v) + A.w * v); // Rotate
|
||||
// v += 2.0 * (A.w * B.xyz - B.w * A.xyz + cross(A.xyz, B.xyz)); // Translate
|
||||
// // Normal
|
||||
// n += 2.0 * cross(A.xyz, cross(A.xyz, n) + A.w * n);
|
||||
void getSkinningDualQuat(vec4 weights, out vec4 A, inout vec4 B) {
|
||||
// Retrieve the real and dual part of the dual-quaternions
|
||||
mat4 matA, matB;
|
||||
matA[0][0] = skinBones[int(bone.x) * 8 + 0];
|
||||
matA[0][1] = skinBones[int(bone.x) * 8 + 1];
|
||||
matA[0][2] = skinBones[int(bone.x) * 8 + 2];
|
||||
matA[0][3] = skinBones[int(bone.x) * 8 + 3];
|
||||
matB[0][0] = skinBones[int(bone.x) * 8 + 4];
|
||||
matB[0][1] = skinBones[int(bone.x) * 8 + 5];
|
||||
matB[0][2] = skinBones[int(bone.x) * 8 + 6];
|
||||
matB[0][3] = skinBones[int(bone.x) * 8 + 7];
|
||||
matA[1][0] = skinBones[int(bone.y) * 8 + 0];
|
||||
matA[1][1] = skinBones[int(bone.y) * 8 + 1];
|
||||
matA[1][2] = skinBones[int(bone.y) * 8 + 2];
|
||||
matA[1][3] = skinBones[int(bone.y) * 8 + 3];
|
||||
matB[1][0] = skinBones[int(bone.y) * 8 + 4];
|
||||
matB[1][1] = skinBones[int(bone.y) * 8 + 5];
|
||||
matB[1][2] = skinBones[int(bone.y) * 8 + 6];
|
||||
matB[1][3] = skinBones[int(bone.y) * 8 + 7];
|
||||
matA[2][0] = skinBones[int(bone.z) * 8 + 0];
|
||||
matA[2][1] = skinBones[int(bone.z) * 8 + 1];
|
||||
matA[2][2] = skinBones[int(bone.z) * 8 + 2];
|
||||
matA[2][3] = skinBones[int(bone.z) * 8 + 3];
|
||||
matB[2][0] = skinBones[int(bone.z) * 8 + 4];
|
||||
matB[2][1] = skinBones[int(bone.z) * 8 + 5];
|
||||
matB[2][2] = skinBones[int(bone.z) * 8 + 6];
|
||||
matB[2][3] = skinBones[int(bone.z) * 8 + 7];
|
||||
matA[3][0] = skinBones[int(bone.w) * 8 + 0];
|
||||
matA[3][1] = skinBones[int(bone.w) * 8 + 1];
|
||||
matA[3][2] = skinBones[int(bone.w) * 8 + 2];
|
||||
matA[3][3] = skinBones[int(bone.w) * 8 + 3];
|
||||
matB[3][0] = skinBones[int(bone.w) * 8 + 4];
|
||||
matB[3][1] = skinBones[int(bone.w) * 8 + 5];
|
||||
matB[3][2] = skinBones[int(bone.w) * 8 + 6];
|
||||
matB[3][3] = skinBones[int(bone.w) * 8 + 7];
|
||||
// Handles antipodality by sticking joints in the same neighbourhood
|
||||
// weights.xyz *= sign(matA[3] * mat3x4(matA)).xyz;
|
||||
weights.xyz *= sign(matA[3] * matA).xyz;
|
||||
// Apply weights
|
||||
A = matA * weights; // Real part
|
||||
B = matB * weights; // Dual part
|
||||
// Normalize
|
||||
float invNormA = 1.0 / length(A);
|
||||
A *= invNormA;
|
||||
B *= invNormA;
|
||||
}
|
||||
// mat4 getBoneMat(const int boneIndex) {
|
||||
// vec4 v0 = vec4(skinBones[boneIndex * 12 + 0],
|
||||
// skinBones[boneIndex * 12 + 1],
|
||||
// skinBones[boneIndex * 12 + 2],
|
||||
// skinBones[boneIndex * 12 + 3]);
|
||||
// vec4 v1 = vec4(skinBones[boneIndex * 12 + 4],
|
||||
// skinBones[boneIndex * 12 + 5],
|
||||
// skinBones[boneIndex * 12 + 6],
|
||||
// skinBones[boneIndex * 12 + 7]);
|
||||
// vec4 v2 = vec4(skinBones[boneIndex * 12 + 8],
|
||||
// skinBones[boneIndex * 12 + 9],
|
||||
// skinBones[boneIndex * 12 + 10],
|
||||
// skinBones[boneIndex * 12 + 11]);
|
||||
// return mat4(v0.x, v0.y, v0.z, v0.w,
|
||||
// v1.x, v1.y, v1.z, v1.w,
|
||||
// v2.x, v2.y, v2.z, v2.w,
|
||||
// 0, 0, 0, 1);
|
||||
// }
|
||||
// mat4 getSkinningMat() {
|
||||
// return weight.x * getBoneMat(int(bone.x)) +
|
||||
// weight.y * getBoneMat(int(bone.y)) +
|
||||
// weight.z * getBoneMat(int(bone.z)) +
|
||||
// weight.w * getBoneMat(int(bone.w));
|
||||
// }
|
||||
// mat3 getSkinningMatVec(const mat4 skinningMat) {
|
||||
// return mat3(skinningMat[0].xyz, skinningMat[1].xyz, skinningMat[2].xyz);
|
||||
// }
|
||||
mat4 getBoneMat(const int boneIndex) {
|
||||
vec4 v0 = vec4(skinBones[boneIndex * 12 + 0],
|
||||
skinBones[boneIndex * 12 + 1],
|
||||
skinBones[boneIndex * 12 + 2],
|
||||
skinBones[boneIndex * 12 + 3]);
|
||||
vec4 v1 = vec4(skinBones[boneIndex * 12 + 4],
|
||||
skinBones[boneIndex * 12 + 5],
|
||||
skinBones[boneIndex * 12 + 6],
|
||||
skinBones[boneIndex * 12 + 7]);
|
||||
vec4 v2 = vec4(skinBones[boneIndex * 12 + 8],
|
||||
skinBones[boneIndex * 12 + 9],
|
||||
skinBones[boneIndex * 12 + 10],
|
||||
skinBones[boneIndex * 12 + 11]);
|
||||
return mat4(v0.x, v0.y, v0.z, v0.w,
|
||||
v1.x, v1.y, v1.z, v1.w,
|
||||
v2.x, v2.y, v2.z, v2.w,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
mat4 getSkinningMat() {
|
||||
return weight.x * getBoneMat(int(bone.x)) +
|
||||
weight.y * getBoneMat(int(bone.y)) +
|
||||
weight.z * getBoneMat(int(bone.z)) +
|
||||
weight.w * getBoneMat(int(bone.w));
|
||||
}
|
||||
mat3 getSkinningMatVec(const mat4 skinningMat) {
|
||||
return mat3(skinningMat[0].xyz, skinningMat[1].xyz, skinningMat[2].xyz);
|
||||
}
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
|
@ -142,9 +162,19 @@ void main() {
|
|||
vec4 sPos = (vec4(pos, 1.0));
|
||||
#endif
|
||||
#ifdef _Skinning
|
||||
mat4 skinningMat = getSkinningMat();
|
||||
mat3 skinningMatVec = getSkinningMatVec(skinningMat);
|
||||
sPos = sPos * skinningMat;
|
||||
// mat4 skinningMat = getSkinningMat();
|
||||
// mat3 skinningMatVec = getSkinningMatVec(skinningMat);
|
||||
// sPos = sPos * skinningMat;
|
||||
// vec3 _normal = normalize(mat3(N) * (nor * skinningMatVec));
|
||||
|
||||
vec4 skinA;
|
||||
vec4 skinB;
|
||||
getSkinningDualQuat(weight, skinA, skinB);
|
||||
sPos.xyz += 2.0 * cross(skinA.xyz, cross(skinA.xyz, sPos.xyz) + skinA.w * sPos.xyz); // Rotate
|
||||
sPos.xyz += 2.0 * (skinA.w * skinB.xyz - skinB.w * skinA.xyz + cross(skinA.xyz, skinB.xyz)); // Translate
|
||||
vec3 _normal = normalize(mat3(N) * (nor + 2.0 * cross(skinA.xyz, cross(skinA.xyz, nor) + skinA.w * nor)));
|
||||
#else
|
||||
vec3 _normal = normalize(mat3(N) * nor);
|
||||
#endif
|
||||
|
||||
#ifdef _Probes
|
||||
|
@ -173,12 +203,6 @@ void main() {
|
|||
texCoord = tex;
|
||||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
vec3 _normal = normalize(mat3(N) * (nor * skinningMatVec));
|
||||
#else
|
||||
vec3 _normal = normalize(mat3(N) * nor);
|
||||
#endif
|
||||
|
||||
matColor = albedo_color;
|
||||
|
||||
#ifdef _VCols
|
||||
|
|
|
@ -54,34 +54,51 @@ out vec3 eyeDir;
|
|||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
mat4 getBoneMat(const int boneIndex) {
|
||||
vec4 v0 = vec4(skinBones[boneIndex * 12 + 0],
|
||||
skinBones[boneIndex * 12 + 1],
|
||||
skinBones[boneIndex * 12 + 2],
|
||||
skinBones[boneIndex * 12 + 3]);
|
||||
vec4 v1 = vec4(skinBones[boneIndex * 12 + 4],
|
||||
skinBones[boneIndex * 12 + 5],
|
||||
skinBones[boneIndex * 12 + 6],
|
||||
skinBones[boneIndex * 12 + 7]);
|
||||
vec4 v2 = vec4(skinBones[boneIndex * 12 + 8],
|
||||
skinBones[boneIndex * 12 + 9],
|
||||
skinBones[boneIndex * 12 + 10],
|
||||
skinBones[boneIndex * 12 + 11]);
|
||||
return mat4(v0.x, v0.y, v0.z, v0.w,
|
||||
v1.x, v1.y, v1.z, v1.w,
|
||||
v2.x, v2.y, v2.z, v2.w,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
mat4 getSkinningMat() {
|
||||
return weight.x * getBoneMat(int(bone.x)) +
|
||||
weight.y * getBoneMat(int(bone.y)) +
|
||||
weight.z * getBoneMat(int(bone.z)) +
|
||||
weight.w * getBoneMat(int(bone.w));
|
||||
}
|
||||
|
||||
mat3 getSkinningMatVec(const mat4 skinningMat) {
|
||||
return mat3(skinningMat[0].xyz, skinningMat[1].xyz, skinningMat[2].xyz);
|
||||
void getSkinningDualQuat(vec4 weights, out vec4 A, inout vec4 B) {
|
||||
// Retrieve the real and dual part of the dual-quaternions
|
||||
mat4 matA, matB;
|
||||
matA[0][0] = skinBones[int(bone.x) * 8 + 0];
|
||||
matA[0][1] = skinBones[int(bone.x) * 8 + 1];
|
||||
matA[0][2] = skinBones[int(bone.x) * 8 + 2];
|
||||
matA[0][3] = skinBones[int(bone.x) * 8 + 3];
|
||||
matB[0][0] = skinBones[int(bone.x) * 8 + 4];
|
||||
matB[0][1] = skinBones[int(bone.x) * 8 + 5];
|
||||
matB[0][2] = skinBones[int(bone.x) * 8 + 6];
|
||||
matB[0][3] = skinBones[int(bone.x) * 8 + 7];
|
||||
matA[1][0] = skinBones[int(bone.y) * 8 + 0];
|
||||
matA[1][1] = skinBones[int(bone.y) * 8 + 1];
|
||||
matA[1][2] = skinBones[int(bone.y) * 8 + 2];
|
||||
matA[1][3] = skinBones[int(bone.y) * 8 + 3];
|
||||
matB[1][0] = skinBones[int(bone.y) * 8 + 4];
|
||||
matB[1][1] = skinBones[int(bone.y) * 8 + 5];
|
||||
matB[1][2] = skinBones[int(bone.y) * 8 + 6];
|
||||
matB[1][3] = skinBones[int(bone.y) * 8 + 7];
|
||||
matA[2][0] = skinBones[int(bone.z) * 8 + 0];
|
||||
matA[2][1] = skinBones[int(bone.z) * 8 + 1];
|
||||
matA[2][2] = skinBones[int(bone.z) * 8 + 2];
|
||||
matA[2][3] = skinBones[int(bone.z) * 8 + 3];
|
||||
matB[2][0] = skinBones[int(bone.z) * 8 + 4];
|
||||
matB[2][1] = skinBones[int(bone.z) * 8 + 5];
|
||||
matB[2][2] = skinBones[int(bone.z) * 8 + 6];
|
||||
matB[2][3] = skinBones[int(bone.z) * 8 + 7];
|
||||
matA[3][0] = skinBones[int(bone.w) * 8 + 0];
|
||||
matA[3][1] = skinBones[int(bone.w) * 8 + 1];
|
||||
matA[3][2] = skinBones[int(bone.w) * 8 + 2];
|
||||
matA[3][3] = skinBones[int(bone.w) * 8 + 3];
|
||||
matB[3][0] = skinBones[int(bone.w) * 8 + 4];
|
||||
matB[3][1] = skinBones[int(bone.w) * 8 + 5];
|
||||
matB[3][2] = skinBones[int(bone.w) * 8 + 6];
|
||||
matB[3][3] = skinBones[int(bone.w) * 8 + 7];
|
||||
// Handles antipodality by sticking joints in the same neighbourhood
|
||||
// weights.xyz *= sign(matA[3] * mat3x4(matA)).xyz;
|
||||
weights.xyz *= sign(matA[3] * matA).xyz;
|
||||
// Apply weights
|
||||
A = matA * weights; // Real part
|
||||
B = matB * weights; // Dual part
|
||||
// Normalize
|
||||
float invNormA = 1.0 / length(A);
|
||||
A *= invNormA;
|
||||
B *= invNormA;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -92,11 +109,18 @@ void main() {
|
|||
#else
|
||||
vec4 sPos = (vec4(pos, 1.0));
|
||||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
mat4 skinningMat = getSkinningMat();
|
||||
mat3 skinningMatVec = getSkinningMatVec(skinningMat);
|
||||
sPos = sPos * skinningMat;
|
||||
vec4 skinA;
|
||||
vec4 skinB;
|
||||
getSkinningDualQuat(weight, skinA, skinB);
|
||||
sPos.xyz += 2.0 * cross(skinA.xyz, cross(skinA.xyz, sPos.xyz) + skinA.w * sPos.xyz); // Rotate
|
||||
sPos.xyz += 2.0 * (skinA.w * skinB.xyz - skinB.w * skinA.xyz + cross(skinA.xyz, skinB.xyz)); // Translate
|
||||
vec3 _normal = normalize(mat3(N) * (nor + 2.0 * cross(skinA.xyz, cross(skinA.xyz, nor) + skinA.w * nor)));
|
||||
#else
|
||||
vec3 _normal = normalize(mat3(N) * nor);
|
||||
#endif
|
||||
|
||||
lPos = LWVP * sPos;
|
||||
|
||||
mat4 WV = V * W;
|
||||
|
@ -117,12 +141,6 @@ void main() {
|
|||
texCoord = tex;
|
||||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
vec3 _normal = normalize(mat3(N) * (nor * skinningMatVec));
|
||||
#else
|
||||
vec3 _normal = normalize(mat3(N) * nor);
|
||||
#endif
|
||||
|
||||
matColor = albedo_color;
|
||||
|
||||
#ifdef _VCols
|
||||
|
|
|
@ -38,34 +38,51 @@ uniform mat4 LWVP;
|
|||
// out vec4 position;
|
||||
|
||||
#ifdef _Skinning
|
||||
mat4 getBoneMat(const int boneIndex) {
|
||||
vec4 v0 = vec4(skinBones[boneIndex * 12 + 0],
|
||||
skinBones[boneIndex * 12 + 1],
|
||||
skinBones[boneIndex * 12 + 2],
|
||||
skinBones[boneIndex * 12 + 3]);
|
||||
vec4 v1 = vec4(skinBones[boneIndex * 12 + 4],
|
||||
skinBones[boneIndex * 12 + 5],
|
||||
skinBones[boneIndex * 12 + 6],
|
||||
skinBones[boneIndex * 12 + 7]);
|
||||
vec4 v2 = vec4(skinBones[boneIndex * 12 + 8],
|
||||
skinBones[boneIndex * 12 + 9],
|
||||
skinBones[boneIndex * 12 + 10],
|
||||
skinBones[boneIndex * 12 + 11]);
|
||||
return mat4(v0.x, v0.y, v0.z, v0.w,
|
||||
v1.x, v1.y, v1.z, v1.w,
|
||||
v2.x, v2.y, v2.z, v2.w,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
mat4 getSkinningMat() {
|
||||
return weight.x * getBoneMat(int(bone.x)) +
|
||||
weight.y * getBoneMat(int(bone.y)) +
|
||||
weight.z * getBoneMat(int(bone.z)) +
|
||||
weight.w * getBoneMat(int(bone.w));
|
||||
}
|
||||
|
||||
mat3 getSkinningMatVec(const mat4 skinningMat) {
|
||||
return mat3(skinningMat[0].xyz, skinningMat[1].xyz, skinningMat[2].xyz);
|
||||
void getSkinningDualQuat(vec4 weights, out vec4 A, inout vec4 B) {
|
||||
// Retrieve the real and dual part of the dual-quaternions
|
||||
mat4 matA, matB;
|
||||
matA[0][0] = skinBones[int(bone.x) * 8 + 0];
|
||||
matA[0][1] = skinBones[int(bone.x) * 8 + 1];
|
||||
matA[0][2] = skinBones[int(bone.x) * 8 + 2];
|
||||
matA[0][3] = skinBones[int(bone.x) * 8 + 3];
|
||||
matB[0][0] = skinBones[int(bone.x) * 8 + 4];
|
||||
matB[0][1] = skinBones[int(bone.x) * 8 + 5];
|
||||
matB[0][2] = skinBones[int(bone.x) * 8 + 6];
|
||||
matB[0][3] = skinBones[int(bone.x) * 8 + 7];
|
||||
matA[1][0] = skinBones[int(bone.y) * 8 + 0];
|
||||
matA[1][1] = skinBones[int(bone.y) * 8 + 1];
|
||||
matA[1][2] = skinBones[int(bone.y) * 8 + 2];
|
||||
matA[1][3] = skinBones[int(bone.y) * 8 + 3];
|
||||
matB[1][0] = skinBones[int(bone.y) * 8 + 4];
|
||||
matB[1][1] = skinBones[int(bone.y) * 8 + 5];
|
||||
matB[1][2] = skinBones[int(bone.y) * 8 + 6];
|
||||
matB[1][3] = skinBones[int(bone.y) * 8 + 7];
|
||||
matA[2][0] = skinBones[int(bone.z) * 8 + 0];
|
||||
matA[2][1] = skinBones[int(bone.z) * 8 + 1];
|
||||
matA[2][2] = skinBones[int(bone.z) * 8 + 2];
|
||||
matA[2][3] = skinBones[int(bone.z) * 8 + 3];
|
||||
matB[2][0] = skinBones[int(bone.z) * 8 + 4];
|
||||
matB[2][1] = skinBones[int(bone.z) * 8 + 5];
|
||||
matB[2][2] = skinBones[int(bone.z) * 8 + 6];
|
||||
matB[2][3] = skinBones[int(bone.z) * 8 + 7];
|
||||
matA[3][0] = skinBones[int(bone.w) * 8 + 0];
|
||||
matA[3][1] = skinBones[int(bone.w) * 8 + 1];
|
||||
matA[3][2] = skinBones[int(bone.w) * 8 + 2];
|
||||
matA[3][3] = skinBones[int(bone.w) * 8 + 3];
|
||||
matB[3][0] = skinBones[int(bone.w) * 8 + 4];
|
||||
matB[3][1] = skinBones[int(bone.w) * 8 + 5];
|
||||
matB[3][2] = skinBones[int(bone.w) * 8 + 6];
|
||||
matB[3][3] = skinBones[int(bone.w) * 8 + 7];
|
||||
// Handles antipodality by sticking joints in the same neighbourhood
|
||||
// weights.xyz *= sign(matA[3] * mat3x4(matA)).xyz;
|
||||
weights.xyz *= sign(matA[3] * matA).xyz;
|
||||
// Apply weights
|
||||
A = matA * weights; // Real part
|
||||
B = matB * weights; // Dual part
|
||||
// Normalize
|
||||
float invNormA = 1.0 / length(A);
|
||||
A *= invNormA;
|
||||
B *= invNormA;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -77,9 +94,11 @@ void main() {
|
|||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
mat4 skinningMat = getSkinningMat();
|
||||
mat3 skinningMatVec = getSkinningMatVec(skinningMat);
|
||||
sPos = sPos * skinningMat;
|
||||
vec4 skinA;
|
||||
vec4 skinB;
|
||||
getSkinningDualQuat(weight, skinA, skinB);
|
||||
sPos.xyz += 2.0 * cross(skinA.xyz, cross(skinA.xyz, sPos.xyz) + skinA.w * sPos.xyz); // Rotate
|
||||
sPos.xyz += 2.0 * (skinA.w * skinB.xyz - skinB.w * skinA.xyz + cross(skinA.xyz, skinB.xyz)); // Translate
|
||||
#endif
|
||||
|
||||
gl_Position = LWVP * sPos;
|
||||
|
|
|
@ -53,34 +53,51 @@ out vec4 matColor;
|
|||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
mat4 getBoneMat(const int boneIndex) {
|
||||
vec4 v0 = vec4(skinBones[boneIndex * 12 + 0],
|
||||
skinBones[boneIndex * 12 + 1],
|
||||
skinBones[boneIndex * 12 + 2],
|
||||
skinBones[boneIndex * 12 + 3]);
|
||||
vec4 v1 = vec4(skinBones[boneIndex * 12 + 4],
|
||||
skinBones[boneIndex * 12 + 5],
|
||||
skinBones[boneIndex * 12 + 6],
|
||||
skinBones[boneIndex * 12 + 7]);
|
||||
vec4 v2 = vec4(skinBones[boneIndex * 12 + 8],
|
||||
skinBones[boneIndex * 12 + 9],
|
||||
skinBones[boneIndex * 12 + 10],
|
||||
skinBones[boneIndex * 12 + 11]);
|
||||
return mat4(v0.x, v0.y, v0.z, v0.w,
|
||||
v1.x, v1.y, v1.z, v1.w,
|
||||
v2.x, v2.y, v2.z, v2.w,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
mat4 getSkinningMat() {
|
||||
return weight.x * getBoneMat(int(bone.x)) +
|
||||
weight.y * getBoneMat(int(bone.y)) +
|
||||
weight.z * getBoneMat(int(bone.z)) +
|
||||
weight.w * getBoneMat(int(bone.w));
|
||||
}
|
||||
|
||||
mat3 getSkinningMatVec(const mat4 skinningMat) {
|
||||
return mat3(skinningMat[0].xyz, skinningMat[1].xyz, skinningMat[2].xyz);
|
||||
void getSkinningDualQuat(vec4 weights, out vec4 A, inout vec4 B) {
|
||||
// Retrieve the real and dual part of the dual-quaternions
|
||||
mat4 matA, matB;
|
||||
matA[0][0] = skinBones[int(bone.x) * 8 + 0];
|
||||
matA[0][1] = skinBones[int(bone.x) * 8 + 1];
|
||||
matA[0][2] = skinBones[int(bone.x) * 8 + 2];
|
||||
matA[0][3] = skinBones[int(bone.x) * 8 + 3];
|
||||
matB[0][0] = skinBones[int(bone.x) * 8 + 4];
|
||||
matB[0][1] = skinBones[int(bone.x) * 8 + 5];
|
||||
matB[0][2] = skinBones[int(bone.x) * 8 + 6];
|
||||
matB[0][3] = skinBones[int(bone.x) * 8 + 7];
|
||||
matA[1][0] = skinBones[int(bone.y) * 8 + 0];
|
||||
matA[1][1] = skinBones[int(bone.y) * 8 + 1];
|
||||
matA[1][2] = skinBones[int(bone.y) * 8 + 2];
|
||||
matA[1][3] = skinBones[int(bone.y) * 8 + 3];
|
||||
matB[1][0] = skinBones[int(bone.y) * 8 + 4];
|
||||
matB[1][1] = skinBones[int(bone.y) * 8 + 5];
|
||||
matB[1][2] = skinBones[int(bone.y) * 8 + 6];
|
||||
matB[1][3] = skinBones[int(bone.y) * 8 + 7];
|
||||
matA[2][0] = skinBones[int(bone.z) * 8 + 0];
|
||||
matA[2][1] = skinBones[int(bone.z) * 8 + 1];
|
||||
matA[2][2] = skinBones[int(bone.z) * 8 + 2];
|
||||
matA[2][3] = skinBones[int(bone.z) * 8 + 3];
|
||||
matB[2][0] = skinBones[int(bone.z) * 8 + 4];
|
||||
matB[2][1] = skinBones[int(bone.z) * 8 + 5];
|
||||
matB[2][2] = skinBones[int(bone.z) * 8 + 6];
|
||||
matB[2][3] = skinBones[int(bone.z) * 8 + 7];
|
||||
matA[3][0] = skinBones[int(bone.w) * 8 + 0];
|
||||
matA[3][1] = skinBones[int(bone.w) * 8 + 1];
|
||||
matA[3][2] = skinBones[int(bone.w) * 8 + 2];
|
||||
matA[3][3] = skinBones[int(bone.w) * 8 + 3];
|
||||
matB[3][0] = skinBones[int(bone.w) * 8 + 4];
|
||||
matB[3][1] = skinBones[int(bone.w) * 8 + 5];
|
||||
matB[3][2] = skinBones[int(bone.w) * 8 + 6];
|
||||
matB[3][3] = skinBones[int(bone.w) * 8 + 7];
|
||||
// Handles antipodality by sticking joints in the same neighbourhood
|
||||
// weights.xyz *= sign(matA[3] * mat3x4(matA)).xyz;
|
||||
weights.xyz *= sign(matA[3] * matA).xyz;
|
||||
// Apply weights
|
||||
A = matA * weights; // Real part
|
||||
B = matB * weights; // Dual part
|
||||
// Normalize
|
||||
float invNormA = 1.0 / length(A);
|
||||
A *= invNormA;
|
||||
B *= invNormA;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -91,11 +108,18 @@ void main() {
|
|||
#else
|
||||
vec4 sPos = (vec4(pos, 1.0));
|
||||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
mat4 skinningMat = getSkinningMat();
|
||||
mat3 skinningMatVec = getSkinningMatVec(skinningMat);
|
||||
sPos = sPos * skinningMat;
|
||||
vec4 skinA;
|
||||
vec4 skinB;
|
||||
getSkinningDualQuat(weight, skinA, skinB);
|
||||
sPos.xyz += 2.0 * cross(skinA.xyz, cross(skinA.xyz, sPos.xyz) + skinA.w * sPos.xyz); // Rotate
|
||||
sPos.xyz += 2.0 * (skinA.w * skinB.xyz - skinB.w * skinA.xyz + cross(skinA.xyz, skinB.xyz)); // Translate
|
||||
vec3 _normal = normalize(mat3(N) * (nor + 2.0 * cross(skinA.xyz, cross(skinA.xyz, nor) + skinA.w * nor)));
|
||||
#else
|
||||
vec3 _normal = normalize(mat3(N) * nor);
|
||||
#endif
|
||||
|
||||
lPos = LWVP * sPos;
|
||||
|
||||
#ifdef _Billboard
|
||||
|
@ -115,12 +139,6 @@ void main() {
|
|||
texCoord = tex;
|
||||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
vec3 _normal = normalize(mat3(N) * (nor * skinningMatVec));
|
||||
#else
|
||||
vec3 _normal = normalize(mat3(N) * nor);
|
||||
#endif
|
||||
|
||||
matColor = albedo_color;
|
||||
|
||||
#ifdef _VCols
|
||||
|
|
|
@ -133,14 +133,14 @@ vec3 shIrradiance(vec3 nor, float scale) {
|
|||
}
|
||||
|
||||
void main() {
|
||||
vec4 g0 = texture(gbuffer0, texCoord); // Normal.xy, roughness/metallic, mask
|
||||
vec4 g0 = texture(gbuffer0, texCoord); // Normal.xy, metallic/roughness, mask
|
||||
|
||||
vec3 n;
|
||||
n.z = 1.0 - abs(g0.x) - abs(g0.y);
|
||||
n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy);
|
||||
n = normalize(n);
|
||||
|
||||
vec2 roughmet = unpackFloat(g0.b);
|
||||
vec2 metrough = unpackFloat(g0.b);
|
||||
|
||||
#ifdef _Rad
|
||||
float depth = texture(gbufferD, texCoord).r * 2.0 - 1.0;
|
||||
|
@ -155,7 +155,7 @@ void main() {
|
|||
float probeFract = fract(probeFactor);
|
||||
vec3 indirect;
|
||||
#ifdef _Rad
|
||||
float lod = getMipLevelFromRoughness(roughmet.x);
|
||||
float lod = getMipLevelFromRoughness(metrough.y);
|
||||
vec3 reflectionWorld = reflect(-v, n);
|
||||
vec2 envCoordRefl = envMapEquirect(reflectionWorld);
|
||||
vec3 prefilteredColor = textureLod(senvmapRadiance, envCoordRefl, lod).rgb;
|
||||
|
@ -178,7 +178,7 @@ void main() {
|
|||
vec3 indirect = shIrradiance(n, 2.2) / PI;
|
||||
#ifdef _Rad
|
||||
vec3 reflectionWorld = reflect(-v, n);
|
||||
float lod = getMipLevelFromRoughness(roughmet.x);
|
||||
float lod = getMipLevelFromRoughness(metrough.y);
|
||||
vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;
|
||||
#endif
|
||||
#endif
|
||||
|
@ -191,16 +191,16 @@ void main() {
|
|||
#endif
|
||||
|
||||
vec4 g1 = texture(gbuffer1, texCoord); // Basecolor.rgb, occlusion
|
||||
vec3 albedo = surfaceAlbedo(g1.rgb, roughmet.y); // g1.rgb - basecolor
|
||||
vec3 albedo = surfaceAlbedo(g1.rgb, metrough.x); // g1.rgb - basecolor
|
||||
indirect *= albedo;
|
||||
|
||||
#ifdef _Rad
|
||||
// Indirect specular
|
||||
float dotNV = max(dot(n, v), 0.0);
|
||||
|
||||
vec3 f0 = surfaceF0(g1.rgb, roughmet.y);
|
||||
vec3 f0 = surfaceF0(g1.rgb, metrough.x);
|
||||
|
||||
vec2 envBRDF = texture(senvmapBrdf, vec2(roughmet.x, 1.0 - dotNV)).xy;
|
||||
vec2 envBRDF = texture(senvmapBrdf, vec2(metrough.y, 1.0 - dotNV)).xy;
|
||||
indirect += prefilteredColor * (f0 * envBRDF.x + envBRDF.y);;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -131,7 +131,24 @@ vec3 specularBRDF(vec3 f0, float roughness, float nl, float nh, float nv, float
|
|||
float a = roughness * roughness;
|
||||
return d_ggx(nh, a) * clamp(v_smithschlick(nl, nv, a), 0.0, 1.0) * f_schlick(f0, vh) / 4.0;
|
||||
}
|
||||
|
||||
// vec3 burleyDiffuseBRDF(vec3 albedo, float roughness, float nv, float nl, float vh) {
|
||||
// float FD90 = 0.5 + 2.0 * vh * vh * roughness;
|
||||
// float FdV = 1.0 + (FD90 - 1.0) * pow(1.0 - nv, 5.0);
|
||||
// float FdL = 1.0 + (FD90 - 1.0) * pow(1.0 - nl, 5.0);
|
||||
// return albedo * ((1.0 / 3.1415926535) * FdV * FdL);
|
||||
// }
|
||||
// vec3 orenNayarDiffuseBRDF(vec3 albedo, float roughness, float nv, float nl, float vh) {
|
||||
// float a = roughness * roughness;
|
||||
// float s = a;// / (1.29 + 0.5 * a);
|
||||
// float s2 = s * s;
|
||||
// float vl = 2.0 * vh * vh - 1.0; // double angle identity
|
||||
// float Cosri = vl - nv * nl;
|
||||
// float C1 = 1.0 - 0.5 * s2 / (s2 + 0.33);
|
||||
// float test = 1.0;
|
||||
// if (Cosri >= 0.0) test = (1.0 / (max(nl, nv)));
|
||||
// float C2 = 0.45 * s2 / (s2 + 0.09) * Cosri * test;
|
||||
// return albedo / PI * (C1 + C2) * (1.0 + roughness * 0.5);
|
||||
// }
|
||||
vec3 diffuseBRDF(vec3 albedo, float nl) {
|
||||
// lambert
|
||||
return albedo * nl; // // albedo * max(0.0, nl);
|
||||
|
@ -684,7 +701,7 @@ void main() {
|
|||
texCoord += vec2(0.5 / screenSize); // Half pixel offset
|
||||
|
||||
float depth = texture(gbufferD, texCoord).r * 2.0 - 1.0;
|
||||
vec4 g0 = texture(gbuffer0, texCoord); // Normal.xy, roughness/metallic, mask
|
||||
vec4 g0 = texture(gbuffer0, texCoord); // Normal.xy, metallic/roughness, mask
|
||||
vec4 g1 = texture(gbuffer1, texCoord); // Basecolor.rgb, occlusion
|
||||
|
||||
vec3 n;
|
||||
|
@ -694,13 +711,13 @@ void main() {
|
|||
|
||||
vec3 p = getPos(depth, texCoord);
|
||||
// vec3 p = getPos(depth);
|
||||
vec2 roughmet = unpackFloat(g0.b);
|
||||
vec2 metrough = unpackFloat(g0.b);
|
||||
|
||||
vec3 v = normalize(eye - p.xyz);
|
||||
float dotNV = max(dot(n, v), 0.0);
|
||||
|
||||
vec3 albedo = surfaceAlbedo(g1.rgb, roughmet.y); // g1.rgb - basecolor
|
||||
vec3 f0 = surfaceF0(g1.rgb, roughmet.y);
|
||||
vec3 albedo = surfaceAlbedo(g1.rgb, metrough.x); // g1.rgb - basecolor
|
||||
vec3 f0 = surfaceF0(g1.rgb, metrough.x);
|
||||
|
||||
// Per-light
|
||||
vec3 l;
|
||||
|
@ -727,8 +744,10 @@ void main() {
|
|||
#endif
|
||||
|
||||
// Direct
|
||||
vec3 direct = diffuseBRDF(albedo, dotNL) + specularBRDF(f0, roughmet.x, dotNL, dotNH, dotNV, dotVH);
|
||||
|
||||
vec3 direct = diffuseBRDF(albedo, dotNL) + specularBRDF(f0, metrough.y, dotNL, dotNH, dotNV, dotVH);
|
||||
// vec3 direct = orenNayarDiffuseBRDF(albedo, metrough.y, dotNV, dotNL, dotVH) + specularBRDF(f0, metrough.y, dotNL, dotNH, dotNV, dotVH);
|
||||
// vec3 direct = burleyDiffuseBRDF(albedo, metrough.y, dotNV, dotNL, dotVH) + specularBRDF(f0, metrough.y, dotNL, dotNH, dotNV, dotVH);
|
||||
|
||||
if (lightType == 2) { // Spot
|
||||
float spotEffect = dot(lightDir, l);
|
||||
if (spotEffect < spotlightCutoff) {
|
||||
|
@ -738,10 +757,10 @@ void main() {
|
|||
}
|
||||
|
||||
// Aniso spec
|
||||
// float shinyParallel = roughmet.x;
|
||||
// float shinyParallel = metrough.y;
|
||||
// float shinyPerpendicular = 0.08;
|
||||
// vec3 fiberDirection = vec3(0.0, 1.0, 8.0);
|
||||
// vec3 direct = diffuseBRDF(albedo, roughmet.x, dotNV, dotNL, dotVH, dotLV) + wardSpecular(n, h, dotNL, dotNV, dotNH, fiberDirection, shinyParallel, shinyPerpendicular);
|
||||
// vec3 direct = diffuseBRDF(albedo, metrough.y, dotNV, dotNL, dotVH, dotLV) + wardSpecular(n, h, dotNL, dotNV, dotNH, fiberDirection, shinyParallel, shinyPerpendicular);
|
||||
direct = direct * lightColor * lightStrength;
|
||||
|
||||
|
||||
|
@ -763,7 +782,7 @@ void main() {
|
|||
// float probeFract = fract(probeFactor);
|
||||
// vec3 indirect;
|
||||
// #ifdef _Rad
|
||||
// float lod = getMipLevelFromRoughness(roughmet.x);
|
||||
// float lod = getMipLevelFromRoughness(metrough.y);
|
||||
// vec3 reflectionWorld = reflect(-v, n);
|
||||
// vec2 envCoordRefl = envMapEquirect(reflectionWorld);
|
||||
// vec3 prefilteredColor = textureLod(senvmapRadiance, envCoordRefl, lod).rgb;
|
||||
|
@ -786,7 +805,7 @@ void main() {
|
|||
// vec3 indirect = shIrradiance(n, 2.2) / PI;
|
||||
// #ifdef _Rad
|
||||
// vec3 reflectionWorld = reflect(-v, n);
|
||||
// float lod = getMipLevelFromRoughness(roughmet.x);
|
||||
// float lod = getMipLevelFromRoughness(metrough.y);
|
||||
// vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;
|
||||
// #endif
|
||||
// #endif
|
||||
|
@ -801,7 +820,7 @@ void main() {
|
|||
|
||||
// #ifdef _Rad
|
||||
// // Indirect specular
|
||||
// vec2 envBRDF = texture(senvmapBrdf, vec2(roughmet.x, 1.0 - dotNV)).xy;
|
||||
// vec2 envBRDF = texture(senvmapBrdf, vec2(metrough.y, 1.0 - dotNV)).xy;
|
||||
// indirect += prefilteredColor * (f0 * envBRDF.x + envBRDF.y);;
|
||||
// #endif
|
||||
// indirect = indirect * envmapStrength;// * lightColor * lightStrength;
|
||||
|
@ -832,7 +851,7 @@ void main() {
|
|||
// vec3 p3 = lightPos + ex - ey;
|
||||
// vec3 p4 = lightPos - ex - ey;
|
||||
// float theta = acos(dotNV);
|
||||
// vec2 tuv = vec2(roughmet.x, theta/(0.5*PI));
|
||||
// vec2 tuv = vec2(metrough.y, theta/(0.5*PI));
|
||||
// tuv = tuv*LUT_SCALE + LUT_BIAS;
|
||||
|
||||
// vec4 t = texture(sltcMat, tuv);
|
||||
|
|
|
@ -6,10 +6,6 @@ precision highp float;
|
|||
|
||||
#include "../compiled.glsl"
|
||||
|
||||
#ifdef _NorTex
|
||||
#define _Tex
|
||||
#endif
|
||||
|
||||
in vec3 pos;
|
||||
in vec3 nor;
|
||||
#ifdef _BaseTex
|
||||
|
@ -37,7 +33,7 @@ uniform mat4 LWVP;
|
|||
uniform vec4 albedo_color;
|
||||
uniform vec3 eye;
|
||||
#ifdef _Skinning
|
||||
uniform float skinBones[skinMaxBones * 12];
|
||||
uniform float skinBones[skinMaxBones * 8];
|
||||
#endif
|
||||
#ifdef _VR
|
||||
uniform mat4 U; // Undistortion
|
||||
|
@ -58,34 +54,51 @@ out vec3 eyeDir;
|
|||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
mat4 getBoneMat(const int boneIndex) {
|
||||
vec4 v0 = vec4(skinBones[boneIndex * 12 + 0],
|
||||
skinBones[boneIndex * 12 + 1],
|
||||
skinBones[boneIndex * 12 + 2],
|
||||
skinBones[boneIndex * 12 + 3]);
|
||||
vec4 v1 = vec4(skinBones[boneIndex * 12 + 4],
|
||||
skinBones[boneIndex * 12 + 5],
|
||||
skinBones[boneIndex * 12 + 6],
|
||||
skinBones[boneIndex * 12 + 7]);
|
||||
vec4 v2 = vec4(skinBones[boneIndex * 12 + 8],
|
||||
skinBones[boneIndex * 12 + 9],
|
||||
skinBones[boneIndex * 12 + 10],
|
||||
skinBones[boneIndex * 12 + 11]);
|
||||
return mat4(v0.x, v0.y, v0.z, v0.w,
|
||||
v1.x, v1.y, v1.z, v1.w,
|
||||
v2.x, v2.y, v2.z, v2.w,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
mat4 getSkinningMat() {
|
||||
return weight.x * getBoneMat(int(bone.x)) +
|
||||
weight.y * getBoneMat(int(bone.y)) +
|
||||
weight.z * getBoneMat(int(bone.z)) +
|
||||
weight.w * getBoneMat(int(bone.w));
|
||||
}
|
||||
|
||||
mat3 getSkinningMatVec(const mat4 skinningMat) {
|
||||
return mat3(skinningMat[0].xyz, skinningMat[1].xyz, skinningMat[2].xyz);
|
||||
void getSkinningDualQuat(vec4 weights, out vec4 A, inout vec4 B) {
|
||||
// Retrieve the real and dual part of the dual-quaternions
|
||||
mat4 matA, matB;
|
||||
matA[0][0] = skinBones[int(bone.x) * 8 + 0];
|
||||
matA[0][1] = skinBones[int(bone.x) * 8 + 1];
|
||||
matA[0][2] = skinBones[int(bone.x) * 8 + 2];
|
||||
matA[0][3] = skinBones[int(bone.x) * 8 + 3];
|
||||
matB[0][0] = skinBones[int(bone.x) * 8 + 4];
|
||||
matB[0][1] = skinBones[int(bone.x) * 8 + 5];
|
||||
matB[0][2] = skinBones[int(bone.x) * 8 + 6];
|
||||
matB[0][3] = skinBones[int(bone.x) * 8 + 7];
|
||||
matA[1][0] = skinBones[int(bone.y) * 8 + 0];
|
||||
matA[1][1] = skinBones[int(bone.y) * 8 + 1];
|
||||
matA[1][2] = skinBones[int(bone.y) * 8 + 2];
|
||||
matA[1][3] = skinBones[int(bone.y) * 8 + 3];
|
||||
matB[1][0] = skinBones[int(bone.y) * 8 + 4];
|
||||
matB[1][1] = skinBones[int(bone.y) * 8 + 5];
|
||||
matB[1][2] = skinBones[int(bone.y) * 8 + 6];
|
||||
matB[1][3] = skinBones[int(bone.y) * 8 + 7];
|
||||
matA[2][0] = skinBones[int(bone.z) * 8 + 0];
|
||||
matA[2][1] = skinBones[int(bone.z) * 8 + 1];
|
||||
matA[2][2] = skinBones[int(bone.z) * 8 + 2];
|
||||
matA[2][3] = skinBones[int(bone.z) * 8 + 3];
|
||||
matB[2][0] = skinBones[int(bone.z) * 8 + 4];
|
||||
matB[2][1] = skinBones[int(bone.z) * 8 + 5];
|
||||
matB[2][2] = skinBones[int(bone.z) * 8 + 6];
|
||||
matB[2][3] = skinBones[int(bone.z) * 8 + 7];
|
||||
matA[3][0] = skinBones[int(bone.w) * 8 + 0];
|
||||
matA[3][1] = skinBones[int(bone.w) * 8 + 1];
|
||||
matA[3][2] = skinBones[int(bone.w) * 8 + 2];
|
||||
matA[3][3] = skinBones[int(bone.w) * 8 + 3];
|
||||
matB[3][0] = skinBones[int(bone.w) * 8 + 4];
|
||||
matB[3][1] = skinBones[int(bone.w) * 8 + 5];
|
||||
matB[3][2] = skinBones[int(bone.w) * 8 + 6];
|
||||
matB[3][3] = skinBones[int(bone.w) * 8 + 7];
|
||||
// Handles antipodality by sticking joints in the same neighbourhood
|
||||
// weights.xyz *= sign(matA[3] * mat3x4(matA)).xyz;
|
||||
weights.xyz *= sign(matA[3] * matA).xyz;
|
||||
// Apply weights
|
||||
A = matA * weights; // Real part
|
||||
B = matB * weights; // Dual part
|
||||
// Normalize
|
||||
float invNormA = 1.0 / length(A);
|
||||
A *= invNormA;
|
||||
B *= invNormA;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -103,15 +116,15 @@ float distortionFactor(float rSquared) {
|
|||
}
|
||||
// Convert point from world space to undistorted camera space
|
||||
vec4 undistort(mat4 WV, vec4 pos) {
|
||||
// Go to camera space
|
||||
pos = WV * pos;
|
||||
const float nearClip = 0.1;
|
||||
if (pos.z <= -nearClip) { // Reminder: Forward is -Z
|
||||
// Undistort the point's coordinates in XY
|
||||
float r2 = clamp(dot(pos.xy, pos.xy) / (pos.z * pos.z), 0.0, maxRadSq);
|
||||
pos.xy *= distortionFactor(r2);
|
||||
}
|
||||
return pos;
|
||||
// Go to camera space
|
||||
pos = WV * pos;
|
||||
const float nearClip = 0.1;
|
||||
if (pos.z <= -nearClip) { // Reminder: Forward is -Z
|
||||
// Undistort the point's coordinates in XY
|
||||
float r2 = clamp(dot(pos.xy, pos.xy) / (pos.z * pos.z), 0.0, maxRadSq);
|
||||
pos.xy *= distortionFactor(r2);
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -122,11 +135,18 @@ void main() {
|
|||
#else
|
||||
vec4 sPos = (vec4(pos, 1.0));
|
||||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
mat4 skinningMat = getSkinningMat();
|
||||
mat3 skinningMatVec = getSkinningMatVec(skinningMat);
|
||||
sPos = sPos * skinningMat;
|
||||
vec4 skinA;
|
||||
vec4 skinB;
|
||||
getSkinningDualQuat(weight, skinA, skinB);
|
||||
sPos.xyz += 2.0 * cross(skinA.xyz, cross(skinA.xyz, sPos.xyz) + skinA.w * sPos.xyz); // Rotate
|
||||
sPos.xyz += 2.0 * (skinA.w * skinB.xyz - skinB.w * skinA.xyz + cross(skinA.xyz, skinB.xyz)); // Translate
|
||||
vec3 _normal = normalize(mat3(N) * (nor + 2.0 * cross(skinA.xyz, cross(skinA.xyz, nor) + skinA.w * nor)));
|
||||
#else
|
||||
vec3 _normal = normalize(mat3(N) * nor);
|
||||
#endif
|
||||
|
||||
lPos = LWVP * sPos;
|
||||
|
||||
mat4 WV = V * W;
|
||||
|
@ -151,12 +171,6 @@ void main() {
|
|||
texCoord = tex;
|
||||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
vec3 _normal = normalize(mat3(N) * (nor * skinningMatVec));
|
||||
#else
|
||||
vec3 _normal = normalize(mat3(N) * nor);
|
||||
#endif
|
||||
|
||||
matColor = albedo_color;
|
||||
|
||||
#ifdef _VCols
|
||||
|
|
|
@ -54,34 +54,51 @@ out vec3 eyeDir;
|
|||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
mat4 getBoneMat(const int boneIndex) {
|
||||
vec4 v0 = vec4(skinBones[boneIndex * 12 + 0],
|
||||
skinBones[boneIndex * 12 + 1],
|
||||
skinBones[boneIndex * 12 + 2],
|
||||
skinBones[boneIndex * 12 + 3]);
|
||||
vec4 v1 = vec4(skinBones[boneIndex * 12 + 4],
|
||||
skinBones[boneIndex * 12 + 5],
|
||||
skinBones[boneIndex * 12 + 6],
|
||||
skinBones[boneIndex * 12 + 7]);
|
||||
vec4 v2 = vec4(skinBones[boneIndex * 12 + 8],
|
||||
skinBones[boneIndex * 12 + 9],
|
||||
skinBones[boneIndex * 12 + 10],
|
||||
skinBones[boneIndex * 12 + 11]);
|
||||
return mat4(v0.x, v0.y, v0.z, v0.w,
|
||||
v1.x, v1.y, v1.z, v1.w,
|
||||
v2.x, v2.y, v2.z, v2.w,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
mat4 getSkinningMat() {
|
||||
return weight.x * getBoneMat(int(bone.x)) +
|
||||
weight.y * getBoneMat(int(bone.y)) +
|
||||
weight.z * getBoneMat(int(bone.z)) +
|
||||
weight.w * getBoneMat(int(bone.w));
|
||||
}
|
||||
|
||||
mat3 getSkinningMatVec(const mat4 skinningMat) {
|
||||
return mat3(skinningMat[0].xyz, skinningMat[1].xyz, skinningMat[2].xyz);
|
||||
void getSkinningDualQuat(vec4 weights, out vec4 A, inout vec4 B) {
|
||||
// Retrieve the real and dual part of the dual-quaternions
|
||||
mat4 matA, matB;
|
||||
matA[0][0] = skinBones[int(bone.x) * 8 + 0];
|
||||
matA[0][1] = skinBones[int(bone.x) * 8 + 1];
|
||||
matA[0][2] = skinBones[int(bone.x) * 8 + 2];
|
||||
matA[0][3] = skinBones[int(bone.x) * 8 + 3];
|
||||
matB[0][0] = skinBones[int(bone.x) * 8 + 4];
|
||||
matB[0][1] = skinBones[int(bone.x) * 8 + 5];
|
||||
matB[0][2] = skinBones[int(bone.x) * 8 + 6];
|
||||
matB[0][3] = skinBones[int(bone.x) * 8 + 7];
|
||||
matA[1][0] = skinBones[int(bone.y) * 8 + 0];
|
||||
matA[1][1] = skinBones[int(bone.y) * 8 + 1];
|
||||
matA[1][2] = skinBones[int(bone.y) * 8 + 2];
|
||||
matA[1][3] = skinBones[int(bone.y) * 8 + 3];
|
||||
matB[1][0] = skinBones[int(bone.y) * 8 + 4];
|
||||
matB[1][1] = skinBones[int(bone.y) * 8 + 5];
|
||||
matB[1][2] = skinBones[int(bone.y) * 8 + 6];
|
||||
matB[1][3] = skinBones[int(bone.y) * 8 + 7];
|
||||
matA[2][0] = skinBones[int(bone.z) * 8 + 0];
|
||||
matA[2][1] = skinBones[int(bone.z) * 8 + 1];
|
||||
matA[2][2] = skinBones[int(bone.z) * 8 + 2];
|
||||
matA[2][3] = skinBones[int(bone.z) * 8 + 3];
|
||||
matB[2][0] = skinBones[int(bone.z) * 8 + 4];
|
||||
matB[2][1] = skinBones[int(bone.z) * 8 + 5];
|
||||
matB[2][2] = skinBones[int(bone.z) * 8 + 6];
|
||||
matB[2][3] = skinBones[int(bone.z) * 8 + 7];
|
||||
matA[3][0] = skinBones[int(bone.w) * 8 + 0];
|
||||
matA[3][1] = skinBones[int(bone.w) * 8 + 1];
|
||||
matA[3][2] = skinBones[int(bone.w) * 8 + 2];
|
||||
matA[3][3] = skinBones[int(bone.w) * 8 + 3];
|
||||
matB[3][0] = skinBones[int(bone.w) * 8 + 4];
|
||||
matB[3][1] = skinBones[int(bone.w) * 8 + 5];
|
||||
matB[3][2] = skinBones[int(bone.w) * 8 + 6];
|
||||
matB[3][3] = skinBones[int(bone.w) * 8 + 7];
|
||||
// Handles antipodality by sticking joints in the same neighbourhood
|
||||
// weights.xyz *= sign(matA[3] * mat3x4(matA)).xyz;
|
||||
weights.xyz *= sign(matA[3] * matA).xyz;
|
||||
// Apply weights
|
||||
A = matA * weights; // Real part
|
||||
B = matB * weights; // Dual part
|
||||
// Normalize
|
||||
float invNormA = 1.0 / length(A);
|
||||
A *= invNormA;
|
||||
B *= invNormA;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -92,11 +109,18 @@ void main() {
|
|||
#else
|
||||
vec4 sPos = (vec4(pos, 1.0));
|
||||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
mat4 skinningMat = getSkinningMat();
|
||||
mat3 skinningMatVec = getSkinningMatVec(skinningMat);
|
||||
sPos = sPos * skinningMat;
|
||||
vec4 skinA;
|
||||
vec4 skinB;
|
||||
getSkinningDualQuat(weight, skinA, skinB);
|
||||
sPos.xyz += 2.0 * cross(skinA.xyz, cross(skinA.xyz, sPos.xyz) + skinA.w * sPos.xyz); // Rotate
|
||||
sPos.xyz += 2.0 * (skinA.w * skinB.xyz - skinB.w * skinA.xyz + cross(skinA.xyz, skinB.xyz)); // Translate
|
||||
vec3 _normal = normalize(mat3(N) * (nor + 2.0 * cross(skinA.xyz, cross(skinA.xyz, nor) + skinA.w * nor)));
|
||||
#else
|
||||
vec3 _normal = normalize(mat3(N) * nor);
|
||||
#endif
|
||||
|
||||
lPos = LWVP * sPos;
|
||||
|
||||
mat4 WV = V * W;
|
||||
|
@ -117,12 +141,6 @@ void main() {
|
|||
texCoord = tex;
|
||||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
vec3 _normal = normalize(mat3(N) * (nor * skinningMatVec));
|
||||
#else
|
||||
vec3 _normal = normalize(mat3(N) * nor);
|
||||
#endif
|
||||
|
||||
matColor = albedo_color;
|
||||
|
||||
#ifdef _VCols
|
||||
|
|
|
@ -38,34 +38,51 @@ uniform mat4 LWVP;
|
|||
// out vec4 position;
|
||||
|
||||
#ifdef _Skinning
|
||||
mat4 getBoneMat(const int boneIndex) {
|
||||
vec4 v0 = vec4(skinBones[boneIndex * 12 + 0],
|
||||
skinBones[boneIndex * 12 + 1],
|
||||
skinBones[boneIndex * 12 + 2],
|
||||
skinBones[boneIndex * 12 + 3]);
|
||||
vec4 v1 = vec4(skinBones[boneIndex * 12 + 4],
|
||||
skinBones[boneIndex * 12 + 5],
|
||||
skinBones[boneIndex * 12 + 6],
|
||||
skinBones[boneIndex * 12 + 7]);
|
||||
vec4 v2 = vec4(skinBones[boneIndex * 12 + 8],
|
||||
skinBones[boneIndex * 12 + 9],
|
||||
skinBones[boneIndex * 12 + 10],
|
||||
skinBones[boneIndex * 12 + 11]);
|
||||
return mat4(v0.x, v0.y, v0.z, v0.w,
|
||||
v1.x, v1.y, v1.z, v1.w,
|
||||
v2.x, v2.y, v2.z, v2.w,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
mat4 getSkinningMat() {
|
||||
return weight.x * getBoneMat(int(bone.x)) +
|
||||
weight.y * getBoneMat(int(bone.y)) +
|
||||
weight.z * getBoneMat(int(bone.z)) +
|
||||
weight.w * getBoneMat(int(bone.w));
|
||||
}
|
||||
|
||||
mat3 getSkinningMatVec(const mat4 skinningMat) {
|
||||
return mat3(skinningMat[0].xyz, skinningMat[1].xyz, skinningMat[2].xyz);
|
||||
void getSkinningDualQuat(vec4 weights, out vec4 A, inout vec4 B) {
|
||||
// Retrieve the real and dual part of the dual-quaternions
|
||||
mat4 matA, matB;
|
||||
matA[0][0] = skinBones[int(bone.x) * 8 + 0];
|
||||
matA[0][1] = skinBones[int(bone.x) * 8 + 1];
|
||||
matA[0][2] = skinBones[int(bone.x) * 8 + 2];
|
||||
matA[0][3] = skinBones[int(bone.x) * 8 + 3];
|
||||
matB[0][0] = skinBones[int(bone.x) * 8 + 4];
|
||||
matB[0][1] = skinBones[int(bone.x) * 8 + 5];
|
||||
matB[0][2] = skinBones[int(bone.x) * 8 + 6];
|
||||
matB[0][3] = skinBones[int(bone.x) * 8 + 7];
|
||||
matA[1][0] = skinBones[int(bone.y) * 8 + 0];
|
||||
matA[1][1] = skinBones[int(bone.y) * 8 + 1];
|
||||
matA[1][2] = skinBones[int(bone.y) * 8 + 2];
|
||||
matA[1][3] = skinBones[int(bone.y) * 8 + 3];
|
||||
matB[1][0] = skinBones[int(bone.y) * 8 + 4];
|
||||
matB[1][1] = skinBones[int(bone.y) * 8 + 5];
|
||||
matB[1][2] = skinBones[int(bone.y) * 8 + 6];
|
||||
matB[1][3] = skinBones[int(bone.y) * 8 + 7];
|
||||
matA[2][0] = skinBones[int(bone.z) * 8 + 0];
|
||||
matA[2][1] = skinBones[int(bone.z) * 8 + 1];
|
||||
matA[2][2] = skinBones[int(bone.z) * 8 + 2];
|
||||
matA[2][3] = skinBones[int(bone.z) * 8 + 3];
|
||||
matB[2][0] = skinBones[int(bone.z) * 8 + 4];
|
||||
matB[2][1] = skinBones[int(bone.z) * 8 + 5];
|
||||
matB[2][2] = skinBones[int(bone.z) * 8 + 6];
|
||||
matB[2][3] = skinBones[int(bone.z) * 8 + 7];
|
||||
matA[3][0] = skinBones[int(bone.w) * 8 + 0];
|
||||
matA[3][1] = skinBones[int(bone.w) * 8 + 1];
|
||||
matA[3][2] = skinBones[int(bone.w) * 8 + 2];
|
||||
matA[3][3] = skinBones[int(bone.w) * 8 + 3];
|
||||
matB[3][0] = skinBones[int(bone.w) * 8 + 4];
|
||||
matB[3][1] = skinBones[int(bone.w) * 8 + 5];
|
||||
matB[3][2] = skinBones[int(bone.w) * 8 + 6];
|
||||
matB[3][3] = skinBones[int(bone.w) * 8 + 7];
|
||||
// Handles antipodality by sticking joints in the same neighbourhood
|
||||
// weights.xyz *= sign(matA[3] * mat3x4(matA)).xyz;
|
||||
weights.xyz *= sign(matA[3] * matA).xyz;
|
||||
// Apply weights
|
||||
A = matA * weights; // Real part
|
||||
B = matB * weights; // Dual part
|
||||
// Normalize
|
||||
float invNormA = 1.0 / length(A);
|
||||
A *= invNormA;
|
||||
B *= invNormA;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -77,9 +94,11 @@ void main() {
|
|||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
mat4 skinningMat = getSkinningMat();
|
||||
mat3 skinningMatVec = getSkinningMatVec(skinningMat);
|
||||
sPos = sPos * skinningMat;
|
||||
vec4 skinA;
|
||||
vec4 skinB;
|
||||
getSkinningDualQuat(weight, skinA, skinB);
|
||||
sPos.xyz += 2.0 * cross(skinA.xyz, cross(skinA.xyz, sPos.xyz) + skinA.w * sPos.xyz); // Rotate
|
||||
sPos.xyz += 2.0 * (skinA.w * skinB.xyz - skinB.w * skinA.xyz + cross(skinA.xyz, skinB.xyz)); // Translate
|
||||
#endif
|
||||
|
||||
gl_Position = LWVP * sPos;
|
||||
|
|
|
@ -27,38 +27,55 @@ in vec3 nor;
|
|||
|
||||
uniform mat4 WVP;
|
||||
#ifdef _Skinning
|
||||
uniform float skinBones[skinMaxBones * 12];
|
||||
uniform float skinBones[skinMaxBones * 8];
|
||||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
mat4 getBoneMat(const int boneIndex) {
|
||||
vec4 v0 = vec4(skinBones[boneIndex * 12 + 0],
|
||||
skinBones[boneIndex * 12 + 1],
|
||||
skinBones[boneIndex * 12 + 2],
|
||||
skinBones[boneIndex * 12 + 3]);
|
||||
vec4 v1 = vec4(skinBones[boneIndex * 12 + 4],
|
||||
skinBones[boneIndex * 12 + 5],
|
||||
skinBones[boneIndex * 12 + 6],
|
||||
skinBones[boneIndex * 12 + 7]);
|
||||
vec4 v2 = vec4(skinBones[boneIndex * 12 + 8],
|
||||
skinBones[boneIndex * 12 + 9],
|
||||
skinBones[boneIndex * 12 + 10],
|
||||
skinBones[boneIndex * 12 + 11]);
|
||||
return mat4(v0.x, v0.y, v0.z, v0.w,
|
||||
v1.x, v1.y, v1.z, v1.w,
|
||||
v2.x, v2.y, v2.z, v2.w,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
mat4 getSkinningMat() {
|
||||
return weight.x * getBoneMat(int(bone.x)) +
|
||||
weight.y * getBoneMat(int(bone.y)) +
|
||||
weight.z * getBoneMat(int(bone.z)) +
|
||||
weight.w * getBoneMat(int(bone.w));
|
||||
}
|
||||
|
||||
mat3 getSkinningMatVec(const mat4 skinningMat) {
|
||||
return mat3(skinningMat[0].xyz, skinningMat[1].xyz, skinningMat[2].xyz);
|
||||
void getSkinningDualQuat(vec4 weights, out vec4 A, inout vec4 B) {
|
||||
// Retrieve the real and dual part of the dual-quaternions
|
||||
mat4 matA, matB;
|
||||
matA[0][0] = skinBones[int(bone.x) * 8 + 0];
|
||||
matA[0][1] = skinBones[int(bone.x) * 8 + 1];
|
||||
matA[0][2] = skinBones[int(bone.x) * 8 + 2];
|
||||
matA[0][3] = skinBones[int(bone.x) * 8 + 3];
|
||||
matB[0][0] = skinBones[int(bone.x) * 8 + 4];
|
||||
matB[0][1] = skinBones[int(bone.x) * 8 + 5];
|
||||
matB[0][2] = skinBones[int(bone.x) * 8 + 6];
|
||||
matB[0][3] = skinBones[int(bone.x) * 8 + 7];
|
||||
matA[1][0] = skinBones[int(bone.y) * 8 + 0];
|
||||
matA[1][1] = skinBones[int(bone.y) * 8 + 1];
|
||||
matA[1][2] = skinBones[int(bone.y) * 8 + 2];
|
||||
matA[1][3] = skinBones[int(bone.y) * 8 + 3];
|
||||
matB[1][0] = skinBones[int(bone.y) * 8 + 4];
|
||||
matB[1][1] = skinBones[int(bone.y) * 8 + 5];
|
||||
matB[1][2] = skinBones[int(bone.y) * 8 + 6];
|
||||
matB[1][3] = skinBones[int(bone.y) * 8 + 7];
|
||||
matA[2][0] = skinBones[int(bone.z) * 8 + 0];
|
||||
matA[2][1] = skinBones[int(bone.z) * 8 + 1];
|
||||
matA[2][2] = skinBones[int(bone.z) * 8 + 2];
|
||||
matA[2][3] = skinBones[int(bone.z) * 8 + 3];
|
||||
matB[2][0] = skinBones[int(bone.z) * 8 + 4];
|
||||
matB[2][1] = skinBones[int(bone.z) * 8 + 5];
|
||||
matB[2][2] = skinBones[int(bone.z) * 8 + 6];
|
||||
matB[2][3] = skinBones[int(bone.z) * 8 + 7];
|
||||
matA[3][0] = skinBones[int(bone.w) * 8 + 0];
|
||||
matA[3][1] = skinBones[int(bone.w) * 8 + 1];
|
||||
matA[3][2] = skinBones[int(bone.w) * 8 + 2];
|
||||
matA[3][3] = skinBones[int(bone.w) * 8 + 3];
|
||||
matB[3][0] = skinBones[int(bone.w) * 8 + 4];
|
||||
matB[3][1] = skinBones[int(bone.w) * 8 + 5];
|
||||
matB[3][2] = skinBones[int(bone.w) * 8 + 6];
|
||||
matB[3][3] = skinBones[int(bone.w) * 8 + 7];
|
||||
// Handles antipodality by sticking joints in the same neighbourhood
|
||||
// weights.xyz *= sign(matA[3] * mat3x4(matA)).xyz;
|
||||
weights.xyz *= sign(matA[3] * matA).xyz;
|
||||
// Apply weights
|
||||
A = matA * weights; // Real part
|
||||
B = matB * weights; // Dual part
|
||||
// Normalize
|
||||
float invNormA = 1.0 / length(A);
|
||||
A *= invNormA;
|
||||
B *= invNormA;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -70,9 +87,11 @@ void main() {
|
|||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
mat4 skinningMat = getSkinningMat();
|
||||
mat3 skinningMatVec = getSkinningMatVec(skinningMat);
|
||||
sPos = sPos * skinningMat;
|
||||
vec4 skinA;
|
||||
vec4 skinB;
|
||||
getSkinningDualQuat(weight, skinA, skinB);
|
||||
sPos.xyz += 2.0 * cross(skinA.xyz, cross(skinA.xyz, sPos.xyz) + skinA.w * sPos.xyz); // Rotate
|
||||
sPos.xyz += 2.0 * (skinA.w * skinB.xyz - skinB.w * skinA.xyz + cross(skinA.xyz, skinB.xyz)); // Translate
|
||||
#endif
|
||||
|
||||
gl_Position = WVP * sPos;
|
||||
|
|
|
@ -34,7 +34,7 @@ uniform mat4 LWVP;
|
|||
uniform vec4 albedo_color;
|
||||
uniform vec3 eye;
|
||||
#ifdef _Skinning
|
||||
uniform float skinBones[skinMaxBones * 12];
|
||||
uniform float skinBones[skinMaxBones * 8];
|
||||
#endif
|
||||
|
||||
out vec3 position;
|
||||
|
@ -51,34 +51,51 @@ out vec3 eyeDir;
|
|||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
mat4 getBoneMat(const int boneIndex) {
|
||||
vec4 v0 = vec4(skinBones[boneIndex * 12 + 0],
|
||||
skinBones[boneIndex * 12 + 1],
|
||||
skinBones[boneIndex * 12 + 2],
|
||||
skinBones[boneIndex * 12 + 3]);
|
||||
vec4 v1 = vec4(skinBones[boneIndex * 12 + 4],
|
||||
skinBones[boneIndex * 12 + 5],
|
||||
skinBones[boneIndex * 12 + 6],
|
||||
skinBones[boneIndex * 12 + 7]);
|
||||
vec4 v2 = vec4(skinBones[boneIndex * 12 + 8],
|
||||
skinBones[boneIndex * 12 + 9],
|
||||
skinBones[boneIndex * 12 + 10],
|
||||
skinBones[boneIndex * 12 + 11]);
|
||||
return mat4(v0.x, v0.y, v0.z, v0.w,
|
||||
v1.x, v1.y, v1.z, v1.w,
|
||||
v2.x, v2.y, v2.z, v2.w,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
mat4 getSkinningMat() {
|
||||
return weight.x * getBoneMat(int(bone.x)) +
|
||||
weight.y * getBoneMat(int(bone.y)) +
|
||||
weight.z * getBoneMat(int(bone.z)) +
|
||||
weight.w * getBoneMat(int(bone.w));
|
||||
}
|
||||
|
||||
mat3 getSkinningMatVec(const mat4 skinningMat) {
|
||||
return mat3(skinningMat[0].xyz, skinningMat[1].xyz, skinningMat[2].xyz);
|
||||
void getSkinningDualQuat(vec4 weights, out vec4 A, inout vec4 B) {
|
||||
// Retrieve the real and dual part of the dual-quaternions
|
||||
mat4 matA, matB;
|
||||
matA[0][0] = skinBones[int(bone.x) * 8 + 0];
|
||||
matA[0][1] = skinBones[int(bone.x) * 8 + 1];
|
||||
matA[0][2] = skinBones[int(bone.x) * 8 + 2];
|
||||
matA[0][3] = skinBones[int(bone.x) * 8 + 3];
|
||||
matB[0][0] = skinBones[int(bone.x) * 8 + 4];
|
||||
matB[0][1] = skinBones[int(bone.x) * 8 + 5];
|
||||
matB[0][2] = skinBones[int(bone.x) * 8 + 6];
|
||||
matB[0][3] = skinBones[int(bone.x) * 8 + 7];
|
||||
matA[1][0] = skinBones[int(bone.y) * 8 + 0];
|
||||
matA[1][1] = skinBones[int(bone.y) * 8 + 1];
|
||||
matA[1][2] = skinBones[int(bone.y) * 8 + 2];
|
||||
matA[1][3] = skinBones[int(bone.y) * 8 + 3];
|
||||
matB[1][0] = skinBones[int(bone.y) * 8 + 4];
|
||||
matB[1][1] = skinBones[int(bone.y) * 8 + 5];
|
||||
matB[1][2] = skinBones[int(bone.y) * 8 + 6];
|
||||
matB[1][3] = skinBones[int(bone.y) * 8 + 7];
|
||||
matA[2][0] = skinBones[int(bone.z) * 8 + 0];
|
||||
matA[2][1] = skinBones[int(bone.z) * 8 + 1];
|
||||
matA[2][2] = skinBones[int(bone.z) * 8 + 2];
|
||||
matA[2][3] = skinBones[int(bone.z) * 8 + 3];
|
||||
matB[2][0] = skinBones[int(bone.z) * 8 + 4];
|
||||
matB[2][1] = skinBones[int(bone.z) * 8 + 5];
|
||||
matB[2][2] = skinBones[int(bone.z) * 8 + 6];
|
||||
matB[2][3] = skinBones[int(bone.z) * 8 + 7];
|
||||
matA[3][0] = skinBones[int(bone.w) * 8 + 0];
|
||||
matA[3][1] = skinBones[int(bone.w) * 8 + 1];
|
||||
matA[3][2] = skinBones[int(bone.w) * 8 + 2];
|
||||
matA[3][3] = skinBones[int(bone.w) * 8 + 3];
|
||||
matB[3][0] = skinBones[int(bone.w) * 8 + 4];
|
||||
matB[3][1] = skinBones[int(bone.w) * 8 + 5];
|
||||
matB[3][2] = skinBones[int(bone.w) * 8 + 6];
|
||||
matB[3][3] = skinBones[int(bone.w) * 8 + 7];
|
||||
// Handles antipodality by sticking joints in the same neighbourhood
|
||||
// weights.xyz *= sign(matA[3] * mat3x4(matA)).xyz;
|
||||
weights.xyz *= sign(matA[3] * matA).xyz;
|
||||
// Apply weights
|
||||
A = matA * weights; // Real part
|
||||
B = matB * weights; // Dual part
|
||||
// Normalize
|
||||
float invNormA = 1.0 / length(A);
|
||||
A *= invNormA;
|
||||
B *= invNormA;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -89,11 +106,18 @@ void main() {
|
|||
#else
|
||||
vec4 sPos = (vec4(pos, 1.0));
|
||||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
mat4 skinningMat = getSkinningMat();
|
||||
mat3 skinningMatVec = getSkinningMatVec(skinningMat);
|
||||
sPos = sPos * skinningMat;
|
||||
vec4 skinA;
|
||||
vec4 skinB;
|
||||
getSkinningDualQuat(weight, skinA, skinB);
|
||||
sPos.xyz += 2.0 * cross(skinA.xyz, cross(skinA.xyz, sPos.xyz) + skinA.w * sPos.xyz); // Rotate
|
||||
sPos.xyz += 2.0 * (skinA.w * skinB.xyz - skinB.w * skinA.xyz + cross(skinA.xyz, skinB.xyz)); // Translate
|
||||
vec3 _normal = normalize(mat3(N) * (nor + 2.0 * cross(skinA.xyz, cross(skinA.xyz, nor) + skinA.w * nor)));
|
||||
#else
|
||||
vec3 _normal = normalize(mat3(N) * nor);
|
||||
#endif
|
||||
|
||||
lPos = LWVP * sPos;
|
||||
|
||||
mat4 WV = V * W;
|
||||
|
@ -115,12 +139,6 @@ void main() {
|
|||
texCoord = tex;
|
||||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
vec3 _normal = normalize(mat3(N) * (nor * skinningMatVec));
|
||||
#else
|
||||
vec3 _normal = normalize(mat3(N) * nor);
|
||||
#endif
|
||||
|
||||
matColor = albedo_color;
|
||||
|
||||
#ifdef _VCols
|
||||
|
|
|
@ -37,7 +37,7 @@ uniform mat4 LWVP;
|
|||
uniform vec4 albedo_color;
|
||||
uniform vec3 eye;
|
||||
#ifdef _Skinning
|
||||
uniform float skinBones[skinMaxBones * 12];
|
||||
uniform float skinBones[skinMaxBones * 8];
|
||||
#endif
|
||||
|
||||
out vec3 position;
|
||||
|
@ -54,34 +54,51 @@ out vec3 eyeDir;
|
|||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
mat4 getBoneMat(const int boneIndex) {
|
||||
vec4 v0 = vec4(skinBones[boneIndex * 12 + 0],
|
||||
skinBones[boneIndex * 12 + 1],
|
||||
skinBones[boneIndex * 12 + 2],
|
||||
skinBones[boneIndex * 12 + 3]);
|
||||
vec4 v1 = vec4(skinBones[boneIndex * 12 + 4],
|
||||
skinBones[boneIndex * 12 + 5],
|
||||
skinBones[boneIndex * 12 + 6],
|
||||
skinBones[boneIndex * 12 + 7]);
|
||||
vec4 v2 = vec4(skinBones[boneIndex * 12 + 8],
|
||||
skinBones[boneIndex * 12 + 9],
|
||||
skinBones[boneIndex * 12 + 10],
|
||||
skinBones[boneIndex * 12 + 11]);
|
||||
return mat4(v0.x, v0.y, v0.z, v0.w,
|
||||
v1.x, v1.y, v1.z, v1.w,
|
||||
v2.x, v2.y, v2.z, v2.w,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
mat4 getSkinningMat() {
|
||||
return weight.x * getBoneMat(int(bone.x)) +
|
||||
weight.y * getBoneMat(int(bone.y)) +
|
||||
weight.z * getBoneMat(int(bone.z)) +
|
||||
weight.w * getBoneMat(int(bone.w));
|
||||
}
|
||||
|
||||
mat3 getSkinningMatVec(const mat4 skinningMat) {
|
||||
return mat3(skinningMat[0].xyz, skinningMat[1].xyz, skinningMat[2].xyz);
|
||||
void getSkinningDualQuat(vec4 weights, out vec4 A, inout vec4 B) {
|
||||
// Retrieve the real and dual part of the dual-quaternions
|
||||
mat4 matA, matB;
|
||||
matA[0][0] = skinBones[int(bone.x) * 8 + 0];
|
||||
matA[0][1] = skinBones[int(bone.x) * 8 + 1];
|
||||
matA[0][2] = skinBones[int(bone.x) * 8 + 2];
|
||||
matA[0][3] = skinBones[int(bone.x) * 8 + 3];
|
||||
matB[0][0] = skinBones[int(bone.x) * 8 + 4];
|
||||
matB[0][1] = skinBones[int(bone.x) * 8 + 5];
|
||||
matB[0][2] = skinBones[int(bone.x) * 8 + 6];
|
||||
matB[0][3] = skinBones[int(bone.x) * 8 + 7];
|
||||
matA[1][0] = skinBones[int(bone.y) * 8 + 0];
|
||||
matA[1][1] = skinBones[int(bone.y) * 8 + 1];
|
||||
matA[1][2] = skinBones[int(bone.y) * 8 + 2];
|
||||
matA[1][3] = skinBones[int(bone.y) * 8 + 3];
|
||||
matB[1][0] = skinBones[int(bone.y) * 8 + 4];
|
||||
matB[1][1] = skinBones[int(bone.y) * 8 + 5];
|
||||
matB[1][2] = skinBones[int(bone.y) * 8 + 6];
|
||||
matB[1][3] = skinBones[int(bone.y) * 8 + 7];
|
||||
matA[2][0] = skinBones[int(bone.z) * 8 + 0];
|
||||
matA[2][1] = skinBones[int(bone.z) * 8 + 1];
|
||||
matA[2][2] = skinBones[int(bone.z) * 8 + 2];
|
||||
matA[2][3] = skinBones[int(bone.z) * 8 + 3];
|
||||
matB[2][0] = skinBones[int(bone.z) * 8 + 4];
|
||||
matB[2][1] = skinBones[int(bone.z) * 8 + 5];
|
||||
matB[2][2] = skinBones[int(bone.z) * 8 + 6];
|
||||
matB[2][3] = skinBones[int(bone.z) * 8 + 7];
|
||||
matA[3][0] = skinBones[int(bone.w) * 8 + 0];
|
||||
matA[3][1] = skinBones[int(bone.w) * 8 + 1];
|
||||
matA[3][2] = skinBones[int(bone.w) * 8 + 2];
|
||||
matA[3][3] = skinBones[int(bone.w) * 8 + 3];
|
||||
matB[3][0] = skinBones[int(bone.w) * 8 + 4];
|
||||
matB[3][1] = skinBones[int(bone.w) * 8 + 5];
|
||||
matB[3][2] = skinBones[int(bone.w) * 8 + 6];
|
||||
matB[3][3] = skinBones[int(bone.w) * 8 + 7];
|
||||
// Handles antipodality by sticking joints in the same neighbourhood
|
||||
// weights.xyz *= sign(matA[3] * mat3x4(matA)).xyz;
|
||||
weights.xyz *= sign(matA[3] * matA).xyz;
|
||||
// Apply weights
|
||||
A = matA * weights; // Real part
|
||||
B = matB * weights; // Dual part
|
||||
// Normalize
|
||||
float invNormA = 1.0 / length(A);
|
||||
A *= invNormA;
|
||||
B *= invNormA;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -92,11 +109,18 @@ void main() {
|
|||
#else
|
||||
vec4 sPos = (vec4(pos, 1.0));
|
||||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
mat4 skinningMat = getSkinningMat();
|
||||
mat3 skinningMatVec = getSkinningMatVec(skinningMat);
|
||||
sPos = sPos * skinningMat;
|
||||
vec4 skinA;
|
||||
vec4 skinB;
|
||||
getSkinningDualQuat(weight, skinA, skinB);
|
||||
sPos.xyz += 2.0 * cross(skinA.xyz, cross(skinA.xyz, sPos.xyz) + skinA.w * sPos.xyz); // Rotate
|
||||
sPos.xyz += 2.0 * (skinA.w * skinB.xyz - skinB.w * skinA.xyz + cross(skinA.xyz, skinB.xyz)); // Translate
|
||||
vec3 _normal = normalize(mat3(N) * (nor + 2.0 * cross(skinA.xyz, cross(skinA.xyz, nor) + skinA.w * nor)));
|
||||
#else
|
||||
vec3 _normal = normalize(mat3(N) * nor);
|
||||
#endif
|
||||
|
||||
lPos = LWVP * sPos;
|
||||
|
||||
mat4 WV = V * W;
|
||||
|
@ -117,12 +141,6 @@ void main() {
|
|||
texCoord = tex;
|
||||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
vec3 _normal = normalize(mat3(N) * (nor * skinningMatVec));
|
||||
#else
|
||||
vec3 _normal = normalize(mat3(N) * nor);
|
||||
#endif
|
||||
|
||||
matColor = albedo_color;
|
||||
|
||||
#ifdef _VCols
|
||||
|
|
|
@ -28,38 +28,55 @@ in vec3 nor;
|
|||
|
||||
uniform mat4 LWVP;
|
||||
#ifdef _Skinning
|
||||
uniform float skinBones[skinMaxBones * 12];
|
||||
uniform float skinBones[skinMaxBones * 8];
|
||||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
mat4 getBoneMat(const int boneIndex) {
|
||||
vec4 v0 = vec4(skinBones[boneIndex * 12 + 0],
|
||||
skinBones[boneIndex * 12 + 1],
|
||||
skinBones[boneIndex * 12 + 2],
|
||||
skinBones[boneIndex * 12 + 3]);
|
||||
vec4 v1 = vec4(skinBones[boneIndex * 12 + 4],
|
||||
skinBones[boneIndex * 12 + 5],
|
||||
skinBones[boneIndex * 12 + 6],
|
||||
skinBones[boneIndex * 12 + 7]);
|
||||
vec4 v2 = vec4(skinBones[boneIndex * 12 + 8],
|
||||
skinBones[boneIndex * 12 + 9],
|
||||
skinBones[boneIndex * 12 + 10],
|
||||
skinBones[boneIndex * 12 + 11]);
|
||||
return mat4(v0.x, v0.y, v0.z, v0.w,
|
||||
v1.x, v1.y, v1.z, v1.w,
|
||||
v2.x, v2.y, v2.z, v2.w,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
mat4 getSkinningMat() {
|
||||
return weight.x * getBoneMat(int(bone.x)) +
|
||||
weight.y * getBoneMat(int(bone.y)) +
|
||||
weight.z * getBoneMat(int(bone.z)) +
|
||||
weight.w * getBoneMat(int(bone.w));
|
||||
}
|
||||
|
||||
mat3 getSkinningMatVec(const mat4 skinningMat) {
|
||||
return mat3(skinningMat[0].xyz, skinningMat[1].xyz, skinningMat[2].xyz);
|
||||
void getSkinningDualQuat(vec4 weights, out vec4 A, inout vec4 B) {
|
||||
// Retrieve the real and dual part of the dual-quaternions
|
||||
mat4 matA, matB;
|
||||
matA[0][0] = skinBones[int(bone.x) * 8 + 0];
|
||||
matA[0][1] = skinBones[int(bone.x) * 8 + 1];
|
||||
matA[0][2] = skinBones[int(bone.x) * 8 + 2];
|
||||
matA[0][3] = skinBones[int(bone.x) * 8 + 3];
|
||||
matB[0][0] = skinBones[int(bone.x) * 8 + 4];
|
||||
matB[0][1] = skinBones[int(bone.x) * 8 + 5];
|
||||
matB[0][2] = skinBones[int(bone.x) * 8 + 6];
|
||||
matB[0][3] = skinBones[int(bone.x) * 8 + 7];
|
||||
matA[1][0] = skinBones[int(bone.y) * 8 + 0];
|
||||
matA[1][1] = skinBones[int(bone.y) * 8 + 1];
|
||||
matA[1][2] = skinBones[int(bone.y) * 8 + 2];
|
||||
matA[1][3] = skinBones[int(bone.y) * 8 + 3];
|
||||
matB[1][0] = skinBones[int(bone.y) * 8 + 4];
|
||||
matB[1][1] = skinBones[int(bone.y) * 8 + 5];
|
||||
matB[1][2] = skinBones[int(bone.y) * 8 + 6];
|
||||
matB[1][3] = skinBones[int(bone.y) * 8 + 7];
|
||||
matA[2][0] = skinBones[int(bone.z) * 8 + 0];
|
||||
matA[2][1] = skinBones[int(bone.z) * 8 + 1];
|
||||
matA[2][2] = skinBones[int(bone.z) * 8 + 2];
|
||||
matA[2][3] = skinBones[int(bone.z) * 8 + 3];
|
||||
matB[2][0] = skinBones[int(bone.z) * 8 + 4];
|
||||
matB[2][1] = skinBones[int(bone.z) * 8 + 5];
|
||||
matB[2][2] = skinBones[int(bone.z) * 8 + 6];
|
||||
matB[2][3] = skinBones[int(bone.z) * 8 + 7];
|
||||
matA[3][0] = skinBones[int(bone.w) * 8 + 0];
|
||||
matA[3][1] = skinBones[int(bone.w) * 8 + 1];
|
||||
matA[3][2] = skinBones[int(bone.w) * 8 + 2];
|
||||
matA[3][3] = skinBones[int(bone.w) * 8 + 3];
|
||||
matB[3][0] = skinBones[int(bone.w) * 8 + 4];
|
||||
matB[3][1] = skinBones[int(bone.w) * 8 + 5];
|
||||
matB[3][2] = skinBones[int(bone.w) * 8 + 6];
|
||||
matB[3][3] = skinBones[int(bone.w) * 8 + 7];
|
||||
// Handles antipodality by sticking joints in the same neighbourhood
|
||||
// weights.xyz *= sign(matA[3] * mat3x4(matA)).xyz;
|
||||
weights.xyz *= sign(matA[3] * matA).xyz;
|
||||
// Apply weights
|
||||
A = matA * weights; // Real part
|
||||
B = matB * weights; // Dual part
|
||||
// Normalize
|
||||
float invNormA = 1.0 / length(A);
|
||||
A *= invNormA;
|
||||
B *= invNormA;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -71,9 +88,11 @@ void main() {
|
|||
#endif
|
||||
|
||||
#ifdef _Skinning
|
||||
mat4 skinningMat = getSkinningMat();
|
||||
mat3 skinningMatVec = getSkinningMatVec(skinningMat);
|
||||
sPos = sPos * skinningMat;
|
||||
vec4 skinA;
|
||||
vec4 skinB;
|
||||
getSkinningDualQuat(weight, skinA, skinB);
|
||||
sPos.xyz += 2.0 * cross(skinA.xyz, cross(skinA.xyz, sPos.xyz) + skinA.w * sPos.xyz); // Rotate
|
||||
sPos.xyz += 2.0 * (skinA.w * skinB.xyz - skinB.w * skinA.xyz + cross(skinA.xyz, skinB.xyz)); // Translate
|
||||
#endif
|
||||
|
||||
gl_Position = LWVP * sPos;
|
||||
|
|
|
@ -187,7 +187,7 @@ vec2 unpackFloat(float f) {
|
|||
void main() {
|
||||
|
||||
vec4 g0 = texture(gbuffer0, texCoord);
|
||||
float roughness = unpackFloat(g0.b).x;
|
||||
float roughness = unpackFloat(g0.b).y;
|
||||
|
||||
if (roughness == 1.0) {
|
||||
outColor = vec4(0.0);
|
||||
|
|
Loading…
Reference in a new issue