ssr屏幕空间射线追踪

本轮作业中,我们需要在一个光源为方向光,材质为漫反射 (Diffuse) 的场景
中,完成屏幕空间下的全局光照效果(两次反射)。
为了在作业框架中实现上述效果,基于我们需要的信息不同我们会分三阶段
着色,每个阶段都有相对应的任务。第一次着色负责计算 Shadow Map 所需的深
度值并保存到贴图中。第二次着色负责计算屏幕空间中,每个像素对应的世界坐
标系下位置、世界坐标系下法线、漫反射反射率和可见性信息并最终保存到对应
贴图中。第三次着色基于之前得到的场景几何信息 (像素对应的位置,法线),场
景与光源的遮挡信息 (光源坐标系的深度值),场景的材质信息 (漫反射反射率),
来计算两次反射的全局光照结果。
本轮作业的主要工作将集中在第三次着色中。

间接光照计算

codes:

/*
 * Evaluate directional light with shadow map
 * uv is in screen space, [0, 1] x [0, 1].
 *
 */
vec3 EvalDirectionalLight(vec2 uv) {
  vec3 Le = uLightRadiance*GetGBufferuShadow(uv);
  return Le;
}

/*
 * Evaluate diffuse bsdf value.
 *
 * wi, wo are all in world space.
 * uv is in screen space, [0, 1] x [0, 1].
 *
 */
vec3 EvalDiffuse(vec3 wi, vec3 wo, vec2 uv) {
  vec3 normal = GetGBufferNormalWorld(uv);
  vec3 L = GetGBufferDiffuse(uv)*max(0.0,dot(wi,normal));
  return L;
}

#define MAX_RARY_MARCH_STEP 50

bool RayMarch(vec3 ori, vec3 dir, out vec3 hitPos,out int stepNum) {
  float step_ = 0.1;
  float len = 0.0;
  //len += step_/2.0;
  for(int i=0; i < MAX_RARY_MARCH_STEP; i++)
  {
    stepNum= i;
    vec3 curPos = ori + dir*len;
    len += step_;
    vec2 uv =  GetScreenCoordinate(curPos);
    float d = GetGBufferDepth(uv);
    if(GetDepth(curPos) > d+0.1){
      hitPos = curPos;
      //stepNum = 5;
      return true;
    }
    if(uv.x<0.0||uv.x>1.0||uv.y<0.0||uv.y>1.0){
       //stepNum = 5;
       break;
    }
  }
  return false;
}

//2 - 4
#define SAMPLE_NUM 3

void main() {
  float s = InitRand(gl_FragCoord.xy);
  vec2 uv = GetScreenCoordinate(vPosWorld.xyz);
  //float shadow = GetGBufferuShadow(uv);
  vec3 L = vec3(0.0);
  vec3 wi = normalize(uLightDir);
  vec3 ori = vec3(float(vPosWorld.x),float(vPosWorld.y),float(vPosWorld.z));
  vec3 wo = normalize(uCameraPos - ori);
  //计算直接光
  L = EvalDiffuse(wi, wo, uv) * EvalDirectionalLight(uv);
  //计算间接光 ssr
  vec3 iL = vec3(0.0);
  vec3 normal = GetGBufferNormalWorld(uv);
  normal = normalize(normal);
  vec3 nb1 = vec3(0.0);
  vec3 nb2 = vec3(0.0);
  LocalBasis(normal,nb1,nb2);
  for(int i=0; i<SAMPLE_NUM; i++){
      float pdf = 0.0;
      vec3 ndir = SampleHemisphereUniform(s, pdf);
      s = s+0.1;
      s = Rand1(s);
      vec3 dir = nb1*ndir.x + nb2*ndir.z + normal*ndir.y;
      //dir = reflect(-wo,normal);//for test 镜面反射
      dir = normalize(dir);
      vec3 hitPos = vec3(0.0);
      int stepNum = 0;
      if(RayMarch(ori,dir,hitPos,stepNum)){
        vec2 uvHitPos = GetScreenCoordinate(hitPos.xyz);
        iL += EvalDirectionalLight(uvHitPos)*EvalDiffuse(wi,-dir,uvHitPos)*EvalDiffuse(dir,wo,uv) / pdf;
        //iL += EvalDirectionalLight(uvHitPos)/ pdf;
        //iL = EvalDiffuse(wi,-dir,uvHitPos);
        //iL = EvalDiffuse(dir,wo,uv);
        //iL = vec3(0.5,0.5,0.5);
        
      }
      //iL = vec3(GetDepth(ori)/100.0);
      //iL = dir;
      //iL = vec3(float(stepNum)/float(MAX_RARY_MARCH_STEP));
  }
  iL/=max(float(SAMPLE_NUM),1.0);
  L += iL;
  //L = iL;
  vec3 color = pow(clamp(L, vec3(0.0), vec3(1.0)), vec3(1.0 / 2.2));
  gl_FragColor = vec4(vec3(color.rgb), 1.0);
}

results:



todo 如果加上时域和空域的光追降噪算法,效果会更佳

posted @ 2024-01-22 21:31  bluebean  阅读(15)  评论(0编辑  收藏  举报