So this shader works on laptop but for some reason it keeps failing on mobile I assume i’m doing something wrong with the precision but i don’t know what here is the error:
THREE.WebGLProgram: shader error: 0 35715 false gl.getProgramInfoLog
invalid shaders THREE.WebGLShader: gl.getShaderInfoLog() fragment
0:434: S0032: no default precision defined for variable 'float[4]'1:
version 300 es 2: #define varying in 3: out highp vec4 pc_fragColor;
and here is the shader code in the js tab:
full:
export const terrain_shader = (function() {
const _VS_1 = `
// Triplanar Attributes
in vec4 weights1;
in vec4 weights2;
// Outputs
out vec3 vCoords;
out vec4 vWeights1;
out vec4 vWeights2;
`;
const _VS_2 = `
vCoords = transformed.xyz;
vWeights1 = weights1;
vWeights2 = weights2;
`;
const _VS = `
// Attributes
in vec3 coords;
in vec3 color;
in vec4 weights1;
in vec4 weights2;
// Outputs
out vec2 vUV;
out vec4 vColor;
out vec3 vNormal;
out vec3 vCoords;
out vec4 vWeights1;
out vec4 vWeights2;
void main(){
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
vUV = uv;
vNormal = normal;
vColor = vec4(color, 1);
vCoords = position.xyz;
vWeights1 = weights1;
vWeights2 = weights2;
}
`;
const _PS = `
precision highp float;
precision highp int;
precision highp sampler2DArray;
uniform sampler2DArray TRIPLANAR_normalMap;
uniform sampler2DArray TRIPLANAR_diffuseMap;
uniform sampler2D TRIPLANAR_noiseMap;
in vec3 vCoords;
in vec4 vWeights1;
in vec4 vWeights2;
const float _TRI_SCALE = 10.0;
float sum( vec3 v ) { return v.x+v.y+v.z; }
vec4 hash4( vec2 p ) {
return fract(
sin(vec4(1.0+dot(p,vec2(37.0,17.0)),
2.0+dot(p,vec2(11.0,47.0)),
3.0+dot(p,vec2(41.0,29.0)),
4.0+dot(p,vec2(23.0,31.0))))*103.0);
}
vec4 _TerrainBlend_4(vec4 samples[4]) {
float depth = 0.2;
float ma = max(
samples[0].w,
max(
samples[1].w,
max(samples[2].w, samples[3].w))) - depth;
float b1 = max(samples[0].w - ma, 0.0);
float b2 = max(samples[1].w - ma, 0.0);
float b3 = max(samples[2].w - ma, 0.0);
float b4 = max(samples[3].w - ma, 0.0);
vec4 numer = (
samples[0] * b1 + samples[1] * b2 +
samples[2] * b3 + samples[3] * b4);
float denom = (b1 + b2 + b3 + b4);
return numer / denom;
}
vec4 _TerrainBlend_4_lerp(vec4 samples[4]) {
return (
samples[0] * samples[0].w + samples[1] * samples[1].w +
samples[2] * samples[2].w + samples[3] * samples[3].w);
}
// Lifted from https://www.shadertoy.com/view/Xtl3zf
vec4 texture_UV(in sampler2DArray srcTexture, in vec3 x) {
float k = texture(TRIPLANAR_noiseMap, 0.0025*x.xy).x; // cheap (cache friendly) lookup
float l = k*8.0;
float f = fract(l);
float ia = floor(l+0.5); // suslik's method (see comments)
float ib = floor(l);
f = min(f, 1.0-f)*2.0;
vec2 offa = sin(vec2(3.0,7.0)*ia); // can replace with any other hash
vec2 offb = sin(vec2(3.0,7.0)*ib); // can replace with any other hash
vec4 cola = texture(srcTexture, vec3(x.xy + offa, x.z));
vec4 colb = texture(srcTexture, vec3(x.xy + offb, x.z));
return mix(cola, colb, smoothstep(0.2,0.8,f-0.1*sum(cola.xyz-colb.xyz)));
}
vec4 _Triplanar_UV(vec3 pos, vec3 normal, float texSlice, sampler2DArray tex) {
vec4 dx = texture_UV(tex, vec3(pos.zy / _TRI_SCALE, texSlice));
vec4 dy = texture_UV(tex, vec3(pos.xz / _TRI_SCALE, texSlice));
vec4 dz = texture_UV(tex, vec3(pos.xy / _TRI_SCALE, texSlice));
vec3 weights = abs(normal.xyz);
weights = weights / (weights.x + weights.y + weights.z);
return dx * weights.x + dy * weights.y + dz * weights.z;
}
vec4 _TriplanarN_UV(vec3 pos, vec3 normal, float texSlice, sampler2DArray tex) {
// Tangent Reconstruction
// Triplanar uvs
vec2 uvX = pos.zy; // x facing plane
vec2 uvY = pos.xz; // y facing plane
vec2 uvZ = pos.xy; // z facing plane
// Tangent space normal maps
vec3 tx = texture_UV(tex, vec3(uvX / _TRI_SCALE, texSlice)).xyz * vec3(2,2,2) - vec3(1,1,1);
vec3 ty = texture_UV(tex, vec3(uvY / _TRI_SCALE, texSlice)).xyz * vec3(2,2,2) - vec3(1,1,1);
vec3 tz = texture_UV(tex, vec3(uvZ / _TRI_SCALE, texSlice)).xyz * vec3(2,2,2) - vec3(1,1,1);
vec3 weights = abs(normal.xyz);
weights = weights / (weights.x + weights.y + weights.z);
// Get the sign (-1 or 1) of the surface normal
vec3 axis = sign(normal);
// Construct tangent to world matrices for each axis
vec3 tangentX = normalize(cross(normal, vec3(0.0, axis.x, 0.0)));
vec3 bitangentX = normalize(cross(tangentX, normal)) * axis.x;
mat3 tbnX = mat3(tangentX, bitangentX, normal);
vec3 tangentY = normalize(cross(normal, vec3(0.0, 0.0, axis.y)));
vec3 bitangentY = normalize(cross(tangentY, normal)) * axis.y;
mat3 tbnY = mat3(tangentY, bitangentY, normal);
vec3 tangentZ = normalize(cross(normal, vec3(0.0, -axis.z, 0.0)));
vec3 bitangentZ = normalize(-cross(tangentZ, normal)) * axis.z;
mat3 tbnZ = mat3(tangentZ, bitangentZ, normal);
// Apply tangent to world matrix and triblend
// Using clamp() because the cross products may be NANs
vec3 worldNormal = normalize(
clamp(tbnX * tx, -1.0, 1.0) * weights.x +
clamp(tbnY * ty, -1.0, 1.0) * weights.y +
clamp(tbnZ * tz, -1.0, 1.0) * weights.z
);
return vec4(worldNormal, 0.0);
}
vec4 _Triplanar(vec3 pos, vec3 normal, float texSlice, sampler2DArray tex) {
vec4 dx = texture(tex, vec3(pos.zy / _TRI_SCALE, texSlice));
vec4 dy = texture(tex, vec3(pos.xz / _TRI_SCALE, texSlice));
vec4 dz = texture(tex, vec3(pos.xy / _TRI_SCALE, texSlice));
vec3 weights = abs(normal.xyz);
weights = weights / (weights.x + weights.y + weights.z);
return dx * weights.x + dy * weights.y + dz * weights.z;
}
vec4 _TriplanarN(vec3 pos, vec3 normal, float texSlice, sampler2DArray tex) {
vec2 uvx = pos.zy;
vec2 uvy = pos.xz;
vec2 uvz = pos.xy;
vec3 tx = texture(tex, vec3(uvx / _TRI_SCALE, texSlice)).xyz * vec3(2,2,2) - vec3(1,1,1);
vec3 ty = texture(tex, vec3(uvy / _TRI_SCALE, texSlice)).xyz * vec3(2,2,2) - vec3(1,1,1);
vec3 tz = texture(tex, vec3(uvz / _TRI_SCALE, texSlice)).xyz * vec3(2,2,2) - vec3(1,1,1);
vec3 weights = abs(normal.xyz);
weights *= weights;
weights = weights / (weights.x + weights.y + weights.z);
vec3 axis = sign(normal);
vec3 tangentX = normalize(cross(normal, vec3(0.0, axis.x, 0.0)));
vec3 bitangentX = normalize(cross(tangentX, normal)) * axis.x;
mat3 tbnX = mat3(tangentX, bitangentX, normal);
vec3 tangentY = normalize(cross(normal, vec3(0.0, 0.0, axis.y)));
vec3 bitangentY = normalize(cross(tangentY, normal)) * axis.y;
mat3 tbnY = mat3(tangentY, bitangentY, normal);
vec3 tangentZ = normalize(cross(normal, vec3(0.0, -axis.z, 0.0)));
vec3 bitangentZ = normalize(-cross(tangentZ, normal)) * axis.z;
mat3 tbnZ = mat3(tangentZ, bitangentZ, normal);
vec3 worldNormal = normalize(
clamp(tbnX * tx, -1.0, 1.0) * weights.x +
clamp(tbnY * ty, -1.0, 1.0) * weights.y +
clamp(tbnZ * tz, -1.0, 1.0) * weights.z);
return vec4(worldNormal, 0.0);
}
void main() {
vec3 worldPosition = vCoords;
float weightIndices[4] = float[4](vWeights1.x, vWeights1.y, vWeights1.z, vWeights1.w);
float weightValues[4] = float[4](vWeights2.x, vWeights2.y, vWeights2.z, vWeights2.w);
// TRIPLANAR SPLATTING w/ NORMALS & UVS
vec3 worldSpaceNormal = normalize(vNormal);
vec4 diffuseSamples[4];
vec4 normalSamples[4];
for (int i = 0; i < 4; ++i) {
vec4 d = vec4(0.0);
vec4 n = vec4(0.0);
if (weightValues[i] > 0.0) {
d = _Triplanar_UV(
worldPosition, worldSpaceNormal, weightIndices[i], TRIPLANAR_diffuseMap);
n = _TriplanarN_UV(
worldPosition, worldSpaceNormal, weightIndices[i], TRIPLANAR_normalMap);
d.w *= weightValues[i];
n.w = d.w;
}
diffuseSamples[i] = d;
normalSamples[i] = n;
}
vec4 diffuseBlended = _TerrainBlend_4(diffuseSamples);
vec4 normalBlended = _TerrainBlend_4(normalSamples);
vec3 diffuse = diffuseBlended.xyz;
vec3 finalColour = diffuse;
// finalColour = vec3(sin(worldPosition.x), sin(worldPosition.y), sin(worldPosition.z));
gl_FragColor = vec4(finalColour, 1);
}
`;
const _PS_1 = `
precision mediump sampler2DArray;
uniform sampler2DArray TRIPLANAR_normalMap;
uniform sampler2DArray TRIPLANAR_diffuseMap;
uniform sampler2D TRIPLANAR_noiseMap;
in vec3 vCoords;
in vec4 vWeights1;
in vec4 vWeights2;
const float _TRI_SCALE = 10.0;
float sum( vec3 v ) { return v.x+v.y+v.z; }
vec4 hash4( vec2 p ) {
return fract(
sin(vec4(1.0+dot(p,vec2(37.0,17.0)),
2.0+dot(p,vec2(11.0,47.0)),
3.0+dot(p,vec2(41.0,29.0)),
4.0+dot(p,vec2(23.0,31.0))))*103.0);
}
vec4 _TerrainBlend_4(vec4 samples[4]) {
float depth = 0.2;
float ma = max(
samples[0].w,
max(
samples[1].w,
max(samples[2].w, samples[3].w))) - depth;
float b1 = max(samples[0].w - ma, 0.0);
float b2 = max(samples[1].w - ma, 0.0);
float b3 = max(samples[2].w - ma, 0.0);
float b4 = max(samples[3].w - ma, 0.0);
vec4 numer = (
samples[0] * b1 + samples[1] * b2 +
samples[2] * b3 + samples[3] * b4);
float denom = (b1 + b2 + b3 + b4);
return numer / denom;
}
vec4 _TerrainBlend_4_lerp(vec4 samples[4]) {
return (
samples[0] * samples[0].w + samples[1] * samples[1].w +
samples[2] * samples[2].w + samples[3] * samples[3].w);
}
// Lifted from https://www.shadertoy.com/view/Xtl3zf
vec4 texture_UV(in sampler2DArray srcTexture, in vec3 x) {
float k = texture(TRIPLANAR_noiseMap, 0.0025*x.xy).x; // cheap (cache friendly) lookup
float l = k*8.0;
float f = fract(l);
float ia = floor(l+0.5); // suslik's method (see comments)
float ib = floor(l);
f = min(f, 1.0-f)*2.0;
vec2 offa = sin(vec2(3.0,7.0)*ia); // can replace with any other hash
vec2 offb = sin(vec2(3.0,7.0)*ib); // can replace with any other hash
vec4 cola = texture(srcTexture, vec3(x.xy + offa, x.z));
vec4 colb = texture(srcTexture, vec3(x.xy + offb, x.z));
return mix(cola, colb, smoothstep(0.2,0.8,f-0.1*sum(cola.xyz-colb.xyz)));
}
vec4 _Triplanar_UV(vec3 pos, vec3 normal, float texSlice, sampler2DArray tex) {
vec4 dx = texture_UV(tex, vec3(pos.zy / _TRI_SCALE, texSlice));
vec4 dy = texture_UV(tex, vec3(pos.xz / _TRI_SCALE, texSlice));
vec4 dz = texture_UV(tex, vec3(pos.xy / _TRI_SCALE, texSlice));
vec3 weights = abs(normal.xyz);
weights = weights / (weights.x + weights.y + weights.z);
return dx * weights.x + dy * weights.y + dz * weights.z;
}
vec4 _TriplanarN_UV(vec3 pos, vec3 normal, float texSlice, sampler2DArray tex) {
// Tangent Reconstruction
// Triplanar uvs
vec2 uvX = pos.zy; // x facing plane
vec2 uvY = pos.xz; // y facing plane
vec2 uvZ = pos.xy; // z facing plane
// Tangent space normal maps
vec3 tx = texture_UV(tex, vec3(uvX / _TRI_SCALE, texSlice)).xyz * vec3(2,2,2) - vec3(1,1,1);
vec3 ty = texture_UV(tex, vec3(uvY / _TRI_SCALE, texSlice)).xyz * vec3(2,2,2) - vec3(1,1,1);
vec3 tz = texture_UV(tex, vec3(uvZ / _TRI_SCALE, texSlice)).xyz * vec3(2,2,2) - vec3(1,1,1);
vec3 weights = abs(normal.xyz);
weights = weights / (weights.x + weights.y + weights.z);
// Get the sign (-1 or 1) of the surface normal
vec3 axis = sign(normal);
// Construct tangent to world matrices for each axis
vec3 tangentX = normalize(cross(normal, vec3(0.0, axis.x, 0.0)));
vec3 bitangentX = normalize(cross(tangentX, normal)) * axis.x;
mat3 tbnX = mat3(tangentX, bitangentX, normal);
vec3 tangentY = normalize(cross(normal, vec3(0.0, 0.0, axis.y)));
vec3 bitangentY = normalize(cross(tangentY, normal)) * axis.y;
mat3 tbnY = mat3(tangentY, bitangentY, normal);
vec3 tangentZ = normalize(cross(normal, vec3(0.0, -axis.z, 0.0)));
vec3 bitangentZ = normalize(-cross(tangentZ, normal)) * axis.z;
mat3 tbnZ = mat3(tangentZ, bitangentZ, normal);
// Apply tangent to world matrix and triblend
// Using clamp() because the cross products may be NANs
vec3 worldNormal = normalize(
clamp(tbnX * tx, -1.0, 1.0) * weights.x +
clamp(tbnY * ty, -1.0, 1.0) * weights.y +
clamp(tbnZ * tz, -1.0, 1.0) * weights.z
);
return vec4(worldNormal, 0.0);
}
vec4 _Triplanar(vec3 pos, vec3 normal, float texSlice, sampler2DArray tex) {
vec4 dx = texture(tex, vec3(pos.zy / _TRI_SCALE, texSlice));
vec4 dy = texture(tex, vec3(pos.xz / _TRI_SCALE, texSlice));
vec4 dz = texture(tex, vec3(pos.xy / _TRI_SCALE, texSlice));
vec3 weights = abs(normal.xyz);
weights = weights / (weights.x + weights.y + weights.z);
return dx * weights.x + dy * weights.y + dz * weights.z;
}
vec4 _TriplanarN(vec3 pos, vec3 normal, float texSlice, sampler2DArray tex) {
vec2 uvx = pos.zy;
vec2 uvy = pos.xz;
vec2 uvz = pos.xy;
vec3 tx = texture(tex, vec3(uvx / _TRI_SCALE, texSlice)).xyz * vec3(2,2,2) - vec3(1,1,1);
vec3 ty = texture(tex, vec3(uvy / _TRI_SCALE, texSlice)).xyz * vec3(2,2,2) - vec3(1,1,1);
vec3 tz = texture(tex, vec3(uvz / _TRI_SCALE, texSlice)).xyz * vec3(2,2,2) - vec3(1,1,1);
vec3 weights = abs(normal.xyz);
weights *= weights;
weights = weights / (weights.x + weights.y + weights.z);
vec3 axis = sign(normal);
vec3 tangentX = normalize(cross(normal, vec3(0.0, axis.x, 0.0)));
vec3 bitangentX = normalize(cross(tangentX, normal)) * axis.x;
mat3 tbnX = mat3(tangentX, bitangentX, normal);
vec3 tangentY = normalize(cross(normal, vec3(0.0, 0.0, axis.y)));
vec3 bitangentY = normalize(cross(tangentY, normal)) * axis.y;
mat3 tbnY = mat3(tangentY, bitangentY, normal);
vec3 tangentZ = normalize(cross(normal, vec3(0.0, -axis.z, 0.0)));
vec3 bitangentZ = normalize(-cross(tangentZ, normal)) * axis.z;
mat3 tbnZ = mat3(tangentZ, bitangentZ, normal);
vec3 worldNormal = normalize(
clamp(tbnX * tx, -1.0, 1.0) * weights.x +
clamp(tbnY * ty, -1.0, 1.0) * weights.y +
clamp(tbnZ * tz, -1.0, 1.0) * weights.z);
return vec4(worldNormal, 0.0);
}
`;
const _PS_2 = `
{
vec3 worldPosition = vCoords;
float weightIndices[4] = float[4](vWeights1.x, vWeights1.y, vWeights1.z, vWeights1.w);
float weightValues[4] = float[4](vWeights2.x, vWeights2.y, vWeights2.z, vWeights2.w);
// TRIPLANAR SPLATTING w/ NORMALS & UVS
vec3 worldSpaceNormal = normalize(vNormal);
vec4 diffuseSamples[4];
// vec4 normalSamples[4];
for (int i = 0; i < 4; ++i) {
vec4 d = vec4(0.0);
// vec4 n = vec4(0.0);
if (weightValues[i] > 0.0) {
d = _Triplanar_UV(
worldPosition, worldSpaceNormal, weightIndices[i], TRIPLANAR_diffuseMap);
// n = _TriplanarN_UV(
// worldPosition, worldSpaceNormal, weightIndices[i], TRIPLANAR_normalMap);
d.w *= weightValues[i];
// n.w = d.w;
}
diffuseSamples[i] = d;
// normalSamples[i] = n;
}
vec4 diffuseBlended = _TerrainBlend_4(diffuseSamples);
// vec4 normalBlended = _TerrainBlend_4(normalSamples);
diffuseColor = sRGBToLinear(diffuseBlended);
// normal = normalBlended.xyz;
}
`;
return {
VS: _VS,
PS: _PS,
VS1: _VS_1,
VS2: _VS_2,
PS1: _PS_1,
PS2: _PS_2,
};
})();
thanks for reading
update I have tried adding:
precision mediump sampler2DArray;
precision mediump float;
precision mediump int;
uniform sampler2DArray TRIPLANAR_normalMap;
uniform sampler2DArray TRIPLANAR_diffuseMap;
uniform sampler2D TRIPLANAR_noiseMap;
to: const _PS_1 and _PS
still the error persists
doing this also throw a new error:
Uniforms with the same name but different type/precision
i was able to make this error go away by adding:
precision mediump float;
to the vertex shaders but i’m still left with the original error of:
no default precision defined for variable 'float[4]'1