1. 程式人生 > >OpenGL設定紋理

OpenGL設定紋理

最近在學習OpenGL,把學習的一些過程寫在這裡,希望與大家共同分享討論。歡迎光臨我的個人網站Orient一起討論學習。這裡是我的GitHub,如果您喜歡,不妨點個贊?☺

紋理

在這份程式碼中我使用了下面這張紋理圖片:

1240
wall.jpg

紋理座標:

1240
texture_coords

從上圖中可以看出,紋理的座標遠點是從圖片的左下方開始。繪製矩形/三角形時對應的紋理座標如下:

//float vertices[] = {
//    // positions        // colors            // texture coords
//     0.5f,  0.5f, 0.0f,  1.0f, 0.0f, 0.0f,  1.0f, 1.0f ,// top right
//     0.5f, -0.5f, 0.0f,  0.0f, 1.0f, 0.0f,  1.0f, 0.0f,// bottom right
//    -0.5f, -0.5f, 0.0f,  0.0f, 0.0f, 1.0f,  0.0f, 0.0f,// bottom left
//    -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,  0.0f, 1.0f// top left 
//};
//unsigned int indices[] = {  // note that we start from 0!
//    0, 1, 3,  // first Triangle
//    1, 2, 3   // second Triangle
//};
float vertices[] = {    // 渲染三角形形所需程式碼
    -0.5f, -0.5f, 0.0f,  0.0f, 0.0f, 1.0f,  0.0f, 0.0f,        // 渲染三角形所需程式碼
     0.5f, -0.5f, 0.0f,  0.0f, 1.0f, 0.0f,  1.0f, 0.0f,        // 渲染三角形所需程式碼
     0.0f,  0.5f, 0.0f,  1.0f, 0.0f, 0.0f,  0.5f, 1.0f        // 渲染三角形所需程式碼
};        // 渲染三角形所需程式碼

矩形的繪製是通過繪製兩個三角形得到,我們只需給出4個頂點屬性和一個索引陣列即可繪製出矩形

接下來繫結VAO,VBO,EBO:

unsigned int VBO, VAO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
//glGenBuffers(1, &EBO);    // 渲染矩形所需程式碼
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
glBindVertexArray(VAO);

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);    // 渲染矩形所需程式碼
//glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);    // 渲染矩形所需程式碼

解析頂點資料:

// 這是繪製的頂點座標屬性
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);

// 這是繪製的頂點顏色屬性
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);

// 這是頂點對應的紋理座標
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);

紋理設定

首先建立一個紋理ID並繫結

unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);

設定環繞、過濾方式

// set the texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

生成並載入紋理

int width, height, nrChannels;
char *texturePath = "../src/wall.jpg";        // 這裡填寫你的圖片路徑
unsigned char *data = stbi_load(texturePath, &width, &height, &nrChannels, 0);        // stbi_load函式首先接受一個影象檔案的位置作為輸入。接下來它需要三個int作為它的第二、第三和第四個引數,stb_image.h將會用影象的寬度、高度和顏色通道的個數填充這三個變數。我們之後生成紋理的時候會用到的影象的寬度和高度的。

在使用stb_image.h之前,需要建立一個stb_image.cpp檔案,並新增如下內容:
通過定義STB_IMAGE_IMPLEMENTATION,前處理器會修改標頭檔案,讓其只包含相關的函式定義原始碼。使用時只需要在程式中包含stb_image.h檔案就可以了。

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

接下來使用前面載入的圖片生成紋理:

if (data)
{
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
    glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
    std::cout << "Failed to load texture" << std::endl;
}
// 釋放影象記憶體
stbi_image_free(data);

當呼叫glTexImage2D時,當前繫結的紋理物件就會被附加上紋理影象。然而,目前只有基本級別(Base-level)的紋理影象被載入了,如果要使用多級漸遠紋理,我們必須手動設定所有不同的影象(不斷遞增第二個引數)。或者,直接在生成紋理之後呼叫glGenerateMipmap。這會為當前繫結的紋理自動生成所有需要的多級漸遠紋理。

