Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shader compile error with troika-3d-text #59

Closed
giulioz opened this issue Jun 9, 2020 · 14 comments
Closed

Shader compile error with troika-3d-text #59

giulioz opened this issue Jun 9, 2020 · 14 comments

Comments

@giulioz
Copy link

giulioz commented Jun 9, 2020

When using the 3d-text module I get this error. It seems that something is wrong with DerivedShader:

THREE.WebGLShader: gl.getShaderInfoLog() vertex
ERROR: 0:390: 'uTroikaSDFTextureSize' : redefinition
ERROR: 0:391: 'uTroikaSDFGlyphSize' : redefinition
ERROR: 0:392: 'uTroikaTotalBounds' : redefinition
ERROR: 0:393: 'uTroikaClipRect' : redefinition
ERROR: 0:394: 'uTroikaOrient' : redefinition
ERROR: 0:395: 'uTroikaUseGlyphColors' : redefinition
ERROR: 0:396: 'aTroikaGlyphBounds' : redefinition
ERROR: 0:397: 'aTroikaGlyphIndex' : redefinition
ERROR: 0:398: 'aTroikaGlyphColor' : redefinition
ERROR: 0:399: 'vTroikaSDFTextureUV' : redefinition
ERROR: 0:400: 'vTroikaGlyphUV' : redefinition
ERROR: 0:401: 'vTroikaGlyphColor' : redefinition
�1: precision highp float;
2: precision highp int;
3: #define HIGH_PRECISION
4: #define SHADER_NAME MeshBasicMaterial
5: #define TROIKA_DERIVED_MATERIAL 3
6: #define VERTEX_TEXTURES
7: #define GAMMA_FACTOR 2
8: #define MAX_BONES 0
9: #define BONE_TEXTURE
10: #define DOUBLE_SIDED
11: #define USE_LOGDEPTHBUF
12: #define USE_LOGDEPTHBUF_EXT
13: uniform mat4 modelMatrix;
14: uniform mat4 modelViewMatrix;
15: uniform mat4 projectionMatrix;
16: uniform mat4 viewMatrix;
17: uniform mat3 normalMatrix;
18: uniform vec3 cameraPosition;
19: uniform bool isOrthographic;
20: #ifdef USE_INSTANCING
21:  attribute mat4 instanceMatrix;
22: #endif
23: attribute vec3 position;
24: attribute vec3 normal;
25: attribute vec2 uv;
26: #ifdef USE_TANGENT
27: 	attribute vec4 tangent;
28: #endif
29: #ifdef USE_COLOR
30: 	attribute vec3 color;
31: #endif
32: #ifdef USE_MORPHTARGETS
33: 	attribute vec3 morphTarget0;
34: 	attribute vec3 morphTarget1;
35: 	attribute vec3 morphTarget2;
36: 	attribute vec3 morphTarget3;
37: 	#ifdef USE_MORPHNORMALS
38: 		attribute vec3 morphNormal0;
39: 		attribute vec3 morphNormal1;
40: 		attribute vec3 morphNormal2;
41: 		attribute vec3 morphNormal3;
42: 	#else
43: 		attribute vec3 morphTarget4;
44: 		attribute vec3 morphTarget5;
45: 		attribute vec3 morphTarget6;
46: 		attribute vec3 morphTarget7;
47: 	#endif
48: #endif
49: #ifdef USE_SKINNING
50: 	attribute vec4 skinIndex;
51: 	attribute vec4 skinWeight;
52: #endif
53: 
54: #define PI 3.14159265359
55: #define PI2 6.28318530718
56: #define PI_HALF 1.5707963267949
57: #define RECIPROCAL_PI 0.31830988618
58: #define RECIPROCAL_PI2 0.15915494
59: #define LOG2 1.442695
60: #define EPSILON 1e-6
61: #ifndef saturate
62: #define saturate(a) clamp( a, 0.0, 1.0 )
63: #endif
64: #define whiteComplement(a) ( 1.0 - saturate( a ) )
65: float pow2( const in float x ) { return x*x; }
66: float pow3( const in float x ) { return x*x*x; }
67: float pow4( const in float x ) { float x2 = x*x; return x2*x2; }
68: float average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }
69: highp float rand( const in vec2 troika_uv_1 ) {
70: 	const highp float a = 12.9898, b = 78.233, c = 43758.5453;
71: 	highp float dt = dot( troika_uv_1.xy, vec2( a,b ) ), sn = mod( dt, PI );
72: 	return fract(sin(sn) * c);
73: }
74: #ifdef HIGH_PRECISION
75: 	float precisionSafeLength( vec3 v ) { return length( v ); }
76: #else
77: 	float max3( vec3 v ) { return max( max( v.x, v.y ), v.z ); }
78: 	float precisionSafeLength( vec3 v ) {
79: 		float maxComponent = max3( abs( v ) );
80: 		return length( v / maxComponent ) * maxComponent;
81: 	}
82: #endif
83: struct IncidentLight {
84: 	vec3 color;
85: 	vec3 direction;
86: 	bool visible;
87: };
88: struct ReflectedLight {
89: 	vec3 directDiffuse;
90: 	vec3 directSpecular;
91: 	vec3 indirectDiffuse;
92: 	vec3 indirectSpecular;
93: };
94: struct GeometricContext {
95: 	vec3 troika_position_1;
96: 	vec3 troika_normal_1;
97: 	vec3 viewDir;
98: #ifdef CLEARCOAT
99: 	vec3 clearcoatNormal;
100: #endif
101: };
102: vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
103: 	return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );
104: }
105: vec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {
106: 	return normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );
107: }
108: vec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {
109: 	float distance = dot( planeNormal, point - pointOnPlane );
110: 	return - distance * planeNormal + point;
111: }
112: float sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {
113: 	return sign( dot( point - pointOnPlane, planeNormal ) );
114: }
115: vec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {
116: 	return lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;
117: }
118: mat3 transposeMat3( const in mat3 m ) {
119: 	mat3 tmp;
120: 	tmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );
121: 	tmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );
122: 	tmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );
123: 	return tmp;
124: }
125: float linearToRelativeLuminance( const in vec3 color ) {
126: 	vec3 weights = vec3( 0.2126, 0.7152, 0.0722 );
127: 	return dot( weights, color.rgb );
128: }
129: bool isPerspectiveMatrix( mat4 m ) {
130:   return m[ 2 ][ 3 ] == - 1.0;
131: }
132: #ifdef USE_UV
133: 	#ifdef UVS_VERTEX_ONLY
134: 		vec2 vUv;
135: 	#else
136: 		varying vec2 vUv;
137: 	#endif
138: 	uniform mat3 uvTransform;
139: #endif
140: #if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )
141: 	attribute vec2 uv2;
142: 	varying vec2 vUv2;
143: 	uniform mat3 uv2Transform;
144: #endif
145: #ifdef USE_ENVMAP
146: 	#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) ||defined( PHONG )
147: 		#define ENV_WORLDPOS
148: 	#endif
149: 	#ifdef ENV_WORLDPOS
150: 		
151: 		varying vec3 vWorldPosition;
152: 	#else
153: 		varying vec3 vReflect;
154: 		uniform float refractionRatio;
155: 	#endif
156: #endif
157: #ifdef USE_COLOR
158: 	varying vec3 vColor;
159: #endif
160: #ifdef USE_FOG
161: 	varying float fogDepth;
162: #endif
163: #ifdef USE_MORPHTARGETS
164: 	uniform float morphTargetBaseInfluence;
165: 	#ifndef USE_MORPHNORMALS
166: 	uniform float morphTargetInfluences[ 8 ];
167: 	#else
168: 	uniform float morphTargetInfluences[ 4 ];
169: 	#endif
170: #endif
171: #ifdef USE_SKINNING
172: 	uniform mat4 bindMatrix;
173: 	uniform mat4 bindMatrixInverse;
174: 	#ifdef BONE_TEXTURE
175: 		uniform highp sampler2D boneTexture;
176: 		uniform int boneTextureSize;
177: 		mat4 getBoneMatrix( const in float i ) {
178: 			float j = i * 4.0;
179: 			float x = mod( j, float( boneTextureSize ) );
180: 			float y = floor( j / float( boneTextureSize ) );
181: 			float dx = 1.0 / float( boneTextureSize );
182: 			float dy = 1.0 / float( boneTextureSize );
183: 			y = dy * ( y + 0.5 );
184: 			vec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );
185: 			vec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );
186: 			vec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );
187: 			vec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );
188: 			mat4 bone = mat4( v1, v2, v3, v4 );
189: 			return bone;
190: 		}
191: 	#else
192: 		uniform mat4 boneMatrices[ MAX_BONES ];
193: 		mat4 getBoneMatrix( const in float i ) {
194: 			mat4 bone = boneMatrices[ int(i) ];
195: 			return bone;
196: 		}
197: 	#endif
198: #endif
199: #ifdef USE_LOGDEPTHBUF
200: 	#ifdef USE_LOGDEPTHBUF_EXT
201: 		varying float vFragDepth;
202: 		varying float vIsPerspective;
203: 	#else
204: 		uniform float logDepthBufFC;
205: 	#endif
206: #endif
207: #if 0 > 0
208: 	varying vec3 vClipPosition;
209: #endif
210: uniform vec3 diffuse;
211: 
212: 
213: uniform vec2 uTroikaSDFTextureSize;
214: uniform float uTroikaSDFGlyphSize;
215: uniform vec4 uTroikaTotalBounds;
216: uniform vec4 uTroikaClipRect;
217: uniform mat3 uTroikaOrient;
218: uniform bool uTroikaUseGlyphColors;
219: attribute vec4 aTroikaGlyphBounds;
220: attribute float aTroikaGlyphIndex;
221: attribute vec3 aTroikaGlyphColor;
222: varying vec2 vTroikaSDFTextureUV;
223: varying vec2 vTroikaGlyphUV;
224: varying vec3 vTroikaGlyphColor;
225: 
226: vec3 troika_position_1;
227: vec3 troika_normal_1;
228: vec2 troika_uv_1;
229: void troikaVertexTransform1(inout vec3 troika_position_3, inout vec3 troika_normal_3, inout vec2 troika_uv_3) {
230:   
231: vec4 bounds = aTroikaGlyphBounds;
232: vec4 clippedBounds = vec4(
233:   clamp(bounds.xy, uTroikaClipRect.xy, uTroikaClipRect.zw),
234:   clamp(bounds.zw, uTroikaClipRect.xy, uTroikaClipRect.zw)
235: );
236: vec2 clippedXY = (mix(clippedBounds.xy, clippedBounds.zw, troika_position_3.xy) - bounds.xy) / (bounds.zw - bounds.xy);
237: vTroikaGlyphUV = clippedXY.xy;
238: 
239: float cols = uTroikaSDFTextureSize.x / uTroikaSDFGlyphSize;
240: vTroikaSDFTextureUV = vec2(
241:   mod(aTroikaGlyphIndex, cols) + clippedXY.x,
242:   floor(aTroikaGlyphIndex / cols) + clippedXY.y
243: ) * uTroikaSDFGlyphSize / uTroikaSDFTextureSize;
244: 
245: troika_position_3.xy = mix(bounds.xy, bounds.zw, clippedXY);
246: 
247: troika_uv_3 = vec2(
248:   (troika_position_3.x - uTroikaTotalBounds.x) / (uTroikaTotalBounds.z - uTroikaTotalBounds.x),
249:   (troika_position_3.y - uTroikaTotalBounds.y) / (uTroikaTotalBounds.w - uTroikaTotalBounds.y)
250: );
251: 
252: troika_position_3 = uTroikaOrient * troika_position_3;
253: troika_normal_3 = uTroikaOrient * troika_normal_3;
254: 
255: }
256: 
257: void troikaOrigMain1() {
258: vTroikaGlyphColor = uTroikaUseGlyphColors ? aTroikaGlyphColor / 255.0 : diffuse;
259: 
260: #ifdef USE_UV
261: 	vUv = ( uvTransform * vec3( troika_uv_1, 1 ) ).xy;
262: #endif
263: #if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )
264: 	vUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;
265: #endif
266: #ifdef USE_COLOR
267: 	vColor.xyz = color.xyz;
268: #endif
269: #ifdef USE_SKINNING
270: 	mat4 boneMatX = getBoneMatrix( skinIndex.x );
271: 	mat4 boneMatY = getBoneMatrix( skinIndex.y );
272: 	mat4 boneMatZ = getBoneMatrix( skinIndex.z );
273: 	mat4 boneMatW = getBoneMatrix( skinIndex.w );
274: #endif
275: 	#ifdef USE_ENVMAP
276: vec3 objectNormal = vec3( troika_normal_1 );
277: #ifdef USE_TANGENT
278: 	vec3 objectTangent = vec3( tangent.xyz );
279: #endif
280: #ifdef USE_MORPHNORMALS
281: 	objectNormal *= morphTargetBaseInfluence;
282: 	objectNormal += morphNormal0 * morphTargetInfluences[ 0 ];
283: 	objectNormal += morphNormal1 * morphTargetInfluences[ 1 ];
284: 	objectNormal += morphNormal2 * morphTargetInfluences[ 2 ];
285: 	objectNormal += morphNormal3 * morphTargetInfluences[ 3 ];
286: #endif
287: #ifdef USE_SKINNING
288: 	mat4 skinMatrix = mat4( 0.0 );
289: 	skinMatrix += skinWeight.x * boneMatX;
290: 	skinMatrix += skinWeight.y * boneMatY;
291: 	skinMatrix += skinWeight.z * boneMatZ;
292: 	skinMatrix += skinWeight.w * boneMatW;
293: 	skinMatrix  = bindMatrixInverse * skinMatrix * bindMatrix;
294: 	objectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;
295: 	#ifdef USE_TANGENT
296: 		objectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;
297: 	#endif
298: #endif
299: vec3 transformedNormal = objectNormal;
300: #ifdef USE_INSTANCING
301: 	mat3 m = mat3( instanceMatrix );
302: 	transformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );
303: 	transformedNormal = m * transformedNormal;
304: #endif
305: transformedNormal = normalMatrix * transformedNormal;
306: #ifdef FLIP_SIDED
307: 	transformedNormal = - transformedNormal;
308: #endif
309: #ifdef USE_TANGENT
310: 	vec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;
311: 	#ifdef FLIP_SIDED
312: 		transformedTangent = - transformedTangent;
313: 	#endif
314: #endif
315: 	#endif
316: vec3 transformed = vec3( troika_position_1 );
317: #ifdef USE_MORPHTARGETS
318: 	transformed *= morphTargetBaseInfluence;
319: 	transformed += morphTarget0 * morphTargetInfluences[ 0 ];
320: 	transformed += morphTarget1 * morphTargetInfluences[ 1 ];
321: 	transformed += morphTarget2 * morphTargetInfluences[ 2 ];
322: 	transformed += morphTarget3 * morphTargetInfluences[ 3 ];
323: 	#ifndef USE_MORPHNORMALS
324: 	transformed += morphTarget4 * morphTargetInfluences[ 4 ];
325: 	transformed += morphTarget5 * morphTargetInfluences[ 5 ];
326: 	transformed += morphTarget6 * morphTargetInfluences[ 6 ];
327: 	transformed += morphTarget7 * morphTargetInfluences[ 7 ];
328: 	#endif
329: #endif
330: #ifdef USE_SKINNING
331: 	vec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );
332: 	vec4 skinned = vec4( 0.0 );
333: 	skinned += boneMatX * skinVertex * skinWeight.x;
334: 	skinned += boneMatY * skinVertex * skinWeight.y;
335: 	skinned += boneMatZ * skinVertex * skinWeight.z;
336: 	skinned += boneMatW * skinVertex * skinWeight.w;
337: 	transformed = ( bindMatrixInverse * skinned ).xyz;
338: #endif
339: vec4 mvPosition = vec4( transformed, 1.0 );
340: #ifdef USE_INSTANCING
341: 	mvPosition = instanceMatrix * mvPosition;
342: #endif
343: mvPosition = modelViewMatrix * mvPosition;
344: gl_Position = projectionMatrix * mvPosition;
345: #ifdef USE_LOGDEPTHBUF
346: 	#ifdef USE_LOGDEPTHBUF_EXT
347: 		vFragDepth = 1.0 + gl_Position.w;
348: 		vIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );
349: 	#else
350: 		if ( isPerspectiveMatrix( projectionMatrix ) ) {
351: 			gl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;
352: 			gl_Position.z *= gl_Position.w;
353: 		}
354: 	#endif
355: #endif
356: #if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )
357: 	vec4 worldPosition = vec4( transformed, 1.0 );
358: 	#ifdef USE_INSTANCING
359: 		worldPosition = instanceMatrix * worldPosition;
360: 	#endif
361: 	worldPosition = modelMatrix * worldPosition;
362: #endif
363: #if 0 > 0
364: 	vClipPosition = - mvPosition.xyz;
365: #endif
366: #ifdef USE_ENVMAP
367: 	#ifdef ENV_WORLDPOS
368: 		vWorldPosition = worldPosition.xyz;
369: 	#else
370: 		vec3 cameraToVertex;
371: 		if ( isOrthographic ) { 
372: 			cameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );
373: 		} else {
374: 			cameraToVertex = normalize( worldPosition.xyz - cameraPosition );
375: 		}
376: 		vec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );
377: 		#ifdef ENVMAP_MODE_REFLECTION
378: 			vReflect = reflect( cameraToVertex, worldNormal );
379: 		#else
380: 			vReflect = refract( cameraToVertex, worldNormal, refractionRatio );
381: 		#endif
382: 	#endif
383: #endif
384: #ifdef USE_FOG
385: 	fogDepth = -mvPosition.z;
386: #endif
387: }
388: 
389: 
390: uniform vec2 uTroikaSDFTextureSize;
391: uniform float uTroikaSDFGlyphSize;
392: uniform vec4 uTroikaTotalBounds;
393: uniform vec4 uTroikaClipRect;
394: uniform mat3 uTroikaOrient;
395: uniform bool uTroikaUseGlyphColors;
396: attribute vec4 aTroikaGlyphBounds;
397: attribute float aTroikaGlyphIndex;
398: attribute vec3 aTroikaGlyphColor;
399: varying vec2 vTroikaSDFTextureUV;
400: varying vec2 vTroikaGlyphUV;
401: varying vec3 vTroikaGlyphColor;
402: 
403: vec3 troika_position_3;
404: vec3 troika_normal_3;
405: vec2 troika_uv_3;
406: void troikaVertexTransform3(inout vec3 position, inout vec3 normal, inout vec2 uv) {
407:   
408: vec4 bounds = aTroikaGlyphBounds;
409: vec4 clippedBounds = vec4(
410:   clamp(bounds.xy, uTroikaClipRect.xy, uTroikaClipRect.zw),
411:   clamp(bounds.zw, uTroikaClipRect.xy, uTroikaClipRect.zw)
412: );
413: vec2 clippedXY = (mix(clippedBounds.xy, clippedBounds.zw, position.xy) - bounds.xy) / (bounds.zw - bounds.xy);
414: vTroikaGlyphUV = clippedXY.xy;
415: 
416: float cols = uTroikaSDFTextureSize.x / uTroikaSDFGlyphSize;
417: vTroikaSDFTextureUV = vec2(
418:   mod(aTroikaGlyphIndex, cols) + clippedXY.x,
419:   floor(aTroikaGlyphIndex / cols) + clippedXY.y
420: ) * uTroikaSDFGlyphSize / uTroikaSDFTextureSize;
421: 
422: position.xy = mix(bounds.xy, bounds.zw, clippedXY);
423: 
424: uv = vec2(
425:   (position.x - uTroikaTotalBounds.x) / (uTroikaTotalBounds.z - uTroikaTotalBounds.x),
426:   (position.y - uTroikaTotalBounds.y) / (uTroikaTotalBounds.w - uTroikaTotalBounds.y)
427: );
428: 
429: position = uTroikaOrient * position;
430: normal = uTroikaOrient * normal;
431: 
432: }
433: 
434: void troikaOrigMain3() {
435:   
436: troika_position_1 = vec3(troika_position_3);
437: troika_normal_1 = vec3(troika_normal_3);
438: troika_uv_1 = vec2(troika_uv_3);
439: troikaVertexTransform1(troika_position_1, troika_normal_1, troika_uv_1);
440: 
441: 
442:   troikaOrigMain1();
443:   
444: }
445: void main() {
446:   
447: troika_position_3 = vec3(position);
448: troika_normal_3 = vec3(normal);
449: troika_uv_3 = vec2(uv);
450: troikaVertexTransform3(troika_position_3, troika_normal_3, troika_uv_3);
451: 
452: 
453:   troikaOrigMain3();
454:   
455: }
@giulioz
Copy link
Author

