cocos2dx:cocos之Shader
轉自:http://blog.csdn.net/u013235682/article/details/46687383
紋理和管線
紋理的概念
在現實生活中,物體都是有邊界的,比如一顆石頭,有一層表面,當我們給它拍個照片,就能變成一張二維的圖片了,那麼這個圖片就是石頭的紋理。
可是石頭是立體的,並不是二維的,立體這種東西,是我們人對石頭的一種感覺,如果把石頭拿在手裡,轉動這個石頭或者轉動我們的位置,我們可以看到這個石頭的多個面,於是給我們一種立體的概念。
計算機圖形學要將這種感覺給繪製出來,形成3d效果,那麼就需要一系列的資料結構來描述這種東西。紋理這個概念就這樣被提出來,石頭的每一個面,都是紋理。
管線的概念
可以想象,一個石頭的紋理也是很多的。。。計算機都要畫呀畫,好累。。。紋理是一個平面的東西,GPU用它來作為繪製的單位
於是,生產顯示卡的那幫人,就想著,要是一下子就能繪製10000個紋理就好了,因此提出了管線的概念。管線指可以獨立繪製紋理的單元,一個顯示卡有16管線,就表示它能同時渲染16個紋理,這個引數也是衡量顯示卡效能的標誌。
管線渲染流程
可程式設計管線上面的連結說了渲染流程,所以我就不說一個管線怎麼渲染紋理的了啊
可程式設計管線
就是cpu向gpu傳送渲染的內容時,同時帶一段程式過去,讓管線可以根據程式來進行一些額外的操作。
一段shader程式
看看一段shader程式吧,來自cocos2dx的cpptest資源裡的,看人家第一行的註釋,也是從別人那邊抄的
// Shader from http://www.iquilezles.org/apps/shadertoy/#ifdef GL_ESprecision highp float;#endifuniform vec2 center;uniform vec2 resolution;void main(void){ float time = CC_Time[1]; vec2 p = 2.0 * (gl_FragCoord.xy - center.xy) / resolution.xy; // animate float tt = mod(time,2.0)/2.0; float ss = pow(tt,.2)*0.5 + 0.5;
C語言程式設計師是不是看著是不是很熟悉,shader語言很像是C語言
cocos2dx怎麼把程式送到GPU去?
很簡單,直接呼叫setShaderProgram即可
bool C01S10Shader::init(){ LayerBack::init(); // 這是一個正常的精靈,用來對比的 Sprite* sprite = Util::addSprite("Images/grossini.png", this); sprite->setPosition(50, winSize.height/2); { // 這個是要用shader處理的精靈,addSprite函式是我自己寫的,沒放上來,就是建立一個精靈,放在this指標的中間 _sprite = Util::addSprite("Images/grossini.png", this); // "Shaders/example_edgeDetection.fsh" // 讀取shader程式,shader程式是寫在一個檔案裡的 auto fileUtiles = FileUtils::getInstance(); auto fragmentFullPath = fileUtiles->fullPathForFilename("Shaders/example_bloom.fsh"); auto fragSource = fileUtiles->getStringFromFile(fragmentFullPath); // 通過shader程式字串去建立一個GLProgam物件 auto glprogram = GLProgram::createWithByteArrays(ccPositionTextureColor_noMVP_vert, fragSource.c_str()); CCLOG("%s\n", ccPositionTextureColor_noMVP_vert); // 設定到這個精靈去,將來這個精靈被渲染時,這段程式也會被帶過去,GPU對這個精靈對應的紋理,進行額外的操作 _sprite->setGLProgram(glprogram); } return true;}