我試圖在SceneKit
左右,並教我自己。基本上,我正在創建一個具有3個矩形邊和1個傾斜滑塊的四邊形。自定義着色器SCNProgram iOS 9 Scenekit
我希望我的紋理能夠在表面上伸展和變形/變形。
在線閱讀一些東西,似乎我需要製作一個SCNProgram
自定義頂點和片段着色器來獲得效果。但是,我似乎無法讓紋理在表面上傳播。需要幫助。 (我是圖形編程的新手,因此試圖教給自己)。
我斯威夫特代碼來創建幾何形狀和質地是如下:
func geometryCreate() -> SCNNode {
let verticesPosition = [
SCNVector3Make(0.0, 0.0, 0.0),
SCNVector3Make(5.0, 0.0, 0.0),
SCNVector3Make(5.0, 5.0, 0.0),
SCNVector3Make(0.0, 3.0, 0.0)
]
let textureCord = [CGPoint (x: 0.0,y: 0.0), CGPoint(x: 1.0,y: 0.0), CGPoint(x: 1.0,y: 1.0), CGPoint(x: 0.0,y: 1.0)]
let indices: [CInt] = [
0, 2, 3,
0, 1, 2
]
let vertexSource = SCNGeometrySource(vertices: verticesPosition, count: 4)
let srcTex = SCNGeometrySource(textureCoordinates: textureCord, count: 4)
let date = NSData(bytes: indices, length: sizeof(CInt) * indices.count)
let scngeometry = SCNGeometryElement(data: date, primitiveType: SCNGeometryPrimitiveType.Triangles, primitiveCount: 2, bytesPerIndex: sizeof(CInt))
let geometry = SCNGeometry(sources: [vertexSource,srcTex], elements: [scngeometry])
let program = SCNProgram()
if let filepath = NSBundle.mainBundle().pathForResource("vertexshadertry", ofType: "vert") {
do {
let contents = try NSString(contentsOfFile: filepath, encoding: NSUTF8StringEncoding) as String
program.vertexShader = contents
} catch {
print("**** happened loading vertex shader")
}
}
if let fragmentShaderPath = NSBundle.mainBundle().pathForResource("fragshadertry", ofType:"frag")
{
do {
let fragmentShaderAsAString = try NSString(contentsOfFile: fragmentShaderPath, encoding: NSUTF8StringEncoding)
program.fragmentShader = fragmentShaderAsAString as String
} catch {
print("**** happened loading frag shader")
}
}
program.setSemantic(SCNGeometrySourceSemanticVertex, forSymbol: "position", options: nil)
program.setSemantic(SCNGeometrySourceSemanticTexcoord, forSymbol: "textureCoordinate", options: nil)
program.setSemantic(SCNModelViewProjectionTransform, forSymbol: "modelViewProjection", options: nil)
do {
let texture = try GLKTextureLoader.textureWithCGImage(UIImage(named: "stripes")!.CGImage!, options: nil)
geometry.firstMaterial?.handleBindingOfSymbol("yourTexture", usingBlock: { (programId:UInt32, location:UInt32, node:SCNNode!, renderer:SCNRenderer!) -> Void in
glTexParameterf(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_S), Float(GL_CLAMP_TO_EDGE))
glTexParameterf(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_T), Float(GL_CLAMP_TO_EDGE))
glTexParameterf(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MAG_FILTER), Float(GL_LINEAR))
glTexParameterf(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MIN_FILTER), Float(GL_LINEAR))
glBindTexture(GLenum(GL_TEXTURE_2D), texture.name)
})
} catch {
print("Texture not loaded")
}
geometry.firstMaterial?.program = program
let scnnode = SCNNode(geometry: geometry)
return scnnode
}
我的頂點着色器是:
attribute vec4 position;
attribute vec2 textureCoordinate;
uniform mat4 modelViewProjection;
varying highp vec2 pos;
varying vec2 texCoord;
void main() {
texCoord = vec2(textureCoordinate.s, 1.0 - textureCoordinate.t) ;
gl_Position = modelViewProjection * position;
pos = vec2(position.x, 1.0 - position.y);
}
我的片段着色器是:
precision highp float;
uniform sampler2D yourTexture;
varying highp vec2 texCoord;
varying highp vec2 pos;
void main() {
gl_FragColor = texture2D(yourTexture, vec2(pos.x, pos.y));
}
我只是似乎無法獲得左下角的紋理在整個表面展開。能否請你幫忙?
做一些手工的頂點和片段着色器雜耍,我可以得到的結果,但它給人的感覺非常不雅,我敢肯定它不應該被寫入特定的代碼是這樣的。
attribute vec4 position;
attribute vec2 textureCoordinate;
uniform mat4 modelViewProjection;
varying highp vec2 pos;
varying vec2 texCoord;
void main() {
// Pass along to the fragment shader
texCoord = vec2(textureCoordinate.s, 1.0 - textureCoordinate.t) ;
// output the projected position
gl_Position = modelViewProjection * position;
pos = vec2(position.x, position.y);
}
更改片段着色器(其中0.4是四邊形的頂部的斜率):
precision highp float;
uniform sampler2D yourTexture;
varying highp vec2 texCoord;
varying highp vec2 pos;
void main() {
gl_FragColor = texture2D(yourTexture, vec2(pos.x/5.0, 1.0 - pos.y/(3.0+0.4*pos.x)));
// gl_FragColor = vec4 (0.0, pos.y/5.0, 0.0, 1.0);
}
這給了我正是我期待的,但感覺做事情非常錯誤的方式。
編輯:我使用的是pos
變量而不是texCoord爲texCoord
是給我怪異的地獄結果,我真的不能明白:(
如果我修改我的。片段着色器爲:
precision highp float;
uniform sampler2D yourTexture;
varying highp vec2 texCoord;
varying highp vec2 pos;
void main() {
// gl_FragColor = texture2D(yourTexture, vec2(pos.x/5.0, 1.0 - pos.y/(3.0+0.4*pos.x)));
gl_FragColor = texture2D(yourTexture, texCoord);
// gl_FragColor = vec4 (0.0, pos.y/5.0, 0.0, 1.0);
}
這對我說,我的紋理座標定義出了問題,但我找不出什麼?
EDIT2:確定進度。在此基礎上鎖定了一個相關的線程我重新定義了我的UV使用下面的方法的答案:
let uvSource = SCNGeometrySource(data: uvData,
semantic: SCNGeometrySourceSemanticTexcoord,
vectorCount: textureCord.count,
floatComponents: true,
componentsPerVector: 3,
bytesPerComponent: sizeof(Float),
dataOffset: 0,
dataStride: sizeof(vector_float2))
現在,它給了我這樣的結果,我在我的frag着色器使用texCoord:
它不如我在上面的紋理中獲得的彎曲變形。但其進展。任何想法如何在這個大規模的問題中得到它像圖片2一樣平滑?
請幫忙。
不錯的作品@AdiTheExplorer。你只需要調整左上角的紋理座標,而不是0,1,它將在0,0.6(3/5)處停止變形。 FWIW,我沒有看到你用來生成紋理座標的代碼有什麼問題,但顯然有些東西並不完全正確。 – lock
Thanks @lock。但是我實際上希望它能像這個線程中的圖片2那樣變形,以便在紋理中獲得好的曲線?它在兩個三角形上均勻變形。 你一直很好的幫助。不能沒有它:) – AdiTheExplorer
不夠公平。在這種情況下,它可能是你想要調整的右上角座標,使得這個y座標更低會將其拉伸。它可能仍然不會給你在圖2中看到的變形,這是你計算紋理座標的一個創造性方程。你可以使用uv來複制它,現在它們沒問題了('gl_FragColor = texture2D(yourTexture,vec2(texCoord.x,texCoord.y /(0.4 * texCoord.x)));''也許......)。但是,通常你的紋理圖像會有變形,允許使用標準着色器。 – lock