Cách nhanh nhất để tạo hiệu ứng hạt đơn giản


12

Tôi đang tìm cách nhanh nhất để tạo hiệu ứng hạt thực sự đơn giản sẽ bị spam như địa ngục trong trò chơi ...

Về cơ bản, trò chơi của tôi trông giống như một trò chơi vectrex, được tạo thành chủ yếu từ các dòng ... Tôi muốn tạo ra một số vụ nổ nhỏ sẽ thực sự phổ biến.

Có điều gì nhanh hơn là chỉ di chuyển xung quanh một số điểm và kết xuất với GL_Point?


+1 chỉ để tham khảo Vectrex. Tôi đã dành vài giờ vui vẻ trên Scramble và Tempest khi còn bé vào đầu những năm 80. Nếu không có điều đó, có lẽ tôi đã không trở thành một nhà phát triển trò chơi ngày hôm nay.
Kylotan

Đúng, Tempest thật tuyệt vời: D
speeder

Làm thế nào tôi nói rằng không có gì là chính xác?
tốc

Câu trả lời:


13

Thực sự không cần lưu trữ bộ nhớ cho mỗi hạt và hoạt hình riêng lẻ từng hạt. Bạn có thể thực hiện nó một cách thủ tục bằng cách tái cấu trúc vị trí hạt trong khi vẽ bằng cách sử dụng phương trình vật lý cổ điển. s = ut + 1 / 2.at ^ 2

Một ví dụ đơn giản (không có gia tốc liên tục của các hạt):


void drawExplosion(ExplosionParameters& s)
{
  Random rng;
  rng.seed(s.startSeed);
  glBegin(GL_POINTS);
  for (int i = 0; i < s.numParticles; i++)
  {
    vec3 vel = rng.getRandomVector(-1.0f, 1.0f) * s.explosionSpeed;
    float timeBias = rng.getRandom(0, s.particleTimeBias);
    vec3 pos = s.explosionCentre + (vel * (s.timeElapsed + timeBias));
    glPoint3fv(&pos);
  }
  glEnd();
}

Sau đó, bạn chỉ cần tăng s.timeElapsed trên mỗi lần lặp của vòng cập nhật của bạn.

Nó cũng hoàn toàn có thể chấp nhận được khi được triển khai trên GPU do đó giải phóng CPU của bạn khỏi phải thực hiện bất kỳ công việc nào. Một triển khai gpu có thể trông như thế này:

void drawExplosion(ExplosionParameters& s)
{
    //bind Vertex Shader If Not Already Bound();
    ...
    // bindVertexBuffer of Zeroes If Not AlreadyBound();
    glVertexPointer(...)
    //uploadShaderUniformsForExplosion(s);
    glUniform3f(...)
    ...
    glDrawArrays(GL_POINTS, 0, s.numParticles);
} 

Bộ tạo bóng đỉnh GPU sau đó sẽ tái cấu trúc vị trí hạt thông qua phương trình vật lý và các đồng phục / hằng số được truyền cho nó - giống như phiên bản CPU đã làm.

Để thêm một số phương sai, bạn có thể sử dụng nhiều vụ nổ đồng thời hơn với các thông số hơi khác nhau, hoạt hình màu sắc / alpha, chọn các vị trí bắt đầu khác nhau. Vân vân.


Ngoài ra, bạn có thể sử dụng khả năng dự đoán của các số ngẫu nhiên giả để tạo ra tất cả các vectơ ban đầu của các hạt, tạo ra hàng trăm hạt từ một vài dữ liệu của int. Sử dụng GPU để tạo ra các quads là một ý tưởng thực sự tốt cho các hạt đơn giản.
Skizz

Trong nhiều năm, tôi đã tạo ra các hệ thống hạt theo cách truyền thống với các lớp các lớp coi các hạt là các thực thể bán thông minh và nó luôn có vẻ lãng phí và cồng kềnh. Cách này tốt hơn nhiều đối với các hạt cơ bản không làm gì hơn là phun ra trên màn hình.
Piku

7

Tôi đã thực hiện một số thử nghiệm và cách NHANH CHÓNG nhất (không phải là mã nhanh nhất) là các hạt được tạo ra từ GL_LINE biết vị trí và tốc độ của chúng và sử dụng đó làm điểm khi kết xuất (vì vậy, hạt đi càng nhanh, "đường" nhanh nhất nó trở thành, càng chậm, nó trở thành một điểm).

Hiệu ứng này thật sự rất tuyệt (nhìn vào bất kỳ video chiến tranh hình học nào để thấy nó) và cũng thật sự rất nhanh. Loại bỏ crap ra khỏi quads (đặc biệt bởi vì quads sẽ khiến tôi cần tính toán gấp đôi số đỉnh)

Ngoài ra, tốt hơn là sử dụng một hệ thống hạt đã được thực hiện, vì tôi muốn có hiệu ứng cụ thể và NHANH CHÓNG, các hệ thống hạt thường hỗ trợ rất nhiều tính năng, với lượng chi phí tương ứng.


2
+1 để giải thích những gì bạn đã làm, mặc dù tôi tò mò muốn biết thêm chi tiết về các bài kiểm tra của bạn. =)
leander

