├── README.md
├── examples
├── images
│ ├── broken.jpg
│ ├── bw.png
│ ├── couch.png
│ ├── floral.jpg
│ ├── grass.png
│ ├── rough.jpg
│ ├── rust.jpg
│ └── scene.jpg
└── index.html
└── main.js
/README.md:
--------------------------------------------------------------------------------
1 | ## aframe-GLSL-component
2 |
3 | Aframe component to inject custom GLSL into the THREE.js MeshStandardMaterial Shader.
4 |
5 | 
6 |
7 | Have a look at the [example](https://pbayer8.github.io/aframe-glsl-component/examples/index.html)
8 |
9 | ### API
10 |
11 | | Property | Description | Default Value |
12 | | ---------- | ----------- | ------------- |
13 | |fragUniformsGLSL | selectorAll - selects the script tag to inject in the beggining of the fragment shader|#fragUniformsGLSL|
14 | |fragModsGLSL | selectorAll - selects the script tag to inject in main() of the fragment shader|#fragModsGLSL|
15 | |vertUniformsGLSL | selectorAll - selects the script tag to inject in the beggining of the vertex shader|#vertUniformsGLSL|
16 | |vertModsGLSL | selectorAll - selects the script tag to inject in main() of the fragment shader|#vertModsGLSL|
17 | Note: you can also set almost every property accessible in the [materials component](https://github.com/aframevr/aframe/blob/a46c1b133634de39e5f40c35bf28823a0960c7b5/docs/components/material.md)
18 |
19 | ### Installation
20 | Include as a `
23 | ```
24 |
25 | ### Usage
26 | Add the `glsl-standard` component to an entity with geometry. Note that it works better with more segments:
27 | ```
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
43 |
44 |
45 | ```
46 |
47 | Then, write GLSL. This component gives you access to two vec3 type variables you can modify:
48 | `finalPosition` in the vertex shader, and `finalColor` in the fragment shader.
49 | The component creates and updates two floats variables `time` (mS) and `seconds` that you can use,
50 | and a vec3 `objectNormal` that you can read and use when modifying the `finalPosition` variable.
51 | I've also included a small collection of noise and shaping functions.
52 | You can specify alternate script tags, otherwise it defaults to what is listed in the API section above:
53 | ```
54 |
59 |
66 |
71 |
76 | ```
77 |
78 | The result will look like:
79 |
80 | 
--------------------------------------------------------------------------------
/examples/images/broken.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pbayer8/aframe-glsl-component/2bac573e0c79e873f7b294c21f98e92f58026628/examples/images/broken.jpg
--------------------------------------------------------------------------------
/examples/images/bw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pbayer8/aframe-glsl-component/2bac573e0c79e873f7b294c21f98e92f58026628/examples/images/bw.png
--------------------------------------------------------------------------------
/examples/images/couch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pbayer8/aframe-glsl-component/2bac573e0c79e873f7b294c21f98e92f58026628/examples/images/couch.png
--------------------------------------------------------------------------------
/examples/images/floral.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pbayer8/aframe-glsl-component/2bac573e0c79e873f7b294c21f98e92f58026628/examples/images/floral.jpg
--------------------------------------------------------------------------------
/examples/images/grass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pbayer8/aframe-glsl-component/2bac573e0c79e873f7b294c21f98e92f58026628/examples/images/grass.png
--------------------------------------------------------------------------------
/examples/images/rough.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pbayer8/aframe-glsl-component/2bac573e0c79e873f7b294c21f98e92f58026628/examples/images/rough.jpg
--------------------------------------------------------------------------------
/examples/images/rust.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pbayer8/aframe-glsl-component/2bac573e0c79e873f7b294c21f98e92f58026628/examples/images/rust.jpg
--------------------------------------------------------------------------------
/examples/images/scene.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pbayer8/aframe-glsl-component/2bac573e0c79e873f7b294c21f98e92f58026628/examples/images/scene.jpg
--------------------------------------------------------------------------------
/examples/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Yippee Skippee
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
30 |
31 |
43 |
44 |
55 |
56 |
57 |
62 |
69 |
74 |
79 |
84 |
87 |
121 |
127 |
128 |
129 |
--------------------------------------------------------------------------------
/main.js:
--------------------------------------------------------------------------------
1 | let start = Date.now()
2 | AFRAME.registerComponent("glsl-standard", {
3 | schema: {
4 | //TODO mipmap/minfilter bug envmap wont blur with roughness)
5 | map: { type: "selector", default: null },
6 | normalMap: { type: "selector", default: null },
7 | envMap: { type: "selector", default: null },
8 | alphaMap: { type: "selector", default: null },
9 | aoMap: { type: "selector", default: null },
10 | lightMap: { type: "selector", default: null },
11 | emissiveMap: { type: "selector", default: null },
12 | bumpMap: { type: "selector", default: null },
13 | displacementMap: { type: "selector", default: null },
14 | roughnessMap: { type: "selector", default: null },
15 | metalnessMap: { type: "selector", default: null },
16 | diffuse: { type: "color", default: null },
17 | emissive: { type: "color", default: null },
18 | opacity: { type: "number", default: null },
19 | roughness: { type: "number", default: null },
20 | metalness: { type: "number", default: null },
21 | envMapIntensity: { type: "number", default: null },
22 | reflectivity: { type: "number", default: null },
23 | refractionRatio: { type: "number", default: null },
24 | aoMapIntensity: { type: "number", default: null },
25 | lightMapIntensity: { type: "number", default: null },
26 | bumpScale: { type: "number", default: null },
27 | normalScale: { type: "number", default: null },
28 | displacementScale: { type: "number", default: null },
29 | displacementBias: { type: "number", default: null },
30 | fragUniformsGLSL: { type: "selectorAll", default: "#fragUniformsGLSL" },
31 | fragModsGLSL: { type: "selectorAll", default: "#fragModsGLSL" },
32 | vertUniformsGLSL: { type: "selectorAll", default: "#vertUniformsGLSL" },
33 | vertModsGLSL: { type: "selectorAll", default: "#vertModsGLSL" }
34 | },
35 |
36 | init: function() {
37 | var standardShader = THREE.ShaderLib["standard"]
38 | this.uniforms = THREE.UniformsUtils.clone(THREE.UniformsUtils.merge([
39 | standardShader.uniforms,
40 | {
41 | time: { type: "f", value: 0.0 }
42 | //add new uniforms here
43 | }
44 | ]))
45 | let fragUniforms = []
46 | this.data.fragUniformsGLSL.forEach((el) => {
47 | fragUniforms.push(el.textContent)
48 | })
49 | let fragMods = []
50 | this.data.fragModsGLSL.forEach((el) => {
51 | fragMods.push(el.textContent)
52 | })
53 | let vertUniforms = []
54 | this.data.vertUniformsGLSL.forEach((el) => {
55 | vertUniforms.push(el.textContent)
56 | })
57 | let vertMods = []
58 | this.data.vertModsGLSL.forEach((el) => {
59 | vertMods.push(el.textContent)
60 | })
61 | this.material = this.el.getOrCreateObject3D("mesh").material = new THREE.ShaderMaterial({
62 | uniforms: this.uniforms,
63 | vertexShader: this.shaderFunctions + vertUniforms.join("\n") + this.vert1 + vertMods.join("\n") + this.vert2,
64 | fragmentShader: this.shaderFunctions + fragUniforms.join("\n") + this.frag1 + fragMods.join("\n") + this.frag2,
65 | lights: true,
66 | fog: true
67 | })
68 | for (var property in this.data) {
69 | if (this.data.hasOwnProperty(property) && this.data[property]) {
70 | if (property === "envMap") {
71 | let texture = new THREE.Texture(this.data[property])
72 | texture.mapping = THREE.EquirectangularReflectionMapping //TODO think of clean way to allow specifying maptype
73 | // texture.mipmaps[0] = texture.image //TODO figure out how to make this work
74 | // texture.generateMipmaps = true
75 | // texture.minFilter = THREE.LinearMipMapLinearFilter
76 | // texture.magFilter = THREE.LinearFilter
77 | texture.needsUpdate = true
78 | this.uniforms[property].value = texture
79 | this.material[property] = texture
80 | } else if (property.toLowerCase().endsWith("map")) {
81 | let texture = new THREE.Texture(this.data[property])
82 | texture.needsUpdate = true
83 | this.uniforms[property].value = texture
84 | this.material[property] = texture
85 | } else if (["emissive", "diffuse"].includes(property.toLowerCase())) {
86 | console.log(this.data[property])
87 | this.uniforms[property].value = new THREE.Color(this.data[property])
88 | } else if (!property.toLowerCase().endsWith("glsl")) {
89 | try {
90 | this.uniforms[property].value = this.data[property]
91 | } catch (er) {
92 | console.log(er)
93 | }
94 |
95 | }
96 | }
97 | }
98 | },
99 | tick: function() {
100 | this.uniforms.time.value = Date.now() - start // Updates this new value
101 | },
102 | vert1: `
103 | uniform float time;
104 | #define PHYSICAL
105 | varying vec3 vViewPosition;
106 | #ifndef FLAT_SHADED
107 | varying vec3 vNormal;
108 | #endif
109 | #include
110 | #include
111 | #include
112 | #include
113 | #include
114 | #include
115 | #include
116 | #include
117 | #include
118 | #include
119 | #include
120 | void main() {
121 | float seconds = time/1000.;
122 | #include
123 | #include
124 | #include
125 | #include
126 | #include
127 | #include
128 | #include
129 | #include
130 | #ifndef FLAT_SHADED // Normal computed with derivatives when FLAT_SHADED
131 | vNormal = normalize( transformedNormal );
132 | #endif
133 | #include
134 | #include
135 | #include
136 | #include
137 | vec3 finalPosition = transformed;`,
138 | vert2: `
139 | transformed = finalPosition;
140 | #include
141 | #include
142 | #include
143 | vViewPosition = - mvPosition.xyz;
144 | #include
145 | #include
146 | #include
147 | }`,
148 | frag1: `
149 | #define PHYSICAL
150 | uniform vec3 diffuse;
151 | uniform vec3 emissive;
152 | uniform float roughness;
153 | uniform float metalness;
154 | uniform float opacity;
155 | #ifndef STANDARD
156 | uniform float clearCoat;
157 | uniform float clearCoatRoughness;
158 | #endif
159 | varying vec3 vViewPosition;
160 | #ifndef FLAT_SHADED
161 | varying vec3 vNormal;
162 | #endif
163 | #include
164 | #include
165 | #include
166 | #include
167 | #include
168 | #include
169 | #include
170 | #include
171 | #include
172 | #include
173 | #include
174 | //#include
175 | #if defined( USE_ENVMAP ) || defined( PHYSICAL )
176 | uniform float reflectivity;
177 | uniform float envMapIntensity;
178 | #endif
179 | #ifdef USE_ENVMAP
180 | #if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )
181 | varying vec3 vWorldPosition;
182 | #endif
183 | #ifdef ENVMAP_TYPE_CUBE
184 | uniform samplerCube envMap;
185 | #else
186 | uniform sampler2D envMap;
187 | #endif
188 | uniform float flipEnvMap;
189 | uniform int maxMipLevel;
190 |
191 | #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )
192 | uniform float refractionRatio;
193 | #else
194 | varying vec3 vReflect;
195 | #endif
196 | #endif
197 | #include
198 | #include
199 | #include
200 | //#include
201 | //#include
202 | uniform vec3 ambientLightColor;
203 | vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {
204 | vec3 irradiance = ambientLightColor;
205 | #ifndef PHYSICALLY_CORRECT_LIGHTS
206 | irradiance *= PI;
207 | #endif
208 | return irradiance;
209 | }
210 | #if NUM_DIR_LIGHTS > 0
211 | struct DirectionalLight {
212 | vec3 direction;
213 | vec3 color;
214 | int shadow;
215 | float shadowBias;
216 | float shadowRadius;
217 | vec2 shadowMapSize;
218 | };
219 | uniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];
220 | void getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {
221 | directLight.color = directionalLight.color;
222 | directLight.direction = directionalLight.direction;
223 | directLight.visible = true;
224 | }
225 | #endif
226 | #if NUM_POINT_LIGHTS > 0
227 | struct PointLight {
228 | vec3 position;
229 | vec3 color;
230 | float distance;
231 | float decay;
232 | int shadow;
233 | float shadowBias;
234 | float shadowRadius;
235 | vec2 shadowMapSize;
236 | float shadowCameraNear;
237 | float shadowCameraFar;
238 | };
239 | uniform PointLight pointLights[ NUM_POINT_LIGHTS ];
240 | // directLight is an out parameter as having it as a return value caused compiler errors on some devices
241 | void getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {
242 | vec3 lVector = pointLight.position - geometry.position;
243 | directLight.direction = normalize( lVector );
244 | float lightDistance = length( lVector );
245 | directLight.color = pointLight.color;
246 | directLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );
247 | directLight.visible = ( directLight.color != vec3( 0.0 ) );
248 | }
249 | #endif
250 | #if NUM_SPOT_LIGHTS > 0
251 | struct SpotLight {
252 | vec3 position;
253 | vec3 direction;
254 | vec3 color;
255 | float distance;
256 | float decay;
257 | float coneCos;
258 | float penumbraCos;
259 | int shadow;
260 | float shadowBias;
261 | float shadowRadius;
262 | vec2 shadowMapSize;
263 | };
264 | uniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];
265 | // directLight is an out parameter as having it as a return value caused compiler errors on some devices
266 | void getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {
267 | vec3 lVector = spotLight.position - geometry.position;
268 | directLight.direction = normalize( lVector );
269 | float lightDistance = length( lVector );
270 | float angleCos = dot( directLight.direction, spotLight.direction );
271 | if ( angleCos > spotLight.coneCos ) {
272 | float spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );
273 | directLight.color = spotLight.color;
274 | directLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );
275 | directLight.visible = true;
276 | } else {
277 | directLight.color = vec3( 0.0 );
278 | directLight.visible = false;
279 | }
280 | }
281 | #endif
282 | #if NUM_RECT_AREA_LIGHTS > 0
283 | struct RectAreaLight {
284 | vec3 color;
285 | vec3 position;
286 | vec3 halfWidth;
287 | vec3 halfHeight;
288 | };
289 | // Pre-computed values of LinearTransformedCosine approximation of BRDF
290 | // BRDF approximation Texture is 64x64
291 | uniform sampler2D ltc_1; // RGBA Float
292 | uniform sampler2D ltc_2; // RGBA Float
293 | uniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];
294 | #endif
295 | #if NUM_HEMI_LIGHTS > 0
296 | struct HemisphereLight {
297 | vec3 direction;
298 | vec3 skyColor;
299 | vec3 groundColor;
300 | };
301 | uniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];
302 | vec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {
303 | float dotNL = dot( geometry.normal, hemiLight.direction );
304 | float hemiDiffuseWeight = 0.5 * dotNL + 0.5;
305 | vec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );
306 | #ifndef PHYSICALLY_CORRECT_LIGHTS
307 | irradiance *= PI;
308 | #endif
309 | return irradiance;
310 | }
311 | #endif
312 | #if defined( USE_ENVMAP ) && defined( PHYSICAL )
313 | vec3 getLightProbeIndirectIrradiance( /*const in SpecularLightProbe specularLightProbe,*/ const in GeometricContext geometry, const in int maxMIPLevel ) {
314 | vec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );
315 | #ifdef ENVMAP_TYPE_CUBE
316 | vec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );
317 | // TODO: replace with properly filtered cubemaps and access the irradiance LOD level, be it the last LOD level
318 | // of a specular cubemap, or just the default level of a specially created irradiance cubemap.
319 | #ifdef TEXTURE_LOD_EXT
320 | vec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );
321 | #else
322 | // force the bias high to get the last LOD level as it is the most blurred.
323 | vec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );
324 | #endif
325 | envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;
326 | #elif defined( ENVMAP_TYPE_CUBE_UV )
327 | vec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );
328 | vec4 envMapColor = textureCubeUV( queryVec, 1.0 );
329 | #else
330 | vec4 envMapColor = vec4( 0.0 );
331 | #endif
332 | return PI * envMapColor.rgb * envMapIntensity;
333 | }
334 | // taken from here: http://casual-effects.blogspot.ca/2011/08/plausible-environment-lighting-in-two.html
335 | float getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {
336 | //float envMapWidth = pow( 2.0, maxMIPLevelScalar );
337 | //float desiredMIPLevel = log2( envMapWidth * sqrt( 3.0 ) ) - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );
338 | float maxMIPLevelScalar = float( maxMIPLevel );
339 | float desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );
340 | // clamp to allowable LOD ranges.
341 | return clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );
342 | }
343 | vec3 getLightProbeIndirectRadiance( /*const in SpecularLightProbe specularLightProbe,*/ const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {
344 | #ifdef ENVMAP_MODE_REFLECTION
345 | vec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );
346 | #else
347 | vec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );
348 | #endif
349 | reflectVec = inverseTransformDirection( reflectVec, viewMatrix );
350 | float specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );
351 | #ifdef ENVMAP_TYPE_CUBE
352 | vec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );
353 | #ifdef TEXTURE_LOD_EXT
354 | vec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );
355 | #else
356 | vec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );
357 | #endif
358 | envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;
359 | #elif defined( ENVMAP_TYPE_CUBE_UV )
360 | vec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );
361 | vec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));
362 | #elif defined( ENVMAP_TYPE_EQUIREC )
363 | vec2 sampleUV;
364 | sampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;
365 | sampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;
366 | #ifdef TEXTURE_LOD_EXT
367 | vec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );
368 | #else
369 | vec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );
370 | #endif
371 | envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;
372 | #elif defined( ENVMAP_TYPE_SPHERE )
373 | vec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );
374 | #ifdef TEXTURE_LOD_EXT
375 | vec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );
376 | #else
377 | vec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );
378 | #endif
379 | envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;
380 | #endif
381 | return envMapColor.rgb * envMapIntensity;
382 | }
383 | #endif
384 | #include
385 | #include
386 | #include
387 | #include
388 | #include
389 | #include
390 | #include
391 | #include
392 | void main() {
393 | #include
394 | vec4 diffuseColor = vec4( diffuse, opacity );
395 | ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );
396 | vec3 totalEmissiveRadiance = emissive;
397 | #include
398 | #include
399 | #include
400 | #include
401 | #include
402 | #include
403 | #include
404 | // #include
405 | // #include
406 | #ifdef FLAT_SHADED
407 | // Workaround for Adreno/Nexus5 not able able to do dFdx( vViewPosition ) ...
408 | vec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );
409 | vec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );
410 | vec3 normal = normalize( cross( fdx, fdy ) );
411 | #else
412 | vec3 normal = normalize( vNormal );
413 | #ifdef DOUBLE_SIDED
414 | normal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );
415 | #endif
416 | #endif
417 | #ifdef USE_NORMALMAP
418 | normal = perturbNormal2Arb( -vViewPosition, normal );
419 | #elif defined( USE_BUMPMAP )
420 | normal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );
421 | #endif
422 | #include
423 | // accumulation
424 | #include
425 | // #include
426 | // #include
427 | // #include
428 | GeometricContext geometry;
429 | geometry.position = - vViewPosition;
430 | geometry.normal = normal;
431 | geometry.viewDir = normalize( vViewPosition );
432 | IncidentLight directLight;
433 | #if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )
434 | PointLight pointLight;
435 | #pragma unroll_loop
436 | for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {
437 | pointLight = pointLights[ i ];
438 | getPointDirectLightIrradiance( pointLight, geometry, directLight );
439 | #ifdef USE_SHADOWMAP
440 | directLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;
441 | #endif
442 | RE_Direct( directLight, geometry, material, reflectedLight );
443 | }
444 | #endif
445 | #if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )
446 | SpotLight spotLight;
447 | #pragma unroll_loop
448 | for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {
449 | spotLight = spotLights[ i ];
450 | getSpotDirectLightIrradiance( spotLight, geometry, directLight );
451 | #ifdef USE_SHADOWMAP
452 | directLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;
453 | #endif
454 | RE_Direct( directLight, geometry, material, reflectedLight );
455 | }
456 | #endif
457 | #if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )
458 | DirectionalLight directionalLight;
459 | #pragma unroll_loop
460 | for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {
461 | directionalLight = directionalLights[ i ];
462 | getDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );
463 | #ifdef USE_SHADOWMAP
464 | directLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;
465 | #endif
466 | RE_Direct( directLight, geometry, material, reflectedLight );
467 | }
468 | #endif
469 | #if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )
470 | RectAreaLight rectAreaLight;
471 | #pragma unroll_loop
472 | for ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {
473 | rectAreaLight = rectAreaLights[ i ];
474 | RE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );
475 | }
476 | #endif
477 | #if defined( RE_IndirectDiffuse )
478 | vec3 irradiance = getAmbientLightIrradiance( ambientLightColor );
479 | #if ( NUM_HEMI_LIGHTS > 0 )
480 | #pragma unroll_loop
481 | for ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {
482 | irradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );
483 | }
484 | #endif
485 | #endif
486 | #if defined( RE_IndirectSpecular )
487 | vec3 radiance = vec3( 0.0 );
488 | vec3 clearCoatRadiance = vec3( 0.0 );
489 | #endif
490 | #if defined( RE_IndirectDiffuse )
491 | #ifdef USE_LIGHTMAP
492 | vec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;
493 | #ifndef PHYSICALLY_CORRECT_LIGHTS
494 | lightMapIrradiance *= PI; // factor of PI should not be present; included here to prevent breakage
495 | #endif
496 | irradiance += lightMapIrradiance;
497 | #endif
498 | #if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )
499 | irradiance += getLightProbeIndirectIrradiance( /*lightProbe,*/ geometry, maxMipLevel );
500 | #endif
501 | #endif
502 | #if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )
503 | radiance += getLightProbeIndirectRadiance( /*specularLightProbe,*/ geometry, Material_BlinnShininessExponent( material ), maxMipLevel );
504 | #ifndef STANDARD
505 | clearCoatRadiance += getLightProbeIndirectRadiance( /*specularLightProbe,*/ geometry, Material_ClearCoat_BlinnShininessExponent( material ), maxMipLevel );
506 | #endif
507 | #endif
508 | #if defined( RE_IndirectDiffuse )
509 | RE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );
510 | #endif
511 | #if defined( RE_IndirectSpecular )
512 | RE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );
513 | #endif
514 | // modulation
515 | #include
516 | vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;
517 | vec3 finalColor = outgoingLight;
518 | `,
519 | frag2: `
520 | gl_FragColor = vec4( finalColor, diffuseColor.a );
521 | #include
522 | #include
523 | #include
524 | #include
525 | #include
526 | }
527 | `,
528 | shaderFunctions: `
529 | // Copyright (c) 2011 Stefan Gustavson. All rights reserved.
530 | // Distributed under the MIT license. See LICENSE file.
531 | // https://github.com/stegu/webgl-noise
532 | //
533 |
534 | vec3 mod289(vec3 x)
535 | {
536 | return x - floor(x * (1.0 / 289.0)) * 289.0;
537 | }
538 |
539 | vec4 mod289(vec4 x)
540 | {
541 | return x - floor(x * (1.0 / 289.0)) * 289.0;
542 | }
543 |
544 | vec4 permute(vec4 x)
545 | {
546 | return mod289(((x*34.0)+1.0)*x);
547 | }
548 |
549 | vec4 taylorInvSqrt(vec4 r)
550 | {
551 | return 1.79284291400159 - 0.85373472095314 * r;
552 | }
553 |
554 | vec3 fade(vec3 t) {
555 | return t*t*t*(t*(t*6.0-15.0)+10.0);
556 | }
557 |
558 | // Classic Perlin noise
559 | float cnoise(vec3 P)
560 | {
561 | vec3 Pi0 = floor(P); // Integer part for indexing
562 | vec3 Pi1 = Pi0 + vec3(1.0); // Integer part + 1
563 | Pi0 = mod289(Pi0);
564 | Pi1 = mod289(Pi1);
565 | vec3 Pf0 = fract(P); // Fractional part for interpolation
566 | vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0
567 | vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
568 | vec4 iy = vec4(Pi0.yy, Pi1.yy);
569 | vec4 iz0 = Pi0.zzzz;
570 | vec4 iz1 = Pi1.zzzz;
571 |
572 | vec4 ixy = permute(permute(ix) + iy);
573 | vec4 ixy0 = permute(ixy + iz0);
574 | vec4 ixy1 = permute(ixy + iz1);
575 |
576 | vec4 gx0 = ixy0 * (1.0 / 7.0);
577 | vec4 gy0 = fract(floor(gx0) * (1.0 / 7.0)) - 0.5;
578 | gx0 = fract(gx0);
579 | vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0);
580 | vec4 sz0 = step(gz0, vec4(0.0));
581 | gx0 -= sz0 * (step(0.0, gx0) - 0.5);
582 | gy0 -= sz0 * (step(0.0, gy0) - 0.5);
583 |
584 | vec4 gx1 = ixy1 * (1.0 / 7.0);
585 | vec4 gy1 = fract(floor(gx1) * (1.0 / 7.0)) - 0.5;
586 | gx1 = fract(gx1);
587 | vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1);
588 | vec4 sz1 = step(gz1, vec4(0.0));
589 | gx1 -= sz1 * (step(0.0, gx1) - 0.5);
590 | gy1 -= sz1 * (step(0.0, gy1) - 0.5);
591 |
592 | vec3 g000 = vec3(gx0.x,gy0.x,gz0.x);
593 | vec3 g100 = vec3(gx0.y,gy0.y,gz0.y);
594 | vec3 g010 = vec3(gx0.z,gy0.z,gz0.z);
595 | vec3 g110 = vec3(gx0.w,gy0.w,gz0.w);
596 | vec3 g001 = vec3(gx1.x,gy1.x,gz1.x);
597 | vec3 g101 = vec3(gx1.y,gy1.y,gz1.y);
598 | vec3 g011 = vec3(gx1.z,gy1.z,gz1.z);
599 | vec3 g111 = vec3(gx1.w,gy1.w,gz1.w);
600 |
601 | vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110)));
602 | g000 *= norm0.x;
603 | g010 *= norm0.y;
604 | g100 *= norm0.z;
605 | g110 *= norm0.w;
606 | vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111)));
607 | g001 *= norm1.x;
608 | g011 *= norm1.y;
609 | g101 *= norm1.z;
610 | g111 *= norm1.w;
611 |
612 | float n000 = dot(g000, Pf0);
613 | float n100 = dot(g100, vec3(Pf1.x, Pf0.yz));
614 | float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z));
615 | float n110 = dot(g110, vec3(Pf1.xy, Pf0.z));
616 | float n001 = dot(g001, vec3(Pf0.xy, Pf1.z));
617 | float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z));
618 | float n011 = dot(g011, vec3(Pf0.x, Pf1.yz));
619 | float n111 = dot(g111, Pf1);
620 |
621 | vec3 fade_xyz = fade(Pf0);
622 | vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z);
623 | vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y);
624 | float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x);
625 | return 2.2 * n_xyz;
626 | }
627 |
628 | // Classic Perlin noise, periodic variant
629 | float pnoise(vec3 P, vec3 rep)
630 | {
631 | vec3 Pi0 = mod(floor(P), rep); // Integer part, modulo period
632 | vec3 Pi1 = mod(Pi0 + vec3(1.0), rep); // Integer part + 1, mod period
633 | Pi0 = mod289(Pi0);
634 | Pi1 = mod289(Pi1);
635 | vec3 Pf0 = fract(P); // Fractional part for interpolation
636 | vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0
637 | vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
638 | vec4 iy = vec4(Pi0.yy, Pi1.yy);
639 | vec4 iz0 = Pi0.zzzz;
640 | vec4 iz1 = Pi1.zzzz;
641 |
642 | vec4 ixy = permute(permute(ix) + iy);
643 | vec4 ixy0 = permute(ixy + iz0);
644 | vec4 ixy1 = permute(ixy + iz1);
645 |
646 | vec4 gx0 = ixy0 * (1.0 / 7.0);
647 | vec4 gy0 = fract(floor(gx0) * (1.0 / 7.0)) - 0.5;
648 | gx0 = fract(gx0);
649 | vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0);
650 | vec4 sz0 = step(gz0, vec4(0.0));
651 | gx0 -= sz0 * (step(0.0, gx0) - 0.5);
652 | gy0 -= sz0 * (step(0.0, gy0) - 0.5);
653 |
654 | vec4 gx1 = ixy1 * (1.0 / 7.0);
655 | vec4 gy1 = fract(floor(gx1) * (1.0 / 7.0)) - 0.5;
656 | gx1 = fract(gx1);
657 | vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1);
658 | vec4 sz1 = step(gz1, vec4(0.0));
659 | gx1 -= sz1 * (step(0.0, gx1) - 0.5);
660 | gy1 -= sz1 * (step(0.0, gy1) - 0.5);
661 |
662 | vec3 g000 = vec3(gx0.x,gy0.x,gz0.x);
663 | vec3 g100 = vec3(gx0.y,gy0.y,gz0.y);
664 | vec3 g010 = vec3(gx0.z,gy0.z,gz0.z);
665 | vec3 g110 = vec3(gx0.w,gy0.w,gz0.w);
666 | vec3 g001 = vec3(gx1.x,gy1.x,gz1.x);
667 | vec3 g101 = vec3(gx1.y,gy1.y,gz1.y);
668 | vec3 g011 = vec3(gx1.z,gy1.z,gz1.z);
669 | vec3 g111 = vec3(gx1.w,gy1.w,gz1.w);
670 |
671 | vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110)));
672 | g000 *= norm0.x;
673 | g010 *= norm0.y;
674 | g100 *= norm0.z;
675 | g110 *= norm0.w;
676 | vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111)));
677 | g001 *= norm1.x;
678 | g011 *= norm1.y;
679 | g101 *= norm1.z;
680 | g111 *= norm1.w;
681 |
682 | float n000 = dot(g000, Pf0);
683 | float n100 = dot(g100, vec3(Pf1.x, Pf0.yz));
684 | float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z));
685 | float n110 = dot(g110, vec3(Pf1.xy, Pf0.z));
686 | float n001 = dot(g001, vec3(Pf0.xy, Pf1.z));
687 | float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z));
688 | float n011 = dot(g011, vec3(Pf0.x, Pf1.yz));
689 | float n111 = dot(g111, Pf1);
690 |
691 | vec3 fade_xyz = fade(Pf0);
692 | vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z);
693 | vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y);
694 | float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x);
695 | return 2.2 * n_xyz;
696 | }
697 |
698 | // Function from Iñigo Quiles
699 | // www.iquilezles.org/www/articles/functions/functions.htm
700 | float cubicPulse( float c, float w, float x ){
701 | x = abs(x - c);
702 | if( x>w ) return 0.0;
703 | x /= w;
704 | return 1.0 - x*x*(3.0-2.0*x);
705 | }
706 |
707 | //MEEEEE
708 | //cosine simlarity of vectors
709 | float cosSim(vec3 v1, vec3 v2){
710 | float d = dot(v1,v2);
711 | float m = length(v1)*length(v2);
712 | return abs(d/m);
713 | }
714 | // get perpendicular component
715 | vec3 perpComp(vec3 v1, vec3 v2){
716 | float d = dot(v1,v2);
717 | float m = d/pow(length(v1),2.);
718 | vec3 v = m*v1;
719 | return v2 - v;
720 |
721 | }
722 |
723 | vec3 rgb2hsb( in vec3 c ){
724 | vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
725 | vec4 p = mix(vec4(c.bg, K.wz),
726 | vec4(c.gb, K.xy),
727 | step(c.b, c.g));
728 | vec4 q = mix(vec4(p.xyw, c.r),
729 | vec4(c.r, p.yzx),
730 | step(p.x, c.r));
731 | float d = q.x - min(q.w, q.y);
732 | float e = 1.0e-10;
733 | return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)),
734 | d / (q.x + e),
735 | q.x);
736 | }
737 |
738 | // Function from Iñigo Quiles
739 | // https://www.shadertoy.com/view/MsS3Wc
740 | vec3 hsb2rgb( in vec3 c ){
741 | vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),
742 | 6.0)-3.0)-1.0,
743 | 0.0,
744 | 1.0 );
745 | rgb = rgb*rgb*(3.0-2.0*rgb);
746 | return c.z * mix(vec3(1.0), rgb, c.y);
747 | }
748 | mat3 xProduct(vec3 v){
749 | return mat3(0.,v.z,-v.y,-v.z,0.,v.x,v.y,-v.x,0);
750 | }
751 | mat3 outerProduct(vec3 u, vec3 v) {
752 | return mat3(u.x*v.x,u.y*v.x,u.z*v.x,
753 | u.x*v.y,u.y*v.y,u.z*v.y,
754 | u.x*v.z,u.y*v.z,u.z*v.z);
755 | }
756 | mat3 rotMatrix(float theta, vec3 v){
757 | v = normalize(v);
758 | mat3 vprod = xProduct(v);
759 | return mat3(cos(theta)) + sin(theta)*vprod + (1.-cos(theta)) * outerProduct(v,v);
760 | }
761 |
762 |
763 | vec2 random2( vec2 p ) {
764 | return fract(sin(vec2(dot(p,vec2(127.1,311.7)),dot(p,vec2(269.5,183.3))))*43758.5453);
765 | }
766 |
767 | float doubleExponentialSeat (float x, float a){
768 |
769 | float epsilon = 0.00001;
770 | float min_param_a = 0.0 + epsilon;
771 | float max_param_a = 1.0 - epsilon;
772 | a = min(max_param_a, max(min_param_a, a));
773 |
774 | float y = 0.;
775 | if (x<=0.5){
776 | y = (pow(2.0*x, 1.-a))/2.0;
777 | } else {
778 | y = 1.0 - (pow(2.0*(1.0-x), 1.-a))/2.0;
779 | }
780 | return y;
781 | }
782 |
783 | float logisticSigmoid (float x, float a){
784 | // n.b.: this Logistic Sigmoid has been normalized.
785 |
786 | float epsilon = 0.0001;
787 | float min_param_a = 0.0 + epsilon;
788 | float max_param_a = 1.0 - epsilon;
789 | a = max(min_param_a, min(max_param_a, a));
790 | a = (1./(1.-a) - 1.);
791 |
792 | float A = 1.0 / (1.0 + exp(0. -((x-0.5)*a*2.0)));
793 | float B = 1.0 / (1.0 + exp(a));
794 | float C = 1.0 / (1.0 + exp(0.-a));
795 | float y = (A-B)/(C-B);
796 | return y;
797 | }
798 | `
799 | })
800 |
--------------------------------------------------------------------------------