因此,由于256色模式已被弃用,并且在Direct3D模式下不再受支持,因此我有了一个想法,改为使用像素着色器来模拟所有可能颜色的NES调色板,以便淡出的对象以及不具有alpha通道的平滑淡出效果。(我知道对象在NES上并不能真正淡出,但是我的所有对象都会在纯黑色背景上淡入和淡出,这可以通过调换调色板来实现。此外,当您暂停时,屏幕也可以淡入和淡出。我知道通过调色板交换也可以实现,就像在《洛克人》游戏中所做的那样。)问题是,我几乎不了解HLSL着色器。
我该怎么做?
因此,由于256色模式已被弃用,并且在Direct3D模式下不再受支持,因此我有了一个想法,改为使用像素着色器来模拟所有可能颜色的NES调色板,以便淡出的对象以及不具有alpha通道的平滑淡出效果。(我知道对象在NES上并不能真正淡出,但是我的所有对象都会在纯黑色背景上淡入和淡出,这可以通过调换调色板来实现。此外,当您暂停时,屏幕也可以淡入和淡出。我知道通过调色板交换也可以实现,就像在《洛克人》游戏中所做的那样。)问题是,我几乎不了解HLSL着色器。
我该怎么做?
Answers:
在像素着色器中,您可以传入256x256 Texture2D,并且托盘颜色连续水平排列。然后,您的NES纹理将被转换为direct3D Texture2Ds,并且将像素转换为0-255的索引值。有一种纹理格式仅在D3D9中使用红色值。因此,纹理每个像素仅占用8位,但是进入着色器的数据将是0-1。
//像素着色器可能看起来像这样:
float4 mainPS() : COLOR0
{
float4 colorIndex = tex2D(MainTexture, uv);
float4 palletColor = tex2D(PalletTexture, float2(colorIndex.x, 0);
return palletColor;
}
编辑:一种更正确的方法是添加您需要在纹理中垂直对齐的所有混合托盘版本,并使用colorIndex的“ alpha”值引用它们:
float4 mainPS() : COLOR0
{
float4 colorIndex = tex2D(MainTexture, uv);
float4 palletColor = tex2D(PalletTexture, float2(colorIndex.x, colorIndex.a);
return palletColor;
}
第三种方法是通过用卡通色调遮盖Alpha颜色来伪造NES低淡变质量:
float4 mainPS() : COLOR0
{
float4 colorIndex = tex2D(MainTexture, uv);
float4 palletColor = tex2D(PalletTexture, float2(colorIndex.x, 0);
palletColor.a = floor(palletColor.a * fadeQuality) / fadeQuality;
//NOTE: If fadeQuality where to equal say '3' there would be only 3 levels of fade.
return palletColor;
}
如果您并不真正在意纹理内存的使用(以及疯狂地消耗大量纹理内存以实现复古外观的想法具有某种反常的吸引力),则可以构建256x256x256 3d纹理,将所有RGB组合映射到所选调色板。然后在您的着色器中,它最后只是一行代码:
return tex3d (paletteMap, color.rgb);
甚至不必完全达到256x256x256的水平-可能像64x64x64之类的东西就足够了-您甚至可以使用此方法即时更改调色板映射(但由于动态纹理更新较大,因此成本很高)。
(仅当您不关心使用着色器动态更改调色板时,我的解决方案均有效)
您可以使用任何类型的纹理,并且只需在着色器上进行简单的计算即可。窍门是您拥有比所需更多的颜色信息,因此您将摆脱掉不需要的信息。
8位彩色格式为RRGGGGGB。这将为您提供8种红色和绿色阴影以及4种蓝色阴影。
该解决方案适用于任何RGB(A)颜色格式的纹理。
float4 mainPS() : COLOR0
{
const float oneOver7 = 1.0 / 8.0;
const float oneOver3 = 1.0 / 3.0;
float4 color = tex2D(YourTexture, uvCoord);
float R = floor(color.r * 7.99) * oneOver7;
float G = floor(color.g * 7.99) * oneOver7;
float B = floor(color.b * 3.99) * oneOver3;
return float4(R, G, B, 1);
}
注意:我从头顶上写了那句话,但是我真的确定它会为您编译和使用
另一种可能性是使用实际上与8位图形相同的D3DFMT_R3G3B2纹理格式。将数据放入此纹理时,可以对每个字节使用简单的位操作。
tex[index] = (R & 8) << 5 + ((G & 8) << 2) + (B & 4);