gpt4 book ai didi

ios - 自定义着色器 SCNProgram iOS 9 Scenekit

转载 作者:技术小花猫 更新时间:2023-10-29 10:51:21 26 4
gpt4 key购买 nike

我正在尝试在 SceneKit 中乱搞并自学。基本上,我正在创建一个具有 3 个矩形边和 1 个倾斜 slider 的四边形。

我希望我的纹理在整个表面上拉伸(stretch)和扭曲/变形。

在网上阅读了一些资料,似乎我需要制作一个带有自定义顶点和片段着色器的 SCNProgram 才能获得效果。但是,我似乎无法让纹理遍布整个表面。请需要帮助。 (我是图形编程的新手,因此尝试自学)。

我创建几何体和纹理的 Swift 代码如下:

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));
}

我似乎无法让左下角的纹理在整个表面展开。你能帮忙吗?

This is what is rendered when I run the code

做一些手动的顶点和碎片着色器杂耍,我可以得到结果,但感觉很不优雅,我很确定它不应该像这样编写特定的代码。

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);
}

这正是我正在寻找的东西,但感觉做事的方式非常错误。

enter image description here

编辑:我正在使用 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);
}

我得到如下图所示的内容: enter image description here

这对我说我的纹理坐标定义有问题,但我不知道是什么?

EDIT2:进展顺利。根据 Lock 在相关主题上给出的答案,我使用以下方法重新定义了我的 uvs:

let uvSource = SCNGeometrySource(data: uvData,
semantic: SCNGeometrySourceSemanticTexcoord,
vectorCount: textureCord.count,
floatComponents: true,
componentsPerVector: 3,
bytesPerComponent: sizeof(Float),
dataOffset: 0,
dataStride: sizeof(vector_float2))

现在,当我在片段着色器中使用 texCoord 时,它会给我这样的结果:

enter image description here

它不如我在上面的纹理中得到的弯曲变形那么大。但它的进步。有什么想法可以让我在这个大问题中像图 2 一样平滑吗?

请帮忙。

最佳答案

在片段着色器中,您必须使用 texCoord 而不是 pos 来对纹理进行采样。

另请注意,您不需要程序来为任意几何体制作纹理。您也可以将常规 Material 用于自定义几何形状。如果你想做一些用普通 Material 做不到的事情,你也可以看看着色器修改器,它们比程序更容易使用,并且不需要你手动处理灯光等。

关于ios - 自定义着色器 SCNProgram iOS 9 Scenekit,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34104369/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com