Advertisement

Again ssao....

Started by June 01, 2020 09:19 AM
2 comments, last by _WeirdCat_ 4 years, 8 months ago

Its been a while but i still cant make my implementation of ssao to work anyhow:

So basically i use ssao with a world space approach that means

after drawing gbuffer i dont use screen space apptoach to find occlusion but rather i decompose fragment original position, apply rotation (kernel sample) to fragment normal and multiple that by some factor (11 cm truth to be told), and check whenever sample translated by this position has lower value than tested fragment

(everything is calculated in worldspace rather than in screen space)

Yet i get this:

weird thing is that within each object i see some weird swirl at the center of each face like what the hell? how?

[Spoiler]

void DrawNormalsToFBO()
{
	InitiateFBODraw(&normalfbo);
	glClear(GL_COLOR_BUFFER_BIT);
	glClear(GL_DEPTH_BUFFER_BIT);
	
				glDepthMask(GL_TRUE);
	glEnable(GL_DEPTH_TEST);
ACTUAL_MODEL.LoadIdentity();
writenormal_shader.Enable();
FPP_CAM->SetView();
//gluPerspectiveA(ACTUAL_PROJECTION, 90.0f, 1.0f,  0.1f, 10000.0f);
gluPerspectiveA(ACTUAL_PROJECTION, 90.0f, lcASPECT, 0.1f, 10000.0f);

mat4 MVP = (ACTUAL_MODEL * ACTUAL_VIEW) * ACTUAL_PROJECTION;
writenormal_shader.SendMVPtoShader(MVP);
writenormal_shader.SendWorldMatrixtoShader( ACTUAL_MODEL );


model3f * p = map->models;
while ( p!=0)
{
p->DrawSimpleModel(&writenormal_shader);
p = ((model3f*)p->next);
}

writenormal_shader.Disable();

	normalfbo.unbind();
}




void DrawTangentsToFBO()
{
	InitiateFBODraw(&tangentfbo);
	glClear(GL_COLOR_BUFFER_BIT);
	glClear(GL_DEPTH_BUFFER_BIT);
	
				glDepthMask(GL_TRUE);
	glEnable(GL_DEPTH_TEST);
ACTUAL_MODEL.LoadIdentity();
writetangent_shader.Enable();
FPP_CAM->SetView();
//gluPerspectiveA(ACTUAL_PROJECTION, 90.0f, 1.0f,  0.1f, 10000.0f);
gluPerspectiveA(ACTUAL_PROJECTION, 90.0f, lcASPECT, 0.1f, 10000.0f);

mat4 MVP = (ACTUAL_MODEL * ACTUAL_VIEW) * ACTUAL_PROJECTION;
writetangent_shader.SendMVPtoShader(MVP);
writetangent_shader.SendWorldMatrixtoShader( ACTUAL_MODEL );


model3f * p = map->models;
while ( p!=0)
{
p->DrawSimpleModel(&writetangent_shader);
p = ((model3f*)p->next);
}

writetangent_shader.Disable();

tangentfbo.unbind();
}

void WriteDepthToFBO()
{
//	InitiateDepthWriteFBODraw();
	InitiateFBODraw(&depthfbo);
	glClear(GL_COLOR_BUFFER_BIT);
	glClear(GL_DEPTH_BUFFER_BIT);
	ClearDepth();
	WriteDepth();
	depthfbo.unbind();
}

where i call these 
void CalculaceTangentData() //Put that into color component
{
	for (int i=0; i < FaceLength; i++)
	{
		int index = VBO_BE[i].INDEX_START;
		int len = VBO_BE[i].length;
		for (int v=index; v < index+len; v++)
		{
			int next;
			if (v == index+len-1) next = index;
			else next = v+1;
			AOS[v].c = Normalize(vectorAB(AOS[v].v, AOS[next].v));
		}
		
	}
//	SendToGPU();
}

void CalcNormals(){}

[/Spoiler]

and so on the thing is i write normals to 24 bit uchar texture

where i use the formula color = normal*0.5+0.5;

and then decompose it in a shader by

tangent or normal = texture2D(coord).xyz*2.0-1.0;

only depth component has 32 bit precision

and i write depth map as a distance from camera to fragment (no fancy matrix multiplications) just distance between eye and fragment and store it as 4 8 bit values (as one pixel)

so basically i create a set of models (scene) calculate all revelant data as: normals tangents

then during rendering stage i draw everything

