javascript - 在 webgl 中渲染到纹理

标签 javascript opengl-es webgl

我正在尝试在纹理上渲染我的场景(立方体)。然后我想用这个纹理渲染同一个立方体。 (请参阅最后的编辑) 我是 webgl 和 javascript 的新手。我用过this webpage作为一个开始。我还阅读并使用 this

纹理似乎已正确创建(没有错误或警告),但 the result不是我所期望的。

good image bad image

第一张图片是具有“真实”纹理的立方体。第二张图片是使用创建的纹理渲染的立方体。 (两张图像均渲染无错误或警告)

由于某种原因,我无法在没有收到警告的情况下调用 gl.viewport (没有显示任何内容):

  RENDER WARNING: texture bound to texture unit 0 is not renderable. It maybe non-power-of-2 and have incompatible texture filtering or is not 'texture complete'

我的问题可能与此相关,但我不知道如何解决此问题。

代码的重要部分:

function drawScene() { 
  gl.bindFramebuffer(gl.FRAMEBUFFER, rttFramebuffer);
  drawOnCube();
  gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
  [...]
  gl.activeTexture(gl.TEXTURE0);
  gl.bindTexture(gl.TEXTURE_2D, rttTexture);    //rttTexture is the created texure
  gl.uniform1i(gl.getUniformLocation(shaderProgram, "uSampler"), 0);
  [...]
}

rq:绘制场景与drawOnCube相同,除了前3行和使用的纹理之外。

function drawOnCube(){

  //gl.viewport(0, 0, rttFramebuffer.width, rttFramebuffer.height);  //
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  perspectiveMatrix = makePerspective(45, rttFramebuffer.width/rttFramebuffer.height, 0.1, 300.0);
  loadIdentity();
  mvTranslate([-0.0, 0.0, -6.0]);
  mvPushMatrix();
  mvRotate(cubeRotation, [1, 0, 1]);

  // Draw the cube by binding the array buffer to the cube's vertices
  // array, setting attributes, and pushing it to GL.

  gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesBuffer);
  gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
  gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesTextureCoordBuffer);
  gl.vertexAttribPointer(textureCoordAttribute, 2, gl.FLOAT, false, 0, 0);

  // Specify the texture to map onto the faces.

  gl.activeTexture(gl.TEXTURE0);
  gl.bindTexture(gl.TEXTURE_2D, cubeTexture);
  gl.uniform1i(gl.getUniformLocation(shaderProgram, "uSampler"), 0);

  // Draw the cube.

  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVerticesIndexBuffer);
  setMatrixUniforms();
  gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);
}

创建frameBuffer、renderBuffer的函数:

function initTextureFramebuffer(){
  rttFramebuffer = gl.createFramebuffer();
  gl.bindFramebuffer(gl.FRAMEBUFFER, rttFramebuffer);
  rttFramebuffer.width = 256;
  rttFramebuffer.height = 256;

  rttTexture = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, rttTexture);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, rttFramebuffer.width, rttFramebuffer.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
  gl.generateMipmap(gl.TEXTURE_2D);

  var renderbuffer = gl.createRenderbuffer();
  gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
  gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, rttFramebuffer.width, rttFramebuffer.height);

  gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, rttTexture, 0);
  gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderbuffer);

  gl.bindTexture(gl.TEXTURE_2D, null);
  gl.bindRenderbuffer(gl.RENDERBUFFER, null);
  gl.bindFramebuffer(gl.FRAMEBUFFER, null);
}

编辑:我用硬编码值替换了 gl.viewportWidth 和 gl.viewportHeight 。我仍然收到警告,但显示了立方体。该纹理似乎一次在一个面上使用,并且在大多数情况下(当立方体旋转时)是“不完整的”。 Pictures. 我检查了我的 TextCoordBuffer,看起来没问题。 我尝试仅渲染立方体的一个面,但仍然遇到问题。

最佳答案

我发现几个可能的问题。

1) cubeTexture 在哪里定义的?我只看到 rttTexture

2) rttTexture 需要 mip 贴图,因为将 gl.TEXTURE_MIN_FILTER 设置为 gl。 LINEAR_MIPMAP_NEAREST 但在渲染后,它只会在第一个 mip(级别 0)中包含立方体。您需要通过将 gl.TEXTURE_MIN_FILTER 设置为 gl.LINEARgl.NEAREST 来关闭 mips,或者需要调用 gl渲染到 rttTexture 后的 .generateMipmap

3) 您需要设置视口(viewport)以匹配渲染缓冲区的大小。您已将该行注释掉。

其他小问题。

4) 为 WebGL 对象分配属性(例如 rttFramebuffer.width) 如果您决定处理 WebGLContextLost 事件,则必须修复该代码,因为当上下文丢失后,gl.create 函数将返回 null,并且尝试向 null 添加属性的代码将会崩溃

5) 没有像 gl.viewportWidthgl.viewportHeight 这样的属性。我确信这些是在某个地方设置的,但是当活生生的东西确实存在时,为什么要制作一个假属性(property)呢?使用gl.drawingBufferWidth和gl.drawinBufferHeight或gl.canvas.width和gl.canvas.height。这些都是直播

6) 查找制服和属性位置很慢,因此您应该只查找一次。现在,他们正在排队的每一帧中查找

 gl.uniform1i(gl.getUniformLocation(shaderProgram, "uSampler"), 0);

关于javascript - 在 webgl 中渲染到纹理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21489594/

相关文章:

c++ - 尽管不支持 S3TC,但 DXT 纹理仍然有效

android - 在 MALI 400 上让 SurfaceTexture 与 Android Videoplayer 一起工作时出现问题

html - Webgl使用视口(viewport)+剪刀更新区域

javascript - Three.js为行星添加高分辨率纹理的方法

javascript - 将网址/路径插入谷歌地图标记,Laravel

javascript - 为什么这个 JavaScript 数组 for 循环不像字面版本那样工作?

iphone - OpenGL ES 推荐的背景图像显示方式

javascript - Postman 上带有 base64 字符串的无效 JSON 数据

javascript - 使用javascript动态控制多个潜水风格的风格,使用类

html - threejs Canvas todataurl 是空白的