Three.js: 예 : webgl_shaders_ocean 문제

에 λ§Œλ“  2017λ…„ 10μ›” 01일  Β·  24μ½”λ©˜νŠΈ  Β·  좜처: mrdoob/three.js

λ¬Έμ œμ— λŒ€ν•œ μ„€λͺ…

λ‚˜λŠ” 였늘 webgl_shaders_ocean 의 ν˜„μž¬ dev 버전이 Firefox 55.0.2 및 Ubuntu 16.04 LTSμ—μ„œ μž‘λ™ν•˜μ§€ μ•ŠμŒμ„ λ°œκ²¬ν–ˆμŠ΅λ‹ˆλ‹€. 물이 λ‚˜νƒ€λ‚˜μ§€ μ•Šκ³  λΈŒλΌμš°μ € μ½˜μ†”μ— 일뢀 였λ₯˜ λ©”μ‹œμ§€κ°€ ν‘œμ‹œλ©λ‹ˆλ‹€.

0:102(109): error: sampler arrays indexed with non-constant expressions are forbidden in GLSL 1.30 and later

κ³Ό

Integer overflow trying to construct a fake vertex attrib 0 array for a draw-operation with -1 vertices. Try reducing the number of vertices.
Drawing without vertex attrib 0 array enabled forces the browser to do expensive emulation work when running on desktop OpenGL platforms, for example on Mac. It is preferable to always draw with vertex attrib 0 array enabled, by using bindAttribLocation to bind some always-used attribute to location 0.

Chromiumμ—μ„œλŠ” λ¬Έμ œκ°€ λ°œμƒν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. κ²Œλ‹€κ°€ webgl_shaders_ocean 의 라이브 버전이 μž‘λ™ν•©λ‹ˆλ‹€. λ”°λΌμ„œμ΄ 였λ₯˜λŠ” THREE.Water 의 μ΅œμ‹  λ³€κ²½ 사항 이후에 μ‘΄μž¬ν•  수 μžˆμŠ΅λ‹ˆλ‹€. # 12167을 μ°Έμ‘°ν•˜μ‹­μ‹œμ˜€. PR을 되 돌리면 였λ₯˜κ°€ λ‚˜νƒ€λ‚˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

/ ping @Astrak

Three.js 버전
  • [X] 개발
  • [] r87
  • [] ...
λΈŒλΌμš°μ €
  • [] λͺ¨λ‘
  • [] 크둬
  • [X] Firefox
  • [ ] 인터넷 μ΅μŠ€ν”Œλ‘œλŸ¬
OS
  • [] λͺ¨λ‘
  • [] Windows
  • [ ] λ§₯ OS
  • [X] Linux
  • [] Android
  • [] iOS
ν•˜λ“œμ›¨μ–΄ μš”κ΅¬ 사항 (κ·Έλž˜ν”½ μΉ΄λ“œ, VR μž₯치 λ“±)

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

이 λ²„κ·ΈλŠ” 이제 # 13140을 톡해 μˆ˜μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 예이! πŸŽ‰ πŸ™Œ

λͺ¨λ“  24 λŒ“κΈ€

FF 52.4 및 FF 58.0을 μ‚¬μš©ν•˜μ—¬ Debian 9.1의 ν˜„μž¬ dev 브랜치 μ—μ„œ 예제λ₯Ό μ‹€ν–‰ν–ˆμ§€λ§Œ, 이런 일이 λ°œμƒν•˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.

κΈ°ν•˜ν•™μ€ PRμ—μ„œ 많이 λ³€κ²½λ˜μ§€ μ•Šμ•˜μœΌλ©° 쑰각 μ…°μ΄λ”λŠ” getShadowMask() λ₯Ό ν˜ΈμΆœν•˜λŠ” 데 ν•„μš”ν•œ 청크 만 ν¬ν•¨ν•©λ‹ˆλ‹€.

였λ₯˜ λ©”μ‹œμ§€κ°€ 0:102(109) 무엇을 κΈ°λ‘ν•©λ‹ˆκΉŒ?

λΆˆν–‰νžˆλ„. λ‘œκΉ… 된 쑰각 μ…°μ΄λ”λŠ” 27 ν–‰ 이후에 μž˜λ¦½λ‹ˆλ‹€.

쑰각 셰이더 ( THREE.Water )μ—μ„œ 셰이더 청크λ₯Ό μ œκ±°ν•˜κ³  getShadowMask() ν˜ΈμΆœν•˜λ©΄ 였λ₯˜κ°€ μ‚¬λΌμ§‘λ‹ˆλ‹€.

λΆˆν–‰νžˆλ„. λ‘œκΉ… 된 쑰각 μ…°μ΄λ”λŠ” 27 ν–‰ 이후에 μž˜λ¦½λ‹ˆλ‹€.

μ§ˆλ¬Έμ— λŒ€ν•΄ μ‚¬κ³Όλ“œλ¦½λ‹ˆλ‹€.ν•˜μ§€λ§Œ 셰이더 둜그 끝에 잘린 뢀뢄에 _ [...] _κ°€ μžˆμŠ΅λ‹ˆκΉŒ?

@moraxy κ·Έ 쑰언에 κ°μ‚¬λ“œλ¦½λ‹ˆλ‹€! _ [...] _을 ν΄λ¦­ν•˜λ©΄ 전체 ν”„λ‘œκ·Έλž¨μ„ λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.
λ‹€μŒμ€ 전체 쑰각 μ…°μ΄λ”μž…λ‹ˆλ‹€.