giulioz commented Jun 9, 2020

(Sorry for the very long error log)

@giulioz
Copy link
Author

giulioz commented Jun 9, 2020

I found out that this only happens when using the postprocessing library, when enabling the instancing workaround.

@giulioz
Copy link
Author

giulioz commented Jun 9, 2020

The reason this is happening is because of this part:

  // Handler for automatically wrapping the base material with our upgrades. We do the wrapping
  // lazily on _read_ rather than write to avoid unnecessary wrapping on transient values.
  get material() {
    let derivedMaterial = this._derivedMaterial
    const baseMaterial = this._baseMaterial || defaultMaterial
    if (!derivedMaterial || derivedMaterial.baseMaterial !== baseMaterial) {
      if (derivedMaterial) {
        derivedMaterial.dispose()
      }
      derivedMaterial = this._derivedMaterial = createTextDerivedMaterial(baseMaterial)
      // dispose the derived material when its base material is disposed:
      baseMaterial.addEventListener('dispose', function onDispose() {
        baseMaterial.removeEventListener('dispose', onDispose)
        derivedMaterial.dispose()
      })
    }
    return derivedMaterial
  }

The postprocessing workaround changes the materials of all the meshes every render two times: https://github.com/vanruesc/postprocessing/blob/master/src/core/OverrideMaterialManager.js

