I have been trying to figure out how to get my project to work on mobile devices, but I came across a very weird problem, and the fix I do not fully understand. I change my float type when a mobile device is detected for all of my WebGlRenderTargets, and my simulation that pings pongs my texture to THREE.HalfFloatType. When I run on mobile and keep the DataTexture as THREE.FloatType, and have everything else change to THREE.HalfFloatType it works, but if my DataTexture uses THREE.HalfFloatType it breaks.
I will give my basics of code for an example.
Creating my data Texture:
// Each object has an x, y, z, and w
let positions = new Float32Array(this.size * this.size * 4);
let r = 100;for (var j = 0; j < positions.length; j += 4) { positions[j + 0] = -r + Math.random() * (r - (-r)); positions[j + 1] = -r + Math.random() * (r - (-r)); positions[j + 2] = -r + Math.random() * (r - (-r)); positions[j + 3] = Math.random() * 100; } this.posTexture = new THREE.DataTexture(positions, this.size, this.size, THREE.RGBAFormat, THREE.FloatType); this.posTexture.needsUpdate = true;
If I switch my THREE.FloatType in the DataTexture to THREE.HalfFloatType it will give me this warning, and I tried changing to a Uint16Array and could not get it to work.
WebGL: INVALID_OPERATION: texImage2D: type HALF_FLOAT_OES but ArrayBufferView is not NULL and not Uint16Array
RENDER WARNING: texture bound to texture unit 1 is not renderable. It maybe non-power-of-2 and have incompatible texture filtering.
Then in all of my shaders I use precision highp float, and when I was testing how well mediump works on mobile it just messes everything up, but I do not think this is apart of the issue. I want to know why the DataTexture with THREE.FloatType will still work on mobile, but if I switch to THREE.HalfFloatType it breaks. All the data in the positions looks like this for values in the DataTexture: 0: -99.54922485351562, 1:-66.3533935546875, 2:75.77011108398438 and so on.
Here are my shaders if you want to see those. My simulation uses the sim shaders, and my mesh uses the material shaders.
public materialVertexShader = `
precision highp float;
attribute vec3 position;
attribute vec3 normal;
attribute vec2 uv;
attribute vec2 lookup;
uniform mat4 modelMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform mat3 normalMatrix;
uniform sampler2D curPos;
uniform sampler2D prevPos;
varying vec2 vUv;
void main() {
vUv = uv;
vec2 luv = lookup;
vec4 i = texture2D( curPos, luv );
vec4 p = texture2D( prevPos, luv );
vec3 vPosition = position;
vPosition += mix(p.xyz, i.xyz, .5);
gl_Position = projectionMatrix * modelViewMatrix * vec4( vPosition, 1.0 );;
}
`;
public materialFragmentShader = `
precision highp float;
varying vec2 vUv;
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;
public simVertexShader = `
precision highp float;
attribute vec3 position;
attribute vec2 uv;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1. );
}
`;
public simFragmentShader = `
precision highp float;
uniform sampler2D source;
uniform sampler2D seed;
uniform vec2 resolution;
uniform float time;
uniform float persistence;
uniform float speed;
uniform float decay;
uniform float spread;
uniform float init;
varying vec2 vUv;
void main() {
vec4 s = texture2D(source,vUv);
if( s.w <= 0. ) {
s = texture2D(seed,vUv);
//s.xyz *= spread;
if( init == 0. ) s.w = 100.;
}else{
s.xyz += .1;
s.w -= decay;
}
gl_FragColor = s;
}
`;
If you have any ideas let me know.