Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
车家大少爷
three.js
提交
e1198317
T
three.js
项目概览
车家大少爷
/
three.js
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
three.js
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
e1198317
编写于
1月 25, 2020
作者:
V
vtHawk
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
CSM example
上级
a3ca9ba6
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
737 addition
and
0 deletion
+737
-0
examples/files.js
examples/files.js
+1
-0
examples/js/libs/three-csm.module.js
examples/js/libs/three-csm.module.js
+531
-0
examples/webgl_cascadedshadowmaps.html
examples/webgl_cascadedshadowmaps.html
+205
-0
未找到文件。
examples/files.js
浏览文件 @
e1198317
...
...
@@ -288,6 +288,7 @@ var files = {
"
webgl_buffergeometry_rawshader
"
,
"
webgl_buffergeometry_selective_draw
"
,
"
webgl_buffergeometry_uint
"
,
"
webgl_cascadedshadowmaps
"
,
"
webgl_custom_attributes
"
,
"
webgl_custom_attributes_lines
"
,
"
webgl_custom_attributes_points
"
,
...
...
examples/js/libs/three-csm.module.js
0 → 100644
浏览文件 @
e1198317
import
{
Vector3
,
ShaderChunk
,
DirectionalLight
,
Vector2
,
LineBasicMaterial
,
Object3D
,
Geometry
,
Line
}
from
'
../../../build/three.module.js
'
;
class
FrustumVertex
{
constructor
(
x
,
y
,
z
)
{
this
.
x
=
x
||
0
;
this
.
y
=
y
||
0
;
this
.
z
=
z
||
0
;
}
fromLerp
(
v1
,
v2
,
amount
)
{
this
.
x
=
(
1
-
amount
)
*
v1
.
x
+
amount
*
v2
.
x
;
this
.
y
=
(
1
-
amount
)
*
v1
.
y
+
amount
*
v2
.
y
;
this
.
z
=
(
1
-
amount
)
*
v1
.
z
+
amount
*
v2
.
z
;
return
this
;
}
}
function
toRad
(
degrees
)
{
return
degrees
*
Math
.
PI
/
180
;
}
class
Frustum
{
constructor
(
data
)
{
data
=
data
||
{};
this
.
fov
=
data
.
fov
||
70
;
this
.
near
=
data
.
near
||
0.1
;
this
.
far
=
data
.
far
||
1000
;
this
.
aspect
=
data
.
aspect
||
1
;
this
.
vertices
=
{
near
:
[],
far
:
[]
};
}
getViewSpaceVertices
()
{
this
.
nearPlaneY
=
this
.
near
*
Math
.
tan
(
toRad
(
this
.
fov
/
2
));
this
.
nearPlaneX
=
this
.
aspect
*
this
.
nearPlaneY
;
this
.
farPlaneY
=
this
.
far
*
Math
.
tan
(
toRad
(
this
.
fov
/
2
));
this
.
farPlaneX
=
this
.
aspect
*
this
.
farPlaneY
;
// 3 --- 0 vertices.near/far order
// | |
// 2 --- 1
this
.
vertices
.
near
.
push
(
new
FrustumVertex
(
this
.
nearPlaneX
,
this
.
nearPlaneY
,
-
this
.
near
),
new
FrustumVertex
(
this
.
nearPlaneX
,
-
this
.
nearPlaneY
,
-
this
.
near
),
new
FrustumVertex
(
-
this
.
nearPlaneX
,
-
this
.
nearPlaneY
,
-
this
.
near
),
new
FrustumVertex
(
-
this
.
nearPlaneX
,
this
.
nearPlaneY
,
-
this
.
near
)
);
this
.
vertices
.
far
.
push
(
new
FrustumVertex
(
this
.
farPlaneX
,
this
.
farPlaneY
,
-
this
.
far
),
new
FrustumVertex
(
this
.
farPlaneX
,
-
this
.
farPlaneY
,
-
this
.
far
),
new
FrustumVertex
(
-
this
.
farPlaneX
,
-
this
.
farPlaneY
,
-
this
.
far
),
new
FrustumVertex
(
-
this
.
farPlaneX
,
this
.
farPlaneY
,
-
this
.
far
)
);
return
this
.
vertices
;
}
split
(
breaks
)
{
const
result
=
[];
for
(
let
i
=
0
;
i
<
breaks
.
length
;
i
++
)
{
const
cascade
=
new
Frustum
();
if
(
i
===
0
)
{
cascade
.
vertices
.
near
=
this
.
vertices
.
near
;
}
else
{
for
(
let
j
=
0
;
j
<
4
;
j
++
)
{
cascade
.
vertices
.
near
.
push
(
new
FrustumVertex
().
fromLerp
(
this
.
vertices
.
near
[
j
],
this
.
vertices
.
far
[
j
],
breaks
[
i
-
1
]));
}
}
if
(
i
===
breaks
-
1
)
{
cascade
.
vertices
.
far
=
this
.
vertices
.
far
;
}
else
{
for
(
let
j
=
0
;
j
<
4
;
j
++
)
{
cascade
.
vertices
.
far
.
push
(
new
FrustumVertex
().
fromLerp
(
this
.
vertices
.
near
[
j
],
this
.
vertices
.
far
[
j
],
breaks
[
i
]));
}
}
result
.
push
(
cascade
);
}
return
result
;
}
toSpace
(
cameraMatrix
)
{
const
result
=
new
Frustum
();
const
point
=
new
Vector3
();
for
(
var
i
=
0
;
i
<
4
;
i
++
)
{
point
.
set
(
this
.
vertices
.
near
[
i
].
x
,
this
.
vertices
.
near
[
i
].
y
,
this
.
vertices
.
near
[
i
].
z
);
point
.
applyMatrix4
(
cameraMatrix
);
result
.
vertices
.
near
.
push
(
new
FrustumVertex
(
point
.
x
,
point
.
y
,
point
.
z
));
point
.
set
(
this
.
vertices
.
far
[
i
].
x
,
this
.
vertices
.
far
[
i
].
y
,
this
.
vertices
.
far
[
i
].
z
);
point
.
applyMatrix4
(
cameraMatrix
);
result
.
vertices
.
far
.
push
(
new
FrustumVertex
(
point
.
x
,
point
.
y
,
point
.
z
));
}
return
result
;
}
}
class
FrustumBoundingBox
{
constructor
()
{
this
.
min
=
{
x
:
0
,
y
:
0
,
z
:
0
};
this
.
max
=
{
x
:
0
,
y
:
0
,
z
:
0
};
}
fromFrustum
(
frustum
)
{
const
vertices
=
[];
for
(
let
i
=
0
;
i
<
4
;
i
++
)
{
vertices
.
push
(
frustum
.
vertices
.
near
[
i
]);
vertices
.
push
(
frustum
.
vertices
.
far
[
i
]);
}
this
.
min
=
{
x
:
vertices
[
0
].
x
,
y
:
vertices
[
0
].
y
,
z
:
vertices
[
0
].
z
};
this
.
max
=
{
x
:
vertices
[
0
].
x
,
y
:
vertices
[
0
].
y
,
z
:
vertices
[
0
].
z
};
for
(
let
i
=
1
;
i
<
8
;
i
++
)
{
this
.
min
.
x
=
Math
.
min
(
this
.
min
.
x
,
vertices
[
i
].
x
);
this
.
min
.
y
=
Math
.
min
(
this
.
min
.
y
,
vertices
[
i
].
y
);
this
.
min
.
z
=
Math
.
min
(
this
.
min
.
z
,
vertices
[
i
].
z
);
this
.
max
.
x
=
Math
.
max
(
this
.
max
.
x
,
vertices
[
i
].
x
);
this
.
max
.
y
=
Math
.
max
(
this
.
max
.
y
,
vertices
[
i
].
y
);
this
.
max
.
z
=
Math
.
max
(
this
.
max
.
z
,
vertices
[
i
].
z
);
}
return
this
;
}
getSize
()
{
this
.
size
=
{
x
:
this
.
max
.
x
-
this
.
min
.
x
,
y
:
this
.
max
.
y
-
this
.
min
.
y
,
z
:
this
.
max
.
z
-
this
.
min
.
z
};
return
this
.
size
;
}
getCenter
(
margin
)
{
this
.
center
=
{
x
:
(
this
.
max
.
x
+
this
.
min
.
x
)
/
2
,
y
:
(
this
.
max
.
y
+
this
.
min
.
y
)
/
2
,
z
:
this
.
max
.
z
+
margin
};
return
this
.
center
;
}
}
var
Shader
=
{
lights_fragment_begin
:
`
GeometricContext geometry;
geometry.position = - vViewPosition;
geometry.normal = normal;
geometry.viewDir = normalize( vViewPosition );
#ifdef CLEARCOAT
geometry.clearcoatNormal = clearcoatNormal;
#endif
IncidentLight directLight;
#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )
PointLight pointLight;
#pragma unroll_loop
for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {
pointLight = pointLights[ i ];
getPointDirectLightIrradiance( pointLight, geometry, directLight );
#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )
directLight.color *= all( bvec3( pointLight.shadow, directLight.visible, receiveShadow ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;
#endif
RE_Direct( directLight, geometry, material, reflectedLight );
}
#endif
#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )
SpotLight spotLight;
#pragma unroll_loop
for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {
spotLight = spotLights[ i ];
getSpotDirectLightIrradiance( spotLight, geometry, directLight );
#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )
directLight.color *= all( bvec3( spotLight.shadow, directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;
#endif
RE_Direct( directLight, geometry, material, reflectedLight );
}
#endif
#if ( NUM_DIR_LIGHTS > 0) && defined( RE_Direct ) && defined( USE_CSM ) && defined( CSM_CASCADES )
DirectionalLight directionalLight;
float linearDepth = (vViewPosition.z) / (shadowFar - cameraNear);
#pragma unroll_loop
for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {
directionalLight = directionalLights[ i ];
getDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );
#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )
if(linearDepth >= CSM_cascades[UNROLLED_LOOP_INDEX].x && linearDepth < CSM_cascades[UNROLLED_LOOP_INDEX].y) directLight.color *= all( bvec3( directionalLight.shadow, directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;
#endif
if(linearDepth >= CSM_cascades[UNROLLED_LOOP_INDEX].x && (linearDepth < CSM_cascades[UNROLLED_LOOP_INDEX].y || UNROLLED_LOOP_INDEX == CSM_CASCADES - 1)) RE_Direct( directLight, geometry, material, reflectedLight );
}
#endif
#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct ) && !defined( USE_CSM ) && !defined( CSM_CASCADES )
DirectionalLight directionalLight;
#pragma unroll_loop
for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {
directionalLight = directionalLights[ i ];
getDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );
#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )
directLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;
#endif
RE_Direct( directLight, geometry, material, reflectedLight );
}
#endif
#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )
RectAreaLight rectAreaLight;
#pragma unroll_loop
for ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {
rectAreaLight = rectAreaLights[ i ];
RE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );
}
#endif
#if defined( RE_IndirectDiffuse )
vec3 iblIrradiance = vec3( 0.0 );
vec3 irradiance = getAmbientLightIrradiance( ambientLightColor );
irradiance += getLightProbeIrradiance( lightProbe, geometry );
#if ( NUM_HEMI_LIGHTS > 0 )
#pragma unroll_loop
for ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {
irradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );
}
#endif
#endif
#if defined( RE_IndirectSpecular )
vec3 radiance = vec3( 0.0 );
vec3 clearcoatRadiance = vec3( 0.0 );
#endif
`
,
lights_pars_begin
:
`
#if defined( USE_CSM ) && defined( CSM_CASCADES )
uniform vec2 CSM_cascades[CSM_CASCADES];
uniform float cameraNear;
uniform float shadowFar;
#endif
`
+
ShaderChunk
.
lights_pars_begin
};
class
CSM
{
constructor
(
data
)
{
data
=
data
||
{};
this
.
camera
=
data
.
camera
;
this
.
parent
=
data
.
parent
;
this
.
fov
=
data
.
fov
||
this
.
camera
.
fov
;
this
.
near
=
this
.
camera
.
near
;
this
.
far
=
data
.
far
||
this
.
camera
.
far
;
this
.
aspect
=
data
.
aspect
||
this
.
camera
.
aspect
;
this
.
cascades
=
data
.
cascades
||
3
;
this
.
mode
=
data
.
mode
||
'
practical
'
;
this
.
shadowMapSize
=
data
.
shadowMapSize
||
2048
;
this
.
shadowBias
=
data
.
shadowBias
||
0.000001
;
this
.
lightDirection
=
data
.
lightDirection
||
new
Vector3
(
1
,
-
1
,
1
).
normalize
();
this
.
lightIntensity
=
data
.
lightIntensity
||
1
;
this
.
lightNear
=
data
.
lightNear
||
1
;
this
.
lightFar
=
data
.
lightFar
||
2000
;
this
.
lightMargin
=
data
.
lightMargin
||
200
;
this
.
customSplitsCallback
=
data
.
customSplitsCallback
;
this
.
lights
=
[];
this
.
materials
=
[];
this
.
createLights
();
this
.
getBreaks
();
this
.
initCascades
();
this
.
injectInclude
();
}
createLights
()
{
for
(
let
i
=
0
;
i
<
this
.
cascades
;
i
++
)
{
const
light
=
new
DirectionalLight
(
0xffffff
,
this
.
lightIntensity
);
light
.
castShadow
=
true
;
light
.
shadow
.
mapSize
.
width
=
this
.
shadowMapSize
;
light
.
shadow
.
mapSize
.
height
=
this
.
shadowMapSize
;
light
.
shadow
.
camera
.
near
=
this
.
lightNear
;
light
.
shadow
.
camera
.
far
=
this
.
lightFar
;
light
.
shadow
.
bias
=
this
.
shadowBias
;
this
.
parent
.
add
(
light
);
this
.
parent
.
add
(
light
.
target
);
this
.
lights
.
push
(
light
);
}
}
initCascades
()
{
this
.
mainFrustum
=
new
Frustum
({
fov
:
this
.
fov
,
near
:
this
.
near
,
far
:
this
.
far
,
aspect
:
this
.
aspect
});
this
.
mainFrustum
.
getViewSpaceVertices
();
this
.
frustums
=
this
.
mainFrustum
.
split
(
this
.
breaks
);
}
getBreaks
()
{
this
.
breaks
=
[];
switch
(
this
.
mode
)
{
case
'
uniform
'
:
this
.
breaks
=
uniformSplit
(
this
.
cascades
,
this
.
near
,
this
.
far
);
break
;
case
'
logarithmic
'
:
this
.
breaks
=
logarithmicSplit
(
this
.
cascades
,
this
.
near
,
this
.
far
);
break
;
case
'
practical
'
:
this
.
breaks
=
practicalSplit
(
this
.
cascades
,
this
.
near
,
this
.
far
,
0.5
);
break
;
case
'
custom
'
:
if
(
this
.
customSplitsCallback
===
undefined
)
console
.
error
(
'
CSM: Custom split scheme callback not defined.
'
);
this
.
breaks
=
this
.
customSplitsCallback
(
this
.
cascades
,
this
.
near
,
this
.
far
);
break
;
}
function
uniformSplit
(
amount
,
near
,
far
)
{
const
r
=
[];
for
(
let
i
=
1
;
i
<
amount
;
i
++
)
{
r
.
push
((
near
+
(
far
-
near
)
*
i
/
amount
)
/
far
);
}
r
.
push
(
1
);
return
r
;
}
function
logarithmicSplit
(
amount
,
near
,
far
)
{
const
r
=
[];
for
(
let
i
=
1
;
i
<
amount
;
i
++
)
{
r
.
push
((
near
*
(
far
/
near
)
**
(
i
/
amount
))
/
far
);
}
r
.
push
(
1
);
return
r
;
}
function
practicalSplit
(
amount
,
near
,
far
,
lambda
)
{
const
log
=
logarithmicSplit
(
amount
,
near
,
far
);
const
uni
=
uniformSplit
(
amount
,
near
,
far
);
const
r
=
[];
for
(
let
i
=
1
;
i
<
amount
;
i
++
)
{
r
.
push
(
lambda
*
log
[
i
-
1
]
+
(
1
-
lambda
)
*
uni
[
i
-
1
]);
}
r
.
push
(
1
);
return
r
;
}
}
update
(
cameraMatrix
)
{
for
(
let
i
=
0
;
i
<
this
.
frustums
.
length
;
i
++
)
{
const
worldSpaceFrustum
=
this
.
frustums
[
i
].
toSpace
(
cameraMatrix
);
const
light
=
this
.
lights
[
i
];
const
lightSpaceFrustum
=
worldSpaceFrustum
.
toSpace
(
light
.
shadow
.
camera
.
matrixWorldInverse
);
light
.
shadow
.
camera
.
updateMatrixWorld
(
true
);
const
bbox
=
new
FrustumBoundingBox
().
fromFrustum
(
lightSpaceFrustum
);
bbox
.
getSize
();
bbox
.
getCenter
(
this
.
lightMargin
);
const
squaredBBWidth
=
Math
.
max
(
bbox
.
size
.
x
,
bbox
.
size
.
y
);
let
center
=
new
Vector3
(
bbox
.
center
.
x
,
bbox
.
center
.
y
,
bbox
.
center
.
z
);
center
.
applyMatrix4
(
light
.
shadow
.
camera
.
matrixWorld
);
light
.
shadow
.
camera
.
left
=
-
squaredBBWidth
/
2
;
light
.
shadow
.
camera
.
right
=
squaredBBWidth
/
2
;
light
.
shadow
.
camera
.
top
=
squaredBBWidth
/
2
;
light
.
shadow
.
camera
.
bottom
=
-
squaredBBWidth
/
2
;
light
.
position
.
copy
(
center
);
light
.
target
.
position
.
copy
(
center
);
light
.
target
.
position
.
x
+=
this
.
lightDirection
.
x
;
light
.
target
.
position
.
y
+=
this
.
lightDirection
.
y
;
light
.
target
.
position
.
z
+=
this
.
lightDirection
.
z
;
light
.
shadow
.
camera
.
updateProjectionMatrix
();
light
.
shadow
.
camera
.
updateMatrixWorld
();
}
}
injectInclude
()
{
ShaderChunk
.
lights_fragment_begin
=
Shader
.
lights_fragment_begin
;
ShaderChunk
.
lights_pars_begin
=
Shader
.
lights_pars_begin
;
}
setupMaterial
(
material
)
{
material
.
defines
=
material
.
defines
||
{};
material
.
defines
.
USE_CSM
=
1
;
material
.
defines
.
CSM_CASCADES
=
this
.
cascades
;
const
breaksVec2
=
[];
for
(
let
i
=
0
;
i
<
this
.
cascades
;
i
++
)
{
let
amount
=
this
.
breaks
[
i
];
let
prev
=
this
.
breaks
[
i
-
1
]
||
0
;
breaksVec2
.
push
(
new
Vector2
(
prev
,
amount
));
}
const
self
=
this
;
material
.
onBeforeCompile
=
function
(
shader
)
{
shader
.
uniforms
.
CSM_cascades
=
{
value
:
breaksVec2
};
shader
.
uniforms
.
cameraNear
=
{
value
:
self
.
camera
.
near
};
shader
.
uniforms
.
shadowFar
=
{
value
:
self
.
far
};
self
.
materials
.
push
(
shader
);
};
}
updateUniforms
()
{
for
(
let
i
=
0
;
i
<
this
.
materials
.
length
;
i
++
)
{
this
.
materials
[
i
].
uniforms
.
CSM_cascades
.
value
=
this
.
getExtendedBreaks
();
this
.
materials
[
i
].
uniforms
.
cameraNear
.
value
=
this
.
camera
.
near
;
this
.
materials
[
i
].
uniforms
.
shadowFar
.
value
=
this
.
far
;
}
}
getExtendedBreaks
()
{
let
breaksVec2
=
[];
for
(
let
i
=
0
;
i
<
this
.
cascades
;
i
++
)
{
let
amount
=
this
.
breaks
[
i
];
let
prev
=
this
.
breaks
[
i
-
1
]
||
0
;
breaksVec2
.
push
(
new
Vector2
(
prev
,
amount
));
}
return
breaksVec2
;
}
setAspect
(
aspect
)
{
this
.
aspect
=
aspect
;
this
.
initCascades
();
}
updateFrustums
()
{
this
.
getBreaks
();
this
.
initCascades
();
this
.
updateUniforms
();
}
helper
(
cameraMatrix
)
{
let
frustum
;
let
geometry
;
const
material
=
new
LineBasicMaterial
({
color
:
0xffffff
});
const
object
=
new
Object3D
();
for
(
let
i
=
0
;
i
<
this
.
frustums
.
length
;
i
++
)
{
frustum
=
this
.
frustums
[
i
].
toSpace
(
cameraMatrix
);
geometry
=
new
Geometry
();
for
(
let
i
=
0
;
i
<
5
;
i
++
)
{
const
point
=
frustum
.
vertices
.
near
[
i
===
4
?
0
:
i
];
geometry
.
vertices
.
push
(
new
Vector3
(
point
.
x
,
point
.
y
,
point
.
z
));
}
object
.
add
(
new
Line
(
geometry
,
material
));
geometry
=
new
Geometry
();
for
(
let
i
=
0
;
i
<
5
;
i
++
)
{
const
point
=
frustum
.
vertices
.
far
[
i
===
4
?
0
:
i
];
geometry
.
vertices
.
push
(
new
Vector3
(
point
.
x
,
point
.
y
,
point
.
z
));
}
object
.
add
(
new
Line
(
geometry
,
material
));
for
(
let
i
=
0
;
i
<
4
;
i
++
)
{
geometry
=
new
Geometry
();
const
near
=
frustum
.
vertices
.
near
[
i
];
const
far
=
frustum
.
vertices
.
far
[
i
];
geometry
.
vertices
.
push
(
new
Vector3
(
near
.
x
,
near
.
y
,
near
.
z
));
geometry
.
vertices
.
push
(
new
Vector3
(
far
.
x
,
far
.
y
,
far
.
z
));
object
.
add
(
new
Line
(
geometry
,
material
));
}
}
return
object
;
}
remove
()
{
for
(
let
i
=
0
;
i
<
this
.
lights
.
length
;
i
++
)
{
this
.
parent
.
remove
(
this
.
lights
[
i
]);
}
}
}
export
default
CSM
;
examples/webgl_cascadedshadowmaps.html
0 → 100644
浏览文件 @
e1198317
<!DOCTYPE html>
<html
lang=
"en"
>
<head>
<title>
three.js webgl - cascaded shadow maps
</title>
<meta
charset=
"utf-8"
>
<meta
name=
"viewport"
content=
"width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"
>
<link
type=
"text/css"
rel=
"stylesheet"
href=
"main.css"
>
</head>
<body>
<div
id=
"container"
></div>
<div
id=
"info"
>
<a
href=
"https://threejs.org"
target=
"_blank"
rel=
"noopener"
>
three.js
</a>
webgl - cascaded shadow maps
<br>
by
<a
href=
"https://github.com/vtHawk"
target=
"_blank"
rel=
"noopener"
>
vtHawk
</a>
(
<a
href=
"https://github.com/vtHawk/three-csm"
target=
"_blank"
rel=
"noopener"
>
original repository
</a>
)
</div>
<script
type=
"module"
>
import
*
as
THREE
from
'
../build/three.module.js
'
;
import
{
OrbitControls
}
from
'
./jsm/controls/OrbitControls.js
'
;
import
{
GUI
}
from
'
./jsm/libs/dat.gui.module.js
'
;
import
*
as
CSM
from
'
./js/libs/three-csm.module.js
'
;
var
renderer
,
scene
,
camera
,
controls
,
csm
;
init
();
animate
();
function
init
()
{
scene
=
new
THREE
.
Scene
();
scene
.
background
=
new
THREE
.
Color
(
'
#454e61
'
);
camera
=
new
THREE
.
PerspectiveCamera
(
70
,
window
.
innerWidth
/
window
.
innerHeight
,
0.1
,
5000
);
renderer
=
new
THREE
.
WebGLRenderer
(
{
antialias
:
true
}
);
renderer
.
setSize
(
window
.
innerWidth
,
window
.
innerHeight
);
document
.
body
.
appendChild
(
renderer
.
domElement
);
renderer
.
shadowMap
.
enabled
=
true
;
renderer
.
shadowMap
.
type
=
THREE
.
PCFSoftShadowMap
;
controls
=
new
OrbitControls
(
camera
,
renderer
.
domElement
);
controls
.
maxPolarAngle
=
Math
.
PI
/
2
;
camera
.
position
.
set
(
60
,
60
,
0
);
controls
.
target
=
new
THREE
.
Vector3
(
-
100
,
10
,
0
);
controls
.
update
();
var
ambientLight
=
new
THREE
.
AmbientLight
(
0xffffff
,
0.5
);
scene
.
add
(
ambientLight
);
var
params
=
{
far
:
1000
,
mode
:
'
practical
'
,
lightX
:
-
1
,
lightY
:
-
1
,
lightZ
:
-
1
,
margin
:
100
,
lightFar
:
5000
,
lightNear
:
1
,
helper
:
function
()
{
var
helper
=
csm
.
helper
(
camera
.
matrix
);
scene
.
add
(
helper
);
}
};
csm
=
new
CSM
.
default
({
fov
:
camera
.
fov
,
near
:
camera
.
near
,
far
:
params
.
far
,
aspect
:
camera
.
aspect
,
cascades
:
4
,
mode
:
params
.
mode
,
parent
:
scene
,
shadowMapSize
:
1024
,
lightDirection
:
new
THREE
.
Vector3
(
params
.
lightX
,
params
.
lightY
,
params
.
lightZ
).
normalize
(),
camera
:
camera
}
);
var
floorMaterial
=
new
THREE
.
MeshPhongMaterial
(
{
color
:
'
#252a34
'
}
);
csm
.
setupMaterial
(
floorMaterial
);
var
floor
=
new
THREE
.
Mesh
(
new
THREE
.
PlaneBufferGeometry
(
10000
,
10000
),
floorMaterial
);
floor
.
rotation
.
x
=
-
Math
.
PI
/
2
;
floor
.
castShadow
=
true
;
floor
.
receiveShadow
=
true
;
scene
.
add
(
floor
);
var
material1
=
new
THREE
.
MeshPhongMaterial
(
{
color
:
'
#08d9d6
'
}
);
csm
.
setupMaterial
(
material1
);
var
material2
=
new
THREE
.
MeshPhongMaterial
(
{
color
:
'
#ff2e63
'
}
);
csm
.
setupMaterial
(
material2
);
var
geometry
=
new
THREE
.
BoxBufferGeometry
(
10
,
10
,
10
);
for
(
var
i
=
0
;
i
<
40
;
i
++
)
{
var
cube1
=
new
THREE
.
Mesh
(
geometry
,
i
%
2
===
0
?
material1
:
material2
);
cube1
.
castShadow
=
true
;
cube1
.
receiveShadow
=
true
;
scene
.
add
(
cube1
);
cube1
.
position
.
set
(
-
i
*
25
,
20
,
30
);
cube1
.
scale
.
y
=
Math
.
random
()
*
2
+
6
;
var
cube2
=
new
THREE
.
Mesh
(
geometry
,
i
%
2
===
0
?
material2
:
material1
);
cube2
.
castShadow
=
true
;
cube2
.
receiveShadow
=
true
;
scene
.
add
(
cube2
);
cube2
.
position
.
set
(
-
i
*
25
,
20
,
-
30
);
cube2
.
scale
.
y
=
Math
.
random
()
*
2
+
6
;
}
var
gui
=
new
GUI
();
gui
.
add
(
params
,
'
far
'
,
1
,
5000
).
step
(
1
).
name
(
'
shadow far
'
).
onChange
(
function
(
value
)
{
csm
.
far
=
value
;
csm
.
updateFrustums
();
}
);
gui
.
add
(
params
,
'
mode
'
,
[
'
uniform
'
,
'
logarithmic
'
,
'
practical
'
]
).
name
(
'
frustum split mode
'
).
onChange
(
function
(
value
)
{
csm
.
mode
=
value
;
csm
.
updateFrustums
();
}
);
gui
.
add
(
params
,
'
lightX
'
,
-
1
,
1
).
name
(
'
light direction x
'
).
onChange
(
function
(
value
)
{
csm
.
lightDirection
.
x
=
value
;
}
);
gui
.
add
(
params
,
'
lightY
'
,
-
1
,
1
).
name
(
'
light direction y
'
).
onChange
(
function
(
value
)
{
csm
.
lightDirection
.
y
=
value
;
}
);
gui
.
add
(
params
,
'
lightZ
'
,
-
1
,
1
).
name
(
'
light direction z
'
).
onChange
(
function
(
value
)
{
csm
.
lightDirection
.
z
=
value
;
}
);
gui
.
add
(
params
,
'
margin
'
,
0
,
200
).
name
(
'
light margin
'
).
onChange
(
function
(
value
)
{
csm
.
lightMargin
=
value
;
}
);
gui
.
add
(
params
,
'
lightNear
'
,
1
,
10000
).
name
(
'
light near
'
).
onChange
(
function
(
value
)
{
for
(
var
i
=
0
;
i
<
csm
.
lights
.
length
;
i
++
)
{
csm
.
lights
[
i
].
shadow
.
camera
.
near
=
value
;
csm
.
lights
[
i
].
shadow
.
camera
.
updateProjectionMatrix
();
}
}
);
gui
.
add
(
params
,
'
lightFar
'
,
1
,
10000
).
name
(
'
light far
'
).
onChange
(
function
(
value
)
{
for
(
var
i
=
0
;
i
<
csm
.
lights
.
length
;
i
++
)
{
csm
.
lights
[
i
].
shadow
.
camera
.
far
=
value
;
csm
.
lights
[
i
].
shadow
.
camera
.
updateProjectionMatrix
();
}
}
);
gui
.
add
(
params
,
'
helper
'
).
name
(
'
add frustum helper
'
);
window
.
addEventListener
(
'
resize
'
,
function
()
{
camera
.
aspect
=
window
.
innerWidth
/
window
.
innerHeight
;
camera
.
updateProjectionMatrix
();
csm
.
setAspect
(
camera
.
aspect
);
renderer
.
setSize
(
window
.
innerWidth
,
window
.
innerHeight
);
},
false
);
}
function
animate
()
{
requestAnimationFrame
(
animate
);
csm
.
update
(
camera
.
matrix
);
controls
.
update
();
renderer
.
render
(
scene
,
camera
);
}
</script>
</body>
</html>
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录