zoukankan      html  css  js  c++  java
  • HLSL ddx / ddy

    HLSL ddx / ddy

      在光栅化的时刻,GPUs会在同一时刻并行运行很多Fragment Shader,但是并不是一个pixel一个pixel去执行的,而是将其组织在2x2的一组pixels分块中,去并行执行。

      偏导数就正好是计算的这一块像素中的变化率。从下图可以看出来ddx 就是右边的像素块的值减去左边像素块的值,而ddy就是下面像素块的值减去上面像素块的值。其中的x,y代表的是屏幕坐标。

        

    偏导数的应用

    1、LOD的确定。

      

      大家应该都知道mipmap 的用处,但是可能并不知道mipmap的核心在选择到底用那一块mipmap的level时,靠的就是偏导数。屏幕空间的贴图UV偏导数过大的时候代表贴图离我们过远,就会选择低等级的mipmap。

      比如,原图的LOD=1,次大的LOD=2,依此类推。

      

      在Shader中使用tex2D(tex, uv)的时候相当于在GPU内部展开成下面:
        

    tex2D(sampler2D tex, float4 uv)
    {
        float lod = CalcLod(ddx(uv), ddy(uv));
        uv.w= lod;
        return tex2Dlod(tex, uv);
    }

     

    2、计算法线。

      如果调用ddx(Pos),和ddy(Pos)这个代表求出相邻的2个像素块之间坐标的差值,即下面图中的红色和绿色2个矢量,而这2个矢量都在这个三角形的平面上,那么执行 normalize( cross(ddx(pos),ddy(pos)) ) 就求出的面的法线。

      但是这里要注意,在HlSL上面,或者Unity上面要写成normalize( cross(ddy(pos),ddx(pos)) ),不然法线是反向的。这个是由于左右手坐标系引起的。

    void surf (Input IN, inout SurfaceOutput o)
    
    {
    
    o.Albedo = normalize(cross(ddy(IN.worldPos),ddx(IN.worldPos)));
    
    }

      

    3、贴图加强勾边。

    void surf (Input IN, inout SurfaceOutput o)
    
    {
    
    half4 c = tex2D(_MainTex, IN.uv_MainTex);
    
    //c += ddx(c)*2 + ddy(c)*2;这行代码开启和关闭的效果
    
    o.Albedo = c.rgb;
    
    o.Alpha = c.a;
    
    }

      

      左边是直接显示图片,右边是在图片上面加上x和y的偏导数。

     【fwidth

      This function computes the following: abs(ddx(x)) + abs(ddy(x)).

      

    参考:

    1、https://blog.csdn.net/wylionheart/article/details/78026707

    2、http://www.aclockworkberry.com/shader-derivative-functions/#footnote_3_1104

  • 相关阅读:
    二叉搜索树第k个节点
    序列化二叉树
    atoi()和stoi()函数
    02.规划过程组表格-风险数据表
    02.规划过程组表格-风险概率和影响评估
    02.规划过程组表格-风险登记册
    02.规划过程组表格-风险管理计划
    02.规划过程组表格-沟通管理计划
    02.规划过程组表格-人力资源管理计划
    02.规划过程组表格-责任分配矩阵
  • 原文地址:https://www.cnblogs.com/tekkaman/p/9542449.html
Copyright © 2011-2022 走看看