一、参考链接
ground_splatting | Babylon.js Playground
PBRCustomMaterial | Babylon.js Playground
二、实践
实践一

var createScene = function () {
// This creates a basic Babylon Scene object (non-mesh)
var scene = new BABYLON.Scene(engine);
// This creates and positions a free camera (non-mesh)
const camera = new BABYLON.ArcRotateCamera("camera", Math.PI / 2, Math.PI / 4, 500, BABYLON.Vector3.Zero(), scene);
// This targets the camera to scene origin
camera.setTarget(BABYLON.Vector3.Zero());
camera.attachControl(canvas, true);
var light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
light.intensity = 0.7;
var skybox = BABYLON.Mesh.CreateBox("BackgroundSkybox", 5000, scene, undefined, BABYLON.Mesh.BACKSIDE);
var backgroundMaterial = new BABYLON.BackgroundMaterial("backgroundMaterial", scene);
backgroundMaterial.reflectionTexture = new BABYLON.CubeTexture("textures/TropicalSunnyDay", scene);
backgroundMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
skybox.material = backgroundMaterial;
const texture1 = new BABYLON.Texture("http://i.endpot.com/image/JZBG4/材质 (10).png", scene);
const texture2 = new BABYLON.Texture("http://i.endpot.com/image/0PEQC/材质 (11).png", scene);
const texture3 = new BABYLON.Texture("http://i.endpot.com/image/DBU1M/TropicalSunnyDay_ny.jpg", scene);
// 创建 PBRCustomMaterial 实例
const simplePBR = new BABYLON.PBRCustomMaterial("simplePBR", scene);
simplePBR.albedoTexture = texture2;
simplePBR.reflectionTexture = BABYLON.CubeTexture.CreateFromPrefilteredData("/textures/environment.dds", scene);
simplePBR.metallicTexture = new BABYLON.Texture("/textures/mr.jpg", scene);
simplePBR.useRoughnessFromMetallicTextureAlpha = false;
simplePBR.useRoughnessFromMetallicTextureGreen = true;
simplePBR.useMetallnessFromMetallicTextureBlue = true;
simplePBR.AddUniform("layerSampler1", "sampler2D", texture1);
simplePBR.AddUniform("layerSampler2", "sampler2D", texture2);
simplePBR.Fragment_Definitions('varying vec3 lPos;');
simplePBR.Vertex_Definitions('varying vec3 lPos;');
simplePBR.Vertex_Before_PositionUpdated('lPos = positionUpdated ;')
simplePBR.Fragment_Custom_Albedo(`
vec4 textureColor1 = texture(layerSampler1, vAlbedoUV*3.0, 0.0);
vec4 textureColor2 = texture(layerSampler2, vAlbedoUV, 0.0);
float blackThreshold = 0.05;
float blackThreshold2 = 0.2;
vec3 rcolor = vec3(0.0,0.0,0.0);
// 判断颜色是否接近黑色
if (textureColor1.r > blackThreshold &&
textureColor1.g > blackThreshold &&
textureColor1.b > blackThreshold) {
rcolor = vec3(0.0, 0.0, 0.0);
} else if (textureColor2.r > blackThreshold2 &&
textureColor2.g > blackThreshold2 &&
textureColor2.b > blackThreshold2) {
rcolor =textureColor2.rgb;
}else{
rcolor = textureColor2.rgb;
}
result = rcolor;
`);
const numBuildings = 30;
const baseWidth = 40; // 基础宽度
const maxHeight = 100;
const buildings = [];
for (let i = 0; i < numBuildings; i++) {
const width = baseWidth + Math.random() * 10;
const height = maxHeight * Math.random() + 10;
const depth = 40; // 固定深度
// 创建立方体
const box = BABYLON.MeshBuilder.CreateBox(`building_${i}`, { width, height, depth }, scene);
// 随机位置
box.position.x = (Math.random() - 0.5) * 500;
box.position.z = (Math.random() - 0.5) * 500;
box.position.y = height / 2;
box.material = simplePBR;
buildings.push(box);
}
// Our built-in 'ground' shape.
var mirror = BABYLON.MeshBuilder.CreateGround("ground", { width: 1000, height: 1000 }, scene);
// 创建深蓝色材质
// const groundMaterial = new BABYLON.StandardMaterial("groundMaterial", scene);
// groundMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0.5); // 深蓝色 (R=0, G=0, B=0.5)
//const mirrorTexture = new BABYLON.MirrorTexture("mirror", 512, scene, true);
//mirrorTexture.mirrorPlane = new BABYLON.Plane(0, -1, 0, 0); // 设置反射平面
//mirrorTexture.renderList.push(buildings[0]); // 添加需要反射的物体
// 将反射纹理应用到地面材质
// const groundMaterial = new BABYLON.StandardMaterial("groundMaterial", scene);
// groundMaterial.reflectionTexture = mirrorTexture;
// ground.material = groundMaterial;
// 将材质应用到地面
// ground.material = groundMaterial;
//var mirror = BABYLON.Mesh.CreateBox("Mirror", 1.0, scene);
//mirror.scaling = new BABYLON.Vector3(100.0, 0.01, 100.0);
mirror.material = new BABYLON.StandardMaterial("mirror", scene);
mirror.material.diffuseColor = new BABYLON.Color3(0.01, 0.1, 0.3);
mirror.material.reflectionTexture = new BABYLON.MirrorTexture("mirror", { ratio: 0.5 }, scene, true);
mirror.material.reflectionTexture.mirrorPlane = new BABYLON.Plane(0, -1.0, 0, -2.0);
mirror.material.reflectionTexture.renderList = buildings;
mirror.material.reflectionTexture.level = 1.0;
mirror.material.reflectionTexture.adaptiveBlurKernel = 32;
mirror.position = new BABYLON.Vector3(0, 0, 0);
return scene;
};