渲染到webgl中的纹理

时间:2014-01-31 20:36:30

标签: 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 个答案:

答案 0 :(得分:3)

我看到了几个可能的问题。

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.generateMipmap后需要致电rttTexture

3)您需要将视口设置为与renderbuffer的大小相匹配。你已将该行注释掉了。

其他小问题。

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

5)没有gl.viewportWidthgl.viewportHeight这样的属性。我确定那些设置在某个地方,但为什么在实际存在的时候制造假物业呢?使用gl.drawingBufferWidthgl.drawinBufferHeightgl.canvas.widthgl.canvas.height。这些都是现场

6)查找统一和属性位置很慢,所以你应该只查看一次。就像现在一样,他们正在寻找行中的每一帧

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