1. 程式人生 > >opengl 畫三角形

opengl 畫三角形


頂點輸入

要渲染一個三角形,需指定三個頂點,每個頂點都有一個3D位置。我們會將它們以標準化裝置座標的形式(OpenGL的可見區域)定義為一個GLfloat陣列。

GLfloat vertices[] = {
    -0.5f, -0.5f, 0.0f,
     0.5f, -0.5f, 0.0f,
     0.0f,  0.5f, 0.0f
};

這些座標點都是“標準化裝置座標(Normalized Device Coordinates, NDC)。標準化裝置座標是一個x、y和z值在-1.0到1.0的一小段空間。任

何落在範圍外的座標都會被丟棄/裁剪,不會顯示在你的螢幕上。下面你會看到我們定義的在標準化裝置座標中的三角形(忽略z軸):

NDC

咱要渲染的是一個2D三角形,所以將它頂點的z座標設定為0.0,這樣子的話三角形每一點的深度都是一樣的,看上去就像是2d了。深度

可以理解為z座標,它代表一個畫素在空間中和你的距離,如果離你遠就可能被別的畫素遮擋,你就看不到它了,它會被丟棄,以節

省資源。

定義這樣的頂點資料以後,我們會把它輸入給圖形渲染管線的第一個處理階段:頂點著色器。它會在GPU上建立記憶體用於儲存我們的頂點數

據,還要配置OpenGL如何解釋這些記憶體,並且指定其如何傳送給顯示卡。頂點著色器接著會處理我們在記憶體中指定數量的頂點。

頂點緩衝物件(Vertex Buffer Objects, VBO)管理這個GPU記憶體(通常被稱為視訊記憶體)

,它會在GPU記憶體中儲存大量頂點。使用這些緩衝物件的好處

是我們可以一次性的傳送一大批資料到顯示卡上,而不是每個頂點發送一次。當資料傳送至顯示卡的記憶體中後,頂點著色器幾乎能立即訪問頂

點,這是個非常快的過程。

vbo的建立

使用glGenBuffers函式和一個緩衝ID生成一個VBO物件

GLuint VBO;
glGenBuffers(1, &VBO); 

頂點緩衝物件的緩衝型別是GL_ARRAY_BUFFER。我們使用glBindBuffer函式把新建立的緩衝繫結到GL_ARRAY_BUFFER目標上:
glBindBuffer(GL_ARRAY_BUFFER, VBO);  

把之前定義的頂點資料複製到緩衝的記憶體中:
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices), vertices, GL_STATIC_DRAW);

glBufferData是一個專門用來把使用者定義的資料複製到當前繫結緩衝的函式。它的第一個引數是目標緩衝的型別:頂點緩衝物件當前繫結到GL_ARRAY_BUFFER目標上。第二個引數指定傳輸資料的大小(以位元組為單位);用一個簡單的sizeof計算出頂點資料大小就行。第三個引數是我們希望傳送的實際資料。

第四個引數指定了我們希望顯示卡如何管理給定的資料。它有三種形式:

  • GL_STATIC_DRAW :資料不會或幾乎不會改變。
  • GL_DYNAMIC_DRAW:資料會被改變很多。
  • GL_STREAM_DRAW :資料每次繪製時都會改變。

三角形的位置資料不會改變,每次渲染呼叫時都保持原樣,所以它的使用型別最好是GL_STATIC_DRAW。如果,比如說一個緩衝中的資料將頻繁被改變,那麼使用的型別就是GL_DYNAMIC_DRAWGL_STREAM_DRAW,這樣就能確保顯示卡把資料放在能夠高速寫入的記憶體部分。


頂點著色器

//三角形的vertex shader
attribute vec3 a_position; // attribute是從外部傳進來的,每一個頂點都會有這兩個屬性,所以它也叫做vertex attribute(頂點屬性)
void main()
{
    gl_Position = vec4(a_position.x, a_position.y, a_position.z, 1);
}

為了設定頂點著色器的輸出,我們必須把位置資料賦值給預定義的gl_Position變數,它在幕後是vec4型別的。在main函式的最後,我們

