Ⅰ 怎麼在ios開發中使用opengl
一、搭建開發環境
1. 打開Xcode, 新建一個工程
選擇:IOS -> Application -> Single View Application模板
輸入工程名稱和基本信息,勾選「UseStoryboards」,然後創建
2. 添加必要的框架
在「Build Phases」中,添加三個框架
3. 修改viewController。h
添加 「#import」,並將它修改為繼承"GLKViewController"
4. 修改「view」的類
雙擊「MainStoryboard.storyboard」展開,選擇"view"
然後,在「Identity Inspector"中,將它的類改為」GLKView「
好了,OpenGL的環境基本上搭建出來了。
二、增加自己代碼
基本上,所有的代碼都是加到ViewController.m文件中
1、添加全局山圓屬性聲明
@interface ViewController ()@property(strong,nonatomic)EAGLContext*
context;@property(strong,nonatomic)GLKBaseEffect* effect;@end@implementation
ViewController@synthesize context, effect;
2、 添加一組頂點數據
這是一個正方形頂點數組。實際上它是二個三角形接合而成的
GLfloat squareVertexData[48] ={ 0.5f, 0.5f, -0.9f, 0.0f, 0.0f, 1.0f, 1.0f,
1.0f, -0.5f, 0.5f, -0.9f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.5f, -0.5f, -0.9f,
0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.5f, -0.5f, -0.9f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.9f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, -0.5f, -0.5f, -0.9f, 0.0f,
0.0f, 1.0f, 1.0f, 1.0f,};
每行頂點數據的排列蠢櫻含義是:
頂點X、頂點Y,頂點Z、法線X、法線Y、法線Z、紋理S、紋理T。
在後面解析此數組時,將參考此規則。
頂點位置用於確定在什麼地方顯示,法線用於光照模型計算,紋理則用在貼圖中。
一般約定為「頂點以逆時針次序出現在屏幕上的面」為「正面」。
世界坐標是OpenGL中用來描述場景的坐標,Z+軸垂直屏幕向外,X+從左到右,Y+軸從下到上,是右手笛卡爾坐標系統。我們用這個坐標系來描述物體及光源的位置。
三、初始化OpenGL環境逗檔塌
1、 基本的初始化代碼
在ViewController.m中有個函數(void)viewDidLoad,它是程序運行時,初始化回調函數。在viewDidLoad函數內補充我們自己的初始化代碼。
// 使用「ES2」創建一個「EAGLEContext」實例 self.context = [[[EAGLContext
alloc]initWithAPI:kEAGLRenderingAPIOpenGLES2]autorelease]; //
將「view」的context設置為這個「EAGLContext」實例的引用。並且設置顏色格式和深度格式。 GLKView* view =
(GLKView*)self.view; view.context = self.context; view.drawableColorFormat =
; view.drawableDepthFormat =
GLKViewDrawableDepthFormat24; //
將此「EAGLContext」實例設置為OpenGL的「當前激活」的「Context」。這樣,以後所有「GL」的指令均作用在這個「Context」上。隨後,發送第一個「GL」指令:激活「深度檢測」。
[EAGLContext setCurrentContext:context]; glEnable(GL_DEPTH_TEST); //
創建一個GLK內置的「著色效果」,並給它提供一個光源,光的顏色為綠色。 self.effect = [[[GLKBaseEffect
alloc]init]autorelease]; self.effect.light0.enabled = GL_TRUE;
self.effect.light0.diffuseColor = GLKVector4Make(0.0f, 1.0f, 0.0f, 1.0f);
2、 運行。現在應該是粉紅色屏幕了(目前場景仍是空的),說明初始化過程沒問題
四、 將項點數據寫入能用的頂點屬性存儲區
1、 寫入過程
首先將數據保存進GUP的一個緩沖區中,然後再按一定規則,將數據取出,復制到各個通用頂點屬性中。
註:如果頂點數據只有一種類型(如單純的位置坐標),換言之,在讀數據時,不需要確定第一個數據的內存位置(總是從0開始),則不必事先保存進緩沖區。
2、 頂點數組保存進緩沖區
//
聲明一個緩沖區的標識(GLuint類型)讓OpenGL自動分配一個緩沖區並且返回這個標識的值.綁定這個緩沖區到當前「Context」.最後,將我們前面預先定義的頂點數據「squareVertexData」復制進這個緩沖區中。
// 註:參數「GL_STATIC_DRAW」,它表示此緩沖區內容只能被修改一次,但可以無限次讀取。 GLuint buffer;
glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(squareVertexData), squareVertexData,
GL_STATIC_DRAW);
3、將緩沖區的數據復制進能用頂點屬性中
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 4*8,
(char*)NULL + 0);
首先,激活頂點屬性(默認它的關閉的)。「GLKVertexAttribPosition」是頂點屬性集中「位置Position」屬性的索引。
頂點屬性集中包含五種屬性:位置、法線、顏色、紋理0,紋理1。
它們的索引值是0到4。
激活後,接下來使用「glVertexAttribPointer」方法填充數據。
Ⅱ iOS-OpenGLES-入門-紋理
這是一篇OpenGlES 系統學習教程,記錄自己的學習過程。
環境: Xcode10 + OpenGL ES 3.0
目標: 紋理貼圖技術
這里 是demo,你的star和fork是對我最好的支持和動力。
紋理坐標在x和y軸上,范圍為0到1之間(注意我們使用的是2D紋理圖像)。使用紋理坐標獲取紋理顏色叫做采樣(Sampling)。紋理坐標起始於(0, 0),也就是紋理圖片的左下角,終始於(1, 1),即紋理圖片的右上角。
下面的圖片展示了昌余我們是如何把紋理坐標映射到三角形上的。
紋理的部分理論知耐檔滾識可以參考 這里
跟生成OpenGl 對象差不多
glTexImage2D 原型如下:
一個紋理的位置值通常稱為一個紋理單元(Texture Unit)。一個紋理的默認紋理單元是0,它是默認的激活紋理單元,本文前面部分我們沒有分配一個位置值。如果使用多個紋理單元需要手動分配。
紋理單元的主要目的是讓我們在著色器中可以使用多於一個的紋理。通過把紋理單元賦值給采樣器,我們可以一次綁定多個紋理,只要我們首先激活對應的紋理單元。就像glBindTexture一樣,我們可以使用glActiveTexture激活紋理單元,傳入我們需要使用的紋理單元:
你可能會奇怪為什麼sampler2D變數是個uniform,我們卻不用glUniform給它賦值。使用glUniform1i,我們可以給紋理采樣器分配一個位置值,這樣的話我們能夠在一個片段著色器中設置多個紋理。
紋理上蠢畢下顛倒解決方法
註:這里使用到了Vertex Buffer Object,下篇會詳解。
Ⅲ iOS-OpenGLES-入門-立方體
這是一篇OpenGlES 系統學習教程,記錄自己的學習過程。
環境: Xcode10.2 + OpenGL ES 3.0
目標: 3D 立方體
這里 是demo,你的star和fork是對我最好的支持和動力。
主要有5個不同的坐標系統:
變換
為了將坐標從一個坐標系變換到另一個坐標系,我們需要用到幾個變換矩陣,最重要的幾個分別是 模型 (Model)、 觀察 (View)、 投影 (Projection)三個矩陣。我們的頂點坐標起始於 局部空間 (Local Space),在這里它稱為 局部坐標 (Local Coordinate),它在之後會變為 世界坐標 (World Coordinate), 觀察坐標 (View Coordinate), 裁剪坐標 (Clip Coordinate),並最後以 屏幕坐標 [圖片上傳中...(坐標系變換.png-d41a13-1555986546530-0)]
(Screen Coordinate)的形式結束。下面的這張圖展示了整個流程以及各個變換過程做了什麼:
透視投影
在現實生活中近大遠燃謹小的效果稱之為 透視 。如鐵軌的兩條軌道,飢緩由於透視,在很遠的地方看起來會相交皮肢基一樣,這就是透視投影想要模仿的效果,它通過 透視投影矩陣 來完成,推導過程可以看 這里 。
正交投影
當使用正射投影時,每一個頂點坐標都會直接映射到裁剪空間中而不經過任何精細的透視除法(它仍然會進行透視除法,只是w分量沒有被改變(它保持為1),因此沒有起作用)。因為正射投影沒有使用透視,遠處的物體不會顯得更小,所以產生奇怪的視覺效果。由於這個原因,正射投影主要用於二維渲染以及一些建築或工程的程序,在這些場景中我們更希望頂點不會被透視所干擾
把以上每個步驟創建的變換矩陣:模型矩陣、觀察矩陣和投影矩陣組合起來。一個頂點坐標將會根據以下過程被變換到剪裁坐標系:
注意矩陣運算的順序是相反的(記住我們需要從右往左閱讀矩陣的乘法)。最後的頂點應該被賦值到頂點著色器中的gl_Position,OpenGL將會自動進行透視除法和裁剪。
頂點數據
矩陣變換過程
最後注意點
Ⅳ 基於視錐體(平截體)的OpenGL ES性能優化
OpenGLES入門教程1-Tutorial01-GLKit
OpenGLES入門教程2-Tutorial02-shader入門
OpenGLES入門教程3-Tutorial03-三維變換
OpenGLES入門教程4-Tutorial04-GLKit進階
OpenGLES進階教程1-Tutorial05-地球月亮
OpenGLES進階教程2-Tutorial06-光線
OpenGLES進階教程3-Tutorial07-粒子效果
OpenGLES進階教程4-Tutorial08-幀緩存
OpenGLES進階教程5-Tutorial09-碰碰車
這一次的是性能優化。
渲染的優化不是僅僅提高渲染的速度,超過60Hz的渲染速度沒有任何意義,用戶永遠看不到這些信息。同時在考慮用電消耗的情況下,30Hz的刷新率能延長電池的使用時間。
以下的渲染優化策略總衫銷是管用的:
通過減少渲染的幾何對象,在不影響顯示效果的喚塌辯前提下,盡可能減少需要繪制的圖元。
在一個場景中,很多物體是處於平截體外部,這些物體是用戶永遠看不到的對象。
計算眼睛到當前測試點的向量,提取這個向量關於平截體X、Y、Z軸的分量,分別進行判斷。
測試球體會測試點更復雜,同樣是對比X/Y/Z軸分量,在判斷的范圍加上半徑的距離。
但是,考慮下面的情況
如下圖,考慮球體被外切情況,得出相應的放大因子。
為什麼FPS會在20FPS和30FPS之間擺動?
繪制 和 顯示 並不一樣。
通過CADisplayLink(hardware generated),繪制的速率可能是60FPS。
如果繪制的時間超過1/60s,理論上幀率最多為30FPS。
想像一條1s的線段,分隔成60小段,每個小段的起點都可以作為繪制的起點。
如果繪制的時間超過1/60s,那麼繪制的終點會延伸到第二個小段。
這樣,一條1s的線段,最多有30個繪制的時間段。
你能得到FPS,但是它不代表真正的性能,每幀持續時間是一個更佳選擇。FPS不能線性評判性能表現。
最後, 即使你自己通過自定義線程(不採用CADisplayLink),把繪制時和缺間的空缺填補,實際上繪制的速率並不會變快 。
主要講解的是數學部分的知識,OpenGL ES的部分沒有引入新的技術點。
工作原因,以後更新會慢一些。能看到這里,你也是喜歡技術的,謝謝支持。來一波關注和喜歡如何 -> 我會加油更新。
附上 源碼
Ⅳ android的如何使用異或方式繪圖
1)使用canvas/paint方式的繪圖為軟體渲染,通過cpu實現;使用opengles/shader方式的繪圖為硬體加速渲染,通過gpu實現。
2)surfaceview和glsurfaceview的顯示一般結合opengles,悉衫使用紋理(texture),為硬體渲染,通過gpu實現
3)glsurfaceview是surfaceview的子類,在後者基礎上封裝了egl環境管理,以及render線程
4)opengles繪制函數及shader是平台無關的,需要egl環境對接android/ios等平台
5)android graphic 底層都與BufferQueue、Surfaceflinger等相關,具體可參畢陸數考android開發者文檔
個人經驗,如有不對之處請幫忙指出
作者:阿占
鏈接:https://www.hu.com/question/36030004/answer/65581599
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請註明出處手首。
Ⅵ iOS 使用openGLES畫線缺少函數
你添OpenGL的框架了么??
Ⅶ iOS使用OpenGLES和freetype繪制字體
-------------挖個坑,還在學習中------------
第一步,理解內存、bitmap、OpenGLES、freetype的使用
第二步,
實現流程:
調用freetype的介面,將文字寫入內存點陣圖
將這塊位置拷貝到一個大圖上面(更到一個內存點陣圖)
記住它在大圖的起始坐標與大小
再將大圖寫入到紋理,就可以按四邊形(兩個三角形)來繪制這個文字了
主要分兩步:第一步是生成點陣圖,第二步是將點陣圖寫入紋理在渲染出來、
freetype,生成的單個字的小點陣圖,你需要將小點陣圖合並到一個大的點陣圖上面(比如1024的大圖,可以容納很多個文字)
再將這個大的位局型置更新gl紋理對象,後面就是繪制三角形了
char *pBitmapDatas = new char[nWidth*nHeight*4];
這個就桐胡猜是32位的點陣圖數據,argb 位8位
字多大,你可以通過freetype的介面做此獲取的嘛
也是你自己設置的
那字點陣圖在大點陣圖上的位置呢?
你自己定啊,按固定大小分好格子,一個個的填充
大小取字體的最大寬度與高度
大圖是為了優化速度用的
不做優化的話,直接一個文字一個貼圖,也是可以的
效果是一樣的
大圖是為了做批渲染,優化渲染速度
Ⅷ 【iOS】(一)GPUImage的結構,濾鏡鏈的實現原理
學了OpenGL,OpenGLES後,去閱讀了GPUImage的源碼,使用了一段時間,接下來,記錄一下我對GPUImage使用和源碼閱讀的一些分析吧。
相關引用
從0打造一個GPUImage(6)-GPUImage的多濾鏡處理邏輯
對於GPUImage,可以分為
上面也提了,所謂的GPUImage濾鏡鏈弊祥就是
GPUImageOutput -> filter -> filter -> GPUImageInput
GPUImageOutput 通過target數組(裡面都是實現 GPUImageInput 組件),組成了濾鏡鏈的關系,我們需要牢牢的記住這個濾鏡鏈的關系,這樣開發的時候,我們就知道如何Debug,如何實現我們需要的效果。那麼問題來了,為什麼GPUImage可以實現這樣的濾鏡鏈呢?
這里租數搏我們先拋開GPUImage,用OpenGL ES去實現一個具有濾鏡疊加效果的Demo,這里的Demo我是參考葉孤城的這篇文章, 從0打造一個GPUImage(6)-GPUImage的多濾鏡處理邏輯
Demo需要實現的效果,是將一張圖片,先後通過疊加 亮度濾畢行鏡 , 飽和度濾鏡 最後顯示在屏幕上。
那麼對應的OpenGLES,我們會怎麼做呢?首先我們需要以下東西
從以上的步驟,我們可以總結以下結論
對於這個Demo的一個流程圖,可以參考 從0打造一個GPUImage(6)-GPUImage的多濾鏡處理邏輯 的一幅圖,Demo的詳細實現請看原文吧。
以上就是GPUImage對於濾鏡鏈的實現原理,只有你懂了OpenGL ES的渲染流程,才能徹底的明白GPUImage的濾鏡鏈的原理。所以時時刻刻記住以下關系
GPUImageOutput -> filter -> filter -> GPUImageInput
當然也可以存在多個Source,多個Input的情況,例如要給一個視頻添加水印,用 GPUImageMovie 用於輸出視頻紋理,用 GPUImageUIElement 輸出UI空間的紋理,通過一個filter進行Blend,最後用一個 GPUImageView 進行預覽,用 GPUImageMovieWriter 進行輸出,濾鏡鏈關系如下
Ⅸ 如何為iOS5創建一個簡單GLKit應用程序
內容: How to start an empty GLKit application for iOS 5
本教程是2D游戲引擎教程的序,但對伏孝於任何一個剛步入iOS世界,想用Xcode4開發GLKit相關應用的人,本教程都有拋針引線的作用。其中大部份內容都是摘取自我的另一篇教程「學習iOS5中GLKit關於OpenGL的基本用法」,那篇教程繪制了一個3D立方體,很值得缺族稿一讀。
用XCode創建一個新的iOS應用,模版選擇「Empty Application」。取個工程名(我將要編寫一個游戲引擎,所以我命名為"ExampleEngine"),保持默認選擇(如果是編寫一個庫,那在類前最好有個前綴,我用的是「EE」),保存。
接著我們添加OpenGL與GLKit相關frameworks。點擊左上角的工程,然後選中TARGETS下你的target,再選中Build Phases欄,在「Link Binary With Libraries」中加入GLKit, OpenGLES,QuartzCore這三個framework。完成後,你將會在工程中看到你加入的framework,當然你也可以用拖的方式將其拖入Frameworks分組下。
確保你選擇的是模擬器(如果你有開發者帳號,你可以用合法的provisioning profile來真機調試,於是你可以選擇device),按⌘B 確保可以正確編譯。
在AppDelegate頭文件里引入GLKit頭文件,這樣就可以調用GLKit中的方法。
01.// AppDelegate.h
02.#import <UIKit/UIKit.h>
03.#import <GLKit/GLKit.h>
04....
GLKit了類化了UIView與UIViewController,利用它們將方便我們把OpenGL場景集成到我們的應用中。兩個類都是用代理(蘋果Objective-C庫中一種非常通用的設計模式)的計設模式嵌入到我們的應用代碼中。我們要用AppDelegate作為GLKit的代理,因此得告訴編譯器AppDelegate會實現代理協議。
01.// AppDelegate.h
02....
03.@interface AppDelegate : UIResponder <UIApplicationDelegate,
04. GLKViewDelegate, GLKViewControllerDelegate>
穗純05....
現在來創建場景。將application:didFinishLaunchingWithOptions:這個方法用下面代碼替換:
01.- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
02.{
03. EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
04. [EAGLContext setCurrentContext:context];
05.
06. GLKView *view = [[GLKView alloc] initWithFrame:[[UIScreen mainScreen] bounds] context:context];
07. view.delegate = self;
08.
09. GLKViewController *controller = [[GLKViewController alloc] init];
10. controller.delegate = self;
11. controller.view = view;
12.
13. self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
14. self.window.rootViewController = controller;
15. [self.window makeKeyAndVisible];
16.
17. return YES;
18.}
■第3,4行創建OpenGL繪制時需要的上下文。
■第6,7行設置繪制場景的view。第6行,由OpenGL上下文創建屏幕大小的view。第7行指明view的代理為AppDelegate。這樣繪制每一幀的時候就會調用glkview:drawInRect:這個方法。
■第9-11行,創建GLKViewController,並指明其代理類與view。代理方法中我們主要關心 glkViewControllerUpdate:
■第13-15行,將我們的controller與"window"關聯,以便顯示。
■第17行通知OS我們的應用已啟動完成。
現在代理方沒還沒實現所以有警告提示,但是也可以運行。運行後,你會看到純色的背景,看一看吧!
現在我們把這些警告去掉交改背景為灰色。在theapplication:didFinishLaunchingWithOptions:方法下面實現如下代理方法:
01.- (void)glkViewControllerUpdate:(GLKViewController *)controller {
02.// NSLog(@"in glkViewControllerUpdate");
03.}
04.
05.- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
06.// NSLog(@"in glkView:drawInRect:");
07. glClearColor(0.5, 0.5, 0.5, 0.5);
08. glClear(GL_COLOR_BUFFER_BIT);
09.}
現在再運行,你會看到灰色背景,由gl開頭的API實現的。在OpenGL與GLKit中,顏色由四個分量組成,分別是紅,綠,藍與alpha(透明度),每一個分量取值范圍是[0,1]。
如果你打開上面代碼中的NSLog注釋,你會在控制台看到如下列印。
這兒有兩個方法,因為GLKit基於state與presentation的(類似於MVC的設計模式或HTML/CSS分開發設計)。State(動畫,物理模擬,游戲邏輯)應在glkViewControllerUpdate:這回調中,而glkView:drawInRect應用來繪制場景的。
申明:本系列教程原稿來自網路,翻譯目的僅供學習與參看,請匆用於商業目的,如果產生商業等糾紛均與翻譯人、該譯稿發表人無關。轉載務必保留此申明。