Hi AF. Cool experiments!
#1: As far inverting… ONCE I needed to “hack” the TWO primary functions used for ground.applyDisplacementMap().
https://www.babylonjs-playground.com/#2Q4S2S#20
CAUTION! ground.applyDisplacementMap() and applyDisplacementMapFromBuffer() are NON-DEFAULT in that playground. They are already customized/modified. Default versions are…
/**
* Modifies the mesh geometry according to a displacement map.
* A displacement map is a colored image. Each pixel color value (actually a gradient computed from red, green, blue values) will give the displacement to apply to each mesh vertex.
* The mesh must be set as updatable. Its internal geometry is directly modified, no new buffer are allocated.
* @param url is a string, the URL from the image file is to be downloaded.
* @param minHeight is the lower limit of the displacement.
* @param maxHeight is the upper limit of the displacement.
* @param onSuccess is an optional Javascript function to be called just after the mesh is modified. It is passed the modified mesh and must return nothing.
* @param uvOffset is an optional vector2 used to offset UV.
* @param uvScale is an optional vector2 used to scale UV.
* @param forceUpdate defines whether or not to force an update of the generated buffers. This is useful to apply on a deserialized model for instance.
* @returns the Mesh.
*/
Mesh.prototype.applyDisplacementMap = function (url, minHeight, maxHeight, onSuccess, uvOffset, uvScale, forceUpdate) {
var _this = this;
if (forceUpdate === void 0) { forceUpdate = false; }
var scene = this.getScene();
var onload = function (img) {
// Getting height map data
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
var heightMapWidth = img.width;
var heightMapHeight = img.height;
canvas.width = heightMapWidth;
canvas.height = heightMapHeight;
context.drawImage(img, 0, 0);
// Create VertexData from map data
//Cast is due to wrong definition in lib.d.ts from ts 1.3 - https://github.com/Microsoft/TypeScript/issues/949
var buffer = context.getImageData(0, 0, heightMapWidth, heightMapHeight).data;
_this.applyDisplacementMapFromBuffer(buffer, heightMapWidth, heightMapHeight, minHeight, maxHeight, uvOffset, uvScale, forceUpdate);
//execute success callback, if set
if (onSuccess) {
onSuccess(_this);
}
};
BABYLON.Tools.LoadImage(url, onload, function () { }, scene.offlineProvider);
return this;
};
/**
* Modifies the mesh geometry according to a displacementMap buffer.
* A displacement map is a colored image. Each pixel color value (actually a gradient computed from red, green, blue values) will give the displacement to apply to each mesh vertex.
* The mesh must be set as updatable. Its internal geometry is directly modified, no new buffer are allocated.
* @param buffer is a `Uint8Array` buffer containing series of `Uint8` lower than 255, the red, green, blue and alpha values of each successive pixel.
* @param heightMapWidth is the width of the buffer image.
* @param heightMapHeight is the height of the buffer image.
* @param minHeight is the lower limit of the displacement.
* @param maxHeight is the upper limit of the displacement.
* @param onSuccess is an optional Javascript function to be called just after the mesh is modified. It is passed the modified mesh and must return nothing.
* @param uvOffset is an optional vector2 used to offset UV.
* @param uvScale is an optional vector2 used to scale UV.
* @param forceUpdate defines whether or not to force an update of the generated buffers. This is useful to apply on a deserialized model for instance.
* @returns the Mesh.
*/
Mesh.prototype.applyDisplacementMapFromBuffer = function (buffer, heightMapWidth, heightMapHeight, minHeight, maxHeight, uvOffset, uvScale, forceUpdate) {
if (forceUpdate === void 0) { forceUpdate = false; }
if (!this.isVerticesDataPresent(BABYLON.VertexBuffer.PositionKind)
|| !this.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind)
|| !this.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
BABYLON.Tools.Warn("Cannot call applyDisplacementMap: Given mesh is not complete. Position, Normal or UV are missing");
return this;
}
var positions = this.getVerticesData(BABYLON.VertexBuffer.PositionKind, true, true);
var normals = this.getVerticesData(BABYLON.VertexBuffer.NormalKind);
var uvs = this.getVerticesData(BABYLON.VertexBuffer.UVKind);
var position = BABYLON.Vector3.Zero();
var normal = BABYLON.Vector3.Zero();
var uv = BABYLON.Vector2.Zero();
uvOffset = uvOffset || BABYLON.Vector2.Zero();
uvScale = uvScale || new BABYLON.Vector2(1, 1);
for (var index = 0; index < positions.length; index += 3) {
BABYLON.Vector3.FromArrayToRef(positions, index, position);
BABYLON.Vector3.FromArrayToRef(normals, index, normal);
BABYLON.Vector2.FromArrayToRef(uvs, (index / 3) * 2, uv);
// Compute height
var u = ((Math.abs(uv.x * uvScale.x + uvOffset.x) * heightMapWidth) % heightMapWidth) | 0;
var v = ((Math.abs(uv.y * uvScale.y + uvOffset.y) * heightMapHeight) % heightMapHeight) | 0;
var pos = (u + v * heightMapWidth) * 4;
var r = buffer[pos] / 255.0;
var g = buffer[pos + 1] / 255.0;
var b = buffer[pos + 2] / 255.0;
var gradient = r * 0.3 + g * 0.59 + b * 0.11;
normal.normalize();
normal.scaleInPlace(minHeight + (maxHeight - minHeight) * gradient);
position = position.add(normal);
position.toArray(positions, index);
}
BABYLON.VertexData.ComputeNormals(positions, this.getIndices(), normals);
if (forceUpdate) {
this.setVerticesData(BABYLON.VertexBuffer.PositionKind, positions);
this.setVerticesData(BABYLON.VertexBuffer.NormalKind, normals);
}
else {
this.updateVerticesData(BABYLON.VertexBuffer.PositionKind, positions);
this.updateVerticesData(BABYLON.VertexBuffer.NormalKind, normals);
}
return this;
};
(found via document search in https://raw.githubusercontent.com/BabylonJS/Babylon.js/master/dist/preview%20release/babylon.max.js)
In the playground… between lines 54 and 66, we are working in “context 2d land”. Let’s visit the transformations section of the W3C context2d spec. HTML Canvas 2D Context
context scale, rotate, translate… all available. I have a nopped-out rotate() in line 62 of above PG. It’s something to goof-around with. There might be easier solves. Let’s listen for more/better comments.
#2: I’m not sure why you have “z-fighting”-like problems with that. Using subMaterials with overLapping vert startAt and endAt values… is something BRAND NEW to me… and is “precarious” and possibly “dangerous” (subject-to unpredictability). Some kind of texture “summing” is being used, and I noticed that all the squirrels and other small animals… ran away and hid… when you started using that method. heh.
I will think on it, and texture experts… are nearby. Perhaps they will comment.