最後應用紋理

while (!glfwWindowShouldClose(window))
    {
        // input
        // -----
        processInput(window);

        // render
        // ------
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        ourShader.use();
        glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized
                                //glDrawArrays(GL_TRIANGLES, 0, 6);
        //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
        // glBindVertexArray(0); // no need to unbind it every time 

        glDrawArrays(GL_TRIANGLES, 0, 3);    // 渲染三角形所需程式碼

        //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);    // 渲染矩形所需程式碼

        // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
        // -------------------------------------------------------------------------------
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    // optional: de-allocate all resources once they've outlived their purpose:
    // ------------------------------------------------------------------------
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);

    // glfw: terminate, clearing all previously allocated GLFW resources.
    // ------------------------------------------------------------------
    glfwTerminate();
    return 0;
}

你可以在這裡找到原始碼,最後渲染出的三角形與矩形(只需要將註釋中三角形與矩形的程式碼互換即可)效果如下:

1240
triangleTexture.png 1240
rectangleTexture.png

相關推薦

OpenGL設定紋理

最近在學習OpenGL,把學習的一些過程寫在這裡,希望與大家共同分享討論。歡迎光臨我的個人網站Orient一起討論學習。這裡是我的GitHub,如果您喜歡,不妨點個贊?☺ 紋理 在這份程式碼中我使用了下面這張紋理圖片: wall.jpg 紋理座標: texture_coords

OpenGL ES 紋理設定

