How to get texture coords in shader chunks

I made my own diffuse chunk by copying whatever exists in diffuse.frag and adding my own code under it.


#ifdef MAPCOLOR
uniform vec3 material_diffuse;
#endif

#ifdef MAPTEXTURE
uniform sampler2D texture_diffuseMap;
#endif

// CUSTOM UNIFORMS
uniform sampler2D u_groutMask;

uniform sampler2D u_groutColor;

//uniform vec3 u_groutColor;
uniform float u_groutIntensity;

void getAlbedo() {
    dAlbedo = vec3(1.0);

    #ifdef MAPCOLOR
    dAlbedo *= material_diffuse.rgb;
    #endif

    #ifdef MAPTEXTURE
    dAlbedo *= gammaCorrectInput(addAlbedoDetail(texture2D(texture_diffuseMap, $UV).$CH));
    #endif

    #ifdef MAPVERTEX
    dAlbedo *= gammaCorrectInput(saturate(vVertexColor.$VC));
    #endif
    
    // Sample pixel from groutMaskTexture
    vec3 maskedSample = vec3(texture2D(u_groutMask, vUv0));
    // Sample Color, Apply to Mask then apply to emissive
    vec3 colorSample = vec3(texture2D(u_groutColor, vUv0));
    vec3 maskedColor = maskedSample * colorSample;    
   
    dAlbedo = mix(dAlbedo, maskedColor*, maskedSample);
}

For ref here is the project: https://playcanvas.com/editor/scene/1181947
The shader itself gets applied using the groutShaderScript.js

Issue#1: Trying to sample a texture as shown in the original shader using texture2D line with my own sampler var ie. u_groutMask gives an error saying the function doesn’t exist. So I tried to solve it by using regular texture2D function and passing $UV to it. (Also tried using texture2DSRGB function but even though it is clearly visible in the error output shader it says that also does not exist)

Issue#2: Error when trying to use $UV with texture2D() so I changed it to vUv0 since it shows up as a varying when my material has default values. The shader finally compiles so i get some output.

Issue#3: But now changing the Tiling values on the material used in the shader breaks the shader again because now vUv0 does not exist. On reading the varying variables I can see this has now changed to varying vec2 vUV0_1;

How do you get default texture coords that are passed by the vertex shader to frag shader so that they always work regardless of what options( tiling/offset values ) are changed in the material when using the Editor?

Hi @sorab_flip ,

I think you got it right on your first try, not sure why it didn’t work for you. I forked your project and set the tiling to 2,2, as you said that broke the shaders.

Then I replaced all instances of vUv0 in both pixel shaders with $UV and that fixed the issue:

2 Likes

As you mentioned I replaced all instances of vUv0 with $UV and while it worked for the diffuse shader.
After changing in the emissive shader and unchecking the UseDiffuse (boolean) on the script, it still gives a shader error UV undeclared identifier.

Failed to compile fragment shader:

