发布网友 发布时间:2022-04-21 15:26
共4个回答
热心网友 时间:2023-09-18 11:33
#ifdef USING_DIRECTIONAL_LIGHT
fixed atten = 1.0;
#else
float3 lightCoord = mul(_LightMatrix0, float4(i.worldPos, 1)).xyz;
fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
#endif
_LightMatrix0:这个变量在书的P184页表格和官方文档中均有说明,它在内置的AutoLight.cginc文件中的特定宏下被定义,可以用于把点从世界空间变换到该光源的局部空间下。因此,上面代码第一句“mul(_LightMatrix0, float4(i.worldPos, 1)).xyz”就是把顶点坐标变换到光源空间下的坐标,这点在书中也有解释。
_LightTexture0:和_LightMatrix0类似的,也是在内置的AutoLight.cginc文件中的特定宏下被定义,紧跟_LightMatrix0的定义。它是一张包含了光源衰减信息的衰减纹理,我们可以用第一句代码得到的坐标进一步处理得到衰减纹理的采样坐标。由于Unity没有官方解释_LightMatrix0具体的数值范围含义,我们可以推测得到(推测方法可以是利用假彩色一节的方法来把这个变量当成颜色输出)_LightMatrix0得到的坐标模范围会是[0, 1],即与光源重合处是(0, 0, 0), 在光源范围的边界处模值为1。而 dot(lightCoord, lightCoord).rr一句,首先是由点积得到光源的距离平方,这是一个标量,我们对这个变量进行.rr操作相当于构建了一个二维矢量,这个二维矢量每个分量的值都是这个标量值,由此得到一个二维采样坐标。这个操作是shader中常见的swizzling操作,Cg的官网上也有说明。我们随后使用这个二维坐标对光照衰减纹理_LightTexture0进行采样,得到衰减值。关于_LightTexture0后面会系统讲。
这段代码不够规范:书上有说这一节的代码不能直接用到项目里,仅仅是用来阐述原理,但如果你想用这段代码直接发布项目的话,是需要修改的,因为当时写的时候不够规范。原因是这段代码的keyword判断条件有问题,导致_LightTexture0或_LightMatrix0可能并没有被定义。我们可以将原来的代码替换成下面的代码(新的代码也已经push到了github上):
#ifdef USING_DIRECTIONAL_LIGHT上面更加精确地判断了keyword条件,保证只在正确的时候执行访问衰减纹理的代码。_LightTexture0和_LightMatrix0只在某些条件下会被定义,例如在开启了POINT、SPOT、POINT_COOKIE、DIRECTIONAL_COOKIE等,具体我们可以在AutoLight.cginc里面找到。但因为原来的代码里没有进行严格判断,在发布的时候由于Unity会严格编译Unity Shader根据不同的keyword生成对应的shader program,此时它就会发现我们的错误了。
热心网友 时间:2023-09-18 11:34
dot出来的是一个向量,rr中的每一个r是rgba中的第一个元素,shader中就是所得向量的第一元素了(如果是二维向量的话就只有r和g有值了),rr的话就是相当于v.vertex.xx这样,获得一个由两个第一个元素组成的二维数热心网友 时间:2023-09-18 11:34
dot()的结果不是一个向量, 是一个数量, float a 和float1 a是基本等价的, 所以float也可以使用swizzle操作符热心网友 时间:2023-09-18 11:35
float2 uv = float2(dot(lightCoord, lightCoord), dot(lightCoord, lightCoord));