gl_Position設定的值會成為該頂點著色器的輸出。由於我們的輸入是一個3分量的向量,我們必須把它轉換為4分量的。我們可以

vec3的資料作為vec4構造器的引數,同時把w分量設定為1.0f(我們會在後面解釋為什麼)來完成這一任務。

在GLSL中一個向量有最多4個分量,每個分量值都代表空間中的一個座標,它們可以通過vec.xvec.yvec.zvec.w來獲取。注

vec.w分量不是用作表達空間中的位置的(我們處理的是3D不是4D),而是用在所謂透視劃分(Perspective Division)上。我們會在後面的

教程中更詳細地討論向量。

編譯著色器

我們已經寫了一個頂點著色器原始碼(儲存在一個C的字串中),但是為了能夠讓OpenGL使用它,我們必須在執行時動態編譯它的原始碼。

在xcode- cocos2d-x 的環境下,只要在init中新增如下程式碼即可:

    auto program = new GLProgram;
    program->initWithFilenames("triangle.vsh", "triangle.fsh");

triangle.vsh就是上邊剛定義的那個vertex shader。triangle.fsh是下邊定義的fragment shader。

片段著色器(Fragment Shader)

片段著色器全是關於計算你的畫素最後的顏色輸出。為了讓事情更簡單,我們的片段著色器將會一直輸出固定色。

//三角形的fragment shader

void main()
{
    gl_FragColor = vec4(1, 0.5, 0.5, 1);
}

這裡弄好後,上邊的 glprogram  著色器程式需要連結這2個著色器:

    auto program = new GLProgram;  
    program->initWithFilenames("triangle.vsh", "triangle.fsh");  
    program->link();  
    this->setGLProgram(program); 


連結頂點屬性

頂點著色器允許我們指定任何以頂點屬性為形式的輸入。這使其具有很強的靈活性的同時,它還的確意味著我們必須手動指定輸入資料的哪

一個部分對應頂點著色器的哪一個頂點屬性。所以,我們必須在渲染前指定OpenGL該如何解釋頂點資料。

頂點緩衝資料會被解析為下面這樣子:

  • 位置資料被儲存為32-bit(4位元組)浮點值。
  • 每個位置包含3個這樣的值。
  • 在這3個值之間沒有空隙(或其他值)。這幾個值在陣列中緊密排列。
  • 資料中第一個值在緩衝開始的位置。
程式碼:
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);

  • 第一個引數指定我們要配置的頂點屬性。這裡把資料傳到vertex shader中第一個位置上(從0開始)的那個屬性,也就是

    attributevec3 a_position; 因為我們希望把資料傳遞到這一個頂點屬性中,所以這裡我們傳入0

  • 第二個引數指定頂點屬性的大小。頂點屬性是一個vec3,它由3個值組成,所以大小是3。
  • 第三個引數指定資料的型別,這裡是GL_FLOAT(GLSL中vecX都是由浮點數值組成的)。
  • 下個引數定義我們是否希望資料被標準化(Normalize)。如果我們設定為GL_TRUE,所有資料都會被對映到0(對於有符號型signed資料是-1)到1之間。我們把它設定為GL_FALSE
  • 第五個引數叫做步長(Stride),它告訴我們在連續的頂點屬性組之間的間隔。由於下個組位置資料在3個GLfloat之後,我們把步長設定為3 * sizeof(GLfloat)。要注意的是由於我們知道這個陣列是緊密排列的(在兩個頂點屬性之間沒有空隙)我們也可以設定為0來讓OpenGL決定具體步長是多少(只有當數值是緊密排列時才可用)。一旦我們有更多的頂點屬性,我們就必須更小心地定義每個頂點屬性之間的間隔,我們在後面會看到更多的例子(譯註: 這個引數的意思簡單說就是從這個屬性第二次出現的地方到整個陣列0位置之間有多少位元組)。
  • 最後一個引數的型別是GLvoid*,所以需要我們進行這個奇怪的強制型別轉換。它表示位置資料在緩衝中起始位置的偏移量(Offset)。由於位置資料在陣列的開頭,所以這裡是0。我們會在後面詳細解釋這個引數。

