Spaces:
Running
Running
File size: 7,792 Bytes
6cd9596 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
/**
* @author sunag / http://www.sunag.com.br/
*/
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 { ReflectNode } from '../accessors/ReflectNode.js';
import { FloatNode } from '../inputs/FloatNode.js';
import { BlinnExponentToRoughnessNode } from '../bsdfs/BlinnExponentToRoughnessNode.js';
function TextureCubeUVNode( uv, textureSize, blinnExponentToRoughness ) {
TempNode.call( this, 'TextureCubeUVData' ); // TextureCubeUVData is type as StructNode
this.uv = uv || new ReflectNode( ReflectNode.VECTOR );
this.textureSize = textureSize || new FloatNode( 1024 );
this.blinnExponentToRoughness = blinnExponentToRoughness || new BlinnExponentToRoughnessNode();
}
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 ] );
return {
TextureCubeUVData: TextureCubeUVData,
textureCubeUV: textureCubeUV
};
} )();
TextureCubeUVNode.prototype = Object.create( TempNode.prototype );
TextureCubeUVNode.prototype.constructor = TextureCubeUVNode;
TextureCubeUVNode.prototype.nodeType = "TextureCubeUV";
TextureCubeUVNode.prototype.generate = function ( builder, output ) {
if ( builder.isShader( 'fragment' ) ) {
var textureCubeUV = builder.include( TextureCubeUVNode.Nodes.textureCubeUV );
return builder.format( textureCubeUV + '( ' + this.uv.build( builder, 'v3' ) + ', ' +
this.blinnExponentToRoughness.build( builder, 'f' ) + ', ' +
this.textureSize.build( builder, 'f' ) + ' )', this.getType( builder ), output );
} else {
console.warn( "THREE.TextureCubeUVNode is not compatible with " + builder.shader + " shader." );
return builder.format( 'vec4( 0.0 )', this.getType( builder ), output );
}
};
TextureCubeUVNode.prototype.toJSON = function ( meta ) {
var data = this.getJSONNode( meta );
if ( ! data ) {
data = this.createJSONNode( meta );
data.uv = this.uv.toJSON( meta ).uuid;
data.textureSize = this.textureSize.toJSON( meta ).uuid;
data.blinnExponentToRoughness = this.blinnExponentToRoughness.toJSON( meta ).uuid;
}
return data;
};
export { TextureCubeUVNode };
|