Làm thế nào để trình đổ bóng phân mảnh biết được biến nào được sử dụng cho màu sắc của pixel?


82

Tôi thấy rất nhiều trình tạo bóng phân mảnh khác nhau,

#version 130

out vec4 flatColor;

void main(void)
{
    flatColor = vec4(0.0,1.0,0.0,0.5);
}

Và tất cả chúng đều sử dụng một biến khác nhau cho "màu ngoài" (trong trường hợp này flatColor). Vậy làm cách nào để OpenGL biết bạn đang cố gắng làm gì?

Tôi đoán điều này hoạt động vì flatColorbiến duy nhất được định nghĩa là out, nhưng bạn được phép thêm nhiều outbiến hơn phải không? Hay điều đó chỉ sụp đổ?


Trên thực tế, như một bài kiểm tra, tôi chỉ chạy điều này:

#version 330

in vec2 TexCoord0;

uniform sampler2D TexSampler;

out vec4 x;
out vec4 y;

void main()
{
    y = texture2D(TexSampler, TexCoord0.xy);
}

Nó hoạt động tốt cho dù tôi sử dụng xhay y.


Hơn nữa, chúng tôi đã xác định trước gl_FragColor. Sự khác biệt là gì, và tại sao mọi người thường khăng khăng sử dụng các biến của riêng họ?

Câu trả lời:


142

Hơn nữa, chúng ta có một gl_FragColor được xác định trước.

Hãy bắt đầu với điều này. Không, bạn không có xác định trước gl_FragColor. Điều đó đã bị xóa khỏi OpenGL 3.1 cốt lõi trở lên. Trừ khi bạn đang sử dụng khả năng tương thích (trong trường hợp đó, bộ đổ bóng 3,30 của bạn sẽ nói #version 330 compatibilityở trên cùng), bạn không bao giờ nên sử dụng cái này.

Bây giờ, quay lại kết quả đầu ra của trình đổ bóng phân đoạn do người dùng xác định. Nhưng trước tiên, một phép loại suy nhanh.

Hãy nhớ làm thế nào, trong bộ đổ bóng đỉnh, bạn có đầu vào? Và những đầu vào đại diện cho đỉnh chỉ số thuộc tính, các số bạn vượt qua glVertexAttribPointerglEnableVertexAttribArrayvà vân vân? Bạn thiết lập đầu vào nào lấy từ thuộc tính nào. Trong GLSL 3.30, bạn sử dụng cú pháp này:

layout(location = 2) in color;

Điều này đặt colorđầu vào bộ đổ bóng đỉnh đến từ vị trí thuộc tính 2. Trước 3.30 (hoặc không có ARB_explicit_attrib_location), bạn sẽ phải thiết lập điều này một cách rõ ràng với glBindAttrbLocationtrước khi liên kết hoặc truy vấn chương trình cho chỉ mục thuộc tính với glGetAttribLocation. Nếu bạn không cung cấp một cách rõ ràng một vị trí thuộc tính, GLSL sẽ chỉ định một vị trí tùy ý (nghĩa là: theo cách được triển khai xác định).

Đặt nó trong shader hầu như luôn là lựa chọn tốt hơn.

Trong mọi trường hợp, kết quả đầu ra của bộ đổ bóng phân mảnh hoạt động gần như giống hệt nhau. Trình tạo bóng phân mảnh có thể ghi vào nhiều màu đầu ra , bản thân chúng sẽ được ánh xạ tới nhiều bộ đệm trong bộ đệm khung . Do đó, bạn cần chỉ ra đầu ra nào chuyển sang màu đầu ra phân mảnh nào.

Quá trình này bắt đầu với giá trị vị trí đầu ra phân mảnh. Nó được đặt rất giống với các vị trí đầu vào của trình đổ bóng đỉnh:

layout(location = 1) out secColor;

Ngoài ra còn có các hàm API glBindFragDataLocationglGetFragDataLocationtương tự với glBindAttribLocationglGetAttribLocation.

Nếu bạn không thực hiện bất kỳ nhiệm vụ rõ ràng nào, việc triển khai thường sẽ gán một trong các biến đầu ra của bạn cho vị trí 0. Tuy nhiên, tiêu chuẩn OpenGL không yêu cầu hành vi này, vì vậy bạn cũng không nên phụ thuộc vào nó.

Công bằng mà nói, chương trình của bạn lẽ ra đã không liên kết được khi bạn sử dụng hai đầu ra không có vị trí đầu ra khác nhau. Điều có thể đã xảy ra là trình biên dịch của bạn đã tối ưu hóa thứ mà bạn không viết ra, vì vậy nó đã quên mất nó khi đến lúc kiểm tra lỗi trình liên kết.


4
Ước gì tôi có thể cho nhiều hơn +1. Câu trả lời ngoạn mục. Tôi đã tự hỏi làm thế nào các vị trí đầu ra phân mảnh hoạt động. :)
kevintodisco

Ahh .. vậy là họ không dùng nữa và gl_FragColorủng hộ bạn linh hoạt hơn để chọn bộ đệm nào để ghi? Có ý nghĩa. Cảm ơn một lần nữa!
mpen

3
@Mark: "Deprecation" có nghĩa là "bạn vẫn có thể sử dụng nó, nhưng nó có thể bị gỡ bỏ trong các phiên bản sau." "Đã loại bỏ" có nghĩa là bị loại bỏ . Có một sự khác biệt. Điều đó đã được đánh dấu là không được chấp nhận trong GL 3.0 đã bị loại bỏ trong 3.1 (tiết kiệm cho một số thứ).
Nicol Bolas

3
@NicolBolas: "GL 3.3 trở lên (đó là một thay đổi so với các phiên bản trước) sẽ gán tất cả chúng vào vị trí 0". Tôi tự hỏi điều này được đảm bảo bởi thông số kỹ thuật ở đâu. 3.3 cho biết "Khi một chương trình được liên kết, bất kỳ biến nào khác nhau mà không có ràng buộc được chỉ định [...] hoặc được đặt rõ ràng trong văn bản đổ bóng sẽ tự động được GL liên kết với các màu và chỉ số phân mảnh. Tất cả các nhiệm vụ như vậy sẽ sử dụng các chỉ số màu của số không.". Câu cuối cùng không có trong 3.2. Tuy nhiên, chỉ mục không đề cập đến số màu mà chỉ đề cập đến chỉ số pha trộn nguồn kép (đã được thêm vào trong 3.3).
derhass

1
Cảm ơn bạn @NicolBolas, câu trả lời tuyệt vời! Vì vậy, tôi chưa hoàn toàn hiểu nó đầy đủ, và chỉ muốn làm cho nó "không có câu hỏi". Trong trình tạo bóng của chúng tôi, chúng tôi luôn chỉ định layout (location = 0) out vec4 outColorkhi vẽ bất kỳ thứ gì bị ràng buộc (thường là "màn hình" chứ không phải FBO). Vì vậy, theo mặc định, nếu chúng ta không ràng buộc FBO (hoặc bộ đệm khác) bằng glDrawBuffers và chúng ta chỉ định location = 0, nó sẽ luôn vẽ chính xác ra màn hình?
AzP

9

Tôi muốn chỉ định điều này cho OpenGLES 3.1 sử dụng liên kết GLSL_ES_3.10 :

§4.4.2

Nếu chỉ có một đầu ra duy nhất [trong bộ đổ bóng phân mảnh], vị trí không cần phải được chỉ định, trong trường hợp đó, nó được mặc định bằng không.

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.