GRAFIKA KOMPUTER
Oleh:
Rully Soelaiman
Berbicara tentang grafika komputer tidak terlepas dari berbagai metode dan
algorithma yang diperlukan untuk membangkitkan gambar pada layar tampilan,
dan cara pemanipulasian gambar tersebut sesuai dengan kebutuhan pengguna.
Dengan selesainya buku ini, penulis ingin mengucapkan terima kasih kepada
semua pihak yang telah banyak membantu hingga terselesaikannya buku ini,
khususnya saudara Pramudyo Ananto yang dengan segenap perhatian dan
komitmennya telah menyunting dan memeriksa bab demi bab dari buku ini.
Sebagai akhir kata, penulis berharap agar buku ini dapat bermanfaat bagi para
pembaca sekalian. Tak lupa, segala kritik dan saran demi sempurnanya buku ini
sangat penulis harapkan.
Penulis
DAFTAR ISI
Pengenalan OpenGL
OpenGL adalah suatu perangkat lunak interface untuk hardware grafik.
Interface ini terdiri dari 120 perintah yang digunakan untuk membentuk obyek
dan operasi yang diperlukan untuk menghasilkan aplikasi tiga dimensi yang
interaktif. OpenGL dirancang sebagai interface yang tidak bergantung kepada
hardware dan efisien untuk diimplementasikan pada berbagai macam platform
hardware.
Perintah OpenGL menggunakan awalan gl dan inisial huruf kapital untuk
tiap-tiap kata dari nama perintah (contohnya glColor()). Sedangkan konstantanya
dimulai dari GL_, seluruhnya menggunakan huruf kapital dan garis hubung
bawah (underscore) untuk menghubungkan tiap-tiap kata (seperti
GL_COLOR_BUFFER_BIT).
Ada juga beberapa huruf yang ditambahkan pada perintah-perintah (seperti 3f
pada glColor3f()). Hal itu disebabkan oleh karena kita dapat mendefinisikan lebih dari
satu perintah, tergantung dari argumen yang kita berikan. Akhiran 3 menunjukkan ada 3
argumen yang diberikan, versi lain dari perintah tersebut membutuhkan 4 argumen.
Akhiran f menunjukkan tipe data dari argumennya, yaitu floating-point. Perintah OpenGL
menerima sebanyak 8 tipe data yang berbeda untuk argumennya (untuk selengkapnya
lihat tabel).
Akhiran Tipe data Tipe data C Tipe data OpenGL
b 8-bit integer signed char GLbyte
s 16-bit integer Short GLshort
i 32-bit integer Long GLint, GLsizei
f 32-bit floating point Float GLfloat, GLclampf
d 64-bit floating point Double GLdouble, GLclampd
ub 8-bit unsigned integer unsigned char GLubyte, GLboolean
us 16-bit unsigned integer unsigned short Glushort
ui 32- bit unsigned integer unsigned long GLuint,GLenum,GLbitfield
Tabel tipe data argumen
glVertex2I(1, 3);
glVertex2f(1.0, 3.0);
Dua perintah di atas adalah senilai, hanya saja yang pertama membentuk
koordinat vertex sebagai integer 32 bit, sedangkan yang kedua membentuknya
sebagai floating point.
Beberapa perintah OpenGL mempunyai huruf akhir v yang menunjukkan
bahwa argumennya adalah sebuah pointer ke vektor (atau array). Ada perintah-
perintah yang mempunyai versi vektor dan nonvektor, tetapi ada pula yang hanya
mempunyai versi nonvektor saja. Berikut ini contoh perintah yang mempunyai
versi vektor dan nonvektor:
glColor3f(1.0, 0.0, 0.0);
?
? ?
?
Gambar 2-1
Hanya untuk garis vertikal, horisontal, serta 45ο yang mempunyai tingkat
kecerahan konstan sepanjang garis. Sedangkan untuk orientasi lain rasterisasi
akan manghasilkan kecerahan yang tidak rata. Bahkan pada kasus khusus,
kecerahan tergantung pada orientasi, sebagai contoh, perhatikan bahwa spasi
efektif antar piksel untuk garis 45ο lebih besar dari garis vertikal dan horisontal.
Hal ini membuat garis vertikal dan horisontal akan tampak lebih cerah dari garis
45ο. Untuk membuat kecerahan yang sama sepanjang garis dengan berbagai
macam variasi panjang dan orientasi memerlukan perhitungan dengan akar
kuadrat. Hal ini akan memperlambat proses perhitungan. Cara mengatasi yang
biasa digunakan adalah dengan melakukan perhitungan hanya kurang lebih
sepanjang garis serta mereduksi perhitungan sampai seminimal mungkin dengan
menggunakan bilangan integer.
Sebagian besar algoritma menggunakan metode incremental untuk
menyederhanakan perhitungan. Salah satu contohnya adalah:
position = start
step = increment
1 if position - end < accuracy then 4
if position > end then 2
if position < end then 3
2 position = position – step
go to 1
3 position = position + step
go to 1
4 finish
dy
= kons.
dx
∆y y2 − y1
=
∆x x2 − x1
yi + 1 = yi + ∆y
y2 − y1
yi + 1 = yi + ∆x
x2 − x1
dimana x1, y1 dan x2, y2 adalah titik awal dan akhir dari garis yang diinginkan dan
y i adalah nilai inisialisasi untuk setiap langkah sepanjang garis. Persamaan di
atas merepresentasikan sebuah hubungan perulangan untuk nilai y berturut-
turut sepanjang garis yang diinginkan. Hal itu dinamakan Digital Differential
Analizer (DDA). Untuk DDA sederhana, antara ∆x atau ∆y, yang terbesar dipilih
sebagai unit raster.
loop utama
i=1
while(i<=length)
Plot(Integer(x), Integer(y))
x = x + ∆x
y = y + ∆y
i=i+1
end while
finish
contoh1:
Buat garis dari (0,0) ke (5,5) dengan menggunakan DDA.
Inisialisasi
x1 = 0
y1 = 0
x2 = 5
y2 = 5
Length = 5
∆x = 1
∆y = 1
x = 0.5
y = 0.5
loop utama
I Plot X Y
0.5 0.5
1 (0,0)
1.5 1.5
2 (1,1)
2.5 2.5
3 (2,2)
3.5 3.5
4 (3,3)
4.5 4.5
5 (4,4)
5.5 5.5
5
4
3
2
1
0
0 1 2 3 4 5
Gambar 2-2
Hasilnya terlihat pada gambar 2-2. Perhatikan bahwa titik awal dan akhir
terlihat tepat dan piksel yang terpilih mempunyai jarak yang sama sepanjang
garis. Jika i diinisialisasi 0 sebagai pengganti 1, piksel di posisi (5,5) akan
diaktifkan. Hal ini akan menyebabkan hasil yang tidak diharapkan. Jika titik awal
berada di pojok kiri bawah, pengaktifan piksel pada posisi (5,5) akan
menghasilkan titik akhir yang tidak tepat (lihat gambar 2-2). Sebagai tambahan,
jika dua garis digambar secara berurutan, maka piksel pada posisi (5,5) akan
diaktifkan dua kali, pertama pada akhir dari garis yang pertama dan kedua pada
awal garis yang kedua. Hal ini menyebabkan piksel menjadi lebih terang
dan/atau piksel mempunyai warna yang salah.
Contoh2:
Buat garis dari (0,0) ke (-8,-4) dengan menggunakan DDA.
Inisialisasi
x1 = 0
y1 = 0
x2 = -8
y 2 = -4
Length = 8
∆x = -1
∆y = -0.5
x = -0.5
y = -0.5
loop utama
i Plot x Y
-0.5 0.5
1 (-1,-1)
-1.5 -1.0
2 (-2,-1)
-2.5 -1.5
3 (-3,-2)
-3.5 -2.0
4 (-4,-2)
-4.5 -2.5
5 (-5,-3)
-5.5 -3.0
6 (-6,-3)
-6.5 -3.5
7 (-7,-4)
-7.5 -4.0
8 (-8,-4)
-8.5 -4.5
-8 -7 -6 -5 -4 -3 -2 -1 0
0
-1
-2
-3
-4
Gambar 2-3
Meskipun hasil yang tampak dalam gambar 2-3 kelihatan bisa diterima,
pada garis dari (0,0) ke (-8,4) dan (8,-4) akan terlihat bahwa rasterisasi garis
condong ke salah satu bagian (dalam hal ini bawah) dari garis yang sebenarnya.
Selain itu titik tambahan terjadi pada akhir dari garis. Jadi garis menjadi
tergantung pada orientasi dan tidak sesuai dengan syarat umum di atas. Lebih
jauh, jika fungsi integer diasumsikan menggunakan fungsi floor (pembulatan ke
bawah), hasilnya akan berbeda lagi. Sehingga harus digunakan algoritma yang
rumit dan lambat, atau akurasi dari posisi titik akhir disesuaikan. Dengan kata lain
algoritma ini kurang bagus karena harus dibentuk dengan menggunakan floating
point.
y
(1,1)
(0,1) ?
x
?
(0,0) (1,0)
Gambar 2-4
0
0 1 2 3
1
0.5
0
-0.5
-1
Gambar 2-5
Tidak semua garis tepat berada di titik raster. Hal ini diperlihatkan pada
gambar 2-5 di mana sebuah garis dengan gradien 3/8 yang melalui titik raster
(0,0) dan secara berurutan melalui tiga titik. Juga diperlihatkan perhitungan error
dalam merepresentasikan garis dengan piksel diskrit. Karena yang diperlukan
hanya tanda dari kondisi error, maka nilai error diinisialisasi dengan -½. Sehingga
jika gradien dari garis lebih dari atau sama dengan ½, nilai dari kondisi error pada
titik raster satu unit berikutnya (1,0) dapat ditentukan dengan menjumlahkan
gradien dari garis pada nilai dari kondisi error, yaitu:
e=e+m
dimana m adalah gradien garis. Dalam hal ini karena e diinisialisasi -½, maka:
e = -½ + 3/8 = -1/8
karena e negatif, garis akan berada di bawah dari pertengahan piksel. Sehingga
piksel pada level horisontal yang sama dengan titik sebelumnya lebih baik dipilih
sehingga y tidak di-increment. Kemudian increment lagi kondisi error dengan
gradien sehingga menghasilkan:
e = -1/8 + 3/8 = ¼
pada titik raster berikutnya (2,0). Di sini e bernilai positif sehingga garis melalui
atas pertengahan titik. Elemen raster pada level vertikal yang lebih tinggi (2,1)
menjadi pilihan yang lebih baik. Sehingga y di-increment satu unit. Sebelum
melanjutkan pada titik berikutnya, kondisi error direinisialisasi terlebih dahulu. Hal
itu dilakukan dengan mengurangi error dengan 1. Jadi,
e = ¼ - 1 = -3/8
Karena e negatif, nilai y tidak di-increment. Hal-hal di atas menunjukkan bahwa
kondisi error merupakan penentu dari perubahan nilai y pada garis yang
diinginkan pada tiap-tiap elemen raster dimulai dari -½.
inisialisasi variabel
x = x1
y = y1
∆x = x2 - x1
∆y = y2 - y1
e = ∆y /∆x – ½
loop utama
for i=1 to ∆x
Plot(x,y)
while(e>=0)
y=y+1
e=e-1
end while
x=x+1
e = e + ∆y /∆x
next i
finish
contoh:
Buat garis dari (0,0) ke (5,5) dengan menggunakan algoritma Bresenham.
Inisialisasi
x=0
y=0
∆x = 5
∆y = 5
e=1–½=½
loop utama
i Plot e x y
½ 0 0
1 (0,0)
-½ 0 1
½ 1 1
2 (1,1)
-½ 1 2
½ 2 2
3 (2,2)
-½ 2 3
½ 3 3
4 (3,3)
-½ 3 4
½ 4 4
5 (4,4)
-½ 4 5
½ 5 5
5
4
3
2
1
0
0 1 2 3 4 5
Gambar 2-6
ε = 2*e*∆x è e = ε /(2*∆x)
dari kondisi error pada algoritma sebelumnya menghasilkan algoritma integer.
Algoritma Bresenham Integer untuk oktan pertama
Titik awal dan akhir adalah (x1, y1) dan (x2, y2) diasumsikan tidak sama.
Semua variabel diasumsikan integer
Inisialisasi variabel
x = x1
y = y1
∆x = x2 – x1
∆y = y2 – y1 ∆y 1
ε = 2*∆y -∆x è e = −
∆x 2
ε ∆y 1
loop utama = −
2 * ∆x ∆x 2
for i=1 to ∆x 2 * ∆y − ∆x
ε
Plot(x,y) =
2 * ∆x 2 * ∆x
while(ε>=0)
y=y+1 e = e − 1
ε = ε – 2*∆x è ε ε 2 * ∆ x
= −
end while 2 * ∆ x 2 * ∆ x 2 * ∆ x
x=x+1 ∆ y
ε = ε + 2*∆y è e = e +
∆ x
next i
ε ε 2 * ∆ y
finish = +
2 * ∆ x 2 * ∆ x 2 * ∆ x
y++ y++
x=x-1 x=x+1
x-- x++
y=y-1 y=y-1
y-- y--
Gambar 2-7
inisialisasi
x = x1
y = y1
∆x = abs(x2- x1)
∆y = abs(y2- y1)
s1 = Sign(x2- x1)
s2 = Sign(y2- y1)
ε = 2*∆y – ∆x
Contoh:
Buat garis dari (0,0) ke (-8,-4) dengan menggunakan algoritma bresenham.
Inisialisasi
x=0
y=0
∆x = 8
∆y = 4
s1 = -1
s2 = -1
Interchange = 0
ε=0
loop utama
i Plot ε X Y
0 0 0
1 (0,0)
-16 0 -1
-8 -1 -1
2 (-1,-1)
0 -2 -1
3 (-2,-1)
-16 -2 -2
-8 -3 -2
4 (-3,-2)
0 -4 -2
5 (-4,-2)
-16 -4 -3
-8 -5 -3
6 (-5,-3)
0 -6 -3
7 (-6,-3)
-16 -6 -4
-8 -7 -4
8 (-7,-4)
0 -8 -4
-8 -7 -6 -5 -4 -3 -2 -1 0
0
-1
-2
-3
-4
Gambar 2-8
digenerate
3 2
4 1 x
5 8
6 7
separuh lingkaran
dicerminkan thd
grs x (y=0)
Gambar 2-9
(0,R)
Gambar 2-10
Pada pemilihan piksel berikutnya, hanya ada tiga kemungkinan piksel
yang akan menghasilkan lingkaran yang diinginkan. Ketiganya adalah vertikal ke
bawah (mV), horisontal ke kanan (mH), serta diagonal ke kanan bawah (mD).
Algoritma akan memilih piksel berikutnya yang memiliki jarak minimum dengan
lingkaran sebenarnya.
mH = |(xi + 1)2 + (yi)2 - R2|
mV = |(xi)2 + (yi - 1)2 - R2|
mD = |(xi + 1)2 + (yi - 1)2 -R2|
(x i,yi) (x i+1,yi)
mH
mV mD
(x i,yi-1) (xi+1,yi-1)
Gambar 2-11
(x i,yi) (x i+1,yi) 2
mH
mV mD
(xi+1,yi-1)
(x i-1,yi-1) (x i,yi-1)
4 3 5
Gambar 2-12
Jika ∆i<0, maka titik diagonal (xi + 1, yi - 1) berada di dalam lingkaran yang
sebenarnya, yakni kondisi 1 dan 2 pada gambar 2-12. Jadi kita harus memilih titik
mH atau mD. Untuk menentukannya, pada kondisi 1 kita memerlukan selisih
antara kuadrat jarak dari lingkaran sebenarnya ke titik mH dan kuadrat jarak dari
lingkaran sebenarnya ke titik mD, yaitu:
δ= |(xi + 1)2 + (yi)2 - R2| - |(xi + 1)2 + (yi - 1)2 -R2|
Jika δ
<0, maka jarak antara lingkaran sebenarnya dengan piksel diagonal
(mD) lebih besar dari jarak antara lingkaran sebenarnya dengan piksel horisontal
(mH). Jadi jika δ
<=0 pilihlah mH(xi + 1, yi), sedangkan jika δ
>0 pilihlah mD(xi + 1, yi -
1).
Perhitungan di atas bisa disederhanakan dengan memperhatikan bahwa
pada kondisi 1 piksel diagonal selalu berada di dalam lingkaran sedangkan piksel
horisontal selalu berada di luar lingkaran, sehingga:
(xi + 1)2 + (yi)2 -R2 >= 0
(xi + 1)2 + (yi - 1)2 -R2 < 0
jadi,
δ= (xi + 1)2 + (yi)2 - R2 + (xi + 1)2 + (yi - 1)2 -R2
dengan manambahkan (yi - 1)2 dan mengurangi dengan (yi)2, maka akan
diperoleh:
δ= 2[(xi + 1)2 + (yi - 1)2 - R2] + 2yi - 1
dengan persamaan dari ∆i maka:
δ= 2(∆i + yi) - 1
yang menjadi jauh lebih sederhana.
Jika ∆i>0, maka titik diagonal (xi + 1, yi - 1) berada di luar lingkaran yang
sebenarnya, yakni kondisi 3 dan 4 pada gambar 2-12. Jadi kita harus memilih titik
mV atau mD. Untuk menentukannya, pada kondisi 3 kita memerlukan selisih
antara kuadrat jarak dari lingkaran sebenarnya ke titik mV dan kuadrat jarak dari
lingkaran sebenarnya ke titik mD, yaitu:
δ
’= |(xi + 1)2 + (yi - 1)2 -R2| - |(xi)2 + (yi - 1)2 - R2|
Jika δ
’<0, maka jarak antara lingkaran sebenarnya dengan piksel vertikal
(mV) lebih besar dari jarak antara lingkaran sebenarnya dengan piksel diagonal
(mD). Jadi jika δ
’<=0 pilihlah mD(xi + 1, yi - 1), sedangkan jika δ
’>0 pilihlah mV(xi, yi
- 1).
Perhitungan di atas bisa disederhanakan dengan memperhatikan bahwa
pada kondisi 3 piksel diagonal selalu berada di luar lingkaran sedangkan piksel
horisontal selalu berada di dalam lingkaran, sehingga:
(xi + 1)2 + (yi - 1)2 -R2 >= 0
(xi)2 + (yi - 1)2 -R2 < 0
jadi,
δ
’= (xi + 1)2 + (yi - 1)2 -R2 + (xi)2 + (yi - 1)2 -R2
dengan manambahkan (xi + 1)2 dan mengurangi dengan (xi)2, maka akan
diperoleh:
δ
’= 2[(xi + 1)2 + (yi - 1)2 - R2] - 2xi - 1
dengan persamaan dari ∆i maka persamaan akan menjadi:
δ
’= 2(∆i - xi) - 1
Jika berada pada kondisi 2 kita tentu saja akan memilih piksel mH(xi + 1,
y i), dan jika berada pada kondisi 4 maka piksel mV(xi, yi - 1) yang akan kita pilih.
Sedangkan jika kita berada pada kondisi 5 maka piksel yang kita pilih adalah
mD(xi + 1, yi - 1).
Algoritma lingkaran Bresenham untuk kuadran pertama
Semua variabel diasumsikan integer
Inisialisasi
xi = 0
yi = R
∆i = 2(1-R)
Limit = 0
1 Plot(xi,yi)
piksel mD
20 xi = xi + 1
y i = yi - 1
∆i = ∆i + 2xi - 2y i + 1
go to 1
piksel mV
30 y i = yi - 1
∆i = ∆i - 2y i + 1
go to 1
4. Finish
Contoh:
Buat kuadran pertama lingkaran dengan jari-jari 8. Gunakan algoritma
Bresenham.
Inisialisasi
x=0
y=0
∆i = 2(1 - 8) = -14
Limit = 0
loop utama
Plot ∆i δ δ’ X y
-14 0 8
(0,8)
-11 -13 1 8
(1,8)
-6 -7 2 8
(2,8)
-12 3 3 7
(3,7)
-3 -11 4 7
(4,7)
-3 7 5 6
(5,6)
1 5 6 5
(6,5)
9 -11 7 4
(7,4)
4 3 7 3
(7,3)
18 -7 8 2
(8,2)
17 19 8 1
(8,1)
18 17 8 0
(8,0)
Hasilnya ditunjukkan pada gambar 2-13. Kuadran yang lain dapat kita
hasilkan dengan mudah menggunakan algoritma di atas.
y
(0,8)
x
(0,0) (8,0)
Gambar 2-13
TRANSFORMASI DUA DIMENSI
DAN METODE PARAMETRIK
a b
[x y] = [( ax + by ) ( cx + dy )] = [ x ' y ']
c d
1 0
[x y] = [x y ] = [ x' y ']
0 1
koordinat dari titik P.
a 0
[x y] = [ ax y ] = [ x' y ']
0 1
Dimana karena x’=ax menghasilkan perubahan skala pada komponen x dari
vektor posisi. Hasil dari transformasi di atas terlihat pada gambar 2-1a. Sekarang
perhatikan notasi di bawah ini:
a 0
[x y] = [ ax dy ] = [ x ' y ']
0 d
− 1 0
[x y] = [− x y ] = [ x' y ']
0 1
1 b
[x y] = [ x (bx + y )] = [ x ' y ']
0 1
P P' P' P P
x x x
y P' y y
P P'
P
P
x x x
P'
(b) (d) (f)
Gambar 2-1
2.1.2 ROTASI
y
8
x
0 2 4 6 8
Gambar 2-2
3 − 1 1 3
4 1 0 1 = − 1 4
− 1 0
− 1 2
2 1
Yang menghasilkan segitiga A’B’C’. Rotasi 180ο terhadap posisi awal akan
dihasilkan dengan menggunakan matrik transformasi:
− 1 0
0 − 1
0 − 1
1 0
1 0
0 1
P'
|
|
|
| P
| |
y' |
|
| y
θ
|
|
|
|
φ X
-----------x----------
------------------x'------------------
Gambar 2-3
Vektor posisi P dan P’dituliskan sebagai:
P =[ x y ]= [r cosφ r sin φ]
P' = [
x' y ']= [
r cos(φ+ θ ) r sin(φ+ θ ) ]
Diperoleh:
P' = [
x' y ']= [
r (cosφcosθ − sin φsin θ ) r (cosφsin θ + sin φcosθ ) ]
P' = [
x' y ']= [
x cosθ − y sin θ x sin θ + y cosθ ]
cosθ sin θ
− sin θ cosθ
2.1.3 REFLEKSI
Y
F''
E'' D''
D
E X
E'
F'
D'
Gambar 2-4
Dua refleksi dari segitiga DEF ditunjukkan pada gambar 2-4. Sebuah
refleksi terhadap garis y=0 (sumbu x) diperoleh dengan menggunakan matrik:
1 0
0 − 1
8 1 8 − 1
7 31 0 = 7 − 3
0 − 1
6 − 2
6 2
− 1 0
0 1
Sedangkan refleksi terhadap garis y=x terjadi untuk
0 1
1 0
8 1 1 8
7 3 0 1
1 0 = 3 7
2 6
6 2
Seperti juga pada garis y=x, refleksi terhadap garis y=-x diperoleh dengan:
0 − 1
− 1 0
E X
2 4 6 8
E'
-2 F'
D'
-4
E'' D''
-6
F''
-8
Gambar 2-5
Pertama refleksikan segitiga ABC terhadap sumbu x:
5 3 5 − 3
5 11 0 = 5 − 1
0 − 1
7 2 7 − 2
5 − 3 3 − 5
5 − 1 0 − 1 = 1 − 5
− 1 0
7 − 2
2 − 7
5 3 3 − 5
5 10 − 1 = 1 − 5
1 0
7 2
2 − 7
2.1.4 SCALING
Seperti yang telah kita bicarakan dalam subbab transformasi titik di
atas, scaling ditentukan oleh nilai dari dua elemen diagonal primer matrik. Jika
2 0
0 2
matrik:
Y
C' B'
8
B
4 C A'
C'' B''
2
A
A'' X
2 4 6 8 10 12
1 2 0
0 3
2.2 PARAMETRIK
Selain metode raster scan seperti yang telah dibahas pada bab pertama,
untuk menggambar suatu obyek kta dapat menggunakan metode yang lain, yaitu
metode parametrik. Pada subbab ini kita akan membahas algoritma
pembangkitan lingkaran dan elips dengan menggunakan metode parametrik.
2.2.1 LINGKARAN
Sebuah lingkaran dengan pusat (0,0) dan jari-jari r direpresentasikan
oleh:
x = r cosθ
y = r sin θ
0 <= θ <= 2π
Gambar 2-7
r
r sinθ
θ
r cos θ x
xi + 1 = r cos(θi + δ)
yi + 1 = r sin(θi + δ)
Dimana θi adalah nilai dari parameter yang menghasilkan xi dan yi. Dengan
menggunakan rumus matematika penjumlahan sudut diperoleh:
xi = r cosθi
yi = r sin θi
2.2.2 ELIPS
Pada lingkaran, sejumlah titik yang berjarak sama menghasilkan
gambar yang bagus jika dihubungkan dengan garis lurus. Selain itu distribusi
titik-titik tersebut merata sehingga kita dapat menggunakan increment sudut yang
sama. Akan tetapi jika increment sudut tersebut kita gunakan untuk menggambar
elips, maka akan diperoleh hasil yang tidak sesuai dengan apa yang kita
harapkan. Hal itu disebabkan oleh karena mendekati bagian ujung dari elips
lengkungan yang terjadi terlalu besar untuk direpresentasikan dengan titik yang
hanya sedikit.
Alternatif yang digunakan adalah dengan menggunakan increment
yang sama sepanjang keliling elips. Dengan jumlah increment yang cukup maka
akan diperoleh hasil yang lebih baik. Yang kita inginkan adalah sedikit increment
pada panjang garis keliling ketika mendekati bagian ujung dimana
lengkungannya besar dan banyak increment pada panjang garis keliling ketika
berada di bagian sisi dimana lengkungannya kecil.
Distribusi titik yang diinginkan dari sebuah elips dengan pusat (0,0),
sumbu mayor a dan sumbu minor b akan dihasilkan oleh persamaan:
x = a cos θ
y = b sin θ
Gambar 2-8
dx = -a sin θ dθ
dy = b cos θ dθ
menunjukkan bahwa increment garis keliling yang diinginkan akan dihasilkan
secara otomatis. Ketika θ mendekati 0 atau π, yaitu mendekati pinggir, |dx| ≈0
dan |dy| ≈bdθ. Ketika θ mendekati π/2 atau 3π/2 yaitu sepanjang sisi, |dx| ≈adθ
dan |dy| ≈ 0. Jadi ketika mendekati ujung dimana lengkungannya besar,
dihasilkan jumlah titik yang lebih banyak. Sedangkan sepanjang sisi, dimana
lengkungannya kecil akan dihasilkan jumlah titik yang lebih sedikit. Nilai
perbandingan increment garis keliling di ujung dengan sisi adalah b/a. Lebih
jauh, perhatikan bahwa jika a=b maka akan dihasilkan increment garis keliling
yang sama dan akan menghasilkan sebuah lingkaran.
Sesuai dengan persamaan dari lingkaran, koordinat kartesius dari
sembarang titik pada elips yang berpusat di (0,0) adalah:
xi + 1 = a cos(θi + δ)
yi + 1 = b sin(θi + δ)
Dimana δ
=2π/(n-1) adalah increment dalam θ, n adalah jumlah titik pada keliling
dan θi adalah nilai dari parameter yang menghasilkan xi dan yi. Dengan
menggunakan rumus matematika penjumlahan sudut diperoleh:
a
xi + 1 = xi cos δ− yi sin δ
b
b
yi + 1 = xi sin δ+ yi cos δ
a
Karena δ
, a dan b adalah konstan, sekali lagi algoritma yang efisien
akan dihasilkan karena hanya memerlukan empat perkalian, satu penjumlahan,
serta satu pengurangan saja dalam setiap perulangannya.
2.3 IMPLEMENTASI
Salah satu contoh implementasi yang sederhana dan umum yang akan
kita bahas adalah menggambar lingkaran melalui tiga buah titik. Kita akan
menggambar lingkaran melalui suatu segitiga, yang pertama berada di luar
segitiga, sedangkan pada contoh yang kedua lingkaran tersebut berada di dalam
segitiga.
y' y
x''
y'' P2
P3
x
x'
P1
Gambar 2-9
( x1 − h) 2 + ( y1 − k ) 2 = R 2 ..........................................1a
( x 2 − h) 2 + ( y 2 − k ) 2 = R 2 ..........................................1b
( x3 − h) 2 + ( y3 − k ) 2 = R 2 ..........................................1c
B y
C
B'
C'
C''
A'/A'' B'' x
Gambar 2-10
3. Cari titik pusat dan jari-jari lingkaran.
4. Rotasikan titik pusat dari lingkaran tersebut dengan sudut yang berlawanan
arah dari langkah nomor 2.
5. Translasikan kembali titik pusat lingkaran dengan arah yang berlawanan dari
langkah pertama sehingga diperoleh titik pusat lingkaran dari segitiga asal.
6. Gambarkan lingkaran yang diinginkan dengan pusat serta jari-jari yang telah
diketahui.
Pada gambar 2-10 diperlihatkan bahwa segitiga ABC telah mengalami
operasi translasi dan rotasi sehingga titik A berada di pusat sistem koordinat dan
titik B berada pada sumbu x positif sehingga persamaan lingkarannya adalah:
x2 + y2 = R2 (a)
(xB - x)2 + y2 = R2 (b)
2 2 2
(xC - x) + (yC - y) =R (c)
dengan mengurangi persamaan (a) oleh persamaan (b) akan didapatkan bahwa
x = x2/2 dan dengan mengurangi persamaan (a) oleh persamaan (c)
diperoleh y = ½ x3/y3 (x3 – x2) + ½ y3 sehingga berdasarkan persamaan (a) akan
diperoleh juga jari-jari lingkaran .
Perhatikan bahwa jika y3=0 maka y menjadi sangat besar (tak terdefinisi).
Bagaimanapun, hal itu hanya akan terjadi jika ketiga titik tersebut berada pada
satu garis, sehingga ketiga titik tersebut tidak membentuk segitiga dan tentu saja
tidak ada lingkaran yang bisa dibuat dengan melalui ketiga titik tersebut.
y
C
(b-x)
(b-x)
a
b
(c-x)
x
α
A x
(c-x)
B x
c
Gambar 2-11
c-x+b–x=c
c + b – a = 2x
sehingga diperoleh x = (c+b-a)/2. Sedangkan untuk mencari y atau jari-jari yaitu:
tg α = yC /x
y = x tg ½ α
Apabila kita sudah mendapatkan pusat dan jari-jari maka titik pusat dapat kita
translasi dan rotasikan secara berlawanan arah dan lingkaran tersebut dapat kita
gambar.
KURVA
Gambar 3-1
Bentuk dari kurva Bezier ditentukan oleh defining polygon seperti yang terlihat
pada gambar 3-1. Kurva Bezier P(t), dengan (L+1) titik dapat dinyatakan dengan:
n
P (t ) = ∑ BiJn, i (t )
i =0
0 ≤t ≤1
n i n− i
Jn, i (t ) =
i
t (1 − t )
n n!
i
= i! ( n − i )!
dengan Jn,i(t) adalah orde-n ke-i dari fungsi basis Bernstein. Disini n adalah derajat dari
fungsi basis Bernstein, nilainya adalah jumlah control point –1.
Gambar 3-2
Pada gambar 3-2 diperlihatkan hasil dari fungsi basis Bezier, masing-masing 3, 4, dan 5
titik.
Gambar 3-3
Adapun hal-hal yang menjadi persyaratan umum dari kurva Bezier antara lain
adalah:
1. Endpoint interpolation
Kurva Bezier tidak menginterpolasi semua control point, tetapi selalu
menginterpolasi titik awal dan akhir. Seperti yang terlihat pada gambar 3-3.
Bukti:
n
P (t ) = ∑ BiJn , i (t )
i =0
n!
Jn, i (t = 0) = (1 − 0) n 0 0
0! ( n − 0)!
n! n
= (1) 1
n!
=1
Untuk t=0 n=0 maka:
Sehingga:
P ( 0) = B 0 Jn , i ( 0)
= B0
n!
Jn, i (t = 1) = (1 − 1) n− i 1i
n!(n − i )!
n!
= ( 0) n − n 1
n!( n − n)!
n! 0
= 01
n!0!
=1
n!
Jn, i (t = 1) = (1 − 1) n− i 1i
n!(n − i )!
n!
= (0) n− i 1
n!( n − i )!
n!
= 01
n!( n − i )!
=0
Sehingga:
P ' (t ) = P (t ) N + tr
n
= ∑ BiJn, i (t ) N + tr
k =0
Gambar 3-4
3. Linier precision
Jika control point ditempatkan sebagai garis lurus maka kurva Bezier yang
dibangkitkan harus membentuk garis lurus juga (lihat gambar 3-4).
Gambar 3-5
4. Convex hull
Setiap titik pada kurva Bezier berada dalam convex hull dari defining
polygon seperti yang terlihat pada gambar 3-5.
5. Variation determinishing
Kurva Bezier tidak akan berisolasi terhadap sembarang garis lebih
banyak dari defining polygon-nya. Pada gambar 3-6 kurva Bezier berisolasi
dengan garis pada tiga titik, sedangkan defining polygon-nya berisolasi pada
empat titik. Kurva akan berisolasi maksimum dengan satu garis sama dengan
isolasi dari defining polygon-nya yaitu jika kurvanya berupa garis lurus.
Gambar 3-6
n+ 1
P (t ) = ∑ BiNi , k (t )
i =1
t min ≤t ≤t max
2 ≤k ≤n + 1
dimana Bi adalah vektor posisi dari n+1 titik defining polygon dan Ni,k adalah
fungsi basis B-Spline ternormalisasi.
Untuk fungsi basis B-Spline ternormalisasi dengan orde k (derajat k-1),
fungsi basis Ni,k(t) didefinisikan sebagai:
1 → if ( xi ≤t < xi + 1)
Ni ,1(t ) = 〈 .......... .
0 → otherwise
dan
(t − xi ) Ni , k − 1(t ) ( xi + k − t ) Ni + 1, k − 1(t )
N i , k (t ) = +
xi + k − 1 − xi xi + k − xi + 1
Nilai dari xi adalah elemen dari knot vektor yang memenuhi persamaan xi≤xi+1.
Parameter t berada antara tmin dan tmax sepanjang kurva P(t).
Gambar 3-8
Gambar 3-10
Dengan menggunakan convex hull akan terlihat jika seluruh control point
adalah kolinear maka kurva B-Spline yang akan terbentuk merupakan garis lurus
pula untuk seluruh orde k. Jika terdapat l control point yang kolinear pada awal
atau akhir dari defining polygon yang non-kolinear, maka jumlah rentang kurva
kolinear yang terjadi adalah l-k+1 seperti yang terlihat pada gambar 3-9 dan 3-10
(k=3). Sedangkan jika control point yang kolinear tersebut berada pada bagian
tengah dari defining polygon, maka jumlah rentang kurva yang terjadi adalah l-
2k+3 (lihat gambar 3-11, k=3).
Gambar 3-11
3.2.1 UNIFORM
Pada knot vektor uniform, jarak dari setiap elemen knot vektor adalah
sama. Biasanya knot vektor uniform dimulai dari 0 sampai suatu nilai maksimum.
Contohnya adalah:
[0 1 2 3 4 5 6]
Untuk setiap order k, knot vektor uniform akan menghasilkan fungsi basis periodic
uniform dimana:
Ni,k(t) = Ni-1,k(t-1) = Ni+1,k(t+1)
Hasil dari fungsi basis dengan menggunakan knot vektor uniform terlihat pada gambar 3-
12:
Gambar 3-12
n≥k
Hal ini menyebabkan adanya salah satu sifat dari kurva tidak terpenuhi yaitu
endpoint interpolation. Sebagai contoh untuk k=3, maka:
1
Ps = ( B1 + B 2)
2
1
Pe = ( Bn + Bn + 1)
2
1
Ps = ( B1 + 4 B 2 + B3)
6
1
Pe = ( Bn − 1 + Bn + Bn + 1)
6
Untuk itu diperlukan suatu cara dalam mengontrol titik-titik tersebut. Salah satu
caranya adalah dengan yang dinamakan multiple coincident vertices, yaitu
dengan menggandakan control point yang berada di awal dan akhir dari defining
polygon. Sebagai contoh, untuk k=3 dengan dua control point pada awal dan
akhir sehingga B1=B2 dan Bn=Bn+1 akan menghasilkan titik awal dan titik akhir
seperti di bawah ini:
1 1
Ps = ( B1 + B 2) = ( 2 B1) = B1
Sedangkan untuk k=4, maka:
2 2
1 1
Pe = ( Bn + Bn + 1) = ( 2 Bn + 1) = Bn + 1
2 2
1 1
Ps = ( B1 + 4 B 2 + B 3) = (5B1 + B 2)
6 6
1 1
Pe = ( Bn − 1 + Bn + Bn + 1) = ( Bn − 1 + 5 Bn + 1)
6 6
Gambar 3-13
Gambar 3-14
Pada gambar 3-13 dan 3-14 diperlihatkan efek dari multiple coincident
vertices. Pada gambar 3-13 terdapat sebuah kurva dengan k=3 dimana bagian
atas tanpa menggunakan multiple coincident vertices, sedangkan pada bagian
bawah akhir dari defining polygon kurva tersebut ditambah satu control point
sehingga ada dua control point yang berhimpit.
Sedangkan pada gambar 3-14 terlihat kurva dengan k=4 tanpa multiple
coincident vertices, dengan satu multiple coincident vertices dan yang paling
bawahdua multiple coincident vertices (perhatikan bahwa pada contoh ini
multiple coincident vertices hanya diberikan pada akhir kurva saja).
3.2.2 OPEN UNIFORM
Knot vektor open uniform mempunyai nilai elemen knot yang sama pada
awal dan akhir sejumlah orde k. Sedangkan elemen knot yang tengah
mempunyai jarak yang sama. Secara umum, persamaan knot vektor open
uniform adalah:
xi = 0 1≤i≤k
xi = i-k k+1≤i≤n+1
xi = n-k+2 n+2≤i≤n+k+1
k=2 [0 0 1 2 3 4 4]
k=3 [0 0 0 1 2 3 3 3]
k=4 [0 0 0 0 1 2 2 2 2]
Hasil dari kurva B-Spline dengan knot vektor open uniform mempunyai sifat-sifat
yang hampir sama dengan kurva Bezier. Jika jumlah control point sama dengan
orde dari fungsi basis B-Spline dan knot vektor yang digunakan adalah open
uniform, maka kurva B-Spline yang dihasilkan adalah sama dengan kurva Bezier.
Pada kasus ini, knot vektor yang terjadi adalah k elemen dengan nilai 0 diikuti
dengan k elemen dengan nilai 1. Sebagai contoh, knot vektor open uniform dari
fungsi basis B-Spline dengan orde 4 adalah:
[0 0 0 0 1 1 1 1]
Hasil dari fungsi basis open uniform dengan knot vektor di atas, orde k=4 dan
jumlah control point (n+1)=4 adalah:
Gambar 3-15
Perhatikan bahwa hasil fungsi basis di atas sama dengan hasil dari fungsi basis
kurva Bezier yang terlihat pada gambar 3-2.
Sebagai tambahan, hasil dari fungsi basis B-Spline dengan knot vektor [0
0 0 1 2 2 2], orde k=3 dan jumlah control point (n+1) = 4 adalah seperti yang
terlihat pada gambar 3-15:
Gambar 3-15
PENGGAMBARAN OBYEK GEOMETRIK
DENGAN OPENGL
Jika kita menggunakan GL_POINTS, hasilnya adalah tampak pada gambar 4-3
(kanan). Argumen yang bisa dimasukkan pada perintah glBegin() ditunjukkan pada tabel
di bawah ini:
Nilai Keterangan
GL_POINTS Menggambar titik dari n vertex
GL_LINES Menggambar segmen garis berurutan secara terpisah.
Jika vertex berjumlah ganjil, maka segmen terakhir tidak
dihiraukan.
GL_LINE_STRI Menggambar segmen garis dari vertex 1 ke vertex 2,
P dari vertex 2 ke vertex 3, dst. Jadi ada n-1 segmen garis.
GL_LINE_LOO Sama dengan GL_LINE_STRIP hanya saja vertex
P terakhir dihubungkan denga vertex 1 sehingga membentuk loop.
GL_POLYGON Menggambar poligon dari n vertex (n>2).
GL_TRIANGLE Menggambar segitiga (poligon tiga sisi) berurutan. Jika
S jumlah vertex bukan merupan kelipatan 3 maka dua atau satu
vertex terakhir tidak dihiraukan.
GL_TRIANGLE Menggambar serangkaian segitiga (poligon tiga sisi)
_STRIP menggunakan vertex 0, vertex 1, vertex2, kemudian vertex 2,
vertex 1, vertex 3, kemudian vertex 2, vertex 3, vertex 4 dan
seterusnya
GL_TRIANGLE Sama dengan triangle strip hanya saja vertexnya adalah
_FAN 0, 1, 2, lalu 0, 2, 3, lalu 0, 3, 4 dan seterusnya.
GL_QUADS Menggambar poligon empat sisi secara berurutan. Jika
jumlah vertex bukan merupakan kelipatan 4 maka tiga, dua atau
satu vertex terakhir tidak dihiraukan.
GL_QUAD_STR Menggambar serangkaian poligon empat sisi dimulai
IP dari vertex 0, 1, 3, 2, kemudian vertex 2, 3, 5, 4, lalu vertex 4, 5,
7, 6 dan seterusnya.
Tabel bangun geometrik sederhana
Selain dengan glVertex*(), ada beberapa perintah yang bisa dimasukkan di antara
perintah glBegin() dan glEnd(). Perintah-perintah tersebut seperti yang diperlihatkan oleh
tabel di bawah ini:
Perintah Keterangan
GlVertex*() Mengeset koordinat vertex
GlColor*() Mengeset warna yang aktif
GlIndex*() Mengeset indeks warna yang aktif
GlNormal*() Mengeset koordinat vektor normal
GlEvalCoord*() Membuat koordinat
GlCallList(),glCa Mengeksekusi display list
llLists()
GlTexCoord*() Mengeset koordinat tekstur
GlEdgeFlag*() Mengontrol penggambaran tepi
GlMaterial*() Mengeset properti material
Tabel perintah-perintah antara glBegin() dan glEnd()
4.3.2. Garis
Dengan OpenGL kita dapat menentukan garis dengan berbagai macam ukuran dan digambar
dalam berbagai macam cara, dengan titik-titik, garis-garis maupun campuran antara titik-titik
dan garis-garis.
void glLineWidth(Glfloat width);
Width harus lebih besar dari 0.0, defaultnya adalah 1.0.
Penggambaran garis, seperti pada titik, dipengaruhi oleh bagaimana
antialiasing diset. Tanpa antialiasing, ukuran 1, 2 atau 3 akan digambar selebar
1, 2 atau 3 piksel. Jika antialiasing diset enable, memungkinkan ukuran lebar
garis dalam bentuk nonintegral, dan piksel-piksel pada bagian tepi digambar
dengan intensitas lebih kecil.
Sama dengan pada ukuran titik, pada implementasi khusus, ukuran titik non-antialiasing
mungkin dibatasi sebesar ukuran maksimum titik antialiasing, dibulatkan ke integer terdekat.
Kita bisa memperolehnya dengan menggunakan GL_LINE_WIDTH_RANGE pada perintah
glGetFloatv().
Untuk menggambarkan garis dalam titik-titik atau garis putus-putus gunakan perintah
glLineStipple() untuk mendefinisikan pola penggambaran garis tersebut dan kemudian kita
bisa mengaktifkan (meng-enable) dengan glEnable().
void glLineStipple(Glint factor, Glushort pattern);
Perintah tersebut mengeset pola penggambaran garis. Argumen pattern adalah rangkaian 0 dan
atau 1 sebanyak 16 bit. Nilai 1 menunjukkan penggambaran terjadi dan nilai 0 sebaliknya.
Pola bisa diperbesar dengan factor yang mengalikan tiap-tiap sub-rangkaian.
Dengan pola 0x3F07 (yang jika dirubah dalam biner menjadi 0011111100000111), garis akan
digambar dengan cara sebagai berikut: 3 piksel digambar, kemudian 5 piksel tidak, 6 piksel
digambar dan 2 piksel tidak (bit rendah digunakan terlebih dahulu). Pola tersebut bisa
diperbesar dengan menggunakan factor, sehingga jika contoh di atas menggunakan factor 2,
maka polanya menjadi: 6 piksel digambar, 10 piksel tidak, 12 piksel digambar dan 4 piksel
tidak.
4.3.3. Poligon
Poligon biasanya digambar dengan cara mengisi seluruh piksel yang tertutup dalam suatu
batas. Tetapi kita juga bisa menggambarnya sebagai poligon outline atau sebagai titik-titik
pada vertex-vertex. Sebuah poligon terisi mungkin terisi dengan solid (padat) atau digambar
dengan pola tertentu.
Sebuah poligon mempunyai dua sisi, yaitu depan dan belakang, dan
mungkin dibangkitkan dengan cara berbeda tergantung sisi mana yang
menghadap lensa. Defaultnya kedua permukaan digambar dengan cara yang
sama. Untuk merubahnya, atau menggambar hanya outline atau vertex, gunakan
perintah glPolygonMode().
Perintah tersebut mengontrol mode penggambaran dari permukaan
depan dan belakang suatu poligon. Parameter face dapat diisi dengan
GL_FRONT, GL_BACK atau GL_FRONT_AND_BACK. Sedangkan parameter
mode dapat diisi GL_POINT, GL_LINE atau GL_FILL. Defaultnya kedua
permukaan digambar terisi.
Secara default, poligon digambar dengan pola yang solid, tetapi juga bisa
diisi dengan pola tertentu dengan perintah glPolygonStipple().
Perintah tersebut mendefinisikan pola penggambaran untuk poligon terisi. Argumen mask
adalah pointer untuk bitmap 32x32 yang diterjemahkan sebagai 0 dan 1. Jika nilainya 1 maka
piksel yang bersesuaian pada poligon digambar, sedangkan jika 0 tidak.
glLoadIdentity();
glColor3f(1.0, 1.0, 1.0);
draw_triangle();
glEnable(GL_LINE_STIPPLE);
glLineStipple(1, 0xF0F0);
glLoadIdentity();
glTranslate(-20.0, 0.0, 0.0);
draw_triangle();
glLineStipple(1, 0xF00F);
glLoadIdentity();
glScale(1.5, 0.5, 1.0);
draw_triangle();
glLineStipple(1, 0x8888);
glLoadIdentity();
glRotate(90.0, 0.0, 0.0, 1.0);
draw_triangle();
glDisable(GL_LINE_STIPPLE);
void display(void)
{
GLdouble eqn = {0.0, 1.0, 0.0, 0.0};
GLdouble eqn2 = {1.0, 0.0, 0.0, 0.0};
glClear(GL_COLOR_BUFFER_BIT);
glClipPlane(GL_CLIP_PLANE0, eqn);
glEnable(GL_CLIP_PLANE0);
glClipPlane(GL_CLIP_PLANE1, eqn2);
glEnable(GL_CLIP_PLANE1);
void myinit(void)
{
glShadeModel(GL_FLAT);
}
void dayAdd(void)
{
day = (day + 10) % 360;
}
void daySubstract(void)
{
day = (day - 10) % 360;
}
void yearAdd(void)
{
year = (year + 5) % 360;
}
void yearSubstract(void)
{
year = (year - 5) % 360;
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
void myinit(void)
{
glShadeModel(GL_FLAT);
}
Jumlah macam warna yang dapat ditampilkan pada tiap-tiap piksel tergantung jumlah bitplane
dan kapasitas dari hardware untuk menginterpretasikan bitplane tersebut. Jumlah warna tidak
dapat melebihi 2n, dimana n adalah jumlah bitplane sehingga mesin dengan 24 bitplane untuk
RGB dapat menampilkan lebih dari 16,77 juta macam warna.
6.2.2. Dithering
Beberapa hardware grafik menggunakan dithering untuk meningkatkan jumlah warna yang
dapat ditampilkan dengan mengorbankan resolusi spatial. Dithering adalah teknik untuk
menggunakan beberapa warna untuk membentuk efek warna lain. Untuk menggambarkan
bagaimana proses dithering bekerja, anggaplah sistem kita hanya mempunyai 1 bit masing-
masing untuk RGB. Jadi sistem tersebut hanya bisa menampilkan 8 warna, yaitu hitam, putih,
merah, hijau, biru, kuning, cyan dan magenta. Untuk menampilkan warna pink pada suatu
daerah, hardware dapat mengisi daerah tersebut dengan warna merah dan putih. Karena mata
kita cukup jauh dari layar sehingga tidak dapat membedakan tiap-tiap piksel,daerah tersebut
akan tampak berwarna pink, rata-rata dari warna merah dan putih. Warna pink yang lebih
merah dapat dihasilkan dengan mengisi proporsi piksel yang lebih banyak dengan warna
merah, sedangkan warna pink yang lebih putih dapat dihasilkan dengan mengisi proporsi
piksel lebih banyak dengan warna putih, dan seterusnya.
Dengan cara ini, tidak ada piksel yang berwarna pink. Satu-satunya jalan untuk menghasilkan
efek di atas adalah dilakukan pada suatu daerah yang terdiri dari berbagai piksel. Kita tidak
bisa melakukan proses dithering pada satu piksel saja. Jika kita membentuk suatu nilai RGB
untuk suatu warna yang tidak tersedia dan mengisi suatu poligon, hardware mengisi piksel
yang berada di dalam poligon dengan campuran dari warna-warna terdekat sehingga
menampilkan warna rata-rata untuk mata kita sesuai dengan warna yang kita inginkan.
Gambar 6-2. Dhitering hitam dan putih untuk menghasilkan abu-abu
Dengan 8 bit pada tiap-tiap RGB, kita bisa mendapatkan gambar berkualitas tinggi tanpa
proses dithering. Tapi walaupun mesin kita mempunyai 24 bitplane bukan berarti proses
dithering tidak terjadi. Sebagai contoh, jika kita menggunakan mode double-buffer, bitplane
mungkin dibagi menjadi 2, masing-masing 12 sehingga hanya ada 4 bit pada tiap-tiap
komponen RGB. Tanpa dithering, 4 bit setiap komponen warna akan memberi hasil yang
kurang memuaskan.
Pelukis memilih sebuah warna dari palet warna dan melukis dengan
warna tersebut. Komputer menyimpan indeks warna dalam bitplane untuk tiap-
tiap piksel. Nilai bitplane tersebut menunjuk ke peta warna dan layar akan
diwarnai dengan nilai RGB dari peta warna.
Gambar 6-4. Menggunakan peta warna untuk mewarnai gambar
Pada mode indeks warna, jumlah warna yang tersedia terbatas oleh
ukuran peta warna dan jumlah bitplane yang tersedia. Ukuran peta warna
ditentukan oleh hardware yang digunakan. Biasanya berkisar antara 256(28)
sampai 4096(212). Ukuran peta warna merupakan pangkat dari 2 diindeks oleh
jumlah bitplane yang tersedia pada mode indeks warna. Jika ada 2n indeks pada
peta warna dan m bitplane yang tersedia, maka jumlah warna yang bisa
ditampung adalah kurang dari 2n dan 2m.
Dengan mode RGBA, tiap-tiap warna piksel tidak tergantung piksel lain.
Sedangkan pada mode indeks warna, tiap-tiap piksel dengan indeks yang sama
disimpan pada lokasi yang sama. Jika isi dari peta warna berubah, seluruh piksel
yang berindeks sama akan ikut berubah.
6.2.6. Dithering
Beberapa hardware grafik menggunakan dithering untuk meningkatkan jumlah warna yang
dapat ditampilkan dengan mengorbankan resolusi spatial. Dithering adalah teknik untuk
menggunakan beberapa warna untuk membentuk efek warna lain. Untuk menggambarkan
bagaimana proses dithering bekerja, anggaplah sistem kita hanya mempunyai 1 bit masing-
masing untuk RGB. Jadi sistem tersebut hanya bisa menampilkan 8 warna, yaitu hitam, putih,
merah, hijau, biru, kuning, cyan dan magenta. Untuk menampilkan warna pink pada suatu
daerah, hardware dapat mengisi daerah tersebut dengan warna merah dan putih. Karena mata
kita cukup jauh dari layar sehingga tidak dapat membedakan tiap-tiap piksel,daerah tersebut
akan tampak berwarna pink, rata-rata dari warna merah dan putih. Warna pink yang lebih
merah dapat dihasilkan dengan mengisi proporsi piksel yang lebih banyak dengan warna
merah, sedangkan warna pink yang lebih putih dapat dihasilkan dengan mengisi proporsi
piksel lebih banyak dengan warna putih, dan seterusnya.
Dengan cara ini, tidak ada piksel yang berwarna pink. Satu-satunya jalan untuk menghasilkan
efek di atas adalah dilakukan pada suatu daerah yang terdiri dari berbagai piksel. Kita tidak
bisa melakukan proses dithering pada satu piksel saja. Jika kita membentuk suatu nilai RGB
untuk suatu warna yang tidak tersedia dan mengisi suatu poligon, hardware mengisi piksel
yang berada di dalam poligon dengan campuran dari warna-warna terdekat sehingga
menampilkan warna rata-rata untuk mata kita sesuai dengan warna yang kita inginkan.
Gambar 6-2. Dhitering hitam dan putih untuk menghasilkan abu-abu
Dengan 8 bit pada tiap-tiap RGB, kita bisa mendapatkan gambar berkualitas tinggi tanpa
proses dithering. Tapi walaupun mesin kita mempunyai 24 bitplane bukan berarti proses
dithering tidak terjadi. Sebagai contoh, jika kita menggunakan mode double-buffer, bitplane
mungkin dibagi menjadi 2, masing-masing 12 sehingga hanya ada 4 bit pada tiap-tiap
komponen RGB. Tanpa dithering, 4 bit setiap komponen warna akan memberi hasil yang
kurang memuaskan.
Pelukis memilih sebuah warna dari palet warna dan melukis dengan
warna tersebut. Komputer menyimpan indeks warna dalam bitplane untuk tiap-
tiap piksel. Nilai bitplane tersebut menunjuk ke peta warna dan layar akan
diwarnai dengan nilai RGB dari peta warna.
Gambar 6-4. Menggunakan peta warna untuk mewarnai gambar
Pada mode indeks warna, jumlah warna yang tersedia terbatas oleh
ukuran peta warna dan jumlah bitplane yang tersedia. Ukuran peta warna
ditentukan oleh hardware yang digunakan. Biasanya berkisar antara 256(28)
sampai 4096(212). Ukuran peta warna merupakan pangkat dari 2 diindeks oleh
jumlah bitplane yang tersedia pada mode indeks warna. Jika ada 2n indeks pada
peta warna dan m bitplane yang tersedia, maka jumlah warna yang bisa
ditampung adalah kurang dari 2n dan 2m.
Dengan mode RGBA, tiap-tiap warna piksel tidak tergantung piksel lain.
Sedangkan pada mode indeks warna, tiap-tiap piksel dengan indeks yang sama
disimpan pada lokasi yang sama. Jika isi dari peta warna berubah, seluruh piksel
yang berindeks sama akan ikut berubah.
Ketika kita melihat suatu permukaan, persepsi mata kita terhadap warna
tergantung dari distribusi energi foton yang tiba dan merangsang sel cone seperti
yang telah dijelaskan pada bab sebelumnya. Foton-foton datang dari satu
ataupun kombinasi dari beberapa sumber cahaya dimana sebagian diserap dan
sebagian lagi dipantulkan oleh permukaan tersebut.
Model pencahayaan OpenGL terdiri dari 3 komponen sinar. Komponen-
komponen sinar tersebut antara lain:
- Ambient
Sinar yang datang ke permukaan obyek dari sembarang arah sebagai
akibat dari pantulan ruangan di sekeliling obyek sehingga tidak
mempunyai arah datang yang khusus.
- Diffuse
Sinar yang datang dari arah tertentu tetapi dipantulkan ke segala arah
oleh permukaan obyek. Jika sinar diarahkan langsung tanpa melalui
sudut tertentu maka obyek pada sisi dimana sinar menyorot akan
tampak lebih terang dari sisi yang lain.
- Specular
Sinar yang terarah, jadi datang dari arah tertentu dan terpantul ke
arah tertentu pula.
Warna material tergantung pada prosentase dari sinar RGB yang
dipantulkan. Contohnya sebuah bola yang berwarna merah memantulkan semua
sinar merah yang datang dan menyerap sinar hijau dan biru. Jika bola tersebut
diberi sinar putih (campuran dari warna RGB dalam jumlah yang sama), seluruh
sinar merah dipantulkan sehingga bola terlihat berwarna merah. Begitu pula jika
sinar yang diberikan berwarna merah. Jika sinar yang diberikan berwarna hijau,
maka bola tersebut akan tampak berwarna hitam karena seluruh sinar hijau akan
diserap sedangkan tidak ada sinar yang dipantulkan, karena tidak ada sinar
merah.
Di bawah ini adalah salah satu contoh penggunaan perintah glLight*() untuk membentuk
sumber cahaya:
GLfloat light_ambient[] = {0.0, 0.0, 0.0, 1.0};
GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 1.0};
GLfloat light_specular[] = {1.0, 1.0, 1.0, 1.0};
GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0};
Pada gambar 7-1 dimana obyeknya adalah sebuah sphere, hanya permukaan
depan saja yang terlihat. Jadi dalam hal ini tidak penting bagaimana tampilan dari
permukaan belakang. Jika sphere tersebut dipotong sehingga permukaan dalamnya
terlihat, mungkin kita perlu menyoroti permukaan dalam dari sphere tersebut dengan
cahaya yang telah kita definisikan. Kita dapat merubah model cahaya menjadi 2
permukaan, yaitu depan dan belakang dengan perintah di bawah ini:
glLightModeli(LIGHT_MODEL_TWO_SIDE, GL_TRUE);
7.3.3. Emisi
Dengan menggunakan warna RGBA untuk GL_EMISSION, kita dapat membuat
sebuah obyek terlihat memancarkan cahaya sesuai dengan warna yang kita set. Karena
sebagian besar obyek nyata tidak memancarkan cahaya, kita mungkin akan menggunakan
perintah ini kebanyakan untuk simulasi lampu atau sumber cahaya lain dalam scene.
Contoh:
GLfloat mat_emission[] = {0.3, 0.2, 0.2, 0.0};
glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);
TEKSTUR MAPPING
8.1.1. Mipmapping
Seperti obyek yang lain, obyek bertekstur dapat ditampilkan dalam berbagai jarak
dengan titik pandang. Oleh karena itu jika obyek tersebut bergeser menjauhi titik
pandang, maka ukuran dari tekstur pun harus berkurang sesuai dengan ukuran dari
obyeknya. Untuk itu OpenGL harus memfilter tekstur map ke ukuran yang tepat untuk
dimapke obyek. Kita dapat menentukan serangkaian tekstur map dalam resolusi yang
lebih kecil yang disebut dengan mipmaps. Kemudian OpenGL menentukan tekstur mana
yang akan dimap ke obyek. Dengan pendekatan ini jika image dari obyek mengecil maka
ukuran dari tekstur map juga berkurang.
Gambar 8-1. mipmaps
Teknik ini disebut dengan mipmapping (mip adalah singkatan dari bahasa
latin multim in parvo yang artinya sesuatu yang banyak di tempat yang
kecil/sempit). Untuk menggunakan mipmapping, kita menyediakan semua ukuran
tekstur dalam pangkat dari 2 antara ukuran terbesar sampai dengan ukuran 1x1.
Sebagai contoh jika resolusi terbesarnya adalah 64x16, kita juga harus
menyediakan map untuk ukuran 32x8, 16x4, 8x2, 4x1, 2x2 dan 1x1.
Untuk menentukan tekstur ini, gunakan perintah glTexImage2D() sekali
tiap resolusi atau ukuran dari tekstur map, dengan nilai yang berbeda dari
parameter level, width, height dan image. Dimulai dari nol, level menunjukkan
tekstur mana yang dipilih. Seperti pada contoh di atas, tekstur dengan ukuran
64x16 dideklarasikan dengan level=0, 32x8 dengan level=1, dan seterusnya.
Kita dapat memberikan koordinat tekstur diluar rang [0,1] dan mengulang
atau melakukan clamp dalam tekstur map. Dengan mengulang tekstur, jika kita
mempunyai bidang yang besar dengan koordinat tekstur antara 0.0 sampai
dengan 10.0 pada kedua arahnya, maka kita akan mendapatkan 100 kopi dari
tekstur tersebut dan diletakkan pada layar.