WebGL and OpenGL Differences - 非2的次幂纹理的那些讲究儿

WebGL and OpenGL Differences

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.

时间: 2024-10-03 20:52:45

WebGL and OpenGL Differences - 非2的次幂纹理的那些讲究儿的相关文章

WebGL 中 OpenGL ES 指令与 iOS 中 C 版指令的差异简析

WebGL 中 OpenGL ES 指令与 iOS 中 C 版指令的差异简析 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. WebGL 中 OpenGL ES 指令与 iOS 中 C 版指令的

WebGL 规范(WebGL Specification)

WebGL 规范(WebGL Specification) 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. WebGL 规范 WebGL Specification 1.0.2 版,发布于 20

从零开始学习OpenGL ES之六 – 纹理及纹理映射

转自:http://bbs.ityran.com/article-9-1.html [转载]从零开始学习OpenGL ES之六 – 纹理及纹理映射 2011-9-14 23:49| 发布者: Iven| 查看: 9206| 评论: 15 摘要: 图形图像, 编程,编程, OpenGL ES, 教程,OpenGL ES 3D 在OpenGL ES中另一种为多边形定义颜色创建材质的方法是将纹理映射到多边形.这是一种很实用的方法,它可以产生很漂亮的外观并节省大量的处理器时间.比如说,你想在游戏中造一个

12. Html5的局:WebGL跨平台的取与舍

紧接上文 在阅读WebKit源码中,讨论了Canvas在iOS平台使用的CoreGraphics框架作为渲染的工具,它运行在CPU上.WebGL是直接运行在GPU上的API,因此优化空间更大,对程序员要求更高.这次我们看看,WebGL如何对格式转换的,为我们后续three.js导入数据模型做铺设. 常见的纹理格式 OpenGL ES2.0在多终端的差异 在WebKit中,默认支持纹理格式,主要有: 现实却是很残酷,iOS设备以上格式都是支持的,Android设备差异化就不同了,简单的说,要想确认

10. Html5的局:这些年,WebGL替我们做的那些事

(一)Html5新功能 最重要的功能之一当属WebGL了,和3D图形规范OpenGL.通用计算规范OpenCL一样,来自Khronos Group,2011年对外公布,到现在已经开始有WebGL2.0规范的雏形了. 这种绘图技术标准允许把JavaScript和OpenGL ES 2.0结合在一起,为Html5的Canvas提供硬件3D加速渲染,如下图所示:WebGL (二)WebGL与品类繁盛的openXX家族 简单列举一下:OpenGL 1/2/3/4.. OpenGL ES 1/2/3..

180 度大转弯 微软宣布加入 WebGL 工作组

8月12日消息:微软在日前宣布加入Khronos Group和WebGL工作组,这让很多人感到诧异,因为这在几年前是根本无法想像的事. WebGL是基于OpenGL ES和Javascript的一种浏览器3D显示技术规范,而微软在此之前一直是排斥WebGL和OpenGL的,理由 是可能会在安全性方面存在隐患.直到不久前微软才表示支持OpenGL,现在更进一步加入了Khronos Group和WebGL工作组. Khronos Group是由其成员所提供之基金支持的行业协会,专注于创立开放标准,免

WebGL 入门-WebGL简介与3D图形学

什么是WebGL? WebGL是一项使用JavaScript实现3D绘图的技术,浏览器无需插件支持,Web开发者就能借助系统显卡(GPU)进行编写代码从而呈现3D场景和对象. WebGL基于OpenGL ES 2.0,OpenGL ES 是 OpenGL 三维图形 API 的子集,针对手机.平板电脑和游戏主机等嵌入式设备而设计.浏览器内核通过对OpenGL API的封装,实现了通过JavaScript调用3D的能力.WebGL 内容作为 HTML5 中的Canvas标签的特殊上下文实现在浏览器中

opengl_NeNe 第九课,移动图像代码.vs 2010_express OPENGL 2.0

// NeNe_lesson_object.cpp : Defines the entry point for the console application. // // NeNe_lesson2.cpp : Defines the entry point for the console application. // // setup.cpp : Defines the entry point for the console application. // #include "stdafx.

VC运用OPENGL加载BMP纹理图的实现方法汇总_C 语言

OpenGL是专业的图形程序接口,功能非常强大,调用方便的底层图形库.本文汇总了运用OPENGL加载BMP纹理图的几个实现方法. 方法一: 首先获取位图句柄: HBITMAP hBmp = (HBITMAP) ::LoadImage (AfxGetResourceHandle(),MAKEINTRESOURCE(IDB_BITMAP1), IMAGE_BITMAP, 0, 0,LR_CREATEDIBSECTION); 然后根据位图句柄得到位图信息: BITMAP BM; ::GetObject