在创建着色器时,我是一个完整的菜鸟。或者更好的说,我昨天刚刚了解了它。
我正在尝试创建一个非常简单的圈子。我终于弄明白了,但事实证明它很大。它应该与应用过滤器的DisplayObject大小匹配。
片段着色器:
precision mediump float;
varying vec2 vTextureCoord;
vec2 resolution = vec2(1.0, 1.0);
void main() {
vec2 uv = vTextureCoord.xy / resolution.xy;
uv -= 0.5;
uv.x *= resolution.x / resolution.y;
float r = 0.5;
float d = length(uv);
float c = smoothstep(d,d+0.003,r);
gl_FragColor = vec4(vec3(c,0.5,0.0),1.0);
}
使用Pixi.js的示例:
var app = new PIXI.Application();
document.body.appendChild(app.view);
var background = PIXI.Sprite.fromImage("required/assets/bkg-grass.jpg");
background.width = 200;
background.height = 200;
app.stage.addChild(background);
var vertexShader = `
attribute vec2 aVertexPosition;
attribute vec2 aTextureCoord;
uniform mat3 projectionMatrix;
varying vec2 vTextureCoord;
void main(void)
{
gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);
vTextureCoord = aTextureCoord;
}
`;
var fragShader = `
precision mediump float;
varying vec2 vTextureCoord;
vec2 resolution = vec2(1.0, 1.0);
void main() {
vec2 uv = vTextureCoord.xy / resolution.xy;
uv -= 0.5;
uv.x *= resolution.x / resolution.y;
float r = 0.5;
float d = length(uv);
float c = smoothstep(d,d+0.003,r);
gl_FragColor = vec4(vec3(c,0.5,0.),1.0);
}
`;
var filter = new PIXI.Filter(vertexShader, fragShader);
filter.padding = 0;
background.filters = [filter];

body { margin: 0; }

<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/4.5.2/pixi.js"></script>
&#13;
答案 0 :(得分:1)
您似乎偶然发现了奇怪的浮点精度问题:片段着色器中的纹理坐标(vTextureCoord
)严格不在(0,1)范围内。这是我添加行gl_FragColor = vec4(vTextureCoord, 0, 1)
后的内容:
看起来不错,但是如果我们仔细检查一下,右下角的像素应该是(1,1,0),但它不是:
问题消失了,如果不是将尺寸设置为500乘500,我们使用2的幂大小(比如512乘512),问题就会消失:
另一种可能的缓解问题的方法是尝试绕过Pixi的代码来计算投影矩阵并提供自己的代码,将较小的四边形转换为所需的屏幕位置。
答案 1 :(得分:1)
Pixi.js的vTextureCoord
不会从0变为1。
来自the docs
V4滤镜与V3不同。您不能只添加着色器并假设纹理坐标位于[0,1]范围内。
...
注意:vTextureCoord乘以filterArea.xy是边界框的实际大小。
如果要获取像素坐标,请使用均匀filterArea,它将自动传递给过滤器。
uniform vec4 filterArea; ... vec2 pixelCoord = vTextureCoord * filterArea.xy;
它们以像素为单位。如果我们想要像#34这样的东西,将椭圆填充到边界框中,那就不会起作用了。所以,让我们传递尺寸! PIXI不会自动执行,我们需要手动修复:
filter.apply = function(filterManager, input, output) { this.uniforms.dimensions[0] = input.sourceFrame.width this.uniforms.dimensions[1] = input.sourceFrame.height // draw the filter... filterManager.applyFilter(this, input, output); }
让我们将它合并到着色器中!
uniform vec4 filterArea; uniform vec2 dimensions; ... vec2 pixelCoord = vTextureCoord * filterArea.xy; vec2 normalizedCoord = pixelCoord / dimensions;
您的代码段已更新。
var app = new PIXI.Application();
document.body.appendChild(app.view);
var background = PIXI.Sprite.fromImage("required/assets/bkg-grass.jpg");
background.width = 200;
background.height = 200;
app.stage.addChild(background);
var vertexShader = `
attribute vec2 aVertexPosition;
attribute vec2 aTextureCoord;
uniform mat3 projectionMatrix;
varying vec2 vTextureCoord;
void main(void)
{
gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);
vTextureCoord = aTextureCoord;
}
`;
var fragShader = `
precision mediump float;
varying vec2 vTextureCoord;
uniform vec2 dimensions;
uniform vec4 filterArea;
void main() {
vec2 pixelCoord = vTextureCoord * filterArea.xy;
vec2 uv = pixelCoord / dimensions;
uv -= 0.5;
float r = 0.5;
float d = length(uv);
float c = smoothstep(d,d+0.003,r);
gl_FragColor = vec4(vec3(c,0.5,0.),1.0);
}
`;
var filter = new PIXI.Filter(vertexShader, fragShader);
filter.apply = function(filterManager, input, output)
{
this.uniforms.dimensions[0] = input.sourceFrame.width
this.uniforms.dimensions[1] = input.sourceFrame.height
// draw the filter...
filterManager.applyFilter(this, input, output);
}
filter.padding = 0;
background.filters = [filter];
&#13;
body { margin: 0; }
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/4.5.2/pixi.js"></script>
&#13;