<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>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # 第二課:畫第一個三角形 # 第二課: 畫第一個三角形 這將又是一篇長教程。 用OpenGL 3實現復雜的東西很方便;為此付出的代價是,畫一個簡單的三角形變得比較麻煩。 不要忘了,定期復制粘貼,跑一下代碼。 > 如果程序啟動時崩潰了,很可能是你從錯誤的目錄下運行了它。請仔細地閱讀第一課中講到的如何配置Visual Studio! ## 頂點數組對象(VAO) 你需要創建一個頂點數組對象,并將它設為當前對象(細節暫不深入): ``` <pre class="calibre16">``` GLuint VertexArrayID<span class="token1">;</span> <span class="token3">glGenVertexArrays</span><span class="token1">(</span><span class="token6">1</span><span class="token1">,</span> <span class="token">&</span>VertexArrayID<span class="token1">)</span><span class="token1">;</span> <span class="token3">glBindVertexArray</span><span class="token1">(</span>VertexArrayID<span class="token1">)</span><span class="token1">;</span> ``` ``` 當窗口創建成功后(即OpenGL上下文創建后),馬上做這一步工作;必須在任何其他OpenGL調用前完成。 若想進一步了解頂點數組對象(VAO),可以參考其他教程;但這不是很重要。 ## 屏幕坐標系 三點定義一個三角形。當我們在三維圖形學中談論“點(point)”時,我們經常說“頂點(Vertex)”。一個頂點有三個坐標:X,Y和Z。你可以用以下方式來想象這三個坐標: X 在你的右方Y 在你的上方Z 是你背后的方向(是的,背后,而不是你的前方)這里有一個更形象的方法:使用右手定則 X 是你的拇指Y 是你的食指Z 是你的中指。如果你把你的拇指指向右邊,食指指向天空,那么中指將指向你的背后。讓Z指往這個方向很奇怪,為什么要這樣呢?簡單的說:因為基于右手定則的坐標系被廣泛使用了100多年,它會給你很多有用的數學工具;而唯一的缺點只是Z方向不直觀。 `補充:`注意,你可以自由地移動你的手:你的X,Y和Z軸也將跟著移動(詳見后文)。 我們需要三個三維點來組成一個三角形;現在開始: ``` <pre class="calibre16">``` <span class="token2">// An array of 3 vectors which represents 3 vertices</span> static const GLfloat g_vertex_buffer_data<span class="token1">[</span><span class="token1">]</span> <span class="token">=</span> <span class="token1">{</span> <span class="token">-</span><span class="token6">1.0</span>f<span class="token1">,</span> <span class="token">-</span><span class="token6">1.0</span>f<span class="token1">,</span> <span class="token6">0.0</span>f<span class="token1">,</span> <span class="token6">1.0</span>f<span class="token1">,</span> <span class="token">-</span><span class="token6">1.0</span>f<span class="token1">,</span> <span class="token6">0.0</span>f<span class="token1">,</span> <span class="token6">0.0</span>f<span class="token1">,</span><span class="token">?</span> <span class="token6">1.0</span>f<span class="token1">,</span> <span class="token6">0.0</span>f<span class="token1">,</span> <span class="token1">}</span><span class="token1">;</span> ``` ``` 第一個頂點是(-1, -1, 0)。 這意味著除非我們以某種方式變換它,否則它將顯示在屏幕的(-1, -1)位置。什么意思呢?屏幕的原點在中間,X在右方,Y在上方。屏幕坐標如下圖: ![](https://box.kancloud.cn/2015-11-02_5636f301c85be.png) 該機制內置于顯卡,無法改變。因此(-1, -1)是屏幕的左下角,(1, -1)是右下角,(0, 1)在中上位置。這個三角形應該占滿了大部分屏幕。 ## 畫我們的三角形 下一步把這個三角形傳給OpenGL。我們通過創建一個緩沖區完成: ``` <pre class="calibre16">``` <span class="token2">// This will identify our vertex buffer</span> GLuint vertexbuffer<span class="token1">;</span> <span class="token2">// Generate 1 buffer, put the resulting identifier in vertexbuffer</span> <span class="token3">glGenBuffers</span><span class="token1">(</span><span class="token6">1</span><span class="token1">,</span> <span class="token">&</span>vertexbuffer<span class="token1">)</span><span class="token1">;</span> <span class="token2">// The following commands will talk about our 'vertexbuffer' buffer</span> <span class="token3">glBindBuffer</span><span class="token1">(</span>GL_ARRAY_BUFFER<span class="token1">,</span> vertexbuffer<span class="token1">)</span><span class="token1">;</span> <span class="token2">// Give our vertices to OpenGL.</span> <span class="token3">glBufferData</span><span class="token1">(</span>GL_ARRAY_BUFFER<span class="token1">,</span> <span class="token3">sizeof</span><span class="token1">(</span>g_vertex_buffer_data<span class="token1">)</span><span class="token1">,</span> g_vertex_buffer_data<span class="token1">,</span> GL_STATIC_DRAW<span class="token1">)</span><span class="token1">;</span> ``` ``` 這只要做一次。 現在,我們的主循環中,那個之前啥都沒有的地方,就能畫我們宏偉的三角形了: ``` <pre class="calibre16">``` <span class="token2">// 1rst attribute buffer : vertices</span> <span class="token3">glEnableVertexAttribArray</span><span class="token1">(</span><span class="token6">0</span><span class="token1">)</span><span class="token1">;</span> <span class="token3">glBindBuffer</span><span class="token1">(</span>GL_ARRAY_BUFFER<span class="token1">,</span> vertexbuffer<span class="token1">)</span><span class="token1">;</span> <span class="token3">glVertexAttribPointer</span><span class="token1">(</span> <span class="token6">0</span><span class="token1">,</span> <span class="token2">// attribute 0. No particular reason for 0, but must match the layout in the shader.</span> <span class="token6">3</span><span class="token1">,</span> <span class="token2">// size</span> GL_FLOAT<span class="token1">,</span> <span class="token2">// type</span> GL_FALSE<span class="token1">,</span> <span class="token2">// normalized?</span> <span class="token6">0</span><span class="token1">,</span> <span class="token2">// stride</span> <span class="token1">(</span>void<span class="token">*</span><span class="token1">)</span><span class="token6">0</span> <span class="token2">// array buffer offset</span> <span class="token1">)</span><span class="token1">;</span> <span class="token2">// Draw the triangle !</span> <span class="token3">glDrawArrays</span><span class="token1">(</span>GL_TRIANGLES<span class="token1">,</span> <span class="token6">0</span><span class="token1">,</span> <span class="token6">3</span><span class="token1">)</span><span class="token1">;</span> <span class="token2">// Starting from vertex 0; 3 vertices total -> 1 triangle</span> <span class="token3">glDisableVertexAttribArray</span><span class="token1">(</span><span class="token6">0</span><span class="token1">)</span><span class="token1">;</span> ``` ``` 結果如圖: ![](https://box.kancloud.cn/2015-11-02_5636f301d42d1.png) 白色略顯無聊。讓我們來看看怎么把它涂成紅色。這就需要用到一個叫『著色器(Shader)』的東西。 ## 著色器 ### 編譯著色器 在最簡單的配置下,你將需要兩個著色器:一個叫頂點著色器,它將作用于每個頂點上;另一個叫片斷(Fragment)著色器,它將作用于每一個采樣點。我們使用4倍反走樣,因此每像素有四個采樣點。 著色器編程使用GLSL(GL Shader Language,GL著色語言),它是OpenGL的一部分。與C或Java不同,GLSL必須在運行時編譯,這意味著每次啟動程序,所有的著色器將重新編譯。 這兩個著色器通常放在單獨的文件里。本例中,我們有SimpleFragmentShader.fragmentshader和SimpleVertexShader.vertexshader兩個著色器。他們的擴展名是無關緊要的,可以是.txt或者.glsl。 以下是代碼。完全理解它不是很重要,因為通常一個程序只做一次,看懂注釋就夠了。所有其他課程代碼都用到了這個函數,所以它被放在一個單獨的文件中:common/loadShader.cpp。注意,和緩沖區一樣,著色器不能直接訪問:我們僅僅有一個編號(ID)。真正的實現隱藏在驅動程序中。 ``` <pre class="calibre16">``` GLuint <span class="token3">LoadShaders</span><span class="token1">(</span>const char <span class="token">*</span> vertex_file_path<span class="token1">,</span>const char <span class="token">*</span> fragment_file_path<span class="token1">)</span><span class="token1">{</span> <span class="token2">// Create the shaders</span> GLuint VertexShaderID <span class="token">=</span> <span class="token3">glCreateShader</span><span class="token1">(</span>GL_VERTEX_SHADER<span class="token1">)</span><span class="token1">;</span> GLuint FragmentShaderID <span class="token">=</span> <span class="token3">glCreateShader</span><span class="token1">(</span>GL_FRAGMENT_SHADER<span class="token1">)</span><span class="token1">;</span> <span class="token2">// Read the Vertex Shader code from the file</span> std<span class="token1">:</span><span class="token1">:</span>string VertexShaderCode<span class="token1">;</span> std<span class="token1">:</span><span class="token1">:</span>ifstream <span class="token3">VertexShaderStream</span><span class="token1">(</span>vertex_file_path<span class="token1">,</span> std<span class="token1">:</span><span class="token1">:</span>ios<span class="token1">:</span><span class="token1">:</span><span class="token4">in</span><span class="token1">)</span><span class="token1">;</span> <span class="token4">if</span><span class="token1">(</span>VertexShaderStream<span class="token1">.</span><span class="token3">is_open</span><span class="token1">(</span><span class="token1">)</span><span class="token1">)</span> <span class="token1">{</span> std<span class="token1">:</span><span class="token1">:</span>string Line <span class="token">=</span> <span class="token5">""</span><span class="token1">;</span> <span class="token4">while</span><span class="token1">(</span><span class="token3">getline</span><span class="token1">(</span>VertexShaderStream<span class="token1">,</span> Line<span class="token1">)</span><span class="token1">)</span> VertexShaderCode <span class="token">+</span><span class="token">=</span> <span class="token5">"\n"</span> <span class="token">+</span> Line<span class="token1">;</span> VertexShaderStream<span class="token1">.</span><span class="token3">close</span><span class="token1">(</span><span class="token1">)</span><span class="token1">;</span> <span class="token1">}</span> <span class="token2">// Read the Fragment Shader code from the file</span> std<span class="token1">:</span><span class="token1">:</span>string FragmentShaderCode<span class="token1">;</span> std<span class="token1">:</span><span class="token1">:</span>ifstream <span class="token3">FragmentShaderStream</span><span class="token1">(</span>fragment_file_path<span class="token1">,</span> std<span class="token1">:</span><span class="token1">:</span>ios<span class="token1">:</span><span class="token1">:</span><span class="token4">in</span><span class="token1">)</span><span class="token1">;</span> <span class="token4">if</span><span class="token1">(</span>FragmentShaderStream<span class="token1">.</span><span class="token3">is_open</span><span class="token1">(</span><span class="token1">)</span><span class="token1">)</span><span class="token1">{</span> std<span class="token1">:</span><span class="token1">:</span>string Line <span class="token">=</span> <span class="token5">""</span><span class="token1">;</span> <span class="token4">while</span><span class="token1">(</span><span class="token3">getline</span><span class="token1">(</span>FragmentShaderStream<span class="token1">,</span> Line<span class="token1">)</span><span class="token1">)</span> FragmentShaderCode <span class="token">+</span><span class="token">=</span> <span class="token5">"\n"</span> <span class="token">+</span> Line<span class="token1">;</span> FragmentShaderStream<span class="token1">.</span><span class="token3">close</span><span class="token1">(</span><span class="token1">)</span><span class="token1">;</span> <span class="token1">}</span> GLint Result <span class="token">=</span> GL_FALSE<span class="token1">;</span> int InfoLogLength<span class="token1">;</span> <span class="token2">// Compile Vertex Shader</span> <span class="token3">printf</span><span class="token1">(</span><span class="token5">"Compiling shader : %s\n"</span><span class="token1">,</span> vertex_file_path<span class="token1">)</span><span class="token1">;</span> char const <span class="token">*</span> VertexSourcePointer <span class="token">=</span> VertexShaderCode<span class="token1">.</span><span class="token3">c_str</span><span class="token1">(</span><span class="token1">)</span><span class="token1">;</span> <span class="token3">glShaderSource</span><span class="token1">(</span>VertexShaderID<span class="token1">,</span> <span class="token6">1</span><span class="token1">,</span> <span class="token">&</span>VertexSourcePointer <span class="token1">,</span> NULL<span class="token1">)</span><span class="token1">;</span> <span class="token3">glCompileShader</span><span class="token1">(</span>VertexShaderID<span class="token1">)</span><span class="token1">;</span> <span class="token2">// Check Vertex Shader</span> <span class="token3">glGetShaderiv</span><span class="token1">(</span>VertexShaderID<span class="token1">,</span> GL_COMPILE_STATUS<span class="token1">,</span> <span class="token">&</span>Result<span class="token1">)</span><span class="token1">;</span> <span class="token3">glGetShaderiv</span><span class="token1">(</span>VertexShaderID<span class="token1">,</span> GL_INFO_LOG_LENGTH<span class="token1">,</span> <span class="token">&</span>InfoLogLength<span class="token1">)</span><span class="token1">;</span> std<span class="token1">:</span><span class="token1">:</span>vector <span class="token3">VertexShaderErrorMessage</span><span class="token1">(</span>InfoLogLength<span class="token1">)</span><span class="token1">;</span> <span class="token3">glGetShaderInfoLog</span><span class="token1">(</span>VertexShaderID<span class="token1">,</span> InfoLogLength<span class="token1">,</span> NULL<span class="token1">,</span> <span class="token">&</span>VertexShaderErrorMessage<span class="token1">[</span><span class="token6">0</span><span class="token1">]</span><span class="token1">)</span><span class="token1">;</span> <span class="token3">fprintf</span><span class="token1">(</span>stdout<span class="token1">,</span> <span class="token5">"%s\n"</span><span class="token1">,</span> <span class="token">&</span>VertexShaderErrorMessage<span class="token1">[</span><span class="token6">0</span><span class="token1">]</span><span class="token1">)</span><span class="token1">;</span> <span class="token2">// Compile Fragment Shader</span> <span class="token3">printf</span><span class="token1">(</span><span class="token5">"Compiling shader : %s\n"</span><span class="token1">,</span> fragment_file_path<span class="token1">)</span><span class="token1">;</span> char const <span class="token">*</span> FragmentSourcePointer <span class="token">=</span> FragmentShaderCode<span class="token1">.</span><span class="token3">c_str</span><span class="token1">(</span><span class="token1">)</span><span class="token1">;</span> <span class="token3">glShaderSource</span><span class="token1">(</span>FragmentShaderID<span class="token1">,</span> <span class="token6">1</span><span class="token1">,</span> <span class="token">&</span>FragmentSourcePointer <span class="token1">,</span> NULL<span class="token1">)</span><span class="token1">;</span> <span class="token3">glCompileShader</span><span class="token1">(</span>FragmentShaderID<span class="token1">)</span><span class="token1">;</span> <span class="token2">// Check Fragment Shader</span> <span class="token3">glGetShaderiv</span><span class="token1">(</span>FragmentShaderID<span class="token1">,</span> GL_COMPILE_STATUS<span class="token1">,</span> <span class="token">&</span>Result<span class="token1">)</span><span class="token1">;</span> <span class="token3">glGetShaderiv</span><span class="token1">(</span>FragmentShaderID<span class="token1">,</span> GL_INFO_LOG_LENGTH<span class="token1">,</span> <span class="token">&</span>InfoLogLength<span class="token1">)</span><span class="token1">;</span> std<span class="token1">:</span><span class="token1">:</span>vector <span class="token3">FragmentShaderErrorMessage</span><span class="token1">(</span>InfoLogLength<span class="token1">)</span><span class="token1">;</span> <span class="token3">glGetShaderInfoLog</span><span class="token1">(</span>FragmentShaderID<span class="token1">,</span> InfoLogLength<span class="token1">,</span> NULL<span class="token1">,</span> <span class="token">&</span>FragmentShaderErrorMessage<span class="token1">[</span><span class="token6">0</span><span class="token1">]</span><span class="token1">)</span><span class="token1">;</span> <span class="token3">fprintf</span><span class="token1">(</span>stdout<span class="token1">,</span> <span class="token5">"%s\n"</span><span class="token1">,</span> <span class="token">&</span>FragmentShaderErrorMessage<span class="token1">[</span><span class="token6">0</span><span class="token1">]</span><span class="token1">)</span><span class="token1">;</span> <span class="token2">// Link the program</span> <span class="token3">fprintf</span><span class="token1">(</span>stdout<span class="token1">,</span> <span class="token5">"Linking programn"</span><span class="token1">)</span><span class="token1">;</span> GLuint ProgramID <span class="token">=</span> <span class="token3">glCreateProgram</span><span class="token1">(</span><span class="token1">)</span><span class="token1">;</span> <span class="token3">glAttachShader</span><span class="token1">(</span>ProgramID<span class="token1">,</span> VertexShaderID<span class="token1">)</span><span class="token1">;</span> <span class="token3">glAttachShader</span><span class="token1">(</span>ProgramID<span class="token1">,</span> FragmentShaderID<span class="token1">)</span><span class="token1">;</span> <span class="token3">glLinkProgram</span><span class="token1">(</span>ProgramID<span class="token1">)</span><span class="token1">;</span> <span class="token2">// Check the program</span> <span class="token3">glGetProgramiv</span><span class="token1">(</span>ProgramID<span class="token1">,</span> GL_LINK_STATUS<span class="token1">,</span> <span class="token">&</span>Result<span class="token1">)</span><span class="token1">;</span> <span class="token3">glGetProgramiv</span><span class="token1">(</span>ProgramID<span class="token1">,</span> GL_INFO_LOG_LENGTH<span class="token1">,</span> <span class="token">&</span>InfoLogLength<span class="token1">)</span><span class="token1">;</span> std<span class="token1">:</span><span class="token1">:</span>vector <span class="token3">ProgramErrorMessage</span><span class="token1">(</span> <span class="token3">max</span><span class="token1">(</span>InfoLogLength<span class="token1">,</span> <span class="token3">int</span><span class="token1">(</span><span class="token6">1</span><span class="token1">)</span><span class="token1">)</span> <span class="token1">)</span><span class="token1">;</span> <span class="token3">glGetProgramInfoLog</span><span class="token1">(</span>ProgramID<span class="token1">,</span> InfoLogLength<span class="token1">,</span> NULL<span class="token1">,</span> <span class="token">&</span>ProgramErrorMessage<span class="token1">[</span><span class="token6">0</span><span class="token1">]</span><span class="token1">)</span><span class="token1">;</span> <span class="token3">fprintf</span><span class="token1">(</span>stdout<span class="token1">,</span> <span class="token5">"%s\n"</span><span class="token1">,</span> <span class="token">&</span>ProgramErrorMessage<span class="token1">[</span><span class="token6">0</span><span class="token1">]</span><span class="token1">)</span><span class="token1">;</span> <span class="token3">glDeleteShader</span><span class="token1">(</span>VertexShaderID<span class="token1">)</span><span class="token1">;</span> <span class="token3">glDeleteShader</span><span class="token1">(</span>FragmentShaderID<span class="token1">)</span><span class="token1">;</span> <span class="token4">return</span> ProgramID<span class="token1">;</span> <span class="token1">}</span> ``` ``` ### 我們的頂點著色器 我們先寫頂點著色器。 第一行告訴編譯器我們將用OpenGL 3的語法。 ``` <pre class="calibre16">``` #version <span class="token6">330</span> core ``` ``` 第二行聲明輸入數據: ``` <pre class="calibre16">``` <span class="token3">layout</span><span class="token1">(</span>location <span class="token">=</span> <span class="token6">0</span><span class="token1">)</span> <span class="token4">in</span> vec3 vertexPosition_modelspace<span class="token1">;</span> ``` ``` 具體解釋一下這一行: “vec3”在GLSL中是一個三維向量。類似于(但不相同)以前我們用來聲明三角形的glm::vec3。最重要的是,如果我們在C++中使用三維向量,那么在GLSL中也使用三維向量。 “layout(location = 0)”指我們用來賦給vertexPosition\_modelspace這個屬性的緩沖區。每個頂點能有多種屬性:位置,一種或多種顏色,一個或多個紋理坐標,等等。OpenGL不知道什么是顏色:它只是看到一個vec3。因此我們必須告訴它,哪個緩沖對應哪個輸入。通過將glvertexAttribPointer函數的第一個參數值賦給layout,我們就完成了這一點。參數值“0”并不重要,它可以是12(但是不大于glGetIntegerv(GL\_MAX\_VERTEX\_ATTRIBS, &v));重要的是兩邊參數值保持一致。 “vertexPosition\_modelspace”這個變量名你可以任取,它將包含每個頂點著色器運行所需的頂點位置值。 “in”的意思是這是一些輸入數據。不久我們將會看到“out”關鍵詞。 每個頂點都會調用main函數(和C語言一樣): ``` <pre class="calibre16">``` void <span class="token3">main</span><span class="token1">(</span><span class="token1">)</span><span class="token1">{</span> ``` ``` 我們的main函數只是將頂點的位置設為緩沖區里的值,無論這值是多少。因此如果我們給出位置(1,1),那么三角形將有一個頂點在屏幕的右上角。在下一課中我們將看到,怎樣對輸入位置做一些更有趣的計算。 ``` <pre class="calibre16">``` gl_Position<span class="token1">.</span>xyz <span class="token">=</span> vertexPosition_modelspace<span class="token1">;</span> gl_Position<span class="token1">.</span>w <span class="token">=</span> <span class="token6">1.0</span><span class="token1">;</span> <span class="token1">}</span> ``` ``` gl\_Position是為數不多的內置變量之一:你必須賦一個值給它。其他操作都是可選的,我們將在第四課中看到“其他操作”指的是什么。 ### 我們的片斷著色器 作為我們的第一個片斷著色器,我們只做一個簡單的事:設置每個片斷的顏色為紅色。(記住,每像素有4個片斷,因為我們用的是4倍反走樣) ``` <pre class="calibre16">``` out vec3 color<span class="token1">;</span> 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">vec3</span><span class="token1">(</span><span class="token6">1</span><span class="token1">,</span><span class="token6">0</span><span class="token1">,</span><span class="token6">0</span><span class="token1">)</span><span class="token1">;</span> <span class="token1">}</span> ``` ``` vec3(1,0,0)代表紅色。因為在計算機屏幕上,顏色由紅,綠,藍這個順序三元組表示。因此(1,0,0)意思是全紅,沒有綠色,也沒有藍色。 ## 把它們組合起來 在main循環前,調用我們的LoadShaders函數: ``` <pre class="calibre16">``` <span class="token2">// Create and compile our GLSL program from the shaders</span> GLuint programID <span class="token">=</span> <span class="token3">LoadShaders</span><span class="token1">(</span> <span class="token5">"SimpleVertexShader.vertexshader"</span><span class="token1">,</span> <span class="token5">"SimpleFragmentShader.fragmentshader"</span> <span class="token1">)</span><span class="token1">;</span> ``` ``` 現在在main循環中,首先清屏: ``` <pre class="calibre16">``` <span class="token3">glClear</span><span class="token1">(</span>GL_COLOR_BUFFER_BIT <span class="token">|</span> GL_DEPTH_BUFFER_BIT<span class="token1">)</span><span class="token1">;</span> ``` ``` 然后告訴OpenGL你想用你的著色器: ``` <pre class="calibre16">``` <span class="token2">// Use our shader</span> <span class="token3">glUseProgram</span><span class="token1">(</span>programID<span class="token1">)</span><span class="token1">;</span> <span class="token2">// Draw triangle...</span> ``` ``` …接著轉眼間,這就是你的紅色三角形! ![](https://box.kancloud.cn/2015-11-02_5636f301e500d.png) 下一課中我們將學習變換:如何設置你的相機,移動物體等等。
                  <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>

                              哎呀哎呀视频在线观看