【问题标题】:Replace Color With Texture in WebGL在 WebGL 中用纹理替换颜色
【发布时间】:2011-12-26 18:40:41
【问题描述】:

在视频游戏中,仅应用颜色以帮助加快加载过程。纹理准备好后,它们会替换当前颜色。 WebGL 有没有办法做到这一点?到目前为止我看到的所有教程都只展示了如何加载颜色或纹理(不是一个接一个)。

我猜每个形状的缓冲区都需要在其纹理完全加载后进行更改。我假设这是通过纹理可用的 AJAX 调用键入的,然后通过某种 JavaScript 函数应用。 WebGL 是否有内置的方式来执行此操作而无需复杂的图像加载过程?

【问题讨论】:

  • 好的,几个月后阅读了我自己的问题后,我明白了我在问什么。要完全回答我自己的问题,请阅读下文。要同时加载纹理和颜色,您需要两组 x-fragment 和 x-vertex 脚本。一个用于颜色,另一个用于纹理。由于它们是通过 DOM 引入的,因此您只需在初始化对象时使用正确的着色器 ID。可以是颜色或纹理。希望这可以帮助像我一样无知的 WebGL 鞋底。

标签: html html5-canvas webgl


【解决方案1】:

这实际上非常简单,无需 WebGL 专门为此提供任何功能,这是您可以从 DOM API 中免费获得的东西。当您加载图像时,无论如何您都必须实现它们的“onload”回调,因为图像加载是异步的。因此,只需将需要运行的任何代码都放入那个“onload”回调中以从纯色切换到纹理。

【讨论】:

    【解决方案2】:

    在我看到的大多数游戏中,您描述的行为通常会从逐顶点着色或非常低分辨率的纹理开始,并在可用时“混合”成完整的纹理。这种平滑的过渡很棘手,但如果你想要的只是从一个快速“弹出”到另一个,那应该不会太麻烦。

    我会采取的基本路线是创建一个顶点缓冲区,它同时具有纹理坐标和颜色信息,以及两个不同的着色器。一个着色器将使用颜色信息,另一个将忽略它并使用纹理。纹理准备好后,您会通知网格开始使用基于纹理的网格。

    至于检测图片加载,一点都不难,甚至不需要 AJAX:

    var image = new Image();
    image.addEventListener("load", function() {
        // Image is done loading, push to texture
        gl.bindTexture(gl.TEXTURE_2D, texture);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
        // Set up any other state needed, such as switching the shader for the mesh
    }, true);
    image.src = src;
    

    我不确定在不发布非常大的代码块的情况下我还能在这个主题上提供多少帮助,但如果你还在苦苦挣扎,我可以详细说明其他一些部分。

    【讨论】:

    • 比我想象的要简单得多。当您说“两个不同的着色器”时,您是在谈论设置的初始着色器吗?如果是这样,我猜绘图功能需要在某个时候切换齿轮并从纹理输出。
    • 我不完全确定您所说的“初始着色器”是什么意思。您使用的是特定教程或框架吗?
    • 实际上是从零开始构建我自己的 WebGL 引擎,它遵循了 Mozilla 的 WebGL 教程中的许多想法和原则。初始着色器是指在设置 WebGL 时用于从 DOM 中抓取和存储着色器元素的那个(如果我没记错的话)。
    • 好的,所以您只需在 DOM 中定义第二个着色器。解析和编译它的工作方式与您现在拥有的着色器相同,您只需要在运行时决定在调用 gl.useShader(); 时使用哪个着色器
    • 这更有意义, gl.useShader() 是我需要的。谢谢!
    【解决方案3】:

    我会采取的方法如下

    loadTexture(url, initialColor) {
    
      var tex = gl.createTexture();
    
      // start with a single color.
      gl.bindTexture(gl.TEXTURE_2D, tex);
      var pixel = new Uint8Array(initialColor);
      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, pixel);
    
      // start loading the image
      var img = new Image();
      img.onload = function() {
    
        // when the image has loaded update the texture.          
        gl.bindTexture(gl.TEXTURE_2D, tex);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
        gl.generateMipmap(gl.TEXTURE_2D);
      }
      img.src = url;
      return tex;
    }
    
    // Load a tree texture, use brown until the texture loads.
    var treeTexture = loadTexture("tree.png", [255, 200, 0, 255]);
    // Load a water texture, use blue until it loads.  
    var waterTexture = loadTexture("water.jpg", [0, 0, 255, 255]);
    

    http://webglsamples.googlecode.com 上的大多数示例都是这样工作的,尽管它们都默认为蓝色纹理。

    您可以轻松地将这个想法扩展为使用纯色,加载低分辨率纹理,然后在完成后加载高分辨率纹理。

    注意:上面的代码假设您正在加载 2 次幂纹理。如果不是,您需要正确设置纹理参数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-05-26
      • 1970-01-01
      • 2021-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多