Problem
The PNG supports 4 channels called RGBA
, and we usually use the alpha channel for opacity.
But there is a different usecase to the alpha channel, the emissive intensity. The finally color will be added to the emissive color * emissive intensity
.
In the fragment shader it would look like:
|
|
Let’s generate a PNG image to render.
|
|
Save the code to random-png.js
, and run npm i ndarray save-pixels
to install dependencies.
Run node random-png.js > random.png
to get the random.png
.
The below tables show the results in different browsers.
Original | Your browser | macOS Chrome | macOS Safari | iOS Safari |
---|---|---|---|---|
The result of iOS Safari
seems so different, all pixels with 0 alpha become black.
It seems iOS Safari did the wrong premultiplication on images.
Solutions
Is there any way to solve the problem?
Yes, I came up with 3 solutions:
- Do not do this. If you want 4 channels and alpha channel is not for opacity, then just use two textures.
- Do not use image, you can put image data into a binary file and read it as a
Uint8Array
and load it into a texture. - Use a PNG decoder to directly decode the image, then you can get a clear image data.