PDA

View Full Version : Realtime terrain rendering



CrazyBabe
23-10-2003, 23:16
Topic này thảo luận về những kĩ thuật dựng địa hình thời gian thực. Các bạn cứ post bài thoải mái hén, đầu tháng sau rảnh tôi sẽ làm một bài basic về vấn đề này. Hì hì, nếu các bài post chất lượng quá càng hay, tui...đỡ phải làm hẹ hẹ, sướng....

gtechvn
07-11-2003, 13:25
Tạo địa hình từ raw file là một kỹ thuật hiệu quả và phổ biến để tạo ra địa hình dạng Height Map realtime
(code C)

#define MAP_SIZE 1024
#define STEP_SIZE 16
#define HEIGHT_RATIO 1.5f

//Lưu Map trong mảng này
BYTE g_HeightMap[MAP_SIZE*MAP_SIZE];

// Nạp .RAW File
void NapRawFile(LPSTR strTen, int nSize, BYTE *pHeightMap)
{
FILE *pFile = NULL;
pFile = fopen( strName, "rb" );
if ( pFile == NULL )
{
return;
}

fread( pHeightMap, 1, nSize, pFile );

fclose(pFile);
}

int Height(BYTE *pHeightMap, int X, int Y)
{
int x = X % MAP_SIZE;
int y = Y % MAP_SIZE;
if(!pHeightMap) return 0;
return pHeightMap[x + (y * MAP_SIZE)];
}

void SetVertexColor(BYTE *pHeightMap, int x, int y)
{
if(!pHeightMap) return;
//Set địa hình màu xanh, hoặc load texture tại đây
float fColor = -0.15f + (Height(pHeightMap, x, y ) / 256.0f);
glColor3f(0, 0, fColor );
}

//Render height map
void RenderHeightMap(BYTE pHeightMap[])
{
int X = 0, Y = 0;
int x, y, z;
if(!pHeightMap) return;

glBegin( GL_QUADS );
for ( X = 0; X < (MAP_SIZE-STEP_SIZE); X += STEP_SIZE )
for ( Y = 0; Y < (MAP_SIZE-STEP_SIZE); Y += STEP_SIZE )
{
x = X;
y = Height(pHeightMap, X, Y );
z = Y;
SetVertexColor(pHeightMap, x, z);

glVertex3i(x, y, z);

x = X;
y = Height(pHeightMap, X, Y + STEP_SIZE );
z = Y + STEP_SIZE ;
// Set Màu hoặc load texture
SetVertexColor(pHeightMap, x, z);

glVertex3i(x, y, z);
x = X + STEP_SIZE;
y = Height(pHeightMap, X + STEP_SIZE, Y + STEP_SIZE );
z = Y + STEP_SIZE ;

SetVertexColor(pHeightMap, x, z);

glVertex3i(x, y, z);

x = X + STEP_SIZE;
y = Height(pHeightMap, X + STEP_SIZE, Y );
z = Y;
SetVertexColor(pHeightMap, x, z);
glVertex3i(x, y, z);
}
glEnd();
//Set lại màu mặc định
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
}

Trong GLScene() nhớ gọi NapRawFile("Đường dẫn/File name.raw", MAP_SIZE * MAP_SIZE, g_HeightMap);

ngocquang19877
14-11-2003, 18:54
ừm.có phải là cái này quá cao siêu hay em quá dốt nên ko biết kô nữa.
xin chen vô hỏi 1 câu khá thiếu iốt là raw là cái gì vậy?????dx hỗ trợ cái này với mức độ nào

CrazyBabe
15-11-2003, 01:40
Hic, raw là một từ chỉ những cái gì thô thô, đơn giản nhất, ví dụ như raw data thì chỉ dữ liệu kô nén, kô mã hóa, nói chung là nguyên bản. Ở đây raw data là một bản đồ chỉ độ cao của terrain. DX hỗ trợ như thế nào àh ? Hic, cái này kô fụ thuộc vào renderer mà phụ thuộc vào thuật toán render của bạn.

ngocquang19877
15-11-2003, 16:11
ừm.em lại có 1 số câu hỏi từ câu trả lời của bác.
tọa độ bản đồ là sao???có nghĩa là 1 model terrain người ta lập trình các giới hạn tọa độ của nó trên các model í ấy à???vậy thì cái này hơi bị siêu à nha.bác có thể nói rõ hơn được kô???
còn nếu ta có 1 tọa độ giới hạn động vd như ta ở trên trực thăng thì làm seo mà giời hạn tọa độ của nó được khi object trựvcthăng lun bay và con ngừơi lun di chuyễn trong cái trực thăng í
phương thức render hình như được DX hỗ trợ từ đầu tới chân rùi mà???

