[{"data":1,"prerenderedAt":761},["ShallowReactive",2],{"settings:minimal":3,"article:magical-reflections-a-webxr-experience-powered-by-nanogl":40,"article-position:magical-reflections-a-webxr-experience-powered-by-nanogl":760},{"offices":4,"business":19,"say_hi":33},[5,12],{"title":6,"address":7,"address_street_address":8,"address_postal_code":9,"address_locality":6,"address_address_region":10,"address_country":11,"telephone":10},"Paris","38 rue Legendre\n75017 Paris","38 rue Legendre","75017",null,"France",{"title":13,"address":14,"address_street_address":15,"address_postal_code":16,"address_locality":13,"address_address_region":17,"address_country":18,"telephone":10},"London","Becket House\n1 Lambeth Palace Road\nLondon\nSE1 7EU","Becket House\n1 Lambeth Palace Road","SE1 7EU","England","United Kingdom",[20,22,24,27,30],{"title":11,"email":21},"sales@makemepulse.com",{"title":18,"email":23},"uk@makemepulse.com",{"title":25,"email":26},"United States East Coast","eastcoast@makemepulse.com",{"title":28,"email":29},"United States Mid West","midwest@makemepulse.com",{"title":31,"email":32},"United States West Coast","westcoast@makemepulse.com",[34,37],{"title":35,"email":36},"Apply now","jobs@makemepulse.com",{"title":38,"email":39},"Contact","contact@makemepulse.com",{"uid":41,"first_publication_date":42,"last_publication_date":43,"cover_image":44,"title":101,"cta_link":106,"cta_label":111,"intro":112,"body":149,"categories":599,"date":10,"selected":614,"seo_title":104,"seo_description":747,"og_type":10,"og_image":748},"magical-reflections-a-webxr-experience-powered-by-nanogl","2022-01-20T09:58:29+0000","2024-02-20T11:47:27+0000",{"dimensions":45,"alt":10,"copyright":10,"url":48,"id":49,"edit":50,"desktop":54,"grid_mobile":62,"grid_small":70,"hover":78,"grid":85,"mobile":93},{"width":46,"height":47},1200,628,"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002Fbc4c20bc-eee6-422d-bd9d-c9d51c26acdf_magische-spiegelungen-technical-breakdown-cover.jpeg?auto=compress,format","YeF9EhAAAIAWImLe",{"x":51,"y":51,"zoom":52,"background":53},0,1,"#fff",{"dimensions":55,"alt":10,"copyright":10,"url":58,"id":49,"edit":59},{"width":56,"height":57},560,463,"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002Fbc4c20bc-eee6-422d-bd9d-c9d51c26acdf_magische-spiegelungen-technical-breakdown-cover.jpeg?auto=compress,format&rect=220,0,760,628&w=560&h=463",{"x":60,"y":51,"zoom":61,"background":53},-162,0.7372611464968153,{"dimensions":63,"alt":10,"copyright":10,"url":66,"id":49,"edit":67},{"width":64,"height":65},336,208,"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002Fbc4c20bc-eee6-422d-bd9d-c9d51c26acdf_magische-spiegelungen-technical-breakdown-cover.jpeg?auto=compress,format&rect=94,0,1014,628&w=336&h=208",{"x":68,"y":51,"zoom":69,"background":53},-31,0.33121019108280253,{"dimensions":71,"alt":10,"copyright":10,"url":74,"id":49,"edit":75},{"width":72,"height":73},480,304,"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002Fbc4c20bc-eee6-422d-bd9d-c9d51c26acdf_magische-spiegelungen-technical-breakdown-cover.jpeg?auto=compress,format&rect=103,0,992,628&w=480&h=304",{"x":76,"y":51,"zoom":77,"background":53},-50,0.4840764331210191,{"dimensions":79,"alt":10,"copyright":10,"url":82,"id":49,"edit":83},{"width":80,"height":81},278,145,"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002Fbc4c20bc-eee6-422d-bd9d-c9d51c26acdf_magische-spiegelungen-technical-breakdown-cover.jpeg?auto=compress,format&rect=0,0,1200,626&w=278&h=145",{"x":51,"y":51,"zoom":84,"background":53},0.23166666666666666,{"dimensions":86,"alt":10,"copyright":10,"url":89,"id":49,"edit":90},{"width":87,"height":88},1120,624,"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002Fbc4c20bc-eee6-422d-bd9d-c9d51c26acdf_magische-spiegelungen-technical-breakdown-cover.jpeg?auto=compress,format&rect=36,0,1127,628&w=1120&h=624",{"x":91,"y":51,"zoom":92,"background":53},-36,0.9936305732484076,{"dimensions":94,"alt":10,"copyright":10,"url":97,"id":49,"edit":98},{"width":95,"height":96},170,136,"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002Fbc4c20bc-eee6-422d-bd9d-c9d51c26acdf_magische-spiegelungen-technical-breakdown-cover.jpeg?auto=compress,format&rect=208,0,785,628&w=170&h=136",{"x":99,"y":51,"zoom":100,"background":53},-45,0.21656050955414013,[102],{"type":103,"text":104,"spans":105},"heading1","Magical Reflections, a WebXR experience powered by NanoGL",[],{"link_type":107,"key":108,"url":109,"target":110},"Web","76856c1a-7705-4e93-a86f-48f03a66d8dd","https:\u002F\u002Fwww.magische-spiegelungen.de\u002F","_blank","See live",[113,121],{"type":114,"text":115,"spans":116},"paragraph","To support Johan Erdmann Hummel exhibit at Alte Nationalgalerie, we created a virtual art experience which leads into one emblematic painting from the artist, The Granite Dish in the Berlin Lustgarten. In this painting, users are able to move freely, discover the art piece from the inside and take pictures to share with the community. ",[117],{"start":118,"end":119,"type":120},159,200,"em",{"type":114,"text":122,"spans":123},"\nThere is one twist, the project has to be accessible in VR through the browser using Oculus Quest 2 and WebXR. \n\nAs for all our realtime virtual experience, we used our homemade WebGL microframework nanogl and push it to the next level with WebXR capabilities. Frontend is handled with Vue.js and all app states via xstate. Photos are stored and presented through a gallery, we used the serverless framework deployed with AWS.",[124,129,134,139,144],{"start":119,"end":125,"type":126,"data":127},206,"hyperlink",{"link_type":107,"url":128},"https:\u002F\u002Fgithub.com\u002Fplepers\u002Fnanogl",{"start":130,"end":131,"type":126,"data":132},287,293,{"link_type":107,"url":133},"https:\u002F\u002Fvuejs.org\u002F",{"start":135,"end":136,"type":126,"data":137},317,323,{"link_type":107,"url":138},"https:\u002F\u002Fxstate.js.org\u002F",{"start":140,"end":141,"type":126,"data":142},388,398,{"link_type":107,"url":143},"https:\u002F\u002Fwww.serverless.com\u002F",{"start":145,"end":146,"type":126,"data":147},423,426,{"link_type":107,"url":148},"https:\u002F\u002Faws.amazon.com\u002F",[150,176,190,229,243,255,287,301,320,329,341,362,373,390,399,419,436,445,464,479,493,514,523,556,565,577,586],{"variation":151,"version":152,"items":153,"primary":155,"id":174,"slice_type":175,"slice_label":10},"default","initial",[154],{},{"bg_color":10,"image_left":156,"video_left":164,"caption_left":166,"image_right":167,"video_right":172,"caption_right":173},{"dimensions":157,"alt":10,"copyright":10,"url":160,"id":161,"edit":162},{"width":158,"height":159},2560,1300,"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002Fd614e615-f502-4429-bd2b-ea3891ed041a_museum.png?auto=compress,format","YeF-bBAAAJMQImlu",{"x":51,"y":51,"zoom":52,"background":163},"transparent",{"link_type":165},"Media","The museum",{"dimensions":168,"alt":10,"copyright":10,"url":169,"id":170,"edit":171},{"width":158,"height":159},"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002Fe72a7e4d-22f9-4cb0-88f8-2f103b7cac42_painting.png?auto=compress,format","YeF-bRAAACEAIml5",{"x":51,"y":51,"zoom":52,"background":163},{"link_type":165},"The Granite Dish in the Berlin Lustgarten","twin_images$5e6d9482-1464-4e63-a3cc-2f5df798ccc6","twin_images",{"variation":151,"version":152,"items":177,"primary":179,"id":188,"slice_type":189,"slice_label":10},[178],{},{"bg_color":10,"text":180},[181,185],{"type":182,"text":183,"spans":184},"heading2","The museum ",[],{"type":114,"text":186,"spans":187},"Our vision of the museum was to create large dreamy rooms with beautiful lights and colors. The museum relies a lot on lightmap, baked using Houdini.  Houdini uses a non destructive workflow to generate on the fly lightmap uv with good texel density scattering, which is great for quick iterations. And since it’s node based, it enables other things, like, cleanup the scene, add and place interactible frames, generate the navmesh used in XR mode, color some part of the scene and more... all at once.",[],"simple_text$40ba9053-30c6-43bd-b6c2-5a756f438c6d","simple_text",{"variation":151,"version":152,"items":191,"primary":224,"id":227,"slice_type":228,"slice_label":10},[192,203,210,217],{"image":193,"video":202},{"dimensions":194,"alt":10,"copyright":10,"url":197,"id":198,"edit":199},{"width":195,"height":196},781,555,"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002Fdee886bc-a5ef-4073-9b2f-8ff9767c0cac_CaptureLights.JPG?auto=compress,format&rect=74,0,2344,1666&w=781&h=555","YeGAGxAAAIAWInGo",{"x":200,"y":51,"zoom":201,"background":53},-24,0.33313325330132054,{"link_type":165},{"image":204,"video":209},{"dimensions":205,"alt":10,"copyright":10,"url":206,"id":207,"edit":208},{"width":195,"height":196},"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F87e816b8-e05b-4690-80d4-cfd161057d25_CaptureSOP.png?auto=compress,format&rect=0,0,781,555&w=781&h=555","YeGAGxAAAIAWInGn",{"x":51,"y":51,"zoom":52,"background":163},{"link_type":165},{"image":211,"video":216},{"dimensions":212,"alt":10,"copyright":10,"url":213,"id":207,"edit":214},{"width":195,"height":196},"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F87e816b8-e05b-4690-80d4-cfd161057d25_CaptureSOP.png?auto=compress,format&rect=0,559,781,555&w=781&h=555",{"x":51,"y":215,"zoom":52,"background":163},-559,{"link_type":165},{"image":218,"video":223},{"dimensions":219,"alt":10,"copyright":10,"url":220,"id":207,"edit":221},{"width":195,"height":196},"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F87e816b8-e05b-4690-80d4-cfd161057d25_CaptureSOP.png?auto=compress,format&rect=0,1094,781,555&w=781&h=555",{"x":51,"y":222,"zoom":52,"background":163},-1094,{"link_type":165},{"bg_color":10,"title":225,"sub_title":10,"rounded":226},[],false,"slider$2fe5431b-f7c9-4102-9514-e29be3e803e0","slider",{"variation":151,"version":152,"items":230,"primary":232,"id":242,"slice_type":189,"slice_label":10},[231],{},{"bg_color":10,"text":233},[234],{"type":114,"text":235,"spans":236},"Some elements are rendered using full PBR and image based lights with nanogl-pbr, for instance the frames and the vases.\n\nTo contribute to the dreamy feel, we added special effects and postprocess, like lens flares, Chromatic Aberration and real time reflections to the floor.\n\nSince all mobile or computer specifications can't afford all these effects. We implemented dynamic quality adjustment based on compute performance. Basically the average fps on time is sampled and after some time, it adapts the quality by removing one effect. It does it again until the frame rate is considered as stable and acceptable.",[237],{"start":238,"end":239,"type":126,"data":240},70,80,{"link_type":107,"url":241},"https:\u002F\u002Fgithub.com\u002Fplepers\u002Fnanogl-pbr","simple_text$26f6c84e-0aec-4a1d-97e2-b82ed495ed6f",{"variation":151,"version":152,"items":244,"primary":246,"id":254,"slice_type":189,"slice_label":10},[245],{},{"bg_color":10,"text":247},[248,251],{"type":182,"text":249,"spans":250},"Painting",[],{"type":114,"text":252,"spans":253},"The painting and elements not visible in the painting like the museum or trees have been entirely reproduced in 3D by our 3D artists. It involved placing volumes, hand painting all the content, creating from historical documents missing parts, modeling all near characters and generating impostors for far characters.",[],"simple_text$1f1ce520-de65-46b1-8ea4-39ea01cd451f",{"variation":151,"version":152,"items":256,"primary":258,"id":286,"slice_type":276,"slice_label":10},[257],{},{"bg_color":10,"poster":259,"video_embed":273,"video_title":10},{"dimensions":260,"alt":10,"copyright":10,"url":263,"id":264,"edit":265,"mobile":266},{"width":261,"height":262},1280,720,"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F88d68de3-1388-4a28-9e4b-b5d275d625de_fang_technical-breakdown-quick_paint-maxresdefault.jpg?auto=compress,format","YeVGQhAAACEAM0Cp",{"x":51,"y":51,"zoom":52,"background":53},{"dimensions":267,"alt":10,"copyright":10,"url":269,"id":264,"edit":270},{"width":64,"height":268},184,"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F88d68de3-1388-4a28-9e4b-b5d275d625de_fang_technical-breakdown-quick_paint-maxresdefault.jpg?auto=compress,format&rect=0,8,1280,701&w=336&h=184",{"x":51,"y":271,"zoom":272,"background":53},-2,0.2625,{"height":274,"width":119,"embed_url":275,"type":276,"version":277,"title":278,"author_name":279,"author_url":280,"provider_name":281,"provider_url":282,"cache_age":10,"thumbnail_url":283,"thumbnail_width":72,"thumbnail_height":284,"html":285},113,"https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=ikw5l3bxlI8","video","1.0","fang technical breakdown quick paint","makemepulse","https:\u002F\u002Fwww.youtube.com\u002Fchannel\u002FUCo0zHygJKrK4obci3u835RQ","YouTube","https:\u002F\u002Fwww.youtube.com\u002F","https:\u002F\u002Fi.ytimg.com\u002Fvi\u002Fikw5l3bxlI8\u002Fhqdefault.jpg",360,"\u003Ciframe width=\"200\" height=\"113\" src=\"https:\u002F\u002Fwww.youtube.com\u002Fembed\u002Fikw5l3bxlI8?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C\u002Fiframe>","video$a517bad8-c879-4a7f-a777-b16ff6561d07",{"variation":151,"version":152,"items":288,"primary":290,"id":300,"slice_type":189,"slice_label":10},[289],{},{"bg_color":10,"text":291},[292],{"type":114,"text":293,"spans":294},"There are 16 characters in the scene (including the dog 🐶). Performance wise, we couldn’t afford two textures (normal, albedo) per character and complex shading. To reduce textures and draw call count we used Simplygon to aggregate characters. Beside other features it can merge selected mesh, generates a new uv set and creates new textures based on sources according to the new uv set.",[295],{"start":296,"end":297,"type":126,"data":298},210,219,{"link_type":107,"url":299},"https:\u002F\u002Fwww.simplygon.com\u002F","simple_text$ed482d42-438f-4797-bb4e-6558833ab6aa",{"variation":151,"version":152,"items":302,"primary":304,"id":319,"slice_type":276,"slice_label":10},[303],{},{"bg_color":10,"poster":305,"video_embed":314,"video_title":10},{"dimensions":306,"alt":10,"copyright":10,"url":307,"id":308,"edit":309,"mobile":310},{"width":261,"height":262},"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F6be5c519-a5be-431a-abc5-954aad1bc95f_fang_technical-breakdown-Simplygon_love-maxresdefault.jpg?auto=compress,format","YeVGixAAAIAWM0G7",{"x":51,"y":51,"zoom":52,"background":53},{"dimensions":311,"alt":10,"copyright":10,"url":312,"id":308,"edit":313},{"width":64,"height":268},"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F6be5c519-a5be-431a-abc5-954aad1bc95f_fang_technical-breakdown-Simplygon_love-maxresdefault.jpg?auto=compress,format&rect=0,8,1280,701&w=336&h=184",{"x":51,"y":271,"zoom":272,"background":53},{"height":274,"width":119,"embed_url":315,"type":276,"version":277,"title":316,"author_name":279,"author_url":280,"provider_name":281,"provider_url":282,"cache_age":10,"thumbnail_url":317,"thumbnail_width":72,"thumbnail_height":284,"html":318},"https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=J-5bXTAyfdI","fang technical breakdown Simplygon love","https:\u002F\u002Fi.ytimg.com\u002Fvi\u002FJ-5bXTAyfdI\u002Fhqdefault.jpg","\u003Ciframe width=\"200\" height=\"113\" src=\"https:\u002F\u002Fwww.youtube.com\u002Fembed\u002FJ-5bXTAyfdI?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C\u002Fiframe>","video$2a4561b2-d26b-4c4c-ba6b-815e6119b6d7",{"variation":151,"version":152,"items":321,"primary":323,"id":328,"slice_type":189,"slice_label":10},[322],{},{"bg_color":10,"text":324},[325],{"type":114,"text":326,"spans":327},"By using this we reduced characters and textures count to 4. From then, we baked global lighting from the scene inside blender and on top of it hand painted again each character to enhance visuals.",[],"simple_text$9bf61ff4-609a-4baa-a5e6-ba039df6fdf5",{"variation":151,"version":152,"items":330,"primary":332,"id":340,"slice_type":189,"slice_label":10},[331],{},{"bg_color":10,"text":333},[334,337],{"type":182,"text":335,"spans":336},"Special FX",[],{"type":114,"text":338,"spans":339},"The core piece of the painting is the granite bowl reflection. Since it’s a flat surface on top of a pillar, using solely a cubemap resulted in a floating bowl and non believable reflections. We decided to take an hybrid approach. Real time reflections on the bottom, cubemap on the sides and top. Using only one shader we used vertex color to blend those two reflections according to the red level.",[],"simple_text$803593e5-cbd0-4925-99e5-b8fdd0fed29b",{"variation":151,"version":152,"items":342,"primary":344,"id":361,"slice_type":175,"slice_label":10},[343],{},{"bg_color":10,"image_left":345,"video_left":353,"caption_left":10,"image_right":354,"video_right":360,"caption_right":10},{"dimensions":346,"alt":10,"copyright":10,"url":349,"id":350,"edit":351},{"width":347,"height":348},1440,741,"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002Fb456653a-2bd4-4859-8cb1-e568c2456054_bowl_highlight.png?auto=compress,format&rect=0,40,1440,741&w=1440&h=741","YeVHpRAAACEAM0Z1",{"x":51,"y":352,"zoom":52,"background":163},-40,{"link_type":165},{"dimensions":355,"alt":10,"copyright":10,"url":356,"id":357,"edit":358},{"width":347,"height":348},"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F9db14c9a-6c4c-4d24-a288-c4d9c323beab_bowl_vertex_color.PNG?auto=compress,format&rect=59,0,1440,741&w=1440&h=741","YeVHjhAAACEAM0YD",{"x":359,"y":51,"zoom":52,"background":163},-59,{"link_type":165},"twin_images$5d1e7146-b1ec-485b-8c5c-e1daa6988ccf",{"variation":151,"version":152,"items":363,"primary":365,"id":372,"slice_type":189,"slice_label":10},[364],{},{"bg_color":366,"text":367},"#ffffff",[368],{"type":369,"text":370,"spans":371},"preformatted","\u002F\u002FGranite reflection sample shader\nvec3 viewDir = normalize( uCameraPosition - vWorldPosition );\nvec3 worldReflect = normalize(reflect( -viewDir, vWorldNormal ));\n\nfloat NoV = sdot( viewDir, vWorldNormal );\n\n\u002F\u002F Base cubemap reflection\nvec3 specular = textureCube(tProbeCubemap, worldReflect).rgb; \n\n\u002F\u002F Sample the reflection texture\nvec2 rcoord = gl_FragCoord.xy \u002F uViewport;\nvec3 rcolor = texture2D(tReflectTex, rcoord).rgb;\n\nspecular = mix(specular, rcolor, vertexColor().r); \n\n\u002F\u002F Apply specular smoothness\nspecular *= F_Schlick( NoV, vec3(uSpecular), uSmoothness );\n\nFragColor.rgb = baseColor() * uDarken + specular;",[],"simple_text$1b771eda-7053-4f99-a84b-94a7f54bdbae",{"variation":151,"version":152,"items":374,"primary":376,"id":389,"slice_type":189,"slice_label":10},[375],{},{"bg_color":10,"text":377},[378,381],{"type":114,"text":379,"spans":380},"The real time reflection is done by reflecting the camera matrix from an arbitrary axis and rendering the scene from this perspective. To gain some fill rate performance the bottom of the bowl is used as a stencil mask to render only pixels that matter.\n",[],{"type":114,"text":382,"spans":383},"We wanted to make the scene more alive. We decided to animate the fountain using a flow map generated with substance painter and then animate, blend the texture based on this flow map.",[384],{"start":385,"end":386,"type":126,"data":387},107,124,{"link_type":107,"url":388},"https:\u002F\u002Fsubstance3d.adobe.com\u002Fdocumentation\u002Fspdoc\u002Fflow-map-painting-143327274.html","simple_text$416374c6-ea8e-48a8-a2cc-5eacb03843da",{"variation":151,"version":152,"items":391,"primary":393,"id":398,"slice_type":189,"slice_label":10},[392],{},{"bg_color":10,"text":394},[395],{"type":369,"text":396,"spans":397},"\u002F\u002F vec2 uFlowMapConfig\n\u002F\u002F   x : time\n\u002F\u002F   y : speed \n\nvec3 flowDir = texture2D(uFlowMap, baseColor_texCoord()).rgb;\nflowDir = (flowDir * vec3(2.0)) - vec3(1.0);\nflowDir *= uFlowMapConfig.y;\n\nfloat phase0 = fract(uFlowMapConfig.x * 0.2 + 0.5);\nfloat phase1 = fract(uFlowMapConfig.x * 0.2 + 1.0);\n\nvec4 tex0 = texture2D(tex_basecolor, baseColor_texCoord() + flowDir.xy * phase0);\nvec4 tex1 = texture2D(tex_basecolor, baseColor_texCoord() + flowDir.xy * phase1);\n\nfloat flowLerp = abs((0.5 - phase0) \u002F 0.5);\nvec4 FragColor = mix(tex0, tex1, flowLerp);",[],"simple_text$1e9df478-a349-415c-9067-3aa900dbf6a2",{"variation":151,"version":152,"items":400,"primary":402,"id":418,"slice_type":276,"slice_label":10},[401],{},{"bg_color":10,"poster":403,"video_embed":412,"video_title":10},{"dimensions":404,"alt":10,"copyright":10,"url":405,"id":406,"edit":407,"mobile":408},{"width":261,"height":262},"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F1ef5f7e7-e9fd-43c9-a0d0-46ee575f569f_fang_technical-breakdown-fountain-maxresdefault.jpg?auto=compress,format","YeVGvRAAACMAM0Ji",{"x":51,"y":51,"zoom":52,"background":53},{"dimensions":409,"alt":10,"copyright":10,"url":410,"id":406,"edit":411},{"width":64,"height":268},"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F1ef5f7e7-e9fd-43c9-a0d0-46ee575f569f_fang_technical-breakdown-fountain-maxresdefault.jpg?auto=compress,format&rect=0,8,1280,701&w=336&h=184",{"x":51,"y":271,"zoom":272,"background":53},{"height":413,"width":119,"embed_url":414,"type":276,"version":277,"title":415,"author_name":279,"author_url":280,"provider_name":281,"provider_url":282,"cache_age":10,"thumbnail_url":416,"thumbnail_width":72,"thumbnail_height":284,"html":417},150,"https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=h0UlE09AGZ8","fang technical breakdown fountain","https:\u002F\u002Fi.ytimg.com\u002Fvi\u002Fh0UlE09AGZ8\u002Fhqdefault.jpg","\u003Ciframe width=\"200\" height=\"150\" src=\"https:\u002F\u002Fwww.youtube.com\u002Fembed\u002Fh0UlE09AGZ8?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C\u002Fiframe>","video$70af9583-7cab-4575-aa92-d10963c3772a",{"variation":151,"version":152,"items":420,"primary":429,"id":434,"slice_type":435,"slice_label":10},[421],{"image":422,"video":428},{"dimensions":423,"alt":10,"copyright":10,"url":425,"id":426,"edit":427},{"width":424,"height":424},518,"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002Fc405e8cf-3c23-4f34-a9db-ce42e2dc69aa_trees.gif?auto=compress,format","YeWi-RAAAIAWNOSx",{"x":51,"y":51,"zoom":52,"background":53},{"link_type":165},{"bg_color":10,"text":430},[431],{"type":114,"text":432,"spans":433},"We added wind by rotating the sky dome and making trees move. Since trees are impostors and therefore simple planes we can add local displacement using the tangent of the face to make it move. \n\nThe trunks need to be sticky and the top needs to move. To handle this and add variety between trees, we added a subdivision on the trunk and used vertex color to adjust the displacement factor. The Z position of trees faces is used to offset the displacement time period.",[],"text_and_image$29483483-2d09-4bd9-ad0e-12f17802a6f4","text_and_image",{"variation":151,"version":152,"items":437,"primary":439,"id":444,"slice_type":189,"slice_label":10},[438],{},{"bg_color":10,"text":440},[441],{"type":369,"text":442,"spans":443}," float height = aColor0.r;\n vec3 tangent = cross(vec3(0.0, 1.0, 0.0), aNormal);\n vertex.position += sin(uTime + vertex.position.z * 0.1) * tangent * height * 0.4;",[],"simple_text$63c7a42b-c9d4-4e9a-9e72-a14b1ad19dd4",{"variation":151,"version":152,"items":446,"primary":448,"id":463,"slice_type":276,"slice_label":10},[447],{},{"bg_color":10,"poster":449,"video_embed":458,"video_title":10},{"dimensions":450,"alt":10,"copyright":10,"url":451,"id":452,"edit":453,"mobile":454},{"width":261,"height":262},"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F40f1d036-e58a-4d33-933e-e0badbcaffe6_fang_technical-breakdown-trees_vertex_color-maxresdefault.jpg?auto=compress,format","YeVHCBAAACMAM0OR",{"x":51,"y":51,"zoom":52,"background":53},{"dimensions":455,"alt":10,"copyright":10,"url":456,"id":452,"edit":457},{"width":64,"height":268},"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F40f1d036-e58a-4d33-933e-e0badbcaffe6_fang_technical-breakdown-trees_vertex_color-maxresdefault.jpg?auto=compress,format&rect=0,8,1280,701&w=336&h=184",{"x":51,"y":271,"zoom":272,"background":53},{"height":413,"width":119,"embed_url":459,"type":276,"version":277,"title":460,"author_name":279,"author_url":280,"provider_name":281,"provider_url":282,"cache_age":10,"thumbnail_url":461,"thumbnail_width":72,"thumbnail_height":284,"html":462},"https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=pRKCxljJN-g","fang technical breakdown trees vertex color","https:\u002F\u002Fi.ytimg.com\u002Fvi\u002FpRKCxljJN-g\u002Fhqdefault.jpg","\u003Ciframe width=\"200\" height=\"150\" src=\"https:\u002F\u002Fwww.youtube.com\u002Fembed\u002FpRKCxljJN-g?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C\u002Fiframe>","video$d7c7699d-c06f-423b-91b1-e2dbc130bc7c",{"variation":151,"version":152,"items":465,"primary":467,"id":478,"slice_type":189,"slice_label":10},[466],{},{"bg_color":10,"text":468},[469,475],{"type":182,"text":470,"spans":471},"WebXR",[472],{"start":51,"end":473,"type":474},5,"strong",{"type":114,"text":476,"spans":477},"WebXR is the new standard to handle virtual reality within a browser (previously called WebVR but has become WebXR to handle augmented reality or any other reality as well). If you are not familiar with the concept, to present a VR frame to the viewer, the scene has to be rendered twice, one for each eye. The WebXR api returns the rendering informations for each eye, transform, projection, viewport and, if available, controllers\u002Fhand positions.",[],"simple_text$e2ca05cc-e693-4b9c-a3f3-209c8600bea9",{"variation":151,"version":152,"items":480,"primary":482,"id":491,"slice_type":492,"slice_label":10},[481],{},{"bg_color":10,"image":483,"video":490,"caption":10,"rounded":226},{"dimensions":484,"alt":10,"copyright":10,"url":487,"id":488,"edit":489},{"width":485,"height":486},1920,1080,"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F4b3ba1b1-744f-4f54-9d24-18464affa170_xr_detail.png?auto=compress,format","YeWjqhAAACMANOgT",{"x":51,"y":51,"zoom":52,"background":163},{"link_type":165},"simple_image$79457574-2c77-4338-82cd-91537668836f","simple_image",{"variation":151,"version":152,"items":494,"primary":503,"id":513,"slice_type":435,"slice_label":10},[495],{"image":496,"video":502},{"dimensions":497,"alt":10,"copyright":10,"url":499,"id":500,"edit":501},{"width":498,"height":498},1024,"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F8fb089e3-0d09-4243-8f31-c312899e103d_Graphik-400-Regular_SDF.png?auto=compress,format","YeWkdBAAAIAWNOsw",{"x":51,"y":51,"zoom":52,"background":163},{"link_type":165},{"bg_color":10,"text":504},[505],{"type":114,"text":506,"spans":507},"Inside an immersive session there is no HTML\u002FCSS presentation, everything happens inside the canvas. The experience had to work in mobile\u002Fdesktop and XR at any time. \nSo we adapted all the UI with a custom toolset in WebGL, including text rendering. \n\nWe are always using Unity a lot in our workflow and text rendering uses SDF textures generated with TextMeshPro and then to a json containing the typography specifications. \nUnity makes it very easy to develop custom editor tools. We wrote an exporter that generates the json and exports the texture in the desired folder. For instance here is one of the font used in the site, Gaphik 400.\n\nAnd a sample of the json with the letter “ A ” below.",[508],{"start":509,"end":510,"type":126,"data":511},352,363,{"link_type":107,"url":512,"target":110},"https:\u002F\u002Fdocs.unity3d.com\u002FManual\u002Fcom.unity.textmeshpro.html","text_and_image$5b6151ec-bb71-4ffa-be6d-310ba32a9b1e",{"variation":151,"version":152,"items":515,"primary":517,"id":522,"slice_type":189,"slice_label":10},[516],{},{"bg_color":10,"text":518},[519],{"type":369,"text":520,"spans":521},"{\n  \"characters\": [\n    …\n    {\n      \"unicode\": 65,\n      \"glyphIndex\": 55,\n      \"scale\": 1.0,\n      \"glyph\": {\n        \"index\": 55,\n        \"metrics\": {\n          \"width\": 65.625,\n          \"height\": 77.9375,\n          \"horizontalBearingX\": 3.921875,\n          \"horizontalBearingY\": 77.9375,\n          \"horizontalAdvance\": 73.46875\n        },\n        \"glyphRect\": {\n          \"x\": 702,\n          \"y\": 113,\n          \"width\": 67,\n          \"height\": 78\n        },\n        \"scale\": 1.0\n      }\n    }\n    …\n  ],\n  \"faceInfo\": {\n    \"lineHeight\": 119.9000015258789,\n    \"scale\": 1.0,\n    \"pointSize\": 109,\n    \"atlasPadding\": 4,\n    \"textureWidth\": 1024,\n    \"textureHeight\": 1024\n  }\n}\n",[],"simple_text$1c422435-b713-4126-9e36-1807e4a04983",{"variation":151,"version":152,"items":524,"primary":526,"id":555,"slice_type":189,"slice_label":10},[525],{},{"bg_color":10,"text":527},[528,531,539,544,552],{"type":114,"text":529,"spans":530},"Every renderable object in the project, and not only ui, follows the same design pattern to be rendered easily from any camera at any time, making graphics components reusable.",[],{"type":114,"text":532,"spans":533},"Controllers are handled with a separate standard, Gamepad API. It is a barebone api and we needed to access controller information from anywhere within the app. So we developed a middleware to easily access controllers events and position, and adapted controllers models supplied by oculus.\n",[534],{"start":535,"end":536,"type":126,"data":537},271,289,{"link_type":107,"url":538},"https:\u002F\u002Fdeveloper.oculus.com\u002Fdownloads\u002Fpackage\u002Foculus-controller-art\u002F",{"type":182,"text":540,"spans":541},"WebXR Optimisations\t",[542],{"start":51,"end":543,"type":474},19,{"type":114,"text":545,"spans":546},"Rendering the scene twice or even four times (one time for each eye + real time reflection) can be heavy. It is important to minimize WebGL state change between renders and when possible only update MVP uniform between eyes render. This is where nanogl-state shines. This module stack GL states and apply only changes needed between renders.",[547],{"start":548,"end":549,"type":126,"data":550},246,258,{"link_type":107,"url":551},"https:\u002F\u002Fgithub.com\u002Fplepers\u002Fnanogl-state",{"type":114,"text":553,"spans":554},"Here is a sample of how nanogl state is used :",[],"simple_text$adca150c-10dd-45c3-a9c2-427daf0271bf",{"variation":151,"version":152,"items":557,"primary":559,"id":564,"slice_type":189,"slice_label":10},[558],{},{"bg_color":10,"text":560},[561],{"type":369,"text":562,"spans":563},"var GLState = require( 'nanogl-state' );\n \n\u002F\u002F create the state machine from a gl context\n\u002F\u002F glStage will be sync with the actual gl state\nvar glState = new GLState( gl );\n \n \n\u002F\u002F create a config to change glCullFace for both opaques and blended\nvar cfgG = GLState.config()\n  .cullFace( gl.FRONT );\n \n \n\u002F\u002F create a configuration to enable DEPTH_TEST\nvar cfgA = GLState.config()\n  .enableDepthTest()\n  .enableCullface();\n \n\u002F\u002F create another config for alpha blending and depth test\n \nvar cfgB = GLState.config()\n  .enableBlend()\n  .blendFunc( gl.SRC_ALPHA, gl.ONE_MINUS_DRC_ALPHA )\n  .enableDepthTest()\n  .enableCullface()\n  .depthMask( false );\n \n \n \n\u002F\u002F somewhere in your render loop\nfunction render(){\n  \u002F\u002F context in default state\n \n  \u002F\u002F add the cullFace cfg to the stack\n  glState.push( cfgG );\n \n  \u002F\u002F add cfgA to the stack, apply the complete stack to the context, then pop cfgA\n  glState.now( cfgA );\n  renderOpaqueStuffs();\n \n \n  \u002F\u002F apply the cfgB, enable DEPTH_TEST and CULL_FACE are skipped since they are already enabled\n  glState.now( cfgB );\n  renderBlendableStuffs();\n \n  \u002F\u002F pop the cullFace config (cfgG)\n  glState.pop();\n \n  \u002F\u002F sync the glState and the actual gl context\n  glState.apply();\n \n  \u002F\u002F here we are back to the default state\n}\n",[],"simple_text$b1f88efc-e384-4478-af84-e9aa7a13bcb2",{"variation":151,"version":152,"items":566,"primary":568,"id":576,"slice_type":189,"slice_label":10},[567],{},{"bg_color":10,"text":569},[570,573],{"type":114,"text":571,"spans":572},"To optimize fill rate performance it can be handy to use the optional WebXR feature Fixed Foveated Rendering. It reduces the resolution of the frame in peripheral vision, which eventually reduces the pixel count, without noticeable downside as the viewer is generally looking forward.",[],{"type":114,"text":574,"spans":575},"Finally maintaining solid 90fps in WebGL and in XR is a hard task, and the motion sickness generally comes from unstable fps. Oculus supports a feature to set at runtime the target fps. We setted it to 72.",[],"simple_text$e1829701-52c4-4bc7-839d-75f167c2183f",{"variation":151,"version":152,"items":578,"primary":580,"id":585,"slice_type":189,"slice_label":10},[579],{},{"bg_color":10,"text":581},[582],{"type":369,"text":583,"spans":584},"navigator.xr.requestSession('immersive-vr', {\n  requiredFeatures: ['local-floor'],\n  optionalFeatures: [\n    'low-fixed-foveation-level',\n  ]\n})\n  .then(this.sessionStarted);\n \n\u002F\u002F...\n\u002F\u002F SESSION STARTED\nif(session.updateTargetFrameRate)\n  session.updateTargetFrameRate(72);",[],"simple_text$47ed5e1c-f01c-4705-a975-5e9cb7a88649",{"variation":151,"version":152,"items":587,"primary":589,"id":598,"slice_type":189,"slice_label":10},[588],{},{"bg_color":10,"text":590},[591],{"type":114,"text":592,"spans":593},"This project has been really fun to work on, from a creative and technical point of view. We hope you enjoyed the reading and if you haven’t seen the website yet, check here",[594],{"start":595,"end":596,"type":126,"data":597},163,173,{"link_type":107,"url":109,"target":110},"simple_text$d7faba82-48ed-4f5d-a366-4b034ea2c6a4",[600],{"category":601},{"id":602,"type":603,"tags":604,"lang":605,"slug":606,"first_publication_date":607,"last_publication_date":608,"uid":609,"data":610,"link_type":612,"key":613,"isBroken":226},"XqmgKxAAACQAbEM2","article_category",[],"en-us","-","2020-04-29T15:41:36+0000","2024-02-20T11:37:06+0000","process",{"name":611},"Process","Document","e1323630-8063-4fb4-b8bb-aaf8b21b17a5",[615,682],{"article":616},{"id":617,"type":618,"tags":619,"lang":605,"slug":606,"first_publication_date":620,"last_publication_date":621,"uid":622,"data":623,"link_type":612,"key":681,"isBroken":226},"XtpV4hIAACMASGCl","article",[],"2020-06-05T14:25:41+0000","2024-02-20T11:41:10+0000","nanogl-experiences-for-the-nissan-platform",{"title":624,"cover_image":628,"date":671,"categories":672,"baseline":678,"caption":680},[625],{"type":103,"text":626,"spans":627},"NanoGL Experiences for the Nissan platform",[],{"dimensions":629,"alt":10,"copyright":10,"url":632,"id":633,"edit":634,"desktop":635,"grid_mobile":641,"grid_small":647,"hover":653,"grid":659,"mobile":665},{"width":630,"height":631},1400,677,"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F1d6ac770-53a9-4140-bd06-d59c25975db1_nanogl-nissan-experience-cover.jpeg?auto=compress,format","XtpVOBIAACIASF2f",{"x":51,"y":51,"zoom":52,"background":53},{"dimensions":636,"alt":10,"copyright":10,"url":637,"id":633,"edit":638},{"width":56,"height":57},"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F1d6ac770-53a9-4140-bd06-d59c25975db1_nanogl-nissan-experience-cover.jpeg?auto=compress,format&rect=291,0,819,677&w=560&h=463",{"x":639,"y":51,"zoom":640,"background":53},-199,0.6838995568685377,{"dimensions":642,"alt":10,"copyright":10,"url":643,"id":633,"edit":644},{"width":64,"height":65},"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F1d6ac770-53a9-4140-bd06-d59c25975db1_nanogl-nissan-experience-cover.jpeg?auto=compress,format&rect=153,0,1094,677&w=336&h=208",{"x":645,"y":51,"zoom":646,"background":53},-47,0.3072378138847858,{"dimensions":648,"alt":10,"copyright":10,"url":649,"id":633,"edit":650},{"width":72,"height":73},"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F1d6ac770-53a9-4140-bd06-d59c25975db1_nanogl-nissan-experience-cover.jpeg?auto=compress,format&rect=165,0,1069,677&w=480&h=304",{"x":651,"y":51,"zoom":652,"background":53},-74,0.44903988183161003,{"dimensions":654,"alt":10,"copyright":10,"url":656,"id":633,"edit":657},{"width":80,"height":655},134,"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F1d6ac770-53a9-4140-bd06-d59c25975db1_nanogl-nissan-experience-cover.jpeg?auto=compress,format&rect=0,0,1400,675&w=278&h=134",{"x":51,"y":51,"zoom":658,"background":53},0.19857142857142857,{"dimensions":660,"alt":10,"copyright":10,"url":661,"id":633,"edit":662},{"width":87,"height":88},"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F1d6ac770-53a9-4140-bd06-d59c25975db1_nanogl-nissan-experience-cover.jpeg?auto=compress,format&rect=92,0,1215,677&w=1120&h=624",{"x":663,"y":51,"zoom":664,"background":53},-85,0.9217134416543574,{"dimensions":666,"alt":10,"copyright":10,"url":667,"id":633,"edit":668},{"width":95,"height":96},"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F1d6ac770-53a9-4140-bd06-d59c25975db1_nanogl-nissan-experience-cover.jpeg?auto=compress,format&rect=279,0,846,677&w=170&h=136",{"x":669,"y":51,"zoom":670,"background":53},-56,0.20088626292466766,"2017-03-08T23:00:00+0000",[673],{"category":674},{"id":602,"type":603,"tags":675,"lang":605,"slug":606,"first_publication_date":607,"last_publication_date":608,"uid":609,"data":676,"link_type":612,"key":677,"isBroken":226},[],{"name":611},"b02ddcba-6968-4ada-a75c-ecef59ddcd59",[679],{"text":611},"9 March\n2017","05a4c256-c1d0-4f91-98b0-1939bee95b6a",{"article":683},{"id":684,"type":618,"tags":685,"lang":605,"slug":606,"first_publication_date":686,"last_publication_date":687,"uid":688,"data":689,"link_type":612,"key":746,"isBroken":226},"XtplvxIAACAASKq3",[],"2020-06-05T15:49:20+0000","2024-02-20T11:39:23+0000","a-world-with-no-heroes",{"title":690,"cover_image":694,"date":736,"categories":737,"baseline":743,"caption":745},[691],{"type":103,"text":692,"spans":693},"A World With No Heroes",[],{"dimensions":695,"alt":10,"copyright":10,"url":698,"id":699,"edit":700,"desktop":701,"grid_mobile":707,"grid_small":713,"hover":719,"grid":725,"mobile":731},{"width":696,"height":697},1600,1000,"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F00c6b513-9cf2-4765-92e8-32a4f1c171dd_a-world-with-no-heroes-cover.jpeg?auto=compress,format","Xtpq2xIAACIASMJy",{"x":51,"y":51,"zoom":52,"background":53},{"dimensions":702,"alt":10,"copyright":10,"url":703,"id":699,"edit":704},{"width":56,"height":57},"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F00c6b513-9cf2-4765-92e8-32a4f1c171dd_a-world-with-no-heroes-cover.jpeg?auto=compress,format&rect=194,0,1210,1000&w=560&h=463",{"x":705,"y":51,"zoom":706,"background":53},-90,0.463,{"dimensions":708,"alt":10,"copyright":10,"url":709,"id":699,"edit":710},{"width":64,"height":65},"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F00c6b513-9cf2-4765-92e8-32a4f1c171dd_a-world-with-no-heroes-cover.jpeg?auto=compress,format&rect=0,5,1600,990&w=336&h=208",{"x":51,"y":711,"zoom":712,"background":53},-1,0.21,{"dimensions":714,"alt":10,"copyright":10,"url":715,"id":699,"edit":716},{"width":72,"height":73},"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F00c6b513-9cf2-4765-92e8-32a4f1c171dd_a-world-with-no-heroes-cover.jpeg?auto=compress,format&rect=10,0,1579,1000&w=480&h=304",{"x":717,"y":51,"zoom":718,"background":53},-3,0.304,{"dimensions":720,"alt":10,"copyright":10,"url":722,"id":699,"edit":723},{"width":80,"height":721},174,"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F00c6b513-9cf2-4765-92e8-32a4f1c171dd_a-world-with-no-heroes-cover.jpeg?auto=compress,format&rect=0,0,1598,1000&w=278&h=174",{"x":51,"y":51,"zoom":724,"background":53},0.174,{"dimensions":726,"alt":10,"copyright":10,"url":727,"id":699,"edit":728},{"width":87,"height":88},"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F00c6b513-9cf2-4765-92e8-32a4f1c171dd_a-world-with-no-heroes-cover.jpeg?auto=compress,format&rect=0,54,1600,891&w=1120&h=624",{"x":51,"y":729,"zoom":730,"background":53},-38,0.7,{"dimensions":732,"alt":10,"copyright":10,"url":733,"id":699,"edit":734},{"width":95,"height":96},"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002F00c6b513-9cf2-4765-92e8-32a4f1c171dd_a-world-with-no-heroes-cover.jpeg?auto=compress,format&rect=176,0,1250,1000&w=170&h=136",{"x":200,"y":51,"zoom":735,"background":53},0.136,"2017-04-09T22:00:00+0000",[738],{"category":739},{"id":602,"type":603,"tags":740,"lang":605,"slug":606,"first_publication_date":607,"last_publication_date":608,"uid":609,"data":741,"link_type":612,"key":742,"isBroken":226},[],{"name":611},"d404678f-f0f5-424d-9ed0-8cc823ab9125",[744],{"text":611},"10 April\n2017","9fd2a0ce-127d-4fb7-8f85-30899caa7284","To support Johan Erdmann Hummel exhibit at Alte Nationalgalerie, we created a virtual art experience which leads into one emblematic painting from the artist, The Granite Dish in the Berlin Lustgarten. In this painting, users are able to move freely, discover the art piece from the inside and take pictures to share with the community.",{"dimensions":749,"alt":10,"copyright":10,"url":750,"id":49,"edit":751,"1.91:1":754},{"width":486,"height":486},"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002Fbc4c20bc-eee6-422d-bd9d-c9d51c26acdf_magische-spiegelungen-technical-breakdown-cover.jpeg?auto=compress,format&rect=286,0,628,628&w=1080&h=1080",{"x":752,"y":51,"zoom":753,"background":53},-492,1.7197452229299364,{"dimensions":755,"alt":10,"copyright":10,"url":757,"id":49,"edit":758},{"width":486,"height":756},565,"https:\u002F\u002Fimages.prismic.io\u002Fmakemepulse\u002Fbc4c20bc-eee6-422d-bd9d-c9d51c26acdf_magische-spiegelungen-technical-breakdown-cover.jpeg?auto=compress,format&rect=0,0,1200,628&w=1080&h=565",{"x":51,"y":51,"zoom":759,"background":53},0.9,{"index":473,"total":238},1792599067912]