每個頂點屬性從一個VBO管理的記憶體中獲得它的資料,而具體是從哪個VBO(程式中可以有多個VBO)獲取則是通過在調

glVetexAttribPointer時繫結到GL_ARRAY_BUFFER的VBO決定的。由於在呼叫glVetexAttribPointer之前繫結的是先前定義的

VBO物件,頂點屬性0現在會連結到它的頂點資料。

已經定義了OpenGL該如何解釋頂點資料,我們現在應該使用glEnableVertexAttribArray,以頂點屬性位置值作為引數,啟用頂點屬

性。程式碼會像是這樣:

// 0. 複製頂點陣列到緩衝中供OpenGL使用
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 1. 設定頂點屬性指標
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// 2. 當我們渲染一個物體時要使用著色器程式
glUseProgram(shaderProgram);
// 3. 繪製物體
someOpenGLFunctionThatDrawsOurTriangle();

每當我們繪製一個物體的時候都必須重複這一過程。這看起來可能不多,但是如果有超過5個頂點屬性,上百個不同物體呢(這其實並不罕

見)。繫結正確的緩衝物件,為每個物體配置所有頂點屬性很快就變成一件麻煩事。有沒有一些方法可以使我們把所有這些狀態配置儲存在

一個物件中,並且可以通過繫結這個物件來恢復狀態呢?

頂點陣列物件

頂點陣列物件(Vertex Array Object, VAO)可以像頂點緩衝物件那樣被繫結,任何隨後的頂點屬性呼叫都會儲存在這個VAO中。這樣的好處就是,當配置頂點屬性指標時,你只需要將那些呼叫執行一次,之後再繪製物體的時候只需要繫結相應的VAO就行了。這使在不同頂點資料和屬性配置之間切換變得非常簡單,只需要繫結不同的VAO就行了。剛剛設定的所有狀態都將儲存在VAO中。

一個頂點陣列物件會儲存以下這些內容:

  • glEnableVertexAttribArray和glDisableVertexAttribArray的呼叫。
  • 通過glVertexAttribPointer設定的頂點屬性配置。
  • 通過glVertexAttribPointer呼叫與頂點屬性關聯的頂點緩衝物件。
建立一個VAO:
GLuint VAO;
glGenVertexArrays(1, &VAO); 

要想使用VAO,要做的只是使用glBindVertexArray繫結VAO。從繫結之後起,我們應該繫結和配置對應的VBO和屬性指標,之後解綁

VAO供之後使用。當我們打算繪製一個物體的時候,我們只要在繪製物體前簡單地把VAO繫結到希望使用的設定上就行了。這段程式碼應該看

起來像這樣(虛擬碼):

// ..:: 初始化程式碼(只執行一次 (除非你的物體頻繁改變)) :: ..
// 1. 繫結VAO
glBindVertexArray(VAO);
    // 2. 把頂點陣列複製到緩衝中供OpenGL使用
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    // 3. 設定頂點屬性指標
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);
//4. 解綁VAO
glBindVertexArray(0);

[...]

// ..:: 繪製代(遊戲迴圈中) :: ..
// 5. 繪製物體
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
someOpenGLFunctionThatDrawsOurTriangle();
glBindVertexArray(0);

全部程式碼如下:
//
//  Triangle.cpp
//  shaderTest
//
//  Created by MacSBL on 2016/12/15.
//
//

#include "OpenGLTriangle.hpp"