THREE.WebGLShader: Shader couldn't compile.
THREE.WebGLShader: gl.getShaderInfoLog() fragment 0:2(12): warning: extension `GL_ARB_gpu_shader5' unsupported in fragment shader
0:102(109): error: sampler arrays indexed with non-constant expressions are forbidden in GLSL 1.30 and later
1: precision highp float;
2: precision highp int;
3: #define SHADER_NAME ShaderMaterial
4: #define GAMMA_FACTOR 2
5: #define USE_FOG
6: #define FOG_EXP2
7: #define NUM_CLIPPING_PLANES 0
8: #define UNION_CLIPPING_PLANES 0
9: #define USE_SHADOWMAP
10: #define SHADOWMAP_TYPE_PCF
11: uniform mat4 viewMatrix;
12: uniform vec3 cameraPosition;
13: #define TONE_MAPPING
14: #define saturate(a) clamp( a, 0.0, 1.0 )
15: uniform float toneMappingExposure;
16: uniform float toneMappingWhitePoint;
17: vec3 LinearToneMapping( vec3 color ) {
18:     return toneMappingExposure * color;
19: }
20: vec3 ReinhardToneMapping( vec3 color ) {
21:     color *= toneMappingExposure;
22:     return saturate( color / ( vec3( 1.0 ) + color ) );
23: }
24: #define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )
25: vec3 Uncharted2ToneMapping( vec3 color ) {
26:     color *= toneMappingExposure;
27:     return saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );
28: }
29: vec3 OptimizedCineonToneMapping( vec3 color ) {
30:     color *= toneMappingExposure;
31:     color = max( vec3( 0.0 ), color - 0.004 );
32:     return pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );
33: }
34: 
35: vec3 toneMapping( vec3 color ) { return LinearToneMapping( color ); }
36: 
37: vec4 LinearToLinear( in vec4 value ) {
38:     return value;
39: }
40: vec4 GammaToLinear( in vec4 value, in float gammaFactor ) {
41:     return vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );
42: }
43: vec4 LinearToGamma( in vec4 value, in float gammaFactor ) {
44:     return vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );
45: }
46: vec4 sRGBToLinear( in vec4 value ) {
47:     return vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );
48: }
49: vec4 LinearTosRGB( in vec4 value ) {
50:     return vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.w );
51: }
52: vec4 RGBEToLinear( in vec4 value ) {
53:     return vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );
54: }
55: vec4 LinearToRGBE( in vec4 value ) {
56:     float maxComponent = max( max( value.r, value.g ), value.b );
57:     float fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );
58:     return vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );
59: }
60: vec4 RGBMToLinear( in vec4 value, in float maxRange ) {
61:     return vec4( value.xyz * value.w * maxRange, 1.0 );
62: }
63: vec4 LinearToRGBM( in vec4 value, in float maxRange ) {
64:     float maxRGB = max( value.x, max( value.g, value.b ) );
65:     float M      = clamp( maxRGB / maxRange, 0.0, 1.0 );
66:     M            = ceil( M * 255.0 ) / 255.0;
67:     return vec4( value.rgb / ( M * maxRange ), M );
68: }
69: vec4 RGBDToLinear( in vec4 value, in float maxRange ) {
70:     return vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );
71: }
72: vec4 LinearToRGBD( in vec4 value, in float maxRange ) {
73:     float maxRGB = max( value.x, max( value.g, value.b ) );
74:     float D      = max( maxRange / maxRGB, 1.0 );
75:     D            = min( floor( D ) / 255.0, 1.0 );
76:     return vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );
77: }
78: const mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );
79: vec4 LinearToLogLuv( in vec4 value )  {
80:     vec3 Xp_Y_XYZp = value.rgb * cLogLuvM;
81:     Xp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));
82:     vec4 vResult;
83:     vResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;
84:     float Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;
85:     vResult.w = fract(Le);
86:     vResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;
87:     return vResult;
88: }
89: const mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );
90: vec4 LogLuvToLinear( in vec4 value ) {
91:     float Le = value.z * 255.0 + value.w;
92:     vec3 Xp_Y_XYZp;
93:     Xp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);
94:     Xp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;
95:     Xp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;
96:     vec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;
97:     return vec4( max(vRGB, 0.0), 1.0 );
98: }
99: 
100: vec4 mapTexelToLinear( vec4 value ) { return LinearToLinear( value ); }
101: vec4 envMapTexelToLinear( vec4 value ) { return LinearToLinear( value ); }
102: vec4 emissiveMapTexelToLinear( vec4 value ) { return LinearToLinear( value ); }
103: vec4 linearToOutputTexel( vec4 value ) { return LinearToLinear( value ); }
104: 
105: uniform sampler2D mirrorSampler;
106: uniform float alpha;
107: uniform float time;
108: uniform float size;
109: uniform float distortionScale;
110: uniform sampler2D normalSampler;
111: uniform vec3 sunColor;
112: uniform vec3 sunDirection;
113: uniform vec3 eye;
114: uniform vec3 waterColor;
115: varying vec4 mirrorCoord;
116: varying vec4 worldPosition;
117: vec4 getNoise( vec2 uv ) {
118:    vec2 uv0 = ( uv / 103.0 ) + vec2(time / 17.0, time / 29.0);
119:    vec2 uv1 = uv / 107.0-vec2( time / -19.0, time / 31.0 );
120:    vec2 uv2 = uv / vec2( 8907.0, 9803.0 ) + vec2( time / 101.0, time / 97.0 );
121:    vec2 uv3 = uv / vec2( 1091.0, 1027.0 ) - vec2( time / 109.0, time / -113.0 );
122:    vec4 noise = texture2D( normalSampler, uv0 ) +
123:        texture2D( normalSampler, uv1 ) +
124:        texture2D( normalSampler, uv2 ) +
125:        texture2D( normalSampler, uv3 );
126:    return noise * 0.5 - 1.0;
127: }
128: void sunLight( const vec3 surfaceNormal, const vec3 eyeDirection, float shiny, float spec, float diffuse, inout vec3 diffuseColor, inout vec3 specularColor ) {
129:    vec3 reflection = normalize( reflect( -sunDirection, surfaceNormal ) );
130:    float direction = max( 0.0, dot( eyeDirection, reflection ) );
131:    specularColor += pow( direction, shiny ) * sunColor * spec;
132:    diffuseColor += max( dot( sunDirection, surfaceNormal ), 0.0 ) * sunColor * diffuse;
133: }
134: #define PI 3.14159265359
135: #define PI2 6.28318530718
136: #define PI_HALF 1.5707963267949
137: #define RECIPROCAL_PI 0.31830988618
138: #define RECIPROCAL_PI2 0.15915494
139: #define LOG2 1.442695
140: #define EPSILON 1e-6
141: #define saturate(a) clamp( a, 0.0, 1.0 )
142: #define whiteCompliment(a) ( 1.0 - saturate( a ) )
143: float pow2( const in float x ) { return x*x; }
144: float pow3( const in float x ) { return x*x*x; }
145: float pow4( const in float x ) { float x2 = x*x; return x2*x2; }
146: float average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }
147: highp float rand( const in vec2 uv ) {
148:    const highp float a = 12.9898, b = 78.233, c = 43758.5453;
149:    highp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );
150:    return fract(sin(sn) * c);
151: }
152: struct IncidentLight {
153:    vec3 color;
154:    vec3 direction;
155:    bool visible;
156: };
157: struct ReflectedLight {
158:    vec3 directDiffuse;
159:    vec3 directSpecular;
160:    vec3 indirectDiffuse;
161:    vec3 indirectSpecular;
162: };
163: struct GeometricContext {
164:    vec3 position;
165:    vec3 normal;
166:    vec3 viewDir;
167: };
168: vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
169:    return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );
170: }
171: vec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {
172:    return normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );
173: }
174: vec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {
175:    float distance = dot( planeNormal, point - pointOnPlane );
176:    return - distance * planeNormal + point;
177: }
178: float sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {
179:    return sign( dot( point - pointOnPlane, planeNormal ) );
180: }
181: vec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {
182:    return lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;
183: }
184: mat3 transposeMat3( const in mat3 m ) {
185:    mat3 tmp;
186:    tmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );
187:    tmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );
188:    tmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );
189:    return tmp;
190: }
191: float linearToRelativeLuminance( const in vec3 color ) {
192:    vec3 weights = vec3( 0.2126, 0.7152, 0.0722 );
193:    return dot( weights, color.rgb );
194: }
195: 
196: vec3 packNormalToRGB( const in vec3 normal ) {
197:    return normalize( normal ) * 0.5 + 0.5;
198: }
199: vec3 unpackRGBToNormal( const in vec3 rgb ) {
200:    return 2.0 * rgb.xyz - 1.0;
201: }
202: const float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;
203: const vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256.,  256. );
204: const vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );
205: const float ShiftRight8 = 1. / 256.;
206: vec4 packDepthToRGBA( const in float v ) {
207:    vec4 r = vec4( fract( v * PackFactors ), v );
208:    r.yzw -= r.xyz * ShiftRight8;   return r * PackUpscale;
209: }
210: float unpackRGBAToDepth( const in vec4 v ) {
211:    return dot( v, UnpackFactors );
212: }
213: float viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {
214:    return ( viewZ + near ) / ( near - far );
215: }
216: float orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {
217:    return linearClipZ * ( near - far ) - near;
218: }
219: float viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {
220:    return (( near + viewZ ) * far ) / (( far - near ) * viewZ );
221: }
222: float perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {
223:    return ( near * far ) / ( ( far - near ) * invClipZ - far );
224: }
225: 
226: float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {
227:    if( decayExponent > 0.0 ) {
228: #if defined ( PHYSICALLY_CORRECT_LIGHTS )
229:        float distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );
230:        float maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );
231:        return distanceFalloff * maxDistanceCutoffFactor;
232: #else
233:        return pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );
234: #endif
235:    }
236:    return 1.0;
237: }
238: vec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {
239:    return RECIPROCAL_PI * diffuseColor;
240: }
241: vec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {
242:    float fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );
243:    return ( 1.0 - specularColor ) * fresnel + specularColor;
244: }
245: float G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {
246:    float a2 = pow2( alpha );
247:    float gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );
248:    float gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );
249:    return 1.0 / ( gl * gv );
250: }
251: float G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {
252:    float a2 = pow2( alpha );
253:    float gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );
254:    float gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );
255:    return 0.5 / max( gv + gl, EPSILON );
256: }
257: float D_GGX( const in float alpha, const in float dotNH ) {
258:    float a2 = pow2( alpha );
259:    float denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;
260:    return RECIPROCAL_PI * a2 / pow2( denom );
261: }
262: vec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {
263:    float alpha = pow2( roughness );
264:    vec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );
265:    float dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );
266:    float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );
267:    float dotNH = saturate( dot( geometry.normal, halfDir ) );
268:    float dotLH = saturate( dot( incidentLight.direction, halfDir ) );
269:    vec3 F = F_Schlick( specularColor, dotLH );
270:    float G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );
271:    float D = D_GGX( alpha, dotNH );
272:    return F * ( G * D );
273: }
274: vec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {
275:    const float LUT_SIZE  = 64.0;
276:    const float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;
277:    const float LUT_BIAS  = 0.5 / LUT_SIZE;
278:    float theta = acos( dot( N, V ) );
279:    vec2 uv = vec2(
280:        sqrt( saturate( roughness ) ),
281:        saturate( theta / ( 0.5 * PI ) ) );
282:    uv = uv * LUT_SCALE + LUT_BIAS;
283:    return uv;
284: }
285: float LTC_ClippedSphereFormFactor( const in vec3 f ) {
286:    float l = length( f );
287:    return max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );
288: }
289: vec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {
290:    float x = dot( v1, v2 );
291:    float y = abs( x );
292:    float a = 0.86267 + (0.49788 + 0.01436 * y ) * y;
293:    float b = 3.45068 + (4.18814 + y) * y;
294:    float v = a / b;
295:    float theta_sintheta = (x > 0.0) ? v : 0.5 * inversesqrt( 1.0 - x * x ) - v;
296:    return cross( v1, v2 ) * theta_sintheta;
297: }
298: vec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {
299:    vec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];
300:    vec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];
301:    vec3 lightNormal = cross( v1, v2 );
302:    if( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );
303:    vec3 T1, T2;
304:    T1 = normalize( V - N * dot( V, N ) );
305:    T2 = - cross( N, T1 );
306:    mat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );
307:    vec3 coords[ 4 ];
308:    coords[ 0 ] = mat * ( rectCoords[ 0 ] - P );
309:    coords[ 1 ] = mat * ( rectCoords[ 1 ] - P );
310:    coords[ 2 ] = mat * ( rectCoords[ 2 ] - P );
311:    coords[ 3 ] = mat * ( rectCoords[ 3 ] - P );
312:    coords[ 0 ] = normalize( coords[ 0 ] );
313:    coords[ 1 ] = normalize( coords[ 1 ] );
314:    coords[ 2 ] = normalize( coords[ 2 ] );
315:    coords[ 3 ] = normalize( coords[ 3 ] );
316:    vec3 vectorFormFactor = vec3( 0.0 );
317:    vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );
318:    vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );
319:    vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );
320:    vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );
321:    vec3 result = vec3( LTC_ClippedSphereFormFactor( vectorFormFactor ) );
322:    return result;
323: }
324: vec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {
325:    float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );
326:    const vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );
327:    const vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );
328:    vec4 r = roughness * c0 + c1;
329:    float a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;
330:    vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;
331:    return specularColor * AB.x + AB.y;
332: }
333: float G_BlinnPhong_Implicit( ) {
334:    return 0.25;
335: }
336: float D_BlinnPhong( const in float shininess, const in float dotNH ) {
337:    return RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );
338: }
339: vec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {
340:    vec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );
341:    float dotNH = saturate( dot( geometry.normal, halfDir ) );
342:    float dotLH = saturate( dot( incidentLight.direction, halfDir ) );
343:    vec3 F = F_Schlick( specularColor, dotLH );
344:    float G = G_BlinnPhong_Implicit( );
345:    float D = D_BlinnPhong( shininess, dotNH );
346:    return F * ( G * D );
347: }
348: float GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {
349:    return ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );
350: }
351: float BlinnExponentToGGXRoughness( const in float blinnExponent ) {
352:    return sqrt( 2.0 / ( blinnExponent + 2.0 ) );
353: }
354: 
355: #ifdef USE_FOG
356:    uniform vec3 fogColor;
357:    varying float fogDepth;
358:    #ifdef FOG_EXP2
359:        uniform float fogDensity;
360:    #else
361:        uniform float fogNear;
362:        uniform float fogFar;
363:    #endif
364: #endif
365: 
366: uniform vec3 ambientLightColor;
367: vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {
368:    vec3 irradiance = ambientLightColor;
369:    #ifndef PHYSICALLY_CORRECT_LIGHTS
370:        irradiance *= PI;
371:    #endif
372:    return irradiance;
373: }
374: #if 1 > 0
375:    struct DirectionalLight {
376:        vec3 direction;
377:        vec3 color;
378:        int shadow;
379:        float shadowBias;
380:        float shadowRadius;
381:        vec2 shadowMapSize;
382:    };
383:    uniform DirectionalLight directionalLights[ 1 ];
384:    void getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {
385:        directLight.color = directionalLight.color;
386:        directLight.direction = directionalLight.direction;
387:        directLight.visible = true;
388:    }
389: #endif
390: #if 0 > 0
391:    struct PointLight {
392:        vec3 position;
393:        vec3 color;
394:        float distance;
395:        float decay;
396:        int shadow;
397:        float shadowBias;
398:        float shadowRadius;
399:        vec2 shadowMapSize;
400:        float shadowCameraNear;
401:        float shadowCameraFar;
402:    };
403:    uniform PointLight pointLights[ 0 ];
404:    void getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {
405:        vec3 lVector = pointLight.position - geometry.position;
406:        directLight.direction = normalize( lVector );
407:        float lightDistance = length( lVector );
408:        directLight.color = pointLight.color;
409:        directLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );
410:        directLight.visible = ( directLight.color != vec3( 0.0 ) );
411:    }
412: #endif
413: #if 0 > 0
414:    struct SpotLight {
415:        vec3 position;
416:        vec3 direction;
417:        vec3 color;
418:        float distance;
419:        float decay;
420:        float coneCos;
421:        float penumbraCos;
422:        int shadow;
423:        float shadowBias;
424:        float shadowRadius;
425:        vec2 shadowMapSize;
426:    };
427:    uniform SpotLight spotLights[ 0 ];
428:    void getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight  ) {
429:        vec3 lVector = spotLight.position - geometry.position;
430:        directLight.direction = normalize( lVector );
431:        float lightDistance = length( lVector );
432:        float angleCos = dot( directLight.direction, spotLight.direction );
433:        if ( angleCos > spotLight.coneCos ) {
434:            float spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );
435:            directLight.color = spotLight.color;
436:            directLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );
437:            directLight.visible = true;
438:        } else {
439:            directLight.color = vec3( 0.0 );
440:            directLight.visible = false;
441:        }
442:    }
443: #endif
444: #if 0 > 0
445:    struct RectAreaLight {
446:        vec3 color;
447:        vec3 position;
448:        vec3 halfWidth;
449:        vec3 halfHeight;
450:    };
451:    uniform sampler2D ltcMat;   uniform sampler2D ltcMag;
452:    uniform RectAreaLight rectAreaLights[ 0 ];
453: #endif
454: #if 0 > 0
455:    struct HemisphereLight {
456:        vec3 direction;
457:        vec3 skyColor;
458:        vec3 groundColor;
459:    };
460:    uniform HemisphereLight hemisphereLights[ 0 ];
461:    vec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {
462:        float dotNL = dot( geometry.normal, hemiLight.direction );
463:        float hemiDiffuseWeight = 0.5 * dotNL + 0.5;
464:        vec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );
465:        #ifndef PHYSICALLY_CORRECT_LIGHTS
466:            irradiance *= PI;
467:        #endif
468:        return irradiance;
469:    }
470: #endif
471: #if defined( USE_ENVMAP ) && defined( PHYSICAL )
472:    vec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {
473:        vec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );
474:        #ifdef ENVMAP_TYPE_CUBE
475:            vec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );
476:            #ifdef TEXTURE_LOD_EXT
477:                vec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );
478:            #else
479:                vec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );
480:            #endif
481:            envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;
482:        #elif defined( ENVMAP_TYPE_CUBE_UV )
483:            vec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );
484:            vec4 envMapColor = textureCubeUV( queryVec, 1.0 );
485:        #else
486:            vec4 envMapColor = vec4( 0.0 );
487:        #endif
488:        return PI * envMapColor.rgb * envMapIntensity;
489:    }
490:    float getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {
491:        float maxMIPLevelScalar = float( maxMIPLevel );
492:        float desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );
493:        return clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );
494:    }
495:    vec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {
496:        #ifdef ENVMAP_MODE_REFLECTION
497:            vec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );
498:        #else
499:            vec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );
500:        #endif
501:        reflectVec = inverseTransformDirection( reflectVec, viewMatrix );
502:        float specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );
503:        #ifdef ENVMAP_TYPE_CUBE
504:            vec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );
505:            #ifdef TEXTURE_LOD_EXT
506:                vec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );
507:            #else
508:                vec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );
509:            #endif
510:            envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;
511:        #elif defined( ENVMAP_TYPE_CUBE_UV )
512:            vec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );
513:            vec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));
514:        #elif defined( ENVMAP_TYPE_EQUIREC )
515:            vec2 sampleUV;
516:            sampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;
517:            sampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;
518:            #ifdef TEXTURE_LOD_EXT
519:                vec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );
520:            #else
521:                vec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );
522:            #endif
523:            envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;
524:        #elif defined( ENVMAP_TYPE_SPHERE )
525:            vec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );
526:            #ifdef TEXTURE_LOD_EXT
527:                vec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );
528:            #else
529:                vec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );
530:            #endif
531:            envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;
532:        #endif
533:        return envMapColor.rgb * envMapIntensity;
534:    }
535: #endif
536: 
537: #ifdef USE_SHADOWMAP
538:    #if 1 > 0
539:        uniform sampler2D directionalShadowMap[ 1 ];
540:        varying vec4 vDirectionalShadowCoord[ 1 ];
541:    #endif
542:    #if 0 > 0
543:        uniform sampler2D spotShadowMap[ 0 ];
544:        varying vec4 vSpotShadowCoord[ 0 ];
545:    #endif
546:    #if 0 > 0
547:        uniform sampler2D pointShadowMap[ 0 ];
548:        varying vec4 vPointShadowCoord[ 0 ];
549:    #endif
550:    float texture2DCompare( sampler2D depths, vec2 uv, float compare ) {
551:        return step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );
552:    }
553:    float texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {
554:        const vec2 offset = vec2( 0.0, 1.0 );
555:        vec2 texelSize = vec2( 1.0 ) / size;
556:        vec2 centroidUV = floor( uv * size + 0.5 ) / size;
557:        float lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );
558:        float lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );
559:        float rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );
560:        float rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );
561:        vec2 f = fract( uv * size + 0.5 );
562:        float a = mix( lb, lt, f.y );
563:        float b = mix( rb, rt, f.y );
564:        float c = mix( a, b, f.x );
565:        return c;
566:    }
567:    float getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {
568:        float shadow = 1.0;
569:        shadowCoord.xyz /= shadowCoord.w;
570:        shadowCoord.z += shadowBias;
571:        bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );
572:        bool inFrustum = all( inFrustumVec );
573:        bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );
574:        bool frustumTest = all( frustumTestVec );
575:        if ( frustumTest ) {
576:        #if defined( SHADOWMAP_TYPE_PCF )
577:            vec2 texelSize = vec2( 1.0 ) / shadowMapSize;
578:            float dx0 = - texelSize.x * shadowRadius;
579:            float dy0 = - texelSize.y * shadowRadius;
580:            float dx1 = + texelSize.x * shadowRadius;
581:            float dy1 = + texelSize.y * shadowRadius;
582:            shadow = (
583:                texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +
584:                texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +
585:                texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +
586:                texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +
587:                texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +
588:                texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +
589:                texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +
590:                texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +
591:                texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )
592:            ) * ( 1.0 / 9.0 );
593:        #elif defined( SHADOWMAP_TYPE_PCF_SOFT )
594:            vec2 texelSize = vec2( 1.0 ) / shadowMapSize;
595:            float dx0 = - texelSize.x * shadowRadius;
596:            float dy0 = - texelSize.y * shadowRadius;
597:            float dx1 = + texelSize.x * shadowRadius;
598:            float dy1 = + texelSize.y * shadowRadius;
599:            shadow = (
600:                texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +
601:                texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +
602:                texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +
603:                texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +
604:                texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +
605:                texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +
606:                texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +
607:                texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +
608:                texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )
609:            ) * ( 1.0 / 9.0 );
610:        #else
611:            shadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );
612:        #endif
613:        }
614:        return shadow;
615:    }
616:    vec2 cubeToUV( vec3 v, float texelSizeY ) {
617:        vec3 absV = abs( v );
618:        float scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );
619:        absV *= scaleToCube;
620:        v *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );
621:        vec2 planar = v.xy;
622:        float almostATexel = 1.5 * texelSizeY;
623:        float almostOne = 1.0 - almostATexel;
624:        if ( absV.z >= almostOne ) {
625:            if ( v.z > 0.0 )
626:                planar.x = 4.0 - v.x;
627:        } else if ( absV.x >= almostOne ) {
628:            float signX = sign( v.x );
629:            planar.x = v.z * signX + 2.0 * signX;
630:        } else if ( absV.y >= almostOne ) {
631:            float signY = sign( v.y );
632:            planar.x = v.x + 2.0 * signY + 2.0;
633:            planar.y = v.z * signY - 2.0;
634:        }
635:        return vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );
636:    }
637:    float getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {
638:        vec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );
639:        vec3 lightToPosition = shadowCoord.xyz;
640:        float dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );       dp += shadowBias;
641:        vec3 bd3D = normalize( lightToPosition );
642:        #if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )
643:            vec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;
644:            return (
645:                texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +
646:                texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +
647:                texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +
648:                texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +
649:                texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +
650:                texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +
651:                texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +
652:                texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +
653:                texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )
654:            ) * ( 1.0 / 9.0 );
655:        #else
656:            return texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );
657:        #endif
658:    }
659: #endif
660: 
661: float getShadowMask() {
662:    float shadow = 1.0;
663:    #ifdef USE_SHADOWMAP
664:    #if 1 > 0
665:    DirectionalLight directionalLight;
666:    for ( int i = 0; i < 1; i ++ ) {
667:        directionalLight = directionalLights[ i ];
668:        shadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;
669:    }
670:    #endif
671:    #if 0 > 0
672:    SpotLight spotLight;
673:    for ( int i = 0; i < 0; i ++ ) {
674:        spotLight = spotLights[ i ];
675:        shadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;
676:    }
677:    #endif
678:    #if 0 > 0
679:    PointLight pointLight;
680:    for ( int i = 0; i < 0; i ++ ) {
681:        pointLight = pointLights[ i ];
682:        shadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;
683:    }
684:    #endif
685:    #endif
686:    return shadow;
687: }
688: 
689: void main() {
690:    vec4 noise = getNoise( worldPosition.xz * size );
691:    vec3 surfaceNormal = normalize( noise.xzy * vec3( 1.5, 1.0, 1.5 ) );
692:    vec3 diffuseLight = vec3(0.0);
693:    vec3 specularLight = vec3(0.0);
694:    vec3 worldToEye = eye-worldPosition.xyz;
695:    vec3 eyeDirection = normalize( worldToEye );
696:    sunLight( surfaceNormal, eyeDirection, 100.0, 2.0, 0.5, diffuseLight, specularLight );
697:    float distance = length(worldToEye);
698:    vec2 distortion = surfaceNormal.xz * ( 0.001 + 1.0 / distance ) * distortionScale;
699:    vec3 reflectionSample = vec3( texture2D( mirrorSampler, mirrorCoord.xy / mirrorCoord.z + distortion ) );
700:    float theta = max( dot( eyeDirection, surfaceNormal ), 0.0 );
701:    float rf0 = 0.3;
702:    float reflectance = rf0 + ( 1.0 - rf0 ) * pow( ( 1.0 - theta ), 5.0 );
703:    vec3 scatter = max( 0.0, dot( surfaceNormal, eyeDirection ) ) * waterColor;
704:    vec3 albedo = mix( ( sunColor * diffuseLight * 0.3 + scatter ) * getShadowMask(), ( vec3( 0.1 ) + reflectionSample * 0.9 + reflectionSample * specularLight ), reflectance);
705:    vec3 outgoingLight = albedo;
706:    gl_FragColor = vec4( outgoingLight, alpha );
707: #if defined( TONE_MAPPING )
708:   gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );
709: #endif
710: 
711: #ifdef USE_FOG
712:    #ifdef FOG_EXP2
713:        float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );
714:    #else
715:        float fogFactor = smoothstep( fogNear, fogFar, fogDepth );
716:    #endif
717:    gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );
718: #endif
719: 
720: }

μƒμˆ˜κ°€ μ•„λ‹Œ μ‹μœΌλ‘œ μΈλ±μ‹±λ˜λŠ” μœ μΌν•œ μƒ˜ν”ŒλŸ¬λŠ” 668 ν–‰μ˜ directionalShadowMap 것 κ°™μŠ΅λ‹ˆλ‹€. 0:102(109) μ°Έμ‘°ν•˜λŠ” 이유λ₯Ό λͺ¨λ¦…λ‹ˆλ‹€.

668: shadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;

λ‹€λ₯Έ 그림자 맡 μ˜ˆμ œκ°€ μž‘λ™ν•©λ‹ˆλ‹€. THREE.Water νŠΉμ • 쑰각 μ…°μ΄λ”λ‘œ λ­”κ°€λ₯Όν•΄μ•Όν•©λ‹ˆλ‹€ ...

같은 κ²°λ‘ . λ˜ν•œ 보이지 μ•ŠλŠ” 쀄 2의 en ν™•μž₯에 λŒ€ν•œ κ²½κ³ λ₯Όλ³΄κ³ ν•˜λ―€λ‘œ 기둝 된 λ‹€λ₯Έ μ½”λ“œλ₯Ό μ°Έμ‘° ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

그런데 https://github.com/mrdoob/three.js/issues/6115 μ—μ„œμ™€ λ™μΌν•œ 문제

@moraxyκ°€ μ–ΈκΈ‰ν•˜κ³  λ¬Έμ œκ°€ μ•”μ‹œν•˜λŠ” κ²ƒμ²˜λŸΌ water.receiveShadow = true λ₯Ό μ œκ±°ν•˜λ©΄ μ–΄λ–»κ²Œλ©λ‹ˆκΉŒ?

κ·Έλ™μ•ˆ μ–΄λ–€ μ•„μ΄λ””μ–΄κ°€μžˆμ„ 경우λ₯Ό λŒ€λΉ„ν•˜μ—¬ 셰이더λ₯Ό 파고 μžˆμŠ΅λ‹ˆλ‹€.

μ˜ˆμ œμ—μ„œ water.receiveShadow = trueλ₯Ό μ œκ±°ν•˜λ©΄ μ–΄λ–»κ²Œλ©λ‹ˆκΉŒ?

그것은 문제λ₯Ό ν•΄κ²°ν•©λ‹ˆλ‹€.

@ Mugen87 μŠ€ν”ŒλΌμΈ νŽΈμ§‘κΈ° 예제 의 κ·Έλ¦Όμžκ°€ μž‘λ™ν•©λ‹ˆκΉŒ? (λ¬Ό μ…°μ΄λ”μ—μ„œ 그림자λ₯Ό μ–»κΈ° μœ„ν•΄ ShadowMaterial의 덩어리λ₯Ό λ³΅μ‚¬ν–ˆμŠ΅λ‹ˆλ‹€)

λ„€, webgl_geometry_spline_editor μž‘λ™ν•©λ‹ˆλ‹€.

이 두 μ˜ˆμ œμ—μ„œ λ™μΌν•œ shadowmask_pars_fragment 청크가 두 개의 λ‹€λ₯Έ getShadowMask ν•¨μˆ˜λ₯Ό 좜λ ₯ν•˜λŠ” μ΄μœ λŠ” λ¬΄μ—‡μž…λ‹ˆκΉŒ? μ›Œν„° μ…°μ΄λ”μ—λŠ” μƒ˜ν”ŒλŸ¬ λ°°μ—΄μ—μ„œ μƒμˆ˜κ°€ μ•„λ‹Œ μš©λ„λ‘œ for 루프가 μžˆμ§€λ§Œ μŠ€ν”ŒλΌμΈ νŽΈμ§‘κΈ° 예제의 ShadowMaterial ν”„λ‘œκ·Έλž¨μ—μ„œλŠ” λ‹€μŒκ³Ό 같이 μ‚¬μš©ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.getShadowMask

루프 ν’€κΈ°? λ£¨ν”„λ§ˆλ‹€ κ°•μ œλ‘œ ν™œμ„±ν™” / λΉ„ν™œμ„±ν™”ν•˜λŠ” ν”Œλž˜κ·Έ λ˜λŠ” μ§€μ‹œλ¬Έμ΄ μžˆμ–΄μ•Όν•©λ‹ˆλ‹€.

λ Œλ”λŸ¬κ°€ ShaderMaterial이 μ•„λ‹Œ λ‚΄μž₯ 재질 (Shadow 및 Lambert μž¬μ§ˆμ— μ‚¬μš©λ¨)의이 청크둜 λ‚΄λΆ€μ μœΌλ‘œ 루프 풀림을 λ‹¬μ„±ν•©λ‹ˆκΉŒ?

λ§žμŠ΅λ‹ˆλ‹€. https://github.com/mrdoob/three.js/blob/dev/src/renderers/webgl/WebGLProgram.js#L509 -L514λ₯Ό μ°Έμ‘°

μš°λ¦¬λŠ” 이것을 μ–΄λ–»κ²Œ μ²˜λ¦¬ν•©λ‹ˆκΉŒ?

쒋은 질문. μ»€μŠ€ν…€ 셰이더 머티리얼에 μ‘°λͺ… + 그림자λ₯Ό μ μš©ν•˜λŠ” 방법을 λ³΄μ—¬μ£ΌλŠ” 예제λ₯Ό μš”μ²­ν•œ μ‚¬μš©μžμ˜ κΈ°λŠ₯ μš”μ²­μ΄ μžˆμ—ˆλ˜ 것을 κΈ°μ–΅ν•©λ‹ˆλ‹€ (λΆˆν–‰νžˆλ„ μ§€κΈˆμ€ 문제λ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€). κ·ΈλŸ¬λ‚˜ 이것을 κ΅¬ν˜„ν•  λ•Œ λ™μΌν•œ 였λ₯˜κ°€ λ°œμƒν•©λ‹ˆλ‹€.

이 문제λ₯Ό ν•΄κ²°ν•˜λŠ” 방법을 잘 λͺ¨λ₯΄κ² μŠ΅λ‹ˆλ‹€. @mrdoob 및 @WestLangley κ°€ 문제λ₯Ό ν‰κ°€ν•˜λŠ” 방법을 κΈ°λ‹€λ¦½λ‹ˆλ‹€.

μ‚¬μš©μžλ‘œμ„œ 이것은 큰 μ§ˆλ¬Έμž…λ‹ˆλ‹€. GPGPU의 경우 ShaderMaterialκ³Ό ν•¨κ»˜ κ±°λŒ€ν•œ for 루프λ₯Ό μ‚¬μš©ν•  수 μžˆμ§€λ§Œ λ‹€λ₯Έ ν•œνŽΈμœΌλ‘œλŠ” 특수 μž¬μ§ˆμ„ λ””μžμΈν•˜λ €λŠ” 경우 μ΄λŸ¬ν•œ μ’…λ₯˜μ˜ 청크λ₯Ό μ‚¬μš©ν•  수 μžˆμ–΄μ•Όν•˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€. ShaderMaterial둜.

이 μƒνƒœλ₯Ό μœ μ§€ν•˜κ³  μ œκ±°ν•˜λ©΄ μ–΄λ”˜κ°€μ—μ„œ λ¬Έμ œκ°€ λ°œμƒν•˜λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€. @moraxy λŠ” ν”Œλž˜κ·Έλ₯Ό μ‚¬μš©ν•˜μ—¬ μ–ΈκΈ‰ν–ˆμŠ΅λ‹ˆλ‹€. 그러면 μœ μΌν•œ 좜ꡬ 문처럼 보일 κ²ƒμž…λ‹ˆλ‹€ ...? κ·ΈλŸ¬λ‚˜ 이것은 κ·Έλ•Œ μ†Œκ°œ ν•  νŠΉλ³„ν•œ μ •μ±…μž…λ‹ˆλ‹€.

이것은 λ˜ν•œ 셰이더λ₯Ό μ»€μŠ€ν„°λ§ˆμ΄μ§•ν•˜λŠ” 일반적인 λ¬Έμ œμž…λ‹ˆλ‹€. λͺ¨λ“  질문과 λ¬Έμ œκ°€ κ³„μ†λ˜κ³  μžˆμŠ΅λ‹ˆλ‹€ ... μ €λŠ” onBeforeCompile μ’‹μ•„ν•˜μ§€λ§Œ ShadowMaterialμ—μ„œμ΄λ₯Ό μ‚¬μš©ν•˜μ—¬ μ›Œν„° 셰이더λ₯Ό λ§Œλ“œλŠ” 것은 κΉŒλ‹€λ‘œμšΈ 수 μžˆμŠ΅λ‹ˆλ‹€. ... λ‹€λ₯Έ κ΄€λ ¨ μ§ˆλ¬Έμ„ ν•΄κ²°ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

λ‚˜λŠ” 당신이 이것을 ν•΄κ²°ν•˜κ²Œν•˜μ˜€μŠ΅λ‹ˆλ‹€ : μˆœμ§„ν•œ :

unrollLoops 속성을 ShaderMaterial μΆ”κ°€ν•΄ λ³Ό 수 μžˆμ„κΉŒμš”?

if ( material.isShaderMaterial === undefined || material.unrollLoops === true ) {

μ’‹μ•„μš”!

μ•„μŠ€νŠΈ 락

슀크린 샷을 κ²Œμ‹œ ν•œ 셰이더 μΈμŠ€νŽ™ν„°λŠ” λ¬΄μ—‡μž…λ‹ˆκΉŒ?

@pailhead Chrome 및 Firefox 용 ν™•μž₯으둜 μ‚¬μš©ν•  μˆ˜μžˆλŠ” WebGL Inspector μž…λ‹ˆλ‹€.

이 λ²„κ·ΈλŠ” 이제 # 13140을 톡해 μˆ˜μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 예이! πŸŽ‰ πŸ™Œ

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