v1.0.1 commit.
This is the first commit.
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
/*!
|
||||
* @class bkcore.ImageData
|
||||
*
|
||||
* Loads an image and gives access to pixel data.
|
||||
*
|
||||
* @author Thibaut 'BKcore' Despoulain <http://bkcore.com>
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @package bkcore
|
||||
*/
|
||||
var bkcore = bkcore || {};
|
||||
|
||||
/*!
|
||||
* Creates a new ImageData object
|
||||
*
|
||||
* @param path String The path of the image
|
||||
* @param callback Function A callback function to be called once th eimage is loaded
|
||||
*/
|
||||
bkcore.ImageData = function(path, callback)
|
||||
{
|
||||
var self = this;
|
||||
|
||||
this.image = new Image();
|
||||
this.pixels = null;
|
||||
this.canvas = null;
|
||||
this.loaded = false;
|
||||
|
||||
this.image.onload = function() {
|
||||
self.canvas = document.createElement('canvas');
|
||||
self.canvas.width = self.image.width;
|
||||
self.canvas.height = self.image.height;
|
||||
|
||||
var context = self.canvas.getContext('2d');
|
||||
context.drawImage(self.image, 0, 0);
|
||||
|
||||
self.pixels = context.getImageData(0, 0, self.canvas.width, self.canvas.height);
|
||||
|
||||
self.loaded = true;
|
||||
|
||||
context = null;
|
||||
self.canvas = null;
|
||||
self.image = null;
|
||||
|
||||
if(callback) callback.call(self);
|
||||
};
|
||||
this.image.crossOrigin = "anonymous";
|
||||
this.image.src = path;
|
||||
};
|
||||
|
||||
/*!
|
||||
* Gets pixel RGBA data at given index
|
||||
*
|
||||
* @param x int In pixels
|
||||
* @param y int In pixels
|
||||
* @return Object{r,g,b,a}
|
||||
*/
|
||||
bkcore.ImageData.prototype.getPixel = function(x, y)
|
||||
{
|
||||
if(this.pixels == null
|
||||
|| x < 0
|
||||
|| y < 0
|
||||
|| x >= this.pixels.width
|
||||
|| y >= this.pixels.height)
|
||||
return {r: 0, g: 0, b: 0, a:0};
|
||||
|
||||
var index = (y*this.pixels.width + x) * 4;
|
||||
|
||||
return {
|
||||
r: this.pixels.data[index],
|
||||
g: this.pixels.data[index + 1],
|
||||
b: this.pixels.data[index + 2],
|
||||
a: this.pixels.data[index + 3]
|
||||
};
|
||||
};
|
||||
|
||||
/*!
|
||||
* Gets pixel RGBA data at given float index using bilinear interpolation
|
||||
*
|
||||
* @param x float In subpixels
|
||||
* @param y float In subpixels
|
||||
* @return Object{r,g,b,a}
|
||||
*/
|
||||
bkcore.ImageData.prototype.getPixelBilinear = function(fx, fy)
|
||||
{
|
||||
var x = Math.floor(fx);
|
||||
var y = Math.floor(fy);
|
||||
var rx = fx - x - .5;
|
||||
var ry = fy - y - .5;
|
||||
var ax = Math.abs(rx);
|
||||
var ay = Math.abs(ry);
|
||||
var c, cxy, cx, cy, cf1, cf2;
|
||||
var dx = rx < 0 ? -1 : 1;
|
||||
var dy = ry < 0 ? -1 : 1;
|
||||
|
||||
c = this.getPixel(x, y);
|
||||
cx = this.getPixel(x+dx, y);
|
||||
cy = this.getPixel(x, y+dy);
|
||||
cxy = this.getPixel(x+dx, y+dy);
|
||||
|
||||
cf1 = [
|
||||
(1-ax) * c.r + ax * cx.r,
|
||||
(1-ax) * c.g + ax * cx.g,
|
||||
(1-ax) * c.b + ax * cx.b,
|
||||
(1-ax) * c.a + ax * cx.a
|
||||
];
|
||||
|
||||
cf2 = [
|
||||
(1-ax) * cy.r + ax * cxy.r,
|
||||
(1-ax) * cy.g + ax * cxy.g,
|
||||
(1-ax) * cy.b + ax * cxy.b,
|
||||
(1-ax) * cy.a + ax * cxy.a
|
||||
];
|
||||
|
||||
return {
|
||||
r: (1-ay) * cf1[0] + ay * cf2[0],
|
||||
g: (1-ay) * cf1[1] + ay * cf2[1],
|
||||
b: (1-ay) * cf1[2] + ay * cf2[2],
|
||||
a: (1-ay) * cf1[3] + ay * cf2[3]
|
||||
};
|
||||
}
|
||||
|
||||
/*!
|
||||
* Gets pixel data at given index
|
||||
* as 3-bytes integer (for floating-point textures erzats, from RGB values)
|
||||
*
|
||||
* @param x int In pixels
|
||||
* @param y int In pixels
|
||||
* @return int (R + G*255 + B*255*255)
|
||||
*/
|
||||
bkcore.ImageData.prototype.getPixelF = function(x, y)
|
||||
{
|
||||
var color = this.getPixel(x, y);
|
||||
return color.r + color.g * 255 + color.b * 255 * 255;
|
||||
};
|
||||
|
||||
/*!
|
||||
* Gets pixel data at given float index using bilinear interpolationas
|
||||
* as 3-bytes integer (for floating-point textures erzats, from RGB values)
|
||||
*
|
||||
* @param x float In subpixels
|
||||
* @param y float In subpixels
|
||||
* @return Object{r,g,b,a}
|
||||
*/
|
||||
bkcore.ImageData.prototype.getPixelFBilinear = function(fx, fy)
|
||||
{
|
||||
var color = this.getPixelBilinear(fx, fy);
|
||||
return color.r + color.g * 255.0 + color.b * 255.0 * 255.0;
|
||||
}
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
/*!
|
||||
* @class bkcore.Timer
|
||||
*
|
||||
* new Date().getTime() wrapper to use as timers.
|
||||
*
|
||||
* @author Thibaut 'BKcore' Despoulain <http://bkcore.com>
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @package bkcore
|
||||
*/
|
||||
var bkcore = bkcore || {};
|
||||
|
||||
/*!
|
||||
* Creates a new timer, inactive by default.
|
||||
* Call Timer.start() to activate.
|
||||
*/
|
||||
bkcore.Timer = function()
|
||||
{
|
||||
this.time = {
|
||||
start: 0,
|
||||
current: 0,
|
||||
previous: 0,
|
||||
elapsed: 0,
|
||||
delta: 0
|
||||
}
|
||||
|
||||
this.active = false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Starts/restarts the timer.
|
||||
*/
|
||||
bkcore.Timer.prototype.start = function()
|
||||
{
|
||||
var now = new Date().getTime();
|
||||
|
||||
this.time.start = now;
|
||||
this.time.current = now;
|
||||
this.time.previous = now;
|
||||
this.time.elapsed = 0;
|
||||
this.time.delta = 0;
|
||||
|
||||
this.active = true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Pauses(true)/Unpauses(false) the timer.
|
||||
*
|
||||
* @param bool Do pause
|
||||
*/
|
||||
bkcore.Timer.prototype.pause = function(bool)
|
||||
{
|
||||
this.active = !bool;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Update method to be called inside a RAF loop
|
||||
*/
|
||||
bkcore.Timer.prototype.update = function()
|
||||
{
|
||||
if(!this.active) return;
|
||||
|
||||
var now = new Date().getTime();
|
||||
|
||||
this.time.current = now;
|
||||
this.time.elapsed = this.time.current - this.time.start;
|
||||
this.time.delta = now - this.time.previous;
|
||||
this.time.previous = now;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns a formatted version of the current elapsed time using msToTime().
|
||||
*
|
||||
*
|
||||
*/
|
||||
bkcore.Timer.prototype.getElapsedTime = function()
|
||||
{
|
||||
return bkcore.Timer.msToTime(this.time.elapsed);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Formats a millisecond integer into a h/m/s/ms object
|
||||
*
|
||||
* @param x int In milliseconds
|
||||
* @return Object{h,m,s,ms}
|
||||
*/
|
||||
bkcore.Timer.msToTime = function(t)
|
||||
{
|
||||
var ms, s, m, h;
|
||||
|
||||
ms = t%1000;
|
||||
|
||||
s = Math.floor((t/1000)%60);
|
||||
|
||||
m = Math.floor((t/60000)%60);
|
||||
h = Math.floor((t/3600000));
|
||||
|
||||
return {h:h, m:m, s:s, ms:ms};
|
||||
}
|
||||
|
||||
/*!
|
||||
* Formats a millisecond integer into a h/m/s/ms object with prefix zeros
|
||||
*
|
||||
* @param x int In milliseconds
|
||||
* @return Object<string>{h,m,s,ms}
|
||||
*/
|
||||
bkcore.Timer.msToTimeString = function(t)
|
||||
{
|
||||
var ms, s, m, h;
|
||||
|
||||
ms = t%1000;
|
||||
if(ms < 10) ms = "00"+ms;
|
||||
else if(ms < 100) ms = "0"+ms;
|
||||
|
||||
s = Math.floor((t/1000)%60);
|
||||
if(s < 10) s = "0"+s;
|
||||
|
||||
m = Math.floor((t/60000)%60);
|
||||
h = Math.floor((t/3600000));
|
||||
|
||||
return {h:h, m:m, s:s, ms:ms};
|
||||
}
|
||||
+197
@@ -0,0 +1,197 @@
|
||||
/*!
|
||||
* @class bkcore.Timer
|
||||
*
|
||||
* new Date().getTime() wrapper to use as timers.
|
||||
*
|
||||
* @author Thibaut 'BKcore' Despoulain <http://bkcore.com>
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @package bkcore
|
||||
*/
|
||||
var bkcore = bkcore || {};
|
||||
|
||||
bkcore.Utils = {};
|
||||
|
||||
/**
|
||||
* Creates a bkcore.threejs.Shaders[ "normalV" | "normal" ] material with given parameters
|
||||
*/
|
||||
bkcore.Utils.createNormalMaterial = function(opts)
|
||||
{
|
||||
var shader = bkcore.threejs.Shaders[ opts.perPixel==false ? "normalV" : "normal" ];
|
||||
|
||||
var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
|
||||
|
||||
uniforms[ "enableDiffuse" ].value = true;
|
||||
uniforms[ "enableSpecular" ].value = true;
|
||||
uniforms[ "enableReflection" ].value = (opts.cube != undefined);
|
||||
|
||||
uniforms[ "tNormal" ].texture = opts.normal;
|
||||
uniforms[ "tDiffuse" ].texture = opts.diffuse;
|
||||
uniforms[ "tSpecular" ].texture = opts.specular;
|
||||
|
||||
uniforms[ "uAmbientColor" ].value.setHex(opts.ambient == undefined ? 0x444444 : opts.ambient);
|
||||
uniforms[ "uAmbientColor" ].value.convertGammaToLinear();
|
||||
|
||||
uniforms[ "uNormalScale" ].value = opts.normalScale == undefined ? 1.0 : opts.normalScale;
|
||||
|
||||
if(opts.cube != undefined)
|
||||
{
|
||||
uniforms[ "tCube" ].texture = opts.cube;
|
||||
uniforms[ "uReflectivity" ].value = opts.reflectivity == undefined ? 0.9 : opts.reflectivity;
|
||||
}
|
||||
|
||||
uniforms[ "uShininess" ].value = opts.shininess == undefined ? 42 : opts.shininess;
|
||||
|
||||
|
||||
var parameters = { fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: uniforms, lights: true, fog: false };
|
||||
|
||||
var material = new THREE.ShaderMaterial( parameters );
|
||||
material.perPixel = true;
|
||||
material.metal = opts.metal == undefined ? false : opts.metal;
|
||||
|
||||
return material;
|
||||
}
|
||||
|
||||
/**
|
||||
* Projects an object origin vector to screen using given camera
|
||||
* @param THREE.Object3D object The object which origin you want to project
|
||||
* @param THREE.Camera camera The camera of the projection
|
||||
* @return THEE.Vector3 Projected verctor
|
||||
*/
|
||||
bkcore.Utils.projectOnScreen = function(object, camera)
|
||||
{
|
||||
var mat = new THREE.Matrix4();
|
||||
mat.multiply( camera.matrixWorldInverse, object.matrixWorld);
|
||||
mat.multiply( camera.projectionMatrix , mat);
|
||||
|
||||
var c = mat.n44;
|
||||
var lPos = new THREE.Vector3(mat.n14/c, mat.n24/c, mat.n34/c);
|
||||
lPos.multiplyScalar(0.5);
|
||||
lPos.addScalar(0.5);
|
||||
return lPos;
|
||||
}
|
||||
|
||||
bkcore.Utils.URLParameters = null;
|
||||
|
||||
/**
|
||||
* Get an url parameter
|
||||
* @param String name Parameter slug
|
||||
* @return Mixed
|
||||
*/
|
||||
bkcore.Utils.getURLParameter = function(name)
|
||||
{
|
||||
if(bkcore.Utils.URLParameters == null)
|
||||
{
|
||||
var vars = {};
|
||||
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi,
|
||||
function(m,key,value) {
|
||||
vars[key] = value;
|
||||
}
|
||||
);
|
||||
bkcore.Utils.URLParameters = vars;
|
||||
}
|
||||
|
||||
return bkcore.Utils.URLParameters[name];
|
||||
}
|
||||
|
||||
bkcore.Utils.getOffsetTop = function(obj)
|
||||
{
|
||||
var curtop = 0;
|
||||
if (obj.offsetParent) {
|
||||
do {
|
||||
curtop += obj.offsetTop;
|
||||
} while (obj = obj.offsetParent);
|
||||
}
|
||||
else
|
||||
{
|
||||
curtop = obj.offsetTop;
|
||||
}
|
||||
return [curtop];
|
||||
}
|
||||
|
||||
/**
|
||||
* Scrolls page to given element id
|
||||
* @param string id The ID of the element
|
||||
*/
|
||||
bkcore.Utils.scrollTo = function(id)
|
||||
{
|
||||
window.scroll(
|
||||
0,
|
||||
bkcore.Utils.getOffsetTop(
|
||||
document.getElementById(id)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add or remove a class from an element
|
||||
* @param string id [description]
|
||||
* @param string cssclass [description]
|
||||
* @param bool active [description]
|
||||
*/
|
||||
bkcore.Utils.updateClass = function(id, cssclass, active)
|
||||
{
|
||||
var element = document.getElementById(id);
|
||||
if(active)
|
||||
element.classList.add(cssclass);
|
||||
else
|
||||
element.classList.remove(cssclass);
|
||||
}
|
||||
|
||||
/**
|
||||
* PErforms an XMLHttpRequest
|
||||
* @param string url [description]
|
||||
* @param bool postData true = POST, false = GET
|
||||
* @param {Function} callback [description]
|
||||
* @param {Object} data [description]
|
||||
*/
|
||||
bkcore.Utils.request = function(url, postData, callback, data)
|
||||
{
|
||||
var XMLHttpFactories = [
|
||||
function () {return new XMLHttpRequest()},
|
||||
function () {return new ActiveXObject("Msxml2.XMLHTTP")},
|
||||
function () {return new ActiveXObject("Msxml3.XMLHTTP")},
|
||||
function () {return new ActiveXObject("Microsoft.XMLHTTP")}
|
||||
];
|
||||
|
||||
function createXMLHTTPObject() {
|
||||
var xmlhttp = false;
|
||||
for (var i=0;i<XMLHttpFactories.length;i++) {
|
||||
try {
|
||||
xmlhttp = XMLHttpFactories[i]();
|
||||
}
|
||||
catch (e) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return xmlhttp;
|
||||
}
|
||||
|
||||
var req = createXMLHTTPObject();
|
||||
if (!req) return;
|
||||
var method = (postData) ? "POST" : "GET";
|
||||
|
||||
var qdata = "o=bk";
|
||||
if(data != undefined) for(var i in data)
|
||||
{
|
||||
qdata += "&"+i+"="+data[i];
|
||||
if(!postData) url += "?"+qdata;
|
||||
}
|
||||
|
||||
req.open(method,url,true);
|
||||
|
||||
if(postData)
|
||||
req.setRequestHeader('Content-type','application/x-www-form-urlencoded');
|
||||
|
||||
req.onreadystatechange = function () {
|
||||
if (req.readyState != 4) return;
|
||||
if (req.status != 200 && req.status != 304) {
|
||||
return;
|
||||
}
|
||||
callback(req);
|
||||
}
|
||||
|
||||
req.send(qdata);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* HexGL
|
||||
* @author Thibaut 'BKcore' Despoulain <http://bkcore.com>
|
||||
* @license This work is licensed under the Creative Commons Attribution-NonCommercial 3.0 Unported License.
|
||||
* To view a copy of this license, visit http://creativecommons.org/licenses/by-nc/3.0/.
|
||||
*/
|
||||
|
||||
var bkcore = bkcore || {};
|
||||
bkcore.hexgl = bkcore.hexgl || {};
|
||||
|
||||
bkcore.hexgl.CameraChase = function(opts)
|
||||
{
|
||||
this.dir = new THREE.Vector3(0,0,1);
|
||||
this.up = new THREE.Vector3(0,1,0);
|
||||
this.target = new THREE.Vector3();
|
||||
this.speedOffset = 0;
|
||||
this.speedOffsetMax = 10;
|
||||
this.speedOffsetStep = 0.05;
|
||||
|
||||
this.camera = opts.camera;
|
||||
this.targetObject = opts.target;
|
||||
this.cameraCube = opts.cameraCube == undefined ? null : opts.cameraCube;
|
||||
|
||||
this.yoffset = opts.yoffest == undefined ? 8.0 : opts.yoffest;
|
||||
this.zoffset = opts.zoffset == undefined ? 10.0 : opts.zoffset;
|
||||
this.viewOffset = opts.viewOffset == undefined ? 10.0 : opts.viewOffset;
|
||||
this.lerp = opts.lerp == undefined ? 0.5 : opts.lerp;
|
||||
}
|
||||
|
||||
bkcore.hexgl.CameraChase.prototype.update = function(dt, ratio)
|
||||
{
|
||||
this.dir.set(0,0,1);
|
||||
this.up.set(0,1,0);
|
||||
|
||||
this.targetObject.matrix.rotateAxis(this.up);
|
||||
this.targetObject.matrix.rotateAxis(this.dir);
|
||||
|
||||
this.speedOffset += (this.speedOffsetMax*ratio - this.speedOffset) * Math.min(1, 0.3*dt);
|
||||
|
||||
this.target.copy(this.targetObject.position);
|
||||
this.target.subSelf(this.dir.multiplyScalar(this.zoffset + this.speedOffset));
|
||||
this.target.addSelf(this.up.multiplyScalar(this.yoffset));
|
||||
this.target.y += -this.up.y + this.yoffset;
|
||||
this.camera.position.copy(this.target, this.lerp);
|
||||
|
||||
this.camera.lookAt(this.dir.normalize().multiplyScalar(this.viewOffset).addSelf(this.targetObject.position));
|
||||
|
||||
if(this.cameraCube != null)
|
||||
this.cameraCube.rotation.copy(this.camera.rotation);
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* HexGL
|
||||
* @author Thibaut 'BKcore' Despoulain <http://bkcore.com>
|
||||
* @license This work is licensed under the Creative Commons Attribution-NonCommercial 3.0 Unported License.
|
||||
* To view a copy of this license, visit http://creativecommons.org/licenses/by-nc/3.0/.
|
||||
*/
|
||||
|
||||
var bkcore = bkcore || {};
|
||||
bkcore.hexgl = bkcore.hexgl || {};
|
||||
|
||||
bkcore.hexgl.Gameplay = function(opts)
|
||||
{
|
||||
var self = this;
|
||||
|
||||
this.startDelay = 1000;
|
||||
this.countDownDelay = 1500;
|
||||
|
||||
this.active = false;
|
||||
this.timer = new bkcore.Timer();
|
||||
this.modes = {
|
||||
'timeattack':null,
|
||||
'survival':null,
|
||||
'replay':null
|
||||
};
|
||||
this.mode = opts.mode == undefined || !(opts.mode in this.modes) ? "timeattack" : opts.mode;
|
||||
this.step = 0;
|
||||
|
||||
this.hud = opts.hud;
|
||||
this.shipControls = opts.shipControls;
|
||||
this.track = opts.track;
|
||||
this.analyser = opts.analyser;
|
||||
this.pixelRatio = opts.pixelRatio;
|
||||
|
||||
this.previousCheckPoint = -1;
|
||||
|
||||
this.results = {
|
||||
FINISH: 1,
|
||||
DESTROYED: 2,
|
||||
WRONGWAY: 3,
|
||||
NONE: -1
|
||||
};
|
||||
this.result = this.results.NONE;
|
||||
|
||||
this.lap = 1;
|
||||
this.lapTimes = [];
|
||||
this.lapTimeElapsed = 0;
|
||||
this.maxLaps = 3;
|
||||
this.score = null;
|
||||
this.finishTime = null;
|
||||
this.onFinish = opts.onFinish == undefined ? function(){console.log("FINISH");} : opts.onFinish;
|
||||
|
||||
this.modes.timeattack = function()
|
||||
{
|
||||
self.hud.updateTime(self.timer.getElapsedTime());
|
||||
var cp = self.checkPoint();
|
||||
|
||||
if(cp == self.track.checkpoints.start && self.previousCheckPoint == self.track.checkpoints.last)
|
||||
{
|
||||
self.previousCheckPoint = cp;
|
||||
var t = self.timer.time.elapsed;
|
||||
self.lapTimes.push(t - self.lapTimeElapsed);
|
||||
self.lapTimeElapsed = t;
|
||||
|
||||
if(self.lap == this.maxLaps)
|
||||
{
|
||||
self.end(self.results.FINISH);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.lap++;
|
||||
self.hud.updateLap(self.lap, self.maxLaps);
|
||||
|
||||
if(self.lap == self.maxLaps)
|
||||
self.hud.display("Final lap", 0.5);
|
||||
}
|
||||
}
|
||||
else if(cp != -1 && cp != self.previousCheckPoint)
|
||||
{
|
||||
self.previousCheckPoint = cp;
|
||||
//self.hud.display("Checkpoint", 0.5);
|
||||
}
|
||||
|
||||
if(self.shipControls.destroyed == true)
|
||||
{
|
||||
self.end(self.results.DESTROYED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bkcore.hexgl.Gameplay.prototype.simu = function()
|
||||
{
|
||||
this.lapTimes = [92300, 91250, 90365];
|
||||
this.finishTime = this.lapTimes[0]+this.lapTimes[1]+this.lapTimes[2];
|
||||
this.hud.display("Finish");
|
||||
this.step = 100;
|
||||
this.result = this.results.FINISH;
|
||||
this.shipControls.active = false;
|
||||
}
|
||||
|
||||
bkcore.hexgl.Gameplay.prototype.start = function()
|
||||
{
|
||||
this.finishTime = null;
|
||||
this.score = null;
|
||||
this.lap = 1;
|
||||
|
||||
this.shipControls.reset(this.track.spawn, this.track.spawnRotation);
|
||||
this.shipControls.active = false;
|
||||
|
||||
this.previousCheckPoint = this.track.checkpoints.start;
|
||||
|
||||
this.active = true;
|
||||
this.step = 0;
|
||||
this.timer.start();
|
||||
this.hud.resetTime();
|
||||
this.hud.display("Get ready", 1);
|
||||
this.hud.updateLap(this.lap, this.maxLaps);
|
||||
}
|
||||
|
||||
bkcore.hexgl.Gameplay.prototype.end = function(result)
|
||||
{
|
||||
this.score = this.timer.getElapsedTime();
|
||||
this.finishTime = this.timer.time.elapsed;
|
||||
this.timer.start();
|
||||
this.result = result;
|
||||
|
||||
this.shipControls.active = false;
|
||||
|
||||
if(result == this.results.FINISH)
|
||||
{
|
||||
this.hud.display("Finish");
|
||||
this.step = 100;
|
||||
}
|
||||
else if(result == this.results.DESTROYED)
|
||||
{
|
||||
this.hud.display("Destroyed");
|
||||
this.step = 100;
|
||||
}
|
||||
}
|
||||
|
||||
bkcore.hexgl.Gameplay.prototype.update = function()
|
||||
{
|
||||
if(!this.active) return;
|
||||
|
||||
this.timer.update();
|
||||
|
||||
if(this.step == 0 && this.timer.time.elapsed >= this.countDownDelay+this.startDelay)
|
||||
{
|
||||
this.hud.display("3");
|
||||
this.step = 1;
|
||||
}
|
||||
else if(this.step == 1 && this.timer.time.elapsed >= 2*this.countDownDelay+this.startDelay)
|
||||
{
|
||||
this.hud.display("2");
|
||||
this.step = 2;
|
||||
}
|
||||
else if(this.step == 2 && this.timer.time.elapsed >= 3*this.countDownDelay+this.startDelay)
|
||||
{
|
||||
this.hud.display("1");
|
||||
this.step = 3;
|
||||
}
|
||||
else if(this.step == 3 && this.timer.time.elapsed >= 4*this.countDownDelay+this.startDelay)
|
||||
{
|
||||
this.hud.display("Go", 0.5);
|
||||
this.step = 4;
|
||||
this.timer.start();
|
||||
this.shipControls.active = true;
|
||||
}
|
||||
else if(this.step == 4)
|
||||
{
|
||||
this.modes[this.mode].call(this);
|
||||
}
|
||||
else if(this.step == 100 && this.timer.time.elapsed >= 2000)
|
||||
{
|
||||
this.active = false;
|
||||
this.onFinish.call(this);
|
||||
}
|
||||
}
|
||||
|
||||
bkcore.hexgl.Gameplay.prototype.checkPoint = function()
|
||||
{
|
||||
var x = Math.round(this.analyser.pixels.width/2 + this.shipControls.dummy.position.x * this.pixelRatio);
|
||||
var z = Math.round(this.analyser.pixels.height/2 + this.shipControls.dummy.position.z * this.pixelRatio);
|
||||
|
||||
var color = this.analyser.getPixel(x, z);
|
||||
|
||||
if(color.r == 255 && color.g == 255 && color.b < 250)
|
||||
return color.b;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* HexGL
|
||||
* @author Thibaut 'BKcore' Despoulain <http://bkcore.com>
|
||||
* @license This work is licensed under the Creative Commons Attribution-NonCommercial 3.0 Unported License.
|
||||
* To view a copy of this license, visit http://creativecommons.org/licenses/by-nc/3.0/.
|
||||
*/
|
||||
|
||||
var bkcore = bkcore || {};
|
||||
bkcore.hexgl = bkcore.hexgl || {};
|
||||
|
||||
bkcore.hexgl.HUD = function(opts)
|
||||
{
|
||||
var self = this;
|
||||
|
||||
this.width = opts.width;
|
||||
this.height = opts.height;
|
||||
|
||||
this.canvas = document.createElement('canvas');
|
||||
this.canvas.width = this.width;
|
||||
this.canvas.height = this.height;
|
||||
|
||||
this.ctx = this.canvas.getContext('2d');
|
||||
this.ctx.textAlign = "center";
|
||||
|
||||
this.bg = opts.bg;//"textures/hud/hud-bg.png";
|
||||
|
||||
this.fgspeed = opts.speed;//"textures/hud/hud-fg-speed.png";
|
||||
|
||||
this.fgshield = opts.shield;//"textures/hud/hud-fg-shield.png";
|
||||
|
||||
this.speedFontRatio = 24;
|
||||
this.speedBarRatio = 2.91;
|
||||
this.shieldFontRatio = 64;
|
||||
this.shieldBarYRatio = 34;
|
||||
this.shieldBarWRatio = 18.3;
|
||||
this.shieldBarHRatio = 14.3;
|
||||
this.timeMarginRatio = 18;
|
||||
this.timeFontRatio = 19.2;
|
||||
|
||||
this.font = opts.font || "Arial";
|
||||
|
||||
this.time = "";
|
||||
|
||||
this.message = "";
|
||||
this.previousMessage = "";
|
||||
this.messageTiming = 0;
|
||||
this.messagePos = 0.0;
|
||||
this.messagePosTarget = 0.0;
|
||||
this.messagePosTargetRatio = 12;
|
||||
this.messageA = 1.0;
|
||||
this.messageAS = 1.0;
|
||||
this.messageDuration = 2*60;
|
||||
this.messageDurationD = 2*60;
|
||||
this.messageDurationS = 30;
|
||||
this.messageYRatio = 34;
|
||||
this.messageFontRatio = 10;
|
||||
this.messageFontRatioStart = 6;
|
||||
this.messageFontRatioEnd = 10;
|
||||
this.messageFontLerp = 0.4;
|
||||
this.messageLerp = 0.4;
|
||||
this.messageFontAlpha = 0.8;
|
||||
|
||||
this.lapMarginRatio = 14;
|
||||
this.lap = "";
|
||||
this.lapSeparator = "/";
|
||||
|
||||
this.timeSeparators = ["","'", "''",""];
|
||||
|
||||
this.step = 0;
|
||||
this.maxStep = 2;
|
||||
};
|
||||
|
||||
bkcore.hexgl.HUD.prototype.resize = function(w, h)
|
||||
{
|
||||
this.width = w;
|
||||
this.height = h;
|
||||
this.canvas.width = w;
|
||||
this.canvas.height = h;
|
||||
}
|
||||
|
||||
bkcore.hexgl.HUD.prototype.display = function(msg, duration)
|
||||
{
|
||||
this.messageTiming = 0;
|
||||
|
||||
if(this.message != "")
|
||||
{
|
||||
this.messageA = this.messageFontAlpha;
|
||||
this.messagePos = 0.0;
|
||||
this.messagePosTarget = this.width/this.messagePosTargetRatio;
|
||||
this.previousMessage = this.message;
|
||||
}
|
||||
|
||||
this.messageFontRatio = this.messageFontRatioStart;
|
||||
this.messageAS = 0.0;
|
||||
this.message = msg;
|
||||
this.messageDuration = duration == undefined ? this.messageDurationD : duration*60;
|
||||
}
|
||||
|
||||
bkcore.hexgl.HUD.prototype.updateLap = function(current, total)
|
||||
{
|
||||
this.lap = current + this.lapSeparator + total;
|
||||
}
|
||||
|
||||
bkcore.hexgl.HUD.prototype.resetLap = function()
|
||||
{
|
||||
this.lap = "";
|
||||
}
|
||||
|
||||
bkcore.hexgl.HUD.prototype.updateTime = function(time)
|
||||
{
|
||||
this.time = this.timeSeparators[0] + time.m + this.timeSeparators[1] + time.s + this.timeSeparators[2] + time.ms + this.timeSeparators[3];
|
||||
}
|
||||
|
||||
bkcore.hexgl.HUD.prototype.resetTime = function()
|
||||
{
|
||||
this.time = "";
|
||||
}
|
||||
|
||||
bkcore.hexgl.HUD.prototype.update = function(speed, speedRatio, shield, shieldRatio)
|
||||
{
|
||||
var SCREEN_WIDTH = this.width;
|
||||
var SCREEN_HEIGHT = this.height;
|
||||
|
||||
var SCREEN_HW = SCREEN_WIDTH / 2;
|
||||
var SCREEN_HH = SCREEN_HEIGHT / 2;
|
||||
|
||||
//this.ctx.clearRect(0 , 0 , SCREEN_WIDTH , SCREEN_HEIGHT);
|
||||
|
||||
var w = this.bg.width;
|
||||
var h = this.bg.height;
|
||||
var r = h/w;
|
||||
var nw = SCREEN_WIDTH;
|
||||
var nh = nw*r;
|
||||
var oh = SCREEN_HEIGHT - nh;
|
||||
var o = 0;
|
||||
//speedbar
|
||||
var ba = nh;
|
||||
var bl = SCREEN_WIDTH/this.speedBarRatio;
|
||||
var bw = bl * speedRatio;
|
||||
//shieldbar
|
||||
var sw = SCREEN_WIDTH/this.shieldBarWRatio;
|
||||
var sho = SCREEN_WIDTH/this.shieldBarHRatio;
|
||||
var sh = sho*shieldRatio;
|
||||
var sy = (SCREEN_WIDTH/this.shieldBarYRatio)+sho-sh;
|
||||
|
||||
|
||||
if(this.step == 0)
|
||||
{
|
||||
this.ctx.clearRect(0 , oh , SCREEN_WIDTH , nh);
|
||||
|
||||
this.ctx.drawImage(this.bg, o, oh, nw, nh);
|
||||
|
||||
this.ctx.save();
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(bw+ba+SCREEN_HW, oh);
|
||||
this.ctx.lineTo(-(bw+ba)+SCREEN_HW, oh);
|
||||
this.ctx.lineTo(-bw+SCREEN_HW, SCREEN_HEIGHT);
|
||||
this.ctx.lineTo(bw+SCREEN_HW, SCREEN_HEIGHT);
|
||||
this.ctx.lineTo(bw+ba+SCREEN_HW, oh);
|
||||
this.ctx.clip();
|
||||
this.ctx.drawImage(this.fgspeed, o, oh, nw, nh);
|
||||
this.ctx.restore();
|
||||
|
||||
this.ctx.save();
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(-sw+SCREEN_HW, oh+sy);
|
||||
this.ctx.lineTo(sw+SCREEN_HW, oh+sy);
|
||||
this.ctx.lineTo(sw+SCREEN_HW, oh+sh+sy);
|
||||
this.ctx.lineTo(-sw+SCREEN_HW, oh+sh+sy);
|
||||
this.ctx.lineTo(-sw+SCREEN_HW, oh+sh);
|
||||
this.ctx.clip();
|
||||
this.ctx.drawImage(this.fgshield, o, oh, nw, nh);
|
||||
this.ctx.restore();
|
||||
|
||||
// SPEED
|
||||
this.ctx.font = (SCREEN_WIDTH/this.speedFontRatio)+"px "+this.font;
|
||||
this.ctx.fillStyle = "rgba(255, 255, 255, 0.8)";
|
||||
this.ctx.fillText(speed, SCREEN_HW, SCREEN_HEIGHT - nh*0.57);
|
||||
|
||||
// SHIELD
|
||||
this.ctx.font = (SCREEN_WIDTH/this.shieldFontRatio)+"px "+this.font;
|
||||
this.ctx.fillStyle = "rgba(255, 255, 255, 0.4)";
|
||||
this.ctx.fillText(shield, SCREEN_HW, SCREEN_HEIGHT - nh*0.44);
|
||||
}
|
||||
else if(this.step == 1)
|
||||
{
|
||||
this.ctx.clearRect(0 , 0 , SCREEN_WIDTH , oh);
|
||||
|
||||
// TIME
|
||||
if(this.time != "")
|
||||
{
|
||||
this.ctx.font = (SCREEN_WIDTH/this.timeFontRatio)+"px "+this.font;
|
||||
this.ctx.fillStyle = "rgba(255, 255, 255, 0.8)";
|
||||
this.ctx.fillText(this.time, SCREEN_HW, SCREEN_WIDTH/this.timeMarginRatio);
|
||||
}
|
||||
|
||||
// LAPS
|
||||
if(this.lap != "")
|
||||
{
|
||||
this.ctx.font = (SCREEN_WIDTH/this.timeFontRatio)+"px "+this.font;
|
||||
this.ctx.fillStyle = "rgba(255, 255, 255, 0.8)";
|
||||
this.ctx.fillText(this.lap, SCREEN_WIDTH-SCREEN_WIDTH/this.lapMarginRatio, SCREEN_WIDTH/this.timeMarginRatio);
|
||||
}
|
||||
|
||||
// MESSAGE
|
||||
var my = SCREEN_HH-SCREEN_WIDTH/this.messageYRatio;
|
||||
|
||||
if(this.messageTiming > this.messageDuration+2000)
|
||||
{
|
||||
this.previousMessage = "";
|
||||
this.message = "";
|
||||
this.messageA = 0.0;
|
||||
}
|
||||
else if(this.messageTiming > this.messageDuration && this.message != "")
|
||||
{
|
||||
this.previousMessage = this.message;
|
||||
this.message = "";
|
||||
this.messagePos = 0.0;
|
||||
this.messagePosTarget = SCREEN_WIDTH/this.messagePosTargetRatio;
|
||||
this.messageA = this.messageFontAlpha;
|
||||
}
|
||||
|
||||
if(this.previousMessage != "")
|
||||
{
|
||||
if(this.messageA < 0.001)
|
||||
this.messageA = 0.0;
|
||||
else
|
||||
this.messageA += (0.0 - this.messageA) * this.messageLerp;
|
||||
|
||||
this.messagePos += (this.messagePosTarget - this.messagePos) * this.messageLerp;
|
||||
|
||||
this.ctx.font = (SCREEN_WIDTH/this.messageFontRatioEnd)+"px "+this.font;
|
||||
this.ctx.fillStyle = "rgba(255, 255, 255, "+this.messageA+")";
|
||||
this.ctx.fillText(this.previousMessage, SCREEN_HW, my+this.messagePos);
|
||||
}
|
||||
|
||||
if(this.message != "")
|
||||
{
|
||||
if(this.messageTiming < this.messageDurationS)
|
||||
{
|
||||
this.messageAS += (this.messageFontAlpha - this.messageAS) * this.messageFontLerp;
|
||||
this.messageFontRatio += (this.messageFontRatioEnd - this.messageFontRatio) * this.messageFontLerp;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.messageAS = this.messageFontAlpha;
|
||||
this.messageFontRatio = this.messageFontRatioEnd;
|
||||
}
|
||||
|
||||
this.ctx.font = (SCREEN_WIDTH/this.messageFontRatio)+"px "+this.font;
|
||||
this.ctx.fillStyle = "rgba(255, 255, 255, "+this.messageAS+")";
|
||||
this.ctx.fillText(this.message, SCREEN_HW, my);
|
||||
}
|
||||
}
|
||||
|
||||
this.messageTiming++;
|
||||
|
||||
this.step++;
|
||||
if(this.step == this.maxStep) this.step = 0;
|
||||
}
|
||||
@@ -0,0 +1,392 @@
|
||||
/*
|
||||
* HexGL
|
||||
* @author Thibaut 'BKcore' Despoulain <http://bkcore.com>
|
||||
* @license This work is licensed under the Creative Commons Attribution-NonCommercial 3.0 Unported License.
|
||||
* To view a copy of this license, visit http://creativecommons.org/licenses/by-nc/3.0/.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
'v1.0.1';
|
||||
|
||||
var bkcore = bkcore || {};
|
||||
bkcore.hexgl = bkcore.hexgl || {};
|
||||
|
||||
bkcore.hexgl.HexGL = function(opts)
|
||||
{
|
||||
var self = this;
|
||||
|
||||
this.document = opts.document || document;
|
||||
|
||||
this.a = window.location.href;
|
||||
|
||||
this.active = true;
|
||||
|
||||
this.width = opts.width == undefined ? window.innerWidth : opts.width;
|
||||
this.height = opts.height == undefined ? window.innerHeight : opts.height;
|
||||
|
||||
this.quality = opts.quality == undefined ? 2 : opts.quality;
|
||||
this.difficulty = opts.difficulty == undefined ? 0 : opts.difficulty;
|
||||
this.player = opts.player == undefined ? "Anonym" : opts.player;
|
||||
|
||||
this.half = opts.half == undefined ? false : opts.half;
|
||||
|
||||
this.track = bkcore.hexgl.tracks[ opts.track == undefined ? 'Cityscape' : opts.track ];
|
||||
|
||||
if(this.half)
|
||||
{
|
||||
this.width /= 2;
|
||||
this.height /=2;
|
||||
}
|
||||
|
||||
this.settings = null;
|
||||
this.renderer = null;
|
||||
this.manager = null;
|
||||
this.lib = null;
|
||||
this.materials = {};
|
||||
this.components = {};
|
||||
this.extras = {
|
||||
vignetteColor: new THREE.Color(0x458ab1),
|
||||
bloom: null,
|
||||
fxaa: null
|
||||
};
|
||||
|
||||
this.containers = {};
|
||||
this.containers.main = opts.container == undefined ? document.body : opts.container;
|
||||
this.containers.overlay = opts.overlay == undefined ? document.body : opts.overlay;
|
||||
|
||||
this.hud = null;
|
||||
|
||||
this.gameplay = null;
|
||||
|
||||
this.composers = {
|
||||
game: null
|
||||
};
|
||||
|
||||
this.initRenderer();
|
||||
|
||||
function onKeyPress(event)
|
||||
{
|
||||
if(event.keyCode == 27/*escape*/)
|
||||
{
|
||||
self.reset();
|
||||
}
|
||||
}
|
||||
|
||||
this.document.addEventListener('keydown', onKeyPress, false);
|
||||
}
|
||||
|
||||
bkcore.hexgl.HexGL.prototype.start = function()
|
||||
{
|
||||
|
||||
this.manager.setCurrent("game");
|
||||
|
||||
var self = this;
|
||||
|
||||
function raf()
|
||||
{
|
||||
requestAnimationFrame( raf );
|
||||
self.update();
|
||||
}
|
||||
|
||||
//if(this.a[15] == "o")
|
||||
raf();
|
||||
|
||||
this.initGameplay();
|
||||
}
|
||||
|
||||
bkcore.hexgl.HexGL.prototype.reset = function()
|
||||
{
|
||||
this.manager.get('game').objects.lowFPS = 0;
|
||||
this.gameplay.start();
|
||||
}
|
||||
|
||||
bkcore.hexgl.HexGL.prototype.restart = function()
|
||||
{
|
||||
this.document.getElementById('finish').style.display = 'none';
|
||||
this.reset();
|
||||
}
|
||||
|
||||
bkcore.hexgl.HexGL.prototype.update = function()
|
||||
{
|
||||
if(!this.active) return;
|
||||
|
||||
if(this.gameplay != null)
|
||||
this.gameplay.update();
|
||||
|
||||
this.manager.renderCurrent();
|
||||
}
|
||||
|
||||
bkcore.hexgl.HexGL.prototype.init = function()
|
||||
{
|
||||
this.initHUD();
|
||||
|
||||
this.track.buildMaterials(this.quality);
|
||||
|
||||
this.track.buildScenes(this, this.quality);
|
||||
|
||||
this.initGameComposer();
|
||||
}
|
||||
|
||||
bkcore.hexgl.HexGL.prototype.load = function(opts)
|
||||
{
|
||||
this.track.load(opts, this.quality);
|
||||
}
|
||||
|
||||
bkcore.hexgl.HexGL.prototype.initGameplay = function()
|
||||
{
|
||||
var self = this;
|
||||
|
||||
this.gameplay = new bkcore.hexgl.Gameplay({
|
||||
mode: "timeattack",
|
||||
hud: this.hud,
|
||||
shipControls: this.components.shipControls,
|
||||
analyser: this.track.analyser,
|
||||
pixelRatio: this.track.pixelRatio,
|
||||
track: {
|
||||
checkpoints: this.track.checkpoints,
|
||||
spawn: this.track.spawn,
|
||||
spawnRotation: this.track.spawnRotation
|
||||
},
|
||||
onFinish: function() {
|
||||
self.displayScore(this.finishTime, this.lapTimes);
|
||||
}
|
||||
});
|
||||
|
||||
this.gameplay.start();
|
||||
}
|
||||
|
||||
bkcore.hexgl.HexGL.prototype.displayScore = function(f, l)
|
||||
{
|
||||
var t = 'cityscape';
|
||||
var dc = this.document.getElementById("finish");
|
||||
var ds = this.document.getElementById("finish-state");
|
||||
var dh = this.document.getElementById("finish-hallmsg");
|
||||
var dr = this.document.getElementById("finish-msg");
|
||||
var dt = this.document.getElementById("finish-result");
|
||||
var dl1 = this.document.getElementById("finish-lap1");
|
||||
var dl2 = this.document.getElementById("finish-lap2");
|
||||
var dl3 = this.document.getElementById("finish-lap3");
|
||||
var dd = this.document.getElementById("finish-diff")
|
||||
var st = this.document.getElementById("finish-twitter");
|
||||
var sf = this.document.getElementById("finish-fb");
|
||||
var sl = this.document.getElementById("lowfps-msg");
|
||||
var d = this.difficulty == 0 ? 'casual' : 'hard';
|
||||
var ts = this.hud.timeSeparators;
|
||||
var tf = bkcore.Timer.msToTimeString(f);
|
||||
var tl = [
|
||||
bkcore.Timer.msToTimeString(l[0]),
|
||||
bkcore.Timer.msToTimeString(l[1]),
|
||||
bkcore.Timer.msToTimeString(l[2])
|
||||
];
|
||||
|
||||
if(this.gameplay.result == this.gameplay.results.FINISH)
|
||||
{
|
||||
ds != undefined && (ds.innerHTML = "Finished!");
|
||||
// local record
|
||||
if(typeof(Storage)!=="undefined")
|
||||
{
|
||||
if(localStorage['score-'+t+'-'+d] == undefined || localStorage['score-'+t+'-'+d] > f)
|
||||
{
|
||||
dr != undefined && (dr.innerHTML = "New local record!");
|
||||
localStorage['score-'+t+'-'+d] = f;
|
||||
}
|
||||
else
|
||||
{
|
||||
dr != undefined && (dr.innerHTML = "Well done!");
|
||||
}
|
||||
}
|
||||
// ladder record
|
||||
var p = bkcore.hexgl.Ladder.global[t][d][bkcore.hexgl.Ladder.global[t][d].length-2];
|
||||
if(p != undefined && p['score'] > f)
|
||||
{
|
||||
dh != undefined && (dh.innerHTML = "You made it to the HOF!");
|
||||
}
|
||||
else
|
||||
{
|
||||
dh != undefined && (dh.innerHTML = "Hall Of Fame");
|
||||
}
|
||||
|
||||
dt != undefined && (dt.innerHTML = tf.m + ts[1] + tf.s + ts[2] + tf.ms);
|
||||
dl1 != undefined && (dl1.innerHTML = tl[0]["m"] != undefined ? tl[0].m + ts[1] + tl[0].s + ts[2] + tl[0].ms : "-");
|
||||
dl2 != undefined && (dl2.innerHTML = tl[1]["m"] != undefined ? tl[1].m + ts[1] + tl[1].s + ts[2] + tl[1].ms : "-");
|
||||
dl3 != undefined && (dl3.innerHTML = tl[2]["m"] != undefined ? tl[2].m + ts[1] + tl[2].s + ts[2] + tl[2].ms : "-");
|
||||
|
||||
// Ladder save
|
||||
// Undisclosed
|
||||
}
|
||||
else
|
||||
{
|
||||
ds != undefined && (ds.innerHTML = "Destroyed!");
|
||||
dr != undefined && (dr.innerHTML = "Maybe next time!");
|
||||
dh != undefined && (dh.innerHTML = "Hall Of Fame");
|
||||
dt != undefined && (dt.innerHTML = "None");
|
||||
dl1 != undefined && (dl1.innerHTML = "None");
|
||||
dl2 != undefined && (dl2.innerHTML = "None");
|
||||
dl3 != undefined && (dl3.innerHTML = "None");
|
||||
}
|
||||
|
||||
dd != undefined && (dd.innerHTML = d);
|
||||
st != undefined && (st.href='http://twitter.com/share?text='+encodeURIComponent('I just scored '+dt.innerHTML+' in '+'Cityscape ('+d+') on #HexGL! Come try it and beat my record on '));
|
||||
sf != undefined && (sf.href='http://www.facebook.com/sharer.php?s=100'
|
||||
+'&p[title]='+encodeURIComponent('I just scored '+dt.innerHTML+' in '+'Cityscape ('+d+') on HexGL!')
|
||||
+'&p[summary]='+encodeURIComponent('HexGL is a futuristic racing game built by Thibaut Despoulain (BKcore) using HTML5, Javascript and WebGL. Come challenge your friends on this fast-paced 3D game!')
|
||||
+'&p[url]='+encodeURIComponent('http://hexgl.bkcore.com')
|
||||
+'&p[images][0]='+encodeURIComponent('http://hexgl.bkcore.com/image.png'));
|
||||
|
||||
bkcore.hexgl.Ladder.displayLadder('finish-ladder', t, d, 8);
|
||||
|
||||
if(this.manager.get('game').objects.lowFPS >= 999)
|
||||
sl != undefined && (sl.innerHTML = 'Note: Your framerate was pretty low, you should try a lesser graphic setting!');
|
||||
else
|
||||
sl != undefined && (sl.innerHTML = '');
|
||||
|
||||
dc.style.display = 'block';
|
||||
}
|
||||
|
||||
bkcore.hexgl.HexGL.prototype.initRenderer = function()
|
||||
{
|
||||
var renderer = new THREE.WebGLRenderer({
|
||||
antialias: false,
|
||||
clearColor: 0x000000
|
||||
});
|
||||
|
||||
renderer.physicallyBasedShading = true;
|
||||
renderer.gammaInput = true;
|
||||
renderer.gammaOutput = true;
|
||||
|
||||
renderer.shadowMapEnabled = true;
|
||||
renderer.shadowMapSoft = true;
|
||||
|
||||
renderer.autoClear = false;
|
||||
renderer.sortObjects = false;
|
||||
renderer.setSize( this.width, this.height );
|
||||
renderer.domElement.style.position = "relative";
|
||||
|
||||
this.containers.main.appendChild( renderer.domElement );
|
||||
this.renderer = renderer;
|
||||
this.manager = new bkcore.threejs.RenderManager(renderer);
|
||||
}
|
||||
|
||||
bkcore.hexgl.HexGL.prototype.initHUD = function()
|
||||
{
|
||||
this.hud = new bkcore.hexgl.HUD({
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
font: "BebasNeueRegular",
|
||||
bg: this.track.lib.get("images", "hud.bg"),
|
||||
speed: this.track.lib.get("images", "hud.speed"),
|
||||
shield: this.track.lib.get("images", "hud.shield")
|
||||
});
|
||||
this.containers.overlay.appendChild(this.hud.canvas);
|
||||
}
|
||||
|
||||
bkcore.hexgl.HexGL.prototype.initGameComposer = function()
|
||||
{
|
||||
var renderTargetParameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBuffer: false };
|
||||
var renderTarget = new THREE.WebGLRenderTarget( this.width, this.height, renderTargetParameters );
|
||||
|
||||
// GAME COMPOSER
|
||||
var renderSky = new THREE.RenderPass( this.manager.get("sky").scene, this.manager.get("sky").camera );
|
||||
|
||||
var renderModel = new THREE.RenderPass( this.manager.get("game").scene, this.manager.get("game").camera );
|
||||
renderModel.clear = false;
|
||||
|
||||
this.composers.game = new THREE.EffectComposer( this.renderer, renderTarget );
|
||||
|
||||
var effectScreen = new THREE.ShaderPass( THREE.ShaderExtras[ "screen" ] );
|
||||
var effectVignette = new THREE.ShaderPass( THREE.ShaderExtras[ "vignette" ] );
|
||||
|
||||
var effectHex = new THREE.ShaderPass( bkcore.threejs.Shaders[ "hexvignette" ] );
|
||||
effectHex.uniforms[ 'size' ].value = 512.0 * (this.width/1633);
|
||||
effectHex.uniforms[ 'rx' ].value = this.width;
|
||||
effectHex.uniforms[ 'ry' ].value = this.height;
|
||||
effectHex.uniforms[ 'tHex' ].texture = this.track.lib.get("textures", "hex");
|
||||
effectHex.uniforms[ 'color' ].value = this.extras.vignetteColor;
|
||||
|
||||
effectHex.renderToScreen = true;
|
||||
|
||||
this.composers.game.addPass( renderSky );
|
||||
this.composers.game.addPass( renderModel );
|
||||
|
||||
if(this.quality > 0)
|
||||
{
|
||||
var effectFXAA = new THREE.ShaderPass( THREE.ShaderExtras[ "fxaa" ] );
|
||||
effectFXAA.uniforms[ 'resolution' ].value.set( 1 / this.width, 1 / this.height );
|
||||
|
||||
this.composers.game.addPass( effectFXAA );
|
||||
|
||||
this.extras.fxaa = effectFXAA;
|
||||
}
|
||||
if(this.quality > 1)
|
||||
{
|
||||
var effectBloom = new THREE.BloomPass( 0.8, 25, 4 , 256);
|
||||
|
||||
this.composers.game.addPass( effectBloom );
|
||||
|
||||
this.extras.bloom = effectBloom;
|
||||
}
|
||||
|
||||
this.composers.game.addPass( effectHex );
|
||||
|
||||
|
||||
}
|
||||
|
||||
bkcore.hexgl.HexGL.prototype.createMesh = function(parent, geometry, x, y, z, mat)
|
||||
{
|
||||
geometry.computeTangents();
|
||||
|
||||
var mesh = new THREE.Mesh( geometry, mat );
|
||||
mesh.position.set( x, y, z );
|
||||
parent.add(mesh);
|
||||
|
||||
if(this.quality > 0)
|
||||
{
|
||||
mesh.castShadow = true;
|
||||
mesh.receiveShadow = true;
|
||||
}
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
bkcore.hexgl.HexGL.prototype.tweakShipControls = function()
|
||||
{
|
||||
var c = this.components.shipControls;
|
||||
if(this.difficulty == 1)
|
||||
{
|
||||
c.airResist = 0.035;
|
||||
c.airDrift = 0.07;
|
||||
c.thrust = 0.035;
|
||||
c.airBrake = 0.04;
|
||||
c.maxSpeed = 9.6;
|
||||
c.boosterSpeed = c.maxSpeed * 0.35;
|
||||
c.boosterDecay = 0.007;
|
||||
c.angularSpeed = 0.0140;
|
||||
c.airAngularSpeed = 0.0165;
|
||||
c.rollAngle = 0.6;
|
||||
c.shieldDamage = 0.03;
|
||||
c.collisionSpeedDecrease = 0.8;
|
||||
c.collisionSpeedDecreaseCoef = 0.5;
|
||||
c.rollLerp = 0.1;
|
||||
c.driftLerp = 0.4;
|
||||
c.angularLerp = 0.4;
|
||||
}
|
||||
else if(this.difficulty == 0)
|
||||
{
|
||||
c.airResist = 0.02;
|
||||
c.airDrift = 0.06;
|
||||
c.thrust = 0.02;
|
||||
c.airBrake = 0.025;
|
||||
c.maxSpeed = 7.0;
|
||||
c.boosterSpeed = c.maxSpeed * 0.5;
|
||||
c.boosterDecay = 0.007;
|
||||
c.angularSpeed = 0.0125;
|
||||
c.airAngularSpeed = 0.0135;
|
||||
c.rollAngle = 0.6;
|
||||
c.shieldDamage = 0.06;
|
||||
c.collisionSpeedDecrease = 0.8;
|
||||
c.collisionSpeedDecreaseCoef = 0.5;
|
||||
c.rollLerp = 0.07;
|
||||
c.driftLerp = 0.3;
|
||||
c.angularLerp = 0.4;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* HexGL
|
||||
* @author Thibaut 'BKcore' Despoulain <http://bkcore.com>
|
||||
* @license This work is licensed under the Creative Commons Attribution-NonCommercial 3.0 Unported License.
|
||||
* To view a copy of this license, visit http://creativecommons.org/licenses/by-nc/3.0/.
|
||||
*/
|
||||
|
||||
var bkcore = bkcore || {};
|
||||
bkcore.hexgl = bkcore.hexgl || {};
|
||||
|
||||
bkcore.hexgl.Ladder = {};
|
||||
bkcore.hexgl.Ladder.global = {};
|
||||
|
||||
bkcore.hexgl.Ladder.load = function(callback)
|
||||
{
|
||||
var s = encodeURIComponent(window.location.href);
|
||||
bkcore.Utils.request("nothing", false, function(req)
|
||||
{
|
||||
try {
|
||||
bkcore.Ladder.global = JSON.parse(req.responseText);
|
||||
if(callback) callback.call(window);
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
console.warn('Unable to load ladder. '+e);
|
||||
}
|
||||
},
|
||||
{
|
||||
u: s
|
||||
});
|
||||
}
|
||||
|
||||
bkcore.hexgl.Ladder.displayLadder = function(id, track, mode, num)
|
||||
{
|
||||
var d = document.getElementById(id);
|
||||
if(d == undefined || bkcore.Ladder.global[track] == undefined || !bkcore.Ladder.global[track][mode] == undefined)
|
||||
{
|
||||
console.warn('Undefined ladder.');
|
||||
return;
|
||||
}
|
||||
|
||||
var l = bkcore.Ladder.global[track][mode];
|
||||
var h = '';
|
||||
var m = Math.min((num == undefined ? 10 : num), l.length-1);
|
||||
for(var i = 0; i < l.length-1; i++)
|
||||
{
|
||||
var t = bkcore.Timer.msToTime(l[i]['score']);
|
||||
h += '<span class="ladder-row"><b>'+(i+1)+'. '+l[i]['name']+'</b><i>'+t.m+'\''+t.s+'\'\''+t.ms+'</i></span>';
|
||||
}
|
||||
|
||||
d.innerHTML = h;
|
||||
}
|
||||
@@ -0,0 +1,535 @@
|
||||
/*
|
||||
* HexGL
|
||||
* @author Thibaut 'BKcore' Despoulain <http://bkcore.com>
|
||||
* @license This work is licensed under the Creative Commons Attribution-NonCommercial 3.0 Unported License.
|
||||
* To view a copy of this license, visit http://creativecommons.org/licenses/by-nc/3.0/.
|
||||
*/
|
||||
|
||||
var bkcore = bkcore || {};
|
||||
bkcore.hexgl = bkcore.hexgl || {};
|
||||
|
||||
bkcore.hexgl.ShipControls = function(domElement)
|
||||
{
|
||||
var self = this;
|
||||
|
||||
this.active = true;
|
||||
this.destroyed = false;
|
||||
|
||||
this.dom = domElement;
|
||||
this.mesh = null;
|
||||
|
||||
this.epsilon = 0.00000001;
|
||||
this.zero = new THREE.Vector3(0,0,0);
|
||||
this.airResist = 0.02;
|
||||
this.airDrift = 0.1;
|
||||
this.thrust = 0.02;
|
||||
this.airBrake = 0.02;
|
||||
this.maxSpeed = 7.0;
|
||||
this.boosterSpeed = this.maxSpeed * 0.4;
|
||||
this.boosterDecay = 0.01;
|
||||
this.angularSpeed = 0.005;
|
||||
this.airAngularSpeed = 0.0065;
|
||||
this.repulsionRatio = 0.5;
|
||||
this.repulsionCap = 2.5;
|
||||
this.repulsionLerp = 0.1;
|
||||
this.collisionSpeedDecrease = 0.8;
|
||||
this.collisionSpeedDecreaseCoef = 0.8;
|
||||
this.maxShield = 1.0;
|
||||
this.shieldDelay = 60;
|
||||
this.shieldTiming = 0;
|
||||
this.shieldDamage = 0.25;
|
||||
this.driftLerp = 0.35;
|
||||
this.angularLerp = 0.35;
|
||||
|
||||
this.movement = new THREE.Vector3(0,0,0);
|
||||
this.rotation = new THREE.Vector3(0,0,0);
|
||||
this.roll = 0.0;
|
||||
this.rollAxis = new THREE.Vector3();
|
||||
this.drift = 0.0;
|
||||
this.speed = 0.0;
|
||||
this.speedRatio = 0.0;
|
||||
this.boost = 0.0;
|
||||
this.shield = 1.0;
|
||||
this.angular = 0.0;
|
||||
|
||||
this.currentVelocity = new THREE.Vector3();
|
||||
|
||||
this.quaternion = new THREE.Quaternion();
|
||||
|
||||
this.dummy = new THREE.Object3D();
|
||||
this.dummy.useQuaternion = true;
|
||||
|
||||
this.collisionMap = null;
|
||||
this.collisionPixelRatio = 1.0;
|
||||
this.collisionDetection = false;
|
||||
this.collisionPreviousPosition = new THREE.Vector3();
|
||||
|
||||
this.heightMap = null;
|
||||
this.heightPixelRatio = 1.0;
|
||||
this.heightBias = 0.0;
|
||||
this.heightLerp = 0.4;
|
||||
this.heightScale = 1.0;
|
||||
|
||||
this.rollAngle = 0.6;
|
||||
this.rollLerp = 0.08;
|
||||
this.rollDirection = new THREE.Vector3(0,0,1);
|
||||
|
||||
this.gradient = 0.0;
|
||||
this.gradientTarget = 0.0;
|
||||
this.gradientLerp = 0.05;
|
||||
this.gradientScale = 4.0;
|
||||
this.gradientVector = new THREE.Vector3(0,0,5);
|
||||
this.gradientAxis = new THREE.Vector3(1,0,0);
|
||||
|
||||
this.tilt = 0.0;
|
||||
this.tiltTarget = 0.0;
|
||||
this.tiltLerp = 0.05;
|
||||
this.tiltScale = 4.0;
|
||||
this.tiltVector = new THREE.Vector3(5,0,0);
|
||||
this.tiltAxis = new THREE.Vector3(0,0,1);
|
||||
|
||||
this.repulsionVLeft = new THREE.Vector3(1,0,0);
|
||||
this.repulsionVRight = new THREE.Vector3(-1,0,0);
|
||||
this.repulsionVFront = new THREE.Vector3(0,0,1);
|
||||
this.repulsionVScale = 4.0;
|
||||
this.repulsionAmount = 0.0;
|
||||
this.repulsionForce = new THREE.Vector3();
|
||||
|
||||
this.resetPos = null;
|
||||
this.resetRot = null;
|
||||
|
||||
this.key = {
|
||||
forward: false,
|
||||
backward: false,
|
||||
left: false,
|
||||
right: false,
|
||||
ltrigger: false,
|
||||
rtrigger: false,
|
||||
use: false
|
||||
};
|
||||
|
||||
this.collision = {
|
||||
front: false,
|
||||
left: false,
|
||||
right: false
|
||||
};
|
||||
|
||||
function onKeyDown(event)
|
||||
{
|
||||
switch(event.keyCode)
|
||||
{
|
||||
case 38: /*up*/ self.key.forward = true; break;
|
||||
|
||||
case 40: /*down*/self.key.backward = true; break;
|
||||
|
||||
case 37: /*left*/self.key.left = true; break;
|
||||
|
||||
case 39: /*right*/self.key.right = true; break;
|
||||
|
||||
case 81: /*Q*/self.key.ltrigger = true; break;
|
||||
case 65: /*A*/self.key.ltrigger = true; break;
|
||||
|
||||
case 68: /*D*/self.key.rtrigger = true; break;
|
||||
case 69: /*E*/self.key.rtrigger = true; break;
|
||||
}
|
||||
};
|
||||
|
||||
function onKeyUp(event)
|
||||
{
|
||||
switch(event.keyCode)
|
||||
{
|
||||
case 38: /*up*/ self.key.forward = false; break;
|
||||
|
||||
case 40: /*down*/self.key.backward = false; break;
|
||||
|
||||
case 37: /*left*/self.key.left = false; break;
|
||||
|
||||
case 39: /*right*/self.key.right = false; break;
|
||||
|
||||
case 81: /*Q*/self.key.ltrigger = false; break;
|
||||
case 65: /*A*/self.key.ltrigger = false; break;
|
||||
|
||||
case 68: /*D*/self.key.rtrigger = false; break;
|
||||
case 69: /*E*/self.key.rtrigger = false; break;
|
||||
}
|
||||
};
|
||||
|
||||
domElement.addEventListener('keydown', onKeyDown, false);
|
||||
domElement.addEventListener('keyup', onKeyUp, false);
|
||||
};
|
||||
|
||||
bkcore.hexgl.ShipControls.prototype.control = function(threeMesh)
|
||||
{
|
||||
this.mesh = threeMesh;
|
||||
this.mesh.martixAutoUpdate = false;
|
||||
this.dummy.position = this.mesh.position;
|
||||
};
|
||||
|
||||
bkcore.hexgl.ShipControls.prototype.reset = function(position, rotation)
|
||||
{
|
||||
this.resetPos = position;
|
||||
this.resetRot = rotation;
|
||||
this.movement.set(0,0,0);
|
||||
this.rotation.copy(rotation);
|
||||
this.roll = 0.0;
|
||||
this.drift = 0.0;
|
||||
this.speed = 0.0;
|
||||
this.speedRatio = 0.0;
|
||||
this.boost = 0.0;
|
||||
this.shield = this.maxShield;
|
||||
this.destroyed = false;
|
||||
|
||||
this.dummy.position.copy(position);
|
||||
this.quaternion.set(rotation.x, rotation.y, rotation.z, 1).normalize();
|
||||
this.dummy.quaternion.set(0,0,0,1);
|
||||
this.dummy.quaternion.multiplySelf(this.quaternion);
|
||||
|
||||
this.dummy.matrix.setPosition(this.dummy.position);
|
||||
this.dummy.matrix.setRotationFromQuaternion(this.dummy.quaternion);
|
||||
|
||||
this.mesh.matrix.identity();
|
||||
this.mesh.applyMatrix(this.dummy.matrix);
|
||||
}
|
||||
|
||||
bkcore.hexgl.ShipControls.prototype.destroy = function()
|
||||
{
|
||||
this.active = false;
|
||||
this.destroyed = true;
|
||||
this.collision.front = false;
|
||||
this.collision.left = false;
|
||||
this.collision.right = false;
|
||||
}
|
||||
|
||||
bkcore.hexgl.ShipControls.prototype.update = function(dt)
|
||||
{
|
||||
if(!this.active) return;
|
||||
|
||||
this.rotation.y = 0;
|
||||
this.movement.set(0,0,0);
|
||||
this.drift += (0.0 - this.drift) * this.driftLerp;
|
||||
this.angular += (0.0 - this.angular) * this.angularLerp * 0.5;
|
||||
|
||||
var rollAmount = 0.0;
|
||||
var angularAmount = 0.0;
|
||||
|
||||
if(this.key.forward)
|
||||
this.speed += this.thrust * dt;
|
||||
else
|
||||
this.speed -= this.airResist * dt;
|
||||
if(this.key.left)
|
||||
{
|
||||
angularAmount += this.angularSpeed * dt;
|
||||
rollAmount -= this.rollAngle;
|
||||
}
|
||||
if(this.key.right)
|
||||
{
|
||||
angularAmount -= this.angularSpeed * dt;
|
||||
rollAmount += this.rollAngle;
|
||||
}
|
||||
if(this.key.ltrigger)
|
||||
{
|
||||
if(this.key.left)
|
||||
angularAmount += this.airAngularSpeed * dt;
|
||||
else
|
||||
angularAmount += this.airAngularSpeed * 0.5 * dt;
|
||||
this.speed -= this.airBrake * dt;
|
||||
this.drift += (this.airDrift - this.drift) * this.driftLerp;
|
||||
this.movement.x += this.speed * this.drift * dt;
|
||||
if(this.drift > 0.0)
|
||||
this.movement.z -= this.speed * this.drift * dt;
|
||||
rollAmount -= this.rollAngle * 0.7;
|
||||
}
|
||||
if(this.key.rtrigger)
|
||||
{
|
||||
if(this.key.right)
|
||||
angularAmount -= this.airAngularSpeed * dt;
|
||||
else
|
||||
angularAmount -= this.airAngularSpeed * 0.5 * dt;
|
||||
this.speed -= this.airBrake * dt;
|
||||
this.drift += (-this.airDrift - this.drift) * this.driftLerp;
|
||||
this.movement.x += this.speed * this.drift * dt;
|
||||
if(this.drift < 0.0)
|
||||
this.movement.z += this.speed * this.drift * dt;
|
||||
rollAmount += this.rollAngle * 0.7;
|
||||
}
|
||||
|
||||
this.angular += (angularAmount - this.angular) * this.angularLerp;
|
||||
this.rotation.y = this.angular;
|
||||
|
||||
this.speed = Math.max(0.0, Math.min(this.speed, this.maxSpeed));
|
||||
this.speedRatio = this.speed / this.maxSpeed;
|
||||
this.movement.z += this.speed * dt;
|
||||
|
||||
if(this.repulsionForce.isZero())
|
||||
{
|
||||
this.repulsionForce.set(0,0,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(this.repulsionForce.z != 0.0) this.movement.z = 0;
|
||||
this.movement.addSelf(this.repulsionForce);
|
||||
this.repulsionForce.lerpSelf(this.zero, dt > 1.5 ? this.repulsionLerp*2 : this.repulsionLerp);
|
||||
}
|
||||
|
||||
this.collisionPreviousPosition.copy(this.dummy.position);
|
||||
|
||||
this.boosterCheck(dt);
|
||||
|
||||
//this.movement.multiplyScalar(dt);
|
||||
//this.rotation.multiplyScalar(dt);
|
||||
|
||||
this.dummy.translateX(this.movement.x);
|
||||
this.dummy.translateZ(this.movement.z);
|
||||
|
||||
|
||||
this.heightCheck(dt);
|
||||
this.dummy.translateY(this.movement.y);
|
||||
|
||||
this.currentVelocity.copy(this.dummy.position).subSelf(this.collisionPreviousPosition);
|
||||
|
||||
this.collisionCheck(dt);
|
||||
|
||||
this.quaternion.set(this.rotation.x, this.rotation.y, this.rotation.z, 1).normalize();
|
||||
this.dummy.quaternion.multiplySelf(this.quaternion);
|
||||
|
||||
this.dummy.matrix.setPosition(this.dummy.position);
|
||||
this.dummy.matrix.setRotationFromQuaternion(this.dummy.quaternion);
|
||||
|
||||
if(this.shield <= 0.0)
|
||||
{
|
||||
this.shield = 0.0;
|
||||
this.destroy();
|
||||
}
|
||||
|
||||
if(this.mesh != null)
|
||||
{
|
||||
this.mesh.matrix.identity();
|
||||
|
||||
// Gradient (Mesh only, no dummy physics impact)
|
||||
var gradientDelta = (this.gradientTarget - this.gradient) * this.gradientLerp;
|
||||
if(Math.abs(gradientDelta) > this.epsilon) this.gradient += gradientDelta;
|
||||
if(Math.abs(this.gradient) > this.epsilon)
|
||||
{
|
||||
this.gradientAxis.set(1,0,0);
|
||||
this.mesh.matrix.rotateByAxis(this.gradientAxis, this.gradient);
|
||||
}
|
||||
|
||||
// Tilting (Idem)
|
||||
var tiltDelta = (this.tiltTarget - this.tilt) * this.tiltLerp;
|
||||
if(Math.abs(tiltDelta) > this.epsilon) this.tilt += tiltDelta;
|
||||
if(Math.abs(this.tilt) > this.epsilon)
|
||||
{
|
||||
this.tiltAxis.set(0,0,1);
|
||||
this.mesh.matrix.rotateByAxis(this.tiltAxis, this.tilt);
|
||||
}
|
||||
|
||||
// Rolling (Idem)
|
||||
var rollDelta = (rollAmount - this.roll) * this.rollLerp;
|
||||
if(Math.abs(rollDelta) > this.epsilon) this.roll += rollDelta;
|
||||
if(Math.abs(this.roll) > this.epsilon)
|
||||
{
|
||||
this.rollAxis.copy(this.rollDirection);
|
||||
this.mesh.matrix.rotateByAxis(this.rollAxis, this.roll);
|
||||
}
|
||||
|
||||
this.mesh.applyMatrix(this.dummy.matrix);
|
||||
this.mesh.updateMatrixWorld(true);
|
||||
}
|
||||
};
|
||||
|
||||
bkcore.hexgl.ShipControls.prototype.boosterCheck = function(dt)
|
||||
{
|
||||
if(!this.collisionMap || !this.collisionMap.loaded)
|
||||
return false;
|
||||
|
||||
this.boost -= this.boosterDecay * dt;
|
||||
if(this.boost < 0)
|
||||
this.boost = 0.0;
|
||||
|
||||
var x = Math.round(this.collisionMap.pixels.width/2 + this.dummy.position.x * this.collisionPixelRatio);
|
||||
var z = Math.round(this.collisionMap.pixels.height/2 + this.dummy.position.z * this.collisionPixelRatio);
|
||||
var pos = new THREE.Vector3(x, 0, z);
|
||||
|
||||
var color = this.collisionMap.getPixel(x, z);
|
||||
|
||||
if(color.r == 255 && color.g < 127 && color.b < 127)
|
||||
this.boost = this.boosterSpeed;
|
||||
|
||||
this.movement.z += this.boost * dt;
|
||||
}
|
||||
|
||||
bkcore.hexgl.ShipControls.prototype.collisionCheck = function(dt)
|
||||
{
|
||||
if(!this.collisionDetection || !this.collisionMap || !this.collisionMap.loaded)
|
||||
return false;
|
||||
|
||||
if(this.shieldDelay > 0)
|
||||
this.shieldDelay -= dt;
|
||||
|
||||
this.collision.left = false;
|
||||
this.collision.right = false;
|
||||
this.collision.front = false;
|
||||
|
||||
var x = Math.round(this.collisionMap.pixels.width/2 + this.dummy.position.x * this.collisionPixelRatio);
|
||||
var z = Math.round(this.collisionMap.pixels.height/2 + this.dummy.position.z * this.collisionPixelRatio);
|
||||
var pos = new THREE.Vector3(x, 0, z);
|
||||
|
||||
//console.log({c: this.collisionMap.getPixel(414, 670), d: this.dummy.position, x: x, y: y, p: this.collisionMap.getPixel(x, y)})
|
||||
|
||||
var collision = this.collisionMap.getPixelBilinear(x, z);
|
||||
|
||||
if(collision.r < 255)
|
||||
{
|
||||
// Shield
|
||||
var sr = (this.getRealSpeed() / this.maxSpeed);
|
||||
this.shield -= sr * sr * 0.8 * this.shieldDamage;
|
||||
|
||||
// Repulsion
|
||||
this.repulsionVLeft.set(1,0,0);
|
||||
this.repulsionVRight.set(-1,0,0);
|
||||
this.dummy.matrix.rotateAxis(this.repulsionVLeft);
|
||||
this.dummy.matrix.rotateAxis(this.repulsionVRight);
|
||||
this.repulsionVLeft.multiplyScalar(this.repulsionVScale);
|
||||
this.repulsionVRight.multiplyScalar(this.repulsionVScale);
|
||||
|
||||
var lPos = this.repulsionVLeft.addSelf(pos);
|
||||
var rPos = this.repulsionVRight.addSelf(pos);
|
||||
var lCol = this.collisionMap.getPixel(Math.round(lPos.x), Math.round(lPos.z)).r;
|
||||
var rCol = this.collisionMap.getPixel(Math.round(rPos.x), Math.round(rPos.z)).r;
|
||||
|
||||
this.repulsionAmount = Math.max(0.8,
|
||||
Math.min(this.repulsionCap,
|
||||
this.speed * this.repulsionRatio
|
||||
)
|
||||
);
|
||||
|
||||
if(rCol > lCol)
|
||||
{// Repulse right
|
||||
this.repulsionForce.x += -this.repulsionAmount;
|
||||
this.collision.left = true;
|
||||
}
|
||||
else if(rCol < lCol)
|
||||
{// Repulse left
|
||||
this.repulsionForce.x += this.repulsionAmount;
|
||||
this.collision.right = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//console.log(collision.r+" -- "+fCol+" @ "+lCol+" / "+rCol);
|
||||
this.repulsionForce.z += -this.repulsionAmount*4;
|
||||
this.collision.front = true;
|
||||
this.speed = 0;
|
||||
}
|
||||
|
||||
this.speed *= this.collisionSpeedDecrease;
|
||||
this.speed *= (1-this.collisionSpeedDecreaseCoef*(1-collision.r/255));
|
||||
this.boost = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bkcore.hexgl.ShipControls.prototype.heightCheck = function(dt)
|
||||
{
|
||||
if(!this.heightMap || !this.heightMap.loaded)
|
||||
return false;
|
||||
|
||||
var x = this.heightMap.pixels.width/2 + this.dummy.position.x * this.heightPixelRatio;
|
||||
var z = this.heightMap.pixels.height/2 + this.dummy.position.z * this.heightPixelRatio;
|
||||
var height = this.heightMap.getPixelFBilinear(x, z) / this.heightScale + this.heightBias;
|
||||
|
||||
var color = this.heightMap.getPixel(x, z);
|
||||
|
||||
if(height < 16777)
|
||||
{
|
||||
var delta = (height - this.dummy.position.y);
|
||||
|
||||
if(delta > 0)
|
||||
{
|
||||
this.movement.y += delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.movement.y += delta * this.heightLerp;
|
||||
}
|
||||
}
|
||||
|
||||
// gradient
|
||||
this.gradientVector.set(0,0,5);
|
||||
this.dummy.matrix.rotateAxis(this.gradientVector);
|
||||
this.gradientVector.addSelf(this.dummy.position);
|
||||
|
||||
x = this.heightMap.pixels.width/2 + this.gradientVector.x * this.heightPixelRatio;
|
||||
z = this.heightMap.pixels.height/2 + this.gradientVector.z * this.heightPixelRatio;
|
||||
|
||||
var nheight = this.heightMap.getPixelFBilinear(x, z) / this.heightScale + this.heightBias;
|
||||
|
||||
if(nheight < 16777)
|
||||
this.gradientTarget = -Math.atan2(nheight-height, 5.0)*this.gradientScale;
|
||||
|
||||
// tilt
|
||||
this.tiltVector.set(5,0,0);
|
||||
this.dummy.matrix.rotateAxis(this.tiltVector);
|
||||
this.tiltVector.addSelf(this.dummy.position);
|
||||
|
||||
x = this.heightMap.pixels.width/2 + this.tiltVector.x * this.heightPixelRatio;
|
||||
z = this.heightMap.pixels.height/2 + this.tiltVector.z * this.heightPixelRatio;
|
||||
|
||||
nheight = this.heightMap.getPixelFBilinear(x, z) / this.heightScale + this.heightBias;
|
||||
|
||||
if(nheight >= 16777) // If right project out of bounds, try left projection
|
||||
{
|
||||
this.tiltVector.subSelf(this.dummy.position).multiplyScalar(-1).addSelf(this.dummy.position);
|
||||
|
||||
x = this.heightMap.pixels.width/2 + this.tiltVector.x * this.heightPixelRatio;
|
||||
z = this.heightMap.pixels.height/2 + this.tiltVector.z * this.heightPixelRatio;
|
||||
|
||||
nheight = this.heightMap.getPixelFBilinear(x, z) / this.heightScale + this.heightBias;
|
||||
}
|
||||
|
||||
if(nheight < 16777)
|
||||
this.tiltTarget = Math.atan2(nheight-height, 5.0)*this.tiltScale;
|
||||
};
|
||||
|
||||
bkcore.hexgl.ShipControls.prototype.getRealSpeed = function(scale)
|
||||
{
|
||||
return Math.round(
|
||||
(this.speed+this.boost)
|
||||
* (scale == undefined ? 1 : scale)
|
||||
);
|
||||
};
|
||||
|
||||
bkcore.hexgl.ShipControls.prototype.getRealSpeedRatio = function()
|
||||
{
|
||||
return Math.min(
|
||||
this.maxSpeed,
|
||||
this.speed+this.boost
|
||||
) / this.maxSpeed;
|
||||
};
|
||||
|
||||
bkcore.hexgl.ShipControls.prototype.getSpeedRatio = function()
|
||||
{
|
||||
return (this.speed+this.boost)/ this.maxSpeed;
|
||||
};
|
||||
|
||||
bkcore.hexgl.ShipControls.prototype.getBoostRatio = function()
|
||||
{
|
||||
return this.boost / this.boosterSpeed;
|
||||
};
|
||||
|
||||
bkcore.hexgl.ShipControls.prototype.getShieldRatio = function()
|
||||
{
|
||||
return this.shield / this.maxShield;
|
||||
};
|
||||
|
||||
bkcore.hexgl.ShipControls.prototype.getShield = function(scale)
|
||||
{
|
||||
return Math.round(
|
||||
this.shield
|
||||
* (scale == undefined ? 1 : scale)
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* HexGL
|
||||
* @author Thibaut 'BKcore' Despoulain <http://bkcore.com>
|
||||
* @license This work is licensed under the Creative Commons Attribution-NonCommercial 3.0 Unported License.
|
||||
* To view a copy of this license, visit http://creativecommons.org/licenses/by-nc/3.0/.
|
||||
*/
|
||||
|
||||
var bkcore = bkcore || {};
|
||||
bkcore.hexgl = bkcore.hexgl || {};
|
||||
|
||||
bkcore.hexgl.ShipEffects = function(opts)
|
||||
{
|
||||
this.scene = opts.scene;
|
||||
this.shipControls = opts.shipControls;
|
||||
|
||||
this.booster = opts.booster;
|
||||
this.boosterLight = opts.boosterLight;
|
||||
this.boosterSprite = opts.boosterSprite;
|
||||
|
||||
this.useParticles = opts.useParticles;
|
||||
|
||||
if(this.useParticles)
|
||||
{
|
||||
this.pVel = new THREE.Vector3(0.5,0,0);
|
||||
this.pOffset = new THREE.Vector3(-3,-0.3,0);
|
||||
this.pRad = new THREE.Vector3(0,0,1.5);
|
||||
|
||||
this.shipVelocity = new THREE.Vector3();
|
||||
|
||||
this.pVelS = this.pVel.length();
|
||||
this.pOffsetS = this.pOffset.length();
|
||||
this.pRadS = this.pRad.length();
|
||||
|
||||
this.pVel.normalize();
|
||||
this.pOffset.normalize();
|
||||
this.pRad.normalize();
|
||||
|
||||
this.particles = {
|
||||
|
||||
leftSparks: new bkcore.threejs.Particles(
|
||||
{
|
||||
randomness: new THREE.Vector3(0.4,0.4,0.4),
|
||||
tint: 0xffffff,
|
||||
color: 0xffc000,
|
||||
color2: 0xffffff,
|
||||
texture: opts.textureSpark,
|
||||
size: 2,
|
||||
life: 60,
|
||||
max: 500
|
||||
}),
|
||||
|
||||
leftClouds: new bkcore.threejs.Particles(
|
||||
{
|
||||
opacity: 0.8,
|
||||
tint: 0xffffff,
|
||||
color: 0x666666,
|
||||
color2: 0xa4f1ff,
|
||||
texture: opts.textureCloud,
|
||||
size: 6,
|
||||
blending: THREE.NormalBlending,
|
||||
life: 60,
|
||||
max: 500,
|
||||
spawn: new THREE.Vector3(3,-0.3,0),
|
||||
spawnRadius: new THREE.Vector3(1,1,2),
|
||||
velocity: new THREE.Vector3(0,0,-0.4),
|
||||
randomness: new THREE.Vector3(0.05,0.05,0.1)
|
||||
}),
|
||||
|
||||
rightSparks: new bkcore.threejs.Particles(
|
||||
{
|
||||
randomness: new THREE.Vector3(0.4,0.4,0.4),
|
||||
tint: 0xffffff,
|
||||
color: 0xffc000,
|
||||
color2: 0xffffff,
|
||||
texture: opts.textureSpark,
|
||||
size: 2,
|
||||
life: 60,
|
||||
max: 500
|
||||
}),
|
||||
|
||||
rightClouds: new bkcore.threejs.Particles(
|
||||
{
|
||||
opacity: 0.8,
|
||||
tint: 0xffffff,
|
||||
color: 0x666666,
|
||||
color2: 0xa4f1ff,
|
||||
texture: opts.textureCloud,
|
||||
size: 6,
|
||||
blending: THREE.NormalBlending,
|
||||
life: 60,
|
||||
max: 500,
|
||||
spawn: new THREE.Vector3(-3,-0.3,0),
|
||||
spawnRadius: new THREE.Vector3(1,1,2),
|
||||
velocity: new THREE.Vector3(0,0,-0.4),
|
||||
randomness: new THREE.Vector3(0.05,0.05,0.1)
|
||||
})
|
||||
};
|
||||
|
||||
this.shipControls.mesh.add(this.particles.leftClouds.system);
|
||||
this.shipControls.mesh.add(this.particles.rightClouds.system);
|
||||
this.scene.add(this.particles.leftSparks.system);
|
||||
this.scene.add(this.particles.rightSparks.system);
|
||||
}
|
||||
}
|
||||
|
||||
bkcore.hexgl.ShipEffects.prototype.update = function(dt)
|
||||
{
|
||||
var boostRatio, opacity, scale, intensity, random;
|
||||
|
||||
if(this.shipControls.destroyed)
|
||||
{
|
||||
opacity = 0;
|
||||
scale = 0;
|
||||
intensity = 0;
|
||||
random = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
boostRatio = this.shipControls.getBoostRatio();
|
||||
opacity = this.shipControls.key.forward ? 0.8 : 0.3 + boostRatio * 0.4;
|
||||
scale = (this.shipControls.key.forward ? 1.0 : 0.8) + boostRatio * 0.5;
|
||||
intensity = this.shipControls.key.forward ? 4.0 : 2.0;
|
||||
random = Math.random()*0.2;
|
||||
}
|
||||
|
||||
if(this.booster)
|
||||
{
|
||||
this.booster.rotation.z += 1;
|
||||
this.booster.scale.set(scale, scale, scale);
|
||||
this.booster.material.opacity = random+opacity;
|
||||
this.boosterSprite.opacity = random+opacity;
|
||||
this.boosterLight.intensity = intensity*(random+0.8);
|
||||
}
|
||||
|
||||
// PARTICLES
|
||||
if(this.useParticles)
|
||||
{
|
||||
this.shipVelocity.copy(this.shipControls.currentVelocity).multiplyScalar(0.7);
|
||||
|
||||
this.particles.rightSparks.velocity.copy(this.pVel);
|
||||
this.particles.rightSparks.spawnRadius.copy(this.pRad);
|
||||
this.particles.rightSparks.spawn.copy(this.pOffset);
|
||||
|
||||
this.particles.leftSparks.velocity.copy(this.pVel).x *= -1;
|
||||
this.particles.leftSparks.spawn.copy(this.pOffset).x *= -1;
|
||||
|
||||
if(this.shipControls.mesh)
|
||||
{
|
||||
// RIGHT
|
||||
this.shipControls.mesh.matrix.rotateAxis(this.particles.rightSparks.spawn);
|
||||
this.particles.rightSparks.spawn.multiplyScalar(this.pOffsetS).addSelf(this.shipControls.dummy.position);
|
||||
|
||||
this.shipControls.mesh.matrix.rotateAxis(this.particles.rightSparks.velocity);
|
||||
this.particles.rightSparks.velocity.multiplyScalar(this.pVelS).addSelf(this.shipVelocity);
|
||||
|
||||
this.shipControls.mesh.matrix.rotateAxis(this.particles.rightSparks.spawnRadius);
|
||||
this.particles.rightSparks.spawnRadius.multiplyScalar(this.pRadS);
|
||||
|
||||
// LEFT
|
||||
this.shipControls.mesh.matrix.rotateAxis(this.particles.leftSparks.spawn);
|
||||
this.particles.leftSparks.spawn.multiplyScalar(this.pOffsetS).addSelf(this.shipControls.dummy.position);
|
||||
|
||||
this.shipControls.mesh.matrix.rotateAxis(this.particles.leftSparks.velocity);
|
||||
this.particles.leftSparks.velocity.multiplyScalar(this.pVelS).addSelf(this.shipVelocity);
|
||||
|
||||
this.particles.leftSparks.spawnRadius.copy(this.particles.rightSparks.spawnRadius);
|
||||
}
|
||||
|
||||
if(this.shipControls.collision.right)
|
||||
{
|
||||
this.particles.rightSparks.emit(Math.round(30*dt));
|
||||
this.particles.rightClouds.emit(Math.round(10*dt));
|
||||
}
|
||||
|
||||
if(this.shipControls.collision.left)
|
||||
{
|
||||
this.particles.leftSparks.emit(Math.round(30*dt));
|
||||
this.particles.leftClouds.emit(Math.round(10*dt));
|
||||
}
|
||||
|
||||
this.particles.rightSparks.update(dt);
|
||||
this.particles.rightClouds.update(dt);
|
||||
this.particles.leftSparks.update(dt);
|
||||
this.particles.leftClouds.update(dt);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,445 @@
|
||||
/*
|
||||
* HexGL
|
||||
* @author Thibaut 'BKcore' Despoulain <http://bkcore.com>
|
||||
* @license This work is licensed under the Creative Commons Attribution-NonCommercial 3.0 Unported License.
|
||||
* To view a copy of this license, visit http://creativecommons.org/licenses/by-nc/3.0/.
|
||||
*/
|
||||
|
||||
var bkcore = bkcore || {};
|
||||
bkcore.hexgl = bkcore.hexgl || {};
|
||||
bkcore.hexgl.tracks = bkcore.hexgl.tracks || {};
|
||||
|
||||
bkcore.hexgl.tracks.Cityscape = {
|
||||
|
||||
lib: null,
|
||||
materials: {},
|
||||
|
||||
checkpoints: {
|
||||
list: [0,1,2],
|
||||
start: 0,
|
||||
last: 2
|
||||
},
|
||||
|
||||
spawn: {
|
||||
x: -1134*2,
|
||||
y: 387,
|
||||
z: -443*2
|
||||
},
|
||||
|
||||
spawnRotation: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
},
|
||||
|
||||
analyser: null,
|
||||
pixelRatio: 2048.0 / 6000.0,
|
||||
|
||||
load: function(opts, quality)
|
||||
{
|
||||
this.lib = new bkcore.threejs.Loader(opts);
|
||||
|
||||
if(quality < 1) // LOW
|
||||
{
|
||||
this.lib.load({
|
||||
textures: {
|
||||
'hex' : "textures/hud/hex.jpg",
|
||||
'ship.feisar.diffuse' : "textures/ships/feisar/diffuse.jpg",
|
||||
'booster.diffuse' : "textures/ships/feisar/booster/booster.png",
|
||||
'booster.sprite' : "textures/ships/feisar/booster/boostersprite.jpg",
|
||||
'track.cityscape.diffuse' : "textures/tracks/cityscape/diffuse.jpg",
|
||||
'track.cityscape.scrapers1.diffuse' : "textures/tracks/cityscape/scrapers1/diffuse.jpg",
|
||||
'track.cityscape.scrapers2.diffuse' : "textures/tracks/cityscape/scrapers2/diffuse.jpg",
|
||||
'track.cityscape.start.diffuse' : "textures/tracks/cityscape/start/diffuse.jpg",
|
||||
'track.cityscape.start.banner' : "textures/tracks/cityscape/start/start.jpg",
|
||||
'bonus.base.diffuse' : "textures/bonus/base/diffuse.jpg"
|
||||
},
|
||||
texturesCube: {
|
||||
'skybox.dawnclouds' : "textures/skybox/dawnclouds/%1.jpg"
|
||||
},
|
||||
geometries: {
|
||||
'bonus.base' : "geometries/bonus/base/base.js",
|
||||
'booster' : "geometries/booster/booster.js",
|
||||
'ship.feisar' : "geometries/ships/feisar/feisar.js",
|
||||
'track.cityscape' : "geometries/tracks/cityscape/track.js",
|
||||
'track.cityscape.scrapers1' : "geometries/tracks/cityscape/scrapers1.js",
|
||||
'track.cityscape.scrapers2' : "geometries/tracks/cityscape/scrapers2.js",
|
||||
'track.cityscape.start' : "geometries/tracks/cityscape/start.js",
|
||||
'track.cityscape.start.banner' : "geometries/tracks/cityscape/startbanner.js",
|
||||
'track.cityscape.bonus.speed' : "geometries/tracks/cityscape/bonus/speed.js"
|
||||
},
|
||||
analysers: {
|
||||
'track.cityscape.collision' : "textures/tracks/cityscape/collision.png",
|
||||
'track.cityscape.height' : "textures/tracks/cityscape/height.png"
|
||||
},
|
||||
images: {
|
||||
'hud.bg' : "textures/hud/hud-bg.png",
|
||||
'hud.speed' : "textures/hud/hud-fg-speed.png",
|
||||
'hud.shield' : "textures/hud/hud-fg-shield.png"
|
||||
}
|
||||
});
|
||||
}
|
||||
else // HIGH
|
||||
{
|
||||
this.lib.load({
|
||||
textures: {
|
||||
'hex' : "textures/hud/hex.jpg",
|
||||
'spark' : "textures/particles/spark.png",
|
||||
'cloud' : "textures/particles/cloud.png",
|
||||
'ship.feisar.diffuse' : "textures/ships/feisar/diffuse.jpg",
|
||||
'ship.feisar.specular' : "textures/ships/feisar/specular.jpg",
|
||||
'ship.feisar.normal' : "textures/ships/feisar/normal.jpg",
|
||||
'booster.diffuse' : "textures/ships/feisar/booster/booster.png",
|
||||
'booster.sprite' : "textures/ships/feisar/booster/boostersprite.jpg",
|
||||
'track.cityscape.diffuse' : "textures/tracks/cityscape/diffuse.jpg",
|
||||
'track.cityscape.specular' : "textures/tracks/cityscape/specular.jpg",
|
||||
'track.cityscape.normal' : "textures/tracks/cityscape/normal.jpg",
|
||||
'track.cityscape.scrapers1.diffuse' : "textures/tracks/cityscape/scrapers1/diffuse.jpg",
|
||||
'track.cityscape.scrapers1.specular': "textures/tracks/cityscape/scrapers1/specular.jpg",
|
||||
'track.cityscape.scrapers1.normal' : "textures/tracks/cityscape/scrapers1/normal.jpg",
|
||||
'track.cityscape.scrapers2.diffuse' : "textures/tracks/cityscape/scrapers2/diffuse.jpg",
|
||||
'track.cityscape.scrapers2.specular': "textures/tracks/cityscape/scrapers2/specular.jpg",
|
||||
'track.cityscape.scrapers2.normal' : "textures/tracks/cityscape/scrapers2/normal.jpg",
|
||||
'track.cityscape.start.diffuse' : "textures/tracks/cityscape/start/diffuse.jpg",
|
||||
'track.cityscape.start.specular' : "textures/tracks/cityscape/start/specular.jpg",
|
||||
'track.cityscape.start.normal' : "textures/tracks/cityscape/start/normal.jpg",
|
||||
'track.cityscape.start.banner' : "textures/tracks/cityscape/start/start.jpg",
|
||||
'bonus.base.diffuse' : "textures/bonus/base/diffuse.jpg",
|
||||
'bonus.base.normal' : "textures/bonus/base/normal.jpg",
|
||||
'bonus.base.specular' : "textures/bonus/base/specular.jpg"
|
||||
},
|
||||
texturesCube: {
|
||||
'skybox.dawnclouds' : "textures/skybox/dawnclouds/%1.jpg"
|
||||
},
|
||||
geometries: {
|
||||
'bonus.base' : "geometries/bonus/base/base.js",
|
||||
'booster' : "geometries/booster/booster.js",
|
||||
'ship.feisar' : "geometries/ships/feisar/feisar.js",
|
||||
'track.cityscape' : "geometries/tracks/cityscape/track.js",
|
||||
'track.cityscape.scrapers1' : "geometries/tracks/cityscape/scrapers1.js",
|
||||
'track.cityscape.scrapers2' : "geometries/tracks/cityscape/scrapers2.js",
|
||||
'track.cityscape.start' : "geometries/tracks/cityscape/start.js",
|
||||
'track.cityscape.start.banner' : "geometries/tracks/cityscape/startbanner.js",
|
||||
'track.cityscape.bonus.speed' : "geometries/tracks/cityscape/bonus/speed.js"
|
||||
},
|
||||
analysers: {
|
||||
'track.cityscape.collision' : "textures/tracks/cityscape/collision.png",
|
||||
'track.cityscape.height' : "textures/tracks/cityscape/height.png"
|
||||
},
|
||||
images: {
|
||||
'hud.bg' : "textures/hud/hud-bg.png",
|
||||
'hud.speed' : "textures/hud/hud-fg-speed.png",
|
||||
'hud.shield' : "textures/hud/hud-fg-shield.png"
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
buildMaterials: function(quality)
|
||||
{
|
||||
if(this.quality < 1) // LOW
|
||||
{
|
||||
this.materials.track = new THREE.MeshBasicMaterial({
|
||||
map: this.lib.get("textures", "track.cityscape.diffuse"),
|
||||
ambient: 0xcccccc
|
||||
});
|
||||
|
||||
this.materials.bonusBase = new THREE.MeshBasicMaterial({
|
||||
map: this.lib.get("textures", "bonus.base.diffuse"),
|
||||
ambient: 0xcccccc
|
||||
});
|
||||
|
||||
this.materials.bonusSpeed = new THREE.MeshBasicMaterial({
|
||||
color: 0x0096ff
|
||||
});
|
||||
|
||||
this.materials.ship = new THREE.MeshBasicMaterial({
|
||||
map: this.lib.get("textures", "ship.feisar.diffuse"),
|
||||
ambient: 0xaaaaaa
|
||||
});
|
||||
|
||||
this.materials.booster = new THREE.MeshBasicMaterial({
|
||||
map: this.lib.get("textures", "booster.diffuse"),
|
||||
transparent: true
|
||||
});
|
||||
|
||||
this.materials.scrapers1 = new THREE.MeshBasicMaterial({
|
||||
map: this.lib.get("textures", "track.cityscape.scrapers1.diffuse"),
|
||||
ambient: 0xcccccc
|
||||
});
|
||||
|
||||
this.materials.scrapers2 = new THREE.MeshBasicMaterial({
|
||||
map: this.lib.get("textures", "track.cityscape.scrapers2.diffuse"),
|
||||
ambient: 0xcccccc
|
||||
});
|
||||
|
||||
this.materials.start = new THREE.MeshBasicMaterial({
|
||||
map: this.lib.get("textures", "track.cityscape.start.diffuse"),
|
||||
ambient: 0xcccccc
|
||||
});
|
||||
|
||||
this.materials.startBanner = new THREE.MeshBasicMaterial({
|
||||
map: this.lib.get("textures", "track.cityscape.start.banner"),
|
||||
transparent: false
|
||||
});
|
||||
}
|
||||
else // HIGH
|
||||
{
|
||||
this.materials.track = bkcore.Utils.createNormalMaterial({
|
||||
diffuse: this.lib.get("textures", "track.cityscape.diffuse"),
|
||||
specular: this.lib.get("textures", "track.cityscape.specular"),
|
||||
normal: this.lib.get("textures", "track.cityscape.normal"),
|
||||
ambient: 0xffffff,
|
||||
shininess: 42,
|
||||
metal: true,
|
||||
perPixel: true
|
||||
});
|
||||
|
||||
this.materials.bonusBase = bkcore.Utils.createNormalMaterial({
|
||||
diffuse: this.lib.get("textures", "bonus.base.diffuse"),
|
||||
specular: this.lib.get("textures", "bonus.base.specular"),
|
||||
normal: this.lib.get("textures", "bonus.base.normal"),
|
||||
normalScale: 3.0,
|
||||
ambient: 0x444444,
|
||||
shininess: 42,
|
||||
metal: false,
|
||||
perPixel: false
|
||||
});
|
||||
|
||||
this.materials.bonusSpeed = new THREE.MeshBasicMaterial({
|
||||
color: 0x0096ff
|
||||
});
|
||||
|
||||
this.materials.ship = bkcore.Utils.createNormalMaterial({
|
||||
diffuse: this.lib.get("textures", "ship.feisar.diffuse"),
|
||||
specular: this.lib.get("textures", "ship.feisar.specular"),
|
||||
normal: this.lib.get("textures", "ship.feisar.normal"),
|
||||
ambient: 0x444444,
|
||||
shininess: 42,
|
||||
metal: true,
|
||||
perPixel: false
|
||||
});
|
||||
|
||||
this.materials.booster = new THREE.MeshBasicMaterial({
|
||||
map: this.lib.get("textures", "booster.diffuse"),
|
||||
transparent: true
|
||||
});
|
||||
|
||||
this.materials.scrapers1 = bkcore.Utils.createNormalMaterial({
|
||||
diffuse: this.lib.get("textures", "track.cityscape.scrapers1.diffuse"),
|
||||
specular: this.lib.get("textures", "track.cityscape.scrapers1.specular"),
|
||||
normal: this.lib.get("textures", "track.cityscape.scrapers1.normal"),
|
||||
cube: this.lib.get("texturesCube", "skybox.dawnclouds"),
|
||||
reflectivity: 0.8,
|
||||
ambient: 0x444444,
|
||||
shininess: 42,
|
||||
metal: false,
|
||||
perPixel: false
|
||||
});
|
||||
|
||||
this.materials.scrapers2 = bkcore.Utils.createNormalMaterial({
|
||||
diffuse: this.lib.get("textures", "track.cityscape.scrapers2.diffuse"),
|
||||
specular: this.lib.get("textures", "track.cityscape.scrapers2.specular"),
|
||||
normal: this.lib.get("textures", "track.cityscape.scrapers2.normal"),
|
||||
cube: this.lib.get("texturesCube", "skybox.dawnclouds"),
|
||||
reflectivity: 0.8,
|
||||
ambient: 0x000000,
|
||||
shininess: 42,
|
||||
metal: false,
|
||||
perPixel: false
|
||||
});
|
||||
|
||||
this.materials.start = bkcore.Utils.createNormalMaterial({
|
||||
diffuse: this.lib.get("textures", "track.cityscape.start.diffuse"),
|
||||
specular: this.lib.get("textures", "track.cityscape.start.specular"),
|
||||
normal: this.lib.get("textures", "track.cityscape.start.normal"),
|
||||
ambient: 0xaaaaaa,
|
||||
shininess: 42,
|
||||
metal: false,
|
||||
perPixel: false
|
||||
});
|
||||
|
||||
this.materials.startBanner = new THREE.MeshBasicMaterial({
|
||||
map: this.lib.get("textures", "track.cityscape.start.banner"),
|
||||
transparent: false
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
buildScenes: function(ctx, quality)
|
||||
{
|
||||
// IMPORTANT
|
||||
this.analyser = this.lib.get("analysers", "track.cityscape.collision");
|
||||
|
||||
// SKYBOX
|
||||
var sceneCube = new THREE.Scene();
|
||||
|
||||
var cameraCube = new THREE.PerspectiveCamera( 70, ctx.width / ctx.height, 1, 6000 );
|
||||
sceneCube.add( cameraCube );
|
||||
|
||||
var skyshader = THREE.ShaderUtils.lib[ "cube" ];
|
||||
skyshader.uniforms[ "tCube" ].texture = this.lib.get("texturesCube", "skybox.dawnclouds");
|
||||
|
||||
var skymaterial = new THREE.ShaderMaterial(
|
||||
{
|
||||
fragmentShader: skyshader.fragmentShader,
|
||||
vertexShader: skyshader.vertexShader,
|
||||
uniforms: skyshader.uniforms,
|
||||
depthWrite: false
|
||||
});
|
||||
|
||||
var mesh = new THREE.Mesh( new THREE.CubeGeometry( 100, 100, 100 ), skymaterial );
|
||||
mesh.flipSided = true;
|
||||
|
||||
sceneCube.add(mesh);
|
||||
|
||||
ctx.manager.add("sky", sceneCube, cameraCube);
|
||||
|
||||
var ambient = 0xbbbbbb, diffuse = 0xffffff, specular = 0xffffff, shininess = 42, scale = 23;
|
||||
|
||||
// MAIN SCENE
|
||||
var camera = new THREE.PerspectiveCamera( 70, ctx.width / ctx.height, 1, 60000 );
|
||||
|
||||
var scene = new THREE.Scene();
|
||||
scene.add( camera );
|
||||
scene.add( new THREE.AmbientLight( ambient ) );
|
||||
|
||||
// SUN
|
||||
var sun = new THREE.DirectionalLight( diffuse, 1.5, 30000 );
|
||||
sun.position.set( -4000, 1200, 1800 );
|
||||
sun.lookAt(new THREE.Vector3());
|
||||
|
||||
if(quality > 0)
|
||||
{
|
||||
sun.castShadow = true;
|
||||
sun.shadowCameraNear = 50;
|
||||
sun.shadowCameraFar = camera.far*2;
|
||||
sun.shadowCameraRight = 3000;
|
||||
sun.shadowCameraLeft = -3000;
|
||||
sun.shadowCameraTop = 3000;
|
||||
sun.shadowCameraBottom = -3000;
|
||||
//sun.shadowCameraVisible = true;
|
||||
sun.shadowBias = 0.0001;
|
||||
sun.shadowDarkness = 0.7;
|
||||
sun.shadowMapWidth = 2048;
|
||||
sun.shadowMapHeight = 2048;
|
||||
}
|
||||
scene.add( sun );
|
||||
|
||||
// SHIP
|
||||
var ship = ctx.createMesh(scene, this.lib.get("geometries", "ship.feisar"), -1134*2, 10, -443*2, this.materials.ship);
|
||||
|
||||
var booster = ctx.createMesh(ship, this.lib.get("geometries", "booster"), 0, 0.665, -3.8, this.materials.booster);
|
||||
booster.depthWrite = false;
|
||||
|
||||
var boosterSprite = new THREE.Sprite({
|
||||
map: this.lib.get("textures", "booster.sprite"),
|
||||
blending: THREE.AdditiveBlending,
|
||||
useScreenCoordinates: false,
|
||||
color: 0xffffff
|
||||
});
|
||||
boosterSprite.scale.set(0.02, 0.02, 0.02);
|
||||
boosterSprite.mergeWith3D = false;
|
||||
booster.add(boosterSprite);
|
||||
|
||||
var boosterLight = new THREE.PointLight(0x00a2ff, 4.0, 60);
|
||||
boosterLight.position.set(0, 0.665, -4);
|
||||
if(quality > 0)
|
||||
ship.add(boosterLight);
|
||||
|
||||
// SHIP CONTROLS
|
||||
var shipControls = new bkcore.hexgl.ShipControls(ctx.document);
|
||||
shipControls.collisionMap = this.lib.get("analysers", "track.cityscape.collision");
|
||||
shipControls.collisionPixelRatio = 2048.0 / 6000.0;
|
||||
shipControls.collisionDetection = true;
|
||||
shipControls.heightMap = this.lib.get("analysers", "track.cityscape.height");;
|
||||
shipControls.heightPixelRatio = 2048.0 / 6000.0;
|
||||
shipControls.heightBias = 4.0;
|
||||
shipControls.heightScale = 10.0;
|
||||
shipControls.control(ship);
|
||||
ctx.components.shipControls = shipControls;
|
||||
ctx.tweakShipControls();
|
||||
|
||||
// SHIP EFFECTS AND PARTICLES
|
||||
var fxParams = {
|
||||
scene: scene,
|
||||
shipControls: shipControls,
|
||||
booster: booster,
|
||||
boosterSprite: boosterSprite,
|
||||
boosterLight: boosterLight,
|
||||
useParticles: false
|
||||
};
|
||||
if(quality > 0)
|
||||
{
|
||||
fxParams.textureCloud = this.lib.get("textures", "cloud");
|
||||
fxParams.textureSpark = this.lib.get("textures", "spark");
|
||||
fxParams.useParticles = true;
|
||||
}
|
||||
ctx.components.shipEffects = new bkcore.hexgl.ShipEffects(fxParams);
|
||||
|
||||
// TRACK
|
||||
var track = ctx.createMesh(scene, this.lib.get("geometries", "track.cityscape"), 0, -5, 0, this.materials.track);
|
||||
var bonusBase = ctx.createMesh(scene, this.lib.get("geometries", "bonus.base"), 0, -5, 0, this.materials.bonusBase);
|
||||
var bonusSpeed = ctx.createMesh(scene, this.lib.get("geometries", "track.cityscape.bonus.speed"), 0, -5, 0, this.materials.bonusSpeed);
|
||||
bonusSpeed.receiveShadow = false;
|
||||
var scrapers1 = ctx.createMesh(scene, this.lib.get("geometries", "track.cityscape.scrapers1"), 0, 0, 0, this.materials.scrapers1);
|
||||
var scrapers2 = ctx.createMesh(scene, this.lib.get("geometries", "track.cityscape.scrapers2"), 0, 0, 0, this.materials.scrapers2);
|
||||
var start = ctx.createMesh(scene, this.lib.get("geometries", "track.cityscape.start"), 0, -5, 0, this.materials.start);
|
||||
var startbanner = ctx.createMesh(scene, this.lib.get("geometries", "track.cityscape.start.banner"), 0, -5, 0, this.materials.startBanner);
|
||||
startbanner.doubleSided = true;
|
||||
|
||||
// CAMERA
|
||||
ctx.components.cameraChase = new bkcore.hexgl.CameraChase({
|
||||
target: ship,
|
||||
camera: camera,
|
||||
cameraCube: ctx.manager.get("sky").camera,
|
||||
lerp: 0.5,
|
||||
yoffset: 8.0,
|
||||
zoffset: 10.0,
|
||||
viewOffset: 10.0
|
||||
});
|
||||
|
||||
ctx.manager.add("game", scene, camera, function(delta, renderer)
|
||||
{
|
||||
if(delta > 25 && this.objects.lowFPS < 1000) this.objects.lowFPS++;
|
||||
|
||||
var dt = delta/16.6;
|
||||
|
||||
this.objects.components.shipControls.update(dt);
|
||||
|
||||
this.objects.components.shipEffects.update(dt);
|
||||
|
||||
this.objects.components.cameraChase.update(dt, this.objects.components.shipControls.getSpeedRatio());
|
||||
/*this.objects.time += 0.002;
|
||||
var c = this.objects.components.cameraChase.camera;
|
||||
c.position.set(
|
||||
Math.cos(this.objects.time)*15+this.objects.components.shipControls.dummy.position.x,
|
||||
10+this.objects.components.shipControls.dummy.position.y,
|
||||
Math.sin(this.objects.time)*15+this.objects.components.shipControls.dummy.position.z
|
||||
);
|
||||
c.lookAt(this.objects.components.shipControls.dummy.position);
|
||||
this.objects.components.cameraChase.cameraCube.rotation.copy(c.rotation);*/
|
||||
|
||||
this.objects.composers.game.render(dt);
|
||||
this.objects.hud.update(
|
||||
this.objects.components.shipControls.getRealSpeed(100),
|
||||
this.objects.components.shipControls.getRealSpeedRatio(),
|
||||
this.objects.components.shipControls.getShield(100),
|
||||
this.objects.components.shipControls.getShieldRatio()
|
||||
);
|
||||
if(this.objects.components.shipControls.getShieldRatio() < 0.2)
|
||||
this.objects.extras.vignetteColor.setHex(0x992020);
|
||||
else
|
||||
this.objects.extras.vignetteColor.setHex(0x458ab1);
|
||||
},
|
||||
{
|
||||
components: ctx.components,
|
||||
composers: ctx.composers,
|
||||
extras: ctx.extras,
|
||||
quality: quality,
|
||||
hud: ctx.hud,
|
||||
time: 0.0,
|
||||
lowFPS: 0
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
/*!
|
||||
* @class bkcore.threejs.Loader
|
||||
*
|
||||
* Loads multiple recources, get progress, callback friendly.
|
||||
* Supports textures, texturesCube, geometries, analysers, images.
|
||||
*
|
||||
* @author Thibaut 'BKcore' Despoulain <http://bkcore.com>
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @package bkcore.threejs
|
||||
*/
|
||||
var bkcore = bkcore || {};
|
||||
bkcore.threejs = bkcore.threejs || {};
|
||||
|
||||
bkcore.NONE = undefined;
|
||||
|
||||
/**
|
||||
* Creates a new loader
|
||||
* @param {Object{onLoad, onError, onProgress}} opts Callbacks
|
||||
*/
|
||||
bkcore.threejs.Loader = function(opts)
|
||||
{
|
||||
var self = this;
|
||||
|
||||
this.jsonLoader = new THREE.JSONLoader();
|
||||
|
||||
this.errorCallback = opts.onError == undefined ? function(s){ console.warn("Error while loading %s.".replace("%s", s)) } : opts.onError;
|
||||
this.loadCallback = opts.onLoad == undefined ? function(){ console.log("Loaded.") } : opts.onLoad;
|
||||
this.progressCallback = opts.onProgress == undefined ? function(progress, type, name){ /**/ } : opts.onProgress;
|
||||
|
||||
this.types = {
|
||||
textures: null,
|
||||
texturesCube: null,
|
||||
geometries: null,
|
||||
analysers: null,
|
||||
images: null,
|
||||
sounds: null
|
||||
};
|
||||
|
||||
this.states = {};
|
||||
this.data = {};
|
||||
|
||||
for(var t in this.types)
|
||||
{
|
||||
this.data[t] = {};
|
||||
this.states[t] = {};
|
||||
}
|
||||
|
||||
this.progress = {
|
||||
total: 0,
|
||||
remaining: 0,
|
||||
loaded: 0,
|
||||
finished: false
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the given list of resources
|
||||
* @param {textures, texturesCube, geometries, analysers, images} data
|
||||
*/
|
||||
bkcore.threejs.Loader.prototype.load = function(data)
|
||||
{
|
||||
var self = this;
|
||||
|
||||
for(var k in this.types)
|
||||
{
|
||||
if(k in data)
|
||||
{
|
||||
var size = 0;
|
||||
for(var j in data[k])
|
||||
size++;
|
||||
this.progress.total += size;
|
||||
this.progress.remaining += size;
|
||||
}
|
||||
}
|
||||
|
||||
for(var t in data.textures)
|
||||
this.loadTexture(t, data.textures[t]);
|
||||
|
||||
for(var c in data.texturesCube)
|
||||
this.loadTextureCube(c, data.texturesCube[c]);
|
||||
|
||||
for(var g in data.geometries)
|
||||
this.loadGeometry(g, data.geometries[g]);
|
||||
|
||||
for(var a in data.analysers)
|
||||
this.loadAnalyser(a, data.analysers[a]);
|
||||
|
||||
for(var i in data.images)
|
||||
this.loadImage(i, data.images[i]);
|
||||
|
||||
this.progressCallback.call(this, this.progress);
|
||||
}
|
||||
|
||||
bkcore.threejs.Loader.prototype.updateState = function(type, name, state)
|
||||
{
|
||||
if(!(type in this.types))
|
||||
{
|
||||
console.warn("Unkown loader type.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(state == true)
|
||||
{
|
||||
this.progress.remaining--;
|
||||
this.progress.loaded++;
|
||||
this.progressCallback.call(this, this.progress, type, name);
|
||||
}
|
||||
|
||||
this.states[type][name] = state;
|
||||
|
||||
|
||||
if(this.progress.loaded == this.progress.total)
|
||||
{
|
||||
this.loadCallback.call(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get loaded resource
|
||||
* @param string type [textures, texturesCube, geometries, analysers, images]
|
||||
* @param string name
|
||||
* @return Mixed
|
||||
*/
|
||||
bkcore.threejs.Loader.prototype.get = function(type, name)
|
||||
{
|
||||
if(!(type in this.types))
|
||||
{
|
||||
console.warn("Unkown loader type.");
|
||||
return null;
|
||||
}
|
||||
if(!(name in this.data[type]))
|
||||
{
|
||||
console.warn("Unkown file.");
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.data[type][name];
|
||||
}
|
||||
|
||||
bkcore.threejs.Loader.prototype.loaded = function(type, name)
|
||||
{
|
||||
if(!(type in this.types))
|
||||
{
|
||||
console.warn("Unkown loader type.");
|
||||
return null;
|
||||
}
|
||||
if(!(name in this.states[type]))
|
||||
{
|
||||
console.warn("Unkown file.");
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.states[type][name];
|
||||
}
|
||||
|
||||
bkcore.threejs.Loader.prototype.loadTexture = function(name, url)
|
||||
{
|
||||
var self = this;
|
||||
this.updateState("textures", name, false);
|
||||
this.data.textures[name] = THREE.ImageUtils.loadTexture(
|
||||
url,
|
||||
bkcore.NONE,
|
||||
function(){
|
||||
self.updateState("textures", name, true);
|
||||
},
|
||||
function(){
|
||||
self.errorCallback.call(self, name);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
bkcore.threejs.Loader.prototype.loadTextureCube = function(name, url)
|
||||
{
|
||||
var self = this;
|
||||
|
||||
var urls = [
|
||||
url.replace("%1", "px"), url.replace("%1", "nx"),
|
||||
url.replace("%1", "py"), url.replace("%1", "ny"),
|
||||
url.replace("%1", "pz"), url.replace("%1", "nz")
|
||||
];
|
||||
|
||||
this.updateState("texturesCube", name, false);
|
||||
this.data.texturesCube[name] = THREE.ImageUtils.loadTextureCube(
|
||||
urls,
|
||||
new THREE.CubeRefractionMapping(),
|
||||
function(){
|
||||
self.updateState("texturesCube", name, true);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
bkcore.threejs.Loader.prototype.loadGeometry = function(name, url)
|
||||
{
|
||||
var self = this;
|
||||
this.data.geometries[name] = null;
|
||||
this.updateState("geometries", name, false);
|
||||
this.jsonLoader.load(
|
||||
url,
|
||||
function(a){
|
||||
self.data.geometries[name] = a;
|
||||
self.updateState("geometries", name, true);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
bkcore.threejs.Loader.prototype.loadAnalyser = function(name, url)
|
||||
{
|
||||
var self = this;
|
||||
this.updateState("analysers", name, false);
|
||||
this.data.analysers[name] = new bkcore.ImageData(
|
||||
url,
|
||||
function(){
|
||||
self.updateState("analysers", name, true);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
bkcore.threejs.Loader.prototype.loadImage = function(name, url)
|
||||
{
|
||||
var self = this;
|
||||
this.updateState("images", name, false);
|
||||
var e = new Image();
|
||||
e.onload = function() {
|
||||
self.updateState("images", name, true) ;
|
||||
};
|
||||
e.crossOrigin = "anonymous";
|
||||
e.src = url;
|
||||
this.data.images[name] = e;
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
/*!
|
||||
* @class bkcore.threejs.Particles
|
||||
*
|
||||
* Particle system wrapper/helper
|
||||
*
|
||||
* @author Thibaut 'BKcore' Despoulain <http://bkcore.com>
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @package bkcore.threejs
|
||||
*/
|
||||
var bkcore = bkcore || {};
|
||||
bkcore.threejs = bkcore.threejs || {};
|
||||
|
||||
/**
|
||||
* Creates a new particle system using given parameters
|
||||
* @param {Object{max, spawnRate, spawn, velocity, randomness, force, spawnRadius, life, friction, color, color2, tint, texture, size, blending, depthTest, transparent, opacity}} opts
|
||||
*/
|
||||
bkcore.threejs.Particles = function(opts)
|
||||
{
|
||||
this.black = new THREE.Color(0x000000);
|
||||
this.white = new THREE.Color(0xffffff);
|
||||
|
||||
this.material = new THREE.ParticleBasicMaterial({
|
||||
color: opts.tint == undefined ? 0xffffff : opts.tint,
|
||||
map: opts.texture == undefined ? null : opts.texture,
|
||||
size: opts.size == undefined ? 4 : opts.size,
|
||||
blending: opts.blending == undefined ? THREE.AdditiveBlending : opts.blending,
|
||||
depthTest: opts.depthTest == undefined ? false : opts.depthTest,
|
||||
transparent: opts.transparent == undefined ? true : opts.transparent,
|
||||
vertexColors: true,
|
||||
opacity: opts.opacity == undefined ? 1.0 : opts.opacity,
|
||||
sizeAttenuation: true
|
||||
});
|
||||
|
||||
this.max = opts.max == undefined ? 1000 : opts.max;
|
||||
this.spawnRate = opts.spawnRate == undefined ? 0 : opts.spawnRate;
|
||||
|
||||
this.spawn = opts.spawn == undefined ? new THREE.Vector3() : opts.spawn;
|
||||
this.velocity = opts.velocity == undefined ? new THREE.Vector3() : opts.velocity;
|
||||
this.randomness = opts.randomness == undefined ? new THREE.Vector3() : opts.randomness;
|
||||
this.force = opts.force == undefined ? new THREE.Vector3() : opts.force;
|
||||
this.spawnRadius = opts.spawnRadius == undefined ? new THREE.Vector3() : opts.spawnRadius;
|
||||
this.life = opts.life == undefined ? 60 : opts.life;
|
||||
this.ageing = 1 / this.life;
|
||||
this.friction = opts.friction == undefined ? 1.0 : opts.friction;
|
||||
this.color = new THREE.Color(opts.color == undefined ? 0xffffff : opts.color);
|
||||
this.color2 = opts.color2 == undefined ? null : new THREE.Color(opts.color2);
|
||||
|
||||
this.position = opts.position == undefined ? new THREE.Vector3() : opts.position;
|
||||
this.rotation = opts.rotation == undefined ? new THREE.Vector3() : opts.rotation;
|
||||
this.sort = opts.sort == undefined ? false : opts.sort;
|
||||
|
||||
this.pool = [];
|
||||
this.buffer = [];
|
||||
this.geometry = null;
|
||||
this.system = null;
|
||||
|
||||
this.build();
|
||||
}
|
||||
|
||||
bkcore.threejs.Particles.prototype.build = function()
|
||||
{
|
||||
this.geometry = new THREE.Geometry();
|
||||
this.geometry.dynamic = true;
|
||||
|
||||
this.pool = [];
|
||||
this.buffer = [];
|
||||
|
||||
for(var i = 0; i < this.max; ++i)
|
||||
{
|
||||
var p = new bkcore.threejs.Particle();
|
||||
this.pool.push(p);
|
||||
this.buffer.push(p);
|
||||
this.geometry.vertices.push(p.position);
|
||||
this.geometry.colors.push(p.color);
|
||||
}
|
||||
|
||||
this.system = new THREE.ParticleSystem(this.geometry, this.material);
|
||||
this.system.position = this.position;
|
||||
this.system.rotation = this.rotation;
|
||||
this.system.sort = this.sort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits given number of particles
|
||||
* @param int count
|
||||
*/
|
||||
bkcore.threejs.Particles.prototype.emit = function(count)
|
||||
{
|
||||
var emitable = Math.min(count, this.pool.length);
|
||||
for(var i = 0; i < emitable; ++i)
|
||||
{
|
||||
var p = this.pool.pop();
|
||||
p.available = false;
|
||||
p.position.copy(this.spawn)
|
||||
.addSelf(
|
||||
this.randomVector()
|
||||
.multiplySelf(this.spawnRadius)
|
||||
);
|
||||
p.velocity.copy(this.velocity)
|
||||
.addSelf(
|
||||
this.randomVector()
|
||||
.multiplySelf(this.randomness)
|
||||
);
|
||||
p.force.copy(this.force);
|
||||
p.basecolor.copy(this.color);
|
||||
if(this.color2 != undefined) p.basecolor.lerpSelf(this.color2, Math.random());
|
||||
p.life = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
bkcore.threejs.Particles.prototype.randomVector = function()
|
||||
{
|
||||
return new THREE.Vector3(
|
||||
Math.random()*2-1,
|
||||
Math.random()*2-1,
|
||||
Math.random()*2-1
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates particles (should be call in a RAF loop)
|
||||
* @param float dt time delta ~1.0
|
||||
*/
|
||||
bkcore.threejs.Particles.prototype.update = function(dt)
|
||||
{
|
||||
var p, l;
|
||||
var df = new THREE.Vector3();
|
||||
var dv = new THREE.Vector3();
|
||||
for(var i = 0; i < this.buffer.length; ++i)
|
||||
{
|
||||
|
||||
p = this.buffer[i];
|
||||
|
||||
if(p.available) continue;
|
||||
|
||||
p.life -= this.ageing;
|
||||
|
||||
if(p.life <= 0 && !p.available)
|
||||
{
|
||||
p.reset();
|
||||
this.pool.push(p);
|
||||
continue;
|
||||
}
|
||||
|
||||
l = p.life > 0.5 ? 1.0 : p.life + 0.5;
|
||||
p.color.setRGB(
|
||||
l * p.basecolor.r,
|
||||
l * p.basecolor.g,
|
||||
l * p.basecolor.b
|
||||
);
|
||||
|
||||
if(this.friction != 1.0)
|
||||
p.velocity.multiplyScalar(this.friction);
|
||||
|
||||
df.copy(p.force).multiplyScalar(dt);
|
||||
p.velocity.addSelf(df);
|
||||
|
||||
dv.copy(p.velocity).multiplyScalar(dt);
|
||||
p.position.addSelf(dv);
|
||||
}
|
||||
|
||||
if(this.spawnRate > 0)
|
||||
this.emit(this.spawnRate);
|
||||
|
||||
this.geometry.verticesNeedUpdate = true;
|
||||
this.geometry.colorsNeedUpdate = true;
|
||||
}
|
||||
|
||||
bkcore.threejs.Particle = function()
|
||||
{
|
||||
this.position = new THREE.Vector3(-10000,-10000,-10000);
|
||||
this.velocity = new THREE.Vector3();
|
||||
this.force = new THREE.Vector3();
|
||||
this.color = new THREE.Color(0x000000);
|
||||
this.basecolor = new THREE.Color(0x000000);
|
||||
this.life = 0.0;
|
||||
this.available = true;
|
||||
}
|
||||
|
||||
bkcore.threejs.Particle.prototype.reset = function()
|
||||
{
|
||||
this.position.set(0,-100000,0);
|
||||
this.velocity.set(0,0,0);
|
||||
this.force.set(0,0,0);
|
||||
this.color.setRGB(0,0,0);
|
||||
this.basecolor.setRGB(0,0,0);
|
||||
this.life = 0.0;
|
||||
this.available = true;
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/*!
|
||||
* @class bkcore.threejs.Preloader
|
||||
*
|
||||
* Displays a small 3D preloader scene
|
||||
*
|
||||
* @author Thibaut 'BKcore' Despoulain <http://bkcore.com>
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @package bkcore.threejs
|
||||
*/
|
||||
var bkcore = bkcore || {};
|
||||
bkcore.threejs = bkcore.threejs || {};
|
||||
|
||||
/**
|
||||
* Creates a new preloader scene.
|
||||
* You have to update Preloader.ratio with the % loaded info (float 0.0-1.0)
|
||||
* @param {Object{width, height, scale, line}} opts
|
||||
*/
|
||||
bkcore.threejs.Preloader = function(opts)
|
||||
{
|
||||
this.document = opts.document || document;
|
||||
|
||||
this.end = false;
|
||||
|
||||
this.time = 0.0;
|
||||
this.y = 0.3;
|
||||
this.ratio = 0.0;
|
||||
|
||||
this.height = opts.height;
|
||||
this.width = opts.width;
|
||||
|
||||
this.scale = opts.scale == undefined ? 10 : opts.scale
|
||||
this.line = opts.line == undefined ? 3 : opts.line;
|
||||
|
||||
this.container = opts.container;
|
||||
|
||||
this.renderer = new THREE.CanvasRenderer({
|
||||
clearColor: 0xffffff
|
||||
});
|
||||
this.renderer.setSize( opts.width, opts.height );
|
||||
|
||||
this.container.appendChild( this.renderer.domElement );
|
||||
|
||||
this.ctx = this.renderer.domElement.getContext('2d');
|
||||
this.ctx.textAlign = "center";
|
||||
|
||||
this.scene = new THREE.Scene();
|
||||
|
||||
this.camera = new THREE.PerspectiveCamera( 70, opts.width / opts.height, 1, 1000 );
|
||||
this.camera.position.z = 100;
|
||||
this.scene.add( this.camera );
|
||||
|
||||
this.stage = new THREE.Object3D();
|
||||
this.stage.position.set(0,10,0);
|
||||
this.scene.add(this.stage);
|
||||
|
||||
this.cube = new THREE.Mesh( new THREE.CubeGeometry( this.scale, this.scale, this.scale, 1, 1, 1 ),
|
||||
new THREE.MeshBasicMaterial( { color: 0x999999 } ) );
|
||||
|
||||
this.cube.scale.set(0.0,0.0,0.0);
|
||||
this.stage.add(this.cube);
|
||||
|
||||
this.cubew = new THREE.Mesh( new THREE.CubeGeometry( this.scale, this.scale, this.scale, 1, 1, 1 ),
|
||||
new THREE.MeshBasicMaterial( {
|
||||
wireframe: true,
|
||||
wireframeLinewidth: this.line,
|
||||
//wireframeLinecap: 'square',
|
||||
//wireframeLinejoin: 'square',
|
||||
color: 0xffffff
|
||||
} ) );
|
||||
this.cube.add(this.cubew);
|
||||
|
||||
this.outercube = new THREE.Mesh( new THREE.CubeGeometry( this.scale, this.scale, this.scale, 1, 1, 1 ),
|
||||
new THREE.MeshBasicMaterial( {
|
||||
wireframe: true,
|
||||
wireframeLinewidth: this.line,
|
||||
//wireframeLinecap: 'square',
|
||||
//wireframeLinejoin: 'square',
|
||||
color: 0x0093d8
|
||||
} ) );
|
||||
this.stage.add(this.outercube);
|
||||
|
||||
var self = this;
|
||||
|
||||
function raf()
|
||||
{
|
||||
if(!self.end)
|
||||
{
|
||||
requestAnimationFrame( raf );
|
||||
self.render();
|
||||
}
|
||||
}
|
||||
raf();
|
||||
|
||||
function mm(e){
|
||||
self.mouseMove.call(self, e);
|
||||
}
|
||||
|
||||
this.mmsave = mm;
|
||||
|
||||
this.document.addEventListener( 'mousemove', mm, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Render method to be called from a RAF loop
|
||||
*/
|
||||
bkcore.threejs.Preloader.prototype.render = function()
|
||||
{
|
||||
this.time += 0.02;
|
||||
|
||||
this.ctx.clearRect(0 , 0 , this.width , this.height);
|
||||
|
||||
var s = (this.ratio - this.cube.scale.x) * 0.3;
|
||||
|
||||
this.cube.scale.addScalar(s);
|
||||
this.cube.rotation.y = this.time;
|
||||
this.outercube.rotation.y = this.time;
|
||||
|
||||
this.stage.rotation.x += (this.y - this.stage.rotation.x)*0.3;
|
||||
|
||||
this.renderer.render( this.scene, this.camera );
|
||||
|
||||
this.ctx.save();
|
||||
this.ctx.font = "40px Arial";
|
||||
this.ctx.fillStyle = "rgb(200, 200, 200)";
|
||||
this.ctx.fillText(Math.round(this.ratio*100), this.width/2, this.height/2+30);
|
||||
this.ctx.restore();
|
||||
}
|
||||
|
||||
bkcore.threejs.Preloader.prototype.mouseMove = function(event)
|
||||
{
|
||||
var h2 = this.height/2;
|
||||
this.y = -(event.clientY - h2)/h2+0.3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the Preloader
|
||||
*/
|
||||
bkcore.threejs.Preloader.prototype.remove = function()
|
||||
{
|
||||
this.document.removeEventListener( 'mousemove', this.mm, false );
|
||||
this.end = true;
|
||||
this.renderer = null;
|
||||
this.scene = null;
|
||||
this.stage = null;
|
||||
this.cube = null;
|
||||
this.cubew = null;
|
||||
this.innercube = null;
|
||||
this.container.innerHTML = "";
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/*!
|
||||
* bkcore.threejs.RenderManager helps handling multiple scenes, cameras and render loops.
|
||||
*
|
||||
* @author Thibaut 'BKcore' Despoulain <http://bkcore.com>
|
||||
* @license MIT
|
||||
*
|
||||
* Initialize the a RenderManager by passing a Renderer object:
|
||||
* var renderManager = new bkcore.threejs.RenderManager(new THREE.WebGLRenderer());
|
||||
*
|
||||
* A render setup structure :
|
||||
* {
|
||||
* id <String> : render setup ID,
|
||||
* scene <THREE.Scene> : main scene,
|
||||
* camera <THREE.Camera> : main camera,
|
||||
* render <Function> : render loop called when render setup is active (current),
|
||||
* objects <Dic> : object references accessible in the render loop via this.objects
|
||||
* }
|
||||
*
|
||||
* The render method's context will be the render setup's object, so in your render loop:
|
||||
* function(delta, renderer)
|
||||
* {
|
||||
* this.scene;
|
||||
* this.camera;
|
||||
* this.id;
|
||||
* this.objects;
|
||||
* renderer.render(...);
|
||||
* }
|
||||
*
|
||||
* Use the "objects" attribute to store useful references and variables like time, geometries, materials, etc.
|
||||
* Example:
|
||||
* renderManager.add('mySetup', scene, camera, function(delta, renderer)
|
||||
* {
|
||||
* this.objects.timer += delta;
|
||||
* this.objects.torus.rotation.z = Math.PI * Math.cos(this.objects.timer);
|
||||
* renderer.render(this.scene, this.camera);
|
||||
* },
|
||||
* {
|
||||
* timer: 0,
|
||||
* torus: torusMesh
|
||||
* });
|
||||
*/
|
||||
|
||||
var bkcore = bkcore || {};
|
||||
bkcore.threejs = bkcore.threejs || {};
|
||||
|
||||
(function(w){
|
||||
var perfNow;
|
||||
var perfNowNames = ['now', 'webkitNow', 'msNow', 'mozNow'];
|
||||
if(!!w['performance']) for(var i = 0; i < perfNowNames.length; ++i)
|
||||
{
|
||||
var n = perfNowNames[i];
|
||||
if(!!w['performance'][n])
|
||||
{
|
||||
perfNow = function(){return w['performance'][n]()};
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!perfNow)
|
||||
{
|
||||
perfNow = Date.now;
|
||||
}
|
||||
w.perfNow = perfNow;
|
||||
})(window);
|
||||
|
||||
bkcore.threejs.RenderManager = function(renderer)
|
||||
{
|
||||
this.renderer = renderer;
|
||||
this.time = window.perfNow();
|
||||
|
||||
this.renders = {};
|
||||
this.current = {};
|
||||
this.size = 0;
|
||||
|
||||
this.defaultRenderMethod = function(delta, renderer)
|
||||
{
|
||||
renderer.render(this.scene, this.camera);
|
||||
};
|
||||
};
|
||||
|
||||
bkcore.threejs.RenderManager.prototype.add = function(id, scene, camera, render, objects)
|
||||
{
|
||||
render = render || this.defaultRenderMethod;
|
||||
objects = objects || {};
|
||||
|
||||
this.renders[id] = {
|
||||
id: id,
|
||||
scene: scene,
|
||||
camera: camera,
|
||||
render: render,
|
||||
objects: objects
|
||||
};
|
||||
|
||||
if(this.size == 0) this.current = this.renders[id];
|
||||
|
||||
this.size++;
|
||||
};
|
||||
|
||||
bkcore.threejs.RenderManager.prototype.get = function(id)
|
||||
{
|
||||
return this.renders[id];
|
||||
};
|
||||
|
||||
bkcore.threejs.RenderManager.prototype.remove = function(id)
|
||||
{
|
||||
if(id in this.renders)
|
||||
{
|
||||
delete this.renders[id];
|
||||
this.size--;
|
||||
}
|
||||
};
|
||||
|
||||
bkcore.threejs.RenderManager.prototype.renderCurrent = function()
|
||||
{
|
||||
if(this.current && this.current.render)
|
||||
{
|
||||
var now = window.perfNow();
|
||||
var delta = now - this.time;
|
||||
this.time = now;
|
||||
|
||||
this.current.render.call(this.current, delta, this.renderer);
|
||||
}
|
||||
else console.warn('RenderManager: No current render defined.');
|
||||
};
|
||||
|
||||
bkcore.threejs.RenderManager.prototype.setCurrent = function(id)
|
||||
{
|
||||
if(id in this.renders)
|
||||
{
|
||||
this.current = this.renders[id];
|
||||
}
|
||||
else console.warn('RenderManager: Render "'+id+'" not found.');
|
||||
};
|
||||
@@ -0,0 +1,950 @@
|
||||
/**
|
||||
* @author Thibaut Despoulain / http://bkcore.com
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
* @author mr.doob / http://mrdoob.com/
|
||||
*/
|
||||
var bkcore = bkcore || {};
|
||||
bkcore.threejs = bkcore.threejs || {};
|
||||
|
||||
bkcore.threejs.Shaders =
|
||||
{
|
||||
'additive' : {
|
||||
uniforms: {
|
||||
tDiffuse: { type: "t", value: 0, texture: null },
|
||||
tAdd: { type: "t", value: 1, texture: null },
|
||||
fCoeff: { type: "f", value: 1.0 }
|
||||
},
|
||||
|
||||
vertexShader: [
|
||||
"varying vec2 vUv;",
|
||||
|
||||
"void main() {",
|
||||
|
||||
"vUv = uv;",
|
||||
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
|
||||
|
||||
"}"
|
||||
].join("\n"),
|
||||
|
||||
fragmentShader: [
|
||||
"uniform sampler2D tDiffuse;",
|
||||
"uniform sampler2D tAdd;",
|
||||
"uniform float fCoeff;",
|
||||
|
||||
"varying vec2 vUv;",
|
||||
|
||||
"void main() {",
|
||||
|
||||
"vec4 texel = texture2D( tDiffuse, vUv );",
|
||||
"vec4 add = texture2D( tAdd, vUv );",
|
||||
"gl_FragColor = texel + add * fCoeff * add.a;",
|
||||
|
||||
"}"
|
||||
].join("\n")
|
||||
},
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
// Hexagonal Vignette shader
|
||||
// by BKcore.com
|
||||
------------------------------------------------------------------------------------------------ */
|
||||
|
||||
'hexvignette': {
|
||||
|
||||
uniforms: {
|
||||
|
||||
tDiffuse: { type: "t", value: 0, texture: null },
|
||||
tHex: {type: "t", value: 1, texture: null},
|
||||
size: {type: "f", value: 512.0},
|
||||
rx: {type: "f", value: 1024.0},
|
||||
ry: {type: "f", value: 768.0},
|
||||
color: {type: "c", value: new THREE.Color(0x458ab1)}
|
||||
|
||||
},
|
||||
|
||||
vertexShader: [
|
||||
|
||||
"varying vec2 vUv;",
|
||||
|
||||
"void main() {",
|
||||
|
||||
"vUv = uv;",
|
||||
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
|
||||
|
||||
"}"
|
||||
|
||||
].join("\n"),
|
||||
|
||||
fragmentShader: [
|
||||
|
||||
"uniform float size;",
|
||||
"uniform float rx;",
|
||||
"uniform float ry;",
|
||||
|
||||
"uniform vec3 color;",
|
||||
|
||||
"uniform sampler2D tDiffuse;",
|
||||
"uniform sampler2D tHex;",
|
||||
|
||||
"varying vec2 vUv;",
|
||||
|
||||
"void main() {",
|
||||
|
||||
"vec4 vcolor = vec4(color,1.0);",
|
||||
|
||||
"vec2 hexuv;",
|
||||
"hexuv.x = mod(vUv.x * rx, size) / size;",
|
||||
"hexuv.y = mod(vUv.y * ry, size) / size;",
|
||||
"vec4 hex = texture2D( tHex, hexuv );",
|
||||
|
||||
"float tolerance = 0.2;",
|
||||
"float vignette_size = 0.6;",
|
||||
"vec2 powers = pow(abs(vec2(vUv.x - 0.5,vUv.y - 0.5)),vec2(2.0));",
|
||||
"float radiusSqrd = vignette_size*vignette_size;",
|
||||
"float gradient = smoothstep(radiusSqrd-tolerance, radiusSqrd+tolerance, powers.x+powers.y);",
|
||||
|
||||
"vec2 uv = ( vUv - vec2( 0.5 ) );",
|
||||
|
||||
"vec2 sample = uv * gradient * 0.5 * (1.0-hex.r);",
|
||||
|
||||
"vec4 texel = texture2D( tDiffuse, vUv-sample );",
|
||||
"gl_FragColor = (((1.0-hex.r)*vcolor) * 0.5 * gradient) + vec4( mix( texel.rgb, vcolor.xyz*0.7, dot( uv, uv ) ), texel.a );",
|
||||
|
||||
"}"
|
||||
|
||||
].join("\n")
|
||||
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
// Normal map shader (perpixel)
|
||||
// - Blinn-Phong
|
||||
// - normal + diffuse + specular + AO + displacement + reflection + shadow maps
|
||||
// - PER-PIXEL point and directional lights (use with "lights: true" material option)
|
||||
// - modified by BKcore
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
'normal' : {
|
||||
|
||||
uniforms: THREE.UniformsUtils.merge( [
|
||||
|
||||
THREE.UniformsLib[ "fog" ],
|
||||
THREE.UniformsLib[ "lights" ],
|
||||
THREE.UniformsLib[ "shadowmap" ],
|
||||
|
||||
{
|
||||
|
||||
"enableAO" : { type: "i", value: 0 },
|
||||
"enableDiffuse" : { type: "i", value: 0 },
|
||||
"enableSpecular" : { type: "i", value: 0 },
|
||||
"enableReflection": { type: "i", value: 0 },
|
||||
|
||||
"tDiffuse" : { type: "t", value: 0, texture: null },
|
||||
"tCube" : { type: "t", value: 1, texture: null },
|
||||
"tNormal" : { type: "t", value: 2, texture: null },
|
||||
"tSpecular" : { type: "t", value: 3, texture: null },
|
||||
"tAO" : { type: "t", value: 4, texture: null },
|
||||
"tDisplacement": { type: "t", value: 5, texture: null },
|
||||
|
||||
"uNormalScale": { type: "f", value: 1.0 },
|
||||
|
||||
"uDisplacementBias": { type: "f", value: 0.0 },
|
||||
"uDisplacementScale": { type: "f", value: 1.0 },
|
||||
|
||||
"uDiffuseColor": { type: "c", value: new THREE.Color( 0xffffff ) },
|
||||
"uSpecularColor": { type: "c", value: new THREE.Color( 0x111111 ) },
|
||||
"uAmbientColor": { type: "c", value: new THREE.Color( 0xffffff ) },
|
||||
"uShininess": { type: "f", value: 30 },
|
||||
"uOpacity": { type: "f", value: 1 },
|
||||
|
||||
"uReflectivity": { type: "f", value: 0.5 },
|
||||
|
||||
"uOffset" : { type: "v2", value: new THREE.Vector2( 0, 0 ) },
|
||||
"uRepeat" : { type: "v2", value: new THREE.Vector2( 1, 1 ) },
|
||||
|
||||
"wrapRGB" : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) }
|
||||
|
||||
}
|
||||
|
||||
] ),
|
||||
|
||||
fragmentShader: [
|
||||
|
||||
"uniform vec3 uAmbientColor;",
|
||||
"uniform vec3 uDiffuseColor;",
|
||||
"uniform vec3 uSpecularColor;",
|
||||
"uniform float uShininess;",
|
||||
"uniform float uOpacity;",
|
||||
|
||||
"uniform bool enableDiffuse;",
|
||||
"uniform bool enableSpecular;",
|
||||
"uniform bool enableAO;",
|
||||
"uniform bool enableReflection;",
|
||||
|
||||
"uniform sampler2D tDiffuse;",
|
||||
"uniform sampler2D tNormal;",
|
||||
"uniform sampler2D tSpecular;",
|
||||
"uniform sampler2D tAO;",
|
||||
|
||||
"uniform samplerCube tCube;",
|
||||
|
||||
"uniform float uNormalScale;",
|
||||
"uniform float uReflectivity;",
|
||||
|
||||
"varying vec3 vTangent;",
|
||||
"varying vec3 vBinormal;",
|
||||
"varying vec3 vNormal;",
|
||||
"varying vec2 vUv;",
|
||||
|
||||
"uniform vec3 ambientLightColor;",
|
||||
|
||||
"#if MAX_DIR_LIGHTS > 0",
|
||||
"uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];",
|
||||
"uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];",
|
||||
"#endif",
|
||||
|
||||
"#if MAX_POINT_LIGHTS > 0",
|
||||
"uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];",
|
||||
"uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
|
||||
"uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
|
||||
"#endif",
|
||||
|
||||
"#ifdef WRAP_AROUND",
|
||||
"uniform vec3 wrapRGB;",
|
||||
"#endif",
|
||||
|
||||
"varying vec3 vViewPosition;",
|
||||
|
||||
THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
|
||||
THREE.ShaderChunk[ "fog_pars_fragment" ],
|
||||
|
||||
"void main() {",
|
||||
|
||||
"gl_FragColor = vec4( vec3( 1.0 ), uOpacity );",
|
||||
|
||||
"vec3 specularTex = vec3( 1.0 );",
|
||||
|
||||
"vec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;",
|
||||
"normalTex.xy *= uNormalScale;",
|
||||
"normalTex = normalize( normalTex );",
|
||||
|
||||
"if( enableDiffuse ) {",
|
||||
|
||||
"#ifdef GAMMA_INPUT",
|
||||
|
||||
"vec4 texelColor = texture2D( tDiffuse, vUv );",
|
||||
"texelColor.xyz *= texelColor.xyz;",
|
||||
|
||||
"gl_FragColor = gl_FragColor * texelColor;",
|
||||
|
||||
"#else",
|
||||
|
||||
"gl_FragColor = gl_FragColor * texture2D( tDiffuse, vUv );",
|
||||
|
||||
"#endif",
|
||||
|
||||
"}",
|
||||
|
||||
"if( enableAO ) {",
|
||||
|
||||
"#ifdef GAMMA_INPUT",
|
||||
|
||||
"vec4 aoColor = texture2D( tAO, vUv );",
|
||||
"aoColor.xyz *= aoColor.xyz;",
|
||||
|
||||
"gl_FragColor.xyz = gl_FragColor.xyz * aoColor.xyz;",
|
||||
|
||||
"#else",
|
||||
|
||||
"gl_FragColor.xyz = gl_FragColor.xyz * texture2D( tAO, vUv ).xyz;",
|
||||
|
||||
"#endif",
|
||||
|
||||
"}",
|
||||
|
||||
"if( enableSpecular )",
|
||||
"specularTex = texture2D( tSpecular, vUv ).xyz;",
|
||||
|
||||
"mat3 tsb = mat3( normalize( vTangent ), normalize( vBinormal ), normalize( vNormal ) );",
|
||||
"vec3 finalNormal = tsb * normalTex;",
|
||||
|
||||
"vec3 normal = normalize( finalNormal );",
|
||||
"vec3 viewPosition = normalize( vViewPosition );",
|
||||
|
||||
"#ifdef DOUBLE_SIDED",
|
||||
|
||||
"normal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );",
|
||||
|
||||
"#endif",
|
||||
|
||||
// point lights
|
||||
|
||||
"#if MAX_POINT_LIGHTS > 0",
|
||||
|
||||
"vec3 pointDiffuse = vec3( 0.0 );",
|
||||
"vec3 pointSpecular = vec3( 0.0 );",
|
||||
|
||||
"for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
|
||||
|
||||
"vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
|
||||
"vec3 pointVector = lPosition.xyz + vViewPosition.xyz;",
|
||||
|
||||
"float pointDistance = 1.0;",
|
||||
"if ( pointLightDistance[ i ] > 0.0 )",
|
||||
"pointDistance = 1.0 - min( ( length( pointVector ) / pointLightDistance[ i ] ), 1.0 );",
|
||||
|
||||
"pointVector = normalize( pointVector );",
|
||||
|
||||
// diffuse
|
||||
|
||||
"#ifdef WRAP_AROUND",
|
||||
|
||||
"float pointDiffuseWeightFull = max( dot( normal, pointVector ), 0.0 );",
|
||||
"float pointDiffuseWeightHalf = max( 0.5 * dot( normal, pointVector ) + 0.5, 0.0 );",
|
||||
|
||||
"vec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );",
|
||||
|
||||
"#else",
|
||||
|
||||
"float pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );",
|
||||
|
||||
"#endif",
|
||||
|
||||
"pointDiffuse += pointDistance * pointLightColor[ i ] * uDiffuseColor * pointDiffuseWeight;",
|
||||
|
||||
// specular
|
||||
|
||||
"vec3 pointHalfVector = normalize( pointVector + viewPosition );",
|
||||
"float pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );",
|
||||
"float pointSpecularWeight = specularTex.r * max( pow( pointDotNormalHalf, uShininess ), 0.0 );",
|
||||
|
||||
"#ifdef PHYSICALLY_BASED_SHADING",
|
||||
|
||||
// 2.0 => 2.0001 is hack to work around ANGLE bug
|
||||
|
||||
"float specularNormalization = ( uShininess + 2.0001 ) / 8.0;",
|
||||
|
||||
"vec3 schlick = specularTex + vec3( 1.0 - specularTex ) * pow( 1.0 - dot( pointVector, pointHalfVector ), 5.0 );",
|
||||
"pointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * pointDistance * specularNormalization;",
|
||||
|
||||
"#else",
|
||||
|
||||
"pointSpecular += pointDistance * pointLightColor[ i ] * specularTex * pointSpecularWeight * pointDiffuseWeight;",
|
||||
|
||||
"#endif",
|
||||
|
||||
"}",
|
||||
|
||||
"#endif",
|
||||
|
||||
// directional lights
|
||||
|
||||
"#if MAX_DIR_LIGHTS > 0",
|
||||
|
||||
"vec3 dirDiffuse = vec3( 0.0 );",
|
||||
"vec3 dirSpecular = vec3( 0.0 );",
|
||||
|
||||
"for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
|
||||
|
||||
"vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );",
|
||||
"vec3 dirVector = normalize( lDirection.xyz );",
|
||||
|
||||
// diffuse
|
||||
|
||||
"#ifdef WRAP_AROUND",
|
||||
|
||||
"float directionalLightWeightingFull = max( dot( normal, dirVector ), 0.0 );",
|
||||
"float directionalLightWeightingHalf = max( 0.5 * dot( normal, dirVector ) + 0.5, 0.0 );",
|
||||
|
||||
"vec3 dirDiffuseWeight = mix( vec3( directionalLightWeightingFull ), vec3( directionalLightWeightingHalf ), wrapRGB );",
|
||||
|
||||
"#else",
|
||||
|
||||
"float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );",
|
||||
|
||||
"#endif",
|
||||
|
||||
"dirDiffuse += directionalLightColor[ i ] * uDiffuseColor * dirDiffuseWeight;",
|
||||
|
||||
// specular
|
||||
|
||||
"vec3 dirHalfVector = normalize( dirVector + viewPosition );",
|
||||
"float dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );",
|
||||
"float dirSpecularWeight = specularTex.r * max( pow( dirDotNormalHalf, uShininess ), 0.0 );",
|
||||
|
||||
"#ifdef PHYSICALLY_BASED_SHADING",
|
||||
|
||||
// 2.0 => 2.0001 is hack to work around ANGLE bug
|
||||
|
||||
"float specularNormalization = ( uShininess + 2.0001 ) / 8.0;",
|
||||
|
||||
"vec3 schlick = specularTex + vec3( 1.0 - specularTex ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );",
|
||||
"dirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;",
|
||||
|
||||
"#else",
|
||||
|
||||
"dirSpecular += directionalLightColor[ i ] * specularTex * dirSpecularWeight * dirDiffuseWeight;",
|
||||
|
||||
"#endif",
|
||||
|
||||
"}",
|
||||
|
||||
"#endif",
|
||||
|
||||
// all lights contribution summation
|
||||
|
||||
"vec3 totalDiffuse = vec3( 0.0 );",
|
||||
"vec3 totalSpecular = vec3( 0.0 );",
|
||||
|
||||
"#if MAX_DIR_LIGHTS > 0",
|
||||
|
||||
"totalDiffuse += dirDiffuse;",
|
||||
"totalSpecular += dirSpecular;",
|
||||
|
||||
"#endif",
|
||||
|
||||
"#if MAX_POINT_LIGHTS > 0",
|
||||
|
||||
"totalDiffuse += pointDiffuse;",
|
||||
"totalSpecular += pointSpecular;",
|
||||
|
||||
"#endif",
|
||||
|
||||
"gl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * uAmbientColor) + totalSpecular;",
|
||||
|
||||
"if ( enableReflection ) {",
|
||||
|
||||
"#ifdef DOUBLE_SIDED",
|
||||
|
||||
"float flipNormal = ( -1.0 + 2.0 * float( gl_FrontFacing ) );",
|
||||
|
||||
"#else",
|
||||
|
||||
"float flipNormal = 1.0;",
|
||||
|
||||
"#endif",
|
||||
|
||||
"vec3 wPos = cameraPosition - vViewPosition;",
|
||||
"vec3 vReflect = reflect( normalize( wPos ), normal );",
|
||||
|
||||
"vec4 cubeColor = textureCube( tCube, flipNormal*vec3( -vReflect.x, vReflect.yz ) );",
|
||||
|
||||
"#ifdef GAMMA_INPUT",
|
||||
|
||||
"cubeColor.xyz *= cubeColor.xyz;",
|
||||
|
||||
"#endif",
|
||||
|
||||
"gl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularTex.r * uReflectivity );",
|
||||
|
||||
"}",
|
||||
|
||||
THREE.ShaderChunk[ "shadowmap_fragment" ],
|
||||
THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
|
||||
THREE.ShaderChunk[ "fog_fragment" ],
|
||||
|
||||
"}"
|
||||
|
||||
].join("\n"),
|
||||
|
||||
vertexShader: [
|
||||
|
||||
"attribute vec4 tangent;",
|
||||
|
||||
"uniform vec2 uOffset;",
|
||||
"uniform vec2 uRepeat;",
|
||||
|
||||
"#ifdef VERTEX_TEXTURES",
|
||||
|
||||
"uniform sampler2D tDisplacement;",
|
||||
"uniform float uDisplacementScale;",
|
||||
"uniform float uDisplacementBias;",
|
||||
|
||||
"#endif",
|
||||
|
||||
"varying vec3 vTangent;",
|
||||
"varying vec3 vBinormal;",
|
||||
"varying vec3 vNormal;",
|
||||
"varying vec2 vUv;",
|
||||
|
||||
"varying vec3 vViewPosition;",
|
||||
|
||||
THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
|
||||
|
||||
"void main() {",
|
||||
|
||||
"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
|
||||
|
||||
"vViewPosition = -mvPosition.xyz;",
|
||||
|
||||
// normal, tangent and binormal vectors
|
||||
|
||||
"vNormal = normalMatrix * normal;",
|
||||
"vTangent = normalMatrix * tangent.xyz;",
|
||||
"vBinormal = cross( vNormal, vTangent ) * tangent.w;",
|
||||
|
||||
"vUv = uv * uRepeat + uOffset;",
|
||||
|
||||
// displacement mapping
|
||||
|
||||
"#ifdef VERTEX_TEXTURES",
|
||||
|
||||
"vec3 dv = texture2D( tDisplacement, uv ).xyz;",
|
||||
"float df = uDisplacementScale * dv.x + uDisplacementBias;",
|
||||
"vec4 displacedPosition = vec4( normalize( vNormal.xyz ) * df, 0.0 ) + mvPosition;",
|
||||
"gl_Position = projectionMatrix * displacedPosition;",
|
||||
|
||||
"#else",
|
||||
|
||||
"gl_Position = projectionMatrix * mvPosition;",
|
||||
|
||||
"#endif",
|
||||
|
||||
THREE.ShaderChunk[ "shadowmap_vertex" ],
|
||||
|
||||
"}"
|
||||
|
||||
].join("\n")
|
||||
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
// Normal map shader
|
||||
// - Blinn-Phong
|
||||
// - normal + diffuse + specular + AO + displacement + reflection + shadow maps
|
||||
// - PER-VERTEX point and directional lights (use with "lights: true" material option)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
'normalV' : {
|
||||
|
||||
uniforms: THREE.UniformsUtils.merge( [
|
||||
|
||||
THREE.UniformsLib[ "fog" ],
|
||||
THREE.UniformsLib[ "lights" ],
|
||||
THREE.UniformsLib[ "shadowmap" ],
|
||||
|
||||
{
|
||||
|
||||
"enableAO" : { type: "i", value: 0 },
|
||||
"enableDiffuse" : { type: "i", value: 0 },
|
||||
"enableSpecular" : { type: "i", value: 0 },
|
||||
"enableReflection": { type: "i", value: 0 },
|
||||
|
||||
"tDiffuse" : { type: "t", value: 0, texture: null },
|
||||
"tCube" : { type: "t", value: 1, texture: null },
|
||||
"tNormal" : { type: "t", value: 2, texture: null },
|
||||
"tSpecular" : { type: "t", value: 3, texture: null },
|
||||
"tAO" : { type: "t", value: 4, texture: null },
|
||||
"tDisplacement": { type: "t", value: 5, texture: null },
|
||||
|
||||
"uNormalScale": { type: "f", value: 1.0 },
|
||||
|
||||
"uDisplacementBias": { type: "f", value: 0.0 },
|
||||
"uDisplacementScale": { type: "f", value: 1.0 },
|
||||
|
||||
"uDiffuseColor": { type: "c", value: new THREE.Color( 0xffffff ) },
|
||||
"uSpecularColor": { type: "c", value: new THREE.Color( 0x111111 ) },
|
||||
"uAmbientColor": { type: "c", value: new THREE.Color( 0xffffff ) },
|
||||
"uShininess": { type: "f", value: 30 },
|
||||
"uOpacity": { type: "f", value: 1 },
|
||||
|
||||
"uReflectivity": { type: "f", value: 0.5 },
|
||||
|
||||
"uOffset" : { type: "v2", value: new THREE.Vector2( 0, 0 ) },
|
||||
"uRepeat" : { type: "v2", value: new THREE.Vector2( 1, 1 ) },
|
||||
|
||||
"wrapRGB" : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) }
|
||||
|
||||
}
|
||||
|
||||
] ),
|
||||
|
||||
fragmentShader: [
|
||||
|
||||
"uniform vec3 uAmbientColor;",
|
||||
"uniform vec3 uDiffuseColor;",
|
||||
"uniform vec3 uSpecularColor;",
|
||||
"uniform float uShininess;",
|
||||
"uniform float uOpacity;",
|
||||
|
||||
"uniform bool enableDiffuse;",
|
||||
"uniform bool enableSpecular;",
|
||||
"uniform bool enableAO;",
|
||||
"uniform bool enableReflection;",
|
||||
|
||||
"uniform sampler2D tDiffuse;",
|
||||
"uniform sampler2D tNormal;",
|
||||
"uniform sampler2D tSpecular;",
|
||||
"uniform sampler2D tAO;",
|
||||
|
||||
"uniform samplerCube tCube;",
|
||||
|
||||
"uniform float uNormalScale;",
|
||||
"uniform float uReflectivity;",
|
||||
|
||||
"varying vec3 vTangent;",
|
||||
"varying vec3 vBinormal;",
|
||||
"varying vec3 vNormal;",
|
||||
"varying vec2 vUv;",
|
||||
|
||||
"uniform vec3 ambientLightColor;",
|
||||
|
||||
"#if MAX_DIR_LIGHTS > 0",
|
||||
"uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];",
|
||||
"uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];",
|
||||
"#endif",
|
||||
|
||||
"#if MAX_POINT_LIGHTS > 0",
|
||||
"uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];",
|
||||
"varying vec4 vPointLight[ MAX_POINT_LIGHTS ];",
|
||||
"#endif",
|
||||
|
||||
"#ifdef WRAP_AROUND",
|
||||
"uniform vec3 wrapRGB;",
|
||||
"#endif",
|
||||
|
||||
"varying vec3 vViewPosition;",
|
||||
|
||||
THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
|
||||
THREE.ShaderChunk[ "fog_pars_fragment" ],
|
||||
|
||||
"void main() {",
|
||||
|
||||
"gl_FragColor = vec4( vec3( 1.0 ), uOpacity );",
|
||||
|
||||
"vec3 specularTex = vec3( 1.0 );",
|
||||
|
||||
"vec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;",
|
||||
"normalTex.xy *= uNormalScale;",
|
||||
"normalTex = normalize( normalTex );",
|
||||
|
||||
"if( enableDiffuse ) {",
|
||||
|
||||
"#ifdef GAMMA_INPUT",
|
||||
|
||||
"vec4 texelColor = texture2D( tDiffuse, vUv );",
|
||||
"texelColor.xyz *= texelColor.xyz;",
|
||||
|
||||
"gl_FragColor = gl_FragColor * texelColor;",
|
||||
|
||||
"#else",
|
||||
|
||||
"gl_FragColor = gl_FragColor * texture2D( tDiffuse, vUv );",
|
||||
|
||||
"#endif",
|
||||
|
||||
"}",
|
||||
|
||||
"if( enableAO ) {",
|
||||
|
||||
"#ifdef GAMMA_INPUT",
|
||||
|
||||
"vec4 aoColor = texture2D( tAO, vUv );",
|
||||
"aoColor.xyz *= aoColor.xyz;",
|
||||
|
||||
"gl_FragColor.xyz = gl_FragColor.xyz * aoColor.xyz;",
|
||||
|
||||
"#else",
|
||||
|
||||
"gl_FragColor.xyz = gl_FragColor.xyz * texture2D( tAO, vUv ).xyz;",
|
||||
|
||||
"#endif",
|
||||
|
||||
"}",
|
||||
|
||||
"if( enableSpecular )",
|
||||
"specularTex = texture2D( tSpecular, vUv ).xyz;",
|
||||
|
||||
"mat3 tsb = mat3( normalize( vTangent ), normalize( vBinormal ), normalize( vNormal ) );",
|
||||
"vec3 finalNormal = tsb * normalTex;",
|
||||
|
||||
"vec3 normal = normalize( finalNormal );",
|
||||
"vec3 viewPosition = normalize( vViewPosition );",
|
||||
|
||||
// point lights
|
||||
|
||||
"#if MAX_POINT_LIGHTS > 0",
|
||||
|
||||
"vec3 pointDiffuse = vec3( 0.0 );",
|
||||
"vec3 pointSpecular = vec3( 0.0 );",
|
||||
|
||||
"for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
|
||||
|
||||
"vec3 pointVector = normalize( vPointLight[ i ].xyz );",
|
||||
"float pointDistance = vPointLight[ i ].w;",
|
||||
|
||||
// diffuse
|
||||
|
||||
"#ifdef WRAP_AROUND",
|
||||
|
||||
"float pointDiffuseWeightFull = max( dot( normal, pointVector ), 0.0 );",
|
||||
"float pointDiffuseWeightHalf = max( 0.5 * dot( normal, pointVector ) + 0.5, 0.0 );",
|
||||
|
||||
"vec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );",
|
||||
|
||||
"#else",
|
||||
|
||||
"float pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );",
|
||||
|
||||
"#endif",
|
||||
|
||||
"pointDiffuse += pointDistance * pointLightColor[ i ] * uDiffuseColor * pointDiffuseWeight;",
|
||||
|
||||
// specular
|
||||
|
||||
"vec3 pointHalfVector = normalize( pointVector + viewPosition );",
|
||||
"float pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );",
|
||||
"float pointSpecularWeight = specularTex.r * max( pow( pointDotNormalHalf, uShininess ), 0.0 );",
|
||||
|
||||
"#ifdef PHYSICALLY_BASED_SHADING",
|
||||
|
||||
// 2.0 => 2.0001 is hack to work around ANGLE bug
|
||||
|
||||
"float specularNormalization = ( uShininess + 2.0001 ) / 8.0;",
|
||||
|
||||
"vec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( pointVector, pointHalfVector ), 5.0 );",
|
||||
"pointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * pointDistance * specularNormalization;",
|
||||
|
||||
"#else",
|
||||
|
||||
"pointSpecular += pointDistance * pointLightColor[ i ] * uSpecularColor * pointSpecularWeight * pointDiffuseWeight;",
|
||||
|
||||
"#endif",
|
||||
|
||||
"}",
|
||||
|
||||
"#endif",
|
||||
|
||||
// directional lights
|
||||
|
||||
"#if MAX_DIR_LIGHTS > 0",
|
||||
|
||||
"vec3 dirDiffuse = vec3( 0.0 );",
|
||||
"vec3 dirSpecular = vec3( 0.0 );",
|
||||
|
||||
"for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
|
||||
|
||||
"vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );",
|
||||
"vec3 dirVector = normalize( lDirection.xyz );",
|
||||
|
||||
// diffuse
|
||||
|
||||
"#ifdef WRAP_AROUND",
|
||||
|
||||
"float directionalLightWeightingFull = max( dot( normal, dirVector ), 0.0 );",
|
||||
"float directionalLightWeightingHalf = max( 0.5 * dot( normal, dirVector ) + 0.5, 0.0 );",
|
||||
|
||||
"vec3 dirDiffuseWeight = mix( vec3( directionalLightWeightingFull ), vec3( directionalLightWeightingHalf ), wrapRGB );",
|
||||
|
||||
"#else",
|
||||
|
||||
"float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );",
|
||||
|
||||
"#endif",
|
||||
|
||||
"dirDiffuse += directionalLightColor[ i ] * uDiffuseColor * dirDiffuseWeight;",
|
||||
|
||||
// specular
|
||||
|
||||
"vec3 dirHalfVector = normalize( dirVector + viewPosition );",
|
||||
"float dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );",
|
||||
"float dirSpecularWeight = specularTex.r * max( pow( dirDotNormalHalf, uShininess ), 0.0 );",
|
||||
|
||||
"#ifdef PHYSICALLY_BASED_SHADING",
|
||||
|
||||
// 2.0 => 2.0001 is hack to work around ANGLE bug
|
||||
|
||||
"float specularNormalization = ( uShininess + 2.0001 ) / 8.0;",
|
||||
|
||||
"vec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );",
|
||||
"dirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;",
|
||||
|
||||
"#else",
|
||||
|
||||
"dirSpecular += directionalLightColor[ i ] * uSpecularColor * dirSpecularWeight * dirDiffuseWeight;",
|
||||
|
||||
"#endif",
|
||||
|
||||
"}",
|
||||
|
||||
"#endif",
|
||||
|
||||
// all lights contribution summation
|
||||
|
||||
"vec3 totalDiffuse = vec3( 0.0 );",
|
||||
"vec3 totalSpecular = vec3( 0.0 );",
|
||||
|
||||
"#if MAX_DIR_LIGHTS > 0",
|
||||
|
||||
"totalDiffuse += dirDiffuse;",
|
||||
"totalSpecular += dirSpecular;",
|
||||
|
||||
"#endif",
|
||||
|
||||
"#if MAX_POINT_LIGHTS > 0",
|
||||
|
||||
"totalDiffuse += pointDiffuse;",
|
||||
"totalSpecular += pointSpecular;",
|
||||
|
||||
"#endif",
|
||||
|
||||
"gl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * uAmbientColor) + totalSpecular;",
|
||||
|
||||
"if ( enableReflection ) {",
|
||||
|
||||
"vec3 wPos = cameraPosition - vViewPosition;",
|
||||
"vec3 vReflect = reflect( normalize( wPos ), normal );",
|
||||
|
||||
"vec4 cubeColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );",
|
||||
|
||||
"#ifdef GAMMA_INPUT",
|
||||
|
||||
"cubeColor.xyz *= cubeColor.xyz;",
|
||||
|
||||
"#endif",
|
||||
|
||||
"gl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularTex.r * uReflectivity );",
|
||||
|
||||
"}",
|
||||
|
||||
THREE.ShaderChunk[ "shadowmap_fragment" ],
|
||||
THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
|
||||
THREE.ShaderChunk[ "fog_fragment" ],
|
||||
|
||||
"}"
|
||||
|
||||
].join("\n"),
|
||||
|
||||
vertexShader: [
|
||||
|
||||
"attribute vec4 tangent;",
|
||||
|
||||
"uniform vec2 uOffset;",
|
||||
"uniform vec2 uRepeat;",
|
||||
|
||||
"#ifdef VERTEX_TEXTURES",
|
||||
|
||||
"uniform sampler2D tDisplacement;",
|
||||
"uniform float uDisplacementScale;",
|
||||
"uniform float uDisplacementBias;",
|
||||
|
||||
"#endif",
|
||||
|
||||
"varying vec3 vTangent;",
|
||||
"varying vec3 vBinormal;",
|
||||
"varying vec3 vNormal;",
|
||||
"varying vec2 vUv;",
|
||||
|
||||
"#if MAX_POINT_LIGHTS > 0",
|
||||
|
||||
"uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
|
||||
"uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
|
||||
|
||||
"varying vec4 vPointLight[ MAX_POINT_LIGHTS ];",
|
||||
|
||||
"#endif",
|
||||
|
||||
"varying vec3 vViewPosition;",
|
||||
|
||||
THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
|
||||
|
||||
"void main() {",
|
||||
|
||||
"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
|
||||
|
||||
"vViewPosition = -mvPosition.xyz;",
|
||||
|
||||
// normal, tangent and binormal vectors
|
||||
|
||||
"vNormal = normalMatrix * normal;",
|
||||
"vTangent = normalMatrix * tangent.xyz;",
|
||||
"vBinormal = cross( vNormal, vTangent ) * tangent.w;",
|
||||
|
||||
"vUv = uv * uRepeat + uOffset;",
|
||||
|
||||
// point lights
|
||||
|
||||
"#if MAX_POINT_LIGHTS > 0",
|
||||
|
||||
"for( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {",
|
||||
|
||||
"vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
|
||||
"vec3 lVector = lPosition.xyz - mvPosition.xyz;",
|
||||
|
||||
"float lDistance = 1.0;",
|
||||
"if ( pointLightDistance[ i ] > 0.0 )",
|
||||
"lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );",
|
||||
|
||||
"lVector = normalize( lVector );",
|
||||
|
||||
"vPointLight[ i ] = vec4( lVector, lDistance );",
|
||||
|
||||
"}",
|
||||
|
||||
"#endif",
|
||||
|
||||
// displacement mapping
|
||||
|
||||
"#ifdef VERTEX_TEXTURES",
|
||||
|
||||
"vec3 dv = texture2D( tDisplacement, uv ).xyz;",
|
||||
"float df = uDisplacementScale * dv.x + uDisplacementBias;",
|
||||
"vec4 displacedPosition = vec4( normalize( vNormal.xyz ) * df, 0.0 ) + mvPosition;",
|
||||
"gl_Position = projectionMatrix * displacedPosition;",
|
||||
|
||||
"#else",
|
||||
|
||||
"gl_Position = projectionMatrix * mvPosition;",
|
||||
|
||||
"#endif",
|
||||
|
||||
THREE.ShaderChunk[ "shadowmap_vertex" ],
|
||||
|
||||
"}"
|
||||
|
||||
].join("\n")
|
||||
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
// Cube map shader
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
'cube': {
|
||||
|
||||
uniforms: { "tCube": { type: "t", value: 1, texture: null },
|
||||
"tFlip": { type: "f", value: -1 } },
|
||||
|
||||
vertexShader: [
|
||||
|
||||
"varying vec3 vViewPosition;",
|
||||
|
||||
"void main() {",
|
||||
|
||||
"vec4 mPosition = objectMatrix * vec4( position, 1.0 );",
|
||||
"vViewPosition = cameraPosition - mPosition.xyz;",
|
||||
|
||||
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
|
||||
|
||||
"}"
|
||||
|
||||
].join("\n"),
|
||||
|
||||
fragmentShader: [
|
||||
|
||||
"uniform samplerCube tCube;",
|
||||
"uniform float tFlip;",
|
||||
|
||||
"varying vec3 vViewPosition;",
|
||||
|
||||
"void main() {",
|
||||
|
||||
"vec3 wPos = cameraPosition - vViewPosition;",
|
||||
"gl_FragColor = textureCube( tCube, vec3( tFlip * wPos.x, wPos.yz ) );",
|
||||
|
||||
"}"
|
||||
|
||||
].join("\n")
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user