@lojjic
Copy link
Collaborator

lojjic commented Jun 9, 2020

Ah I see, so it essentially ends up doing...

let mtl = textMesh.material
...
textMesh.material = mtl

I can see how that would end up double-deriving the material. Should be a simple fix, I just have to check whether the incoming material is already a derived text material.

@giulioz Do you happen to have an online example using your particular postprocessing setup that I could test this with - a Codesandbox or something?

lojjic added a commit that referenced this issue Jun 9, 2020
Potential fix for #59. Setting `mesh.material = mesh.material` would
result in the derived text material being derived again, causing shader
errors. This fix checks whether the incoming material is already derived
and if so then it's just used as is.
@giulioz
Copy link
Author

giulioz commented Jun 9, 2020

I tried to replicate a similar situation with react-three-fiber and I got even another kind of error: https://codesandbox.io/s/troika-text-pp-bug-ymsv1?file=/src/index.js

@lojjic
Copy link
Collaborator

lojjic commented Jun 9, 2020

That codesandbox is using an old version, that shadowSide bug was fixed already.

I've just published version 0.28.0 which I think should fix your postprocessing error, give that a try and reopen this ticket if there's still an issue.

@lojjic lojjic closed this as completed Jun 9, 2020
@giulioz
Copy link
Author

giulioz commented Jun 9, 2020