1:	#version 300 es
2:	#define varying in
3:	out highp vec4 pc_fragColor;
4:	#define gl_FragColor pc_fragColor
5:	#define texture2D texture
6:	#define textureCube texture
7:	#define texture2DProj textureProj
8:	#define texture2DLodEXT textureLod
9:	#define texture2DProjLodEXT textureProjLod
10:	#define textureCubeLodEXT textureLod
11:	#define texture2DGradEXT textureGrad
12:	#define texture2DProjGradEXT textureProjGrad
13:	#define textureCubeGradEXT textureGrad
14:	#define GL2
15:	precision highp float;
16:	#ifdef GL2
17:	precision highp sampler2DShadow;
18:	#endif
19:	varying vec3 vPositionW;
20:	varying vec3 vNormalW;
21:	varying vec2 vUv0;
22:	uniform vec3 view_position;
23:	
24:	uniform vec3 light_globalAmbient;
25:	
26:	float square(float x) {
27:		return x*x;
28:	}
29:	
30:	float saturate(float x) {
31:		return clamp(x, 0.0, 1.0);
32:	}
33:	
34:	vec3 saturate(vec3 x) {
35:		return clamp(x, vec3(0.0), vec3(1.0));
36:	}
37:	vec3 detailMode_mul(vec3 c1, vec3 c2) {
38:		return c1 * c2;
39:	}
40:	
41:	vec3 detailMode_add(vec3 c1, vec3 c2) {
42:		return c1 + c2;
43:	}
44:	
45:	// https://en.wikipedia.org/wiki/Blend_modes#Screen
46:	vec3 detailMode_screen(vec3 c1, vec3 c2) {
47:		return 1.0 - (1.0 - c1)*(1.0 - c2);
48:	}
49:	
50:	// https://en.wikipedia.org/wiki/Blend_modes#Overlay
51:	vec3 detailMode_overlay(vec3 c1, vec3 c2) {
52:		return mix(1.0 - 2.0*(1.0 - c1)*(1.0 - c2), 2.0*c1*c2, step(c1, vec3(0.5)));
53:	}
54:	
55:	vec3 detailMode_min(vec3 c1, vec3 c2) {
56:		return min(c1, c2);
57:	}
58:	
59:	vec3 detailMode_max(vec3 c1, vec3 c2) {
60:		return max(c1, c2);
61:	}
62:	vec4 dReflection;
63:	vec3 dAlbedo;
64:	vec3 dNormalW;
65:	vec3 dVertexNormalW;
66:	vec3 dViewDirW;
67:	vec3 dReflDirW;
68:	vec3 dDiffuseLight;
69:	vec3 dSpecularLight;
70:	vec3 dLightDirNormW;
71:	vec3 dLightDirW;
72:	vec3 dLightPosW;
73:	vec3 dShadowCoord;
74:	vec3 dSpecularity;
75:	float dGlossiness;
76:	float dAlpha;
77:	float dAtten;
78:	vec4 ccReflection;
79:	vec3 ccNormalW;
80:	vec3 ccSpecularLight;
81:	float ccSpecularity;
82:	float ccGlossiness;
83:	#define AREA_LUTS_PRECISION highp
84:	uniform vec3 light0_color;
85:	uniform vec3 light0_direction;
86:	uniform mat4 light0_shadowMatrix;
87:	uniform mat4 light0_shadowMatrixPalette[4];
88:	uniform float light0_shadowCascadeDistances[4];
89:	uniform float light0_shadowCascadeCount;
90:	uniform vec3 light0_shadowParams;
91:	uniform sampler2DShadow light0_shadowMap;
92:	
93:	void getNormal() {
94:		dNormalW = normalize(dVertexNormalW);
95:	}
96:	vec3 gammaCorrectInput(vec3 color) {
97:		return pow(color, vec3(2.2));
98:	}
99:	
100:	float gammaCorrectInput(float color) {
101:		return pow(color, 2.2);
102:	}
103:	
104:	vec4 gammaCorrectInput(vec4 color) {
105:		return vec4(pow(color.rgb, vec3(2.2)), color.a);
106:	}
107:	
108:	vec4 texture2DSRGB(sampler2D tex, vec2 uv) {
109:		vec4 rgba = texture2D(tex, uv);
110:		rgba.rgb = gammaCorrectInput(rgba.rgb);
111:		return rgba;
112:	}
113:	
114:	vec4 texture2DSRGB(sampler2D tex, vec2 uv, float bias) {
115:		vec4 rgba = texture2D(tex, uv, bias);
116:		rgba.rgb = gammaCorrectInput(rgba.rgb);
117:		return rgba;
118:	}
119:	
120:	vec4 textureCubeSRGB(samplerCube tex, vec3 uvw) {
121:		vec4 rgba = textureCube(tex, uvw);
122:		rgba.rgb = gammaCorrectInput(rgba.rgb);
123:		return rgba;
124:	}
125:	
126:	vec3 gammaCorrectOutput(vec3 color) {
127:		#ifdef HDR
128:		return color;
129:		#else
130:		color += vec3(0.0000001);
131:		return pow(color, vec3(0.45));
132:		#endif
133:	}
134:	uniform float exposure;
135:	
136:	vec3 toneMap(vec3 color) {
137:		return color * exposure;
138:	}
139:	float dBlendModeFogFactor = 1.0;
140:	
141:	vec3 addFog(vec3 color) {
142:		return color;
143:	}
144:	#ifdef CUBEMAP_ROTATION
145:	uniform mat3 cubeMapRotationMatrix;
146:	#endif
147:	
148:	vec3 cubeMapRotate(vec3 refDir) {
149:	#ifdef CUBEMAP_ROTATION
150:		return refDir * cubeMapRotationMatrix;
151:	#else
152:		return refDir;
153:	#endif
154:	}
155:	vec3 cubeMapProject(vec3 dir) {
156:		return cubeMapRotate(dir);
157:	}
158:	vec3 processEnvironment(vec3 color) {
159:		return color;
160:	}
161:	
162:	#undef MAPFLOAT
163:	
164:	#undef MAPCOLOR
165:	
166:	#undef MAPVERTEX
167:	
168:	#undef MAPTEXTURE
169:	#ifdef MAPTEXTURE
170:	uniform sampler2D texture_diffuseDetailMap;
171:	#endif
172:	
173:	vec3 addAlbedoDetail(vec3 albedo) {
174:		#ifdef MAPTEXTURE
175:		vec3 albedoDetail = vec3(texture2D(texture_diffuseDetailMap, UV).CH);
176:		return detailMode_mul(albedo, albedoDetail);
177:		#else
178:		return albedo;
179:		#endif
180:	}
181:	
182:	#undef MAPFLOAT
183:	
184:	#undef MAPCOLOR
185:	
186:	#undef MAPVERTEX
187:	
188:	#undef MAPTEXTURE
189:	 #define MAPTEXTURE
190:	#ifdef MAPCOLOR
191:	uniform vec3 material_diffuse;
192:	#endif
193:	
194:	#ifdef MAPTEXTURE
195:	uniform sampler2D texture_diffuseMap;
196:	#endif
197:	
198:	void getAlbedo() {
199:		dAlbedo = vec3(1.0);
200:	
201:		#ifdef MAPCOLOR
202:		dAlbedo *= material_diffuse.rgb;
203:		#endif
204:	
205:		#ifdef MAPTEXTURE
206:		dAlbedo *= gammaCorrectInput(addAlbedoDetail(texture2D(texture_diffuseMap, vUv0).rgb));
207:		#endif
208:	
209:		#ifdef MAPVERTEX
210:		dAlbedo *= gammaCorrectInput(saturate(vVertexColor.VC));
211:		#endif
212:	}
213:	
214:	#undef MAPFLOAT
215:	
216:	#undef MAPCOLOR
217:	 #define MAPCOLOR
218:	
219:	#undef MAPVERTEX
220:	
221:	#undef MAPTEXTURE
222:	#ifdef MAPCOLOR
223:	uniform vec3 material_emissive;
224:	#endif
225:	
226:	#ifdef MAPFLOAT
227:	uniform float material_emissiveIntensity;
228:	#endif
229:	
230:	#ifdef MAPTEXTURE
231:	uniform sampler2D texture_emissiveMap;
232:	#endif
233:	
234:	// CUSTOM UNIFORMS
235:	uniform sampler2D u_groutMask;
236:	
237:	uniform sampler2D u_groutColor;
238:	
239:	//uniform vec3 u_groutColor;
240:	uniform float u_groutIntensity;
241:	
242:	vec3 getEmission() {
243:	    vec3 emission = vec3(1.0);
244:	
245:	    #ifdef MAPFLOAT
246:	    emission *= material_emissiveIntensity;
247:	    #endif
248:	
249:	    #ifdef MAPCOLOR
250:	    emission *= material_emissive;
251:	    #endif
252:	
253:	    #ifdef MAPTEXTURE
254:	    emission *= texture2DSAMPLE(texture_emissiveMap, UV).CH;
255:	    #endif
256:	
257:	    #ifdef MAPVERTEX
258:	    emission *= gammaCorrectInput(saturate(vVertexColor.VC));
259:	    #endif
260:	    
261:	    // Sample pixel from groutMaskTexture
262:	    vec3 maskedSample = vec3(texture2D(u_groutMask, UV));
263:	
264:	    // IF GROUTCOLOR IS A VEC3: Apply groutColor to Mask and show that as emissiveColor 
265:	    // -while keeping original emissive calculation in tact(i.e. can modify in editor and it will get added with the grout)
266:	    //emission = mix(emission, u_groutColor * u_groutIntensity, maskedSample);
267:	    
268:	    // IF GROUTCOLOR IS A TEXTURE:
269:	    // Sample Color, Apply to Mask then apply to emissive
270:	    vec3 colorSample = vec3(texture2D(u_groutColor, UV));
271:	    
272:	    vec3 maskedColor = maskedSample * colorSample;
273:	    
274:	    //emission = mix(emission, u_groutColor * u_groutIntensity, maskedSample);
275:	    
276:	    emission = mix(emission, maskedColor*u_groutIntensity, maskedSample);
277:	    
278:	    return emission;
279:	}
280:	
281:	float antiAliasGlossiness(float power) {
282:		return power;
283:	}
284:	
285:	#undef MAPFLOAT
286:	
287:	#undef MAPCOLOR
288:	 #define MAPCOLOR
289:	
290:	#undef MAPVERTEX
291:	
292:	#undef MAPTEXTURE
293:	#ifdef MAPCOLOR
294:	uniform vec3 material_specular;
295:	#endif
296:	
297:	#ifdef MAPTEXTURE
298:	uniform sampler2D texture_specularMap;
299:	#endif
300:	
301:	void getSpecularity() {
302:		dSpecularity = vec3(1.0);
303:	
304:		#ifdef MAPCOLOR
305:		dSpecularity *= material_specular;
306:		#endif
307:	
308:		#ifdef MAPTEXTURE
309:		dSpecularity *= texture2D(texture_specularMap, UV).CH;
310:		#endif
311:	
312:		#ifdef MAPVERTEX
313:		dSpecularity *= saturate(vVertexColor.VC);
314:		#endif
315:	}
316:	
317:	#undef MAPFLOAT
318:	 #define MAPFLOAT
319:	
320:	#undef MAPCOLOR
321:	
322:	#undef MAPVERTEX
323:	
324:	#undef MAPTEXTURE
325:	#ifdef MAPFLOAT
326:	uniform float material_shininess;
327:	#endif
328:	
329:	#ifdef MAPTEXTURE
330:	uniform sampler2D texture_glossMap;
331:	#endif
332:	
333:	void getGlossiness() {
334:		dGlossiness = 1.0;
335:	
336:		#ifdef MAPFLOAT
337:		dGlossiness *= material_shininess;
338:		#endif
339:	
340:		#ifdef MAPTEXTURE
341:		dGlossiness *= texture2D(texture_glossMap, UV).CH;
342:		#endif
343:	
344:		#ifdef MAPVERTEX
345:		dGlossiness *= saturate(vVertexColor.VC);
346:		#endif
347:	
348:		dGlossiness += 0.0000001;
349:	}
350:	// Schlick's approximation
351:	uniform float material_fresnelFactor; // unused
352:	
353:	void getFresnel() {
354:		float fresnel = 1.0 - max(dot(dNormalW, dViewDirW), 0.0);
355:		float fresnel2 = fresnel * fresnel;
356:		fresnel *= fresnel2 * fresnel2;
357:		fresnel *= dGlossiness * dGlossiness;
358:		dSpecularity = dSpecularity + (1.0 - dSpecularity) * fresnel;
359:	
360:		#ifdef CLEARCOAT
361:		fresnel = 1.0 - max(dot(ccNormalW, dViewDirW), 0.0);
362:		fresnel2 = fresnel * fresnel;
363:		fresnel *= fresnel2 * fresnel2;
364:		fresnel *= ccGlossiness * ccGlossiness;
365:		ccSpecularity = ccSpecularity + (1.0 - ccSpecularity) * fresnel;
366:		#endif
367:	}
368:	const float maxCascades = 4.0;
369:	
370:	// shadow matrix for selected cascade
371:	mat4 cascadeShadowMat;
372:	
373:	// function which selects a shadow projection matrix based on cascade distances 
374:	void getShadowCascadeMatrix(mat4 shadowMatrixPalette[4], float shadowCascadeDistances[4], float shadowCascadeCount) {
375:	
376:		// depth in 0 .. far plane range
377:		float depth = 1.0 / gl_FragCoord.w;
378:	
379:		// find cascade index based on the depth (loop as there is no per component vec compare operator in webgl)
380:		float cascadeIndex = 0.0;
381:		for (float i = 0.0; i < maxCascades; i++) {
382:			if (depth < shadowCascadeDistances[int(i)]) {
383:				cascadeIndex = i;
384:				break;
385:			}
386:		}
387:	
388:		// limit to actual number of used cascades
389:		cascadeIndex = min(cascadeIndex, shadowCascadeCount - 1.0);
390:	
391:		// pick shadow matrix
392:		#ifdef GL2
393:			cascadeShadowMat = shadowMatrixPalette[int(cascadeIndex)];
394:		#else
395:			// webgl 1 does not allow non-cost index array lookup
396:			if (cascadeIndex == 0.0) {
397:				cascadeShadowMat = shadowMatrixPalette[0];
398:			}
399:			else if (cascadeIndex == 1.0) {
400:				cascadeShadowMat = shadowMatrixPalette[1];
401:			}
402:			else if (cascadeIndex == 2.0) {
403:				cascadeShadowMat = shadowMatrixPalette[2];
404:			}
405:			else {
406:				cascadeShadowMat = shadowMatrixPalette[3];
407:			}
408:		#endif
409:	}
410:	
411:	void fadeShadow(float shadowCascadeDistances[4]) {				  
412:	
413:		// if the pixel is past the shadow distance, remove shadow
414:		// this enforces straight line instead of corner of shadow which moves when camera rotates  
415:		float depth = 1.0 / gl_FragCoord.w;
416:		if (depth > shadowCascadeDistances[int(maxCascades - 1.0)]) {
417:			dShadowCoord.z = -9999999.0;
418:		}
419:	}
420:	vec3 lessThan2(vec3 a, vec3 b) {
421:		return clamp((b - a)*1000.0, 0.0, 1.0); // softer version
422:	}
423:	
424:	#ifndef UNPACKFLOAT
425:	#define UNPACKFLOAT
426:	float unpackFloat(vec4 rgbaDepth) {
427:		const vec4 bitShift = vec4(1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0);
428:		return dot(rgbaDepth, bitShift);
429:	}
430:	#endif
431:	
432:	// ----- Direct/Spot Sampling -----
433:	
434:	#ifdef GL2
435:	float _getShadowPCF3x3(sampler2DShadow shadowMap, vec3 shadowParams) {
436:		float z = dShadowCoord.z;
437:		vec2 uv = dShadowCoord.xy * shadowParams.x; // 1 unit - 1 texel
438:		float shadowMapSizeInv = 1.0 / shadowParams.x;
439:		vec2 base_uv = floor(uv + 0.5);
440:		float s = (uv.x + 0.5 - base_uv.x);
441:		float t = (uv.y + 0.5 - base_uv.y);
442:		base_uv -= vec2(0.5);
443:		base_uv *= shadowMapSizeInv;
444:	
445:		float sum = 0.0;
446:	
447:		float uw0 = (3.0 - 2.0 * s);
448:		float uw1 = (1.0 + 2.0 * s);
449:	
450:		float u0 = (2.0 - s) / uw0 - 1.0;
451:		float u1 = s / uw1 + 1.0;
452:	
453:		float vw0 = (3.0 - 2.0 * t);
454:		float vw1 = (1.0 + 2.0 * t);
455:	
456:		float v0 = (2.0 - t) / vw0 - 1.0;
457:		float v1 = t / vw1 + 1.0;
458:	
459:		u0 = u0 * shadowMapSizeInv + base_uv.x;
460:		v0 = v0 * shadowMapSizeInv + base_uv.y;
461:	
462:		u1 = u1 * shadowMapSizeInv + base_uv.x;
463:		v1 = v1 * shadowMapSizeInv + base_uv.y;
464:	
465:		sum += uw0 * vw0 * texture(shadowMap, vec3(u0, v0, z));
466:		sum += uw1 * vw0 * texture(shadowMap, vec3(u1, v0, z));
467:		sum += uw0 * vw1 * texture(shadowMap, vec3(u0, v1, z));
468:		sum += uw1 * vw1 * texture(shadowMap, vec3(u1, v1, z));
469:	
470:		sum *= 1.0f / 16.0;
471:		return sum;
472:	}
473:	
474:	float getShadowPCF3x3(sampler2DShadow shadowMap, vec3 shadowParams) {
475:		return _getShadowPCF3x3(shadowMap, shadowParams);
476:	}
477:	
478:	float getShadowSpotPCF3x3(sampler2DShadow shadowMap, vec4 shadowParams) {
479:		return _getShadowPCF3x3(shadowMap, shadowParams.xyz);
480:	}
481:	#else
482:	float _xgetShadowPCF3x3(mat3 depthKernel, sampler2D shadowMap, vec3 shadowParams) {
483:		mat3 shadowKernel;
484:		vec3 shadowCoord = dShadowCoord;
485:		vec3 shadowZ = vec3(shadowCoord.z);
486:		shadowKernel[0] = vec3(greaterThan(depthKernel[0], shadowZ));
487:		shadowKernel[1] = vec3(greaterThan(depthKernel[1], shadowZ));
488:		shadowKernel[2] = vec3(greaterThan(depthKernel[2], shadowZ));
489:	
490:		vec2 fractionalCoord = fract( shadowCoord.xy * shadowParams.x );
491:	
492:		shadowKernel[0] = mix(shadowKernel[0], shadowKernel[1], fractionalCoord.x);
493:		shadowKernel[1] = mix(shadowKernel[1], shadowKernel[2], fractionalCoord.x);
494:	
495:		vec4 shadowValues;
496:		shadowValues.x = mix(shadowKernel[0][0], shadowKernel[0][1], fractionalCoord.y);
497:		shadowValues.y = mix(shadowKernel[0][1], shadowKernel[0][2], fractionalCoord.y);
498:		shadowValues.z = mix(shadowKernel[1][0], shadowKernel[1][1], fractionalCoord.y);
499:		shadowValues.w = mix(shadowKernel[1][1], shadowKernel[1][2], fractionalCoord.y);
500:	
501:		return dot( shadowValues, vec4( 1.0 ) ) * 0.25;
502:	}
503:	
504:	float _getShadowPCF3x3(sampler2D shadowMap, vec3 shadowParams) {
505:		vec3 shadowCoord = dShadowCoord;
506:	
507:		float xoffset = 1.0 / shadowParams.x; // 1/shadow map width
508:		float dx0 = -xoffset;
509:		float dx1 = xoffset;
510:	
511:		mat3 depthKernel;
512:		depthKernel[0][0] = unpackFloat(texture2D(shadowMap, shadowCoord.xy + vec2(dx0, dx0)));
513:		depthKernel[0][1] = unpackFloat(texture2D(shadowMap, shadowCoord.xy + vec2(dx0, 0.0)));
514:		depthKernel[0][2] = unpackFloat(texture2D(shadowMap, shadowCoord.xy + vec2(dx0, dx1)));
515:		depthKernel[1][0] = unpackFloat(texture2D(shadowMap, shadowCoord.xy + vec2(0.0, dx0)));
516:		depthKernel[1][1] = unpackFloat(texture2D(shadowMap, shadowCoord.xy));
517:		depthKernel[1][2] = unpackFloat(texture2D(shadowMap, shadowCoord.xy + vec2(0.0, dx1)));
518:		depthKernel[2][0] = unpackFloat(texture2D(shadowMap, shadowCoord.xy + vec2(dx1, dx0)));
519:		depthKernel[2][1] = unpackFloat(texture2D(shadowMap, shadowCoord.xy + vec2(dx1, 0.0)));
520:		depthKernel[2][2] = unpackFloat(texture2D(shadowMap, shadowCoord.xy + vec2(dx1, dx1)));
521:	
522:		return _xgetShadowPCF3x3(depthKernel, shadowMap, shadowParams);
523:	}
524:	
525:	float getShadowPCF3x3(sampler2D shadowMap, vec3 shadowParams) {
526:		return _getShadowPCF3x3(shadowMap, shadowParams);
527:	}
528:	
529:	float getShadowSpotPCF3x3(sampler2D shadowMap, vec4 shadowParams) {
530:		return _getShadowPCF3x3(shadowMap, shadowParams.xyz);
531:	}
532:	#endif
533:	
534:	
535:	// ----- Point Sampling -----
536:	
537:	float _getShadowPoint(samplerCube shadowMap, vec4 shadowParams, vec3 dir) {
538:	
539:		vec3 tc = normalize(dir);
540:		vec3 tcAbs = abs(tc);
541:	
542:		vec4 dirX = vec4(1,0,0, tc.x);
543:		vec4 dirY = vec4(0,1,0, tc.y);
544:		float majorAxisLength = tc.z;
545:		if ((tcAbs.x > tcAbs.y) && (tcAbs.x > tcAbs.z)) {
546:			dirX = vec4(0,0,1, tc.z);
547:			dirY = vec4(0,1,0, tc.y);
548:			majorAxisLength = tc.x;
549:		} else if ((tcAbs.y > tcAbs.x) && (tcAbs.y > tcAbs.z)) {
550:			dirX = vec4(1,0,0, tc.x);
551:			dirY = vec4(0,0,1, tc.z);
552:			majorAxisLength = tc.y;
553:		}
554:	
555:		float shadowParamsInFaceSpace = ((1.0/shadowParams.x) * 2.0) * abs(majorAxisLength);
556:	
557:		vec3 xoffset = (dirX.xyz * shadowParamsInFaceSpace);
558:		vec3 yoffset = (dirY.xyz * shadowParamsInFaceSpace);
559:		vec3 dx0 = -xoffset;
560:		vec3 dy0 = -yoffset;
561:		vec3 dx1 = xoffset;
562:		vec3 dy1 = yoffset;
563:	
564:		mat3 shadowKernel;
565:		mat3 depthKernel;
566:	
567:		depthKernel[0][0] = unpackFloat(textureCube(shadowMap, tc + dx0 + dy0));
568:		depthKernel[0][1] = unpackFloat(textureCube(shadowMap, tc + dx0));
569:		depthKernel[0][2] = unpackFloat(textureCube(shadowMap, tc + dx0 + dy1));
570:		depthKernel[1][0] = unpackFloat(textureCube(shadowMap, tc + dy0));
571:		depthKernel[1][1] = unpackFloat(textureCube(shadowMap, tc));
572:		depthKernel[1][2] = unpackFloat(textureCube(shadowMap, tc + dy1));
573:		depthKernel[2][0] = unpackFloat(textureCube(shadowMap, tc + dx1 + dy0));
574:		depthKernel[2][1] = unpackFloat(textureCube(shadowMap, tc + dx1));
575:		depthKernel[2][2] = unpackFloat(textureCube(shadowMap, tc + dx1 + dy1));
576:	
577:		vec3 shadowZ = vec3(length(dir) * shadowParams.w + shadowParams.z);
578:	
579:		shadowKernel[0] = vec3(lessThan2(depthKernel[0], shadowZ));
580:		shadowKernel[1] = vec3(lessThan2(depthKernel[1], shadowZ));
581:		shadowKernel[2] = vec3(lessThan2(depthKernel[2], shadowZ));
582:	
583:		vec2 uv = (vec2(dirX.w, dirY.w) / abs(majorAxisLength)) * 0.5;
584:	
585:		vec2 fractionalCoord = fract( uv * shadowParams.x );
586:	
587:		shadowKernel[0] = mix(shadowKernel[0], shadowKernel[1], fractionalCoord.x);
588:		shadowKernel[1] = mix(shadowKernel[1], shadowKernel[2], fractionalCoord.x);
589:	
590:		vec4 shadowValues;
591:		shadowValues.x = mix(shadowKernel[0][0], shadowKernel[0][1], fractionalCoord.y);
592:		shadowValues.y = mix(shadowKernel[0][1], shadowKernel[0][2], fractionalCoord.y);
593:		shadowValues.z = mix(shadowKernel[1][0], shadowKernel[1][1], fractionalCoord.y);
594:		shadowValues.w = mix(shadowKernel[1][1], shadowKernel[1][2], fractionalCoord.y);
595:	
596:		return 1.0 - dot( shadowValues, vec4( 1.0 ) ) * 0.25;
597:	}
598:	
599:	float getShadowPointPCF3x3(samplerCube shadowMap, vec4 shadowParams) {
600:		return _getShadowPoint(shadowMap, shadowParams, dLightDirW);
601:	}
602:	void _getShadowCoordOrtho(mat4 shadowMatrix, vec3 shadowParams, vec3 wPos) {
603:		dShadowCoord = (shadowMatrix * vec4(wPos, 1.0)).xyz;
604:		dShadowCoord.z = saturate(dShadowCoord.z) - 0.0001;
605:	
606:		#ifdef SHADOWBIAS
607:		dShadowCoord.z += getShadowBias(shadowParams.x, shadowParams.z);
608:		#endif
609:	}
610:	
611:	void _getShadowCoordPersp(mat4 shadowMatrix, vec4 shadowParams, vec3 wPos) {
612:		vec4 projPos = shadowMatrix * vec4(wPos, 1.0);
613:		projPos.xy /= projPos.w;
614:		dShadowCoord.xy = projPos.xy;
615:		dShadowCoord.z = length(dLightDirW) * shadowParams.w;
616:	
617:		#ifdef SHADOWBIAS
618:		dShadowCoord.z += getShadowBias(shadowParams.x, shadowParams.z);
619:		#endif
620:	}
621:	
622:	void getShadowCoordOrtho(mat4 shadowMatrix, vec3 shadowParams) {
623:		_getShadowCoordOrtho(shadowMatrix, shadowParams, vPositionW);
624:	}
625:	
626:	void getShadowCoordPersp(mat4 shadowMatrix, vec4 shadowParams) {
627:		_getShadowCoordPersp(shadowMatrix, shadowParams, vPositionW);
628:	}
629:	
630:	void getShadowCoordPerspNormalOffset(mat4 shadowMatrix, vec4 shadowParams) {
631:		float distScale = abs(dot(vPositionW - dLightPosW, dLightDirNormW)); // fov?
632:		vec3 wPos = vPositionW + dVertexNormalW * shadowParams.y * clamp(1.0 - dot(dVertexNormalW, -dLightDirNormW), 0.0, 1.0) * distScale;
633:	
634:		_getShadowCoordPersp(shadowMatrix, shadowParams, wPos);
635:	}
636:	
637:	void getShadowCoordOrthoNormalOffset(mat4 shadowMatrix, vec3 shadowParams) {
638:		vec3 wPos = vPositionW + dVertexNormalW * shadowParams.y * clamp(1.0 - dot(dVertexNormalW, -dLightDirNormW), 0.0, 1.0); //0.08
639:	
640:		_getShadowCoordOrtho(shadowMatrix, shadowParams, wPos);
641:	}
642:	void normalOffsetPointShadow(vec4 shadowParams) {
643:		float distScale = length(dLightDirW);
644:		vec3 wPos = vPositionW + dVertexNormalW * shadowParams.y * clamp(1.0 - dot(dVertexNormalW, -dLightDirNormW), 0.0, 1.0) * distScale; //0.02
645:		vec3 dir = wPos - dLightPosW;
646:		dLightDirW = dir;
647:	}
648:	float getLightDiffuse() {
649:		return max(dot(dNormalW, -dLightDirNormW), 0.0);
650:	}
651:	// Energy-conserving (hopefully) Blinn-Phong
652:	float calcLightSpecular(float tGlossiness, vec3 tNormalW) {
653:		vec3 h = normalize( -dLightDirNormW + dViewDirW );
654:		float nh = max( dot( h, tNormalW ), 0.0 );
655:	
656:		float specPow = exp2(tGlossiness * 11.0); // glossiness is linear, power is not; 0 - 2048
657:		specPow = antiAliasGlossiness(specPow);
658:	
659:		// Hack: On Mac OS X, calling pow with zero for the exponent generates hideous artifacts so bias up a little
660:		specPow = max(specPow, 0.0001);
661:	
662:		return pow(nh, specPow) * (specPow + 2.0) / 8.0;
663:	}
664:	
665:	float getLightSpecular() {
666:		return calcLightSpecular(dGlossiness, dNormalW);
667:	}
668:	
669:	float getLightSpecularCC() {
670:		return calcLightSpecular(ccGlossiness, ccNormalW);
671:	}
672:	vec3 combineColor() {
673:		return mix(dAlbedo * dDiffuseLight, dSpecularLight + dReflection.rgb * dReflection.a, dSpecularity);
674:	}
675:	void addAmbient() {
676:		dDiffuseLight += light_globalAmbient;
677:	}
678:	void getViewDir() {
679:		dViewDirW = normalize(view_position - vPositionW);
680:	}
681:	void getReflDir() {
682:		dReflDirW = normalize(-reflect(dViewDirW, dNormalW));
683:	}
684:	void main(void) {
685:		dDiffuseLight = vec3(0);
686:		dSpecularLight = vec3(0);
687:		dReflection = vec4(0);
688:		dSpecularity = vec3(0);
689:	
690:		#ifdef CLEARCOAT
691:		ccSpecularLight = vec3(0);
692:		ccReflection = vec4(0);
693:		#endif
694:		 dVertexNormalW = normalize(vNormalW);
695:		 dAlpha = 1.0;
696:		 getViewDir();
697:		 getNormal();
698:		 getReflDir();
699:		 getAlbedo();
700:		 getSpecularity();
701:		 getGlossiness();
702:		 getFresnel();
703:		 addAmbient();
704:		 dLightDirNormW = light0_direction;
705:		 dAtten = 1.0;
706:				 dAtten *= getLightDiffuse();
707:	getShadowCoordOrthoNormalOffset(light0_shadowMatrix, light0_shadowParams);
708:	fadeShadow(light0_shadowCascadeDistances);
709:				 dAtten *= getShadowPCF3x3(light0_shadowMap, light0_shadowParams);
710:				 dDiffuseLight += dAtten * light0_color;
711:				 dSpecularLight += getLightSpecular() * dAtten * light0_color;
712:	
713:	
714:		#ifdef CLEARCOAT
715:		gl_FragColor.rgb = combineColorCC();
716:		#else
717:		gl_FragColor.rgb = combineColor();
718:		#endif 
719:	
720:		gl_FragColor.rgb += getEmission();
721:		gl_FragColor.rgb = addFog(gl_FragColor.rgb);
722:	
723:		#ifndef HDR
724:		gl_FragColor.rgb = toneMap(gl_FragColor.rgb);
725:		gl_FragColor.rgb = gammaCorrectOutput(gl_FragColor.rgb);
726:		#endif
727:	gl_FragColor.a = 1.0;
728:	
729:	}
730:	

ERROR: 0:262: 'UV' : undeclared identifier
ERROR: 0:262: 'texture' : no matching overloaded function found
ERROR: 0:270: 'UV' : undeclared identifier
ERROR: 0:270: 'texture' : no matching overloaded function found

For UV (tex) coordinates to be included to the shader you need to instruct somehow the shader to do that. The easiest way is to assign a texture to at least one material channel.

If you are using only the emissive channel, then reference a texture on that channel and your shader will work:

2 Likes

Thank you for clearing this up. Adding the texture to the emissive slot made it work.

1 Like