mirror of
https://github.com/smallmain/cocos-enhance-kit.git
synced 2025-10-09 17:55:28 +00:00
初始化
This commit is contained in:
503
engine/cocos2d/renderer/scene/camera.js
Normal file
503
engine/cocos2d/renderer/scene/camera.js
Normal file
@@ -0,0 +1,503 @@
|
||||
// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
import { Vec3, Mat4, lerp, Vec4 } from '../../core/value-types';
|
||||
import { Ray } from '../../core/geom-utils';
|
||||
import enums from '../enums';
|
||||
|
||||
let _tmp_mat4 = new Mat4();
|
||||
|
||||
let _matView = new Mat4();
|
||||
let _matViewInv = new Mat4();
|
||||
let _matProj = new Mat4();
|
||||
let _matViewProj = new Mat4();
|
||||
let _matInvViewProj = new Mat4();
|
||||
let _tmp_v3 = new Vec3();
|
||||
let _tmp2_v3 = new Vec3();
|
||||
|
||||
/**
|
||||
* A representation of a camera instance
|
||||
*/
|
||||
export default class Camera {
|
||||
_poolID = -1;
|
||||
_node = null;
|
||||
_projection = enums.PROJ_PERSPECTIVE;
|
||||
|
||||
// priority. the smaller one will be rendered first
|
||||
_priority = 0;
|
||||
|
||||
// clear options
|
||||
_color = new Vec4(0.2, 0.3, 0.47, 1);
|
||||
_depth = 1;
|
||||
_stencil = 0;
|
||||
_clearFlags = enums.CLEAR_COLOR | enums.CLEAR_DEPTH;
|
||||
_clearModel = null;
|
||||
|
||||
// stages & framebuffer
|
||||
_stages = [];
|
||||
_framebuffer = null;
|
||||
|
||||
// projection properties
|
||||
_near = 0.01;
|
||||
_far = 1000.0;
|
||||
_fov = Math.PI / 4.0; // vertical fov
|
||||
_rect = {
|
||||
x: 0, y: 0, w: 1, h: 1
|
||||
};
|
||||
|
||||
// ortho properties
|
||||
_orthoHeight = 10;
|
||||
|
||||
_cullingMask = 0xffffffff;
|
||||
|
||||
|
||||
// culling mask
|
||||
get cullingMask () {
|
||||
return this._cullingMask;
|
||||
}
|
||||
|
||||
set cullingMask (mask) {
|
||||
this._cullingMask = mask;
|
||||
}
|
||||
|
||||
setCullingMask (mask) {
|
||||
this._cullingMask = mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hosting node of this camera
|
||||
* @returns {Node} the hosting node
|
||||
*/
|
||||
getNode () {
|
||||
return this._node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the hosting node of this camera
|
||||
* @param {Node} node the hosting node
|
||||
*/
|
||||
setNode (node) {
|
||||
this._node = node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the projection type of the camera
|
||||
* @returns {number} camera projection type
|
||||
*/
|
||||
getType () {
|
||||
return this._projection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the projection type of the camera
|
||||
* @param {number} type camera projection type
|
||||
*/
|
||||
setType (type) {
|
||||
this._projection = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the priority of the camera
|
||||
* @returns {number} camera priority
|
||||
*/
|
||||
getPriority () {
|
||||
return this._priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the priority of the camera
|
||||
* @param {number} priority camera priority
|
||||
*/
|
||||
setPriority (priority) {
|
||||
this._priority = priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the orthogonal height of the camera
|
||||
* @returns {number} camera height
|
||||
*/
|
||||
getOrthoHeight () {
|
||||
return this._orthoHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the orthogonal height of the camera
|
||||
* @param {number} val camera height
|
||||
*/
|
||||
setOrthoHeight (val) {
|
||||
this._orthoHeight = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the field of view of the camera
|
||||
* @returns {number} camera field of view
|
||||
*/
|
||||
getFov () {
|
||||
return this._fov;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the field of view of the camera
|
||||
* @param {number} fov camera field of view
|
||||
*/
|
||||
setFov (fov) {
|
||||
this._fov = fov;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the near clipping distance of the camera
|
||||
* @returns {number} camera near clipping distance
|
||||
*/
|
||||
getNear () {
|
||||
return this._near;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the near clipping distance of the camera
|
||||
* @param {number} near camera near clipping distance
|
||||
*/
|
||||
setNear (near) {
|
||||
this._near = near;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the far clipping distance of the camera
|
||||
* @returns {number} camera far clipping distance
|
||||
*/
|
||||
getFar () {
|
||||
return this._far;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the far clipping distance of the camera
|
||||
* @param {number} far camera far clipping distance
|
||||
*/
|
||||
setFar (far) {
|
||||
this._far = far;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the clear color of the camera
|
||||
* @returns {Vec4} out the receiving color vector
|
||||
*/
|
||||
getColor (out) {
|
||||
return Vec4.copy(out, this._color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the clear color of the camera
|
||||
* @param {number} r red channel of camera clear color
|
||||
* @param {number} g green channel of camera clear color
|
||||
* @param {number} b blue channel of camera clear color
|
||||
* @param {number} a alpha channel of camera clear color
|
||||
*/
|
||||
setColor (r, g, b, a) {
|
||||
Vec4.set(this._color, r, g, b, a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the clear depth of the camera
|
||||
* @returns {number} camera clear depth
|
||||
*/
|
||||
getDepth () {
|
||||
return this._depth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the clear depth of the camera
|
||||
* @param {number} depth camera clear depth
|
||||
*/
|
||||
setDepth (depth) {
|
||||
this._depth = depth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the clearing stencil value of the camera
|
||||
* @returns {number} camera clearing stencil value
|
||||
*/
|
||||
getStencil () {
|
||||
return this._stencil;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the clearing stencil value of the camera
|
||||
* @param {number} stencil camera clearing stencil value
|
||||
*/
|
||||
setStencil (stencil) {
|
||||
this._stencil = stencil;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the clearing flags of the camera
|
||||
* @returns {number} camera clearing flags
|
||||
*/
|
||||
getClearFlags () {
|
||||
return this._clearFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the clearing flags of the camera
|
||||
* @param {number} flags camera clearing flags
|
||||
*/
|
||||
setClearFlags (flags) {
|
||||
this._clearFlags = flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the rect of the camera
|
||||
* @param {Object} out the receiving object
|
||||
* @returns {Object} camera rect
|
||||
*/
|
||||
getRect (out) {
|
||||
out.x = this._rect.x;
|
||||
out.y = this._rect.y;
|
||||
out.w = this._rect.w;
|
||||
out.h = this._rect.h;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the rect of the camera
|
||||
* @param {Number} x - [0,1]
|
||||
* @param {Number} y - [0,1]
|
||||
* @param {Number} w - [0,1]
|
||||
* @param {Number} h - [0,1]
|
||||
*/
|
||||
setRect (x, y, w, h) {
|
||||
this._rect.x = x;
|
||||
this._rect.y = y;
|
||||
this._rect.w = w;
|
||||
this._rect.h = h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the stages of the camera
|
||||
* @returns {string[]} camera stages
|
||||
*/
|
||||
getStages () {
|
||||
return this._stages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the stages of the camera
|
||||
* @param {string[]} stages camera stages
|
||||
*/
|
||||
setStages (stages) {
|
||||
this._stages = stages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the framebuffer of the camera
|
||||
* @returns {FrameBuffer} camera framebuffer
|
||||
*/
|
||||
getFramebuffer () {
|
||||
return this._framebuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the framebuffer of the camera
|
||||
* @param {FrameBuffer} framebuffer camera framebuffer
|
||||
*/
|
||||
setFrameBuffer (framebuffer) {
|
||||
this._framebuffer = framebuffer;
|
||||
}
|
||||
|
||||
_calcMatrices (width, height) {
|
||||
// view matrix
|
||||
this._node.getWorldRT(_matViewInv);
|
||||
Mat4.invert(_matView, _matViewInv);
|
||||
|
||||
// projection matrix
|
||||
let aspect = width / height;
|
||||
if (this._projection === enums.PROJ_PERSPECTIVE) {
|
||||
Mat4.perspective(_matProj,
|
||||
this._fov,
|
||||
aspect,
|
||||
this._near,
|
||||
this._far
|
||||
);
|
||||
} else {
|
||||
let x = this._orthoHeight * aspect;
|
||||
let y = this._orthoHeight;
|
||||
Mat4.ortho(_matProj,
|
||||
-x, x, -y, y, this._near, this._far
|
||||
);
|
||||
}
|
||||
|
||||
// view-projection
|
||||
Mat4.mul(_matViewProj, _matProj, _matView);
|
||||
// inv view-projection
|
||||
Mat4.invert(_matInvViewProj, _matViewProj);
|
||||
}
|
||||
|
||||
/**
|
||||
* extract a view of this camera
|
||||
* @param {View} out the receiving view
|
||||
* @param {number} width framebuffer width
|
||||
* @param {number} height framebuffer height
|
||||
*/
|
||||
extractView (out, width, height) {
|
||||
if (this._framebuffer) {
|
||||
width = this._framebuffer._width;
|
||||
height = this._framebuffer._height;
|
||||
}
|
||||
|
||||
// priority
|
||||
out._priority = this._priority;
|
||||
|
||||
// rect
|
||||
out._rect.x = this._rect.x * width;
|
||||
out._rect.y = this._rect.y * height;
|
||||
out._rect.w = this._rect.w * width;
|
||||
out._rect.h = this._rect.h * height;
|
||||
|
||||
// clear opts
|
||||
this.getColor(out._color);
|
||||
out._depth = this._depth;
|
||||
out._stencil = this._stencil;
|
||||
out._clearFlags = this._clearFlags;
|
||||
out._clearModel = this._clearModel;
|
||||
|
||||
// stages & framebuffer
|
||||
out._stages = this._stages;
|
||||
out._framebuffer = this._framebuffer;
|
||||
|
||||
this._calcMatrices(width, height);
|
||||
Mat4.copy(out._matView, _matView);
|
||||
Mat4.copy(out._matViewInv, _matViewInv);
|
||||
Mat4.copy(out._matProj, _matProj);
|
||||
Mat4.copy(out._matViewProj, _matViewProj);
|
||||
Mat4.copy(out._matInvViewProj, _matInvViewProj);
|
||||
|
||||
out._cullingMask = this._cullingMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* transform a screen position to a world space ray
|
||||
* @param {number} x the screen x position to be transformed
|
||||
* @param {number} y the screen y position to be transformed
|
||||
* @param {number} width framebuffer width
|
||||
* @param {number} height framebuffer height
|
||||
* @param {Ray} out the resulting ray
|
||||
* @returns {Ray} the resulting ray
|
||||
*/
|
||||
screenPointToRay (x, y, width, height, out) {
|
||||
if (!cc.geomUtils) return out;
|
||||
|
||||
out = out || new Ray();
|
||||
this._calcMatrices(width, height);
|
||||
|
||||
let cx = this._rect.x * width;
|
||||
let cy = this._rect.y * height;
|
||||
let cw = this._rect.w * width;
|
||||
let ch = this._rect.h * height;
|
||||
|
||||
// far plane intersection
|
||||
Vec3.set(_tmp2_v3, (x - cx) / cw * 2 - 1, (y - cy) / ch * 2 - 1, 1);
|
||||
Vec3.transformMat4(_tmp2_v3, _tmp2_v3, _matInvViewProj);
|
||||
|
||||
if (this._projection === enums.PROJ_PERSPECTIVE) {
|
||||
// camera origin
|
||||
this._node.getWorldPosition(_tmp_v3);
|
||||
} else {
|
||||
// near plane intersection
|
||||
Vec3.set(_tmp_v3, (x - cx) / cw * 2 - 1, (y - cy) / ch * 2 - 1, -1);
|
||||
Vec3.transformMat4(_tmp_v3, _tmp_v3, _matInvViewProj);
|
||||
}
|
||||
|
||||
return Ray.fromPoints(out, _tmp_v3, _tmp2_v3);
|
||||
}
|
||||
|
||||
/**
|
||||
* transform a screen position to world space
|
||||
* @param {Vec3} out the resulting vector
|
||||
* @param {Vec3} screenPos the screen position to be transformed
|
||||
* @param {number} width framebuffer width
|
||||
* @param {number} height framebuffer height
|
||||
* @returns {Vec3} the resulting vector
|
||||
*/
|
||||
screenToWorld (out, screenPos, width, height) {
|
||||
this._calcMatrices(width, height);
|
||||
|
||||
let cx = this._rect.x * width;
|
||||
let cy = this._rect.y * height;
|
||||
let cw = this._rect.w * width;
|
||||
let ch = this._rect.h * height;
|
||||
|
||||
if (this._projection === enums.PROJ_PERSPECTIVE) {
|
||||
// calculate screen pos in far clip plane
|
||||
Vec3.set(out,
|
||||
(screenPos.x - cx) / cw * 2 - 1,
|
||||
(screenPos.y - cy) / ch * 2 - 1,
|
||||
0.9999
|
||||
);
|
||||
|
||||
// transform to world
|
||||
Vec3.transformMat4(out, out, _matInvViewProj);
|
||||
|
||||
// lerp to depth z
|
||||
this._node.getWorldPosition(_tmp_v3);
|
||||
|
||||
Vec3.lerp(out, _tmp_v3, out, lerp(this._near / this._far, 1, screenPos.z));
|
||||
} else {
|
||||
Vec3.set(out,
|
||||
(screenPos.x - cx) / cw * 2 - 1,
|
||||
(screenPos.y - cy) / ch * 2 - 1,
|
||||
screenPos.z * 2 - 1
|
||||
);
|
||||
|
||||
// transform to world
|
||||
Vec3.transformMat4(out, out, _matInvViewProj);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* transform a world space position to screen space
|
||||
* @param {Vec3} out the resulting vector
|
||||
* @param {Vec3} worldPos the world space position to be transformed
|
||||
* @param {number} width framebuffer width
|
||||
* @param {number} height framebuffer height
|
||||
* @returns {Vec3} the resulting vector
|
||||
*/
|
||||
worldToScreen (out, worldPos, width, height) {
|
||||
this._calcMatrices(width, height);
|
||||
|
||||
let cx = this._rect.x * width;
|
||||
let cy = this._rect.y * height;
|
||||
let cw = this._rect.w * width;
|
||||
let ch = this._rect.h * height;
|
||||
|
||||
Vec3.transformMat4(out, worldPos, _matViewProj);
|
||||
out.x = cx + (out.x + 1) * 0.5 * cw;
|
||||
out.y = cy + (out.y + 1) * 0.5 * ch;
|
||||
out.z = out.z * 0.5 + 0.5;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* transform a world space matrix to screen space
|
||||
* @param {Mat4} out the resulting vector
|
||||
* @param {Mat4} worldMatrix the world space matrix to be transformed
|
||||
* @param {number} width framebuffer width
|
||||
* @param {number} height framebuffer height
|
||||
* @returns {Mat4} the resulting vector
|
||||
*/
|
||||
worldMatrixToScreen (out, worldMatrix, width, height) {
|
||||
this._calcMatrices(width, height);
|
||||
|
||||
Mat4.mul(out, _matViewProj, worldMatrix);
|
||||
|
||||
let halfWidth = width / 2;
|
||||
let halfHeight = height / 2;
|
||||
Mat4.identity(_tmp_mat4);
|
||||
Mat4.transform(_tmp_mat4, _tmp_mat4, Vec3.set(_tmp_v3, halfWidth, halfHeight, 0));
|
||||
Mat4.scale(_tmp_mat4, _tmp_mat4, Vec3.set(_tmp_v3, halfWidth, halfHeight, 1));
|
||||
|
||||
Mat4.mul(out, _tmp_mat4, out);
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
485
engine/cocos2d/renderer/scene/light.js
Normal file
485
engine/cocos2d/renderer/scene/light.js
Normal file
@@ -0,0 +1,485 @@
|
||||
// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
import { Mat4, Mat3, Vec3, toRadian } from '../../core/value-types';
|
||||
import gfx from '../gfx';
|
||||
|
||||
import enums from '../enums';
|
||||
|
||||
const _forward = cc.v3(0, 0, -1);
|
||||
|
||||
let _m4_tmp = cc.mat4();
|
||||
let _m3_tmp = Mat3.create();
|
||||
let _transformedLightDirection = cc.v3(0, 0, 0);
|
||||
|
||||
// compute light viewProjMat for shadow.
|
||||
function _computeSpotLightViewProjMatrix(light, outView, outProj) {
|
||||
// view matrix
|
||||
light._node.getWorldRT(outView);
|
||||
Mat4.invert(outView, outView);
|
||||
|
||||
// proj matrix
|
||||
Mat4.perspective(outProj, light._spotAngle * light._spotAngleScale, 1, light._shadowMinDepth, light._shadowMaxDepth);
|
||||
}
|
||||
|
||||
function _computeDirectionalLightViewProjMatrix(light, outView, outProj) {
|
||||
// view matrix
|
||||
light._node.getWorldRT(outView);
|
||||
Mat4.invert(outView, outView);
|
||||
|
||||
// TODO: should compute directional light frustum based on rendered meshes in scene.
|
||||
// proj matrix
|
||||
let halfSize = light._shadowFrustumSize / 2;
|
||||
Mat4.ortho(outProj, -halfSize, halfSize, -halfSize, halfSize, light._shadowMinDepth, light._shadowMaxDepth);
|
||||
}
|
||||
|
||||
function _computePointLightViewProjMatrix(light, outView, outProj) {
|
||||
// view matrix
|
||||
light._node.getWorldRT(outView);
|
||||
Mat4.invert(outView, outView);
|
||||
|
||||
// The transformation from Cartesian to polar coordinates is not a linear function,
|
||||
// so it cannot be achieved by means of a fixed matrix multiplication.
|
||||
// Here we just use a nearly 180 degree perspective matrix instead.
|
||||
Mat4.perspective(outProj, toRadian(179), 1, light._shadowMinDepth, light._shadowMaxDepth);
|
||||
}
|
||||
|
||||
/**
|
||||
* A representation of a light source.
|
||||
* Could be a point light, a spot light or a directional light.
|
||||
*/
|
||||
export default class Light {
|
||||
/**
|
||||
* Setup a default directional light with no shadows
|
||||
*/
|
||||
constructor() {
|
||||
this._poolID = -1;
|
||||
this._node = null;
|
||||
|
||||
this._type = enums.LIGHT_DIRECTIONAL;
|
||||
|
||||
this._color = new Vec3(1, 1, 1);
|
||||
this._intensity = 1;
|
||||
|
||||
// used for spot and point light
|
||||
this._range = 1;
|
||||
// used for spot light, default to 60 degrees
|
||||
this._spotAngle = toRadian(60);
|
||||
this._spotExp = 1;
|
||||
// cached for uniform
|
||||
this._directionUniform = new Float32Array(3);
|
||||
this._positionUniform = new Float32Array(3);
|
||||
this._colorUniform = new Float32Array([this._color.x * this._intensity, this._color.y * this._intensity, this._color.z * this._intensity]);
|
||||
this._spotUniform = new Float32Array([Math.cos(this._spotAngle * 0.5), this._spotExp]);
|
||||
|
||||
// shadow params
|
||||
this._shadowType = enums.SHADOW_NONE;
|
||||
this._shadowFrameBuffer = null;
|
||||
this._shadowMap = null;
|
||||
this._shadowMapDirty = false;
|
||||
this._shadowDepthBuffer = null;
|
||||
this._shadowResolution = 1024;
|
||||
this._shadowBias = 0.0005;
|
||||
this._shadowDarkness = 1;
|
||||
this._shadowMinDepth = 1;
|
||||
this._shadowMaxDepth = 1000;
|
||||
this._frustumEdgeFalloff = 0; // used by directional and spot light.
|
||||
this._viewProjMatrix = cc.mat4();
|
||||
this._spotAngleScale = 1; // used for spot light.
|
||||
this._shadowFrustumSize = 50; // used for directional light.
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hosting node of this camera
|
||||
* @returns {Node} the hosting node
|
||||
*/
|
||||
getNode() {
|
||||
return this._node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the hosting node of this camera
|
||||
* @param {Node} node the hosting node
|
||||
*/
|
||||
setNode(node) {
|
||||
this._node = node;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the color of the light source
|
||||
* @param {number} r red channel of the light color
|
||||
* @param {number} g green channel of the light color
|
||||
* @param {number} b blue channel of the light color
|
||||
*/
|
||||
setColor(r, g, b) {
|
||||
Vec3.set(this._color, r, g, b);
|
||||
this._colorUniform[0] = r * this._intensity;
|
||||
this._colorUniform[1] = g * this._intensity;
|
||||
this._colorUniform[2] = b * this._intensity;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the color of the light source
|
||||
* @returns {Vec3} the light color
|
||||
*/
|
||||
get color() {
|
||||
return this._color;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the intensity of the light source
|
||||
* @param {number} val the light intensity
|
||||
*/
|
||||
setIntensity(val) {
|
||||
this._intensity = val;
|
||||
this._colorUniform[0] = val * this._color.x;
|
||||
this._colorUniform[1] = val * this._color.y;
|
||||
this._colorUniform[2] = val * this._color.z;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the intensity of the light source
|
||||
* @returns {number} the light intensity
|
||||
*/
|
||||
get intensity() {
|
||||
return this._intensity;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the type of the light source
|
||||
* @param {number} type light source type
|
||||
*/
|
||||
setType(type) {
|
||||
this._type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the type of the light source
|
||||
* @returns {number} light source type
|
||||
*/
|
||||
get type() {
|
||||
return this._type;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the spot light angle
|
||||
* @param {number} val spot light angle
|
||||
*/
|
||||
setSpotAngle(val) {
|
||||
this._spotAngle = val;
|
||||
this._spotUniform[0] = Math.cos(this._spotAngle * 0.5);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the spot light angle
|
||||
* @returns {number} spot light angle
|
||||
*/
|
||||
get spotAngle() {
|
||||
return this._spotAngle;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the spot light exponential
|
||||
* @param {number} val spot light exponential
|
||||
*/
|
||||
setSpotExp(val) {
|
||||
this._spotExp = val;
|
||||
this._spotUniform[1] = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the spot light exponential
|
||||
* @returns {number} spot light exponential
|
||||
*/
|
||||
get spotExp() {
|
||||
return this._spotExp;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the range of the light source
|
||||
* @param {number} val light source range
|
||||
*/
|
||||
setRange(val) {
|
||||
this._range = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the range of the light source
|
||||
* @returns {number} range of the light source
|
||||
*/
|
||||
get range() {
|
||||
return this._range;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the shadow type of the light source
|
||||
* @param {number} type light source shadow type
|
||||
*/
|
||||
setShadowType(type) {
|
||||
if (this._shadowType === enums.SHADOW_NONE && type !== enums.SHADOW_NONE) {
|
||||
this._shadowMapDirty = true;
|
||||
}
|
||||
this._shadowType = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the shadow type of the light source
|
||||
* @returns {number} light source shadow type
|
||||
*/
|
||||
get shadowType() {
|
||||
return this._shadowType;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the shadowmap of the light source
|
||||
* @returns {Texture2D} light source shadowmap
|
||||
*/
|
||||
get shadowMap() {
|
||||
return this._shadowMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the view-projection matrix of the light source
|
||||
* @returns {Mat4} light source view-projection matrix
|
||||
*/
|
||||
get viewProjMatrix() {
|
||||
return this._viewProjMatrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the shadow resolution of the light source
|
||||
* @param {number} val light source shadow resolution
|
||||
*/
|
||||
setShadowResolution(val) {
|
||||
if (this._shadowResolution !== val) {
|
||||
this._shadowMapDirty = true;
|
||||
}
|
||||
this._shadowResolution = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the shadow resolution of the light source
|
||||
* @returns {number} light source shadow resolution
|
||||
*/
|
||||
get shadowResolution() {
|
||||
return this._shadowResolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the shadow bias of the light source
|
||||
* @param {number} val light source shadow bias
|
||||
*/
|
||||
setShadowBias(val) {
|
||||
this._shadowBias = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the shadow bias of the light source
|
||||
* @returns {number} light source shadow bias
|
||||
*/
|
||||
get shadowBias() {
|
||||
return this._shadowBias;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the shadow darkness of the light source
|
||||
* @param {number} val light source shadow darkness
|
||||
*/
|
||||
setShadowDarkness(val) {
|
||||
this._shadowDarkness = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the shadow darkness of the light source
|
||||
* @returns {number} light source shadow darkness
|
||||
*/
|
||||
get shadowDarkness() {
|
||||
return this._shadowDarkness;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the shadow min depth of the light source
|
||||
* @param {number} val light source shadow min depth
|
||||
*/
|
||||
setShadowMinDepth(val) {
|
||||
this._shadowMinDepth = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the shadow min depth of the light source
|
||||
* @returns {number} light source shadow min depth
|
||||
*/
|
||||
get shadowMinDepth() {
|
||||
if (this._type === enums.LIGHT_DIRECTIONAL) {
|
||||
return 1.0;
|
||||
}
|
||||
return this._shadowMinDepth;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the shadow max depth of the light source
|
||||
* @param {number} val light source shadow max depth
|
||||
*/
|
||||
setShadowMaxDepth(val) {
|
||||
this._shadowMaxDepth = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the shadow max depth of the light source
|
||||
* @returns {number} light source shadow max depth
|
||||
*/
|
||||
get shadowMaxDepth() {
|
||||
if (this._type === enums.LIGHT_DIRECTIONAL) {
|
||||
return 1.0;
|
||||
}
|
||||
return this._shadowMaxDepth;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the frustum edge falloff of the light source
|
||||
* @param {number} val light source frustum edge falloff
|
||||
*/
|
||||
setFrustumEdgeFalloff(val) {
|
||||
this._frustumEdgeFalloff = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the frustum edge falloff of the light source
|
||||
* @returns {number} light source frustum edge falloff
|
||||
*/
|
||||
get frustumEdgeFalloff() {
|
||||
return this._frustumEdgeFalloff;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the shadow frustum size of the light source
|
||||
* @param {number} val light source shadow frustum size
|
||||
*/
|
||||
setShadowFrustumSize(val) {
|
||||
this._shadowFrustumSize = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the shadow frustum size of the light source
|
||||
* @returns {number} light source shadow frustum size
|
||||
*/
|
||||
get shadowFrustumSize() {
|
||||
return this._shadowFrustumSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract a view of this light source
|
||||
* @param {View} out the receiving view
|
||||
* @param {string[]} stages the stages using the view
|
||||
*/
|
||||
extractView(out, stages) {
|
||||
// TODO: view should not handle light.
|
||||
out._shadowLight = this;
|
||||
|
||||
// priority. TODO: use varying value for shadow view?
|
||||
out._priority = -1;
|
||||
|
||||
// rect
|
||||
out._rect.x = 0;
|
||||
out._rect.y = 0;
|
||||
out._rect.w = this._shadowResolution;
|
||||
out._rect.h = this._shadowResolution;
|
||||
|
||||
// clear opts
|
||||
Vec3.set(out._color, 1, 1, 1);
|
||||
out._depth = 1;
|
||||
out._stencil = 1;
|
||||
out._clearFlags = enums.CLEAR_COLOR | enums.CLEAR_DEPTH;
|
||||
|
||||
// stages & framebuffer
|
||||
out._stages = stages;
|
||||
out._framebuffer = this._shadowFrameBuffer;
|
||||
|
||||
// view projection matrix
|
||||
switch(this._type) {
|
||||
case enums.LIGHT_SPOT:
|
||||
_computeSpotLightViewProjMatrix(this, out._matView, out._matProj);
|
||||
break;
|
||||
|
||||
case enums.LIGHT_DIRECTIONAL:
|
||||
_computeDirectionalLightViewProjMatrix(this, out._matView, out._matProj);
|
||||
break;
|
||||
|
||||
case enums.LIGHT_POINT:
|
||||
_computePointLightViewProjMatrix(this, out._matView, out._matProj);
|
||||
break;
|
||||
case enums.LIGHT_AMBIENT:
|
||||
break;
|
||||
default:
|
||||
console.warn('shadow of this light type is not supported');
|
||||
}
|
||||
|
||||
// view-projection
|
||||
Mat4.mul(out._matViewProj, out._matProj, out._matView);
|
||||
this._viewProjMatrix = out._matViewProj;
|
||||
Mat4.invert(out._matInvViewProj, out._matViewProj);
|
||||
|
||||
// update view's frustum
|
||||
// out._frustum.update(out._matViewProj, out._matInvViewProj);
|
||||
|
||||
out._cullingMask = 0xffffffff;
|
||||
}
|
||||
|
||||
_updateLightPositionAndDirection() {
|
||||
this._node.getWorldMatrix(_m4_tmp);
|
||||
Mat3.fromMat4(_m3_tmp, _m4_tmp);
|
||||
Vec3.transformMat3(_transformedLightDirection, _forward, _m3_tmp);
|
||||
Vec3.toArray(this._directionUniform, _transformedLightDirection);
|
||||
let pos = this._positionUniform;
|
||||
let m = _m4_tmp.m;
|
||||
pos[0] = m[12];
|
||||
pos[1] = m[13];
|
||||
pos[2] = m[14];
|
||||
}
|
||||
|
||||
_generateShadowMap(device) {
|
||||
this._shadowMap = new gfx.Texture2D(device, {
|
||||
width: this._shadowResolution,
|
||||
height: this._shadowResolution,
|
||||
format: gfx.TEXTURE_FMT_RGBA8,
|
||||
wrapS: gfx.WRAP_CLAMP,
|
||||
wrapT: gfx.WRAP_CLAMP,
|
||||
});
|
||||
this._shadowDepthBuffer = new gfx.RenderBuffer(device,
|
||||
gfx.RB_FMT_D16,
|
||||
this._shadowResolution,
|
||||
this._shadowResolution
|
||||
);
|
||||
this._shadowFrameBuffer = new gfx.FrameBuffer(device, this._shadowResolution, this._shadowResolution, {
|
||||
colors: [this._shadowMap],
|
||||
depth: this._shadowDepthBuffer,
|
||||
});
|
||||
}
|
||||
|
||||
_destroyShadowMap() {
|
||||
if (this._shadowMap) {
|
||||
this._shadowMap.destroy();
|
||||
this._shadowDepthBuffer.destroy();
|
||||
this._shadowFrameBuffer.destroy();
|
||||
this._shadowMap = null;
|
||||
this._shadowDepthBuffer = null;
|
||||
this._shadowFrameBuffer = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* update the light source
|
||||
* @param {Device} device the rendering device
|
||||
*/
|
||||
update(device) {
|
||||
this._updateLightPositionAndDirection();
|
||||
|
||||
if (this._shadowType === enums.SHADOW_NONE) {
|
||||
this._destroyShadowMap();
|
||||
} else if (this._shadowMapDirty) {
|
||||
this._destroyShadowMap();
|
||||
this._generateShadowMap(device);
|
||||
this._shadowMapDirty = false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
65
engine/cocos2d/renderer/scene/model.js
Normal file
65
engine/cocos2d/renderer/scene/model.js
Normal file
@@ -0,0 +1,65 @@
|
||||
// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
/**
|
||||
* A representation of a model
|
||||
*/
|
||||
export default class Model {
|
||||
/**
|
||||
* Setup a default empty model
|
||||
*/
|
||||
constructor() {
|
||||
this._type = 'default';
|
||||
this._poolID = -1;
|
||||
this._node = null;
|
||||
this._inputAssembler = null;
|
||||
this._effect = null;
|
||||
this._viewID = -1;
|
||||
this._cameraID = -1;
|
||||
this._userKey = -1;
|
||||
this._castShadow = false;
|
||||
this._boundingShape = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the hosting node of this model
|
||||
* @param {Node} node the hosting node
|
||||
*/
|
||||
setNode(node) {
|
||||
this._node = node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the input assembler
|
||||
* @param {InputAssembler} ia
|
||||
*/
|
||||
setInputAssembler(ia) {
|
||||
this._inputAssembler = ia;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the model effect
|
||||
* @param {?Effect} effect the effect to use
|
||||
*/
|
||||
setEffect(effect) {
|
||||
this._effect = effect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user key
|
||||
* @param {number} key
|
||||
*/
|
||||
setUserKey(key) {
|
||||
this._userKey = key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a drawing item
|
||||
* @param {Object} out the receiving item
|
||||
*/
|
||||
extractDrawItem(out) {
|
||||
out.model = this;
|
||||
out.node = this._node;
|
||||
out.ia = this._inputAssembler;
|
||||
out.effect = this._effect;
|
||||
}
|
||||
}
|
181
engine/cocos2d/renderer/scene/scene.js
Normal file
181
engine/cocos2d/renderer/scene/scene.js
Normal file
@@ -0,0 +1,181 @@
|
||||
// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
import { FixedArray } from '../memop';
|
||||
|
||||
/**
|
||||
* A representation of the scene
|
||||
*/
|
||||
class Scene {
|
||||
/**
|
||||
* Setup a default empty scene
|
||||
*/
|
||||
constructor(app) {
|
||||
this._lights = new FixedArray(16);
|
||||
this._models = new FixedArray(16);
|
||||
this._cameras = new FixedArray(16);
|
||||
this._debugCamera = null;
|
||||
this._app = app;
|
||||
|
||||
// NOTE: we don't use pool for views (because it's less changed and it doesn't have poolID)
|
||||
this._views = [];
|
||||
}
|
||||
|
||||
_add(pool, item) {
|
||||
if (item._poolID !== -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
pool.push(item);
|
||||
item._poolID = pool.length - 1;
|
||||
}
|
||||
|
||||
_remove(pool, item) {
|
||||
if (item._poolID === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
pool.data[pool.length-1]._poolID = item._poolID;
|
||||
pool.fastRemove(item._poolID);
|
||||
item._poolID = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* reset the model viewIDs
|
||||
*/
|
||||
reset() {
|
||||
for (let i = 0; i < this._models.length; ++i) {
|
||||
let model = this._models.data[i];
|
||||
model._viewID = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the debug camera
|
||||
* @param {Camera} cam the debug camera
|
||||
*/
|
||||
setDebugCamera(cam) {
|
||||
this._debugCamera = cam;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the count of registered cameras
|
||||
* @returns {number} camera count
|
||||
*/
|
||||
getCameraCount() {
|
||||
return this._cameras.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specified camera
|
||||
* @param {number} idx camera index
|
||||
* @returns {Camera} the specified camera
|
||||
*/
|
||||
getCamera(idx) {
|
||||
return this._cameras.data[idx];
|
||||
}
|
||||
|
||||
/**
|
||||
* register a camera
|
||||
* @param {Camera} camera the new camera
|
||||
*/
|
||||
addCamera(camera) {
|
||||
this._add(this._cameras, camera);
|
||||
}
|
||||
|
||||
/**
|
||||
* remove a camera
|
||||
* @param {Camera} camera the camera to be removed
|
||||
*/
|
||||
removeCamera(camera) {
|
||||
this._remove(this._cameras, camera);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the count of registered model
|
||||
* @returns {number} model count
|
||||
*/
|
||||
getModelCount() {
|
||||
return this._models.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specified model
|
||||
* @param {number} idx model index
|
||||
* @returns {Model} the specified model
|
||||
*/
|
||||
getModel(idx) {
|
||||
return this._models.data[idx];
|
||||
}
|
||||
|
||||
/**
|
||||
* register a model
|
||||
* @param {Model} model the new model
|
||||
*/
|
||||
addModel(model) {
|
||||
this._add(this._models, model);
|
||||
}
|
||||
|
||||
/**
|
||||
* remove a model
|
||||
* @param {Model} model the model to be removed
|
||||
*/
|
||||
removeModel(model) {
|
||||
this._remove(this._models, model);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the count of registered light
|
||||
* @returns {number} light count
|
||||
*/
|
||||
getLightCount() {
|
||||
return this._lights.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specified light
|
||||
* @param {number} idx light index
|
||||
* @returns {Light} the specified light
|
||||
*/
|
||||
getLight(idx) {
|
||||
return this._lights.data[idx];
|
||||
}
|
||||
|
||||
/**
|
||||
* register a light
|
||||
* @param {Light} light the new light
|
||||
*/
|
||||
addLight(light) {
|
||||
this._add(this._lights, light);
|
||||
}
|
||||
|
||||
/**
|
||||
* remove a light
|
||||
* @param {Light} light the light to be removed
|
||||
*/
|
||||
removeLight(light) {
|
||||
this._remove(this._lights, light);
|
||||
}
|
||||
|
||||
/**
|
||||
* register a view
|
||||
* @param {View} view the new view
|
||||
*/
|
||||
addView(view) {
|
||||
if (this._views.indexOf(view) === -1) {
|
||||
this._views.push(view);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* remove a view
|
||||
* @param {View} view the view to be removed
|
||||
*/
|
||||
removeView(view) {
|
||||
let idx = this._views.indexOf(view);
|
||||
if (idx !== -1) {
|
||||
this._views.splice(idx, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Scene;
|
Reference in New Issue
Block a user