2012-12-13 30 views
13

Tôi đang viết một ứng dụng OpenGL ES 2.0 làm cho một hòn đảo 3D. Tôi đã có mã để tạo ra một mái vòm trên khắp hòn đảo. Đây là một bán cầu bao gồm các hình tam giác mà nằm trên đảo với z điểm trở lên.Làm cách nào để hiển thị một skydome thuyết phục?

Mái vòm có một số đám mây di chuyển rất cơ bản được tạo ra bằng cách sử dụng kết cấu nhiễu perlin phủ lên chính nó và di chuyển các tốc độ khác nhau.

Nhưng cuối cùng tôi cần những mái vòm cũng để render:

  • Sun (mà theo dõi trên bầu trời) Moon (bao gồm cả giai đoạn)
  • Stars (vào ban đêm)
  • đất xa như một kết cấu tĩnh
  • màu sắc khác nhau để mô phỏng đêm, bình minh, hoàng hôn, ngày

tôi cần phải làm điều này khá hiệu quả vì nó sẽ kết thúc o n Android mặc dù cho thời điểm nó chạy trong một khai thác thử nghiệm. Vì vậy, mặt trời, mặt trăng và các ngôi sao ví dụ sẽ chỉ là kết cấu mặc dù điểm của chúng có thể được vẽ với độ chính xác hợp lý.

Tôi đã có mã để tạo mái vòm và mã để vẽ một mặt trời dựa vào ngày giờ. Vì vậy, chủ yếu là các shaders tôi cần và những gì họ đang cung cấp với.

Có ví dụ nào thể hiện những điều này không? Tôi đã tìm thấy rất nhiều điều mà làm bản đồ khối cơ bản, hoặc các công cụ hạn chế, nhưng không có gì đến mức độ tinh tế tôi cần. Rõ ràng vì đây là OpenGL ES 2.0 nó phải được thực hiện trong shader.

Trình đổ bóng cho vòm trời hiện tại của tôi hiển thị 2 lớp nhiễu perlin để mô phỏng đám mây. Kết cấu kết thúc liên tục để tôi có thể tính toán độ lệch u dựa trên góc của đỉnh mái vòm vào mặt phẳng xy (bằng cách cho x và y vào trong) và v bù bằng đỉnh của mái vòm z.

Các vertex chứng minh làm thế nào tôi làm điều đó:

#ifdef GL_ES 
precision mediump float; 
precision mediump int; 
#endif 

attribute vec4 aVertex; 

uniform mat4 uPMVMatrix; 
uniform float uTime; 
uniform float uSkyDomeRadius; 

const float PI = 3.1415926535897932384626433832795; 

varying vec2 texCoord0, texCoord1; 

void main() 
{ 
    vec2 centre = vec2(600., 600.); 

    gl_Position = uPMVMatrix * aVertex; 

    float slow_time = uTime/100.; 

    vec2 dome_point = aVertex.xy - centre; 
    float tex_u = atan(dome_point.x, dome_point.y);///(.25 * PI); 
    float tex_v = aVertex.z/(uSkyDomeRadius * .5); 

    texCoord0 = vec2(tex_u/2.0 + slow_time, tex_v/2.0); 
    texCoord1 = vec2(tex_u + slow_time/2.0, tex_v); 
} 

tôi cũng sử dụng một thời gian để bù đắp u một chút mỗi khung để những đám mây di chuyển. Điều này hoạt động tốt ngoại trừ atan đi từ -PI đến PI và đột nhiên các giá trị texCoord0 và texCoord1 các nội suy đổ bóng phân đoạn được phân cách bởi một khoảng cách lớn mà ống nội suy.

Cách tốt nhất để mô tả nó là nếu tôi có 16 hình tam giác tại cơ sở của tôi thì nội suy từ 0/16 đến 1/16 hoạt động, 1/16 đến 2/16 tác phẩm và vân vân. Nhưng khi tôi nhận được 15/16 đến 0/16 nội suy đi ngược lại và biến thể lớn gây ra đổ bóng frag để lặp lại kết cấu hơn và hơn trong một không gian nhỏ dẫn đến sọc như được hiển thị.

Interpolation goes haywire as angle goes into reverse

Tôi không thể nhìn thấy bất cứ cách nào để có một cái nhìn 360 độ liền mạch Tôi nghĩ rằng cách duy nhất tôi sẽ khắc phục điều này là nếu tôi xoay toàn bộ mái vòm nên đường may luôn là phía sau máy ảnh nhưng nó có thể vẫn hiển thị nếu máy ảnh chỉ thẳng lên đỉnh mái vòm.

Ví dụ làm việc với nguồn sẽ rất tuyệt vời, đặc biệt là nếu nó giải quyết các loại vấn đề này.

+0

câu hỏi ngu ngốc nhưng có thể tex_x là> PI hoặc <-PI – BevynQ

+0

tex_x sẽ luôn ở giữa PI và -PI vì atan trả về các giá trị đó. Tôi có 16 hình tam giác ở đáy mái vòm để mỗi tam giác căn cứ quy định một vòng cung của 2PI/16 hoặc PI/8. Vì vậy, v0 có thể là 3/16th cách xung quanh và v1 4/16 và tex_x nội suy đúng cách. Vấn đề xảy ra nếu v0 là 15/16 và v1 là 0/16 và nội suy hoàn toàn bị hỏng. Tôi không thể nghĩ ra bất kỳ cách nào để sửa lỗi này đúng cách vì vậy tôi suy đoán rằng tôi sẽ phải xoay mái vòm để đường may luôn ở phía sau camera và bù đắp bất cứ thứ gì tôi render bằng một lượng tương đương. – locka

+0

Tôi đã cập nhật câu hỏi để làm rõ điều này và đổi tên thành tex_x và tex_y là tex_u và tex_v – locka

Trả lời

3

Vấn đề là bạn sử dụng cùng một đỉnh ở một góc 0 ° và 360 °. Vì vậy, bây giờ bạn có một hình tam giác nơi đỉnh đầu tiên có tọa độ kết cấu là 15/16, 0 và đỉnh thứ hai có 0, 0 thay vì 1,0.Để khắc phục điều đó, bạn phải mở quả cầu sao cho bạn có một cặp đỉnh ở cùng vị trí không gian, một cho 0 ° và một cho 360 °. Bằng cách đó, hai đỉnh có thể có các tọa độ kết cấu khác nhau và sẽ không có bất kỳ họa tiết bị xáo trộn nào.

Để xoay chúng, bạn phải sử dụng chế độ gói, đảm bảo rằng gói kết cấu được đặt lặp lại. Nếu bạn chưa thay đổi, nó phải được thiết lập chính xác, nhưng nó có thể được thiết lập với chức năng glTexParameter, các tham số là GL_TEXTURE_WRAP_SGL_TEXTURE_WRAP_T và giá trị phải là GL_REPEAT. Sau đó, nếu một giá trị kết cấu là> 1 nó sẽ không quấn quanh nhưng lặp lại kết cấu. Bây giờ bạn chỉ cần có thể cho biết các đỉnh ở đầu quả cầu (cho các đỉnh ở 0 °) từ những điểm ở cuối (cho các đỉnh ở 360 °) để bạn có thể sửa tex_u, bạn có thể cần một thuộc tính bổ sung cho điều đó .

+0

Cảm ơn tôi sẽ cho nó đi. Tôi biết rằng vấn đề là góc hiệu quả gói trở lại bằng không nhưng tôi sẽ xem nếu tôi có thể tạo ra các skydome trong một số cách mà bù đắp cho điều này như cách bạn đề nghị. – locka