1

ここにC++の問題がありますが、これは単純に理解できません。

私は2つのわずかに異なる機能を持っています。どちらもまったく同じことをする必要があります。ただし、正しく機能するのは1つだけです。

メソッド1:メソッドの入力は'const string samplerName = "test"'


void setUniformSampler(Gluint program, const string samplerName, GLuint sampler) {
    GLint uniformLocation = glGetUniformLocation(program, samplerName.c_str()); // returns -1

    if(uniformLocation >= 0) {
        glUniform1i(uniformLocation, sampler);
    } else {
        throw exception(...);
    }
}

方法2:


void setUniformSampler(Gluint program, GLuint sampler) {
    GLint uniformLocation = glGetUniformLocation(program, "test"); // returns 0

    if(uniformLocation >= 0) {
        glUniform1i(uniformLocation, sampler);
    } else {
        throw exception(...);
    }
}

ご覧のとおり、glGetUniformLocationは2つの異なる値を返します。正しい戻り値は、「-1」ではなく「0」になります。では、2つの呼び出しの違いは正確には何でしょうか。

quote: "c_str()は、文字列オブジェクトと同じ内容のnullで終了する文字シーケンス(c-string)を生成し、それを文字配列へのポインタとして返します"。そして、それこそが、メソッドglGetUniformLocation(...)が2番目のパラメーターとして必要とするものです。では、なぜ上記の方法2だけが成功するのでしょうか。コンパイラの問題ですか?

Win7でMSVisualStudio2008を使用しています。

私はこのバグを2日近く探しています。私は本当にこれを明確にしたいと思います。それは私を夢中にさせました...

ありがとうウォルター

編集:

これも機能しません。


void setUniformSampler(Gluint program, const string samplerName, GLuint sampler) {
    const GLchar* name = samplerName.c_str();

    GLint uniformLocation = glGetUniformLocation(program, name); // still returns -1

    if(uniformLocation >= 0) {
        glUniform1i(uniformLocation, sampler);
    } else {
        throw exception(...);
    }
}

4

3 に答える 3

0

パラメータは const であり、const オブジェクトで非 const 関数を呼び出すことはできません。多分それが問題ですか?関数には、NULL で終わる文字列へのポインターが必要です。それがあなたが与えているものであることを確認してください。

于 2010-12-09T06:23:03.047 に答える
0

のパラメータの実装と型を確認してくださいglGetUniformLocation(parameter)。「test」は、実行可能ファイルの存続期間と場所が変更されない const リテラルですが、c_str() は文字列オブジェクトから動的に計算され、文字列オブジェクトが終了すると終了します。

言い換えれば、glGetUniformLocation()理由を見つけるために横にチェックインする必要があります。これは、いくつかの CRT 文字列関数に関連していると思います。

于 2010-12-09T06:54:36.787 に答える
0

ワイド文字とスリム (つまり 8 ビット) 文字列の混同の犠牲になるかもしれません。シェーダー ソースと統一名の両方が静的文字列として定義されている場合、それらは文字列表現に一致します。c_str は常に char の文字列を返すため、string::c_str はこれを変更する可能性があります。つまり、wchar を認識しません。

バグのないシェーダー コンパイラは明確な内部表現を使用するため、技術的には違いが生じるはずです。ただし、ワイド文字とスリム文字の違いが異なる識別子として解釈されるというバグがある可能性があります。

シェーダー ソースも string::c_str を介して渡すとどうなりますか? 文字列変数のデバッガーの hexedit ビューも確認してください。次のようになっている場合:

00000000  74 65 73 74 0a                                    |test.|

8 ビットの文字列が得られました。次のようになっている場合:

00000000  74 00 65 00 73 00 74 00  0a 00                    |t.e.s.t...|

次に、幅の広い文字列を取得します。そして、これをシェーダーが提供されている変数と比較します。

于 2010-12-09T10:04:36.997 に答える