Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
车家大少爷
three.js
提交
948b89f9
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,发现更多精彩内容 >>
提交
948b89f9
编写于
4月 04, 2015
作者:
W
WestLangley
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Clean up phong shader
上级
8b645efb
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
162 addition
and
143 deletion
+162
-143
src/renderers/shaders/ShaderChunk/common.glsl
src/renderers/shaders/ShaderChunk/common.glsl
+100
-21
src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl
src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl
+44
-122
src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl
...erers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl
+18
-0
未找到文件。
src/renderers/shaders/ShaderChunk/common.glsl
浏览文件 @
948b89f9
...
...
@@ -4,57 +4,136 @@
#define LOG2 1.442695
#define EPSILON 1e-6
float
square
(
in
float
a
)
{
return
a
*
a
;
}
vec2
square
(
in
vec2
a
)
{
return
vec2
(
a
.
x
*
a
.
x
,
a
.
y
*
a
.
y
);
}
vec3
square
(
in
vec3
a
)
{
return
vec3
(
a
.
x
*
a
.
x
,
a
.
y
*
a
.
y
,
a
.
z
*
a
.
z
);
}
vec4
square
(
in
vec4
a
)
{
return
vec4
(
a
.
x
*
a
.
x
,
a
.
y
*
a
.
y
,
a
.
z
*
a
.
z
,
a
.
w
*
a
.
w
);
}
float
square
(
in
float
a
)
{
return
a
*
a
;
}
vec2
square
(
in
vec2
a
)
{
return
vec2
(
a
.
x
*
a
.
x
,
a
.
y
*
a
.
y
);
}
vec3
square
(
in
vec3
a
)
{
return
vec3
(
a
.
x
*
a
.
x
,
a
.
y
*
a
.
y
,
a
.
z
*
a
.
z
);
}
vec4
square
(
in
vec4
a
)
{
return
vec4
(
a
.
x
*
a
.
x
,
a
.
y
*
a
.
y
,
a
.
z
*
a
.
z
,
a
.
w
*
a
.
w
);
}
float
saturate
(
in
float
a
)
{
return
clamp
(
a
,
0
.
0
,
1
.
0
);
}
vec2
saturate
(
in
vec2
a
)
{
return
clamp
(
a
,
0
.
0
,
1
.
0
);
}
vec3
saturate
(
in
vec3
a
)
{
return
clamp
(
a
,
0
.
0
,
1
.
0
);
}
vec4
saturate
(
in
vec4
a
)
{
return
clamp
(
a
,
0
.
0
,
1
.
0
);
}
float
average
(
in
float
a
)
{
return
a
;
}
float
average
(
in
vec2
a
)
{
return
(
a
.
x
+
a
.
y
)
*
0
.
5
;
}
float
average
(
in
vec3
a
)
{
return
(
a
.
x
+
a
.
y
+
a
.
z
)
/
3
.
0
;
}
float
average
(
in
vec4
a
)
{
return
(
a
.
x
+
a
.
y
+
a
.
z
+
a
.
w
)
*
0
.
25
;
}
float
average
(
in
vec2
a
)
{
return
(
a
.
x
+
a
.
y
)
*
0
.
5
;
}
float
average
(
in
vec3
a
)
{
return
(
a
.
x
+
a
.
y
+
a
.
z
)
/
3
.
0
;
}
float
average
(
in
vec4
a
)
{
return
(
a
.
x
+
a
.
y
+
a
.
z
+
a
.
w
)
*
0
.
25
;
}
float
whiteCompliment
(
in
float
a
)
{
return
saturate
(
1
.
0
-
a
);
}
vec2
whiteCompliment
(
in
vec2
a
)
{
return
saturate
(
vec2
(
1
.
0
)
-
a
);
}
vec3
whiteCompliment
(
in
vec3
a
)
{
return
saturate
(
vec3
(
1
.
0
)
-
a
);
}
vec4
whiteCompliment
(
in
vec4
a
)
{
return
saturate
(
vec4
(
1
.
0
)
-
a
);
}
vec2
whiteCompliment
(
in
vec2
a
)
{
return
saturate
(
vec2
(
1
.
0
)
-
a
);
}
vec3
whiteCompliment
(
in
vec3
a
)
{
return
saturate
(
vec3
(
1
.
0
)
-
a
);
}
vec4
whiteCompliment
(
in
vec4
a
)
{
return
saturate
(
vec4
(
1
.
0
)
-
a
);
}
vec3
transformDirection
(
in
vec3
normal
,
in
mat4
matrix
)
{
return
normalize
(
(
matrix
*
vec4
(
normal
,
0
.
0
)
).
xyz
);
}
// http://en.wikibooks.org/wiki/GLSL_Programming/Applying_Matrix_Transformations
vec3
inverseTransformDirection
(
in
vec3
normal
,
in
mat4
matrix
)
{
return
normalize
(
(
vec4
(
normal
,
0
.
0
)
*
matrix
).
xyz
);
}
vec3
projectOnPlane
(
in
vec3
point
,
in
vec3
pointOnPlane
,
in
vec3
planeNormal
)
{
vec3
projectOnPlane
(
in
vec3
point
,
in
vec3
pointOnPlane
,
in
vec3
planeNormal
)
{
float
distance
=
dot
(
planeNormal
,
point
-
pointOnPlane
);
return
point
-
distance
*
planeNormal
;
}
float
sideOfPlane
(
in
vec3
point
,
in
vec3
pointOnPlane
,
in
vec3
planeNormal
)
{
return
sign
(
dot
(
point
-
pointOnPlane
,
planeNormal
)
);
}
vec3
linePlaneIntersect
(
in
vec3
pointOnLine
,
in
vec3
lineDirection
,
in
vec3
pointOnPlane
,
in
vec3
planeNormal
)
{
return
pointOnLine
+
lineDirection
*
(
dot
(
planeNormal
,
pointOnPlane
-
pointOnLine
)
/
dot
(
planeNormal
,
lineDirection
)
);
}
float
calcLightAttenuation
(
float
lightDistance
,
float
cutoffDistance
,
float
decayExponent
)
{
if
(
decayExponent
>
0
.
0
)
{
return
pow
(
saturate
(
1
.
0
-
lightDistance
/
cutoffDistance
),
decayExponent
);
}
return
1
.
0
;
}
vec3
F_Schlick
(
in
vec3
specularColor
,
in
float
dotLH
)
{
return
specularColor
+
(
1
.
0
-
specularColor
)
*
pow
(
1
.
0
-
dotLH
,
5
.
0
);
}
float
G_BlinnPhong_Implicit
(
/* in float dotNL, in float dotNV */
)
{
// geometry term is (n⋅l)(n⋅v) / 4(n⋅l)(n⋅v)
return
0
.
25
;
}
float
D_BlinnPhong
(
in
float
shininess
,
in
float
dotNH
)
{
// factor of 1/PI in distribution term omitted
return
(
shininess
*
0
.
5
+
1
.
0
)
*
pow
(
dotNH
,
shininess
);
}
vec3
BRDF_BlinnPhong
(
in
vec3
specularColor
,
in
float
shininess
,
in
vec3
normal
,
in
vec3
lightDir
,
in
vec3
viewDir
)
{
vec3
halfDir
=
normalize
(
lightDir
+
viewDir
);
//float dotNL = saturate( dot( normal, lightDir ) );
//float dotNV = saturate( dot( normal, viewDir ) );
float
dotNH
=
saturate
(
dot
(
normal
,
halfDir
)
);
float
dotLH
=
saturate
(
dot
(
lightDir
,
halfDir
)
);
vec3
F
=
F_Schlick
(
specularColor
,
dotLH
);
float
G
=
G_BlinnPhong_Implicit
(
/* dotNL, dotNV */
);
float
D
=
D_BlinnPhong
(
shininess
,
dotNH
);
return
F
*
G
*
D
;
}
vec3
inputToLinear
(
in
vec3
a
)
{
#ifdef GAMMA_INPUT
return
pow
(
a
,
vec3
(
float
(
GAMMA_FACTOR
)
)
);
#else
return
a
;
#endif
#ifdef GAMMA_INPUT
return
pow
(
a
,
vec3
(
float
(
GAMMA_FACTOR
)
)
);
#else
return
a
;
#endif
}
vec3
linearToOutput
(
in
vec3
a
)
{
#ifdef GAMMA_OUTPUT
return
pow
(
a
,
vec3
(
1
.
0
/
float
(
GAMMA_FACTOR
)
)
);
#else
return
a
;
#endif
#ifdef GAMMA_OUTPUT
return
pow
(
a
,
vec3
(
1
.
0
/
float
(
GAMMA_FACTOR
)
)
);
#else
return
a
;
#endif
}
src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl
浏览文件 @
948b89f9
...
...
@@ -16,8 +16,6 @@
#endif
vec3
viewPosition
=
normalize
(
vViewPosition
);
#ifdef USE_NORMALMAP
normal
=
perturbNormal2Arb
(
-
vViewPosition
,
normal
);
...
...
@@ -28,6 +26,8 @@ vec3 viewPosition = normalize( vViewPosition );
#endif
vec3
viewDir
=
normalize
(
vViewPosition
);
vec3
totalDiffuseLight
=
vec3
(
0
.
0
);
vec3
totalSpecularLight
=
vec3
(
0
.
0
);
...
...
@@ -35,42 +35,29 @@ vec3 totalSpecularLight = vec3( 0.0 );
for
(
int
i
=
0
;
i
<
MAX_POINT_LIGHTS
;
i
++
)
{
vec4
lPosition
=
viewMatrix
*
vec4
(
pointLightPosition
[
i
],
1
.
0
);
vec3
lightColor
=
pointLightColor
[
i
];
vec3
lightPosition
=
pointLightPosition
[
i
];
vec4
lPosition
=
viewMatrix
*
vec4
(
lightPosition
,
1
.
0
);
vec3
lVector
=
lPosition
.
xyz
+
vViewPosition
.
xyz
;
vec3
lightDir
=
normalize
(
lVector
);
float
attenuation
=
calcLightAttenuation
(
length
(
lVector
),
pointLightDistance
[
i
],
pointLightDecay
[
i
]
);
// attenuation
lVector
=
normalize
(
lVector
);
float
attenuation
=
calcLightAttenuation
(
length
(
lVector
),
pointLightDistance
[
i
],
pointLightDecay
[
i
]
);
// diffuse
float
dotProduct
=
dot
(
normal
,
lVector
);
#ifdef WRAP_AROUND
float
pointDiffuseWeightFull
=
max
(
dotProduct
,
0
.
0
);
float
pointDiffuseWeightHalf
=
max
(
0
.
5
*
dotProduct
+
0
.
5
,
0
.
0
);
vec3
pointDiffuseWeight
=
mix
(
vec3
(
pointDiffuseWeightFull
),
vec3
(
pointDiffuseWeightHalf
),
wrapRGB
);
#else
float
pointDiffuseWeight
=
max
(
dotProduct
,
0
.
0
);
#endif
vec3
cosineTerm
=
calcCosineTerm
(
normal
,
lightDir
);
totalDiffuseLight
+=
pointLightColor
[
i
]
*
pointDiffuseWeight
*
attenuation
;
totalDiffuseLight
+=
lightColor
*
attenuation
*
cosineTerm
;
// specular
// specular
vec3
pointHalfVector
=
normalize
(
lVector
+
viewPosition
);
float
pointDotNormalHalf
=
max
(
dot
(
normal
,
pointHalfVector
),
0
.
0
);
float
pointSpecularWeight
=
specularStrength
*
max
(
pow
(
pointDotNormalHalf
,
shininess
),
0
.
0
);
vec3
brdf
=
BRDF_BlinnPhong
(
specular
,
shininess
,
normal
,
lightDir
,
viewDir
);
float
specularNormalization
=
(
shininess
+
2
.
0
)
/
8
.
0
;
totalSpecularLight
+=
brdf
*
specularStrength
*
lightColor
*
attenuation
*
cosineTerm
;
vec3
schlick
=
specular
+
vec3
(
1
.
0
-
specular
)
*
pow
(
max
(
1
.
0
-
dot
(
lVector
,
pointHalfVector
),
0
.
0
),
5
.
0
);
totalSpecularLight
+=
schlick
*
pointLightColor
[
i
]
*
pointSpecularWeight
*
pointDiffuseWeight
*
attenuation
*
specularNormalization
;
}
...
...
@@ -80,48 +67,36 @@ vec3 totalSpecularLight = vec3( 0.0 );
for
(
int
i
=
0
;
i
<
MAX_SPOT_LIGHTS
;
i
++
)
{
vec4
lPosition
=
viewMatrix
*
vec4
(
spotLightPosition
[
i
],
1
.
0
);
vec3
lVector
=
lPosition
.
xyz
+
vViewPosition
.
xyz
;
float
attenuation
=
calcLightAttenuation
(
length
(
lVector
),
spotLightDistance
[
i
],
spotLightDecay
[
i
]
);
vec3
lightColor
=
spotLightColor
[
i
];
lVector
=
normalize
(
lVector
);
vec3
lightPosition
=
spotLightPosition
[
i
];
vec4
lPosition
=
viewMatrix
*
vec4
(
lightPosition
,
1
.
0
);
vec3
lVector
=
lPosition
.
xyz
+
vViewPosition
.
xyz
;
vec3
lightDir
=
normalize
(
lVector
);
float
spotEffect
=
dot
(
spotLightDirection
[
i
],
normalize
(
spotLightPosition
[
i
]
-
vWorldPosition
)
);
float
spotEffect
=
dot
(
spotLightDirection
[
i
],
normalize
(
lightPosition
-
vWorldPosition
)
);
if
(
spotEffect
>
spotLightAngleCos
[
i
]
)
{
spotEffect
=
max
(
pow
(
max
(
spotEffect
,
0
.
0
),
spotLightExponent
[
i
]
),
0
.
0
);
// diffuse
float
dotProduct
=
dot
(
normal
,
lVector
);
#ifdef WRAP_AROUND
spotEffect
=
saturate
(
pow
(
saturate
(
spotEffect
),
spotLightExponent
[
i
]
)
);
float
spotDiffuseWeightFull
=
max
(
dotProduct
,
0
.
0
);
float
spotDiffuseWeightHalf
=
max
(
0
.
5
*
dotProduct
+
0
.
5
,
0
.
0
);
// attenuation
vec3
spotDiffuseWeight
=
mix
(
vec3
(
spotDiffuseWeightFull
),
vec3
(
spotDiffuseWeightHalf
),
wrapRGB
);
float
attenuation
=
calcLightAttenuation
(
length
(
lVector
),
spotLightDistance
[
i
],
spotLightDecay
[
i
]
);
#else
attenuation
*=
spotEffect
;
float
spotDiffuseWeight
=
max
(
dotProduct
,
0
.
0
);
// diffuse
#endif
vec3
cosineTerm
=
calcCosineTerm
(
normal
,
lightDir
);
totalDiffuseLight
+=
spotLightColor
[
i
]
*
spotDiffuseWeight
*
attenuation
*
spotEffect
;
totalDiffuseLight
+=
lightColor
*
attenuation
*
cosineTerm
;
// specular
vec3
spotHalfVector
=
normalize
(
lVector
+
viewPosition
);
float
spotDotNormalHalf
=
max
(
dot
(
normal
,
spotHalfVector
),
0
.
0
);
float
spotSpecularWeight
=
specularStrength
*
max
(
pow
(
spotDotNormalHalf
,
shininess
),
0
.
0
);
float
specularNormalization
=
(
shininess
+
2
.
0
)
/
8
.
0
;
vec3
brdf
=
BRDF_BlinnPhong
(
specular
,
shininess
,
normal
,
lightDir
,
viewDir
);
vec3
schlick
=
specular
+
vec3
(
1
.
0
-
specular
)
*
pow
(
max
(
1
.
0
-
dot
(
lVector
,
spotHalfVector
),
0
.
0
),
5
.
0
);
totalSpecularLight
+=
schlick
*
spotLightColor
[
i
]
*
spotSpecularWeight
*
spotDiffuseWeight
*
attenuation
*
specularNormalization
*
spotEffect
;
totalSpecularLight
+=
brdf
*
specularStrength
*
lightColor
*
attenuation
*
cosineTerm
;
}
...
...
@@ -133,59 +108,21 @@ vec3 totalSpecularLight = vec3( 0.0 );
for
(
int
i
=
0
;
i
<
MAX_DIR_LIGHTS
;
i
++
)
{
vec3
dirVector
=
transformDirection
(
directionalLightDirection
[
i
],
viewMatrix
)
;
vec3
lightColor
=
directionalLightColor
[
i
]
;
// diffuse
float
dotProduct
=
dot
(
normal
,
dirVector
);
#ifdef WRAP_AROUND
float
dirDiffuseWeightFull
=
max
(
dotProduct
,
0
.
0
);
float
dirDiffuseWeightHalf
=
max
(
0
.
5
*
dotProduct
+
0
.
5
,
0
.
0
);
vec3
dirDiffuseWeight
=
mix
(
vec3
(
dirDiffuseWeightFull
),
vec3
(
dirDiffuseWeightHalf
),
wrapRGB
);
#else
vec3
lightDir
=
transformDirection
(
directionalLightDirection
[
i
],
viewMatrix
);
float
dirDiffuseWeight
=
max
(
dotProduct
,
0
.
0
);
// diffuse
#endif
vec3
cosineTerm
=
calcCosineTerm
(
normal
,
lightDir
);
totalDiffuseLight
+=
directionalLightColor
[
i
]
*
dirDiffuseWeight
;
totalDiffuseLight
+=
lightColor
*
cosineTerm
;
// specular
vec3
dirHalfVector
=
normalize
(
dirVector
+
viewPosition
);
float
dirDotNormalHalf
=
max
(
dot
(
normal
,
dirHalfVector
),
0
.
0
);
float
dirSpecularWeight
=
specularStrength
*
max
(
pow
(
dirDotNormalHalf
,
shininess
),
0
.
0
);
/*
// fresnel term from skin shader
const float F0 = 0.128;
float base = 1.0 - dot( viewPosition, dirHalfVector );
float exponential = pow( base, 5.0 );
float fresnel = exponential + F0 * ( 1.0 - exponential );
*/
/*
// fresnel term from fresnel shader
const float mFresnelBias = 0.08;
const float mFresnelScale = 0.3;
const float mFresnelPower = 5.0;
float fresnel = mFresnelBias + mFresnelScale * pow( 1.0 + dot( normalize( -viewPosition ), normal ), mFresnelPower );
*/
float
specularNormalization
=
(
shininess
+
2
.
0
)
/
8
.
0
;
// dirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization * fresnel;
vec3
schlick
=
specular
+
vec3
(
1
.
0
-
specular
)
*
pow
(
max
(
1
.
0
-
dot
(
dirVector
,
dirHalfVector
),
0
.
0
),
5
.
0
);
totalSpecularLight
+=
schlick
*
directionalLightColor
[
i
]
*
dirSpecularWeight
*
dirDiffuseWeight
*
specularNormalization
;
vec3
brdf
=
BRDF_BlinnPhong
(
specular
,
shininess
,
normal
,
lightDir
,
viewDir
);
totalSpecularLight
+=
brdf
*
specularStrength
*
lightColor
*
cosineTerm
;
}
...
...
@@ -195,38 +132,23 @@ vec3 totalSpecularLight = vec3( 0.0 );
for
(
int
i
=
0
;
i
<
MAX_HEMI_LIGHTS
;
i
++
)
{
vec3
l
Vecto
r
=
transformDirection
(
hemisphereLightDirection
[
i
],
viewMatrix
);
vec3
l
ightDi
r
=
transformDirection
(
hemisphereLightDirection
[
i
],
viewMatrix
);
// diffuse
float
dotProduct
=
dot
(
normal
,
lVector
);
float
hemiDiffuseWeight
=
0
.
5
*
dotProduct
+
0
.
5
;
vec3
hemiColor
=
mix
(
hemisphereLightGroundColor
[
i
],
hemisphereLightSkyColor
[
i
],
hemiDiffuseWeight
);
totalDiffuseLight
+=
hemiColor
;
// specular (sky light)
float
dotProduct
=
dot
(
normal
,
lightDir
);
vec3
hemiHalfVectorSky
=
normalize
(
lVector
+
viewPosition
);
float
hemiDotNormalHalfSky
=
0
.
5
*
dot
(
normal
,
hemiHalfVectorSky
)
+
0
.
5
;
float
hemiSpecularWeightSky
=
specularStrength
*
max
(
pow
(
max
(
hemiDotNormalHalfSky
,
0
.
0
),
shininess
),
0
.
0
);
// specular (ground light)
float
hemiDiffuseWeight
=
0
.
5
*
dotProduct
+
0
.
5
;
vec3
l
VectorGround
=
-
lVector
;
vec3
l
ightColor
=
mix
(
hemisphereLightGroundColor
[
i
],
hemisphereLightSkyColor
[
i
],
hemiDiffuseWeight
)
;
vec3
hemiHalfVectorGround
=
normalize
(
lVectorGround
+
viewPosition
);
float
hemiDotNormalHalfGround
=
0
.
5
*
dot
(
normal
,
hemiHalfVectorGround
)
+
0
.
5
;
float
hemiSpecularWeightGround
=
specularStrength
*
max
(
pow
(
max
(
hemiDotNormalHalfGround
,
0
.
0
),
shininess
),
0
.
0
);
totalDiffuseLight
+=
lightColor
;
float
dotProductGround
=
dot
(
normal
,
lVectorGround
);
// specular (sky term only)
float
specularNormalization
=
(
shininess
+
2
.
0
)
/
8
.
0
;
vec3
brdf
=
BRDF_BlinnPhong
(
specular
,
shininess
,
normal
,
lightDir
,
viewDir
)
;
vec3
schlickSky
=
specular
+
vec3
(
1
.
0
-
specular
)
*
pow
(
max
(
1
.
0
-
dot
(
lVector
,
hemiHalfVectorSky
),
0
.
0
),
5
.
0
);
vec3
schlickGround
=
specular
+
vec3
(
1
.
0
-
specular
)
*
pow
(
max
(
1
.
0
-
dot
(
lVectorGround
,
hemiHalfVectorGround
),
0
.
0
),
5
.
0
);
totalSpecularLight
+=
hemiColor
*
specularNormalization
*
(
schlickSky
*
hemiSpecularWeightSky
*
max
(
dotProduct
,
0
.
0
)
+
schlickGround
*
hemiSpecularWeightGround
*
max
(
dotProductGround
,
0
.
0
)
);
totalSpecularLight
+=
brdf
*
specularStrength
*
lightColor
*
max
(
dotProduct
,
0
.
0
);
}
...
...
src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl
浏览文件 @
948b89f9
...
...
@@ -56,3 +56,21 @@ varying vec3 vViewPosition;
varying
vec3
vNormal
;
#endif
vec3
calcCosineTerm
(
in
vec3
normal
,
in
vec3
lightDir
)
{
float
dotProduct
=
dot
(
normal
,
lightDir
);
vec3
cosineTerm
=
vec3
(
saturate
(
dotProduct
)
);
#ifdef WRAP_AROUND
vec3
cosineTermHalf
=
vec3
(
saturate
(
0
.
5
*
dotProduct
+
0
.
5
)
);
cosineTerm
=
mix
(
cosineTerm
,
cosineTermHalf
,
wrapRGB
);
#endif
return
cosineTerm
;
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录