My fault, I forked from another sandbox and forgot to update...
I updated the sandbox and now it exhibit the bug: https://codesandbox.io/s/troika-text-pp-bug-ymsv1?file=/src/index.js

I'll let you know if 0.28.0 fixes the bug, thank you very much in advance.

@giulioz
Copy link
Author

giulioz commented Jun 9, 2020

The fix works but it slows down everything. The profiler shows that a lot of time is spent in shader program compilation (getProgramInfoLog).
The debugger shows that createDerivedMaterial gets called every frame, is this right?

In the material getter it enters this branch when rendering the normals for postprocessing:
image

@lojjic
Copy link
Collaborator

lojjic commented Jun 9, 2020

Hmm, yeah I suppose that makes sense if postprocessing is assigning a different MeshNormalMaterial instance every frame. The createDerivedMaterial utility will cache by base material instance, not by material class, so if it's not using the same material instance each time it will re-derive.

Still, though, ThreeJS's program management should reuse a webgl program if the shader content isn't changing, so there must be something I'm doing that causes slightly different shader content each time. I'll look into that.

@lojjic lojjic reopened this Jun 9, 2020
@lojjic
Copy link
Collaborator

lojjic commented Jun 9, 2020

Ah yes, the rewritten shaders use an id to disambiguate certain things. That id is different per base material, hence the resulting shaders are different.

