【发布时间】:2012-02-22 03:46:41
【问题描述】:
我们的游戏使用“方块图集”,即对应游戏中方块特定面的方形纹理网格。我们的目标是通过将纹理数据存储在顶点中作为 shorts 而不是 float2s 来简化顶点数据内存。这是我们的顶点定义(XNA,C#):
public struct BlockVertex : IVertexType
{
public Vector3 Position;
public Vector3 Normal;
/// <summary>
/// The texture coordinate of this block in reference to the top left corner of an ID's square on the atlas
/// </summary>
public short TextureID;
public short DecalID;
// Describe the layout of this vertex structure.
public static readonly VertexDeclaration VertexDeclaration = new VertexDeclaration
(
new VertexElement(0, VertexElementFormat.Vector3,
VertexElementUsage.Position, 0),
new VertexElement(sizeof(float) * 3, VertexElementFormat.Vector3,
VertexElementUsage.Normal, 0),
new VertexElement(sizeof(float) * 6, VertexElementFormat.Short2,
VertexElementUsage.TextureCoordinate, 0)
);
public BlockVertex(Vector3 Position, Vector3 Normal, short TexID)
{
this.Position = Position;
this.Normal = Normal;
this.TextureID = TexID;
this.DecalID = TexID;
}
// Describe the size of this vertex structure.
public const int SizeInBytes = (sizeof(float) * 6) + (sizeof(short) * 2);
VertexDeclaration IVertexType.VertexDeclaration
{
get { return VertexDeclaration; }
}
}
我在 HLSL 方面几乎没有经验,但是当我尝试调整我们当前的着色器以使用这个顶点时(与将纹理和贴花存储为 Vector2 坐标的旧着色器相反),我得到的只是透明的蓝色模型,它我相信意味着面部的纹理坐标都相同?
这是我尝试解释顶点数据的 HLSL:
int AtlasWidth = 25;
int SquareSize = 32;
float TexturePercent = 0.04; //percent of the entire texture taken up by 1 pixel
[snipped]
struct VSInputTx
{
float4 Position : POSITION0;
float3 Normal : NORMAL0;
short2 BlockAndDecalID : TEXCOORD0;
};
struct VSOutputTx
{
float4 Position : POSITION0;
float3 Normal : TEXCOORD0;
float3 CameraView : TEXCOORD1;
short2 TexCoords : TEXCOORD2;
short2 DecalCoords : TEXCOORD3;
float FogAmt : TEXCOORD4;
};
[snipped]
VSOutputTx VSBasicTx( VSInputTx input )
{
VSOutputTx output;
float4 worldPosition = mul( input.Position, World );
float4 viewPosition = mul( worldPosition, View );
output.Position = mul( viewPosition, Projection );
output.Normal = mul( input.Normal, World );
output.CameraView = normalize( CameraPosition - worldPosition );
output.FogAmt = 1 - saturate((distance(worldPosition,CameraPosition)-FogBegin)/(FogEnd-FogBegin)); //This sets the fog amount (since it needs position data)
// Convert texture coordinates to short2 from blockID
// When they transfer to the pixel shader, they will be interpolated
// per pixel.
output.TexCoords = short2((short)(((input.BlockAndDecalID.x) % (AtlasWidth)) * TexturePercent), (short)(((input.BlockAndDecalID.x) / (AtlasWidth)) * TexturePercent));
output.DecalCoords = short2((short)(((input.BlockAndDecalID.y) % (AtlasWidth)) * TexturePercent), (short)(((input.BlockAndDecalID.y) / (AtlasWidth)) * TexturePercent));
return output;
}
我没有改变原始着色器的任何其他内容,它显示一切正常,但您可以看到整个 .fx 文件here。
如果我可以调试我可能能够得到它的东西,但是......好吧,无论如何,我认为这与我对着色器如何工作的知识有限有关。我想我尝试使用整数算术不太有效。此外,有很多演员表,如果值在某个地方被强制为 0,我可以相信它。万一我离题了,这就是我的目标:
- 着色器获取一个顶点,该顶点存储两个短裤以及其他数据。短裤表示正方形纹理网格的某个角的 ID。一个用于块面,另一个用于在该面上绘制的贴花。
- 着色器使用这些 ID 以及一些定义纹理网格(以下称为“Atlas”)大小的常量来确定该特定角的实际纹理坐标。
- 纹理坐标的 X 是 (ID % AtlasWidth) * TexturePercent,其中 TexturePercent 是一个常数,表示 1 个像素表示的整个纹理的百分比。
- 纹理坐标的 Y 是 (ID / AtlasWidth) * TexturePercent。
我该怎么办?
更新:我在某些时候遇到错误“vs_1_1 不支持 8 位或 16 位整数”这可能是问题的一部分吗?
【问题讨论】:
-
嘿A-Type,我不知道你是否知道,但你应该看看Game Development。您可能会在游戏开发上找到比 SO 上更多的资源。