日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

四、纹理显示图片

發布時間:2024/1/18 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 四、纹理显示图片 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

第一部分紋理基礎

1)基礎概念

在 OpenGLES 開發中,紋理除了用于裝飾物體表面,還可以用來作為存儲數據的容器。

紋理映射:紋理映射就是通過為圖元的頂點坐標指定恰當的紋理坐標,通過紋理坐標在紋理圖中選定特定的紋理區域,最后通過紋理坐標與頂點的映射關系,將選定的紋理區域映射到指定圖元上。
紋理映射也稱為紋理貼圖,簡單地說就是將紋理坐標(紋理坐標系)所指定的紋理區域,映射到頂點坐標(渲染坐標系或OpenGLES 坐標系)對應的區域。

紋理坐標【備注 opengles紋理坐真正的原點為左上角,向下為Y正方向,右為X正方向】

頂點坐標

這里在頂點數組編寫的時候紋理坐標也需要對應。

繪制三角形:

編寫代碼的流程:

2)頂點著色器,片段著色器的修改

頂點數組中引入頂點索引位置+對應點的紋理坐標 float vertices[] = {//---- 位置 ---- - 紋理坐標 -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, // 右上0.5f, -0.5f, 0.0f, 1.0f, 0.0f, // 右下-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, // 左下-0.5f, 0.5f, 0.0f, 0.0f, 1.0f // 左上 };

頂點著色器

需要引入紋理屬性,并傳出out給片段著色器

#version 300 es layout (location = 0) in vec4 vPosition; layout (location = 1) in vec2 aTexCoord;out vec2 TexCoord;void main() {gl_Position = vPosition;TexCoord = aTexCoord; }

片段著色器

引入ourTexture 疊加頂點著色器傳入的TexCoord組合成片段著色器傳出的顏色。

#version 300 es precision mediump float; out vec4 fragColor; in vec2 TexCoord;//在調用glDrawElements之前綁定紋理了,它會自動把紋理賦值給片段著色器的采樣器: uniform sampler2D ourTexture;//紋理單元void main() {//texture 是OpenGL ES內置函數,稱之為采樣器,獲取紋理上指定位置的顏色值。//ourTexture 綁定定義的紋理//TexCoord 由頂點坐標那邊傳來的紋理坐標//最后輸出還可以把顏色也疊加上去fragColor = texture(ourTexture, TexCoord); }

3)初始化時準備工作

索引數組

//索引數組 就是畫矩形圖片時對應的兩個三角形坐標 unsigned int indices[] = {0, 1, 3, // first triangle1, 2, 3 // second triangle };

綁定紋理相關

//將GL_ELEMENT_ARRAY_BUFFER緩沖區綁定到EBO glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); //將索引坐標綁定到GL_ELEMENT_ARRAY_BUFFER glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

紋理屬性綁定

1表示頂點著色器里面location里面的1屬性,2表示從頂點數組取兩個數據 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float ), (void *)(3*sizeof(float)));//這個與頂點數組的數據內容相關 glEnableVertexAttribArray(1);//啟動

創建加載紋理

//創建紋理對象 glGenTextures(1, &texture); //將紋理綁定到GL_TEXTURE_2D 紋理目標 glBindTexture(GL_TEXTURE_2D, texture); //為當前綁定的紋理對象設定紋理環繞方式 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);//重復紋理的填充方式 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); //為當前綁定的紋理對象設定紋理過濾方式 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);//縮小時線性插值 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//放到就是線性

綁定紋理數據

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texturewidth, textureheight, 0, GL_RGB, GL_UNSIGNED_BYTE, texturedata); LOGD("CreateProgram %s", texturedata); glGenerateMipmap(GL_TEXTURE_2D);//為當前綁定的紋理自動生成所有需要的多級漸遠紋理 LOGD("CreateProgram END");

4)繪畫紋理

//指定使用的著色器程序 glUseProgram(program);glBindTexture(GL_TEXTURE_2D, texture); LOGD("glBindTexture"); //綁定頂點數組 glBindVertexArray(VAO); //畫紋理 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); glBindVertexArray(0);

第二部分項目工程部分

以三、畫三角形的區別為例

Java端沒有區別,都是一致的。

C++端存在區別,需引入紋理相關的

1)加載assets資源文件下面的圖片資源并解析bmp的圖片數據

