whs.terrain
Version:
Terrain component for WhitestormJS
357 lines (283 loc) • 17 kB
JavaScript
"use strict";
var _get = function get(object, property, receiver) {
if (object === null) object = Function.prototype;
var desc = Object.getOwnPropertyDescriptor(object, property);
if (desc === undefined) {
var parent = Object.getPrototypeOf(object);
if (parent === null) {
return undefined;
} else {
return get(parent, property, receiver);
}
} else if ("value" in desc) {
return desc.value;
} else {
var getter = desc.get;
if (getter === undefined) {
return undefined;
}
return getter.call(receiver);
}
};
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _possibleConstructorReturn(self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && (typeof call === "object" || typeof call === "function") ? call : self;
}
function _inherits(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}
/**
* © Alexander Buzin, 2014-2015
* Site: http://alexbuzin.me/
* Email: alexbuzin88@gmail.com
*/
/**
* @author alteredq / http://alteredqualia.com/
* @author alex2401 / http://alexbuzin.me/
*
*/
THREE.ShaderTerrain = {
'terrain': {
uniforms: THREE.UniformsUtils.merge([THREE.UniformsLib["fog"], THREE.UniformsLib["lights"], THREE.UniformsLib["shadowmap"], {
"enableDiffuse1": {
type: "i",
value: 0
},
"enableDiffuse2": {
type: "i",
value: 0
},
"enableSpecular": {
type: "i",
value: 0
},
"enableReflection": {
type: "i",
value: 0
},
"tDiffuse1": {
type: "t",
value: null
},
"tDiffuse2": {
type: "t",
value: null
},
"tDetail": {
type: "t",
value: null
},
"tNormal": {
type: "t",
value: null
},
"tSpecular": {
type: "t",
value: null
},
"tDisplacement": {
type: "t",
value: null
},
"uNormalScale": {
type: "f",
value: 1.0
},
"uDisplacementBias": {
type: "f",
value: 0.0
},
"uDisplacementScale": {
type: "f",
value: 1.0
},
"diffuse": {
type: "c",
value: new THREE.Color(0xeeeeee)
},
"specular": {
type: "c",
value: new THREE.Color(0x111111)
},
"shininess": {
type: "f",
value: 30
},
"opacity": {
type: "f",
value: 1
},
"uRepeatBase": {
type: "v2",
value: new THREE.Vector2(1, 1)
},
"uRepeatOverlay": {
type: "v2",
value: new THREE.Vector2(1, 1)
},
"uOffset": {
type: "v2",
value: new THREE.Vector2(0, 0)
}
}]),
fragmentShader: "\n\t\t uniform vec3 diffuse;\n\t\t uniform vec3 emissive;\n\t\t uniform float opacity;\n\t\t uniform vec3 ambientLightColor;\n\t\t varying vec3 vLightFront;\n\t\t #ifdef DOUBLE_SIDED\n\t\t\t varying vec3 vLightBack;\n\t\t\t uniform vec2 uRepeatOverlay;\n\t\t\t uniform vec2 uRepeatBase;\n\t\t\t uniform vec2 uOffset;\n\t\t\t uniform float uNormalScale;\n\t\t\t uniform sampler2D tNormal;\n\t\t #endif\n\t\t uniform sampler2D oceanTexture;\n\t\t uniform sampler2D sandyTexture;\n\t\t uniform sampler2D grassTexture;\n\t\t uniform sampler2D rockyTexture;\n\t\t uniform sampler2D snowyTexture;\n\t\t varying vec3 vTangent;\n\t\t varying vec3 vBinormal;\n\t\t varying vec3 vNormal;\n\t\t varying vec3 vViewPosition;\n\t\t" + [THREE.ShaderChunk["common"], THREE.ShaderChunk["color_pars_fragment"], THREE.ShaderChunk["map_pars_fragment"], THREE.ShaderChunk["alphamap_pars_fragment"], THREE.ShaderChunk["lightmap_pars_fragment"], THREE.ShaderChunk["envmap_pars_fragment"], THREE.ShaderChunk["fog_pars_fragment"], THREE.ShaderChunk["shadowmap_pars_fragment"], THREE.ShaderChunk["specularmap_pars_fragment"], THREE.ShaderChunk["logdepthbuf_pars_fragment"]].join("\n") + "\n\t\t varying vec2 vUv;\n\t\t varying float vAmount;\n\t\t void main() {\n\t\t \t// UVs.\n\t\t vec2 uvOverlay = uRepeatOverlay * vUv + uOffset;\n\t\t vec2 uvBase = uRepeatBase * vUv;\n\t\t\t\t\tvec3 specularTex = vec3( 1.0 );\n\t\t vec3 normalTex = texture2D( tNormal, uvOverlay ).xyz * 2.0 - 1.0;\n\t\t normalTex.xy *= uNormalScale;\n\t\t normalTex = normalize( normalTex );\n\t\t mat3 tsb = mat3( vTangent, vBinormal, vNormal );\n\t\t vec3 finalNormal = tsb * normalTex;\n\t\t vec3 normal = normalize( finalNormal );\n\t\t vec3 viewPosition = normalize( vViewPosition );\n\t\t vec3 shadowMask = vec3( 1.0 );\n\t\t vec3 outgoingLight = vec3( 0.0 );\n\t\t vec3 totalAmbientLight = ambientLightColor;\n\t\t vec4 diffuseColor = vec4(0.0);\n\t\t // Color by texture.\n\t\t vec4 water = (smoothstep(0.01, 0.25, vAmount)\n\t\t - smoothstep(0.24, 0.26, vAmount))\n\t\t * texture2D( oceanTexture, vUv * 10.0 );\n\t\t vec4 sandy = (smoothstep(0.24, 0.27, vAmount)\n\t\t - smoothstep(0.28, 0.31, vAmount))\n\t\t * texture2D( sandyTexture, vUv * 10.0 );\n\t\t vec4 grass = (smoothstep(0.28, 0.32, vAmount)\n\t\t - smoothstep(0.35, 0.40, vAmount))\n\t\t * texture2D( grassTexture, vUv * 20.0 );\n\t\t vec4 rocky = (smoothstep(0.30, 0.40, vAmount)\n\t\t - smoothstep(0.40, 0.70, vAmount))\n\t\t * texture2D( rockyTexture, vUv * 20.0 );\n\t\t vec4 snowy = (smoothstep(0.42, 0.45, vAmount))\n\t\t * texture2D( snowyTexture, vUv * 10.0 );\n\t\t diffuseColor = vec4(0.0, 0.0, 0.0, 1.0)\n\t\t + water + sandy + grass + rocky + snowy;\n\t\t" + [THREE.ShaderChunk["logdepthbuf_fragment"], THREE.ShaderChunk["map_fragment"], THREE.ShaderChunk["alphamap_fragment"], THREE.ShaderChunk["alphatest_fragment"], THREE.ShaderChunk["specularmap_fragment"], THREE.ShaderChunk["lightmap_fragment"], THREE.ShaderChunk["color_fragment"], THREE.ShaderChunk["shadowmap_fragment"], THREE.ShaderChunk["linear_to_gamma_fragment"], THREE.ShaderChunk["fog_fragment"]].join("\n") + "\n\t\t #ifdef DOUBLE_SIDED\n\t\t if ( gl_FrontFacing )\n\t\t outgoingLight += diffuseColor.rgb * \n\t\t \t\t( vLightFront * shadowMask + totalAmbientLight )\n\t\t \t\t+ emissive;\n\t\t else\n\t\t outgoingLight += diffuseColor.rgb * \n\t\t \t\t( vLightBack * shadowMask + totalAmbientLight )\n\t\t \t\t+ emissive;\n\t\t #else\n\t\t outgoingLight += diffuseColor.rgb * \n\t\t \t( vLightFront * shadowMask + totalAmbientLight )\n\t\t \t+ emissive;\n\t\t #endif\n\t\t gl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t\t }\n\t\t",
vertexShader: "\n\t\t #define TERRAIN;\n\t\t varying vec3 vLightFront;\n\t\t #ifdef DOUBLE_SIDED\n\t\t varying vec3 vLightBack;\n\t\t #endif\n\t\t \n\t\t varying float vAmount;\n\t\t attribute vec4 tangent;\n\t\t uniform vec2 uRepeatBase;\n\t\t uniform sampler2D tNormal;\n\t\t #ifdef VERTEX_TEXTURES\n\t\t\t uniform sampler2D tDisplacement;\n\t\t\t uniform float uDisplacementScale;\n\t\t\t uniform float uDisplacementBias;\n\t\t #endif\n\t\t varying vec3 vTangent;\n\t\t varying vec3 vBinormal;\n\t\t varying vec3 vNormal;\n\t\t varying vec2 vUv;\n\t\t varying vec3 vViewPosition;\n\t\t" + [THREE.ShaderChunk["common"], THREE.ShaderChunk["uv_pars_vertex"], THREE.ShaderChunk["uv2_pars_vertex"], THREE.ShaderChunk["envmap_pars_vertex"], THREE.ShaderChunk["lights_lambert_pars_vertex"], THREE.ShaderChunk["color_pars_vertex"], THREE.ShaderChunk["morphtarget_pars_vertex"], THREE.ShaderChunk["skinning_pars_vertex"], THREE.ShaderChunk["shadowmap_pars_vertex"], THREE.ShaderChunk["logdepthbuf_pars_vertex"], THREE.ShaderChunk["bsdfs"], THREE.ShaderChunk["lights_pars"]].join("\n") + "\n\t\t void main() {\n\t\t" + [THREE.ShaderChunk["color_vertex"], THREE.ShaderChunk["beginnormal_vertex"], THREE.ShaderChunk["morphnormal_vertex"], THREE.ShaderChunk["skinbase_vertex"], THREE.ShaderChunk["skinnormal_vertex"], THREE.ShaderChunk["defaultnormal_vertex"], THREE.ShaderChunk["begin_vertex"], THREE.ShaderChunk["morphtarget_vertex"], THREE.ShaderChunk["skinning_vertex"], THREE.ShaderChunk["project_vertex"], THREE.ShaderChunk["logdepthbuf_vertex"], THREE.ShaderChunk["uv_vertex"], THREE.ShaderChunk["uv2_vertex"]].join("\n") + "\n\t\t\t vNormal = normalize( normalMatrix * normal);\n\t\t\t // Tangent and binormal vectors.\n\t\t\t vTangent = normalize( normalMatrix * tangent.xyz );\n\t\t\t vBinormal = cross( vNormal, vTangent ) * tangent.w;\n\t\t\t vBinormal = normalize( vBinormal );\n\t\t\t // Texture coordinates.\n\t\t\t vUv = uv;\n\t\t\t vec2 uvBase = uv * uRepeatBase;\n\t\t\t // displacement mapping\n\t\t\t vec4 worldPosition = modelMatrix * vec4( position, 1.0 );\n\t\t\t mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\t\t\t transformedNormal = normalize( normalMatrix * normal );\n\t\t\t gl_Position = projectionMatrix * mvPosition;\n\t\t\t vViewPosition = -mvPosition.xyz;\n\t\t\t vAmount = position.z * 0.005 + 0.1;\n\t\t" + [THREE.ShaderChunk["envmap_vertex"], THREE.ShaderChunk["lights_lambert_vertex"], THREE.ShaderChunk["shadowmap_vertex"]].join("\n") + "\n\t\t }\n\t\t",
side: THREE.DoubleSide,
shading: THREE.SmoothShading
}
};
/**
* © Alexander Buzin, 2014-2015
* Site: http://alexbuzin.me/
* Email: alexbuzin88@gmail.com
*/
WHS.Terrain = function(_WHS$Shape) {
_inherits(Terrain, _WHS$Shape);
function Terrain(params) {
_classCallCheck(this, Terrain);
var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(Terrain).call(this, params, "terrain"));
api.extend(params.geometry, {
width: 1,
height: 1,
depth: 1,
map: false
});
var canvas = document.createElement('canvas');
canvas.setAttribute("width", params.geometry.width);
canvas.setAttribute("height", params.geometry.height);
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.drawImage(params.geometry.map, 0, 0);
}
// Ocean texture.
var oceanTexture = api.TextureLoader().load(WHS._settings.assets + '/textures/terrain/dirt-512.jpg');
oceanTexture.wrapS = oceanTexture.wrapT = THREE.RepeatWrapping;
// Sandy texture.
var sandyTexture = api.TextureLoader().load(WHS._settings.assets + '/textures/terrain/sand-512.jpg');
sandyTexture.wrapS = sandyTexture.wrapT = THREE.RepeatWrapping;
// Grass texture.
var grassTexture = api.TextureLoader().load(WHS._settings.assets + '/textures/terrain/grass-512.jpg');
grassTexture.wrapS = grassTexture.wrapT = THREE.RepeatWrapping;
// Rocky texture.
var rockyTexture = api.TextureLoader().load(WHS._settings.assets + '/textures/terrain/rock-512.jpg');
rockyTexture.wrapS = rockyTexture.wrapT = THREE.RepeatWrapping;
// Snowy texture.
var snowyTexture = api.TextureLoader().load(WHS._settings.assets + '/textures/terrain/snow-512.jpg');
snowyTexture.wrapS = snowyTexture.wrapT = THREE.RepeatWrapping;
// Normal Map.
var normalShader = THREE.NormalMapShader;
var rx = 256,
ry = 256;
var pars = {
minFilter: THREE.LinearFilter,
magFilter: THREE.LinearFilter,
format: THREE.RGBFormat
};
// Heightmap.
var heightMap = new THREE.WebGLRenderTarget(rx, ry, pars);
heightMap.texture = api.TextureLoader().load(WHS._settings.assets + '/terrain/default_terrain.png');
// Normalmap.
var normalMap = new THREE.WebGLRenderTarget(rx, ry, pars);
normalMap.texture = api.TextureLoader().load(WHS._settings.assets + '/terrain/NormalMap.png');
// Specularmap.
var specularMap = new THREE.WebGLRenderTarget(256, 256, pars); //2048
specularMap.texture = api.TextureLoader().load(WHS._settings.assets + '/terrain/default_terrain.png');
// Terrain shader (ShaderTerrain.js).
var terrainShader = THREE.ShaderTerrain["terrain"];
var uniformsTerrain = Object.assign(THREE.UniformsUtils.clone(terrainShader.uniforms), {
oceanTexture: {
type: "t",
value: oceanTexture
},
sandyTexture: {
type: "t",
value: sandyTexture
},
grassTexture: {
type: "t",
value: grassTexture
},
rockyTexture: {
type: "t",
value: rockyTexture
},
snowyTexture: {
type: "t",
value: snowyTexture
},
fog: true,
lights: true
}, THREE.UniformsLib['common'], THREE.UniformsLib['fog'], THREE.UniformsLib['lights'], THREE.UniformsLib['ambient'], THREE.UniformsLib['shadowmap'], {
ambient: {
type: "c",
value: new THREE.Color(0xffffff)
},
emissive: {
type: "c",
value: new THREE.Color(0x000000)
},
wrapRGB: {
type: "v3",
value: new THREE.Vector3(1, 1, 1)
}
});
console.log(uniformsTerrain);
uniformsTerrain["tDisplacement"].value = heightMap;
uniformsTerrain["spotShadowMap"].value = [normalMap];
uniformsTerrain["uDisplacementScale"].value = 100;
uniformsTerrain["uRepeatOverlay"].value.set(6, 6);
var material = new THREE.ShaderMaterial({
uniforms: uniformsTerrain,
vertexShader: terrainShader.vertexShader,
fragmentShader: terrainShader.fragmentShader,
lights: true,
fog: true,
side: THREE.DoubleSide,
shading: THREE.SmoothShading
});
var geom = new THREE.PlaneGeometry(256, 256, 255, 255);
geom.verticesNeedUpdate = true;
_this._rot.set(Math.PI / 180 * -90, 0, 0);
var index = 0,
i = 0,
imgdata = ctx.getImageData(0, 0, 256, 256).data;
for (var x = 0; x <= 255; x++) {
for (var y = 255; y >= 0; y--) {
geom.vertices[index].z = imgdata[i] / 255 * 100;
i += 4;
index++;
}
}
_this.mesh = new Physijs.HeightfieldMesh(geom, Physijs.createMaterial(material, 0.8, 0.1));
geom.computeVertexNormals();
geom.computeFaceNormals();
geom.computeTangents();
_this.mesh.updateMatrix();
_this.mesh.castShadow = true;
_this.mesh.receiveShadow = true;
_get(Object.getPrototypeOf(Terrain.prototype), "build", _this).call(_this, "skip");
return _this;
}
return Terrain;
}(WHS.Shape);
WHS.init.prototype.Terrain = function(params) {
return new WHS.Terrain(params).addTo(this);
};