在Three.js定制ssao

时间:2014-06-07 03:29:46

标签: three.js glsl shader pixel-shader ssao

我正在尝试从教程中完成一个ssao着色器:http://www.nutty.ca/?page_id=352&link=ssao 我在three.js中使用多次渲染。 stackoverflow SSAO artefacts in Three中有一个类似的问题,我发现我们从同一个教程中学到了很多东西。 我详细地按照教程,我不知道我渲染的纹理是完全错误的。有人有点想法吗?谢谢! 如下教程, 我将整个场景存储在一个颜色tDiffusion纹理中: enter image description here, 将视图空间位置存储到tPosition纹理: enter image description here, 将视图空间线性深度存储到tDepth纹理: enter image description here, Shader是这样的:

"custom_vsPosition" :{
    uniforms:{
        "cameraNear":   { type: "f", value: 1.0 },
        "cameraFar":    { type: "f", value: 100.0 }
    },
    vertexShader:[
        "varying vec4 mvPosition;",         //View-space position
        "void main() {",
        // Calculate and include linear depth
        "   mvPosition = modelViewMatrix * vec4(position, 1.0);",
        "   gl_Position = projectionMatrix * mvPosition;",
        "}"
    ].join("\n"),
    fragmentShader:[
        "uniform float cameraNear;",
        "uniform float cameraFar;",
        "varying vec4 mvPosition;",         //View-space position
        "void main() {",
        "    float linearDepth = length(mvPosition) / (cameraFar - cameraNear);",
        "    linearDepth = clamp(linearDepth, 0.0, 1.0);",
        "    gl_FragColor = vec4(mvPosition.xyz, linearDepth);",
        "}"
    ].join("\n")
},

将视图空间法线向量存储到tNormal纹理: enter image description here

"custom_vsNormal" :{
    uniforms:{
    },
    vertexShader:[
        "varying vec3 vNormal ;",
        "void main(void) {",
        "   vNormal  = normalMatrix * normal ;",   //transforming the normal vector into view
                                                                        //space and then scaling and biasing the vector components
        "   gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);",
        "}"
    ].join("\n"),
    fragmentShader:[
        "varying vec3 vNormal ;",  //Normal transform
        "void main() {",
        "    gl_FragColor = vec4(normalize( vNormal ).xyz, 1.0);",
        "}"
    ].join("\n")
},

然后根据tDepth,tPosition和tNormal来计算ao。

