Skip to content

Commit 73b9411

Browse files
added the refraction effect of envmap (oppenfuture#45)
Co-authored-by: WenjieLiuu <[email protected]>
1 parent ce740a8 commit 73b9411

14 files changed

+144
-25
lines changed

docs/api/en/materials/MeshPhysicalMaterial.html

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ <h1>[name]</h1>
2929
<li>
3030
<b>Advanced reflectivity:</b> More flexible reflectivity for non-metallic materials.
3131
</li>
32+
<li>
33+
<b>Refraction:</b> Mixed indirect reflections and refractions.
34+
</li>
3235
</ul>
3336

3437
<p>
@@ -61,7 +64,8 @@ <h2>Examples</h2>
6164
[example:webgl_materials_variations_physical materials / variations / physical]<br />
6265
[example:webgl_materials_physical_clearcoat materials / physical / clearcoat]<br />
6366
[example:webgl_materials_physical_reflectivity materials / physical / reflectivity]<br />
64-
[example:webgl_materials_physical_transmission materials / physical / transmission]
67+
[example:webgl_materials_physical_transmission materials / physical / transmission]<br />
68+
[example:webgl_materials_physical_refraction materials / physical / refraction]
6569
</p>
6670

6771
<h2>Constructor</h2>
@@ -132,6 +136,12 @@ <h3>[property:Float reflectivity]</h3>
132136
This models the reflectivity of non-metallic materials. It has no effect when [page:MeshStandardMaterial.metalness metalness] is *1.0*
133137
</p>
134138

139+
<h3>[property:Float refraction]</h3>
140+
<p>
141+
The portion of light that's refracted instead of diffusely reflected, from *0.0* to *1.0*. Default is *0.0*,
142+
which means the diffuse component is fully preserved.
143+
</p>
144+
135145
<h3>[property:Float sheen]</h3>
136146
<p>
137147
The intensity of the sheen layer, from *0.0* to *1.0*. Default is *0.0*.

docs/api/zh/materials/MeshPhysicalMaterial.html

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ <h1>物理网格材质([name])</h1>
2929
<li>
3030
<b>Advanced reflectivity:</b> More flexible reflectivity for non-metallic materials.
3131
</li>
32+
<li>
33+
<b>Refraction:</b> Mixed indirect reflections and refractions.
34+
</li>
3235
</ul>
3336

3437
<p>
@@ -62,7 +65,8 @@ <h2>例子</h2>
6265
[example:webgl_materials_variations_physical materials / variations / physical]<br />
6366
[example:webgl_materials_physical_clearcoat materials / physical / clearcoat]<br />
6467
[example:webgl_materials_physical_reflectivity materials / physical / reflectivity]<br />
65-
[example:webgl_materials_physical_transmission materials / physical / transmission]
68+
[example:webgl_materials_physical_transmission materials / physical / transmission]<br />
69+
[example:webgl_materials_physical_refraction materials / physical / refraction]
6670
</p>
6771

6872
<h2>构造函数(Constructor)</h2>
@@ -129,6 +133,11 @@ <h3>[property:Float reflectivity]</h3>
129133
这模拟了非金属材质的反射率。当[page:MeshStandardMaterial]为*1.0*时,此属性无效。
130134
</p>
131135

136+
<h3>[property:Float refraction]</h3>
137+
<p>
138+
控制材质中漫反射部分有多少被折射取代,范围为*0.0*到*1.0*。默认值为*0.0*,即保留全部漫反射部分。
139+
</p>
140+
132141
<h3>[property:Float sheen]</h3>
133142
<p>
134143
The intensity of the sheen layer, from *0.0* to *1.0*. Default is *0.0*.

src/materials/MeshPhysicalMaterial.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ import * as MathUtils from '../math/MathUtils.js';
3333
* specularIntensityMap: new THREE.Texture( <Image> ),
3434
* specularColor: <Color>,
3535
* specularColorMap: new THREE.Texture( <Image> )
36+
*
37+
* refraction: <float>,
3638
* }
3739
*/
3840

