Skip to content

Commit

Permalink
Repair shadow matrix for 3d-v1.2 (#7223)
Browse files Browse the repository at this point in the history
* calculate sphere

* calculate shadowCamera matirx

* update

* add pcf shadow

* update

* Modify shadowUI style

* Solve the error

* use else if

* add pcf sampler to x25 times
  • Loading branch information
troublemaker52025 committed Aug 28, 2020
1 parent c451c8a commit c99525c
Show file tree
Hide file tree
Showing 10 changed files with 223 additions and 24 deletions.
24 changes: 12 additions & 12 deletions cocos/core/3d/builtin/effects.ts

Large diffs are not rendered by default.

43 changes: 42 additions & 1 deletion cocos/core/geometry/sphere.ts
Expand Up @@ -4,8 +4,12 @@

import { Mat4, Quat, Vec3 } from '../math';
import enums from './enums';
import aabb from './aabb';

const _v3_tmp = new Vec3();
const _offset = new Vec3();
const _min = new Vec3();
const _max = new Vec3();
function maxComponent (v: Vec3) { return Math.max(Math.max(v.x, v.y), v.z); }

/**
Expand Down Expand Up @@ -79,7 +83,7 @@ export default class sphere {
/**
* @en
* Set the components of a sphere to the given values
* @zh
* @zh
* 将球体的属性设置为给定的值。
* @param {sphere} out 接受操作的 sphere。
* @param cx 形状的相对于原点的 X 坐标。
Expand All @@ -98,6 +102,43 @@ export default class sphere {
return out;
}

/**
* @zh
* 球跟点合并
*/
public static mergePoint (out: sphere, s: sphere, point: Vec3) {
if (s.radius < 0.0) {
out.center = point;
out.radius = 0.0;
return out;
}

Vec3.subtract(_offset, point, s.center);
const dist = _offset.length();

if (dist > s.radius) {
const half = (dist - s.radius) * 0.5;
out.radius += half;
Vec3.multiplyScalar(_offset, _offset, half / dist);
Vec3.add(out.center, out.center, _offset);
}

return out;
}

/**
* @zh
* 球跟立方体合并
*/
public static mergeAABB (out: sphere, s:sphere, a: aabb) {
a.getBoundary(_min, _max);

sphere.mergePoint(out, s, _min);
sphere.mergePoint(out, s, _max);

return out;
}

/**
* @en
* The center of this sphere.
Expand Down
6 changes: 5 additions & 1 deletion cocos/core/pipeline/define.ts
Expand Up @@ -198,7 +198,9 @@ export class UBOShadow {
public static MAT_LIGHT_PLANE_PROJ_OFFSET: number = 0;
public static MAT_LIGHT_VIEW_PROJ_OFFSET: number = UBOShadow.MAT_LIGHT_PLANE_PROJ_OFFSET + 16;
public static SHADOW_COLOR_OFFSET: number = UBOShadow.MAT_LIGHT_VIEW_PROJ_OFFSET + 16;
public static COUNT: number = UBOShadow.SHADOW_COLOR_OFFSET + 4;
public static SHADOW_PCF_OFFSET: number = UBOShadow.SHADOW_COLOR_OFFSET + 4;
public static SHADOW_SIZE_OFFSET: number = UBOShadow.SHADOW_PCF_OFFSET + 4;
public static COUNT: number = UBOShadow.SHADOW_SIZE_OFFSET + 4;
public static SIZE: number = UBOShadow.COUNT * 4;

public static BLOCK: IBlockInfo = {
Expand All @@ -207,6 +209,8 @@ export class UBOShadow {
{ name: 'cc_matLightPlaneProj', type: GFXType.MAT4, count: 1 },
{ name: 'cc_matLightViewProj', type: GFXType.MAT4, count: 1 },
{ name: 'cc_shadowColor', type: GFXType.FLOAT4, count: 1 },
{ name: 'cc_shadowPCF', type: GFXType.FLOAT4, count: 1 },
{ name: 'cc_shadowSize', type: GFXType.FLOAT4, count: 1 },
],
};
}
Expand Down
22 changes: 19 additions & 3 deletions cocos/core/pipeline/forward/forward-pipeline.ts
Expand Up @@ -27,6 +27,7 @@ import { sceneCulling } from './scene-culling';

const matShadowView = new Mat4();
const matShadowViewProj = new Mat4();
const vec4 = new Vec4();

/**
* @en The forward render pipeline
Expand Down Expand Up @@ -178,11 +179,20 @@ export class ForwardPipeline extends RenderPipeline {

if (mainLight && shadowInfo.type === ShadowType.ShadowMap) {
// light view
Mat4.invert(matShadowView, mainLight!.node!.worldMatrix);
const shadowCameraView = shadowInfo.getWorldMatrix(mainLight!.node!.worldRotation, mainLight!.direction);
Mat4.invert(matShadowView, shadowCameraView);

// light proj
const x = shadowInfo.orthoSize * shadowInfo.aspect;
const y = shadowInfo.orthoSize;
let x: number = 0;
let y: number = 0;
if (shadowInfo.orthoSize > shadowInfo.sphere.radius) {
x = shadowInfo.orthoSize * shadowInfo.aspect;
y = shadowInfo.orthoSize;
} else {
// if orthoSize is the smallest, auto calculate orthoSize.
x = shadowInfo.sphere.radius * shadowInfo.aspect;
y = shadowInfo.sphere.radius;
}
const projectionSignY = device.screenSpaceSignY * device.UVSpaceSignY;
Mat4.ortho(matShadowViewProj, -x, x, -y, y, shadowInfo.near, shadowInfo.far,
device.clipSpaceMinZ, projectionSignY);
Expand All @@ -191,6 +201,12 @@ export class ForwardPipeline extends RenderPipeline {
Mat4.multiply(matShadowViewProj, matShadowViewProj, matShadowView);

Mat4.toArray(this._shadowUBO, matShadowViewProj, UBOShadow.MAT_LIGHT_VIEW_PROJ_OFFSET);

vec4.set(shadowInfo.pcf);
Vec4.toArray(this._shadowUBO, vec4, UBOShadow.SHADOW_PCF_OFFSET);

vec4.set(shadowInfo.size.x, shadowInfo.size.y);
Vec4.toArray(this._shadowUBO, vec4, UBOShadow.SHADOW_SIZE_OFFSET);
}

// update ubos
Expand Down
6 changes: 5 additions & 1 deletion cocos/core/pipeline/forward/scene-culling.ts
@@ -1,4 +1,4 @@
import { intersect } from '../../geometry';
import { intersect, sphere } from '../../geometry';
import { Model, Camera } from '../../renderer';
import { Layers } from '../../scene-graph';
import { Vec3} from '../../math';
Expand Down Expand Up @@ -48,6 +48,9 @@ export function sceneCulling (pipeline: ForwardPipeline, view: RenderView) {

const mainLight = scene.mainLight;
const shadows = pipeline.shadows;
const shadowSphere = shadows.sphere;
shadowSphere.center.set(0.0, 0.0, 0.0);
shadowSphere.radius = 0.01;
if (mainLight) {
mainLight.update();
if (shadows.type === ShadowType.Planar) {
Expand Down Expand Up @@ -78,6 +81,7 @@ export function sceneCulling (pipeline: ForwardPipeline, view: RenderView) {

// shadow render Object
if (model.castShadow) {
sphere.mergeAABB(shadowSphere, shadowSphere, model.worldBounds!);
shadowObjects.push(getCastShadowRenderObject(model, camera));
}

Expand Down
70 changes: 67 additions & 3 deletions cocos/core/renderer/scene/shadows.ts
@@ -1,8 +1,8 @@

import { Material } from '../../assets/material';
import { aabb, frustum, intersect } from '../../geometry';
import { aabb, frustum, intersect, sphere } from '../../geometry';
import { GFXPipelineState } from '../../gfx/pipeline-state';
import { Color, Mat4, Quat, Vec3, Vec2 } from '../../math';
import { Color, Mat4, Quat, Vec3, Vec2, Vec4 } from '../../math';
import { UBOShadow, SetIndex} from '../../pipeline/define';
import { DirectionalLight } from './directional-light';
import { Model } from './model';
Expand All @@ -21,6 +21,9 @@ const _v3 = new Vec3();
const _ab = new aabb();
const _qt = new Quat();
const _up = new Vec3(0, 1, 0);
const _dir_negate = new Vec3();
const _vec3_p = new Vec3();
const _mat4_trans = new Mat4();

/**
* @zh 阴影类型。
Expand All @@ -46,6 +49,42 @@ export const ShadowType = Enum({
ShadowMap: 1,
})

/**
* @zh pcf阴影等级。
* @en The pcf type
* @static
* @enum Shadows.ShadowType
*/
export const PCFType = Enum({
/**
* @zh x1 次采样
* @en x1 times
* @readonly
*/
HARD: 0,

/**
* @zh x5 次采样
* @en x5 times
* @readonly
*/
FILTER_X5: 1,

/**
* @zh x9 次采样
* @en x9 times
* @readonly
*/
FILTER_X9: 2,

/**
* @zh x25 次采样
* @en x25 times
* @readonly
*/
FILTER_X25: 3,
})

interface IShadowRenderData {
model: Model;
shaders: GFXShader[];
Expand Down Expand Up @@ -134,6 +173,9 @@ export class Shadows {
get data () {
return this._data;
}
get sphere () {
return this._sphere;
}
protected _enabled: boolean = false;
protected _type = ShadowType.Planar;
protected _normal = new Vec3(0, 1, 0);
Expand All @@ -151,6 +193,11 @@ export class Shadows {
protected _device: GFXDevice|null = null;
protected _globalDescriptorSet: GFXDescriptorSet | null = null;
protected _dirty: boolean = true;
/**
* @zh
* 场景包围球
*/
protected _sphere: sphere = new sphere(0.0, 0.0, 0.0, 0.01);
/**
* @en get or set shadow camera near
* @zh 获取或者设置阴影相机近裁剪面
Expand All @@ -170,13 +217,19 @@ export class Shadows {
* @en get or set shadow camera orthoSize
* @zh 获取或者设置阴影相机正交大小
*/
public orthoSize: number = 5;
public orthoSize: number = 1;
/**
* @en get or set shadow camera orthoSize
* @zh 获取或者设置阴影纹理大小
*/
public size: Vec2 = new Vec2(512, 512);

/**
* @en get or set shadow pcf
* @zh 获取或者设置阴影pcf等级
*/
public pcf = PCFType.HARD;

public activate () {
const pipeline = legacyCC.director.root.pipeline;
this._globalDescriptorSet = pipeline.descriptorSet;
Expand All @@ -190,6 +243,17 @@ export class Shadows {
}
}

public getWorldMatrix (rotation: Quat, dir: Vec3) {
Vec3.negate(_dir_negate, dir);
const distance: number = Math.sqrt(2) * this._sphere.radius;
Vec3.multiplyScalar(_vec3_p, _dir_negate, distance);
Vec3.add(_vec3_p, _vec3_p, this._sphere.center);

Mat4.fromRT(_mat4_trans, rotation, _vec3_p);

return _mat4_trans;
}

protected _updatePlanarInfo () {
this._dirty = true;
if (!this._material) {
Expand Down
18 changes: 17 additions & 1 deletion cocos/core/scene-graph/scene-globals.ts
Expand Up @@ -28,7 +28,7 @@ import { ccclass, property, visible, type, displayOrder, slide, range, rangeStep
import { CCBoolean, CCFloat } from '../data/utils/attribute';
import { Color, Quat, Vec3, Vec2 } from '../math';
import { Ambient } from '../renderer/scene/ambient';
import { Shadows, ShadowType } from '../renderer/scene/shadows';
import { Shadows, ShadowType, PCFType } from '../renderer/scene/shadows';
import { Skybox } from '../renderer/scene/skybox';
import { Fog, FogType } from '../renderer/scene/fog';
import { Node } from './node';
Expand Down Expand Up @@ -386,6 +386,8 @@ export class ShadowsInfo {
@property
protected _shadowColor = new Color(0, 0, 0, 76);
@property
protected _pcf = PCFType.HARD;
@property
protected _near: number = 1;
@property
protected _far: number = 30;
Expand Down Expand Up @@ -461,6 +463,20 @@ export class ShadowsInfo {
return this._distance;
}

/**
* @en The normal of the plane which receives shadow
* @zh 阴影接收平面的法线
*/
@type(PCFType)
@visible(function (this: ShadowsInfo) { return this._type === ShadowType.ShadowMap; })
set pcf (val) {
this._pcf = val;
if (this._resource) { this._resource.pcf = val; }
}
get pcf () {
return this._pcf;
}

/**
* @en get or set shadow camera near
* @zh 获取或者设置阴影相机近裁剪面
Expand Down
47 changes: 46 additions & 1 deletion editor/assets/chunks/cc-shadow-map-fs.chunk
Expand Up @@ -7,9 +7,54 @@ in vec4 v_shadowPos;
#pragma builtin(global)
layout(set = 0, binding = 4) uniform sampler2D cc_shadowMap;

vec4 CCGetShadowFactor () {
vec4 CCGetShadowFactorX1 () {
vec3 clipPos = v_shadowPos.xyz / v_shadowPos.w * 0.5 + 0.5;
float depth = unpackRGBAToDepth(texture(cc_shadowMap, clipPos.xy));
if (depth < (clipPos.z - 0.001)) return cc_shadowColor;
else return vec4(0);
}

vec4 CCGetShadowFactorX5 () {
vec3 clipPos = v_shadowPos.xyz / v_shadowPos.w * 0.5 + 0.5;
float offsetx = 1.0 / cc_shadowSize.x;
float offsety = 1.0 / cc_shadowSize.y;
float depth = 0.0;
depth += unpackRGBAToDepth(texture(cc_shadowMap, vec2(clipPos.x - offsetx, clipPos.y - offsety)));
depth += unpackRGBAToDepth(texture(cc_shadowMap, vec2(clipPos.x - offsetx, clipPos.y + offsety)));
depth += unpackRGBAToDepth(texture(cc_shadowMap, vec2(clipPos.x, clipPos.y)));
depth += unpackRGBAToDepth(texture(cc_shadowMap, vec2(clipPos.x + offsetx, clipPos.y - offsety)));
depth += unpackRGBAToDepth(texture(cc_shadowMap, vec2(clipPos.x + offsetx, clipPos.y + offsety)));
depth /= 5.0;
if (depth < (clipPos.z - 0.001)) return cc_shadowColor;
else return vec4(0);
}

vec4 CCGetShadowFactorX9 () {
vec3 clipPos = v_shadowPos.xyz / v_shadowPos.w * 0.5 + 0.5;
float offsetx = 1.0 / cc_shadowSize.x;
float offsety = 1.0 / cc_shadowSize.y;
float depth = 0.0;
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
depth += unpackRGBAToDepth(texture(cc_shadowMap, clipPos.xy + vec2(i, j) * vec2(offsetx, offsety)));
}
}
depth /= 9.0;
if (depth < (clipPos.z - 0.001)) return cc_shadowColor;
else return vec4(0);
}

vec4 CCGetShadowFactorX25 () {
vec3 clipPos = v_shadowPos.xyz / v_shadowPos.w * 0.5 + 0.5;
float offsetx = 1.0 / cc_shadowSize.x;
float offsety = 1.0 / cc_shadowSize.y;
float depth = 0.0;
for (int i = -2; i <= 2; i++) {
for (int j = -2; j <= 2; j++) {
depth += unpackRGBAToDepth(texture(cc_shadowMap, clipPos.xy + vec2(i, j) * vec2(offsetx, offsety)));
}
}
depth /= 25.0;
if (depth < (clipPos.z - 0.001)) return cc_shadowColor;
else return vec4(0);
}
2 changes: 2 additions & 0 deletions editor/assets/chunks/cc-shadow.chunk
Expand Up @@ -5,4 +5,6 @@ layout(set = 0, binding = 1) uniform CCShadow {
highp mat4 cc_matLightPlaneProj;
highp mat4 cc_matLightViewProj;
lowp vec4 cc_shadowColor;
lowp vec4 cc_shadowPCF;
lowp vec4 cc_shadowSize;
};

0 comments on commit c99525c

Please sign in to comment.