CrazyBabe
17-11-2003, 01:21
Hic, đọc xong post của pác này nhức đầu chả hiểu gì cả ?
Kô fải tọa độ bản đồ hén. Terrain ở đây được tạo từ các mesh, rite ? Các mesh liền nhau có chung đỉnh, rite ? Độ cao của các đỉnh này được lấy từ raw map đó.
Giới hạn frustum view ? Đó là do tính toán và renderer của bạn.
Phương thức render thì platform như Direct3D (kô fải DX à nha) sinh ra để làm nên dĩ nhiên nó fải hỗ trợ "từ đầu đến chân" rùi, nhưng nên nhớ còn rất nhiều flatform khác như OpenGL, Glide hoặc là Matrox...linh tinh, nhiều lém.

Terminator
22-11-2003, 14:03
Đúng là chú quang này hỏi lung tung, dễ hiểu như vậy mà...
Nếu muốn 1 model ngồi trên trực thăng thì phải tự lập trình thôi. Terrain thì có liên quan gì đâu ?

Joe Dalton
02-12-2003, 18:40
hi vong các pa post cái gì đó mới mẻ hơn.

gtechvn
03-12-2003, 13:04
Đối với bác thì cũ, nhưng quan trọng là có thành viên thấy mới là được, phục vụ từ cơ bản tới nc mà :D

3dgamestudio
20-01-2004, 12:46
Bên engine 3dgamestudio có terrain dạng *.hmp; Ai có cái nào đẹp đẹp gửi tui với.

