gpt4 book ai didi

shader - 如何在 WebGL 中使用数据纹理

转载 作者:行者123 更新时间:2023-12-04 02:38:21 26 4
gpt4 key购买 nike

我一直在学习 WebGL 教程,例如 webglfundamentals并且遇到了一个绊脚石 - 我相信我需要使用我创建的纹理将信息直接传递给片段着色器,但我似乎无法正确索引纹理。

目标是传递有关光源(位置和颜色)的信息,这些信息将被考虑到片段颜色中。理想情况下,此信息在值(value)和长度上都是动态的。

再生产

我在这个 fiddle 中创建了一个简化版本的问题:WebGL - Data Texture Testing

这是一些代码。

一次性设置我们创建一个纹理,用数据填充它,并在该纹理上应用似乎最简单的设置(没有 mips,没有字节打包问题[?])

  // lookup uniforms
var textureLocation = gl.getUniformLocation(program, "u_texture");

// Create a texture.
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);

// fill texture with 1x3 pixels
const level = 0;
const internalFormat = gl.RGBA; // I've also tried to work with gl.LUMINANCE
// but it feels harder to debug
const width = 1;
const height = 3;
const border = 0;
const type = gl.UNSIGNED_BYTE;
const data = new Uint8Array([
// R, G, B, A (unused) // : 'texel' index (?)
64, 0, 0, 0, // : 0
0, 128, 0, 0, // : 1
0, 0, 255, 0, // : 2
]);
const alignment = 1; // should be uneccessary for this texture, but
gl.pixelStorei(gl.UNPACK_ALIGNMENT, alignment); // I don't think this is hurting
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, width, height, border,
internalFormat, type, data);

// set the filtering so we don't need mips and it's not filtered
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
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);

抽奖序列(只发生一次,但可以想象可能会重复)我们强调程序应该使用我们的纹理
    // Tell the shader to use texture unit 0 for u_texture
gl.activeTexture(gl.TEXTURE0); // added this and following line to be extra sure which texture is being used...
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.uniform1i(textureLocation, 0);

最后,在片段着色器中,我们试图可靠地使用一个“纹素”作为传达信息的手段。我似乎无法确定如何可靠地检索存储在纹理中的值。
precision mediump float;

// The texture.
uniform sampler2D u_texture;

void main() {

vec4 sample_00 = texture2D(u_texture, vec2(0, 0));
// This sample generally appears to be correct.
// Changing the provided data for the B channel of texel
// index 0 seems to add blue as expected

vec4 sample_01 = texture2D(u_texture, vec2(0, 1));
vec4 sample_02 = texture2D(u_texture, vec2(0, 2));
// These samples are how I expected this to work since
// the width of the texture is set to 1
// For some reason 01 and 02 both show the same color

vec4 sample_10 = texture2D(u_texture, vec2(1, 0));
vec4 sample_20 = texture2D(u_texture, vec2(2, 0));
// These samples are just there for testing - I don't think
// that they should work

// choose which sample to display
vec4 sample = sample_00;
gl_FragColor = vec4(sample.x, sample.y, sample.z, 1);
}

问题)

使用纹理是最好的方法吗?我也听说过传递向量数组的能力,但纹理似乎更常见。

你应该如何创建纹理? (特别是当我指定 'width' 和 'height' 时,我应该指的是生成的 texel 尺寸还是我将用于构造纹理的 gl.UNSIGNED_BYTE 元素的数量?? texImage2D documentation )

当不使用“不同”类型时,您应该如何索引片段着色器中的纹理? (即我只想要一个或多个特定纹素的值 - 没有插值 [与顶点几乎没有任何关系])

其他资源

我暂时已经尽可能多地阅读了这方面的内容。这是一个非详尽列表:
  • JMI Madison 表示他们已经想通了,但是 the solution埋在一大堆项目特定的代码中
  • webglfundamentals教程接近 - 使用 3x2 data texture - 但它使用插值并且似乎不能很好地转换为我的用例
  • 这里有人在谈论 trying to use vec3 arrays
  • 当然,我一直在尝试将我的工作与一些 OpenGL 文档( texImage2Dtexture2d )
  • 进行比较

    编辑 这是我刚刚找到的另一个资源: Hassles with array access in WebGL, and a couple of workarounds .让我充满希望。

    这真的很困扰我。

    提前致谢!

    最佳答案

    在 WebGL1 中处理纹理中的单个像素使用此公式

    vec2 pixelCoord = vec2(x, y);
    vec2 textureDimension = vec2(textureWidth, textureHeight)
    vec2 texcoord = (pixelCoord + 0.5) / textureDimensions;
    vec4 pixelValue = texture2D(someSamplerUniform, texcoord);

    因为纹理坐标是按边的。如果你有一个 2x1 的纹理
    1.0+-------+-------+
    | | |
    | A | B |
    | | |
    0.0+-------+-------+
    0.0 0.5 1.0

    像素 A 中心的纹理坐标 = 0.25, 0.5。像素 B 中心的纹理坐标为 0.75, 0.5

    如果您不遵循上面的论坛并仅使用 pixelCoord/textureDimensions 那么您将指向像素之间,而数学错误将使您获得一个或另一个像素。

    当然,如果您对数据使用纹理,您可能还想设置 gl.NEAREST过滤。

    在 WebGL2 中,你可以只使用 texelFetch
    ivec2 pixelCoord = ivec2(x, y);
    int mipLevel = 0;
    vec4 pixelValue = texelFetch(someSamplerUniform, texcoord, mipLevel);

    将纹理用于数据的一个工作示例是 here

    Is using a texture the best way to do this? I have heard of the ability to pass arrays of vectors as well, but textures seem to be more common.



    做什么?不清楚你想做什么。每个像素都会有不同的光源吗?

    How are you supposed to create the texture? (particularly when I specify 'width' and 'height' should I be referring to resulting texel dimensions or the number of gl.UNSIGNED_BYTE elements that I will use to construct the texture?? texImage2D documentation)



    做任何最简单或需要的事情。例如,如果您要提取的每件事有 5 条数据,我可能会将每条数据放在纹理中的单独行中。然后我可以做
    vec4 datum1 = texture2D(dataTexture, vec2(indexTexCoordX, rowTexCoordY0);
    vec4 datum2 = texture2D(dataTexture, vec2(indexTexCoordX, rowTexCoordY1);
    vec4 datum3 = texture2D(dataTexture, vec2(indexTexCoordX, rowTexCoordY2);
    vec4 datum4 = texture2D(dataTexture, vec2(indexTexCoordX, rowTexCoordY3);

    其中 indexTexCoordX 和 rowTexCoordY0-3 是从上面的论坛计算出来的。 rowTexCoordY0-3 甚至可以是常量。

    纹理在维度上有限制,所以如果你有更多的数据,那么将适合一个维度,那么你必须更紧密地打包数据并做更多的数学运算才能将其取出。

    请注意纹理具有缓存,因此理想情况下您希望您提取的数据靠近您之前提取的数据。如果您每次跳过纹理以获得下一个值,您的性能就会下降。 (当然,它可能仍然比替代解决方案更快,具体取决于您在做什么)

    How are you supposed to index into the texture in a fragment shader when not using 'varying' types? (i.e. I just want the value of one or more particular texels - no interpolation [having little to nothing to do with vertices])



    片段着色器的唯一变化输入是变化的, gl_FragCoord (正在写入的坐标像素)和 gl_PointCoord , 仅在绘图时可用 POINTS .所以你必须使用其中之一,否则所有其他值对于所有像素都是恒定的。

    关于shader - 如何在 WebGL 中使用数据纹理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60614318/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com