Gần đây, tôi đã nghiên cứu một chút về shader (trong Unity) và đang cố gắng tạo lại "nội tuyến dựa trên ánh sáng" có thể được quan sát trong Legend of Zelda mới nhất. Nhưng có lẽ nhiệm vụ là một chút trên kiến thức của tôi, bây giờ.
Theo như những gì tôi có thể phân tích, nó dường như hành xử (khi di chuyển) tương tự như những gì "viền bóng" làm, ngoại trừ nó có một đường cắt sắc nét (đơn giản để làm) và - phần tôi đang vật lộn - dường như có chiều rộng không đổi độc lập với độ cong cục bộ của lưới và khoảng cách với camera, về cơ bản có "chiều rộng" không đổi so với màn hình. (tốt, nó thực sự thay đổi một chút với khoảng cách máy ảnh, nhưng chủ yếu là không nên giả sử nó không)
Hơi khó để hiển thị trong một ảnh tĩnh, nhưng bạn có thể tìm thấy nhiều video trên trò chơi và hiệu ứng có thể nhìn thấy ở mọi nơi.
Tôi đã quản lý để làm phần đơn giản hơn, bóng râm cắt ra. Nhưng điều này mang lại hiệu ứng khó xử, tùy thuộc vào hướng máy ảnh và độ cong hình học, "nội tuyến" chiếm diện tích màn hình nhiều hay ít. Dưới đây là hình ảnh về kết quả hiện tại tôi nhận được trên các góc máy ảnh khác nhau, với mũi tên màu xanh lá cây hiển thị các khu vực tốt / chấp nhận được và mũi tên màu đỏ biểu thị độ lệch so với hiệu ứng dự định.
Đây là triển khai hiện tại của tôi để tham khảo, với tư cách là Mô hình ánh sáng bề mặt Unity:
half4 LightingToonPoster(SurfaceOutputStandard surf, float3 viewDir, UnityGI gi) {
// Material properties
half3 specular;
half oneMinusReflectivity;
DiffuseAndSpecularFromMetallic(surf.Albedo, surf.Metallic, /*out*/ specular, /*out*/ oneMinusReflectivity);
float3 reflected = normalize(-reflect(gi.light.dir, surf.Normal));
float specularity = dot(viewDir, reflected) * _Specularity;
// Light setup
float ndotl = dot(surf.Normal, gi.light.dir) * 0.5 + 0.5;
float lightIncidence = gi.light.color * ndotl;
float3 ramp = tex2D(_Ramp, lightIncidence.xx).rgb;
float3 specularRamp = tex2D(_Ramp, specularity.xx).rgb;
gi.light.color = ramp * _LightColor0.rgb;
// Rim and camera-light convergence
float rim = 1 - saturate(dot(surf.Normal, viewDir));
float facing = -dot(viewDir, gi.light.dir) * 0.5 + 0.25;
// sigmoid of rim for smooth falloff centered at _EdgeBias
float outline = 1 / (1 + exp(-100 * (rim - _EdgeBias)));
float highlight = _HighlightStrength * outline * facing * outline;
float4 std = LightingStandard(surf, viewDir, gi);
float3 toonDiffuse = surf.Albedo * (gi.light.color / 2 + ShadeSH9(float4(viewDir, 1)));
float3 toonSpecular = specular * gi.indirect.specular * specularRamp;
float4 toon = half4(toonDiffuse + toonSpecular, surf.Alpha);
return lerp(std, toon, _UnshadeFactor) * half4(1 + highlight.xxx, 1);
}
Hoặc kiểm tra Gist này để biết tập tin shader đầy đủ
Câu hỏi bây giờ là, tôi có thể sử dụng cái gì thay vì tạo bóng râm để có được hiệu ứng tương tự, trong đó độ cong không được tính đến và tôi có được một "hình nhỏ" không đổi?