ngocquang19877
25-01-2004, 16:02
è cho tui hỏi 1 chút nhé.nếu ta dựng 1 địa hình hơi phức tẹp 1 chút (có đồi núi chập chùng,hoa cỏ tứ tung " thì làm sao ta có thể detect collision nó bi giờ??vd như như việc 1 character đi lên 1 cái đồi ? co tai lieu nao khong shảe cho tui nhe

CrazyBabe
25-01-2004, 23:50
Địa hình dù có thế nào thì cũng là tập hợp của các tris đúng kô ?
Thế thì detect cho từng tris một...
Dĩ nhiên là có cách crop, đơn giản thôi mà...
Tài liệu detect collision thì tui send rùi...

Godbloc
20-03-2004, 16:54
Cai' cach' ma` cac ong lam` la` dia hinh vat ly thuc . Nghia la` do lon cua no phu thuoc vao` mang Vertext thuc . Cach nay` vua` trau bo` vua` ton bo nho lai ton thoi gian trong viec Detectcoliision . Toi dung cach khac , do la toa do logic + tinymap . Chi dung vai cai map nho thoi sau do , offset no theo toaj do diem cua map lon .
Tpolygon = record
Quads : Array[0..3] of Word;
CoorV : Array [0..3] of point2f ; // toa do Uv de dan' texture
Normal : Array [0..1] of point3f; // 2 cai normal vi` toi dung quad ko dung tris
Color : point3f ;
Texture : Gluint;
End;
Ttynimap = record
VertexA : Array of Vertex3f; // Mang diem thuc
Vmax : DoubleWord;
PolyA : Array of Tpolygon; // mang cac mesh
Pmax : Dword;
MatList : Array of Gluint; // mang vat lieu
End;
Dung phuong phap matran de chia ban do` , hoac choi thu cong , detect tung diem 1
roi noi' chung lai thanh` 1 quad ,Add texture cho no .xong
Van de chi con lai la` ve tai cac diem offset bang cach
Glpushmatrix;
Gltranslate ;
Drawmap ;
Glpopmatrix..
Nhung no 1 mot nhuoc diem chet nguoi` , la` tinh don dieu va nhieu khoang ho ,
khi muon check va cham voi 1 doi tuong phuc tap thi` ..chet ngay vi` van phai check vat ly' . Nhung no cung co uu diem , do la` su quan li chat che ban do` .
Vi du 1 cai map lon chia thanh` 8 khu vuc , moi khu vuc la` 1 cai tinymap thi` co the check khu vuc truoc , sau do moi check den va cham , tiet kiem thoi gian ve va` check rat nhieu`.

By CrazyBabe: Cảnh cáo thằng GodBloc nhé, anh bảo mày viết có dấu bao nhiêu lần gòi, mấy hôm nữa mà kô sửa lại là anh del đấy

whitepenguin
09-11-2004, 12:21
BÁc quang muốn biết về cái này thì bác kiếm cuốn Voxel &Landscape mà đọc nhá,Hoắc tìm cuốn Kỹ thuật lập trình mô phỏng và ứng dụng mà đọc

Mach2
09-11-2004, 12:40
Giờ này ai lại đi làm voxel. Cái cuốn blackart giề đó của thời Bảo Đại cởi truồng tắm mưa mà oeoe

whitepenguin
09-11-2004, 14:37
Đã nói với bác ở bên kia rồi ,dù sao thì học căn bản cũng tốt hơn hết ,sách càng cũ càng có giá trị -thằng học căn bản đi lên bao giờ cũng giời hơn thằng hạy theo công nghệ mà không biết cốt lõi là gì

Mach2
09-11-2004, 14:55
ko phải cốt lõi hay gì mà vấn đề là technique. Voxel là một technique xưa quá rồi, hiện nay để render terrain có nhiều technique tốt hơn nhiều.
Ko phải tôi chê, nhưng quyển "Black art of 3D Game Programming" mà KS. Tú gì đó dịch ra là collection của một số article/paper/technique của thời 1995. 10 năm gần đây đổ lại thì có thể nói các technique đó đã khá lỗi thời. Voxel là một ví dụ, biết nó theo kiếu "biết so-so" thì được chứ để xài thì tôi ko thấy có gì tốt so với một số cái mới hiện giờ. Nói về techniques, cứ so sánh quyển trên với một số series gần đây là "Game Programmings Gems", "Graphics Gems" hay "GPU Gems" thì thấy rõ ràng là nó quá ư lạc hậu.
Đúng là học căn bản tốt nhưng phải tùy mức độ, tùy mục đích sử dụng chứ.

lancelot
30-11-2004, 12:40
Cái code này mà dùng để load một cái terrain lớn 1 tí là crash ngay. Các chú cứ thử vào website của USGS download 1 cái terrain demo thử về mà xem. Mới nhất đây, ở SIGGRAPH 2004 có 1 paper làm về cái terrain rendering in real time using GPU, quên mất cái title rồi, anh khuyên các chú nên tham khảo cái paper này trước khi nói phét lung tung.

Godbloc
03-12-2004, 19:39
Thôi mấy cha cãi nhau gì cho mệt , học cái quái gì không quan trọng bằng làm được cái quái gì .Đại ca Lancelot , cái terran ấy nó lớn từng nào mà Crash ? tính bằng m hay ....km? em có con map bay mất ...4 ngày mới đến nơi mà chĩ nặng khoảng trên dưới 1mb thôi.

lancelot
04-12-2004, 00:20
Chú nói cái map có 1Mb thì bố ai biết được nó to như thế nào, bay 4 ngày mới đến nơi cũng chả nói lên được cái gì cả vì nó phụ thuộc vào tốc độ của cái rendering engine. Với raw data file, 1MB data thì quá nhỏ. Nói như thế này, cái terrain thực tế mà bọn nó viết trong cái paper đó là terrain của toàn bộ nước Mỹ dùng tỉ lệ 1/100. Thông thường để render được 1 cái terrain lớn, có nhiều techniques: thông dụng nhất là dùng view dependend polygon simplification. Cái này bọn graphics researchers làm nhiều lắm, các chú cứ google một cái là ra ngaỵ

Nhắn bọn mod - bọn mod ở đây quê bỏ xừ, hơi 1 tí là sửa bài, anh cũng chẳng nhớ anh viết cái gì mà bị bọn này sửa lại bài (nhớ xóa luôn dòng này sau khi đọc)

CrazyBabe
06-12-2004, 23:11
Ông lancelot ăn nói cẩn thận, nhảy vào mà xưng chú với cả anh, ở đây lắm "thằng" già khú đấy.
Chỉ chỗ load paper thằng nào chả làm được, mới biết được vài chữ tiếng anh thế chưa đủ trình để hót đâu.
Viết gì thì phải nhớ và có trách nhiệm với những gì mình viết, nếu không bị xóa ráng chịu.
Babe - F

daem0n
08-12-2004, 00:49
Ông lancelot ăn nói cẩn thận, nhảy vào mà xưng chú với cả anh, ở đây lắm "thằng" già khú đấy.
Chỉ chỗ load paper thằng nào chả làm được, mới biết được vài chữ tiếng anh thế chưa đủ trình để hót đâu.
Viết gì thì phải nhớ và có trách nhiệm với những gì mình viết, nếu không bị xóa ráng chịu.
Babe - F

Mod gì mà cãi nhau với "dân đen" vậy cha?

lancelot
08-12-2004, 04:51
Ở đây không nói chuyện về điện - BabeF
Tôi cũng không cãi nhau - BabeF

quangkid
04-01-2005, 13:27
phần terrain này các bạn tìm đọc cuốn Focus on 3d Terrain của NXB Premier Press là hay nhất có nhiều phương pháp tạo địa hình.
đơn giản xúc tích gắn gọn .

whitepenguin
01-03-2005, 18:42
Chửi nhau nữa đê đang thích nghe đây

Bác Crazy có cái Hình em nào đẹp thía ,bồ bác hả :D đọc xong xóa luôn cái bài này đê :D

daem0n
03-03-2005, 18:01
CrazyBabe mấy nay bận đi làm ăn hay sao mà ít thấy xuất đầu lộ diện trên diễn đàn vậy?

expert
18-09-2005, 09:39
Tôi muốn viết một cái terrain editor. Hiện nay cần nghiên cứu về tạo heightmap (tự động, nâng lên hạ xuống, làm phẳng v.v...) và cách vẽ paint texture lên các bề mặt, theo kiểu alpha và blend. Có ai có tài liệu hoặc thư viện không làm ơn chỉ giúp?

ChymDangSun
23-08-2006, 18:13
Mình có 2 câu hỏi về vấn đề terrain rendering:
- Câu hỏi 1: Về vấn đề LOD (Level of detail)
Mình có tham khảo một số thuật toán về LOD, chẳng hạn: Geomipmap, geoclipmap, ROAM, SOAR, Chunk LOD...
ROAM thì có vẻ là khá cũ, ngày nay, khi phần cứng độ họa đã trở nên mạnh mẽ thì ROAM có vẻ không phù hợp, vì nó chiếm tài nguyên CPU khá lớn. Geomipmap và geoclipmap thì thích hợp để render các terrain kích thước nhỏ (theo mình). Mình được biết là engine của Farcry dùng geomipmap với map 1024x1024. Chunk LOD thì hiệu quả khi render 1 map kích thước lớn.
Mình muốn viết cái demo terrain kiểu Land Object (đi trên địa hình) và Aircraft (bay trên địa hình). Vậy thì với phần cứng hiện nay, thuật toán nào là hiệu quả nhất? (Chiếm ít tài nguyên CPU càng tốt)
- Câu hỏi 2: Vấn đề về Index Buffer
Mình định viết demo bằng DX. Mình tổ chức terrain theo dạng cây tứ phân (QuadTree). Mỗi lá của cây là một terrain block (có kích thước theo mình đặt là 17x17 - tương ứng n = 4 (17 = 2^4 + 1)). Mình dùng 1 Vertex Buffer để lưu các đỉnh của toàn terrain. Vậy:
+ Vấn đề 1: Nên dùng 1 index buffer để lưu toàn bộ các indices trên toàn bộ các terrain block, hay mỗi terrain block tạo 1 Index buffer. Cái nào hiệu quả hơn.
+ Vấn đề 2: Mình được biết render kiểu TRIANGLESTRIP hiệu quả hơn 60% (ko biết có nhớ nhầm ko :)) so với TRIANGLELIST. Nhưng không biết tổ chức các indices trên mỗi terrain block như thế nào để có thể render dạng TRIANGLESTRIP. Cụ thể là khi render dòng thứ i (dạng TRIANGLESTRIP), mình không biết làm thế nào để kết nối với các indices ở dòng thứ i+1 để render.
Tạm thời hỏi vậy thôi. Có gì mình sẻ hỏi tiếp :D.
Welcome mọi đóng góp !

