Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
车家大少爷
three.js
提交
3492536c
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,发现更多精彩内容 >>
未验证
提交
3492536c
编写于
12月 16, 2019
作者:
M
Michael Herzog
提交者:
GitHub
12月 16, 2019
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #18161 from sunag/dev-nodematerial-prem
NodeMaterial: PREM Update
上级
75a5d82d
7de2e8d4
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
299 addition
and
274 deletion
+299
-274
examples/jsm/nodes/accessors/ReflectNode.js
examples/jsm/nodes/accessors/ReflectNode.js
+2
-2
examples/jsm/nodes/misc/TextureCubeNode.js
examples/jsm/nodes/misc/TextureCubeNode.js
+9
-51
examples/jsm/nodes/misc/TextureCubeUVNode.js
examples/jsm/nodes/misc/TextureCubeUVNode.js
+223
-146
examples/webgl_materials_envmaps_hdr_nodes.html
examples/webgl_materials_envmaps_hdr_nodes.html
+61
-31
examples/webgl_materials_envmaps_pmrem_nodes.html
examples/webgl_materials_envmaps_pmrem_nodes.html
+4
-15
src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl.js
...s/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl.js
+0
-29
未找到文件。
examples/jsm/nodes/accessors/ReflectNode.js
浏览文件 @
3492536c
...
...
@@ -54,7 +54,7 @@ ReflectNode.prototype.generate = function ( builder, output ) {
case
ReflectNode
.
VECTOR
:
var
viewNormalNode
=
builder
.
context
.
viewNormal
||
new
NormalNode
();
var
viewNormalNode
=
builder
.
context
.
viewNormal
||
new
NormalNode
(
NormalNode
.
VIEW
);
var
roughnessNode
=
builder
.
context
.
roughness
;
var
viewNormal
=
viewNormalNode
.
build
(
builder
,
'
v3
'
);
...
...
@@ -63,7 +63,7 @@ ReflectNode.prototype.generate = function ( builder, output ) {
var
method
=
`reflect( -normalize(
${
viewPosition
}
),
${
viewNormal
}
)`
;
if
(
viewNormalNode
&&
roughness
)
{
if
(
roughness
)
{
// Mixing the reflection with the normal is more accurate and keeps rough objects from gathering light from behind their tangent plane.
method
=
`normalize( mix(
${
method
}
,
${
viewNormal
}
,
${
roughness
}
*
${
roughness
}
) )`
;
...
...
examples/jsm/nodes/misc/TextureCubeNode.js
浏览文件 @
3492536c
...
...
@@ -10,26 +10,24 @@ import { ReflectNode } from '../accessors/ReflectNode.js';
import
{
NormalNode
}
from
'
../accessors/NormalNode.js
'
;
import
{
ColorSpaceNode
}
from
'
../utils/ColorSpaceNode.js
'
;
function
TextureCubeNode
(
value
,
textureSize
,
uv
,
bias
)
{
function
TextureCubeNode
(
value
,
uv
,
bias
)
{
TempNode
.
call
(
this
,
'
v4
'
);
this
.
value
=
value
;
textureSize
=
textureSize
||
new
FloatNode
(
1024
);
this
.
radianceCache
=
{
uv
:
new
TextureCubeUVNode
(
this
.
radianceNode
=
new
TextureCubeUVNode
(
this
.
value
,
uv
||
new
ReflectNode
(
ReflectNode
.
VECTOR
),
textureSize
,
// bias should be replaced in builder.context in build process
bias
)
}
;
);
this
.
irradianceCache
=
{
uv
:
new
TextureCubeUVNode
(
this
.
irradianceNode
=
new
TextureCubeUVNode
(
this
.
value
,
new
NormalNode
(
NormalNode
.
WORLD
),
textureSize
,
new
FloatNode
(
1
).
setReadonly
(
true
)
)
}
;
);
}
...
...
@@ -37,45 +35,6 @@ TextureCubeNode.prototype = Object.create( TempNode.prototype );
TextureCubeNode
.
prototype
.
constructor
=
TextureCubeNode
;
TextureCubeNode
.
prototype
.
nodeType
=
"
TextureCube
"
;
TextureCubeNode
.
prototype
.
generateTextureCubeUV
=
function
(
builder
,
cache
)
{
var
uv_10
=
cache
.
uv
.
build
(
builder
)
+
'
.uv_10
'
,
uv_20
=
cache
.
uv
.
build
(
builder
)
+
'
.uv_20
'
,
t
=
cache
.
uv
.
build
(
builder
)
+
'
.t
'
;
var
color10
=
'
texture2D(
'
+
this
.
value
.
build
(
builder
,
'
sampler2D
'
)
+
'
,
'
+
uv_10
+
'
)
'
,
color20
=
'
texture2D(
'
+
this
.
value
.
build
(
builder
,
'
sampler2D
'
)
+
'
,
'
+
uv_20
+
'
)
'
;
// add a custom context for fix incompatibility with the core
// include ColorSpace function only for vertex shader (in fragment shader color space functions is added automatically by core)
// this should be removed in the future
// context.include =: is used to include or not functions if used FunctionNode
// context.ignoreCache =: not create temp variables nodeT0..9 to optimize the code
var
context
=
{
include
:
builder
.
isShader
(
'
vertex
'
),
ignoreCache
:
true
};
var
outputType
=
this
.
getType
(
builder
);
builder
.
addContext
(
context
);
cache
.
colorSpace10
=
cache
.
colorSpace10
||
new
ColorSpaceNode
(
new
ExpressionNode
(
''
,
outputType
)
);
cache
.
colorSpace10
.
fromDecoding
(
builder
.
getTextureEncodingFromMap
(
this
.
value
.
value
)
);
cache
.
colorSpace10
.
input
.
parse
(
color10
);
color10
=
cache
.
colorSpace10
.
build
(
builder
,
outputType
);
cache
.
colorSpace20
=
cache
.
colorSpace20
||
new
ColorSpaceNode
(
new
ExpressionNode
(
''
,
outputType
)
);
cache
.
colorSpace20
.
fromDecoding
(
builder
.
getTextureEncodingFromMap
(
this
.
value
.
value
)
);
cache
.
colorSpace20
.
input
.
parse
(
color20
);
color20
=
cache
.
colorSpace20
.
build
(
builder
,
outputType
);
// end custom context
builder
.
removeContext
();
return
'
mix(
'
+
color10
+
'
,
'
+
color20
+
'
,
'
+
t
+
'
).rgb
'
;
};
TextureCubeNode
.
prototype
.
generate
=
function
(
builder
,
output
)
{
if
(
builder
.
isShader
(
'
fragment
'
)
)
{
...
...
@@ -88,10 +47,9 @@ TextureCubeNode.prototype.generate = function ( builder, output ) {
}
var
cache
=
builder
.
slot
===
'
irradiance
'
?
this
.
irradianceCache
:
this
.
radianceCache
;
var
result
=
this
.
generateTextureCubeUV
(
builder
,
cache
);
var
scopeNode
=
builder
.
slot
===
'
irradiance
'
?
this
.
irradianceNode
:
this
.
radianceNode
;
return
builder
.
format
(
'
vec4(
'
+
result
+
'
, 1.0 )
'
,
this
.
getType
(
builder
)
,
output
);
return
scopeNode
.
build
(
builder
,
output
);
}
else
{
...
...
examples/jsm/nodes/misc/TextureCubeUVNode.js
浏览文件 @
3492536c
...
...
@@ -6,157 +6,159 @@ import { TempNode } from '../core/TempNode.js';
import
{
ConstNode
}
from
'
../core/ConstNode.js
'
;
import
{
StructNode
}
from
'
../core/StructNode.js
'
;
import
{
FunctionNode
}
from
'
../core/FunctionNode.js
'
;
import
{
FunctionCallNode
}
from
'
../core/FunctionCallNode.js
'
;
import
{
ExpressionNode
}
from
'
../core/ExpressionNode.js
'
;
import
{
ReflectNode
}
from
'
../accessors/ReflectNode.js
'
;
import
{
FloatNode
}
from
'
../inputs/FloatNode.js
'
;
import
{
OperatorNode
}
from
'
../math/OperatorNode.js
'
;
import
{
MathNode
}
from
'
../math/MathNode.js
'
;
import
{
CondNode
}
from
'
../math/CondNode.js
'
;
import
{
ColorSpaceNode
}
from
'
../utils/ColorSpaceNode.js
'
;
function
TextureCubeUVNode
(
uv
,
textureSize
,
bias
)
{
function
TextureCubeUVNode
(
value
,
uv
,
bias
)
{
TempNode
.
call
(
this
,
'
TextureCubeUVData
'
);
// TextureCubeUVData is type as StructNode
TempNode
.
call
(
this
,
'
v4
'
);
this
.
value
=
value
,
this
.
uv
=
uv
;
this
.
textureSize
=
textureSize
;
this
.
bias
=
bias
;
}
TextureCubeUVNode
.
Nodes
=
(
function
()
{
var
TextureCubeUVData
=
new
StructNode
(
[
"
struct TextureCubeUVData {
"
,
"
vec2 uv_10;
"
,
"
vec2 uv_20;
"
,
"
float t;
"
,
"
}
"
].
join
(
"
\n
"
)
);
var
getFaceFromDirection
=
new
FunctionNode
(
[
"
int getFaceFromDirection(vec3 direction) {
"
,
"
vec3 absDirection = abs(direction);
"
,
"
int face = -1;
"
,
"
if( absDirection.x > absDirection.z ) {
"
,
"
if(absDirection.x > absDirection.y )
"
,
"
face = direction.x > 0.0 ? 0 : 3;
"
,
"
else
"
,
"
face = direction.y > 0.0 ? 1 : 4;
"
,
"
}
"
,
"
else {
"
,
"
if(absDirection.z > absDirection.y )
"
,
"
face = direction.z > 0.0 ? 2 : 5;
"
,
"
else
"
,
"
face = direction.y > 0.0 ? 1 : 4;
"
,
"
}
"
,
"
return face;
"
,
"
}
"
].
join
(
"
\n
"
)
);
var
cubeUV_maxLods1
=
new
ConstNode
(
"
#define cubeUV_maxLods1 ( log2( cubeUV_textureSize * 0.25 ) - 1.0 )
"
);
var
cubeUV_rangeClamp
=
new
ConstNode
(
"
#define cubeUV_rangeClamp ( exp2( ( 6.0 - 1.0 ) * 2.0 ) )
"
);
var
MipLevelInfo
=
new
FunctionNode
(
[
"
vec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness, in float cubeUV_textureSize ) {
"
,
"
float scale = exp2(cubeUV_maxLods1 - roughnessLevel);
"
,
"
float dxRoughness = dFdx(roughness);
"
,
"
float dyRoughness = dFdy(roughness);
"
,
"
vec3 dx = dFdx( vec * scale * dxRoughness );
"
,
"
vec3 dy = dFdy( vec * scale * dyRoughness );
"
,
"
float d = max( dot( dx, dx ), dot( dy, dy ) );
"
,
// Clamp the value to the max mip level counts. hard coded to 6 mips"
"
d = clamp(d, 1.0, cubeUV_rangeClamp);
"
,
"
float mipLevel = 0.5 * log2(d);
"
,
"
return vec2(floor(mipLevel), fract(mipLevel));
"
,
"
}
"
].
join
(
"
\n
"
),
[
cubeUV_maxLods1
,
cubeUV_rangeClamp
],
{
derivatives
:
true
}
);
var
cubeUV_maxLods2
=
new
ConstNode
(
"
#define cubeUV_maxLods2 ( log2( cubeUV_textureSize * 0.25 ) - 2.0 )
"
);
var
cubeUV_rcpTextureSize
=
new
ConstNode
(
"
#define cubeUV_rcpTextureSize ( 1.0 / cubeUV_textureSize )
"
);
var
getCubeUV
=
new
FunctionNode
(
[
"
vec2 getCubeUV( vec3 direction, float roughnessLevel, float mipLevel, in float cubeUV_textureSize ) {
"
,
"
mipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;
"
,
"
float a = 16.0 * cubeUV_rcpTextureSize;
"
,
""
,
"
vec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );
"
,
"
vec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;
"
,
// float powScale = exp2(roughnessLevel + mipLevel);"
"
float powScale = exp2_packed.x * exp2_packed.y;
"
,
// float scale = 1.0 / exp2(roughnessLevel + 2.0 + mipLevel);"
"
float scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;
"
,
// float mipOffset = 0.75*(1.0 - 1.0/exp2(mipLevel))/exp2(roughnessLevel);"
"
float mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;
"
,
""
,
"
bool bRes = mipLevel == 0.0;
"
,
"
scale = bRes && (scale < a) ? a : scale;
"
,
""
,
"
vec3 r;
"
,
"
vec2 offset;
"
,
"
int face = getFaceFromDirection(direction);
"
,
""
,
"
float rcpPowScale = 1.0 / powScale;
"
,
""
,
"
if( face == 0) {
"
,
"
r = vec3(direction.x, -direction.z, direction.y);
"
,
"
offset = vec2(0.0+mipOffset,0.75 * rcpPowScale);
"
,
"
offset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;
"
,
"
}
"
,
"
else if( face == 1) {
"
,
"
r = vec3(direction.y, direction.x, direction.z);
"
,
"
offset = vec2(scale+mipOffset, 0.75 * rcpPowScale);
"
,
"
offset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;
"
,
"
}
"
,
"
else if( face == 2) {
"
,
"
r = vec3(direction.z, direction.x, direction.y);
"
,
"
offset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);
"
,
"
offset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;
"
,
"
}
"
,
"
else if( face == 3) {
"
,
"
r = vec3(direction.x, direction.z, direction.y);
"
,
"
offset = vec2(0.0+mipOffset,0.5 * rcpPowScale);
"
,
"
offset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;
"
,
"
}
"
,
"
else if( face == 4) {
"
,
"
r = vec3(direction.y, direction.x, -direction.z);
"
,
"
offset = vec2(scale+mipOffset, 0.5 * rcpPowScale);
"
,
"
offset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;
"
,
"
}
"
,
"
else {
"
,
"
r = vec3(direction.z, -direction.x, direction.y);
"
,
"
offset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);
"
,
"
offset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;
"
,
"
}
"
,
"
r = normalize(r);
"
,
"
float texelOffset = 0.5 * cubeUV_rcpTextureSize;
"
,
"
vec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;
"
,
"
vec2 base = offset + vec2( texelOffset );
"
,
"
return base + s * ( scale - 2.0 * texelOffset );
"
,
"
}
"
].
join
(
"
\n
"
),
[
cubeUV_maxLods2
,
cubeUV_rcpTextureSize
,
getFaceFromDirection
]
);
var
cubeUV_maxLods3
=
new
ConstNode
(
"
#define cubeUV_maxLods3 ( log2( cubeUV_textureSize * 0.25 ) - 3.0 )
"
);
var
textureCubeUV
=
new
FunctionNode
(
[
"
TextureCubeUVData textureCubeUV( vec3 reflectedDirection, float roughness, in float cubeUV_textureSize ) {
"
,
"
float roughnessVal = roughness * cubeUV_maxLods3;
"
,
"
float r1 = floor(roughnessVal);
"
,
"
float r2 = r1 + 1.0;
"
,
"
float t = fract(roughnessVal);
"
,
"
vec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness, cubeUV_textureSize);
"
,
"
float s = mipInfo.y;
"
,
"
float level0 = mipInfo.x;
"
,
"
float level1 = level0 + 1.0;
"
,
"
level1 = level1 > 5.0 ? 5.0 : level1;
"
,
""
,
// round to nearest mipmap if we are not interpolating."
"
level0 += min( floor( s + 0.5 ), 5.0 );
"
,
""
,
// Tri linear interpolation."
"
vec2 uv_10 = getCubeUV(reflectedDirection, r1, level0, cubeUV_textureSize);
"
,
"
vec2 uv_20 = getCubeUV(reflectedDirection, r2, level0, cubeUV_textureSize);
"
,
""
,
"
return TextureCubeUVData(uv_10, uv_20, t);
"
,
"
}
"
].
join
(
"
\n
"
),
[
TextureCubeUVData
,
cubeUV_maxLods3
,
MipLevelInfo
,
getCubeUV
]
);
var
TextureCubeUVData
=
new
StructNode
(
`struct TextureCubeUVData {
vec4 tl;
vec4 tr;
vec4 br;
vec4 bl;
vec2 f;
}`
);
var
cubeUV_maxMipLevel
=
new
ConstNode
(
`float cubeUV_maxMipLevel 8.0`
,
true
);
var
cubeUV_minMipLevel
=
new
ConstNode
(
`float cubeUV_minMipLevel 4.0`
,
true
);
var
cubeUV_maxTileSize
=
new
ConstNode
(
`float cubeUV_maxTileSize 256.0`
,
true
);
var
cubeUV_minTileSize
=
new
ConstNode
(
`float cubeUV_minTileSize 16.0`
,
true
);
// These shader functions convert between the UV coordinates of a single face of
// a cubemap, the 0-5 integer index of a cube face, and the direction vector for
// sampling a textureCube (not generally normalized).
var
getFace
=
new
FunctionNode
(
`float getFace(vec3 direction) {
vec3 absDirection = abs(direction);
float face = -1.0;
if (absDirection.x > absDirection.z) {
if (absDirection.x > absDirection.y)
face = direction.x > 0.0 ? 0.0 : 3.0;
else
face = direction.y > 0.0 ? 1.0 : 4.0;
} else {
if (absDirection.z > absDirection.y)
face = direction.z > 0.0 ? 2.0 : 5.0;
else
face = direction.y > 0.0 ? 1.0 : 4.0;
}
return face;
}`
);
getFace
.
useKeywords
=
false
;
var
getUV
=
new
FunctionNode
(
`vec2 getUV(vec3 direction, float face) {
vec2 uv;
if (face == 0.0) {
uv = vec2(-direction.z, direction.y) / abs(direction.x);
} else if (face == 1.0) {
uv = vec2(direction.x, -direction.z) / abs(direction.y);
} else if (face == 2.0) {
uv = direction.xy / abs(direction.z);
} else if (face == 3.0) {
uv = vec2(direction.z, direction.y) / abs(direction.x);
} else if (face == 4.0) {
uv = direction.xz / abs(direction.y);
} else {
uv = vec2(-direction.x, direction.y) / abs(direction.z);
}
return 0.5 * (uv + 1.0);
}`
);
getUV
.
useKeywords
=
false
;
var
bilinearCubeUV
=
new
FunctionNode
(
`TextureCubeUVData bilinearCubeUV(sampler2D envMap, vec3 direction, float mipInt) {
float face = getFace(direction);
float filterInt = max(cubeUV_minMipLevel - mipInt, 0.0);
mipInt = max(mipInt, cubeUV_minMipLevel);
float faceSize = exp2(mipInt);
float texelSize = 1.0 / (3.0 * cubeUV_maxTileSize);
vec2 uv = getUV(direction, face) * (faceSize - 1.0);
vec2 f = fract(uv);
uv += 0.5 - f;
if (face > 2.0) {
uv.y += faceSize;
face -= 3.0;
}
uv.x += face * faceSize;
if(mipInt < cubeUV_maxMipLevel){
uv.y += 2.0 * cubeUV_maxTileSize;
}
uv.y += filterInt * 2.0 * cubeUV_minTileSize;
uv.x += 3.0 * max(0.0, cubeUV_maxTileSize - 2.0 * faceSize);
uv *= texelSize;
vec4 tl = texture2D(envMap, uv);
uv.x += texelSize;
vec4 tr = texture2D(envMap, uv);
uv.y += texelSize;
vec4 br = texture2D(envMap, uv);
uv.x -= texelSize;
vec4 bl = texture2D(envMap, uv);
return TextureCubeUVData( tl, tr, br, bl, f );
}`
,
[
TextureCubeUVData
,
getFace
,
getUV
,
cubeUV_maxMipLevel
,
cubeUV_minMipLevel
,
cubeUV_maxTileSize
,
cubeUV_minTileSize
]
);
bilinearCubeUV
.
useKeywords
=
false
;
// These defines must match with PMREMGenerator
var
r0
=
new
ConstNode
(
`float r0 1.0`
,
true
);
var
v0
=
new
ConstNode
(
`float v0 0.339`
,
true
);
var
m0
=
new
ConstNode
(
`float m0 -2.0`
,
true
);
var
r1
=
new
ConstNode
(
`float r1 0.8`
,
true
);
var
v1
=
new
ConstNode
(
`float v1 0.276`
,
true
);
var
m1
=
new
ConstNode
(
`float m1 -1.0`
,
true
);
var
r4
=
new
ConstNode
(
`float r4 0.4`
,
true
);
var
v4
=
new
ConstNode
(
`float v4 0.046`
,
true
);
var
m4
=
new
ConstNode
(
`float m4 2.0`
,
true
);
var
r5
=
new
ConstNode
(
`float r5 0.305`
,
true
);
var
v5
=
new
ConstNode
(
`float v5 0.016`
,
true
);
var
m5
=
new
ConstNode
(
`float m5 3.0`
,
true
);
var
r6
=
new
ConstNode
(
`float r6 0.21`
,
true
);
var
v6
=
new
ConstNode
(
`float v6 0.0038`
,
true
);
var
m6
=
new
ConstNode
(
`float m6 4.0`
,
true
);
var
defines
=
[
r0
,
v0
,
m0
,
r1
,
v1
,
m1
,
r4
,
v4
,
m4
,
r5
,
v5
,
m5
,
r6
,
v6
,
m6
];
var
roughnessToMip
=
new
FunctionNode
(
`float roughnessToMip(float roughness) {
float mip = 0.0;
if (roughness >= r1) {
mip = (r0 - roughness) * (m1 - m0) / (r0 - r1) + m0;
} else if (roughness >= r4) {
mip = (r1 - roughness) * (m4 - m1) / (r1 - r4) + m1;
} else if (roughness >= r5) {
mip = (r4 - roughness) * (m5 - m4) / (r4 - r5) + m4;
} else if (roughness >= r6) {
mip = (r5 - roughness) * (m6 - m5) / (r5 - r6) + m5;
} else {
mip = -2.0 * log2(1.16 * roughness);// 1.16 = 1.79^0.25
}
return mip;
}`
,
defines
);
return
{
TextureCubeUVData
:
TextureCubeUVData
,
textureCubeUV
:
textureCubeUV
bilinearCubeUV
:
bilinearCubeUV
,
roughnessToMip
:
roughnessToMip
,
m0
:
m0
,
cubeUV_maxMipLevel
:
cubeUV_maxMipLevel
};
}
)();
...
...
@@ -165,17 +167,92 @@ TextureCubeUVNode.prototype = Object.create( TempNode.prototype );
TextureCubeUVNode
.
prototype
.
constructor
=
TextureCubeUVNode
;
TextureCubeUVNode
.
prototype
.
nodeType
=
"
TextureCubeUV
"
;
TextureCubeUVNode
.
prototype
.
bilinearCubeUV
=
function
(
builder
,
texture
,
uv
,
mipInt
)
{
var
bilinearCubeUV
=
new
FunctionCallNode
(
TextureCubeUVNode
.
Nodes
.
bilinearCubeUV
,
[
texture
,
uv
,
mipInt
]
);
this
.
colorSpaceTL
=
this
.
colorSpaceTL
||
new
ColorSpaceNode
(
new
ExpressionNode
(
''
,
'
v4
'
)
);
this
.
colorSpaceTL
.
fromDecoding
(
builder
.
getTextureEncodingFromMap
(
this
.
value
.
value
)
);
this
.
colorSpaceTL
.
input
.
parse
(
bilinearCubeUV
.
build
(
builder
)
+
'
.tl
'
);
this
.
colorSpaceTR
=
this
.
colorSpaceTR
||
new
ColorSpaceNode
(
new
ExpressionNode
(
''
,
'
v4
'
)
);
this
.
colorSpaceTR
.
fromDecoding
(
builder
.
getTextureEncodingFromMap
(
this
.
value
.
value
)
);
this
.
colorSpaceTR
.
input
.
parse
(
bilinearCubeUV
.
build
(
builder
)
+
'
.tr
'
);
this
.
colorSpaceBL
=
this
.
colorSpaceBL
||
new
ColorSpaceNode
(
new
ExpressionNode
(
''
,
'
v4
'
)
);
this
.
colorSpaceBL
.
fromDecoding
(
builder
.
getTextureEncodingFromMap
(
this
.
value
.
value
)
);
this
.
colorSpaceBL
.
input
.
parse
(
bilinearCubeUV
.
build
(
builder
)
+
'
.bl
'
);
this
.
colorSpaceBR
=
this
.
colorSpaceBR
||
new
ColorSpaceNode
(
new
ExpressionNode
(
''
,
'
v4
'
)
);
this
.
colorSpaceBR
.
fromDecoding
(
builder
.
getTextureEncodingFromMap
(
this
.
value
.
value
)
);
this
.
colorSpaceBR
.
input
.
parse
(
bilinearCubeUV
.
build
(
builder
)
+
'
.br
'
);
var
f
=
bilinearCubeUV
.
build
(
builder
)
+
'
.f
'
;
// add a custom context for fix incompatibility with the core
// include ColorSpace function only for vertex shader (in fragment shader color space functions is added automatically by core)
// this should be removed in the future
// context.include =: is used to include or not functions if used FunctionNode
// context.ignoreCache =: not create temp variables nodeT0..9 to optimize the code
var
context
=
{
include
:
builder
.
isShader
(
'
vertex
'
),
ignoreCache
:
true
};
builder
.
addContext
(
context
);
this
.
colorSpaceTLExp
=
new
ExpressionNode
(
this
.
colorSpaceTL
.
build
(
builder
,
'
v4
'
),
'
v4
'
);
this
.
colorSpaceTRExp
=
new
ExpressionNode
(
this
.
colorSpaceTR
.
build
(
builder
,
'
v4
'
),
'
v4
'
);
this
.
colorSpaceBLExp
=
new
ExpressionNode
(
this
.
colorSpaceBL
.
build
(
builder
,
'
v4
'
),
'
v4
'
);
this
.
colorSpaceBRExp
=
new
ExpressionNode
(
this
.
colorSpaceBR
.
build
(
builder
,
'
v4
'
),
'
v4
'
);
// end custom context
builder
.
removeContext
();
// --
var
output
=
new
ExpressionNode
(
`mix( mix( cubeUV_TL, cubeUV_TR, cubeUV.f.x ), mix( cubeUV_BL, cubeUV_BR, cubeUV.f.x ), cubeUV.f.y )`
,
'
v4
'
);
output
.
keywords
[
'
cubeUV_TL
'
]
=
this
.
colorSpaceTLExp
;
output
.
keywords
[
'
cubeUV_TR
'
]
=
this
.
colorSpaceTRExp
;
output
.
keywords
[
'
cubeUV_BL
'
]
=
this
.
colorSpaceBLExp
;
output
.
keywords
[
'
cubeUV_BR
'
]
=
this
.
colorSpaceBRExp
;
output
.
keywords
[
'
cubeUV
'
]
=
bilinearCubeUV
;
return
output
;
};
TextureCubeUVNode
.
prototype
.
generate
=
function
(
builder
,
output
)
{
if
(
builder
.
isShader
(
'
fragment
'
)
)
{
var
textureCubeUV
=
builder
.
include
(
TextureCubeUVNode
.
Nodes
.
textureCubeUV
);
var
uv
=
this
.
uv
;
var
bias
=
this
.
bias
||
builder
.
context
.
roughness
;
var
mipV
=
new
FunctionCallNode
(
TextureCubeUVNode
.
Nodes
.
roughnessToMip
,
[
bias
]
);
var
mip
=
new
MathNode
(
mipV
,
TextureCubeUVNode
.
Nodes
.
m0
,
TextureCubeUVNode
.
Nodes
.
cubeUV_maxMipLevel
,
MathNode
.
CLAMP
);
var
mipInt
=
new
MathNode
(
mip
,
MathNode
.
FLOOR
);
var
mipF
=
new
MathNode
(
mip
,
MathNode
.
FRACT
);
var
color0
=
this
.
bilinearCubeUV
(
builder
,
this
.
value
,
uv
,
mipInt
);
var
color1
=
this
.
bilinearCubeUV
(
builder
,
this
.
value
,
uv
,
new
OperatorNode
(
mipInt
,
new
FloatNode
(
1
).
setReadonly
(
true
),
OperatorNode
.
ADD
)
);
var
color1Mix
=
new
MathNode
(
color0
,
color1
,
mipF
,
MathNode
.
MIX
);
var
biasNode
=
this
.
bias
||
builder
.
context
.
roughness
;
/*
// TODO: Optimize this in the future
var cond = new CondNode(
mipF,
new FloatNode( 0 ).setReadonly( true ),
CondNode.EQUAL,
color0, // if
color1Mix // else
);
*/
return
builder
.
format
(
textureCubeUV
+
'
(
'
+
this
.
uv
.
build
(
builder
,
'
v3
'
)
+
'
,
'
+
biasNode
.
build
(
builder
,
'
f
'
)
+
'
,
'
+
this
.
textureSize
.
build
(
builder
,
'
f
'
)
+
'
)
'
,
this
.
getType
(
builder
),
output
);
return
builder
.
format
(
color1Mix
.
build
(
builder
),
'
v4
'
,
output
);
}
else
{
...
...
@@ -195,9 +272,9 @@ TextureCubeUVNode.prototype.toJSON = function ( meta ) {
data
=
this
.
createJSONNode
(
meta
);
data
.
value
=
this
.
value
.
toJSON
(
meta
).
uuid
;
data
.
uv
=
this
.
uv
.
toJSON
(
meta
).
uuid
;
data
.
textureSize
=
this
.
textureSize
.
toJSON
(
meta
).
uuid
;
data
.
blinnExponentToRoughness
=
this
.
blinnExponentToRoughness
.
toJSON
(
meta
).
uuid
;
data
.
bias
=
this
.
bias
.
toJSON
(
meta
).
uuid
;
}
...
...
examples/webgl_materials_envmaps_hdr_nodes.html
浏览文件 @
3492536c
<!DOCTYPE html>
<html
lang=
"en"
>
<head>
<title>
threejs webgl -
node material
- hdr environment mapping
</title>
<title>
threejs webgl -
materials
- hdr environment mapping
</title>
<meta
charset=
"utf-8"
>
<meta
name=
"viewport"
content=
"width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"
>
<style>
body
{
color
:
#fff
;
font-family
:
Monospace
;
font-size
:
13px
;
text-align
:
center
;
background-color
:
#000
;
margin
:
0px
;
overflow
:
hidden
;
}
a
{
color
:
#00f
}
#info
{
position
:
absolute
;
top
:
0px
;
width
:
100%
;
padding
:
5px
;
}
</style>
<link
type=
"text/css"
rel=
"stylesheet"
href=
"main.css"
>
</head>
<body>
<div
id=
"container"
></div>
<div
id=
"info"
><a
href=
"http://threejs.org"
target=
"_blank"
rel=
"noopener"
>
threejs
</a>
- High dynamic range (RGBE) Image-based Lighting (IBL)
<br
/>
using run-time generated pre-filtered roughness mipmaps (PMREM)
<br/>
Created by Prashant Sharma and
<a
href=
"http://clara.io/"
target=
"_blank"
rel=
"noopener"
>
Ben Houston
</a>
.
</div>
<div
id=
"info"
>
<a
href=
"http://threejs.org"
target=
"_blank"
rel=
"noopener"
>
threejs
</a>
- High dynamic range (RGBE) Image-based Lighting (IBL)
<br
/>
using run-time generated pre-filtered roughness mipmaps (PMREM)
<br/>
Created by Prashant Sharma and
<a
href=
"http://clara.io/"
target=
"_blank"
rel=
"noopener"
>
Ben Houston
</a>
.
</div>
<script
type=
"module"
>
...
...
@@ -41,6 +24,7 @@
import
{
OrbitControls
}
from
'
./jsm/controls/OrbitControls.js
'
;
import
{
HDRCubeTextureLoader
}
from
'
./jsm/loaders/HDRCubeTextureLoader.js
'
;
import
{
PMREMGenerator
}
from
'
./jsm/pmrem/PMREMGenerator.js
'
;
import
{
MeshStandardNodeMaterial
}
from
'
./jsm/nodes/Nodes.js
'
;
var
params
=
{
...
...
@@ -50,18 +34,53 @@
exposure
:
1.0
,
nodes
:
true
,
animate
:
true
,
debug
:
false
,
debug
:
false
};
var
container
,
stats
;
var
camera
,
scene
,
renderer
,
controls
;
var
torusMesh
,
torusMeshNode
,
planeMesh
;
var
ldrCubeRenderTarget
,
hdrCubeRenderTarget
,
rgbmCubeRenderTarget
;
var
generatedCubeRenderTarget
,
ldrCubeRenderTarget
,
hdrCubeRenderTarget
,
rgbmCubeRenderTarget
;
var
ldrCubeMap
,
hdrCubeMap
,
rgbmCubeMap
;
init
();
animate
();
function
getEnvScene
()
{
var
envScene
=
new
THREE
.
Scene
();
var
geometry
=
new
THREE
.
BoxBufferGeometry
();
geometry
.
deleteAttribute
(
'
uv
'
);
var
roomMaterial
=
new
THREE
.
MeshStandardMaterial
({
metalness
:
0
,
side
:
THREE
.
BackSide
});
var
room
=
new
THREE
.
Mesh
(
geometry
,
roomMaterial
);
room
.
scale
.
setScalar
(
10
);
envScene
.
add
(
room
);
var
mainLight
=
new
THREE
.
PointLight
(
0xffffff
,
50
,
0
,
2
);
envScene
.
add
(
mainLight
);
var
lightMaterial
=
new
THREE
.
MeshLambertMaterial
(
{
color
:
0x000000
,
emissive
:
0xffffff
,
emissiveIntensity
:
10
}
);
var
light1
=
new
THREE
.
Mesh
(
geometry
,
lightMaterial
);
light1
.
position
.
set
(
-
5
,
2
,
0
);
light1
.
scale
.
set
(
0.1
,
1
,
1
);
envScene
.
add
(
light1
);
var
light2
=
new
THREE
.
Mesh
(
geometry
,
lightMaterial
);
light2
.
position
.
set
(
0
,
5
,
0
);
light2
.
scale
.
set
(
1
,
0.1
,
1
);
envScene
.
add
(
light2
);
var
light2
=
new
THREE
.
Mesh
(
geometry
,
lightMaterial
);
light2
.
position
.
set
(
2
,
1
,
5
);
light2
.
scale
.
set
(
1.5
,
2
,
0.1
);
envScene
.
add
(
light2
);
return
envScene
;
}
function
init
()
{
container
=
document
.
createElement
(
'
div
'
);
...
...
@@ -74,6 +93,7 @@
scene
.
background
=
new
THREE
.
Color
(
0x000000
);
renderer
=
new
THREE
.
WebGLRenderer
();
renderer
.
physicallyCorrectLights
=
true
;
renderer
.
toneMapping
=
THREE
.
LinearToneMapping
;
//
...
...
@@ -97,7 +117,10 @@
torusMeshNode
=
new
THREE
.
Mesh
(
geometry
,
material
);
scene
.
add
(
torusMeshNode
);
planeMesh
=
new
THREE
.
Mesh
(
new
THREE
.
PlaneBufferGeometry
(
200
,
200
),
new
THREE
.
MeshBasicMaterial
()
);
var
geometry
=
new
THREE
.
PlaneBufferGeometry
(
200
,
200
);
var
material
=
new
THREE
.
MeshBasicMaterial
();
planeMesh
=
new
THREE
.
Mesh
(
geometry
,
material
);
planeMesh
.
position
.
y
=
-
50
;
planeMesh
.
rotation
.
x
=
-
Math
.
PI
*
0.5
;
scene
.
add
(
planeMesh
);
...
...
@@ -109,6 +132,9 @@
}
var
envScene
=
getEnvScene
();
generatedCubeRenderTarget
=
pmremGenerator
.
fromScene
(
envScene
,
0.04
);
var
hdrUrls
=
[
'
px.hdr
'
,
'
nx.hdr
'
,
'
py.hdr
'
,
'
ny.hdr
'
,
'
pz.hdr
'
,
'
nz.hdr
'
];
hdrCubeMap
=
new
HDRCubeTextureLoader
()
.
setPath
(
'
./textures/cube/pisaHDR/
'
)
...
...
@@ -153,7 +179,7 @@
renderer
.
setSize
(
window
.
innerWidth
,
window
.
innerHeight
);
container
.
appendChild
(
renderer
.
domElement
);
//renderer.toneMapping =
THREE.
ReinhardToneMapping;
//renderer.toneMapping = ReinhardToneMapping;
renderer
.
outputEncoding
=
THREE
.
sRGBEncoding
;
stats
=
new
Stats
();
...
...
@@ -167,7 +193,7 @@
var
gui
=
new
GUI
();
gui
.
add
(
params
,
'
envMap
'
,
[
'
LDR
'
,
'
HDR
'
,
'
RGBM16
'
]
);
gui
.
add
(
params
,
'
envMap
'
,
[
'
Generated
'
,
'
LDR
'
,
'
HDR
'
,
'
RGBM16
'
]
);
gui
.
add
(
params
,
'
roughness
'
,
0
,
1
,
0.01
);
gui
.
add
(
params
,
'
metalness
'
,
0
,
1
,
0.01
);
gui
.
add
(
params
,
'
exposure
'
,
0
,
2
,
0.01
);
...
...
@@ -202,19 +228,23 @@
function
render
()
{
torusMesh
.
visible
=
!
params
.
nodes
;
torusMeshNode
.
visible
=
params
.
nodes
;
torusMesh
.
material
.
roughness
=
params
.
roughness
;
torusMesh
.
material
.
metalness
=
params
.
metalness
;
torusMeshNode
.
material
.
roughness
=
params
.
roughness
;
torusMeshNode
.
material
.
metalness
=
params
.
metalness
;
torusMesh
.
visible
=
!
params
.
nodes
;
torusMeshNode
.
visible
=
params
.
nodes
;
var
renderTarget
,
cubeMap
;
switch
(
params
.
envMap
)
{
case
'
Generated
'
:
renderTarget
=
generatedCubeRenderTarget
;
cubeMap
=
generatedCubeRenderTarget
.
texture
;
break
;
case
'
LDR
'
:
renderTarget
=
ldrCubeRenderTarget
;
cubeMap
=
ldrCubeMap
;
...
...
examples/webgl_materials_envmaps_pmrem_nodes.html
浏览文件 @
3492536c
...
...
@@ -51,7 +51,6 @@
}
from
'
./jsm/nodes/Nodes.js
'
;
var
params
=
{
textureSize
:
1024
,
roughness
:
0.0
,
metalness
:
0.0
,
exposure
:
1.0
,
...
...
@@ -62,16 +61,14 @@
var
container
,
stats
;
var
camera
,
scene
,
renderer
,
controls
;
var
nodeMaterial
,
nodeTexture
,
nodeTexture
Size
,
nodeTexture
Intensity
,
torusMesh
,
planeMesh
;
var
nodeMaterial
,
nodeTexture
,
nodeTextureIntensity
,
torusMesh
,
planeMesh
;
var
hdrCubeRenderTarget
;
var
hdrCubeMap
;
init
();
animate
();
function
generate
(
textureSize
)
{
nodeTextureSize
.
value
=
textureSize
;
function
generate
()
{
var
pmremGenerator
=
new
PMREMGenerator
(
renderer
);
hdrCubeRenderTarget
=
pmremGenerator
.
fromCubemap
(
hdrCubeMap
);
...
...
@@ -112,10 +109,9 @@
nodeMaterial
.
visible
=
false
;
nodeTexture
=
new
TextureNode
();
nodeTextureSize
=
new
FloatNode
(
1024
);
nodeTextureIntensity
=
new
FloatNode
(
1
);
nodeMaterial
.
environment
=
new
OperatorNode
(
new
TextureCubeNode
(
nodeTexture
,
nodeTextureSize
),
nodeTextureIntensity
,
OperatorNode
.
MUL
);
nodeMaterial
.
environment
=
new
OperatorNode
(
new
TextureCubeNode
(
nodeTexture
),
nodeTextureIntensity
,
OperatorNode
.
MUL
);
torusMesh
=
new
THREE
.
Mesh
(
geometry
,
nodeMaterial
);
scene
.
add
(
torusMesh
);
...
...
@@ -131,7 +127,7 @@
.
setDataType
(
THREE
.
UnsignedByteType
)
.
load
(
hdrUrls
,
function
()
{
generate
(
params
.
textureSize
);
generate
();
nodeMaterial
.
visible
=
true
;
...
...
@@ -155,7 +151,6 @@
var
gui
=
new
GUI
();
gui
.
add
(
params
,
'
textureSize
'
,
[
128
,
256
,
512
,
1024
,
2048
,
4096
]
);
gui
.
add
(
params
,
'
roughness
'
,
0
,
1
,
0.01
);
gui
.
add
(
params
,
'
metalness
'
,
0
,
1
,
0.01
);
gui
.
add
(
params
,
'
exposure
'
,
0
,
2
,
0.01
);
...
...
@@ -195,12 +190,6 @@
nodeTextureIntensity
.
value
=
params
.
intensity
;
if
(
nodeTextureSize
.
value
!==
params
.
textureSize
)
{
generate
(
params
.
textureSize
);
}
if
(
params
.
animate
)
{
torusMesh
.
rotation
.
y
+=
0.005
;
...
...
src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl.js
浏览文件 @
3492536c
...
...
@@ -98,35 +98,6 @@ vec3 bilinearCubeUV(sampler2D envMap, vec3 direction, float mipInt) {
#define v6 0.0038
#define m6 4.0
float roughnessToVariance(float roughness) {
float variance = 0.0;
if (roughness >= r1) {
variance = (r0 - roughness) * (v1 - v0) / (r0 - r1) + v0;
} else if (roughness >= r4) {
variance = (r1 - roughness) * (v4 - v1) / (r1 - r4) + v1;
} else if (roughness >= r5) {
variance = (r4 - roughness) * (v5 - v4) / (r4 - r5) + v4;
} else {
float roughness2 = roughness * roughness;
variance = 1.79 * roughness2 * roughness2;
}
return variance;
}
float varianceToRoughness(float variance) {
float roughness = 0.0;
if (variance >= v1) {
roughness = (v0 - variance) * (r1 - r0) / (v0 - v1) + r0;
} else if (variance >= v4) {
roughness = (v1 - variance) * (r4 - r1) / (v1 - v4) + r1;
} else if (variance >= v5) {
roughness = (v4 - variance) * (r5 - r4) / (v4 - v5) + r4;
} else {
roughness = pow(0.559 * variance, 0.25);// 0.559 = 1.0 / 1.79
}
return roughness;
}
float roughnessToMip(float roughness) {
float mip = 0.0;
if (roughness >= r1) {
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录