{"id":284035,"date":"2017-03-28T15:45:02","date_gmt":"2017-03-28T11:45:02","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=284035"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=284035","title":{"rendered":"\u041c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0435 \u0442\u0440\u044e\u043a\u0438 DirectX \u0438 HLSL"},"content":{"rendered":"<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440!<br \/>  \u0420\u0435\u0448\u0438\u043b \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e-\u0437\u0430\u043c\u0435\u0442\u043a\u0443 \u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0442\u0440\u044e\u043a\u0430\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0432 \u0441\u0432\u043e\u0435\u043c \u0441\u043a\u0440\u043e\u043c\u043d\u043e\u043c \u0434\u0432\u0438\u0436\u043a\u0435. \u042d\u0442\u043e \u0441\u043a\u043e\u0440\u0435\u0435 \u0437\u0430\u043c\u0435\u0442\u043a\u0430 \u0441\u0430\u043c\u043e\u043c\u0443-\u0441\u0435\u0431\u0435, \u0438 \u043c\u0430\u0442\u0451\u0440\u044b\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u044b \u043b\u0438\u0448\u044c \u0443\u0441\u043c\u0435\u0445\u043d\u0443\u0442\u0441\u044f, \u043d\u043e, \u0434\u0443\u043c\u0430\u044e, \u043d\u043e\u0432\u0438\u0447\u043a\u0430\u043c \u043e\u043d\u0430 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f.<br \/>  <a name=\"habracut\"><\/a><\/p>\n<h3>1. \u041c\u0430\u0442\u0440\u0438\u0446\u044b \u0432 HLSL<\/h3>\n<p>  \u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c \u0432 \u0432\u0435\u0440\u0442\u0435\u043a\u0441\u043d\u043e\u043c \u0448\u0435\u0439\u0434\u0435\u0440\u0435 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043d\u043e\u0440\u043c\u0430\u043b\u044c (\u0442\u0430\u043d\u0433\u0435\u043d\u0442\u0443, \u0431\u0438\u043d\u043e\u0440\u043c\u0430\u043b\u044c) \u0432\u0435\u0440\u0442\u0435\u043a\u0441\u0430 \u0438 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043c\u0438\u0440\u043e\u0432\u0430\u044f \u043c\u0430\u0442\u0440\u0438\u0446\u0430 4\u04454. \u041d\u043e \u0441\u0434\u0432\u0438\u0433, \u0437\u0430\u0448\u0438\u0442\u044b\u0439 \u0432 \u043c\u0430\u0442\u0440\u0438\u0446\u0443, \u043d\u0430\u043c \u043d\u0435 \u043d\u0443\u0436\u0435\u043d. \u0422\u043e\u0433\u0434\u0430 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u043c \u043c\u0430\u0442\u0440\u0438\u0446\u0443 \u043a 3\u04453:  <\/p>\n<pre><code class=\"cpp\">output.Normal = mul(input.Normal.xyz, (float3x3)RotM);<\/code><\/pre>\n<p>  \u041a\u0441\u0442\u0430\u0442\u0438, \u0435\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u043d\u0432\u0435\u0440\u0441\u043d\u0443\u044e \u043c\u0430\u0442\u0440\u0438\u0446\u0443 \u043e\u0442 \u043c\u0430\u0442\u0440\u0438\u0446\u044b \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u0430 3\u04453, \u0438 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043e\u043d\u0430 \u043e\u0440\u0442\u043e\u0433\u043e\u043d\u0430\u043b\u044c\u043d\u0430, \u0442\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c:  <\/p>\n<pre><code class=\"cpp\">float3\u04453 invMat = transpose(Mat);<\/code><\/pre>\n<p>  \u0418\u043b\u0438 \u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u043e\u0439\u0442\u0438\u0441\u044c \u0438 \u0431\u0435\u0437 \u044d\u0442\u043e\u0433\u043e, \u0435\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043b\u0438\u0448\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0438\u043d\u0432\u0435\u0440\u0441\u043d\u043e\u0439 \u043c\u0430\u0442\u0440\u0438\u0446\u0435\u0439 \u0432\u0435\u043a\u0442\u043e\u0440 \u2014 \u0442\u043e\u0433\u0434\u0430 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u0430\u0442\u0440\u0438\u0446\u044b \u0438 \u0432\u0435\u043a\u0442\u043e\u0440\u0430:  <\/p>\n<pre><code class=\"cpp\">float3 outVector = mul((float3x3)RotM, inVector.xyz);<\/code><\/pre>\n<p>  \u0412\u044b \u043d\u0430\u0432\u0435\u0440\u043d\u044f\u043a\u0430 \u0437\u043d\u0430\u0435\u0442\u0435, \u0447\u0442\u043e \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443 \u043c\u0430\u0442\u0440\u0438\u0446\u044b \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u044c \u0442\u0438\u043f\u0430:  <\/p>\n<pre><code class=\"cpp\">float value = World._m30;<\/code><\/pre>\n<p>  \u041e\u0434\u043d\u0430\u043a\u043e \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u0440\u0430\u0437\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0438\u0437 \u043c\u0430\u0442\u0440\u0438\u0446\u044b. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0438\u0437 \u043c\u0430\u0442\u0440\u0438\u0446\u044b \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438:  <\/p>\n<pre><code class=\"cpp\">float3 objPosition = World._m30_m31_m32;<\/code><\/pre>\n<h3>2. \u0420\u0435\u043d\u0434\u0435\u0440 \u0431\u0435\u0437 \u0432\u0435\u0440\u0442\u0435\u043a\u0441\u043d\u043e\u0433\u043e \u0431\u0443\u0444\u0435\u0440\u0430<\/h3>\n<p>  \u0412 DX11 \u0435\u0441\u0442\u044c \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043d\u0430 \u0440\u0435\u043d\u0434\u0435\u0440 \u0432\u0435\u0440\u0448\u0438\u043d\u044b, \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u044f \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432\u0435\u0440\u0448\u0438\u043d\u043d\u044b\u0439 \u0431\u0443\u0444\u0435\u0440. \u041a\u043e\u0434 \u0434\u043b\u044f C# \u0438 \u0432\u0440\u0430\u043f\u0435\u0440\u0430 SharpDX:  <\/p>\n<pre><code class=\"cpp\">System.IntPtr n_IntPtr = new System.IntPtr(0); device.ImmediateContext.InputAssembler.InputLayout = null; device.ImmediateContext.InputAssembler.SetVertexBuffers(0, 0, n_IntPtr, n_IntPtr, n_IntPtr); device.ImmediateContext.InputAssembler.SetIndexBuffer(null, Format.R32_UInt, 0); device.ImmediateContext.Draw(3, 0);<\/code><\/pre>\n<p>  \u0417\u0434\u0435\u0441\u044c \u043c\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u0430 \u0440\u0435\u043d\u0434\u0435\u0440 \u0442\u0440\u0438 \u0432\u0435\u0440\u0448\u0438\u043d\u044b. \u0410 \u0432 \u0448\u0435\u0439\u0434\u0435\u0440\u0435, \u0434\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0438\u0437 \u043d\u0438\u0445 \u043f\u043e\u043b\u043d\u043e\u044d\u043a\u0440\u0430\u043d\u043d\u044b\u0439 \u043a\u0432\u0430\u0434:  <\/p>\n<pre><code class=\"cpp\">struct VertexInput { \tuint VertexID : SV_VertexID; }; struct PixelInput { \tfloat4 Position : SV_POSITION; };  PixelInput DefaultVS(VertexInput input) { \tPixelInput output = (PixelInput)0;  \tuint id = input.VertexID;  \tfloat x = -1, y = -1; \tx = (id == 2) ? 3.0 : -1.0; \ty = (id == 1) ? 3.0 : -1.0;  \toutput.Position = float4(x, y, 1.0, 1.0); \treturn output; }<\/code><\/pre>\n<h3>3. \u0420\u0435\u043d\u0434\u0435\u0440 \u0431\u0435\u0437 \u043f\u0438\u043a\u0441\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0448\u0435\u0439\u0434\u0435\u0440\u0430<\/h3>\n<p>  \u0415\u0449\u0435 \u043e\u0434\u043d\u043e\u0439 \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0435\u043d\u0434\u0435\u0440 \u0431\u0435\u0437 \u043f\u0438\u043a\u0441\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0448\u0435\u0439\u0434\u0435\u0440\u0430. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0437\u0430\u043c\u0435\u0442\u043d\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u043d\u0430 \u0440\u0435\u043d\u0434\u0435\u0440 \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u0438 \u043f\u0440\u0435\u043f\u0430\u0441\u0435 \u0433\u043b\u0443\u0431\u0438\u043d\u044b, \u0438\u043b\u0438 \u043f\u0440\u0438 \u0440\u0435\u043d\u0434\u0435\u0440\u0435 \u0442\u0435\u043d\u0435\u0439. \u041c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0435 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u043f\u0438\u043a\u0441\u0435\u043b\u044c\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u0432 \u043d\u0430\u0448 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d:  <\/p>\n<pre><code class=\"cpp\">pass GS_PSSM {     SetVertexShader(CompileShader(vs_5_0, ShadowMapVS()));     SetGeometryShader(CompileShader(gs_5_0, ShadowMapGS()));     SetPixelShader(NULL);      SetBlendState(NoBlending, float4(0.0f, 0.0f, 0.0f, 0.0f), 0xFFFFFFFF);     SetDepthStencilState(EnableDepth, 0); }<\/code><\/pre>\n<p>  \u0418\u043b\u0438 \u0436\u0435:  <\/p>\n<pre><code class=\"cpp\">device.ImmediateContext.PixelShader.Set(null);<\/code><\/pre>\n<p>  \u0412 \u043e\u0431\u043e\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u043f\u0438\u043a\u0441\u0435\u043b\u044c\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d, \u0438 \u0432 \u0440\u0435\u043d\u0434\u0435\u0440 \u0442\u0430\u0440\u0433\u0435\u0442 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u0430 \u0438\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0432 \u0432\u0435\u0440\u0442\u0435\u043a\u0441\u043d\u043e\u043c \u0448\u0435\u0439\u0434\u0435\u0440\u0435 \u0433\u043b\u0443\u0431\u0438\u043d\u0430.<br \/>  \u041c\u043e\u0436\u043d\u043e \u043f\u043e\u0439\u0442\u0438 \u0434\u0430\u043b\u044c\u0448\u0435, \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u0438\u043a\u0441\u0435\u043b\u044c\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0438 \u0447\u0435\u0433\u043e \u043d\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442:  <\/p>\n<pre><code class=\"cpp\">void ZPrepasPS(PixelInputZPrePass input) {     float4 albedo = AlbedoMap.Sample(Aniso, input.UV.xy);     if (albedo.w &lt; AlphaTest.x)         discard; }<\/code><\/pre>\n<p>  \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0430\u043b\u044c\u0444\u0430\u0442\u0435\u0441\u0442. \u0418 \u0435\u0441\u043b\u0438 \u043e\u043d \u043d\u0435 \u043f\u0440\u043e\u0439\u0434\u0435\u043d, \u0442\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u044c \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0431\u0440\u043e\u0448\u0435\u043d \u0438\u0437 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u0430. \u0415\u0441\u043b\u0438 \u0436\u0435 \u0432\u0441\u0435 \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435, \u0442\u043e, \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c\u0443 \u0441\u043b\u0443\u0447\u0430\u044e, \u0432 \u0440\u0435\u043d\u0434\u0435\u0440\u0442\u0430\u0440\u0433\u0435\u0442 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u0430 \u0438\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0432\u0435\u0440\u0442\u0435\u043a\u0441\u043d\u044b\u043c \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u043c \u0433\u043b\u0443\u0431\u0438\u043d\u0430.<\/p>\n<h3>4. Alpha to coverage<\/h3>\n<p>  \u0412 DX10\/11 \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0430\u043f\u043f\u0430\u0440\u0430\u0442\u043d\u043e, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e MSAA, \u0441\u0433\u043b\u0430\u0436\u0438\u0432\u0430\u0442\u044c \u0430\u043b\u044c\u0444\u0430\u0442\u0435\u0441\u0442. \u0415\u0441\u043b\u0438 \u043f\u0440\u043e\u0441\u0442\u044b\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438, \u0442\u043e \u044d\u0442\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432 \u043f\u0438\u043a\u0441\u0435\u043b\u044c\u043d\u043e\u043c \u0448\u0435\u0439\u0434\u0435\u0440\u0435 \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0435\u043c\u043f\u043b\u043e\u0432 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u044f MSAA \u0440\u0435\u043d\u0434\u0435\u0440\u0442\u0430\u0440\u0433\u0435\u0442\u0430 \u043f\u0440\u043e\u0448\u043b\u0438 \u0442\u0435\u0441\u0442.<\/p>\n<pre><code class=\"cpp\">static const float2 MSAAOffsets8[8] = {     float2(0.0625, -0.1875), float2(-0.0625, 0.1875),     float2(0.3125, 0.0625), float2(-0.1875, -0.3125),     float2(-0.3125, 0.3125), float2(-0.4375, -0.0625),     float2(0.1875, 0.4375), float2(0.4375, -0.4375) };  void ZPrepasPSMS8(PixelInputZPrePass input, out uint coverage : SV_Coverage) {     coverage = 0;      [branch]     if (AlphaTest.x &lt;= 1 \/ 255.0)         coverage = 255;     else     {         float2 tc_ddx = ddx(input.UV.xy);         float2 tc_ddy = ddy(input.UV.xy);          [unroll]         for (int i = 0; i &lt; 8; i++)         {             float2 texelOffset = MSAAOffsets8[i].x * tc_ddx + v2MSAAOffsets8[i].y * tc_ddy;             float temp = AlbedoMap.Sample(Aniso, input.UV.xy + texelOffset).w;              if (temp &gt;= 0.5)                 coverage |= 1 &lt;&lt; i;         }     } }<\/code><\/pre>\n<p>  \u0423 \u043c\u0435\u043d\u044f \u0443\u0447\u0435\u0442 \u0430\u043b\u044c\u0444\u0430\u0442\u0435\u0441\u0442\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u0441\u0442\u0430\u0434\u0438\u0438 Z-\u043f\u0440\u0435\u043f\u0430\u0441\u0430. \u041f\u043e\u0441\u043b\u0435 \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0445\u043e\u0434\u0430 \u043d\u0430\u043c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0440\u0435\u0437\u043e\u043b\u0432 MSAA \u0431\u0443\u0444\u0435\u0440\u0430 \u0438 \u043d\u0430\u0448 \u0430\u043b\u044c\u0444\u0430\u0442\u0435\u0441\u0442 \u0441\u0433\u043b\u0430\u0434\u0438\u0442\u0441\u044f \u043f\u043e\u0434\u043e\u0431\u043d\u043e \u043e\u0431\u044b\u0447\u043d\u043e\u0439 \u0433\u0435\u043e\u043c\u0435\u0442\u0440\u0438\u0438 (\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u0437\u043e\u043b\u0432 HDR MSAA \u0431\u0443\u0444\u0435\u0440\u0430 \u0442\u0435\u043c\u0430 \u0434\u043b\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438).  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0421\u0440\u0430\u0432\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u043a\u0440\u0438\u043d\u044b<\/b><\/p>\n<div class=\"spoiler_text\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/010\/807\/ca1\/010807ca11d24bc3b683cbcbd1e9b0a6.png\"\/><br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/b5f\/c14\/e39\/b5fc14e3941a496a8e92792c13731daf.png\"\/>  <\/div>\n<\/div>\n<h3>5. \u042d\u043a\u0440\u0430\u043d\u043d\u044b\u0439 \u0430\u043d\u0442\u0438\u0430\u043b\u044c\u044f\u0441\u0438\u043d\u0433 \u043d\u043e\u0440\u043c\u0430\u043b\u0435\u0439<\/h3>\n<p>  \u0414\u0430\u043d\u043d\u0430\u044f \u0438\u0434\u0435\u044f \u043c\u043d\u0435 \u043f\u0440\u0438\u0448\u043b\u0430 \u043f\u043e\u0441\u043b\u0435 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044f \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u043f\u0443\u043d\u043a\u0442\u0430. \u042f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e \u0441\u0443\u043f\u0435\u0440\u0441\u043a\u043c\u043f\u043b\u0438\u043d\u0433 \u0438\u0437 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b \u043d\u043e\u0440\u043c\u0430\u043b\u0438 \u0441\u043e \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435\u043c UV, \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u043c \u0432 \u0441\u043a\u0440\u0438\u043d\u0441\u043f\u0435\u0439\u0441\u0435. \u0422\u0430\u043a \u043a\u0430\u043a \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u043f\u043e\u0434\u0445\u043e\u0434 Forward+ c Z-\u043f\u0440\u0435\u043f\u0430\u0441\u043e\u043c, \u0442\u043e \u0442\u0430\u043a\u0430\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u0441\u0442\u043e\u0438\u0442 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e.  <\/p>\n<pre><code class=\"cpp\">static const float2 MSAAOffsets4[4] = {     float2(-0.125, -0.375), float2(0.375, -0.125),     float2(-0.375, 0.125), float2(0.125, 0.375) };  float3 ONormal = float3(0,0,0); float2 tc_ddx = ddx(input.UV.xy); float2 tc_ddy = ddy(input.UV.xy); [unroll] for (int i = 0; i &lt; 4; i++) {     float2 texelOffset = MSAAOffsets4[i].x * tc_ddx + MSAAOffsets4[i].y * tc_ddy;     float4 temp = NormalMap.Sample(Aniso, input.UV.xy + texelOffset*1.5);     ONormal += temp.ywy; } ONormal *= 0.25; Normal = ONormal * 2.0f - 1.0f;<\/code><\/pre>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0421\u0440\u0430\u0432\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u043a\u0440\u0438\u043d\u044b<\/b><\/p>\n<div class=\"spoiler_text\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/bce\/21f\/b43\/bce21fb4341a4408b99025f2a2bbe7d3.png\"\/><br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/c82\/006\/8c7\/c820068c7e9d4ffe96c0ad2f418444e4.png\"\/>  <\/div>\n<\/div>\n<h3>6. \u041d\u043e\u0440\u043c\u0430\u043b\u0438 \u0434\u0432\u0443\u0445\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u0439 \u0433\u0435\u043e\u043c\u0435\u0442\u0440\u0438\u0438<\/h3>\n<p>  \u0427\u0442\u043e \u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432 \u043e\u0441\u0432\u0435\u0449\u0435\u043d\u0438\u044f, \u0434\u043b\u044f \u0434\u0430\u0431\u043b\u0441\u0430\u0439\u0434 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432 \u043d\u0443\u0436\u043d\u043e \u0438\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u043e\u0440\u043c\u0430\u043b\u044c, \u0435\u0441\u043b\u0438 \u043c\u044b \u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043e\u0431\u0440\u0430\u0442\u043d\u0443\u044e \u0438\u0445 \u0441\u0442\u043e\u0440\u043e\u043d\u0443:  <\/p>\n<pre><code class=\"cpp\">float3 FinalPS(PixelInput input, bool isFrontFace : SV_IsFrontFace) : SV_Target {     input.Normal *= (1 - isFrontFace * 2);     ...<\/code><\/pre>\n<h3>7. \u0423\u0437\u043d\u0430\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b \u0432 \u0448\u0435\u0439\u0434\u0435\u0440\u0435<\/h3>\n<p>  \u0421\u0430\u043c \u0442\u0430\u043a\u043e\u0439 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u0435 \u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0441\u044c, \u0442\u0430\u043a \u043a\u0430\u043a \u0435\u0441\u0442\u044c \u0441\u043e\u043c\u043d\u0435\u043d\u0438\u044f \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0435\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u043e\u0434\u043d\u0430\u043a\u043e \u043a\u043e\u043c\u0443-\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c:  <\/p>\n<pre><code class=\"cpp\">Texture2D texture;  uint width, height; texture.GetDimensions(width, height);<\/code><\/pre>\n<h3>8. \u0421\u043f\u0440\u0430\u0439\u0442\u044b \u0433\u0435\u043e\u043c\u0435\u0442\u0440\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438 \u0448\u0435\u0439\u0434\u0435\u0440\u0430\u043c\u0438<\/h3>\n<p>  \u0421 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0433\u0435\u043e\u043c\u0435\u0442\u0440\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432 \u0441\u0442\u0430\u043b\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u0440\u0435\u043d\u0434\u0435\u0440 \u0441\u043f\u0440\u0430\u0439\u0442\u043e\u0432. \u0412 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u0443 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0435\u0434\u0438\u043d\u0438\u0447\u043d\u044b\u0435 \u0432\u0435\u0440\u0442\u0435\u043a\u0441\u044b, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0435 \u0432\u0441\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0441\u043f\u0440\u0430\u0439\u0442\u0435. \u0412 \u0433\u0435\u043e\u043c\u0435\u0442\u0440\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u0448\u0435\u0439\u0434\u0435\u0440\u0435 \u0438\u0437 \u043d\u0438\u0445 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 \u0441\u043f\u0440\u0430\u0439\u0442:  <\/p>\n<pre><code class=\"cpp\">struct VS_IN {     float4 Position : POSITION;     float4 UV       : TEXCOORD0;     float4 Rotation : TEXCOORD1;     float4 Color    : TEXCOORD2; };  struct VS_OUT {     float4 Position : SV_POSITION;     float4 UV       : TEXCOORD0;     float4 Rotation : TEXCOORD1;     float4 Color    : TEXCOORD2; };  struct GS_OUT {     float4 Position : SV_POSITION;     float2 TexCoord\t: TEXCOORD0;     float4 Color    : TEXCOORD1; }  VS_OUT GSSprite_VS( VS_IN Input ) {     VS_OUT Output;          float2 center = (Input.Position.xy + Input.Position.zw) * 0.5;     float2 size = (Input.Position.zw - center)*2.0;      Output.Position = float4(center, size);     Output.UV = Input.UV;     Output.Color = Input.Color;     Output.Rotation = Input.Rotation;      return Output; }  [maxvertexcount(6)]   void GSSprite_GS(point VS_OUT In[1], inout TriangleStream&lt;GS_OUT&gt; triStream) {     GS_OUT p0 = (GS_OUT) 0;     GS_OUT p1 = (GS_OUT) 0;     GS_OUT p2 = (GS_OUT) 0;     GS_OUT p3 = (GS_OUT) 0;      In[0].Position.xy = In[0].Position.xy * Resolution.zw * 2.0 - 1.0;     In[0].Position.y = -In[0].Position.y;      float2 r = float2(In[0].Rotation.x, -In[0].Rotation.y);     float2 t = float2(In[0].Rotation.y, In[0].Rotation.x);      p0.Position = float4(In[0].Position.xy + (-In[0].Position.z * r + In[0].Position.w * t) * Resolution.zw, 0.5, 1.0);     p0.TexCoord = In[0].UV.xy;     p0.Color = In[0].Color;      p1.Position = float4(In[0].Position.xy + (In[0].Position.z * r + In[0].Position.w * t) * Resolution.zw, 0.5, 1.0);     p1.TexCoord = In[0].UV.zy;     p1.Color = In[0].Color;      p2.Position = float4(In[0].Position.xy + (In[0].Position.z * r - In[0].Position.w * t) * Resolution.zw, 0.5, 1.0);     p2.TexCoord = In[0].UV.zw;     p2.Color = In[0].Color;      p3.Position = float4(In[0].Position.xy + (-In[0].Position.z * r - In[0].Position.w * t) * Resolution.zw, 0.5, 1.0);     p3.TexCoord = In[0].UV.xw;     p3.Color = In[0].Color;      triStream.Append(p0);     triStream.Append(p1);     triStream.Append(p2);     triStream.RestartStrip();      triStream.Append(p0);     triStream.Append(p2);     triStream.Append(p3);     triStream.RestartStrip(); }<\/code><\/pre>\n<p>  \u041f\u043e \u043c\u043e\u0438\u043c \u0437\u0430\u043c\u0435\u0440\u0430\u043c \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0434\u0430\u0435\u0442 \u043f\u043e\u0440\u044f\u0434\u043a\u0430 20-30% \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u044f \u043a\u0430\u043a \u043d\u0430 \u0441\u043b\u0430\u0431\u043e\u043c, \u0442\u0430\u043a \u0438 \u043c\u043e\u0449\u043d\u043e\u043c \u0436\u0435\u043b\u0435\u0437\u0435.<\/p>\n<h3>9. Lens Flare<\/h3>\n<p>  \u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0434\u043b\u044f \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f \u043b\u0438\u043d\u0437\u043e\u0432\u044b\u0445 \u044d\u0444\u0444\u0435\u043a\u0442\u043e\u0432. \u0422\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u044f \u043f\u0440\u043e\u0432\u043e\u0436\u0443 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u0435\u0440\u0435\u0434 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0441\u043f\u0440\u0430\u0439\u0442\u0430. \u0421\u043f\u0435\u0440\u0432\u0430 \u044f \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e \u043a\u0430\u043a \u0434\u0430\u043b\u0435\u043a\u043e \u044d\u0444\u0444\u0435\u043a\u0442 \u043e\u0442 \u043a\u0440\u0430\u0435\u0432 \u044d\u043a\u0440\u0430\u043d\u0430. \u041f\u043e\u0442\u043e\u043c \u0438\u0434\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u043f\u0440\u043e\u0446\u0435\u043d\u0442 \u043f\u0435\u0440\u0435\u043a\u0440\u044b\u0442\u0438\u044f \u044d\u0444\u0444\u0435\u043a\u0442\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u043f\u043e \u0431\u0443\u0444\u0435\u0440\u0443 \u0433\u043b\u0443\u0431\u0438\u043d\u044b. \u0415\u0441\u043b\u0438 \u043e\u0431\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043f\u0440\u043e\u0439\u0434\u0435\u043d\u044b, \u0442\u043e \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u0438\u0440\u0443\u044e \u0441\u043f\u0440\u0430\u0439\u0442:  <\/p>\n<pre><code class=\"cpp\">static const int2 offset[61] = { int2( 0, 0), int2( 1, 0), int2( 1,-1), int2( 0,-1), int2(-1,-1), int2(-1, 0), int2(-1, 1), int2( 0, 1), int2( 1, 1), int2( 2, 0), int2( 2,-1), int2( 2,-2), int2( 1,-2), int2( 0,-2), int2(-1, 2), int2(-2,-2), int2(-2,-1), int2(-2, 0), int2(-2, 1), int2(-2, 2), int2(-1, 2), int2( 0, 2), int2( 1, 2), int2( 2, 2), int2( 2, 1), int2( 3, 0), int2( 3,-1), int2( 1,-3), int2( 0,-3), int2(-1,-3), int2(-3,-1), int2(-3, 0), int2(-3, 1), int2(-1,-3), int2( 0, 3), int2( 1, 3), int2( 3, 1), int2( 4, 0), int2( 4,-1), int2( 3,-2), int2( 3,-3), int2(-2,-3), int2( 1,-4), int2( 0,-4), int2(-1,-4), int2(-2,-3), int2( 3,-3), int2(-3,-2), int2(-4,-1), int2(-4, 0), int2(-4, 1), int2(-3, 2), int2(-3, 3), int2(-2, 3), int2(-1, 4), int2( 0, 4), int2( 1, 4), int2( 2, 3), int2( 3, 3), int2( 3, 2), int2( 4, 1)};  [maxvertexcount(6)]   void GSSprite_GS(point VS_OUT In[1], inout TriangleStream&lt;GS_OUT&gt; triStream, uniform bool MSAA) {     LensFlareStruct LFS = LensFlares[In[0].VertexID];     float4 Position = mul(LFS.Direction, ViewProection);      float3 NPos = Position.xyz \/ Position.w;      float dist = NPos.x - -1;     dist = min(1 - NPos.x, dist) * ScrRes.z; \/\/Proportion     dist = min(NPos.y - -1, dist);     dist = min(1 - NPos.y, dist);     dist = min(NPos.z &lt; 0.9, dist);     dist = saturate(dist * 20);      if (dist &gt; 0)     {         float2 SPos = float2(NPos.x, -NPos.y) * 0.5 + 0.5;         int2 LPos = round(SPos * ScrRes.xy);         float v = 0;          if (MSAA)         {             for (int i = 0; i &lt; 61; i++)                  v += DepthTextureMS.Load(LPos + offset[i],  0) &lt; NPos.z;         }         else         {             for (int i = 0; i &lt; 61; i++)                 v += DepthTexture.Load(uint3(LPos + offset[i], 0)) &lt; NPos.z;         }          v = pow(v \/ 61.0, 2.0);         dist *= v;          if (dist &gt; 0)         {             float2 Size = LFS.Size.xy * float2(ScrRes.w, 1);              Quad(triStream, Position, LFS.UV, Size * saturate(dist + 0.1), LFS.Color.xyz * dist);         }     } }<\/code><\/pre>\n<h3>10. \u0420\u0435\u043d\u0434\u0435\u0440 PSSM \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0433\u0435\u043e\u043c\u0435\u0442\u0440\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432<\/h3>\n<p>  \u0415\u0449\u0435 \u043e\u0434\u043d\u0438\u043c \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u043c \u043c\u043e\u0436\u0435\u0442 \u0441\u043b\u0443\u0436\u0438\u0442\u044c \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f Parallel-Split Shadow Maps \u0433\u0435\u043e\u043c\u0435\u0442\u0440\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438 \u0448\u0435\u0439\u0434\u0435\u0440\u0430\u043c\u0438 \u0438\u0437 GPU Gems. \u0412 \u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0431\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0434\u0438\u043f \u043d\u0430 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432 \u043a\u0430\u0436\u0434\u044b\u0439 \u0441\u043f\u043b\u0438\u0442, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u0438\u043b\u0430\u043c\u0438 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u044b \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0433\u0435\u043e\u043c\u0435\u0442\u0440\u0438\u044e \u0438 \u043e\u0442\u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u044c \u0435\u0435 \u0432 \u0440\u0430\u0437\u043d\u044b\u0435 \u0440\u0435\u043d\u0434\u0435\u0440\u0442\u0430\u0440\u0433\u0435\u0442\u044b \u0437\u0430 \u043e\u0434\u0438\u043d \u0434\u0438\u043f:  <\/p>\n<pre><code class=\"cpp\">struct SHADOW_VS_OUT {     float4 pos : SV_POSITION;     float4 UV1 : TEXCOORD0;     nointerpolation uint instId  : SV_InstanceID; };  struct GS_OUT {     float4 pos : SV_POSITION;     float2 Texcoord : TEXCOORD0;     nointerpolation uint RTIndex : SV_RenderTargetArrayIndex; };  [maxvertexcount(SPLITCOUNT * 3)] void GS_RenderShadowMap(triangle SHADOW_VS_OUT In[3], inout TriangleStream&lt;GS_OUT&gt; triStream) {     \/\/ For each split to render     for (int split = IstanceData[In[0].instId].Start; split &lt;= IstanceData[In[0].instId].Stop; split++)     {         GS_OUT Out;         \/\/ Set render target index.           Out.RTIndex = split;         \/\/ For each vertex of triangle           [unroll(3)]         for (int vertex = 0; vertex &lt; 3; vertex++)         {             \/\/ Transform vertex with split-specific crop matrix.               Out.pos = mul(In[vertex].pos, cropMatrix[split]);              Out.Texcoord = In[vertex].UV1.xy;             \/\/ Append vertex to stream               triStream.Append(Out);         }         \/\/ Mark end of triangle           triStream.RestartStrip();     } }<\/code><\/pre>\n<h3>11. \u0418\u043d\u0441\u0442\u0430\u043d\u0441\u0438\u043d\u0433<\/h3>\n<p>  \u0421 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u043e\u043c \u043d\u0430 DX11 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u044c \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0438\u043d\u0433\u0430 \u0441\u0442\u0430\u043b\u043e \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u043f\u0440\u043e\u0449\u0435. \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a \u0432\u0435\u0440\u0442\u0435\u043a\u0441\u043e\u0432 \u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0430. \u041c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u043e\u0432 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e:  <\/p>\n<pre><code class=\"cpp\">device.ImmediateContext.DrawIndexedInstanced(IndicesCount, Meshes.Count, StartInd, 0, 0);<\/code><\/pre>\n<p>  \u0410 \u0437\u0430\u0442\u0435\u043c \u0432 \u0448\u0435\u0439\u0434\u0435\u0440\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0430 \u0435\u0433\u043e \u0438\u043d\u0434\u0435\u043a\u0441 \u0438 \u0443\u0436\u0435 \u043f\u043e \u043d\u0435\u043c\u0443 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0443\u044e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e:  <\/p>\n<pre><code class=\"cpp\">struct PerInstanceData {     float4x4 WVP;     float4x4 World;     int Start;     int Stop;     int2 Padding; };  StructuredBuffer&lt;PerInstanceData&gt; IstanceData : register(t16);  PixelInput DefaultVS(VertexInput input, uint id : SV_InstanceID) {     PixelInput output = (PixelInput) 0;     output.Position = mul(float4(input.Position.xyz, 1), IstanceData[id].WVP);     output.UV.xy = input.UV;     output.WorldPos = mul(float4(input.Position, 1), IstanceData[id].World).xyz;     ...<\/code><\/pre>\n<h3>12. \u041a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 2D UV \u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0432 \u0432\u0435\u043a\u0442\u043e\u0440 \u0434\u043b\u044f \u043a\u0443\u0431\u043c\u0430\u043f\u044b<\/h3>\n<p>  \u0411\u044b\u0432\u0430\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u043a\u0443\u0431\u043c\u0430\u043f\u0430\u043c\u0438.  <\/p>\n<pre><code class=\"cpp\">static const float3 offsetV[6] = { float3(1,1,1),  float3(-1,1,-1), float3(-1,1,-1),\tfloat3(-1,-1,1), float3(-1,1,1), float3(1,1,-1) }; static const float3 offsetX[6] = { float3(0,0,-2), float3(0,0,2),   float3(2,0,0),\t\tfloat3(2,0,0),   float3(2,0,0),  float3(-2,0,0) }; static const float3 offsetY[6] = { float3(0,-2,0), float3(0,-2,0),  float3(0,0,2),\t\tfloat3(0,0,-2),  float3(0,-2,0), float3(0,-2,0) };  float3 ConvertUV(float2 UV, int FaceIndex) { \tfloat3 outV = offsetV[FaceIndex] + offsetX[FaceIndex] * UV.x + offsetY[FaceIndex] * UV.y; \treturn normalize(outV); }<\/code><\/pre>\n<h3>13. \u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430 \u0413\u0430\u0443\u0441\u0441a<\/h3>\n<p>  \u0418 \u043d\u0430 \u0437\u0430\u043a\u0443\u0441\u043a\u0443 \u2014 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0413\u0430\u0443\u0441\u0441a. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0430\u043f\u043f\u0430\u0440\u0430\u0442\u043d\u0443\u044e \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044e \u2014 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c \u0432\u044b\u0431\u043e\u0440\u043a\u0443 \u0434\u0432\u0443\u0445 \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u0445 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439, \u0441 \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u043d\u043d\u044b\u043c \u0441\u0434\u0432\u0438\u0433\u043e\u043c \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438. \u0422\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u044b\u0431\u043e\u0440\u043e\u043a.<\/p>\n<pre><code class=\"cpp\">static const float Shift[4] = {0.4861161486, 0.4309984373, 0.3775380497, 0.3269038909 }; static const float Mult[4] = {0.194624, 0.189416, 0.088897, 0.027063 };   float3 GetGauss15(Texture2D&lt;float3&gt; Tex, float2 UV, float2 dx)  {     float3 rez = 0;     for (int i = 1; i &lt; 4; i++)         rez += (Tex.Sample(LinSampler, UV + (Shift[i] + i*2)*dx ).xyz + Tex.Sample(LinSampler, UV - (Shift[i] + i*2)*dx).xyz) * Mult[i];      rez += Tex.Sample( LinSampler, UV ).xyz * 0.134598;     rez += (Tex.Sample( LinSampler, UV + dx ).xyz + Tex.Sample( LinSampler, UV - dx ).xyz )* 0.127325;      return rez; }<\/code><\/pre>\n<p>  \u0412\u043e\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0438 \u0432\u0441\u044f \u0447\u0451\u0440\u0442\u043e\u0432\u0430 \u0434\u044e\u0436\u0438\u043d\u0430, \u043d\u0430\u0434\u0435\u044e\u0441\u044c \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043a\u043e\u043c\u0443-\u0442\u043e \u043f\u043e\u043b\u0435\u0437\u0435\u043d.<br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habrahabr.ru\/post\/325016\/\"> https:\/\/habrahabr.ru\/post\/325016\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440!<br \/>  \u0420\u0435\u0448\u0438\u043b \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e-\u0437\u0430\u043c\u0435\u0442\u043a\u0443 \u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0442\u0440\u044e\u043a\u0430\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0432 \u0441\u0432\u043e\u0435\u043c \u0441\u043a\u0440\u043e\u043c\u043d\u043e\u043c \u0434\u0432\u0438\u0436\u043a\u0435. \u042d\u0442\u043e \u0441\u043a\u043e\u0440\u0435\u0435 \u0437\u0430\u043c\u0435\u0442\u043a\u0430 \u0441\u0430\u043c\u043e\u043c\u0443-\u0441\u0435\u0431\u0435, \u0438 \u043c\u0430\u0442\u0451\u0440\u044b\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u044b \u043b\u0438\u0448\u044c \u0443\u0441\u043c\u0435\u0445\u043d\u0443\u0442\u0441\u044f, \u043d\u043e, \u0434\u0443\u043c\u0430\u044e, \u043d\u043e\u0432\u0438\u0447\u043a\u0430\u043c \u043e\u043d\u0430 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f.  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-284035","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/284035","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=284035"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/284035\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=284035"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=284035"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=284035"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}