Trình tạo bóng mặc định GLSL


7

Tôi đã trang bị cho động cơ của mình mã kiểm tra lỗi. Tôi sẽ cố gắng mô tả tình huống này với khả năng tốt nhất của tôi. Bất cứ khi nào tôi tải một shader và có lỗi (tập tin không tồn tại, lỗi biên dịch, bất cứ điều gì có thể sai) tôi xóa shader và đặt con trỏ về 0 (không thể nghĩ ra cách nào để đảm bảo rằng tôi không cố gắng đính kèm hoặc xóa rác một cách tình cờ). Tôi không muốn dừng chương trình nếu điều này xảy ra, bởi vì ai đó có thể xóa hoặc sửa đổi một tệp một cách tình cờ trong thư mục trò chơi và không muốn làm cho toàn bộ trò chơi không thể sử dụng được vì điều đó.

Bây giờ vấn đề là, có một hành vi mặc định trong tình huống tôi gắn shader vào một chương trình có con trỏ bằng 0 không?

Trong chương trình của tôi, nếu tôi đính kèm một shader đỉnh bằng 0 và shader mảnh bằng 0, thì OpenGL sẽ sử dụng chương trình mặc định (sẽ hiển thị mọi thứ màu trắng):

nhập mô tả hình ảnh ở đây

Đây là một khối được xoay mà kích thước đã có trong không gian clip, được hiển thị mà không cần chiếu phối cảnh hoặc kiểm tra độ sâu. Nó được tải từ tệp .obj.

Bây giờ, nếu tôi đính kèm một shader mảnh thích hợp, nhưng shader đỉnh sẽ là 0, tôi nhận được điều này:

nhập mô tả hình ảnh ở đây

Đó là những gì tôi mong đợi, tất cả các shader mảnh làm ra một vec4 (1.0, 0.3, 0.7, 1.0), không có shader đỉnh nên OpenGL sử dụng mặc định (đây có phải là giả định chính xác không?).

Tuy nhiên, bây giờ, nếu tôi đính kèm một shader đỉnh chính xác, nhưng tôi đính kèm một shader mảnh bằng 0 (hoặc tôi sẽ không đính kèm một shader mảnh nào cả) tôi sẽ gặp rắc rối này:

nhập mô tả hình ảnh ở đây

Một cái gì đó bạn không thể nhìn thấy là mô hình này liên tục được sơn các màu khác nhau, vì vậy trên màn hình của tôi, nó trông giống như một chuyến đi axit với các đường ngang màu đen đi qua.

Tôi bối rối một chút, vì tôi sẽ mong khối lập phương chỉ có màu trắng. Tôi muốn chỉ ra rằng mã shader của tôi là xương trần, tôi không trao đổi bất kỳ biến nào giữa các shader đỉnh và mảnh. Kiểm tra xem con trỏ có bằng 0 không thay đổi gì không, chương trình được liên kết hoạt động giống như khi tôi đưa cho nó một con trỏ bằng 0. Điều kỳ lạ nhất với tôi là nó luôn được tô bóng đẹp, nó không chỉ là rác.

EDIT: Có lẽ shader mảnh mặc định mong đợi một giá trị gl_ từ đỉnh mà tôi đang đặt ra? Điều đó sẽ giải thích lý do tại sao bề mặt được tô bóng đẹp mắt, shader mảnh vỡ mong đợi sự trơn tru, nhưng giá trị đó chỉ là rác, vì tôi đã không đặt nó.

Bây giờ đây có phải là "hành vi không xác định" hay đây là cách nó hoạt động tốt?


Tôi cảm thấy như lưu ý rằng muốn bảo vệ chống lại "ai đó có thể xóa một tệp" không phải là siêu năng suất. Họ cũng có khả năng xóa .exe của bạn, thay thế một tệp bằng một tệp hoàn toàn không tương thích, v.v. Các shader, vật liệu, mắt lưới mặc định, v.v ... rất hữu ích cho việc gỡ lỗi và thử nghiệm, và bạn hoàn toàn muốn chúng, nhưng đừng quá căng thẳng về việc mọi thứ hoạt động hoàn hảo khi dữ liệu được yêu cầu bị phá hủy một cách ngu ngốc bởi những người dùng cuối ngớ ngẩn.
Sean Middleditch

@seanmiddleditch Đó là một cách để xem xét nó. Tôi đoán tôi có thể di chuyển mã kiểm tra lỗi sang #ifdef _DEBUG?
dreta

Quan điểm của tôi là không nên viết hàng tấn mã tự bảo quản ưa thích, không phải mã đó chỉ ở chế độ gỡ lỗi. Có một loạt bài gồm 3 phần tuyệt vời trên blog bitquid.se abou xử lý lỗi trong các trò chơi, bitsquid.blogspot.com/2012/01/ Khăn
Sean Middleditch

Câu trả lời:


5

Kiểm tra phần 2.11 của đặc tả OpenGL 4.2 :

