zoukankan      html  css  js  c++  java
  • WebGL学习笔记(六):纹理贴图

    只可以绘制纯色的模型是不够的,为了呈现出更真实的模型,我们还需要通过纹理贴图给模型进行上色。

    丢失上下文

    GPU作为一种公用资源,是会被多个进程同时使用的,在资源不足的情况下(比如PC或手机系统进入休眠状态前或被唤醒后),我们持有的上下文会出现丢失的情况,为了保证程序运行的健壮性,我们必须在丢失上下文之后做出处理。

    Canvas为我们提供了两个事件来监听,上下文的丢失和恢复,具体使用看下面的代码:

     1 var canvas = document.getElementById("myGLCanvas");
     2 // 监听上下文丢失的事件
     3 canvas.addEventListener("webglcontextlost", function (event) {
     4     // 取消默认行为
     5     event.preventDefault();
     6     // 停止继续绘图的代码
     7 }, false);
     8 // 监听上下文恢复的事件
     9 canvas.addEventListener("webglcontextrestored", function () {
    10     // 重新初始化的代码
    11     // 需要注意的是 Canvas 通过 getContext 方法获得的上下文对象不需要重新获取, 还可以继续使用之前获取的上下文对象
    12     // 开始继续绘图的代码
    13 }, false);

    模拟丢失上下文

    我们要测试丢失上下文的处理代码是否正常,就需要触发丢失上下文,我们可以使用下面的js库来模拟上下文的丢失:

    https://github.com/KhronosGroup/WebGLDeveloperTools

    可以参考其目录下的srcdebuglost-context-simulator-test.html示例来使用。

    2D映射和立方体映射

    我们需要将2D图片贴到3D模型上,需要使用到2D的图片,采用UV坐标来确定3D的面上的一个点可以对应2D图片上的一个像素或多个像素(采样),下面是uv坐标的坐标系:

    (s对应u、t对应v),范围[0-1]。

    立方体映射,是一个包含了6个2D图片的映射,一般用来实现环境映射,或者实现环境反射,下面的示例可以很好的展现环境反射的应用:

    https://threejs.org/examples/#webgl_materials_envmaps

    另外立方体映射还常用于创建天空盒(SkyBox)。

    纹理大小

    我们提交到GPU的图片尺寸的高和宽必须是2的n次方,即(2、4、8、16、32、64、128、256...),不过在OpenGL ES 2.0和WebGL中,我们也可以使用高宽非2的n次方的图片,即NPOT(Non Power Of Two);

    如果我们使用了非2的n次方的图片,会有下面的一些限制:

    • 不能使用MipMap映射;
    • 在着色器中采样纹理贴图时:纹理过滤方式只能用最近点或线性, 不能使用重复模式。

    具体请看:https://www.khronos.org/webgl/wiki/WebGL_and_OpenGL_Differences

    关于y轴翻转

    我们先看看DOM里的Image对象的坐标系和WebGL纹理的坐标系的区别:

    可以发现,两个坐标系的y轴刚好是相反的,所以为了使坐标系一致,我们需要使用下面的代码来翻转y轴:

    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);

    纹理过滤

    我们的纹理图片和将要渲染的区域尺寸是不一定完全一致的,当纹理小于渲染区域时需要纹理伸展,当纹理大于渲染区域时需要纹理收缩;

    MipMap

    当纹理进行伸展过大和收缩过大时,会出现模糊和锯齿,为了解决这个问题,我们可以使用多套尺寸的纹理,来对应不同尺寸的渲染区域,GPU会根据渲染区域的大小自动选择;

    优点

    • 模型无论是远离还是离摄像机较近时,显示都会比较自然;
    • 渲染效率更高;

    缺点

    • 内存使用会增大为单张图片的1/3;

    创建MipMap的方法

    • 提交纹理之后,调用gl.generateMipmap方法WebGL会自动生成指定纹理的MipMap;
    • 通过外部工具,直接将所有的MipMap生成好之后,手动进行提交,该方法一般用于比较特殊的情况,比如不同级别的MipMap纹理图像不一致的情况;

    纹理坐标包装

    • GL_REPEAT: 超出纹理范围的坐标整数部分被忽略,形成重复效果。
    • GL_MIRRORED_REPEAT: 超出纹理范围的坐标整数部分被忽略,但当整数部分为奇数时进行取反,形成镜像效果。
    • GL_CLAMP_TO_EDGE:超出纹理范围的坐标被截取成0和1,形成纹理边缘延伸的效果。

    activeTexture和bindTexture

    gl.activeTexture

    激活当前的操作贴图,指定后续代码操作的贴图是哪一个,参数是枚举gl.TEXTURE0到gl.TEXTURE7(最大值请查看gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS,最少是8);

    后面会调用bindTexture来绑定当前的操作贴图,如果没有调用activeTexture就调用了bindTexture,则默认激活0号纹理单元(可以理解为默认调用了gl.activeTexture(gl.TEXTURE0)代码);

    gl.bindTexture

    绑定指定纹理到activeTexture激活的纹理单元中,同时可以指定该纹理的类型;

    更多详细信息可以参考这里:https://www.jianshu.com/p/1829b4acc58d

    示例

    https://hammerc.github.io/dou3d-ts/learning/learningNotes/lesson_4/index.html

  • 相关阅读:
    不常用的cmd命令
    js获取宽度
    Marshaling Data with Platform Invoke 概览
    Calling a DLL Function 之三 How to: Implement Callback Functions
    Marshaling Data with Platform Invoke 之四 Marshaling Arrays of Types
    Marshaling Data with Platform Invoke 之一 Platform Invoke Data Types
    Marshaling Data with Platform Invoke 之三 Marshaling Classes, Structures, and Unions(用时查阅)
    Calling a DLL Function 之二 Callback Functions
    WCF 引论
    Marshaling Data with Platform Invoke 之二 Marshaling Strings (用时查阅)
  • 原文地址:https://www.cnblogs.com/hammerc/p/11296130.html
Copyright © 2011-2022 走看看