bool OpenGLTriangle::init()
{
    if (!Layer::init()) {
        return false;
    }
    
    GLfloat vertices[] =
    {
        -0.5, -0.5, 0,
        0.5, -0.5, 0,
        0, 0.5, 0
    };
    
    //1、繫結vao
    //頂點陣列物件(Vertex Array Object)被繫結後,任何隨後的頂點屬性呼叫都會儲存在這個VAO中。這樣的好處就是,當配置頂點屬性指標時,你只需要將那些呼叫執行一次,之後再繪製物體的時候只需要繫結相應的VAO就行了。這使在不同頂點資料和屬性配置之間切換變得非常簡單,只需要繫結不同的VAO就行了。剛剛設定的所有狀態都將儲存在VAO中
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    
    // 2. 把頂點陣列複製到緩衝(vbo)中供OpenGL使用
    //使用glGenBuffers函式和一個緩衝ID生成一個VBO物件
    GLuint vbo;
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    //把之前定義的頂點資料複製到緩衝的記憶體中
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    
    //告訴OpenGL該如何解析頂點資料(應用到逐個頂點屬性上)
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3* sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);
    
    //解除繫結vao和vbo
    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    
    //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
    auto program = new GLProgram;
    program->initWithFilenames("triangle.vsh", "triangle.fsh");
    program->link();
    this->setGLProgram(program);
    
    return true;
}

void OpenGLTriangle::visit(cocos2d::Renderer *renderer, const cocos2d::Mat4 &parentTransform, uint32_t parentFlags)
{
    Layer::visit(renderer, parentTransform, parentFlags);
    _command.init(_globalZOrder);
    _command.func = CC_CALLBACK_0(OpenGLTriangle::onDraw, this);
    Director::getInstance()->getRenderer()->addCommand(&_command);
}

void OpenGLTriangle::onDraw()
{
    //獲取當前node 的shader
    auto glprogram = getGLProgram();
    //需要在init中指定shader才能在這use
    glprogram->use();
    glBindVertexArray(vao);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glBindVertexArray(0);
}

如無意外,三角形就畫出來了。

索引緩衝物件

要畫一個四邊形,我們可以繪製兩個三角形來組成一個矩形(OpenGL主要處理三角形)。這會生成下面的頂點的集合:

GLfloat vertices[] = {
    // 第一個三角形
    0.5f, 0.5f, 0.0f,   // 右上角
    0.5f, -0.5f, 0.0f,  // 右下角
    -0.5f, 0.5f, 0.0f,  // 左上角
    // 第二個三角形
    0.5f, -0.5f, 0.0f,  // 右下角
    -0.5f, -0.5f, 0.0f, // 左下角
    -0.5f, 0.5f, 0.0f   // 左上角
};
如果有包括上千個三角形的模型之後就太糟糕了,這會產生一大堆浪費。更好的解決方案是隻儲存不同的頂點,並設定繪製這些頂點的順

序。這樣子我們只要儲存4個頂點就能繪製矩形了,之後只要指定繪製的順序就行了。索引緩衝物件(Element Buffer Object,EBO,也叫

Index Buffer Object,IBO)的工作方式正是這樣的。和頂點緩衝物件一樣,EBO也是一個緩衝,它專門儲存索引,OpenGL呼叫這些頂點的

索引來決定該繪製哪個頂點:

GLfloat vertices[] = {
    0.5f, 0.5f, 0.0f,   // 右上角
    0.5f, -0.5f, 0.0f,  // 右下角
    -0.5f, -0.5f, 0.0f, // 左下角
    -0.5f, 0.5f, 0.0f   // 左上角
};

GLuint indices[] = { // 注意索引從0開始! 
    0, 1, 3, // 第一個三角形
    1, 2, 3  // 第二個三角形
};

下一步我們需要建立索引緩衝物件:
GLuint EBO;
glGenBuffers(1, &EBO);

然後用glBufferData把索引複製到緩衝裡,這次我們把緩衝的型別定義為GL_ELEMENT_ARRAY_BUFFER
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); 

最後一件要做的事是用glDrawElements來替換glDrawArrays函式,來指明我們從索引緩衝渲染。使用glDrawElements時,我們會使

用當前繫結的索引緩衝物件中的索引進行繪製:

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

第一個引數指定了我們繪製的模式,這個和glDrawArrays的一樣。第二個引數是我們打算繪製頂點的個數,這裡填6,也就是說我們一共需要繪製6個頂點。第三個引數是索引的型別,這裡是GL_UNSIGNED_INT。最後一個引數裡我們可以指定EBO中的偏移量(或者傳遞一個索引陣列,但是這是當你不在使用索引緩衝物件的時候),但是我們會在這裡填寫0。

