Ich versuche in SceneKit
herumzualbern und es mir beizubringen. Grundsätzlich erstelle ich ein Quad mit 3 rechteckigen Seiten und 1 Schrägrutsche.Benutzerdefinierte Shader SCNProgram iOS 9 Scenekit
Ich möchte meine Textur auf der Oberfläche dehnen und verformen/verformen.
Ich lese einige Sachen online, es scheint, dass ich einen SCNProgram
mit benutzerdefinierten Vertex- und Fragment-Shadern machen muss, um den Effekt zu bekommen. Aber ich kann nicht scheinen, dass sich die Textur über die Oberfläche ausbreitet. Brauche Hilfe bitte. (Ich bin neu in der Grafikprogrammierung und versuche es mir selbst beizubringen).
Mein Swift Code, um die Geometrie und Textur zu erstellen, ist es wie folgt:
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
}
Mein Vertex-Shader ist:
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);
}
Mein Fragment-Shader ist:
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));
}
I Ich kann einfach nicht scheinen, dass die Textur unten links über die Oberfläche verteilt ist. Kannst du bitte helfen?
einige manuelle Vertex und Shader-Splitter Jonglieren tun, kann ich das Ergebnis erhalten, aber es fühlt sich sehr unelegant, und ich bin ziemlich sicher, dass es keine spezifischen Code wie folgt schreiben sollte.
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);
}
Änderungen an Fragment-Shader (wobei 0,4 die Neigung der Oberseite des Quad):
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);
}
Was mir genau das gibt, was ich suche, aber es fühlt sich sehr falschen Weg, Dinge zu tun .
EDIT: Ich bin mit dem pos
Variable statt texCoord als texCoord
gibt mir höllisch Ergebnisse seltsam, die ich nicht wirklich verstehen kann :(
Wenn ich zu ändern war meiner. Fragment-Shader als:
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);
}
ich so etwas wie das Bild unten:
Was sagt mir, dass etwas mit meiner Definition der Texturkoordinaten nicht stimmt, aber ich kann nicht herausfinden, was?
EDIT2: OK Fortschritt. Basierend auf einer Antwort, die Sperre auf einem verwandten Thread habe ich meine UVS mit der Methode unten neu definiert:
let uvSource = SCNGeometrySource(data: uvData,
semantic: SCNGeometrySourceSemanticTexcoord,
vectorCount: textureCord.count,
floatComponents: true,
componentsPerVector: 3,
bytesPerComponent: sizeof(Float),
dataOffset: 0,
dataStride: sizeof(vector_float2))
Jetzt gibt es mir ein Ergebnis wie dieses, als ich texCoord in meinem frag Shader verwenden:
Es ist nicht so groß wie die gekrümmten Deformitäten, die ich in der Textur oben bekomme. Aber sein Fortschritt.Irgendwelche Ideen wie kann ich es glattstellen wie Bild 2 in dieser Massive Frage?
Bitte helfen.
Gute Arbeit @AdiTheExplorer. Sie müssen nur die obere linke Texturkoordinate anpassen, statt 0,1 wird es bei 0,0,6 (3/5) sein, um die Verformung zu stoppen. FWIW, ich sehe nicht, was mit dem Code, den Sie zum Erzeugen der Texturkoordinaten hatten, nicht stimmt, aber offensichtlich stimmte etwas nicht damit. – lock
Danke @lock. Aber ich möchte eigentlich, dass es sich wie in Bild 2 in diesem Thread verformt, um eine schöne Kurve in der Textur zu bekommen? Wo es sich gleichmäßig über die 2 Dreiecke verformt. Sie waren übrigens eine große Hilfe. Konnte es ohne es nicht geschafft haben :) – AdiTheExplorer
Fair genug. In diesem Fall ist es wahrscheinlich die obere rechte Koordinate, die Sie optimieren möchten. Wenn Sie diese y-Koordinate verringern, wird sie gestreckt. Es wird wahrscheinlich immer noch nicht die Verformung geben, die Sie in Abbildung 2 sehen, das ist eine kreative Gleichung, die Sie für die Berechnung der Texturkoordinaten haben. Sie können dies wahrscheinlich mit den uvs replizieren, jetzt da sie in Ordnung sind ('gl_FragColor = texture2D (IhreTextur, vec2 (texCoord.x, texCoord.y/(0.4 * texCoord.x)));' vielleicht ...). ABER, im Allgemeinen hat Ihr Texturbild bereits die Deformation, die die Verwendung von Standard-Shadern ermöglicht. – lock