首页 > 其他分享 >pcss 软阴影

pcss 软阴影

时间:2024-01-17 21:44:44浏览次数:35  
标签:1.0 pcss float 阴影 NUM coords 0.0 vec2

PCF

Percentage Closer Filtering:PCF是一种用于阴影反锯齿的方法,本身不是软阴影方法。

算法流程说明:

  1. Perform multiple (e.g. 7x7) depth
    comparisons for each fragment
  2. Then, averages results of comparisons
  3. e.g. for point P on the floor,
  1. compare its depth with all pixels
    in the red box, e.g. 3x3
  2. get the compared results, e.g.
    1, 0, 1,
    1, 0, 1,
    1, 1, 0,
  3. take avg. to get visibility, e.g. 0.667

pcf使用的过滤size越大,得到的阴影结果越模糊,范围也被扩大。

code:

vec2 poissonDisk[NUM_SAMPLES];

void poissonDiskSamples( const in vec2 randomSeed ) {
  float ANGLE_STEP = PI2 * float( NUM_RINGS ) / float( NUM_SAMPLES );
  float INV_NUM_SAMPLES = 1.0 / float( NUM_SAMPLES );

  float angle = rand_2to1( randomSeed ) * PI2;
  float radius = INV_NUM_SAMPLES;
  float radiusStep = radius;

  for( int i = 0; i < NUM_SAMPLES; i ++ ) {
    poissonDisk[i] = vec2( cos( angle ), sin( angle ) ) * pow( radius, 0.75 );
    radius += radiusStep;
    angle += ANGLE_STEP;
  }
}

float PCF(sampler2D shadowMap, vec4 coords,float filterSize) {
  if(coords.x <-1.0 || coords.y>1.0 || coords.y<-1.0 || coords.y>1.0){
    //不在灯光相机视野中,默认完全照亮
    return 1.0;
  }
  float pixelSize = 1.0/2048.0;
  float count = 0.0;
  poissonDiskSamples(vec2(coords.x,coords.y));
  for(int i=0;i<NUM_SAMPLES;i++){
    vec2 uv = poissonDisk[i]*pixelSize*filterSize + coords.xy;
    if(uv.x <-1.0 || uv.y>1.0 || uv.y<-1.0 || uv.y>1.0){
      //不在灯光相机视野中,默认完全照亮
      return 1.0;
    }
    float dNearest = sampleDepth(shadowMap, uv) * Z_RANGE;
    float d = (coords.z+1.0)/2.0*Z_RANGE;//[-1,1]->[0,1.0]
    if(!(d > dNearest+Z_EPS)){//pcf 返回可见性指标
      count += 1.0;
    }
  }
  float res = count/float(NUM_SAMPLES);
  return res;
}

result:

PCF_8X8

PCF_64X64

PCSS

Percentage Closer Soft Shadows

通过观察可知阴影的软硬与阴影距离阴影投掷物的距离有关,距离越近,阴影越实(硬);距离越远,阴影越虚(软)。因此可以在PCF的基础上,动态调整filter size从而实现软阴影效果。

关键在于如何选择filter size,filter size和阴影距离阴影投掷物的距离(d_receiver-d_blocker)和遮挡物距离光源的距离(d_blocker)有关, 如下图所示:

其中W_penumbra就是面光源形成的软阴影范围,也就是pcf使用的filter size。

通过三角相似关系,可以得到下面的数量关系:

w_{Pemumbra} = (d_{Reciiver}- d_{Blocker}) * w_{Light}/d_{Blocker}

其中W_light为光源宽度,在代码中可以取常量;d_receiver是物体深度,可以在shader中uLightMVP*aPosition计算得到;

d_blocker是遮挡物深度可以从pass1中记录的最近物体深度读取,读取一定范围内的遮挡物的平均深度,这个范围需要取多大?

1.Can be set constant (e.g. 5x5), but can be better with heuristics

2.理论上的blocker search region:

依赖于光源面积大小和观察点距离光源的距离,即图中红虚线构成四棱锥范围。有一个问题是从面光源的不同点看场景会有不同的shadw map,如果只用一个shadw map进行采样,本身这里是精确分析,最后的结果又变成了近似。