glDrawElements函式從當前繫結到GL_ELEMENT_ARRAY_BUFFER目標的EBO中獲取索引。這意味著我們必須在每次要用索引渲染一個物體時繫結相應的EBO,這還是有點麻煩。不過頂點陣列物件同樣可以儲存索引緩衝物件的繫結狀態。VAO繫結時正在繫結的索引緩衝物件會被儲存為VAO的元素緩衝物件。繫結VAO的同時也會自動繫結EBO。


最後的初始化和繪製程式碼現在看起來像這樣:
// ..:: 初始化程式碼 :: ..
// 1. 繫結頂點陣列物件
glBindVertexArray(VAO);
    // 2. 把我們的頂點陣列複製到一個頂點緩衝中,供OpenGL使用
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    // 3. 複製我們的索引陣列到一個索引緩衝中,供OpenGL使用
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    // 3. 設定頂點屬性指標
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);
// 4. 解綁VAO(不是EBO!)
glBindVertexArray(0);

[...]

// ..:: 繪製程式碼(遊戲迴圈中) :: ..

glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0)
glBindVertexArray(0);

完整程式碼:
#include "OpenGLQuadrangle.hpp"

bool OpenGLQuadrangle::init()
{
    if (!Layer::init()) {
        return false;
    }
    
    GLfloat vertices[] = {
        0.5, 0.5, 0, //右上
        0.5, -0.5, 0,   //右下
        -0.5, -0.5, 0,   //左下
        -0.5, 0.5, 0  //左上
    };
    GLuint indices[] = {
        0, 1, 3,
        1, 2, 3
    };
    
     //1. 繫結頂點陣列物件
    //vao,
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    // 2. 把我們的頂點陣列複製到一個頂點緩衝中,供OpenGL使用
    //vbo
    GLuint vbo;
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    // 3. 複製我們的索引陣列到一個索引緩衝中,供OpenGL使用
    //ebo
    glGenBuffers(1, &ebo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    // 4. 設定頂點屬性指標
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);
    //5.解綁VAO(不是EBO!)
    glBindVertexArray(0);
    
    //著色器程式
    auto program = new GLProgram;
    program->initWithFilenames("triangle.vsh", "triangle.fsh");
    program->link();
    this->setGLProgram(program);
    
    return true;
}

void OpenGLQuadrangle::visit(cocos2d::Renderer *renderer, const cocos2d::Mat4 &parentTransform, uint32_t parentFlags)
{
    Layer::visit(renderer, parentTransform, parentFlags);
    _command.init(_globalZOrder);
    _command.func = CC_CALLBACK_0(OpenGLQuadrangle::onDraw, this);
    Director::getInstance()->getRenderer()->addCommand(&_command);
}

void OpenGLQuadrangle::onDraw()
{
    //獲取當前node 的shader
    auto glprogram = getGLProgram();
    //需要在init中指定shader才能在這use
    glprogram->use();
    glBindVertexArray(vao);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);
}


相關推薦

opengl 三角形

