{
はは、これら 2 つのレッスンはずっと前に翻訳されていますが、まだ投稿されていません。皆さん長い間待っていました (もう待っている人はいますか?)。
シンプルな透明性
OpenGL の特殊効果の大部分は、ある種の (色の) 混合に関連しています。
混色は、特定のピクセルの色と、画面上に描画された対応するピクセルの色を組み合わせると定義されます。
2 つの色がどのように組み合わされるかは、色のアルファ チャネル コンポーネントの値、および/または使用される色混合関数によって異なります。
アルファは通常、カラー値の最後の 4 番目のカラー コンポーネントです。
前のレッスンでは、GL_RGB を使用して 3 つの色の成分を指定しました。
対応する GL_RGBA は、アルファ コンポーネントの値を指定できます。
さらに一歩進んで、glColor3f() の代わりに glColor4f() を使用できます。
ほとんどの人は、アルファ コンポーネントがマテリアルの透明度を表すことに同意します。
これは、アルファ値 0.0 が完全に透明なマテリアルを表すことを意味します。
アルファ値 1.0 は、完全に不透明なマテリアルを表します。
混色配合
数学に興味がなく、透明性を実現する方法だけを知りたい場合は、このセクションを飛ばしてください。
(色の) 混合がどのように機能するかをより深く理解したい場合は、このセクションが最適です。
『CKER追記:実は難しくありません^-^。元の記事の式は次のとおりです。CKER でもう一度話しましょう。
実際、混合の基本原理は、RGB ルールに従って、各ピクセルの色と分離される画像の背景色を分離することです。
による - 画像の RGB カラー成分 * アルファ値 + 背景の RGB カラー成分 * (1-アルファ値)
- このような単純な計算式で混合した後、混合によって得られた RGB コンポーネントが最終的に再結合されます。 』
式は次のとおりです。
(Rs Sr + Rd Dr、Gs Sg + Gd Dg、Bs Sb + Bd Db、As Sa + Ad Da)
OpenGL は、上記の式に従ってこれら 2 つのピクセルの混色結果を計算します。
小文字の s と r は、それぞれソース ピクセルとターゲット ピクセルを表します。大文字の S と D は、対応する色混合係数です。
これらは、それらのピクセルの色をどのように混合するかを決定します。
ほとんどの場合、各カラー チャネルのアルファ混合値は同じです。
このようにして、ソース ピクセルの (As, As, As, As) が得られます。
対象となるピクセルは 1, 1, 1, 1) - (As, As, As, As) です。
上の式は次のようになります。
(Rs As + Rd (1 - As)、Gs As + Gd (1 - As)、Bs As + Bs (1 - As)、As As + Ad (1 - As))
この配合により、透明/半透明の効果が得られます。
OpenGLでのカラーミキシング
OpenGL でカラーミキシングを実装する手順は、前に説明した OpenGL プロセスと似ています。
次に、数式を設定し、透明なオブジェクトを描画するときに書き込み深度キャッシュをオフにします。
半透明の図形の背後にオブジェクトを描画したいためです。
これは色を混合する正しい方法ではありませんが、ほとんどの場合、単純なプロジェクトでは問題なく機能します。
Rui Martins 氏の追加: 正しい色の混合プロセスは、最初にシーン全体を描画してから、透明なグラフィックを描画することです。
そして、それらは深度バッファーの逆の順序で描画されます (最も遠いオブジェクトが最初に描画されます)。
2 つのポリゴン (1 と 2) をアルファ ブレンドする場合、描画順序が異なると結果も異なります。
(ここでは、ポリゴン 1 が観察者に最も近いと想定されており、正しいプロセスでは最初にポリゴン 2 を描画し、次にポリゴン 1 を描画する必要があります。
実際に見てわかるように、
これら 2 つの <透明> ポリゴンの後ろから来る光は、常に最初にポリゴン 2 を通過します。
そしてポリゴン 1 を通過し、最終的に観察者の目に到達します。 )
深度キャッシュが有効になっている場合は、透明なグラフィックを深度で並べ替える必要があります。
そして、すべてのシーンを描画した後で、これらの透明なオブジェクトを描画します。そうしないと、不正確な結果が得られます。
時々これを行うのは苦痛であることはわかっていますが、それが正しい方法です。
レッスン 7 のコードを使用します。
まず、コードの先頭に 2 つの新しい変数を追加します。わかりやすくするためにコード全体を書き直しました。
}
ヴァール
h_RC: HGLRC; // レンダリング コンテキスト (シェーディング記述テーブル)。
h_DC: HDC; // デバイスコンテキスト (デバイス記述テーブル)
h_Wnd: HWND;
h_Instance: HINST; // プログラムインスタンス(インスタンス)。
key : Array[0..255] Of Boolean // キーボード ルーチンの配列;
light : ブール値; // 光源のオン/オフ
Blend : Boolean // ブレンドのオフ/オン (新規)
lp : Boolean // L キーが押されましたか?
fp : Boolean; // F キーが押されましたか?
bp : Boolean; // B キーが押されましたか?
xrot : GLfloat // X 回転;
yrot : GLfloat // Y回転;
xspeed : GLfloat // X 回転速度
yspeed : GLfloat; // Y 回転速度
z : GLfloat = -5.0 f; // 画面奥までの距離
LightAmbient: Array[0..3] Of GLfloat = (0.5, 0.5, 0.5, 1.0); //環境光パラメータ (新規)
LightDiffuse: Array[0..3] Of GLfloat = (1.0, 1.0, 1.0, 1.0); // 拡散光パラメータ (新規)
LightPosition: Array[0..3] Of GLfloat = (0.0, 0.0, 2.0, 1.0); // 光源位置 (new)
filter : Gluint; // フィルターの種類
texture : Array[0..2] Of Gluint // 3 つのテクスチャ用のストレージ スペース;
プロシージャ glGenTextures(n: GLsizei; 変数テクスチャ: stdcall);
opengl32;
プロシージャ glBindTexture(ターゲット: GLenum; テクスチャ: stdcall);
opengl32;
関数 gluBuild2DMipmaps(ターゲット: GLenum; コンポーネント、幅、高さ: GLint;
形式、タイプ: GLenum; データ: ポインタ): 外部 glu32 名。
'gluBuild2DMipmaps';
{
次に、LoadGLTextures() に進みます。
(TextureImage[0]=LoadBMP('Data/Crate.bmp')) を検索します。
この行。前のレッスンの木箱テクスチャの代わりに色付きガラス テクスチャを使用します。
if (TextureImage[0]=LoadBMP("Data/glass.bmp")); // ガラスビットマップをロードします(変更済み)
}
Function LoadTexture: boolean //ビットマップをロードしてテクスチャに変換します。
ヴァール
Status : boolean // ステータスインジケーター
TextureImage : Array[0..1] Of PTAUX_RGBImageRec // テクスチャの保存領域を作成します。
始める
ステータス := false;
ZeroMemory(@TextureImage, sizeof(TextureImage)); // ポインタを NULL に設定します。
TextureImage[0] := LoadBMP('Walls.bmp');
TextureImage[0] <> Nil の場合
始める
ステータス := TRUE // ステータスを TRUE に設定します。
glGenTextures(1, texture[0]); // テクスチャを作成します
// 最近接フィルター マップを作成します
glBindTexture(GL_TEXTURE_2D, テクスチャ[0]);
// テクスチャを生成する
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0].sizeX,
TextureImage[0].sizeY、0、GL_RGB、GL_UNSIGNED_BYTE、
テクスチャイメージ[0].data);
glBindTexture(GL_TEXTURE_2D, texture[1]); //ビットマップデータから生成された一般的なテクスチャを使用します。
// テクスチャを生成する
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0].sizeX,
TextureImage[0].sizeY、0、GL_RGB、GL_UNSIGNED_BYTE、
テクスチャイメージ[0].data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // 線形フィルタリング
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 線形フィルタリング
//MipMapped テクスチャを作成
glBindTexture(GL_TEXTURE_2D, テクスチャ[2]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_NEAREST); // (新規)
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0].sizeX,
TextureImage[0].sizey、GL_RGB、GL_UNSIGNED_BYTE、
TextureImage[0].data); //(新規) }
終わり;
If assign(TextureImage[0]) then // テクスチャが存在するかどうか
If assign(TextureImage[0].data) then // テクスチャ画像が存在するかどうか
TextureImage[0].data := Nil // テクスチャ画像が占有しているメモリを解放します。
TextureImage[0] := Nil // 画像構造を解放します。
result := ステータス // ステータスを返します。
終わり;
{
次の 2 行を glInit() コード セクションに追加します。
最初の行は、このオブジェクトを最大の明るさで描画し、50% のアルファ ブレンディング (半透明) を与えます。
ブレンド オプションをオンにすると、このオブジェクトは 50% 透明になります。
2 行目は、使用するブレンドのタイプを設定します。
ルイ・マーティンズが追加:
アルファ チャネル値 0.0 は、オブジェクトのマテリアルが完全に透明であることを意味します。
1.0 は完全に不透明であることを意味します。
}
Procedure glInit(); // ここで OpenGL のすべての設定を開始します
始める
If (Not LoadTexture) then // テクスチャ読み込みサブルーチンを呼び出す
exit; // ロードに失敗した場合は終了します。
glEnable(GL_TEXTURE_2D); // テクスチャマッピングを有効にする
glShadeModel(GL_SMOOTH); // 影のスムージングを有効にする
glClearColor(0.0, 0.0, 0.0, 0.0); // 黒の背景
glClearDepth(1.0); //深度バッファを設定します。
glEnable(GL_DEPTH_TEST); // 深度テストを有効にする
glDepthFunc(GL_LESS); // 完了した深度テストのタイプ
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); //高度に最適化された透視投影計算
glLightfv(GL_LIGHT1, GL_AMBIENT, @LightAmbient[0]); // 環境光を設定します。
glLightfv(GL_LIGHT1, GL_DIFFUSE, @LightDiffuse[0]); // 拡散光を設定します。
glLightfv(GL_LIGHT1, GL_POSITION, @LightPosition); // 光源の位置
glEnable(GL_LIGHT1); // 光源 1 番を有効にする
glColor4f(1.0, 1.0, 1.0, 0.5); // 最大輝度、50% アルファ ブレンディング (新規)
glBlendFunc(GL_SRC_ALPHA, GL_ONE); // ソースピクセルのアルファチャンネル値に基づく半透明ブレンディング関数 (新規)
終わり;
{レッスン 7 の終わり近くにある次のコード スニペットを見つけてください。
If Keys[VK_LEFT] then //左方向キーが押されましたか?
yspeed := yspeed - 0.01; //はいの場合は、yspeed を下げます。
上記のコードに続いて、次のコードを追加します。
これらの行は、B キーが押されたかどうかを監視します。
そうである場合、コンピュータはブレンド オプションがオンになっているかどうかを確認します。
次に、逆の状態に設定します。
}
If (keys[ord('B')] And Not bp) then //B キーが押されていて、bp は FALSE?
始める
bp := TRUE; // はいの場合、bp は TRUE に設定されます。
Blend := ブレンドではありません // ブレンド オプションを TRUE / FALSE に切り替えます。
If (ブレンド) then // ブレンドはオンですか?
始める
glEnable(GL_BLEND); // ブレンドをオンにする
glDisable(GL_DEPTH_TEST); // 深度テストをオフにする
終わり
それ以外の場合 // それ以外の場合
始める
glDisable(GL_BLEND); // ブレンドをオフにする
glEnable(GL_DEPTH_TEST); // 深度テストをオンにする
終わり;
終わり;
If (Not Keys[ord('B')]) then // B キーは離されましたか?
始める
bp := FALSE; // はいの場合、bp を FALSE に設定します。
終わり;
{
しかし、テクスチャ マッピングを使用する場合、ブレンドの色を指定するにはどうすればよいでしょうか? それは非常に簡単です。
テクスチャ モードを調整する場合、テクスチャ テクスチャの各ピクセルの色はアルファ チャネル パラメータによって決まります。
現在のピクセルの色を乗算して取得します。
例えば、描画色は(0.5, 0.6, 0.4)、
色を乗算して (0.5、0.6、0.4、0.2) を取得します。
(alpha パラメータが指定されていない場合、デフォルトは 0 になります)。
それでおしまい! OpenGL でのアルファ ブレンディングの実装は確かに非常に簡単です。
}
{
オリジナルのメモ (1999/11/13)
私 (NeHe) の色混合コードは、表示されるオブジェクトがよりリアルに見えるように変更されました。
アルファ パラメータを使用してソース ピクセルとデスティネーション ピクセルを同時にブレンドすると、オブジェクトの人工的な痕跡が明白に見えます。
これにより、オブジェクトの背面が側面に沿って暗く見えます。
基本的にオブジェクトは奇妙に見えます。
私が使用した色の混合方法は最良ではないかもしれませんが、うまくいきました。
ライトを有効にすると、オブジェクトがリアルに見えます。
オリジナルのコードを提供してくれた Tom に感謝します。彼が使用した色の混合方法は正しいです。
しかし、オブジェクトは期待したほど魅力的には見えません:)
一部のグラフィックス カードの glDepthMask() 関数の問題に対処するため、コードが再度変更されました。
このコマンドは、一部のカードで深度バッファ テストを有効または無効にする場合にはあまり効果的ではないようです。
そこで、深度バッファテストを有効または無効にするコードを昔ながらの glEnable と glDisable に変換しました。
テクスチャ マップのアルファ ブレンディング
テクスチャ マップに使用されるアルファ パラメータは、色と同様に問題マップから読み取ることができます。
方法は次のとおりです。必要なマテリアルをロードし、同時にそのアルファパラメータを取得する必要があります。
次に、glTexImage2D() を呼び出すときに GL_RGBA のカラー形式を使用します。
}