当前位置:  开发笔记 > IOS > 正文

自定义着色器SCNProgram iOS 9 Scenekit

如何解决《自定义着色器SCNProgramiOS9Scenekit》经验,为你挑选了1个好方法。

我试图搞砸SceneKit并自学它.基本上,我正在创建一个带有3个矩形边和1个倾斜滑块的四边形.

我希望我的纹理在表面上伸展和变形/变形.

在线阅读一些内容,似乎我需要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));  
} 

我似乎无法让左下方的纹理在表面上散开.能否请你帮忙?

这是我运行代码时呈现的内容

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

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:好的进展.根据Lock在相关主题上给出的答案,我使用以下方法重新定义了我的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 shader中使用texCoord时,它会给我一个这样的结果:

在此输入图像描述

它不像我在上面的纹理中得到的弯曲变形那么大.但它的进步.任何想法如何让我在这个Massive问题中像照片2一样平滑?

请帮助.



1> mnuages..:

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

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


还是坚持这个:(
推荐阅读
小妖694_807
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有