{
Selamat datang di pelajaran sembilan. Saat ini, Anda seharusnya sudah memiliki pemahaman yang baik tentang OpenGL.
"CKER: Jika tidak, itu pasti kesalahan penerjemah saya...".
(Myling menambahkan: Dosa saya semakin besar, haha)
Anda telah mempelajari setiap detail pengaturan jendela OpenGL.
Belajar memetakan dan menambahkan pencampuran cahaya dan warna (transparansi) pada objek yang berputar.
Pelajaran ini harus dianggap sebagai tutorial perantara.
Anda akan mempelajari cara memindahkan bitmap di sekitar adegan 3D dan menghilangkan piksel hitam dari bitmap (menggunakan pencampuran warna).
Selanjutnya, warnai tekstur hitam putih, dan terakhir Anda akan belajar membuat warna yang kaya,
Dan padukan tekstur dengan warna berbeda satu sama lain untuk mendapatkan efek animasi sederhana.
Kita akan melakukan modifikasi berdasarkan kode dari pelajaran pertama. Pertama tambahkan beberapa variabel di awal kode sumber program.
Saya menulis ulang seluruh kode untuk kejelasan.
}
Var
h_RC: HGLRC; // Rendering Konteks (tabel deskripsi bayangan).
h_DC: HDC; // Konteks Perangkat (tabel deskripsi perangkat)
h_Wnd: HWND; // pegangan jendela
h_Instance: HINST; // Contoh Program (contoh).
kunci : Array[0..255] Dari Boolean; // Array untuk rutinitas keyboard
{Baris berikut baru ditambahkan.
twinkle dan tp merupakan variabel Boolean, artinya hanya dapat disetel ke TRUE atau FALSE.
twinkle digunakan untuk melacak apakah efek kedipan diaktifkan.
tp digunakan untuk memeriksa apakah tombol 'T' ditekan atau dilepaskan.
(tp=TRUE bila ditekan, tp=FALSE bila dilepas).}
twinkle : Boolean; // Bintang berkelap-kelip (baru)
tp : Boolean; // Apakah 'T' ditekan?
{Sekarang mari kita membuat struktur.
Struktur kata terdengar menakutkan, tetapi sebenarnya tidak. (Ini adalah tipe rekaman Delphi)
Struktur menggunakan sekumpulan tipe data sederhana (dan variabel, dll.) untuk mengekspresikan kombinasi data serupa yang lebih besar.
Kami tahu kami sedang melacak bintang-bintang.
Anda dapat melihat bintang-bintang di bawah;
Setiap bintang memiliki tiga nilai warna bilangan bulat. Satu merah (kanan), satu hijau (g), dan satu biru (b).
Selain itu, setiap bintang berada pada jarak yang berbeda dari pusat layar,
Dan bisa dalam sudut mana saja dalam 360 derajat dengan bagian tengah layar sebagai titik asal.
Jumlah dist floating point untuk melacak jarak.
Jumlah sudut floating point melacak nilai sudut bintang.
Jadi kami menggunakan sekumpulan data untuk mendeskripsikan warna, jarak, dan sudut bintang di layar.
Sayangnya kami melacak lebih dari satu bintang.
Namun tidak perlu membuat 50 nilai merah, 50 nilai hijau, 50 nilai biru, 50 nilai jarak
dan 50 nilai sudut, dan buat saja bintang array. }
Jenis
bintang = Rekam // Buat struktur untuk bintang, beri nama bintang
r, g, b: bilangan bulat; // warna bintang
dist: GLfloat; //Jarak bintang dari pusat
sudut: GLfloat; //Sudut bintang saat ini
Akhir;
Var
star : Array[0..49] Bintang; // Gunakan struktur 'bintang' untuk menghasilkan array 'bintang' yang berisi 50 elemen
{Selanjutnya kita menyiapkan beberapa variabel pelacakan:
Variabel jarak (zoom) bintang dari pengamat,
Sudut (kemiringan) saat kita melihat bintang,
dan putaran variabel yang menyebabkan bintang berkelap-kelip berputar mengelilingi sumbu Z.
Variabel loop digunakan untuk menggambar 50 bintang.
texture[1] digunakan untuk menyimpan tekstur hitam putih.
Jika Anda membutuhkan lebih banyak tekstur,
Anda harus menambah ukuran susunan tekstur ke jumlah tekstur yang Anda putuskan untuk digunakan.
}
zoom : GLfloat = -15.0; // Jarak bintang dari pengamat
kemiringan : GLfloat = 90.0; // Kemiringan bintang
spin : GLfloat; // Rotasi bintang yang berkelap-kelip
lingkaran : GLuint; // Variabel Lingkaran Global
tekstur : Array[0..1] Dari GLuint; // Menyimpan tekstur
Prosedur glGenTextures(n: GLsizei; Var tekstur: GLuint);
bukagl32;
Prosedur glBindTexture(target: GLenum; tekstur: GLuint);
bukagl32;
{
Kode tepat di atas adalah kode yang kita gunakan untuk memuat tekstur.
Saya tidak akan menjelaskan kode ini secara detail.
Kode ini persis sama dengan yang kita gunakan pada Pelajaran 6, 7, dan 8.
Bitmap yang dimuat kali ini disebut star.bmp.
Di sini kita menggunakan glGenTextures(1, &texture[0]),
untuk menghasilkan tekstur. Teksturnya menggunakan pemfilteran linier.
}
Fungsi LoadTexture: boolean; //Muat bitmap dan ubah menjadi tekstur
Var
Status : boolean; // Indikator status
TextureImage : Array[0..1] Of PTAUX_RGBImageRec; // Membuat ruang penyimpanan tekstur
Mulai
Status := salah;
ZeroMemory(@TextureImage, sizeof(TextureImage)); // Setel penunjuk ke NULL
TextureImage[0] := LoadBMP('Bintang.bmp');
Jika TextureImage[0] <> Nihil Lalu
Mulai
Status := BENAR; // Atur Status ke BENAR
glGenTextures(1, tekstur[0]); // Membuat tekstur
// Buat peta filter terdekat
glBindTexture(GL_TEXTURE_2D, tekstur[0]);
// Menghasilkan tekstur
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, Gambar Tekstur[0].ukuranX,
Gambar Tekstur[0].ukuranY, 0, GL_RGB, GL_UNSIGNED_BYTE,
TeksturGambar[0].data);
Akhir;
Jika ditugaskan(TextureImage[0]) Lalu // Apakah teksturnya ada
Jika ditugaskan(TextureImage[0].data) Lalu // Apakah gambar tekstur ada
TextureImage[0].data := Nihil; // Lepaskan memori yang ditempati oleh gambar tekstur
TextureImage[0] := Nihil; // Lepaskan struktur gambar
hasil := Status; // Status Pengembalian
Akhir;
{Atur mode rendering OpenGL di glInit(). Kami tidak akan menggunakan pengujian mendalam di sini,
Jika Anda menggunakan kode dari Pelajaran 1,
Harap konfirmasi apakah glDepthFunc(GL_LEQUAL) dan glEnable(GL_DEPTH_TEST) telah dihapus.
Jika tidak, hasil yang Anda lihat akan berantakan.
Di sini kita menggunakan pemetaan tekstur,
Jadi pastikan Anda telah menambahkan kode apa pun yang tidak disertakan pada pelajaran pertama.
Anda akan melihat bahwa kami mengaktifkan pemetaan tekstur dengan mencampurkan warna.
}
Prosedur glInit();
Mulai
If (Bukan LoadTexture) Then // Panggil subrutin pemuatan tekstur (baru)
exit; // Jika gagal memuat, keluar (baru)
glEnable(GL_TEXTURE_2D); // Aktifkan pemetaan tekstur
glShadeModel(GL_SMOOTH); // Aktifkan penghalusan bayangan
glClearColor(0.0, 0.0, 0.0, 0.5); // latar belakang hitam
glClearDepth(1.0); //Setel buffer kedalaman
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Koreksi perspektif yang sangat bagus
glBlendFunc(GL_SRC_ALPHA, GL_ONE); // Mengatur fungsi pencampuran warna untuk mencapai efek tembus cahaya
glEnable(GL_BLEND); // Aktifkan pencampuran warna
{Berikut ini adalah kode baru.
Sudut awal, jarak, dan warna setiap bintang ditentukan.
Anda akan melihat betapa mudahnya mengubah properti struktur.
Semua 50 bintang akan didaur ulang.
Untuk mengubah sudut star[1] yang harus kita lakukan adalah star[1].angle=nilai tertentu;
Sesederhana itu! }
For loop := 0 To 49 Do // Membuat loop untuk mengatur semua bintang
Mulai
star[loop].angle := 0.0; // Semua bintang dimulai dari sudut nol
{Jarak bintang ke-loop dari pusat dibagi nilai loop dengan jumlah total bintang, lalu dikalikan 5,0.
Pada dasarnya hal ini membuat bintang terakhir sedikit lebih jauh dari pusat dibandingkan bintang sebelumnya.
Dengan cara ini, ketika loop adalah 50 (bintang terakhir), loop dibagi dengan angka adalah tepat 1,0.
Alasan mengapa kita perlu mengalikannya dengan 5,0 adalah karena 1,0*5,0 adalah 5,0.
『CKER: Omong kosong, omong kosong! Kenapa orang asing ini mirip Kong Yiji! :) 』
5.0 sudah sangat dekat dengan tepi layar. Saya tidak ingin bintang-bintang terbang keluar dari layar, jadi 5.0 adalah pilihan terbaik.
Tentu saja, jika Anda mengatur adegannya lebih dalam ke layar,
Mungkin Anda bisa menggunakan nilai yang lebih besar dari 5.0, namun bintang-bintang akan terlihat lebih kecil (semuanya karena perspektif).
Anda juga akan melihat bahwa warna setiap bintang adalah angka acak dari 0 hingga 255.
Anda mungkin bertanya-tanya mengapa kisaran nilai warna di sini bukan kisaran OpenGL yang biasa yaitu 0,0 hingga 1,0.
Fungsi pengaturan warna yang kami gunakan di sini adalah glColor4ub, bukan glColor4f sebelumnya.
ub berarti parameternya bertipe Unsigned Byte.
Kisaran nilai satu byte adalah 0~255.
Tampaknya lebih mudah menggunakan nilai byte untuk mendapatkan bilangan bulat acak daripada mendapatkan bilangan acak floating point.
}
star[loop].dist := (Trunc(loop) / 50) * 5.0; // Hitung jarak bintang dari pusat
star[loop].r := random(256); // Tetapkan komponen merah acak untuk star[loop]
star[loop].g := random(256); // Tetapkan komponen merah acak untuk star[loop]
star[loop].b := random(256); // Tetapkan komponen merah acak untuk star[loop]
Akhir;
Akhir;
{
Sekarang kita beralih ke kode gambar glDraw().
Jika Anda menggunakan kode dari Pelajaran 1, hapus kode DrawGLScene yang lama dan cukup salin kode di bawah ini.
Faktanya, kode pelajaran pertama hanya memiliki dua baris, jadi tidak banyak yang perlu dipotong.
}
Prosedur glDraw();
Mulai
glClear(GL_COLOR_BUFFER_BIT Atau GL_DEPTH_BUFFER_BIT); // Hapus layar dan buffer kedalaman
glBindTexture(GL_TEXTURE_2D, tekstur[0]); //Pilih tekstur
For loop := 0 Sampai 49 Do // Loop untuk mengatur semua bintang
Mulai
glLoadIdentity(); // Sebelum menggambar setiap bintang, setel ulang matriks observasi model
glTranslatef(0.0, 0.0, zoom); // Masuk lebih dalam ke layar (menggunakan nilai 'zoom')
glRotatef(tilt, 1.0, 0.0, 0.0); // Sudut pandang miring (menggunakan nilai 'tilt')
{
Sekarang mari kita pindahkan bintang-bintang.
Bintang dimulai di tengah layar.
Hal pertama yang perlu kita lakukan adalah memutar pemandangan sepanjang sumbu Y.
Kalau kita putar 90 derajat, sumbu Xnya tidak lagi dari kiri ke kanan, melainkan keluar layar dari dalam ke luar.
Agar lebih jelas, mari kita beri contoh. Bayangkan Anda sedang berdiri di tengah-tengah sebuah rumah.
Sekarang bayangkan dinding di sebelah kiri Anda bertuliskan -x, dan dinding di depan Anda bertuliskan -z.
Dinding di sebelah kanan adalah +x, dan dinding di belakang Anda adalah +z.
Jika seluruh rumah diputar 90 derajat ke kanan, tetapi Anda tidak bergerak, maka dinding di depannya akan menjadi -x, bukan -z.
Semua dinding lainnya juga bergerak. -z muncul di sebelah kanan, +z muncul di sebelah kiri, dan +x muncul di belakang Anda.
Apakah kamu sudah gila? Dengan memutar pemandangan, kita mengubah orientasi bidang x dan z.
Baris kode kedua memindahkan nilai positif sepanjang sumbu x.
Biasanya nilai positif pada sumbu x berarti berpindah ke sisi kanan layar (yaitu, arah positif sumbu x yang biasa).
Namun di sini karena kita memutar sistem koordinat di sekitar sumbu y, arah positif sumbu x bisa ke segala arah.
Jika kita memutarnya 180 derajat, sisi kiri dan kanan layar akan terpantul.
Jadi kalau kita bergerak sepanjang sumbu x positif, bisa ke kiri, kanan, maju, atau mundur.
}
glRotatef(star[loop].angle, 0.0, 1.0, 0.0); //Putar ke sudut bintang yang sedang digambar
glTranslatef(star[loop].dist, 0.0, 0.0); // Bergerak maju sepanjang sumbu X
{
Kode berikut memiliki sedikit trik.
Bintang-bintang sebenarnya memiliki tekstur yang datar.
Sekarang Anda menggambar segi empat datar di tengah layar dan menerapkan tekstur, dan itu terlihat bagus.
Semuanya seperti yang Anda bayangkan. Namun saat Anda memutar 90 derajat sepanjang sumbu y,
Dua sisi tekstur pada layar yang menghadap Anda hanyalah sisi kanan dan kiri. Itu hanya terlihat seperti garis tipis.
Ini bukan yang kami inginkan. Kami ingin bintang-bintang selalu menghadap kami, tidak peduli bagaimana layar diputar atau dimiringkan.
Kami melakukannya dengan membatalkan rotasi apa pun yang dilakukan pada bintang sebelum menggambarnya.
Anda dapat membalikkan rotasi untuk melawan rotasi. Saat kita memiringkan layar, sebenarnya kita memutar bintang pada sudutnya saat ini.
Dengan membalik urutannya, kita melakukan "anti-rotasi" bintang pada sudutnya saat ini. Artinya, bintang diputar oleh nilai negatif sudut arus.
yaitu,
Jika kita memutar bintang 10 derajat, kita memutarnya -10 derajat sehingga bintang kembali menghadap layar pada sumbu tersebut.
Baris pertama di bawah membatalkan rotasi sepanjang sumbu y. Lalu, kita juga perlu mengimbangi kemiringan layar sepanjang sumbu x.
Untuk melakukan ini, kita hanya perlu memutar layar lagi – miringkan.
Setelah menghilangkan rotasi pada sumbu x dan y, bintang tersebut kini kembali menghadap kita sepenuhnya.
}
glRotatef(-star[loop].angle, 0.0, 1.0, 0.0); // Membatalkan sudut bintang saat ini
glRotatef(-tilt, 1.0, 0.0, 0.0); // Batalkan kemiringan layar
{Jika binar BENAR, pertama-tama kita menggambar bintang yang tidak diputar di layar:
Kurangi jumlah bintang saat ini (lingkaran) dari jumlah total bintang (angka) lalu kurangi 1.
untuk mengekstrak warna berbeda dari setiap bintang (hal ini dilakukan karena rentang loop dari 0 hingga angka-1).
Misal hasilnya 10, kita pakai warna bintang no 10.
Dengan cara ini warna bintang yang berdekatan selalu berbeda. Itu bukan ide yang bagus, tapi berhasil.
Nilai terakhir adalah komponen saluran alfa. Semakin kecil nilainya, semakin redup bintangnya.
Karena binar diaktifkan, setiap bintang akan diundi dua kali.
Program akan berjalan lebih lambat, tergantung pada kinerja mesin Anda.
Namun warna bintang yang digambar dalam dua lintasan menyatu satu sama lain dan menghasilkan efek yang luar biasa.
Pada saat yang sama, karena bintang pada lintasan pertama tidak berputar, bintang setelah mengaktifkan binar terlihat seperti efek animasi.
(Jika Anda tidak mengerti di sini, lihat sendiri efek berjalan dari program ini.)
Perlu dicatat bahwa mewarnai tekstur itu mudah.
Meskipun teksturnya sendiri berwarna hitam putih, namun teksturnya akan berubah sesuai warna apa pun yang kita pilih sebelum mengecatnya.
Selain itu, perlu diperhatikan juga bahwa nilai warna yang kami gunakan di sini adalah tipe byte,
bukan angka floating point biasa. Bahkan komponen saluran alfa pun seperti ini. }
If (twinkle) Then // Aktifkan efek twinkle
Mulai
// Tentukan warna menggunakan nilai byte
glColor4ub(bintang[(50 - putaran) - 1].r, bintang[(50 - putaran) - 1].g,
bintang[(50 - putaran) - 1].b, 255);
glBegin(GL_QUADS); // Mulai menggambar segi empat yang dipetakan tekstur
glTexCoord2f(0,0, 0,0);
glVertex3f(-1.0, -1.0, 0.0);
glTexCoord2f(1.0, 0.0);
glVertex3f(1.0, -1.0, 0.0);
glTexCoord2f(1.0, 1.0);
glVertex3f(1.0, 1.0, 0.0);
glTexCoord2f(0.0, 1.0);
glVertex3f(-1.0, 1.0, 0.0);
glEnd(); // Akhir gambar segi empat
Akhir;
{
Sekarang gambarlah lintasan kedua dari bintang-bintang.
Satu-satunya perbedaan dari kode sebelumnya adalah bintang kali ini pasti akan digambar, dan kali ini bintang akan berputar mengelilingi sumbu z.
}
glRotatef(spin, 0.0, 0.0, 1.0); // Memutar bintang pada sumbu z
// Tentukan warna menggunakan nilai byte
glColor4ub(bintang[loop].r, bintang[loop].g, bintang[loop].b, 255);
glBegin(GL_QUADS); // Mulai menggambar segi empat yang dipetakan tekstur
glTexCoord2f(0,0, 0,0);
glVertex3f(-1.0, -1.0, 0.0);
glTexCoord2f(1.0, 0.0);
glVertex3f(1.0, -1.0, 0.0);
glTexCoord2f(1.0, 1.0);
glVertex3f(1.0, 1.0, 0.0);
glTexCoord2f(0.0, 1.0);
glVertex3f(-1.0, 1.0, 0.0);
glEnd(); // Akhir gambar segi empat
{Kode di bawah mewakili pergerakan bintang.
Kami meningkatkan nilai putaran untuk memutar semua bintang (revolusi).
Kemudian, tingkatkan sudut rotasi setiap bintang sebanyak loop/angka.
Hal ini menyebabkan bintang yang berada jauh dari pusat berputar lebih cepat. Terakhir kurangi jarak tiap bintang dari tengah layar.
Sepertinya bintang-bintang terus-menerus tersedot ke tengah layar. }
spin := spin + 0,01; // Revolusi bintang
star[loop].angle := star[loop].angle + Trunc(loop) / 50; // Mengubah sudut rotasi bintang
star[loop].dist := star[loop].dist - 0.01; // Mengubah jarak bintang dari pusat
{Beberapa baris berikutnya memeriksa apakah bintang telah menyentuh bagian tengah layar.
Saat bintang menyentuh bagian tengah layar, kami memberinya warna baru dan memindahkannya 5 unit ke luar.
Sang bintang akan memulai perjalanannya kembali ke tengah layar. }
If (star[loop].dist < 0.0) Lalu // Apakah bintang sudah sampai di pusat?
Mulai
star[loop].dist := star[loop].dist + 5.0; // Pindahkan 5 unit ke luar
star[loop].r := random(256); // Tetapkan komponen merah baru
star[loop].g := random(256); // Tetapkan komponen hijau baru
star[loop].b := random(256); // Tetapkan komponen biru baru
Akhir;
Akhir;
Akhir;
{
Sekarang kita tambahkan kode untuk memonitor keyboard.
Pindah ke WinMain(). Temukan baris SwapBuffers(hDC).
Kami akan menambahkan kode pemantauan keyboard setelah baris ini.
Kode akan memeriksa apakah tombol T telah ditekan.
Jika tombol T ditekan dan dilepaskan maka kode pada blok if akan dieksekusi.
Jika binar itu SALAH maka akan menjadi BENAR.
sebaliknya. Selama tombol T ditekan, tp menjadi BENAR.
Ini mencegah kode di dalam blok dieksekusi berulang kali jika Anda terus menekan tombol T.
}
If (keys[ord('T')] And Not tp) Then // Apakah tombol T sudah ditekan dan nilai tp FALSE
Mulai
tp := BENAR; // Jika ya, setel tp ke BENAR
twinkle := Bukan twinkle; // Balikkan nilai twinkle
Akhir;
{
Kode di bawah ini memeriksa apakah kunci T telah dilepaskan.
Jika ya, setel tp=FALSE.
Kecuali jika nilai tp adalah FALSE,
Kalau tidak, tidak akan terjadi apa-apa sambil menahan tombol T. Jadi baris kode ini penting.
}
If (Bukan kunci[Ord('T')]) Lalu // Apakah kunci T sudah dilepas?
Mulai
tp := SALAH; // Jika ya, tp SALAH
Akhir;
{Kode yang tersisa memeriksa apakah tombol panah atas dan bawah, tombol halaman atas atau tombol halaman bawah ditekan. }
If (keys[VK_UP]) Lalu // Apakah tombol panah atas ditekan?
tilt := tilt - 0,5; // Miringkan layar ke atas
If (keys[VK_DOWN]) Then // Apakah tombol panah bawah ditekan?
tilt := tilt + 0.5; // Miringkan layar ke bawah
If (keys[VK_PRIOR]) Then // Apakah tombol page up ditekan?
memperbesar := memperbesar - 0,2; // memperkecil
If (keys[VK_NEXT]) Lalu // Apakah tombol halaman bawah ditekan?
memperbesar := memperbesar + 0,2; // Memperbesar
{
Dalam pelajaran ini saya mencoba yang terbaik untuk menjelaskan cara memuat tekstur bitmap skala abu-abu,
Setelah menghilangkan warna latar belakangnya (menggunakan warna campuran), warnai lagi, dan terakhir buatlah bergerak dalam adegan 3D.
Saya telah menunjukkan kepada Anda cara membuat warna dan efek animasi yang indah.
Prinsip penerapannya adalah tumpang tindih salinan bitmap pada bitmap asli.
Hingga saat ini, selama Anda memiliki pemahaman yang baik tentang semua yang telah saya ajarkan kepada Anda,
Anda seharusnya dapat membuat demo 3D Anda sendiri tanpa masalah apa pun.
Semua dasar-dasarnya tercakup! }
//========saya:
//Kuliah 1-9 telah diterjemahkan. Seperti yang dikatakan NEHE, pengetahuan dasar pada dasarnya telah dijelaskan.
//Saya melihat tutorial berikut, dan sepertinya ditulis oleh orang lain.
//Diperbarui, aku sangat lelah, tidur siang :), sampai jumpa lagi