2 registered members (AndrewAMD, Quad),
608
guests, and 5
spiders. |
Key:
Admin,
Global Mod,
Mod
|
|
|
Alternative SSAO
#452489
06/13/15 20:08
06/13/15 20:08
|
Joined: Jan 2012
Posts: 14
1234David
OP
Newbie
|
OP
Newbie
Joined: Jan 2012
Posts: 14
|
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
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
#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
#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
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]
Last edited by 1234David; 06/13/15 20:19.
|
|
|
|