eXecutive
05-07-2007, 14:43
Ko biết post lên có thừa hay không nhưng mà cứ đưa lên 1 cách tạo heightmap mà tui biết:

Bước 1: Chuẩn bị 1 file BITMAP (trắng đen) thể hiện địa hình dạng 2D
Nhỏ thôi, không cần lớn để không làm chậm quá trình đọc file. Ví dụ (128x128) -> (128 km x 128 km hay m,...).

http://i77.photobucket.com/albums/j72/thanhduongnt/TextureMap.jpg

Tại sao phải là trắng đen, Vì 1 pixel của hình trắng đen có giá trị R = G = B = height;
Màu đen (height = 0) là nơi có địa hình thấp nhất.
Màu trắng (height = 255) là nơi có địa hình cao nhất.

Bước 2: Xây dựng MAP dưới dạng MESH


typedef struct TagVERTEX {
float x,y,z;
float nx,ny,nz;
D3DCOLOR color;
}VERTEX;



Xây dựng cấu trúc mảng VERTEX aMap[widthBMP][heightBMP].(Cấu trúc này tui cài đặt theo kiểu DX, với OpenGL thì đơn giản hơn nhiều).

- Giải mã format file BMP trên (lưu dạng *.TGA cho dễ giải mã) và duyệt từng PIXEL để lấy giá trị màu -> Height.



