<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 第十一課:2D文本 # 第十一課:2D文本 本課將學習如何在三維場景之上繪制二維文本。本例是一個簡單的計時器: ![](https://box.kancloud.cn/2015-11-02_5636f306628c8.png) ## API 我們將實現這些簡單的接口(位于`common/text2D.h`): ``` <pre class="calibre16">``` void <span class="token3">initText2D</span><span class="token1">(</span>const char <span class="token">*</span> texturePath<span class="token1">)</span><span class="token1">;</span> void <span class="token3">printText2D</span><span class="token1">(</span>const char <span class="token">*</span> text<span class="token1">,</span> int x<span class="token1">,</span> int y<span class="token1">,</span> int size<span class="token1">)</span><span class="token1">;</span> void <span class="token3">cleanupText2D</span><span class="token1">(</span><span class="token1">)</span><span class="token1">;</span> ``` ``` 為了讓代碼在640\*480和1080p分辨率下都能正常工作,x和y的范圍分別設為\[0-800\]和\[0-600\]。頂點著色器將根據實際屏幕大小做對它做調整。 完整的實現代碼請參閱`common/text2D.cpp`。 ## 紋理 `initText2D`簡單地讀取一個紋理和一些著色器,很好理解。來看看紋理: ![](https://box.kancloud.cn/2015-11-02_5636f30685ab5.png) 該紋理由[CBFG](http://www.codehead.co.uk/cbfg/)生成。CBFG是諸多從字體生成紋理的工具之一。[把紋理加載到Paint.NET](http://xn--Paint-6o6h7zu10h846atmw824b.NET),加上紅色背景(僅為了觀察方便;本教程中的紅色背景,都代表透明)。 `printText2D()`在屏幕的適當位置,生成一個紋理坐標正確的四邊形。 ## 繪制 首先,填充這些緩沖區: ``` <pre class="calibre16">``` std<span class="token1">:</span><span class="token1">:</span>vector<span class="token"><</span>glm<span class="token1">:</span><span class="token1">:</span>vec2<span class="token">></span> vertices<span class="token1">;</span> std<span class="token1">:</span><span class="token1">:</span>vector<span class="token"><</span>glm<span class="token1">:</span><span class="token1">:</span>vec2<span class="token">></span> UVs<span class="token1">;</span> ``` ``` 文本中的每個字母,都要計算其四邊形包圍盒的頂點坐標,然后添加兩個三角形(組成一個四邊形): ``` <pre class="calibre16">``` <span class="token4">for</span> <span class="token1">(</span> unsigned int i<span class="token">=</span><span class="token6">0</span> <span class="token1">;</span> i<span class="token"><</span>length <span class="token1">;</span> i<span class="token">++</span> <span class="token1">)</span><span class="token1">{</span> glm<span class="token1">:</span><span class="token1">:</span>vec2 vertex_up_left<span class="token">?</span><span class="token">?</span><span class="token">?</span> <span class="token">=</span> glm<span class="token1">:</span><span class="token1">:</span><span class="token3">vec2</span><span class="token1">(</span> x<span class="token">+</span>i<span class="token">*</span>size<span class="token">?</span><span class="token">?</span><span class="token">?</span><span class="token">?</span> <span class="token1">,</span> y<span class="token">+</span>size <span class="token1">)</span><span class="token1">;</span> glm<span class="token1">:</span><span class="token1">:</span>vec2 vertex_up_right<span class="token">?</span><span class="token">?</span> <span class="token">=</span> glm<span class="token1">:</span><span class="token1">:</span><span class="token3">vec2</span><span class="token1">(</span> x<span class="token">+</span>i<span class="token">*</span>size<span class="token">+</span>size<span class="token1">,</span> y<span class="token">+</span>size <span class="token1">)</span><span class="token1">;</span> glm<span class="token1">:</span><span class="token1">:</span>vec2 vertex_down_right <span class="token">=</span> glm<span class="token1">:</span><span class="token1">:</span><span class="token3">vec2</span><span class="token1">(</span> x<span class="token">+</span>i<span class="token">*</span>size<span class="token">+</span>size<span class="token1">,</span> y<span class="token">?</span><span class="token">?</span><span class="token">?</span><span class="token">?</span><span class="token">?</span> <span class="token1">)</span><span class="token1">;</span> glm<span class="token1">:</span><span class="token1">:</span>vec2 vertex_down_left<span class="token">?</span> <span class="token">=</span> glm<span class="token1">:</span><span class="token1">:</span><span class="token3">vec2</span><span class="token1">(</span> x<span class="token">+</span>i<span class="token">*</span>size<span class="token">?</span><span class="token">?</span><span class="token">?</span><span class="token">?</span> <span class="token1">,</span> y<span class="token">?</span><span class="token">?</span><span class="token">?</span><span class="token">?</span><span class="token">?</span> <span class="token1">)</span><span class="token1">;</span> vertices<span class="token1">.</span><span class="token3">push_back</span><span class="token1">(</span>vertex_up_left<span class="token">?</span><span class="token">?</span> <span class="token1">)</span><span class="token1">;</span> vertices<span class="token1">.</span><span class="token3">push_back</span><span class="token1">(</span>vertex_down_left <span class="token1">)</span><span class="token1">;</span> vertices<span class="token1">.</span><span class="token3">push_back</span><span class="token1">(</span>vertex_up_right<span class="token">?</span> <span class="token1">)</span><span class="token1">;</span> vertices<span class="token1">.</span><span class="token3">push_back</span><span class="token1">(</span>vertex_down_right<span class="token1">)</span><span class="token1">;</span> vertices<span class="token1">.</span><span class="token3">push_back</span><span class="token1">(</span>vertex_up_right<span class="token1">)</span><span class="token1">;</span> vertices<span class="token1">.</span><span class="token3">push_back</span><span class="token1">(</span>vertex_down_left<span class="token1">)</span><span class="token1">;</span> ``` ``` 輪到UV坐標了。計算左上角的坐標: ``` <pre class="calibre16">``` char character <span class="token">=</span> text<span class="token1">[</span>i<span class="token1">]</span><span class="token1">;</span> float uv_x <span class="token">=</span> <span class="token1">(</span>character<span class="token">%</span><span class="token6">16</span><span class="token1">)</span><span class="token">/</span><span class="token6">16.0</span>f<span class="token1">;</span> float uv_y <span class="token">=</span> <span class="token1">(</span>character<span class="token">/</span><span class="token6">16</span><span class="token1">)</span><span class="token">/</span><span class="token6">16.0</span>f<span class="token1">;</span> ``` ``` 這樣做是可行的(基本可行,詳見下文),因為[A的ASCII值](http://www.asciitable.com/)為65。65%16 = 1,因此A位于第1列(列號從0開始)。 65/16 = 4,因此A位于第4行(這是整數除法,所以結果不是想象中的4.0625) 兩者都除以16.0以使之落于\[0.0 - 1.0\]區間內,這正是OpenGL紋理所需的。 現在只需對頂點重復相同的操作: ``` <pre class="calibre16">``` glm<span class="token1">:</span><span class="token1">:</span>vec2 uv_up_left <span class="token">=</span> glm<span class="token1">:</span><span class="token1">:</span><span class="token3">vec2</span><span class="token1">(</span> uv_x <span class="token1">,</span> <span class="token6">1.0</span>f <span class="token">-</span> uv_y <span class="token1">)</span><span class="token1">;</span> glm<span class="token1">:</span><span class="token1">:</span>vec2 uv_up_right <span class="token">=</span> glm<span class="token1">:</span><span class="token1">:</span><span class="token3">vec2</span><span class="token1">(</span> uv_x<span class="token">+</span><span class="token6">1.0</span>f<span class="token">/</span><span class="token6">16.0</span>f<span class="token1">,</span> <span class="token6">1.0</span>f <span class="token">-</span> uv_y <span class="token1">)</span><span class="token1">;</span> glm<span class="token1">:</span><span class="token1">:</span>vec2 uv_down_right <span class="token">=</span> glm<span class="token1">:</span><span class="token1">:</span><span class="token3">vec2</span><span class="token1">(</span> uv_x<span class="token">+</span><span class="token6">1.0</span>f<span class="token">/</span><span class="token6">16.0</span>f<span class="token1">,</span> <span class="token6">1.0</span>f <span class="token">-</span> <span class="token1">(</span>uv_y <span class="token">+</span> <span class="token6">1.0</span>f<span class="token">/</span><span class="token6">16.0</span>f<span class="token1">)</span> <span class="token1">)</span><span class="token1">;</span> glm<span class="token1">:</span><span class="token1">:</span>vec2 uv_down_left <span class="token">=</span> glm<span class="token1">:</span><span class="token1">:</span><span class="token3">vec2</span><span class="token1">(</span> uv_x <span class="token1">,</span> <span class="token6">1.0</span>f <span class="token">-</span> <span class="token1">(</span>uv_y <span class="token">+</span> <span class="token6">1.0</span>f<span class="token">/</span><span class="token6">16.0</span>f<span class="token1">)</span> <span class="token1">)</span><span class="token1">;</span> UVs<span class="token1">.</span><span class="token3">push_back</span><span class="token1">(</span>uv_up_left <span class="token1">)</span><span class="token1">;</span> UVs<span class="token1">.</span><span class="token3">push_back</span><span class="token1">(</span>uv_down_left <span class="token1">)</span><span class="token1">;</span> UVs<span class="token1">.</span><span class="token3">push_back</span><span class="token1">(</span>uv_up_right <span class="token1">)</span><span class="token1">;</span> UVs<span class="token1">.</span><span class="token3">push_back</span><span class="token1">(</span>uv_down_right<span class="token1">)</span><span class="token1">;</span> UVs<span class="token1">.</span><span class="token3">push_back</span><span class="token1">(</span>uv_up_right<span class="token1">)</span><span class="token1">;</span> UVs<span class="token1">.</span><span class="token3">push_back</span><span class="token1">(</span>uv_down_left<span class="token1">)</span><span class="token1">;</span> <span class="token1">}</span> ``` ``` 其余的操作和往常一樣:綁定緩沖區,填充,選擇著色器程序,綁定紋理,開啟、綁定、配置頂點屬性,開啟混合,調用glDrawArrays。歐也,搞定了。 注意非常重要的一點:這些坐標位于\[0,800\]\[0,600\]范圍內。也就是說,這里**不需要**矩陣。vertex shader只需簡單換算就可以把這些坐標轉換到\[-1,1\]\[-1,1\]范圍內(也可以在C++代碼中完成這一步)。 ``` <pre class="calibre16">``` void <span class="token3">main</span><span class="token1">(</span><span class="token1">)</span><span class="token1">{</span> <span class="token2">// Output position of the vertex, in clip space</span> <span class="token2">// map [0..800][0..600] to [-1..1][-1..1]</span> vec2 vertexPosition_homoneneousspace <span class="token">=</span> vertexPosition_screenspace <span class="token">-</span> <span class="token3">vec2</span><span class="token1">(</span><span class="token6">400</span><span class="token1">,</span><span class="token6">300</span><span class="token1">)</span><span class="token1">;</span> <span class="token2">// [0..800][0..600] -> [-400..400][-300..300]</span> vertexPosition_homoneneousspace <span class="token">/</span><span class="token">=</span> <span class="token3">vec2</span><span class="token1">(</span><span class="token6">400</span><span class="token1">,</span><span class="token6">300</span><span class="token1">)</span><span class="token1">;</span> gl_Position <span class="token">=</span> <span class="token3">vec4</span><span class="token1">(</span>vertexPosition_homoneneousspace<span class="token1">,</span><span class="token6">0</span><span class="token1">,</span><span class="token6">1</span><span class="token1">)</span><span class="token1">;</span> <span class="token2">// UV of the vertex. No special space for this one.</span> UV <span class="token">=</span> vertexUV<span class="token1">;</span> <span class="token1">}</span> ``` ``` fragment shader的工作也很少: ``` <pre class="calibre16">``` void <span class="token3">main</span><span class="token1">(</span><span class="token1">)</span><span class="token1">{</span> color <span class="token">=</span> <span class="token3">texture</span><span class="token1">(</span> myTextureSampler<span class="token1">,</span> UV <span class="token1">)</span><span class="token1">;</span> <span class="token1">}</span> ``` ``` 順便說一下,別在工程中使用這些代碼,因為它只能處理拉丁字符。否則你的產品在印度、中國、日本(甚至德國,因為紋理上沒有?這個字母)就別想賣了。這幅紋理是我用法語字符集生成的,在法國用用還可以(注意 é, à, ?等字母)。修改其他教程的代碼時注意庫的使用。其他教程大多使用OpenGL 2,和本教程不兼容。很可惜,我還沒找到一個足夠好的、能處理UTF-8字符集的庫。 順帶提一下,您最好看看Joel Spolsky寫的[The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)](http://www.joelonsoftware.com/articles/Unicode.html)。 如果您需要處理大量的文本,可以參考這篇[Valve的文章](http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf)。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看