<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>MirrorShih.github.io</title>
  
  
  <link href="https://mirrorshih.github.io/atom.xml" rel="self"/>
  
  <link href="https://mirrorshih.github.io/"/>
  <updated>2025-04-19T11:06:08.349Z</updated>
  <id>https://mirrorshih.github.io/</id>
  
  <author>
    <name>Mirror Shih</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Microsoft RDI 實習心得</title>
    <link href="https://mirrorshih.github.io/post/Microsoft-RDI-%E5%AF%A6%E7%BF%92%E5%BF%83%E5%BE%97.html"/>
    <id>https://mirrorshih.github.io/post/Microsoft-RDI-%E5%AF%A6%E7%BF%92%E5%BF%83%E5%BE%97.html</id>
    <published>2025-04-19T10:15:08.000Z</published>
    <updated>2025-04-19T11:06:08.349Z</updated>
    
    <content type="html"><![CDATA[<div class="custom-quote warning"><span class="custom-quote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M20.86 14.13C20 14.7 19.56 15.74 19.77 16.76C20.13 18.55 18.55 20.13 16.76 19.77C15.74 19.57 14.7 20 14.13 20.86C13.12 22.38 10.89 22.38 9.88 20.86C9.3 20 8.26 19.56 7.24 19.77C5.45 20.13 3.87 18.55 4.23 16.76C4.43 15.74 4 14.7 3.14 14.13C1.62 13.12 1.62 10.89 3.14 9.88C4 9.3 4.44 8.26 4.23 7.24C3.87 5.45 5.45 3.87 7.24 4.23C8.26 4.44 9.3 4 9.87 3.14C10.88 1.62 13.11 1.62 14.12 3.14C14.7 4 15.74 4.44 16.76 4.23C18.55 3.87 20.13 5.45 19.77 7.24C19.56 8.26 20 9.3 20.86 9.87C22.38 10.88 22.38 13.12 20.86 14.13Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M12 8V13"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M12 15.99V16.01"></path></svg></span><p class="custom-quote-title">WARNING</p><p>本文中所提到的實習計劃是<a href="https://www.microsoft.com/taiwan/campus/">微軟未來生涯體驗計劃</a>，在本文中可能會簡稱為微軟實習，實習計劃等等，僅代表我在微軟未來生涯體驗計劃中的心得，有可能有其他的微軟實習管道，因我沒有參與，故在本文中不做討論</p></div><h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>因為今年的實習招募快要開始了，而且在我參與微軟實習計劃時有關聯的人也都陸陸續續離開了，因此決定寫心得文紀錄一下過去的時光。寫這篇文也是為了讓正在評估要不要參與微軟實習計劃的學生們能參考看看微軟實習的生活是不是你想要的</p><h1 id="聲明"><a href="#聲明" class="headerlink" title="聲明"></a>聲明</h1><ol><li>這篇文會從我自己的視角來分享我實習的經驗和心得，沒辦法代表其他實習生的立場，特別是不同部門、不同職位的實習生跟我的經驗可能會有很大的差異，這點大家再自己評估看看。這篇文會主要分享RDI在 Maps Services Engineering 工作的心得</li><li>在參與微軟實習之前，我沒有在其他任何公司做過類似的實習，因此無法對於微軟實習的RDI職位和其他公司軟體工程師的實習作出比較</li><li>這篇文不會寫任何跟面試有關的內容，如果需要參考的話可以自行上網尋找</li><li>若實習計劃方對於本文有任何疑慮以及需要修改、無法透露的資訊，請寄信至<a href="mailto:&#109;&#105;&#114;&#x72;&#x6f;&#114;&#115;&#x68;&#x69;&#x68;&#64;&#103;&#x6d;&#x61;&#105;&#108;&#x2e;&#x63;&#x6f;&#x6d;">mirrorshih@gmail.com</a>聯絡我，我將協助修改</li></ol><h1 id="FAQ"><a href="#FAQ" class="headerlink" title="FAQ"></a>FAQ</h1><p>在開始寫心得前，先解釋一些常見的問題  </p><ol><li>好像很多人以為未來生涯體驗計劃的5個實習職位工作內容會跟同職位的實習生相同，其實不是這樣的，每個職位的實習生可能會在不同的部門下面工作，因此就算是同職位的實習生之間工作內容的差異也很大。</li><li>未來生涯體驗計劃官網上寫的委託人力資源公司是什麼意思？ 簡單來說就是這個實習計劃會透過人力資源公司來聘用實習生，在公司內實際的身份更接近contractor，就我所知微軟也有直聘的intern名額，但相對稀少，轉正的機會可能也比較大。</li></ol><h1 id="實習生活"><a href="#實習生活" class="headerlink" title="實習生活"></a>實習生活</h1><p>我當時在 Maps Services Engineering 實習的時候是可以完全WFH的，除了onboard和offboard時要去辦公室還電腦以外，大部分時候完全不進辦公室也沒關係。辦公室時不時會有一些小活動，像是萬聖節的時候有科學怪人、南瓜燈的軟餅乾，聖誕節時有熱紅酒、蛋糕、聖誕樹等等，因此雖然不是強制要進辦公室，但跟我同屆的實習生們還是會約好一起進辦公室，不管是討論一下各自的工作或是聊聊天。現在懷念起來那是一段很快樂的時光，實習的工作壓力沒有正職那麼大，通常也更容易拿到一些好玩的project可以做，也不會有太多routine但無聊的事。</p><p><img src="/post/Microsoft-RDI-%E5%AF%A6%E7%BF%92%E5%BF%83%E5%BE%97/christmas.png"></p><p>雖然說都是在 Maps Services Engineering 這個部門當intern，但其實每個實習生也會被分配到不同的小team，雖然都跟地圖服務有關，但每個team負責的事情不太一樣，這邊就不細談。每個intern都會有一個自己的mentor，通常mentor會負責帶intern做project，遇到技術上的問題或是流程上不懂的部分都可以問mentor。有些mentor也會關心實習生的生活，甚至會跟實習生討論找工作的心得XD跟正職們聊天獲益良多。實習生活快結束的時候，由於是做地圖相關的服務的部門，當時我所待的team還辦了一個大家一起玩geo guesser的活動，讓我驚訝的是大家都好厲害，可以看路牌就知道地點在哪，身為一個國外旅遊經驗不足的小小實習生，我都只能關麥在旁邊聽大家討論XD</p><p>在實習計劃中，除了主要的部門工作以外，我也參加了很多活動，像是校園分享會、工作坊、就業博覽會等等。每次跟其他學生分享自己準備面試、履歷、以及實習經驗的時候，我都覺得好像看到一兩年前的自己，坐在台下迫不及待地想要描繪未來的樣子。準備活動很累，要做簡報，要寫稿，要自己練好幾次，但每次結束後都覺得很值得。希望未來的我莫忘初心，成為一個樂於跟學生分享經驗的好前輩。</p><h1 id="軟體工程與軟實力"><a href="#軟體工程與軟實力" class="headerlink" title="軟體工程與軟實力"></a>軟體工程與軟實力</h1><p>未來生涯體驗計劃是一個長達一年的實習，我自己常聽到別人說短期的實習通常會給intern一個project來做，但不一定跟同部門的正職做的事情有關，最後你做的project可能實習結束就不會再被使用了。但長達一年的實習更像是一個小正職，大家會從原本就在做的事情中切出一部分給你，跟正職們的合作可能會更密切，不會像是自己做一個玩具小project的感覺。</p><p>在實習中我體會最深刻的是工程師不是一個人在工作，我個人以前還是學生身份的時候有一些迷思，覺得工程師不太需要與人交流，也不太需要什麼軟實力，只要技術能力夠強就好，但在實習中深深感受到資深工程師和自己的差距。</p><p>還記得實習剛開始時，跟mentor 1 on 1的時候都不知道要講什麼，做了一些東西但沒辦法清楚地說明，或是有問題的時候也沒辦法清楚地描述問題。但每次mentor都可以快速地釐清問題，並且用非常精準的文字描述出來，讓人一聽就懂。在意識到這個問題之後，我會在meeting開始前先整理一下這禮拜想要討論的內容，順便梳理一下細節，以方便meeting的時候可以快速說明。</p><p>跟自己一個人做project最大的不同，在工作中需要讓其他人也知道你在做什麼，可能是code層面，可能是feature層面，要清楚地解釋並讓合作的人都懂不是一件容易的事。在這個過程中可能需要寫design，需要寫document，需要畫圖，還記得我拿到最多comments的PR通常都不是跟code有關的，都是document沒寫清楚XD</p><p>如果讀者未來也想做軟體工程師，而且剛好有一個實習的機會，我會建議要利用這個機會好好觀察那些資深工程師都是怎麼開會，怎麼解決問題的。畢竟junior和senior負責的scope不一樣，如果不特別觀察，只focus在自己的事情上我覺得有點可惜，錯過了一個可以在正式工作前就提升軟實力的機會。</p><p>每週的1 on 1，除了討論project，我也會跟我的mentor討論一些soft skills、面試等話題的看法，我很感謝我的mentor願意百忙之中花時間跟我聊天，在微軟實習這段時間獲得的寶貴經驗讓我在之後開始正式工作後沒有遇到很大的陣痛期。</p><p>在 Maps Services Engineering 部門，intern會負責下一屆intern的面試，面試的形式就是傳統的coding interview，解白板題。當interviewer也是很有價值的一件事，在短時間內面試大量的candidates，有表現好的，也有表現不好的，可以從中總結出不少面試需要注意的事，而且大部分很難用文字或口頭傳遞，是一種interviewer視角的感受。除了面試coding interview以外，我也有參與到pm intern的behavioral interview。這段負責面試的經驗也為我之後找工作面試時帶來不小的幫助，不管是coding還是behavioral，更容易知道interviewer想要看到什麼樣的signal。</p><h1 id="突然的離別"><a href="#突然的離別" class="headerlink" title="突然的離別"></a>突然的離別</h1><p>在實習的過程中，離別其實並不稀有，那些常常跟我們聊天的正職，有人可能選擇轉team，有人則可能選擇離職。在實習快結束時，我所在的 Maps Services Engineering 部門經歷了一次大搬遷，從信義搬到南港，那個我和其他intern一起吃午餐，談笑風生的辦公室被拆了，取而代之的是一個遙遠且陌生的地方。再後來，經歷了一些組織變動上的調整，我不知道今年以後台灣還會不會有 Maps Services Engineering 的intern了</p>]]></content>
    
    
      
      
    <summary type="html">&lt;div class=&quot;custom-quote warning&quot;&gt;
&lt;span class=&quot;custom-quote-svg&quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;&quot; xmlns=&quot;http://www.</summary>
      
    
    
    
    <category term="Internship" scheme="https://mirrorshih.github.io/categories/Internship/"/>
    
    
    <category term="Internship" scheme="https://mirrorshih.github.io/tags/Internship/"/>
    
  </entry>
  
  <entry>
    <title>2023資工系普通人軟體工程師實習面試心得</title>
    <link href="https://mirrorshih.github.io/post/2023%E8%B3%87%E5%B7%A5%E7%B3%BB%E6%99%AE%E9%80%9A%E4%BA%BA%E8%BB%9F%E9%AB%94%E5%B7%A5%E7%A8%8B%E5%B8%AB%E5%AF%A6%E7%BF%92%E9%9D%A2%E8%A9%A6%E5%BF%83%E5%BE%97.html"/>
    <id>https://mirrorshih.github.io/post/2023%E8%B3%87%E5%B7%A5%E7%B3%BB%E6%99%AE%E9%80%9A%E4%BA%BA%E8%BB%9F%E9%AB%94%E5%B7%A5%E7%A8%8B%E5%B8%AB%E5%AF%A6%E7%BF%92%E9%9D%A2%E8%A9%A6%E5%BF%83%E5%BE%97.html</id>
    <published>2023-07-01T08:31:29.000Z</published>
    <updated>2025-04-19T10:21:25.677Z</updated>
    
    <content type="html"><![CDATA[<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>因為在找實習時很愛看前人們分享的找實習經驗，也受到很多幫助，因此決定來寫一篇我自己的實習面試經驗，在開始時想先跟讀這篇文章的大家說，如果你現在是剛踏入這個領域，未來也想找實習的學生，我個人覺得在看到這篇文章的時候就可以開始做我稍後提到的準備了，準備是越早開始越好。再來想跟同樣在努力找實習的各位說聲加油，如果被公司拒絕也不要氣餒，對你來說順位不高的公司拒絕你也不一定代表你不夠好，你心中的夢幻公司還是有機會錄取你！</p><h1 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h1><p>在找實習面試心得文時，常常看到背景是演算法競賽選手、已經有很多實習經驗或是Github破百stars的各路鬼神們，相較他們的話我的背景相當普通，可以給也想找實習但不是神人的各位參考</p><ul><li>118 CS 大三升大四</li><li>無演算法競賽、實習經驗</li><li>書卷獎x1</li><li>接過系上Online Judge的案子和校內行政單位的案子</li><li>一些高職到大學時累積的一些奇奇怪怪競賽經驗（感覺這部分有沒有差別不大）</li></ul><h1 id="面試結果"><a href="#面試結果" class="headerlink" title="面試結果"></a>面試結果</h1><p>先上面試結果的表格，等一下會講一下有面試到的公司的流程</p><table><thead><tr><th>公司</th><th>職位</th><th>有無面試</th><th>結果</th></tr></thead><tbody><tr><td>Google</td><td>SWE intern</td><td>無</td><td>感謝信</td></tr><tr><td><a href="#cooby">Cooby</a></td><td>Backend intern</td><td>有</td><td>無聲卡</td></tr><tr><td>LINE</td><td>TECH FRESH Backend</td><td>無</td><td>無聲卡</td></tr><tr><td>Yahoo</td><td>SWE intern</td><td>無</td><td>感謝信</td></tr><tr><td><a href="#%E6%97%A5%E5%95%86%E6%81%A9%E6%B2%9BNetProtections">日商恩沛NetProtections</a></td><td>實習生</td><td>有</td><td>感謝信</td></tr><tr><td>Synology</td><td>Collaboration Product intern</td><td>無</td><td>無聲卡</td></tr><tr><td>Appier</td><td>Backend intern</td><td>無</td><td>無聲卡</td></tr><tr><td>Skymizer</td><td>SWE intern</td><td>無</td><td>無聲卡</td></tr><tr><td><a href="#kkcompany">KKcompany</a></td><td>Tomorrow Lab Program</td><td>有</td><td>感謝信</td></tr><tr><td><a href="#hp">HP</a></td><td>SWE intern</td><td>有</td><td>感謝信</td></tr><tr><td>Dell</td><td>SWE intern</td><td>無</td><td>無聲卡</td></tr><tr><td><a href="#hpe">HPE</a></td><td>SWE intern</td><td>有</td><td>offer</td></tr><tr><td><a href="#garmin">Garmin</a></td><td>資訊處_網路應用服務 學期間實習生</td><td>有</td><td>offer</td></tr><tr><td>趨勢</td><td>軟體開發與測試</td><td>無</td><td>無聲卡</td></tr><tr><td><a href="#aics">AICS</a></td><td>Summer Internship(後來被轉成學期實習)</td><td>有</td><td>感謝信</td></tr><tr><td><a href="#microsoft">Microsoft</a></td><td>RDI</td><td>有</td><td>offer</td></tr></tbody></table><h1 id="準備"><a href="#準備" class="headerlink" title="準備"></a>準備</h1><p>關於如何準備我分成三個部分:</p><ul><li>履歷</li><li>LeetCode</li><li>英文</li></ul><p>除了這三點以外，面試還有可能會考學科知識和實務經驗等等，這些就交給大家自己想辦法累積了</p><h2 id="履歷"><a href="#履歷" class="headerlink" title="履歷"></a><span style="font-size:16px;">履歷</span></h2><p>履歷上最基本的就是要放上學歷，聯絡方式，過去的實習經驗等，如果是要面試外商公司的話不建議放個人照片，這部分大家可以去查查看。</p><p>除此之外，最重要的就是project了，我認為可以從一些解決生活中小痛點的方向去嘗試開始一些side project，像是如果你覺得學校的哪些系統沒有很好用，就可以試着自己去解決這些問題。</p><p>除此之外，做一些開源貢獻也能夠寫在履歷上，翻譯一些知名open source project的文件、發過PR等等，不要覺得這些事情可能很微不足道，如果你剛好遇到有相似經驗的面試官，就有機會勾起他的興趣，我有朋友就在面試時遇到面試官跟他聊翻譯文件的經驗。</p><h2 id="LeetCode"><a href="#LeetCode" class="headerlink" title="LeetCode"></a><span style="font-size:16px;">LeetCode</span></h2><p>LeetCode這部分我覺得大家可以視自己的目標公司來決定要不要刷，因為其實不是所有公司找實習生都一定會考LeetCode，可以多多參考之前的面試心得文</p><p>不過如果你的目標是Google, Microsoft等公司而且你沒有演算法競賽相關的背景，那我會建議越早開始刷越好</p><p>就算目標不是這些白板題佔比重的公司，如果有餘力的話還是儘量準備，有些不在面試中考白板題的公司也有可能有OA，或是一些簡單的現場coding（跑跑迴圈之類的），這時候如果你有常刷LeetCode的話會比較容易應對</p><p>我個人的話是從去年2022的4月中開始每天刷1~2題，在面試的這段時間大約在300~500題之間，LeetCode contest分數打到1900+就沒有再打了，應該是能夠突破2000分，如果要面試白板題難度高的公司建議至少要刷到跟我差不多的程度，即便到這個程度也沒有辦法保證一定能通過面試</p><p>題單的話我自己是刷<a href="https://www.techinterviewhandbook.org/grind75">Grind 169</a>，也有人會推薦<a href="https://neetcode.io/">NeetCode</a>之類的其他題單，雖然我沒有都刷過，但我猜測題單的內容大部分都大同小異，重點是在學習思考演算法和資料結構的解題過程，而不是把重點放在記住對應題目的固定解法，所以各位挑自己看得順眼的題單照着刷就好，沒有優劣之分</p><p>接下來想回答一些我在網路上看到的刷題新手可能會有的疑問，但由於我個人也不是面試官，僅能提供一些主觀淺見：</p><ul><li><p>Q1:刷題要用什麼語言呢？不想用C++可以用Python嗎？</p></li><li><p>A1:除非你面試的職位有特別限定語言，不然通常白板題的面試更注重在解題使用的方法和溝通上，OA平台通常也都會提供常見的語言（C/C++, Python, Java）來做選擇，因此用什麼語言來刷題對於面試的影響不大</p></li><li><p>Q2:刷題天賦比努力更重要嗎？</p></li><li><p>A2:依我的經驗來說我認為不是，面試中會出現的演算法題不像競賽那麼困難，去年我開始刷題時也是常常寫不出easy，但隨着題數的累積（前提是刷題時都有思考而不是直接看解答），很多題目在看完敘述時就能知道怎麼做，如果是要憑空創造那些演算法的話可能需要天賦沒錯，但刷題就是靠前人的智慧，將他們所想的東西刻在自己的腦中，我相信投入時間一定會有回報</p></li></ul><h2 id="英文"><a href="#英文" class="headerlink" title="英文"></a><span style="font-size:16px;">英文</span></h2><p>如果你面試的公司是外商的話，很有可能會在面試時需要英文口說，根據我和身邊朋友的經驗來說，這邊的口說可能是佔面試時的一小部分，也有可能是整場面試都使用全英文，因此建議要事先準備好相對應的英文自我介紹</p><p>除了口說以外，有些公司也會在面試前寄類似多益的英文測驗，但我也不確定這部分的表現是否真的會影響錄取結果</p><p>以我個人的經驗來說，在面試時的口說並不會要求你講得像native speaker一樣，沒有任何文法上的錯誤，只要能夠清楚得表達自己的想法，讓面試官能夠聽懂就OK，最重要的是要敢講，不要怕失誤就放棄</p><p>其實我也不是英文口說能力很好的人，而且如果沒有另外花錢請英文家教的話感覺不太會有能練英文口說的機會，因此我是參加我們校內跟英文演講有關的社團，花了1年的時間，一開始我也是都不敢開口說英文，很怕講錯尷尬在那，但每次在路上看到有外國人在問路，而且有人用一口流利的英文回答他的時候，就覺得英文講得好的人真的很帥</p><p>後來交了一些在學中文的外國朋友，我發現對方中文講得不清楚我聽不懂的時候，身為母語者的我其實會盡力的去引導和理解對方的意思，並不會懷有惡意的嘲笑對方，因此大家不用害怕開口說英文被嘲笑，只要願意開口都很勇敢，持之以恆的話一定會進步！</p><hr><p>結果上面這一大段好像寫了很多雞湯和自己找實習的時候觀察到的一些現象，好像對於如何準備沒有提太多QQ，大家可以再多多看其他人的心得文，最後我一句話想送給正在準備找實習的你</p><div class="language-txt"><button title="Copy code" class="copy"></button><span class="lang">txt</span><pre class="shiki material-theme-palenight" style="background-color: #1a1a1a" tabindex="0"><code><span class="line"><span style="color: #babed8">懦夫從不啟程，</span></span><span class="line"><span style="color: #babed8">弱者死於路中，</span></span><span class="line"><span style="color: #babed8">只剩我們前行，</span></span><span class="line"><span style="color: #babed8">一步都不能停！</span></span><span class="line"><span style="color: #babed8">        --Phil Knight</span></span></code></pre></div><hr><h1 id="面試流程"><a href="#面試流程" class="headerlink" title="面試流程"></a>面試流程</h1><p>關於下面的面試流程，我寫這篇文章的時候也過了一段時間，沒有記得很清楚，可能沒辦法提供非常準確的流程，如果各公司HR有任何不想公開的資訊，歡迎隨時聯絡<a href="mailto:mirrorshih@gmail.com">我</a>進行修改</p><h2 id="Cooby"><a href="#Cooby" class="headerlink" title="Cooby"></a>Cooby</h2><table><thead><tr><th>時程</th><th></th></tr></thead><tbody><tr><td>2022/11/16</td><td>投履歷</td></tr><tr><td>2022/11/23</td><td>收到HR面試通知</td></tr><tr><td>2022/12/1</td><td>HR面試</td></tr></tbody></table><h3 id="HR面試"><a href="#HR面試" class="headerlink" title="HR面試"></a>HR面試</h3><p>Cooby的HR在面試前有寄一封mail講面試當天的流程，裡面很貼心的提醒我該準備的問題，問題大概就是自我介紹、個人的優缺點、為什麼想來Cooby實習等等，一場面試大概就是30mins，一開始HR先介紹關於Cooby和收實習生的理由，再來就請我做自我介紹和相對應的問題回答，記得這段聊完之後好像時間差不多就到了，最後就以問對方想問的問題收尾</p><hr><p><span style="font-size:20px;">結果：無聲卡</span></p><h2 id="日商恩沛NetProtections"><a href="#日商恩沛NetProtections" class="headerlink" title="日商恩沛NetProtections"></a>日商恩沛NetProtections</h2><table><thead><tr><th>時程</th><th></th></tr></thead><tbody><tr><td>2023/1/1</td><td>投履歷（含前測問題）</td></tr><tr><td>2023/1/5</td><td>收到電話面試通知</td></tr><tr><td>2023/1/12</td><td>電話面試</td></tr><tr><td>2023/1/13</td><td>收到一面通知</td></tr><tr><td>2023/1/31</td><td>一面</td></tr><tr><td>2023/2/3</td><td>收到二面通知</td></tr><tr><td>2023/2/8</td><td>二面</td></tr><tr><td>2023/2/13</td><td>感謝信</td></tr></tbody></table><p>恩沛是一間做Fintech的公司，有興趣的話可以查查看，他們的實習計劃是讓實習生面試之後再選擇自己想要負責的工作和職位，蠻彈性的，作為一間新創公司，我覺得他們的面試蠻特別的，感覺他們非常注重實習生的個人特質，在面試的過程中沒有遇到任何技術問題</p><h3 id="前測"><a href="#前測" class="headerlink" title="前測"></a>前測</h3><p>在投遞履歷的時候，有一個前測問題，今年的是問對於台灣人平均收入和體罰的關係，沒有規定要如何回答這個問題，可以完全按照自己的想法去做，我個人是查了一些跟貧富差距，體罰相關的文章和論文，透過數據去佐證兩者之間的關聯，根據實習生說明會的說法，這個前測關卡非常重要，如果沒有認真寫很有可能沒辦法進入面試階段</p><h3 id="電話面試"><a href="#電話面試" class="headerlink" title="電話面試"></a>電話面試</h3><p>雖然說是電話面試，其實是需要線上開鏡頭對話的面試，在這一輪面試中也是要討論跟前者相似類型的社會議題，面試官會根據你的回答不斷做延伸，一開始聽到題目時面試官有給我5分鐘的時間去查我需要的資料，但其實5分鐘查不太到什麼資料，所以後續的回答我基本上就是按照個人想法去答</p><h3 id="一面"><a href="#一面" class="headerlink" title="一面"></a>一面</h3><p>從這一關面試開始，就會需要去公司的辦公室實體面試，恩沛的辦公室環境感覺還不錯，就是想像中新創公司會有的環境，因為這是我第一次實體面試，我很怕會找不到公司的位置，結果很早出發換來的就是太早到XD，我記得我提早了大概半小時就到辦公室，後來面試官有提早大約10分鐘開始我的面試，很感謝他</p><p>這一關的話沒有上面說的社會議題，面試官感覺會比較想了解我這個人，會從興趣、職涯規劃等問題下手</p><h3 id="二面"><a href="#二面" class="headerlink" title="二面"></a>二面</h3><p>這關的話我是跟在台灣的日本人工程師面試，他會講中文所以溝通上面沒有問題，有些詞不達意的時候可以靠Google翻譯幫忙，二面跟一面很像，也是聚焦在我身上，但二面感覺跟注重在我的價值觀上，總之是一次很有趣的經驗</p><hr><p><span style="font-size:20px;">結果：感謝信</span><br>恩沛的面試方式真的很特別，面試的問題都會從你的回答不斷進行延伸，所以其實面試完的時候會覺得很累</p><h2 id="KKcompany"><a href="#KKcompany" class="headerlink" title="KKcompany"></a>KKcompany</h2><table><thead><tr><th>時程</th><th></th></tr></thead><tbody><tr><td>2023/1/20</td><td>投履歷</td></tr><tr><td>2023/3/21</td><td>OA</td></tr><tr><td>2023/4/19</td><td>收到一面通知</td></tr><tr><td>2023/5/5</td><td>一面</td></tr><tr><td>2023/5/15</td><td>主動寄信詢問一面結果</td></tr><tr><td>2023/5/16</td><td>感謝信</td></tr></tbody></table><p>今年KKcompany的面試流程時間拖得蠻長的，在我面試那天結束時HR跟我說還要一兩週才會得知能否進二面，所以大家如果有投KKcompany的話不要太焦慮，慢慢等還有機會</p><h3 id="OA"><a href="#OA" class="headerlink" title="OA"></a>OA</h3><p>這是我第一次寫OA，平台是用Codility，我記得常見的語言都有，我在寫OA的前一天上去稍微熟悉了一下平台，HR是說只要50分就能推進下一關，然後要記得在OA的平台上面直接寫code，不要在自己的ide寫完貼上去，Codility好像會把作答過程錄下來給面試官參考的樣子</p><p>題目總共有4題，我自己體感是2 easy, 1 medium-, 1 medium+，作答時間有2小時，我寫了不到半小時就交了，後來拿到97分，漏了一個正確性相關的測資</p><h3 id="一面-1"><a href="#一面-1" class="headerlink" title="一面"></a>一面</h3><p>面試同時和HR以及另外兩位不同部門的主管面試，我朋友也有面這個實習計劃，不知道面試官是如何分配的，不同面試官的風格差很多，面試的流程也不一樣，根據我同學的說法，他遇到的面試官都在問他履歷相關的問題，而我遇到的面試官則是問了很多不同領域的問題，從API到DB到圖學到OOP到OS等等，能想到的領域都被問過一次了，算是一場題目轟炸的面試</p><hr><p><span style="font-size:20px;">結果：感謝信</span></p><h2 id="HP"><a href="#HP" class="headerlink" title="HP"></a>HP</h2><table><thead><tr><th>時程</th><th></th></tr></thead><tbody><tr><td>2023/2/22</td><td>投履歷</td></tr><tr><td>2023/3/23</td><td>收到電話面試通知</td></tr><tr><td>2023/3/30</td><td>電話面試</td></tr><tr><td>2023/4/26</td><td>感謝信</td></tr></tbody></table><h3 id="電話面試-1"><a href="#電話面試-1" class="headerlink" title="電話面試"></a>電話面試</h3><p>這次電話面試不是突襲式的電話面試，會先寄信約時間，面試時會進行簡單的英文對話，我這部分講超爛的，第一次面試講英文太緊張了，我猜可能就是這個原因被刷掉的，除了英文以外就是一場常規的HR面試，問為什麼想實習等等</p><hr><p><span style="font-size:20px;">結果：感謝信</span></p><h2 id="HPE"><a href="#HPE" class="headerlink" title="HPE"></a>HPE</h2><table><thead><tr><th>時程</th><th></th></tr></thead><tbody><tr><td>2023/3/14</td><td>投履歷</td></tr><tr><td>2023/4/14</td><td>收到HR電話約面試</td></tr><tr><td>2023/4/17</td><td>面試</td></tr><tr><td>2023/4/26</td><td>offer</td></tr></tbody></table><h3 id="面試"><a href="#面試" class="headerlink" title="面試"></a>面試</h3><p>HPE的面試流程比較簡單，第一次面試就是直接跟兩位部門主管面試，這次面試完就會直接決定錄不錄取，相對其他動不動就要好幾關的面試來說輕鬆很多</p><p>我面試的Team好像是做firmware QA的Team，兩位面試官人都超級親切，會很吸引我加入他們部門，風氣應該很不錯，在HR打電話來約面試時有說要準備5分鐘的英文自我介紹，我簡單做了一個ppt，在面試時分享畫面講給面試官聽</p><p>接下來就是問一些自我介紹和履歷相關的問題，聊完之後寫了一個簡單的題目，大概LeetCode easy的程度，在Google docs上面作答</p><p>最後的問答環節，面試官跟我說我可以慢慢想問題，他們都可以回答我，也跟我聊了很多職涯規劃等等的問題，很感謝他們願意花時間回答我這個還不一定會加入公司的面試者，能感受到HPE的正職員工真的有喜歡公司的感覺，這次面試的感受非常不錯</p><hr><p><span style="font-size:20px;">結果：offer</span></p><h2 id="Garmin"><a href="#Garmin" class="headerlink" title="Garmin"></a>Garmin</h2><table><thead><tr><th>時程</th><th></th></tr></thead><tbody><tr><td>2023/3/16</td><td>投履歷</td></tr><tr><td>2023/4/25</td><td>漏接電話</td></tr><tr><td>2023/4/26</td><td>HR電話約面試時間</td></tr><tr><td>2023/5/8</td><td>面試</td></tr><tr><td>2023/5/15</td><td>offer</td></tr></tbody></table><h3 id="面試-1"><a href="#面試-1" class="headerlink" title="面試"></a>面試</h3><p>Garmin的面試是一天面完HR面試和主管面試，在約定時間時先跟HR面試，差不多之後HR會通知主管來面試，在中間可以小小休息一下，大概5分鐘</p><p>我面試的部門是負責做Garmin商城服務的，主管說實習生進來的話會負責做QA，問我對於QA的意願如何，我說如果可以的話我更想接觸功能開發，主管就說如果我加入他們的話，可以等我熟悉系統之後做一些開發相關的工作，這點讓我蠻開心的，可以感受到主管還是有在意實習生的個人意願，不會覺得他分配什麼工作我就要做什麼，面試的過程中大部分就是聊履歷和過往的經驗</p><hr><p><span style="font-size:20px;">結果：offer</span></p><h2 id="AICS"><a href="#AICS" class="headerlink" title="AICS"></a>AICS</h2><table><thead><tr><th>時程</th><th></th></tr></thead><tbody><tr><td>2023/3/25</td><td>投履歷</td></tr><tr><td>2023/3/28</td><td>OA</td></tr><tr><td>2023/4/10</td><td>收到一面通知</td></tr><tr><td>2023/4/14</td><td>暑期實習改學期實習</td></tr><tr><td>2023/4/19</td><td>一面</td></tr><tr><td>2023/4/25</td><td>感謝信</td></tr></tbody></table><h3 id="OA-1"><a href="#OA-1" class="headerlink" title="OA"></a>OA</h3><p>OA在Codility上進行，語言的話沒什麼印象，總共有3題，難度都不會很難，但感覺比較靠巧思，比較特別的是有debug題，蠻有趣的，大概就是給你一段code和他預期的功能，要你只能改幾行，讓這段code功能正常，OA最後不會給結果，所以我也不知道我做得怎麼樣</p><h3 id="一面-2"><a href="#一面-2" class="headerlink" title="一面"></a>一面</h3><p>在OA結束後，HR就跟我約了一面的時間，結果在面試前收到AICS暑期實習收滿的消息，於是HR問我要不要換成學期實習，換成學期實習後還是維持原本的面試時間，面試的話就是考白板題，問了2題，第二題是第一題的延伸，第一題大概是LeetCode easy的難度，第二題的話難度介於medium和hard之間，我要了提示之後嘗試去寫，但時間到也沒有完整的寫出來</p><p>要注意的是如果面會考白板題的公司要準備一下local的編譯環境，因為我自己習慣用C++刷題，但都直接在對應的平台上面coding，結果AICS的面試官要我在本地跑結果給他看，但我本地的C++環境之前電腦重灌的時候沒有再裝，寫作業的時候可能都remote到其他linux系統寫，只能很尷尬的跟他說我能不能用online ide跑結果給他看</p><p>除此之外，建議大家面試時手機不要關通知，我那時候網路不好，面試官請HR打電話過來確認，結果我手機勿擾就都沒接到</p><hr><p><span style="font-size:20px;">結果：感謝信</span></p><h2 id="Microsoft"><a href="#Microsoft" class="headerlink" title="Microsoft"></a>Microsoft</h2><table><thead><tr><th>時程</th><th></th></tr></thead><tbody><tr><td>2023/4/1</td><td>投履歷</td></tr><tr><td>2023/4/14</td><td>接到電話面試（改時間）</td></tr><tr><td>2023/4/17</td><td>電話面試</td></tr><tr><td>2023/4/19</td><td>HR主管面試</td></tr><tr><td>2023/4/26</td><td>收到部門面試通知</td></tr><tr><td>2023/5/2</td><td>部門一面</td></tr><tr><td>2023/5/3</td><td>部門二面</td></tr><tr><td>2023/5/15</td><td>寄信問面試結果</td></tr><tr><td>2023/5/16</td><td>offer</td></tr></tbody></table><p>其實我去年大二時就嘗試過投微軟履歷，但當時連履歷都寫不好，也沒有對找實習這件事查資料做準備，因此沒有進到面試，但從那時候開始就有在準備LeetCode，還是很感謝去年的自己XD，大家如果投履歷第一次沒成功的話千萬不要氣餒，只要持續精進自己總有一天還是有機會找到自己的dream job</p><h3 id="電話面試-2"><a href="#電話面試-2" class="headerlink" title="電話面試"></a>電話面試</h3><p>微軟實習計劃的電話面試是突襲式的打過來，因此如果有投遞實習計劃的話要注意電話，第一次接到的時候我不方便講電話就改時間了</p><p>電話面試主要是確認一下投遞的職位和基本的資料，再來就是可能會需要簡單的英文對話，自我介紹等等</p><p>這次電話面試的最後HR就跟我約了HR主管的面試</p><h3 id="HR主管面試"><a href="#HR主管面試" class="headerlink" title="HR主管面試"></a>HR主管面試</h3><p>一開始進到面試的時候，HR主管就以英文開頭要我介紹一下自己，結果我語系一時沒切過來愣了一下，但馬上就有反應過來，應該還OK，接下來也是一些常規會遇到的問題，最後的話由HR主管做部門的介紹，然後問我對於每個部門的意願排序</p><h3 id="Bing-Geocoding部門面試"><a href="#Bing-Geocoding部門面試" class="headerlink" title="Bing Geocoding部門面試"></a>Bing Geocoding部門面試</h3><p>Bing Geocoding部門的面試是以白板題為主，總共會面試兩次，一次2題，我覺得整體來說難度滿高的，大概落在2題medium 2題hard的程度，如果也要面試這個部門的話刷題要認真一點</p><hr><p><span style="font-size:20px;">結果：offer</span></p><h1 id="結語"><a href="#結語" class="headerlink" title="結語"></a>結語</h1><p>第一次自己寫實習面試心得的文章，寫了7000+字（而且感覺沒寫什麼有用的內容）才知道原來寫面試心得文這麼累，真的很感謝每一個願意分享自己面試心得的前輩</p><p>最後我想要感謝所有在找實習過程中幫助過我的人<br>特別感謝<a href="https://www.linkedin.com/in/justyu2001"><strong>陳彥宇</strong></a>跟我一起在實習面試的路上一起交流奮鬥<br>感謝<a href="https://www.linkedin.com/in/yoyofish/"><strong>余昭佑</strong></a>花時間協助我改善英文自我介紹<br>感謝<a href="https://www.linkedin.com/in/hengrylin/"><strong>林宇亨</strong></a>幫我祈禱，還有你畫的頭貼都很讚<br>最後用林宇亨畫的圖片結束這篇文章，祝大家都可以跟圖片中的蛋蛋先生一樣成為offer收割機<br><img src="/post/2023%E8%B3%87%E5%B7%A5%E7%B3%BB%E6%99%AE%E9%80%9A%E4%BA%BA%E8%BB%9F%E9%AB%94%E5%B7%A5%E7%A8%8B%E5%B8%AB%E5%AF%A6%E7%BF%92%E9%9D%A2%E8%A9%A6%E5%BF%83%E5%BE%97/offer.png" alt="Mr.Egg offer"></p>]]></content>
    
    
      
      
    <summary type="html">&lt;h1 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h1&gt;&lt;p&gt;因為在找實習時很愛看前人們分享的找實習經驗，也受到很多幫助，因此決定來寫一篇我自己的實習面試經驗，在開始時想先跟讀這篇文章的大家說，如果你現</summary>
      
    
    
    
    <category term="Internship" scheme="https://mirrorshih.github.io/categories/Internship/"/>
    
    
    <category term="Internship" scheme="https://mirrorshih.github.io/tags/Internship/"/>
    
  </entry>
  
  <entry>
    <title>OpenGL 互動式水面</title>
    <link href="https://mirrorshih.github.io/post/OpenGL-%E4%BA%92%E5%8B%95%E5%BC%8F%E6%B0%B4%E9%9D%A2.html"/>
    <id>https://mirrorshih.github.io/post/OpenGL-%E4%BA%92%E5%8B%95%E5%BC%8F%E6%B0%B4%E9%9D%A2.html</id>
    <published>2022-02-06T08:48:18.000Z</published>
    <updated>2025-04-19T10:20:09.082Z</updated>
    
    <content type="html"><![CDATA[<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>會想寫這篇文章其實有一個契機，我在讀<a href="https://madebyevan.com/webgl-water/">WebGL Water</a> 的source code時，其中有一段程式碼中提到了 ping-pong rendering，不過在我自己搜尋資料時卻發現相關的技術幾乎沒有人對它進行比較詳細的解釋，在跟朋友抱怨這件事後，他說：「既然沒有人寫那你就可以寫一篇阿。」於是這篇文章就這樣誕生了。雖然說是OpenGL互動式水面，但這篇文章不會將重點放在實作細節上，會有很大一部分是WebGL Water source code導讀。</p><h1 id="目標受衆"><a href="#目標受衆" class="headerlink" title="目標受衆"></a>目標受衆</h1><ul><li>OpenGL/WebGL新手，想了解用GL製作水面的方式</li><li>正在台科電腦圖學導論痛苦掙扎的你</li></ul><h1 id="先備知識"><a href="#先備知識" class="headerlink" title="先備知識"></a>先備知識</h1><p>在看這篇文章之前，最好對下列的技術有一定程度的了解：</p><ul><li>OpenGL/WebGL（廢話）</li><li>FrameBuffer Object</li><li>Shader</li></ul><hr><p>那就讓我們開始吧</p><h1 id="Height-map"><a href="#Height-map" class="headerlink" title="Height map"></a>Height map</h1><p>首先我們要引入一個概念<strong>Height map</strong>，Height map的概念是將一張圖片的顏色（ex:rgb）當作水面的高度，這裏我以一張灰階圖爲例<br><img src="/post/OpenGL-%E4%BA%92%E5%8B%95%E5%BC%8F%E6%B0%B4%E9%9D%A2/water_gray.png"><br>我們先建一個有很多vertex的平面，將這張圖當作texture丟進vertex shader中，並在vertex shader中讀取這張圖的顏色（是灰階圖所以rgb相同，擇一即可），對當前的高度加上顏色的值，就能得到一個不平整的水面，這裏我們來看看WebGL Water是怎麼實作的</p><div class="language-txt"><button title="Copy code" class="copy"></button><span class="lang">txt</span><pre class="shiki material-theme-palenight" style="background-color: #1a1a1a" tabindex="0"><code><span class="line"><span style="color: #babed8">uniform sampler2D water;</span></span><span class="line"><span style="color: #babed8">varying vec3 position;</span></span><span class="line"><span style="color: #babed8">void main() {</span></span><span class="line"><span style="color: #babed8">vec4 info = texture2D(water, gl_Vertex.xy * 0.5 + 0.5);</span></span><span class="line"><span style="color: #babed8">position = gl_Vertex.xzy;</span></span><span class="line"><span style="color: #babed8">position.y += info.r;</span></span><span class="line"><span style="color: #babed8">gl_Position = gl_ModelViewProjectionMatrix * vec4(position, 1.0);</span></span><span class="line"><span style="color: #babed8">}</span></span></code></pre></div><p>用上圖面那張圖做出來的效果：<br><img src="/post/OpenGL-%E4%BA%92%E5%8B%95%E5%BC%8F%E6%B0%B4%E9%9D%A2/water_gray_example.png"></p><p>想象如果我們擁有一連串的水流動的灰階圖，按照順序畫出來，就可以模擬出水流動的效果了！</p><div class="custom-quote warning"><span class="custom-quote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M20.86 14.13C20 14.7 19.56 15.74 19.77 16.76C20.13 18.55 18.55 20.13 16.76 19.77C15.74 19.57 14.7 20 14.13 20.86C13.12 22.38 10.89 22.38 9.88 20.86C9.3 20 8.26 19.56 7.24 19.77C5.45 20.13 3.87 18.55 4.23 16.76C4.43 15.74 4 14.7 3.14 14.13C1.62 13.12 1.62 10.89 3.14 9.88C4 9.3 4.44 8.26 4.23 7.24C3.87 5.45 5.45 3.87 7.24 4.23C8.26 4.44 9.3 4 9.87 3.14C10.88 1.62 13.11 1.62 14.12 3.14C14.7 4 15.74 4.44 16.76 4.23C18.55 3.87 20.13 5.45 19.77 7.24C19.56 8.26 20 9.3 20.86 9.87C22.38 10.88 22.38 13.12 20.86 14.13Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M12 8V13"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M12 15.99V16.01"></path></svg></span><p class="custom-quote-title">WARNING</p><p>如果想要對這個平面染上水的顏色<br>記得要算normal<br>對不同高度的地方染不同的顏色<br>否則人眼會很難看出高度差</p></div><h1 id="Picking"><a href="#Picking" class="headerlink" title="Picking"></a>Picking</h1><p>再來我們來談談OpenGL中要如何實作滑鼠選取的功能，在OpenGL中我們可以使用下列兩種做法：  </p><ul><li>Ray tracing</li><li>Shader</li></ul><p>閱讀WebGL Water的source code可以發現他是選擇第一種方式來做，但今天我們這篇文章會把重點放在第二種做法上。  </p><hr><p>先解釋一下兩者的差別，Ray tracing是從滑鼠點擊的位置打出一條ray，用那條ray跟場景上的物件的面做intersection來判斷ray打到的位置，在場景上有很多面需要做intersection時計算量就會增加，而且實作起來也不是很容易。</p><hr><p>再來就是今天要介紹的方法，這個方法使用Shader來達成，相信讀者看到這可能會有一個疑問，Shader不是用來輸出的嗎？？？沒錯，而我們就是要使用輸出顏色的方式來達成選取的功能。  </p><p>要怎麼做呢？<br>其實很簡單，<br>我們開一個FrameBuffer Object（以下簡稱FBO），在裏面畫上水的平面，但這次我們要在fragment shader中將顏色畫成平面的texture coordinate。  </p><p>如下圖所示<br><img src="/post/OpenGL-%E4%BA%92%E5%8B%95%E5%BC%8F%E6%B0%B4%E9%9D%A2/water_pick.png"></p><div class="language-txt"><button title="Copy code" class="copy"></button><span class="lang">txt</span><pre class="shiki material-theme-palenight" style="background-color: #1a1a1a" tabindex="0"><code><span class="line"><span style="color: #babed8">#version 430 core</span></span><span class="line"><span style="color: #babed8">out vec4 f_color;</span></span><span class="line"><span style="color: #babed8"></span></span><span class="line"><span style="color: #babed8">in V_OUT</span></span><span class="line"><span style="color: #babed8">{</span></span><span class="line"><span style="color: #babed8">   vec3 position;</span></span><span class="line"><span style="color: #babed8">   vec3 normal;</span></span><span class="line"><span style="color: #babed8">   vec2 texture_coordinate;</span></span><span class="line"><span style="color: #babed8">} f_in;</span></span><span class="line"><span style="color: #babed8"></span></span><span class="line"><span style="color: #babed8">void main()</span></span><span class="line"><span style="color: #babed8">{   </span></span><span class="line"><span style="color: #babed8">    vec3 color = vec3(f_in.texture_coordinate.x,f_in.texture_coordinate.y,0.1);</span></span><span class="line"><span style="color: #babed8">    f_color = vec4(color, 1.0f);</span></span><span class="line"><span style="color: #babed8">}</span></span></code></pre></div><p>再來我們我們使用glReadPixels()來讀取滑鼠點擊位置的顏色，就能夠判斷點到的位置在水面上的相對位置了</p><div class="language-cpp"><button title="Copy code" class="copy"></button><span class="lang">cpp</span><pre class="shiki material-theme-palenight" style="background-color: #1a1a1a" tabindex="0"><code><span class="line"><span style="color: #82AAFF">glBindFramebuffer</span><span style="color: #89DDFF">(</span><span style="color: #BABED8">GL_READ_FRAMEBUFFER</span><span style="color: #89DDFF">,</span><span style="color: #BABED8"> framebufferPick</span><span style="color: #89DDFF">);</span></span><span class="line"><span style="color: #82AAFF">glReadBuffer</span><span style="color: #89DDFF">(</span><span style="color: #BABED8">GL_COLOR_ATTACHMENT0</span><span style="color: #89DDFF">);</span></span><span class="line"></span><span class="line"><span style="color: #FFCB6B">glm</span><span style="color: #89DDFF">::</span><span style="color: #BABED8">vec3 uv</span><span style="color: #89DDFF">;</span></span><span class="line"><span style="color: #82AAFF">glReadPixels</span><span style="color: #89DDFF">(</span><span style="color: #BABED8">mouse_x</span><span style="color: #89DDFF">,</span><span style="color: #BABED8"> mouse_y</span><span style="color: #89DDFF">,</span><span style="color: #BABED8"> </span><span style="color: #F78C6C">1</span><span style="color: #89DDFF">,</span><span style="color: #BABED8"> </span><span style="color: #F78C6C">1</span><span style="color: #89DDFF">,</span><span style="color: #BABED8"> GL_RGB</span><span style="color: #89DDFF">,</span><span style="color: #BABED8"> GL_FLOAT</span><span style="color: #89DDFF">,</span><span style="color: #BABED8"> </span><span style="color: #89DDFF">&amp;</span><span style="color: #BABED8">uv</span><span style="color: #89DDFF">[</span><span style="color: #F78C6C">0</span><span style="color: #89DDFF">]);</span></span><span class="line"></span><span class="line"><span style="color: #82AAFF">glReadBuffer</span><span style="color: #89DDFF">(</span><span style="color: #BABED8">GL_NONE</span><span style="color: #89DDFF">);</span></span><span class="line"><span style="color: #82AAFF">glBindFramebuffer</span><span style="color: #89DDFF">(</span><span style="color: #BABED8">GL_READ_FRAMEBUFFER</span><span style="color: #89DDFF">,</span><span style="color: #BABED8"> </span><span style="color: #F78C6C">0</span><span style="color: #89DDFF">);</span></span></code></pre></div><div class="custom-quote tip"><span class="custom-quote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M20.86 14.13C20 14.7 19.56 15.74 19.77 16.76C20.13 18.55 18.55 20.13 16.76 19.77C15.74 19.57 14.7 20 14.13 20.86C13.12 22.38 10.89 22.38 9.88 20.86C9.3 20 8.26 19.56 7.24 19.77C5.45 20.13 3.87 18.55 4.23 16.76C4.43 15.74 4 14.7 3.14 14.13C1.62 13.12 1.62 10.89 3.14 9.88C4 9.3 4.44 8.26 4.23 7.24C3.87 5.45 5.45 3.87 7.24 4.23C8.26 4.44 9.3 4 9.87 3.14C10.88 1.62 13.11 1.62 14.12 3.14C14.7 4 15.74 4.44 16.76 4.23C18.55 3.87 20.13 5.45 19.77 7.24C19.56 8.26 20 9.3 20.86 9.87C22.38 10.88 22.38 13.12 20.86 14.13Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M12.01 15C12.01 14.5 12.01 14.5 12.01 14.5C12.04 13.75 13 13.46 14.04 12.2C14.41 11.74 14.69 11.41 14.86 10.85C15.15 9.95 14.92 9.18 14.86 9.02C14.8 8.79 14.52 8 13.72 7.46C13.06 7.02 12.42 7 12.14 7C11.9 7 11.36 7 10.78 7.3C10.28 7.56 9.98 7.9 9.83 8.1C9.24 8.82 9.06 9.63 9 10.06"></path><path stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M11.99 18H12.01"></path></svg></span><p class="custom-quote-title">TIP</p><p>在輸出顏色時我們選擇將b設成固定的0.1<br>並在每次畫FBO時glClearColor()將b設成0.0<br>後續判斷點擊的顏色時則可透過b的值來判斷是否有點擊到水面<br>若b值爲0.0則無<br>爲0.1則有</p></div><div class="custom-quote warning"><span class="custom-quote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M20.86 14.13C20 14.7 19.56 15.74 19.77 16.76C20.13 18.55 18.55 20.13 16.76 19.77C15.74 19.57 14.7 20 14.13 20.86C13.12 22.38 10.89 22.38 9.88 20.86C9.3 20 8.26 19.56 7.24 19.77C5.45 20.13 3.87 18.55 4.23 16.76C4.43 15.74 4 14.7 3.14 14.13C1.62 13.12 1.62 10.89 3.14 9.88C4 9.3 4.44 8.26 4.23 7.24C3.87 5.45 5.45 3.87 7.24 4.23C8.26 4.44 9.3 4 9.87 3.14C10.88 1.62 13.11 1.62 14.12 3.14C14.7 4 15.74 4.44 16.76 4.23C18.55 3.87 20.13 5.45 19.77 7.24C19.56 8.26 20 9.3 20.86 9.87C22.38 10.88 22.38 13.12 20.86 14.13Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M12 8V13"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M12 15.99V16.01"></path></svg></span><p class="custom-quote-title">WARNING</p><p>在讀取滑鼠點擊位置的pixel時<br>要注意滑鼠的xy可能和水面貼圖的xy方向不一<br>需要根據情況調整傳入的滑鼠位置數值</p></div><h1 id="Ping-Pong-Rendering"><a href="#Ping-Pong-Rendering" class="headerlink" title="Ping-Pong Rendering"></a>Ping-Pong Rendering</h1><p>處理完點擊的功能了，接下來我們就來看看如何讓水產生漣漪吧。這裏就不得不提到此文誕生的原因，WebGL Water使用的ping-pong rendering。</p><hr><p>Ping-Pong Rendering其實是一個在實作上才需要使用的技術，今天我們想要計算水面漣漪的動態過程，我們需要前一張水面漣漪圖來當作下一張漣漪的輸入，透過前一張的高度來計算下一張的高度，Ping-Pong Rendering就是這個可以把每一次的畫面丟給下一次當輸入的技巧。<strong>江湖一點訣，講破毋值三仙錢。</strong>那我們就來看看要怎麼做吧。</p><hr><p>首先這個技巧的核心就是FBO render to texture的能力，我們會開兩個FBO，先畫FBO1，然後將FBO1輸出的那個texture丟到FBO2中當作輸入的texture，這時我們就能在FBO2中用shader來對前一張texture做想要的操作了。在FBO2中輸出的結果又可以丟回FBO1中當輸入，就像打乒乓球一樣。<br><img src="/post/OpenGL-%E4%BA%92%E5%8B%95%E5%BC%8F%E6%B0%B4%E9%9D%A2/ping_pong.png"></p><div class="custom-quote tip"><span class="custom-quote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M20.86 14.13C20 14.7 19.56 15.74 19.77 16.76C20.13 18.55 18.55 20.13 16.76 19.77C15.74 19.57 14.7 20 14.13 20.86C13.12 22.38 10.89 22.38 9.88 20.86C9.3 20 8.26 19.56 7.24 19.77C5.45 20.13 3.87 18.55 4.23 16.76C4.43 15.74 4 14.7 3.14 14.13C1.62 13.12 1.62 10.89 3.14 9.88C4 9.3 4.44 8.26 4.23 7.24C3.87 5.45 5.45 3.87 7.24 4.23C8.26 4.44 9.3 4 9.87 3.14C10.88 1.62 13.11 1.62 14.12 3.14C14.7 4 15.74 4.44 16.76 4.23C18.55 3.87 20.13 5.45 19.77 7.24C19.56 8.26 20 9.3 20.86 9.87C22.38 10.88 22.38 13.12 20.86 14.13Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M12.01 15C12.01 14.5 12.01 14.5 12.01 14.5C12.04 13.75 13 13.46 14.04 12.2C14.41 11.74 14.69 11.41 14.86 10.85C15.15 9.95 14.92 9.18 14.86 9.02C14.8 8.79 14.52 8 13.72 7.46C13.06 7.02 12.42 7 12.14 7C11.9 7 11.36 7 10.78 7.3C10.28 7.56 9.98 7.9 9.83 8.1C9.24 8.82 9.06 9.63 9 10.06"></path><path stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M11.99 18H12.01"></path></svg></span><p class="custom-quote-title">TIP</p><p>Ping-Pong Rendering適用在後面的texture依賴前面texture的情況<br>舉一個常見的例子<br>Gaussian Blur就是使用Ping-Pong Rendering的好地方</p></div><h1 id="漣漪"><a href="#漣漪" class="headerlink" title="漣漪"></a>漣漪</h1><p>學會了Ping-Pong Rendering，我們終於可以來繪製漣漪了，我們來看看WebGL Water是怎麼實作的。</p><div class="custom-quote warning"><span class="custom-quote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M20.86 14.13C20 14.7 19.56 15.74 19.77 16.76C20.13 18.55 18.55 20.13 16.76 19.77C15.74 19.57 14.7 20 14.13 20.86C13.12 22.38 10.89 22.38 9.88 20.86C9.3 20 8.26 19.56 7.24 19.77C5.45 20.13 3.87 18.55 4.23 16.76C4.43 15.74 4 14.7 3.14 14.13C1.62 13.12 1.62 10.89 3.14 9.88C4 9.3 4.44 8.26 4.23 7.24C3.87 5.45 5.45 3.87 7.24 4.23C8.26 4.44 9.3 4 9.87 3.14C10.88 1.62 13.11 1.62 14.12 3.14C14.7 4 15.74 4.44 16.76 4.23C18.55 3.87 20.13 5.45 19.77 7.24C19.56 8.26 20 9.3 20.86 9.87C22.38 10.88 22.38 13.12 20.86 14.13Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M12 8V13"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M12 15.99V16.01"></path></svg></span><p class="custom-quote-title">WARNING</p><p>如果你是使用OpenGL，<br>那此處需要注意你開的texture要可以進行浮點數運算，<br>在WebGL中他是使用gl.RGBA的形式，<br>但在OpenGL中要使用如GL_RGB32F的internal format</p></div><div class="language-txt"><button title="Copy code" class="copy"></button><span class="lang">txt</span><pre class="shiki material-theme-palenight" style="background-color: #1a1a1a" tabindex="0"><code><span class="line"><span style="color: #babed8">uniform sampler2D texture;</span></span><span class="line"><span style="color: #babed8">uniform vec2 delta;</span></span><span class="line"><span style="color: #babed8">varying vec2 coord;</span></span><span class="line"><span style="color: #babed8">void main() {</span></span><span class="line"><span style="color: #babed8">  /* get vertex info */</span></span><span class="line"><span style="color: #babed8">  vec4 info = texture2D(texture, coord);</span></span><span class="line"><span style="color: #babed8">  </span></span><span class="line"><span style="color: #babed8">  /* calculate average neighbor height */</span></span><span class="line"><span style="color: #babed8">  vec2 dx = vec2(delta.x, 0.0);</span></span><span class="line"><span style="color: #babed8">  vec2 dy = vec2(0.0, delta.y);</span></span><span class="line"><span style="color: #babed8">  float average = (</span></span><span class="line"><span style="color: #babed8">    texture2D(texture, coord - dx).r +</span></span><span class="line"><span style="color: #babed8">    texture2D(texture, coord - dy).r +</span></span><span class="line"><span style="color: #babed8">    texture2D(texture, coord + dx).r +</span></span><span class="line"><span style="color: #babed8">    texture2D(texture, coord + dy).r</span></span><span class="line"><span style="color: #babed8">  ) * 0.25;</span></span><span class="line"><span style="color: #babed8">  </span></span><span class="line"><span style="color: #babed8">  /* change the velocity to move toward the average */</span></span><span class="line"><span style="color: #babed8">  info.g += (average - info.r) * 2.0;</span></span><span class="line"><span style="color: #babed8">  </span></span><span class="line"><span style="color: #babed8">  /* attenuate the velocity a little so waves do not last forever */</span></span><span class="line"><span style="color: #babed8">  info.g *= 0.995;</span></span><span class="line"><span style="color: #babed8">  </span></span><span class="line"><span style="color: #babed8">  /* move the vertex along the velocity */</span></span><span class="line"><span style="color: #babed8">  info.r += info.g;</span></span><span class="line"><span style="color: #babed8">  </span></span><span class="line"><span style="color: #babed8">  gl_FragColor = info;</span></span><span class="line"><span style="color: #babed8">}</span></span></code></pre></div><p>我們把這個shader當作剛剛提到的Ping-Pong Rendering繪製texture的fragment shader，每次都拿前一張的texture，找當前位置附近高度的平均來當作這次這個位置的高度。</p><hr><p>那現在我們可以模擬漣漪的流動過程了，所以我們需要加一個在滑鼠點擊時產生的漣漪，一樣來看WebGL Water是怎麼做的</p><div class="language-txt"><button title="Copy code" class="copy"></button><span class="lang">txt</span><pre class="shiki material-theme-palenight" style="background-color: #1a1a1a" tabindex="0"><code><span class="line"><span style="color: #babed8">const float PI = 3.141592653589793;</span></span><span class="line"><span style="color: #babed8">uniform sampler2D texture;</span></span><span class="line"><span style="color: #babed8">uniform vec2 center;</span></span><span class="line"><span style="color: #babed8">uniform float radius;</span></span><span class="line"><span style="color: #babed8">uniform float strength;</span></span><span class="line"><span style="color: #babed8">varying vec2 coord;</span></span><span class="line"><span style="color: #babed8">void main() {</span></span><span class="line"><span style="color: #babed8">  /* get vertex info */</span></span><span class="line"><span style="color: #babed8">  vec4 info = texture2D(texture, coord);</span></span><span class="line"><span style="color: #babed8">  </span></span><span class="line"><span style="color: #babed8">  /* add the drop to the height */</span></span><span class="line"><span style="color: #babed8">  float drop = max(0.0, 1.0 - length(center * 0.5 + 0.5 - coord) / radius);</span></span><span class="line"><span style="color: #babed8">  drop = 0.5 - cos(drop * PI) * 0.5;</span></span><span class="line"><span style="color: #babed8">  info.r += drop * strength;</span></span><span class="line"><span style="color: #babed8">  </span></span><span class="line"><span style="color: #babed8">  gl_FragColor = info;</span></span><span class="line"><span style="color: #babed8">}</span></span></code></pre></div><p>至此，我們就可以產生漣漪了</p><div class="language-cpp"><button title="Copy code" class="copy"></button><span class="lang">cpp</span><pre class="shiki material-theme-palenight" style="background-color: #1a1a1a" tabindex="0"><code><span class="line"><span style="color: #82AAFF">glBindFramebuffer</span><span style="color: #89DDFF">(</span><span style="color: #BABED8">GL_READ_FRAMEBUFFER</span><span style="color: #89DDFF">,</span><span style="color: #BABED8"> framebufferPick</span><span style="color: #89DDFF">);</span></span><span class="line"><span style="color: #82AAFF">glReadBuffer</span><span style="color: #89DDFF">(</span><span style="color: #BABED8">GL_COLOR_ATTACHMENT0</span><span style="color: #89DDFF">);</span></span><span class="line"></span><span class="line"><span style="color: #FFCB6B">glm</span><span style="color: #89DDFF">::</span><span style="color: #BABED8">vec3 uv</span><span style="color: #89DDFF">;</span></span><span class="line"><span style="color: #82AAFF">glReadPixels</span><span style="color: #89DDFF">(</span><span style="color: #BABED8">mouse_x</span><span style="color: #89DDFF">,</span><span style="color: #BABED8"> mouse_y</span><span style="color: #89DDFF">,</span><span style="color: #BABED8"> </span><span style="color: #F78C6C">1</span><span style="color: #89DDFF">,</span><span style="color: #BABED8"> </span><span style="color: #F78C6C">1</span><span style="color: #89DDFF">,</span><span style="color: #BABED8"> GL_RGB</span><span style="color: #89DDFF">,</span><span style="color: #BABED8"> GL_FLOAT</span><span style="color: #89DDFF">,</span><span style="color: #BABED8"> </span><span style="color: #89DDFF">&amp;</span><span style="color: #BABED8">uv</span><span style="color: #89DDFF">[</span><span style="color: #F78C6C">0</span><span style="color: #89DDFF">]);</span></span><span class="line"></span><span class="line"><span style="color: #82AAFF">glReadBuffer</span><span style="color: #89DDFF">(</span><span style="color: #BABED8">GL_NONE</span><span style="color: #89DDFF">);</span></span><span class="line"><span style="color: #82AAFF">glBindFramebuffer</span><span style="color: #89DDFF">(</span><span style="color: #BABED8">GL_READ_FRAMEBUFFER</span><span style="color: #89DDFF">,</span><span style="color: #BABED8"> </span><span style="color: #F78C6C">0</span><span style="color: #89DDFF">);</span></span><span class="line"><span style="color: #89DDFF; font-style: italic">if</span><span style="color: #BABED8"> </span><span style="color: #89DDFF">(</span><span style="color: #BABED8">uv</span><span style="color: #89DDFF">.</span><span style="color: #BABED8">z </span><span style="color: #89DDFF">!=</span><span style="color: #BABED8"> </span><span style="color: #F78C6C">0.0</span><span style="color: #89DDFF">)</span></span><span class="line"><span style="color: #89DDFF">{</span></span><span class="line"><span style="color: #F07178">    </span><span style="color: #89DDFF">this-&gt;</span><span style="color: #82AAFF">addDrop</span><span style="color: #89DDFF">(</span><span style="color: #FFCB6B">glm</span><span style="color: #89DDFF">::</span><span style="color: #82AAFF">vec2</span><span style="color: #89DDFF">(</span><span style="color: #F07178">uv</span><span style="color: #89DDFF">));</span></span><span class="line"><span style="color: #89DDFF">}</span></span></code></pre></div><p>在addDrop function中，我們就把Ping-Pong Rendering那兩個FBO的texture拿出來用產生漣漪的shader畫一次，然後丟回去繼續update就可以了。<br><img src="/post/OpenGL-%E4%BA%92%E5%8B%95%E5%BC%8F%E6%B0%B4%E9%9D%A2/cover.png"></p>]]></content>
    
    
      
      
    <summary type="html">&lt;h1 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h1&gt;&lt;p&gt;會想寫這篇文章其實有一個契機，我在讀&lt;a href=&quot;https://madebyevan.com/webgl-water/&quot;&gt;WebGL </summary>
      
    
    
    
    <category term="Computer Graphics" scheme="https://mirrorshih.github.io/categories/Computer-Graphics/"/>
    
    
    <category term="Computer Graphics" scheme="https://mirrorshih.github.io/tags/Computer-Graphics/"/>
    
    <category term="OpenGL" scheme="https://mirrorshih.github.io/tags/OpenGL/"/>
    
  </entry>
  
</feed>
