[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Public WebGL] Default WebGL sampler precission

On Aug 10, 2011, at 8:32 AM, Jonathan Feldstein wrote:

Is the goal of WebGL to have content appear as visually identical as possible across platforms? If so, should the default sampler precision on embedded and non-embedded platforms be treated the same way?
To be more specific, the following sample http://learningwebgl.com/lessons/lesson15/index.html looks different on desktop and mobile platforms due to the fact that on desktop sampler precision is ignored, while on mobile platforms sampler2D precision defaults to lowp.
I’m not quite sure what to suggest as a good fix to this problem, but it does seem like a bit of a uniformity issue.

The only thing we could do would be to mandate that all WebGL shaders behave as though their variables had the exact width stated in the precision specifier. This could probably be done with extra code (injected by ANGLE), but it wouldn't be very practical. It would add significant overhead and it would be difficult or impossible to know whether or not such extra code was needed.

The only practical way to "solve" this problem is for authors to adhere to the specified precision. The content specifies 'highp' precision on the fragment shader which seems like it should make it work the same. The two problems with the statement I made are 1) OpenGL ES implementations are not required to support highp in the fragment shader, and 2) even if highp is supported it could have less precision that a desktop GPU. 

On iPhone 4 the content does look different. It looks like this line is the culprit:

shininess = texture2D(uSpecularMapSampler, vec2(vTextureCoord.s, vTextureCoord.t)).r * 255.0;

On iPhone this behaves as though the multiplication by 255.0 is never performed, leaving shininess with values between 0 and 1, and causing the artifacts I'm seeing. Changing the above line to:

float shade = texture2D(uSpecularMapSampler, vec2(vTextureCoord.s, vTextureCoord.t)).r;
shininess = shade * 255.0;

solves the problem, but I don't understand why. I thought the single line version would convert the sampler output to a float (because of the multiplication by a float), so it should do the same thing. But not even an explicit cast of the sampler output, as in:

shininess = float(texture2D(uSpecularMapSampler, vec2(vTextureCoord.s, vTextureCoord.t)).r) * 255.0;

fixes the problem. I'm not sure if this is a bug in the Imagination driver or a subtlety of the spec I'm not aware of. Any GLSL experts out there know the answer?

Anyway, I think the best we could do is to add some non-normative language to the spec about the fact that highp is not mandated for fragment shaders and for authors to be careful about ranges.