diff --git a/hide.hxml b/hide.hxml index 5a158cf8b..caefeebe3 100644 --- a/hide.hxml +++ b/hide.hxml @@ -12,3 +12,4 @@ common.hxml --macro include("hrt.shgraph.nodes") -dce no -debug +-D prefab_refacto \ No newline at end of file diff --git a/hide/comp/SceneEditor.hx b/hide/comp/SceneEditor.hx index 7446ad6f6..b80ad2aa0 100644 --- a/hide/comp/SceneEditor.hx +++ b/hide/comp/SceneEditor.hx @@ -2159,7 +2159,7 @@ class SceneEditor { var prevIndex = prev.children.indexOf(elt); var obj3d = elt.to(Object3D); - var preserveTransform = Std.is(toElt, hrt.prefab.fx.Emitter) || Std.is(prev, hrt.prefab.fx.Emitter); + var preserveTransform = #if prefab_refacto false #else Std.is(toElt, hrt.prefab.fx.Emitter) || Std.is(prev, hrt.prefab.fx.Emitter) #end; var toObj = getObject(toElt); var obj = getObject(elt); var prevState = null, newState = null; diff --git a/hide/prefab/PolygonEditor.hx b/hide/prefab/PolygonEditor.hx deleted file mode 100644 index caeb87b88..000000000 --- a/hide/prefab/PolygonEditor.hx +++ /dev/null @@ -1,668 +0,0 @@ -package hide.prefab; -import hxd.Key as K; -import hrt.prefab.Context; - -enum ColorState{ - None; - Overlapped; - OverlappedForDelete; - Selected; -} - -class Edge{ - public var p1 : h2d.col.Point; - public var p2 : h2d.col.Point; - public function new(p1, p2){ - this.p1 = p1; - this.p2 = p2; - } -} - -class SphereHandle extends h3d.scene.Mesh { - public function new(prim, mat, parent) { - super(prim, mat, parent); - } - - var tmp = new h3d.Vector(); - override function sync(ctx:h3d.scene.RenderContext) { - var cam = ctx.camera; - var gpos = getAbsPos().getPosition(); - var distToCam = cam.pos.sub(gpos).length(); - var engine = h3d.Engine.getCurrent(); - var ratio = 18 / engine.height; - // Ignore parent scale - parent.getAbsPos().getScale(tmp); - var scale = ratio * distToCam * Math.tan(cam.fovY * 0.5 * Math.PI / 180.0); - scaleX = scale / tmp.x; - scaleY = scale / tmp.y; - scaleZ = scale / tmp.z; - calcAbsPos(); - super.sync(ctx); - } -} - -class MovablePoint { - - public var showDebug : Bool; - public var point : h2d.col.Point; - var mesh: h3d.scene.Mesh; - public var colorState = None; - var localPosText : h2d.ObjectFollower; - var worldPosText : h2d.ObjectFollower; - - public function new(point : h2d.col.Point, ctx : Context){ - this.point = point; - mesh = new SphereHandle(h3d.prim.Cube.defaultUnitCube(), null, ctx.local3d); - mesh.name = "_movablePoint"; - mesh.material.setDefaultProps("ui"); - mesh.material.mainPass.depthTest = Always; - mesh.scale(0.1); - mesh.setPosition(point.x, point.y, 0); - localPosText = createText(ctx); - worldPosText = createText(ctx); - worldPosText.offsetZ = (0.3); - localPosText.offsetZ = (0.6); - updateText(ctx); - } - - function createText(ctx : Context){ - var o = new h2d.ObjectFollower(mesh, @:privateAccess ctx.local2d.getScene()); - var t = new h2d.Text(hxd.res.DefaultFont.get(), o); - t.textColor = 0xFFFFFF; - t.textAlign = Center; - t.dropShadow = { dx : 1.5, dy : 1.5, color : 0x202020, alpha : 1.0 }; - return o; - } - - public function dispose(){ - mesh.remove(); - worldPosText.remove(); - localPosText.remove(); - } - - function worldToScreen(wx: Float, wy: Float, wz: Float, ctx : Context) { - var s2d = @:privateAccess ctx.local2d.getScene(); - var camera = @:privateAccess ctx.local3d.getScene().camera; - camera.update(); - var pt = camera.project(wx, wy, wz, s2d.width, s2d.height); - return new h2d.col.Point( pt.x, pt.y); - } - - public function updateText(ctx : Context){ - inline function getText(o) : h2d.Text{ - return Std.downcast(o.getChildAt(0), h2d.Text); - } - getText(localPosText).visible = showDebug; - getText(worldPosText).visible = showDebug; - var pointWorldPos = new h3d.col.Point(point.x, point.y, 0.); - ctx.local3d.localToGlobal(pointWorldPos); - getText(localPosText).text = "Local : " + untyped point.x.toFixed(3) + " / " + untyped point.y.toFixed(3); - getText(worldPosText).text = "World : " + untyped pointWorldPos.x.toFixed(3) + " / " + untyped pointWorldPos.y.toFixed(3) + " / " + untyped pointWorldPos.z.toFixed(3); - } - - public function updateColor(){ - switch(colorState){ - case None : mesh.material.color.set(0,0,0); - case Overlapped : mesh.material.color.set(1,1,0); - case OverlappedForDelete : mesh.material.color.set(1,0,0); - case Selected : mesh.material.color.set(0,0,1); - } - } - - public function interset(ray : h3d.col.Ray) : Bool{ - return mesh.getCollider().rayIntersection(ray, false) != -1; - } - - public function setColorState(s : ColorState){ - colorState = s; - } -} - -class PolygonEditor { - - public var editContext : EditContext; - public var showDebug : Bool; - public var gridSize = 1; - public var showTriangles : Bool = false; - public var worldSnap = false; - - var polygonPrefab : hrt.prefab.l3d.Polygon; - var undo : hide.ui.UndoHistory; - var interactive : h2d.Interactive; - var lineGraphics : h3d.scene.Graphics; - var triangleGraphics : h3d.scene.Graphics; - var movablePoints : Array = []; - var selectedPoints : Array = []; - var lastPointSelected : h2d.col.Point; - var lastPos : h3d.col.Point; - var selectedEdge : Edge; - var selectedEdgeGraphic : h3d.scene.Graphics; - //var lastClickStamp = 0.0; - var editMode = false; - - // Temp container for Undo - var beforeMoveList : Array = []; - var afterMoveList : Array = []; - - public function new( polygonPrefab , undo : hide.ui.UndoHistory ){ - this.polygonPrefab = polygonPrefab; - this.undo = undo; - } - - public function dispose(){ - reset(); - } - - function removeGraphics(g : h3d.scene.Graphics){ - if(g != null){ - g.clear(); - g.remove(); - } - } - - public function reset(){ - clearMovablePoints(); - clearSelectedPoint(); - if(interactive != null) interactive.remove(); - removeGraphics(lineGraphics); - removeGraphics(selectedEdgeGraphic); - removeGraphics(triangleGraphics); - } - - inline function getContext(){ - return editContext.getContext(polygonPrefab); - } - - inline function refreshInteractive() { - editContext.scene.editor.refreshInteractive(polygonPrefab); - } - - public function update( ?propName : String) { - if(propName == "showDebug"){ - for(mp in movablePoints){ - mp.showDebug = showDebug; - mp.updateText(getContext()); - } - } - else if(propName == "showTriangles") { - drawTriangles(showTriangles); - } - else if(propName == "editMode") { - setSelected(getContext(), true); - } else { - refreshInteractive(); - } - } - - function copyArray(array : Array){ - var copy : Array = []; - for(p in array) - copy.push(p.clone()); - return copy; - } - - function addUndo( prev : Array, next : Array){ - undo.change(Custom(function(undo) { - var prevList = prev; - var newList = next; - if(undo) - polygonPrefab.points = prevList; - else - polygonPrefab.points = newList; - refreshPolygon(); - })); - } - - function refreshPolygon(withProps=false) { - if(!polygonPrefab.points.isClockwise()) - polygonPrefab.points.reverse(); // Ensure poly is always clockwise - - var polyPrim = polygonPrefab.generateCustomPolygon(); - var mesh : h3d.scene.Mesh = cast getContext().local3d; - mesh.primitive = polyPrim; - refreshEditorDisplay(withProps); - } - - function refreshDebugDisplay(){ - for(mp in movablePoints) - mp.updateText(getContext()); - } - - function clearSelectedPoint(){ - selectedPoints.splice(0, selectedPoints.length); - lastPointSelected = null; - } - - function isAlreadySelected( p : h2d.col.Point ) : Bool { - if( p == null) return false; - for( point in selectedPoints ) - if( point == p ) return true; - return false; - } - - function addSelectedPoint( p : h2d.col.Point ){ - if( p == null) return; - for( point in selectedPoints ) - if( point == p ) return; - selectedPoints.push(p); - } - - function removePoint( p : h2d.col.Point) { - polygonPrefab.points.remove(p); - refreshPolygon(); - } - - function addPointOnEdge( pos: h2d.col.Point, e : Edge) { - if(e == null){ - polygonPrefab.points.points.push(pos); - return; - } - function findIndex(p) : Int { - for(i in 0 ... polygonPrefab.points.length) - if( p == polygonPrefab.points[i]) - return i; - return -1; - } - var i1 = findIndex(e.p1); - var i2 = findIndex(e.p2); - if( hxd.Math.abs(i1 - i2) > 1 ) - polygonPrefab.points.points.push(pos); - else - polygonPrefab.points.points.insert(Std.int(hxd.Math.max(i1,i2)), pos); - refreshPolygon(); - } - - function projectToGround( ray: h3d.col.Ray) { - var minDist = -1.; - var normal = getContext().local3d.getAbsPos().up(); - var plane = h3d.col.Plane.fromNormalPoint(normal.toPoint(), new h3d.col.Point(getContext().local3d.getAbsPos().tx, getContext().local3d.getAbsPos().ty, getContext().local3d.getAbsPos().tz)); - var pt = ray.intersect(plane); - if(pt != null) { minDist = pt.sub(ray.getPos()).length();} - return minDist; - } - - function screenToWorld( u : Float, v : Float ) { - var camera = @:privateAccess getContext().local3d.getScene().camera; - var ray = camera.rayFromScreen(u, v); - var dist = projectToGround(ray); - return dist >= 0 ? ray.getPoint(dist) : null; - } - - function trySelectPoint( ray: h3d.col.Ray ) : MovablePoint { - for(mp in movablePoints) - if(mp.interset(ray)) - return mp; - return null; - } - - function trySelectEdge( pos : h2d.col.Point ) : Edge { - inline function crossProduct( a : h2d.col.Point, b : h2d.col.Point ){ - return a.x * b.y - a.y * b.x; - } - inline function dist(s1 : h2d.col.Point, s2 : h2d.col.Point, p : h2d.col.Point){ - var l = s2.distance(s1); - l = l * l; - if(l == 0) return p.distance(s1); - var t = hxd.Math.max(0, hxd.Math.min(1, p.sub(s1).dot(s2.sub(s1)) / l)); - var proj = s1.add((s2.sub(s1).multiply(t))); - return p.distance(proj); - } - if(polygonPrefab.points.length < 2) return null; - var minDist = dist(polygonPrefab.points[0], polygonPrefab.points[polygonPrefab.points.length - 1], pos); - var edge : Edge = new Edge(polygonPrefab.points[0],polygonPrefab.points[polygonPrefab.points.length - 1]); - for(i in 1 ... polygonPrefab.points.length){ - var p1 = polygonPrefab.points[i-1]; - var p2 = polygonPrefab.points[i]; - var dist = dist(p1, p2, pos); - if(dist < minDist){ - edge.p1 = p1; - edge.p2 = p2; - minDist = dist; - } - } - return edge; - } - - function getFinalPos( mouseX, mouseY ){ - var worldPos = screenToWorld(mouseX, mouseY); - var localPos = getContext().local3d.globalToLocal(worldPos); - if( K.isDown( K.CTRL ) ){ // Snap To Grid with Ctrl - var gridPos = new h3d.col.Point(); - if( worldSnap ){ - var absPos = getContext().local3d.getAbsPos(); - worldPos = getContext().local3d.localToGlobal(worldPos); - gridPos.x = hxd.Math.round(localPos.x / gridSize) * gridSize; - gridPos.y = hxd.Math.round(localPos.y / gridSize) * gridSize; - gridPos.z = hxd.Math.round(localPos.z / gridSize) * gridSize; - gridPos = getContext().local3d.globalToLocal(gridPos); - } - else{ - gridPos.x = hxd.Math.round(worldPos.x / gridSize) * gridSize; - gridPos.y = hxd.Math.round(worldPos.y / gridSize) * gridSize; - gridPos.z = hxd.Math.round(worldPos.z / gridSize) * gridSize; - } - localPos = gridPos; - } - return localPos; - } - - public function setSelected( ctx : Context, b : Bool ) { - reset(); - if(!editMode) return; - if(b){ - var s2d = @:privateAccess ctx.local2d.getScene(); - interactive = new h2d.Interactive(10000, 10000, s2d); - interactive.propagateEvents = true; - interactive.cancelEvents = false; - lineGraphics = new h3d.scene.Graphics(ctx.local3d); - lineGraphics.lineStyle(2, 0xFFFFFF); - lineGraphics.material.mainPass.setPassName("overlay"); - lineGraphics.material.mainPass.depth(false, LessEqual); - selectedEdgeGraphic = new h3d.scene.Graphics(ctx.local3d); - selectedEdgeGraphic.lineStyle(3, 0xFFFF00, 0.5); - selectedEdgeGraphic.material.mainPass.setPassName("overlay"); - selectedEdgeGraphic.material.mainPass.depth(false, LessEqual); - triangleGraphics = new h3d.scene.Graphics(ctx.local3d); - triangleGraphics.lineStyle(2, 0xFF0000); - triangleGraphics.material.mainPass.setPassName("overlay"); - triangleGraphics.material.mainPass.depth(false, LessEqual); - - refreshEditorDisplay(); - drawTriangles(showTriangles); - - interactive.onWheel = function(e) { - refreshDebugDisplay(); - }; - interactive.onKeyDown = - function(e) { - e.propagate = false; - if( K.isDown( K.SHIFT ) ){ - clearSelectedPoint(); - var ray = @:privateAccess ctx.local3d.getScene().camera.rayFromScreen(s2d.mouseX, s2d.mouseY); - refreshMovablePoints(ray); - if(lastPos == null) lastPos = getFinalPos(s2d.mouseX, s2d.mouseY); - refreshSelectedEdge(new h2d.col.Point(lastPos.x, lastPos.y)); - } - } - interactive.onKeyUp = - function(e) { - e.propagate = false; - var ray = @:privateAccess ctx.local3d.getScene().camera.rayFromScreen(s2d.mouseX, s2d.mouseY); - refreshMovablePoints(ray); - if(lastPos == null) lastPos = getFinalPos(s2d.mouseX, s2d.mouseY); - refreshSelectedEdge(new h2d.col.Point(lastPos.x, lastPos.y)); - } - interactive.onPush = - function(e) { - var finalPos = getFinalPos(s2d.mouseX, s2d.mouseY); - var ray = @:privateAccess ctx.local3d.getScene().camera.rayFromScreen(s2d.mouseX, s2d.mouseY); - if( K.isDown( K.MOUSE_LEFT ) ){ - e.propagate = false; - // Shift + Left Click : Remove Point - if( K.isDown( K.SHIFT ) ){ - var mp = trySelectPoint(ray); - if(mp != null){ - var prevList = copyArray(polygonPrefab.points.points); - removePoint(mp.point); - var newList = copyArray(polygonPrefab.points.points); - addUndo(prevList, newList); - } - } - else { - // Left Click : Add/Set selected point / Clear selection - lastPos = finalPos.clone(); - var mp = trySelectPoint(ray); - if(mp != null){ - if( K.isDown(K.ALT) && !isAlreadySelected(mp.point)) - addSelectedPoint(mp.point); - lastPointSelected = mp.point; - beforeMoveList = copyArray(polygonPrefab.points.points); - } - // Double Left Click : Create point - else{ - clearSelectedPoint(); - if(K.isDown(K.CTRL)) { - // var curStamp = haxe.Timer.stamp(); - // var diff = curStamp - lastClickStamp; - // if(diff < 0.2){ - var prevList = copyArray(polygonPrefab.points.points); - var pt = new h2d.col.Point(finalPos.x, finalPos.y); - addPointOnEdge(pt, selectedEdge); - var newList = copyArray(polygonPrefab.points.points); - addUndo(prevList, newList); - refreshSelectedEdge(new h2d.col.Point(finalPos.x, finalPos.y)); - // Select new point - lastPointSelected = pt; - } - //lastClickStamp = curStamp; - } - refreshMovablePoints(); - } - } - }; - interactive.onRelease = - function(e) { - //lastPos = null; - lastPointSelected = null; - if( beforeMoveList != null ){ - afterMoveList = copyArray(polygonPrefab.points.points); - addUndo(beforeMoveList, afterMoveList); - beforeMoveList = null; - afterMoveList = null; - } - }; - interactive.onMove = - function(e) { - var ray = @:privateAccess ctx.local3d.getScene().camera.rayFromScreen(s2d.mouseX, s2d.mouseY); - var finalPos = getFinalPos(s2d.mouseX, s2d.mouseY); - refreshMovablePoints(ray); - refreshSelectedEdge(new h2d.col.Point(finalPos.x, finalPos.y)); - if( K.isDown( K.MOUSE_LEFT )){ - var move : h2d.col.Point = null; - var pos = new h2d.col.Point(finalPos.x, finalPos.y); - if(lastPointSelected != null){ - move = pos.sub(lastPointSelected); - lastPointSelected.load(pos); - for(p in selectedPoints){ - if(lastPointSelected == p) continue; - p.x += move.x; p.y += move.y; - } - } - refreshMovablePoints(); - refreshSelectedEdge(new h2d.col.Point(finalPos.x, finalPos.y)); - refreshPolygon(false); - lastPos = finalPos.clone(); - } - else - refreshDebugDisplay(); - }; - } - else - editMode = false; - } - - function refreshSelectedEdge( pos : h2d.col.Point ){ - selectedEdge = trySelectEdge(pos); - selectedEdgeGraphic.clear(); - if(K.isDown( K.SHIFT ) ) - return; - if(selectedEdge != null){ - selectedEdgeGraphic.moveTo(selectedEdge.p1.x, selectedEdge.p1.y, 0); - selectedEdgeGraphic.lineTo(selectedEdge.p2.x, selectedEdge.p2.y, 0); - } - } - - function drawTriangles( b : Bool ){ - triangleGraphics.clear(); - if(b && polygonPrefab.getPrimitive(getContext()) != null){ - var i = 0; - var prim = polygonPrefab.getPrimitive(getContext()); - while(i < prim.idx.length){ - triangleGraphics.moveTo(prim.points[prim.idx[i]].x, prim.points[prim.idx[i]].y, 0); - triangleGraphics.lineTo(prim.points[prim.idx[i + 1]].x, prim.points[prim.idx[i + 1]].y, 0); - triangleGraphics.lineTo(prim.points[prim.idx[i + 2]].x, prim.points[prim.idx[i + 2]].y, 0); - triangleGraphics.lineTo(prim.points[prim.idx[i]].x, prim.points[prim.idx[i]].y, 0); - i += 3; - } - } - } - - function clearMovablePoints(){ - for(mp in movablePoints) - mp.dispose(); - movablePoints.splice(0, movablePoints.length); - } - - function createMovablePoints(){ - for(p in polygonPrefab.points){ - var mp = new MovablePoint(p, getContext()); - movablePoints.push(mp); - } - } - - function refreshMovablePoints( ?ray ){ - for(mp in movablePoints) - mp.setColorState(None); - if(ray != null){ - var mp = trySelectPoint(ray); - if( mp != null && mp.colorState != Selected) - K.isDown( K.SHIFT ) ? mp.setColorState(OverlappedForDelete) : mp.setColorState(Overlapped); - } - for(p in selectedPoints) - for(mp in movablePoints) - if(mp.point == p){ - mp.setColorState(Selected); - break; - } - for(mp in movablePoints){ - if( mp.point == lastPointSelected) mp.setColorState(Selected); - mp.updateColor(); - mp.showDebug = showDebug; - mp.updateText(getContext()); - } - } - - function refreshEditorDisplay(withProps=true) { - lineGraphics.clear(); - clearMovablePoints(); - if(polygonPrefab.points == null || polygonPrefab.points.length == 0) return; - lineGraphics.moveTo(polygonPrefab.points[polygonPrefab.points.length - 1].x, polygonPrefab.points[polygonPrefab.points.length - 1].y, 0); - for(p in polygonPrefab.points) - lineGraphics.lineTo(p.x, p.y, 0); - createMovablePoints(); - refreshMovablePoints(); - if(withProps) - refreshPointList(editContext.getCurrentProps(polygonPrefab)); - } - - public function addProps( ctx : EditContext ){ - var props = new hide.Element(' -
-
-
- -
-
- Ctrl + Left Click : Add point on edge
- Shift + Left Click : Delete selected point
- Drag with Left Click : Move selected points
- Drag with Left Click + Ctrl : Move selected points on grid
- Alt + Left Click : Add point to selection -
-
Show Debug
-
Show Triangles
-
Grid Size
-
World Snap
-
-
-
-
- -
-
-
'); - - var editModeButton = props.find(".editModeButton"); - editModeButton.click(function(_) { - editMode = !editMode; - editModeButton.val(editMode ? "Edit Mode : Enabled" : "Edit Mode : Disabled"); - editModeButton.toggleClass("editModeEnabled", editMode); - setSelected(getContext(), true); - if(!editMode) - refreshInteractive(); - }); - - props.find(".reset").click(function(_) { - var prevList = copyArray(polygonPrefab.points.points); - polygonPrefab.points.points.splice(0, polygonPrefab.points.points.length); - var nextList = copyArray(polygonPrefab.points.points); - addUndo(prevList, nextList); - refreshPolygon(); - }); - - refreshPointList(props); - - ctx.properties.add(props, this, function(pname) {ctx.onChange(polygonPrefab, pname); }); - return props; - } - - function refreshPointList( props : hide.Element){ - var container = props.find(".point-list"); - container.empty(); - - function createVector(p : h2d.col.Point){ - var v = new Element('
'); - var deleteButton = new Element(''); - var fieldX = new Element(''); - var fieldY = new Element(''); - - fieldX.val(p.x); - fieldY.val(p.y); - - fieldX.on("input", function(_) { - var prevValue = p.x; - p.x = Std.parseFloat(fieldX.val()); - var nextValue = p.x; - undo.change(Custom(function(undo) { - p.x = undo ? prevValue : nextValue; - refreshPolygon(); - })); - refreshPolygon(); - }); - - fieldY.on("input", function(_) { - var prevValue = p.y; - p.y = Std.parseFloat(fieldY.val()); - var nextValue = p.y; - undo.change(Custom(function(undo) { - p.y = undo ? prevValue : nextValue; - refreshPolygon(); - })); - refreshPolygon(); - }); - - deleteButton.on("click", function(_) { - var prevList = copyArray(polygonPrefab.points.points); - polygonPrefab.points.points.remove(p); - var nextList = copyArray(polygonPrefab.points.points); - addUndo(prevList, nextList); - refreshPolygon(); - refreshPointList(props); - }); - - v.append(''); - v.append(fieldX); - v.append(''); - v.append(fieldY); - v.append(deleteButton); - v.append('
'); - container.append(v); - } - - if(polygonPrefab.points != null) { - for(p in polygonPrefab.points){ - createVector(p); - } - } - } -} diff --git a/hide/prefab/SplineEditor.hx b/hide/prefab/SplineEditor.hx deleted file mode 100644 index 8fe4e5c44..000000000 --- a/hide/prefab/SplineEditor.hx +++ /dev/null @@ -1,590 +0,0 @@ -package hide.prefab; -import hxd.Key as K; -import hrt.prefab.l3d.Spline; - -#if editor - -class NewSplinePointViewer extends h3d.scene.Object { - - var pointViewer : h3d.scene.Mesh; - var connectionViewer : h3d.scene.Graphics; - var tangentViewer : h3d.scene.Graphics; - - public function new( parent : h3d.scene.Object ) { - super(parent); - name = "SplinePointViewer"; - pointViewer = new h3d.scene.Mesh(h3d.prim.Sphere.defaultUnitSphere(), null, this); - pointViewer.name = "pointViewer"; - pointViewer.material.setDefaultProps("ui"); - pointViewer.material.color.set(1,1,0,1); - pointViewer.material.mainPass.depthTest = Always; - - connectionViewer = new h3d.scene.Graphics(this); - connectionViewer.name = "connectionViewer"; - connectionViewer.lineStyle(3, 0xFFFF00); - connectionViewer.material.mainPass.setPassName("ui"); - connectionViewer.material.mainPass.depthTest = Always; - connectionViewer.clear(); - - tangentViewer = new h3d.scene.Graphics(this); - tangentViewer.name = "tangentViewerViewer"; - tangentViewer.lineStyle(3, 0xFFFF00); - tangentViewer.material.mainPass.setPassName("ui"); - tangentViewer.material.mainPass.depthTest = Always; - tangentViewer.clear(); - } - - override function sync( ctx : h3d.scene.RenderContext ) { - var cam = ctx.camera; - var gpos = getAbsPos().getPosition(); - var distToCam = cam.pos.sub(gpos).length(); - var engine = h3d.Engine.getCurrent(); - var ratio = 18 / engine.height; - var correctionFromParents = 1.0 / getAbsPos().getScale().x; - pointViewer.setScale(correctionFromParents * ratio * distToCam * Math.tan(cam.fovY * 0.5 * Math.PI / 180.0)); - calcAbsPos(); - super.sync(ctx); - } - - public function update( spd : SplinePointData ) { - - pointViewer.setPosition(spd.pos.x, spd.pos.y, spd.pos.z); - - tangentViewer.clear(); - tangentViewer.visible = spd.tangent != null; - if( spd.tangent != null ) { - var scale = 1.0; - if( spd.prev != null && spd.next != null ) scale = (spd.prev.scaleX + spd.next.scaleX) * 0.5; - else if( spd.prev != null ) scale = spd.prev.scaleX; - else if( spd.next != null ) scale = spd.next.scaleX; - tangentViewer.moveTo(spd.pos.x - spd.tangent.x * scale, spd.pos.y - spd.tangent.y * scale, spd.pos.z - spd.tangent.z * scale); - tangentViewer.lineTo(spd.pos.x + spd.tangent.x * scale, spd.pos.y + spd.tangent.y * scale, spd.pos.z + spd.tangent.z * scale); - } - - // Only display the connection if we are adding the new point at the end or the beggining fo the spline - connectionViewer.clear(); - connectionViewer.visible = spd.prev == null || spd.next == null; - if( connectionViewer.visible ) { - var startPos = spd.prev == null ? spd.next.getPoint() : spd.prev.getPoint(); - connectionViewer.moveTo(startPos.x, startPos.y, startPos.z); - connectionViewer.lineTo(spd.pos.x, spd.pos.y, spd.pos.z); - } - } -} - -@:access(hrt.prefab.l3d.Spline) -class SplineEditor { - - public var prefab : Spline; - public var editContext : EditContext; - var editMode = false; - var undo : hide.ui.UndoHistory; - - var interactive : h2d.Interactive; - - // Easy way to keep track of viewers - var gizmos : Array = []; - var newSplinePointViewer : NewSplinePointViewer; - - public function new( prefab : Spline, undo : hide.ui.UndoHistory ){ - this.prefab = prefab; - this.undo = undo; - } - - public function update( ctx : hrt.prefab.Context , ?propName : String ) { - if( editMode ) { - showViewers(); - } - } - - function reset() { - removeViewers(); - removeGizmos(); - if( interactive != null ) { - interactive.remove(); - interactive = null; - } - if( newSplinePointViewer != null ) { - newSplinePointViewer.remove(); - newSplinePointViewer = null; - } - } - - inline function getContext() { - return editContext.getContext(prefab); - } - - function getClosestSplinePointFromMouse( mouseX : Float, mouseY : Float, ctx : hrt.prefab.Context ) : SplinePoint { - if( ctx == null || ctx.local3d == null || ctx.local3d.getScene() == null ) - return null; - - var mousePos = new h3d.Vector( mouseX / h3d.Engine.getCurrent().width, 1.0 - mouseY / h3d.Engine.getCurrent().height, 0); - var minDist = -1.0; - var result : SplinePoint = null; - for( sp in prefab.points ) { - var screenPos = sp.getPoint().toVector(); - screenPos.project(ctx.local3d.getScene().camera.m); - screenPos.z = 0; - screenPos.scale3(0.5); - screenPos = screenPos.add(new h3d.Vector(0.5,0.5)); - var dist = screenPos.distance(mousePos); - if( dist < minDist || minDist == -1 ) { - minDist = dist; - result = sp; - } - } - return result; - } - - function getNewPointPosition( mouseX : Float, mouseY : Float, ctx : hrt.prefab.Context ) : SplinePointData { - if( prefab.points.length == 0 ) { - return { pos : ctx.local3d.getAbsPos().getPosition().toPoint(), tangent : ctx.local3d.getAbsPos().right().toPoint() , prev : null, next : null }; - } - - var closestPt = getClosestPointFromMouse(mouseX, mouseY, ctx); - - // If we are are adding a new point at the beginning/end, just make a raycast 'cursor -> plane' with the transform of the first/last SplinePoint - if( !prefab.loop && (closestPt.next == null || closestPt.prev == null) ) { - var camera = @:privateAccess ctx.local3d.getScene().camera; - var ray = camera.rayFromScreen(mouseX, mouseY); - var normal = closestPt.next == null ? closestPt.prev.getAbsPos().up().toPoint() : closestPt.next.getAbsPos().up().toPoint(); - var point = closestPt.next == null ? closestPt.prev.getAbsPos().getPosition().toPoint() : closestPt.next.getAbsPos().getPosition().toPoint(); - var plane = h3d.col.Plane.fromNormalPoint(normal, point); - var pt = ray.intersect(plane); - return { pos : pt, tangent : closestPt.tangent, prev : closestPt.prev, next : closestPt.next }; - } - else - return closestPt; - } - - function getClosestPointFromMouse( mouseX : Float, mouseY : Float, ctx : hrt.prefab.Context ) : SplinePointData { - - if( ctx == null || ctx.local3d == null || ctx.local3d.getScene() == null ) - return null; - - var result : SplinePointData = null; - var mousePos = new h3d.Vector( mouseX / h3d.Engine.getCurrent().width, 1.0 - mouseY / h3d.Engine.getCurrent().height, 0); - var minDist = -1.0; - for( s in prefab.data.samples ) { - var screenPos = s.pos.toVector(); - screenPos.project(ctx.local3d.getScene().camera.m); - screenPos.z = 0; - screenPos.scale3(0.5); - screenPos = screenPos.add(new h3d.Vector(0.5,0.5)); - var dist = screenPos.distance(mousePos); - if( (dist < minDist || minDist == -1) && dist < 0.1 ) { - minDist = dist; - result = s; - } - } - - if( result == null ) { - result = { pos : null, tangent : null, prev : null, next : null }; - - var firstSp = prefab.points[0]; - var firstPt = firstSp.getPoint(); - var firstPtScreenPos = firstPt.toVector(); - firstPtScreenPos.project(ctx.local3d.getScene().camera.m); - firstPtScreenPos.z = 0; - firstPtScreenPos.scale3(0.5); - firstPtScreenPos = firstPtScreenPos.add(new h3d.Vector(0.5,0.5)); - var distToFirstPoint = firstPtScreenPos.distance(mousePos); - - var lastSp = prefab.points[prefab.points.length - 1]; - var lastPt = lastSp.getPoint(); - var lastPtSreenPos = lastPt.toVector(); - lastPtSreenPos.project(ctx.local3d.getScene().camera.m); - lastPtSreenPos.z = 0; - lastPtSreenPos.scale3(0.5); - lastPtSreenPos = lastPtSreenPos.add(new h3d.Vector(0.5,0.5)); - var distTolastPoint = lastPtSreenPos.distance(mousePos); - - if( distTolastPoint < distToFirstPoint ) { - result.pos = lastPt; - result.tangent = lastSp.getAbsPos().right().toPoint(); - result.prev = prefab.points[prefab.points.length - 1]; - result.next = null; - } - else { - result.pos = firstPt; - result.tangent = firstSp.getAbsPos().right().toPoint(); - result.prev = null; - result.next = prefab.points[0]; - } - } - - return result; - } - - function addSplinePoint( spd : SplinePointData, ctx : hrt.prefab.Context ) : SplinePoint { - - var invMatrix = new h3d.Matrix(); - invMatrix.identity(); - var o : hrt.prefab.Object3D = prefab; - while(o != null) { - invMatrix.multiply(invMatrix, o.getTransform()); - o = o.parent.to(hrt.prefab.Object3D); - } - invMatrix.initInverse(invMatrix); - - var pos = spd.pos.toVector(); - pos.project(invMatrix); - - var index = 0; - var scale = 1.0; - if( spd.prev == null && spd.next == null ) { - scale = 1.0; - index = 0; - } - else if( spd.prev == null ) { - index = 0; - scale = prefab.points[0].getAbsPos().getScale().x; - } - else if( spd.next == null ) { - index = prefab.points.length; - scale = prefab.points[prefab.points.length - 1].getAbsPos().getScale().x; - } - else { - index = prefab.points.indexOf(spd.next); - scale = (spd.prev.scaleX + spd.next.scaleX) * 0.5; - } - - var sp = new SplinePoint(prefab); - sp.x = pos.x; - sp.y = pos.y; - sp.z = pos.z; - prefab.children.remove(sp); - prefab.children.insert(index, sp); - if( spd.tangent != null ) { - var dir = spd.tangent.toVector(); - dir.transform3x3(invMatrix); // Don't take the translation - dir.scale3(-1); - sp.rotationX = h3d.Matrix.lookAtX(dir).getFloats()[0]; - sp.rotationY = h3d.Matrix.lookAtX(dir).getFloats()[1]; - sp.rotationZ = h3d.Matrix.lookAtX(dir).getFloats()[2]; - } - sp.scaleX = scale; - sp.scaleY = scale; - sp.scaleZ = scale; - editContext.scene.editor.addElements([sp], false, true, false); - - prefab.updateInstance(ctx); - showViewers(); - return sp; - } - - function removeViewers() { - for( sp in prefab.points ) { - sp.setViewerVisible(false); - } - } - - function showViewers() { - for( sp in prefab.points ) { - sp.setViewerVisible(true); - } - } - - function removeGizmos() { - for( g in gizmos ) { - g.remove(); - @:privateAccess editContext.scene.editor.updates.remove(g.update); - } - gizmos = []; - } - - function createGizmos( ctx : hrt.prefab.Context ) { - removeGizmos(); // Security, avoid duplication - var sceneEditor = @:privateAccess editContext.scene.editor; - for( sp in prefab.points ) { - var gizmo = new hide.view.l3d.Gizmo(editContext.scene); - gizmo.getRotationQuat().identity(); - gizmo.visible = true; - var tmpMat = new h3d.Matrix(); - tmpMat.load(sp.getAbsPos()); - var tmpScale = new h3d.Vector(); - tmpMat.getScale(tmpScale); - tmpMat.prependScale(1.0/tmpScale.x, 1.0/tmpScale.y, 1.0/tmpScale.z); - gizmo.setTransform(tmpMat); - @:privateAccess sceneEditor.updates.push( gizmo.update ); - gizmos.insert(gizmos.length, gizmo); - gizmo.visible = false; // Not visible by default, only show the closest in the onMove of interactive - - var posQuant = @:privateAccess sceneEditor.view.config.get("sceneeditor.xyzPrecision"); - var scaleQuant = @:privateAccess sceneEditor.view.config.get("sceneeditor.scalePrecision"); - var rotQuant = @:privateAccess sceneEditor.view.config.get("sceneeditor.rotatePrecision"); - - inline function quantize(x: Float, step: Float) { - if(step > 0) { - x = Math.round(x / step) * step; - x = untyped parseFloat(x.toFixed(5)); // Snap to closest nicely displayed float :cold_sweat: - } - return x; - } - - gizmo.onStartMove = function(mode) { - - var sceneObj = sceneEditor.getContext(sp).local3d; - var obj3d = sp.to(hrt.prefab.Object3D); - var pivotPt = sceneObj.getAbsPos().getPosition(); - var pivot = new h3d.Matrix(); - pivot.initTranslation(pivotPt.x, pivotPt.y, pivotPt.z); - var invPivot = pivot.clone(); - invPivot.invert(); - - var localMat : h3d.Matrix = sceneEditor.worldMat(sceneObj).clone(); - localMat.multiply(localMat, invPivot); - - var prevState = obj3d.saveTransform(); - gizmo.onMove = function(translate: h3d.Vector, rot: h3d.Quat, scale: h3d.Vector) { - var transf = new h3d.Matrix(); - transf.identity(); - - if(rot != null) rot.toMatrix(transf); - if(translate != null) transf.translate(translate.x, translate.y, translate.z); - - var newMat = localMat.clone(); - newMat.multiply(newMat, transf); - newMat.multiply(newMat, pivot); - if(sceneEditor.snapToGround && (mode == MoveXY || mode == MoveX || mode == MoveY || mode == MoveZ || mode == MoveYZ || mode == MoveZX)) { - newMat.tz = sceneEditor.getZ(newMat.tx, newMat.ty); - } - - var parentInvMat = sceneObj.parent.getAbsPos().clone(); - parentInvMat.initInverse(parentInvMat); - newMat.multiply(newMat, parentInvMat); - if(scale != null) newMat.prependScale(scale.x, scale.y, scale.z); - - var rot = newMat.getEulerAngles(); - obj3d.x = quantize(newMat.tx, posQuant); - obj3d.y = quantize(newMat.ty, posQuant); - obj3d.z = quantize(newMat.tz, posQuant); - obj3d.rotationX = quantize(hxd.Math.radToDeg(rot.x), rotQuant); - obj3d.rotationY = quantize(hxd.Math.radToDeg(rot.y), rotQuant); - obj3d.rotationZ = quantize(hxd.Math.radToDeg(rot.z), rotQuant); - if(scale != null) { - inline function scaleSnap(x: Float) { - if(K.isDown(K.CTRL)) { - var step = K.isDown(K.SHIFT) ? 0.5 : 1.0; - x = Math.round(x / step) * step; - } - return x; - } - var s = newMat.getScale(); - obj3d.scaleX = quantize(scaleSnap(s.x), scaleQuant); - obj3d.scaleY = quantize(scaleSnap(s.y), scaleQuant); - obj3d.scaleZ = quantize(scaleSnap(s.z), scaleQuant); - } - obj3d.applyTransform(sceneObj); - } - - gizmo.onFinishMove = function() { - var newState = obj3d.saveTransform(); - undo.change(Custom(function(undo) { - if( undo ) { - obj3d.loadTransform(prevState); - obj3d.applyTransform(sceneObj); - prefab.updateInstance(ctx); - showViewers(); - @:privateAccess editContext.scene.editor.refresh(Partial); - showViewers(); - createGizmos(ctx); - } - else { - obj3d.loadTransform(newState); - obj3d.applyTransform(sceneObj); - prefab.updateInstance(ctx); - showViewers(); - createGizmos(ctx); - } - })); - var worldPos = ctx.local3d.localToGlobal(new h3d.col.Point(sp.x, sp.y, sp.z)); - gizmo.setPosition(worldPos.x, worldPos.y, worldPos.z); - } - } - } - } - - public function setSelected( ctx : hrt.prefab.Context , b : Bool ) { - reset(); - - if( !b ) { - editMode = false; - return; - } - - if( editMode ) { - createGizmos(ctx); - var s2d = @:privateAccess ctx.local2d.getScene(); - interactive = new h2d.Interactive(10000, 10000, s2d); - interactive.propagateEvents = true; - interactive.onPush = - function(e) { - // Add a new point - if( K.isDown( K.MOUSE_LEFT ) && K.isDown( K.CTRL ) ) { - e.propagate = false; - var pt = getNewPointPosition(s2d.mouseX, s2d.mouseY, ctx); - var sp = addSplinePoint(pt, ctx); - showViewers(); - createGizmos(ctx); - - undo.change(Custom(function(undo) { - if( undo ) { - editContext.scene.editor.deleteElements([sp], () -> {}, false, false); - for (sp in prefab.points) - sp.computeName(editContext.getContext(sp)); - @:privateAccess editContext.scene.editor.refresh(Partial); - prefab.updateInstance(ctx); - showViewers(); - createGizmos(ctx); - } - else { - addSplinePoint(pt, ctx); - showViewers(); - createGizmos(ctx); - } - })); - - } - // Delete a point - if( K.isDown( K.MOUSE_LEFT ) && K.isDown( K.SHIFT ) ) { - e.propagate = false; - var sp = getClosestSplinePointFromMouse(s2d.mouseX, s2d.mouseY, ctx); - var index = prefab.points.indexOf(sp); - editContext.scene.editor.deleteElements([sp], () -> {}, false, false); - for (sp in prefab.points) - sp.computeName(editContext.getContext(sp)); - @:privateAccess editContext.scene.editor.refresh(Partial); - - prefab.updateInstance(ctx); - showViewers(); - createGizmos(ctx); - - undo.change(Custom(function(undo) { - if( undo ) { - prefab.children.insert(index, sp); - editContext.scene.editor.addElements([sp], false, true, false); - prefab.updateInstance(ctx); - showViewers(); - createGizmos(ctx); - } - else { - editContext.scene.editor.deleteElements([sp], () -> {}, false, false); - for (sp in prefab.points) - sp.computeName(editContext.getContext(sp)); - @:privateAccess editContext.scene.editor.refresh(Partial); - prefab.updateInstance(ctx); - showViewers(); - createGizmos(ctx); - } - })); - } - }; - - interactive.onMove = - function(e) { - - if( prefab.points.length == 0 ) - return; - - // Only show the gizmo of the closest splinePoint - var closetSp = getClosestSplinePointFromMouse(s2d.mouseX, s2d.mouseY, ctx); - var index = prefab.points.indexOf(closetSp); - for( g in gizmos ) { - g.visible = gizmos.indexOf(g) == index && !K.isDown( K.CTRL ) && !K.isDown( K.SHIFT ); - } - - if( K.isDown( K.CTRL ) ) { - if( newSplinePointViewer == null ) - newSplinePointViewer = new NewSplinePointViewer(ctx.local3d.getScene()); - newSplinePointViewer.visible = true; - - var npt = getNewPointPosition(s2d.mouseX, s2d.mouseY, ctx); - newSplinePointViewer.update(npt); - } - else { - if( newSplinePointViewer != null ) - newSplinePointViewer.visible = false; - } - - if( K.isDown( K.SHIFT ) ) { - var index = prefab.points.indexOf(getClosestSplinePointFromMouse(s2d.mouseX, s2d.mouseY, ctx)); - for( sp in prefab.points ) { - if( index == prefab.points.indexOf(sp) ) - sp.setColor(0xFFFF0000); - else - sp.setColor(0xFF0000FF); - } - } - - }; - } - } - - public function edit( ctx : EditContext ) { - - var props = new hide.Element(' -
-
-
- -
-
-
-
- Ctrl + Left Click Add a point on the spline
- Shift + Left Click Delete a point from the spline -
-
-
-
- -
-
-
'); - - var reverseButton = props.find(".reverse"); - reverseButton.click(function(_) { - prefab.children.reverse(); - for (sp in prefab.points) { - sp.rotationZ += hxd.Math.degToRad(180); - sp.computeName(editContext.getContext(sp)); - } - @:privateAccess editContext.scene.editor.refresh(Partial); - - undo.change(Custom(function(undo) { - prefab.children.reverse(); - for (sp in prefab.points) { - sp.rotationZ += hxd.Math.degToRad(180); - sp.computeName(editContext.getContext(sp)); - } - @:privateAccess editContext.scene.editor.refresh(Partial); - })); - ctx.onChange(prefab, null); - removeGizmos(); - createGizmos(getContext()); - }); - - var editModeButton = props.find(".editModeButton"); - editModeButton.toggleClass("editModeEnabled", editMode); - editModeButton.click(function(_) { - editMode = !editMode; - prefab.onEdit(editMode); - editModeButton.val(editMode ? "Edit Mode : Enabled" : "Edit Mode : Disabled"); - editModeButton.toggleClass("editModeEnabled", editMode); - prefab.updateInstance(ctx.getContext(prefab)); - setSelected(getContext(), true); - @:privateAccess editContext.scene.editor.showGizmo = !editMode; - ctx.onChange(prefab, null); - }); - - ctx.properties.add(props, this, function(pname) { - ctx.onChange(prefab, pname); - }); - - return props; - } - -} - -#end \ No newline at end of file diff --git a/hide/prefab/terrain/Brush.hx b/hide/prefab/terrain/Brush.hx deleted file mode 100644 index d18a2d876..000000000 --- a/hide/prefab/terrain/Brush.hx +++ /dev/null @@ -1,136 +0,0 @@ -package hide.prefab.terrain; -import h3d.shader.pbr.AlphaMultiply; -import h3d.shader.FixedColor; -import h3d.mat.Stencil; -using Lambda; -import hxd.Key as K; - -class Brush { - public var name : String; - public var size : Float; - public var strength : Float; - public var step : Float; - public var tex : h3d.mat.Texture; - public var bitmap : h2d.Bitmap; - public var texPath : String; - public var index : Int = -1; - public var brushMode : BrushMode; - public var firstClick = false; - - public function new(){ - brushMode = new BrushMode(); - } - - public function isValid() : Bool { - return ( brushMode.mode == Delete || (bitmap != null && tex != null && name != null && step > 0.0 && texPath != null) ); - } - - public function scaleForTex( tileSize : h2d.col.Point, texResolution : h2d.col.IPoint ) { - if( tex != null ) { - bitmap.scaleX = size / ((tileSize.x / texResolution.x) * tex.width); - bitmap.scaleY = size / ((tileSize.y / texResolution.y) * tex.height); - } - } - - public function drawTo( target : h3d.mat.Texture, pos : h3d.col.Point, tileSize : h2d.col.Point, ?offset = 0 ) { - var texSize = new h2d.col.IPoint(target.width + offset, target.height + offset); - scaleForTex(tileSize, texSize); - bitmap.setPosition( - (pos.x * texSize.x - ( size / (tileSize.x / texSize.x) * 0.5 )), - (pos.y * texSize.y - ( size / (tileSize.y / texSize.y) * 0.5 ))); - bitmap.drawTo(target); - } -} - -enum Mode { - AddSub; - Set; - Smooth; - Paint; - Delete; - NoMode; -} - -enum LockAxe { - LockX; - LockY; - NoLock; -} - -class BrushMode { - public var accumulate = false; - public var subAction = false; - public var lockDir = false; - public var snapToGrid = false; - public var mode = NoMode; - public var lockAxe = NoLock; - public var setHeightValue = 0.0; - public function new(){} -} - -class AlphaMult extends hxsl.Shader { - static var SRC = { - @param var amount : Float; - var pixelColor : Vec4; - function fragment() { - pixelColor.a *= amount; - } - } -} - -class BrushPreview extends h3d.scene.Mesh { - - var terrain : hrt.prefab.terrain.TerrainMesh; - var decalShader : h3d.shader.pbr.VolumeDecal.DecalOverlay; - public var opacity : Float = 1.0; - - public function new( terrain : hrt.prefab.terrain.TerrainMesh ) { - this.terrain = terrain; - var material = h3d.mat.MaterialSetup.current.createMaterial(); - material.props = material.getDefaultProps(); - material.mainPass.removeShader(material.mainPass.getShader(h3d.shader.pbr.PropsValues)); - material.mainPass.setPassName("afterTonemappingDecal"); - material.mainPass.depthWrite = false; - material.mainPass.depthTest = GreaterEqual; - material.mainPass.culling = Front; - material.mainPass.setBlendMode(Alpha); - material.shadows = false; - super(h3d.prim.Cube.defaultUnitCube(), material, terrain.getScene()); - decalShader = new h3d.shader.pbr.VolumeDecal.DecalOverlay(); - decalShader.fadeStart = 1; - decalShader.fadeEnd = 0; - decalShader.fadePower = 1; - decalShader.emissive = 0; - decalShader.CENTERED = true; - decalShader.GAMMA_CORRECT = false; - material.mainPass.addShader(decalShader); - var colorSet = new FixedColor(); - colorSet.color.set(1,1,1,1); - colorSet.USE_ALPHA = false; - material.mainPass.addShader(colorSet); - var am = new AlphaMult(); - am.setPriority(-1); - am.amount = opacity; - material.mainPass.addShader(am); - - // Only draw the preview on terrain - material.mainPass.stencil = new h3d.mat.Stencil(); - material.mainPass.stencil.setFunc(Equal, 0x01, 0x01, 0x01); - material.mainPass.stencil.setOp(Keep, Keep, Keep); - } - - public function previewAt( brush : Brush, pos : h3d.col.Point ) { - setPosition(pos.x, pos.y, pos.z); - setScale(brush.size); - scaleZ = 1000; - decalShader.colorTexture = brush.tex; - material.mainPass.getShader(AlphaMult).amount = opacity; - visible = true; - } - - public function reset() { - setPosition(0,0,0); - visible = false; - decalShader.colorTexture = null; - } -} diff --git a/hide/prefab/terrain/ClampWeight.hx b/hide/prefab/terrain/ClampWeight.hx deleted file mode 100644 index b3ba243bb..000000000 --- a/hide/prefab/terrain/ClampWeight.hx +++ /dev/null @@ -1,31 +0,0 @@ -package hide.prefab.terrain; - -class ClampWeight extends h3d.shader.ScreenShader { - - static var SRC = { - - @param var weightTextures : Sampler2DArray; - @param var weightCount : Int; - @param var baseTexIndex : Int; - @param var curTexIndex : Int; - - function fragment() { - var count = 0; - var smallestWeightIndex = -1; - var smallestWeight = 1.0; - for(i in 0 ... weightCount){ - var w = weightTextures.get(vec3(calculatedUV, i)).r; - if(w > 0.0){ - count++; - if(i != baseTexIndex && smallestWeight > w){ - smallestWeight = w; - smallestWeightIndex = i; - } - } - } - pixelColor = weightTextures.get(vec3(calculatedUV, curTexIndex)).rgba; - if(count > 3 && curTexIndex == smallestWeightIndex) - pixelColor = vec4(0); - } - } -} diff --git a/hide/prefab/terrain/CustomRenderer.hx b/hide/prefab/terrain/CustomRenderer.hx deleted file mode 100644 index 4dcb323d3..000000000 --- a/hide/prefab/terrain/CustomRenderer.hx +++ /dev/null @@ -1,21 +0,0 @@ -package hide.prefab.terrain; - -class CustomRenderer extends h3d.scene.Renderer { - - var passName : String; - - public function new(passName) { - super(); - this.passName = passName; - defaultPass = new h3d.pass.Default("default"); - allPasses.push(defaultPass); - } - - override function start() { - - } - - override function render() { - defaultPass.draw(get(passName)); - } -} \ No newline at end of file diff --git a/hide/prefab/terrain/CustomUV.hx b/hide/prefab/terrain/CustomUV.hx deleted file mode 100644 index 16a738f89..000000000 --- a/hide/prefab/terrain/CustomUV.hx +++ /dev/null @@ -1,27 +0,0 @@ -package hide.prefab.terrain; - -class CustomUV extends hxsl.Shader { - - static var SRC = { - - @:import h3d.shader.BaseMesh; - @param var tileIndex : Float; - - @param var heightMapSize : Vec2; - @param var heightMap : Sampler2D; - @param var primSize : Vec2; - - var calculatedUV : Vec2; - var terrainUV : Vec2; - - function vertex() { - calculatedUV = input.position.xy / primSize.xy; - transformedPosition += (vec3(0,0, heightMap.get(calculatedUV).r) * global.modelView.mat3()); - transformedNormal = vec3(0,0,0); - } - - function fragment() { - pixelColor = vec4(calculatedUV.x, calculatedUV.y, tileIndex , 1); - } - } -} diff --git a/hide/prefab/terrain/GenerateIndex.hx b/hide/prefab/terrain/GenerateIndex.hx deleted file mode 100644 index d417127d7..000000000 --- a/hide/prefab/terrain/GenerateIndex.hx +++ /dev/null @@ -1,29 +0,0 @@ -package hide.prefab.terrain; - -class GenerateIndex extends h3d.shader.ScreenShader { - - static var SRC = { - - @param var weightTextures : Sampler2DArray; - @param var weightCount : Int; - @param var mask : Array; - - function fragment() { - var indexes = vec4(0,0,0,1); - var curMask = 0; - for(i in 0 ... weightCount){ - var w = weightTextures.get(vec3(calculatedUV, i)).r; - if( w > 0 && curMask < 3){ - indexes += mask[curMask] * i / 255.0; - curMask++; - } - } - pixelColor = indexes; - } - } - - public function new(){ - super(); - mask = [new h3d.Vector(1,0,0,0), new h3d.Vector(0,1,0,0), new h3d.Vector(0,0,1,0), new h3d.Vector(0,0,0,1)]; - } -} diff --git a/hide/prefab/terrain/NormalizeWeight.hx b/hide/prefab/terrain/NormalizeWeight.hx deleted file mode 100644 index 0cd1d6432..000000000 --- a/hide/prefab/terrain/NormalizeWeight.hx +++ /dev/null @@ -1,25 +0,0 @@ -package hide.prefab.terrain; - -class NormalizeWeight extends h3d.shader.ScreenShader { - - static var SRC = { - - @param var weightTextures : Sampler2DArray; - @param var weightCount : Int; - @param var baseTexIndex : Int; - @param var curTexIndex : Int; - - function fragment() { - var refValue = weightTextures.get(vec3(calculatedUV, baseTexIndex)).r; - var sum = 0.0; - for(i in 0 ... weightCount) - if(i != baseTexIndex) sum += weightTextures.get(vec3(calculatedUV, i)).r; - var targetSum = 1 - refValue; - pixelColor = vec4(vec3((weightTextures.get(vec3(calculatedUV, curTexIndex)).rgb / sum) * targetSum), 1.0); - - if(baseTexIndex == curTexIndex){ - pixelColor = mix(vec4(1), vec4(refValue), ceil(min(1,sum))); - } - } - } -} diff --git a/hide/prefab/terrain/SetHeight.hx b/hide/prefab/terrain/SetHeight.hx deleted file mode 100644 index 2ae6c9f87..000000000 --- a/hide/prefab/terrain/SetHeight.hx +++ /dev/null @@ -1,17 +0,0 @@ -package hide.prefab.terrain; - -class SetHeight extends h3d.shader.ScreenShader { - - static var SRC = { - - @param var prevHeight : Sampler2D; - @param var strengthTex : Sampler2D; - @param var targetHeight : Float; - - function fragment() { - var height = prevHeight.get(calculatedUV).r; - var strength = strengthTex.get(calculatedUV).r; - pixelColor = vec4(mix(height, targetHeight, clamp(strength,0,1))); - } - } -} diff --git a/hide/prefab/terrain/SmoothHeight.hx b/hide/prefab/terrain/SmoothHeight.hx deleted file mode 100644 index 155d189fd..000000000 --- a/hide/prefab/terrain/SmoothHeight.hx +++ /dev/null @@ -1,27 +0,0 @@ -package hide.prefab.terrain; - -class SmoothHeight extends h3d.shader.ScreenShader { - - static var SRC = { - - @param var prevHeight : Sampler2D; - @param var prevHeightResolution : Vec2; - @param var strengthTex : Sampler2D; - @param var range : Int; - - function fragment() { - var height = prevHeight.get(calculatedUV).r; - var strength = strengthTex.get(calculatedUV).r; - var pixelSize = 1.0 / prevHeightResolution; - - var averageHeight = 0.0; - for( i in -range ... range + 1 ){ - for( j in -range ... range + 1){ - averageHeight += prevHeight.getLod(calculatedUV + pixelSize * vec2(i,j), 0).r; - } - } - averageHeight /= (range * 2 + 1) * (range * 2 + 1); - pixelColor = vec4(mix(height, averageHeight, clamp(strength,0,1))); - } - } -} diff --git a/hide/prefab/terrain/StrokeBuffer.hx b/hide/prefab/terrain/StrokeBuffer.hx deleted file mode 100644 index cc6b2c13f..000000000 --- a/hide/prefab/terrain/StrokeBuffer.hx +++ /dev/null @@ -1,91 +0,0 @@ -package hide.prefab.terrain; - -class StrokeBuffer { - public var tex : h3d.mat.Texture; - public var x : Int; - public var y : Int; - public var used : Bool; - public var prevTex : h3d.mat.Texture; - public var tempTex : h3d.mat.Texture; - public var format : hxd.PixelFormat; - - public function new(size : h2d.col.IPoint, x, y, format){ - this.format = format; - tex = new h3d.mat.Texture(size.x, size.y, [Target], format); - tempTex = new h3d.mat.Texture(size.x, size.y, [Target], format); - tex.filter = Linear; - tempTex.filter = Linear; - this.x = x; - this.y = y; - used = false; - } - - public function dispose(){ - if(tex != null) tex.dispose(); - if(tempTex != null) tempTex.dispose(); - } - - public function refresh(size: h2d.col.IPoint){ - if(tex != null) tex.dispose(); - if(tempTex != null) tempTex.dispose(); - tex = new h3d.mat.Texture(size.x, size.y, [Target], format); - tempTex = new h3d.mat.Texture(size.x, size.y, [Target], format); - tex.filter = Linear; - tempTex.filter = Linear; - tex.preventAutoDispose(); - tempTex.preventAutoDispose(); - } - - public function reset(){ - used = false; - switch tex.format { - case RGB16F, RGB32F: - if(tex != null) tex.clearF(0); - if(tempTex != null) tempTex.clearF(0); - default: - if(tex != null) tex.clear(0); - if(tempTex != null) tempTex.clear(0); - } - } -} - -class StrokeBufferArray{ - - public var strokeBuffers(default, null) : Array = []; - var texSize = new h2d.col.IPoint(0,0); - var format : hxd.PixelFormat; - - public function new(format, texSize : h2d.col.IPoint ) { - this.format = format; - this.texSize = texSize; - } - - public function dispose(){ - for(strokebuffer in strokeBuffers) strokebuffer.dispose(); - } - - public function getStrokeBuffer(x, y){ - for(strokebuffer in strokeBuffers) - if((strokebuffer.x == x && strokebuffer.y == y) || strokebuffer.used == false){ - strokebuffer.x = x; - strokebuffer.y = y; - return strokebuffer; - } - var strokeBuffer = new StrokeBuffer(texSize, x, y, format); - strokeBuffers.push(strokeBuffer); - return strokeBuffer; - } - - public function refresh( size : h2d.col.IPoint ){ - if(texSize == size) return; - texSize = size; - for(strokeBuffer in strokeBuffers) - strokeBuffer.refresh(size); - } - - public function reset(){ - for(strokeBuffer in strokeBuffers){ - strokeBuffer.reset(); - } - } -} diff --git a/hide/prefab/terrain/SwapIndex.hx b/hide/prefab/terrain/SwapIndex.hx deleted file mode 100644 index af9d2f50d..000000000 --- a/hide/prefab/terrain/SwapIndex.hx +++ /dev/null @@ -1,40 +0,0 @@ -package hide.prefab.terrain; - -class SwapIndex extends h3d.shader.ScreenShader { - - static var SRC = { - - @const var USE_ARRAY : Bool; - @const var INDEX_COUNT : Int; - @param var surfaceIndexMap : Sampler2D; - @param var oldIndex : Int; - @param var newIndex : Int; - @param var oldIndexes : Array; - @param var newIndexes : Array; - - function fragment() { - var indexes = surfaceIndexMap.get(calculatedUV); - var i1 = int(indexes.r * 255); - var i2 = int(indexes.g * 255); - var i3 = int(indexes.b * 255); - if(USE_ARRAY){ - for(i in 0 ... INDEX_COUNT){ - if(i1 == int(oldIndexes[i].r)) i1 = int(newIndexes[i].r); - if(i2 == int(oldIndexes[i].r)) i2 = int(newIndexes[i].r); - if(i3 == int(oldIndexes[i].r)) i3 = int(newIndexes[i].r); - } - } - else { - if(i1 == oldIndex) i1 = newIndex; - if(i2 == oldIndex) i2 = newIndex; - if(i3 == oldIndex) i3 = newIndex; - } - pixelColor = vec4(i1 / 255, i2 / 255, i3 / 255, 1); - } - } - - public function new(){ - super(); - this.USE_ARRAY = false; - } -} diff --git a/hide/prefab/terrain/TerrainEditor.hx b/hide/prefab/terrain/TerrainEditor.hx deleted file mode 100644 index 54895becd..000000000 --- a/hide/prefab/terrain/TerrainEditor.hx +++ /dev/null @@ -1,1231 +0,0 @@ -package hide.prefab.terrain; -using Lambda; -import hxd.Pixels; -import hrt.prefab.terrain.Tile; -import hxd.Key as K; -import hrt.prefab.Context; - -enum RenderMode { - PBR; - ShaderComplexity; - Checker; -} - -class TerrainRevertData { - public var surfaceIndex : Int; - public var surface : hrt.prefab.terrain.Surface; - public function new(){ - - } -} - -class TileRevertData { - public var x : Int; - public var y : Int; - public var prevHeightMapPixels : hxd.Pixels; - public var nextHeightMapPixels : hxd.Pixels; - public var prevWeightMapPixels : Array = []; - public var nextWeightMapPixels : Array = []; - public var prevSurfaceIndexMapPixels : hxd.Pixels; - public var nextSurfaceIndexMapPixels : hxd.Pixels; - public function new(x, y){ - this.x = x; - this.y = y; - } -} - -@:access(hrt.prefab.terrain.TerrainMesh) -@:access(hrt.prefab.terrain.Terrain) -@:access(hrt.prefab.terrain.Tile) -class TerrainEditor { - - public var currentBrush = new Brush(); - public var currentSurface : hrt.prefab.terrain.Surface; - public var textureType = ["_Albedo", "_Normal", "_MetallicGlossAO"]; - public var autoCreateTile = false; - public var editContext : hide.prefab.EditContext; - - // Debug - var renderMode : RenderMode = PBR; - // Edition - var brushPreview : hide.prefab.terrain.Brush.BrushPreview; - var interactive : h2d.Interactive; - var remainingDist = 0.0; - var lastPos : h3d.col.Point; - var lastMousePos : h2d.col.Point; - var lastBrushSize : Float; - var heightStrokeBufferArray : hide.prefab.terrain.StrokeBuffer.StrokeBufferArray; - var weightStrokeBufferArray : hide.prefab.terrain.StrokeBuffer.StrokeBufferArray; - // Shader for edition - var copyPass = new h3d.pass.Copy(); - var normalizeWeight = new h3d.pass.ScreenFx(new hide.prefab.terrain.NormalizeWeight()); - var clampWeight = new h3d.pass.ScreenFx(new hide.prefab.terrain.ClampWeight()); - var generateIndex = new h3d.pass.ScreenFx(new hide.prefab.terrain.GenerateIndex()); - var swapIndex = new h3d.pass.ScreenFx(new hide.prefab.terrain.SwapIndex()); - var setHeight = new h3d.pass.ScreenFx(new hide.prefab.terrain.SetHeight()); - var smoothHeight = new h3d.pass.ScreenFx(new hide.prefab.terrain.SmoothHeight()); - // Revert - var terrainPrefab : hrt.prefab.terrain.Terrain; - var undo : hide.ui.UndoHistory; - var tileTrashBin : Array = []; - var paintRevertDatas : Array = []; - // Render UV offscreen - var uvTexPixels : hxd.Pixels; - var uvTex : h3d.mat.Texture; - var uvTexRes = 0.5; - var customScene = new h3d.scene.Scene(false, false); - var customRenderer = new hide.prefab.terrain.CustomRenderer("terrainUV"); - - public function new( terrainPrefab : hrt.prefab.terrain.Terrain, undo : hide.ui.UndoHistory ) { - this.terrainPrefab = terrainPrefab; - this.undo = undo; - renderMode = terrainPrefab.showChecker ? Checker : PBR; - autoCreateTile = terrainPrefab.autoCreateTile; - - brushPreview = new hide.prefab.terrain.Brush.BrushPreview(terrainPrefab.terrain); - - heightStrokeBufferArray = new hide.prefab.terrain.StrokeBuffer.StrokeBufferArray(R32F,new h2d.col.IPoint(terrainPrefab.terrain.heightMapResolution.x, terrainPrefab.terrain.heightMapResolution.y)); - weightStrokeBufferArray = new hide.prefab.terrain.StrokeBuffer.StrokeBufferArray(R8, terrainPrefab.terrain.weightMapResolution); - customScene.renderer = customRenderer; - #if debug - customScene.checkPasses = false; - #end - } - - public function dispose() { - if(uvTex != null) uvTex.dispose(); - heightStrokeBufferArray.dispose(); - weightStrokeBufferArray.dispose(); - brushPreview.remove(); - if( interactive != null ) interactive.remove(); - } - - public function update( ?propName : String ) { - if( propName == "editor.currentSurface.tilling" - || propName == "editor.currentSurface.offset.x" - || propName == "editor.currentSurface.offset.y" - || propName == "editor.currentSurface.angle" - || propName == "editor.currentSurface.minHeight" - || propName == "editor.currentSurface.maxHeight" - || propName == "editor.currentSurface.parallaxAmount" ) - terrainPrefab.terrain.updateSurfaceParams(); - - autoCreateTile = terrainPrefab.autoCreateTile; - brushPreview.opacity = terrainPrefab.brushOpacity; - - if( propName == "editor.renderMode" ) updateRender(); - } - - public function refresh() { - heightStrokeBufferArray.refresh(new h2d.col.IPoint(terrainPrefab.terrain.heightMapResolution.x + 1, terrainPrefab.terrain.heightMapResolution.y + 1)); - weightStrokeBufferArray.refresh(terrainPrefab.terrain.weightMapResolution); - } - - function updateRender() { - for( tile in terrainPrefab.terrain.tiles ) - tile.material.removePass(tile.material.getPass("overlay")); - terrainPrefab.terrain.showChecker = false; - terrainPrefab.terrain.showComplexity = false; - terrainPrefab.showChecker = false; - switch( renderMode ) { - case PBR : - case ShaderComplexity : terrainPrefab.terrain.showComplexity = true; - case Checker : - terrainPrefab.terrain.showChecker = true; - terrainPrefab.showChecker = true; - } - } - - function renderTerrainUV( ctx : Context ) { - if( customScene == null ) return; - if( ctx == null || ctx.local3d == null || ctx.local3d.getScene() == null ) return; - var engine = h3d.Engine.getCurrent(); - var mainScene = @:privateAccess ctx.local3d.getScene(); - - if( uvTex == null || uvTex.width != Std.int(h3d.Engine.getCurrent().width * uvTexRes) || uvTex.height != Std.int(h3d.Engine.getCurrent().height * uvTexRes) ) { - if(uvTex != null) { - uvTex.depthBuffer.dispose(); - uvTex.dispose(); - } - uvTex = new h3d.mat.Texture( Std.int(h3d.Engine.getCurrent().width * uvTexRes), Std.int(h3d.Engine.getCurrent().height * uvTexRes), [Target], RGBA32F); - uvTex.depthBuffer = new h3d.mat.DepthBuffer(uvTex.width, uvTex.height); - } - - var prevParent = terrainPrefab.terrain.parent; - @:privateAccess { - customScene.children = [terrainPrefab.terrain]; // Prevent OnRemove() call - terrainPrefab.terrain.parent = customScene; - } - - customScene.camera = mainScene.camera; - brushPreview.reset(); - - var tiles = terrainPrefab.terrain.tiles; - for( i in 0 ... tiles.length ) { - var tile = tiles[i]; - var p = new h3d.mat.Pass("terrainUV"); - p.addShader(new h3d.shader.BaseMesh()); - p.depthTest = Less; - p.culling = None; - p.depthWrite = true; - tile.material.addPass(p); - var s = new hide.prefab.terrain.CustomUV(); - s.primSize.set(terrainPrefab.terrain.tileSize.x, terrainPrefab.terrain.tileSize.y); - s.heightMapSize.set(terrainPrefab.terrain.heightMapResolution.x, terrainPrefab.terrain.heightMapResolution.y); - s.heightMap = tile.heightMap; - s.tileIndex = i; - p.addShader(s); - } - - engine.begin(); - engine.pushTarget(uvTex); - engine.clear(0xffffff,1,0); - engine.clearF(new h3d.Vector(-1, -1, -1, -1),1,0); - customScene.render(engine); - engine.popTarget(); - - for( tile in tiles ) - tile.material.removePass(tile.material.getPass("terrainUV")); - - @:privateAccess { - customScene.children = []; - terrainPrefab.terrain.parent = prevParent; - } - customScene.camera = null; - - uvTexPixels = uvTex.capturePixels(); - } - - function checkTrashBin() { - if( tileTrashBin.length > 0 ) { - var tileTrashBinTmp = tileTrashBin.copy(); - tileTrashBin = []; - undo.change(Custom(function(undo) { - for( t in tileTrashBinTmp ) { - if( undo ) { - var tile = terrainPrefab.terrain.createTile(t.x, t.y); - tile.material.mainPass.stencil = new h3d.mat.Stencil(); - tile.material.mainPass.stencil.setFunc(Always, 0x01, 0x01, 0x01); - tile.material.mainPass.stencil.setOp(Keep, Keep, Replace); - tile.refreshHeightMap(); - tile.refreshNormalMap(); - tile.refreshIndexMap(); - tile.refreshSurfaceWeightArray(); - tile.heightMap.uploadPixels(t.prevHeightMapPixels); - tile.surfaceIndexMap.uploadPixels(t.prevSurfaceIndexMapPixels); - for( i in 0 ... t.prevWeightMapPixels.length ) - tile.surfaceWeights[i].uploadPixels(t.prevWeightMapPixels[i]); - tile.generateWeightTextureArray(); - } - else - terrainPrefab.terrain.removeTileAt(t.x, t.y); - } - })); - tileTrashBin = []; - } - } - - function blendEdges( modifiedTile : Array ) { - - // Adjust the edge for each modified tiles and their neighbors - var tiles : Array = []; - for( t in modifiedTile ) { - for( i in -1 ... 2 ) { - for( j in - 1 ... 2 ) { - var adj = t.terrain.getTile(t.tileX + i, t.tileY + j); - if( adj != null && tiles.indexOf(adj) == -1 ) - tiles.push(adj); - } - } - } - - // Adjust the height to avoid seams - for( t in tiles ) { - var pixels = t.getHeightMapPixels(); - if( pixels == null ) - throw("Try to blend the edges of a null heightmap."); - var adjTileX = t.terrain.getTile(t.tileX + 1, t.tileY); - var adjHeightMapX = adjTileX != null ? adjTileX.heightMap : null; - if( adjHeightMapX != null ) { - var adjpixels = adjTileX.getHeightMapPixels(); - for( i in 0 ... t.heightMap.height ) { - pixels.setPixelF(t.heightMap.width - 1, i, adjpixels.getPixelF(0,i) ); - } - } - - var adjTileY = t.terrain.getTile(t.tileX, t.tileY + 1); - var adjHeightMapY = adjTileY != null ? adjTileY.heightMap : null; - if( adjHeightMapY != null ) { - var adjpixels = adjTileY.getHeightMapPixels(); - for( i in 0 ... t.heightMap.width ) { - pixels.setPixelF(i, t.heightMap.height - 1, adjpixels.getPixelF(i,0) ); - } - } - - var adjTileXY = t.terrain.getTile(t.tileX + 1, t.tileY + 1); - var adjHeightMapXY = adjTileXY != null ? adjTileXY.heightMap : null; - if( adjHeightMapXY != null ) { - var adjpixels = adjTileXY.getHeightMapPixels(); - pixels.setPixelF(t.heightMap.width - 1, t.heightMap.height - 1, adjpixels.getPixelF(0,0)); - } - - t.heightMapPixels = pixels; - t.heightMap.uploadPixels(pixels); - t.needNewPixelCapture = false; - } - - // Compute the normal for each tile, but there's seam on the edge - for( t in tiles ) { - t.bakeNormal(); - t.normalMapPixels = t.normalMap.capturePixels(); - } - - // Compute the average normal on edge - for( t in tiles ) { - - var pixelsAfterBlend = t.normalMapPixels; - var left = t.terrain.getTile(t.tileX - 1, t.tileY); - var right = t.terrain.getTile(t.tileX + 1, t.tileY); - var up = t.terrain.getTile(t.tileX, t.tileY - 1); - var down = t.terrain.getTile(t.tileX, t.tileY + 1); - var upRight = t.terrain.getTile(t.tileX + 1, t.tileY - 1); - var upLeft = t.terrain.getTile(t.tileX - 1, t.tileY - 1); - var downRight = t.terrain.getTile(t.tileX + 1, t.tileY + 1); - var downLeft = t.terrain.getTile(t.tileX - 1, t.tileY + 1); - var width = pixelsAfterBlend.width - 1; - var height = pixelsAfterBlend.height - 1; - - // Return the normal of tile t at (x,y) without any blend - function getNormalFromHeightMap(t : Tile, x : Int, y : Int ) { - var h = t.heightMapPixels.getPixelF(x, y).x; - var h1 = y + 1 >= t.heightMapPixels.height ? h : t.heightMapPixels.getPixelF(x, y + 1).x; - var h2 = x + 1 >= t.heightMapPixels.width ? h : t.heightMapPixels.getPixelF(x + 1, y).x; - var h3 = y - 1 < 0 ? h : t.heightMapPixels.getPixelF(x, y - 1).x; - var h4 = x - 1 < 0 ? h : t.heightMapPixels.getPixelF(x - 1, y).x; - var v1 = new h3d.Vector(0, 1, h1 - h); - var v2 = new h3d.Vector(1, 0, h2 - h); - var v3 = new h3d.Vector(0, -1, h3 - h); - var v4 = new h3d.Vector(-1, 0, h4 - h); - var n = v1.cross(v2).add(v2.cross(v3).add(v3.cross(v4).add(v4.cross(v1)))); - n.scale3(-1.0); - n.normalize(); - return n; - } - - inline function packNormal( n : h3d.Vector ) { - n.scale3(0.5); - return n.add(new h3d.Vector(0.5, 0.5, 0.5)).toColor(); - } - - inline function unpackNormal( n : Int ) { - var n = h3d.Vector.fromColor(n); - n = n.add(new h3d.Vector(-0.5, -0.5, -0.5)); - n.scale3(2.0); - return n; - } - - for( i in 1 ... pixelsAfterBlend.width - 1 ) { - if( up != null ) { - var n = unpackNormal(pixelsAfterBlend.getPixel(i, 0)).add(getNormalFromHeightMap(up, i, height)); - n.normalize(); - pixelsAfterBlend.setPixel(i, 0, packNormal(n)); - } - if( down != null ) { - var n = unpackNormal(pixelsAfterBlend.getPixel(i, height)).add(getNormalFromHeightMap(down, i, 0)); - n.normalize(); - pixelsAfterBlend.setPixel(i, height, packNormal(n)); - } - } - for( i in 1 ... pixelsAfterBlend.height - 1 ) { - if( left != null ) { - var n = unpackNormal(pixelsAfterBlend.getPixel(0, i)).add(getNormalFromHeightMap(left, width, i)); - n.normalize(); - pixelsAfterBlend.setPixel(0, i, packNormal(n)); - } - if( right != null ) { - var n = unpackNormal(pixelsAfterBlend.getPixel(width, i)).add(getNormalFromHeightMap(right, 0, i)); - n.normalize(); - pixelsAfterBlend.setPixel(width, i, packNormal(n)); - } - } - - var n = unpackNormal(pixelsAfterBlend.getPixel(0, 0)); - if( up != null ) n = n.add(getNormalFromHeightMap(up, 0, height)); - if( left != null ) n = n.add(getNormalFromHeightMap(left, width, 0)); - if( upLeft != null ) n = n.add(getNormalFromHeightMap(upLeft, width, height)); - n.normalize(); - pixelsAfterBlend.setPixel(0, 0, packNormal(n)); - - var n = unpackNormal(pixelsAfterBlend.getPixel(width, 0)); - if( up != null ) n = n.add(getNormalFromHeightMap(up, width, height)); - if( right != null ) n = n.add(getNormalFromHeightMap(right, 0, 0)); - if( upRight != null ) n = n.add(getNormalFromHeightMap(upRight, 0, height)); - n.normalize(); - pixelsAfterBlend.setPixel(width, 0, packNormal(n)); - - var n = unpackNormal(pixelsAfterBlend.getPixel(0, height)); - if( down != null ) n = n.add(getNormalFromHeightMap(down, 0, 0)); - if( left != null ) n = n.add(getNormalFromHeightMap(left, width, height)); - if( downLeft != null ) n = n.add(getNormalFromHeightMap(downLeft, width, 0)); - n.normalize(); - pixelsAfterBlend.setPixel(0, height, packNormal(n)); - - var n = unpackNormal(pixelsAfterBlend.getPixel(width, height)); - if( down != null ) n = n.add(getNormalFromHeightMap(down, width, 0)); - if( right != null ) n = n.add(getNormalFromHeightMap(right, 0, height)); - if( downRight != null ) n = n.add(getNormalFromHeightMap(downRight, 0, 0)); - n.normalize(); - pixelsAfterBlend.setPixel(width, height, packNormal(n)); - - t.normalMap.uploadPixels(pixelsAfterBlend); - t.needNormalBake = false; - } - } - - function resetStrokeBuffers() { - heightStrokeBufferArray.reset(); - weightStrokeBufferArray.reset(); - } - - function applyStrokeBuffers() { - - var revertDatas = new Array(); - - for( strokeBuffer in heightStrokeBufferArray.strokeBuffers ) { - if( strokeBuffer.used == true ) { - var tile = terrainPrefab.terrain.getTile(strokeBuffer.x, strokeBuffer.y); - strokeBuffer.tempTex = tile.heightMap; - tile.heightMap = strokeBuffer.prevTex; - strokeBuffer.prevTex = null; - var revert = new TileRevertData(strokeBuffer.x, strokeBuffer.y); - revert.prevHeightMapPixels = tile.heightMapPixels; - - switch( currentBrush.brushMode.mode ) { - case AddSub : - copyPass.apply(strokeBuffer.tex, tile.heightMap, currentBrush.brushMode.subAction ? Sub : Add); - case Set : - copyPass.apply(tile.heightMap, strokeBuffer.tempTex); - setHeight.shader.prevHeight = strokeBuffer.tempTex; - setHeight.shader.targetHeight = currentBrush.brushMode.setHeightValue; - setHeight.shader.strengthTex = strokeBuffer.tex; - h3d.Engine.getCurrent().pushTarget(tile.heightMap); - setHeight.render(); - case Smooth : - copyPass.apply(tile.heightMap, strokeBuffer.tempTex); - smoothHeight.shader.prevHeight = strokeBuffer.tempTex; - smoothHeight.shader.prevHeightResolution = new h3d.Vector(strokeBuffer.tempTex.width, strokeBuffer.tempTex.height); - smoothHeight.shader.range = 4; - smoothHeight.shader.strengthTex = strokeBuffer.tex; - h3d.Engine.getCurrent().pushTarget(tile.heightMap); - smoothHeight.render(); - default: - } - revertDatas.push(revert); - tile.heightMapPixels = tile.heightMap.capturePixels(); - revert.nextHeightMapPixels = tile.heightMapPixels; - tile.cachedBounds = null; - } - } - var tiles = [ for( sb in heightStrokeBufferArray.strokeBuffers ) { if( sb.used ) terrainPrefab.terrain.getTile(sb.x, sb.y); }]; - blendEdges(tiles); - - if( revertDatas.length > 0 ) { - undo.change(Custom(function(undo) { - for( revertData in revertDatas ) { - var tile = terrainPrefab.terrain.getTile(revertData.x, revertData.y); - if( tile == null ) continue; - tile.heightMap.uploadPixels(undo ? revertData.prevHeightMapPixels : revertData.nextHeightMapPixels); - tile.heightMapPixels = undo ? revertData.prevHeightMapPixels : revertData.nextHeightMapPixels; - } - var tiles = [ for( rd in revertDatas ) { terrainPrefab.terrain.getTile(rd.x, rd.y); }]; - blendEdges(tiles); - })); - } - - for( strokeBuffer in weightStrokeBufferArray.strokeBuffers ) { - if( strokeBuffer.used == true ) { - var tile = terrainPrefab.terrain.getTile(strokeBuffer.x, strokeBuffer.y); - strokeBuffer.tempTex = tile.surfaceWeights[currentBrush.index]; - tile.surfaceWeights[currentBrush.index] = strokeBuffer.prevTex; - strokeBuffer.prevTex = null; - - copyPass.apply(strokeBuffer.tex, tile.surfaceWeights[currentBrush.index], currentBrush.brushMode.subAction ? Sub : Add); - tile.generateWeightTextureArray(); - - clampWeight.shader.weightTextures = tile.surfaceWeightArray; - clampWeight.shader.weightCount = tile.surfaceWeights.length; - clampWeight.shader.baseTexIndex = currentBrush.index; - for( i in 0 ... tile.surfaceWeights.length ) { - if( i == currentBrush.index ) continue; - clampWeight.shader.curTexIndex = i; - h3d.Engine.getCurrent().pushTarget(tile.surfaceWeights[i]); - clampWeight.render(); - } - tile.generateWeightTextureArray(); - - normalizeWeight.shader.weightTextures = tile.surfaceWeightArray; - normalizeWeight.shader.weightCount = tile.surfaceWeights.length; - normalizeWeight.shader.baseTexIndex = currentBrush.index; - for( i in 0 ... tile.surfaceWeights.length ) { - normalizeWeight.shader.curTexIndex = i; - h3d.Engine.getCurrent().pushTarget(tile.surfaceWeights[i]); - normalizeWeight.render(); - } - tile.generateWeightTextureArray(); - - var revert : TileRevertData = null; - for( r in paintRevertDatas ) - if( r.x == strokeBuffer.x && r.y == strokeBuffer.y ) { - revert = r; - break; - } - if( revert != null ) - for( w in tile.surfaceWeights ) - revert.nextWeightMapPixels.push(w.capturePixels()); - - generateIndex.shader.weightTextures = tile.surfaceWeightArray; - generateIndex.shader.weightCount = tile.surfaceWeights.length; - h3d.Engine.getCurrent().pushTarget(tile.surfaceIndexMap); - generateIndex.render(); - } - } - - if( paintRevertDatas.length > 0 ) { - var paintRevertdataTmp = paintRevertDatas.copy(); - paintRevertDatas = []; - undo.change(Custom(function(undo) { - for( revertData in paintRevertdataTmp ) { - var tile = terrainPrefab.terrain.getTile(revertData.x, revertData.y); - if (tile == null ) continue; - for (i in 0 ... tile.surfaceWeights.length ) - tile.surfaceWeights[i].uploadPixels(undo ? revertData.prevWeightMapPixels[i] : revertData.nextWeightMapPixels[i]); - tile.generateWeightTextureArray(); - generateIndex.shader.weightTextures = tile.surfaceWeightArray; - generateIndex.shader.weightCount = tile.surfaceWeights.length; - h3d.Engine.getCurrent().pushTarget(tile.surfaceIndexMap); - generateIndex.render(); - } - })); - } - } - - function previewStrokeBuffers() { - for( strokeBuffer in heightStrokeBufferArray.strokeBuffers ) { - if( strokeBuffer.used == true ) { - var tile = terrainPrefab.terrain.getTile(strokeBuffer.x, strokeBuffer.y); - switch( currentBrush.brushMode.mode ) { - case AddSub : - copyPass.apply(strokeBuffer.prevTex, tile.heightMap); - copyPass.apply(strokeBuffer.tex, tile.heightMap, currentBrush.brushMode.subAction ? Sub : Add); - case Set : - setHeight.shader.prevHeight = strokeBuffer.prevTex; - setHeight.shader.targetHeight = currentBrush.brushMode.setHeightValue; - setHeight.shader.strengthTex = strokeBuffer.tex; - h3d.Engine.getCurrent().pushTarget(tile.heightMap); - setHeight.render(); - case Smooth : - smoothHeight.shader.prevHeight = strokeBuffer.prevTex; - smoothHeight.shader.prevHeightResolution = new h3d.Vector(strokeBuffer.tempTex.width, strokeBuffer.tempTex.height); - smoothHeight.shader.range = 4; - smoothHeight.shader.strengthTex = strokeBuffer.tex; - h3d.Engine.getCurrent().pushTarget(tile.heightMap); - smoothHeight.render(); - default: - } - } - } - - for( strokeBuffer in weightStrokeBufferArray.strokeBuffers ) { - if( strokeBuffer.used == true ) { - var tile = terrainPrefab.terrain.getTile(strokeBuffer.x, strokeBuffer.y); - copyPass.apply(strokeBuffer.prevTex, strokeBuffer.tempTex); - copyPass.apply(strokeBuffer.tex, strokeBuffer.tempTex, currentBrush.brushMode.subAction ? Sub : Add); - tile.generateWeightTextureArray(); - - var engine = h3d.Engine.getCurrent(); - clampWeight.shader.weightTextures = tile.surfaceWeightArray; - clampWeight.shader.weightCount = tile.surfaceWeights.length; - clampWeight.shader.baseTexIndex = currentBrush.index; - for( i in 0 ... tile.surfaceWeights.length) { - if( i == currentBrush.index ) continue; - clampWeight.shader.curTexIndex = i; - engine.pushTarget(tile.surfaceWeights[i]); - clampWeight.render(); - } - tile.generateWeightTextureArray(); - - normalizeWeight.shader.weightTextures = tile.surfaceWeightArray; - normalizeWeight.shader.weightCount = tile.surfaceWeights.length; - normalizeWeight.shader.baseTexIndex = currentBrush.index; - for( i in 0 ... tile.surfaceWeights.length ) { - normalizeWeight.shader.curTexIndex = i; - engine.pushTarget(tile.surfaceWeights[i]); - normalizeWeight.render(); - } - tile.generateWeightTextureArray(); - - generateIndex.shader.weightTextures = tile.surfaceWeightArray; - generateIndex.shader.weightCount = tile.surfaceWeights.length; - engine.pushTarget(tile.surfaceIndexMap); - generateIndex.render(); - } - } - } - - function projectToGround( ray: h3d.col.Ray ) { - var minDist = -1.; - var normal = terrainPrefab.terrain.getAbsPos().up(); - var plane = h3d.col.Plane.fromNormalPoint(normal.toPoint(), new h3d.col.Point(terrainPrefab.terrain.getAbsPos().tx, terrainPrefab.terrain.getAbsPos().ty, terrainPrefab.terrain.getAbsPos().tz)); - var pt = ray.intersect(plane); - if(pt != null) { minDist = pt.sub(ray.getPos()).length();} - return minDist; - } - - function screenToWorld( u : Float, v : Float, ctx : Context ) { - if( ctx == null || ctx.local3d == null || ctx.local3d.getScene() == null ) return new h3d.col.Point(); - var camera = @:privateAccess ctx.local3d.getScene().camera; - var ray = camera.rayFromScreen(u, v); - var dist = projectToGround(ray); - return dist >= 0 ? ray.getPoint(dist) : new h3d.col.Point(); - } - - function worldToScreen( wx: Float, wy: Float, wz: Float, ctx : Context ) { - if( ctx == null || ctx.local3d == null || ctx.local3d.getScene() == null || ctx.local2d == null || ctx.local2d.getScene() == null ) return new h2d.col.Point(); - var camera = @:privateAccess ctx.local3d.getScene().camera; - var pt = camera.project(wx, wy, wz, h3d.Engine.getCurrent().width, h3d.Engine.getCurrent().height); - return new h2d.col.Point(hxd.Math.abs(pt.x), hxd.Math.abs(pt.y)); - } - - function getBrushPlanePos( mouseX : Float, mouseY : Float, ctx : Context ) { - var worldPos = screenToWorld(mouseX, mouseY, ctx); - if( currentBrush.brushMode.snapToGrid ) { - var localPos = terrainPrefab.terrain.globalToLocal(worldPos.clone()); - localPos.x = hxd.Math.round(localPos.x / terrainPrefab.terrain.cellSize.x) * terrainPrefab.terrain.cellSize.x; - localPos.y = hxd.Math.round(localPos.y / terrainPrefab.terrain.cellSize.y) * terrainPrefab.terrain.cellSize.y; - localPos.z = localPos.z; - worldPos = terrainPrefab.terrain.globalToLocal(localPos.clone()); - } - return worldPos; - } - - function getBrushWorldPosFromTex( worldPos : h3d.col.Point, ctx : Context ) : h3d.col.Point { - if(currentBrush.brushMode.snapToGrid) return worldPos; - var screenPos = worldToScreen(worldPos.x, worldPos.y, worldPos.z, ctx); - var brushWorldPos = worldPos.clone(); - var fetchPos = new h2d.col.Point(hxd.Math.floor(screenPos.x * uvTexRes), hxd.Math.floor(screenPos.y * uvTexRes)); - fetchPos.x = hxd.Math.clamp(fetchPos.x, 0, uvTexPixels.width - 1); - fetchPos.y = hxd.Math.clamp(fetchPos.y, 0, uvTexPixels.height - 1); - var pixel = uvTexPixels.getPixelF( Std.int(fetchPos.x), Std.int(fetchPos.y)); - var tiles = terrainPrefab.terrain.tiles; - for( i in 0 ... tiles.length ) - if( hxd.Math.ceil(pixel.z) == i ) - brushWorldPos = tiles[i].localToGlobal(new h3d.col.Point(pixel.x * terrainPrefab.tileSizeX, pixel.y * terrainPrefab.tileSizeY, 0)); - return brushWorldPos; - } - - function drawBrushPreview( worldPos : h3d.col.Point, ctx : Context ) { - if( ctx == null || ctx.local3d == null || ctx.local3d.getScene() == null ) return; - brushPreview.reset(); - if( currentBrush.brushMode.mode == Delete || currentBrush.bitmap == null ) return; - var brushWorldPos = uvTexPixels == null ? worldPos : getBrushWorldPosFromTex(worldPos, ctx); - brushPreview.previewAt(currentBrush, brushWorldPos); - } - - function applyBrush( pos : h3d.col.Point, ctx : Context ) { - switch ( currentBrush.brushMode.mode ) { - case Paint: drawSurface(pos, ctx); - case AddSub: drawHeight(pos, ctx); - case Smooth: drawHeight(pos, ctx); - case Set: drawHeight(pos, ctx); - case Delete: deleteTile(pos, ctx); - default: - } - terrainPrefab.modified = true; - } - - function useBrush( from : h3d.col.Point, to : h3d.col.Point, ctx : Context ) { - var dist = (to.sub(from)).length(); - if( currentBrush.firstClick ) { - if( currentBrush.brushMode.mode == Set ) { - if( currentBrush.brushMode.subAction ) - currentBrush.brushMode.setHeightValue = terrainPrefab.terrain.getHeight(from.x, from.y); - else - currentBrush.brushMode.setHeightValue = currentBrush.strength; - } - applyBrush(from, ctx); - previewStrokeBuffers(); - return; - } - - if( currentBrush == null || currentBrush.step <= 0 ) return; - - var dist = (to.sub(from)).length(); - if( dist + remainingDist >= currentBrush.step ) { - var dir = to.sub(from); - dir.normalize(); - var pos = from.clone(); - var step = dir.clone(); - step.scale(currentBrush.step); - while( dist + remainingDist >= currentBrush.step ) { - if( remainingDist > 0 ) { - var firstStep = dir.clone(); - firstStep.scale(currentBrush.step - remainingDist); - pos = pos.add(firstStep); - }else - pos = pos.add(step); - applyBrush(pos, ctx); - dist -= currentBrush.step - remainingDist; - remainingDist = 0; - } - remainingDist = dist; - previewStrokeBuffers(); - }else - remainingDist += dist; - } - - public function deleteTile( pos : h3d.col.Point, ctx : Context ) { - var brushWorldPos = uvTexPixels == null ? pos : getBrushWorldPosFromTex(pos, ctx); - if( brushWorldPos == null ) return; - var tile = terrainPrefab.terrain.getTileAtWorldPos(brushWorldPos.x, brushWorldPos.y); - if( tile == null ) return; - var trd = new TileRevertData(tile.tileX, tile.tileY); - trd.prevHeightMapPixels = tile.heightMap.capturePixels(); - trd.prevSurfaceIndexMapPixels = tile.surfaceIndexMap.capturePixels(); - for( w in tile.surfaceWeights ) - trd.prevWeightMapPixels.push(w.capturePixels()); - tileTrashBin.push(trd); - terrainPrefab.terrain.removeTile(tile); - renderTerrainUV(ctx); - } - - public function drawSurface( pos : h3d.col.Point, ctx : Context ) { - if( currentBrush.index == -1 ) return; - var brushWorldPos = uvTexPixels == null ? pos : getBrushWorldPosFromTex(pos, ctx); - if( brushWorldPos == null ) return; - var c = terrainPrefab.terrain.tiles.length; - var tiles = terrainPrefab.terrain.getTiles(brushWorldPos.x, brushWorldPos.y, currentBrush.size / 2.0, autoCreateTile); - if( c != terrainPrefab.terrain.tiles.length ) { - renderTerrainUV(ctx); - brushWorldPos = getBrushWorldPosFromTex(pos, ctx); - } - - currentBrush.bitmap.color = new h3d.Vector(1.0); - var shader : hrt.shader.Brush = currentBrush.bitmap.getShader(hrt.shader.Brush); - if( shader == null ) shader = currentBrush.bitmap.addShader(new hrt.shader.Brush()); - currentBrush.bitmap.blendMode = currentBrush.brushMode.accumulate ? Add : Max; - shader.strength = currentBrush.strength; - shader.size.set(currentBrush.size / terrainPrefab.tileSizeX, currentBrush.size / terrainPrefab.tileSizeY); - - for( tile in tiles ) { - var strokeBuffer = weightStrokeBufferArray.getStrokeBuffer(tile.tileX, tile.tileY); - if( strokeBuffer.used == false ) { - var revert = new TileRevertData(strokeBuffer.x, strokeBuffer.y); - for( w in tile.surfaceWeights ) - revert.prevWeightMapPixels.push(w.capturePixels()); - paintRevertDatas.push(revert); - strokeBuffer.prevTex = tile.surfaceWeights[currentBrush.index]; - tile.surfaceWeights[currentBrush.index] = strokeBuffer.tempTex; - strokeBuffer.used = true; - } - var localPos = tile.globalToLocal(brushWorldPos.clone()); - localPos.x *= 1.0 / terrainPrefab.tileSizeX; - localPos.y *= 1.0 / terrainPrefab.tileSizeY; - shader.pos = new h3d.Vector(localPos.x - (currentBrush.size / terrainPrefab.tileSizeX * 0.5), localPos.y - (currentBrush.size / terrainPrefab.tileSizeY * 0.5)); - currentBrush.drawTo(strokeBuffer.tex, localPos, terrainPrefab.terrain.tileSize ); - } - } - - public function drawHeight( pos : h3d.col.Point, ctx : Context ) { - var brushWorldPos = uvTexPixels == null ? pos : getBrushWorldPosFromTex(pos, ctx); - if( brushWorldPos == null ) return; - var c = terrainPrefab.terrain.tiles.length; - var tiles = terrainPrefab.terrain.getTiles(brushWorldPos.x, brushWorldPos.y, currentBrush.size / 2.0, autoCreateTile); - if( c != terrainPrefab.terrain.tiles.length ) { - renderTerrainUV(ctx); - brushWorldPos = getBrushWorldPosFromTex(pos, ctx); - } - - var shader : hrt.shader.Brush = currentBrush.bitmap.getShader(hrt.shader.Brush); - if( shader == null ) shader = currentBrush.bitmap.addShader(new hrt.shader.Brush()); - currentBrush.bitmap.color = new h3d.Vector(1.0); - shader.size.set(currentBrush.size / terrainPrefab.tileSizeX, currentBrush.size / terrainPrefab.tileSizeY); - - switch( currentBrush.brushMode.mode ) { - case AddSub : - currentBrush.bitmap.blendMode = currentBrush.brushMode.accumulate ? Add : Max; - shader.strength = currentBrush.strength; - case Set : - currentBrush.bitmap.blendMode = Max; - shader.strength = 1; - case Smooth : - currentBrush.bitmap.blendMode = Max; - shader.strength = 1; - default: - } - - for( tile in tiles ) { - var localPos = tile.globalToLocal(brushWorldPos.clone()); - localPos.x *= 1.0 / terrainPrefab.tileSizeX; - localPos.y *= 1.0 / terrainPrefab.tileSizeY; - var strokeBuffer = heightStrokeBufferArray.getStrokeBuffer(tile.tileX, tile.tileY); - if( strokeBuffer.used == false ) { - strokeBuffer.prevTex = tile.heightMap; - tile.heightMap = strokeBuffer.tempTex; - strokeBuffer.used = true; - } - shader.pos = new h3d.Vector(localPos.x - (currentBrush.size / terrainPrefab.tileSizeX * 0.5), localPos.y - (currentBrush.size / terrainPrefab.tileSizeY * 0.5)); - currentBrush.drawTo(strokeBuffer.tex, localPos, terrainPrefab.terrain.tileSize, -1); - } - } - - public function setSelected( ctx : Context, b : Bool ) { - if( b ) { - var s2d = @:privateAccess ctx.local2d.getScene(); - if( interactive == null ) - interactive.remove(); - interactive = new h2d.Interactive(10000, 10000, s2d); - interactive.propagateEvents = true; - interactive.cancelEvents = false; - - interactive.onWheel = function(e) { - e.propagate = true; - var worldPos = getBrushPlanePos(s2d.mouseX, s2d.mouseY, ctx); - renderTerrainUV(ctx); - drawBrushPreview(worldPos, ctx); - }; - - interactive.onPush = function(e) { - e.propagate = false; - currentBrush.brushMode.lockDir = K.isDown(K.ALT); - currentBrush.brushMode.subAction = K.isDown(K.SHIFT); - currentBrush.brushMode.snapToGrid = K.isDown(K.CTRL); - var worldPos = getBrushPlanePos(s2d.mouseX, s2d.mouseY, ctx); - if( K.isDown( K.MOUSE_LEFT) ) { - currentBrush.firstClick = true; - lastPos = worldPos.clone(); - if( currentBrush.isValid() ) { - useBrush( lastPos, worldPos, ctx); - previewStrokeBuffers(); - drawBrushPreview(worldPos, ctx); - } - } - }; - - interactive.onRelease = function(e) { - e.propagate = false; - var worldPos = getBrushPlanePos(s2d.mouseX, s2d.mouseY, ctx); - remainingDist = 0; - lastPos = null; - currentBrush.brushMode.lockAxe = NoLock; - currentBrush.firstClick = false; - applyStrokeBuffers(); - resetStrokeBuffers(); - drawBrushPreview(worldPos, ctx); - checkTrashBin(); - }; - - interactive.onMove = function(e) { - - // Brush Scale - Drag left/right - if( K.isDown(K.MOUSE_RIGHT) && K.isDown(K.CTRL) ) { - if( lastMousePos == null ) { - lastMousePos = new h2d.col.Point(s2d.mouseX, s2d.mouseY); - lastBrushSize = currentBrush.size; - } - e.propagate = false; - var newMousePos = new h2d.col.Point(s2d.mouseX, s2d.mouseY); - var dist = newMousePos.x - lastMousePos.x; - var sensibility = 0.5; - currentBrush.size = hxd.Math.max(0, lastBrushSize + sensibility * dist); - @:privateAccess Lambda.find(editContext.properties.fields, f->f.fname=="editor.currentBrush.size").range.value = currentBrush.size; - drawBrushPreview(getBrushPlanePos(lastMousePos.x, lastMousePos.y, ctx), ctx); - return; - } - else { - lastMousePos = null; - lastBrushSize = 0; - } - - currentBrush.brushMode.snapToGrid = /*K.isDown(K.CTRL)*/ false; - var worldPos = getBrushPlanePos(s2d.mouseX, s2d.mouseY, ctx); - if( K.isDown( K.MOUSE_LEFT) ) { - currentBrush.firstClick = false; - e.propagate = false; - if( lastPos == null ) return; - if( currentBrush.isValid() ) { - if( currentBrush.brushMode.lockDir ){ - var dir = worldPos.sub(lastPos); - if( currentBrush.brushMode.lockAxe == NoLock && dir.length() > 0.4 ) - currentBrush.brushMode.lockAxe = hxd.Math.abs(dir.x) > hxd.Math.abs(dir.y) ? LockX : LockY; - if( currentBrush.brushMode.lockAxe == LockX ) { - var distX = worldPos.sub(lastPos).x; - worldPos.load(lastPos); - worldPos.x += distX; - } - else if( currentBrush.brushMode.lockAxe == LockY ) { - var distY = worldPos.sub(lastPos).y; - worldPos.load(lastPos); - worldPos.y += distY; - } - } - useBrush( lastPos, worldPos, ctx); - lastPos = worldPos; - } - } - else { - renderTerrainUV(ctx); - e.propagate = true; - } - drawBrushPreview(worldPos, ctx); - }; - } - else { - if( interactive != null ) interactive.remove(); - brushPreview.reset(); - } - } - - function removeSurface( index :Int, onChange : Void -> Void ) { - terrainPrefab.modified = true; - var terrainRevertData = new TerrainRevertData(); - var tileRevertDatas = new Array(); - for( tile in terrainPrefab.terrain.tiles ) - tileRevertDatas.push(new TileRevertData(tile.tileX, tile.tileY)); - - var oldIndexes : Array = []; - var newIndexes : Array = []; - for( i in 0 ... terrainPrefab.terrain.surfaces.length ) - oldIndexes.push(new h3d.Vector(i)); - var offset = 0; - for( i in 0 ... terrainPrefab.terrain.surfaces.length ) { - if( i == index ) { - offset = -1; - newIndexes.push(new h3d.Vector(0)); // Replace the surface removec by the surface 0 - } - else - newIndexes.push(new h3d.Vector(i + offset)); - } - - swapIndex.shader.USE_ARRAY = true; - swapIndex.shader.INDEX_COUNT = oldIndexes.length; - swapIndex.shader.oldIndexes = oldIndexes; - swapIndex.shader.newIndexes = newIndexes; - var newSurfaceIndexMap = new h3d.mat.Texture(terrainPrefab.terrain.weightMapResolution.x, terrainPrefab.terrain.weightMapResolution.y, [Target], RGBA); - for( i in 0 ... terrainPrefab.terrain.tiles.length ) { - var tile = terrainPrefab.terrain.tiles[i]; - var revert = tileRevertDatas[i]; - revert.prevSurfaceIndexMapPixels = tile.surfaceIndexMap.capturePixels(); - for( w in tile.surfaceWeights ) revert.prevWeightMapPixels.push(w.capturePixels()); - swapIndex.shader.surfaceIndexMap = tile.surfaceIndexMap; - h3d.Engine.getCurrent().pushTarget(newSurfaceIndexMap); - swapIndex.render(); - copyPass.apply(newSurfaceIndexMap, tile.surfaceIndexMap); - tile.surfaceWeights.remove(tile.surfaceWeights[index]); - tile.generateWeightTextureArray(); - } - terrainRevertData.surfaceIndex = index; - terrainRevertData.surface = terrainPrefab.terrain.surfaces[index]; - terrainPrefab.terrain.surfaces.remove(terrainPrefab.terrain.surfaces[index]); - terrainPrefab.terrain.generateSurfaceArray(); - - for( i in 0 ... terrainPrefab.terrain.tiles.length ) { - var tile = terrainPrefab.terrain.tiles[i]; - normalizeWeight.shader.weightTextures = tile.surfaceWeightArray; - normalizeWeight.shader.weightCount = tile.surfaceWeights.length; - normalizeWeight.shader.baseTexIndex = 0; - for( i in 0 ... tile.surfaceWeights.length ) { - normalizeWeight.shader.curTexIndex = i; - h3d.Engine.getCurrent().pushTarget(tile.surfaceWeights[i]); - normalizeWeight.render(); - } - tile.generateWeightTextureArray(); - - generateIndex.shader.weightTextures = tile.surfaceWeightArray; - generateIndex.shader.weightCount = tile.surfaceWeights.length; - h3d.Engine.getCurrent().pushTarget(tile.surfaceIndexMap); - generateIndex.render(); - - var revert = tileRevertDatas[i]; - revert.nextSurfaceIndexMapPixels = tile.surfaceIndexMap.capturePixels(); - for( w in tile.surfaceWeights ) revert.nextWeightMapPixels.push(w.capturePixels()); - } - - onChange(); - - undo.change(Custom(function(undo) { - terrainPrefab.modified = true; - if( undo ) - terrainPrefab.terrain.surfaces.insert(terrainRevertData.surfaceIndex, terrainRevertData.surface); - else - terrainPrefab.terrain.surfaces.remove(terrainRevertData.surface); - terrainPrefab.terrain.generateSurfaceArray(); - - for( revertData in tileRevertDatas ) { - var tile = terrainPrefab.terrain.getTile(revertData.x, revertData.y); - if( tile == null ) continue; - var oldArray = tile.surfaceWeights; - tile.surfaceWeights = new Array(); - tile.surfaceWeights = [for( i in 0...terrainPrefab.terrain.surfaces.length ) null]; - for( i in 0 ... tile.surfaceWeights.length ) { - tile.surfaceWeights[i] = new h3d.mat.Texture(terrainPrefab.terrain.weightMapResolution.x, terrainPrefab.terrain.weightMapResolution.y, [Target], R8); - tile.surfaceWeights[i].wrap = Clamp; - tile.surfaceWeights[i].preventAutoDispose(); - } - for( i in 0 ... oldArray.length ) - if( oldArray[i] != null) oldArray[i].dispose(); - - tile.surfaceIndexMap.uploadPixels(undo ? revertData.prevSurfaceIndexMapPixels : revertData.nextSurfaceIndexMapPixels); - - for( i in 0 ... tile.surfaceWeights.length ) - tile.surfaceWeights[i].uploadPixels(undo ? revertData.prevWeightMapPixels[i] : revertData.nextWeightMapPixels[i]); - - tile.generateWeightTextureArray(); - generateIndex.shader.weightTextures = tile.surfaceWeightArray; - generateIndex.shader.weightCount = tile.surfaceWeights.length; - h3d.Engine.getCurrent().pushTarget(tile.surfaceIndexMap); - generateIndex.render(); - } - onChange(); - })); - - } - - function loadTexture( ctx : hide.prefab.EditContext, propsName : String, ?wrap : h3d.mat.Data.Wrap ) { - var texture = ctx.rootContext.shared.loadTexture(propsName); - texture.wrap = wrap == null ? Repeat : wrap; - return texture; - } - - inline function setRange( name, value, ctx : EditContext ) { - var field = Lambda.find(ctx.properties.fields, f->f.fname==name); - if(field != null) @:privateAccess field.range.value = value; - } - - function refreshSurfaces( props : hide.Element, ctx : EditContext ) { - - if( currentSurface == null ) - props.find('div[name="Params"]').hide(); - else - props.find('div[name="Params"]').show(); - - var surfacesContainer = props.find(".terrain-surfaces"); - surfacesContainer.empty(); - for( i in 0 ... terrainPrefab.terrain.surfaces.length ){ - var surface = terrainPrefab.terrain.surfaces[i]; - if(surface == null || surface.albedo == null) continue; - var texName = surface.albedo.name.split("."); - texName = texName[0].split("/"); - texName = texName[texName.length - 1].split("_Albedo"); - var label = texName[0]; - var img : Element; - if( i == currentBrush.index) img = new Element('
'); - else img = new Element('
'); - var imgPath = ctx.ide.getPath(surface.albedo.name); - img.css("background-image", 'url("file://$imgPath")'); - var surfaceElem = new Element('
$label
').prepend(img); - surfaceElem.contextmenu(function(e) { - e.preventDefault(); - var cmi :Array< hide.comp.ContextMenu.ContextMenuItem> = []; - var delete : hide.comp.ContextMenu.ContextMenuItem = {label : "Delete"}; - delete.click = function(){ - removeSurface(i, function(){refreshSurfaces(props, ctx);}); - }; - cmi.push(delete); - var cm = new hide.comp.ContextMenu(cmi); - }); - surfaceElem.click(function(e){ - editContext.scene.setCurrent(); - currentBrush.index = i; - currentSurface = terrainPrefab.terrain.getSurface(i); - refreshSurfaces(props, ctx); - }); - surfacesContainer.append(surfaceElem); - } - if( currentSurface != null ) { - setRange("editor.currentSurface.tilling", currentSurface.tilling, ctx); - setRange("editor.currentSurface.offset.x", currentSurface.offset.x, ctx); - setRange("editor.currentSurface.offset.y", currentSurface.offset.y, ctx); - setRange("editor.currentSurface.angle", currentSurface.angle, ctx); - setRange("editor.currentSurface.minHeight", currentSurface.minHeight, ctx); - setRange("editor.currentSurface.maxHeight", currentSurface.maxHeight, ctx); - } - } - - function refreshBrushMode (props : hide.Element, ctx : EditContext ) { - var brushIcons = ["icons/addsub.png", "icons/set.png", "icons/smooth.png", "icons/paint.png", "icons/delete.png"]; - var brushMode = [Brush.Mode.AddSub, Brush.Mode.Set, Brush.Mode.Smooth, Brush.Mode.Paint, Brush.Mode.Delete]; - var brushDescription = [ - 'Raiser / Lower Terrain
- Click to raise, hold down shift to lower', - 'Paint height
- Hold down shift to sample target height', - 'Smooth height
- Paint to smooth the terrain', - 'Paint surface
- Hold down shift to subsract', - 'Delete tile
- Paint to delete tiles']; - var brushModeContainer = props.find(".terrain-brushModeContainer"); - brushModeContainer.empty(); - for( i in 0 ... brushIcons.length ) { - var elem = new Element('
'); - var img = new Element('
'); - img.css("background-image", 'url("file://${ctx.ide.getPath("${HIDE}/res/" + brushIcons[i])}")'); - elem.prepend(img); - elem.click(function(_) { - editContext.scene.setCurrent(); - var l = props.find(".terrain-brushModeIcon"); - for( e in l ) { - var elem = new Element(e); - elem.toggleClass("selected", false); - } - img.toggleClass("selected", true); - currentBrush.brushMode.mode = brushMode[i]; - var desc = props.find(".terrain-brushModeDescription"); - desc.empty(); - desc.append(brushDescription[i]); - - }); - brushModeContainer.append(elem); - } - } - - var brushMode = - '
-
-
- Please select a tool -
-
AutoCreate
-
Accumulate
-
'; - - var brushParams = - '
-
-
Size
-
Strength
-
Step
-
Opacity
-
'; - - var surfaceParams = - '
-
Surface
-
-
-
Tilling
-
Offset X
-
Offset Y
-
Rotate
-
Min Height
-
Max Height
-
-
'; - - public function setupUI( props : hide.Element, ctx : EditContext ) { - props.append(brushMode); - props.append(brushParams); - props.append(surfaceParams); - props.find("#addSurface").click(function(_) { - ctx.ide.chooseImage(onSurfaceAdd.bind(props,ctx)); - }); - refreshBrushMode(props, ctx); - - var brushes : Array = ctx.scene.config.get("terrain.brushes"); - var brushesContainer = props.find(".terrain-brushes"); - function refreshBrushes() { - brushesContainer.empty(); - for( brush in brushes ) { - var label = brush.name + "
Step : " + brush.step + "
Strength : " + brush.strength + "
Size : " + brush.size ; - var img : Element; - if( brush.name == currentBrush.name ) img = new Element('
'); - else img = new Element('
'); - img.css("background-image", 'url("file://${ctx.ide.getPath(brush.texture)}")'); - var brushElem = new Element('
$label
').prepend(img); - brushElem.click(function(e){ - editContext.scene.setCurrent(); - currentBrush.size = brush.size; - currentBrush.strength = brush.strength; - currentBrush.step = brush.step; - currentBrush.texPath = ctx.ide.getPath(brush.texture); - currentBrush.tex = loadTexture(ctx, currentBrush.texPath); - currentBrush.name = brush.name; - if( currentBrush.tex != null ) { - if( currentBrush.bitmap != null ) { - currentBrush.bitmap.tile.dispose(); - currentBrush.bitmap.tile = h2d.Tile.fromTexture(currentBrush.tex); - } - else - currentBrush.bitmap = new h2d.Bitmap(h2d.Tile.fromTexture(currentBrush.tex)); - - currentBrush.bitmap.smooth = true; - currentBrush.bitmap.color = new h3d.Vector(currentBrush.strength); - } - refreshBrushes(); - }); - brushesContainer.append(brushElem); - } - if( currentBrush != null ) { - setRange("editor.currentBrush.size", currentBrush.size, ctx); - setRange("editor.currentBrush.strength", currentBrush.strength, ctx); - setRange("editor.currentBrush.step", currentBrush.step, ctx); - } - } - refreshBrushes(); - refreshSurfaces(props, ctx); - } - - function onSurfaceAdd( props : Element, ctx : EditContext, path : String ) { - editContext.scene.setCurrent(); - terrainPrefab.modified = true; - var split : Array = []; - var curTypeIndex = 0; - while( split.length <= 1 && curTypeIndex < textureType.length) { - split = path.split(textureType[curTypeIndex]); - curTypeIndex++; - } - if( split.length <= 1 ) { - ctx.ide.error("Invalid file name format, should be name_Albedo"); - return; - } - var name = split[0]; - var ext = "."+path.split(".").pop(); - var albedo = ctx.rootContext.shared.loadTexture(name + textureType[0] + ext); - var normal = ctx.rootContext.shared.loadTexture(name + textureType[1] + ext); - var pbr = ctx.rootContext.shared.loadTexture(name + textureType[2] + ext); - - if( albedo == null || normal == null || pbr == null ) return; - - function wait() { - if( albedo.flags.has(Loading) || normal.flags.has(Loading)|| pbr.flags.has(Loading)) - haxe.Timer.delay(wait, 1); - else{ - if( terrainPrefab.terrain.getSurfaceFromTex(name + textureType[0] + ext, name + textureType[1] + ext, name + textureType[2] + ext) == null ) { - terrainPrefab.terrain.addSurface(albedo, normal, pbr); - terrainPrefab.terrain.generateSurfaceArray(); - refreshSurfaces(props, ctx); - var terrainRevertData = new TerrainRevertData(); - terrainRevertData.surface = terrainPrefab.terrain.getSurface(terrainPrefab.terrain.surfaces.length - 1); - terrainRevertData.surfaceIndex = terrainPrefab.terrain.surfaces.length - 1; - undo.change(Custom(function(undo) { - if( undo ) { - terrainPrefab.terrain.surfaces.remove(terrainRevertData.surface); - if( currentSurface == terrainRevertData.surface ) currentSurface = null; - currentBrush.index = Std.int(hxd.Math.min(terrainPrefab.terrain.surfaces.length - 1, currentBrush.index)); - } - else - terrainPrefab.terrain.surfaces.push(terrainRevertData.surface); - terrainPrefab.terrain.generateSurfaceArray(); - refreshSurfaces(props, ctx); - })); - } - albedo.dispose(); - normal.dispose(); - pbr.dispose(); - } - } - wait(); - } - -} diff --git a/hide/view/FXEditor.hx b/hide/view/FXEditor.hx deleted file mode 100644 index 2da3ae287..000000000 --- a/hide/view/FXEditor.hx +++ /dev/null @@ -1,1782 +0,0 @@ -package hide.view; -import hrt.prefab.Light; -using Lambda; - -import hide.Element; -import hrt.prefab.Prefab in PrefabElement; -import hrt.prefab.Curve; -import hrt.prefab.fx.Event; -import hide.view.CameraController.CamController; - -typedef PropTrackDef = { - name: String, - ?def: Float -}; - -@:access(hide.view.FXEditor) -class FXEditContext extends hide.prefab.EditContext { - var parent : FXEditor; - public function new(parent, context) { - super(context); - this.parent = parent; - } - override function onChange(p, propName) { - super.onChange(p, propName); - parent.onPrefabChange(p, propName); - } -} - -@:access(hide.view.FXEditor) -private class FXSceneEditor extends hide.comp.SceneEditor { - var parent : hide.view.FXEditor; - public function new(view, data) { - super(view, data); - parent = cast view; - } - - override function onSceneReady() { - super.onSceneReady(); - parent.onSceneReady(); - } - - override function onPrefabChange(p: PrefabElement, ?pname: String) { - super.onPrefabChange(p, pname); - parent.onPrefabChange(p, pname); - } - - override function update(dt) { - super.update(dt); - parent.onUpdate(dt); - } - - override function duplicate(thenMove : Bool) { - if(curEdit == null) return; - var elements = curEdit.rootElements; - if(elements == null || elements.length == 0) - return; - if( isDuplicating ) - return; - isDuplicating = true; - if( gizmo.moving ) { - @:privateAccess gizmo.finishMove(); - } - var undoes = []; - var newElements = []; - for(elt in elements) { - var clone = elt.cloneData(); - var index = elt.parent.children.indexOf(elt) + 1; - clone.parent = elt.parent; - elt.parent.children.remove(clone); - elt.parent.children.insert(index, clone); - autoName(clone); - makeInstance(clone); - newElements.push(clone); - - undoes.push(function(undo) { - if(undo) elt.parent.children.remove(clone); - else elt.parent.children.insert(index, clone); - }); - } - refresh(Full, function() { - selectElements(newElements); - tree.setSelection(newElements); - if(thenMove && curEdit.rootObjects.length > 0) { - gizmo.startMove(MoveXY, true); - gizmo.onFinishMove = function() { - refreshProps(); - } - } - isDuplicating = false; - }); - refreshParents(elements); - - undo.change(Custom(function(undo) { - selectElements([], NoHistory); - - var fullRefresh = false; - if(undo) { - for(elt in newElements) { - if(!removeInstance(elt)) { - fullRefresh = true; - break; - } - } - } - - for(u in undoes) u(undo); - - if(!undo) { - for(elt in newElements) - makeInstance(elt); - } - - refresh(fullRefresh ? Full : Partial); - })); - - } - - override function setElementSelected( p : PrefabElement, ctx : hrt.prefab.Context, b : Bool ) { - if( p.getParent(hrt.prefab.fx.Emitter) != null ) - return false; - return super.setElementSelected(p, ctx, b); - } - - override function selectElements( elts, ?mode ) { - super.selectElements(elts, mode); - parent.onSelect(elts); - } - - override function refresh(?mode, ?callb:Void->Void) { - // Always refresh scene - refreshScene(); - refreshTree(callb); - parent.onRefreshScene(); - } - - override function getNewContextMenu(current: PrefabElement, ?onMake: PrefabElement->Void=null, ?groupByType = true ) { - if(current != null && current.to(hrt.prefab.Shader) != null) { - var ret : Array = []; - ret.push({ - label: "Animation", - menu: parent.getNewTrackMenu(current) - }); - return ret; - } - var allTypes = super.getNewContextMenu(current, onMake, false); - var recents = getNewRecentContextMenu(current, onMake); - - var menu = []; - if (parent.is2D) { - for(name in ["Group 2D", "Bitmap", "Anim2D", "Atlas", "Particle2D", "Text", "Shader", "Shader Graph", "Placeholder"]) { - var item = allTypes.find(i -> i.label == name); - if(item == null) continue; - allTypes.remove(item); - menu.push(item); - } - if(current != null) { - menu.push({ - label: "Animation", - menu: parent.getNewTrackMenu(current) - }); - } - } else { - for(name in ["Group", "Polygon", "Model", "Shader", "Emitter"]) { - var item = allTypes.find(i -> i.label == name); - if(item == null) continue; - allTypes.remove(item); - menu.push(item); - } - if(current != null) { - menu.push({ - label: "Animation", - menu: parent.getNewTrackMenu(current) - }); - } - - menu.push({ - label: "Material", - menu: [ - getNewTypeMenuItem("material", current, onMake, "Default"), - getNewTypeMenuItem("material", current, function (p) { - // TODO: Move material presets to props.json - p.props = { - PBR: { - mode: "BeforeTonemapping", - blend: "Alpha", - shadows: false, - culling: "Back", - colorMask: 0xff - } - } - if(onMake != null) onMake(p); - }, "Unlit") - ] - }); - menu.sort(function(l1,l2) return Reflect.compare(l1.label,l2.label)); - } - - var events = allTypes.filter(i -> StringTools.endsWith(i.label, "Event")); - if(events.length > 0) { - menu.push({ - label: "Events", - menu: events - }); - for(e in events) - allTypes.remove(e); - } - - menu.push({label: null, isSeparator: true}); - menu.push({ - label: "Other", - menu: allTypes - }); - menu.unshift({ - label : "Recents", - menu : recents, - }); - return menu; - } - - override function getAvailableTags(p:PrefabElement) { - return cast ide.currentConfig.get("fx.tags"); - } -} - -class FXEditor extends FileView { - - var sceneEditor : FXSceneEditor; - var data : hrt.prefab.fx.BaseFX; - var is2D : Bool = false; - var tabs : hide.comp.Tabs; - var fxprops : hide.comp.PropsEditor; - - var tools : hide.comp.Toolbar; - var treePanel : hide.comp.ResizablePanel; - var animPanel : hide.comp.ResizablePanel; - var light : h3d.scene.fwd.DirLight; - var lightDirection = new h3d.Vector( 1, 2, -4 ); - - var scene(get, null): hide.comp.Scene; - function get_scene() return sceneEditor.scene; - var properties(get, null): hide.comp.PropsEditor; - function get_properties() return sceneEditor.properties; - - // autoSync - var autoSync : Bool; - var currentVersion : Int = 0; - var lastSyncChange : Float = 0.; - var showGrid = true; - var grid : h3d.scene.Graphics; - var grid2d : h2d.Graphics; - - var lastPan : h2d.col.Point; - - var timelineLeftMargin = 10; - var xScale = 200.; - var xOffset = 0.; - - var pauseButton : hide.comp.Toolbar.ToolToggle; - var currentTime : Float; - var selectMin : Float; - var selectMax : Float; - var previewMin : Float; - var previewMax : Float; - var curveEdits : Array; - var timeLineEl : Element; - var afterPanRefreshes : ArrayVoid> = []; - var statusText : h2d.Text; - - var scriptEditor : hide.comp.ScriptEditor; - var fxScriptParser : hrt.prefab.fx.FXScriptParser; - var cullingPreview : h3d.scene.Sphere; - - override function getDefaultContent() { - return haxe.io.Bytes.ofString(ide.toJSON(new hrt.prefab.fx.FX().saveData())); - } - - override function canSave() { - return data != null; - } - - override function save() { - if( !canSave() ) - return; - var content = ide.toJSON(data.saveData()); - var newSign = haxe.crypto.Md5.encode(content); - if(newSign != currentSign) - haxe.Timer.delay(saveBackup.bind(content), 0); - currentSign = newSign; - sys.io.File.saveContent(getPath(), content); - super.save(); - } - - override function onDisplay() { - if( sceneEditor != null ) sceneEditor.dispose(); - currentTime = 0.; - xOffset = -timelineLeftMargin / xScale; - var content = sys.io.File.getContent(getPath()); - var json = haxe.Json.parse(content); - if (json.type == "fx") - data = new hrt.prefab.fx.FX(); - else { - is2D = true; - data = new hrt.prefab.fx.FX2D(); - } - data.loadData(json); - currentSign = haxe.crypto.Md5.encode(content); - - element.html(' -
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
'); - tools = new hide.comp.Toolbar(null,element.find(".tools-buttons")); - tabs = new hide.comp.Tabs(null,element.find(".tabs")); - sceneEditor = new FXSceneEditor(this, data); - element.find(".hide-scenetree").first().append(sceneEditor.tree.element); - element.find(".hide-scroll").first().append(sceneEditor.properties.element); - element.find(".heaps-scene").first().append(sceneEditor.scene.element); - - var treeColumn = element.find(".tree-column").first(); - treePanel = new hide.comp.ResizablePanel(Horizontal, treeColumn); - treePanel.saveDisplayKey = "treeColumn"; - treePanel.onResize = () -> @:privateAccess if( scene.window != null) scene.window.checkResize(); - - var fxPanel = element.find(".fx-animpanel").first(); - animPanel = new hide.comp.ResizablePanel(Vertical, fxPanel); - animPanel.saveDisplayKey = "animPanel"; - animPanel.onResize = () -> @:privateAccess if( scene.window != null) scene.window.checkResize(); - - refreshLayout(); - element.resize(function(e) { - refreshTimeline(false); - rebuildAnimPanel(); - }); - element.find(".collapse-btn").click(function(e) { - sceneEditor.collapseTree(); - }); - fxprops = new hide.comp.PropsEditor(undo,null,element.find(".fx-props")); - { - var edit = new FXEditContext(this, sceneEditor.context); - edit.properties = fxprops; - edit.scene = sceneEditor.scene; - edit.cleanups = []; - data.edit(edit); - } - - if (is2D) { - sceneEditor.camera2D = true; - } - - var scriptElem = element.find(".fx-script"); - scriptEditor = new hide.comp.ScriptEditor(data.scriptCode, null, scriptElem, scriptElem); - function onSaveScript() { - data.scriptCode = scriptEditor.code; - save(); - skipNextChange = true; - modified = false; - } - scriptEditor.onSave = onSaveScript; - fxScriptParser = new hrt.prefab.fx.FXScriptParser(); - data.scriptCode = scriptEditor.code; - - keys.register("playPause", function() { pauseButton.toggle(!pauseButton.isDown()); }); - - currentVersion = undo.currentID; - sceneEditor.tree.element.addClass("small"); - - var timeline = element.find(".timeline"); - var sMin = 0.0; - var sMax = 0.0; - timeline.contextmenu(function(e) { - var offset = e.clientX - timeline.offset().left; - var marker = data.markers.find(m -> hxd.Math.abs(offset - xt(m.t)) < 4); - new hide.comp.ContextMenu([ - { label : "Add marker", click : function() { - if(data.markers == null) - data.markers = []; - var prevVal = data.markers.copy(); - data.markers.push({t : ixt(e.clientX - timeline.offset().left)}); - undo.change(Field(data, "markers", prevVal), refreshTimeline.bind(false)); - refreshTimeline(false); - } }, - { label : "Remove marker", enabled: marker != null, click : function() { - var prevVal = data.markers.copy(); - data.markers.remove(marker); - undo.change(Field(data, "markers", prevVal), refreshTimeline.bind(false)); - refreshTimeline(false); - } } - ]); - e.preventDefault(); - return false; - }); - timeline.mousedown(function(e) { - var lastX = e.clientX; - var shift = e.shiftKey; - var ctrl = e.ctrlKey; - var xoffset = timeline.offset().left; - var clickTime = ixt(e.clientX - xoffset); - - if(shift) { - sMin = hxd.Math.max(0, clickTime); - } - else if(ctrl) { - previewMin = hxd.Math.max(0, clickTime); - } - - function updateMouse(e: js.jquery.Event) { - var dt = (e.clientX - lastX) / xScale; - if(e.which == 2) { - xOffset -= dt; - xOffset = hxd.Math.max(xOffset, -timelineLeftMargin/xScale); - } - else if(e.which == 1) { - if(shift) { - sMax = ixt(e.clientX - xoffset); - } - else if(ctrl) { - previewMax = ixt(e.clientX - xoffset); - } - else { - if(!pauseButton.isDown()) - pauseButton.toggle(true); - currentTime = ixt(e.clientX - xoffset); - currentTime = hxd.Math.max(currentTime, 0); - } - } - - if(hxd.Math.abs(sMax - sMin) < 1e-5) { - selectMin = 0; - selectMax = 0; - } - else { - selectMax = hxd.Math.max(sMin, sMax); - selectMin = hxd.Math.min(sMin, sMax); - } - } - - if(data.markers != null) { - var marker = data.markers.find(m -> hxd.Math.abs(xt(clickTime) - xt(m.t)) < 4); - if(marker != null) { - var prevVal = marker.t; - startDrag(function(e) { - updateMouse(e); - var x = ixt(e.clientX - xoffset); - x = hxd.Math.max(0, x); - x = untyped parseFloat(x.toFixed(5)); - marker.t = x; - refreshTimeline(true); - }, function(e) { - undo.change(Field(marker, "t", prevVal), refreshTimeline.bind(false)); - }); - e.preventDefault(); - e.stopPropagation(); - return; - } - } - - element.mousemove(function(e: js.jquery.Event) { - updateMouse(e); - lastX = e.clientX; - refreshTimeline(true); - afterPan(true); - }); - element.mouseup(function(e: js.jquery.Event) { - updateMouse(e); - - if(previewMax < previewMin + 0.1) { - previewMin = 0; - previewMax = data.duration == 0 ? 5000 : data.duration; - } - - element.off("mousemove"); - element.off("mouseup"); - e.preventDefault(); - e.stopPropagation(); - refreshTimeline(false); - afterPan(false); - }); - e.preventDefault(); - e.stopPropagation(); - }); - - var wheelTimer : haxe.Timer = null; - timeline.on("mousewheel", function(e) { - var step = e.originalEvent.wheelDelta > 0 ? 1.0 : -1.0; - xScale *= Math.pow(1.125, step); - e.preventDefault(); - e.stopPropagation(); - refreshTimeline(false); - if(wheelTimer != null) - wheelTimer.stop(); - wheelTimer = haxe.Timer.delay(function() { - for(ce in curveEdits) { - ce.xOffset = xOffset; - ce.xScale = xScale; - ce.refresh(); - } - afterPan(false); - }, 50); - }); - - selectMin = 0.0; - selectMax = 0.0; - previewMin = 0.0; - previewMax = data.duration == 0 ? 5000 : data.duration; - refreshTimeline(false); - } - - function refreshLayout() { - if (animPanel != null) animPanel.setSize(); - if (treePanel != null) treePanel.setSize(); - } - - override function onActivate() { - if( sceneEditor != null ) - refreshLayout(); - } - - - public function onSceneReady() { - light = sceneEditor.scene.s3d.find(function(o) return Std.downcast(o, h3d.scene.fwd.DirLight)); - if( light == null ) { - light = new h3d.scene.fwd.DirLight(scene.s3d); - light.enableSpecular = true; - } else - light = null; - - var axis = new h3d.scene.Graphics(scene.s3d); - axis.z = 0.001; - axis.lineStyle(2,0xFF0000); axis.lineTo(1,0,0); - axis.lineStyle(1,0x00FF00); axis.moveTo(0,0,0); axis.lineTo(0,1,0); - axis.lineStyle(1,0x0000FF); axis.moveTo(0,0,0); axis.lineTo(0,0,1); - axis.lineStyle(); - axis.material.mainPass.setPassName("debuggeom"); - axis.visible = (!is2D) ? showGrid : false; - - cullingPreview = new h3d.scene.Sphere(0xffffff, data.cullingRadius, true, scene.s3d); - cullingPreview.visible = (!is2D) ? showGrid : false; - - tools.saveDisplayKey = "FXScene/tools"; - tools.addButton("video-camera", "Perspective camera", () -> sceneEditor.resetCamera()); - - function renderProps() { - properties.clear(); - var renderer = scene.s3d.renderer; - var group = new Element('
'); - renderer.editProps().appendTo(group); - properties.add(group, renderer.props, function(_) { - renderer.refreshProps(); - if( !properties.isTempChange ) renderProps(); - }); - var lprops = { - power : Math.sqrt(light.color.r), - enable: true - }; - var group = new Element('
-
-
Power
-
-
'); - properties.add(group, lprops, function(_) { - var p = lprops.power * lprops.power; - light.color.set(p, p, p); - }); - } - tools.addButton("gears", "Renderer Properties", renderProps); - - tools.addToggle("th", "Show grid", function(v) { - showGrid = v; - axis.visible = (is2D) ? false : v; - cullingPreview.visible = (is2D) ? false : v; - updateGrid(); - }, showGrid); - tools.addColor("Background color", function(v) { - scene.engine.backgroundColor = v; - updateGrid(); - }, scene.engine.backgroundColor); - tools.addToggle("refresh", "Auto synchronize", function(b) { - autoSync = b; - }); - tools.addToggle("compass", "Local transforms", (v) -> sceneEditor.localTransform = v, sceneEditor.localTransform); - pauseButton = tools.addToggle("pause", "Pause animation", function(v) {}, false); - tools.addRange("Speed", function(v) { - scene.speed = v; - }, scene.speed); - - statusText = new h2d.Text(hxd.res.DefaultFont.get(), scene.s2d); - statusText.setPosition(5, 5); - - updateGrid(); - } - - function onPrefabChange(p: PrefabElement, ?pname: String) { - if(p == data) { - previewMax = hxd.Math.min(data.duration == 0 ? 5000 : data.duration, previewMax); - refreshTimeline(false); - - cullingPreview.radius = data.cullingRadius; - } - - if(p.to(Event) != null) { - afterPan(false); - data.refreshObjectAnims(sceneEditor.getContext(data)); - } - } - - function onRefreshScene() { - var renderProps = data.find(e -> e.to(hrt.prefab.RenderProps)); - if(renderProps != null) - renderProps.applyProps(scene.s3d.renderer); - updateGrid(); - } - - override function onDragDrop(items : Array, isDrop : Bool) { - return sceneEditor.onDragDrop(items,isDrop); - } - - function onSelect(elts : Array) { - rebuildAnimPanel(); - } - - inline function xt(x: Float) return Math.round((x - xOffset) * xScale); - inline function ixt(px: Float) return px / xScale + xOffset; - - function refreshTimeline(anim: Bool) { - var scroll = element.find(".timeline-scroll"); - scroll.empty(); - var width = scroll.parent().width(); - var minX = Math.floor(ixt(0)); - var maxX = Math.ceil(hxd.Math.min(data.duration == 0 ? 5000 : data.duration, ixt(width))); - for(ix in minX...(maxX+1)) { - var mark = new Element('').appendTo(scroll); - mark.css({left: xt(ix)}); - mark.text(ix + ".00"); - } - - var overlay = element.find(".overlay"); - overlay.empty(); - timeLineEl = new Element('').appendTo(overlay); - timeLineEl.css({left: xt(currentTime)}); - - if(data.markers != null) { - for(m in data.markers) { - var el = new Element('').appendTo(overlay); - el.css({left: xt(m.t)}); - } - } - - var select = new Element('').appendTo(overlay); - select.css({left: xt(selectMin), width: xt(selectMax) - xt(selectMin)}); - - if(!anim && selectMax != selectMin) { - var selLeft = new Element('').appendTo(overlay); - var selRight = new Element('').appendTo(overlay); - - function updateSelectPos() { - select.css({left: xt(selectMin), width: xt(selectMax) - xt(selectMin)}); - selLeft.css({left: xt(selectMin) - 4}); - selRight.css({left: xt(selectMax)}); - } - updateSelectPos(); - - function refreshViews() { - for(ce in curveEdits) { - ce.refreshGraph(false); - ce.onChange(false); - } - } - - var curves = null; - var allKeys = null; - - function updateSelected() { - curves = []; - var anyNonEmitter = curveEdits.find(ce -> !isInstanceCurve(ce.curve)) != null; - for(ce in curveEdits) { - if(anyNonEmitter && isInstanceCurve(ce.curve)) - continue; // Filter-out emitter curves unless only emitter curves are selected - curves.push(ce.curve); - } - - allKeys = []; - for(curve in curves) { - for(key in curve.keys) { - if(key.time >= selectMin && key.time <= selectMax) - allKeys.push(key); - } - } - } - - var backup = null; - var prevSel = null; - - function beforeChange() { - backup = [for(c in curves) haxe.Json.parse(haxe.Json.stringify(c.save()))]; - prevSel = [selectMin, selectMax]; - } - - function afterChange() { - var newVals = [for(c in curves) haxe.Json.parse(haxe.Json.stringify(c.save()))]; - var newSel = [selectMin, selectMax]; - undo.change(Custom(function(undo) { - if(undo) { - for(i in 0...curves.length) - curves[i].load(backup[i]); - selectMin = prevSel[0]; - selectMax = prevSel[1]; - } - else { - for(i in 0...curves.length) - curves[i].load(newVals[i]); - selectMin = newSel[0]; - selectMax = newSel[1]; - } - updateSelected(); - updateSelectPos(); - refreshViews(); - })); - refreshViews(); - } - - var duplicateMode = false; - var previewKeys = []; - function setupSelectDrag(element: js.jquery.JQuery, update: Float->Float->Void) { - element.mousedown(function(e) { - updateSelected(); - - if(e.button != 0) - return; - var offset = scroll.offset(); - e.preventDefault(); - e.stopPropagation(); - var lastTime = ixt(e.clientX); - beforeChange(); - startDrag(function(e) { - var time = ixt(e.clientX); - update(time, lastTime); - for(ce in curveEdits) { - ce.refreshGraph(true); - ce.onChange(true); - } - updateSelectPos(); - lastTime = time; - }, function(e) { - for (pKey in previewKeys) { - var curve = curves.find((curve) -> return curve.previewKeys.contains(pKey)); - curve.previewKeys.remove(pKey); - } - previewKeys = []; - for(ce in curveEdits) { - ce.refreshGraph(true); - ce.onChange(true); - } - afterChange(); - }, function(e) { - if (e.keyCode == hxd.Key.ALT){ - if (!duplicateMode) { - duplicateMode = !duplicateMode; - for (key in allKeys) { - var curve = curves.find((curve) -> return curve.keys.contains(key)); - var pKey = curve.addPreviewKey(key.time, key.value); - previewKeys.push(pKey); - } - allKeys = []; - for(ce in curveEdits) { - ce.refreshGraph(true); - ce.onChange(true); - } - } - } - }, function(e) { - if (e.keyCode == hxd.Key.ALT){ - if (duplicateMode) { - duplicateMode = !duplicateMode; - for (pKey in previewKeys) { - var curve = curves.find((curve) -> return curve.previewKeys.contains(pKey)); - curve.previewKeys.remove(pKey); - allKeys.push(curve.addKey(pKey.time, pKey.value)); - } - previewKeys = []; - for(ce in curveEdits) { - ce.refreshGraph(true); - ce.onChange(true); - } - } - } - }); - }); - } - - setupSelectDrag(selRight, function(time, lastTime) { - var shift = time - lastTime; - if(selectMax > selectMin + 0.1) { - var scaleFactor = (selectMax + shift - selectMin) / (selectMax - selectMin); - - if (duplicateMode) { - for (key in previewKeys) - key.time = (key.time - selectMin) * scaleFactor + selectMin; - } - else { - for(key in allKeys) - key.time = (key.time - selectMin) * scaleFactor + selectMin; - } - - selectMax += shift; - } - }); - - setupSelectDrag(selLeft, function(time, lastTime) { - var shift = time - lastTime; - if(selectMax > selectMin + 0.1) { - var scaleFactor = (selectMax - (selectMin + shift)) / (selectMax - selectMin); - - if (duplicateMode) { - for(key in previewKeys) - key.time = selectMax - (selectMax - key.time) * scaleFactor; - } - else { - for(key in allKeys) - key.time = selectMax - (selectMax - key.time) * scaleFactor; - } - - selectMin += shift; - } - }); - - setupSelectDrag(select, function(time, lastTime) { - var shift = time - lastTime; - - if (duplicateMode) { - for(key in previewKeys) - key.time += shift; - } - else { - for(key in allKeys) - key.time += shift; - } - selectMin += shift; - selectMax += shift; - - }); - } - - //var preview = new Element('').appendTo(overlay); - // preview.css({left: xt(previewMin), width: xt(previewMax) - xt(previewMin)}); - var prevLeft = new Element('').appendTo(overlay); - prevLeft.css({left: 0, width: xt(previewMin)}); - var prevRight = new Element('').appendTo(overlay); - prevRight.css({left: xt(previewMax), width: xt(data.duration == 0 ? 5000 : data.duration) - xt(previewMax)}); - } - - function afterPan(anim: Bool) { - if(!anim) { - for(curve in curveEdits) { - curve.setPan(xOffset, curve.yOffset); - } - } - for(clb in afterPanRefreshes) { - clb(anim); - } - } - - function addCurvesTrack(trackName: String, curves: Array, tracksEl: Element) { - var keyTimeTolerance = 0.05; - var trackEdits : Array = []; - var trackEl = new Element('
-
-
- -
-
-
-
-
-
'); - if(curves.length == 0) - return; - var parent = curves[0].parent; - var isColorTrack = trackName.toLowerCase().indexOf("color") >= 0 && (curves.length == 3 || curves.length == 4); - var isColorHSL = isColorTrack && curves.find(c -> StringTools.endsWith(c.name, ".h")) != null; - - var trackToggle = trackEl.find(".track-toggle"); - tracksEl.append(trackEl); - var curvesContainer = trackEl.find(".curves"); - var trackKey = "trackVisible:" + parent.getAbsPath(true) + "/" + trackName; - var expand = getDisplayState(trackKey) == true; - function updateExpanded() { - var icon = trackToggle.find(".icon"); - if(expand) - icon.removeClass("ico-angle-right").addClass("ico-angle-down"); - else - icon.removeClass("ico-angle-down").addClass("ico-angle-right"); - curvesContainer.toggleClass("hidden", !expand); - for(c in trackEdits) - c.refresh(); - } - trackEl.find(".track-prop").click(function(e) { - expand = !expand; - saveDisplayState(trackKey, expand); - updateExpanded(); - }); - var dopesheet = trackEl.find(".dopesheet"); - var evaluator = new hrt.prefab.fx.Evaluator(new hxd.Rand(0)); - - function getKeyColor(key) { - return evaluator.getVector(Curve.getColorValue(curves), key.time); - } - - function dragKey(from: hide.comp.CurveEditor, prevTime: Float, newTime: Float) { - for(edit in trackEdits) { - if(edit == from) continue; - var k = edit.curve.findKey(prevTime, keyTimeTolerance); - if(k != null) { - newTime = hxd.Math.clamp(newTime, 0.0, edit.curve.maxTime); - k.time = newTime; - edit.refreshGraph(false, k); - } - } - } - function refreshCurves(anim: Bool) { - for(c in trackEdits) { - c.refreshGraph(anim); - } - } - - function refreshKey(key: hide.comp.CurveEditor.CurveKey, el: Element) { - if(isColorTrack) { - var color = getKeyColor(key); - var colorStr = "#" + StringTools.hex(color.toColor() & 0xffffff, 6); - el.css({background: colorStr}); - } - } - - var refreshDopesheet : Void -> Void; - - function backupCurves() { - return [for(c in curves) haxe.Json.parse(haxe.Json.stringify(c.save()))]; - } - var lastBackup = backupCurves(); - - function beforeChange() { - lastBackup = backupCurves(); - } - - function afterChange() { - var newVal = backupCurves(); - var oldVal = lastBackup; - lastBackup = newVal; - undo.change(Custom(function(undo) { - if(undo) { - for(i in 0...curves.length) - curves[i].load(oldVal[i]); - } - else { - for(i in 0...curves.length) - curves[i].load(newVal[i]); - } - lastBackup = backupCurves(); - refreshCurves(false); - refreshDopesheet(); - })); - refreshCurves(false); - } - - function addKey(time: Float) { - beforeChange(); - for(curve in curves) { - curve.addKey(time); - } - afterChange(); - refreshDopesheet(); - } - - - function keyContextClick(key: hrt.prefab.Curve.CurveKey, el: Element) { - function setCurveVal(suffix: String, value: Float) { - var c = curves.find(c -> StringTools.endsWith(c.name, suffix)); - if(c != null) { - var k = c.findKey(key.time, keyTimeTolerance); - if(k == null) { - k = c.addKey(key.time); - } - k.value = value; - } - } - - if(isColorTrack) { - var picker = new Element("
").css({ - "z-index": 100, - }).appendTo(el); - var cp = new hide.comp.ColorPicker(false, picker); - var prevCol = getKeyColor(key); - cp.value = prevCol.toColor(); - cp.open(); - cp.onClose = function() { - picker.remove(); - }; - cp.onChange = function(dragging) { - if(dragging) - return; - var col = h3d.Vector.fromColor(cp.value, 1.0); - if(isColorHSL) { - col = col.toColorHSL(); - setCurveVal(".h", col.x); - setCurveVal(".s", col.y); - setCurveVal(".l", col.z); - setCurveVal(".a", prevCol.a); - } - else { - setCurveVal(".r", col.x); - setCurveVal(".g", col.y); - setCurveVal(".b", col.z); - setCurveVal(".a", prevCol.a); - } - refreshCurves(false); - refreshKey(key, el); - }; - } - } - - refreshDopesheet = function () { - dopesheet.empty(); - dopesheet.off(); - dopesheet.mouseup(function(e) { - var offset = dopesheet.offset(); - if(e.ctrlKey) { - var x = ixt(e.clientX - offset.left); - addKey(x); - } - }); - var refKeys = curves[0].keys; - for(ik in 0...refKeys.length) { - var key = refKeys[ik]; - var keyEl = new Element('').appendTo(dopesheet); - function updatePos() keyEl.css({left: xt(refKeys[ik].time)}); - updatePos(); - keyEl.contextmenu(function(e) { - keyContextClick(key, keyEl); - e.preventDefault(); - e.stopPropagation(); - }); - keyEl.mousedown(function(e) { - var offset = dopesheet.offset(); - e.preventDefault(); - e.stopPropagation(); - if(e.button == 2) { - } - else { - var prevVal = key.time; - beforeChange(); - startDrag(function(e) { - var x = ixt(e.clientX - offset.left); - x = hxd.Math.max(0, x); - var next = refKeys[ik + 1]; - if(next != null) - x = hxd.Math.min(x, next.time - 0.01); - var prev = refKeys[ik - 1]; - if(prev != null) - x = hxd.Math.max(x, prev.time + 0.01); - dragKey(null, key.time, x); - updatePos(); - }, function(e) { - afterChange(); - }); - } - }); - afterPanRefreshes.push(function(anim) { - updatePos(); - }); - refreshKey(key, keyEl); - } - } - - var minHeight = 40; - var ctx = sceneEditor.getContext(data); - for(curve in curves) { - var dispKey = getPath() + "/" + curve.getAbsPath(true); - var curveContainer = new Element('
').appendTo(curvesContainer); - var height = getDisplayState(dispKey + "/height"); - if(height == null) - height = 100; - if(height < minHeight) height = minHeight; - curveContainer.height(height); - curve.maxTime = data.duration; - var curveEdit = new hide.comp.CurveEditor(this.undo, curveContainer); - curveEdit.saveDisplayKey = dispKey; - curveEdit.lockViewX = true; - if(curves.length > 1) - curveEdit.lockKeyX = true; - if(["visibility", "s", "l", "a"].indexOf(curve.name.split(".").pop()) >= 0) { - curveEdit.minValue = 0; - curveEdit.maxValue = 1; - } - if(curve.name.indexOf("Rotation") >= 0) { - curveEdit.minValue = 0; - curveEdit.maxValue = 360; - } - var shader = curve.parent.to(hrt.prefab.Shader); - if(shader != null) { - var sh = shader.getShaderDefinition(ctx); - if(sh != null) { - var v = sh.data.vars.find(v -> v.kind == Param && v.name == curve.name); - if(v != null && v.qualifiers != null) { - for( q in v.qualifiers ) - switch( q ) { - case Range(rmin, rmax): - curveEdit.minValue = rmin; - curveEdit.maxValue = rmax; - default: - } - } - } - } - curveEdit.xOffset = xOffset; - curveEdit.xScale = xScale; - if(isInstanceCurve(curve) && curve.parent.to(hrt.prefab.fx.Emitter) == null || curve.name.indexOf("inst") >= 0) - curve.maxTime = 1.0; - curveEdit.curve = curve; - curveEdit.onChange = function(anim) { - refreshDopesheet(); - } - - curveContainer.on("mousewheel", function(e) { - var step = e.originalEvent.wheelDelta > 0 ? 1.0 : -1.0; - if(e.ctrlKey) { - var prevH = curveContainer.height(); - var newH = hxd.Math.max(minHeight, prevH + Std.int(step * 20.0)); - curveContainer.height(newH); - saveDisplayState(dispKey + "/height", newH); - curveEdit.yScale *= newH / prevH; - curveEdit.refresh(); - e.preventDefault(); - e.stopPropagation(); - } - }); - trackEdits.push(curveEdit); - curveEdits.push(curveEdit); - } - refreshDopesheet(); - updateExpanded(); - } - - function addEventsTrack(events: Array, tracksEl: Element) { - var trackEl = new Element('
-
-
- -
-
-
-
'); - var eventsEl = trackEl.find(".events"); - var items : Array<{el: Element, event: Event }> = []; - function refreshItems() { - var yoff = 1; - for(item in items) { - var info = item.event.getDisplayInfo(sceneEditor.curEdit); - item.el.css({left: xt(item.event.time), top: yoff}); - item.el.width(info.length * xScale); - item.el.find("label").text(info.label); - yoff += 21; - } - eventsEl.css("height", yoff + 1); - } - - function refreshTrack() { - trackEl.remove(); - trackEl = addEventsTrack(events, tracksEl); - } - - for(event in events) { - var info = event.getDisplayInfo(sceneEditor.curEdit); - var evtEl = new Element('
- -
').appendTo(eventsEl); - items.push({el: evtEl, event: event }); - - evtEl.click(function(e) { - sceneEditor.showProps(event); - }); - - evtEl.contextmenu(function(e) { - e.preventDefault(); - e.stopPropagation(); - new hide.comp.ContextMenu([ - { - label: "Delete", click: function() { - events.remove(event); - sceneEditor.deleteElements([event], refreshTrack); - } - } - ]); - }); - - evtEl.mousedown(function(e) { - var offsetX = e.clientX - xt(event.time); - e.preventDefault(); - e.stopPropagation(); - if(e.button == 2) { - } - else { - var prevVal = event.time; - startDrag(function(e) { - var x = ixt(e.clientX - offsetX); - x = hxd.Math.max(0, x); - x = untyped parseFloat(x.toFixed(5)); - event.time = x; - refreshItems(); - }, function(e) { - undo.change(Field(event, "time", prevVal), refreshItems); - }); - } - }); - } - refreshItems(); - afterPanRefreshes.push(function(anim) refreshItems()); - tracksEl.append(trackEl); - return trackEl; - } - - function rebuildAnimPanel() { - if(element == null) - return; - var selection = sceneEditor.getSelection(); - var scrollPanel = element.find(".anim-scroll"); - scrollPanel.empty(); - curveEdits = []; - afterPanRefreshes = []; - - var sections : Array<{ - elt: PrefabElement, - curves: Array, - events: Array - }> = []; - - function getSection(elt: PrefabElement) { - var ctxElt = elt.parent; - var sect = sections.find(s -> s.elt == ctxElt); - if(sect == null) { - sect = {elt: ctxElt, curves: [], events: []}; - sections.push(sect); - } - return sect; - } - - function getTagRec(elt : PrefabElement) { - var p = elt; - while(p != null) { - var tag = sceneEditor.getTag(p); - if(tag != null) - return tag; - p = p.parent; - } - return null; - } - - for(sel in selection) { - for(curve in sel.flatten(Curve)) - getSection(curve).curves.push(curve); - for(evt in sel.flatten(Event)) - getSection(evt).events.push(evt); - } - - for(sec in sections) { - var objPanel = new Element('
-
-
- -
-
-
').appendTo(scrollPanel); - var addTrackEl = objPanel.find(".addtrack"); - - var parentTag = getTagRec(sec.elt); - if(parentTag != null) { - objPanel.find(".name").css("background", parentTag.color); - } - - addTrackEl.click(function(e) { - var menuItems = getNewTrackMenu(sec.elt); - new hide.comp.ContextMenu(menuItems); - }); - var tracksEl = objPanel.find(".tracks"); - - if(sec.events.length > 0) - addEventsTrack(sec.events, tracksEl); - - var groups = Curve.getGroups(sec.curves); - for(group in groups) { - addCurvesTrack(group.name, group.items, tracksEl); - } - } - } - - function startDrag(onMove: js.jquery.Event->Void, onStop: js.jquery.Event->Void, ?onKeyDown: js.jquery.Event->Void, ?onKeyUp: js.jquery.Event->Void) { - var el = new Element(element[0].ownerDocument.body); - var startX = null, startY = null; - var dragging = false; - var threshold = 3; - el.keydown(onKeyDown); - el.keyup(onKeyUp); - el.on("mousemove.fxedit", function(e: js.jquery.Event) { - if(startX == null) { - startX = e.clientX; - startY = e.clientY; - } - else { - if(!dragging) { - if(hxd.Math.abs(e.clientX - startX) + hxd.Math.abs(e.clientY - startY) > threshold) { - dragging = true; - } - } - if(dragging) - onMove(e); - } - }); - el.on("mouseup.fxedit", function(e: js.jquery.Event) { - el.off("mousemove.fxedit"); - el.off("mouseup.fxedit"); - e.preventDefault(); - e.stopPropagation(); - onStop(e); - }); - } - - function addTracks(element : PrefabElement, props : Array, ?prefix: String) { - var added = []; - for(prop in props) { - var id = prefix != null ? prefix + "." + prop.name : prop.name; - if(Curve.getCurve(element, id) != null) - continue; - var curve = new Curve(element); - curve.name = id; - if(prop.def != null) - curve.addKey(0, prop.def, Linear); - added.push(curve); - } - - if(added.length == 0) - return added; - - undo.change(Custom(function(undo) { - for(c in added) { - if(undo) - element.children.remove(c); - else - element.children.push(c); - } - sceneEditor.refresh(); - })); - sceneEditor.refresh(function() { - sceneEditor.selectElements([element]); - }); - return added; - } - - public function getNewTrackMenu(elt: PrefabElement) : Array { - var obj3dElt = Std.downcast(elt, hrt.prefab.Object3D); - var obj2dElt = Std.downcast(elt, hrt.prefab.Object2D); - var shaderElt = Std.downcast(elt, hrt.prefab.Shader); - var emitterElt = Std.downcast(elt, hrt.prefab.fx.Emitter); - var particle2dElt = Std.downcast(elt, hrt.prefab.l2d.Particle2D); - var menuItems : Array = []; - var lightElt = Std.downcast(elt, Light); - - inline function hasTrack(pname) { - return getTrack(elt, pname) != null; - } - - function trackItem(name: String, props: Array, ?prefix: String) : hide.comp.ContextMenu.ContextMenuItem { - var hasAllTracks = true; - for(p in props) { - if(getTrack(elt, prefix + "." + p.name) == null) - hasAllTracks = false; - } - return { - label: upperCase(name), - click: function() { - var added = addTracks(elt, props, prefix); - }, - enabled: !hasAllTracks }; - } - - function groupedTracks(prefix: String, props: Array) : Array { - var allLabel = [for(p in props) upperCase(p.name)].join("/"); - var ret = []; - ret.push(trackItem(allLabel, props, prefix)); - for(p in props) { - var label = upperCase(p.name); - ret.push(trackItem(label, [p], prefix)); - } - return ret; - } - - var hslTracks : Void -> Array = () -> [{name: "h", def: 0.0}, {name: "s", def: 0.0}, {name: "l", def: 1.0}]; - var alphaTrack : Void -> Array = () -> [{name: "a", def: 1.0}]; - var xyzwTracks : Int -> Array = (n) -> [{name: "x"}, {name: "y"}, {name: "z"}, {name: "w"}].slice(0, n); - - if (obj2dElt != null) { - var scaleTracks = groupedTracks("scale", xyzwTracks(2)); - scaleTracks.unshift(trackItem("Uniform", [{name: "scale"}])); - menuItems.push({ - label: "Position", - menu: groupedTracks("position", xyzwTracks(2)), - }); - menuItems.push({ - label: "Rotation", - menu: [trackItem("X", [{name: "x"}], "rotation")], - }); - menuItems.push({ - label: "Scale", - menu: scaleTracks, - }); - menuItems.push({ - label: "Color", - menu: [ - trackItem("HSL", hslTracks(), "color"), - trackItem("Alpha", alphaTrack(), "color") - ] - }); - menuItems.push(trackItem("Visibility", [{name: "visibility"}])); - } - if(obj3dElt != null) { - var scaleTracks = groupedTracks("scale", xyzwTracks(3)); - scaleTracks.unshift(trackItem("Uniform", [{name: "scale"}])); - menuItems.push({ - label: "Position", - menu: groupedTracks("position", xyzwTracks(3)), - }); - menuItems.push({ - label: "Rotation", - menu: groupedTracks("rotation", xyzwTracks(3)), - }); - menuItems.push({ - label: "Scale", - menu: scaleTracks, - }); - menuItems.push({ - label: "Color", - menu: [ - trackItem("HSL", hslTracks(), "color"), - trackItem("Alpha", alphaTrack(), "color") - ] - }); - menuItems.push(trackItem("Visibility", [{name: "visibility"}])); - } - if(shaderElt != null) { - var shader = shaderElt.makeShader(); - var inEmitter = shaderElt.getParent(hrt.prefab.fx.Emitter) != null; - var params = shader == null ? [] : @:privateAccess shader.shader.data.vars.filter(inEmitter ? isPerInstance : v -> v.kind == Param); - for(param in params) { - var item : hide.comp.ContextMenu.ContextMenuItem = switch(param.type) { - case TVec(n, VFloat): - var color = param.name.toLowerCase().indexOf("color") >= 0; - var label = upperCase(param.name); - var menu = null; - if(color) { - if(n == 3) - menu = trackItem(label, hslTracks(), param.name); - else if(n == 4) - menu = trackItem(label, hslTracks().concat(alphaTrack()), param.name); - } - if(menu == null) - menu = trackItem(label, xyzwTracks(n), param.name); - menu; - case TFloat: - trackItem(upperCase(param.name), [{name: param.name}]); - default: - null; - } - if(item != null) - menuItems.push(item); - } - } - function addParam(param : hrt.prefab.fx.Emitter.ParamDef, prefix: String) { - var label = prefix + (param.disp != null ? param.disp : upperCase(param.name)); - var item : hide.comp.ContextMenu.ContextMenuItem = switch(param.t) { - case PVec(n, _): - { - label: label, - menu: groupedTracks(param.name, xyzwTracks(n)), - } - default: - trackItem(label, [{name: param.name}]); - }; - menuItems.push(item); - } - if(emitterElt != null) { - for(param in hrt.prefab.fx.Emitter.emitterParams) { - if(!param.animate) - continue; - addParam(param, ""); - } - for(param in hrt.prefab.fx.Emitter.instanceParams) { - if(!param.animate) - continue; - addParam(param, "Instance "); - } - } - if (particle2dElt != null) { - for(param in hrt.prefab.l2d.Particle2D.emitter2dParams) { - if(!param.animate) - continue; - addParam(param, ""); - } - } - if( lightElt != null ) { - switch lightElt.kind { - case Point: - menuItems.push({ - label: "PointLight", - menu: [ trackItem("Color", hslTracks(), "color"), - trackItem("Power",[{name: "power"}]), - trackItem("Size", [{name: "size"}]), - trackItem("Range", [{name: "range"}]), - ] - }); - case Directional: - menuItems.push({ - label: "DirLight", - menu: [ trackItem("Color", hslTracks(), "color"), - trackItem("Power",[{name: "power"}]), - ] - }); - case Spot: - menuItems.push({ - label: "SpotLight", - menu: [ trackItem("Color", hslTracks(), "color"), - trackItem("Power",[{name: "power"}]), - trackItem("Range", [{name: "range"}]), - trackItem("Angle", [{name: "angle"}]), - trackItem("FallOff", [{name: "fallOff"}]), - ] - }); - } - } - return menuItems; - } - - function isPerInstance( v : hxsl.Ast.TVar ) { - if( v.kind != Param ) - return false; - if( v.qualifiers == null ) - return false; - for( q in v.qualifiers ) - if( q.match(PerInstance(_)) ) - return true; - return false; - } - - function updateGrid() { - if(grid != null) { - grid.remove(); - grid = null; - } - if(grid2d != null) { - grid2d.remove(); - grid2d = null; - } - - if(!showGrid) - return; - - if (is2D) { - grid2d = new h2d.Graphics(scene.editor.context.local2d); - grid2d.scale(1); - - grid2d.lineStyle(1.0, 12632256, 1.0); - grid2d.moveTo(0, -2000); - grid2d.lineTo(0, 2000); - grid2d.moveTo(-2000, 0); - grid2d.lineTo(2000, 0); - grid2d.lineStyle(0); - - return; - } - - grid = new h3d.scene.Graphics(scene.s3d); - grid.scale(1); - grid.material.mainPass.setPassName("debuggeom"); - - var col = h3d.Vector.fromColor(scene.engine.backgroundColor); - var hsl = col.toColorHSL(); - if(hsl.z > 0.5) hsl.z -= 0.1; - else hsl.z += 0.1; - col.makeColor(hsl.x, hsl.y, hsl.z); - - grid.lineStyle(1.0, col.toColor(), 1.0); - for(ix in -10...11) { - grid.moveTo(ix, -10, 0); - grid.lineTo(ix, 10, 0); - grid.moveTo(-10, ix, 0); - grid.lineTo(10, ix, 0); - - } - grid.lineStyle(0); - } - - function onUpdate(dt : Float) { - if (is2D) - onUpdate2D(dt); - else - onUpdate3D(dt); - - @:privateAccess scene.s3d.renderer.ctx.time = currentTime - scene.s3d.renderer.ctx.elapsedTime; - } - - function onUpdate2D(dt:Float) { - var anim : hrt.prefab.fx.FX2D.FX2DAnimation = null; - var ctx = sceneEditor.getContext(data); - if(ctx != null && ctx.local2d != null) { - anim = Std.downcast(ctx.local2d, hrt.prefab.fx.FX2D.FX2DAnimation); - } - if(!pauseButton.isDown()) { - currentTime += scene.speed * dt; - if(timeLineEl != null) - timeLineEl.css({left: xt(currentTime)}); - if(currentTime >= previewMax) { - currentTime = previewMin; - - anim.setRandSeed(Std.random(0xFFFFFF)); - } - } - - if(anim != null) { - anim.setTime(currentTime); - } - - if(statusText != null) { - var lines : Array = [ - 'Time: ${Math.round(currentTime*1000)} ms', - 'Scene objects: ${scene.s2d.getObjectsCount()}', - 'Drawcalls: ${h3d.Engine.getCurrent().drawCalls}', - ]; - statusText.text = lines.join("\n"); - } - - if( autoSync && (currentVersion != undo.currentID || lastSyncChange != properties.lastChange) ) { - save(); - lastSyncChange = properties.lastChange; - currentVersion = undo.currentID; - } - - if (grid2d != null) { - @:privateAccess grid2d.setPosition(scene.s2d.children[0].x, scene.s2d.children[0].y); - } - - - } - - function onUpdate3D(dt:Float) { - var anim : hrt.prefab.fx.FX.FXAnimation = null; - var ctx = sceneEditor.getContext(data); - if(ctx != null && ctx.local3d != null) { - anim = Std.downcast(ctx.local3d,hrt.prefab.fx.FX.FXAnimation); - } - - if(!pauseButton.isDown()) { - currentTime += scene.speed * dt; - if(timeLineEl != null) - timeLineEl.css({left: xt(currentTime)}); - if(currentTime >= previewMax) { - currentTime = previewMin; - - //if(data.scriptCode != null && data.scriptCode.length > 0) - //sceneEditor.refreshScene(); // This allow to reset the scene when values are modified causes edition issues, solves - - if( anim.script != null ) - anim.script.init(); - - anim.setRandSeed(Std.random(0xFFFFFF)); - } - } - - if(anim != null) { - anim.setTime(currentTime); - - var emitters = anim.findAll(o -> Std.downcast(o, hrt.prefab.fx.Emitter.EmitterObject)); - var totalParts = 0; - for(e in emitters) - totalParts += @:privateAccess e.numInstances; - - if(statusText != null) { - var lines : Array = [ - 'Time: ${Math.round(currentTime*1000)} ms', - 'Scene objects: ${scene.s3d.getObjectsCount()}', - 'Drawcalls: ${h3d.Engine.getCurrent().drawCalls}', - 'Particles: $totalParts', - ]; - statusText.text = lines.join("\n"); - } - } - - var cam = scene.s3d.camera; - if( light != null ) { - var angle = Math.atan2(cam.target.y - cam.pos.y, cam.target.x - cam.pos.x); - light.setDirection(new h3d.Vector( - Math.cos(angle) * lightDirection.x - Math.sin(angle) * lightDirection.y, - Math.sin(angle) * lightDirection.x + Math.cos(angle) * lightDirection.y, - lightDirection.z - )); - } - if( autoSync && (currentVersion != undo.currentID || lastSyncChange != properties.lastChange) ) { - save(); - lastSyncChange = properties.lastChange; - currentVersion = undo.currentID; - } - - if( data.scriptCode != scriptEditor.code || !fxScriptParser.firstParse ){ - modified = fxScriptParser.firstParse; - data.scriptCode = scriptEditor.code; - anim.script = fxScriptParser.createFXScript(scriptEditor.code, anim); - anim.script.init(); - fxScriptParser.generateUI(anim.script, this); - fxScriptParser.firstParse = true; - } - } - - static function getTrack(element : PrefabElement, propName : String) { - return Curve.getCurve(element, propName, false); - } - - static function upperCase(prop: String) { - if(prop == null) return ""; - return prop.charAt(0).toUpperCase() + prop.substr(1); - } - - static function isInstanceCurve(curve: Curve) { - return curve.getParent(hrt.prefab.fx.Emitter) != null; - } - - static var _ = FileTree.registerExtension(FXEditor, ["fx"], { icon : "sitemap", createNew : "FX" }); -} - - -class FX2DEditor extends FXEditor { - - override function getDefaultContent() { - return haxe.io.Bytes.ofString(ide.toJSON(new hrt.prefab.fx.FX2D().saveData())); - } - - static var _2d = FileTree.registerExtension(FX2DEditor, ["fx2d"], { icon : "sitemap", createNew : "FX 2D" }); -} \ No newline at end of file diff --git a/hide/view/Prefab.hx b/hide/view/Prefab.hx index 8ae0bcf0a..54183178d 100644 --- a/hide/view/Prefab.hx +++ b/hide/view/Prefab.hx @@ -7,7 +7,6 @@ import hxd.Key as K; import hrt.prefab.Prefab as PrefabElement; import hrt.prefab.Object3D; -import hrt.prefab.l3d.Instance; import hide.comp.cdb.DataFiles; @@ -60,18 +59,19 @@ private class PrefabSceneEditor extends hide.comp.SceneEditor { haxe.Timer.delay(addElements.bind([p]), 0); } + #if !prefab_refacto function addNewInstances() { var items = new Array(); for(type in DataFiles.getAvailableTypes() ) { var typeId = DataFiles.getTypeName(type); var label = typeId.charAt(0).toUpperCase() + typeId.substr(1); - var refCols = Instance.findRefColumns(type); + var refCols = hrt.prefab.l3d.Instance.findRefColumns(type); var refSheet = refCols == null ? null : type.base.getSheet(refCols.sheet); - var idCol = refCols == null ? null : Instance.findIDColumn(refSheet); + var idCol = refCols == null ? null : hrt.prefab.l3d.Instance.findIDColumn(refSheet); function make(name) { - var p = new Instance(current == null ? sceneData : current); + var p = new hrt.prefab.l3d.Instance(current == null ? sceneData : current); p.name = name; p.props = makeCdbProps(p, type); setup(p); @@ -122,6 +122,8 @@ private class PrefabSceneEditor extends hide.comp.SceneEditor { }); }; addNewInstances(); + #end + newItems.unshift({ label : "Recents", menu : recents, @@ -536,10 +538,12 @@ class Prefab extends FileView { { case "shadows": r.shadows = enable; + #if !prefab_refacto case "ssr": var effect = r.getEffect(hrt.prefab.rfx.SSR); if (effect != null) effect.enabled = enable; + #end default: } } @@ -631,6 +635,7 @@ class Prefab extends FileView { } } var color = getDisplayColor(p); + #if !prefab_refacto if(color != null){ color = (color & 0xffffff) | 0xa0000000; var box = p.to(hrt.prefab.l3d.Box); @@ -644,6 +649,7 @@ class Prefab extends FileView { poly.setColor(ctx, color); } } + #end } function getDisplayColor(p: PrefabElement) : Null { diff --git a/hide/view/l3d/LightProbeBaker.hx b/hide/view/l3d/LightProbeBaker.hx deleted file mode 100644 index 7a0e666c2..000000000 --- a/hide/view/l3d/LightProbeBaker.hx +++ /dev/null @@ -1,445 +0,0 @@ -package hide.view.l3d; - -import h3d.scene.pbr.Renderer; - -class LightProbeBaker { - - public var useGPU = false; - public var environment : h3d.scene.pbr.Environment; - - var context : hrt.prefab.Context; - var offScreenScene : h3d.scene.Scene = null; - var prim : h3d.prim.Plane2D; - - var envMap : h3d.mat.Texture; - var customCamera : h3d.Camera; - var cubeDir = [ h3d.Matrix.L([0,0,-1,0, 0,1,0,0, -1,-1,1,0]), - h3d.Matrix.L([0,0,1,0, 0,1,0,0, 1,-1,-1,0]), - h3d.Matrix.L([-1,0,0,0, 0,0,1,0, 1,-1,-1,0]), - h3d.Matrix.L([-1,0,0,0, 0,0,-1,0, 1,1,1,0]), - h3d.Matrix.L([-1,0,0,0, 0,1,0,0, 1,-1,1,0]), - h3d.Matrix.L([1,0,0,0, 0,1,0,0, -1,-1,-1,0]) ]; - - function getSwiz(name,comp) : hxsl.Output { return Swiz(Value(name,3),[comp]); } - - var computeSH : h3d.pass.ScreenFx; - var output0 : h3d.mat.Texture; - var output1 : h3d.mat.Texture; - var output2 : h3d.mat.Texture; - var output3 : h3d.mat.Texture; - var output4 : h3d.mat.Texture; - var output5 : h3d.mat.Texture; - var output6 : h3d.mat.Texture; - var output7 : h3d.mat.Texture; - var textureArray: Array; - - public function new(){ - customCamera = new h3d.Camera(); - customCamera.screenRatio = 1.0; - customCamera.fovY = 90; - customCamera.zFar = 100; - context = new hrt.prefab.Context(); - } - - public function dispose() { - if( envMap != null ) { - envMap.dispose(); - envMap = null; - } - if(output0 != null) output0.dispose(); - if(output1 != null) output1.dispose(); - if(output2 != null) output2.dispose(); - if(output3 != null) output3.dispose(); - if(output4 != null) output4.dispose(); - if(output5 != null) output5.dispose(); - if(output6 != null) output6.dispose(); - if(output7 != null) output7.dispose(); - if(prim != null) prim.dispose(); - if(offScreenScene != null) offScreenScene.dispose(); - } - - public function initScene( sceneData : hrt.prefab.Prefab, shared : hide.prefab.ContextShared, scene : hide.comp.Scene , env : h3d.scene.pbr.Environment) { - if(offScreenScene != null) offScreenScene.dispose(); - offScreenScene = new h3d.scene.Scene(); - - var newShared = new hide.prefab.ContextShared(scene); - newShared.currentPath = shared.currentPath; - @:privateAccess newShared.shaderCache = @:privateAccess hide.Ide.inst.shaderLoader.shaderCache; - context.shared = newShared; - context.shared.root3d = offScreenScene; - context.local3d = offScreenScene; - - var whiteList = [ "level3d", "object", "model", "material", "light"]; - function keep( p : hrt.prefab.Prefab ) { - for( f in whiteList ) - if( f == p.type ) return true; - return false; - } - function filter( p : hrt.prefab.Prefab ) { - for( c in p.children ) { - if(!keep(c)) - sceneData.children.remove(c); - } - for( c in p.children ) - filter(c); - } - filter(sceneData); - sceneData.make(context); - - /*function disableFaceCulling( o : Object ){ - for( m in o.getMaterials() ) - m.mainPass.culling = None; - for( i in 0 ... o.numChildren) - disableFaceCulling(o.getChildAt(i)); - } - disableFaceCulling(offScreenScene);*/ - - var pbrRenderer = Std.downcast(offScreenScene.renderer, h3d.scene.pbr.Renderer) ; - pbrRenderer.env = env; - pbrRenderer.renderMode = LightProbe; - offScreenScene.camera = customCamera; - - setupScene(); - } - - var passes = []; - function setupScene() { - var engine = h3d.Engine.getCurrent(); - var ctx = @:privateAccess offScreenScene.ctx; - - if( customCamera.rightHanded ) - engine.driver.setRenderFlag(CameraHandness,1); - - ctx.camera = customCamera; - ctx.engine = engine; - ctx.scene = offScreenScene; - ctx.start(); - offScreenScene.renderer.start(); - ctx.lightSystem = @:privateAccess offScreenScene.lightSystem; - - @:privateAccess offScreenScene.syncRec(ctx); - @:privateAccess offScreenScene.emitRec(ctx); - - // sort by pass id - @:privateAccess ctx.passes = haxe.ds.ListSort.sortSingleLinked(@:privateAccess ctx.passes, function(p1, p2) { - return @:privateAccess p1.pass.passId - @:privateAccess p2.pass.passId; - }); - - // group by pass implementation - var curPass = @:privateAccess ctx.passes; - passes = []; - while( curPass != null ) { - var passId = @:privateAccess curPass.pass.passId; - var p = curPass, prev = null; - while( p != null && @:privateAccess p.pass.passId == passId ) { - prev = p; - p = p.next; - } - prev.next = null; - var po = new h3d.scene.Renderer.PassObjects(); - po.name = curPass.pass.name; - po.passes = new h3d.pass.PassList(curPass); - passes.push(po); - curPass = p; - } - } - - function renderScene(){ - offScreenScene.lightSystem.initLights( @:privateAccess offScreenScene.ctx); - offScreenScene.renderer.process(passes); - } - - var pixels : hxd.Pixels = null; - public function bake( volumetricLightMap : hrt.prefab.vlm.VolumetricMesh, resolution : Int, ?time :Float ) { - - var timer = haxe.Timer.stamp(); - var timeElapsed = 0.0; - - var index = volumetricLightMap.lastBakedProbeIndex + 1; - if(index > volumetricLightMap.getProbeCount() - 1) return time; - - setupEnvMap(resolution); - setupShaderOutput(volumetricLightMap.shOrder, volumetricLightMap.getProbeCount() ); - - var coefCount = volumetricLightMap.getCoefCount(); - var sizeX = volumetricLightMap.probeCount.x * coefCount; - var sizeY = volumetricLightMap.probeCount.y * volumetricLightMap.probeCount.z; - if( volumetricLightMap.lightProbeTexture == null || volumetricLightMap.lightProbeTexture.width != sizeX || volumetricLightMap.lightProbeTexture.height != sizeY ) { - if( volumetricLightMap.lightProbeTexture != null ) volumetricLightMap.lightProbeTexture.dispose(); - volumetricLightMap.lightProbeTexture = new h3d.mat.Texture(sizeX, sizeY, [Dynamic], RGBA32F); - volumetricLightMap.lightProbeTexture.filter = Nearest; - } - - if( pixels == null || pixels.width != sizeX || pixels.height != sizeY){ - if( pixels != null ) pixels.dispose(); - var bytes = haxe.io.Bytes.alloc(volumetricLightMap.getProbeCount() * volumetricLightMap.getCoefCount() * 4 * 4); - pixels = new hxd.Pixels(sizeX, sizeY, bytes, RGBA32F, 0); - } - - var engine = h3d.Engine.getCurrent(); - while( ( time != null && timeElapsed < time) || time == null ) { - var coords = volumetricLightMap.getProbeCoords(index); - // Bake a Probe - for( f in 0...6 ) { - engine.begin(); - customCamera.setCubeMap(f, volumetricLightMap.getProbePosition(coords).toVector()); - customCamera.update(); - engine.pushTarget(envMap, f); - engine.clear(0,1,0); - //offScreenScene.render(engine); - renderScene(); - engine.popTarget(); - } - volumetricLightMap.lastBakedProbeIndex = index; - - var pbrRenderer = Std.downcast(offScreenScene.renderer, h3d.scene.pbr.Renderer); - if( useGPU ) { - drawSHIntoTexture(pbrRenderer, envMap, volumetricLightMap.shOrder, index); - } - else { - var pbrRenderer = Std.downcast(offScreenScene.renderer, h3d.scene.pbr.Renderer); - var sh : hrt.prefab.vlm.SphericalHarmonic = convertEnvIntoSH_CPU(envMap, volumetricLightMap.shOrder); - for( coef in 0 ... coefCount ) { - var u = coords.x + volumetricLightMap.probeCount.x * coef; - var v = coords.y + coords.z * volumetricLightMap.probeCount.y; - pixels.setPixelF(u, v, new h3d.Vector(sh.coefR[coef], sh.coefG[coef], sh.coefB[coef], 0)); - } - } - - index = volumetricLightMap.lastBakedProbeIndex + 1; - if( index > volumetricLightMap.getProbeCount() - 1 ) { - if( useGPU ) convertOuputTexturesIntoSH(volumetricLightMap, pixels); - volumetricLightMap.lightProbeTexture.uploadPixels(pixels, 0, 0); - break; - } - - timeElapsed = haxe.Timer.stamp() - timer; - } - - return time - timeElapsed; - } - - function setupEnvMap( resolution : Int ) { - if( envMap == null || resolution != envMap.width ) { - if( envMap != null ) envMap.dispose(); - envMap = new h3d.mat.Texture(resolution, resolution, [Cube, Target], RGBA32F); - } - } - - function setupShaderOutput( order : Int, probeCount: Int ) { - - if( order > 3 || order <= 0 ){ throw "Not Supported"; return; } - - if( !useGPU ) - probeCount = 1; - - if( order >= 1 && (output0 == null || output0.width != probeCount)){ - if(output0 != null) output0.dispose(); - output0 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F); - } - if( order >= 2 && (output1 == null || output1.width != probeCount)){ - if(output1 != null) output1.dispose(); - if(output2 != null) output2.dispose(); - if(output3 != null) output3.dispose(); - output1 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F); - output2 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F); - output3 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F); - } - if( order >= 3 && (output4 == null || output4.width != probeCount)){ - if(output4 != null) output4.dispose(); - if(output5 != null) output5.dispose(); - if(output6 != null) output6.dispose(); - if(output7 != null) output7.dispose(); - output4 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F); - output5 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F); - output6 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F); - output7 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F); - } - - switch(order){ - case 1: - textureArray = [output0]; - computeSH = new h3d.pass.ScreenFx(new hrt.shader.ComputeSH(),[ - Vec4([Value("out.coefL00", 3), Const(0)])]); - case 2: - textureArray = [output0, output1, output2, output3]; - computeSH = new h3d.pass.ScreenFx(new hrt.shader.ComputeSH(),[ - Vec4([Value("out.coefL00", 3), Const(0)]), - Vec4([Value("out.coefL1n1", 3), Const(0)]), - Vec4([Value("out.coefL10", 3), Const(0)]), - Vec4([Value("out.coefL11", 3), Const(0)])]); - - case 3: - textureArray = [output0, output1, output2, output3, output4, output5, output6, output7]; - computeSH = new h3d.pass.ScreenFx(new hrt.shader.ComputeSH(),[ - Vec4([Value("out.coefL00", 3), getSwiz("out.coefL22",X) ]), - Vec4([Value("out.coefL1n1", 3), getSwiz("out.coefL22",Y) ]), - Vec4([Value("out.coefL10", 3), getSwiz("out.coefL22",Z) ]), - Vec4([Value("out.coefL11", 3), Const(0)]), - Vec4([Value("out.coefL2n2", 3), Const(0)]), - Vec4([Value("out.coefL2n1", 3), Const(0)]), - Vec4([Value("out.coefL20", 3), Const(0)]), - Vec4([Value("out.coefL21", 3), Const(0)])]); - } - } - - function drawSHIntoTexture(renderer : h3d.scene.Renderer, env : h3d.mat.Texture, order : Int, probeIndex: Int) { - if( prim == null ){ - prim = new h3d.prim.Plane2D(); - } - - function setPrimPos( index : Int ){ - var v = new hxd.FloatBuffer(); - var pixelSize = (1.0 / output0.width); - var translation = pixelSize * index * 2; - var posX = -1.0 + translation; - v.push( posX ) ; v.push( -1 ); v.push(0); v.push(0); - v.push( posX ); v.push( 1 ); v.push(0); v.push(0); - v.push( posX + pixelSize * 2 ); v.push( -1 ); v.push(0); v.push(0); - v.push( posX + pixelSize * 2 ); v.push( 1 ); v.push(0); v.push(0); - prim.buffer = h3d.Buffer.ofFloats(v, 4, [Quads, RawFormat]); - } - setPrimPos(probeIndex); - - @:privateAccess renderer.ctx.engine = h3d.Engine.getCurrent(); - @:privateAccess renderer.setTargets(textureArray); - computeSH.shader.ORDER = order; - computeSH.shader.width = env.width; - computeSH.shader.environment = env; - computeSH.shader.cubeDir = cubeDir; - computeSH.primitive = prim; - computeSH.render(); - @:privateAccess renderer.resetTarget(); - @:privateAccess renderer.ctx.engine.flushTarget(); - } - - function convertOuputTexturesIntoSH( volumetricLightMap : hrt.prefab.vlm.VolumetricMesh, pixelsOut : hxd.Pixels ) { - - var order = volumetricLightMap.shOrder; - var sh = new hrt.prefab.vlm.SphericalHarmonic(order); - var coefCount = order * order; - var maxCoef : Int = Std.int(Math.min(8, coefCount)); - - for(coef in 0 ... maxCoef){ - var pixels = textureArray[coef].capturePixels(); - for( index in 0 ... pixels.width){ - var coefs : h3d.Vector = pixels.getPixelF(index, 0); - var coords = volumetricLightMap.getProbeCoords(index); - var u = coords.x + volumetricLightMap.probeCount.x * coef; - var v = coords.y + coords.z * volumetricLightMap.probeCount.y; - pixelsOut.setPixelF(u, v, new h3d.Vector(coefs.r, coefs.g, coefs.b, 0)); - - // Last coefs is inside the alpha channel - if( order == 3 ){ - var u = coords.x + volumetricLightMap.probeCount.x * 8; - var v = coords.y + coords.z * volumetricLightMap.probeCount.y; - var prev = pixelsOut.getPixelF(u, v); - if( coef == 0 ){ prev.r = coefs.a; } - if( coef == 1 ){ prev.g = coefs.a; } - if( coef == 2 ){ prev.b = coefs.a; } - pixelsOut.setPixelF(u, v, prev); - } - } - } - } - - function convertEnvIntoSH_CPU( env : h3d.mat.Texture, order : Int ) : hrt.prefab.vlm.SphericalHarmonic { - var coefCount = order * order; - var sphericalHarmonic = new hrt.prefab.vlm.SphericalHarmonic(order); - var face : hxd.Pixels; - var weightSum = 0.0; - var invWidth = 1.0 / env.width; - var shData : Array = [for ( value in 0...coefCount ) 0]; - - for( f in 0...6 ){ - face = env.capturePixels(f, 0); - for (u in 0...face.width) { - var fU : Float = (u / face.width ) * 2 - 1;// Texture coordinate U in range [-1 to 1] - fU *= fU; - var uCoord = 2.0 * u * invWidth + invWidth; - for (v in 0...face.width) { - var fV : Float = (v / face.height ) * 2 - 1;// Texture coordinate V in range [-1 to 1] - fV *= fV; - var vCoord = 2.0 * v * invWidth + invWidth; - var dir = getDir(uCoord, vCoord, f);// Get direction from center of cube texture to current texel - var diffSolid = 4.0 / ((1.0 + fU + fV) * Math.sqrt(1.0 + fU + fV)); // Scale factor depending on distance from center of the face - weightSum += diffSolid; - var color = face.getPixelF(u,v);// Get color from the current face - evalSH(order, dir, shData);// Calculate coefficients of spherical harmonics for current direction - for(i in 0...coefCount){ - sphericalHarmonic.coefR[i] += shData[i] * color.r * diffSolid; - sphericalHarmonic.coefG[i] += shData[i] * color.g * diffSolid; - sphericalHarmonic.coefB[i] += shData[i] * color.b * diffSolid; - } - } - } - } - // Final scale for coefficients - var normProj = (4.0 * Math.PI) / weightSum; - for( i in 0...coefCount ){ - sphericalHarmonic.coefR[i] *= normProj; - sphericalHarmonic.coefG[i] *= normProj; - sphericalHarmonic.coefB[i] *= normProj; - } - return sphericalHarmonic; - } - - inline function evalSH( order : Int, dir : h3d.Vector, shData : Array ) { - for (l in 0...order) { - for (m in -l...l+1) { - shData[getIndex(l, m)] = evalCoef(l, m, dir); - } - } - } - - inline function getIndex( l : Int, m :Int ) : Int { - return l * (l + 1) + m; - } - - inline function getDir( u : Float, v : Float, face : Int ) : h3d.Vector { - var dir = new h3d.Vector(); - switch( face ) { - case 0: dir.x = -1.0; dir.y = -1.0 + v; dir.z = 1.0 - u; - case 1: dir.x = 1.0; dir.y = -1.0 + v; dir.z = -1.0 + u; - case 2: dir.x = 1.0 - u; dir.y = -1.0; dir.z = -1.0 + v; - case 3: dir.x = 1.0 - u; dir.y = 1.0; dir.z = 1.0 - v; - case 4: dir.x = 1.0 - u; dir.y = -1.0 + v; dir.z = 1.0; - case 5: dir.x = -1.0 + u; dir.y = -1.0 + v; dir.z = -1.0; - default: - } - dir.normalizeFast(); - return dir; - } - - inline function evalCoef( l : Int, m : Int, dir : h3d.Vector ) : Float { - // Coef from Stupid Spherical Harmonics (SH) Peter-Pike Sloan Microsoft Corporation - return switch [l,m] { - case[0,0]: 0.282095; // 0.5 * sqrt(1/pi) - case[1,-1]: -0.488603 * dir.y; // -sqrt(3/(4pi)) * y - case[1,0]: 0.488603 * dir.z; // sqrt(3/(4pi)) * z - case[1,1]: -0.488603 * dir.x; // -sqrt(3/(4pi)) * x - case[2,-2]: 1.092548 * dir.y * dir.x;// 0.5 * sqrt(15/pi) * y * x - case[2,-1]: -1.092548 * dir.y * dir.z; // -0.5 * sqrt(15/pi) * y * z - case[2,0]: 0.315392 * (-dir.x * dir.x - dir.y * dir.y + 2.0 * dir.z * dir.z);// 0.25 * sqrt(5/pi) * (-x^2-y^2+2z^2) - case[2,1]: -1.092548 * dir.x * dir.z; // -0.5 * sqrt(15/pi) * x * z - case[2,2]: 0.546274 * (dir.x * dir.x - dir.y * dir.y); // 0.25 * sqrt(15/pi) * (x^2 - y^2) - case[3,-3]: -0.590044 * dir.y * (3.0 * dir.x * dir.x - dir.y * dir.y);// -0.25 * sqrt(35/(2pi)) * y * (3x^2 - y^2) - case[3,-2]: 2.890611 * dir.x * dir.y * dir.z; // 0.5 * sqrt(105/pi) * x * y * z - case[3,-1]: -0.457046 * dir.y * (4.0 * dir.z * dir.z - dir.x * dir.x - dir.y * dir.y); // -0.25 * sqrt(21/(2pi)) * y * (4z^2-x^2-y^2) - case[3,0]: 0.373176 * dir.z * (2.0 * dir.z * dir.z - 3.0 * dir.x * dir.x - 3.0 * dir.y * dir.y); // 0.25 * sqrt(7/pi) * z * (2z^2 - 3x^2 - 3y^2) - case[3,1]: -0.457046 * dir.x * (4.0 * dir.z * dir.z - dir.x * dir.x - dir.y * dir.y); // -0.25 * sqrt(21/(2pi)) * x * (4z^2-x^2-y^2) - case[3,2]: 1.445306 * dir.z * (dir.x * dir.x - dir.y * dir.y); // 0.25 * sqrt(105/pi) * z * (x^2 - y^2) - case[3,3]: -0.590044 * dir.x * (dir.x * dir.x - 3.0 * dir.y * dir.y); // -0.25 * sqrt(35/(2pi)) * x * (x^2-3y^2) - case[4,-4]: 2.503343 * dir.x * dir.y * (dir.x * dir.x - dir.y * dir.y);// 0.75 * sqrt(35/pi) * x * y * (x^2-y^2) - case[4,-3]: -1.770131 * dir.y * dir.z * (3.0 * dir.x * dir.x - dir.y * dir.y); // -0.75 * sqrt(35/(2pi)) * y * z * (3x^2-y^2) - case[4,-2]: 0.946175 * dir.x * dir.y * (7.0 * dir.z * dir.z - 1.0);// 0.75 * sqrt(5/pi) * x * y * (7z^2-1) - case[4,-1]: -0.669047 * dir.y * dir.z * (7.0 * dir.z * dir.z - 3.0);// -0.75 * sqrt(5/(2pi)) * y * z * (7z^2-3) - case[4,0]: 0.105786 * (35.0 * dir.z * dir.z * dir.z * dir.z - 30.0 * dir.z * dir.z + 3.0);// 3/16 * sqrt(1/pi) * (35z^4-30z^2+3) - case[4,1]: -0.669047 * dir.x * dir.z * (7.0 * dir.z * dir.z - 3.0);// -0.75 * sqrt(5/(2pi)) * x * z * (7z^2-3) - case[4,2]: 0.473087 * (dir.x * dir.x - dir.y * dir.y) * (7.0 * dir.z * dir.z - 1.0);// 3/8 * sqrt(5/pi) * (x^2 - y^2) * (7z^2 - 1) - case[4,3]: -1.770131 * dir.x * dir.z * (dir.x * dir.x - 3.0 * dir.y * dir.y);// -0.75 * sqrt(35/(2pi)) * x * z * (x^2 - 3y^2) - case[4,4]: 0.625836 * (dir.x * dir.x * (dir.x * dir.x - 3.0 * dir.y * dir.y) - dir.y * dir.y * (3.0 * dir.x * dir.x - dir.y * dir.y)); // 3/16*sqrt(35/pi) * (x^2 * (x^2 - 3y^2) - y^2 * (3x^2 - y^2)) - default: 0; - } - } -} \ No newline at end of file diff --git a/hide/view/l3d/ProbeBakerProcess.hx b/hide/view/l3d/ProbeBakerProcess.hx deleted file mode 100644 index 788e588e0..000000000 --- a/hide/view/l3d/ProbeBakerProcess.hx +++ /dev/null @@ -1,40 +0,0 @@ -package hide.view.l3d; - -class ProbeBakerProcess { - - public var progress : Float = 0.; - - var lightProbeBaker : hide.view.l3d.LightProbeBaker; - var volumetricLightmap : hrt.prefab.vlm.VolumetricLightmap; - var bakeTime : Float; - var resolution : Int; - - public function new(volumetricLightmap, res, useGPU, bakeTime = 0.016 ){ - progress = 0; - this.bakeTime = bakeTime; - this.volumetricLightmap = volumetricLightmap; - this.resolution = res; - lightProbeBaker = new hide.view.l3d.LightProbeBaker(); - lightProbeBaker.useGPU = useGPU; - } - - public function init( env : h3d.scene.pbr.Environment, sceneData : hrt.prefab.Prefab , shared : hide.prefab.ContextShared, scene : hide.comp.Scene) { - lightProbeBaker.initScene(sceneData, shared, scene, env); - } - - public function update(dt:Float) { - lightProbeBaker.bake(volumetricLightmap.volumetricLightmap, resolution, bakeTime); - progress = (volumetricLightmap.volumetricLightmap.lastBakedProbeIndex +1.0) / volumetricLightmap.volumetricLightmap.getProbeCount(); - if( progress == 1 ) { - lightProbeBaker.dispose(); - lightProbeBaker = null; - onEnd(); - } - } - - public dynamic function onEnd() { - - } - -} - diff --git a/hrt/prefab/Curve.hx b/hrt/prefab/Curve.hx deleted file mode 100644 index 2d6f1f2af..000000000 --- a/hrt/prefab/Curve.hx +++ /dev/null @@ -1,385 +0,0 @@ -package hrt.prefab; -using Lambda; - -class CurveHandle { - public var dt: Float; - public var dv: Float; - public function new(t, v) { - this.dt = t; - this.dv = v; - } -} - -enum abstract CurveKeyMode(Int) { - var Aligned = 0; - var Free = 1; - var Linear = 2; - var Constant = 3; -} - -class CurveKey { - public var time: Float; - public var value: Float; - public var mode: CurveKeyMode; - public var prevHandle: CurveHandle; - public var nextHandle: CurveHandle; - public function new() {} -} - -typedef CurveKeys = Array; - -class Curve extends Prefab { - - @:s public var keyMode : CurveKeyMode = Linear; - @:c public var keys : CurveKeys = []; - @:c public var previewKeys : CurveKeys = []; - - @:s public var loop : Bool = false; - - public var maxTime : Float; - public var duration(get, never): Float; - function get_duration() { - if(keys.length == 0) return 0.0; - return keys[keys.length-1].time; - } - - public function new(?parent) { - super(parent); - this.type = "curve"; - } - - public override function load(o:Dynamic) { - super.load(o); - keys = []; - if(o.keys != null) { - for(k in (o.keys: Array)) { - var nk = new CurveKey(); - nk.time = k.time; - nk.value = k.value; - nk.mode = k.mode; - if(k.prevHandle != null) - nk.prevHandle = new CurveHandle(k.prevHandle.dt, k.prevHandle.dv); - if(k.nextHandle != null) - nk.nextHandle = new CurveHandle(k.nextHandle.dt, k.nextHandle.dv); - keys.push(nk); - } - } - if( keys.length == 0 ) { - addKey(0.0, 0.0); - addKey(1.0, 1.0); - } - } - - public override function save() { - var obj : Dynamic = super.save(); - var keysDat = []; - for(k in keys) { - var o = { - time: k.time, - value: k.value, - mode: k.mode - }; - if(k.prevHandle != null) Reflect.setField(o, "prevHandle", { dv: k.prevHandle.dv, dt: k.prevHandle.dt }); - if(k.nextHandle != null) Reflect.setField(o, "nextHandle", { dv: k.nextHandle.dv, dt: k.nextHandle.dt }); - keysDat.push(o); - } - obj.keys = keysDat; - return obj; - } - - static inline function bezier(c0: Float, c1:Float, c2:Float, c3: Float, t:Float) { - var u = 1 - t; - return u * u * u * c0 + c1 * 3 * t * u * u + c2 * 3 * t * t * u + t * t * t * c3; - } - - public function findKey(time: Float, tolerance: Float) { - var minDist = tolerance; - var closest = null; - for(k in keys) { - var d = hxd.Math.abs(k.time - time); - if(d < minDist) { - minDist = d; - closest = k; - } - } - return closest; - } - - public function addKey(time: Float, ?val: Float, ?mode=null) { - var index = 0; - for(ik in 0...keys.length) { - var key = keys[ik]; - if(time > key.time) - index = ik + 1; - } - - if(val == null) - val = getVal(time); - - var key = new hrt.prefab.Curve.CurveKey(); - key.time = time; - key.value = val; - key.mode = mode != null ? mode : (keys[index] != null ? keys[index].mode : keyMode); - keys.insert(index, key); - return key; - } - - public function addPreviewKey(time: Float, val: Float) { - var key = new hrt.prefab.Curve.CurveKey(); - key.time = time; - key.value = val; - previewKeys.push(key); - return key; - } - - public function getBounds() { - // TODO: Take bezier handles into account - var ret = new h2d.col.Bounds(); - for(k in keys) { - ret.addPos(k.time, k.value); - } - return ret; - } - - public function getVal(time: Float) : Float { - switch(keys.length) { - case 0: return 0; - case 1: return keys[0].value; - default: - } - - if (loop) - time = time % keys[keys.length-1].time; - - var idx = -1; - for(ik in 0...keys.length) { - var key = keys[ik]; - if(time > key.time) - idx = ik; - } - - if(idx < 0) - return keys[0].value; - - var cur = keys[idx]; - var next = keys[idx + 1]; - if(next == null || cur.mode == Constant) - return cur.value; - - var minT = 0.; - var maxT = 1.; - var maxDelta = 1./ 25.; - - inline function sampleTime(t) { - return bezier( - cur.time, - cur.time + (cur.nextHandle != null ? cur.nextHandle.dt : 0.), - next.time + (next.prevHandle != null ? next.prevHandle.dt : 0.), - next.time, t); - } - - inline function sampleVal(t) { - return bezier( - cur.value, - cur.value + (cur.nextHandle != null ? cur.nextHandle.dv : 0.), - next.value + (next.prevHandle != null ? next.prevHandle.dv : 0.), - next.value, t); - } - - while( maxT - minT > maxDelta ) { - var t = (maxT + minT) * 0.5; - var x = sampleTime(t); - if( x > time ) - maxT = t; - else - minT = t; - } - - var x0 = sampleTime(minT); - var x1 = sampleTime(maxT); - var dx = x1 - x0; - var xfactor = dx == 0 ? 0.5 : (time - x0) / dx; - - var y0 = sampleVal(minT); - var y1 = sampleVal(maxT); - var y = y0 + (y1 - y0) * xfactor; - return y; - } - - public function getSum(time: Float) : Float { - var duration = keys[keys.length-1].time; - if(loop && time > duration) { - var cycles = Math.floor(time / duration); - return getSum(duration) * cycles + getSum(time - cycles); - } - - var sum = 0.0; - for(ik in 0...keys.length) { - var key = keys[ik]; - if(time < key.time) - break; - - if(ik == 0 && key.time > 0) { - // Account for start of curve - sum += key.time * key.value; - } - - var nkey = keys[ik + 1]; - if(nkey != null) { - if(time > nkey.time) { - // Full interval - sum += key.value * (nkey.time - key.time); - if(key.mode != Constant) - sum += 0.5 * (nkey.time - key.time) * (nkey.value - key.value); - } - else { - // Split interval - sum += key.value * (time - key.time); - if(key.mode != Constant) - sum += 0.5 * (time - key.time) * hxd.Math.lerp(key.value, nkey.value, (time - key.time) / (nkey.time - key.time)); - } - } - else { - sum += key.value * (time - key.time); - } - } - return sum; - } - - public function sample(numPts: Int) { - var vals = []; - var duration = this.duration; - for(i in 0...numPts) { - var v = getVal(duration * i/(numPts-1)); - vals.push(v); - } - return vals; - } - - #if editor - override function edit( ctx : EditContext ) { - super.edit(ctx); - ctx.properties.add(new hide.Element(' -
-
-
Loop curve
-
-
'), this, function(pname) { - ctx.onChange(this, pname); - }); - - var ce = new hide.comp.CurveEditor(ctx.properties.undo, ctx.properties.element); - ce.curve = this; - } - - override function getHideProps() : HideProps { - return { icon : "paint-brush", name : "Curve" }; - } - #end - - public static function getCurve(parent : Prefab, name: String, onlyEnabled=true) { - for(c in parent.children) { - if(onlyEnabled && !c.enabled) continue; - if(c.name != name) continue; - var curve = c.to(Curve); - if(curve == null) continue; - return curve; - } - return null; - } - - public static function getCurves(parent: Prefab, prefix: String) { - var ret = null; - for(c in parent.children) { - if(!c.enabled) continue; - var idx = c.name.indexOf("."); - var curvePrefix = (idx >= 0) ? c.name.substr(0, idx) : c.name; - if(curvePrefix != prefix) - continue; - var curve = c.to(Curve); - if(curve == null) continue; - if (ret == null) ret = []; - ret.push(curve); - } - return ret; - } - - public static function getGroups(curves: Array) { - var groups : Array<{name: String, items: Array}> = []; - for(c in curves) { - var prefix = c.name.split(".")[0]; - var g = groups.find(g -> g.name == prefix); - if(g == null) { - groups.push({ - name: prefix, - items: [c] - }); - } - else { - g.items.push(c); - } - } - return groups; - } - - - static inline function findCurve(curves: Array, suffix: String) { - return curves.find(c -> StringTools.endsWith(c.name, suffix)); - } - - public static function getVectorValue(curves: Array, defVal: Float=0.0, scale: Float=1.0) : hrt.prefab.fx.Value { - inline function find(s) { - return findCurve(curves, s); - } - var x = find(".x"); - var y = find(".y"); - var z = find(".z"); - var w = find(".w"); - - inline function curveOrVal(c: Curve, defVal: Float) : hrt.prefab.fx.Value { - return c != null ? (scale != 1.0 ? VCurveScale(c, scale) : VCurve(c)) : VConst(defVal); - } - - return VVector( - curveOrVal(x, defVal), - curveOrVal(y, defVal), - curveOrVal(z, defVal), - curveOrVal(w, 1.0)); - } - - public static function getColorValue(curves: Array) : hrt.prefab.fx.Value { - inline function find(s) { - return findCurve(curves, s); - } - - var r = find(".r"); - var g = find(".g"); - var b = find(".b"); - var a = find(".a"); - var h = find(".h"); - var s = find(".s"); - var l = find(".l"); - - if(h != null || s != null || l != null) { - return VHsl( - h != null ? VCurve(h) : VConst(0.0), - s != null ? VCurve(s) : VConst(1.0), - l != null ? VCurve(l) : VConst(1.0), - a != null ? VCurve(a) : VConst(1.0)); - } - - if(a != null && r == null && g == null && b == null) - return VCurve(a); - - if(a == null && r == null && g == null && b == null) - return VOne; // White by default - - return VVector( - r != null ? VCurve(r) : VConst(1.0), - g != null ? VCurve(g) : VConst(1.0), - b != null ? VCurve(b) : VConst(1.0), - a != null ? VCurve(a) : VConst(1.0)); - } - - static var _ = Library.register("curve", Curve); -} diff --git a/hrt/prefab/Model.hx b/hrt/prefab/Model.hx index 318709b67..97596603e 100644 --- a/hrt/prefab/Model.hx +++ b/hrt/prefab/Model.hx @@ -181,7 +181,7 @@ class Model extends Object3D { override function getHideProps() : HideProps { return { icon : "cube", name : "Model", fileSource : ["fbx","hmd"], - allowChildren : function(t) return Library.isOfType(t,Object3D) || Library.isOfType(t,Material) || Library.isOfType(t,Shader) || Library.isOfType(t, hrt.prefab.fx.AnimEvent), + allowChildren : function(t) return Library.isOfType(t,Object3D) || Library.isOfType(t,Material) || Library.isOfType(t,Shader) #if !prefab_refacto || Library.isOfType(t, hrt.prefab.fx.AnimEvent) #end, onResourceRenamed : function(f) animation = f(animation), }; } diff --git a/hrt/prefab/RenderProps.hx b/hrt/prefab/RenderProps.hx index e61669c4e..9d8a2c5bf 100644 --- a/hrt/prefab/RenderProps.hx +++ b/hrt/prefab/RenderProps.hx @@ -68,9 +68,11 @@ class RenderProps extends Prefab { for(fx in renderer.effects) fx.dispose(); renderer.effects = [for( v in getAll(hrt.prefab.rfx.RendererFX,true) ) v]; + #if !prefab_refacto var env = getOpt(hrt.prefab.l3d.Environment); if( env != null ) env.applyToRenderer(renderer); + #end renderer.refreshProps(); return true; } @@ -101,7 +103,7 @@ class RenderProps extends Prefab { return { icon : "sun-o", name : "RenderProps", allowChildren : function(t) { return Library.isOfType(t,hrt.prefab.rfx.RendererFX) || Library.isOfType(t,Light) - || Library.isOfType(t,hrt.prefab.l3d.Environment); + #if !prefab_refacto || Library.isOfType(t,hrt.prefab.l3d.Environment) #end; }}; } diff --git a/hrt/prefab/Shader.hx b/hrt/prefab/Shader.hx index e955cc344..948bf2d4b 100644 --- a/hrt/prefab/Shader.hx +++ b/hrt/prefab/Shader.hx @@ -44,11 +44,13 @@ class Shader extends Prefab { case TSampler2D: if( val != null ) val = hxd.res.Loader.currentInstance.load(val).toTexture(); + #if !prefab_refacto else { var childNoise = getOpt(hrt.prefab.l2d.NoiseGenerator, v.name); if(childNoise != null) val = childNoise.toTexture(); } + #end default: } if(val == null) @@ -167,12 +169,14 @@ class Shader extends Prefab { ectx.properties.add(group,this.props, function(pname) { ectx.onChange(this, pname); + #if !prefab_refacto // Notify change to emitter in case param is used by curves var emitter = getParent(hrt.prefab.fx.Emitter); if(emitter != null) { var ec = ectx.getContext(emitter); emitter.updateInstance(ec); } + #end }); } diff --git a/hrt/prefab/ShaderGraph.hx b/hrt/prefab/ShaderGraph.hx deleted file mode 100644 index 61baf3446..000000000 --- a/hrt/prefab/ShaderGraph.hx +++ /dev/null @@ -1,46 +0,0 @@ -package hrt.prefab; - -class ShaderGraph extends DynamicShader { - - public function new(?parent) { - super(parent); - type = "shadergraph"; - } - - override public function loadShaderDef(ctx: Context) { - if(shaderDef == null) { - var shaderGraph = new hrt.shgraph.ShaderGraph(source); - shaderDef = shaderGraph.compile(); - } - if(shaderDef == null) - return; - - #if editor - for( v in shaderDef.inits ) { - if(!Reflect.hasField(props, v.variable.name)) { - Reflect.setField(props, v.variable.name, v.value); - } - } - #end - } - - #if editor - override function getHideProps() : HideProps { - return { icon : "scribd", name : "Shader Graph", fileSource : ["shgraph"], allowParent : function(p) return p.to(Object2D) != null || p.to(Object3D) != null }; - } - - override function edit( ctx : EditContext ) { - super.edit(ctx); - - var btn = new hide.Element(""); - btn.on("click", function() { - ctx.ide.openFile(source); - }); - ctx.properties.add(btn,this.props, function(pname) { - ctx.onChange(this, pname); - }); - } - #end - - static var _ = Library.register("shgraph", ShaderGraph); -} \ No newline at end of file diff --git a/hrt/prefab/fx/AnimEvent.hx b/hrt/prefab/fx/AnimEvent.hx deleted file mode 100644 index c90d4ba23..000000000 --- a/hrt/prefab/fx/AnimEvent.hx +++ /dev/null @@ -1,102 +0,0 @@ -package hrt.prefab.fx; - -class AnimEvent extends hrt.prefab.fx.Event { - - @:s public var animation: String; - @:s public var speed : Float = 1.0; - @:s public var duration : Float = 0.0; - @:s public var offset : Float = 0.0; - - public function new(?parent) { - super(parent); - this.type = "animEvent"; - } - - override function prepare(ctx: Context) : Event.EventInstance { - var obj = ctx.local3d; - var anim = animation != null ? ctx.loadAnimation(animation) : null; - var lastTime = -1.0; - var inst = null; - if(anim == null) { return null; } - return { - evt: this, - setTime: function(localTime) { - var duration = duration > 0 ? duration : anim.getDuration(); - if(localTime > 0 && localTime < duration) { - if(inst == null) { - inst = obj.playAnimation(anim); - inst.pause = true; - inst.loop = false; - } - inst.setFrame(hxd.Math.clamp((localTime + offset) * anim.sampling * anim.speed * speed, 0, anim.frameCount)); - } - else inst = null; - lastTime = localTime; - } - } - } - - #if editor - override function edit( ctx : EditContext ) { - super.edit(ctx); - var props = ctx.properties.add(new hide.Element(' -
-
-
Time
-
Animation
-
Speed
-
Duration
-
Offset
-
-
- '),this, function(pname) { - ctx.onChange(this, pname); - }); - - if(parent.source != null) { - var select = props.find("select"); - var anims = try ctx.scene.listAnims(parent.source) catch(e: Dynamic) []; - for( a in anims ) - new hide.Element('
- '),this); - var dist = distort; - if( dist == null ) - dist = { - path : null, - scale : 1, - speed : 0, - angle : 0, - amount : 1, - }; - ctx.properties.add(new hide.Element(' -
-
Texture
-
Amount
-
Scale
-
Speed
-
Angle
-
- '),dist, function(name) { - if( name == "path" ) { - if( dist.path == null ) - distort = js.Lib.undefined; - else - distort = dist; - } - }); - } - #end - - static var _ = Library.register("rfx.cloudShadow", CloudShadow); - -} \ No newline at end of file diff --git a/hrt/prefab/rfx/ColorGrading.hx b/hrt/prefab/rfx/ColorGrading.hx deleted file mode 100644 index c8221cbc3..000000000 --- a/hrt/prefab/rfx/ColorGrading.hx +++ /dev/null @@ -1,103 +0,0 @@ -package hrt.prefab.rfx; - -import hxd.Pixels; - -class ColorGradingTonemap extends hxsl.Shader { - static var SRC = { - - @param var size : Int; - @param var intensity : Float; - @param var lut : Sampler2D; - var hdrColor : Vec4; - var pixelColor : Vec4; - - function fragment() { - var uv = pixelColor.rgb; - var innerWidth = size - 1.0; - var sliceSize = 1.0 / size; - var slicePixelSize = sliceSize / size; - var sliceInnerSize = slicePixelSize * innerWidth; - var blueSlice0 = min(floor(uv.b * innerWidth), innerWidth); - var blueSlice1 = min(blueSlice0 + 1.0, innerWidth); - var xOffset = slicePixelSize * 0.5 + uv.r * sliceInnerSize; - var yOffset = sliceSize * 0.5 + uv.g * (1.0 - sliceSize); - var s0 = vec2(xOffset + (blueSlice0 * sliceSize), yOffset); - var s1 = vec2(xOffset + (blueSlice1 * sliceSize), yOffset); - var slice0Color = texture(lut, s0).rgb; - var slice1Color = texture(lut, s1).rgb; - var bOffset = mod(uv.b * innerWidth, 1.0); - pixelColor.rgb = mix(pixelColor.rgb, mix(slice0Color, slice1Color, bOffset), intensity); - } - } -} - -class ColorGrading extends RendererFX { - - var tonemap = new ColorGradingTonemap(); - public var customLut : h3d.mat.Texture; - - @:s var size : Int = 16; - @:s var texturePath : String; - @:s public var intensity : Float = 1; - - public function getLutTexture() { - if( texturePath == null ) return null; - return hxd.res.Loader.currentInstance.load(texturePath).toTexture(); - } - - override function end( r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step ) { - if( step == BeforeTonemapping ) { - r.mark("ColorGrading"); - tonemap.intensity = intensity; - tonemap.size = size; - tonemap.lut = customLut != null ? customLut : getLutTexture(); - if( tonemap.lut != null && intensity > 0 ) - r.addShader(tonemap); - } - } - - #if editor - - override function edit( ctx : hide.prefab.EditContext ) { - - var e = new hide.Element(' -
-
-
LUT
-
Size
-
Intensity
-
-
-
-
- -
-
- '); - - var but = e.find(".createDefault"); - but.click(function(_) { - function saveTexture( name : String ) { - var step = hxd.Math.ceil(255/(size - 1)); - var p = hxd.Pixels.alloc(size * size, size, RGBA); - for( r in 0 ... size ) { - for( g in 0 ... size ) { - for( b in 0 ... size ) { - p.setPixel(r + b * size, g, 255 << 24 | ((r*step) << 16) | ((g*step) << 8 ) | (b*step)); - } - } - } - var path = ctx.ide.getPath(name); - sys.io.File.saveBytes(path, p.toPNG()); - p.dispose(); - } - ctx.ide.chooseFileSave("defaultLUT.png", saveTexture); - }); - - ctx.properties.add(e, this); - } - #end - - static var _ = Library.register("rfx.colorGrading", ColorGrading); - -} \ No newline at end of file diff --git a/hrt/prefab/rfx/Configurator.hx b/hrt/prefab/rfx/Configurator.hx deleted file mode 100644 index 4cd453303..000000000 --- a/hrt/prefab/rfx/Configurator.hx +++ /dev/null @@ -1,274 +0,0 @@ -package hrt.prefab.rfx; - -import h3d.scene.Renderer; - -#if hscript - -private typedef ChangedVar = { obj : Dynamic, field : String, value : Dynamic, set : Bool }; - -class ConfiguratorInterp extends hscript.Interp { - public var allowChanges : Bool = false; - var prevVars : Map> = []; - var allVars : Array = []; - public function new() { - super(); - } - - override function set( o : Dynamic, f : String, v : Dynamic ) : Dynamic { - var prev = prevVars.get(f); - if( prev == null ) { - prev = []; - prevVars.set(f, prev); - } - var found = null; - for( v in prev ) { - if( v.obj == o ) { - found = v; - break; - } - } - if( found == null ) { - #if editor - if( !Reflect.hasField(o,f) ) { - var c = Type.getClass(o); - while( c != null ) { - if( Type.getInstanceFields(c).indexOf(f) >= 0 ) - break; - c = Type.getSuperClass(c); - } - if( c == null ) { - var cl = Type.getClass(o); - throw (cl == null ? ""+o : Type.getClassName(cl)) + " has no field "+f; - } - } - #end - found = { obj : o, field : f, value : null, set : false }; - if ( !allowChanges ) - allVars.push(found); - prev.push(found); - if( allVars.length > 200 ) throw "Vars are leaking"; - } - if( !found.set ) { - found.set = true; - found.value = Reflect.getProperty(o, f); - } - Reflect.setProperty(o, f, v); - return v; - } - - public function restoreVars() { - for( v in allVars ) { - if( v.set ) { - Reflect.setProperty(v.obj, v.field, v.value); - v.set = false; - } - } - } - -} -#end - - -class Configurator extends RendererFX { - - @:s public var vars : Array<{ name : String, defValue : Float }> = []; - @:s var script : String = ""; - var values : Map = new Map(); - - var prefabCache : Map = new Map(); - var particlesCache : Map = new Map(); - - #if hscript - var interp : ConfiguratorInterp; - var parsedExpr : hscript.Expr; - #end - #if editor - var errorTarget : hide.Element; - #end - var rootPrefab : Prefab; - - public function new(?parent) { - super(parent); - type = "configurator"; - } - - public function set( name : String, value : Float ) { - values.set(name,value); - } - - function smoothValue( v : Float, easing : Float ) : Float { - var bpow = Math.pow(v, 1 + easing); - return bpow / (bpow + Math.pow(1 - v, easing + 1)); - } - - function getParts( r : Renderer, id : String) { - var p = particlesCache.get(id); - if (p != null) - return p.v; - var obj = r.ctx.scene.getObjectByName(id); - if ( obj == null) - throw "Missing object #"+id; - #if !editor - particlesCache.set(id, { v : obj }); - #end - return obj; - } - - function getPrefab( opt : Bool, id : String ) { - var p = prefabCache.get(id); - if( p != null ) - return p.r; - var p = rootPrefab.getOpt(hrt.prefab.Prefab,id,true); - if( p == null ) { - if( opt ) return null; - throw "Missing prefab #"+id; - } - #if !editor - prefabCache.set(id, { r : p }); - #end - return p; - } - - #if hscript - function allowChanges( v : Bool ) { - interp.allowChanges = v; - } - #end - - function resetCache() { - prefabCache = []; - particlesCache = []; - } - - override function makeInstance(ctx:Context):Context { - for( v in vars ) - values.set(v.name, v.defValue); - rootPrefab = this; - var shared = ctx.shared; - while( shared.parent != null ) { - rootPrefab = shared.parent.prefab; - shared = shared.parent.shared; - } - while( rootPrefab.parent != null ) - rootPrefab = rootPrefab.parent; - resetCache(); - #if hscript - interp = null; - #end - return super.makeInstance(ctx); - } - - override function begin(r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step) { - #if !hscript - throw "Requires -lib hscript"; - #else - if( step == MainDraw ) { - var errorMessage = null; - if( parsedExpr == null ) { - var parser = new hscript.Parser(); - parsedExpr = try parser.parseString(script) catch( e : hscript.Expr.Error ) { errorMessage = hscript.Printer.errorToString(e); null; }; - } - if( interp == null ) { - interp = new ConfiguratorInterp(); - interp.variables.set("get", getPrefab.bind(false)); - interp.variables.set("getParts", getParts.bind(r)); - interp.variables.set("getOpt", getPrefab.bind(true)); - interp.variables.set("smooth", smoothValue); - interp.variables.set("allowChanges", allowChanges); - } - for( k => v in values ) - interp.variables.set(k, v); - if( errorMessage == null ) - try { - interp.execute(parsedExpr); - } catch( e : Dynamic ) { - errorMessage = Std.string(e); - } - if( errorMessage != null ) { - #if editor - if( errorTarget != null ) errorTarget.text(errorMessage); - #end - } else { - #if editor - if( errorTarget != null ) errorTarget.html(" "); - #end - } - } - #end - } - - #if hscript - override function end(r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step) { - if( step == Overlay ) - interp.restoreVars(); - } - #end - - #if editor - override function getHideProps() : HideProps { - return { name : "Configurator", icon : "dashboard" }; - } - - override function edit( ectx : EditContext ) { - var props = new hide.Element(' -
-
-
-
-
-
-
-
-
-
-
-
 
-
-
-
-
- '); - errorTarget = props.find(".error"); - var evars = props.find("#vars"); - props.find("#addvar").click(function(_) { - var name = ectx.ide.ask("Variable name"); - if( name == null ) return; - ectx.makeChanges(this, function() vars.push({ name : name, defValue: 0 })); - values.set(name, 0); - ectx.rebuildProperties(); - }); - ectx.properties.add(props); - for( v in vars ) { - var ref = { v : values.get(v.name) }; - var def = new hide.Element('
${v.name}
').appendTo(evars); - ectx.properties.build(def, ref, function(_) { - values.set(v.name, ref.v); - }); - def.find("dt").contextmenu(function(e) { - new hide.comp.ContextMenu([ - { label : "Set Default", click : () -> v.defValue = ref.v }, - { label : "Remove", click : () -> { - vars.remove(v); - values.remove(v.name); - interp.variables.remove(v.name); - ectx.rebuildProperties(); - }}, - ]); - return false; - }); - } - - var selt = props.find("#script"); - var editor = new hide.comp.ScriptEditor(this.script, selt, selt); - editor.onSave = function() { - script = editor.code; - parsedExpr = null; - interp = null; - }; - } - #end - - static var _ = Library.register("rfx.configurator", Configurator); - - -} \ No newline at end of file diff --git a/hrt/prefab/rfx/DistanceBlur.hx b/hrt/prefab/rfx/DistanceBlur.hx deleted file mode 100644 index 13ca48fb1..000000000 --- a/hrt/prefab/rfx/DistanceBlur.hx +++ /dev/null @@ -1,135 +0,0 @@ -package hrt.prefab.rfx; - -class DistanceBlurShader extends hrt.shader.PbrShader { - - static var SRC = { - - @param var nearStartDistance : Float; - @param var nearEndDistance : Float; - @param var nearStartIntensity : Float; - @param var nearEndIntensity : Float; - - @param var farStartDistance : Float; - @param var farEndDistance : Float; - @param var farStartIntensity : Float; - @param var farEndIntensity : Float; - - @param var blurredTexture : Sampler2D; - - @const var DEBUG : Bool = false; - - var currentPosition : Vec3; - var blurAmount : Float; - - function __init__fragment() {{ - currentPosition = getPosition(); - var distance = (currentPosition - camera.position).length(); - blurAmount = 0; - if( distance < nearEndDistance ) { - var nearIntensityFactor = clamp((distance - nearStartDistance) / (nearEndDistance - nearStartDistance), 0, 1); - blurAmount = mix(nearStartIntensity, nearEndIntensity, nearIntensityFactor); - } - else if( distance > farStartDistance ) { - var farIntensityFactor = clamp((distance - farStartDistance) / (farEndDistance - farStartDistance), 0, 1); - blurAmount = mix(farStartIntensity, farEndIntensity, farIntensityFactor); - } - }} - - function fragment() { - if( blurAmount <= 0.004 ) discard; - pixelColor = DEBUG ? vec4(blurAmount.xxx, 1.0) : vec4(blurredTexture.get(calculatedUV).rgb, blurAmount); - } - - }; - - public function new() { - super(); - } - -} - -class DistanceBlur extends RendererFX { - - var blurPass = new h3d.pass.ScreenFx(new DistanceBlurShader()); - var lbrBlur = new h3d.pass.Blur(); - - @:s public var nearStartDistance : Float; - @:s public var nearEndDistance : Float; - @:s public var nearStartIntensity : Float = 1; - @:s public var nearEndIntensity : Float; - - @:s public var farStartDistance : Float; - @:s public var farEndDistance : Float; - @:s public var farStartIntensity : Float; - @:s public var farEndIntensity : Float = 1; - - @:s public var showDebug : Bool; - @:s public var blurTextureSize : Float; - @:s public var blurRange : Int; - - function new(?parent) { - super(parent); - nearEndDistance = 10; - farStartDistance = 100; - farEndDistance = 500; - blurTextureSize = 0.5; - blurRange = 6; - blurPass.pass.setBlendMode(Alpha); - } - - override function end(r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step) { - if( !checkEnabled() ) return; - if( step == AfterTonemapping ) { - var ctx = r.ctx; - blurPass.shader.nearStartDistance = nearStartDistance; - blurPass.shader.nearEndDistance = nearEndDistance; - blurPass.shader.nearStartIntensity = nearStartIntensity; - blurPass.shader.nearEndIntensity = nearEndIntensity; - blurPass.shader.farStartDistance = farStartDistance; - blurPass.shader.farEndDistance = farEndDistance; - blurPass.shader.farStartIntensity = farStartIntensity; - blurPass.shader.farEndIntensity = farEndIntensity; - blurPass.shader.DEBUG = #if editor showDebug #else false #end; - - var ldr : h3d.mat.Texture = ctx.getGlobal("ldrMap"); - var lbrBlurred = r.allocTarget("ldrBlurred", false, blurTextureSize, RGBA); - r.copy(ldr, lbrBlurred); - lbrBlur.radius = blurRange; - lbrBlur.apply(ctx, lbrBlurred); - - blurPass.shader.blurredTexture = lbrBlurred; - blurPass.setGlobals(ctx); - blurPass.render(); - } - } - - #if editor - override function edit( ctx : hide.prefab.EditContext ) { - ctx.properties.add(new hide.Element(' -
-
Start Distance
-
End Distance
-
Start Opacity
-
End Opacity
-
-
-
Start Distance
-
End Distance
-
Start Opacity
-
End Opacity
-
-
-
Texture Size
-
Range
-
-
-
Show Debug
-
- '),this); - super.edit(ctx); - } - #end - - static var _ = Library.register("rfx.distanceBlur", DistanceBlur); - -} \ No newline at end of file diff --git a/hrt/prefab/rfx/Distortion.hx b/hrt/prefab/rfx/Distortion.hx deleted file mode 100644 index b224ca340..000000000 --- a/hrt/prefab/rfx/Distortion.hx +++ /dev/null @@ -1,51 +0,0 @@ -package hrt.prefab.rfx; - -class DistortionTonemap extends hxsl.Shader { - static var SRC = { - - var calculatedUV : Vec2; - @param var distortionMap : Sampler2D; - @param var amount : Float; - - function fragment() { - var distortionVal = distortionMap.get(calculatedUV).rg * amount; - calculatedUV += distortionVal; - } - } -} - -class Distortion extends RendererFX { - - var tonemap = new DistortionTonemap(); - @:s public var amount : Float = 1; - - override function end( r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step ) { - if( step == BeforeTonemapping ) { - r.mark("Distortion"); - var distortionMap = r.allocTarget("distortion", true, 1.0, RG16F); - r.ctx.setGlobal("distortion", distortionMap); - r.setTarget(distortionMap); - r.clear(0); - r.draw("distortion"); - - tonemap.amount = amount; - tonemap.distortionMap = distortionMap; - r.addShader(tonemap); - } - } - - #if editor - override function edit( ctx : hide.prefab.EditContext ) { - ctx.properties.add(new hide.Element(' -
-
-
Amount
-
-
- '),this); - } - #end - - static var _ = Library.register("rfx.distortion", Distortion); - -} \ No newline at end of file diff --git a/hrt/prefab/rfx/FrustumJitter.hx b/hrt/prefab/rfx/FrustumJitter.hx deleted file mode 100644 index 4b34f1637..000000000 --- a/hrt/prefab/rfx/FrustumJitter.hx +++ /dev/null @@ -1,231 +0,0 @@ -package hrt.prefab.rfx; - -enum abstract Pattern(String) { - var Still; - var Uniform2; - var Uniform4; - var Uniform4_Helix; - var Uniform4_DoubleHelix; - var SkewButterfly; - var Rotated4; - var Rotated4_Helix; - var Rotated4_Helix2; - var Poisson10; - var Pentagram; - var Halton_2_3_x8; - var Halton_2_3_x16; - var Halton_2_3_x32; - var Halton_2_3_x256; - var MotionPerp2; - var MotionVPerp2; -} - -class FrustumJitter { - - public var points_Still : Array = [ - 0.0, 0.0, - ]; - - public var points_Uniform2 : Array = [ - -0.2, -0.2,//ll - 0.2, 0.2,//ur - ]; - - public var points_Uniform4 : Array = [ - -0.2, -0.2,//ll - 0.2, -0.2,//lr - 0.2, 0.2,//ur - -0.2, 0.2,//ul - ]; - - public var points_Uniform4_Helix : Array = [ - -0.2, -0.2,//ll 3 1 - 0.2, 0.2,//ur \/| - 0.2, -0.2,//lr /\| - -0.2, 0.2,//ul 0 2 - ]; - - public var points_Uniform4_DoubleHelix : Array = [ - -0.2, -0.2,//ll 3 1 - 0.2, 0.2,//ur \/| - 0.2, -0.2,//lr /\| - -0.2, 0.2,//ul 0 2 - -0.2, -0.2,//ll 6--7 - 0.2, -0.2,//lr \ - -0.2, 0.2,//ul \ - 0.2, 0.2,//ur 4--5 - ]; - - public var points_SkewButterfly : Array = [ - -0.250, -0.250, - 0.250, 0.250, - 0.12, -0.12, - -0.12, 0.12, - ]; - - public var points_Rotated4 : Array = [ - -0.12, -0.37,//ll - 0.37, -0.12,//lr - 0.12, 0.37,//ur - -0.37, 0.12,//ul - ]; - - public var points_Rotated4_Helix : Array = [ - -0.12, -0.37,//ll 3 1 - 0.12, 0.37,//ur \/| - 0.37, -0.12,//lr /\| - -0.37, 0.12,//ul 0 2 - ]; - - public var points_Rotated4_Helix2 : Array = [ - -0.12, -0.37,//ll 2--1 - 0.12, 0.37,//ur \/ - -0.37, 0.12,//ul /\ - 0.37, -0.12,//lr 0 3 - ]; - - public var points_Poisson10 : Array = [ - -0.16795960*0.2, 0.65544910*0.2, - -0.69096030*0.2, 0.59015970*0.2, - 0.49843820*0.2, 0.83099720*0.2, - 0.17230150*0.2, -0.03882703*0.2, - -0.60772670*0.2, -0.06013587*0.2, - 0.65606390*0.2, 0.24007600*0.2, - 0.80348370*0.2, -0.48096900*0.2, - 0.33436540*0.2, -0.73007030*0.2, - -0.47839520*0.2, -0.56005300*0.2, - -0.12388120*0.2, -0.96633990*0.2, - ]; - - public var points_Pentagram : Array = [ - 0.000000, 0.525731,// head - -0.309017, -0.42532,// lleg - 0.500000, 0.162460,// rarm - -0.500000, 0.162460,// larm - 0.309017, -0.42532,// rleg - ]; - - public var points_Halton_2_3_x8 : Array = []; - public var points_Halton_2_3_x16 : Array = []; - public var points_Halton_2_3_x32 : Array = []; - public var points_Halton_2_3_x256 : Array = []; - public var points_MotionPerp2 : Array = [ - 0.00, -0.2, - 0.00, 0.2, - ]; - - public var points_MotionVPerp2 : Array = [ - -0.20, -0.0, - 0.20, 0.0, - ]; - - - - private inline function getSeq( pattern : Pattern ) : Array { - return switch (pattern) { - case Still: points_Still; - case Uniform2 : points_Uniform2; - case Uniform4 : points_Uniform4; - case Uniform4_Helix : points_Uniform4_Helix; - case Uniform4_DoubleHelix : points_Uniform4_DoubleHelix; - case SkewButterfly : points_SkewButterfly; - case Rotated4 : points_Rotated4; - case Rotated4_Helix : points_Rotated4_Helix; - case Rotated4_Helix2 : points_Rotated4_Helix2; - case Poisson10 : points_Poisson10; - case Pentagram : points_Pentagram; - case Halton_2_3_x8 : points_Halton_2_3_x8; - case Halton_2_3_x16 : points_Halton_2_3_x16; - case Halton_2_3_x32 : points_Halton_2_3_x32; - case Halton_2_3_x256 : points_Halton_2_3_x256; - case MotionPerp2 : points_MotionPerp2; - case MotionVPerp2 : points_MotionVPerp2; - default : null; - } - } - - public var patternScale = 1.0; - public var activeIndex = 0; - public var curSample = new h2d.col.Point(0,0); - public var prevSample = new h2d.col.Point(0,0); - public var curPattern : Pattern = Still; - - public function new() { - points_Halton_2_3_x8.resize(8); - initializeHalton_2_3(points_Halton_2_3_x8); - points_Halton_2_3_x16.resize(16); - initializeHalton_2_3(points_Halton_2_3_x16); - points_Halton_2_3_x32.resize(32); - initializeHalton_2_3(points_Halton_2_3_x32); - points_Halton_2_3_x256.resize(256); - initializeHalton_2_3(points_Halton_2_3_x256); - } - - public function update() { - - var seq = getSeq(curPattern); - if( seq == null ) - return; - - activeIndex += 1; - activeIndex %= seq.length; - - var newSample = sample(seq, activeIndex); - prevSample.load(curSample); - curSample.load(newSample); - } - - private function sample( pattern : Array, index : Int ) : h2d.col.Point - { - var n = Std.int(pattern.length / 2.0); - var i = index % n; - - var x = patternScale * pattern[2 * i + 0]; - var y = patternScale * pattern[2 * i + 1]; - - return new h2d.col.Point(x, y); - - /*if (pattern != Pattern.MotionPerp2) - return new Vector2(x, y); - else - return new Vector2(x, y).Rotate(Vector2.right.SignedAngle(focalMotionDir));*/ - } - - private function transformPattern( seq : Array, theta : Float, scale : Float) { - var cs = hxd.Math.cos(theta); - var sn = hxd.Math.sin(theta); - var i = 0; - var j = 1; - while( i != seq.length ) { - var x = scale * seq[i]; - var y = scale * seq[j]; - seq[i] = x * cs - y * sn; - seq[j] = x * sn + y * cs; - i += 2; - j += 2; - } - } - - // http://en.wikipedia.org/wiki/Halton_sequence - private function haltonSeq(prime : Int, index : Int = 1/* NOT! zero-based */) : Float { - var r = 0.0; - var f = 1.0; - var i = index; - while( i > 0 ) { - f /= prime; - r += f * (i % prime); - i = hxd.Math.floor(i / prime); - } - return r; - } - - private function initializeHalton_2_3( seq : Array ) { - var sampleCount = Std.int(seq.length / 2.0); - for( i in 0 ... sampleCount ) { - var u = haltonSeq(2, i + 1) - 0.5; - var v = haltonSeq(3, i + 1) - 0.5; - seq[2 * i + 0] = u; - seq[2 * i + 1] = v; - } - } -} \ No newline at end of file diff --git a/hrt/prefab/rfx/GenFog.hx b/hrt/prefab/rfx/GenFog.hx deleted file mode 100644 index cb41a9629..000000000 --- a/hrt/prefab/rfx/GenFog.hx +++ /dev/null @@ -1,245 +0,0 @@ -package hrt.prefab.rfx; - -class GenFogShader extends hrt.shader.PbrShader { - - static var SRC = { - - @param var startDistance : Float; - @param var distanceScale : Float; - @param var distanceOpacity : Float; - @param var cameraDistance : Float; - - @param var startHeight : Float; - @param var heightScale : Float; - @param var heightOpacity : Float; - - @param var startColor : Vec4; - @param var endColor : Vec4; - - @const var usePosition : Bool; - @param var position : Vec3; - - @const var useNoise : Bool; - @param var noiseTex : Sampler2D; - @param var noiseScale : Float; - @param var noiseSpeed : Float; - @param var noiseAmount : Vec3; - - @param var lightDirection : Vec3; - @param var lightColor : Vec3; - - function fragment() { - var origin = getPosition(); - var amount = 0.; - - if( useNoise ) { - var noise = noiseTex.get( origin.xy * noiseScale + vec2(global.time * noiseSpeed, noiseScale * origin.z) * vec2(1,-1) ); - origin += (noise.rgb - 0.5) * noiseAmount; - } - - if( distanceOpacity != 0 ) { - var distance = (origin - (usePosition ? position : camera.position)).length() - cameraDistance; - amount += clamp((distance - startDistance) * distanceScale, 0, 1) * distanceOpacity; - } - - if( heightOpacity != 0 ) { - var height = origin.z; - if( usePosition ) height -= position.z; - amount += clamp((height - startHeight) * heightScale, 0, 1) * heightOpacity; - } - - var fogColor = mix(startColor, endColor, clamp(amount,0,1)); - fogColor.rgb += (camera.position - origin).normalize().dot(lightDirection).max(0) * lightColor; - pixelColor = fogColor; - } - - }; - - public function new() { - super(); - } - -} - -typedef GenFogNoise = { - var texture : String; - var speed : Float; - var scale : Float; - var amount : Float; - var distAmount : Float; -} - -enum abstract GenFogRenderMode(String) { - var BeforeTonemapping; - var AfterTonemapping; -} - -class GenFog extends RendererFX { - - var fogPass = new h3d.pass.ScreenFx(new GenFogShader()); - - @:s public var startDistance : Float; - @:s public var endDistance : Float; - @:s public var distanceOpacity : Float; - @:s public var distanceFixed : Bool; - - @:s public var startHeight : Float; - @:s public var endHeight : Float; - @:s public var heightOpacity : Float; - - @:s public var startOpacity : Float; - @:s public var endOpacity : Float; - - @:s public var startColor : Int; - @:s public var endColor : Int; - @:s public var renderMode : GenFogRenderMode; - - @:s public var noise : GenFogNoise; - - @:s public var posX : Float; - @:s public var posY : Float; - @:s public var posZ : Float; - @:s public var usePosition : Bool; - - @:s public var lightColor = 0xFFFFFF; - @:s public var lightColorAmount : Float; - - public function new(?parent) { - super(parent); - renderMode = AfterTonemapping; - endDistance = 100; - startHeight = 100; - endOpacity = 1; - startColor = 0xffffff; - endColor = 0xffffff; - fogPass.pass.setBlendMode(Alpha); - } - - override function end(r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step) { - if( !checkEnabled() ) return; - if( (step == AfterTonemapping && renderMode == AfterTonemapping) || (step == BeforeTonemapping && renderMode == BeforeTonemapping) ) { - r.mark("DistanceFog"); - var ctx = r.ctx; - - fogPass.shader.startDistance = startDistance; - fogPass.shader.distanceScale = 1 / (endDistance - startDistance); - fogPass.shader.distanceOpacity = distanceOpacity; - fogPass.shader.cameraDistance = distanceFixed ? r.ctx.camera.pos.sub(r.ctx.camera.target).length() : 0; - - fogPass.shader.startHeight = startHeight; - fogPass.shader.heightScale = 1 / (endHeight - startHeight); - fogPass.shader.heightOpacity = heightOpacity; - - fogPass.shader.startColor.setColor(startColor); - fogPass.shader.endColor.setColor(endColor); - fogPass.shader.startColor.a = startOpacity; - fogPass.shader.endColor.a = endOpacity; - - fogPass.shader.position.set(posX, posY, posZ); - fogPass.shader.usePosition = usePosition; - - fogPass.shader.useNoise = noise != null && noise.texture != null; - if( noise != null && noise.texture != null ) { - fogPass.shader.noiseTex = hxd.res.Loader.currentInstance.load(noise.texture).toTexture(); - fogPass.shader.noiseTex.wrap = Repeat; - fogPass.shader.noiseScale = 1 / noise.scale; - fogPass.shader.noiseSpeed = noise.speed / noise.scale; - fogPass.shader.noiseAmount.set(noise.amount * noise.distAmount, noise.amount * noise.distAmount, noise.amount); - } - - var ls = r.getLightSystem().shadowLight; - if( ls == null ) - fogPass.shader.lightDirection.set(0,0,0); - else - fogPass.shader.lightDirection.load(@:privateAccess ls.getShadowDirection()); - fogPass.shader.lightColor.setColor(lightColor); - fogPass.shader.lightColor.scale3(lightColorAmount); - - - fogPass.setGlobals(ctx); - fogPass.render(); - } - } - - #if editor - override function edit( ctx : hide.prefab.EditContext ) { - ctx.properties.add(new hide.Element(' -
-
-
Start Distance
-
End Distance
-
Distance Opacity
-
Camera Independant
-
-
-
Start Height
-
End Height
-
Height Opacity
-
-
-
X
-
Y
-
Z
-
Use Center Point
-
-
-
Start Color
-
End Color
-
Start Opacity
-
End Opacity
-
-
-
Light Color
-
Amount
-
-
-
Render Mode
-
-
- -
- '),this); - if( noise == null ) { - var e = ctx.properties.add(new hide.Element(' -
-
Add
-
- ')); - e.find("a.button").click(function(_) { - noise = { - texture : null, - amount : 1, - scale : 1, - speed : 1, - distAmount : 0.5, - }; - ctx.rebuildProperties(); - }); - } else { - var e = ctx.properties.add(new hide.Element(' -
-
-
Texture
-
Amount
-
Scale
-
Speed
-
Dist.Amount
-
Remove
-
-
- '),noise); - e.find("a.button").click(function(_) { - noise = null; - ctx.rebuildProperties(); - }); - } - super.edit(ctx); - } - #end - - static var _ = Library.register("rfx.genFog", GenFog); - -} \ No newline at end of file diff --git a/hrt/prefab/rfx/SSR.hx b/hrt/prefab/rfx/SSR.hx deleted file mode 100644 index 7ac24d4c0..000000000 --- a/hrt/prefab/rfx/SSR.hx +++ /dev/null @@ -1,144 +0,0 @@ -package hrt.prefab.rfx; - -class SSRShader extends hxsl.Shader { - - static var SRC = { - - @global var camera : { - var inverseViewProj : Mat4; - var position : Vec3; - var viewProj : Mat4; - var zNear : Float; - var zFar : Float; - }; - - @global var depthMap:Channel; - - @param var ldrMap:Sampler2D; - - @param var maxRayDistance : Float; - @param var stepsFirstPass : Int; - @param var stepsSecondPass : Int; - - var projectedPosition:Vec4; - var pixelColor:Vec4; - var transformedNormal : Vec3; - var transformedPosition : Vec3; - - function reflectedRay(ray : Vec3, normal : Vec3) : Vec3 { - return ray - 2.0 * dot(ray, normal) * normal; - } - - function fragment() { - - var startRay = screenToUv(projectedPosition.xy / projectedPosition.w); - - var camDir = (transformedPosition - camera.position).normalize(); - var reflectedRay = camDir - 2.0 * dot(camDir, transformedNormal) * transformedNormal; - var endRayWS = transformedPosition + reflectedRay * maxRayDistance; - var endRayProjected = vec4(endRayWS, 1.0) * camera.viewProj; - var endRay = screenToUv(endRayProjected.xy / endRayProjected.w); - - var delta = endRay - startRay; - var curPos = startRay + delta / stepsFirstPass; - var curPosWS = transformedPosition + reflectedRay * maxRayDistance / stepsFirstPass; - var hitFirstPass = false; - @unroll for (i in 0 ... stepsFirstPass) { - - var projPos = vec4(curPosWS, 1.0) * camera.viewProj; - var distToCam = projPos.z / projPos.w; - if (distToCam > depthMap.get(curPos) && curPos.x <= 1.0 && curPos.x >= 0.0 && curPos.y <= 1.0 && curPos.y >= 0.0) { - hitFirstPass = true; - } - if (hitFirstPass == false) { - curPos += delta / stepsFirstPass; - curPosWS += reflectedRay * maxRayDistance / stepsFirstPass; - } - } - - delta = delta / stepsFirstPass; - endRay = curPos - delta; - curPos -= delta / stepsSecondPass; - curPosWS -= reflectedRay * maxRayDistance / stepsFirstPass / stepsSecondPass; - var hitSecondPass = false; - @unroll for (i in 0 ... stepsSecondPass) { - var projPos = vec4(curPosWS, 1.0) * camera.viewProj; - var distToCam = projPos.z / projPos.w; - if (distToCam < depthMap.get(curPos) && curPos.x <= 1.0 && curPos.x >= 0.0 && curPos.y <= 1.0 && curPos.y >= 0.0) { - hitSecondPass = true; - } - if (hitSecondPass == false) { - curPos -= delta / stepsSecondPass; - curPosWS -= reflectedRay * maxRayDistance / stepsFirstPass / stepsSecondPass; - } - } - - var fragmentColor = vec3(0.0, 0.0, 0.0); - var alpha = 0.0; - if (hitFirstPass && hitSecondPass) { - fragmentColor = ldrMap.get(curPos).rgb; - alpha = 1.0 - (curPosWS - transformedPosition).length() / maxRayDistance; - } - - pixelColor.rgba *= vec4(fragmentColor, alpha); - } - } -} - -class SSR extends RendererFX { - - public var ssrShader : SSRShader; - - @:s public var maxRayDistance : Float = 1.; - @:s public var steps : Int = 10; - @:s public var stepsFirstPass : Int = 10; - @:s public var stepsSecondPass : Int = 10; - - function new(?parent) { - super(parent); - - ssrShader = new SSRShader(); - } - - override function end( r : h3d.scene.Renderer, step : h3d.impl.RendererFX.Step ) { - if( step == Lighting ) { - r.mark("SSR"); - - var ldrCopy = r.allocTarget("ldrMapCopy", false, 0.5); - var ldr = r.ctx.getGlobal("ldrMap"); - h3d.pass.Copy.run(ldr, ldrCopy); - - ssrShader.ldrMap = ldrCopy; - ssrShader.maxRayDistance = maxRayDistance; - ssrShader.stepsFirstPass = stepsFirstPass; - ssrShader.stepsSecondPass = stepsSecondPass; - - var ssrPasses : h3d.pass.PassList = r.get("ssr"); - @:privateAccess var it = ssrPasses.current; - @:privateAcces while (it != null) { - if (@:privateAccess it.pass.getShaderByName("hrt.prefab.rfx.SSRShader") == null) - @:privateAccess it.pass.addShader(ssrShader); - it = it.next; - } - - r.draw("ssr"); - } - } - - #if editor - override function edit( ctx : hide.prefab.EditContext ) { - ctx.properties.add(new hide.Element(' -
-
-
Max ray distance
-
Steps first pass
-
Steps second pass
-
-
- '),this); - } - #end - - static var _ = Library.register("rfx.ssr", SSR); - -} diff --git a/hrt/prefab/rfx/Sao.hx b/hrt/prefab/rfx/Sao.hx deleted file mode 100644 index 41222098c..000000000 --- a/hrt/prefab/rfx/Sao.hx +++ /dev/null @@ -1,110 +0,0 @@ -package hrt.prefab.rfx; - -class Sao extends RendererFX { - - @:s public var size : Float = 1; - @:s public var blur : Float; - @:s public var blurQuality : Float = 1; - @:s public var noiseScale : Float = 1; - @:s public var samples : Int; - @:s public var radius : Float; - @:s public var intensity : Float = 1; - @:s public var bias : Float; - @:s public var microIntensity : Float = 1; - @:s public var useWorldUV : Bool; - @:s public var noiseTexturePath: String; - - var sao : h3d.pass.ScalableAO; - var saoBlur = new h3d.pass.Blur(); - var saoCopy = new h3d.pass.Copy(); - - function new(?parent) { - super(parent); - blur = 5; - samples = 30; - radius = 1; - bias = 0.1; - } - - function loadNoiseTexture(path : String, ?wrap : h3d.mat.Data.Wrap){ - if( path != null ) { - var texture = hxd.res.Loader.currentInstance.load(path).toTexture(); - if( texture == null ) return null; - if( wrap != null ) texture.wrap = wrap; - // Need mipmap for later - return texture; - } - return null; - } - - override function begin( r : h3d.scene.Renderer, step : h3d.impl.RendererFX.Step ) { - if( step == Lighting ) { - r.mark("SSAO"); - if( sao == null ) sao = new h3d.pass.ScalableAO(); - var ctx = r.ctx; - var saoTex = r.allocTarget("sao",false, size); - var normal : hxsl.ChannelTexture = ctx.getGlobal("normalMap"); - var depth : hxsl.ChannelTexture = ctx.getGlobal("depthMap"); - var occlu : hxsl.ChannelTexture = ctx.getGlobal("occlusionMap"); - ctx.engine.pushTarget(saoTex); - sao.shader.numSamples = samples; - sao.shader.sampleRadius = radius; - sao.shader.intensity = intensity - 1; - sao.shader.bias = bias * bias; - sao.shader.depthTextureChannel = depth.channel; - sao.shader.normalTextureChannel = normal.channel; - sao.shader.useWorldUV = useWorldUV; - sao.shader.microOcclusion = occlu.texture; - sao.shader.microOcclusionChannel = occlu.channel; - sao.shader.microOcclusionIntensity = microIntensity; - sao.shader.noiseScale.set(noiseScale, noiseScale); - if( noiseTexturePath != null ) - sao.shader.noiseTexture = loadNoiseTexture(noiseTexturePath, Repeat); - else - sao.shader.noiseTexture = h3d.mat.Texture.genNoise(128); - sao.apply(depth.texture,normal.texture,ctx.camera); - ctx.engine.popTarget(); - - saoBlur.radius = blur; - saoBlur.quality = blurQuality; - saoBlur.apply(ctx, saoTex); - - saoCopy.pass.setColorChannel(occlu.channel); - saoCopy.apply(saoTex, occlu.texture); - } - } - - #if editor - override function edit( ctx : hide.prefab.EditContext ) { - ctx.properties.add(new hide.Element(' -
-
-
Intensity
-
Radius
-
Bias
-
Texture Size
-
Samples
-
Micro Intensity
-
-
-
-
-
Scale
-
Use World UV
-
Texture
-
-
-
-
-
Size
-
Quality
-
- -
- '),this); - } - #end - - static var _ = Library.register("rfx.sao", Sao); - -} diff --git a/hrt/prefab/rfx/ScreenShaderGraph.hx b/hrt/prefab/rfx/ScreenShaderGraph.hx deleted file mode 100644 index 7a03a2db5..000000000 --- a/hrt/prefab/rfx/ScreenShaderGraph.hx +++ /dev/null @@ -1,265 +0,0 @@ -package hrt.prefab.rfx; - -import hrt.prefab.rfx.RendererFX; -import hrt.prefab.Library; -import hxd.Math; - -private class GraphShader extends h3d.shader.ScreenShader { - - static var SRC = { - @param var source : Sampler2D; - - function fragment() { - pixelColor = source.get(calculatedUV); - } - } -} -class ScreenShaderGraph extends RendererFX { - - var shaderPass = new h3d.pass.ScreenFx(new GraphShader()); - var shaderGraph : hrt.shgraph.ShaderGraph; - var shaderDef : hrt.prefab.ContextShared.ShaderDef; - var shader : hxsl.DynamicShader; - - override function end(r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step) { - if( !checkEnabled() ) return; - if( step == AfterTonemapping ) { - r.mark("ScreenShaderGraph"); - if (shader != null) { - var ctx = r.ctx; - var target = r.allocTarget("ppTarget", false); - shaderPass.shader.source = ctx.getGlobal("ldrMap"); - - ctx.engine.pushTarget(target); - shaderPass.render(); - ctx.engine.popTarget(); - - ctx.setGlobal("ldrMap", target); - r.setTarget(target); - } - } - if( step == BeforeTonemapping ) { - r.mark("ScreenShaderGraph"); - if (shader != null) { - var ctx = r.ctx; - var target = r.allocTarget("ppTarget", false); - shaderPass.shader.source = ctx.getGlobal("hdrMap"); - - ctx.engine.pushTarget(target); - shaderPass.render(); - ctx.engine.popTarget(); - - ctx.setGlobal("hdrMap", target); - r.setTarget(target); - } - } - } - - override function load( obj : Dynamic ) { - loadSerializedFields(obj); - } - - public function loadShaderDef() { - shaderDef = shaderGraph.compile(); - if(shaderDef == null) - return; - - #if editor - for( v in shaderDef.inits ) { - if (props == null) - props = {}; - if(!Reflect.hasField(props, v.variable.name)) { - Reflect.setField(props, v.variable.name, v.value); - } - } - #end - } - - function getShaderDefinition():hxsl.SharedShader { - if( shaderDef == null ) - loadShaderDef(); - return shaderDef == null ? null : shaderDef.shader; - } - - function setShaderParam(shader:hxsl.Shader, v:hxsl.Ast.TVar, value:Dynamic) { - cast(shader,hxsl.DynamicShader).setParamValue(v, value); - } - - function syncShaderVars() { - for(v in shaderDef.shader.data.vars) { - if(v.kind != Param) - continue; - var val : Dynamic = Reflect.field(props, v.name); - switch(v.type) { - case TVec(_, VFloat): - if(val != null) { - if( Std.is(val,Int) ) { - var v = new h3d.Vector(); - v.setColor(val); - val = v; - } else - val = h3d.Vector.fromArray(val); - } else - val = new h3d.Vector(); - case TSampler2D: - if( val != null ) - val = hxd.res.Loader.currentInstance.load(val).toTexture(); - else { - var childNoise = getOpt(hrt.prefab.l2d.NoiseGenerator, v.name); - if(childNoise != null) - val = childNoise.toTexture(); - } - default: - } - if(val == null) - continue; - setShaderParam(shader,v,val); - } - } - - function makeShader() { - if( getShaderDefinition() == null ) - return null; - var dshader = new hxsl.DynamicShader(shaderDef.shader); - for( v in shaderDef.inits ) { - #if !hscript - throw "hscript required"; - #else - dshader.hscriptSet(v.variable.name, v.value); - #end - } - shader = dshader; - syncShaderVars(); - shaderPass.addShader(shader); - return shader; - } - - override function makeInstance(ctx: Context) : Context { - ctx = super.makeInstance(ctx); - updateInstance(ctx); - return ctx; - } - - override function updateInstance( ctx: Context, ?propName : String ) { - var p = resolveRef(ctx.shared); - if(p == null) - return; - if (shader == null) - shader = makeShader(); - else - syncShaderVars(); - } - - public function resolveRef(shared : hrt.prefab.ContextShared) { - if(shaderGraph != null) - return shaderGraph; - if(source == null) - return null; - - #if editor - shaderGraph = new hrt.shgraph.ShaderGraph(source); - #else - return null; - #end - return shaderGraph; - } - - function makeShaderParam( v : hxsl.Ast.TVar ) : hrt.prefab.Props.PropType { - var min : Null = null, max : Null = null; - if( v.qualifiers != null ) - for( q in v.qualifiers ) - switch( q ) { - case Range(rmin, rmax): min = rmin; max = rmax; - default: - } - return switch( v.type ) { - case TInt: - PInt(min == null ? null : Std.int(min), max == null ? null : Std.int(max)); - case TFloat: - PFloat(min != null ? min : 0.0, max != null ? max : 1.0); - case TBool: - PBool; - case TSampler2D: - PTexture; - case TVec(n, VFloat): - PVec(n); - default: - PUnsupported(hxsl.Ast.Tools.toString(v.type)); - } - } - - #if editor - override function edit( ectx : hide.prefab.EditContext ) { - var element = new hide.Element(' -
-
-
Reference
-
-
'); - - function updateProps() { - var input = element.find("input"); - updateInstance(ectx.rootContext); - var found = shaderGraph != null; - input.toggleClass("error", !found); - } - updateProps(); - - ectx.properties.add(element, this, function(pname) { - ectx.onChange(this, pname); - if(pname == "source") { - shaderGraph = null; - shaderPass.removeShader(shader); - shader = null; - if (shaderDef != null) { - for(v in shaderDef.inits) { - if (Reflect.hasField(props, v.variable.name)) - Reflect.deleteField(props, v.variable.name); - } - shaderDef = null; - } - - updateProps(); - ectx.properties.clear(); - edit(ectx); - } - }); - - - super.edit(ectx); - if (shaderGraph == null) - return; - getShaderDefinition(); - - var group = new hide.Element('
'); - var props = []; - for(v in shaderDef.shader.data.vars) { - if( v.kind != Param ) - continue; - if( v.qualifiers != null && v.qualifiers.contains(Ignore) ) - continue; - var prop = makeShaderParam(v); - if( prop == null ) continue; - props.push({name: v.name, t: prop, def: Reflect.field(this.props, v.name)}); - } - group.append(hide.comp.PropsEditor.makePropsList(props)); - ectx.properties.add(group, this.props, function(pname) { - ectx.onChange(this, pname); - updateInstance(ectx.rootContext, pname); - - }); - - var btn = new hide.Element(""); - btn.on("click", function() { - ectx.ide.openFile(source); - }); - - ectx.properties.add(btn, this, function(pname) { - ectx.onChange(this, pname); - }); - } - #end - - static var _ = Library.register("rfx.ScreenShaderGraph", ScreenShaderGraph); - -} \ No newline at end of file diff --git a/hrt/prefab/rfx/Sharpen.hx b/hrt/prefab/rfx/Sharpen.hx deleted file mode 100644 index 4656de16c..000000000 --- a/hrt/prefab/rfx/Sharpen.hx +++ /dev/null @@ -1,61 +0,0 @@ -package hrt.prefab.rfx; - -class SharpenShader extends h3d.shader.ScreenShader { - static var SRC = { - - @param var source : Sampler2D; - @param var intensity : Float; - @param var resolution : Vec2; - - function fragment() { - - var offset = 1.0 / resolution; - var center = texture(source, calculatedUV); - var sum = vec4(0); - sum += texture(source, calculatedUV + vec2(0, offset.y)); - sum += texture(source, calculatedUV + vec2(-offset.x, 0)); - sum += texture(source, calculatedUV + vec2(offset.x, 0)); - sum += texture(source, calculatedUV + vec2(0, -offset.y) ); - - // Return edge detection - pixelColor = (1.0 + 4.0 * intensity) * center - intensity * sum; - } - } -} - -class Sharpen extends RendererFX { - - var sharpenPass = new h3d.pass.ScreenFx(new SharpenShader()); - @:s public var intensity : Float; - - override function end( r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step ) { - if( step == AfterTonemapping ) { - r.mark("Sharpen"); - var sharpen = r.allocTarget("sharpen", true, 1.0, RGBA); - var ctx = r.ctx; - ctx.engine.pushTarget(sharpen); - sharpenPass.shader.source = ctx.getGlobal("ldrMap"); - sharpenPass.shader.intensity = intensity; - sharpenPass.shader.resolution.set(ctx.engine.width, ctx.engine.height); - sharpenPass.render(); - ctx.engine.popTarget(); - ctx.setGlobal("ldrMap", sharpen); - r.setTarget(sharpen); - } - } - - #if editor - override function edit( ctx : hide.prefab.EditContext ) { - ctx.properties.add(new hide.Element(' -
-
-
Intensity
-
-
- '),this); - } - #end - - static var _ = Library.register("rfx.sharpen", Sharpen); - -} \ No newline at end of file diff --git a/hrt/prefab/rfx/TemporalBloom.hx b/hrt/prefab/rfx/TemporalBloom.hx deleted file mode 100644 index 60f69146e..000000000 --- a/hrt/prefab/rfx/TemporalBloom.hx +++ /dev/null @@ -1,192 +0,0 @@ -package hrt.prefab.rfx; - -import hxsl.Eval; -import h3d.pass.Copy; - -class DualFilterDown extends h3d.shader.ScreenShader { - - static var SRC = { - - @param var source : Sampler2D; - @param var halfPixel : Vec2; - - function fragment() { - var sum = vec3(0,0,0); - sum += texture(source, calculatedUV).rgb * 4.0; - sum += texture(source, calculatedUV + halfPixel.xy).rgb; - sum += texture(source, calculatedUV - halfPixel.xy).rgb; - sum += texture(source, calculatedUV + vec2(halfPixel.x, -halfPixel.y)).rgb; - sum += texture(source, calculatedUV - vec2(halfPixel.x, -halfPixel.y)).rgb; - pixelColor.rgb = sum / 8.0; - } - }; -} - -class DualFilterUp extends h3d.shader.ScreenShader { - - static var SRC = { - - @param var source : Sampler2D; - @param var halfPixel : Vec2; - - function fragment() { - var sum = vec3(0,0,0); - sum += texture(source, calculatedUV + vec2(-halfPixel.x * 2.0, 0.0)).rgb; - sum += texture(source, calculatedUV + vec2(-halfPixel.x, halfPixel.y)).rgb * 2.0; - sum += texture(source, calculatedUV + vec2(0.0, halfPixel.y * 2.0)).rgb; - sum += texture(source, calculatedUV + vec2(halfPixel.x, halfPixel.y)).rgb * 2.0; - sum += texture(source, calculatedUV + vec2(halfPixel.x * 2.0, 0.0)).rgb; - sum += texture(source, calculatedUV + vec2(halfPixel.x, -halfPixel.y)).rgb * 2.0; - sum += texture(source, calculatedUV + vec2(0.0, -halfPixel.y * 2.0)).rgb; - sum += texture(source, calculatedUV + vec2(-halfPixel.x, -halfPixel.y)).rgb * 2.0; - pixelColor.rgb = sum / 12.0; - } - }; -} - -class Threshold extends h3d.shader.ScreenShader { - - static var SRC = { - - @param var hdr : Sampler2D; - @param var threshold : Float; - @param var intensity : Float; - @param var maxIntensity : Float; - - @const var USE_TEMPORAL_FILTER : Bool; - @const var PREVENT_GHOSTING : Bool; - @param var cur : Sampler2D; - @param var prev : Sampler2D; - @param var prevCamMat : Mat4; - @param var cameraInverseViewProj : Mat4; - @param var strength : Float; - - function fragment() { - var curVal = max(hdr.get(calculatedUV).rgb - threshold, 0.0) * intensity; - pixelColor.rgb = min(curVal, maxIntensity); - - if( USE_TEMPORAL_FILTER ) { - var pixelPos = vec4(uvToScreen(calculatedUV), 1, 1) * cameraInverseViewProj; - pixelPos.xyz /= pixelPos.w; - var prevPos = vec4(pixelPos.xyz, 1.0) * prevCamMat; - prevPos.xyz /= prevPos.w; - var prevUV = screenToUv(prevPos.xy); - var blendStrengh = strength * ceil(1 - max(abs(prevPos.x), abs(prevPos.y))); - var prevVal = prev.get(prevUV).rgb; - pixelColor.rgb = mix(curVal, prevVal, blendStrengh); - } - } - }; -} - -class TemporalBloom extends RendererFX { - - @:s public var size : Float; - @:s public var downScaleCount : Int; - @:s public var threshold : Float; - @:s public var intensity : Float = 1; - @:s public var maxValue : Float; - @:s public var useTemporalFilter : Bool = true; - @:s public var temporalStrength : Float; - - var thresholdPass = new h3d.pass.ScreenFx(new Threshold()); - var downScale = new h3d.pass.ScreenFx(new DualFilterDown()); - var upScale = new h3d.pass.ScreenFx(new DualFilterUp()); - - var prevResult : h3d.mat.Texture; - var prevCamMat : h3d.Matrix; - - var tonemap = new Bloom.BloomTonemap(); - - function new(?parent) { - super(parent); - size = 0.5; - downScaleCount = 5; - threshold = 0.5; - maxValue = 100.0; - prevCamMat = new h3d.Matrix(); - prevCamMat.identity(); - } - - override function end(r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step) { - if( step == BeforeTonemapping ) { - r.mark("TBloom"); - var ctx = r.ctx; - - var source = r.allocTarget("source", false, size, RGBA16F); - ctx.engine.pushTarget(source); - thresholdPass.shader.hdr = ctx.getGlobal("hdrMap"); - thresholdPass.shader.threshold = threshold; - thresholdPass.shader.intensity = intensity; - thresholdPass.shader.maxIntensity = maxValue; - if( useTemporalFilter ) { - thresholdPass.shader.USE_TEMPORAL_FILTER = true; - prevResult = r.allocTarget("pr", false, size, RGBA16F); - thresholdPass.shader.prev = prevResult; - thresholdPass.shader.prevCamMat.load(prevCamMat); - thresholdPass.shader.cameraInverseViewProj.load(ctx.camera.getInverseViewProj()); - thresholdPass.shader.strength = temporalStrength; - thresholdPass.render(); - ctx.engine.popTarget(); - Copy.run(source, prevResult); - prevCamMat.load(ctx.camera.m); - } - else { - thresholdPass.shader.USE_TEMPORAL_FILTER = false; - thresholdPass.render(); - ctx.engine.popTarget(); - } - - var curSize = size; - var curTarget : h3d.mat.Texture = source; - for( i in 0 ... downScaleCount ) { - curSize *= 0.5; - var prevTarget = curTarget; - curTarget = r.allocTarget("dso_"+i, false, curSize, RGBA16F); - ctx.engine.pushTarget(curTarget); - downScale.shader.source = prevTarget; - downScale.shader.halfPixel.set(1.0 / prevTarget.width, 1.0 / prevTarget.height); - downScale.render(); - ctx.engine.popTarget(); - } - for( i in 0 ... downScaleCount ) { - curSize *= 2.0; - var prevTarget = curTarget; - curTarget = r.allocTarget("uso_"+i, false, curSize, RGBA16F); - ctx.engine.pushTarget(curTarget); - upScale.shader.source = prevTarget; - upScale.shader.halfPixel.set(1.0 / prevTarget.width, 1.0 / prevTarget.height); - upScale.render(); - ctx.engine.popTarget(); - } - - tonemap.bloomTexture = curTarget; - r.addShader(tonemap); - } - } - - #if editor - override function edit( ctx : hide.prefab.EditContext ) { - ctx.properties.add(new hide.Element(' -
-
-
Threshold
-
Intensity
-
Max
-
Texture Size
-
DownScale/UpScale Count
-
-
-
-
-
Enable
-
Strength
-
-
- '),this); - } - #end - - static var _ = Library.register("rfx.temporalbloom", TemporalBloom); - -} \ No newline at end of file diff --git a/hrt/prefab/rfx/TemporalFiltering.hx b/hrt/prefab/rfx/TemporalFiltering.hx deleted file mode 100644 index 2a084ea04..000000000 --- a/hrt/prefab/rfx/TemporalFiltering.hx +++ /dev/null @@ -1,247 +0,0 @@ -package hrt.prefab.rfx; - -class TemporalFilteringShader extends h3d.shader.ScreenShader { - - static var SRC = { - - @const var VARIANCE_CLIPPING : Bool; - @const var YCOCG : Bool; - @const var UNJITTER : Bool; - - @param var prevFrame : Sampler2D; - @param var curFrame : Sampler2D; - @param var resolution : Vec2; - @param var amount : Float; - @param var jitterUV : Vec2; - @param var prevJitterUV : Vec2; - - @param var prevCamMat : Mat4; - @param var cameraInverseViewProj : Mat4; - - @const var PACKED_DEPTH : Bool; - @param var depthChannel : Channel; - @param var depthTexture : Sampler2D; - - function rgb2ycocg( rgb : Vec3 ) : Vec3 { - if( YCOCG ) { - var co = rgb.r - rgb.b; - var t = rgb.b + co / 2.0; - var cg = rgb.g - t; - var y = t + cg / 2.0; - return vec3(y, co, cg); - } - else - return rgb; - } - - function ycocg2rgb( ycocg : Vec3 ) : Vec3 { - if( YCOCG ) { - var t = ycocg.r - ycocg.b / 2.0; - var g = ycocg.b + t; - var b = t - ycocg.g / 2.0; - var r = ycocg.g + b; - return vec3(r, g, b); - } - else - return ycocg; - } - - function clipToAABB( cOld : Vec3, cNew : Vec3, centre : Vec3, halfSize : Vec3 ) : Vec3 { - var a = abs(cOld - centre); - if( a.r <= halfSize.r && a.g <= halfSize.g && a.b <= halfSize.b ) { - return cOld; - } - else { - var dir = (cNew - cOld); - var near = centre - sign(dir) * halfSize; - var tAll = (near - cOld) / dir; - var t = 1.0; - if( tAll.x >= 0.0 && tAll.x < t ) t = tAll.x; - if( tAll.y >= 0.0 && tAll.y < t ) t = tAll.y; - if( tAll.z >= 0.0 && tAll.z < t ) t = tAll.z; - - if( t >= 1.0 ) { - return cOld; - } - else - return cOld + dir * t; - } - } - - var isSky : Bool; - - function getPixelPosition( uv : Vec2 ) : Vec3 { - var d = PACKED_DEPTH ? unpack(depthTexture.get(uv)) : depthChannel.get(uv).r; - var tmp = vec4(uvToScreen(uv), d, 1) * cameraInverseViewProj; - tmp.xyz /= tmp.w; - isSky = d <= 0; - return tmp.xyz; - } - - function fragment() { - var unJitteredUV = calculatedUV; - if( UNJITTER ) - unJitteredUV -= jitterUV * 0.5; - - var curPos = getPixelPosition(calculatedUV); - var prevPos = vec4(curPos, 1.0) * prevCamMat; - prevPos.xyz /= prevPos.w; - - var curColor = curFrame.get(unJitteredUV).rgb; - var prevUV = screenToUv(prevPos.xy); - var prevColor = prevFrame.get(prevUV).rgb; - - // Neighborhood clipping [MALAN 2012][KARIS 2014] - if( VARIANCE_CLIPPING ) { - var offsets : Array = [ vec2(-1.0,0.0), vec2(1.0,0.0), vec2(0.0,-1.0), vec2(0.0, 1.0) ]; - var m1 = rgb2ycocg(curColor); - var m2 = m1 * m1; - for( i in 0 ... 4 ) { - var c = rgb2ycocg(curFrame.getLod(unJitteredUV + (offsets[i] / resolution), 0).rgb); - m1 += c; - m2 += c * c; - } - m1 /= 5.0; - m2 = sqrt(m2 / 5.0 - m1 * m1); - prevColor = max(vec3(0.0), ycocg2rgb(clipToAABB(rgb2ycocg(prevColor), rgb2ycocg(curColor), m1, m2))); - } - pixelColor.rgb = isSky ? curColor : mix(curColor, prevColor, amount); - pixelColor.a = 1.0; - } - } -} - -class TemporalFiltering extends hrt.prefab.rfx.RendererFX { - - @:s public var amount : Float; - @:s public var varianceClipping : Bool = true; - @:s public var ycocg : Bool = true; - @:s public var unjitter : Bool = true; - @:s public var jitterPattern : FrustumJitter.Pattern = Still; - @:s public var jitterScale : Float = 1; - @:s public var renderMode : String = "AfterTonemapping"; - - public var frustumJitter = new FrustumJitter(); - public var pass = new h3d.pass.ScreenFx(new TemporalFilteringShader()); - public var jitterMat = new h3d.Matrix(); - var curMatNoJitter = new h3d.Matrix(); - - var tmp = new h3d.Matrix(); - public function getMatrixJittered( camera : h3d.Camera ) : h3d.Matrix { - tmp.identity(); - tmp.multiply(camera.mproj, jitterMat); - tmp.multiply(camera.mcam, tmp); - return tmp; - } - - override function begin( r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step ) { - if( step == MainDraw ) { - var ctx = r.ctx; - var s = pass.shader; - - frustumJitter.curPattern = jitterPattern; - frustumJitter.patternScale = jitterScale; - frustumJitter.update(); - - // Translation Matrix for Jittering - jitterMat.identity(); - jitterMat.translate(frustumJitter.curSample.x / ctx.engine.width, frustumJitter.curSample.y / ctx.engine.height); - - s.prevJitterUV.set(-frustumJitter.prevSample.x / ctx.engine.width, frustumJitter.prevSample.y / ctx.engine.height); - s.jitterUV.set(-frustumJitter.curSample.x / ctx.engine.width, frustumJitter.curSample.y / ctx.engine.height); - - curMatNoJitter.load(ctx.camera.m); - ctx.camera.m.load(getMatrixJittered(ctx.camera)); - @:privateAccess ctx.camera.needInv = true; - s.cameraInverseViewProj.initInverse(curMatNoJitter); - } - } - - override function end( r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step ) { - var ctx = r.ctx; - if( ( step == AfterTonemapping && renderMode == "AfterTonemapping") || (step == BeforeTonemapping && renderMode == "BeforeTonemapping" ) ) { - r.mark("TemporalFiltering"); - var output : h3d.mat.Texture = ctx.engine.getCurrentTarget(); - var depthMap : Dynamic = ctx.getGlobal("depthMap"); - var prevFrame = r.allocTarget("prevFrame", false, 1.0, output.format); - var curFrame = r.allocTarget("curFrame", false, 1.0, output.format); - h3d.pass.Copy.run(output, curFrame); - - var s = pass.shader; - s.curFrame = curFrame; - s.prevFrame = prevFrame; - s.amount = amount; - - s.PACKED_DEPTH = depthMap.packed != null && depthMap.packed == true; - if( s.PACKED_DEPTH ) { - s.depthTexture = depthMap.texture; - } - else { - s.depthChannel = depthMap.texture; - s.depthChannelChannel = depthMap.channel == null ? hxsl.Channel.R : depthMap.channel; - } - - s.resolution.set(output.width, output.height); - s.VARIANCE_CLIPPING = varianceClipping; - s.YCOCG = ycocg; - s.UNJITTER = unjitter; - - r.setTarget(output); - pass.render(); - - h3d.pass.Copy.run(output, prevFrame); - s.prevCamMat.load(curMatNoJitter); - - // Remove Jitter for effects post TAA - r.ctx.camera.update(); - } - } - - #if editor - override function edit( ctx : hide.prefab.EditContext ) { - ctx.properties.add(new hide.Element(' -
-
Amount
-
Variance Clipping
-
Ycocg
-
Unjitter
-
-
Pattern
-
- -
-
Scale
-
-
-
Render Mode
-
-
-
- '),this); - } - #end - - static var _ = hrt.prefab.Library.register("rfx.temporalFiltering", TemporalFiltering); - -} \ No newline at end of file diff --git a/hrt/prefab/rfx/Vignetting.hx b/hrt/prefab/rfx/Vignetting.hx deleted file mode 100644 index 67db9332f..000000000 --- a/hrt/prefab/rfx/Vignetting.hx +++ /dev/null @@ -1,67 +0,0 @@ -package hrt.prefab.rfx; - -import hrt.prefab.rfx.RendererFX; -import hrt.prefab.Library; -import hxd.Math; - -class VignettingShader extends h3d.shader.ScreenShader { - static var SRC = { - - @param var color : Vec4; - @param var radius : Float; - @param var softness : Float; - - function fragment() { - var pos = uvToScreen(calculatedUV); - var dist = length(pos); - var intensity = 1 - smoothstep(radius, radius-softness, dist); - var alpha = color.a * intensity; - pixelColor = vec4(color.rgb, alpha); - } - } -} - -class Vignetting extends RendererFX { - - var vignettingPass = new h3d.pass.ScreenFx(new VignettingShader()); - - @:s public var color : Int = 0xFFFFFF; - @:s public var alpha : Float = 1; - @:s public var radius : Float = 1; - @:s public var softness : Float; - - function sync( r : h3d.scene.Renderer ) { - var ctx = r.ctx; - vignettingPass.shader.color.setColor(color); - vignettingPass.shader.color.a = alpha; - vignettingPass.shader.radius = radius; - vignettingPass.shader.softness = softness; - vignettingPass.pass.setBlendMode(Alpha); - } - - override function end(r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step) { - if( !checkEnabled() ) return; - if( step == AfterTonemapping ) { - r.mark("Vignetting"); - sync(r); - vignettingPass.render(); - } - } - - #if editor - override function edit( ctx : hide.prefab.EditContext ) { - ctx.properties.add(new hide.Element(' -
-
Color
-
Alpha
-
Radius
-
Softness
-
- '),this); - super.edit(ctx); - } - #end - - static var _ = Library.register("rfx.Vignetting", Vignetting); - -} \ No newline at end of file diff --git a/hrt/prefab/terrain/PackWeight.hx b/hrt/prefab/terrain/PackWeight.hx deleted file mode 100644 index c27c5e933..000000000 --- a/hrt/prefab/terrain/PackWeight.hx +++ /dev/null @@ -1,35 +0,0 @@ -package hrt.prefab.terrain; - -class PackWeight extends h3d.shader.ScreenShader { - - static var SRC = { - - @param var indexMap : Sampler2D; - @param var weightTextures : Sampler2DArray; - @param var weightCount : Int; - @param var mask : Array; - - function fragment() { - pixelColor = vec4(0,0,0,1); - var curMaskIndex = 0; - for(i in 0 ... weightCount){ - var w = weightTextures.get(vec3(calculatedUV, i)).r; - if( w > 0 && curMaskIndex < 3){ - pixelColor += mask[curMaskIndex] * w; - curMaskIndex++; - } - } - - /*var texIndex = indexMap.get(calculatedUV).rgb; - var i1 : Int = int(texIndex.r * 255); - var i2 : Int = int(texIndex.g * 255); - var i3 : Int = int(texIndex.b * 255); - pixelColor = vec4(weightTextures.get(vec3(calculatedUV, i1)).r, weightTextures.get(vec3(calculatedUV, i2)).r, weightTextures.get(vec3(calculatedUV, i3)).r, 0);*/ - } - } - - public function new(){ - super(); - mask = [new h3d.Vector(1,0,0,0), new h3d.Vector(0,1,0,0), new h3d.Vector(0,0,1,0), new h3d.Vector(0,0,0,1)]; - } -} diff --git a/hrt/prefab/terrain/Surface.hx b/hrt/prefab/terrain/Surface.hx deleted file mode 100644 index 948ffe23c..000000000 --- a/hrt/prefab/terrain/Surface.hx +++ /dev/null @@ -1,67 +0,0 @@ -package hrt.prefab.terrain; - -class Surface { - public var albedo : h3d.mat.Texture; - public var normal : h3d.mat.Texture; - public var pbr : h3d.mat.Texture; - public var tilling = 1.0; - public var offset : h3d.Vector; - public var angle = 0.0; - public var minHeight = 0.0; - public var maxHeight = 1.0; - - public function new( ?albedo : h3d.mat.Texture, ?normal : h3d.mat.Texture, ?pbr : h3d.mat.Texture ) { - this.albedo = albedo; - this.normal = normal; - this.pbr = pbr; - this.offset = new h3d.Vector(0); - } - - public function clone() : Surface { - var o = new Surface(albedo, normal, pbr); - o.tilling = tilling; - o.offset.load(offset); - o.angle = angle; - o.minHeight = minHeight; - o.maxHeight = maxHeight; - return o; - } - - public function dispose() { - } -} - -class SurfaceArray { - public var albedo : h3d.mat.TextureArray; - public var normal : h3d.mat.TextureArray; - public var pbr : h3d.mat.TextureArray; - public var surfaceCount : Int; - public var params : Array = []; - public var secondParams : Array = []; - - public function new( count, res ) { - surfaceCount = count; - if( count > 0 && res > 0 ) { - albedo = new h3d.mat.TextureArray(res, res, count, [Target], RGBA); - normal = new h3d.mat.TextureArray(res, res, count, [Target], RGBA); - pbr = new h3d.mat.TextureArray(res, res, count, [Target], RGBA); - albedo.wrap = Repeat; - albedo.preventAutoDispose(); - normal.wrap = Repeat; - normal.preventAutoDispose(); - pbr.wrap = Repeat; - pbr.preventAutoDispose(); - } - } - - public function clone() : SurfaceArray { - var o = new SurfaceArray(albedo.layerCount, albedo.width); - return o; - } - - public function dispose() { - if( albedo != null ) albedo.dispose(); - if( normal != null ) normal.dispose(); - if( pbr != null ) pbr.dispose(); - } -} diff --git a/hrt/prefab/terrain/Terrain.hx b/hrt/prefab/terrain/Terrain.hx deleted file mode 100644 index 73a5ccfa0..000000000 --- a/hrt/prefab/terrain/Terrain.hx +++ /dev/null @@ -1,626 +0,0 @@ -package hrt.prefab.terrain; -using Lambda; - -typedef SurfaceProps = { - albedo : String, - normal : String, - pbr : String, - tilling : Float, - angle : Float, - offsetX : Float, - offsetY : Float, - minHeight : Float, - maxHeight : Float, -}; - -@:access(hrt.prefab.terrain.TerrainMesh) -@:access(hrt.prefab.terrain.Tile) -class Terrain extends Object3D { - - public var terrain : TerrainMesh; - - // Tile Param - @:s public var tileSizeX : Float = 64.0; - @:s public var tileSizeY : Float = 64.0; - @:s public var vertexPerMeter : Float = 1.0; - // Texture Param - @:s public var weightMapPixelPerMeter : Float = 1.0; - // Parallax Param - @:s public var parallaxAmount = 0.0; - @:s public var parallaxMinStep : Int = 1; - @:s public var parallaxMaxStep : Int = 16; - // Blend Param - @:s public var heightBlendStrength : Float = 0.0; - @:s public var blendSharpness : Float = 0.0; - // Shadows Param - @:s public var castShadows = false; - // Data for binary save/load - @:c var surfaceCount = 0; - @:c var surfaceSize = 0; - // Utility - @:c var tmpSurfacesProps : Array = []; - var unpackWeight = new h3d.pass.ScreenFx(new UnpackWeight()); - var modified = false; - - #if editor - var packWeight = new h3d.pass.ScreenFx(new PackWeight()); - var editor : hide.prefab.terrain.TerrainEditor; - @:s public var showChecker = false; - @:s public var autoCreateTile = false; - @:s public var brushOpacity : Float = 1.0; - var myContext : Context; - #end - - public function new( ?parent ) { - super(parent); - type = "terrain"; - } - - override function load( obj : Dynamic ) { - super.load(obj); - if( obj.surfaces != null ) tmpSurfacesProps = obj.surfaces; - surfaceCount = obj.surfaceCount == null ? 0 : obj.surfaceCount; - surfaceSize = obj.surfaceSize == null ? 0 : obj.surfaceSize; - } - - override function save() { - var obj : Dynamic = super.save(); - if( terrain != null && terrain.surfaces != null ) { - - obj.surfaceCount = terrain.surfaces.length == 0 ? 0 : terrain.surfaceArray.surfaceCount; - obj.surfaceSize = terrain.surfaces.length == 0 ? 0 : terrain.surfaceArray.albedo.width; - - var surfacesProps : Array = []; - for(surface in terrain.surfaces){ - var surfaceProps : SurfaceProps = - { - albedo : surface.albedo.name, - normal : surface.normal.name, - pbr : surface.pbr.name, - tilling : surface.tilling, - angle : surface.angle, - offsetX : surface.offset.x, - offsetY : surface.offset.y, - minHeight : surface.minHeight, - maxHeight : surface.maxHeight, - }; - surfacesProps.push(surfaceProps); - } - obj.surfaces = surfacesProps; - } - else { - // When cloning - obj.surfaces = tmpSurfacesProps; - obj.surfaceCount = tmpSurfacesProps.length; - } - - #if editor - if( terrain != null ) obj.showChecker = terrain.showChecker; - if( modified ) { - modified = false; - saveTextures(myContext); - } - #end - - return obj; - } - - override function localRayIntersection(ctx:Context, ray:h3d.col.Ray):Float { - if( ray.lz > 0 ) - return -1; // only from top - if( ray.lx == 0 && ray.ly == 0 ) { - var z = terrain.getLocalHeight(ray.px, ray.py); - if( z == null || z > ray.pz ) return -1; - return ray.pz - z; - } - - var b = new h3d.col.Bounds(); - for( t in terrain.tiles ) { - var cb = t.getCachedBounds(); - if( cb != null ) - b.add(cb); - else { - b.addPos(t.x, t.y, -10000); - b.addPos(t.x + terrain.cellSize.x * terrain.cellCount.x, t.y + terrain.cellSize.y * terrain.cellCount.y, 10000); - } - } - - var dist = b.rayIntersection(ray, false); - if( dist < 0 ) - return -1; - var pt = ray.getPoint(dist); - var m = this.vertexPerMeter; - var prevH = pt.z; - while( true ) { - pt.x += ray.lx * m; - pt.y += ray.ly * m; - pt.z += ray.lz * m; - if( !b.contains(pt) ) - break; - var h = terrain.getLocalHeight(pt.x, pt.y); - if( pt.z < h ) { - var k = 1 - (prevH - (pt.z - ray.lz * m)) / (ray.lz * m - (h - prevH)); - pt.x -= k * ray.lx * m; - pt.y -= k * ray.ly * m; - pt.z -= k * ray.lz * m; - return pt.sub(ray.getPos()).length(); - } - prevH = h; - } - return -1; - } - - function loadTiles( ctx : Context ) { - - var resDir = ctx.shared.loadDir(name); - if( resDir == null ) - return; - - var prevWatch = @:privateAccess hxd.res.Image.ENABLE_AUTO_WATCH; - @:privateAccess hxd.res.Image.ENABLE_AUTO_WATCH = false; - - // Avoid texture alloc for unpacking - var tmpPackedWeightTexture = new h3d.mat.Texture(terrain.weightMapResolution.x, terrain.weightMapResolution.y, [Target]); - var bakeHeightAndNormalInGeometry = false; - - var heightData = []; - var weightData = []; - var normalData = []; - var indexData = []; - for( res in resDir ) { - var fileInfos = res.name.split("."); - var ext = fileInfos[1]; - var file = fileInfos[0]; - var coords = file.split("_"); - var x = Std.parseInt(coords[0]); - var y = Std.parseInt(coords[1]); - if( x == null || y == null ) continue; - var type = coords[2]; - var data = { res : res, x : x, y : y, ext : ext }; - switch( type ) { - case "n": normalData.push(data); - case "h": heightData.push(data); - case "w": weightData.push(data); - case "i": indexData.push(data); - } - - var tile = terrain.createTile(x, y, false); - tile.material.shadows = castShadows; - tile.material.mainPass.stencil = new h3d.mat.Stencil(); - tile.material.mainPass.stencil.setFunc(Always, 0x01, 0x01, 0x01); - tile.material.mainPass.stencil.setOp(Keep, Keep, Replace); - } - - // NORMAL - for( nd in normalData ) { - var t = terrain.getTile(nd.x, nd.y); - var bytes = nd.res.entry.getBytes(); - var pixels = new hxd.Pixels(terrain.heightMapResolution.x, terrain.heightMapResolution.y, bytes, RGBA); - t.normalMapPixels = pixels; - if( !bakeHeightAndNormalInGeometry ) { - t.refreshNormalMap(); - t.normalMap.uploadPixels(pixels); - t.needNormalBake = false; - } - } - - // INDEX - for( id in indexData ) { - var t = terrain.getTile(id.x, id.y); - if( t.surfaceIndexMap == null ) - @:privateAccess t.refreshIndexMap(); - if( id.ext == "png" ) { // Retro-compatibility - var indexAsPNG = id.res.toTexture(); - h3d.pass.Copy.run(indexAsPNG, t.surfaceIndexMap); - t.indexMapPixels = t.surfaceIndexMap.capturePixels(); - indexAsPNG.dispose(); - } - else { - var pixels : hxd.Pixels = new hxd.Pixels(terrain.weightMapResolution.x, terrain.weightMapResolution.y, id.res.entry.getBytes(), RGBA); - t.indexMapPixels = pixels; - t.surfaceIndexMap.uploadPixels(pixels); - } - } - - // WEIGHT - for( wd in weightData ) { - var t = terrain.getTile(wd.x, wd.y); - var pixels : hxd.Pixels = new hxd.Pixels(terrain.weightMapResolution.x, terrain.weightMapResolution.y, wd.res.entry.getBytes(), RGBA); - tmpPackedWeightTexture.uploadPixels(pixels); - t.packedWeightMapPixel = pixels; - - // Notice that we need the surfaceIndexMap loaded before doing the unpacking - var engine = h3d.Engine.getCurrent(); - #if editor - // Unpack weight from RGBA texture into a array of texture of R8, and create the TextureArray - if( t.surfaceWeights.length == 0 ) - @:privateAccess t.refreshSurfaceWeightArray(); - for( i in 0 ... t.surfaceWeights.length ) { - engine.pushTarget(t.surfaceWeights[i]); - unpackWeight.shader.indexMap = t.surfaceIndexMap; - unpackWeight.shader.packedWeightTexture = tmpPackedWeightTexture; - unpackWeight.shader.index = i; - unpackWeight.render(); - engine.popTarget(); - } - t.generateWeightTextureArray(); - #else - // Unpack weight from RGBA texture directly into the TextureArray of R8 - t.generateWeightTextureArray(); - for( i in 0 ... terrain.surfaceArray.surfaceCount ) { - engine.pushTarget(t.surfaceWeightArray, i); - unpackWeight.shader.indexMap = t.surfaceIndexMap; - unpackWeight.shader.packedWeightTexture = tmpPackedWeightTexture; - unpackWeight.shader.index = i; - unpackWeight.render(); - engine.popTarget(); - } - #end - } - - // HEIGHT - for( hd in heightData ) { - var t = terrain.getTile(hd.x, hd.y); - var bytes = hd.res.entry.getBytes(); - var pixels = new hxd.Pixels(terrain.heightMapResolution.x, terrain.heightMapResolution.y, bytes, R32F); - t.heightMapPixels = pixels; - - if( !bakeHeightAndNormalInGeometry ) { - // Need heightmap texture for editing - t.refreshHeightMap(); - t.heightMap.uploadPixels(pixels); - t.needNewPixelCapture = false; - } - } - - // BAKE HEIGHT & NORMAL - if( bakeHeightAndNormalInGeometry ) { - for( t in terrain.tiles ) { - t.createBigPrim(); - } - } - - #if editor - for( t in terrain.tiles ) { - if( t == null ) { - "Missing tile" + terrain.tiles.indexOf(t); - continue; - } - if( t.heightMap == null ) trace("Missing heightmap for tile" + terrain.tiles.indexOf(t)); - if( t.normalMap == null ) trace("Missing normalmap for tile" + terrain.tiles.indexOf(t)); - if( t.surfaceIndexMap == null ) trace("Missing surfaceIndexMap for tile" + terrain.tiles.indexOf(t)); - if( t.surfaceWeightArray == null ) trace("Missing surfaceWeightArray for tile" + terrain.tiles.indexOf(t)); - } - #end - - tmpPackedWeightTexture.dispose(); - @:privateAccess hxd.res.Image.ENABLE_AUTO_WATCH = prevWatch; - } - - function loadSurfaces( ctx : Context, onEnd : Void -> Void ) { - for( surfaceProps in tmpSurfacesProps ) { - var surface = terrain.addEmptySurface(); - } - for( i in 0 ... tmpSurfacesProps.length ) { - var surfaceProps = tmpSurfacesProps[i]; - var surface = terrain.getSurface(i); - var albedo = ctx.shared.loadTexture(surfaceProps.albedo); - var normal = ctx.shared.loadTexture(surfaceProps.normal); - var pbr = ctx.shared.loadTexture(surfaceProps.pbr); - function wait() { - if( albedo.isDisposed() || albedo.flags.has(Loading) || normal.flags.has(Loading) || pbr.flags.has(Loading) ) - return; - - albedo.preventAutoDispose(); - normal.preventAutoDispose(); - pbr.preventAutoDispose(); - surface.albedo = albedo; - surface.normal = normal; - surface.pbr = pbr; - surface.offset.x = surfaceProps.offsetX; - surface.offset.y = surfaceProps.offsetY; - surface.angle = surfaceProps.angle; - surface.tilling = surfaceProps.tilling; - surface.minHeight = surfaceProps.minHeight; - if( onEnd != null ) - onEnd(); - } - albedo.waitLoad(wait); - normal.waitLoad(wait); - pbr.waitLoad(wait); - } - } - - public function initTerrain( ctx : Context ) { - - terrain.createBigPrimitive(); - - // Fix terrain being reloaded after a scene modification - if( terrain.surfaceArray != null ) - return; - - #if editor - var shared : hide.prefab.ContextShared = cast myContext.shared; - @:privateAccess shared.scene.setCurrent(); - #end - - var initDone = false; - function waitAll() { - - if( initDone ) - return; - - for( surface in terrain.surfaces ) { - if( surface == null || surface.albedo == null || surface.normal == null || surface.pbr == null ) - return; - } - terrain.generateSurfaceArray(); - - loadTiles(ctx); - - initDone = true; - } - loadSurfaces(ctx, waitAll); - } - - #if editor - - public function saveTextures( ctx : Context ) { - if( !readyToSave(ctx) ) { - throw "Failed to save terrain"; - return; - } - var shared : hide.prefab.ContextShared = cast myContext.shared; - @:privateAccess shared.scene.setCurrent(); - clearSavedTextures(ctx); - saveWeightTextures(ctx); - saveHeightTextures(ctx); - saveNormalTextures(ctx); - return; - } - - function readyToSave( ctx : Context ) : Bool { - var error = "Failed to save terrain : "; - if( terrain == null ){ - trace(error + "terrain is null"); - return false; - } - if( terrain.surfaceArray == null ) { - trace(error + "surfaceArray is null"); - return false; - } - if( terrain.surfaceArray.albedo == null || terrain.surfaceArray.albedo.isDisposed() ){ - trace(error + "surfaceArray.albedo is null"); - return false; - } - if( terrain.surfaceArray.normal == null || terrain.surfaceArray.normal.isDisposed() ){ - trace(error + "surfaceArray.normal is null"); - return false; - } - if( terrain.surfaceArray.pbr == null || terrain.surfaceArray.pbr.isDisposed() ){ - trace(error + "surfaceArray.pbr is null"); - return false; - } - - for( tile in terrain.tiles ) { - if( tile == null ) { - trace(error + "tile is null"); - return false; - } - for( s in tile.surfaceWeights ) { - if( s == null || s.isDisposed() ) { - trace(error + "surfaceWeights "+ tile.surfaceWeights.indexOf(s) +" is null or disposed "); - return false; - } - } - if( tile.heightMap == null || tile.heightMap.isDisposed() ) { - trace(error + "heightMap is null or disposed "); - return false; - } - if( tile.surfaceIndexMap == null || tile.surfaceIndexMap.isDisposed() ) { - trace(error + "surfaceIndexMap is null or disposed "); - return false; - } - if( tile.surfaceWeightArray == null || tile.surfaceWeightArray.isDisposed() ) { - trace(error + "surfaceWeightArray is null or disposed "); - return false; - } - } - return true; - } - - function clearSavedTextures( ctx : Context ) { - var datPath = new haxe.io.Path(ctx.shared.currentPath); - datPath.ext = "dat"; - var fullPath = hide.Ide.inst.getPath(datPath.toString() + "/" + name); - if( sys.FileSystem.isDirectory(fullPath) ) { - var files = sys.FileSystem.readDirectory(fullPath); - for( f in files ) - sys.FileSystem.deleteFile(fullPath + "/" + f); - } - } - - public function saveHeightTextures( ctx : Context ) { - for( tile in terrain.tiles ) { - var pixels = tile.heightMap.capturePixels(); - var fileName = tile.tileX + "_" + tile.tileY + "_" + "h"; - ctx.shared.savePrefabDat(fileName, "bin", name, pixels.bytes); - } - } - - public function saveNormalTextures( ctx : Context ) { - for( tile in terrain.tiles ) { - var pixels : hxd.Pixels = tile.normalMap.capturePixels(); - var fileName = tile.tileX + "_" + tile.tileY + "_" + "n"; - ctx.shared.savePrefabDat(fileName, "bin", name, pixels.bytes); - } - } - - public function saveWeightTextures( ctx : Context ) { - var packedWeightsTex = new h3d.mat.Texture(terrain.weightMapResolution.x, terrain.weightMapResolution.y, [Target], RGBA); - for( tile in terrain.tiles ) { - h3d.Engine.getCurrent().pushTarget(packedWeightsTex); - packWeight.shader.indexMap = tile.surfaceIndexMap; - packWeight.shader.weightTextures = tile.surfaceWeightArray; - packWeight.shader.weightCount = tile.surfaceWeights.length; - packWeight.render(); - - var pixels = packedWeightsTex.capturePixels(); - var fileName = tile.tileX + "_" + tile.tileY + "_" + "w"; - ctx.shared.savePrefabDat(fileName, "bin", name, pixels.bytes); - - var pixels = tile.surfaceIndexMap.capturePixels(); - var fileName = tile.tileX + "_" + tile.tileY + "_" + "i"; - ctx.shared.savePrefabDat(fileName, "bin", name, pixels.bytes); - } - } - - #end - - function createTerrain( ctx : Context ) { - return new TerrainMesh(ctx.local3d); - } - - override function makeInstance( ctx : Context ) : Context { - ctx = ctx.clone(this); - #if editor - myContext = ctx; - #end - - terrain = createTerrain(ctx); - terrain.tileSize = new h2d.col.Point(tileSizeX, tileSizeY); - terrain.cellCount = new h2d.col.IPoint(Math.ceil(tileSizeX * vertexPerMeter), Math.ceil(tileSizeY * vertexPerMeter) ); - terrain.cellSize = new h2d.col.Point(tileSizeX / terrain.cellCount.x, tileSizeY / terrain.cellCount.y ); - terrain.heightMapResolution = new h2d.col.IPoint(terrain.cellCount.x + 1, terrain.cellCount.y + 1); - terrain.weightMapResolution = new h2d.col.IPoint(Math.round(tileSizeX * weightMapPixelPerMeter), Math.round(tileSizeY * weightMapPixelPerMeter)); - terrain.parallaxAmount = parallaxAmount; - terrain.parallaxMinStep = parallaxMinStep; - terrain.parallaxMaxStep = parallaxMaxStep; - terrain.heightBlendStrength = heightBlendStrength; - terrain.blendSharpness = blendSharpness; - terrain.name = "terrain"; - - ctx.local3d = terrain; - ctx.local3d.name = name; - - updateInstance(ctx); - initTerrain(ctx); - return ctx; - } - - override function updateInstance( ctx: Context, ?propName : String ) { - super.updateInstance(ctx, null); - - #if editor - terrain.parallaxAmount = parallaxAmount; - terrain.parallaxMinStep = parallaxMinStep; - terrain.parallaxMaxStep = parallaxMaxStep; - terrain.heightBlendStrength = heightBlendStrength; - terrain.blendSharpness = blendSharpness; - terrain.showChecker = showChecker; - - if( propName == "castShadows" ) { - if( terrain != null ) { - for( t in terrain.tiles ) - t.material.castShadows = castShadows; - } - } - - if( editor != null ) - editor.update(propName); - #end - } - - #if editor - override function makeInteractive( ctx : Context ) : h3d.scene.Interactive { - return null; - } - - override function setSelected( ctx : Context, b : Bool ) { - if( editor != null ) editor.setSelected(ctx, b); - return true; - } - - override function getHideProps() : HideProps { - return { icon : "industry", name : "Terrain", isGround : true }; - } - - override function edit( ctx : EditContext ) { - super.edit(ctx); - var props = new hide.Element('
'); - if( editor == null ) editor = new hide.prefab.terrain.TerrainEditor(this, ctx.properties.undo); - editor.editContext = ctx; - editor.setupUI(props, ctx); - - props.append(' -
-
Cast Shadows
-
Height Blend
-
Sharpness
-
-
-
Amount
-
Min Step
-
Max Step
-
- '); - - ctx.properties.add(props, this, function(pname) { - modified = true; - ctx.onChange(this, pname); - }); - - var obj = { - tileSize : tileSizeX, - vertexes : vertexPerMeter, - pixels : weightMapPixelPerMeter, - }; - var options = new hide.Element(' -
-
Tile Size (Units 3D)
-
Vertexes and HeightMap
(per Unit)
-
Painting Weight Pixels
(per Unit)
-
-
- '); - ctx.properties.add(options,obj); - - options.find('.apply').click(function(_) { - tileSizeY = tileSizeX = obj.tileSize; - TerrainResize.resize(this, new h2d.col.Point(tileSizeX, tileSizeY) ); - weightMapPixelPerMeter = obj.pixels; - vertexPerMeter = obj.vertexes; - terrain.weightMapResolution = new h2d.col.IPoint(Math.round(tileSizeX * weightMapPixelPerMeter), Math.round(tileSizeY * weightMapPixelPerMeter)); - terrain.weightMapResolution.x = Std.int(hxd.Math.max(1, terrain.weightMapResolution.x)); - terrain.weightMapResolution.y = Std.int(hxd.Math.max(1, terrain.weightMapResolution.y)); - terrain.tileSize = new h2d.col.Point(tileSizeX, tileSizeY); - terrain.cellCount = new h2d.col.IPoint(Math.ceil(tileSizeX * vertexPerMeter), Math.ceil(tileSizeY * vertexPerMeter) ); - terrain.cellCount.x = Std.int(hxd.Math.max(1, terrain.cellCount.x)); - terrain.cellCount.y = Std.int(hxd.Math.max(1, terrain.cellCount.y)); - terrain.cellSize = new h2d.col.Point(tileSizeX / terrain.cellCount.x, tileSizeY / terrain.cellCount.y ); - terrain.heightMapResolution = new h2d.col.IPoint(terrain.cellCount.x + 1, terrain.cellCount.y + 1); - terrain.refreshAllGrids(); - terrain.refreshAllTex(); - if( editor != null ) { - editor.refresh(); - @:privateAccess editor.blendEdges(terrain.tiles); - } - modified = true; - }); - - ctx.properties.add(new hide.Element(' -
-
Show Grid
-
Mode
-
-
- '), this); - } - #end - - static var _ = Library.register("terrain", Terrain); -} \ No newline at end of file diff --git a/hrt/prefab/terrain/TerrainMesh.hx b/hrt/prefab/terrain/TerrainMesh.hx deleted file mode 100644 index ca6a7faf3..000000000 --- a/hrt/prefab/terrain/TerrainMesh.hx +++ /dev/null @@ -1,296 +0,0 @@ -package hrt.prefab.terrain; - -import h3d.mat.Texture; - -@:access(hrt.prefab.terrain.Tile) -class TerrainMesh extends h3d.scene.Object { - - var primitive : h3d.prim.BigPrimitive; - - // Resolution Vertexes/Pixels - public var tileSize : h2d.col.Point; - public var cellSize : h2d.col.Point; - public var cellCount : h2d.col.IPoint; - - public var heightMapResolution : h2d.col.IPoint; - public var weightMapResolution : h2d.col.IPoint; - public var useBigPrim = false; - - // Shader Params - #if editor - public var showGrid : Bool; - public var showChecker : Bool; - public var showComplexity : Bool; - #end - public var enableParallax : Bool = true; - public var parallaxAmount : Float; - public var parallaxMinStep : Int; - public var parallaxMaxStep : Int; - public var heightBlendStrength : Float; - public var blendSharpness : Float; - - // Data - var tiles : Array = []; - var surfaces : Array = []; - var surfaceArray : Surface.SurfaceArray; - - public function new(?parent){ - super(parent); - } - - override function onRemove() { - super.onRemove(); - if( surfaceArray != null ) - surfaceArray.dispose(); - } - - public function getLocalHeight( x : Float, y : Float, fast = false) : Null { - var xi = hxd.Math.floor(x/tileSize.x); - var yi = hxd.Math.floor(y/tileSize.y); - var t = getTile(xi, yi); - if( t != null ) { - return t.getHeight((x - xi * tileSize.x) / tileSize.x, (y - yi * tileSize.y) / tileSize.y, fast); - } - return null; - } - - public function getHeight( x : Float, y : Float, fast = false) : Null { - var t = getTileAtWorldPos(x, y); - if( t != null ) { - tmpPt.set(x, y); - var pos = t.globalToLocal(tmpPt); - return t.getHeight(pos.x / tileSize.x, pos.y / tileSize.y, fast); - } - return null; - } - - public function getSurface( i : Int ) : Surface { - if(i < surfaces.length) - return surfaces[i]; - return null; - } - - public function getSurfaceFromTex( albedo, ?normal, ?pbr ) : Surface { - for( s in surfaces ) { - var valid = false; - valid = s.albedo.name == albedo; - valid = valid && !( normal != null && s.normal.name != normal ); - valid = valid && !( pbr != null && s.pbr.name != pbr ); - if( valid ) return s; - } - return null; - } - - public function addSurface( albedo, normal, pbr ) : Surface { - surfaces.push(new Surface(albedo, normal, pbr)); - return surfaces[surfaces.length - 1]; - } - - public function addEmptySurface() : Surface { - surfaces.push( new Surface() ); - return surfaces[surfaces.length - 1]; - } - - public function generateSurfaceArray() { - if( surfaces.length == 0 ) return; - var surfaceSize = 1; - for( i in 0 ... surfaces.length ) - if( surfaces[i].albedo != null ) surfaceSize = hxd.Math.ceil(hxd.Math.max(surfaces[i].albedo.width, surfaceSize)); - - if(surfaceArray != null) surfaceArray.dispose(); - surfaceArray = new Surface.SurfaceArray(surfaces.length, surfaceSize); - for( i in 0 ... surfaces.length ) { - if( surfaces[i].albedo != null ) h3d.pass.Copy.run(surfaces[i].albedo, surfaceArray.albedo, null, null, i); - if( surfaces[i].normal != null ) h3d.pass.Copy.run(surfaces[i].normal, surfaceArray.normal, null, null, i); - if( surfaces[i].pbr != null ) h3d.pass.Copy.run(surfaces[i].pbr, surfaceArray.pbr, null, null, i); - } - - // OnContextLost support - surfaceArray.albedo.realloc = function() { - for( i in 0 ... surfaceArray.surfaceCount ) - h3d.pass.Copy.run(surfaces[i].albedo, surfaceArray.albedo, null, null, i); - } - surfaceArray.normal.realloc = function() { - for( i in 0 ... surfaceArray.surfaceCount ) - h3d.pass.Copy.run(surfaces[i].normal, surfaceArray.normal, null, null, i); - } - surfaceArray.pbr.realloc = function() { - for( i in 0 ... surfaceArray.surfaceCount ) - h3d.pass.Copy.run(surfaces[i].pbr, surfaceArray.pbr, null, null, i); - } - - updateSurfaceParams(); - refreshAllTex(); - } - - public function updateSurfaceParams() { - for( i in 0 ... surfaces.length ) { - surfaceArray.params[i] = new h3d.Vector(surfaces[i].tilling, surfaces[i].offset.x, surfaces[i].offset.y, hxd.Math.degToRad(surfaces[i].angle)); - surfaceArray.secondParams[i] = new h3d.Vector(surfaces[i].minHeight, surfaces[i].maxHeight, 0, 0); - } - } - - function createBigPrimitive() { - - if( primitive != null ) - primitive.dispose(); - - primitive = new h3d.prim.BigPrimitive(3, true); - - inline function addVertice(x : Float, y : Float, i : Int) { - primitive.addPoint(x, y, 0); - } - - primitive.begin(0,0); - for( y in 0 ... cellCount.y + 1 ) { - for( x in 0 ... cellCount.x + 1 ) { - addVertice(x * cellSize.x, y * cellSize.y, x + y * (cellCount.x + 1)); - } - } - - for( y in 0 ... cellCount.y ) { - for( x in 0 ... cellCount.x ) { - var i = x + y * (cellCount.x + 1); - if( i % 2 == 0 ) { - primitive.addIndex(i); - primitive.addIndex(i + 1); - primitive.addIndex(i + cellCount.x + 2); - primitive.addIndex(i); - primitive.addIndex(i + cellCount.x + 2); - primitive.addIndex(i + cellCount.x + 1); - } - else { - primitive.addIndex(i + cellCount.x + 1); - primitive.addIndex(i); - primitive.addIndex(i + 1); - primitive.addIndex(i + 1); - primitive.addIndex(i + cellCount.x + 2); - primitive.addIndex(i + cellCount.x + 1); - } - } - } - primitive.flush(); - } - - public function refreshAllGrids() { - createBigPrimitive(); - } - - public function refreshAllTex() { - for( tile in tiles ) - tile.refreshTex(); - } - - public function refreshAll() { - refreshAllGrids(); - refreshAllTex(); - } - - public function createTile(x : Int, y : Int, ?createTexture = true) : Tile { - var tile = getTile(x,y); - if(tile == null){ - tile = new Tile(x, y, this); - if( createTexture ) tile.refreshTex(); - tiles.push(tile); - } - return tile; - } - - public function addTile( tile : Tile, ?replace = false ) { - for( t in tiles ) { - if( tile == t ) return; - if( tile.tileX == t.tileX && tile.tileY == t.tileY ) { - if( replace ) { - removeTile(t); - break; - }else - return; - } - } - tile.parent = this; - tiles.push(tile); - addChild(tile); - } - - public function removeTileAt( x : Int, y : Int ) : Bool { - var t = getTile(x,y); - if( t == null ) { - removeTile(t); - return true; - } - return false; - } - - public function removeTile( t : Tile ) : Bool { - if( t == null ) return false; - var r = tiles.remove(t); - if( r ) t.remove(); - return r; - } - - public function getTileIndex( t : Tile ) : Int { - for( i in 0 ... tiles.length ) - if( t == tiles[i] ) return i; - return -1; - } - - public function getTile( x : Int, y : Int ) : Tile { - var result : Tile = null; - for( tile in tiles ) - if( tile.tileX == x && tile.tileY == y ) result = tile; - return result; - } - - public function getTileAtWorldPos( x : Float, y : Float ) : Tile { - var pos = toLocalPos(x, y); - var result : Tile = null; - var tileX = Math.floor(pos.x / tileSize.x); - var tileY = Math.floor(pos.y / tileSize.y); - for( tile in tiles ) - if( tile.tileX == tileX && tile.tileY == tileY ) result = tile; - return result; - } - - public function createTileAtWorldPos( x : Float, y : Float ) : Tile { - var pos = toLocalPos(x, y); - var tileX = Math.floor(pos.x / tileSize.x); - var tileY = Math.floor(pos.y / tileSize.y); - var result = getTile(tileX, tileY); - return result == null ? createTile(tileX, tileY) : result; - } - - public function getTiles( x : Float, y : Float, range : Float, ?create = false ) : Array { - var pos = toLocalPos(x, y); - if( create != null && create ) { - var maxTileX = Math.floor((pos.x + range)/ tileSize.x); - var minTileX = Math.floor((pos.x - range)/ tileSize.x); - var maxTileY = Math.floor((pos.y + range)/ tileSize.y); - var minTileY = Math.floor((pos.y - range)/ tileSize.y); - for( x in minTileX ... maxTileX + 1) { - for( y in minTileY...maxTileY + 1) { - var t = createTile(x, y); - #if editor - t.material.mainPass.stencil = new h3d.mat.Stencil(); - t.material.mainPass.stencil.setFunc(Always, 0x01, 0x01, 0x01); - t.material.mainPass.stencil.setOp(Keep, Keep, Replace); - #end - } - } - } - var result : Array = []; - for( tile in tiles) - if( Math.abs(pos.x - (tile.tileX * tileSize.x + tileSize.x * 0.5)) <= range + (tileSize.x * 0.5) - && Math.abs(pos.y - (tile.tileY * tileSize.y + tileSize.y * 0.5)) <= range + (tileSize.y * 0.5) ) - result.push(tile); - return result; - } - - static var tmpPt = new h3d.col.Point(); - inline function toLocalPos( x : Float, y : Float ) { - tmpPt.set(x, y); - globalToLocal(tmpPt); - return tmpPt; - } -} - - diff --git a/hrt/prefab/terrain/TerrainResize.hx b/hrt/prefab/terrain/TerrainResize.hx deleted file mode 100644 index 9389bbbee..000000000 --- a/hrt/prefab/terrain/TerrainResize.hx +++ /dev/null @@ -1,148 +0,0 @@ -package hrt.prefab.terrain; -import h3d.pass.ScreenFx; -using Lambda; - -class TerrainCopy extends h3d.shader.ScreenShader { - static var SRC = { - - @param var from : Vec2; - @param var to : Vec2; - @param var source : Sampler2D; - - function vertex() { - output.position = vec4(uvToScreen(mix(from, to, screenToUv(input.position))), 0, 1); - output.position.y *= flipY; - } - - function fragment() { - pixelColor = source.get(calculatedUV); - } - } -} - -@:access(hrt.prefab.terrain.TerrainMesh) -@:access(hrt.prefab.terrain.Tile) -class TerrainResize { - - public function new( ) { - - } - - static inline function getTileBounds( xi, yi, s : h2d.col.Point ) : h2d.col.Bounds { - var b = new h2d.col.Bounds(); - b.xMin = xi * s.x; - b.yMin = yi * s.y; - b.xMax = (xi + 1) * s.x; - b.yMax = (yi + 1) * s.y; - return b; - } - - static public function resize( prefab : Terrain, tileSize : h2d.col.Point ) { - - if( prefab.terrain.tileSize.x == tileSize.x && prefab.terrain.tileSize.y == tileSize.y ) - return; - - var engine = h3d.Engine.getCurrent(); - var terrainCopy = new ScreenFx(new TerrainCopy()); - - var prevTiles = prefab.terrain.tiles; - var prevSize = prefab.terrain.tileSize; - var curSize = tileSize; - - // Recreate tiles to fit with the new size - var terrainMinMax = new h3d.Vector(); - terrainMinMax.set(hxd.Math.POSITIVE_INFINITY, hxd.Math.POSITIVE_INFINITY, hxd.Math.NEGATIVE_INFINITY); - for( t in prefab.terrain.tiles ) { - terrainMinMax.x = hxd.Math.min(terrainMinMax.x, t.tileX * prevSize.x); - terrainMinMax.y = hxd.Math.min(terrainMinMax.y, t.tileY * prevSize.y); - terrainMinMax.z = hxd.Math.max(terrainMinMax.z, (t.tileX + 1) * prevSize.x); - terrainMinMax.w = hxd.Math.max(terrainMinMax.w, (t.tileY + 1) * prevSize.y); - } - var terrainBounds : Array = []; - var bias = 0.1; - for( t in prefab.terrain.tiles ) { - var b = new h2d.col.Bounds(); - b.xMin = t.tileX * prevSize.x + bias; - b.yMin = t.tileY * prevSize.y + bias; - b.xMax = (t.tileX + 1) * prevSize.x - bias; - b.yMax = (t.tileY + 1) * prevSize.y - bias; - terrainBounds.push(b); - } - prefab.terrain.tiles = []; - prefab.terrain.tileSize = tileSize; - var x = terrainMinMax.x; - var y = terrainMinMax.y; - var tmpBounds = new h2d.col.Bounds(); - while( x < terrainMinMax.z ) { - while( y < terrainMinMax.w ) { - - tmpBounds.xMin = x; - tmpBounds.yMin = y; - tmpBounds.xMax = x + curSize.x; - tmpBounds.yMax = y + curSize.y; - var intersectTerrain = false; - for( b in terrainBounds ) { - if( b.intersects(tmpBounds) ) { - intersectTerrain = true; - break; - } - } - if( intersectTerrain ) - prefab.terrain.createTile(Std.int(x / curSize.x), Std.int(y / curSize.y)); - - y += curSize.y; - } - y = terrainMinMax.y; - x += curSize.x; - } - - // Copy Textures - for( curTile in prefab.terrain.tiles ) { - var curTileBounds = getTileBounds(curTile.tileX, curTile.tileY, curSize); - for( prevTile in prevTiles ) { - - var prevTileBounds = getTileBounds(prevTile.tileX, prevTile.tileY, prevSize); - if( !prevTileBounds.intersects(curTileBounds) ) - continue; - - terrainCopy.shader.from.set((prevTileBounds.x - curTileBounds.x) / curTileBounds.width, (prevTileBounds.y - curTileBounds.y) / curTileBounds.height); - terrainCopy.shader.to.set(terrainCopy.shader.from.x + prevTileBounds.width / curTileBounds.width, terrainCopy.shader.from.y + prevTileBounds.height / curTileBounds.height ); - - // Copy HeightMap - engine.pushTarget(curTile.heightMap); - terrainCopy.shader.source = prevTile.heightMap; - terrainCopy.render(); - engine.popTarget(); - - // Copy NormalMap - engine.pushTarget(curTile.normalMap); - terrainCopy.shader.source = prevTile.normalMap; - terrainCopy.render(); - engine.popTarget(); - - // Copy Index Map - engine.pushTarget(curTile.surfaceIndexMap); - terrainCopy.shader.source = prevTile.surfaceIndexMap; - terrainCopy.render(); - engine.popTarget(); - - // Copy Weight Map - for( i in 0 ... curTile.surfaceWeightArray.layerCount ) { - engine.pushTarget(curTile.surfaceWeights[i]); - terrainCopy.shader.source = prevTile.surfaceWeights[i]; - terrainCopy.render(); - engine.popTarget(); - engine.pushTarget(curTile.surfaceWeightArray, i); - terrainCopy.render(); - engine.popTarget(); - } - } - } - - // Dispose old tiles - for( t in prevTiles ) { - t.remove(); - } - } - -} \ No newline at end of file diff --git a/hrt/prefab/terrain/Tile.hx b/hrt/prefab/terrain/Tile.hx deleted file mode 100644 index 84c303725..000000000 --- a/hrt/prefab/terrain/Tile.hx +++ /dev/null @@ -1,462 +0,0 @@ -package hrt.prefab.terrain; - -class NormalBake extends h3d.shader.ScreenShader { - - static var SRC = { - - @param var heightMap : Sampler2D; - @param var heightMapSize : Vec2; - - function fragment() { - var pixelSize = 1.0 / heightMapSize; - var h = heightMap.get(calculatedUV).r; - var h1 = heightMap.get(calculatedUV + vec2(0, pixelSize.y)).r; - var h2 = heightMap.get(calculatedUV + vec2(pixelSize.x, 0)).r; - var h3 = heightMap.get(calculatedUV + vec2(0, -pixelSize.y)).r; - var h4 = heightMap.get(calculatedUV + vec2(-pixelSize.x, 0)).r; - var v1 = vec3( 0, 1, h1 - h); - var v2 = vec3( 1, 0, h2 - h); - var v3 = vec3( 0, -1, h3 - h); - var v4 = vec3( -1, 0, h4 - h); - var n = (cross(v1, v2) + cross(v2, v3) + cross(v3, v4) + cross(v4, v1)) / -4; - n = n.normalize(); - pixelColor.rgb = n * 0.5 + 0.5; - } - }; -} - -enum Direction { - Up; Down; Left; Right; UpLeft; UpRight; DownLeft; DownRight; -} - -@:access(hrt.prefab.terrain.TerrainMesh) -class Tile extends h3d.scene.Mesh { - - var shader : hrt.shader.Terrain; - var terrain : TerrainMesh; - - // INDEXES - public var tileX (default, null) : Int; - public var tileY (default, null) : Int; - - // TEXTURE & PIXEL - public var heightMap : h3d.mat.Texture; - var heightMapPixels : hxd.Pixels; - - public var normalMap(default, null) : h3d.mat.Texture; - var normalMapPixels : hxd.Pixels.Pixels; - var needNormalBake = true; - - public var surfaceIndexMap : h3d.mat.Texture; - public var surfaceWeights : Array = []; - public var surfaceWeightArray (default, null) : h3d.mat.TextureArray; - public var needNewPixelCapture = false; - - // PRIMITIVE - var bigPrim : h3d.prim.BigPrimitive; - public var insideFrustrum(default, null) = false; - - // Set by prefab loader for CPU access ingame - public var packedWeightMapPixel : hxd.Pixels; - public var indexMapPixels : hxd.Pixels; - public var normalTangentBytes : haxe.io.Bytes; - - public function new( x : Int, y : Int, parent : TerrainMesh) { - super(null, null, parent); - terrain = parent; - tileX = x; - tileY = y; - shader = new hrt.shader.Terrain(); - material.mainPass.addShader(shader); - material.mainPass.culling = Back; - material.staticShadows = true; - material.mainPass.setPassName("terrain"); - material.mainPass.stencil = new h3d.mat.Stencil(); - material.mainPass.stencil.setFunc(Always, 0x01, 0xFF, 0xFF); - material.mainPass.stencil.setOp(Keep, Keep, Replace); - this.x = x * terrain.tileSize.x; - this.y = y * terrain.tileSize.y; - name = "tile_" + x + "_" + y; - } - - override function onRemove() { - super.onRemove(); - - inline function disposeTex( t : h3d.mat.Texture ) { if( t != null ) { t.dispose(); t = null; } } - inline function disposePixels( p : hxd.Pixels ) { if( p != null ) { p.dispose(); p = null; } } - - disposeTex(heightMap); - disposeTex(normalMap); - disposeTex(surfaceIndexMap); - disposeTex(surfaceWeightArray); - for( i in 0 ... surfaceWeights.length ) - disposeTex(surfaceWeights[i]); - - disposePixels(packedWeightMapPixel); - disposePixels(indexMapPixels); - disposePixels(heightMapPixels); - - normalTangentBytes = null; - if( bigPrim != null ) bigPrim.dispose(); - } - - public inline function getHeightMapPixels() { - if( (needNewPixelCapture || heightMapPixels == null) && heightMap != null ) - heightMapPixels = heightMap.capturePixels(); - needNewPixelCapture = false; - return heightMapPixels; - } - - public inline function getNormalMapPixels() { - if( normalMapPixels == null && normalMap != null ) - normalMapPixels = normalMap.capturePixels(); - return normalMapPixels; - } - - function bakeNormal() { - if( heightMap == null ) - throw "Can't bake the normalMap of the tile if the heightMap is null."; - var s = new NormalBake(); - s.heightMap = heightMap; - s.heightMapSize.set(heightMap.width, heightMap.height); - h3d.pass.ScreenFx.run(s, normalMap); - needNormalBake = false; - if( normalMapPixels != null ) { - normalMapPixels.dispose(); - normalMapPixels = null; - } - } - - public function createBigPrim() { - - if( normalMapPixels == null || heightMapPixels == null ) - return; - - if( bigPrim != null ) - bigPrim.dispose(); - - bigPrim = new h3d.prim.BigPrimitive(6, true); - - var cellCount = terrain.cellCount; - var cellSize = terrain.cellSize; - inline function addVertice(x : Int, y : Int) { - // Pos - bigPrim.addPoint(x * cellSize.x, y * cellSize.y, getHeight((x * cellSize.x) / terrain.tileSize.x, (y * cellSize.y) / terrain.tileSize.y, true)); // Use addPoint() instead of addVertexValue() for the bounds - // Normal - var n = h3d.Vector.fromColor(normalMapPixels.getPixel(x, y)); - n = n.add(new h3d.Vector(-0.5, -0.5, -0.5)); - n.scale3(2.0); - bigPrim.addVertexValue(n.x); - bigPrim.addVertexValue(n.y); - bigPrim.addVertexValue(n.z); - } - - bigPrim.begin(0,0); - for( y in 0 ... cellCount.y + 1 ) { - for( x in 0 ... cellCount.x + 1 ) { - addVertice(x, y); - } - } - - for( y in 0 ... cellCount.y ) { - for( x in 0 ... cellCount.x ) { - var i = x + y * (cellCount.x + 1); - bigPrim.addIndex(i); - bigPrim.addIndex(i + 1); - bigPrim.addIndex(i + cellCount.x + 2); - bigPrim.addIndex(i); - bigPrim.addIndex(i + cellCount.x + 2); - bigPrim.addIndex(i + cellCount.x + 1); - } - } - bigPrim.flush(); - } - - function refreshNormalMap() { - if( normalMap == null || normalMap.width != terrain.heightMapResolution.x || normalMap.height != terrain.heightMapResolution.y ) { - var oldNormalMap = normalMap; - normalMap = new h3d.mat.Texture(terrain.heightMapResolution.x, terrain.heightMapResolution.y, [Target], RGBA); - normalMap.setName("terrainNormalMap"); - normalMap.wrap = Clamp; - normalMap.filter = Linear; - normalMap.preventAutoDispose(); - normalMap.realloc = function() { - if( normalMapPixels != null ) - normalMap.uploadPixels(normalMapPixels); - else - needNormalBake = true; - } - if( oldNormalMap != null ) - oldNormalMap.dispose(); - - if( normalMapPixels != null && (normalMapPixels.width != normalMap.width || normalMapPixels.height != normalMap.height) ) { - normalMapPixels.dispose(); - normalMapPixels = null; - } - } - } - - function refreshHeightMap() { - if( heightMap == null || heightMap.width != terrain.heightMapResolution.x || heightMap.height != terrain.heightMapResolution.y ) { - var oldHeightMap = heightMap; - heightMap = new h3d.mat.Texture(terrain.heightMapResolution.x, terrain.heightMapResolution.y, [Target], R32F); - heightMap.setName("terrainHeightMap"); - heightMap.wrap = Clamp; - heightMap.filter = Linear; - heightMap.preventAutoDispose(); - needNewPixelCapture = true; - - heightMap.realloc = function() { - if( heightMapPixels != null ) - heightMap.uploadPixels(heightMapPixels); - } - - if( oldHeightMap != null ) { - h3d.pass.Copy.run(oldHeightMap, heightMap); - oldHeightMap.dispose(); - } - - if( heightMapPixels != null && (heightMapPixels.width != heightMap.width || heightMapPixels.height != heightMap.height) ) { - heightMapPixels.dispose(); - heightMapPixels = null; - } - } - } - - function refreshIndexMap() { - if( surfaceIndexMap == null || surfaceIndexMap.width != terrain.weightMapResolution.x || surfaceIndexMap.height != terrain.weightMapResolution.y ) { - var oldSurfaceIndexMap = surfaceIndexMap; - surfaceIndexMap = new h3d.mat.Texture(terrain.weightMapResolution.x, terrain.weightMapResolution.y, [Target], RGBA); - surfaceIndexMap.setName("terrainSurfaceIndexMap"); - surfaceIndexMap.filter = Nearest; - surfaceIndexMap.preventAutoDispose(); - - surfaceIndexMap.realloc = function() { - if( indexMapPixels != null ) - surfaceIndexMap.uploadPixels(indexMapPixels); - } - - if( oldSurfaceIndexMap != null ) { - h3d.pass.Copy.run(oldSurfaceIndexMap, surfaceIndexMap); - oldSurfaceIndexMap.dispose(); - } - } - } - - function refreshSurfaceWeightArray() { - if( terrain.surfaceArray.surfaceCount > 0 && (surfaceWeights.length != terrain.surfaceArray.surfaceCount || surfaceWeights[0].width != terrain.weightMapResolution.x || surfaceWeights[0].height != terrain.weightMapResolution.y) ) { - var oldArray = surfaceWeights; - surfaceWeights = new Array(); - surfaceWeights = [for( i in 0...terrain.surfaceArray.surfaceCount ) null]; - for( i in 0 ... surfaceWeights.length ) { - surfaceWeights[i] = new h3d.mat.Texture(terrain.weightMapResolution.x, terrain.weightMapResolution.y, [Target], R8); - surfaceWeights[i].setName("terrainSurfaceWeight"+i); - surfaceWeights[i].wrap = Clamp; - surfaceWeights[i].preventAutoDispose(); - if( i < oldArray.length && oldArray[i] != null ) - h3d.pass.Copy.run(oldArray[i], surfaceWeights[i]); - } - for( t in oldArray ) - if( t != null) - t.dispose(); - } - } - - function disposeSurfaceWeightArray() { - if( surfaceWeights != null ) { - for( t in surfaceWeights ) - if( t != null ) t.dispose(); - } - } - - public function refreshTex() { - refreshHeightMap(); - refreshNormalMap(); - refreshIndexMap(); - refreshSurfaceWeightArray(); - generateWeightTextureArray(); - } - - public function generateWeightTextureArray() { - if( surfaceWeightArray == null || surfaceWeightArray.width != terrain.weightMapResolution.x || surfaceWeightArray.height != terrain.weightMapResolution.y || surfaceWeightArray.layerCount != terrain.surfaceArray.surfaceCount ) { - if( surfaceWeightArray != null ) surfaceWeightArray.dispose(); - surfaceWeightArray = new h3d.mat.TextureArray(terrain.weightMapResolution.x, terrain.weightMapResolution.y, terrain.surfaceArray.surfaceCount, [Target], R8); - surfaceWeightArray.setName("terrainSurfaceWeightArray"); - surfaceWeightArray.wrap = Clamp; - surfaceWeightArray.preventAutoDispose(); - - // OnContextLost support : Restore the textureArray with the pixels from the packedWeight texture - surfaceWeightArray.realloc = function() { - var engine = h3d.Engine.getCurrent(); - var unpackWeight = new h3d.pass.ScreenFx(new UnpackWeight()); - var tmpPackedWeightTexture = new h3d.mat.Texture(terrain.weightMapResolution.x, terrain.weightMapResolution.y, [Target]); - tmpPackedWeightTexture.uploadPixels(packedWeightMapPixel); - for( i in 0 ... surfaceWeightArray.layerCount ) { - engine.pushTarget(surfaceWeightArray, i); - unpackWeight.shader.indexMap = surfaceIndexMap; - unpackWeight.shader.packedWeightTexture = tmpPackedWeightTexture; - unpackWeight.shader.index = i; - unpackWeight.render(); - engine.popTarget(); - } - } - } - for( i in 0 ... surfaceWeights.length ) - if( surfaceWeights[i] != null ) h3d.pass.Copy.run(surfaceWeights[i], surfaceWeightArray, None, null, i); - } - - public function getHeight( u : Float, v : Float, ?fast = false ) : Float { - var pixels = heightMapPixels; - if( pixels == null ) return 0.0; - if( !fast ) { - inline function getPix(u, v) { - return pixels.getPixelF(Std.int(hxd.Math.clamp(u, 0, pixels.width - 1)), Std.int(hxd.Math.clamp(v, 0, pixels.height - 1))).r; - } - var px = u * (pixels.width - 1) ; - var py = v * (pixels.height - 1) ; - var pxi = hxd.Math.floor(px); - var pyi = hxd.Math.floor(py); - var c00 = getPix(pxi, pyi); - var c10 = getPix(pxi + 1, pyi); - var c01 = getPix(pxi, pyi + 1); - var c11 = getPix(pxi + 1, pyi + 1); - var wx = px - pxi; - var wy = py - pyi; - var a = c00 * (1 - wx) + c10 * wx; - var b = c01 * (1 - wx) + c11 * wx; - return a * (1 - wy) + b * wy; - - } - else{ - var x = hxd.Math.floor(u * (pixels.width - 1)); - var y = hxd.Math.floor(v * (pixels.height - 1)); - return pixels.getPixelF(x, y).r; - } - } - - var cachedBounds : h3d.col.Bounds; - function computeBounds() { - - if( bigPrim == null && heightMapPixels == null ) - return; - - if( cachedBounds == null ) { - if( heightMap != null ) { - cachedBounds = new h3d.col.Bounds(); - cachedBounds.xMax = terrain.tileSize.x; - cachedBounds.xMin = 0.0; - cachedBounds.yMax = terrain.tileSize.y; - cachedBounds.yMin = 0.0; - for( u in 0 ... heightMap.width ) { - for( v in 0 ... heightMap.height ) { - var h = getHeight(u / heightMap.width, v / heightMap.height, true); - if( cachedBounds.zMin > h ) cachedBounds.zMin = h; - if( cachedBounds.zMax < h ) cachedBounds.zMax = h; - } - } - } - else if( bigPrim != null ) { - cachedBounds = bigPrim.getBounds(); - } - } - if( cachedBounds != null ) - cachedBounds.transform(getAbsPos()); - } - - inline public function getCachedBounds() : h3d.col.Bounds { - if( cachedBounds == null ) - computeBounds(); - return cachedBounds; - } - - public dynamic function beforeEmit() : Bool { return true; }; - override function emit( ctx:h3d.scene.RenderContext ) { - if( !isReadyForDraw() ) - return; - insideFrustrum = getCachedBounds() != null ? ctx.camera.frustum.hasBounds(getCachedBounds()) : false; - insideFrustrum = true; - var b = beforeEmit(); - if( b && insideFrustrum ) - super.emit(ctx); - } - - override function sync(ctx:h3d.scene.RenderContext) { - - primitive = bigPrim == null ? terrain.primitive : bigPrim; - - // DEBUG - shader.SHOW_GRID = #if editor terrain.showGrid #else false #end; - shader.CHECKER = #if editor terrain.showChecker #else false #end; - shader.COMPLEXITY = #if editor terrain.showComplexity #else false #end; - - // TILE INFO - shader.VERTEX_DISPLACEMENT = bigPrim == null; - shader.primSize.set(terrain.tileSize.x, terrain.tileSize.y); - shader.cellSize.set(terrain.cellSize.x, terrain.cellSize.y); - shader.tileIndex.set(tileX, tileY); - - // SURFACE - if( terrain.surfaceArray != null ) { - shader.SURFACE_COUNT = terrain.surfaceArray.surfaceCount; - shader.albedoTextures = terrain.surfaceArray.albedo; - shader.normalTextures = terrain.surfaceArray.normal; - shader.pbrTextures = terrain.surfaceArray.pbr; - shader.surfaceParams = terrain.surfaceArray.params; - shader.secondSurfaceParams = terrain.surfaceArray.secondParams; - } - - // BLEND PARAM - shader.PARALLAX = terrain.enableParallax && terrain.parallaxAmount != 0; - shader.parallaxAmount = terrain.parallaxAmount; - shader.minStep = terrain.parallaxMinStep; - shader.maxStep = terrain.parallaxMaxStep; - shader.heightBlendStrength = terrain.heightBlendStrength; - shader.blendSharpness = terrain.blendSharpness; - - // TILE TEXTURE - shader.weightTextures = surfaceWeightArray; - shader.heightMap = heightMap; - shader.normalMap = normalMap; - shader.surfaceIndexMap = surfaceIndexMap; - - - if( bigPrim == null && needNormalBake && isReadyForDraw() ) - bakeNormal(); - - // OnContextLost support : re-create the bigPrim - var needRealloc = false; - if( bigPrim != null ) { - for( b in @:privateAccess bigPrim.buffers ) { - if( b.isDisposed() ) { - needRealloc = true; - break; - } - } - if( needRealloc ) { - createBigPrim(); - cachedBounds = null; - } - } - } - - function isReadyForDraw() { - - if( primitive == null ) - return false; - - if( bigPrim == null && (heightMap == null || heightMap.isDisposed()) ) - return false; - - if( !shader.CHECKER && (shader.weightTextures == null || shader.weightTextures.isDisposed()) ) - return false; - - if( !shader.CHECKER && !shader.COMPLEXITY ) { - if( shader.albedoTextures == null || shader.albedoTextures.isDisposed() ) return false; - if( shader.normalTextures == null || shader.normalTextures.isDisposed() ) return false; - if( shader.pbrTextures == null || shader.pbrTextures.isDisposed() ) return false; - if( shader.surfaceIndexMap == null || shader.surfaceIndexMap.isDisposed() ) return false; - } - - return true; - } -} diff --git a/hrt/prefab/terrain/UnpackWeight.hx b/hrt/prefab/terrain/UnpackWeight.hx deleted file mode 100644 index 25ca6c4a4..000000000 --- a/hrt/prefab/terrain/UnpackWeight.hx +++ /dev/null @@ -1,22 +0,0 @@ -package hrt.prefab.terrain; - -class UnpackWeight extends h3d.shader.ScreenShader { - - static var SRC = { - - @param var indexMap : Sampler2D; - @param var packedWeightTexture : Sampler2D; - @param var index : Int; - - function fragment() { - pixelColor = vec4(0,0,0,1); - var texIndex = indexMap.get(calculatedUV).rgb; - var i1 : Int = int(texIndex.r * 255); - var i2 : Int = int(texIndex.g * 255); - var i3 : Int = int(texIndex.b * 255); - if(i1 == index) pixelColor = vec4(vec3(packedWeightTexture.get(calculatedUV).r), 1.0); - else if(i2 == index) pixelColor = vec4(vec3(packedWeightTexture.get(calculatedUV).g), 1.0); - else if(i3 == index) pixelColor = vec4(vec3(packedWeightTexture.get(calculatedUV).b), 1.0); - } - } -} diff --git a/hrt/prefab/vlm/LightProbe.hx b/hrt/prefab/vlm/LightProbe.hx deleted file mode 100644 index c86c94fcb..000000000 --- a/hrt/prefab/vlm/LightProbe.hx +++ /dev/null @@ -1,733 +0,0 @@ -package hrt.prefab.vlm; - -import hrt.prefab.l3d.Level3D; -import h3d.scene.pbr.Environment; - -enum abstract ProbeMode(String) { - var Texture; - var Capture; -} - -enum abstract ProbeFadeMode(String) { - var Linear; - var Smoothstep; - var Pow2; -} - -class DebugView extends hxsl.Shader { - - static var SRC = { - - var pixelColor : Vec4; - @param var source : SamplerCube; - @param var irrRotation : Vec2; - @param var power : Float; - var transformedNormal : Vec3; - - function fragment() { - var n = vec3(transformedNormal.x * irrRotation.x - transformedNormal.y * irrRotation.y, transformedNormal.x * irrRotation.y + transformedNormal.y * irrRotation.x, transformedNormal.z); - var color = source.getLod(n, 0).rgb * power; - pixelColor = vec4(color, 1); - } - - } -} - -class BoundsFade extends hxsl.Shader { - - static var SRC = { - - @const var SMOOTHSTEP : Bool; - @const var POWER2 : Bool; - - @param var scale : Vec3; - @param var fadeDist : Float; - - var pixelRelativePosition : Vec3; - var pixelColor : Vec4; - - function fragment() { - var normalizedPos = abs(pixelRelativePosition) * 2.0; - var maxDist = min(min(scale.x - normalizedPos.x * scale.x, scale.y - normalizedPos.y * scale.y), scale.z - normalizedPos.z * scale.z); - var fadeAmount = saturate(maxDist / fadeDist); - if( SMOOTHSTEP ) - fadeAmount = smoothstep(0.0, 1.0, fadeAmount); - else if( POWER2 ) - fadeAmount = fadeAmount * fadeAmount; - pixelColor.a *= fadeAmount; - } - }; - -} - -class BoundsClipping extends hxsl.Shader { - - static var SRC = { - - @global var global : { - @perObject var modelViewInverse : Mat4; - }; - - var transformedPosition : Vec3; - var pixelRelativePosition : Vec3; - - function fragment() { - pixelRelativePosition = (transformedPosition * global.modelViewInverse.mat3x4()).xyz; - if( abs(pixelRelativePosition.x) > 0.5 || abs(pixelRelativePosition.y) > 0.5 || abs(pixelRelativePosition.z) > 0.5 ) - discard; - } - }; - -} - -class LightProbeObject extends h3d.scene.Mesh { - - public var env : Environment; - public var indirectShader : h3d.shader.pbr.Lighting.Indirect; - public var boundClippingShader : BoundsClipping; - public var boundFadeShader : BoundsFade; - public var fadeDist : Float; - public var fadeMode : ProbeFadeMode; - public var priority : Int; - - public function new(?parent) { - var probeMaterial = h3d.mat.MaterialSetup.current.createMaterial(); - super(h3d.prim.Cube.defaultUnitCube(), probeMaterial, parent); - material.castShadows = false; - material.mainPass.setPassName("lightProbe"); - boundClippingShader = new BoundsClipping(); - material.mainPass.addShader(boundClippingShader); - indirectShader = new h3d.shader.pbr.Lighting.Indirect(); - indirectShader.drawIndirectDiffuse = true; - indirectShader.drawIndirectSpecular = true; - indirectShader.showSky = false; - indirectShader.gammaCorrect = false; - material.mainPass.addShader(indirectShader); - material.mainPass.setBlendMode(Alpha); - material.mainPass.depthTest = GreaterEqual; - material.mainPass.culling = Front; - material.mainPass.depthWrite = false; - - boundFadeShader = new BoundsFade(); - material.mainPass.addShader(boundFadeShader); - } - - public function clear() { - if( env.env != null ) - env.env.clear(0); - if( env.diffuse != null ) - env.diffuse.clear(0); - if( env.specular != null ) { - env.specular.dispose(); - env.specular.alloc(); - } - } - - override function emit( ctx : h3d.scene.RenderContext ) { - - if( env == null || env.diffuse == null || env.specular == null ) - return; - - indirectShader.cameraPosition = ctx.camera.pos; - indirectShader.irrLut = env.lut; - indirectShader.irrDiffuse = env.diffuse; - indirectShader.irrSpecular = env.specular; - indirectShader.irrSpecularLevels = env.specLevels; - indirectShader.irrPower = env.power * env.power; - indirectShader.irrRotation.set(Math.cos(env.rotation), Math.sin(env.rotation)); - - super.emit(ctx); - } - - override function sync( ctx : h3d.scene.RenderContext ) { - super.sync(ctx); - - var r : h3d.scene.pbr.Renderer = cast ctx.scene.renderer; - if( r != null ) { - if( material.mainPass.getShader(h3d.shader.pbr.PropsImport) == null ) - @:privateAccess material.mainPass.addShader(r.pbrProps); - var props : h3d.scene.pbr.Renderer.RenderProps = r.props; - indirectShader.emissivePower = props.emissive; - } - - getAbsPos().getScale(boundFadeShader.scale); - getAbsPos()._44 = priority; - boundFadeShader.fadeDist = fadeDist; - switch fadeMode { - case Linear: - boundFadeShader.POWER2 = false; - boundFadeShader.SMOOTHSTEP = false; - case Smoothstep: - boundFadeShader.POWER2 = false; - boundFadeShader.SMOOTHSTEP = true; - case Pow2: - boundFadeShader.POWER2 = true; - boundFadeShader.SMOOTHSTEP = false; - } - } - -} - -@:access(h3d.scene.pbr.Environment) -class LightProbe extends Object3D { - - // Probe - @:s public var mode : ProbeMode = Texture; - @:s public var priority : Int = 0; - - // Fade - @:s public var fadeDist : Float = 0.0; - @:s public var fadeMode : ProbeFadeMode = Linear; - - // Texture Mode - @:s public var texturePath : String = null; - @:s public var hdrMax : Float = 10.0; - @:s public var rotation : Float = 0.0; - - // Capture Mode - @:s public var bounce : Int = 1; - - // Shared - @:s public var power : Float = 1.0; - @:s public var sampleBits : Int = 12; - @:s public var diffSize : Int = 16; - @:s public var specSize : Int = 64; - @:s public var ignoredSpecLevels : Int = 2; - - // Debug - @:s public var debugDisplay : Bool = true; - @:s public var sphereRadius : Float = 0.5; - - public function new( ?parent : Prefab ) { - super(parent); - type = "lightProbe"; - - // Duplicate Name Fix - Prevent baked data conflict - var root : Prefab = this; - while( root.parent != null ) { - root = root.parent; - } - var probeList : Array = cast root.findAll( p -> Std.is(p, LightProbe) ? p : null ); - var curIndex = 0; - var needCheck = true; - while( needCheck ) { - needCheck = false; - for( p in probeList ) { - if( p.name != null && p.name.indexOf("_" + curIndex) != -1 ) { - curIndex++; - needCheck = true; - continue; - } - } - } - name = "lightProbe_" + curIndex; - } - - override function makeInstance( ctx : Context ) : Context { - ctx = ctx.clone(this); - var lpo = new LightProbeObject(ctx.local3d); - lpo.material.castShadows = false; - lpo.material.mainPass.setPassName("lightProbe"); - lpo.ignoreCollide = true; - ctx.local3d = lpo; - ctx.local3d.name = name; - - #if editor - var wire = new h3d.scene.Box(lpo); - wire.thickness = 2.0; - wire.material.mainPass.setPassName("overlay"); - wire.name = "wire_select"; - wire.color = 0xFFFFFF; - wire.ignoreCollide = true; - wire.material.shadows = false; - wire.visible = false; - wire.material.mainPass.depthTest = Always; - - var previewSphereDiffuse = new h3d.scene.Mesh(h3d.prim.Sphere.defaultUnitSphere(), lpo); - previewSphereDiffuse.name = "preview_sphere_diffuse"; - previewSphereDiffuse.material.mainPass.setPassName("overlay"); - previewSphereDiffuse.material.mainPass.addShader(new DebugView()); - previewSphereDiffuse.material.castShadows = false; - - var previewSphereSpecular = new h3d.scene.Mesh(h3d.prim.Sphere.defaultUnitSphere(), lpo); - previewSphereSpecular.name = "preview_sphere_specular"; - previewSphereSpecular.material.mainPass.setPassName("overlay"); - previewSphereSpecular.material.mainPass.addShader(new DebugView()); - previewSphereSpecular.material.castShadows = false; - #end - - updateInstance(ctx, texturePath == null ? null : "texturePath"); - return ctx; - } - - override function updateInstance( ctx : Context, ?propName : String ) { - super.updateInstance(ctx, propName); - var lpo : LightProbeObject = cast ctx.local3d; - lpo.fadeDist = fadeDist; - lpo.fadeMode = fadeMode; - lpo.priority = priority; - - // Full Reset - if( propName == "mode" ) { - if( lpo.env != null ) { - lpo.env.dispose(); - lpo.env = null; - } - } - - switch mode { - case Texture: - var needCompute = false; - if( propName == "texturePath" || propName == "mode" ) { - var t = texturePath == null ? null : ctx.loadTexture(texturePath); - if( t != null ) { - lpo.env = new Environment(t); - needCompute = true; - } - } - if( lpo.env != null ) { - lpo.env.power = power; - lpo.env.hdrMax = hdrMax; - lpo.env.rotation = hxd.Math.degToRad(rotation); - lpo.env.sampleBits = sampleBits; - lpo.env.ignoredSpecLevels = ignoredSpecLevels; - if( lpo.env.specSize != specSize ) { - if( lpo.env.specular != null ) lpo.env.specular.dispose(); - lpo.env.specular = null; - needCompute = true; - } - lpo.env.specSize = specSize; - if( lpo.env.diffSize != diffSize ) { - if( lpo.env.diffuse != null ) lpo.env.diffuse.dispose(); - lpo.env.diffuse = null; - needCompute = true; - } - lpo.env.diffSize = diffSize; - - if( propName == "hdrMax" || propName == "sampleBits" ) - needCompute = true; - - if( needCompute ) { - if( lpo.env.source.flags.has(Loading) ) - lpo.env.source.waitLoad(lpo.env.compute); - else - lpo.env.compute(); - } - } - - case Capture: - - var needCompute = false; - - if( lpo.env == null ) - lpo.env = new Environment(null); - - lpo.env.power = power; - lpo.env.sampleBits = sampleBits; - lpo.env.ignoredSpecLevels = ignoredSpecLevels; - - if( propName == "sampleBits" || propName == "ignoredSpecLevels" ) - needCompute = true; - - if( loadBinary(lpo.env, ctx) ) - needCompute = false; // No Env available with binary load, everything else is already baked - - if( needCompute ) - lpo.env.compute(); - } - - updatePreviewSphere(lpo); - } - - function updatePreviewSphere( o : h3d.scene.Object ) { - #if editor - var lpo : LightProbeObject = cast o; - var previewSphereDiffuse : h3d.scene.Mesh = Std.downcast(lpo.find( o -> o.name == "preview_sphere_diffuse" ? o : null), h3d.scene.Mesh); - var previewSphereSpecular : h3d.scene.Mesh = Std.downcast(lpo.find( o -> o.name == "preview_sphere_specular" ? o : null), h3d.scene.Mesh); - var parentScale = lpo.getAbsPos().getScale(); - - // Don't use scale from parent for preview phere - function updateScale( m : h3d.scene.Mesh ) { - m.scaleX = sphereRadius / parentScale.x; - m.scaleY = sphereRadius / parentScale.y; - m.scaleZ = sphereRadius / parentScale.z; - } - - if( previewSphereDiffuse != null ) { - previewSphereDiffuse.visible = debugDisplay; - previewSphereDiffuse.x = (sphereRadius + (sphereRadius * 0.5)) / parentScale.x; - var s = previewSphereDiffuse.material.mainPass.getShader(DebugView); - if( lpo.env != null ) { - if( lpo.env.source != null && lpo.env.source.flags.has(Loading) ) - lpo.env.source.waitLoad( () -> s.source = lpo.env.diffuse ); - else - s.source = lpo.env.diffuse; - s.irrRotation.set(Math.cos(lpo.env.rotation), Math.sin(lpo.env.rotation)); - s.power = lpo.env.power * lpo.env.power; - } - - updateScale(previewSphereDiffuse); - } - if( previewSphereSpecular != null ) { - previewSphereSpecular.visible = debugDisplay; - previewSphereSpecular.x = -(sphereRadius + (sphereRadius * 0.5)) / parentScale.x; - var s = previewSphereSpecular.material.mainPass.getShader(DebugView); - if( lpo.env != null ) { - if( lpo.env.source != null && lpo.env.source.flags.has(Loading) ) - lpo.env.source.waitLoad( () -> s.source = lpo.env.specular ); - else - s.source = lpo.env.specular; - s.irrRotation.set(Math.cos(lpo.env.rotation), Math.sin(lpo.env.rotation)); - s.power = lpo.env.power * lpo.env.power; - } - - updateScale(previewSphereSpecular); - } - #end - } - - override function applyTransform( o : h3d.scene.Object ) { - super.applyTransform(o); - updatePreviewSphere(o); - } - - function saveBinary( env : Environment, ctx : Context ) { - - var diffuse = hxd.Pixels.toDDSLayers([for( i in 0...6 ) env.diffuse.capturePixels(i)], true); - var specular = hxd.Pixels.toDDSLayers([for( i in 0...6 ) for( mip in 0...env.getMipLevels() ) env.specular.capturePixels(i,mip)],true); - - var totalBytes = 4 + 4; //ignoredSpecLevels + sampleBits - var data = haxe.io.Bytes.alloc(totalBytes); - var curPos = 0; - data.setInt32(curPos, env.sampleBits); curPos += 4; - data.setInt32(curPos, env.ignoredSpecLevels); curPos += 4; - - ctx.shared.savePrefabDat("envd", "dds", name, diffuse); - ctx.shared.savePrefabDat("envs", "dds", name, specular); - ctx.shared.savePrefabDat("data", "bake", name, data); - } - - function loadBinary( env : Environment, ctx : Context ) { - - var diffuse = ctx.shared.loadPrefabDat("envd", "dds", name); - var specular = ctx.shared.loadPrefabDat("envs", "dds", name); - var data = ctx.shared.loadPrefabDat("data", "bake", name); - - if( data == null || specular == null || diffuse == null ) - return false; - - env.diffuse = diffuse.toImage().toTexture(); - env.diffSize = env.diffuse.width; - env.specular = specular.toImage().toTexture(); - env.specular.mipMap = Linear; - env.specSize = env.specular.width; - env.specLevels = @:privateAccess env.getMipLevels() - env.ignoredSpecLevels; - - var curPos = 0; - var bytes = data.entry.getBytes(); - env.sampleBits = bytes.getInt32(curPos); curPos += 4; - env.ignoredSpecLevels = bytes.getInt32(curPos); curPos += 4; - - return true; - } - - #if editor - - function exportData( env : Environment ) : haxe.io.Bytes { - - var diffusePixels : Array = [ for( i in 0 ... 6) env.diffuse.capturePixels(i) ]; - var mipLevels = env.getMipLevels(); - var specularPixels : Array = - [ - for( i in 0 ... 6 ) { - for( m in 0 ... mipLevels ) { - env.specular.capturePixels(i, m); - } - } - ]; - - var totalBytes = 0; - totalBytes += 4 + 4 + 4 + 4; // diffSize + specSize + ignoredSpecLevels + sampleBits - for( p in diffusePixels ) - totalBytes += p.bytes.length; - for( p in specularPixels ) - totalBytes += p.bytes.length; - - var bytes = haxe.io.Bytes.alloc(totalBytes); - - var curPos = 0; - bytes.setInt32(curPos, env.sampleBits); curPos += 4; - bytes.setInt32(curPos, env.diffSize); curPos += 4; - bytes.setInt32(curPos, env.specSize); curPos += 4; - bytes.setInt32(curPos, env.ignoredSpecLevels); curPos += 4; - - for( p in diffusePixels ) { - bytes.blit(curPos, p.bytes, 0, p.bytes.length); - curPos += p.bytes.length; - } - - for( p in specularPixels ) { - bytes.blit(curPos, p.bytes, 0, p.bytes.length); - curPos += p.bytes.length; - } - - return bytes; - } - - function importData( env : Environment, bytes : haxe.io.Bytes ) { - - var curPos = 0; - env.sampleBits = bytes.getInt32(curPos); curPos += 4; - env.diffSize = bytes.getInt32(curPos); curPos += 4; - env.specSize = bytes.getInt32(curPos); curPos += 4; - env.ignoredSpecLevels = bytes.getInt32(curPos); curPos += 4; - env.createTextures(); - - var diffSize = hxd.Pixels.calcStride(env.diffuse.width, env.diffuse.format) * env.diffuse.height; - for( i in 0 ... 6 ) { - var diffByte = bytes.sub(curPos, diffSize); - curPos += diffByte.length; - var diffPixels = new hxd.Pixels(env.diffuse.width, env.diffuse.height, diffByte, env.diffuse.format); - env.diffuse.uploadPixels(diffPixels, 0, i); - } - - var mipLevels = env.getMipLevels(); - env.specLevels = mipLevels - ignoredSpecLevels; - for( i in 0 ... 6 ) { - for( m in 0 ... mipLevels ) { - var mipMapSize = hxd.Pixels.calcStride(env.specular.width >> m, env.specular.format) * env.specular.height >> m; - var specByte = bytes.sub(curPos, mipMapSize); - curPos += specByte.length; - var specPixels = new hxd.Pixels(env.specular.width >> m, env.specular.height >> m, specByte, env.specular.format); - env.specular.uploadPixels(specPixels, m, i); - } - } - } - - override function getHideProps() : HideProps { - return { icon : "map-o", name : "LightProbe" }; - } - - override function setSelected( ctx : Context, b : Bool ) { - var w = ctx.local3d.find( o -> o.name == "wire_select" ? o : null); - if( w != null ) - w.visible = b; - return true; - } - - override function edit( ctx : EditContext ) { - super.edit(ctx); - - var captureModeParams = - '
-
Power
-
Bounce
-
-
- -
-
- -
-
-
- -
-
- -
-
-
-
-
-
Diffuse
-
Specular
-
Sample Count
-
Ignored Spec Levels
-
-
'; - - var textureModeParams = - '
-
-
Texture
-
Rotation
-
Power
-
-
-
-
-
Diffuse
-
Specular
-
Sample Count
-
Ignored Spec Levels
-
-
-
-
-
Threshold
-
Scale
-
-
'; - - var props = new hide.Element(' -
-
-
Mode
-
- -
-
Priority
-
-
- ' + (mode == Texture ? textureModeParams : captureModeParams) + ' -
-
-
Mode
-
- -
-
Distance
-
-
-
-
-
Debug Display
-
Sphere Radius
-
-
- '); - ctx.properties.add(props, this, function(pname) { - ctx.onChange(this, pname); - if( pname == "mode" ) - ctx.rebuildProperties(); - }); - - var clearButton = props.find(".clear"); - if( clearButton != null ) { - clearButton.click(function(_) { - var lpo : LightProbeObject = cast ctx.getContext(this).local3d; - lpo.env.createTextures(); - lpo.clear(); - ctx.properties.undo.change(Custom(function(undo) { - // TO DO - })); - }); - } - - var exportButton = props.find(".export"); - if( exportButton != null ) { - exportButton.click(function(_) { - - var lpo : LightProbeObject = cast ctx.getContext(this).local3d; - if( lpo.env == null || lpo.env.specular == null || lpo.env.diffuse == null ) { - hide.Ide.inst.message("Capture is empty."); - return; - } - - var data = exportData(lpo.env); - function saveData( name : String ) { - var path = ctx.ide.getPath(name)+"/"+this.name+"_export.bake"; - sys.io.File.saveBytes(path, data); - } - ctx.ide.chooseDirectory(saveData); - - }); - } - - var importButton = props.find(".import"); - if( importButton != null ) { - importButton.click(function(_) { - - var lpo : LightProbeObject = cast ctx.getContext(this).local3d; - - function loadData( name : String ) { - - if( name == "null" ) - return; - - var b = hxd.res.Loader.currentInstance.load(name).entry.getBytes(); - - if( lpo.env != null ) - lpo.env.dispose(); - - lpo.env = new Environment(null); - importData(lpo.env, b); - - // Upate the prefab - sampleBits = lpo.env.sampleBits; - diffSize = lpo.env.diffSize; - specSize = lpo.env.specSize; - ignoredSpecLevels = lpo.env.ignoredSpecLevels; - - // Save the import - ctx.rootContext.shared.savePrefabDat("probe", "bake", this.name, b); - - ctx.onChange(this, null); - ctx.rebuildProperties(); - } - - ctx.ide.chooseFile(["bake"], loadData); - - ctx.properties.undo.change(Custom(function(undo) { - // TO DO - })); - - }); - } - - var bakeButton = props.find(".bake"); - if( bakeButton != null ) { - bakeButton.click(function(_) { - - var lpo : LightProbeObject = cast ctx.getContext(this).local3d; - var captureSize = specSize; - - // Start with a black texture, need to override the default env - lpo.env.createTextures(); - lpo.clear(); - - if( lpo.env.env == null || lpo.env.env.width != captureSize ) { - if( lpo.env.env != null ) - lpo.env.env.dispose(); - lpo.env.env = new h3d.mat.Texture(captureSize, captureSize, [Cube, Target], RGBA32F); - } - - var probeBaker = new ProbeBaker(); - if( bounce > 1 ) { - var tmpTexture = new h3d.mat.Texture(captureSize, captureSize, [Cube, Target], RGBA32F); - var curCapture : h3d.mat.Texture = tmpTexture; - for( b in 0 ... bounce ) { - probeBaker.captureEnvironment(lpo.getAbsPos().getPosition(), captureSize, ctx.scene.s3d, curCapture); - var tmp = lpo.env.env; - lpo.env.env = curCapture; - lpo.env.compute(); - curCapture = tmp; - } - curCapture.dispose(); - } - else { - probeBaker.captureEnvironment(lpo.getAbsPos().getPosition(), captureSize, ctx.scene.s3d, lpo.env.env); - lpo.env.compute(); - } - - probeBaker.dispose(); - - saveBinary(lpo.env, ctx.rootContext); - - ctx.onChange(this, null); - }); - } - } - - #end - - static var _ = Library.register("lightProbe", LightProbe); -} \ No newline at end of file diff --git a/hrt/prefab/vlm/ProbeBaker.hx b/hrt/prefab/vlm/ProbeBaker.hx deleted file mode 100644 index d65c29276..000000000 --- a/hrt/prefab/vlm/ProbeBaker.hx +++ /dev/null @@ -1,310 +0,0 @@ -package hrt.prefab.vlm; - -import hrt.prefab.vlm.LightProbe.LightProbeObject; - -class ProbeBaker { - - public var useGPU = false; - - // Tmp cube texture for rendring environment - var envMap : h3d.mat.Texture; - - // Params for CubeMap rendering - var customCamera : h3d.Camera; - var cubeDir = [ h3d.Matrix.L([0,0,-1,0, 0,1,0,0, -1,-1,1,0]), - h3d.Matrix.L([0,0,1,0, 0,1,0,0, 1,-1,-1,0]), - h3d.Matrix.L([-1,0,0,0, 0,0,1,0, 1,-1,-1,0]), - h3d.Matrix.L([-1,0,0,0, 0,0,-1,0, 1,1,1,0]), - h3d.Matrix.L([-1,0,0,0, 0,1,0,0, 1,-1,1,0]), - h3d.Matrix.L([1,0,0,0, 0,1,0,0, -1,-1,-1,0]) ]; - - // Output for SH computation on GPU - var computeSH : h3d.pass.ScreenFx; - var output0 : h3d.mat.Texture; - var output1 : h3d.mat.Texture; - var output2 : h3d.mat.Texture; - var output3 : h3d.mat.Texture; - var output4 : h3d.mat.Texture; - var output5 : h3d.mat.Texture; - var output6 : h3d.mat.Texture; - var output7 : h3d.mat.Texture; - var textureArray: Array; - - // Tmp Buffer - var pixels : hxd.Pixels = null; - var prim : h3d.prim.Plane2D; - - public function new(){ - customCamera = new h3d.Camera(); - customCamera.screenRatio = 1.0; - customCamera.fovY = 90; - customCamera.zNear = 0.01; - customCamera.zFar = 4000; - } - - public function dispose() { - if( envMap != null ) { - envMap.dispose(); - envMap = null; - } - if(output0 != null) output0.dispose(); - if(output1 != null) output1.dispose(); - if(output2 != null) output2.dispose(); - if(output3 != null) output3.dispose(); - if(output4 != null) output4.dispose(); - if(output5 != null) output5.dispose(); - if(output6 != null) output6.dispose(); - if(output7 != null) output7.dispose(); - if(prim != null) prim.dispose(); - } - - public function captureEnvironment( position : h3d.Vector, resolution : Int, scene : h3d.scene.Scene, output : h3d.mat.Texture ) { - var pbrRenderer = Std.downcast(scene.renderer, h3d.scene.pbr.Renderer); - - var prevCam = scene.camera; - var prevRenderMode = pbrRenderer.renderMode; - pbrRenderer.renderMode = LightProbe; - scene.camera = customCamera; - - // Bake a Probe - var engine = h3d.Engine.getCurrent(); - for( f in 0 ... 6 ) { - engine.begin(); - customCamera.setCubeMap(f, position); - customCamera.update(); - scene.camera = customCamera; - engine.pushTarget(output, f); - engine.clear(0,1,0); - scene.render(engine); - engine.popTarget(); - } - - scene.camera = prevCam; - pbrRenderer.renderMode = prevRenderMode; - } - - function setupEnvMap( resolution : Int ) { - if( envMap == null || resolution != envMap.width || resolution != envMap.height ) { - if( envMap != null ) envMap.dispose(); - envMap = new h3d.mat.Texture(resolution, resolution, [Cube, Target], RGBA32F); - } - } - - function setupShaderOutput( order : Int, probeCount: Int ) { - - if( order > 3 || order <= 0 ){ throw "Not Supported"; return; } - - if( !useGPU ) - probeCount = 1; - - if( order >= 1 && (output0 == null || output0.width != probeCount)){ - if(output0 != null) output0.dispose(); - output0 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F); - } - if( order >= 2 && (output1 == null || output1.width != probeCount)){ - if(output1 != null) output1.dispose(); - if(output2 != null) output2.dispose(); - if(output3 != null) output3.dispose(); - output1 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F); - output2 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F); - output3 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F); - } - if( order >= 3 && (output4 == null || output4.width != probeCount)){ - if(output4 != null) output4.dispose(); - if(output5 != null) output5.dispose(); - if(output6 != null) output6.dispose(); - if(output7 != null) output7.dispose(); - output4 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F); - output5 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F); - output6 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F); - output7 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F); - } - - switch(order){ - case 1: - textureArray = [output0]; - computeSH = new h3d.pass.ScreenFx(new hrt.shader.ComputeSH(),[ - Vec4([Value("out.coefL00", 3), Const(0)])]); - case 2: - textureArray = [output0, output1, output2, output3]; - computeSH = new h3d.pass.ScreenFx(new hrt.shader.ComputeSH(),[ - Vec4([Value("out.coefL00", 3), Const(0)]), - Vec4([Value("out.coefL1n1", 3), Const(0)]), - Vec4([Value("out.coefL10", 3), Const(0)]), - Vec4([Value("out.coefL11", 3), Const(0)])]); - - case 3: - function getSwiz(name,comp) : hxsl.Output { return Swiz(Value(name,3),[comp]); } - textureArray = [output0, output1, output2, output3, output4, output5, output6, output7]; - computeSH = new h3d.pass.ScreenFx(new hrt.shader.ComputeSH(),[ - Vec4([Value("out.coefL00", 3), getSwiz("out.coefL22",X) ]), - Vec4([Value("out.coefL1n1", 3), getSwiz("out.coefL22",Y) ]), - Vec4([Value("out.coefL10", 3), getSwiz("out.coefL22",Z) ]), - Vec4([Value("out.coefL11", 3), Const(0)]), - Vec4([Value("out.coefL2n2", 3), Const(0)]), - Vec4([Value("out.coefL2n1", 3), Const(0)]), - Vec4([Value("out.coefL20", 3), Const(0)]), - Vec4([Value("out.coefL21", 3), Const(0)])]); - } - } - - function drawSHIntoTexture(renderer : h3d.scene.Renderer, env : h3d.mat.Texture, order : Int, probeIndex: Int) { - if( prim == null ){ - prim = new h3d.prim.Plane2D(); - } - - function setPrimPos( index : Int ){ - var v = new hxd.FloatBuffer(); - var pixelSize = (1.0 / output0.width); - var translation = pixelSize * index * 2; - var posX = -1.0 + translation; - v.push( posX ) ; v.push( -1 ); v.push(0); v.push(0); - v.push( posX ); v.push( 1 ); v.push(0); v.push(0); - v.push( posX + pixelSize * 2 ); v.push( -1 ); v.push(0); v.push(0); - v.push( posX + pixelSize * 2 ); v.push( 1 ); v.push(0); v.push(0); - prim.buffer = h3d.Buffer.ofFloats(v, 4, [Quads, RawFormat]); - } - setPrimPos(probeIndex); - - @:privateAccess renderer.ctx.engine = h3d.Engine.getCurrent(); - @:privateAccess renderer.setTargets(textureArray); - computeSH.shader.ORDER = order; - computeSH.shader.width = env.width; - computeSH.shader.environment = env; - computeSH.shader.cubeDir = cubeDir; - computeSH.primitive = prim; - computeSH.render(); - @:privateAccess renderer.resetTarget(); - @:privateAccess renderer.ctx.engine.flushTarget(); - } - - function convertOuputTexturesIntoSH( volumetricLightMap : hrt.prefab.vlm.VolumetricMesh, pixelsOut : hxd.Pixels ) { - - var order = volumetricLightMap.shOrder; - var sh = new hrt.prefab.vlm.SphericalHarmonic(order); - var coefCount = order * order; - var maxCoef : Int = Std.int(Math.min(8, coefCount)); - - for(coef in 0 ... maxCoef){ - var pixels = textureArray[coef].capturePixels(); - for( index in 0 ... pixels.width){ - var coefs : h3d.Vector = pixels.getPixelF(index, 0); - var coords = volumetricLightMap.getProbeCoords(index); - var u = coords.x + volumetricLightMap.probeCount.x * coef; - var v = coords.y + coords.z * volumetricLightMap.probeCount.y; - pixelsOut.setPixelF(u, v, new h3d.Vector(coefs.r, coefs.g, coefs.b, 0)); - - // Last coefs is inside the alpha channel - if( order == 3 ){ - var u = coords.x + volumetricLightMap.probeCount.x * 8; - var v = coords.y + coords.z * volumetricLightMap.probeCount.y; - var prev = pixelsOut.getPixelF(u, v); - if( coef == 0 ){ prev.r = coefs.a; } - if( coef == 1 ){ prev.g = coefs.a; } - if( coef == 2 ){ prev.b = coefs.a; } - pixelsOut.setPixelF(u, v, prev); - } - } - } - } - - function convertEnvIntoSH_CPU( env : h3d.mat.Texture, order : Int ) : hrt.prefab.vlm.SphericalHarmonic { - var coefCount = order * order; - var sphericalHarmonic = new hrt.prefab.vlm.SphericalHarmonic(order); - var face : hxd.Pixels; - var weightSum = 0.0; - var invWidth = 1.0 / env.width; - var shData : Array = [for ( value in 0...coefCount ) 0]; - - for( f in 0...6 ) { - face = env.capturePixels(f, 0); - for (u in 0...face.width) { - var fU : Float = (u / face.width ) * 2 - 1;// Texture coordinate U in range [-1 to 1] - fU *= fU; - var uCoord = 2.0 * u * invWidth + invWidth; - for (v in 0...face.width) { - var fV : Float = (v / face.height ) * 2 - 1;// Texture coordinate V in range [-1 to 1] - fV *= fV; - var vCoord = 2.0 * v * invWidth + invWidth; - var dir = getDir(uCoord, vCoord, f);// Get direction from center of cube texture to current texel - var diffSolid = 4.0 / ((1.0 + fU + fV) * Math.sqrt(1.0 + fU + fV)); // Scale factor depending on distance from center of the face - weightSum += diffSolid; - var color = face.getPixelF(u,v);// Get color from the current face - evalSH(order, dir, shData);// Calculate coefficients of spherical harmonics for current direction - for(i in 0...coefCount){ - sphericalHarmonic.coefR[i] += shData[i] * color.r * diffSolid; - sphericalHarmonic.coefG[i] += shData[i] * color.g * diffSolid; - sphericalHarmonic.coefB[i] += shData[i] * color.b * diffSolid; - } - } - } - } - // Final scale for coefficients - var normProj = (4.0 * Math.PI) / weightSum; - for( i in 0...coefCount ){ - sphericalHarmonic.coefR[i] *= normProj; - sphericalHarmonic.coefG[i] *= normProj; - sphericalHarmonic.coefB[i] *= normProj; - } - return sphericalHarmonic; - } - - inline function evalSH( order : Int, dir : h3d.Vector, shData : Array ) { - for (l in 0...order) { - for (m in -l...l+1) { - shData[getIndex(l, m)] = evalCoef(l, m, dir); - } - } - } - - inline function getIndex( l : Int, m :Int ) : Int { - return l * (l + 1) + m; - } - - inline function getDir( u : Float, v : Float, face : Int ) : h3d.Vector { - var dir = new h3d.Vector(); - switch( face ) { - case 0: dir.x = -1.0; dir.y = -1.0 + v; dir.z = 1.0 - u; - case 1: dir.x = 1.0; dir.y = -1.0 + v; dir.z = -1.0 + u; - case 2: dir.x = 1.0 - u; dir.y = -1.0; dir.z = -1.0 + v; - case 3: dir.x = 1.0 - u; dir.y = 1.0; dir.z = 1.0 - v; - case 4: dir.x = 1.0 - u; dir.y = -1.0 + v; dir.z = 1.0; - case 5: dir.x = -1.0 + u; dir.y = -1.0 + v; dir.z = -1.0; - default: - } - dir.normalizeFast(); - return dir; - } - - inline function evalCoef( l : Int, m : Int, dir : h3d.Vector ) : Float { - // Coef from Stupid Spherical Harmonics (SH) Peter-Pike Sloan Microsoft Corporation - return switch [l,m] { - case[0,0]: 0.282095; // 0.5 * sqrt(1/pi) - case[1,-1]: -0.488603 * dir.y; // -sqrt(3/(4pi)) * y - case[1,0]: 0.488603 * dir.z; // sqrt(3/(4pi)) * z - case[1,1]: -0.488603 * dir.x; // -sqrt(3/(4pi)) * x - case[2,-2]: 1.092548 * dir.y * dir.x;// 0.5 * sqrt(15/pi) * y * x - case[2,-1]: -1.092548 * dir.y * dir.z; // -0.5 * sqrt(15/pi) * y * z - case[2,0]: 0.315392 * (-dir.x * dir.x - dir.y * dir.y + 2.0 * dir.z * dir.z);// 0.25 * sqrt(5/pi) * (-x^2-y^2+2z^2) - case[2,1]: -1.092548 * dir.x * dir.z; // -0.5 * sqrt(15/pi) * x * z - case[2,2]: 0.546274 * (dir.x * dir.x - dir.y * dir.y); // 0.25 * sqrt(15/pi) * (x^2 - y^2) - case[3,-3]: -0.590044 * dir.y * (3.0 * dir.x * dir.x - dir.y * dir.y);// -0.25 * sqrt(35/(2pi)) * y * (3x^2 - y^2) - case[3,-2]: 2.890611 * dir.x * dir.y * dir.z; // 0.5 * sqrt(105/pi) * x * y * z - case[3,-1]: -0.457046 * dir.y * (4.0 * dir.z * dir.z - dir.x * dir.x - dir.y * dir.y); // -0.25 * sqrt(21/(2pi)) * y * (4z^2-x^2-y^2) - case[3,0]: 0.373176 * dir.z * (2.0 * dir.z * dir.z - 3.0 * dir.x * dir.x - 3.0 * dir.y * dir.y); // 0.25 * sqrt(7/pi) * z * (2z^2 - 3x^2 - 3y^2) - case[3,1]: -0.457046 * dir.x * (4.0 * dir.z * dir.z - dir.x * dir.x - dir.y * dir.y); // -0.25 * sqrt(21/(2pi)) * x * (4z^2-x^2-y^2) - case[3,2]: 1.445306 * dir.z * (dir.x * dir.x - dir.y * dir.y); // 0.25 * sqrt(105/pi) * z * (x^2 - y^2) - case[3,3]: -0.590044 * dir.x * (dir.x * dir.x - 3.0 * dir.y * dir.y); // -0.25 * sqrt(35/(2pi)) * x * (x^2-3y^2) - case[4,-4]: 2.503343 * dir.x * dir.y * (dir.x * dir.x - dir.y * dir.y);// 0.75 * sqrt(35/pi) * x * y * (x^2-y^2) - case[4,-3]: -1.770131 * dir.y * dir.z * (3.0 * dir.x * dir.x - dir.y * dir.y); // -0.75 * sqrt(35/(2pi)) * y * z * (3x^2-y^2) - case[4,-2]: 0.946175 * dir.x * dir.y * (7.0 * dir.z * dir.z - 1.0);// 0.75 * sqrt(5/pi) * x * y * (7z^2-1) - case[4,-1]: -0.669047 * dir.y * dir.z * (7.0 * dir.z * dir.z - 3.0);// -0.75 * sqrt(5/(2pi)) * y * z * (7z^2-3) - case[4,0]: 0.105786 * (35.0 * dir.z * dir.z * dir.z * dir.z - 30.0 * dir.z * dir.z + 3.0);// 3/16 * sqrt(1/pi) * (35z^4-30z^2+3) - case[4,1]: -0.669047 * dir.x * dir.z * (7.0 * dir.z * dir.z - 3.0);// -0.75 * sqrt(5/(2pi)) * x * z * (7z^2-3) - case[4,2]: 0.473087 * (dir.x * dir.x - dir.y * dir.y) * (7.0 * dir.z * dir.z - 1.0);// 3/8 * sqrt(5/pi) * (x^2 - y^2) * (7z^2 - 1) - case[4,3]: -1.770131 * dir.x * dir.z * (dir.x * dir.x - 3.0 * dir.y * dir.y);// -0.75 * sqrt(35/(2pi)) * x * z * (x^2 - 3y^2) - case[4,4]: 0.625836 * (dir.x * dir.x * (dir.x * dir.x - 3.0 * dir.y * dir.y) - dir.y * dir.y * (3.0 * dir.x * dir.x - dir.y * dir.y)); // 3/16*sqrt(35/pi) * (x^2 * (x^2 - 3y^2) - y^2 * (3x^2 - y^2)) - default: 0; - } - } -} \ No newline at end of file diff --git a/hrt/prefab/vlm/SphericalHarmonic.hx b/hrt/prefab/vlm/SphericalHarmonic.hx deleted file mode 100644 index f6483b241..000000000 --- a/hrt/prefab/vlm/SphericalHarmonic.hx +++ /dev/null @@ -1,17 +0,0 @@ -package hrt.prefab.vlm; - -class SphericalHarmonic { - - public var coefR : Array = []; - public var coefG : Array = []; - public var coefB : Array = []; - public var order : Int; - - public function new(order:Int) { - this.order = order; - var coefCount = order * order; - coefR = [for (value in 0...coefCount) 0]; - coefG = [for (value in 0...coefCount) 0]; - coefB = [for (value in 0...coefCount) 0]; - } -} diff --git a/hrt/prefab/vlm/VolumetricLightmap.hx b/hrt/prefab/vlm/VolumetricLightmap.hx deleted file mode 100644 index 927be6974..000000000 --- a/hrt/prefab/vlm/VolumetricLightmap.hx +++ /dev/null @@ -1,297 +0,0 @@ -package hrt.prefab.vlm; - -class VolumetricLightmap extends Object3D { - - @:s var voxelsize_x : Float = 1.0; - @:s var voxelsize_y : Float = 1.0; - @:s var voxelsize_z : Float = 1.0; - @:s var strength : Float = 1.0; - @:s var order : Int = 1; - - public var volumetricLightmap : VolumetricMesh; - @:s var useWorldAlignedProbe = false; - @:s var displaySH = false; - @:s var resolution : Int = 16; - var useGPU = true; - - #if editor - @:c var displaySH_field = false; - var maxOrderBaked = 0; - var baker : hide.view.l3d.ProbeBakerProcess; - #end - - public function new(?parent) { - super(parent); - type = "volumetricLightmap"; - } - - #if editor - override function load( obj : Dynamic ) { - super.load(obj); - displaySH_field = displaySH; - } - #end - - function initProbes(){ - createDebugPreview(); - } - - function resetLightmap(){ - if(volumetricLightmap.lightProbeTexture != null) volumetricLightmap.lightProbeTexture.dispose(); - volumetricLightmap.lightProbeTexture = null; - volumetricLightmap.updateProbeCount(); - createDebugPreview(); - } - - function updateVolumetricLightmap(){ - #if editor - - if(volumetricLightmap == null) return; - - if(volumetricLightmap.voxelSize.x != voxelsize_x || volumetricLightmap.voxelSize.y != voxelsize_y ||volumetricLightmap.voxelSize.z != voxelsize_z){ - volumetricLightmap.voxelSize = new h3d.Vector(voxelsize_x,voxelsize_y,voxelsize_z); - resetLightmap(); - } - - if(volumetricLightmap.shOrder != order){ - if(maxOrderBaked >= order){ - volumetricLightmap.shOrder = order; - createDebugPreview(); - } - else{ - volumetricLightmap.shOrder = order; - resetLightmap(); - } - } - - if(volumetricLightmap.useAlignedProb != useWorldAlignedProbe){ - volumetricLightmap.useAlignedProb = useWorldAlignedProbe; - resetLightmap(); - } - - if(volumetricLightmap.strength != strength){ - volumetricLightmap.strength = strength; - } - - if(displaySH != displaySH_field){ - displaySH = displaySH_field; - if(!displaySH) clearDebugPreview(); - else createDebugPreview(); - } - #end - } - - function clearDebugPreview(){ - var previewSpheres = volumetricLightmap.findAll(c -> if(c.name == "_previewSphere") c else null); - if (previewSpheres != null) { - while(previewSpheres.length > 0){ - previewSpheres[previewSpheres.length- 1].remove(); - previewSpheres.pop(); - } - } - } - - public function createDebugPreview(){ - - if(!displaySH) return; - - clearDebugPreview(); - - if(volumetricLightmap == null) return; - - var pixels : hxd.Pixels = null; - if(volumetricLightmap.lightProbeTexture != null) - pixels = volumetricLightmap.lightProbeTexture.capturePixels(); - - for( i in 0...volumetricLightmap.getProbeCount()){ - var previewSphere = new h3d.scene.Mesh(h3d.prim.Sphere.defaultUnitSphere(), volumetricLightmap ); - previewSphere.name = "_previewSphere"; - previewSphere.material.setDefaultProps("ui"); - var size = 0.1; - previewSphere.scaleX = size/volumetricLightmap.parent.scaleX; - previewSphere.scaleY = size/volumetricLightmap.parent.scaleY; - previewSphere.scaleZ = size/volumetricLightmap.parent.scaleZ; - var probePos = volumetricLightmap.getProbePosition(volumetricLightmap.getProbeCoords(i)); - volumetricLightmap.globalToLocal(probePos); - previewSphere.setPosition(probePos.x, probePos.y, probePos.z); - var shader = new hrt.shader.DisplaySH(); - shader.order = volumetricLightmap.shOrder; - shader.strength = volumetricLightmap.strength; - var coefCount = volumetricLightmap.getCoefCount(); - shader.SIZE = coefCount; - - var sh = volumetricLightmap.getProbeSH(volumetricLightmap.getProbeCoords(i), pixels); - shader.shCoefsRed = sh.coefR.slice(0, coefCount); - shader.shCoefsGreen = sh.coefG.slice(0, coefCount); - shader.shCoefsBlue = sh.coefB.slice(0, coefCount); - - previewSphere.material.mainPass.culling = Back; - previewSphere.material.shadows = false; - previewSphere.material.mainPass.addShader(shader); - } - } - - override function updateInstance( ctx: Context, ?propName : String ) { - super.updateInstance(ctx, propName); - - if(propName == "strength" && displaySH){ - var previewSpheres = volumetricLightmap.findAll(c -> if(c.name == "_previewSphere") c else null); - for(ps in previewSpheres){ - var mesh = Std.downcast(ps, h3d.scene.Mesh); - var shader = mesh.material.mainPass.getShader(hrt.shader.DisplaySH); - if(shader != null) shader.strength = volumetricLightmap.strength; - } - } - if( propName != "visible" && propName != "strength" && propName != "order" && propName != "displaySH_field" && propName != "useGPU" && propName != "resolution") - resetLightmap(); - } - - override function makeInstance(ctx:Context):Context { - - ctx = ctx.clone(this); - var obj = new h3d.scene.Object(ctx.local3d); - volumetricLightmap = new hrt.prefab.vlm.VolumetricMesh(obj); - volumetricLightmap.ignoreCollide = true; - volumetricLightmap.setPosition(-0.5, -0.5, 0); - ctx.local3d = obj; - ctx.local3d.name = name; - updateInstance(ctx); - - volumetricLightmap.voxelSize = new h3d.Vector(voxelsize_x,voxelsize_y,voxelsize_z); - volumetricLightmap.shOrder = order; - volumetricLightmap.useAlignedProb = false; - volumetricLightmap.strength = strength; - - var res = ctx.shared.loadPrefabDat("sh", "bake", name); - if(res != null) volumetricLightmap.load(res.entry.getBytes()); - - #if editor - initProbes(); - #end - return ctx; - } - - #if editor - - override function getHideProps() : HideProps { - return { icon : "map-o", name : "VolumetricLightmap" }; - } - - override function setSelected( ctx : Context, b : Bool ) { - if( b ) { - var obj = ctx.shared.contexts.get(this).local3d; - var wire = new h3d.scene.Box(volumetricLightmap.lightProbeTexture == null ? 0xFFFF0000 : 0xFFFFFFFF,h3d.col.Bounds.fromValues(-0.5,-0.5,0,1,1,1),obj); - wire.name = "_highlight"; - wire.material.setDefaultProps("ui"); - wire.ignoreCollide = true; - wire.material.shadows = false; - } else { - for( o in ctx.shared.getObjects(this,h3d.scene.Box) ) - if( o.name == "_highlight" ) { - o.remove(); - return false; - } - } - return true; - } - - override function edit( ctx : EditContext ) { - super.edit(ctx); - var props = new hide.Element(' -
-
-
Strength
-
Display SH
-
-
-
-
SH Order
-
Resolution
-
Use GPU
-
-
-
Baking Process
-
-
-
-
-
X
-
Y
-
Z
-
-
- '); - ctx.properties.add(props, this, function(pname) { - updateVolumetricLightmap(); - ctx.onChange(this, pname); - }); - - function bakeUpdate(dt:Float){ - if(baker == null || baker.progress == 1){ - ctx.removeUpdate(bakeUpdate); - baker = null; - ctx.rebuildProperties(); - } - else{ - baker.update(dt); - if( baker == null ) return; - var props = ctx.getCurrentProps(this); - props.find(".bakeProgress").val(baker.progress); - } - } - - function cancel() { - ctx.removeUpdate(bakeUpdate); - baker = null; - ctx.rebuildProperties(); - } - - function startedBake() { - //var props = ctx.getCurrentProps(this); - props.find(".progress").show(); - props.find(".bake").attr("value","Cancel").off("click").click(function(_) cancel()); - bakeUpdate(0); - } - - props.find(".progress").hide(); - props.find(".bake").click(function(_) { - startBake(ctx, cancel); - startedBake(); - ctx.addUpdate(bakeUpdate); - }); - - if( baker != null ){ - startedBake(); - ctx.addUpdate(bakeUpdate); - } - - } - - public function startBake(ctx : EditContext, ?onEnd){ - maxOrderBaked = order; - volumetricLightmap.lastBakedProbeIndex = -1; - var s3d = @:privateAccess ctx.rootContext.local3d.getScene(); - baker = new hide.view.l3d.ProbeBakerProcess(this, resolution, useGPU, 0.032); - - var pbrRenderer = Std.downcast(s3d.renderer, h3d.scene.pbr.Renderer); - if(pbrRenderer != null) { - if( pbrRenderer.env == null || pbrRenderer.env.env == null || pbrRenderer.env.env.isDisposed() ) - trace("Environment missing"); - } else - trace("Invalid renderer"); - - var sceneData = @:privateAccess ctx.scene.editor.sceneData; - baker.init(pbrRenderer.env, sceneData.cloneData(), cast ctx.rootContext.shared, ctx.scene); - - baker.onEnd = function() { - if( onEnd != null ) onEnd(); - var bytes = volumetricLightmap.save(); - ctx.rootContext.shared.savePrefabDat("sh", "bake", name, bytes); - createDebugPreview(); - } - } - - #end - - static var _ = Library.register("volumetricLightmap", VolumetricLightmap); -} \ No newline at end of file diff --git a/hrt/prefab/vlm/VolumetricMesh.hx b/hrt/prefab/vlm/VolumetricMesh.hx deleted file mode 100644 index 36806ee93..000000000 --- a/hrt/prefab/vlm/VolumetricMesh.hx +++ /dev/null @@ -1,176 +0,0 @@ -package hrt.prefab.vlm; - -class VolumetricMesh extends h3d.scene.Mesh { - - public var lightProbeTexture : h3d.mat.Texture; - public var shOrder : Int = 1; - public var voxelSize (default, set) : h3d.Vector; - public var probeCount : h3d.col.IPoint; - public var useAlignedProb : Bool = false; - public var strength : Float = 1.; - - public var lastBakedProbeIndex = -1; - - var prim : h3d.prim.Cube; - - var shader : hrt.shader.VolumetricLightmap; - - function set_voxelSize(newSize) :h3d.Vector { - voxelSize = newSize; - updateProbeCount(); - return voxelSize; - } - - public function new(?parent) { - var prim = new h3d.prim.Cube(1,1,1,false); - prim.addNormals(); - super(prim, null, parent); - shader = new hrt.shader.VolumetricLightmap(); - material.mainPass.removeShader(material.mainPass.getShader(h3d.shader.pbr.PropsValues)); - material.mainPass.addShader(shader); - material.mainPass.setPassName("volumetricLightmap"); - material.mainPass.blend(One, One); - material.mainPass.culling = Front; - material.mainPass.depth(false, Greater); - material.mainPass.enableLights = false; - material.castShadows = false; - material.shadows = false; - material.mainPass.stencil = new h3d.mat.Stencil(); - material.mainPass.stencil.setFunc(NotEqual, 0x80, 0x80, 0x80); - material.mainPass.stencil.setOp(Keep, Keep, Replace); - probeCount = new h3d.col.IPoint(); - voxelSize = new h3d.Vector(1,1,1); - } - - public override function clone( ?o : h3d.scene.Object ) : h3d.scene.Object { - var vm = o == null ? new VolumetricMesh(null) : cast o; - vm.shOrder = shOrder; - vm.strength = strength; - vm.useAlignedProb = useAlignedProb; - vm.lightProbeTexture = lightProbeTexture != null ? lightProbeTexture.clone() : null; - vm.probeCount.load(probeCount); - vm.voxelSize.load(voxelSize); - return vm; - } - - public function getProbeSH(coords : h3d.col.IPoint, ?pixels : hxd.Pixels ) : SphericalHarmonic { - - if(lightProbeTexture == null) - return new SphericalHarmonic(shOrder); - - if(pixels == null) - pixels = lightProbeTexture.capturePixels(); - - var sh = new SphericalHarmonic(shOrder); - - var coefCount = getCoefCount(); - for(c in 0...coefCount){ - var u = coords.x + probeCount.x * c; - var v = coords.y + coords.z * probeCount.y; - var color = pixels.getPixelF(u, v); - sh.coefR[c] = color.r; - sh.coefG[c] = color.g; - sh.coefB[c] = color.b; - } - - return sh; - } - - public inline function getCoefCount() : Int{ - return shOrder * shOrder; - } - - public function getProbePosition(coords : h3d.col.IPoint){ - var probePos = new h3d.col.Point( coords.x/(probeCount.x - 1), coords.y/(probeCount.y - 1), coords.z/(probeCount.z - 1)); - localToGlobal(probePos); - return probePos; - } - - public function getProbeCoords(i : Int) : h3d.col.IPoint { - var coords = new h3d.col.IPoint(); - coords.z = Std.int(i / (probeCount.x * probeCount.y)); - coords.y = Std.int((i - coords.z * probeCount.y * probeCount.x) / (probeCount.x)); - coords.x = Std.int((i - coords.z * probeCount.y * probeCount.x - coords.y * probeCount.x)); - return coords; - } - - public function getProbeCount() { - return probeCount.x * probeCount.y * probeCount.z; - } - - override function onRemove() { - super.onRemove(); - if( lightProbeTexture != null ) { - lightProbeTexture.dispose(); - lightProbeTexture = null; - } - } - - public function updateProbeCount(){ - syncPos(); - var scale = absPos.getScale(); - probeCount.set(Std.int(Math.max(1,Math.floor(scale.x/voxelSize.x)) + 1), - Std.int(Math.max(1,Math.floor(scale.y/voxelSize.y)) + 1), - Std.int(Math.max(1,Math.floor(scale.z/voxelSize.z)) + 1)); - } - - public function load( bytes : haxe.io.Bytes ) { - if( bytes.length == 0 ) - return false; - bytes = try haxe.zip.Uncompress.run(bytes) catch( e : Dynamic ) throw e; - var count = getProbeCount(); - if( bytes.length != count * getCoefCount() * 4 * 4 ) - return false; - lastBakedProbeIndex = count; - if( lightProbeTexture != null ) lightProbeTexture.dispose(); - lightProbeTexture = new h3d.mat.Texture(probeCount.x * getCoefCount(), probeCount.y * probeCount.z, [Dynamic], RGBA32F); - lightProbeTexture.filter = Nearest; - lightProbeTexture.uploadPixels(new hxd.Pixels(lightProbeTexture.width, lightProbeTexture.height, bytes, RGBA32F)); - return true; - } - - public function save() : haxe.io.Bytes { - var data; - if( lightProbeTexture == null ) - data = haxe.io.Bytes.alloc(0); - else - data = lightProbeTexture.capturePixels().bytes; - return haxe.zip.Compress.run(data,9); - } - - override function emit(ctx:h3d.scene.RenderContext){ - if( lightProbeTexture != null ) super.emit(ctx); - } - - override function sync(ctx:h3d.scene.RenderContext) { - if( lightProbeTexture == null ) - return; - var scale = absPos.getScale(); - shader.ORDER = shOrder; - shader.lightmapInvPos.load(getInvPos()); - shader.lightmapSize.load(new h3d.Vector(probeCount.x, probeCount.y, probeCount.z)); - shader.voxelSize.load(new h3d.Vector(scale.x/(probeCount.x - 1), scale.y/(probeCount.y - 1), scale.z/(probeCount.z - 1))); - shader.lightProbeTexture = lightProbeTexture; - shader.cameraInverseViewProj.load(ctx.camera.getInverseViewProj()); - shader.cameraPos.load(ctx.camera.pos); - shader.strength = strength; - } - - public function getWorldAlignment(lightmaps : Array) : h3d.Vector { - var scale = absPos.getScale(); - var result = new h3d.Vector(scale.x/(probeCount.x - 1), scale.y/(probeCount.y - 1), scale.z/(probeCount.z - 1)); - for(i in 0...lightmaps.length){ - var lsc = lightmaps[i].absPos.getScale(); - result.x = Math.max(result.x, lsc.x / (lightmaps[i].probeCount.x - 1.0)); - result.y = Math.max(result.y, lsc.y / (lightmaps[i].probeCount.y - 1.0)); - result.z = Math.max(result.z, lsc.z / (lightmaps[i].probeCount.z - 1.0)); - } - return result; - } - - public function isInsideVolume(worldPos: h3d.col.Point) : Bool { - var localPos = worldPos.clone(); - globalToLocal(localPos); - return (localPos.x >= 0 && localPos.y >= 0 && localPos.z >= 0 && localPos.x <= 1 && localPos.y <= 1 && localPos.z <= 1); - } -}