頂點輸入 要渲染一個三角形,需指定三個頂點,每個頂點都有一個3D位置。我們會將它們以標準化裝置座標的形式(OpenGL的可見區域)定義為一個GLfloat陣列。 GLfloat vertices[] = { -0.5f, -0.5f, 0.0f,

openGL三角形---openGL學習筆記(四)

在openGL中,所有面狀圖形的繪製都是使用畫三角形方法,而針對不同需求,openGL給出三種不同的畫三角形方法: ①traingles:畫三角形集 ②traingle_strip:畫三角形帶 ③traingle_fan:畫三角形扇面 畫三角形集在筆記(一)中已經實現

<三> 初探opengl三角形

版本 目的 轉換 著色器 jpg open false https bar   環境搭建好,我們當然就是開始寫代碼,這裏就得先了解opengl的一些工作流程。首先我們得了解三個單詞:     頂點數組對象(VAO)     頂點緩沖對象(VBO)     索引緩

opengl三角形一個立方體(二)

前一節內容,如果讀者能夠堅持看到最後,並且能夠將立方體畫出來,我相信還是有一點點的成就感的,畢竟我們從點、到三角形、再到立方體、再到立方體的旋轉一步一步的走,而且學會了VBO、VAO、EBO的資料傳輸、shader的使用等等最最基本的知識,這一步好艱難,但是畢竟

opengl三角形一個立方體(四)

小孔成像 圖片到底是怎麼形成的?如下圖所示: 如上圖所示,座標真實的蠟燭,透過紅色面板上的點,最終形成一個倒立的蠟燭。我們可以自己做一個圖看看,利用相似三角形的原理,即可看到成像的規律。 如上圖所示,如果投影面與小孔面距離比較近,那麼蠟燭投影之後得

轉 css3三角形的原理

bsp spa http com .html otto 三角形 blue ide 轉自 www.cnblogs.com/huangzhilong/p/5030659.html 下面是一個很簡單的向上的三角形代碼 #triangle-up { width:

css-利用邊框三角形

OS lsp css ble light htm lpad log x11 html中代碼 1 2 3 4 <div class=‘box-rihgt‘></div> <div class=‘box-top‘></

css中border三角形

wid script words tor keyword key class des edi <!doctype html><html lang="en"> <head> <meta charset="UTF-8"> &l

css三角形以及實現帶三角的陰影效果

什麽 覆蓋 parent jpg 利用 ron 通過 技術 定位 先上圖看效果 1.三角形怎麽畫 通過控制四周邊框實現,想要紅色區域三角形的就設置其他三邊顏色設置為transparent,想要什麽什麽三角形就其他邊設置為透明顏色即可. 2.三角形畫好後,利用偽類,定位

Python3 tkinter基礎 Canvas create_polygon 三角形

charm strong pep 進行 pyqt5 源碼 顏色 4.5 交互式 ? python : 3.7.0 OS : Ubuntu 18.04.1 LTS

css趣味案例:三角形

程式碼: <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>畫三角形</title> <style> #trip{ width:0px;

如何用border來三角形

學習總結 HTML <div class="son"></div> CSS             .son{      &nbs

OpenGl 一個專屬的鐘表

效果顯示: #include <bits/stdc++.h> #include <windows.h> #include <time.h> #include <GL/gl.h> #include <GL/glut.h> #

opengl繪製三角形

#include <iostream> #include <glad/glad.h> #include <GLFW/glfw3.h> void framebuffer_size_callback(GLFWwindow* window, int width,

OpenGL改變三角形的頂點顏色

在下面這一篇文章的基礎上進行修改 OpenGL建立一個帶顏色的矩形https://blog.csdn.net/qq_15267341/article/details/83476125      main.cpp #define GLEW_STAT

css三角形的方法

第一次寫部落格,想想還有點小激動呢。哈哈! 今天學習瞭如何使用css畫三角的方法,覺得所看書得作者分析的很好,本著學習知識,尊重知識的原則(此時內心慌的一批,不知道自己是否正真吸收了這些知識),所以動動自己的小手指敲了點字記錄一下,也算是吧自己的第一次交付出去了,哈哈(害羞)。 廢話不多說,

css小技巧-元素分類、字型的樣式、三角形、游標樣式

行級元素(span,strong,em,a,del)-內聯元素 Feature:內容決定元素所佔位置         不可以通過css改變寬高 display:inline; 2.塊級元素(div,p,u

css 三角形

1、斜邊在左邊三角形 <style> .triangle { border-top: 50px solid transparent; border-bottom: 50px solid transparent;

HTML/CSS三角形

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style>

qt opengl 球體

和一般寫opengl的程式一樣,就直接出程式碼不多說。         在qt中我使用qopenglwidget來操作opengl程式,宣告如下 #ifndef WIDGET_H #define WIDGET_H #include <QOpenGLWidget&g