系列文來到三部分,開始寫些什麼了!
這次寫的是類似電視雜訊的效果:
分為兩個部分:
電視雜訊的效果分作兩個部分,x
與y
:
x
float c = fract(sin(uv.x*2304.)*3057.);
驚人,我知道 sin() 會回傳 -1
~1
,
怎麼加上 fract() 跟乘上神奇數字就變成...類似條碼的效果了?
fract:
fract — compute the fractional part of the argument
Declaration
genType fract( genType x);
Description
fract returns the fractional part of x. This is calculated as x - floor(x).
當被除數是負數
時,除出來的結果是多少?
JavaScript:
> 1 % 3
<. 1
> -1 % 3
<. -1
> -2 % 3
<. -2
在 JavaScript 裡, 被除數 小於 0
時,餘數是 負數
Shader:
The Book of Shaders: fract
從圖上看出,寫 Shader 時, fract() 取餘數的結果是正數
sin() 的結果是 -1
~ 1
,用 fract 取餘數的結果就是 0
~ 1
了
註: 負數取餘數的實作取決於
程式語言
,並非所有語言的結果都相同
why?
如果直接取 sin() 的餘數
由於 uv.x 的範圍是 0.
~1.
sin(uv.x) 的結果會是 sin(0.)
~ sin(1.)
大約是 0
~0.8414709848078965
float c = fract(sin(uv.x));
輸出會從黑
到約 84% 白色
的漸層
sin(uv.x*2.) 的結果會是 sin(0.) ~ sin(2.),負數取餘數是正數
float c = fract(sin(uv.x*2.));
sin(uv.x*6.) 的結果會是 sin(0.) ~ sin(6.)
float c = fract(sin(uv.x*6.));
簡諧運動加上負數取餘數的結果,畫面有點特別
float c = fract(sin(uv.x*2304.+uv.y*181.)*3057.);
真的只是加上 uv.y ,就完成了
uv.x 跟 uv.y 如果乘的是一樣的數字,
結果會很規律,不是想要的效果
數學真是太神奇了...
如同電視雜訊,一直沙沙沙的效果?
把 Shadertoy 內建變數 iTime
乘進輸出公式
float c = fract(sin(uv.x*2304.+uv.y*181.)*3057.*iTime);
完成!
看起來好像很吃效能的效果,意外的有些單純
前幾天的文章有提到在 PixiJS 裡寫濾鏡的方法,
將剛剛完成的 fragment shader 放進 PixiJS 濾鏡 裡:
JavaScript:
const shaderFrag = `
precision highp float;
varying vec2 vTextureCoord;
uniform vec4 inputSize;
uniform vec4 outputFrame;
uniform float time;
void main() {
float c = fract(sin(vTextureCoord.x*2304.+vTextureCoord.y*181.)*3057.*time);
gl_FragColor = vec4(c) * 0.7;
}
`;
const filter = new PIXI.Filter(null, shaderFrag, {
time: 0,
});
filterContainer.filters = [filter];
uniform
:const filter = new PIXI.Filter(null, shaderFrag, {
time: 0,
});
filterContainer.filters = [filter];
let time = 0;
app.ticker.add((delta) => {
time ++;
filter.uniforms.time = (time);
});
完成!
這是目前我實作 PixiJS 濾鏡的方法:
uniform
變數