最后得到PCSS的算法流程:

The complete algorithm of PCSS

  • Step 1: Blocker search
    (getting the average blocker depth in a certain region)
  • Step 2: Penumbra estimation
    (use the average blocker depth to determine filter size)
  • Step 3: Percentage Closer Filtering

code:

vec2 findBlocker( sampler2D shadowMap,  vec2 uv, float zReceiver ) {
  if(uv.x <-1.0 || uv.y>1.0 || uv.y<-1.0 || uv.y>1.0){
    //不在灯光相机视野中,默认没有遮挡物
    return vec2(0.0,0.0);
  }
  //uniformDiskSamples(uv);
  
  float pixelSize = 1.0/2048.0;
	float db = 0.0;
  float ds = 0.0;
  //启发式的得到搜索范围,单位:像素
  float searchSize = 0.0;
  searchSize = LIGHT_WIDTH*(zReceiver-NEAR_PLANE)/zReceiver;
  searchSize = searchSize/200.0/pixelSize;
  searchSize *= 1.5;
  //固定
  //searchSize = 64.0;// 64.0;

  float count = 0.0;
  poissonDiskSamples(vec2(uv.x*9999.0+8888.0,uv.y*7777.0+12345.0));
  for(int i = 0; i < NUM_SAMPLES; i++){
    vec2 uv2 = poissonDisk[i]*pixelSize*searchSize + uv;
    if(uv2.x <-1.0 || uv2.y>1.0 || uv2.y<-1.0 || uv2.y>1.0){
      //不在灯光相机视野中,默认没有遮挡物
      return vec2(0.0,0.0);
    }
    float d = sampleDepth(shadowMap, uv2);
    d = d*Z_RANGE;
    if(d < zReceiver-5.0 ){
      db += d;
      count += 1.0;
    }
  }
  db = db / count;
  ds = zReceiver - db;
  //db = db / float(NUM_SAMPLES);
  //ds = ds / float(NUM_SAMPLES);
  return vec2(db,ds);
}

float PCF(sampler2D shadowMap, vec4 coords,float filterSize) {
  if(coords.x <-1.0 || coords.y>1.0 || coords.y<-1.0 || coords.y>1.0){
    //不在灯光相机视野中,默认完全照亮
    return 1.0;
  }
  float pixelSize = 1.0/2048.0;
  float count = 0.0;
  poissonDiskSamples(vec2(coords.x,coords.y));
  for(int i=0;i<NUM_SAMPLES;i++){
    vec2 uv = poissonDisk[i]*pixelSize*filterSize + coords.xy;
    if(uv.x <-1.0 || uv.y>1.0 || uv.y<-1.0 || uv.y>1.0){
      //不在灯光相机视野中,默认完全照亮
      return 1.0;
    }
    float dNearest = sampleDepth(shadowMap, uv) * Z_RANGE;
    float d = (coords.z+1.0)/2.0*Z_RANGE;//[-1,1]->[0,1.0]
    if(!(d > dNearest+10.0)){//pcf 返回可见性指标
      count += 1.0;
    }
  }
  float res = count/float(NUM_SAMPLES);
  return res;
}

float PCSS(sampler2D shadowMap, vec4 coords){
  float d_r = (coords.z+1.0)/2.0*Z_RANGE;// d_receiver
  float pixelSize = 1.0/2048.0;
  float d_b = 0.0;//d_blocker
  float d_s = 0.0;//average d_reciver - d_blocker
  float filterSize = 16.0;
  // STEP 1: avgblocker depth
  vec2 vB = findBlocker(shadowMap,coords.xy,d_r);
  d_b = vB.x;
  d_s = vB.y;
  //return d_b/Z_RANGE;
  //return d_s/Z_RANGE;
  if(d_s<=EPS){
    //不受遮挡,可见性为1
    return 1.0;
  }
  // STEP 2: penumbra size
  //float wp = pow(d_s / d_b,2.0) * LIGHT_WIDTH; // d_s / d_b* LIGHT_WIDTH;//  
  float wp = d_s / d_b* LIGHT_WIDTH;
  //float wp = (dr/db-1.0) * L_WIDTH;
  float penumbraPixelSize = wp/200.0/pixelSize;//200是正交相机里设定的窗口范围
  //return penumbraPixelSize/100.0;
  // STEP 3: filtering
  //filterSize = penumbraPixelSize+8.0;
  filterSize = penumbraPixelSize;
  float res = PCF(shadowMap, coords, filterSize);
  return res;
}