然而,Ao似乎错了。比较我的纹理和turtorial,我找不到哪里错了。来自SSAO artefacts in Three,也许正常生成中存在问题。但我真的生成了视图空间正常。 只有Ao图片: enter image description here Ao与彩色场景: enter image description here 教程中的SSAO着色器:     " custom_NVD_SSAOShader&#34 ;:     {         制服:{

        "tDiffuse":     { type: "t", value: null },  // Render texture
        "tPosition":     { type: "t", value: null },  // View space position data
        "tNormal":       { type: "t", value: null },  // View space normal vectors
        "tNoise":       { type: "t", value: null },// Normalmap to randomize the sampling kernel
        "size":         { type: "v2", value: new THREE.Vector2( 512, 512 ) },
        "occluderBias":   { type: "f", value: 0.005 },  // Occluder bias to minimize self-occlusion.
        "samplingRadius":   { type: "f", value: 20 }, // Specifies the size of the sampling radius.
        "cAttenuation":       { type: "v3", value: new THREE.Vector3( 1, 1.5, 0 ) },
        "onlyAo":      { type: "f", value: 0.0 },
        "lumInfluence": { type: "f", value: 0.9 }
        // Ambient occlusion attenuation values. These parameters control the amount of AO calculated based on distance to the occluders. You need to play with them to find the right balance.
        // .x = constant attenuation. This is useful for removing self occlusion. When
        //  set to zero or a low value, you will start to notice edges or wireframes
        //  being shown. Typically use a value between 1.0 and 3.0.
        //  .y = linear attenuation. This provides a linear distance falloff.
        // .z = quadratic attenuation. Smoother falloff, but is not used in this shader.
    },

    vertexShader: [

        "varying vec2 vUv;",

        "void main() {",

        "vUv = uv;",

        "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",

        "}"

    ].join("\n"),

    fragmentShader: [
        "#define sampleCount 16",
        "#define patternSize 4.0",

        "varying vec2 vUv;",
        "uniform sampler2D tDiffuse;",
        "uniform sampler2D tPosition;",
        "uniform sampler2D tNormal;",
        "uniform sampler2D tNoise;",   //input random noise for random sampling
        "uniform vec2 size;",
        "uniform float occluderBias;",
        "uniform float samplingRadius;",
        "uniform vec3 cAttenuation;",
        "uniform float onlyAo;",
        "uniform float lumInfluence;",

        "const vec3 onlyAOColor = vec3( 1.0, 0.7, 0.5 );",

        "float SamplePixels (vec3 srcPosition, vec3 srcNormal, vec2 uv)",
        "{",
        // Get the 3D position of the destination pixel
        "   vec3 dstPosition = texture2D(tPosition, uv).xyz;",

        // Calculate ambient occlusion amount between these two points
        // It is simular to diffuse lighting. Objects directly above the fragment cast
        // the hardest shadow and objects closer to the horizon have minimal effect.
        "   vec3 positionVec = dstPosition - srcPosition;",

        "   float intensity = max(dot(normalize(positionVec), srcNormal)- occluderBias, 0.0);",

        "   float dist = length(positionVec);",
        "   float attenuation = 1.0 / (cAttenuation.x + (cAttenuation.y * dist));",

        "   return intensity * attenuation;",
        "}",

        "vec2 texelSize = vec2(0.5 , 0.5);",
        /*
        // These are the Poisson Disk Samples
        "vec2 getPoisson16(int i){;",
        "vec2 poisson16;",
        "if(i==0)",
        "   poisson16 = vec2( -0.94201624,  -0.39906216 );",
        "else if(i==1)",
        "   poisson16 = vec2(  0.94558609,  -0.76890725 );",
        "else if(i==2)",
        "   poisson16 = vec2( -0.094184101, -0.92938870 );",
        "else if(i==3)",
        "   poisson16 = vec2(  0.34495938,   0.29387760 );",
        "else if(i==4)",
        "   poisson16 = vec2( -0.91588581,   0.45771432 );",
        "else if(i==5)",
        "   poisson16 = vec2( -0.81544232,  -0.87912464 );",
        "else if(i==6)",
        "   poisson16 = vec2( -0.38277543,   0.27676845 );",
        "else if(i==7)",
        "   poisson16 = vec2(  0.97484398,   0.75648379 );",
        "else if(i==8)",
        "   poisson16 = vec2(  0.44323325,  -0.97511554 );",
        "else if(i==9)",
        "   poisson16 = vec2(  0.53742981,  -0.47373420 );",
        "else if(i==10)",
        "   poisson16 = vec2( -0.26496911,  -0.41893023 );",
        "else if(i==11)",
        "   poisson16 = vec2(  0.79197514,   0.19090188 );",
        "else if(i==12)",
        "   poisson16 = vec2( -0.24188840,   0.99706507 );",
        "else if(i==13)",
        "   poisson16 = vec2( -0.81409955,   0.91437590 );",
        "else if(i==14)",
        "   poisson16 = vec2(  0.19984126,   0.78641367 );",
        "else if(i==15)",
        "   poisson16 = vec2(  0.14383161,  -0.14100790 );",
        "return poisson16;",
        "}",
        */
        "void main ()",
        "{",
        // Get position and normal vector for this fragment
        "   vec3 srcPosition = texture2D(tPosition, vUv).xyz;",
        "   float srcDepth = texture2D(tPosition, vUv).w;",
        "   vec3 srcNormal = texture2D(tNormal, vUv).xyz;",
        /*
        "   float ao = 0.0;",
        "   float kernelRadius = samplingRadius * (1.0 - srcDepth);",
        "   for(int i =0; i < sampleCount; ++i)",
        "   {",
        "       ao += SamplePixels(srcPosition, srcNormal, vUv + getPoisson16(i) * kernelRadius);",
        "    }",
        "   ao /= 16.0;",
        "   ao = clamp(ao, 0.0, 1.0);",
        "   ao = 1.0 - ao;",
        */
        "   vec2 randVec = normalize(texture2D(tNoise, vUv).xy * 2.0 - 1.0);",
        "   float kernelRadius = samplingRadius * (1.0 - srcDepth);",
        "   vec2 kernel[4];",
        "   kernel[0] = vec2(0.0, 1.0);",   // top",
        "   kernel[1] = vec2(1.0, 0.0);",   // right
        "   kernel[2] = vec2(0.0, -1.0);",  // bottom
        "   kernel[3] = vec2(-1.0, 0.0);",  // left
        "   const float Sin45 = 0.707107;", // 45 degrees = sin(PI / 4)
        "   float ao = 0.0;",
        "   for (int i = 0; i < 4; ++i)",
        "   {",
        "       vec2 k1 = reflect(kernel[i], randVec);",
        "       vec2 k2 = vec2(k1.x * Sin45 - k1.y * Sin45,",
        "                      k1.x * Sin45 + k1.y * Sin45);",
        "       k1 *= texelSize;",
        "       k2 *= texelSize;",
        "       ao += SamplePixels(srcPosition, srcNormal, vUv + k1 * kernelRadius);",
        "       ao += SamplePixels(srcPosition, srcNormal, vUv + k2 * kernelRadius * 0.75);",
        "       ao += SamplePixels(srcPosition, srcNormal, vUv + k1 * kernelRadius * 0.5);",
        "       ao += SamplePixels(srcPosition, srcNormal, vUv + k2 * kernelRadius * 0.25);",
        "   }",
        "   ao /= 16.0;",

        "   ao = clamp(ao, 0.0, 1.0);",
        "   ao = 1.0 - ao;",

        "   vec3 color = texture2D( tDiffuse, vUv ).rgb;",
        "if ( onlyAo == 1.0 )",
        "   gl_FragColor.xyz = vec3( ao, ao, ao );",
        "else if ( onlyAo == 2.0 )",
        "   gl_FragColor.xyz = vec3( srcNormal.x, srcNormal.y, srcNormal.z );",
        "else if ( onlyAo == 3.0 )",
        "   gl_FragColor.xyz = vec3( srcDepth, srcDepth, srcDepth );",
        "else if ( onlyAo == 4.0 )",
        "   gl_FragColor.xyz = vec3( srcPosition.x, srcPosition.y, srcPosition.z );",
        "else if ( onlyAo == 5.0 )",
        "   gl_FragColor.xyz = color;",
        "else",
        "{",
        "   gl_FragColor.xyz = color * ao;",
        "}",

        "gl_FragColor.w = 1.0;",
    "}"
    ].join("\n")
}

0 个答案:

没有答案