This could be a tricky one to fix without breaking other things. If you could still provide a testcase for me that would be very helpful.

@giulioz
Copy link
Author

giulioz commented Jun 9, 2020

I've updated the Codesandbox (https://codesandbox.io/s/troika-text-pp-bug-ymsv1).
If you put a breakpoint in createTextDerivedMaterial (textmesh-standalone.umd.js:5944) you can see it's called every frame.

@lojjic
Copy link
Collaborator

lojjic commented Jun 9, 2020

@giulioz Thank you for that CSB example, that's perfect. I've been able to reproduce it locally using that and I have a tentative fix that seems to be working. But this derived material logic is pretty finnicky/fragile so I'm going to put it through its paces during my day job work for the rest of the week, before pushing it out. Hope that doesn't hold you up too badly.

@giulioz
Copy link
Author

giulioz commented Jun 9, 2020

No problem! Thanks for the assistance and your hard work on this amazing library :)

lojjic added a commit that referenced this issue Jun 17, 2020
… switch

Followup performance fix for #59. When used in postprocessing, the
base material can be temporarily reassigned, and disposing the original
derived material triggers recompilation of the shader program on every
next frame.
lojjic added a commit that referenced this issue Jun 17, 2020
…erivedMaterial

Related to #59. Different instances of the same Material class can
easily give identical shader output; however we were injecting a unique
id into the rewritten shader code for every instance, preventing the
resulting shader code from ever being the same and causing separate
compiled webgl programs for each instance. This change chooses a
consistent id based on incoming derived material options, allowing the
result to match when the input shader code is the same.
@lojjic
Copy link
Collaborator

lojjic commented Jun 17, 2020

Thanks for the patience; I've published v 0.28.1 which should fix your frame rate issue. Please reopen if that's not the case. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants