The code is kinda messy, but I’m still working on it:
#version 330
precision highp float;
uniform vec4 mainColor;
uniform vec3 eyePosition;
uniform sampler2D reflectionPropertiesTexture;
uniform sampler2D depthTexture;
uniform sampler2D renderTexture;
uniform sampler2D positionTexture;
uniform sampler2D normalTexture;
uniform mat4 camera;
uniform vec4 refSteps;
in vec2 fragTexCoord;
out vec4 finalColor[2];
vec3 worldToScreenUV(vec3 position) {
vec4 LightSpacePos = camera * vec4(position, 1.0); //NDC
vec3 ProjCoords = LightSpacePos.xyz / LightSpacePos.w;
vec3 UVCoords;
UVCoords.x = 0.5 * ProjCoords.x + 0.5;
UVCoords.y = 0.5 * ProjCoords.y + 0.5;
UVCoords.z = 0.5 * ProjCoords.z + 0.5;
return UVCoords;
}
vec4 SSR()
{
float Shin = 1.0; //Shiness
float myDepth = texture(depthTexture, fragTexCoord).x; //Current depth
vec4 out_Color = texture(renderTexture, fragTexCoord) ; //Output color
//vec4 out_Color = vec4(0,1,0,1); //Output color
if (Shin<=0.01) // NO SCREENSPACE REFLECTION
{
//Output color
//nothinf
} else {
vec3 Normal = normalize(texture(normalTexture, fragTexCoord).xyz) ;
vec3 Position = texture(positionTexture, fragTexCoord).xyz;
vec3 View = Position - eyePosition;
vec3 R = reflect(normalize(View),Normal); //Reflected vector
float vdotn = (dot(normalize(View),Normal)); //dot product
vec2 size = vec2(1280, 720);
// Fresnel
//Shin = Shin * pow ( 1.0-abs(vdotn), 1.0 );
Shin *= .6;
bool outOfBounds = false;
float STEP_SIZE = refSteps.x;
float MAX_STEP = refSteps.y;
float MAX_STEP_BACK = refSteps.z;
float MIN_OFFSET = refSteps.a;
float steps = 0;
vec3 currentPos = Position ; //Posicao inicial para a marcha de raios
float CurrentPosDepth;
vec3 texPos ;
//vec3 ScenePos ;
float SceneDepth;
float real_step = MAX_STEP;
// marcha de raios
while ( steps < MAX_STEP ){
currentPos += R.xyz*STEP_SIZE;
texPos = worldToScreenUV(currentPos);
//ScenePos = texture( positionTexture, texPos.xy ).xyz;
SceneDepth = texture( depthTexture, texPos.xy ).x;
if ( (SceneDepth <= texPos.z ) ) {
if(texPos.z - SceneDepth < MIN_OFFSET )
{
real_step = steps;
steps = MAX_STEP;
} else {
steps++;
outOfBounds = true;
break;
}
}
else {
steps ++ ;
}
if(!(texPos.x <= 1.0 && texPos.x >= 0.0 && texPos.y <= 1.0 && texPos.y >= 0.0)) {
outOfBounds = true;
break;
}
}
// Colidiu com alguma coisa
if (real_step < MAX_STEP && !outOfBounds){
steps = 0;
while ( steps < MAX_STEP_BACK ){
currentPos -= R.xyz*(STEP_SIZE/2)/MAX_STEP_BACK;
texPos = worldToScreenUV(currentPos) ;
//ScenePos = texture( positionTexture, texPos.xy ).xyz;
SceneDepth = texture( depthTexture, texPos.xy ).x;
if ( (SceneDepth > currentPos.z ) ) {
if(texPos.z - SceneDepth < MIN_OFFSET )
{
steps = MAX_STEP_BACK;
} else {
steps++;
outOfBounds = true;
break;
}
} else {
steps ++ ;
}
}
}
Shin = Shin*(1.0-real_step/MAX_STEP);
// COMBINING REFLECTION TO THE ORIGINAL PIXEL COLOR
if (Shin > 0.01 && !outOfBounds){
vec3 colorReflect = texture(renderTexture, texPos.xy ).rgb ;
out_Color.rgb = mix ( out_Color.rgb, colorReflect.rgb , Shin);
//out_Color.rgb = mix ( out_Color.rgb, colorReflect.rgb , 0);
}
if(outOfBounds) {
finalColor[1] = vec4(1.0,1.0,1.0,1.0);
} else {
finalColor[1] = vec4(0.0,0.0,0.0,1.0);
//finalColor[1] = vec4(1.0,1.0,1.0,1.0);
}
if (Shin <= 0.01){
finalColor[1] = vec4(1.0,1.0,1.0,1.0);
}
}
return out_Color;
//return vec4(eyePosition ,1) + texture(normalTexture, fragTexCoord);
}
void main() {
float depth = texture(depthTexture, fragTexCoord).x;
vec3 position = texture(positionTexture, fragTexCoord).xyz;
vec4 ssPos = camera * vec4(position, 1.0);;
vec4 renderedColor = texture(renderTexture, fragTexCoord);
vec4 reflectionProperties = texture(reflectionPropertiesTexture, fragTexCoord);
if (depth<1.0) {
if(reflectionProperties.x==0) {
finalColor[0] = (texture(renderTexture, fragTexCoord) * mainColor);
finalColor[1] = vec4(0.0,0.0,0.0,1.0);
} else {
finalColor[0] = SSR();
}
} else {
finalColor[0] = vec4(0.0,0.0,0.0,1.0);
finalColor[1] = vec4(0.0,0.0,0.0,1.0);
}
}