1.3. Tổng quan về Billboard
Billboard là kỹ thuật giả lập đối tượng 3D bởi các hình 2D bằng cách định hướng cho đối tượng 2D luôn quay bề mặt về phía mục tiêu, thông thường là camera. Kỹ thuật này rất phổ biến trong các trò chơi và các ứng dụng đòi hỏi phải xử lý một số lượng lớn các hình đa giác. Những người lập trình game 3D luôn phải đối mặt với việc làm sao để thể hiện một số lượng lớn các hình ảnh với một tỷ lệ khung hình hợp lý. Trong thực tế, khả năng xử lý của card đồ họa là có hạn, trong khi yêu cầu của các ứng dụng thì không ngừng được nâng cao. Điều này khiến cho công nghệ chế tạo phần cứng cũng phải liên tục được cải tiến.
Billboard được sử dụng để làm giảm số lượng hình ảnh cần thiết để thiết lập một chuỗi hình ảnh chuyển động liên tiếp bằng cách thay thế các đối tượng hình học bằng một kết cấu giả lập. Một trong những ví dụ phổ biến là hình ảnh về một cái cây. Thử nghĩ xem cần phải có bao nhiêu hình cơ sở để có thể biểu diễn trung thực hình ảnh của một cái cây. Billboard cho phép chúng ta thay thế hình ảnh của cái cây bằng một cấu trúc mặt phẳng đơn giản. Nó đảm bảo rằng cấu trúc hình học này luôn đối mặt với hướng của camera, và theo đó người dùng không bao giờ nhận ra rằng cái cây thực ra chỉ mà một mặt phẳng, người dùng chỉ có thể phát hiện ra điều này khi họ bay lên phía trên của cái cây.
Tuy nhiên, các hiệu ứng chiếu sáng sẽ không được biểu diễn một cách trung thực khi mà ta sử dụng một hình ảnh duy nhất cho mọi hướng của đối tượng. Một cái cây 3D phải thể hiện khác nhau ở các góc nhìn khác nhau, hay ít nhất thì nó cũng phải có sự thay đổi về hiệu ứng chiếu sáng khi góc nhìn có sự thay đổi. Trong trường hợp 2D billboard, khi mà ta sử dụng một hình duy nhất cho mọi hướng của đối tượng, nó có vẻ như là ánh sáng di chuyển cùng với camera. Cũng có thể là người dùng đôi khi không để ý tới sự không nhất quán này, tuy nhiên để khắc phục, có một giải pháp là ta có thể sử dụng nhiều hình cơ sở hơn để biểu diễn đối tượng từ các góc nhìn khác nhau.
Tuy nhiên, trừ khi chúng ta sử dụng một số lượng rất lớn các hình cơ sở, nếu không sẽ xảy ra hiện tượng giật hình khi có sự thay đổi của hai hình cơ sở.
Billboard có thể được sử dụng để giả lập một đối tượng 3D mà không cần đến một lượng lớn các hình ảnh cơ sở của đối tượng. Tuy nhiên kỹ thuật này không chỉ đơn giản là nhằm tiết kiệm số lượng hình cần biểu diễn. Về cơ bản, kỹ thuật này sẽ thực hiện việc xoay mặt đối tượng về phía camera, một đối tượng khác, hoặc đơn giản là về một hướng nào đó trong không gian 3D. Trong một số trường hợp, billboard không chỉ được sử dụng để tiết kiệm số lượng hình biểu diễn mà còn nhằm đáp ứng những mục đích cụ thể của ứng dụng. Chẳng hạn như là trong một trò chơi mà quân địch luôn quay mặt về phía bạn, hay trường hợp cầu thủ luôn đối mặt với quả bóng.
Có hai phương pháp billboard phổ biến là: phương pháp hình trụ và phương pháp hình cầu. Trong phương pháp hình cầu, không có sự giới hạn về hướng của đối tượng, trong khi với phương pháp hình trụ, hướng quay của đối tượng bị dàng buộc bởi một vector, thông thường là hướng của trục Y.
CHƢƠNG 2: CÁC KỸ THUẬT TẠO LẬP BILLBOARD 2.1. Các kỹ thuật billboard trụ
Kỹ thuật billboard trụ là kỹ thuật làm cho đối tượng billboard quay xung quanh một trục nào đó (thường là trục Y) để luôn hướng bề mặt của nó về phía camera.
2.1.1. Kỹ thuật giả billboard trụ
Kỹ thuật giả billboard trụ sẽ thực hiện quay đối tượng billboard quanh một trục sao cho vector pháp tuyến của nó song song với hình chiếu của vector hướng nhìn của camera xuống mặt phẳng xoz.
Các kỹ thuật billboard trình bày trong luận văn này sẽ được thực hiện việc quay đối tượng thông qua việc biến đổi ma trận mẫu sau:
Ba giá trị phía trên của cột bên phải cho biết sự liên quan giữa vị trí hiện tại của đối tượng với vị trí và hướng nhìn của camera. Ma trận con 3x3 M1 chứa các thông tin về tỷ lệ và hướng quay.
Chúng ta sẽ phân tích kỹ hơn về cấu trúc của ma trận con này. Ma trận này chứa 3 cột, và mỗi cột có một ý nghĩa riêng. Cột đầu tiên là right vector, cột thứ hai là up vector và cột thứ ba đại diện cho lookAt vector. Những vector này có liên quan tới hướng của camera. Khi chuyển ma trận con này thành ma trận đơn vị sẽ khiến cho camera được căn theo hệ trục toàn cục. Để thực hiện kỹ thuật giả
billboard trụ, ta chỉ cần quan tâm tới right và lookAt vector, còn up vector là không thay đổi.
Với phương pháp này thì đối tượng billboard sẽ không thay đổi khi camera quay lên trên hoặc quay xuống dưới. Billboard sẽ chỉ quay khi mà camera quay sang bên trái hoặc bên phải.
Kiểu billboard này có thể áp dụng để biểu diễn những cái cây. Những cái cây sẽ không bị uốn cong về phía sau hoặc về phía trước khi mà camera quay xuống dưới hoặc lên trên bởi vì up vector đã được cố định, do đó khả năng thể hiên của nó sẽ không được sinh động. Lưu ý là ảo giác này sẽ thất bại khi mà bạn bay lên phía trên của những cái cây. Khi đó những cái cây này sẽ ngày càng trở lên mảnh hơn và cuối cùng sẽ hoàn toàn bị biến mất. Tuy nhiên, với những ứng dụng mà trong đó bạn luôn được giữ để đứng trên mặt đất thì billboard trụ thực sự là một lựa chọn tốt.
Sau đây là mã nguồn cho phương pháp giả billboard trụ.
float modelview[16]; int i,j;
// save the current modelview matrix glPushMatrix();
// get the current modelview matrix
glGetFloatv(GL_MODELVIEW_MATRIX , modelview); // The only difference now is that
// the i variable will jump over the
// up vector, 2nd column in OpenGL convention for( i=0; i<3; i+=2 )
if ( i==j )
modelview[i*4+j] = 1.0; else
modelview[i*4+j] = 0.0; }
// set the modelview matrix with the // up vector unchanged
glLoadMatrixf(modelview); drawObject();
// restores the modelview matrix glPopMatrix();
Đoạn mã trên cũng được chia làm hai hàm, đó là biểu diễn và vẽ đối tượng. Chức năng thứ nhất là thiết lập ma trận modelview, còn chức năng thứ hai sẽ phục hồi là ma trận hiện thời.
void billboardCheatCylindricalBegin() { float modelview[16];
int i,j;
// save the current modelview matrix glPushMatrix();
// get the current modelview matrix
glGetFloatv(GL_MODELVIEW_MATRIX , modelview); for( i=0; i<3; i+=2 )
if ( i==j )
modelview[i*4+j] = 1.0; else
modelview[i*4+j] = 0.0; }
// set the modelview matrix glLoadMatrixf(modelview); }
void billboardEnd() { // restore the previously // stored modelview matrix glPopMatrix();
}
Đoạn mã biểu diễn đối tượng billboard trở thành:
billboardCheatCylindricalBegin(); drawObject();
billboardEnd();
Với phương pháp này, các phép tỷ lệ theo trục X và Y sẽ bị mất, nhưng phép tỷ lệ theo trục Z thì vẫn được thực hiện. Lựa chọn tốt nhất là thực hiện các phép tỷ lệ sau khi gọi hàm billboardCheatCylindricalBegin().
2.1.2. Billboard trụ thực sự
Billboard trụ thực sự sẽ làm cho đối tượng quay quanh một trục, giống như trong phiên bản giả billboard trụ, nhưng vector lookAt của đối tượng sẽ được quay về phía của camera. Hình sau thể hiện cách thức biến đổi của kỹ thuật billboard trụ.
2.1 Cách quay đối tƣợng trong kỹ thuật billboard trụ thực sự
Lúc này, khi người dùng di chuyển trên mặt đất, những cái cây sẽ thực sự đối mặt với người dùng. Phương pháp sử dụng ở đây đòi hỏi phải biết được vị trí của đối tượng cũng như vị trí của mục tiêu trong hệ trục toàn cục. Thường thì mục tiêu chính là vị trí của camera mà ta đã biết. Tuy nhiên điều tương tự không đúng đối với đối tượng.
Nếu như vị trí của đối tượng được xác định thông qua các phép biến đổi hình học, như là dịch chuyển, phép quay, khi đó giữ được thông tin về vị trí của đối tượng trong hệ trục toàn cục là một nhiệm vụ khá khó khăn
Giả như biết được vị trí của các đối tượng và mục tiêu trong hệ trục toàn cục, khi đó kỹ thuật billboard sẽ trở thành một thao tác biến đổi hình học đơn giản. Vì một lý do đơn giản là giả sử đối tượng có các vector sau:
right vector = [1,0,0] up vector = [0,1,0] lookAt vector = [0,0,1]
Trong thực tế, điều này có nghĩa là đối tượng được vẽ trong hệ trục cục bộ và nhìn về chiều dương của trục Z.
Việc định hướng cho phép quay của đối tượng quanh up vector được xác định thông qua góc giữa lookAt vector và vector từ đối tượng tới camera.
2.2 Xác định góc quay trong billboard trụ thực sự (a)
Vector từ đối tượng tới camera được định nghĩa như sau: objToCam = CamPos – ObjPos.
Vector objToCamProj là chiếu của objToCam lên mặt phẳng XOZ. Vì vậy thành phần Y của nó được đặt bằng 0.
Nếu objToCamProj là normalized khi đó tích giữa lookAt và objToCam sẽ cho phép tính được cosine của góc quay. Tuy nhiên chỉ biết được cosine thì vẫn
chưa đủ, khi mà cos(a) = cos(-a). Việc tính tích có hướng cho phép ta xác định được một góc duy nhất. Vector tích cùng hướng với up vector nếu góc quay là dương và ngược hướng nếu góc quay là âm.
2.3 Xác định góc quay trong billboard trụ thực sự (b)
Các bước cần thực hiện sau khi tính được objToCamProj là: 1. normalize(objToCamProj)
2. angleCosine = innerProduct(lookAt,objToCamProj) 3. upAux = crossProduct(lookAt,objToCamProj)
4. glRotatef(acos(aux)*180/3.14,upAux[0], upAux[1], upAux[2]);
Tương tự như phần trước, một hàm sẽ được xây dựng để thiết lập billboard. Mã nguồn được cho như sau:
void billboardCylindricalBegin( float camX, float camY, float camZ,
float objPosX, float objPosY, float objPosZ) { float lookAt[3],objToCamProj[3],upAux[3];
float modelview[16],angleCosine; glPushMatrix();
// objToCamProj is the vector in world coordinates from the // local origin to the camera projected in the XZ plane objToCamProj[0] = camX - objPosX ;
objToCamProj[1] = 0;
objToCamProj[2] = camZ - objPosZ ;
// This is the original lookAt vector for the object // in world coordinates
lookAt[0] = 0; lookAt[1] = 0; lookAt[2] = 1;
// normalize both vectors to get the cosine directly afterwards
mathsNormalize(objToCamProj);
// easy fix to determine wether the angle is negative or positive
// for positive angles upAux will be a vector pointing in the // positive y direction, otherwise upAux will point downwards // effectively reversing the rotation.
mathsCrossProduct(upAux,lookAt,objToCamProj); // compute the angle
angleCosine = mathsInnerProduct(lookAt,objToCamProj);
// perform the rotation. The if statement is used for stability
reasons
// if the lookAt and objToCamProj vectors are too close together then
// |angleCosine| could be bigger than 1 due to lack of precision
if ((angleCosine < 0.99990) && (angleCosine > -0.9999)) glRotatef(acos(angleCosine)*180/3.14,upAux[0], upAux[1], upAux[2]);
}
Hàm billboardEnd() có thể được gọi sau khi biểu diễn đối tượng.
billboardCylindricalBegin(cx,cy,cz,ox,oy,oz); drawObject();
billboardEnd();
2.1.3. Ƣu điểm và những hạn chế của phƣơng pháp billboard trụ
Phương pháp billboard trụ thực sự phù hợp cho những ứng dụng mà người sử dụng chỉ có thể di chuyển được ở trên mặt đất. Với những ứng dụng như vậy,
các đối tượng billboard sẽ được điều chỉnh để luôn hướng về phía người sử dụng. Và khi người sử dụng không có khả năng di chuyển lên phía bên trên của các đối tượng billboard thì họ sẽ khó có thể phát hiện ra các đối tượng billboard đó thực chất chỉ là một mặt phẳng. Trong trường hợp người sử dụng có khả năng bay lên phía trên cao thì phương pháp này không còn phù hợp, vì khi đó người dùng sẽ nhận ra đối tượng billboard là một mặt phẳng.
2.2. Các kỹ thuật billboard cầu
Khắc phục nhược điểm của kỹ thuật billboard trụ trong trường hợp người sử dụng di chuyển lên phía trên của các đối tượng billboard. Kỹ thuật billboard cầu thực hiện quay đối tượng billboard quanh một tâm sao cho bề mặt của nó luôn hướng về phía camera. Với kỹ thuật này đối tượng billboard luôn hướng bề mặt về phía camera tại bất kì vị trí và góc nhìn nào của camera. Và người sử dụng chỉ phát hiện ra các đối tượng billboard là một mặt phẳng khi so sánh và phát hiện ra sự bất hợp lý về hình dạng của đối tượng tại các vị trí nhìn khác nhau.
2.2.1. Kỹ thuật giả billboard cầu
Kỹ thuật giả billboard cầu sẽ thực hiện quay đối tượng billboard quanh một tâm sao cho vector pháp tuyến của nó song song với vector hướng nhìn của camera.
Hình ảnh sau đây chỉ mang tính chất minh họa. Nó thể hiện một người tuyết và một vài cái cây được áp dụng kỹ thuật billboard. Thật khó để có thể nói rằng những cái cây không hướng về phía của camera. Nhưng thực tế là, người ta làm cho bề mặt của cái cây hướng vuông góc với hướng nhìn của camera.
2.5 Phƣơng pháp giả billboard cầu
Sơ đồ dưới đây thể hiện điều gì đã thực sự xảy ra. Vòng tròn màu đen ở phía dưới biểu diễn cho camera. Vector xuất phát từ camera chỉ hướng nhìn hiện tại của camera. Vector này chỉ ra phương của mặt phẳng vuông góc với hướng nhìn của camera. Các đối tượng trong các tình huống từ O1 tới O3 được quay sao cho vector pháp tuyến của chúng luôn hướng về phía mặt phẳng này. Điều này khiến cho đối tượng dường như là được đặt vào một hệ trục cục bộ và bề mặt của nó thì luôn hướng về phía chiều dương của trục Z.
2.6 Bản chất của phƣơng pháp giả billboard cầu
Để thực hiện được kỹ thuật này người ta cũng sử dụng một ma trận mẫu như ở phần trước. Ma trận này lưu trữ thông tin về các biến đổi hình học, hướng quay, tỷ lệ và vị trí của đối tượng billboard.
Khi ma trận con M1 được chuyển thành ma trận đơn vị, các phép tỷ lệ và quay sẽ bị loại bỏ, theo đó hướng nhìn của camera sẽ được căn theo trục Z của hệ trục toàn cục, vector up và right của camera cũng được căn theo các trục của hệ trục tọa độ toàn cục. Dạng billboard này hoạt động theo kiểu giả billboard cầu, tâm của billboard là gốc tọa độ cục bộ. Nếu sử dụng kiểu billboard này cho những cái cây, thì khi người dùng nhìn lên trên hoặc xuống dưới, những cái cây sẽ bị kéo về phía trước hoặc phía sau.
Trong thực tế, khi chuyển ma trận con này thành ma trận đơn vị có nghĩa là đối tượng sẽ không chịu một phép quay nào khi nó được biểu diễn. Do đó nó sẽ được biểu diễn giống như khi mà camera hướng về phía chiều âm của trục tọa độ Z. Chú ý là phép tỉ lệ cũng sẽ bị phá vỡ, vì vậy các phép tỷ lệ cần phải được thực hiện sau khi thực hiện các phép biến đổi trên mà trận mẫu.
Đầu tiên, ma trận mẫu hiện tại sẽ được lưu lại. Sau đó ma trận này sẽ được đem ra biến đổi, ma trận con 3x3 ở góc trên bên trái sẽ được chuyển thành ma trận đơn vị. Ma trận này sẽ được nạp vào cho máy trạng thái OpenGL, và biểu diễn đối tượng tại gốc trục tọa độ cục bộ. Cuối cùng mà trận mẫu gốc sẽ được phục hồi.
float modelview[16]; int i,j;
// save the current modelview matrix glPushMatrix();
// get the current modelview matrix
glGetFloatv(GL_MODELVIEW_MATRIX , modelview); // undo all rotations
// beware all scaling is lost as well for( i=0; i<3; i++ )
for( j=0; j<3; j++ ) { if ( i==j ) modelview[i*4+j] = 1.0; else modelview[i*4+j] = 0.0; }
// set the modelview with no rotations and scaling glLoadMatrixf(modelview);
drawObject();
// restores the modelview matrix glPopMatrix();
Với đoạn mã trên, đối tượng sẽ quay để luôn đối mặt với mặt phẳng trực giao với hướng nhìn của camera. Tâm quay chính là gốc của hệ trục cục bộ. Đoạn mã trên thực hiện hai chức năng, đó là chức năng biểu diễn và vẽ đối