WebGL is based on the OpenGL ES 2.0 specification, and retains the semantics of OpenGL ES in order to maximize portability to mobile devices. There are some significant differences in behavior of similar APIs between OpenGL ES 2.0 and the OpenGL API on desktop systems. Many OpenGL programmers are familiar with the semantics on the desktop, and may not know about these differences in behavior. We highlight them here for clarity.
Contents
[
hide
]
Non-Power of Two Texture Support
While OpenGL 2.0 and later for the desktop offer full support for non-power-of-two (NPOT) textures, OpenGL ES 2.0 and WebGL have only limited NPOT support. The restrictions are defined in Sections 3.8.2, "Shader Execution", and 3.7.11, "Mipmap Generation", of the
OpenGL ES 2.0 specification
, and are summarized here:
-
generateMipmap(target)
generates an INVALID_OPERATION error if the level 0 image of the texture currently bound to
target
has an NPOT width or height.
-
Sampling an NPOT texture in a shader will produce the RGBA color (0, 0, 0, 1) if:
-
The minification filter is set to anything but NEAREST or LINEAR: in other words, if it uses one of the mipmapped filters.
-
The repeat mode is set to anything but CLAMP_TO_EDGE; repeating NPOT textures are not supported.
If your application doesn't require the REPEAT wrap mode, and can tolerate the lack of mipmaps, then you can simply configure the WebGLTexture object appropriately at creation time:
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
However, if your application requires the REPEAT wrap mode for correctness, you can easily resize the image to the next largest power of two dimensions using DOM APIs. Here is an example of how to do this.
image
is an HTML image object that has been fully loaded; its
onload
handler has already been called.
function createTextureFromImage(image) {
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
if (!isPowerOfTwo(image.width) || !isPowerOfTwo(image.height)) {
// Scale up the texture to the next highest power of two dimensions.
var canvas = document.createElement("canvas");
canvas.width = nextHighestPowerOfTwo(image.width);
canvas.height = nextHighestPowerOfTwo(image.height);
var ctx = canvas.getContext("2d");
ctx.drawImage(image, 0, 0, image.width, image.height);
image = canvas;
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
gl.generateMipmap(gl.TEXTURE_2D);
gl.bindTexture(gl.TEXTURE_2D, null);
return texture;
function isPowerOfTwo(x) {
return (x & (x - 1)) == 0;
function nextHighestPowerOfTwo(x) {
--x;
for (var i = 1; i < 32; i <<= 1) {
x =
x | x >> i;
return x + 1;
If your application allows, you can also resize your source images offline.
Vertex Attribute 0
On desktop GL, vertex attribute 0 has special semantics. First, it must be enabled as an array, or no geometry will be drawn. Second, it does not have persistent state, so calling glGetVertexAttribfv(0, GL_CURRENT_VERTEX_ATTRIB, ...) generates an OpenGL error.
On OpenGL ES 2.0, vertex attribute 0 has no special semantics.
WebGL follows the OpenGL ES 2.0 convention; all vertex attributes behave identically. This requires implementations on desktop GL to perform a certain amount of emulation, but this was considered to be a small price to pay for consistent behavior.
No double-precision floating-point support
OpenGL ES 2.0 does not support the GL_DOUBLE data type, either for vertex attributes or texture data. This means that the Typed Array view type Float64Array is not currently useful in conjunction with the WebGL API.
No 3D Texture support
OpenGL ES 2.0 does not support 3D textures. It is possible to emulate 3D textures with 2D textures.
// tex is a texture with each slice of the cube placed horizontally across the texture.
// texCoord is a 3d texture coord
// size is the size if the cube in pixels.
vec4 sampleAs3DTexture(sampler2D tex, vec3 texCoord, float size) {
float sliceSize = 1.0 / size; // space of 1 slice
float slicePixelSize = sliceSize / size; // space of 1 pixel
float sliceInnerSize = slicePixelSize * (size - 1.0); // space of size pixels
float zSlice0 = min(floor(texCoord.z * size), size - 1.0);
float zSlice1 = min(zSlice0 + 1.0, size - 1.0);
float xOffset = slicePixelSize * 0.5 + texCoord.x * sliceInnerSize;
float s0 = xOffset + (zSlice0 * sliceSize);
float s1 = xOffset + (zSlice1 * sliceSize);
vec4 slice0Color = texture2D(tex, vec2(s0, texCoord.y));
vec4 slice1Color = texture2D(tex, vec2(s1, texCoord.y));
float zOffset = mod(texCoord.z * size, 1.0);
return mix(slice0Color, slice1Color, zOffset);
You can see this in use in this sample. There's an explanation of how it works here.
Here's another where each slice is placed in a grid. For example an 8x8x8 cube might be a texture that is 4x2 slices, each slice 8x8 pixels
// tex is a texture with each slice of the cube placed in grid in a texture.
// texCoord is a 3d texture coord
// size is the size if the cube in pixels.
// slicesPerRow is how many slices there are across the texture
// numRows is the number of rows of slices
vec2 computeSliceOffset(float slice, float slicesPerRow, vec2 sliceSize) {
return sliceSize * vec2(mod(slice, slicesPerRow),
floor(slice / slicesPerRow));
vec4 sampleAs3DTexture(
sampler2D tex, vec3 texCoord, float size, float numRows, float slicesPerRow) {
float slice = texCoord.z * size;
float sliceZ = floor(slice); // slice we need
float zOffset = fract(slice); // dist between slices
vec2 sliceSize = vec2(1.0 / slicesPerRow, // u space of 1 slice
1.0 / numRows); // v space of 1 slice
vec2 slice0Offset = computeSliceOffset(sliceZ, slicesPerRow, sliceSize);
vec2 slice1Offset = computeSliceOffset(sliceZ + 1.0, slicesPerRow, sliceSize);
vec2 slicePixelSize = sliceSize / size; // space of 1 pixel
vec2 sliceInnerSize = slicePixelSize * (size - 1.0); // space of size pixels
vec2 uv = slicePixelSize * 0.5 + texCoord.xy * sliceInnerSize;
vec4 slice0Color = texture2D(tex, slice0Offset + uv);
vec4 slice1Color = texture2D(tex, slice1Offset + uv);
return mix(slice0Color, slice1Color, zOffset);
return slice0Color;
See example here
texture2DLod
GLSL texture functions that end in "Lod" (eg texture2DLod) are only permitted in the vertex shader.
Precision Qualifiers
Precision qualifiers for variables in shaders are significant in GLSL ES. In contrast, on desktop systems, the maximum precision is often used even for lower-precision variables. This implies that the effects of precision qualifiers can often only be seen by testing content on mobile devices.
Per the OpenGL ES 2.0 specification, the built-in macro GL_FRAGMENT_PRECISION_HIGH is defined to one on systems supporting highp precision in the fragment language. Developers wishing to use the highest available precision in their fragment shaders are encouraged to write:
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
Otherwise, if the highest precision is not absolutely required, then this unconditional declaration in the fragment shader:
precision mediump float;
will achieve the best portability. Testing should still be done on mobile devices to ensure no rendering artifacts are visible because of the use of lower precision than on desktop systems.
Use non-power-of-two (
NPOT)
textures when appropriate
No performance penalty
Saves memory
无二
次幂限制的
纹理(Non-Power-of-Two
Textures)
OpenGL仅支持分辨率为2mx2n的
纹理。但现在我们可以使用“无二
次幂限制”的
纹理。
如果对three.js一无所知的同学可以先看一篇关于three.js的介绍(什么是three.js):
https://blog.csdn.net/doupi520/article/details/53907179
photo-sphere-viewer介绍可以直接看官网:
https://photo-sphere-viewer.js.org/
doT.js JS模板语言,...
gl.pixelStorei(gl.UNPACK_FLIP_Y_
WEBGL,1);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D,texture);
gl.t.
unity 可以通过修改图片格式来减少包体大小,不同平台对不用格式图片的加载速度,也有差别.在开发
WebGl是因为没有开发好的工具,要对图片进行一个处理,自己写了一个脚本工具类,来进行图片适配
WebGl端.
最后的效果,用过选择文件夹来处理文件夹下的图片,不用人工一张一张设置了.
先创建一个TextureImportChanging类,继承EditorWindow类.
主要方法:先设置一个设置图片格式的界面,
using UnityEngine;
using UnityEditor;
texture bound to texture unit 0 is not renderable. It maybe non-power-of-2 and have incompatible tex
解决办法:有可能是你加载的图片不是2的
幂次方尺寸的图片,然后你又在代码中使用了必须使用2的
幂次方尺寸
纹理才能做的特效,比如渐进
纹理mipmap,还有可能是你的图片还没加载完成,你就开始使用了,这个时候需要等待加载完毕
1. 简介
在PC上开发时,其天空盒的效果很好,但是为Android平台Build之后,其效果简直没法看。
更为恼火的是,之后PC上的纹理效果也变差了,新加入的纹理效果都会变差,看其纹理格式,使用ETC进行了压缩。
2. Unity3D默认纹理格式问题
2.1 在导入时是否自动压缩
Edit->Preferences...
当选择此选项之后,每当导入新的