first to texture that stores normals

then to texture that stores tangents

then to texture that stores depth

and here is how i produce kernel samples

for (int i=0; i < 64; i++)

{

float iter = float(i)/64.0;

float acoord = 160.0;

float xc = (10.0+iter*acoord)*imopi;

kernsamples[i] = Normalize(vec3(sin(xc), RandFloat()*2.0-1.0, cos(xc)));

}

they are facing z+ from right(x+) to left (x-) with random y (top down value)

and then i apply lets call it ssao

void DrawSSAO()
{


FPP_CAM->SetView();

WriteDepthToFBO();
DrawNormalsToFBO();
DrawTangentsToFBO();

FPP_CAM->SetView();
ACTUAL_MODEL.LoadIdentity();
gluPerspectiveA(ACTUAL_PROJECTION, 90.0f, lcASPECT, 0.1f, 10000.0f);
mat4 MVP = (ACTUAL_MODEL * ACTUAL_VIEW) * ACTUAL_PROJECTION;

	 InitiateFBODraw(&amp;ssaofbo);

	glClear(GL_COLOR_BUFFER_BIT);
	glClear(GL_DEPTH_BUFFER_BIT);
	gluPerspectiveA(ACTUAL_PROJECTION, 90.0f, lcASPECT, 0.1f, 10000.0f);

	ssao_shader.Enable();
	
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, depthfbo.FBO_TEX);
	glActiveTexture(GL_TEXTURE1);
	glBindTexture(GL_TEXTURE_2D, normalfbo.FBO_TEX);
	glActiveTexture(GL_TEXTURE2);
	glBindTexture(GL_TEXTURE_2D, tangentfbo.FBO_TEX);

	

	ssao_shader.Send1I("depthtex", 0);
	ssao_shader.Send1I("normaltex", 1);
	ssao_shader.Send1I("tangenttex", 2);


	ssao_shader.Send1F("z_near", 0.1);
	ssao_shader.Send1F("z_far", 10000.0);
	
	ssao_shader.Send1F("fov", 90.0);
	ssao_shader.Send1F("aspect", lcASPECT);
	
	ssao_shader.Send3F("campos", FPP_CAM->pos);
	ssao_shader.Send3F("front_vec", FPP_CAM->ReturnFrontVector());
	ssao_shader.Send3F("dirX", FPP_CAM->ReturnRightVector());
	ssao_shader.Send3F("dirY", FPP_CAM->ReturnUpVector());
	ssao_shader.SendMVPtoShader(MVP);

	
	
	for ( int i=0; i < 64; i++)
	ssao_shader.Send3F("samples["+IntToStr(i)+"]", kernsamples[i]);
	
	DrawFullScrQuad(&amp;ssao_shader);
	
	ssao_shader.Disable();
	ssaofbo.unbind();
	 //when you call unbind it automatically binds main framebuffer
	
	
			glViewport(0, 0, int ( rSCREEN_WIDTH ), int ( rSCREEN_HEIGHT ));

	glClear(GL_COLOR_BUFFER_BIT);
	glClear(GL_DEPTH_BUFFER_BIT);	

//now drae fullscreen quad with ssao texture to display it on the screen
	ssao_mask.Enable();
	
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, ssaofbo.FBO_TEX);
	
	ssao_mask.Send1I("ssaotex", 0);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_COLOR, GL_ONE);
	DrawFullScrQuad(&amp;ssao_mask);
	glDisable(GL_BLEND);
	ssao_mask.Disable();
}

And the frag shader

precision highp float;




uniform vec4 MVP1;
uniform vec4 MVP2;
uniform vec4 MVP3;
uniform vec4 MVP4;

float dp43(vec4 matrow, vec3 p)
{
return ( (matrow.x*p.x) + (matrow.y*p.y) + (matrow.z*p.z) + matrow.w );
}


float dp33(vec3 matrow, vec3 p)
{
return matrow.x*p.x + matrow.y*p.y + matrow.z*p.z;
}

vec3 vectorAB( vec3 A,  vec3 B)
{
return B-A;
}

const float imopi          = 0.01745329251; //pi / 180.0 RAD_2_DEG
uniform vec3 dirX; //RIGHT VIEW VECTOR
uniform vec3 dirY; //UP VIEW VECTOR
uniform vec3 front_vec; //FRONT VIEW VECTOR

uniform float fov;
uniform float z_near;
uniform float z_far;
uniform float aspect;
uniform vec3 campos;

