OpenGL: Tôi nên đặt shader ở đâu?


17

Tôi đang cố gắng học OpenGL ES 2.0 và tôi tự hỏi đâu là cách phổ biến nhất để "quản lý" trình đổ bóng.
Tôi đang hỏi câu hỏi này vì trong các ví dụ tôi đã tìm thấy (như một ví dụ được bao gồm trong API Demo được cung cấp với sdk android), tôi thường thấy mọi thứ bên trong lớp GLRenderer và tôi muốn tách biệt mọi thứ để tôi có thể có, ví dụ, một đối tượng GLImage mà tôi có thể sử dụng lại bất cứ khi nào tôi muốn vẽ một hình tứ giác có kết cấu (tôi chỉ tập trung vào 2D vào lúc này), giống như tôi đã có trong mã OpenGL ES 1.0 của mình. Trong hầu hết mọi ví dụ tôi đã tìm thấy, các shader chỉ được định nghĩa là các thuộc tính lớp. Ví dụ:

public class Square {

public final String vertexShader =
        "uniform mat4 uMVPMatrix;\n" +
        "attribute vec4 aPosition;\n" +
        "attribute vec4 aColor;\n" +
        "varying vec4 vColor;\n" +
        "void main() {\n" +
        "  gl_Position = uMVPMatrix * aPosition;\n" +
        "  vColor = aColor;\n" +
        "}\n";

public final String fragmentShader =
        "precision mediump float;\n" +
        "varying vec4 vColor;\n" +
        "void main() {\n" +
        "  gl_FragColor = vColor;\n" +
        "}\n";
// ...
}

Tôi xin lỗi trước nếu một số trong những câu hỏi này bị câm, nhưng tôi chưa bao giờ làm việc với các shader trước đó.

1) Mã ở trên có phải là cách phổ biến để xác định shader (thuộc tính lớp cuối cùng công khai) không?
2) Tôi có nên có một lớp Shader riêng không?
3) Nếu các shader được định nghĩa bên ngoài lớp sử dụng chúng, làm thế nào tôi biết được tên của các thuộc tính của chúng (ví dụ "aColor" trong đoạn mã sau) để tôi có thể liên kết chúng?

colorHandle = GLES20.glGetAttribLocation(program, "aColor");

Câu trả lời:


16

Tôi luôn không thích cách định nghĩa các shader (trong một chuỗi). Tôi thích làm việc của tôi trong một tệp văn bản và đọc nó khi tải. Xác định nó trong một chuỗi là khó chịu để gỡ lỗi và nó trông có vẻ lộn xộn đối với tôi. Thật dễ dàng hơn nhiều để có thể gõ nó ra và thấy nó được định dạng như nó phải, thay vì bên trong một chuỗi.

Tôi cũng có một lớp riêng có chức năng đổ bóng thông thường, như đọc trong các shader và in thông tin đăng nhập để gỡ lỗi shader.

Bất cứ khi nào các shader được xác định, bạn có thể truy cập vào các tên giống như bạn làm trong ví dụ của mình. Sử dụng chuỗi ký tự được chấp nhận cho các shader vì các giá trị đó khó có thể thay đổi khi bạn triển khai chúng.

Tuy nhiên, cuối cùng thì tùy bạn. Cách bạn đang làm nó hoạt động rất tốt, nếu nó không gây rắc rối cho bạn.


2
Có các shader của bạn trong các tệp riêng biệt cũng có nghĩa là bạn có thể sử dụng các trình soạn thảo shader tiện dụng và có tô sáng cú pháp đầy đủ, và thậm chí xem trước chúng trước khi kiểm tra chúng trong chương trình của bạn, nếu bạn hỗ trợ điều đó.
Raceimaztion

6
Lý do thực sự duy nhất để có các shader trong chuỗi là để kiểm tra nhanh và hướng dẫn .. trong đó việc xử lý tệp thêm phần lớn "mã không cần thiết".
Jari Komppa

2
Bạn cũng có thể thực hiện tải lại nóng trên các tệp shader - cho phép bạn gỡ lỗi các thay đổi mà không cần khởi chạy lại trò chơi. Năng suất ++
Liosan

Tôi thích ý tưởng đọc chúng tạo thành một tập tin và có một lớp Shader riêng. Nhìn thấy chúng luôn ở trong Chuỗi khiến tôi bối rối vì tôi không biết đó là cách chúng thường được xác định hay chỉ nhằm mục đích học tập. Cảm ơn!
miviclin

8

Quản lý Shader (và do đó là vật liệu) là một vấn đề khá khó khăn mà bạn gặp phải khi hệ thống đồ họa của bạn trở nên phức tạp hơn và bạn nhận thấy mã hóa cứng, mọi shader sẽ dẫn đến sự sao chép mã lớn. Dưới đây là một vài cách khác để giải quyết nó:

  • Các ví dụ nhỏ chỉ có một vài shader có xu hướng mã hóa chúng thành chuỗi để tránh xử lý tệp như Jari Komppa đã nhận xét
  • Tốt hơn là sử dụng các tệp riêng biệt trong đó bạn có thể đánh dấu cú pháp và định dạng đúng. Bạn cũng có thể mã hóa một hệ thống gỡ lỗi đơn giản để theo dõi các thay đổi trong các tệp đó và áp dụng trình đổ bóng đã được sửa đổi khi đang chạy trong trò chơi của bạn.
  • Khi số lượng vật liệu tăng lên, một bộ tạo bóng trở nên gần như là một điều cần thiết. Về cơ bản, bạn xác định các đoạn mã phổ biến như "đoạn mã ánh xạ mảnh bình thường" và soạn thảo các trình đổ bóng hoàn chỉnh của bạn bằng cách bao gồm các thành phần mong muốn.
    • Bạn có thể sử dụng các đoạn mã được mã hóa cứng, nhưng điều đó thực sự rất nhanh, vì vậy một lần nữa các tệp là một ý tưởng tốt.
    • Bạn có thể có thể có bit mã trong tập tin riêng biệt (hoặc tương tự) hoặc cách khác sử dụng ubershader / supershader nơi bạn sử dụng tiền xử lý (hoặc cờ thống nhất) để bật / tắt công cụ.

Đối với các thuộc tính và tên thống nhất và như vậy, bạn chỉ cần sử dụng một cách đặt tên nhất quán trên tất cả các shader.


Tôi chắc chắn sẽ chuyển các shader của tôi sang một tập tin riêng biệt. Cảm ơn!
miviclin
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.