Mã thực thi cho một giai đoạn đổ bóng riêng lẻ được lấy từ chương trình hiện tại cho giai đoạn đó. Nếu có một đối tượng chương trình hiện tại được sử dụng bởi UseProgram, chương trình đó được coi là hiện tại cho tất cả các giai đoạn. Mặt khác, nếu có một đối tượng đường ống chương trình bị ràng buộc (xem phần 2.11.4), chương trình bị ràng buộc với giai đoạn thích hợp của đối tượng đường ống được coi là hiện tại. Nếu không có đối tượng chương trình hiện tại hoặc đối tượng đường ống chương trình bị ràng buộc, không có chương trình nào là hiện tại cho bất kỳ giai đoạn nào. Chương trình hiện tại cho một giai đoạn được coi là hoạt động nếu nó chứa mã thực thi cho giai đoạn đó; mặt khác, không có chương trình nào được coi là hoạt động cho giai đoạn đó. Nếu không có chương trình hoạt động cho các giai đoạn đổ bóng đỉnh hoặc phân đoạn, kết quả xử lý đỉnh và / hoặc phân đoạn sẽ không được thực hiện.Tuy nhiên, đây không phải là một lỗi. Nếu không có chương trình hoạt động nào cho điều khiển tessname, đánh giá tessname hoặc các giai đoạn đổ bóng hình học, các giai đoạn đó sẽ bị bỏ qua.

Đây là "hành vi không xác định" hoạt động khác nhau trên mỗi lần thực hiện.

Đối với giải pháp không thể tìm thấy một shader, tôi thấy tốt nhất là mã hóa cả shader đỉnh và mảnh và tải chúng trước bất cứ thứ gì khác, sau đó sử dụng nó thay cho bất kỳ shader bị thiếu nào. Bằng cách đó, rất nhiều đồng phục tôi xác định (ma trận biến đổi) vẫn sẽ đi qua và kết quả sẽ trông có vẻ không đáng kể. Ví dụ: đây là cách tôi làm (C #):

string defaultVertShaderText = 
    @"#version 120

    attribute vec4 in_vertex;

    uniform mat4 model;
    uniform mat4 view;
    uniform mat4 projection;

    void main()
    {
        gl_Position = projection * view * model * in_vertex;
    }";

string defaultFragShaderText =
    @"#version 120

    void main()
    {
        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
    }";

Ngoài ra mã hóa một kết cấu mặc định là một ý tưởng tốt.


Cảm ơn câu trả lời. Và tôi đã suy nghĩ về cùng một cách để đối phó với các shader trống, chỉ là tôi làm điều đó ở cấp độ quản lý chương trình (nếu chương trình sai tôi sử dụng một chương trình mặc định), vì vậy tất cả những gì tôi phải làm là sử dụng các shader mặc định của mình trên chương trình giai đoạn biên dịch và nó sẽ hoạt động, yeah. Cảm ơn một lần nữa.
dreta

@Robert: -1: Vui lòng không chuyển các chuỗi chuỗi như thế này sang OpenGL. glShaderSource thực hiện các mảng, nhưng đây không phải là cách sử dụng chức năng đó. Mỗi chuỗi không có nghĩa là một dòng riêng biệt.
Nicol Bolas

@NicolBolas Tôi đã đề cập rằng đây là cách tôi thực hiện nó trong trò chơi của mình trong C #. OpenTK cung cấp quá tải các cuộc gọi GL thông thường để tương tác với các loại C # theo cách mà bạn mong đợi một cách tự nhiên. Theo như tôi đã thử nghiệm (ATI, AMD, NVIDIA, Intel, Apple và Mesa giữa Windows, Linux và OS X), các trình tạo bóng sẽ biên dịch, liên kết và hoạt động đúng và không có lỗi. Tôi đoán nếu bạn thích, tôi có thể xóa "đây là cách tôi thực hiện (C #)" và thay thế nó bằng sytnax C cho cùng một thứ.
Robert Rouhani

@RobertRouhani: Điều này không liên quan gì đến "Cú pháp C". Đó là về thực tế là bạn đang xây dựng một mảng. Nó phải là một chuỗi đơn , không phải là một chuỗi các chuỗi (hoặc một mảng của một chuỗi). Có, nó "biên dịch, liên kết và hoạt động đúng và không có lỗi". Nhưng đó vẫn là cách sai để sử dụng thực tế glShaderSourcecần một chuỗi các chuỗi.
Nicol Bolas

2
@RobertRouhani: Không đúng vì đó không phải là mảng dành cho. Nó cần một chuỗi các chuỗi để bạn có thể xây dựng một shader được biên dịch hiệu quả từ các phần tham chiếu lẫn nhau. Và để bạn có thể kết hợp các tiền tố tiêu đề cho các shader, để chúng có thể hoạt động với các phiên bản khác nhau bằng cách sử dụng #ifdef. Nó không ở đó để bạn có thể gửi mỗi dòng dưới dạng một chuỗi riêng biệt. Vâng, nó hoạt động, nhưng đó là phong cách mã hóa khủng khiếp. Nó giống như xây dựng tệp .cpp bằng cách bao gồm từng dòng riêng lẻ . Vâng, nó sẽ biên dịch, nhưng đó không phải là cách bạn sử dụng #include.
Nicol Bolas
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.