WebGL:将8位灰度图像加载到纹理

时间:2017-12-07 01:14:14

标签: javascript webgl

我正在尝试将从我的服务器下载的8位灰度JPG渲染到纹理中以使用WebGL进行渲染。

// Pretend for the sake of example that I have passed in an argument 
// 'img' that is an Image object that I used to download the jpg.
// See the EDIT below for how this happens...

// ...also presume that I have set up my WebGL context and assigned it 
// to the variable 'gl':
// const gl = canvas.getContext('experimental-webgl');

const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);

// Set the parameters so we can render any size image.
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);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);

// Upload the image into the texture.
gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, gl.LUMINANCE, gl.UNSIGNED_BYTE, img);

此时,WebGL对我不屑一顾,并拿走了我的午餐钱:

WebGL: INVALID_VALUE: texImage2D: invalid image

我还有一个问题:什么是MOAR U WANT WebGL?你为什么不快乐???

我可能遗漏了一些基本的东西,但互联网是一堆混乱的WebGL东西,不回答我的问题。这里有任何WebGL大师可以提供建议吗?

这是图片:

8-bit Grayscale JPGs 4LYFE!

修改

以下是有关如何获取图像的更多详细信息。 注意:这样做的原因是我需要一个下载队列,我可以随机播放,取消和重新启动,令人作呕。因此使用了fetch,blob和object URL。整个过程是深度缩放图像查看器的一部分,它应该只有效地加载视口中可见的图像切片(通常会随时改变)。无论如何,这是我得到图像的方式:

// Take care of vendor prefixes:
window.URL = window.URL || window.webkitURL;

// This is where we'll assign our final product
const imageTag = new Image();

imageTag.onerror = (err) => {
  console.error('IMG ERROR:', err);
};
imageTag.onload = () => {
  // Once the image tag has loaded the blob data, clean up our object url:
  window.URL.revokeObjectURL(imageTag.src);

  // imageTag is now passed into the code above as 'img'
};

// Grab the image data as a blob
fetch(`<url_of_image>`)
  .then(res => res.blob())
  .then(blob => {
    // When we get the image data, wrap it in an object url and assign
    // it to src. The onload event won't fire until the next tick.
    imageTag.src = window.URL.createObjectURL(blob);
  });

我应该指出,我最初使用canvas2D API进行渲染,并且能够使用drawImage()方法很好地绘制图像。所以我很确定图像对象加载正常。我实现WebGL渲染器的原因是为更高的性能增强打开了大门。

感谢您的期待!

2 个答案:

答案 0 :(得分:1)

从通过Chromium代码库搜索错误消息字符串并查看struct Activity { string ID; string Name; string quantitiy; }; Activity* fillStructure(ifstream &fileActivity) { int i = 0; int numberOfElements = numberOfLines(fileActivity); Activity* myActivity = new Activity[numberOfElements]; while (i < numberOfElements) { getline(fileActivity, myActivity[i].ID, ','); getline(fileActivity, myActivity[i].Name, ','); getline(fileActivity, myActivity[i].quantitiy, '\n'); i++; } fileActivity.close(); return myActivity; } int main(){ ifstream fileActivity ("test.txt", ifstream::in); Activity* retFile; retFile = fillStructure(fileActivity); cout << retFile[1].ID << endl; return 0; } 引用,似乎它是罪魁祸首。由图像URL表示的图像内容简单地“释放”到早期。解决方案是在调用Activity* retFile; 后致电revokeObjectURL

答案 1 :(得分:1)

好的派对人,我想出来了(至少这样做的一种方法)。

原始流程,我永远无法工作,是:

  1. 以blob格式获取图片数据
  2. 使用ObjectURL将blob传递到src属性
  3. 上的图片代码
  4. 将图片代码传递到texImage2D(旧方法签名)
  5. 对我有用的新流程是:

    1. 将图像数据作为数组缓冲区
    2. 获取
    3. 使用jpeg-js 将jpg数据解码为Uint8Array
    4. 将Uint8Array传递给texImage2D(新方法签名)
    5. 看起来像这样:

      // I am using the decode() method from jpeg-js. Passing true as a second parameter 
      // causes the data to be returned wrapped in a Uint8Array. Even though the data
      // was one channel going in, it's going to come out with all four (RGBA) channels.
      
      import { decode } from 'jpeg-js';
      
      // Like before, please presume a global gl variable to be my WebGL context.
      const gl = '<my-webgl-context-that-I-set-up-elsewhere>';
      
      fetch(`<url_of_image>`)
        .then(res => res.arrayBuffer())
        .then(buffer => {
          // When we get the image data, it's still encoded. We need to decode it
          // before we've got pixel data. We want it as a Uint8Array which will make
          // texImage2D() happy.
          const pixels = decode(buffer, true);
      
          // Set up a new texture where we'll capture and keep the image data
          const texture = gl.createTexture();
          gl.bindTexture(gl.TEXTURE_2D, texture);
      
          // Set the parameters so we can render any size image.
          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);
          gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
          gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
      
          // Upload the image into the texture:
      
          // Here we are telling WebGL how many bytes each pixel will be (I think 
          // think the default is 4, but I thought that this step was important to show).
          gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);
      
          // jpeg-js is kind enough to provide the dimensions of the image data in its
          // returned value. Since jpeg-js returns the data with all 4 channels, we use
          // gl.RGBA here.
          gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, pixels.width, pixels.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels.data);
      
          // Ready to draw!
        });
      

      希望这对未来的某个人有用。感谢所有贡献想法和想法的人,感谢jpeg-js的合作者!