{"id":5111,"date":"2016-07-17T05:54:00","date_gmt":"2016-07-17T05:54:00","guid":{"rendered":"http:\/\/anthroponaute.fr\/blog-informatique\/?p=5111"},"modified":"2016-08-20T14:56:14","modified_gmt":"2016-08-20T14:56:14","slug":"lanticrenelage-fxaa-shader-de-post-traitement","status":"publish","type":"post","link":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/?p=5111","title":{"rendered":"L\u2019anticr\u00e9nelage FXAA &#8211; Shader de Post-Traitement"},"content":{"rendered":"<p><a href=\"https:\/\/anthropoya.cluster014.ovh.net\/blog-informatique\/wp-content\/uploads\/2016\/07\/image.png.jpg\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone  wp-image-5113\" src=\"https:\/\/anthropoya.cluster014.ovh.net\/blog-informatique\/wp-content\/uploads\/2016\/07\/image.png.jpg\" alt=\"image.png\" width=\"545\" height=\"273\" srcset=\"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/wp-content\/uploads\/2016\/07\/image.png.jpg 2100w, https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/wp-content\/uploads\/2016\/07\/image.png-300x150.jpg 300w, https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/wp-content\/uploads\/2016\/07\/image.png-1024x512.jpg 1024w, https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/wp-content\/uploads\/2016\/07\/image.png-624x312.jpg 624w\" sizes=\"(max-width: 545px) 100vw, 545px\" \/><\/a><\/p>\n<p><strong>Intro: <\/strong><\/p>\n<p>Une image num\u00e9rique est compos\u00e9e de pixels. Lorsqu&rsquo;elle est redimensionn\u00e9e, le bord des formes ayant un angle particulier prend la forme d&rsquo;escalier : c&rsquo;est le <strong>cr\u00e9nelage<\/strong>, ou <strong>aliasing<\/strong>.<\/p>\n<p><strong>Explication : <\/strong><\/p>\n<p>Voici une technique tr\u00e8s efficace et tr\u00e8s performante en ressource syst\u00e8me afin d&rsquo;effectuer du rendu anti-cr\u00e9nelage. Elle utilise une <strong>render target<\/strong> et un <strong>Quad<\/strong> de post-traitement.<\/p>\n<p>Voici le fichier ShaderTechique_Declarations.h :<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\/\/------------------------------------------------------\r\n\/\/ FXAA shader\r\n\/\/------------------------------------------------------\r\nclass ShaderTechnique_FXAA : public ShaderTechnique\r\n{\r\npublic:\r\n\u00a0\u00a0 \u00a0ShaderTechnique_FXAA();\r\n\u00a0\u00a0 \u00a0virtual ~ShaderTechnique_FXAA();\r\n\r\n\u00a0\u00a0 \u00a0virtual bool Initialize() override;\r\n\r\n\u00a0\u00a0 \u00a0virtual void SetupShaderVariables();\r\n\r\n\u00a0\u00a0 \u00a0virtual void Update(float fTimeSinceLastFrame);\r\n\r\n\u00a0\u00a0 \u00a0void SetRenderTarget(RenderTarget* pRT);\r\n\r\n\u00a0\u00a0 \u00a0void SetEnabled(bool bEnabled);\r\n\u00a0\u00a0 \u00a0bool GetEnabled();\r\n\r\nprivate:\r\n\u00a0\u00a0 \u00a0D3DXMATRIX m_WorldMatrix;\r\n\u00a0\u00a0 \u00a0D3DXMATRIX m_ViewMatrix;\r\n\u00a0\u00a0 \u00a0D3DXMATRIX m_OrthoMatrix;\r\n\r\n\u00a0\u00a0 \u00a0bool m_bEnabled;\r\n};\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Voici le fichier ShaderTechnique_FXAA.cpp :<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n#include &quot;ShaderTechnique_Declarations.h&quot;\r\n#include &quot;Defines.h&quot;\r\n#include &quot;D3D10Renderer.h&quot;\r\n\r\nShaderTechnique_FXAA::ShaderTechnique_FXAA() :\r\nShaderTechnique(&quot;FXAA.fx&quot;, &quot;Render&quot;, VertexLayoutType::PT_VERTEX),\r\nm_bEnabled(true)\r\n{\r\n}\r\n\r\nShaderTechnique_FXAA::~ShaderTechnique_FXAA()\r\n{\r\n}\r\n\r\nbool ShaderTechnique_FXAA::Initialize()\r\n{\r\n\u00a0\u00a0 \u00a0if (ShaderTechnique::Initialize() == false)\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0return false;\r\n\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0SetupShaderVariables();\r\n\r\n\u00a0\u00a0 \u00a0return true;\r\n}\r\n\r\nvoid ShaderTechnique_FXAA::SetRenderTarget(RenderTarget* pRT)\r\n{\r\n\u00a0\u00a0 \u00a0SetTextureRV(&quot;TextureDiffuse&quot;, pRT-&gt;GetShaderResourceView());\r\n}\r\n\r\nvoid ShaderTechnique_FXAA::SetupShaderVariables()\r\n{\r\n\u00a0\u00a0 \u00a0RegisterMatrixVariable(&quot;World&quot;, ShaderVariableType::WORLD);\r\n\u00a0\u00a0 \u00a0RegisterMatrixVariable(&quot;View&quot;, ShaderVariableType::VIEW);\r\n\u00a0\u00a0 \u00a0RegisterMatrixVariable(&quot;Projection&quot;, ShaderVariableType::PROJECTION);\r\n\u00a0\u00a0 \u00a0RegisterTextureVariable(&quot;TextureDiffuse&quot;, ShaderVariableType::ANY);\r\n\u00a0\u00a0 \u00a0RegisterVectorVariable(&quot;FrameBufferSize&quot;, ShaderVariableType::ANY);\r\n\u00a0\u00a0 \u00a0RegisterVectorVariable(&quot;Color&quot;, ShaderVariableType::ANY);\r\n\u00a0\u00a0 \u00a0RegisterScalarVariable(&quot;Enabled&quot;, ShaderVariableType::ANY);\r\n\r\n\u00a0\u00a0 \u00a0D3DXMatrixIdentity(&amp;m_WorldMatrix);\r\n\u00a0\u00a0 \u00a0D3DXMatrixIdentity(&amp;m_ViewMatrix);\r\n\u00a0\u00a0 \u00a0D3DXMatrixIdentity(&amp;m_OrthoMatrix);\r\n\r\n\u00a0\u00a0 \u00a0D3DXVECTOR3 Eye(0.0f, 0.0f, 1.0f);\r\n\u00a0\u00a0 \u00a0D3DXVECTOR3 At(0.0f, 0.0f, 0.0f);\r\n\u00a0\u00a0 \u00a0D3DXVECTOR3 Up(0.0f, 1.0f, 0.0f);\r\n\r\n\u00a0\u00a0 \u00a0D3DXMatrixLookAtLH(&amp;m_ViewMatrix, &amp;Eye, &amp;At, &amp;Up);\r\n\r\n\u00a0\u00a0 \u00a0float fViewportWidth = (float)D3D10_RENDERER-&gt;GetViewportWidth();\r\n\u00a0\u00a0 \u00a0float fViewportHeigth = (float)D3D10_RENDERER-&gt;GetViewportHeight();\r\n\r\n\u00a0\u00a0 \u00a0D3DXMatrixOrthoLH(&amp;m_OrthoMatrix, fViewportWidth, fViewportHeigth, 0.01f, 20.0f);\r\n\r\n\u00a0\u00a0 \u00a0SetVector(&quot;FrameBufferSize&quot;, D3DXVECTOR2(fViewportWidth, fViewportHeigth));\r\n}\r\n\r\nvoid ShaderTechnique_FXAA::Update(float fTimeSinceLastFrame)\r\n{\r\n\u00a0\u00a0 \u00a0SetMatrix(&quot;World&quot;, &amp;m_WorldMatrix);\r\n\u00a0\u00a0 \u00a0SetMatrix(&quot;View&quot;, &amp;m_ViewMatrix);\r\n\u00a0\u00a0 \u00a0SetMatrix(&quot;Projection&quot;, &amp;m_OrthoMatrix);\r\n\r\n\u00a0\u00a0 \u00a0SetAutoMatrix(ShaderVariableType::ANY);\r\n}\r\n\r\nvoid ShaderTechnique_FXAA::SetEnabled(bool bEnabled)\r\n{\r\n\u00a0\u00a0 \u00a0SetScalar(&quot;Enabled&quot;, bEnabled);\r\n\u00a0\u00a0 \u00a0m_bEnabled = bEnabled;\r\n}\r\n\r\nbool ShaderTechnique_FXAA::GetEnabled()\r\n{\r\n\u00a0\u00a0 \u00a0return m_bEnabled;\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Voici les bouts de code pour initialiser le shader FXAA :<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\r\nbool D3D10Renderer::Initialize(bool bFullscreen)\r\n{\r\n\u00a0\u00a0 \u00a0[...]\r\n\u00a0\u00a0 \u00a0m_pQuad = new TextureScreenQuad();\r\n\u00a0\u00a0 \u00a0m_pQuad-&gt;Initialize();\r\n\u00a0\u00a0 \u00a0m_pQuad-&gt;SetShaderTechnique( SHADER_MANAGER-&gt;GetShader(&quot;FXAA&quot;) );\r\n\u00a0\u00a0 \u00a0[...]\r\n}\r\n\r\nvoid D3D10Renderer::Render()\r\n{\r\n\u00a0\u00a0 \u00a0[...]\r\n\u00a0\u00a0 \u00a0\/\/ Efface la surface de rendu\r\n\u00a0\u00a0 \u00a0m_pd3dDevice-&gt;ClearDepthStencilView(m_pDepthStencilView, D3D10_CLEAR_DEPTH, 1.0f, 0 );\r\n\u00a0\u00a0 \u00a0m_pd3dDevice-&gt;ClearRenderTargetView(m_pRenderTargetView, afClearColor);\r\n\r\n\u00a0\u00a0 \u00a0SCENE_MANAGER-&gt;DrawAll(fTimeSinceLastFrame);\r\n\r\n\u00a0\u00a0 \u00a0DrawTextInfo();\r\n\r\n\u00a0\u00a0 \u00a0RenderToTexture(fTimeSinceLastFrame);\r\n\r\n\u00a0\u00a0 \u00a0UpdateWindowTitle();\r\n\r\n\u00a0\u00a0 \u00a0m_pQuad-&gt;OnRender(fTimeSinceLastFrame);\r\n\r\n\u00a0\u00a0 \u00a0m_pSwapChain-&gt;Present(0, 0);\r\n\u00a0\u00a0 \u00a0[...]\r\n}\r\n\r\nvoid D3D10Renderer::RenderToTexture(float fTimeSinceLastFrame)\r\n{\r\n\u00a0\u00a0 \u00a0\/\/ Set the render target to be the render to texture.\r\n\u00a0\u00a0 \u00a0m_pQuad-&gt;GetRT()-&gt;SetRenderTarget(m_pDepthStencilView);\r\n\r\n\u00a0\u00a0 \u00a0\/\/ Clear the render to texture.\r\n\u00a0\u00a0 \u00a0m_pQuad-&gt;GetRT()-&gt;ClearRenderTarget(m_pDepthStencilView);\r\n\r\n\u00a0\u00a0 \u00a0\/\/ Render the scene now and it will draw to the render to texture instead of the back buffer.\r\n\u00a0\u00a0 \u00a0SCENE_MANAGER-&gt;DrawAll(fTimeSinceLastFrame);\r\n\r\n\u00a0\u00a0 \u00a0\/\/ Reset the render target back to the original back buffer and not the render to texture anymore.\r\n\u00a0\u00a0 \u00a0m_pd3dDevice-&gt;OMSetRenderTargets(1, &amp;m_pRenderTargetView, m_pDepthStencilView);\r\n}\r\n\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Voici le fichier shader .fx :<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nSamplerState SamplerLinear\r\n{\r\n\u00a0\u00a0 \u00a0Filter = ANISOTROPIC;\r\n\u00a0\u00a0\u00a0 AddressU = Wrap;\r\n\u00a0\u00a0\u00a0 AddressV = Wrap;\r\n\u00a0\u00a0 \u00a0MaxAnisotropy = 1;\r\n};\r\n\r\nmatrix World;\r\nmatrix View;\r\nmatrix Projection;\r\n\r\nTexture2D TextureDiffuse;\r\n\r\nfloat2 FrameBufferSize;\r\n\r\nfloat4 Color;\r\n\r\nbool Enabled;\r\n\r\nstruct VS_INPUT\r\n{\r\n\u00a0\u00a0\u00a0 float4 Pos : POSITION;\r\n\u00a0\u00a0\u00a0 float2 Tex : TEXCOORD;\r\n};\r\n\u00a0\r\nstruct PS_INPUT\r\n{\r\n\u00a0\u00a0\u00a0 float4 Pos : SV_POSITION;\r\n\u00a0\u00a0\u00a0 float2 Tex : TEXCOORD0;\r\n};\r\n\r\nPS_INPUT VS(VS_INPUT input)\r\n{\r\n\u00a0\u00a0\u00a0 PS_INPUT output = (PS_INPUT)0;\r\n\u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 output.Pos = mul(input.Pos, World);\r\n\u00a0\u00a0\u00a0 output.Pos = mul(output.Pos, View);\r\n\u00a0\u00a0\u00a0 output.Pos = mul(output.Pos, Projection);\r\n\u00a0\u00a0\u00a0 output.Tex = input.Tex;\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 return output;\r\n}\u00a0\u00a0 \u00a0\r\n\r\nstatic const float FXAA_SPAN_MAX = 4.0;\r\nstatic const float FXAA_REDUCE_MUL = 1.0\/8.0;\r\nstatic const float FXAA_REDUCE_MIN = 1.0\/128.0;\r\n\u00a0\u00a0 \u00a0\r\nfloat4 PS(PS_INPUT input) : SV_Target\r\n{\r\n\u00a0\u00a0 \u00a0input.Tex = 1.0f - input.Tex;\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0float3 rgbNW = TextureDiffuse.Sample(SamplerLinear, input.Tex + (float2(-1.0,-1.0) \/ FrameBufferSize)).xyz;\r\n\u00a0\u00a0 \u00a0float3 rgbNE = TextureDiffuse.Sample(SamplerLinear, input.Tex + (float2(1.0,-1.0) \/ FrameBufferSize)).xyz;\r\n\u00a0\u00a0 \u00a0float3 rgbSW = TextureDiffuse.Sample(SamplerLinear, input.Tex + (float2(-1.0,1.0) \/ FrameBufferSize)).xyz;\r\n\u00a0\u00a0 \u00a0float3 rgbSE = TextureDiffuse.Sample(SamplerLinear, input.Tex + (float2(1.0,1.0) \/ FrameBufferSize)).xyz;\r\n\u00a0\u00a0 \u00a0float3 rgbM\u00a0 = TextureDiffuse.Sample(SamplerLinear, input.Tex).xyz;\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0float3 luma = float3(0.299, 0.587, 0.114);\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0float lumaNW = dot(rgbNW, luma);\r\n\u00a0\u00a0 \u00a0float lumaNE = dot(rgbNE, luma);\r\n\u00a0\u00a0 \u00a0float lumaSW = dot(rgbSW, luma);\r\n\u00a0\u00a0 \u00a0float lumaSE = dot(rgbSE, luma);\r\n\u00a0\u00a0 \u00a0float lumaM\u00a0 = dot(rgbM, luma);\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));\r\n\u00a0\u00a0 \u00a0float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0float2 dir;\r\n\u00a0\u00a0 \u00a0dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));\r\n\u00a0\u00a0 \u00a0dir.y =\u00a0 ((lumaNW + lumaSW) - (lumaNE + lumaSE));\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0float dirReduce = max(\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0 (lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL),\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 FXAA_REDUCE_MIN);\r\n\u00a0\u00a0 \u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0float rcpDirMin = 1.0\/(min(abs(dir.x), abs(dir.y)) + dirReduce);\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0dir = min(float2( FXAA_SPAN_MAX,\u00a0 FXAA_SPAN_MAX),\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0 max(float2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0 dir * rcpDirMin)) \/ FrameBufferSize;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0float3 rgbA = (1.0\/2.0) * (\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0TextureDiffuse.Sample(SamplerLinear, input.Tex + dir * (1.0\/3.0 - 0.5)).xyz +\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0TextureDiffuse.Sample(SamplerLinear, input.Tex + dir * (2.0\/3.0 - 0.5)).xyz);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0float3 rgbB = rgbA * (1.0\/2.0) + (1.0\/4.0) * (\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0TextureDiffuse.Sample(SamplerLinear, input.Tex + dir * (0.0\/3.0 - 0.5)).xyz +\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0TextureDiffuse.Sample(SamplerLinear, input.Tex + dir * (3.0\/3.0 - 0.5)).xyz);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0float lumaB = dot(rgbB, luma);\r\n\r\n\u00a0\u00a0 \u00a0if (Enabled)\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if ((lumaB &lt; lumaMin) || (lumaB &gt; lumaMax))\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0return float4(rgbA, 1.0f) * Color;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0else\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0return float4(rgbB, 1.0f) * Color;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0else\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0return TextureDiffuse.Sample(SamplerLinear, input.Tex);\r\n\u00a0\u00a0 \u00a0}\r\n}\r\n\r\ntechnique10 Render\r\n{\r\n\u00a0\u00a0\u00a0 pass P0\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 SetVertexShader( CompileShader( vs_4_0, VS() ) );\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 SetGeometryShader( NULL );\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 SetPixelShader( CompileShader( ps_4_0, PS() ) );\r\n\u00a0\u00a0\u00a0 }\r\n}\r\n<\/pre>\n<p><strong>R\u00e9sum\u00e9 : <\/strong><\/p>\n<p>Nous avons pr\u00e9sent\u00e9 une technique FXAA par un fichier shader .fx afin d&rsquo;effectuer le rendu d&rsquo;anti-cr\u00e9n\u00e9lage.<\/p>\n<p><strong>R\u00e9f\u00e9rences :<\/strong><\/p>\n<p>&#8211;\u00a0 https:\/\/fr.wikipedia.org\/wiki\/Fast_approximate_anti-aliasing<\/p>\n<p>&#8211; http:\/\/horde3d.org\/wiki\/index.php5?title=Shading_Technique_-_FXAA<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Intro: Une image num\u00e9rique est compos\u00e9e de pixels. Lorsqu&rsquo;elle est redimensionn\u00e9e, le bord des formes ayant un angle particulier prend la forme d&rsquo;escalier : c&rsquo;est le cr\u00e9nelage, ou aliasing. Explication : Voici une technique tr\u00e8s efficace et tr\u00e8s performante en ressource syst\u00e8me afin d&rsquo;effectuer du rendu anti-cr\u00e9nelage. Elle utilise une render target et un Quad [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[23],"tags":[],"_links":{"self":[{"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/posts\/5111"}],"collection":[{"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=5111"}],"version-history":[{"count":20,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/posts\/5111\/revisions"}],"predecessor-version":[{"id":5402,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/posts\/5111\/revisions\/5402"}],"wp:attachment":[{"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5111"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5111"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5111"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}