Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Opengl es 如何在webgl中的渲染过程之间传递高精度uv坐标?_Opengl Es_Three.js_Glsl_Webgl_Shader - Fatal编程技术网

Opengl es 如何在webgl中的渲染过程之间传递高精度uv坐标?

Opengl es 如何在webgl中的渲染过程之间传递高精度uv坐标?,opengl-es,three.js,glsl,webgl,shader,Opengl Es,Three.js,Glsl,Webgl,Shader,假设我正在处理WebGL中的一个问题,该问题要求从大纹理中检索值,例如,2048x2048,精度达到像素级 到目前为止,一切都很顺利。我可以将大纹理传递给片段着色器,片段着色器将其转换为渲染目标,我甚至可以将该渲染目标作为另一个渲染过程的输入,始终检索我需要的确切像素 但现在我想把事情搞混。我想创建一个渲染过程,该过程返回一个纹理,该纹理为我开始使用的大纹理中的每个像素存储一对uv坐标。作为最简单的用例,我们假设: precision highp float; precision highp s

假设我正在处理WebGL中的一个问题,该问题要求从大纹理中检索值,例如,2048x2048,精度达到像素级

到目前为止,一切都很顺利。我可以将大纹理传递给片段着色器,片段着色器将其转换为渲染目标,我甚至可以将该渲染目标作为另一个渲染过程的输入,始终检索我需要的确切像素

但现在我想把事情搞混。我想创建一个渲染过程,该过程返回一个纹理,该纹理为我开始使用的大纹理中的每个像素存储一对uv坐标。作为最简单的用例,我们假设:

precision highp float;
precision highp sampler2D;
varying vec2 vUv;

void main() {

    gl_FragColor = vec4(vUv, 0, 1);

}
使用此第一次渲染过程返回的uv坐标,我希望从我开始使用的大纹理中访问一个像素:

precision highp float;
precision highp sampler2D;
uniform sampler2D firstPass;
uniform sampler2D largeTexture;
varying vec2 vUv;

void main() {

    vec2 uv = texture2D(firstPass, vUv);
    gl_FragColor = texture2D(largeTexture, uv);

}
然而,这并不具有足够的精度。我通常会从相邻的像素中得到一种颜色,而不是我想要处理的像素。通过一些修补,我发现这只适用于大小高达~512x512的纹理

您会注意到,我在这些示例中指定了高精度浮点和取样器2D的使用。这是我脑海中浮现的唯一解决方案,但这仍然不能解决我的问题。我知道我总是可以使用相对坐标系来寻址需要较低精度的像素,但为了简单起见,我希望我仍然能够使用uv来寻址。

将UV纹理设置为浮点纹理?当前,每个通道的纹理可能只有8位,这意味着它只能处理256个唯一位置。浮点纹理不会有这个问题

不幸的是,并非所有地方都支持对浮点纹理进行渲染,浏览器也没有统一实现所需的扩展来检查它是否有效。如果你在一个现代的桌面上,它很可能会工作

要确定它是否有效,请尝试获取浮点纹理扩展,如果它存在,请创建浮点纹理并将其附加到帧缓冲区,然后检查帧缓冲区是否完整。如果是,您可以渲染到它

var floatTextures = gl.getExtension("OES_texture_float");
if (!floatTextures) {
   alert("floating point textures are not supported on your system");
   return;
}

// If you need linear filtering then...
var floatLinearTextures = gl.getExtension("OES_texture_float_linear");
if (!floatLinearTextures) {
   alert("linear filtering of floating point textures is not supported on your system");
}

// check if we can render to floating point textures.
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.FLOAT, null);

// some drivers have a bug that requires you turn off filtering before
// rendering to a texture. 
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); 

// make a framebuffer
var fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);

// attach the texture
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, 
                        gl.TEXTURE_2D, tex, 0);

// check if we can render
var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
if (status != gl.FRAMEBUFFER_COMPLETE) {
    alert("can't render to floating point textures");
    return;
}

// You should be good to go.
通过将数据组合到多个通道中来提高分辨率

写入UV纹理时,将UV从0-1范围转换为0到65535范围,然后将modfuv、256/255写入一个通道,将flooruv/256/256写入另一个通道。读取时,使用uv=低通道*256.0+高通道*65535.0/65535.0等方式重新组合通道

这应该适用于任何地方,并为您提供足够的分辨率来处理65536x65536纹理

想法

将UV纹理设置为浮点纹理?当前,每个通道的纹理可能只有8位,这意味着它只能处理256个唯一位置。浮点纹理不会有这个问题

不幸的是,并非所有地方都支持对浮点纹理进行渲染,浏览器也没有统一实现所需的扩展来检查它是否有效。如果你在一个现代的桌面上,它很可能会工作

要确定它是否有效,请尝试获取浮点纹理扩展,如果它存在,请创建浮点纹理并将其附加到帧缓冲区,然后检查帧缓冲区是否完整。如果是,您可以渲染到它

var floatTextures = gl.getExtension("OES_texture_float");
if (!floatTextures) {
   alert("floating point textures are not supported on your system");
   return;
}

// If you need linear filtering then...
var floatLinearTextures = gl.getExtension("OES_texture_float_linear");
if (!floatLinearTextures) {
   alert("linear filtering of floating point textures is not supported on your system");
}

// check if we can render to floating point textures.
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.FLOAT, null);

// some drivers have a bug that requires you turn off filtering before
// rendering to a texture. 
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); 

// make a framebuffer
var fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);

// attach the texture
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, 
                        gl.TEXTURE_2D, tex, 0);

// check if we can render
var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
if (status != gl.FRAMEBUFFER_COMPLETE) {
    alert("can't render to floating point textures");
    return;
}

// You should be good to go.
通过将数据组合到多个通道中来提高分辨率

写入UV纹理时,将UV从0-1范围转换为0到65535范围,然后将modfuv、256/255写入一个通道,将flooruv/256/256写入另一个通道。读取时,使用uv=低通道*256.0+高通道*65535.0/65535.0等方式重新组合通道

这应该适用于任何地方,并为您提供足够的分辨率来处理65536x65536纹理


到目前为止,我已经使用了浮点纹理,效果非常好。该项目是一个内部应用程序,考虑到支持浮点纹理的浏览器的数量,我认为这不会是一个问题。具有讽刺意味的是,Three.js的使用使采用浮点纹理变得复杂,但幸运的是,在Three.Texture和Three.WebGLRenderTarget的构造函数中已经有了一个指定浮点的选项。谢谢到目前为止,我已经使用了浮点纹理,效果非常好。该项目是一个内部应用程序,考虑到支持浮点纹理的浏览器的数量,我认为这不会是一个问题。具有讽刺意味的是,Three.js的使用使采用浮点纹理变得复杂,但幸运的是,在Three.Texture和Three.WebGLRenderTarget的构造函数中已经有了一个指定浮点的选项。谢谢