在這個教程中,我們會做一個可以渲染Mandelbrot Set的應用程序,我們可以縮放和平鋪它來看分形那令人驚嘆的復雜之美。終的結果可點擊鏈接查看小視頻。
著色程序代碼如下:
[cpp] view plaincopy
void main() {
#define iterations 128
vec2 position = v_tex_coord; // gets the location of the current pixel in the intervals [0..1] [0..1]
vec3 color = vec3(0.0,0.0,0.0); // initialize color to black
vec2 z = position; // z.x is the real component z.y is the imaginary component
// Rescale the position to the intervals [-2,1] [-1,1]
z *= vec2(3.0,2.0);
z -= vec2(2.0,1.0);
vec2 c = z;
float it = 0.0; // Keep track of what iteration we reached
for (int i = 0;i < iterations; ++i) {
// zn = zn-1 ^ 2 + c
// (x + yi) ^ 2 = x ^ 2 - y ^ 2 + 2xyi
z = vec2(z.x * z.x - z.y * z.y, 2.0 * z.x * z.y);
z += c;
if (dot(z,z) > 4.0) { // dot(z,z) == length(z) ^ 2 only faster to compute
break;
}
it += 1.0;
}
if (it < float(iterations)) {
color.x = sin(it / 3.0);
color.y = cos(it / 6.0);
color.z = cos(it / 12.0 + 3.14 / 4.0);
}
gl_FragColor = vec4(color,1.0);
}
你可以下載 起始版本跟著教程一起做,也可以在本文結尾找到終版本的代碼。
Gamescene.sks文件里包含一個名為fractal的子畫面,它填充了整個界面并且著色程序程序Fractal.fsh也附在它上。
Fractal.fsh包含了上面著色程序的代碼;
GameViewController.swift包含了設置游戲場景的代碼;
GameScene.swift為空。
如果你現在運行代碼,你將會得到如下的結果:
請注意縱橫比固定為3/2,我們需要先根據屏幕大小調節它。同時,由于畫面是靜態的,所以你不可能與它有任何方式的交互。
我們將用一個透明的scrollview來處理平鋪縮放。scrollview將自動跟蹤我們的位置以及我們在分形中的縮放程度。
打開'Main.storyboard'文件,拖進去一個scrollview。將scrollview設置成fill the view,并對它的寬度,到頂部距離,到底部距離設置限制。
將scrollview的大縮放程度設置為100000,意味著我們將可以把分享放大到十萬倍!我們不能再放大更多了因為已經接近了`float`類型的準確極限。
拖一個view(畫面)到scrollview里,它將用作處理縮放。這個view本身不會展示任何東西,我們將用到它的contentOffset和scrollView的zoom屬性來更新我們的著色程序。要確保這個畫面可以填滿scrollView,并且設定好寬度,到頂部底部左右距離的限制。將畫面的背景色設置為 Clear Color (透明色)。
接下來我們將連接我們所需要的outlet和scrollView的代理。給scrollView和scrollView的contentView拖進outlet。
[cpp] view plaincopy
class GameViewController: UIViewController, UIScrollViewDelegate {
@IBOutlet weak var contentView: UIView!
@IBOutlet weak var scrollView: UIScrollView!
...
}
接下來我們去掉代理方法,并且實現viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? 這個方法
[cpp] view plaincopy
class GameViewController: UIViewController, UIScrollViewDelegate {
...
func scrollViewDidScroll(scrollView: UIScrollView) {
}
func scrollViewDidZoom(scrollView: UIScrollView) {
}
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
return contentView
}
...
}
向著色程序發送數據
著色程序可以從你的swift代碼里的uniform變量里獲得數據。uniform變量可以在SpriteKit編輯器里聲明。那現在我們來聲明一下uniform變量。
打開GameScene.sks文件,選擇mandelbrote sprite。將insepctor拖到底部,在“Custom shader Uniforms”里添加兩項:float類型的zoom ,值為1, 以及vec2類型的offset。我們將用這兩項uniform變量儲存scrollView的 contentOffset 以及zoom 屬性。
注意:Xcode 6.3的uniform變量有bug。它不能直接在編輯器里賦值初始化,你必須在代碼里初始化它們。
我們可以通過shader屬性來獲取節點上(node)著色程序,用 theuniformedName()方法來從著色程序得到uniform變量。以下是我們獲取zoom uniform變量的例子:
[cpp] view plaincopy
let zoomUniform = node.shader!.uniformNamed("zoom")!
當我們有了uniform變量后,我們可以通過它的屬性來改變它的值。
[cpp] view plaincopy
var textureValue: SKTexture!
var floatValue: Float
var floatVector2Value: GLKVector2
var floatVector3Value: GLKVector3
var floatVector4Value: GLKVector4
var floatMatrix2Value: GLKMatrix2
var floatMatrix3Value: GLKMatrix3
var floatMatrix4Value: GLKMatrix4
在本教程里,我們只對 floatValue和floatVector2Value感興趣。
例子:將zoom的值設置成2
[cpp] view plaincopy
zoomUniform.floatValue = 2
本站文章版權歸原作者及原出處所有 。內容為作者個人觀點, 并不代表本站贊同其觀點和對其真實性負責,本站只提供參考并不構成任何投資及應用建議。本站是一個個人學習交流的平臺,網站上部分文章為轉載,并不用于任何商業目的,我們已經盡可能的對作者和來源進行了通告,但是能力有限或疏忽,造成漏登,請及時聯系我們,我們將根據著作權人的要求,立即更正或者刪除有關內容。本站擁有對此聲明的最終解釋權。