我试图通过纹理将一个浮点数组(在我的例子中是一个音频波)传递给片段着色器。它有效但我得到一些不完美的东西,好像从1px高度纹理读取的值不可靠。
条形宽度和金额的许多组合会发生这种情况。
我从纹理中获取值:
precision mediump float;
...
uniform sampler2D uDisp;
...
void main(){
...
float columnWidth = availableWidth / barsCount;
float barIndex = floor((coord.x-paddingH)/columnWidth);
float textureX = min( 1.0, (barIndex+1.0)/barsCount );
float barValue = texture2D(uDisp, vec2(textureX, 0.0)).r;
...
如果不使用纹理中的值而使用其他东西,那么问题似乎就不存在了。
barValue = barIndex*0.1;
知道可能是什么问题吗?为此目的使用纹理是个坏主意吗? 我使用Pixi.JS作为WebGL框架,因此我无法访问低级API。
对于数据和许多条形的渐变纹理,问题变得非常明显。
更新:看起来这个问题与textureX值的一致性有关。
尝试使用barIndex/(barsCount-1.0)
等不同的公式可以减少噪音。将其包裹在min
上肯定会增加更多噪音。
答案 0 :(得分:1)
原来问题不在于从纹理中读取值,而是在绘图中。我没有使用IF,而是切换到步骤,问题就消失了。
vec2 topLeft = vec2(
paddingH + (barIndex*columnWidth) + ((columnWidth-barWidthInPixels)*0.5),
top
);
vec2 bottomRight = vec2(
topLeft.x + barWidthInPixels,
bottom
);
vec2 tl = step(topLeft, coord);
vec2 br = 1.0-step(bottomRight, coord);
float blend = tl.x * tl.y * br.x * br.y;
我想通过IF对浮点数进行比较在着色器中并不十分可靠。
答案 1 :(得分:0)
通常mediump
不足以用于任何非平凡纹理的纹理坐标,因此尽可能使用highp
。这在一些较旧的GPU上始终不可用,因此根据平台,这可能无法解决您的问题。
如果您知道您正在进行1:1映射,那么也使用GL_NEAREST而不是GL_LINEAR,因为量化效果更可能隐藏一些精确的副作用。
鉴于你可能知道列和条的数量,你可以预先计算CPU上的一些值(例如预计算1/columns
并以fp32精度传递它)。传递0到1之间的小值总是要更好地保持浮点精度,而不是传递大值然后分割。