nenuzhno-engine_iter1/assets/ssr/shaders/ssr.fs

171 lines
4.5 KiB
GLSL

#version 100
precision highp float;
varying vec4 v_scrpos;
varying vec4 v_position;
varying vec3 v_normal;
uniform sampler2D u_tex;
uniform sampler2D u_depthTex;
uniform mat4 u_mvpMtx;
uniform mat4 u_invMVPMtx;
uniform vec3 u_eyePos;// = vec3(0.0, 0.6, 1.0);
vec3 GetPos(vec2 uv, float depth)
{
vec4 pos = u_invMVPMtx*(vec4(uv,depth,1.0)*2.0-1.0);
pos.xyz /= pos.w;
return pos.xyz;
}
vec3 GetUV(vec3 apos)
{
vec4 pVP = u_mvpMtx*vec4(apos,1.0);
pVP.xy = vec2(0.5,0.5)+vec2(0.5,0.5)*pVP.xy / pVP.w;
return vec3(pVP.xy,pVP.z/pVP.w);
}
vec4 u_camera = vec4(0.1,2.0,0.5,1.0);//near far fov aspect
float GetDepth(vec2 uv)
{
float depth = texture2D(u_depthTex,uv).r;
depth = 2.0 * u_camera.x * u_camera.y /
(u_camera.y + u_camera.x -
(depth*2.0-1.0)*(u_camera.y-u_camera.x));
return depth;
}
const float rayStepSize = 0.1;
vec2 v_uv;
vec3 raytrace(in vec3 reflectionVector, in float startDepth)
{
vec3 color = vec3(0.0);
float stepSize = rayStepSize;
float size = length(reflectionVector.xy);
reflectionVector = normalize(reflectionVector/size);
reflectionVector = reflectionVector * stepSize;
//Current sampling position is at current fragment
vec2 sampledPosition = v_uv;
//Current depth at current fragment
float currentDepth = startDepth;
//The sampled depth at the current sampling position
//float sampledDepth = linearizeDepth(texture2D(u_depthTexture, sampledPosition).x);
float sampledDepth = GetDepth(sampledPosition);
// Raytrace as long as in texture space of depth buffer (between 0 and 1)
while(sampledPosition.x <= 1.0 && sampledPosition.x >= 0.0 && sampledPosition.y <= 1.0 && sampledPosition.y >= 0.0)
{
//Update sampling position by adding reflection vector's xy and y components
sampledPosition = sampledPosition + reflectionVector.xy;
//Updating depth values
currentDepth = currentDepth + reflectionVector.z * startDepth;
//float sampledDepth = linearizeDepth( texture2D(u_depthTexture, sampledPosition).x);
float sampledDepth = GetDepth(sampledPosition);
//If current depth is greater than sampled depth of depth buffer, intersection is found
if(currentDepth > sampledDepth)
{
//Delta is for stop the raytracing after the first intersection is found
//Not using delta will create "repeating artifacts"
float delta = (currentDepth - sampledDepth);
if(delta < 0.003)
{
color = texture2D(u_tex, v_uv).rgb;
break;
}
}
}
return color;
}
#if 0
vec4 ssr()
{
vec3 reflectedColor = vec3(0.0);
//vec3 normal = normalize( texture2D(u_normalTexture, v_uv).xyz*2.0-1.0 );
vec3 normal = v_normal;
//Depth at current fragment
//float currDepth = linearizeDepth( texture2D(u_depthTex, v_uv).x );
float currDepth = GetDepth(v_uv);
vec3 pos = GetPos(v_uv,currDepth);
//Eye position, camera is at (0, 0, 0), we look along negative z, add near plane to correct parallax
vec3 eyePosition = normalize(pos-u_eyePos);// vec3(0.0, 0.0, 0.01) );
vec3 reflectionVector = reflect(eyePosition, normal);
reflectionVector= GetUV(reflectionVector);
//Call raytrace to get reflected color
reflectedColor = raytrace(reflectionVector, currDepth);
float nl = max(-dot(normal, eyePosition),0.0);
float fresnel = pow(1.0-nl,0.82);
return vec4(reflectedColor, 1.0);
}
#else
vec4 ssr()
{
//todo: normal buffer
vec3 normal = v_normal;
//vec3 pos = GetPos(uv, depth);
vec3 pos = v_position.xyz;
vec3 viewDir = normalize(pos-u_eyePos);
vec3 reflectDir = normalize(reflect(viewDir, normal));
vec3 currentRay = vec3(0.0);
vec3 nuv = vec3(0.0);
float L = 0.06;//???
for(int i = 0; i<10; i++){
currentRay = pos+reflectDir*L;
nuv = GetUV(currentRay);
float nd = texture2D(u_depthTex, nuv.xy).x;
vec3 newPos = GetPos(nuv.xy, nd);//2???
L = length(pos-newPos);
}
if(L>0.4)
return vec4(0.0);
vec4 cnuv = vec4(0.0);
cnuv = texture2D(u_tex, nuv.xy);
/*for(float x = -0.1; x<=0.1; x+=0.025){
cnuv += texture2D(u_tex, nuv.xy+vec2(x*L,0.0))*0.1;
}*/
float nl = max(-dot(normal, viewDir),0.0);
float fresnel = pow(1.0-nl,0.82);
//return vec4(normalize(currentRay),1.0);
//return vec4(vec3(pow(nuv.z,0.4)),1.0);
//return vec4(L*4.0);
return cnuv*fresnel*(1.0-L*2.0);
// return vec4(L*4.0);
}
#endif
void main()
{
vec2 uv = v_scrpos.xy/v_scrpos.w*0.5+0.5;
v_uv = uv;
vec4 col = texture2D(u_tex, uv);
//float depth = texture2D(u_depthTex, uv).x;
float depth = gl_FragCoord.z;
vec4 reflect = vec4(0.0);
if(depth<(texture2D(u_depthTex, uv).x+0.002))
{
reflect = ssr();
}
gl_FragColor = col+reflect;
//gl_FragColor = reflect;
//gl_FragColor = col*pow(depth, 10.0);
//gl_FragColor = vec4(reflectDir, 1.0);
}