XDRender_LightMode_Anisotropic(1) 各项异性着色(1)

时间:2020-11-23 11:59:51   收藏:0   阅读:11

XDRender_LightMode_Anisotropic(1) 各项异性着色(1)

正文

@Author: 白袍小道

见笑各位大神

技术图片

理论基础关键点

首先梳理一下和各项异性相关的知识和基础, 这里特别注意切线空间以及切线和副切线, 法线扰动. 下面做个大概列举, 论文和网络都有很详细的说明. 这里就不再继续展开.

外部链接:

1、http://www.bluevoid.com/opengl/sig00/advanced00/notes/node159.html

2、切线空间:https://zhuanlan.zhihu.com/p/139593847

技术图片

各项异性

法线扰动

切线空间和切线

实现

1、世界空间的法线和切线、UV量可视化

这部分属于Utils部分,

a、需要查看计算好的切线,法线,

利用几何作色器部分,这里如果是Unity的话记得在Mac上使用OpenGLCoreAPI

大致代码

[maxvertexcount(9)]
void GS_Main(triangle v2g IN[3], inout LineStream<g2f> tristream) 
{
    g2f o;

    for (uint i = 0; i < 3; i++)
    {

        if(_ShowValue == 0 || _ShowValue==1)
        {
            //看法线
            o.vertex = UnityObjectToClipPos(IN[i].positionOS);
            o.baseUV = IN[i].baseUV;
            o.color = _NormalColor;
            tristream.Append(o);
            o.vertex = UnityObjectToClipPos(IN[i].positionOS+IN[i].normalOS*_LineLength);
            o.baseUV = IN[i].baseUV;
            o.color = _NormalColor;
            tristream.Append(o);
            tristream.RestartStrip();
        }
        if(_ShowValue == 0 || _ShowValue==2)
        {
            //看切线
            o.vertex = UnityObjectToClipPos(IN[i].positionOS);
            o.baseUV = IN[i].baseUV;
            o.color = _TangentColor;
            tristream.Append(o);
            o.vertex = UnityObjectToClipPos(IN[i].positionOS+IN[i].tangentOS*_LineLength);
            o.baseUV = IN[i].baseUV;
            o.color = _TangentColor;
            tristream.Append(o);
            tristream.RestartStrip();
        }
        if(_ShowValue == 0 || _ShowValue==3)
        {
            //看副切线
            o.vertex = UnityObjectToClipPos(IN[i].positionOS);
            o.baseUV = IN[i].baseUV;
            o.color = _BitangentColor;
            tristream.Append(o);
            o.vertex = UnityObjectToClipPos(IN[i].positionOS+IN[i].bitangentOS*_LineLength);
            o.baseUV = IN[i].baseUV;
            o.color = _BitangentColor;
            tristream.Append(o);
            tristream.RestartStrip();
        }
        if(_ShowValue == 0 || _ShowValue==4)
        {
            //看U
            o.vertex = UnityObjectToClipPos(IN[i].positionOS);
            o.baseUV = IN[i].baseUV;
            o.color = float4(1,1,1,1);
            tristream.Append(o);
            o.vertex = UnityObjectToClipPos(IN[i].positionOS+IN[i].normalOS*IN[i].baseUV.x*1.0);
            o.baseUV = IN[i].baseUV;
            o.color = float4(1,1,1,1);
            tristream.Append(o);
            tristream.RestartStrip();
        }
        if(_ShowValue == 0 || _ShowValue==5)
        {
            o.vertex = UnityObjectToClipPos(IN[i].positionOS);
            o.baseUV = IN[i].baseUV;
            o.color = float4(1,1,0,1);
            tristream.Append(o);
            o.vertex = UnityObjectToClipPos(IN[i].positionOS+IN[i].normalOS*IN[i].baseUV.y*1.0);
            o.baseUV = IN[i].baseUV;
            o.color = float4(1,1,0,1);
            tristream.Append(o);
            tristream.RestartStrip();
        }

    }
}

技术图片

这里看到原始的Tangent横了,下面我们看下UV.

技术图片

技术图片

2、计算所需要的切线

2.1 模型空间下的切线计算

2.2 世界空间下的切线(用来光照)

备注:这里也可以全部转到切线空间下进行计算

 real sign = tangentOS.w * GetOddNegativeScale();
    tbn.normalWS = TransformObjectToWorldNormal(normalOS);
    tbn.tangentWS = TransformObjectToWorldDir(tangentOS.xyz);
    tbn.bitangentWS = cross(tbn.normalWS, tbn.tangentWS) * sign;

这里的GetNegativeScale() 使用是否反转副法线的,分量为- 1,否则为1。(这个变量我们可以按照Unity或者自己来, 存放到一个Float4的W中)

这里切线直接使用副切线, (由于制作模型的)

//2.1 
float3 tangentWS = input.bitangentWS;

原因如下: 绿色是副切线,红色是切线

技术图片

技术图片

如果这里做一个Trik : 比如采样完计算好NormalWS,再求一次.

//float3 tangentWS = //cross(outSurfaceData.normalWS,input.tangentWS.xyz) * 0.7f;
//Cross src
//float3 tangentWS = //cross(input.normalWS,input.tangentWS.xyz) * 0.7f;

技术图片

3、法线扰动

float3 ShiftTangent(float3 T, float3 N, float shift)
            {
                float3 shiftedT = T + (shift * N);
                return normalize(shiftedT);
            }

4、计算光照

漫反射部分

(2)续

镜面反射部分

(2)续

传统公式, 注意一下dirAtten

:https://www.zhihu.com/question/36946353/answer/361767154

float StrandSpecular(float3 T, float3 V, float L, float exponent)
{
    float3 H = normalize(L + V);
    float dotTH = dot(T, H);
    float sinTH = sqrt(1.0 - dotTH*dotTH);
    float dirAtten = smoothstep(-1.0, 0.0, dot(T, H));

    return dirAtten * pow(sinTH, exponent);
}

参考文献

1、http://www.bluevoid.com/opengl/sig00/advanced00/notes/node159.html

2、https://github.com/mmikk/MikkTSpace/blob/master/mikktspace.c

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!