const int MAX_KERNEL_SIZE = 64;


uniform sampler2D depthtex;
uniform sampler2D normaltex;
uniform sampler2D tangenttex;



uniform vec3 samples[64];


varying vec2 TexCoord; //position of the fragment on the screen range 0..1





highp float getDepth(highp vec2 pos)
{

    highp vec4 packedZValue = texture2D(depthtex, pos);

    const highp vec4 bitShifts = vec4(1.0 / (256.0 * 256.0 * 256.0),
                        1.0 / (256.0 * 256.0),
                        1.0 / 256.0,
                        1.0);
    highp float shadow = dot(packedZValue , bitShifts);
 
    return shadow;
}

vec3 getNormal(vec2 pos)
{
	    vec4 tn = texture2D(normaltex, pos);
return tn.xyz * 2.0 - 1.0;
}

vec3 getTangent(vec2 pos)
{
	    vec4 tn = texture2D(tangenttex, pos);
return tn.xyz * 2.0 - 1.0;
}

vec3 GetDirectionFromScreen(vec3 pos, float depth, vec2 coord)
{
float a = fov / 2.0;

float cotangent = 1.0 / tan( a * imopi );

float ax = z_near / cotangent;

float screen_w = 2.0*ax;

float screen_h = screen_w;

screen_w = screen_w * aspect;

float scr_coord_x = coord.x;
float scr_coord_y = coord.y;

vec3 dir = front_vec;

//move to lower left corner of the near screen
vec3 start_pos = (pos + dir * z_near) + (-dirX * (screen_w / 2.0)) + (-dirY * (screen_h/2.0));

vec3 start = start_pos + (dirX * (screen_w * scr_coord_x)) + (dirY * (screen_h * scr_coord_y));

return normalize( vectorAB(pos, start) );

}



const float ssao_range = 30.0;





void main()
{
float sample_depth = getDepth(TexCoord);
vec3 sample_pos = campos + GetDirectionFromScreen(campos, sample_depth, TexCoord)*sample_depth;
vec3 sample_normal = getNormal(TexCoord);
vec3 sample_tangent = getTangent(TexCoord);
vec3 sample_binormal = normalize(cross(sample_normal*100.0, sample_tangent*100.0));

//compute rotation matrix
/*
vec3 tbn1 = vec3(sample_tangent.x, sample_binormal.x, sample_normal.x);
vec3 tbn2 = vec3(sample_tangent.y, sample_binormal.y, sample_normal.y);
vec3 tbn3 = vec3(sample_tangent.z, sample_binormal.z, sample_normal.z);
*/

vec3 tbn1 = vec3(sample_tangent.x, sample_tangent.y, sample_tangent.z);
vec3 tbn2 = vec3(sample_binormal.x, sample_binormal.y, sample_binormal.z);
vec3 tbn3 = vec3(sample_normal.x, sample_normal.y, sample_normal.z);


    float AO = 0.0;

    for (int i = 0 ; i < MAX_KERNEL_SIZE ; i++)
    {

vec3 rot_sample_dir;
rot_sample_dir.x = dp33(tbn1, samples[i]);
rot_sample_dir.y = dp33(tbn2, samples[i]);
rot_sample_dir.z = dp33(tbn3, samples[i]);


vec3 kernel_pos = sample_pos + rot_sample_dir*30.0;




vec4 vertexClip;

vertexClip.x = -dp43(MVP1, kernel_pos);
vertexClip.y = dp43(MVP2, kernel_pos);
vertexClip.z = dp43(MVP3, kernel_pos);
vertexClip.w = dp43(MVP4, kernel_pos);

vertexClip = vertexClip / vertexClip.w;
vertexClip = vertexClip*0.5 + 0.5;

float kernel_depth = getDepth(vertexClip.xy);

if (kernel_depth < sample_depth) AO = AO + 1.0;


    }

    AO = 1.0 - AO/128.0;
    gl_FragColor = vec4(vec3(AO),1.0);
}

I know theres a lot of code to go through but maybe someone will see something that i cant?

I was checking depthmap, normalmap and tangent map they seem to be fine, also getdirectionfromscreen seems to work as expected too

So you say those swirls come from SSAO, and there are no textures at all?

We really need a sticky thread about cool glitches and debug renders : )

Advertisement

Yeah no textures at all, just this shader

This topic is closed to new replies.

Advertisement