SCNProgram不影响SCNFloor

时间:2017-01-21 07:25:59

标签: swift glsl shader opengl-es-2.0 scenekit

在我使用着色器修改器的实验中,我看到无法将数组数据传输到着色器。

Scenekit giving buffer size error while passing array data to uniform array in openGL shader

因此我决定尝试SCNProgram。但是现在我意识到我使用SCNProgram添加的着色器在SCNFloor上不起作用。

这个问题是否有特殊原因?

我用于测试的超简单着色器;

顶点着色器

precision highp float;
attribute vec3 vertex;
uniform mat4 ModelViewProjectionMatrix;

void main()
{
    gl_Position = ModelViewProjectionMatrix * vec4(vertex, 1.0);
}

片段着色器

precision mediump float;

void main( void )
{   
    gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}

2 个答案:

答案 0 :(得分:1)

你可以尝试制作自己的vert和frag着色器来做同样的事情。我用webgl / glsl es2做了类似的事情,或者只是把它画得很扎实,给现有的地板着色:

uniform mat4 uCameraWM;  //camera world matrix
uniform vec2 uCamAspFov; //x:aspect ratio y:tan(fov/2) 


varying vec3 vVDw; //view direction

void main(){

//construct frustum, scale and transform a unit quad

vec4 viewDirWorld = vec4(
    position.x * uCamAspFov.x,
    position.y,
    -uCamAspFov.y, //move it to where 1:aspect fits
    0.
);

vVDw = ( uCameraWM * viewDirWorld ).xyz; //transform to world


gl_Position = vec4( position.xy , 0. , 1. ); //draw a full screen quad

}

分片: (忽略瑕疵,点是将视线方向射线与平面相交,映射它,你可以在天空部分查找立方体贴图而不是丢弃它)

uniform float uHeight;


uniform sampler2D uTexDiff;
uniform sampler2D uTexNorm;
uniform sampler2D uTexMask;

varying vec2 vUv;

varying vec3 vVDw;

struct Plane
{
    vec3 point;
    vec3 normal;
    float d;
};


bool rpi( in Plane p , in vec3 p0 , in vec3 vd , out vec3 wp )
{

    float t;

    t = -( dot( p0 , p.normal ) + p.d ) / dot( vd , p.normal );

    wp = p0 + t * vd;

    return t > 0. ? true : false;

}

void main(){


    Plane plane;

    plane.point = vec3( 0. , uHeight , 0. );
    plane.normal = vec3( 0. , 1. , .0 );
    plane.d = -dot( plane.point , plane.normal );



    vec3 ld = normalize( vec3(1.,1.,1.) );

    vec3 norm = plane.normal;
    float ndl = dot( norm , ld ) ;



    vec2 uv;
    vec3 wp;
    vec3 viewDir = normalize( vVDw );

    vec3 h = normalize((-viewDir + ld));

    float spec = clamp( dot( h , norm ) , .0 , 1. );

    // spec = pow( spec , 5. ); 

    if( dot(plane.normal , cameraPosition) < 0. ) discard;

    if( !rpi( plane , cameraPosition , viewDir , wp ) ) discard;

    uv = wp.xz;

    vec2 uvm = uv * .0105;
    vec2 uvt = uv * .2;

    vec4 tmask = texture2D( uTexMask , uvm );

    vec2 ch2Scale = vec2(1.8,1.8);
    vec2 ch2Scale2 = vec2(1.6,1.6);

    vec2 t1 = uvt * ch2Scale2 - vec2(tmask.z , -tmask.z) ;
    // vec2 t2 = uvt * ch2Scale + tmask.z ;
    // vec2 t3 = uvt + vec2(0. , mask.z-.5) * 1.52;


    vec3 diffLevels = ( texture2D( uTexDiff , t1 ) ).xyz;

    // vec3 diffuse2 = ( texture2D( uTexDiff, fract(t1) * vec2(.5,1.) + vec2(.5,.0) ) ).xyz;
    // vec3 diffuse1 = ( texture2D( uTexDiff, fract(t2) * vec2(.5,1.) ) ).xyz;


    // vec4 normalMap2 = texture2D( uTexNorm, fract(t1) * vec2(.5,1.) + vec2(.5,.0) );
    // vec4 normalMap1 = texture2D( uTexNorm, fract(t2) * vec2(.5,1.) );

    float diffLevel = mix(diffLevels.y, diffLevels.x, tmask.x);
    diffLevel = mix( diffLevel , diffLevels.z, tmask.y );

    // vec3 normalMix = mix(normalMap1.xyz, normalMap2.xyz, tmask.x);


    // vec2 g = fract(uv*.1) - .5;

    // float e = .1;
    // g = -abs( g ) + e;

    float fog = distance( wp.xz , cameraPosition.xz );

    // float r = max( smoothstep( 0.,e,g.x) , smoothstep( 0.,e,g.y) );

    gl_FragColor.w = 1.;

    gl_FragColor.xyz = vec3(tmask.xxx);
    gl_FragColor.xyz = vec3(diffLevel) * ndl + spec * .5;

}

但总的来说,更好的建议就是放弃使用scenekit并为自己节省一点挫折感。

答案 1 :(得分:0)

最后,Apple Developer Technical Support回答了我提出的有关此问题的问题。

这是他们给出的答案。

  

不幸的是,没有办法遮挡地板。该   SceneKit团队承认SCNFloor是一种不同类型的对象   不适用于SCNProgram。而且,使用   .fragment着色器入口点也不起作用(例如:)

func setFragmentEntryPoint( _ node: SCNNode ) {

    print( #function + " setting fragment entry point for \(node)" )

    DispatchQueue.main.asyncAfter( deadline: DispatchTime.now() + DispatchTimeInterval.milliseconds( 2500 ) ) {

        let geometry = node.geometry!

        let dict: [SCNShaderModifierEntryPoint:String] = [.fragment :
            "_output.color = vec4( 0.0, 1.0, 0.0, 1.0 );"]

        geometry.shaderModifiers = dict


    }
}
     

虽然SceneKit团队认为这是预期的行为,但是你   可能仍会提交错误报告,在这种情况下将被解释为   API增强请求。