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