Posted By: 1234David
Alternative SSAO - 06/13/15 20:08
Good evening,
I despair! I've found a tutorial how to create A Simple and Practical Approach to SSAO.
I think the basic preconditions are clear.
I created two views, which renders the POSITION and the NORMALS to the given targets (g_buffer_pos_bmap, g_buffer_norm_bmap).
Here is my edited SSAO-Shader:
SSAO.fx
But the results are unusable!
For thoseones who want to try it, here's the rest of my code:
main.c
Position_buffer_view.fx
Normal_buffer_view.fx
Good Luck! And have fun.
But please, if there is a solution, let me know.
Good night.
P.S.: For any questions, post here.
Edit: What the result and POSITION/NORMALS SHOULD look like!
[video:youtube]https://www.youtube.com/watch?v=a45hUtn_GyM[/video]
I despair! I've found a tutorial how to create A Simple and Practical Approach to SSAO.
I think the basic preconditions are clear.
I created two views, which renders the POSITION and the NORMALS to the given targets (g_buffer_pos_bmap, g_buffer_norm_bmap).
Here is my edited SSAO-Shader:
SSAO.fx
Code:
float random_size = 64; float g_sample_rad = 32; float g_intensity = 1; float g_scale = 5; float g_bias = 0.1; float2 g_screen_size = { 720,480 }; //I know, but for testreasons i didnt want to give them by the main-script :x //float2 g_screen_size = { 800,600 }; //4:3 texture g_buffer_scene_bmap; texture g_buffer_pos_bmap; texture g_buffer_posb_bmap; //backfaces rendered with CULL_CW texture g_buffer_norm_bmap; texture g_random_bmap; sampler sceneSampler = sampler_state { Texture = <g_buffer_scene_bmap>; }; sampler g_buffer_pos = sampler_state { Texture = <g_buffer_pos_bmap>; }; sampler g_buffer_posb = sampler_state { Texture = <g_buffer_posb_bmap>; }; sampler g_buffer_norm = sampler_state { Texture = <g_buffer_norm_bmap>; }; sampler g_random = sampler_state { Texture = <g_random_bmap>; }; struct PS_INPUT { float4 pos : POSITION0; float2 uv : TEXCOORD0; }; struct PS_OUTPUT { float4 color : COLOR0; }; float3 getPosition(in float2 uv) { return tex2D(g_buffer_pos,uv).xyz; } float3 getNormal(in float2 uv) { return normalize(tex2D(g_buffer_norm, uv).xyz * 2.0f - 1.0f); } float2 getRandom(in float2 uv) { return normalize(tex2D(g_random, g_screen_size * uv / random_size).xy * 2.0f - 1.0f); } float3 getPositionBack(in float2 uv) { return tex2D(g_buffer_posb,uv).xyz; } float doAmbientOcclusion(in float2 tcoord,in float2 uv, in float3 p, in float3 cnorm) { float3 diff = getPosition(tcoord + uv) - p; const float3 v = normalize(diff); const float d = length(diff)*g_scale; return max(0.0,dot(cnorm,v)-g_bias)*(1.0/(1.0+d))*g_intensity; } float doAmbientOcclusionBack(in float2 tcoord,in float2 uv, in float3 p, in float3 cnorm) { float3 diff = getPositionBack(tcoord + uv) - p; const float3 v = normalize(diff); const float d = length(diff)*g_scale; return max(0.0,dot(cnorm,v)-g_bias)*(1.0/(1.0+d)); } float4 AOPixelShader(PS_INPUT i) : COLOR0 { float4 color = 0.0f; const float2 vec[4] = {float2(1,0),float2(-1,0), float2(0,1),float2(0,-1)}; float3 p = getPosition(i.uv); float3 n = getNormal(i.uv); float2 rand = getRandom(i.uv); float ao = 0.0f; float rad = g_sample_rad/p.z; //**SSAO Calculation**// int iterations = 4; for (int j = 0; j < iterations; ++j) { float2 coord1 = reflect(vec[j],rand)*rad; float2 coord2 = float2(coord1.x*0.707 - coord1.y*0.707, coord1.x*0.707 + coord1.y*0.707); ao += doAmbientOcclusion(i.uv,coord1*0.25, p, n); ao += doAmbientOcclusion(i.uv,coord2*0.5, p, n); ao += doAmbientOcclusion(i.uv,coord1*0.75, p, n); ao += doAmbientOcclusion(i.uv,coord2, p, n); //Backfaces ao += doAmbientOcclusionBack(i.uv,coord1*(0.25+0.125), p, n); ao += doAmbientOcclusionBack(i.uv,coord2*(0.5+0.125), p, n); ao += doAmbientOcclusionBack(i.uv,coord1*(0.75+0.125), p, n); ao += doAmbientOcclusionBack(i.uv,coord2*1.125, p, n); } ao/=(float)iterations*4.0; //**END**// float4 finalColor = tex2D(sceneSampler, i.uv); finalColor.xyz *= 1-ao; //This should be the combined version //Do stuff here with your occlusion value âaoâ: modulate ambient lighting, write it to a buffer for later //use, etc. return 1-ao; //< This will return only the AO ;) } technique SSAO { pass P0 { PixelShader = compile ps_3_0 AOPixelShader(); } }
But the results are unusable!
For thoseones who want to try it, here's the rest of my code:
main.c
Code:
#include <acknex.h> #include <default.c> #include "PP_Helper.c" BMAP* camera_clean; BMAP* depthtex; BMAP* g_buffer_pos; BMAP* g_buffer_posb; BMAP* g_buffer_norm; BMAP* g_random = "g_random.pcx"; MATERIAL* matPosition_buffer_view = { effect = "Position_buffer_view.fx"; } MATERIAL* matNormal_buffer_view = { effect = "Normal_buffer_view.fx"; } MATERIAL* matSSAO = { effect = "SSAO.fx"; } #define PRAGMA_PATH "scene"; void main() { level_load("atrium.wmb"); VIEW* position_buffer = view_create(-3); set(position_buffer, VISIBLE); g_buffer_pos = bmap_createblack(screen_size.x, screen_size.y, 24); position_buffer.bmap = g_buffer_pos; position_buffer.material = matPosition_buffer_view; VIEW* positionb_buffer = view_create(-2); set(positionb_buffer, VISIBLE); g_buffer_posb = bmap_createblack(screen_size.x, screen_size.y, 24); positionb_buffer.bmap = g_buffer_posb; set(positionb_buffer,CULL_CW); positionb_buffer.material = matPosition_buffer_view; VIEW* normal_buffer = view_create(-1); set(normal_buffer, VISIBLE); g_buffer_norm = bmap_createblack(screen_size.x, screen_size.y, 24); normal_buffer.bmap = g_buffer_norm; normal_buffer.material = matNormal_buffer_view; PP_Add(matSSAO, camera, NULL); //Start the SSAO while(1) { vec_set(position_buffer.x,camera.x); vec_set(position_buffer.pan,camera.pan); vec_set(normal_buffer.x,camera.x); vec_set(normal_buffer.pan,camera.pan); wait (1); } }
Position_buffer_view.fx
Code:
#define FarZ 1000.0f float4x4 matWorld; float4x4 matWorldView; float4x4 matWorldViewProj; struct VS_INPUT { float4 position : POSITION; }; struct VS_OUTPUT { float4 position : POSITION; float3 viewpos : TEXCOORD; }; VS_OUTPUT vertexShader(VS_INPUT input) { VS_OUTPUT output; output.position=mul(input.position,matWorldViewProj); output.viewpos=mul(input.position,matWorldView).xyz; return output; } float4 pixelShader(VS_OUTPUT input) : COLOR { return float4((input.viewpos.x/250)*(input.viewpos.z/FarZ),(input.viewpos.y/250)*(input.viewpos.z/FarZ),1-input.viewpos.z/FarZ,0); //I thried much versions, but here is my actual } technique tech_00 { pass pass_00 { VertexShader = compile vs_3_0 vertexShader(); PixelShader = compile ps_3_0 pixelShader(); } }
Normal_buffer_view.fx
Code:
float4x4 matWorldView; float4x4 matWorldViewProj; texture TargetMap; sampler2D smpScreen = sampler_state { Texture = <TargetMap>; MinFilter = linear; MagFilter = linear; MipFilter = linear; AddressU = Wrap; AddressV = Wrap; }; struct VS_OUT { float4 Pos : POSITION; float4 WorldPos : TEXCOORD0; float3 Norm : TEXCOORD1; }; VS_OUT Shader_VS(float4 inPos : POSITION, float3 Normal : NORMAL) { VS_OUT Out = (VS_OUT)0; Out.Pos = mul(inPos, matWorldViewProj); Out.Norm = mul(Normal, matWorldView); return Out; } float4 Shader_PS(float3 Norm : TEXCOORD1) : COLOR { return float4(Norm.x,Norm.y,Norm.z,0); } technique tech_00 { pass pass_00 { VertexShader = compile vs_3_0 Shader_VS(); PixelShader = compile ps_3_0 Shader_PS(); } }
Good Luck! And have fun.
But please, if there is a solution, let me know.
Good night.
P.S.: For any questions, post here.
Edit: What the result and POSITION/NORMALS SHOULD look like!
[video:youtube]https://www.youtube.com/watch?v=a45hUtn_GyM[/video]