result:

PCF 64X64

PCSS

标签:1.0,pcss,float,阴影,NUM,coords,0.0,vec2
From: https://www.cnblogs.com/bluebean/p/17971238

相关文章

  • 去掉bootstrap4自带的input输入框半透明阴影
    bootstrap 输入框等输入时会自带蓝色阴影效果,有时候我们并不需要。button同理查看bootstrap.css代码,搜索focus,找到相关内容。所以我们再写css,把它原来的覆盖掉就可以啦/*去掉bootstrap自带的input输入框半透明阴影*/.form-control:focus{ box-shadow:none;}......
  • [AHK2] 为toolwindow窗口添加阴影效果
    如下示例g:=Gui('-Caption+Border');或包含+ToolWindowg.SetFont('s13','consolas')g.AddText('c4c071d',data)g.BackColor:='f6eeda'g.Show('x100y50')WinSetTransColor('white......
  • 滚动阴影解决方案
    1.backgroud,限制高度,加overflow,codeopen,.g-scroll{top:-1px;position:relative;height:500px;overflow-y:scroll;overflow-x:hidden;background:linear-gradient(#fff,transparent)top/100%100px,radial-grad......
  • 【Windows】微软自带的系统阴影副本(VSS)
    学习就是在生活的方方面面!在前两天和我的老哥的一次闲聊中,老哥介绍了Windows系统的NTFS磁盘自带的,类似于快照的系统,VSS于是我就开始了学习! 1.什么是VSSVSS是微软公司的一种技术,全称为VolumeShadowCopyService(卷影复制服务)。VSS是Windows操作系统中的一个功能,用于创建文......
  • css实现元素四周阴影
    首先确定的是需要使用box-shadow这一属性语法如下:box-shadow:h-shadowv-shadowblurspreadcolorinset;h-shadow:表示水平方向上的阴影偏移量,必须指明,可以是正数、负数、0,如果为正数左方有阴影,如果为负数右方有阴影,如果为0它位于元素的正中间。v-shadow:表示垂直方向上的阴影偏移......
  • box-shadow内阴影实现各种效果收集
    1.月牙    详见一步步打造自己的纯CSS单标签图标库.moon{display:inline-block;height:1.5em;width:1.5em;box-shadow:inset-.4em00;border-radius:2em;transform:rotate(20deg);}2.向内填充动画  详见SVG描边动画(......
  • 纯CSS实现炫酷文本阴影效果
    如图所示,这是一个文本阴影效果,阴影有多个颜色,鼠标悬停时文本阴影效果消失,文本回到正常的效果。让我们逐步分解代码,看看如何使用纯CSS实现这个效果的。基于以上动图可以分析出以下是本次实现的主要几个功能点:文本有多个颜色的阴影的效果文本有空心镂空的效果鼠标悬停时文本回......
  • 11月12日基础的网页设计以及阴影的设计box-shadow属性
    目录基础的网页设计html的代码css的代码阴影效果添加基础的网页设计html的代码<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>今天网页</title><linkrel="stylesheet"href="样式.css"......
  • 11月12日基础的网页设计以及阴影的设计box-shadow属性
    目录基础的网页设计html的代码css的代码基础的网页设计html的代码<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>今天网页</title><linkrel="stylesheet"href="样式.css">&......
  • 【算法】十一月阳光下的阴影面积
    十一月的阳光透过窗户,照射在一位笑起来甜美、青春洋溢的女子的办公桌上。小悦,一个总是以高马尾造型亮相的软件工程师,展现出她的干练与活力。那乌黑亮丽的长发轻盈飘动,仿佛在诉说着她的独特魅力。她的眉眼如画,那双明亮的眼睛里闪烁着对知识的渴望和对技术挑战的热情。这一天,她收到......