浏览代码

Examples: More usage of template strings. (#21816)

Michael Herzog 4 年之前
父节点
当前提交
415f35b9c7

+ 10 - 10
examples/jsm/nodes/accessors/CameraNode.js

@@ -203,23 +203,23 @@ class CameraNode extends TempNode {
 
 CameraNode.Nodes = ( function () {
 
-	const depthColor = new FunctionNode( [
-		'float depthColor( float mNear, float mFar ) {',
+	const depthColor = new FunctionNode( /* glsl */`
+		float depthColor( float mNear, float mFar ) {
 
-		'	#ifdef USE_LOGDEPTHBUF_EXT',
+			#ifdef USE_LOGDEPTHBUF_EXT
 
-		'		float depth = gl_FragDepthEXT / gl_FragCoord.w;',
+				float depth = gl_FragDepthEXT / gl_FragCoord.w;
 
-		'	#else',
+			#else
 
-		'		float depth = gl_FragCoord.z / gl_FragCoord.w;',
+				float depth = gl_FragCoord.z / gl_FragCoord.w;
 
-		'	#endif',
+			#endif
 
-		'	return 1.0 - smoothstep( mNear, mFar, depth );',
+			return 1.0 - smoothstep( mNear, mFar, depth );
 
-		'}'
-	].join( '\n' ) );
+		}`
+	 );
 
 	return {
 		depthColor: depthColor

+ 14 - 16
examples/jsm/nodes/core/NodeBuilder.js

@@ -75,29 +75,27 @@ class NodeBuilder {
 
 		this.attributes = {};
 
-		this.prefixCode = [
-			'#ifdef TEXTURE_LOD_EXT',
+		this.prefixCode = /* glsl */`
+			#ifdef TEXTURE_LOD_EXT
 
-			'	#define texCube(a, b) textureCube(a, b)',
-			'	#define texCubeBias(a, b, c) textureCubeLodEXT(a, b, c)',
+				#define texCube(a, b) textureCube(a, b)
+				#define texCubeBias(a, b, c) textureCubeLodEXT(a, b, c)
 
-			'	#define tex2D(a, b) texture2D(a, b)',
-			'	#define tex2DBias(a, b, c) texture2DLodEXT(a, b, c)',
+				#define tex2D(a, b) texture2D(a, b)
+				#define tex2DBias(a, b, c) texture2DLodEXT(a, b, c)
 
-			'#else',
+			#else
 
-			'	#define texCube(a, b) textureCube(a, b)',
-			'	#define texCubeBias(a, b, c) textureCube(a, b, c)',
+				#define texCube(a, b) textureCube(a, b)
+				#define texCubeBias(a, b, c) textureCube(a, b, c)
 
-			'	#define tex2D(a, b) texture2D(a, b)',
-			'	#define tex2DBias(a, b, c) texture2D(a, b, c)',
+				#define tex2D(a, b) texture2D(a, b)
+				#define tex2DBias(a, b, c) texture2D(a, b, c)
 
-			'#endif',
+			#endif
 
-			'#include <packing>',
-			'#include <common>'
-
-		].join( '\n' );
+			#include <packing>
+			#include <common>`;
 
 		this.parsCode = {
 			vertex: '',

+ 31 - 31
examples/jsm/nodes/effects/BlurNode.js

@@ -126,37 +126,37 @@ class BlurNode extends TempNode {
 
 BlurNode.Nodes = ( function () {
 
-	const blurX = new FunctionNode( [
-		'vec4 blurX( sampler2D tex, vec2 uv, float s ) {',
-		'	vec4 sum = vec4( 0.0 );',
-		'	sum += texture2D( tex, vec2( uv.x - 4.0 * s, uv.y ) ) * 0.051;',
-		'	sum += texture2D( tex, vec2( uv.x - 3.0 * s, uv.y ) ) * 0.0918;',
-		'	sum += texture2D( tex, vec2( uv.x - 2.0 * s, uv.y ) ) * 0.12245;',
-		'	sum += texture2D( tex, vec2( uv.x - 1.0 * s, uv.y ) ) * 0.1531;',
-		'	sum += texture2D( tex, vec2( uv.x, uv.y ) ) * 0.1633;',
-		'	sum += texture2D( tex, vec2( uv.x + 1.0 * s, uv.y ) ) * 0.1531;',
-		'	sum += texture2D( tex, vec2( uv.x + 2.0 * s, uv.y ) ) * 0.12245;',
-		'	sum += texture2D( tex, vec2( uv.x + 3.0 * s, uv.y ) ) * 0.0918;',
-		'	sum += texture2D( tex, vec2( uv.x + 4.0 * s, uv.y ) ) * 0.051;',
-		'	return sum * .667;',
-		'}'
-	].join( '\n' ) );
-
-	const blurY = new FunctionNode( [
-		'vec4 blurY( sampler2D tex, vec2 uv, float s ) {',
-		'	vec4 sum = vec4( 0.0 );',
-		'	sum += texture2D( tex, vec2( uv.x, uv.y - 4.0 * s ) ) * 0.051;',
-		'	sum += texture2D( tex, vec2( uv.x, uv.y - 3.0 * s ) ) * 0.0918;',
-		'	sum += texture2D( tex, vec2( uv.x, uv.y - 2.0 * s ) ) * 0.12245;',
-		'	sum += texture2D( tex, vec2( uv.x, uv.y - 1.0 * s ) ) * 0.1531;',
-		'	sum += texture2D( tex, vec2( uv.x, uv.y ) ) * 0.1633;',
-		'	sum += texture2D( tex, vec2( uv.x, uv.y + 1.0 * s ) ) * 0.1531;',
-		'	sum += texture2D( tex, vec2( uv.x, uv.y + 2.0 * s ) ) * 0.12245;',
-		'	sum += texture2D( tex, vec2( uv.x, uv.y + 3.0 * s ) ) * 0.0918;',
-		'	sum += texture2D( tex, vec2( uv.x, uv.y + 4.0 * s ) ) * 0.051;',
-		'	return sum * .667;',
-		'}'
-	].join( '\n' ) );
+	const blurX = new FunctionNode( /* glsl */`
+		vec4 blurX( sampler2D tex, vec2 uv, float s ) {
+			vec4 sum = vec4( 0.0 );
+			sum += texture2D( tex, vec2( uv.x - 4.0 * s, uv.y ) ) * 0.051;
+			sum += texture2D( tex, vec2( uv.x - 3.0 * s, uv.y ) ) * 0.0918;
+			sum += texture2D( tex, vec2( uv.x - 2.0 * s, uv.y ) ) * 0.12245;
+			sum += texture2D( tex, vec2( uv.x - 1.0 * s, uv.y ) ) * 0.1531;
+			sum += texture2D( tex, vec2( uv.x, uv.y ) ) * 0.1633;
+			sum += texture2D( tex, vec2( uv.x + 1.0 * s, uv.y ) ) * 0.1531;
+			sum += texture2D( tex, vec2( uv.x + 2.0 * s, uv.y ) ) * 0.12245;
+			sum += texture2D( tex, vec2( uv.x + 3.0 * s, uv.y ) ) * 0.0918;
+			sum += texture2D( tex, vec2( uv.x + 4.0 * s, uv.y ) ) * 0.051;
+			return sum * .667;
+		}`
+	);
+
+	const blurY = new FunctionNode( /* glsl */`
+		vec4 blurY( sampler2D tex, vec2 uv, float s ) {
+			vec4 sum = vec4( 0.0 );
+			sum += texture2D( tex, vec2( uv.x, uv.y - 4.0 * s ) ) * 0.051;
+			sum += texture2D( tex, vec2( uv.x, uv.y - 3.0 * s ) ) * 0.0918;
+			sum += texture2D( tex, vec2( uv.x, uv.y - 2.0 * s ) ) * 0.12245;
+			sum += texture2D( tex, vec2( uv.x, uv.y - 1.0 * s ) ) * 0.1531;
+			sum += texture2D( tex, vec2( uv.x, uv.y ) ) * 0.1633;
+			sum += texture2D( tex, vec2( uv.x, uv.y + 1.0 * s ) ) * 0.1531;
+			sum += texture2D( tex, vec2( uv.x, uv.y + 2.0 * s ) ) * 0.12245;
+			sum += texture2D( tex, vec2( uv.x, uv.y + 3.0 * s ) ) * 0.0918;
+			sum += texture2D( tex, vec2( uv.x, uv.y + 4.0 * s ) ) * 0.051;
+			return sum * .667;
+		}`
+	 );
 
 	return {
 		blurX: blurX,

+ 29 - 26
examples/jsm/nodes/effects/ColorAdjustmentNode.js

@@ -76,46 +76,49 @@ class ColorAdjustmentNode extends TempNode {
 
 ColorAdjustmentNode.Nodes = ( function () {
 
-	const hue = new FunctionNode( [
-		'vec3 hue(vec3 rgb, float adjustment) {',
+	const hue = new FunctionNode( /* glsl */`
+		vec3 hue(vec3 rgb, float adjustment) {
 
-		'	const mat3 RGBtoYIQ = mat3(0.299, 0.587, 0.114, 0.595716, -0.274453, -0.321263, 0.211456, -0.522591, 0.311135);',
-		'	const mat3 YIQtoRGB = mat3(1.0, 0.9563, 0.6210, 1.0, -0.2721, -0.6474, 1.0, -1.107, 1.7046);',
+			const mat3 RGBtoYIQ = mat3(0.299, 0.587, 0.114, 0.595716, -0.274453, -0.321263, 0.211456, -0.522591, 0.311135);
+			const mat3 YIQtoRGB = mat3(1.0, 0.9563, 0.6210, 1.0, -0.2721, -0.6474, 1.0, -1.107, 1.7046);
 
-		'	vec3 yiq = RGBtoYIQ * rgb;',
+			vec3 yiq = RGBtoYIQ * rgb;
 
-		'	float hue = atan(yiq.z, yiq.y) + adjustment;',
-		'	float chroma = sqrt(yiq.z * yiq.z + yiq.y * yiq.y);',
+			float hue = atan(yiq.z, yiq.y) + adjustment;
+			float chroma = sqrt(yiq.z * yiq.z + yiq.y * yiq.y);
 
-		'	return YIQtoRGB * vec3(yiq.x, chroma * cos(hue), chroma * sin(hue));',
+			return YIQtoRGB * vec3(yiq.x, chroma * cos(hue), chroma * sin(hue));
 
-		'}'
-	].join( '\n' ) );
+		}`
+	);
 
-	const saturation = new FunctionNode( [
-		// Algorithm from Chapter 16 of OpenGL Shading Language
-		'vec3 saturation(vec3 rgb, float adjustment) {',
+	// Algorithm from Chapter 16 of OpenGL Shading Language
 
-		'	vec3 intensity = vec3( luminance( rgb ) );',
+	const saturation = new FunctionNode( /* glsl */`
+		vec3 saturation(vec3 rgb, float adjustment) {
 
-		'	return mix( intensity, rgb, adjustment );',
+			vec3 intensity = vec3( luminance( rgb ) );
 
-		'}'
-	].join( '\n' ), [ LuminanceNode.Nodes.luminance ] ); // include LuminanceNode function
+			return mix( intensity, rgb, adjustment );
 
-	const vibrance = new FunctionNode( [
-		// Shader by Evan Wallace adapted by @lo-th
-		'vec3 vibrance(vec3 rgb, float adjustment) {',
+		}`
+	, [ LuminanceNode.Nodes.luminance ] ); // include LuminanceNode function
 
-		'	float average = (rgb.r + rgb.g + rgb.b) / 3.0;',
+	// Shader by Evan Wallace adapted by @lo-th
 
-		'	float mx = max(rgb.r, max(rgb.g, rgb.b));',
-		'	float amt = (mx - average) * (-3.0 * adjustment);',
+	const vibrance = new FunctionNode( /* glsl */`
 
-		'	return mix(rgb.rgb, vec3(mx), amt);',
+		vec3 vibrance(vec3 rgb, float adjustment) {
 
-		'}'
-	].join( '\n' ) );
+			float average = (rgb.r + rgb.g + rgb.b) / 3.0;
+
+			float mx = max(rgb.r, max(rgb.g, rgb.b));
+			float amt = (mx - average) * (-3.0 * adjustment);
+
+			return mix(rgb.rgb, vec3(mx), amt);
+
+		}`
+	);
 
 	return {
 		hue: hue,

+ 8 - 6
examples/jsm/nodes/effects/LuminanceNode.js

@@ -52,14 +52,16 @@ LuminanceNode.Nodes = ( function () {
 
 	const LUMA = new ConstNode( 'vec3 LUMA vec3( 0.2125, 0.7154, 0.0721 )' );
 
-	const luminance = new FunctionNode( [
-		// Algorithm from Chapter 10 of Graphics Shaders
-		'float luminance( vec3 rgb ) {',
+	// Algorithm from Chapter 10 of Graphics Shaders
 
-		'	return dot( rgb, LUMA );',
+	const luminance = new FunctionNode( /* glsl */`
 
-		'}'
-	].join( '\n' ), [ LUMA ] );
+		float luminance( vec3 rgb ) {
+
+			return dot( rgb, LUMA );
+
+		}`
+	, [ LUMA ] );
 
 	return {
 		LUMA: LUMA,

+ 12 - 12
examples/jsm/nodes/materials/nodes/BasicNode.js

@@ -19,15 +19,15 @@ class BasicNode extends Node {
 
 			const position = this.position ? this.position.analyzeAndFlow( builder, 'v3', { cache: 'position' } ) : undefined;
 
-			builder.addParsCode( [
-				'varying vec3 vViewPosition;',
+			builder.addParsCode( /* glsl */`
+				varying vec3 vViewPosition;
 
-				'#ifndef FLAT_SHADED',
+				#ifndef FLAT_SHADED
 
-				' varying vec3 vNormal;',
+				 varying vec3 vNormal;
 
-				'#endif',
-			].join( '\n' ) );
+				#endif`
+			);
 
 			const output = [
 				'#include <beginnormal_vertex>',
@@ -82,15 +82,15 @@ class BasicNode extends Node {
 
 			builder.requires.transparent = alpha !== undefined;
 
-			builder.addParsCode( [
-				'varying vec3 vViewPosition;',
+			builder.addParsCode( /* glsl */`
+				varying vec3 vViewPosition;
 
-				'#ifndef FLAT_SHADED',
+				#ifndef FLAT_SHADED
 
-				' varying vec3 vNormal;',
+				 varying vec3 vNormal;
 
-				'#endif',
-			].join( '\n' ) );
+				#endif`
+			);
 
 			const output = [
 				// add before: prevent undeclared normal

+ 21 - 21
examples/jsm/nodes/materials/nodes/PhongNode.js

@@ -38,23 +38,23 @@ class PhongNode extends Node {
 
 			] ) );
 
-			builder.addParsCode( [
-				'varying vec3 vViewPosition;',
+			builder.addParsCode( /* glsl */`
+				varying vec3 vViewPosition;
 
-				'#ifndef FLAT_SHADED',
+				#ifndef FLAT_SHADED
 
-				'	varying vec3 vNormal;',
+					varying vec3 vNormal;
 
-				'#endif',
+				#endif
 
-				//"#include <encodings_pars_fragment>", // encoding functions
-				'#include <fog_pars_vertex>',
-				'#include <morphtarget_pars_vertex>',
-				'#include <skinning_pars_vertex>',
-				'#include <shadowmap_pars_vertex>',
-				'#include <logdepthbuf_pars_vertex>',
-				'#include <clipping_planes_pars_vertex>'
-			].join( '\n' ) );
+				//"#include <encodings_pars_fragment> // encoding functions
+				#include <fog_pars_vertex>
+				#include <morphtarget_pars_vertex>
+				#include <skinning_pars_vertex>
+				#include <shadowmap_pars_vertex>
+				#include <logdepthbuf_pars_vertex>
+				#include <clipping_planes_pars_vertex>`
+			);
 
 			const output = [
 				'#include <beginnormal_vertex>',
@@ -146,14 +146,14 @@ class PhongNode extends Node {
 
 			builder.requires.transparent = alpha !== undefined;
 
-			builder.addParsCode( [
-				'#include <fog_pars_fragment>',
-				'#include <bsdfs>',
-				'#include <lights_pars_begin>',
-				'#include <lights_phong_pars_fragment>',
-				'#include <shadowmap_pars_fragment>',
-				'#include <logdepthbuf_pars_fragment>'
-			].join( '\n' ) );
+			builder.addParsCode( /* glsl */`
+				#include <fog_pars_fragment>
+				#include <bsdfs>
+				#include <lights_pars_begin>
+				#include <lights_phong_pars_fragment>
+				#include <shadowmap_pars_fragment>
+				#include <logdepthbuf_pars_fragment>`
+			);
 
 			const output = [
 				// prevent undeclared normal

+ 14 - 14
examples/jsm/nodes/materials/nodes/SpriteNode.js

@@ -34,11 +34,11 @@ class SpriteNode extends Node {
 				UniformsLib.fog
 			] ) );
 
-			builder.addParsCode( [
-				'#include <fog_pars_vertex>',
-				'#include <logdepthbuf_pars_vertex>',
-				'#include <clipping_planes_pars_vertex>'
-			].join( '\n' ) );
+			builder.addParsCode( /* glsl */`
+				#include <fog_pars_vertex>
+				#include <logdepthbuf_pars_vertex>
+				#include <clipping_planes_pars_vertex>`
+			);
 
 			output = [
 				'#include <clipping_planes_fragment>',
@@ -109,16 +109,16 @@ class SpriteNode extends Node {
 
 		} else {
 
-			builder.addParsCode( [
-				'#include <fog_pars_fragment>',
-				'#include <logdepthbuf_pars_fragment>',
-				'#include <clipping_planes_pars_fragment>'
-			].join( '\n' ) );
+			builder.addParsCode( /* glsl */`
+				#include <fog_pars_fragment>
+				#include <logdepthbuf_pars_fragment>
+				#include <clipping_planes_pars_fragment>`
+			);
 
-			builder.addCode( [
-				'#include <clipping_planes_fragment>',
-				'#include <logdepthbuf_fragment>'
-			].join( '\n' ) );
+			builder.addCode( /* glsl */`
+				#include <clipping_planes_fragment>
+				#include <logdepthbuf_fragment>`
+			);
 
 			// analyze all nodes to reuse generate codes
 

+ 26 - 26
examples/jsm/nodes/materials/nodes/StandardNode.js

@@ -60,24 +60,24 @@ class StandardNode extends Node {
 
 			}
 
-			builder.addParsCode( [
-				'varying vec3 vViewPosition;',
+			builder.addParsCode( /* glsl */`
+				varying vec3 vViewPosition;
 
-				'#ifndef FLAT_SHADED',
+				#ifndef FLAT_SHADED
 
-				'	varying vec3 vNormal;',
+					varying vec3 vNormal;
 
-				'#endif',
+				#endif
 
-				//"#include <encodings_pars_fragment>", // encoding functions
-				'#include <fog_pars_vertex>',
-				'#include <morphtarget_pars_vertex>',
-				'#include <skinning_pars_vertex>',
-				'#include <shadowmap_pars_vertex>',
-				'#include <logdepthbuf_pars_vertex>',
-				'#include <clipping_planes_pars_vertex>'
+				//"#include <encodings_pars_fragment> // encoding functions
+				#include <fog_pars_vertex>
+				#include <morphtarget_pars_vertex>
+				#include <skinning_pars_vertex>
+				#include <shadowmap_pars_vertex>
+				#include <logdepthbuf_pars_vertex>
+				#include <clipping_planes_pars_vertex>`
 
-			].join( '\n' ) );
+			);
 
 			const output = [
 				'#include <beginnormal_vertex>',
@@ -234,23 +234,23 @@ class StandardNode extends Node {
 
 			builder.requires.transparent = alpha !== undefined;
 
-			builder.addParsCode( [
-				'varying vec3 vViewPosition;',
+			builder.addParsCode( /* glsl */`
+				varying vec3 vViewPosition;
 
-				'#ifndef FLAT_SHADED',
+				#ifndef FLAT_SHADED
 
-				'	varying vec3 vNormal;',
+					varying vec3 vNormal;
 
-				'#endif',
+				#endif
 
-				'#include <dithering_pars_fragment>',
-				'#include <fog_pars_fragment>',
-				'#include <bsdfs>',
-				'#include <lights_pars_begin>',
-				'#include <lights_physical_pars_fragment>',
-				'#include <shadowmap_pars_fragment>',
-				'#include <logdepthbuf_pars_fragment>'
-			].join( '\n' ) );
+				#include <dithering_pars_fragment>
+				#include <fog_pars_fragment>
+				#include <bsdfs>
+				#include <lights_pars_begin>
+				#include <lights_physical_pars_fragment>
+				#include <shadowmap_pars_fragment>
+				#include <logdepthbuf_pars_fragment>`
+			);
 
 			const output = [
 				'#include <clipping_planes_fragment>',

+ 36 - 40
examples/jsm/nodes/misc/BumpMapNode.js

@@ -89,69 +89,65 @@ class BumpMapNode extends TempNode {
 
 BumpMapNode.Nodes = ( function () {
 
-	const dHdxy_fwd = new FunctionNode( [
+	// Bump Mapping Unparametrized Surfaces on the GPU by Morten S. Mikkelsen
+	// http://api.unrealengine.com/attachments/Engine/Rendering/LightingAndShadows/BumpMappingWithoutTangentSpace/mm_sfgrad_bump.pdf
 
-		// Bump Mapping Unparametrized Surfaces on the GPU by Morten S. Mikkelsen
-		// http://api.unrealengine.com/attachments/Engine/Rendering/LightingAndShadows/BumpMappingWithoutTangentSpace/mm_sfgrad_bump.pdf
+	// Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)
 
-		// Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)
+	const dHdxy_fwd = new FunctionNode( /* glsl */`
 
-		'vec2 dHdxy_fwd( sampler2D bumpMap, vec2 vUv, float bumpScale ) {',
+		vec2 dHdxy_fwd( sampler2D bumpMap, vec2 vUv, float bumpScale ) {
 
-		// Workaround for Adreno 3XX dFd*( vec3 ) bug. See #9988
+			vec2 dSTdx = dFdx( vUv );
+			vec2 dSTdy = dFdy( vUv );
 
-		'	vec2 dSTdx = dFdx( vUv );',
-		'	vec2 dSTdy = dFdy( vUv );',
+			float Hll = bumpScale * texture2D( bumpMap, vUv ).x;
+			float dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;
+			float dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;
 
-		'	float Hll = bumpScale * texture2D( bumpMap, vUv ).x;',
-		'	float dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;',
-		'	float dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;',
+			return vec2( dBx, dBy );
 
-		'	return vec2( dBx, dBy );',
+		}`
 
-		'}'
+	, null, { derivatives: true } );
 
-	].join( '\n' ), null, { derivatives: true } );
+	const perturbNormalArb = new FunctionNode( /* glsl */`
 
-	const perturbNormalArb = new FunctionNode( [
+		vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {
 
-		'vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {',
+			vec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );
+			vec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );
+			vec3 vN = surf_norm; // normalized
 
-		// Workaround for Adreno 3XX dFd*( vec3 ) bug. See #9988
+			vec3 R1 = cross( vSigmaY, vN );
+			vec3 R2 = cross( vN, vSigmaX );
 
-		'	vec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );',
-		'	vec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );',
-		'	vec3 vN = surf_norm;', // normalized
+			float fDet = dot( vSigmaX, R1 );
 
-		'	vec3 R1 = cross( vSigmaY, vN );',
-		'	vec3 R2 = cross( vN, vSigmaX );',
+			fDet *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );
 
-		'	float fDet = dot( vSigmaX, R1 );',
+			vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );
 
-		'	fDet *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );',
+			return normalize( abs( fDet ) * surf_norm - vGrad );
 
-		'	vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );',
+		}`
 
-		'	return normalize( abs( fDet ) * surf_norm - vGrad );',
+	, [ dHdxy_fwd ], { derivatives: true } );
 
-		'}'
+	const bumpToNormal = new FunctionNode( /* glsl */`
+		vec3 bumpToNormal( sampler2D bumpMap, vec2 uv, float scale ) {
 
-	].join( '\n' ), [ dHdxy_fwd ], { derivatives: true } );
+			vec2 dSTdx = dFdx( uv );
+			vec2 dSTdy = dFdy( uv );
 
-	const bumpToNormal = new FunctionNode( [
-		'vec3 bumpToNormal( sampler2D bumpMap, vec2 uv, float scale ) {',
+			float Hll = texture2D( bumpMap, uv ).x;
+			float dBx = texture2D( bumpMap, uv + dSTdx ).x - Hll;
+			float dBy = texture2D( bumpMap, uv + dSTdy ).x - Hll;
 
-		'	vec2 dSTdx = dFdx( uv );',
-		'	vec2 dSTdy = dFdy( uv );',
+			return vec3( .5 - ( dBx * scale ), .5 - ( dBy * scale ), 1.0 );
 
-		'	float Hll = texture2D( bumpMap, uv ).x;',
-		'	float dBx = texture2D( bumpMap, uv + dSTdx ).x - Hll;',
-		'	float dBy = texture2D( bumpMap, uv + dSTdy ).x - Hll;',
-
-		'	return vec3( .5 - ( dBx * scale ), .5 - ( dBy * scale ), 1.0 );',
-
-		'}'
-	].join( '\n' ), null, { derivatives: true } );
+		}`
+	, null, { derivatives: true } );
 
 	return {
 		dHdxy_fwd: dHdxy_fwd,

+ 8 - 8
examples/jsm/nodes/procedural/CheckerNode.js

@@ -52,17 +52,17 @@ CheckerNode.Nodes = ( function () {
 
 	// https://github.com/mattdesl/glsl-checker/blob/master/index.glsl
 
-	const checker = new FunctionNode( [
-		'float checker( vec2 uv ) {',
+	const checker = new FunctionNode( /* glsl */`
+		float checker( vec2 uv ) {
 
-		'	float cx = floor( uv.x );',
-		'	float cy = floor( uv.y ); ',
-		'	float result = mod( cx + cy, 2.0 );',
+			float cx = floor( uv.x );
+			float cy = floor( uv.y );
+			float result = mod( cx + cy, 2.0 );
 
-		'	return sign( result );',
+			return sign( result );
 
-		'}'
-	].join( '\n' ) );
+		}`
+	);
 
 	return {
 		checker: checker

+ 86 - 87
examples/jsm/nodes/utils/ColorSpaceNode.js

@@ -108,107 +108,106 @@ ColorSpaceNode.Nodes = ( function () {
 
 	// For a discussion of what this is, please read this: http://lousodrome.net/blog/light/2013/05/26/gamma-correct-and-hdr-rendering-in-a-32-bits-buffer/
 
-	const LinearToLinear = new FunctionNode( [
-		'vec4 LinearToLinear( in vec4 value ) {',
+	const LinearToLinear = new FunctionNode( /* glsl */`
+		vec4 LinearToLinear( in vec4 value ) {
 
-		'	return value;',
+			return value;
 
-		'}'
-	].join( '\n' ) );
+		}`
+	);
 
-	const GammaToLinear = new FunctionNode( [
-		'vec4 GammaToLinear( in vec4 value, in float gammaFactor ) {',
+	const GammaToLinear = new FunctionNode( /* glsl */`
+		vec4 GammaToLinear( in vec4 value, in float gammaFactor ) {
 
-		'	return vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );',
+			return vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );
 
-		'}'
-	].join( '\n' ) );
+		}`
+	);
 
-	const LinearToGamma = new FunctionNode( [
-		'vec4 LinearToGamma( in vec4 value, in float gammaFactor ) {',
+	const LinearToGamma = new FunctionNode( /* glsl */`
+		vec4 LinearToGamma( in vec4 value, in float gammaFactor ) {
 
-		'	return vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );',
+			return vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );
 
-		'}'
-	].join( '\n' ) );
+		}`
+	);
 
-	const sRGBToLinear = new FunctionNode( [
-		'vec4 sRGBToLinear( in vec4 value ) {',
+	const sRGBToLinear = new FunctionNode( /* glsl */`
+		vec4 sRGBToLinear( in vec4 value ) {
 
-		'	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 );',
+			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 );
 
-		'}'
-	].join( '\n' ) );
+		}`
+	);
 
-	const LinearTosRGB = new FunctionNode( [
-		'vec4 LinearTosRGB( in vec4 value ) {',
+	const LinearTosRGB = new FunctionNode( /* glsl */`
+		vec4 LinearTosRGB( in vec4 value ) {
 
-		'	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 );',
+			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 );
 
-		'}'
-	].join( '\n' ) );
+		}`
+	);
 
-	const RGBEToLinear = new FunctionNode( [
-		'vec4 RGBEToLinear( in vec4 value ) {',
+	const RGBEToLinear = new FunctionNode( /* glsl */`
+		vec4 RGBEToLinear( in vec4 value ) {
 
-		'	return vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );',
+			return vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );
 
-		'}'
-	].join( '\n' ) );
+		}`
+	);
 
-	const LinearToRGBE = new FunctionNode( [
-		'vec4 LinearToRGBE( in vec4 value ) {',
+	const LinearToRGBE = new FunctionNode( /* glsl */`
+		vec4 LinearToRGBE( in vec4 value ) {
 
-		'	float maxComponent = max( max( value.r, value.g ), value.b );',
-		'	float fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );',
-		'	return vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );',
-		//  return vec4( value.brg, ( 3.0 + 128.0 ) / 256.0 );
+			float maxComponent = max( max( value.r, value.g ), value.b );
+			float fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );
+			return vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );
 
-		'}'
-	].join( '\n' ) );
+		}`
+	);
 
 	// reference: http://iwasbeingirony.blogspot.ca/2010/06/difference-between-rgbm-and-rgbd.html
 
-	const RGBMToLinear = new FunctionNode( [
-		'vec3 RGBMToLinear( in vec4 value, in float maxRange ) {',
+	const RGBMToLinear = new FunctionNode( /* glsl */`
+		vec3 RGBMToLinear( in vec4 value, in float maxRange ) {
 
-		'	return vec4( value.xyz * value.w * maxRange, 1.0 );',
+			return vec4( value.xyz * value.w * maxRange, 1.0 );
 
-		'}'
-	].join( '\n' ) );
+		}`
+	);
 
-	const LinearToRGBM = new FunctionNode( [
-		'vec3 LinearToRGBM( in vec4 value, in float maxRange ) {',
+	const LinearToRGBM = new FunctionNode( /* glsl */`
+		vec3 LinearToRGBM( in vec4 value, in float maxRange ) {
 
-		'	float maxRGB = max( value.x, max( value.g, value.b ) );',
-		'	float M      = clamp( maxRGB / maxRange, 0.0, 1.0 );',
-		'	M            = ceil( M * 255.0 ) / 255.0;',
-		'	return vec4( value.rgb / ( M * maxRange ), M );',
+			float maxRGB = max( value.x, max( value.g, value.b ) );
+			float M      = clamp( maxRGB / maxRange, 0.0, 1.0 );
+			M            = ceil( M * 255.0 ) / 255.0;
+			return vec4( value.rgb / ( M * maxRange ), M );
 
-		'}'
-	].join( '\n' ) );
+		}`
+	);
 
 	// reference: http://iwasbeingirony.blogspot.ca/2010/06/difference-between-rgbm-and-rgbd.html
 
-	const RGBDToLinear = new FunctionNode( [
-		'vec3 RGBDToLinear( in vec4 value, in float maxRange ) {',
+	const RGBDToLinear = new FunctionNode( /* glsl */`
+		vec3 RGBDToLinear( in vec4 value, in float maxRange ) {
 
-		'	return vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );',
+			return vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );
 
-		'}'
-	].join( '\n' ) );
+		}`
+	);
 
 
-	const LinearToRGBD = new FunctionNode( [
-		'vec3 LinearToRGBD( in vec4 value, in float maxRange ) {',
+	const LinearToRGBD = new FunctionNode( /* glsl */`
+		vec3 LinearToRGBD( in vec4 value, in float maxRange ) {
 
-		'	float maxRGB = max( value.x, max( value.g, value.b ) );',
-		'	float D      = max( maxRange / maxRGB, 1.0 );',
-		'	D            = clamp( floor( D ) / 255.0, 0.0, 1.0 );',
-		'	return vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );',
+			float maxRGB = max( value.x, max( value.g, value.b ) );
+			float D      = max( maxRange / maxRGB, 1.0 );
+			D            = clamp( floor( D ) / 255.0, 0.0, 1.0 );
+			return vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );
 
-		'}'
-	].join( '\n' ) );
+		}`
+	);
 
 	// LogLuv reference: http://graphicrants.blogspot.ca/2009/04/rgbm-color-encoding.html
 
@@ -216,38 +215,38 @@ ColorSpaceNode.Nodes = ( function () {
 
 	const cLogLuvM = new ConstNode( 'const mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );' );
 
-	const LinearToLogLuv = new FunctionNode( [
-		'vec4 LinearToLogLuv( in vec4 value ) {',
+	const LinearToLogLuv = new FunctionNode( /* glsl */`
+		vec4 LinearToLogLuv( in vec4 value ) {
 
-		'	vec3 Xp_Y_XYZp = cLogLuvM * value.rgb;',
-		'	Xp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));',
-		'	vec4 vResult;',
-		'	vResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;',
-		'	float Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;',
-		'	vResult.w = fract(Le);',
-		'	vResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;',
-		'	return vResult;',
+			vec3 Xp_Y_XYZp = cLogLuvM * value.rgb;
+			Xp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));
+			vec4 vResult;
+			vResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;
+			float Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;
+			vResult.w = fract(Le);
+			vResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;
+			return vResult;
 
-		'}'
-	].join( '\n' ), [ cLogLuvM ] );
+		}`
+	, [ cLogLuvM ] );
 
 	// Inverse M matrix, for decoding
 
 	const cLogLuvInverseM = new ConstNode( 'const mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );' );
 
-	const LogLuvToLinear = new FunctionNode( [
-		'vec4 LogLuvToLinear( in vec4 value ) {',
+	const LogLuvToLinear = new FunctionNode( /* glsl */`
+		vec4 LogLuvToLinear( in vec4 value ) {
 
-		'	float Le = value.z * 255.0 + value.w;',
-		'	vec3 Xp_Y_XYZp;',
-		'	Xp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);',
-		'	Xp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;',
-		'	Xp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;',
-		'	vec3 vRGB = cLogLuvInverseM * Xp_Y_XYZp.rgb;',
-		'	return vec4( max(vRGB, 0.0), 1.0 );',
+			float Le = value.z * 255.0 + value.w;
+			vec3 Xp_Y_XYZp;
+			Xp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);
+			Xp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;
+			Xp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;
+			vec3 vRGB = cLogLuvInverseM * Xp_Y_XYZp.rgb;
+			return vec4( max(vRGB, 0.0), 1.0 );
 
-		'}'
-	].join( '\n' ), [ cLogLuvInverseM ] );
+		}`
+	, [ cLogLuvInverseM ] );
 
 	return {
 		LinearToLinear: LinearToLinear,

+ 10 - 9
examples/jsm/nodes/utils/SpecularMIPLevelNode.js

@@ -76,18 +76,19 @@ class SpecularMIPLevelNode extends TempNode {
 
 SpecularMIPLevelNode.Nodes = ( function () {
 
-	const getSpecularMIPLevel = new FunctionNode( [
-		// taken from here: http://casual-effects.blogspot.ca/2011/08/plausible-environment-lighting-in-two.html
-		'float getSpecularMIPLevel( const in float roughness, const in float maxMIPLevelScalar ) {',
+	// taken from here: http://casual-effects.blogspot.ca/2011/08/plausible-environment-lighting-in-two.html
 
-		'	float sigma = PI * roughness * roughness / ( 1.0 + roughness );',
-		'	float desiredMIPLevel = maxMIPLevelScalar + log2( sigma );',
+	const getSpecularMIPLevel = new FunctionNode( /* glsl */`
 
-		// clamp to allowable LOD ranges.
-		'	return clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );',
+		float getSpecularMIPLevel( const in float roughness, const in float maxMIPLevelScalar ) {
 
-		'}'
-	].join( '\n' ) );
+			float sigma = PI * roughness * roughness / ( 1.0 + roughness );
+			float desiredMIPLevel = maxMIPLevelScalar + log2( sigma );
+
+			return clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );
+
+		}`
+	);
 
 	return {
 		getSpecularMIPLevel: getSpecularMIPLevel