Btw: Tất cả những thứ đó đều ở chế độ ngay lập tức (đó là điều duy nhất tôi biết cách viết mã và tôi đã học được tên ngày hôm qua ...)
speeder

6

Thông thường tôi nghĩ bạn sẽ làm các hạt như các quads ánh xạ kết cấu. Đối xử với chúng như các họa tiết 2D về cơ bản và làm mờ dần chúng theo thời gian, phá hủy chúng khi vô hình. Tốt hơn hết, hãy sử dụng lại những cái cũ khi bạn tạo cái mới để bạn không bị mất trí nhớ cho những thứ này.

Nếu bạn sử dụng alpha tiền kỹ thuật trong nghệ thuật thì bạn có thể dễ dàng hỗ trợ đèn, lửa, khói và hơn thế nữa với tất cả một loại hoạt động pha trộn.


Hum ... điểm không NHANH CHÓNG hơn kết cấu?
tốc

2
Phần cứng đồ họa được tối ưu hóa đặc biệt cho kết cấu rasterising cho bộ đệm khung. Nếu các điểm nhanh hơn, nó có thể bằng một lượng không đáng kể và bạn mất đi tất cả các khả năng mà bạn có được với kết cấu.
Kylotan

như thế nào? Xin lưu ý rằng tôi không tạo ra một hệ thống hạt đầy đủ tính năng, nó chỉ là một hiệu ứng cụ thể (vụ nổ nhỏ, chủ yếu là cho phản hồi chơi trò chơi mà bạn đạt được)
speeder

Nếu bạn chỉ muốn sử dụng điểm hoặc đường thì không sao. Tôi chỉ có thể nhận xét về những gì hầu hết mọi người làm cho các hạt. Có lẽ một tam giác không hàn sẽ tạo ra một hạt tốt đẹp.
Kylotan

4

Với OpenGL ES 2.0, ES 1.X có phần mở rộng và OpenGL => 2.1, bạn có thể sử dụng GL_POINTinksRITES. GL_POINTinksRITES giống như một hình tứ giác luôn ở phía trước máy ảnh.

Trong shader mảnh, bạn có thể:

  • xác định kích thước của sprite với gl_PointSize trong shader đỉnh
  • sử dụng gl_PointCoord (tọa độ uv) trong shader mảnh

Bạn có thể sử dụng kết cấu với alpha để vẽ các họa tiết bóng ...

Hướng dẫn cho Sprites Point


Tôi đang tránh các tiện ích mở rộng, những tiện ích ngớ ngẩn mà động cơ (mà tôi không tạo ra) đã sử dụng, đủ để nhiều người phàn nàn rằng trò chơi không chạy ...
speeder

1

Hầu hết các hệ thống hiệu ứng hạt mà tôi đã thấy, thay vì vẽ một số lượng lớn các điểm, vẽ một số lượng tương đối nhỏ hơn các kết cấu biển quảng cáo trong đó mỗi kết cấu trông hơi giống một vụ nổ. Trừ khi phong cách nghệ thuật của bạn thực sự ngăn cản, bạn sẽ có thể hạnh phúc hơn khi đi theo con đường đó. Nó sẽ giảm thiểu lượng hạt bạn cần để tạo hiệu ứng riêng lẻ và kết xuất trong khi vẫn mang lại hiệu ứng hình ảnh lớn.


1
Đúng, nhưng anh ấy đang nhắm đến phong cách Vectrex, nó sẽ hoạt động kém hơn ở đó.
Kaj

1
Chính xác những gì Kaj đã nói ... nó sẽ là vô nghĩa, VÀ sẽ tăng kích thước tải xuống (Tôi đang chuyển đổi đồ họa nhiều nhất có thể từ sprite sang các vectơ thực, vì vậy tôi có thể giảm kích thước tệp)
speeder

1

Để có một cách gọn gàng để xử lý việc sinh sản / xóa / cập nhật các hạt, giả sử bạn có một mảng các hạt đơn giản - Các hạt [MAX_PARTICLES]:

Theo dõi các hạt hoạt động (bắt đầu với NumActiveParticles = 0)

Các hạt mới luôn được thêm vào cuối mảng:

pNewParticle = &Particles[NumActiveParticles++];

Bit thông minh - Khi loại bỏ hạt 'chết' - trao đổi nó với hạt hoạt động cuối cùng và giảm số NumActiveParticles:

if ( DeadParticle < NumActiveParticles-1 )
{
  Particles[ DeadParticle ] = Particles[ NumActiveParticles-1 ];
}
NumActiveParticles--;

Điều này tránh mọi tìm kiếm 'các hạt không sử dụng' khi sinh sản và tránh mọi hoạt động quét qua một mảng MAX_PARTICLES nếu không sử dụng.

Lưu ý rằng điều này chỉ hoạt động nếu thứ tự cập nhật / kết xuất không quan trọng (như trường hợp của nhiều hiệu ứng hạt, sử dụng trộn phụ gia) - vì phương pháp xóa hạt này sắp xếp lại mảng


-1

Cách nhanh nhất tôi sẽ giả định là tìm một động cơ hạt và sử dụng nó cho các hiệu ứng của bạn. Ở đây có một ít:

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.