我一直在学习WebGL,像webglfundamentals这样的教程,但现在遇到了一个问题——我相信我需要使用自己创建的纹理将信息直接传递到片段着色器中,但我似乎无法正确地索引该纹理。
目标是传递有关光源(位置和颜色)的信息,这些信息将影响片段的颜色。理想情况下,这些信息的值和长度都是动态的。
重现步骤
我在这个fiddle中创建了一个简化版本的问题:WebGL-数据纹理测试
以下是部分代码。
在一次性设置中,我们创建一个纹理,填充数据,并对该纹理应用最简单的设置(无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);
}
问题
使用纹理是否是实现此目的的最佳方式?我听说过也可以传递向量数组,但纹理似乎更常见。
您应该如何创建纹理?(特别是当我指定“宽度”和“高度”时,我应该是参考结果像素维度还是我将用于构建纹理的gl.UNSIGNED_BYTE元素数量?texImage2D文档)
在片段着色器中不使用“varying”类型时,您应该如何索引纹理? (即,我只想得到一个或多个特定纹素的值 - 没有插值[与顶点几乎没有关系])
其他资源
目前为止,我已经读了尽可能多的关于此问题的内容。 这里是一个非详尽列表:
- JMI Madison表示他们已经解决了这个问题,但解决方案 buried在大量特定于项目的代码中
- WebGL Fundamentals教程接近 - 使用3x2数据纹理 - 但它使用插值,似乎不能很好地适用于我的用例
- 有人在讨论尝试使用vec3数组
- 当然,我一直在尝试将我的工作与一些OpenGL文档(texImage2D和texture2d)进行比较
编辑这是我刚刚找到的另一个资源:WebGL中访问数组的麻烦及其几种解决方法。 让我感到有希望。
这真的很烦人。
提前致谢!
uniform vec3 lights[4];
?此外,查找纹理像素应该使用单位坐标而不是像素坐标。例如,texture2D(tex, vec2(0,2))
应该是texture2D(tex, vec2(0,0.5))
。 - Blindman67