紋理過濾 紋理取樣 最近點取樣 線性紋理取樣 MIPMAP紋理 紋理過濾 紋理拉伸:重複拉伸和擷取拉伸 用於指定紋理座標超過(00.0,1

Unity3D設定紋理格式

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

如何將opencv-iamge上載到opengl紋理

opencv-image-loading-for-opengl-texture GLuint cvMat2glTexture(const cv::Mat& mat) { // https://stackoverflow.com/questions/1680

OpenGL ES 紋理壓縮之ETC (二)

前面介紹了OpenGL ES2.0 支援的壓縮ETC1;下面我們來學習一下ETC2。 從opengl es3.0 開始支援ETC2紋理壓縮,而這種壓縮可以支援透明通道。 下面看如何使用 載入pkm檔案 public static byte[] loadDataFromAsse

qt opengl 2d紋理到3d球面

   根據前面的實踐,已能通過程式碼生成球面的頂點,要將2維圖貼到球表面;只要能計算出每個頂點對應的紋理座標就可以了;關於2維圖貼到球面的公式如下:          float pi = 3.14159265; U = arcsin(z / R)/pi + 0.

自動設定紋理資源屬性(一)

實際專案中,我們會對指定的紋理設定不同平臺不同屬性。手動去設定操作量相對較大特別是資源持續性迭代的情況下,所以為了目標需求,我們需要去製作一個工具來設定我們匯入的紋理資源。 目標1:獲取匯入的紋理資源,並修改紋理資源屬性。可用介面:AssetPostprocessor;T

自動設定紋理資源屬性(二)

完成了匯入設定紋理,接下來我們要製作自己的配置檔案工具,需要製作一個編輯器視窗。 目前需求是兩個窗體,一個是配置列表介面;一個是配置介面。 因為要製作強制更新所以自身擴充套件兩個方法,一個是重新匯入某個路徑下所有資源,一個是獲取目錄下所有指定檔案格式檔案資訊。  我

OpenGL (二): 紋理繪製

紋理繪製 前言 部分程式碼 texture.vs texture.fs main.cpp ( 部分 ) 結果 逐行解釋 其他API Texture Wrap Texture Mi

OpenGL-對紋理的理解

看了《OpenGL程式設計指南》第九章紋理貼圖之後,一開始還對紋理的理解思路還是有點亂,後面不斷的閱讀別人的部落格之後才慢慢的有了更加清晰的認識,於是通過部落格再進一步理順一下思路。 1.關於紋理的一些基本概念理解 紋理:簡單的說,紋理就是矩形的資料陣列。例

opengl設定了光源之後,畫圖的顏色設定為什麼不生效了?怎麼改?

圖形顯示出來的顏色就是光源的顏色,glColor3f設定顏色壓根沒用。應該如何操作才能顯示後頭設定的畫圖顏色呢? 如果在光照下希望模型的顏色可以起作用,需要啟動顏色材料模式:glEnable( GL_COLOR_MATERIAL );然後還需要設定材料屬性:glLig

android opengl es--紋理對映,光照

import zhou.ne.he.four.FourRend; import zhou.ne.he.one.OneRend; import zhou.ne.he.thri.ThriRend; import zhou.ne.he.two.TwoRend; import a

[OpenGL] 基於紋理繪製的透明精靈(透明紋理

        在二維遊戲中,我們幾乎繞不開精靈繪製這一過程,除了直接在opengl讀入影象並繪製外,我們更常使用紋理來完成這一過程,把紋理貼到在xy平面上的面片,做出二維遊戲的效果。         這樣我們可以很方便的使用opengl提供給我們的一些方法來執行精靈的變換

OpenGL紋理過濾的四種方式

I.紋理過濾: 當三維空間裡面的多邊形經過座標變換、投影、光柵化等過程,變成二維螢幕上的一組象素的時候,對每個象素需要到相應紋理影象中進行取樣,這個過程就稱為紋理過濾。II.紋理過濾通常分為2種情況: a) 紋理被縮小 GL_TEXTURE_MIN_FILTER 比如說

OpenGL ES 紋理貼圖

頂點座標和紋理座標 在沒有投影矩陣的情況下,我們要傳給頂點著色器的座標值都在(-1,1)範圍內,超出了這個範圍將不可見。因此對於一個四邊形的繪製,我們經常看到下面的頂點座標: GLfloat vertices[] = { // P

qt opengl 壓縮紋理

    壓縮紋理與普通紋理的區別是,佔用的記憶體空間變小了;es 2.0 es3.0都支援ETC1。es 3.0支援ETC2。ETC2支援帶有透明通道的圖片,ETC1不支援透明通道。我這裡使用的是ETC1,png、jpg或其它格式轉換為ETC1的pkm格式壓縮圖片,可以用網上

opengl紋理 顏色怎麼共存的問題

 使用opengl繪製煙花 其中紋理映射了一張背景圖片 此時再使用glcolor控制煙花粒子顏色的時候 發現粒子顏色不顯示 只有白色 如果不使用glcolor 則背景紋理可以正常顯示 請問怎麼能讓紋理和顏色都正常顯示呢? void display(void) {  

OpenGL多重紋理

一、簡單介紹在先前的時候,我一直都是隻給要渲染的幾何體中將一個單獨的紋理載入到一個紋理物件上面,然後我們要使用紋理的時候就會去繫結它到選定的紋理物件上面。傳遞給片元著色器的uniform sampler2D texture設定為0,這裡傳0是因為我們預設使用的就是第一個紋理單

OpenGL曲面紋理貼圖技術--波浪的模擬

{ GLuint  PixelFormat;   // 儲存查詢匹配的結果 WNDCLASS wc;      // 視窗類結構 DWORD  dwExStyle;    // 擴充套件視窗風格 DWORD  dwStyle;    // 視窗風格 RECT  WindowRect;    // 取得矩形的左

OpenGL ES 紋理

使用前面學過的技術已經可以利用OpenGL ES構建立體圖形,並通過頂點著色器和片元著色器對其進行各種變化呢和光照等效果使得三維效果更加真實,實際上我看看到很多的3D遊戲漂亮多了,那是因為有各種各樣的漂亮的影象帶給人很多視覺盛宴,這篇文章在前面的基礎上,增