これはやっかいです。適切な説明のために、私がやろうとしていることを説明させてください。コードリストをフォローアップしてから、コードを後で説明します。
目標
私が持っているすべてのGLSLシェーダーファイルの変数の名前を取得しようとしています。現在、私は単一の頂点シェーダーと、それを補完するフラグメントシェーダーしか持っていません。これの目的は、すべての変数名を入力しなくても、値をシェーダーに動的にバインドできるようにすることです。
コード
std::vector< const char* > GetShaderVariableNames( const Shader& shader )
{
Config::Log::info( "Getting shader variable names." );
static const char* keyLookupTable[] =
{
"vec2", "vec3", "vec4",
"mat2", "mat3", "mat4",
"float", "int", "double"
};
std::vector< const char* > keys;
std::vector< std::string > lines;
SplitIntoLines( &lines, std::string( shader.shaderSrc ) );
for( int32_t iLines = 0; iLines < lines.size(); ++iLines )
{
const char* line = lines[ iLines ].c_str();
int32_t index = 0;
bool foundMatch = false;
for( int32_t iKey = 0; iKey < sizeof( keyLookupTable ) / sizeof( char ); ++iKey )
{
if( strContains( lines[ iLines ], keyLookupTable[ iKey ] ) )
{
index = iKey;
foundMatch = true;
break;
}
}
if( foundMatch )
{
const int32_t pos = lines[ iLines ].find( keyLookupTable[ index ] );
Config::Log::info( "Position found is %i", pos );
const int32_t lineLen = strlen( line );
char* var = new char[ lineLen - pos ];
int32_t iLine = pos + strlen( keyLookupTable[ index ] );
for( ; iLine < lineLen; ++iLine )
{
var[ iLine ] = line[ iLine ];
}
Config::Log::info( "Shader Variable Found is: %s", var );
keys.push_back( var );
}
}
return keys;
}
赤いピルを飲む
したがって、最も一般的に使用される変数タイプを含むキールックアップテーブルがあるという考え方です。まず、受け取ったシェーダーは、ハンドル、タイプ(フラグメント、頂点、テクスチャなど)、そしてもちろんソースなど、データに関する情報を保持するクラスです。これらはすべて、文字列ではなく、シェーダーファイルから解析しています。
何が起こるかというと、シェーダーファイルで解析された各行を繰り返すおじいちゃんのループがあります。すべての行で、キールックアップテーブルに一致がある場合、反復する2番目のループは、の値(つまり、一致が見つかった配列内のインデックス)keyLookupTable[]
をとるインデックス値で中断されます。iKey
その後、ループが中断します。
一致が見つかった場合は、一致が見つかった行の位置(vec4
またはmat3
)が取得されます。そこから、に格納されている位置pos
を使用pos
して、変数名の長さの基準として機能します。これは、char配列に必要な文字数を指定することによって行われます。必要な量は、線の長さから位置を引いたものです。
そこから、3番目の最後のループが行を繰り返し、aを使用しchar*
てそれを参照し、値を取り込んでline
、割り当てられたvar
文字配列にコピーします。
最後に、std::vector
キーが挿入var
されてループに進み、プロセスが繰り返されます。
注目すべき懸念
- シェーダー自体はJavaを介して解析され、JNIを介してC ++に送信されるため、JNIを使用してシェーダー文字列を取得しています。
- 私は次のような出力を取得しているので、Unicodeが問題になる可能性があります。
Shader Variable Found is: |uԯ|uԯ/
- シェーダーsrcは、JNIからconstchar*に渡されます。
env->GetStringUTFChars()
結論
これを行うには、おそらく何かを使用するなど、より良い方法があると確信していますstd::stringstream
が、私はそれについてあまり詳しくないので、このアルゴリズムを何らかの形で機能させたいと考えています。ただし、これが「素朴な」方法である場合は、提案を受け付けています。
質問
解析を機能させるためにこれを達成するための最良の方法は何ですか?