parseShader¶
-
GPGPU.
parseShader
(pkg, param)¶ シェーダのソースコードを解析します。
ソース¶
parseShader(pkg, param) {
// attribute変数、uniform変数、テクスチャ、varying変数の配列を初期化する。
pkg.attributes = [];
pkg.uniforms = [];
pkg.textures = [];
pkg.varyings = [];
// 頂点シェーダとフラグメントシェーダのソースに対し
for(let shader_text of[ param.vertexShader, param.fragmentShader ]) {
// 行ごとに分割する。
var lines = shader_text.split(/(\r\n|\r|\n)+/);
// すべての行に対し
for(let line of lines) {
// 行を空白で分割する。
var tokens = line.trim().split(/[\s\t]+/);
if (tokens.length < 3) {
// トークンの長さが3未満の場合
continue;
}
// 最初、2番目、3番目のトークン
var tkn0 = tokens[0];
var tkn1 = tokens[1];
var tkn2 = tokens[2];
if (tkn0 != "in" && tkn0 != "uniform" && tkn0 != "out") {
// 最初のトークンが in, uniform, out でない場合
continue;
}
if (shader_text == param.fragmentShader && tkn0 != "uniform") {
// フラグメントシェーダで uniform でない場合 ( フラグメントシェーダの入力(in)と出力(out)はアプリ側では使わない。 )
continue;
}
assert(tkn1 == "int" || tkn1 == "float" || tkn1 == "vec2" || tkn1 == "vec3" || tkn1 == "vec4" ||
tkn1 == "sampler2D" || tkn1 == "sampler3D" ||
tkn1 == "mat4" || tkn1 == "mat3" || tkn1 == "bool");
var arg_name;
var is_array = false;
var k1 = tkn2.indexOf("[");
if (k1 != -1) {
// 3番目のトークンが [ を含む場合
// 配列と見なす。
is_array = true;
// 変数名を得る。
arg_name = tkn2.substring(0, k1);
}
else{
// 3番目のトークンが [ を含まない場合
var k2 = tkn2.indexOf(";");
if (k2 != -1) {
// 3番目のトークンが ; を含む場合
// 変数名を得る。
arg_name = tkn2.substring(0, k2);
}
else{
// 3番目のトークンが ; を含まない場合
// 変数名を得る。
arg_name = tkn2;
}
}
// 変数の値を得る。
var arg_val = param.args[arg_name];
if (arg_val == undefined) {
if(tokens[0] == "out"){
continue;
}
}
if (tkn1 == "sampler2D" || tkn1 == "sampler3D") {
// テクスチャのsamplerの場合
assert(tokens[0] == "uniform" && arg_val instanceof TextureInfo);
// 変数名をセットする。
arg_val.name = arg_name;
// samplerのタイプをセットする。
arg_val.samplerType = tkn1;
// 配列かどうかをセットする。
arg_val.isArray = is_array;
// テクスチャの配列に追加する。
pkg.textures.push(arg_val);
}
else {
// テクスチャのsamplerでない場合
// 変数の名前、値、型、配列かどうかをセットする。
var arg_inf = { name: arg_name, value: arg_val, type: tkn1, isArray: is_array };
switch (tokens[0]) {
case "in":
// attribute変数の場合
pkg.attributes.push(arg_inf);
break;
case "uniform":
// uniform変数の場合
pkg.uniforms.push(arg_inf);
break;
case "out":
// varying変数の場合
pkg.varyings.push(arg_inf);
break;
}
}
}
}
}