像素化光照着色器
Pixelated lighting shader
我用我的像素化 iOS 应用程序编写了一个 GLSL 着色器,用于 Unity3D。它有 两个 个问题:
1) 影响并不总是与月亮有关,而且
2) 灯光看起来没有像素化。
我稍微解释一下。着色器用于在月亮位于前景物体后面时对前景物体产生照明效果。我有一个通常显示为全黑(如剪影)的精灵,但是当月亮物体离它足够近时,它会显示纹理的细节,如下所示:
实际的精灵(没有着色器)看起来像这样:
我这样做的原因是我可以有一个只有一个纹理的光照贴图。但是,它有两个问题:
1) 当我靠近屏幕边缘时,光效并没有完全跟随月亮。我不确定这是否与我对 TEXCOORD1 变量的错误使用有关。我制作了一个覆盖整个屏幕的精灵,这样您就可以看到它是如何不跟随月亮的。这是我的效果测试场景中的问题图片。有一个带有黑色条纹和 alpha 的全屏精灵,可以始终准确显示效果所在的位置。我想摆脱这种不同步,因为它使照明看起来不真实。
2) 造成的光照效果非常锐利 -- 我认为,如果每个像素单独点亮,效果会更好,如 SpriteLamp。我知道它与在着色器中舍入片段坐标有关,但由于我从来不知道我的着色器中变量的值是什么,所以我似乎无法让它正常工作。
我可以四舍五入并降低距离,但后来我得到了这个,它服从与月球的距离,但不服从原始精灵中的像素。有像素化,但如果你明白我的意思的话,我们最终会在应该只有一个像素的地方得到这条奇怪的曲线......
我正在寻找的更像是这样。看看原始纹理的各个像素是如何照亮的?
这是着色器本身的 link:http://pastebin.com/0zbqrP57。它主要是默认的 unity 精灵着色器,但在 SampleSpriteTexture 函数的末尾添加了一些代码。
这是一个统一包的 link,您可以使用它来查看正在运行的着色器。只需在播放场景时尝试移动月亮即可。
https://drive.google.com/open?id=0BxCQjUHiAAQWZGpPZ3R2SExTcXc
我的问题:您对如何解决这些问题或解决方案有什么建议吗?
改变
OUT.worldSpacePosition = mul(_Object2World, OUT.vertex);
对于
OUT.worldSpacePosition = mul(_Object2World, IN.vertex);
应该修复月球错位问题。
对于第二个问题,我想到了这个:
aS = floor(aS * 100) / 100;
bS = floor(bS * 100) / 100;
float dist = sqrt((aS * aS) + (bS * bS));
float percentClose = 1 - (dist / _LightStrength);
float rounded = floor(percentClose * 10) / 10;
if (color.r + color.g + color.b > 0) {
color.r = lerp(0, color.r, rounded);
color.g = lerp(0, color.g, rounded);
color.b = lerp(0, color.b, rounded);
}
我想你可以放弃 if 语句和 lerps 到:
aS = floor(aS * 100) / 100;
bS = floor(bS * 100) / 100;
float dist = sqrt((aS * aS) + (bS * bS));
float percentClose = 1 - (dist / _LightStrength);
float rounded = floor(percentClose * 10) / 10;
color.rgb *= rounded;
但在这种情况下,您应该在您的终端设备上测试它并检查它是否提高了性能。
我用我的像素化 iOS 应用程序编写了一个 GLSL 着色器,用于 Unity3D。它有 两个 个问题:
1) 影响并不总是与月亮有关,而且 2) 灯光看起来没有像素化。
我稍微解释一下。着色器用于在月亮位于前景物体后面时对前景物体产生照明效果。我有一个通常显示为全黑(如剪影)的精灵,但是当月亮物体离它足够近时,它会显示纹理的细节,如下所示:
实际的精灵(没有着色器)看起来像这样:
我这样做的原因是我可以有一个只有一个纹理的光照贴图。但是,它有两个问题:
1) 当我靠近屏幕边缘时,光效并没有完全跟随月亮。我不确定这是否与我对 TEXCOORD1 变量的错误使用有关。我制作了一个覆盖整个屏幕的精灵,这样您就可以看到它是如何不跟随月亮的。这是我的效果测试场景中的问题图片。有一个带有黑色条纹和 alpha 的全屏精灵,可以始终准确显示效果所在的位置。我想摆脱这种不同步,因为它使照明看起来不真实。
2) 造成的光照效果非常锐利 -- 我认为,如果每个像素单独点亮,效果会更好,如 SpriteLamp。我知道它与在着色器中舍入片段坐标有关,但由于我从来不知道我的着色器中变量的值是什么,所以我似乎无法让它正常工作。
我可以四舍五入并降低距离,但后来我得到了这个,它服从与月球的距离,但不服从原始精灵中的像素。有像素化,但如果你明白我的意思的话,我们最终会在应该只有一个像素的地方得到这条奇怪的曲线......
我正在寻找的更像是这样。看看原始纹理的各个像素是如何照亮的?
这是着色器本身的 link:http://pastebin.com/0zbqrP57。它主要是默认的 unity 精灵着色器,但在 SampleSpriteTexture 函数的末尾添加了一些代码。
这是一个统一包的 link,您可以使用它来查看正在运行的着色器。只需在播放场景时尝试移动月亮即可。
https://drive.google.com/open?id=0BxCQjUHiAAQWZGpPZ3R2SExTcXc
我的问题:您对如何解决这些问题或解决方案有什么建议吗?
改变
OUT.worldSpacePosition = mul(_Object2World, OUT.vertex);
对于
OUT.worldSpacePosition = mul(_Object2World, IN.vertex);
应该修复月球错位问题。
对于第二个问题,我想到了这个:
aS = floor(aS * 100) / 100;
bS = floor(bS * 100) / 100;
float dist = sqrt((aS * aS) + (bS * bS));
float percentClose = 1 - (dist / _LightStrength);
float rounded = floor(percentClose * 10) / 10;
if (color.r + color.g + color.b > 0) {
color.r = lerp(0, color.r, rounded);
color.g = lerp(0, color.g, rounded);
color.b = lerp(0, color.b, rounded);
}
我想你可以放弃 if 语句和 lerps 到:
aS = floor(aS * 100) / 100;
bS = floor(bS * 100) / 100;
float dist = sqrt((aS * aS) + (bS * bS));
float percentClose = 1 - (dist / _LightStrength);
float rounded = floor(percentClose * 10) / 10;
color.rgb *= rounded;
但在这种情况下,您应该在您的终端设备上测试它并检查它是否提高了性能。