-4

今日、私は単純な OpenGL シェーダー クラスをまとめようとしました。これは、ファイルからテキストをロードし、いくつかの (かなり甘い) カスタム構文 (たとえば、" .varying [type] [name];" を使用すると、".version" と同じように、一度だけ書き込むだけで、両方のシェーダーで可変変数を定義できます)。次に、2 つを使用して OpenGL シェーダー プログラムをコンパイルし、シェーダー クラスをマークします。シェーダーコードが正しくコンパイルされた場合にのみ、「準備完了」として。

さて、私はこれをすべて実行しましたが、最も奇妙な(そして率直に言ってちょっと怖い)問題に遭遇しました. すべてをセットアップし、有効なシェーダー コードを含むファイルで新しい 'tt::Shader' を宣言しましたが、シェーダーが無効であるとだけ言われましたが、エラーの内容を尋ねると空の文字列が返されました (つまり、 OpenGL は、そこから取得するため、空の文字列を提供してくれました。)

今回は明らかに無効なシェーダーコードを使用して再試行しましたが、シェーダーが無効であることが識別されましたが、エラーの内容については何も表示されず、空の文字列のみが表示されました(エラー識別部分は明らかにエラー識別部分であると想定しました)のも以前とまったく同じでした。)

混乱して、有効なシェーダーと無効なシェーダーの両方を文字列として手動で書き直し、ファイルにアクセスせずに、文字列を直接使用してクラスを再度コンパイルしました。これを行うと、エラーは消え、最初のものは正しくコンパイルされ、2番目のものは失敗しましたが、エラーが何であるかを正しく識別しました.

さらに混乱して、ファイルの文字列と自分で書いた文字列を比較し始めました。同じものを印刷したにもかかわらず、前者ははしごよりも少し長かったことがわかりました。少し数えてみたところ、これらの文字は、インポート プロセスで切り取られた Windows CR LF 行末キャリッジ文字に違いないことがわかりました。

これをテストするために、手書きの文字列を取得し、文字列が切り取られる位置にキャリッジを挿入して、文字列比較テストを再度実行しました。今回は、そこの長さが同じであると評価しましたが、それでも2つが等しくないことを教えてくれました。これは非常に不可解でした.

そこで、単純な for ループを作成して、2 つの文字列の文字を反復処理し、それぞれを並べて出力し、整数にキャストして、インデックス値を確認できるようにしました。私はプログラムを実行し、(非常に長い) リストに目を通し、さまざまな洞察に満ちた答えにたどり着きました。

私が使用しているファイル読み取り関数のコードは次のとおりです。それは空想的なものではなく、標準ライブラリのものです。

// Attempts to read the file with the given path, returning a string of its contents.
// If the file could not be found and read, an empty string will be returned.
// File strings are build by reading the file line-by-line and assembling a single with new lines placed between them.
// Given this line-by-line method, take note that it will copy no more than 4096 bytes from a single line before moving on.
inline std::string fileRead(const std::string& path) {


    if (!tt::fileExists(path))
        return "";
    std::ifstream a;
    a.open(path);
    std::string r;
    const tt::uint32 _LIMIT = 4096;
    char r0[_LIMIT];

    tt::uint32 i = 0;
    while (a.good()) {
        a.getline(r0, _LIMIT);
        if (i > 0)
            r += "\n";
        i++;
        r += std::string(r0, static_cast<tt::uint32>(a.gcount()));
    }

    // TODO: Ask StackOverflow why on earth our file reading function is placing null characters where excess carriages should go.

    for (tt::uint32 i = 0; i < r.length(); i++)
        if (r[i] == '\0')
            r[i] = '\r';
    a.close();
    tt::printL("Reading file '" + path + "' ...");
    return r;
}

皆さんが読んで、一体何が起こっているのか教えてくれたら、それは素晴らしいことです.

最後に、null ターミネータが表示されなかった理由がわかりましたが、OpenGL では表示されました。はしごは C 文字列を使用していましたが、指定された長さに基づいて物を格納する std::string オブジェクトですべてを行っていました。それらはほとんどただの派手な std::vector オブジェクトです。

4

1 に答える 1