Closed22
個人勉強メモ: 2023/10/24

目標
- WebGLの使い方を知る、文法も含めて
- PhotoMoshのWebGLの動かし方を知る
- (可能であれば) glitchとwebglを組み合わせる
- p5.jsで読み込ませた画像にシェーダーの効果をシンプルに適用する

参考資料
- https://community.troikatronix.com/topic/5385/using-webgl-from-mosh-with-glsl-shader
- https://itp-xstory.github.io/p5js-shaders/#/./docs/why-use-shaders
- https://himco.jp/2020/08/09/p5-js-shader-スタート-5-シェーダーの書き方/
- https://github.com/aferriss/p5jsShaderExamples
- https://thebookofshaders.com/?lan=jp
- https://p5js.org/learn/getting-started-in-webgl-shaders.html

シェーダーとは
- .vertと.frag の2種類のファイルがある、頂点シェーダー、フラグメントシェーダー
- p5.js では
loadShader()
を使用してロードされる - vec3は3次元、みたいな型の意味を表す
頂点シェーダー
- すべての頂点シェーダーには main 関数がある
- 頂点位置を変更し、スケッチ全体に影響を及ぼすようにする
- 最後に
gl_Position
に値を与える
フラグメントシェーダー
- 最後に
gl_FragColor
を割り当てる - uniform という機能を使うと、sketch側から値を渡せる。
setUniform()
などを使う

GL_ES
- 定義されていればというときに使える
.xy について
- .xyを実行すると、x位置とy位置の両方に同じ計算が行われる

bing AIで出力したサンプルコード
画像の縦横比を維持したままWEBGLを使う
let img;
let shader;
function preload() {
img = loadImage('assets/image.jpg');
shader = loadShader('assets/shader.vert', 'assets/shader.frag');
}
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
textureMode(NORMAL);
}
function draw() {
background(0);
translate(-width / 2, -height / 2);
let ratio = img.width / img.height;
let screenRatio = width / height;
let w, h;
if (ratio > screenRatio) {
w = width;
h = w / ratio;
} else {
h = height;
w = h * ratio;
}
translate(width / 2, height / 2);
shader(shader);
shader.setUniform('tex0', img);
shader.setUniform('ratio', ratio);
rectMode(CENTER);
rect(0, 0, w, h);
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}
precision highp float;
uniform sampler2D tex0;
uniform float ratio;
varying vec4 vertTexCoord;
void main() {
vec2 texCoord = vertTexCoord.st;
if (ratio > 1.0) {
texCoord.x /= ratio;
texCoord.x += (1.0 - (1.0 / ratio)) / 2.0;
} else {
texCoord.y *= ratio;
texCoord.y += (1.0 - ratio) / 2.0;
}
vec4 color = texture2D(tex0, texCoord);
gl_FragColor = vec4(1.0 - color.rgb, color.a);
}

シェーダーを勉強し直す
- シェーダーとは、描画方法を記述したプログラムのこと
- コンピュータへの指示、それがすべてのピクセルへの指示
- プログラムは画面上の位置を入力としてピクセルの色を返す関数として働くイメージ
- 並列処理をやってくれるが、ほかのスレッドや前の状態がわからないという制限がある
- GLSLはopenGL Shading Languageの略
フラグメントシェーダー
- 予約語として確保されたグローバル変数、gl_FragColor
- vec3, vec4というのは変数の型
ユニフォーム変数
-
CPUからそれぞれのスレッドに入力を渡すことができる
-
英語の”uniform”には均一な、一様なという意味がある
-
u_time(シェーダーが開始してから経過した秒数)、u_resolution(シェーダーが描画する領域の大きさ)、u_mouse(描画領域の中のマウスの位置)などを渡せる
-
u_ で始めるという慣例に従ってるところがある
-
p5jsからは p5.Shader objectのsetUniform(); を使う
-
gl_FragCoordはvarying変数、uniform変数と違う
ベクトルの正規化
- ベクトルの正規化は、ベクトルのxy成分をベクトルの長さで割ることで求められる。
xy座標の線形空間

ベクトル型について
vec4 vector;
vector[0] = vector.r = vector.x = vector.s;
vector[1] = vector.g = vector.y = vector.t;
vector[2] = vector.b = vector.z = vector.p;
vector[3] = vector.a = vector.w = vector.q;
sin(u_time)
で、-1.0 ~ 1.0 を行ったり来たりする動かし方ができる

画像処理について
- GPU で、画像はsampler2D浮動小数点ベクトルのテーブル (または行列) に似たものとして保存される
- さらに興味深いことに、このベクトルのテーブルの値は連続的です。つまり、ピクセル間の値は低レベルで補完される
- 画像を扱うには、CPU から GPU に画像をアップロードし、idをuniformに渡す
-
vec4 texture2D(sampler2D texture, vec2 coordinates)
というテーブル変数
参考URL

複数シェーダーを読み込む

画像にsetUniformによる変化を与えるには、createGraphicsを使ったほうがいいのだろうか

グリッチのチュートリアル

pixel sorting

サンプルコード集、glslの

シェーダーのサンプル集 ブロックノイズ
シェーダーの乱数などについて

chatGPTにきいたテクスチャ座標と画面座標の違い
テクスチャ座標と画面座標は、異なる座標系であり、異なる役割を果たします。
-
テクスチャ座標(UV座標):
- テクスチャ座標は、通常は0から1の範囲で表される正規化された座標系です。各成分は通常、横軸(U軸)と縦軸(V軸)に対応しています。
- 例えば、(0, 0) はテクスチャの左上隅を、(1, 1) は右下隅を指します。これにより、テクスチャ上の特定の位置を指定することができます。
- シェーダー内で
texture2D(u_image, uv)
のように使用され、テクスチャから色をサンプリングするために利用されます。
-
画面座標(フラグメント座標):
- 画面座標(またはフラグメント座標)は、ピクセルが描かれる画面上の位置を表します。これは通常、ピクセル単位で表され、左上が原点です。
- 例えば、(0, 0) は画面の左上隅を、(width, height) は右下隅を指します。ここで、
width
は画面の幅、height
は高さです。 - シェーダー内で
gl_FragCoord.xy
のように使用され、各ピクセルの座標を取得するために利用されます。
簡単に言えば、テクスチャ座標はテクスチャ内の位置を指定するのに対して、画面座標は描画されるピクセルの位置を指定します。シェーダー内での利用目的によって、これらの座標系が使い分けられます。

シェーダー基礎

asciiアート
このスクラップは2023/11/07にクローズされました