iOS-----openGL--openGL ES iOS 入門篇3---> 紋理貼圖(texture)

來源:互聯網
上載者:User

標籤:gen   文章   tcl   linear   ima   size   過程   shader   bitmap   

在這篇文章中,我們將學習如何在openGL中使用紋理貼圖。

penGL中紋理可以分為1D,2D和3D紋理,我們在綁定紋理對象的時候需要指定紋理的種類。由於本文將以一張圖片為例,因此我們為我們的紋理對象綁定一個GL_TEXTURE_2D的紋理。

本文將分為兩個部分,一部分是如何通過圖片擷取一個2D的紋理,另一部分是如何使用一個紋理。

在上一篇中,我們介紹了如何使用shader來繪製一個多邊形,本文是基於上一篇的提高,我們也將繼續使用shader,對於shader使用不熟的童鞋可以看上一篇。

 

首先我們來看看如何通過圖片擷取一張2D的紋理。

+ (GLuint)createTextureWithImage:(UIImage *)image{
  //轉換為CGImage,擷取圖片基本參數 CGImageRef cgImageRef = [image CGImage]; GLuint width = (GLuint)CGImageGetWidth(cgImageRef); GLuint height = (GLuint)CGImageGetHeight(cgImageRef); CGRect rect = CGRectMake(0, 0, width, height);
  //繪製圖片 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); void *imageData = malloc(width * height * 4); CGContextRef context = CGBitmapContextCreate(imageData, width, height, 8, width * 4, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmap    ByteOrder32Big); CGContextTranslateCTM(context, 0, height); CGContextScaleCTM(context, 1.0f, -1.0f); CGColorSpaceRelease(colorSpace); CGContextClearRect(context, rect); CGContextDrawImage(context, rect, cgImageRef);
 //紋理一些設定,可有可無    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  
//產生紋理
glEnable(GL_TEXTURE_2D);
  GLuint textureID;
  glGenTextures(1, &textureID);
  glBindTexture(GL_TEXTURE_2D, textureID);  
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
  //綁定紋理位置  glBindTexture(GL_TEXTURE_2D, 0);
  //釋放記憶體 CGContextRelease(context); free(imageData); return textureID;}

 

擷取紋理之後,我們就要開始使用紋理了。

和之前繪製多邊形的過程一樣,我們要先把參數傳入shader中。在繪製多邊形時我們只需要傳入各個頂點的位置,但為了使用紋理,我們需要把紋理傳入shader,

此外,還要傳入所使用的紋理的範圍(使用紋理的哪一部分來映射)。

 

Vertex Shader代碼如下:

attribute vec4 Position;attribute vec2 TextureCoords;varying vec2 TextureCoordsOut;void main(void){
//用來展現紋理的多邊形頂點 gl_Position = Position;
//表示使用的紋理的範圍的頂點,因為是2D紋理,所以用vec2類型 TextureCoordsOut = TextureCoords;}

 

Fragment Shader代碼如下:

precision mediump float;uniform sampler2D Texture;varying vec2 TextureCoordsOut;void main(void){
//擷取紋理的像素 vec4 mask = texture2D(Texture, TextureCoordsOut);
gl_FragColor = vec4(mask.rgb, 1.0);}

 

注意:

attribute屬性只能通過Vertex Shader傳入,再傳給Fragment Shader,而uniform屬性可以直接傳入Fragment Shader。

 

同理的,與繪製多邊形的過程一樣,我們要編譯shader,產生一個glProgram。不同的是,這次我們要傳入著色器程式的參數有三個

  GLuint fragmentShader = [self compileShader:@"MTShaderFragment"                                       withType:GL_FRAGMENT_SHADER];    _glProgram = glCreateProgram();    glAttachShader(_glProgram, vertexShader);    glAttachShader(_glProgram, fragmentShader);    glLinkProgram(_glProgram);    glUseProgram(_glProgram);        _positionSlot = glGetAttribLocation(_glProgram, "Position");
  //uniform類型的參數擷取方式不同 _textureSlot = glGetUniformLocation(_glProgram, "Texture"); _textureCoordsSlot = glGetAttribLocation(_glProgram, "TextureCoords");

 

接下來就到了最後一步,將紋理“貼”到多邊形上。

首先將紋理傳入,啟用索引為1的紋理。表示接下來的操作都是針對紋理1

glActiveTexture(GL_TEXTURE1);
//載入紋理glBindTexture(GL_TEXTURE_2D, _textureID);
//為當前程式對象指定Uniform變數的值,參數1代表使用的新值(GL_TEXTURE1)glUniform1i(_textureSlot, 1);

 

在指定地區繪製紋理。

注意:用於表示紋理範圍時的座標表示方式與UIKit和openGL的座標都不同,範圍從(0,0)左下到(1,1)右上。

//紋理使用範圍頂點
const GLfloat texCoords[] = { 0, 0,//左下 1, 0,//右下 0, 1,//左上 1, 1,//右上 }; glVertexAttribPointer(_textureCoordsSlot, 2, GL_FLOAT, GL_FALSE, 0, texCoords); glEnableVertexAttribArray(_textureCoordsSlot); //繪圖區域頂點 const GLfloat vertices[] = { -1, -1, 0, //左下 1, -1, 0, //右下 -1, 1, 0, //左上 1, 1, 0 }; //右上 glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, 0, vertices); glEnableVertexAttribArray(_positionSlot); const GLubyte indices[] = { 0,1,2, 1,2,3 }; glDrawElements(GL_TRIANGLES, sizeof(indices)/sizeof(indices[0]), GL_UNSIGNED_BYTE, indices); [_context presentRenderbuffer:GL_RENDERBUFFER];

 

下一篇我們會講解如何進行一些動態操作和簡單濾鏡,讓手指划過的地區變成灰色。

iOS-----openGL--openGL ES iOS 入門篇3---> 紋理貼圖(texture)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.