简体   繁体   English

在WebGL中渲染到纹理

[英]Rendering to texture in webgl

I'm trying to render my scene (a cube) on a texture. 我正在尝试在纹理上渲染场景(立方体)。 Then I'd like to render the same cube with this texture. 然后,我想用此纹理渲染相同的立方体。 (see edit at the end) I'm new to webgl and javascript. (请参阅最后的编辑 )我是webgl和javascript的新手。 I used this webpage as a start. 我以这个网页为起点。 I also read and use this . 我也阅读并使用了

The texture seems to be created properly (no errors or warnings) but the result is not the one I expected. 纹理似乎创建正确(没有错误或警告),但结果不是我期望的。

好形象 不好的形象

The first picture is the cube with it's "real" texture. 第一张图片是具有“真实”纹理的立方体。 The second picture is the cube rendered with the created texture. 第二张图片是使用创建的纹理渲染的立方体。 (both images rendered without errors or warnings) (两种图像均无错误或警告)

For some reason I can't call gl.viewport without getting a warning (nothing displayed) : 由于某种原因,我不能在没有得到警告的情况下调用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'

My issue might be related to this but I got no idea how to fix this. 我的问题可能与此有关,但我不知道如何解决此问题。

Important parts of the code: 该代码的重要部分:

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: draw scene is the same as drawOnCube except for the 3 first lines and for the texture used. rq:绘制场景与drawOnCube相同,除了前三行和所使用的纹理。

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);
}

The function which creates the frameBuffer, the renderBuffer: 创建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);
}

EDIT : I replaced gl.viewportWidth and gl.viewportHeight by hardcoded values. 编辑 :我用硬编码值替换了gl.viewportWidth和gl.viewportHeight。 I still got the warning but the cube is displayed. 我仍然收到警告,但显示了多维数据集。 The texture seems to be used on one face at a time and is "incomplete" in most cases (when the cube is rotating). 纹理似乎一次只能在一个面上使用,并且在大多数情况下(立方体旋转时)是“不完整的”。 Pictures. 图片。 I checked my TextCoordBuffer, it looks okay. 我检查了我的TextCoordBuffer,看起来还好。 I tried to render only 1 face of the cube but I still got the issue. 我尝试仅渲染立方体的1个面,但仍然遇到问题。

I see several possible issues. 我看到了几个可能的问题。

1) Where is cubeTexture defined? 1) cubeTexture在哪里定义? I only see rttTexture 我只看到rttTexture

2) rttTexture require mip maps because of setting gl.TEXTURE_MIN_FILTER to gl. LINEAR_MIPMAP_NEAREST 2)由于将gl.TEXTURE_MIN_FILTER设置为gl. LINEAR_MIPMAP_NEAREST rttTexture需要mip映射gl. LINEAR_MIPMAP_NEAREST gl. LINEAR_MIPMAP_NEAREST but after it's been rendered to it will only have the cube in the first mip (level 0). gl. LINEAR_MIPMAP_NEAREST但是渲染到它之后,只会在第一个mip(0级)中包含该多维数据集。 You either need to turn off mips by setting gl.TEXTURE_MIN_FILTER to gl.LINEAR or gl.NEAREST or you need to call gl.generateMipmap after rendering to rttTexture . 你要么需要通过设置来关闭MIPS gl.TEXTURE_MIN_FILTERgl.LINEARgl.NEAREST或者你需要调用gl.generateMipmap渲染后rttTexture

3) You need to set the viewport to match the size of the renderbuffer. 3)您需要设置视口以匹配渲染缓冲区的大小。 You have that line commented out. 您已将该行注释掉。

Other minor issues. 其他小问题。

4) Assigning properties to WebGL objects (eg rttFramebuffer.width ) If you ever decide to handle WebGLContextLost events you'll have to fix that code because when the context is lost the gl.create functions will return null and your code that's trying to add a property to null will crash 4)为WebGL对象分配属性(例如rttFramebuffer.width )如果您决定处理WebGLContextLost事件,则必须修复该代码,因为当上下文丢失时, gl.create函数将返回null并且您尝试添加的代码一个为null的属性将崩溃

5) There's no such property as gl.viewportWidth and gl.viewportHeight . 5)没有诸如gl.viewportWidthgl.viewportHeight这样的属性。 I'm sure those are set up somewhere but why make a fake property when a live ones actually exist? 我敢肯定这些设置在某个地方,但是当实际存在一个活着的房子时,为什么要建一个假房子呢? Use gl.drawingBufferWidth and gl.drawinBufferHeight or gl.canvas.width and gl.canvas.height . 使用gl.drawingBufferWidthgl.drawinBufferHeightgl.canvas.widthgl.canvas.height Those are live 那些是活的

6) Looking up uniform and attribute locations is slow so you should only look them up once. 6)查找制服和属性位置很慢,因此您应该只查找一次。 As it is now they're being looked up every frame in line 现在,他们正在逐行向上查找

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM