2010-01-27 16 views
16

Tôi đang làm việc trên một trò chơi mà tôi muốn tạo bóng dưới một loạt các sprites trên một mạng lưới. Bóng tối lớn hơn bản thân sprites và các sprites được làm động (tức là di chuyển và xoay).Có thể đạt được kết hợp mở rộng MAX (Như, Quảng cáo) không?

Tôi không thể chỉ đơn giản là hiển thị chúng thành png sprite hoặc bóng sẽ chồng chéo các vân liền kề.

Tôi cũng không thể chỉ đơn giản đặt bóng trên một lớp thấp hơn, bởi vì khi chúng chồng lên nhau, chúng sẽ tạo các dải tối ở giao lộ của chúng.

Các sprites này là hoạt ảnh, vì vậy không thể thực hiện được những điều này.

Về cơ bản, tôi muốn các bóng của sprites hòa trộn với nhau sao cho chúng tối đa ở độ mờ được đặt. Ví dụ:

enter image description here

Tôi tin rằng đây là tương đương với một pha trộn OpenGL của (Rs, Gs, Bs, Max (As, Ds)), nơi tôi không thực sự quan tâm đến R, G và B , vì nó sẽ luôn có cùng màu trong src và dst.

Tuy nhiên, đây không phải là chế độ hòa trộn OpenGL hợp lệ. Có một cách dễ dàng để thực hiện điều này, đặc biệt là trong cocos2d-iphone?

Tôi sẽ có thể ước tính điều này bằng cách làm cho bóng mờ đục, sau đó áp dụng cả hai cho một sprite cha mẹ, và làm cho phụ huynh sprite 40% opacity. Tuy nhiên, cách thức hoạt động của cocos2d, điều này chỉ đặt độ mờ đục của mỗi trẻ là 40%, chứ không phải là hình ảnh kết hợp sprite, kết quả là cùng một sọc.

Trả lời

16

OK, tôi nghĩ sau nhiều nghiên cứu, tôi nhận ra lỗi trong suy nghĩ của mình.

Đầu tiên, có cách để thực hiện phối hợp OpenGL tối đa Alpha, và đó là sử dụng glBlendEquations. Bạn sẽ phải thay đổi phương pháp bốc thăm để làm điều này (và làm cho một số thuộc tính mới cho một textureNode để chuyển đổi giữa các phương pháp này), và sử dụng một trong những:

glBlendEquationOES(GL_MAX_EXT); 
glBlendEquationSeparateOES(GL_FUNC_ADD_OES, GL_MAX_EXT); 

Đầu tiên sử dụng tối đa() cho RGBA, trong khi thứ hai sử dụng bổ sung tiêu chuẩn cho RGB và max() cho alpha.

Bây giờ, vấn đề là mỗi sprite, và đó là trẻ em, theo thứ tự z, được vẽ đến màn hình . Điều này có nghĩa, sau khi bóng đầu tiên được vẽ, nó là một phần của bộ đệm màn hình chính. Nói cách khác, độ mờ đục của nó được thay đổi, và với sự pha trộn max() và nền mờ chuẩn, nó được vẽ lên nền, vì vậy khi bạn vẽ bóng tiếp theo, nó sẽ làm tối đa (As, 1) là 1, bởi vì nền mờ đục. Vì vậy, tôi không đạt được sự pha trộn tôi muốn. Nó sẽ "làm việc" nếu nền của tôi là trong suốt, nhưng sau đó tôi không thể áp dụng bất kỳ nền "đằng sau" đó, chúng tôi chỉ có thể thêm vào bộ đệm.

Tôi có thể vẽ bóng đầu tiên, sử dụng phép trộn max() và sau đó thực hiện {ONE_MINUS_DST_ALPHA, DST_ALPHA} glBlend. Đây là giải pháp thay thế OK, nhưng tôi có các vấn đề khác khiến việc này trở nên khó khăn.

Bây giờ, giải pháp thực sự, cuối cùng tôi nhận ra, là sử dụng RenderTexture để hiển thị bóng cho bộ đệm riêng biệt trước khi áp dụng chúng vào nền. Điều này có thể có tác động hiệu suất, vì vậy chúng tôi sẽ xem nơi này đi.

Cập nhật:

OK, tôi có một giải pháp làm việc bây giờ.

Thật kỳ lạ, cuối cùng tôi không cần giải pháp này, vì trong trường hợp cụ thể của tôi, dải không đủ chú ý để đảm bảo nỗ lực, tuy nhiên đây là giải pháp mà tôi đưa ra để làm điều tôi muốn:

  1. Đầu tiên vẽ 0% alpha png đen lên toàn bộ màn hình. (Tôi không biết nếu điều này là cần thiết. Tôi không biết alpha mặc định của màn hình là gì).

  2. Vẽ bóng cho màn hình bằng cách sử dụng glEquationSeperateOES(GL_ADD, GL_MAX_ENT)glBlend(GL_ONE, GL_ONE). Điều này sẽ pha trộn tất cả các bóng với nhau như mô tả, lấy tối đa() của các chữ cái.

    • Bởi vì bạn đang hợp lại thành màu đen, nó tương đương với sử dụng glBlendEquationOES(GL_MAX_ENT). (X + 0 == tối đa (X, 0))

    • glBlend(GL_ZERO, GL_ONE) sẽ loại bỏ nhu cầu của bước 1 hoặc ít nhất yêu cầu của lớp đó là 0% đen. GL_ZERO về cơ bản buộc nó phải là 0% màu đen.

  3. Vẽ sàn, sẽ được qua bóng tối, nhưng sử dụng glBlend(ONE_MINUS_DST_ALPHA, DST_ALPHA). Điều này dẫn đến kết quả chính xác giống như nếu bạn thêm bóng vào sàn với glBlend(SRC_ALPHA, ONE_MINUS_SRC_ALPHA), tuy nhiên nếu bạn đã làm theo cách này, bạn sẽ không thể trộn lẫn các bóng với nhau (đọc tại sao ở đầu câu trả lời).

  4. Bạn đã hoàn tất! Điều tốt đẹp về phương pháp này là các sprites shadow có thể hoạt hình như bình thường, mà không cần phải gọi "visit" trên một renderTexture riêng biệt.

Phần còn lại:

Tôi cũng sửa đổi CocosNode để cho phép tôi thêm một bóng tối để một lớp, mà liên kết đến CocosNode khác. Bằng cách này, bóng được hiển thị như một đứa trẻ của tầng, (hoặc 0% nền đen sprite cho bóng pha trộn), nhưng được liên kết với một CocosNode. Khi một sprite di chuyển, nếu nó có bóng đổ, nó sẽ cập nhật vị trí đổ bóng. Điều này cho phép tôi có tất cả các bóng bên dưới tất cả các đối tượng trên màn hình và để các bóng đổ tự động theo đối tượng.

Xin lỗi vì câu trả lời dài. Có lẽ giải pháp của tôi là kludgy, nhưng có vẻ như nó hoạt động rất tốt.

+1

Cảm ơn bạn đã theo dõi câu hỏi của mình bằng câu trả lời thông tin! –

+0

cũng cảm ơn! Thông tin này là thực tế không nơi nào khác. :) –

Các vấn đề liên quan