在ReadFileUtil.h中添加

unsigned char *DecodeBMP(unsigned char *bmpFileData, int &width, int &height) {if (0x4D42 == *((short *) bmpFileData)) { // 數據頭是否為0x4D42 判斷是否是 24 位的位圖,// 讀格式頭int pixelDataOffset = *((int *) (bmpFileData + 10));// 取出像素數據在內存塊的偏移地址width = *((int *) (bmpFileData + 18));height = *((int *) (bmpFileData + 22));LOGD("pixelDataOffset %d", pixelDataOffset);unsigned char *pixelData = bmpFileData + pixelDataOffset;// 位圖像素數據是 BGR 排布的,所以更換 r b 的位置for (int i = 0; i < width * height * 3; i += 3) {char temp = pixelData[i];pixelData[i] = pixelData[i + 2];pixelData[i + 2] = temp;}return pixelData;}LOGD("DecodeBMP END");return nullptr; }unsigned char *ReadBMP(char *bmpPath, int &width, int &height) {unsigned char *bmpFileContent = const_cast<unsigned char *>(LoadFileContent(bmpPath));if (bmpFileContent == NULL) {return 0;}unsigned char *pixelData = DecodeBMP(bmpFileContent, width, height);LOGD("pixelData %d, width = %d, height = %d",pixelData, width, height);if (pixelData == NULL) {delete[] bmpFileContent;return 0;}LOGD("ReadBMP END");return bmpFileContent; }

2)在Nativity.cpp中調用解析bmp數據并賦值到紋理類中

JNIEXPORT void JNICALL NativeImpl_init(JNIEnv *env, jobject instance) {TextureDemo::GetInstance();int width = 0, height = 0;unsigned char *img = ReadBMP("awesomeface.bmp", width, height);//解析獲取圖片數據TextureDemo::GetInstance()->getTexturedata(img, width, height);TextureDemo::GetInstance()->CreateProgram(reinterpret_cast<const char *>(LoadFileContent("vertex.vs")),reinterpret_cast<const char *>(LoadFileContent("fragment.fs"))); }

3)紋理實現類

TextureDemo.h

// // Created by CreatWall_zhouwen on 2023/4/13. //#ifndef TWODRAWTEXTURE_TEXTUREDEMO_H #define TWODRAWTEXTURE_TEXTUREDEMO_H#include <GLES3/gl3.h>class TextureDemo { public:TextureDemo(){program = 0;vertexShaderHandle = 0;fragShaderHandle = 0;};~TextureDemo(){};void CreateProgram(const char *ver, const char *frag);void Draw();void getTexturedata(unsigned char *data, int width, int height);static TextureDemo* GetInstance();static void DestroyInstance(); private:GLuint program;GLuint vertexShaderHandle;GLuint fragShaderHandle;GLuint VBO, VAO, EBO;unsigned int texture;unsigned char *texturedata;int texturewidth, textureheight; };#endif //TWODRAWTEXTURE_TEXTUREDEMO_H

TextureDemo.cpp

// // Created by CreatWall_zhouwen on 2023/4/13. //#include "TextureDemo.h" #include "Util.h" TextureDemo* m_pContext = nullptr; #define TAG "DRAWTEXTURE"float vertices[] = {//---- 位置 ---- - 紋理坐標 -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, // 右上0.5f, -0.5f, 0.0f, 1.0f, 0.0f, // 右下-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, // 左下-0.5f, 0.5f, 0.0f, 0.0f, 1.0f // 左上 }; //索引數組 unsigned int indices[] = {0, 1, 3, // first triangle1, 2, 3 // second triangle };void TextureDemo::CreateProgram(const char *ver, const char *frag) {LOGD("CreateProgram Enter");//程序中加載編譯頂點著色器vertexShaderHandle = glCreateShader(GL_VERTEX_SHADER);//創建頂點著色器glShaderSource(vertexShaderHandle, 1, &ver, NULL);glCompileShader(vertexShaderHandle);GLint compiled = 0;glGetShaderiv(vertexShaderHandle, GL_COMPILE_STATUS, &compiled);//if (!compiled){LOGD("glCompileShader vertexShaderHandle error");return;}//程序中加載編譯片段著色器fragShaderHandle = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragShaderHandle, 1, &frag, NULL);glCompileShader(fragShaderHandle);glGetShaderiv(fragShaderHandle, GL_COMPILE_STATUS, &compiled);if(!compiled){LOGD("glCompileShader fragShaderHandle error");return;}//創建程序program = glCreateProgram();if (program){//添加頂點著色器GLint AttachStatus = GL_FALSE;glAttachShader(program, vertexShaderHandle);glGetShaderiv(vertexShaderHandle, GL_ATTACHED_SHADERS, &AttachStatus);if(AttachStatus == 1){LOGD("glAttachShader vertexShaderHandle error");return;}//添加片段著色器glAttachShader(program, fragShaderHandle);glGetShaderiv(fragShaderHandle, GL_ATTACHED_SHADERS, &AttachStatus);if(AttachStatus == 2){LOGD("glAttachShader fragShaderHandle error");return;}//鏈接glLinkProgram(program);GLint linkStatus = GL_FALSE;glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);if (linkStatus != GL_TRUE){LOGD("glLinkProgram error");return;}//成功連接到程序之后就可以解綁刪除glDetachShader(program, vertexShaderHandle);glDeleteShader(vertexShaderHandle);glDetachShader(program, fragShaderHandle);glDeleteShader(fragShaderHandle);vertexShaderHandle = 0;fragShaderHandle = 0;}LOGD("program success");/* -----頂點相關------ *///創建頂點數組glGenVertexArrays(1, &VAO);//創建頂點緩沖區glGenBuffers(1, &VBO);//綁定頂點數組glBindVertexArray(VAO);//將頂點緩沖區綁定為GL_ARRAY_BUFFERglBindBuffer(GL_ARRAY_BUFFER, VBO);//將定義的頂點數組綁定到GL_ARRAY_BUFFER這個緩存中,這個緩存對應頂點緩沖區數據glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);/* -----綁定紋理相關------ *///將GL_ELEMENT_ARRAY_BUFFER緩沖區綁定到EBOglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);//將索引坐標綁定到GL_ELEMENT_ARRAY_BUFFERglBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);//指定配置的頂點屬性,第一個index參數對應頂點著色器的location值glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float ), (void *)0);//啟用頂點屬性glEnableVertexAttribArray(0);//紋理屬性綁定glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float ), (void *)(3*sizeof(float)));glEnableVertexAttribArray(1);//將頂點數組和頂點緩沖區置空則不讓其他修改glBindBuffer(GL_ARRAY_BUFFER, 0);glBindVertexArray(0);/* -----創建加載紋理------ *///創建紋理glGenTextures(1, &texture);//將紋理綁定到GL_TEXTURE_2DglBindTexture(GL_TEXTURE_2D, texture);//為當前綁定的紋理對象設定紋理環繞方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);//重復紋理的填充方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);//為當前綁定的紋理對象設定紋理過濾方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);//縮小時線性插值glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//放到就是線性//綁定紋理數據glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texturewidth, textureheight, 0, GL_RGB, GL_UNSIGNED_BYTE, texturedata);LOGD("CreateProgram %s", texturedata);glGenerateMipmap(GL_TEXTURE_2D);//為當前綁定的紋理自動生成所有需要的多級漸遠紋理LOGD("CreateProgram END"); } void TextureDemo::Draw() {glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glClearColor(0.2f, 0.9f, 0.3f, 1.0f);//指定使用的著色器程序glUseProgram(program);glBindTexture(GL_TEXTURE_2D, texture);LOGD("glBindTexture");//綁定頂點數組glBindVertexArray(VAO);//畫紋理glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);glBindVertexArray(0);} TextureDemo* TextureDemo::GetInstance() {if (m_pContext == nullptr){m_pContext = new TextureDemo();}return m_pContext; } void TextureDemo::DestroyInstance() {if (m_pContext){delete m_pContext;m_pContext = nullptr;} }void TextureDemo::getTexturedata(unsigned char *data, int width, int height) {texturedata = data;texturewidth = width;textureheight = height; }

安卓配置部分與三、畫三角形一致。

引入資源與三、畫三角形一致,只是多出一個解析bmp圖片數據的接口

參考鏈接

OpenGL ES 3.0 開發之紋理貼圖 https://blog.csdn.net/qq_39792615/article/details/113394702

總結

以上是生活随笔為你收集整理的四、纹理显示图片的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。