@@ -92,6 +94,7 @@ class MeshPhysicalMaterial extends MeshStandardMaterial {
9294
this._sheen = 0.0;
9395
this._clearcoat = 0;
9496
this._transmission = 0;
97+
this._refraction = 0.0;
9598

9699
this.setValues( parameters );
97100

@@ -151,6 +154,24 @@ class MeshPhysicalMaterial extends MeshStandardMaterial {
151154

152155
}
153156

157+
get refraction() {
158+
159+
return this._refraction;
160+
161+
}
162+
163+
set refraction( value ) {
164+
165+
if ( this._refraction > 0 !== value > 0 ) {
166+
167+
this.version ++;
168+
169+
}
170+
171+
this._refraction = value;
172+
173+
}
174+
154175
copy( source ) {
155176

156177
super.copy( source );
@@ -185,6 +206,8 @@ class MeshPhysicalMaterial extends MeshStandardMaterial {
185206
this.attenuationDistance = source.attenuationDistance;
186207
this.attenuationColor.copy( source.attenuationColor );
187208

209+
this.refraction = source.refraction;
210+
188211
this.specularIntensity = source.specularIntensity;
189212
this.specularIntensityMap = source.specularIntensityMap;
190213
this.specularColor.copy( source.specularColor );

src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
export default /* glsl */`
22
#if defined( USE_ENVMAP )
33
4-
#ifdef ENVMAP_MODE_REFRACTION
5-
6-
uniform float refractionRatio;
7-
8-
#endif
4+
uniform float refractionRatio;
95
106
vec3 getIBLIrradiance( const in vec3 normal ) {
117
@@ -25,36 +21,47 @@ export default /* glsl */`
2521
2622
}
2723
28-
vec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {
24+
vec3 getIBLRadiance( const in vec3 outVec, const in float roughness ) {
2925
3026
#if defined( ENVMAP_TYPE_CUBE_UV )
3127
32-
vec3 reflectVec;
28+
vec3 worldOutVec = inverseTransformDirection( outVec, viewMatrix );
3329
34-
#ifdef ENVMAP_MODE_REFLECTION
30+
vec4 envMapColor = textureCubeUV( envMap, worldOutVec, roughness );
3531
36-
reflectVec = reflect( - viewDir, normal );
32+
return envMapColor.rgb * envMapIntensity;
3733
38-
// Mixing the reflection with the normal is more accurate and keeps rough objects from gathering light from behind their tangent plane.
39-
reflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );
34+
#else
4035
41-
#else
36+
return vec3( 0.0 );
4237
43-
reflectVec = refract( - viewDir, normal, refractionRatio );
38+
#endif
4439
45-
#endif
40+
}
4641
47-
reflectVec = inverseTransformDirection( reflectVec, viewMatrix );
42+
vec3 getIBLRadianceReflection( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {
4843
49-
vec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );
44+
vec3 reflectVec = reflect( -viewDir, normal );
5045
51-
return envMapColor.rgb * envMapIntensity;
46+
// Mixing the reflection with the normal is more accurate and keeps rough objects from gathering light from behind their tangent plane.
47+
reflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );
5248
53-
#else
49+
return getIBLRadiance(reflectVec, roughness);
5450
55-
return vec3( 0.0 );
51+
}
5652
57-
#endif
53+
vec3 refract2(vec3 viewVec, vec3 Normal, float ior) {
54+
float vn = dot(viewVec, Normal);
55+
float k = 1.0 - ior * ior * (1.0 - vn * vn);
56+
vec3 refrVec = ior * viewVec - (ior * vn + sqrt(k)) * Normal;
57+
return refrVec;
58+
}
59+
60+
vec3 getIBLRadianceRefraction( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {
61+
62+
vec3 refractVec = refract2( -viewDir, normal, refractionRatio );
63+
64+
return getIBLRadiance(refractVec, roughness);
5865
5966
}
6067

src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,14 @@ IncidentLight directLight;
173173
#if defined( RE_IndirectSpecular )
174174
175175
vec3 radiance = vec3( 0.0 );
176+
176177
vec3 clearcoatRadiance = vec3( 0.0 );
177178
179+
#ifdef USE_REFRACTION
180+
181+
vec3 radianceRefraction = vec3( 0.0 );
182+
183+
#endif
184+
178185
#endif
179186
`;

src/renderers/shaders/ShaderChunk/lights_fragment_end.glsl.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ export default /* glsl */`
99
1010
RE_IndirectSpecular(
1111
radiance,
12+
#ifdef USE_REFRACTION
13+
radianceRefraction,
14+
#endif
1215
iblIrradiance,
1316
clearcoatRadiance,
1417
splitGeoNormal,

src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,33 @@ export default /* glsl */`
2626
2727
#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )
2828
29-
radiance += getIBLRadiance( geometry.viewDir, splitGeoNormal, material.roughness );
29+
#ifdef ENVMAP_MODE_REFLECTION
30+
31+
radiance += getIBLRadianceReflection( geometry.viewDir, splitGeoNormal, material.roughness );
32+
33+
#ifdef USE_REFRACTION
34+
35+
radianceRefraction += getIBLRadianceRefraction( geometry.viewDir, splitGeoNormal, material.roughness );
36+
37+
#endif
38+
39+
#else
40+
41+
radiance += getIBLRadianceRefraction( geometry.viewDir, splitGeoNormal, material.roughness );
42+
43+
#endif
3044
3145
#ifdef USE_CLEARCOAT
3246
33-
clearcoatRadiance += getIBLRadiance( geometry.viewDir, splitGeoClearcoatNormal, material.clearcoatRoughness );
47+
#ifdef ENVMAP_MODE_REFLECTION
48+
49+
clearcoatRadiance += getIBLRadianceReflection( geometry.viewDir, splitGeoClearcoatNormal, material.clearcoatRoughness );
50+
51+
#else
52+
53+
clearcoatRadiance += getIBLRadianceRefraction( geometry.viewDir, splitGeoClearcoatNormal, material.clearcoatRoughness );
54+
55+
#endif
3456
3557
#endif
3658

src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,5 +91,11 @@ material.roughness = min( material.roughness, 1.0 );
9191
9292
#endif
9393
94+
#endif
95+
96+
#ifdef USE_REFRACTION
97+
98+
material.refraction = refraction;
99+
94100
#endif
95101
`;

src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ struct PhysicalMaterial {
1818
float sheenRoughness;
1919
#endif
2020
21+
#ifdef USE_REFRACTION
22+
float refraction;
23+
#endif
24+
2125
};
2226
2327
// temporary
@@ -179,6 +183,9 @@ void RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricCo
179183
180184
void RE_IndirectSpecular_Physical(
181185
const in vec3 radiance,
186+
#ifdef USE_REFRACTION
187+
const in vec3 radianceRefraction,
188+
#endif
182189
const in vec3 irradiance,
183190
const in vec3 clearcoatRadiance,
184191
const in vec3 normal,
@@ -215,7 +222,15 @@ void RE_IndirectSpecular_Physical(
215222
reflectedLight.indirectSpecular += radiance * singleScattering;
216223
reflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;
217224
218-
reflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;
225+
vec3 indirectDiffuse = diffuse * cosineWeightedIrradiance;
226+
227+
#ifdef USE_REFRACTION
228+
229+
indirectDiffuse = mix(indirectDiffuse, radianceRefraction * material.diffuseColor, material.refraction);
230+
231+
#endif
232+
233+
reflectedLight.indirectDiffuse += indirectDiffuse;
219234
220235
}
221236

src/renderers/shaders/ShaderLib.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ ShaderLib.physical = {
309309
thicknessMap: { value: null },
310310
attenuationDistance: { value: 0 },
311311
attenuationColor: { value: new Color( 0x000000 ) },
312+
refraction: { value: 0 },
312313
specularIntensity: { value: 0 },
313314
specularIntensityMap: { value: null },
314315
specularColor: { value: new Color( 1, 1, 1 ) },

0 commit comments

Comments
 (0)