// Xây dựng HEIGHT
for (int i = 0;i<widthBMP;i++){
for (int j = 0;j<heightBMP;i++){
aMap[j].x = i * DONVI;
aMap[i][j].y = GetHeight(i,j) * DONVI; // <- GetHeight tự viết
aMap[i][j].z = j * DONVI;
}
}

// Make IndexBuff
int aIndexBuffer[];
int nIndex=0;
/*
[i]
(0)---(1)(4)--(5) .........
| / | / | .........
| / | / | .........
| / | / | .........
(2)--(3) (6)--(7) .........
.........
.........

*/
for (i = 0;i<widthBMP-1;i++){
for (j = 0;j<heightBMP-1;j++){
aIndexBuffer[nIndex] = j*widthBMP+ i;
nIndex++;
aIndexBuffer[nIndex] = j*widthBMP+ i + 1;
nIndex++;
aIndexBuffer[nIndex] = (j+1)*widthBMP+ i;
nIndex++;
aIndexBuffer[nIndex] = (j+1)*widthBMP+ i + 1;
nIndex++;
}
}


Như vậy ta đã có 1 mảng aHeightMap. Tuy nhiên, nếu vẽ nó lên thì vẫn chưa hoàn chỉnh vì nó vẫn còn bị bậc thang do GetHeight. Do đó chưa cần phải vội vàng vẽ.
http://i77.photobucket.com/albums/j72/thanhduongnt/HeightMap_NoSmooth.png

Bước 3: Xử lý SMOOTH
- Có rất nhiều thuật toán xử lý SMOOTH nhưng với dạng HEIGHTMAP này thì có lẽ chỉ nên xử dụng kỹ thuật tính trung bình các height trong MAP.
Ví dụ:


......
......[1] [2] [3] ......
|
......[4]<-[5]->[6] ......
|
......[7] [8] [9] ......
......

Height[5] = Height[1]
+ Height[2]
+ Height[3]
+ Height[4]
+ Height[5]
+ Height[6]
+ Height[7]
+ Height[8]
+ Height[9]
Height[5] = Height[5] / 9




void SmoothMap(VERTEX aMap[][heightBMP])
for (int i = 1;i<widthBMP-1;i++){
for (int j = 1;j<heightBMP-1;i++){
aMap[i][j].y += aMap[i-1][j-1].y + aMap[i][j].y + aMap[i][j+1].y +
aMap[i][j-1].y + + aMap[i][j+1].y +
aMap[i+1][j-1].y + aMap[i+1][j].y + aMap[i+1][j+1].y;
aMap[i][j].y = aMap[i][j].y / 9;

// Tính VECTOR PHÁP TUYẾN.....
}
}
}

Gọi chừng 3 -> 5 (Load càng nhiều thì nó càng mượt)lần hàm SmoothMap thì chúng ta sẽ có 1 MAP mượt mà.
Lúc này có lẽ ta nên load lại MAP để tính VECTOR PHÁP TUYẾN... Tuơng đối dễ
http://i77.photobucket.com/albums/j72/thanhduongnt/HeightMap1_LINE.jpg

Bước cuối cùng:
Có lẽ cũng là bước khó nhất. Là dùng TEXTURE và MULTI_TEXURE (BUMP MAPPING) để trang điểm cho cái MAP dễ thương của mình.
http://i77.photobucket.com/albums/j72/thanhduongnt/Scence.jpg

whitepenguin
13-03-2008, 11:32
Lạ nhỉ ,em thử lấy cái Height Map của để sinh terrain mà sinh ra cũng đẹp lắm chứ đâu có cái hình bậc thang như của anh đâu