C# 从栅格位置计算纹理坐标

C# 从栅格位置计算纹理坐标,c#,xna,shader,hlsl,C#,Xna,Shader,Hlsl,我们的游戏使用了一个“积木图集”,一个方格纹理,对应于游戏中积木的特定面。我们的目标是简化顶点数据存储,将纹理数据存储在顶点中,使其成为短裤而不是漂浮物。这是我们的顶点定义(XNA,C#): 我没有改变原始着色器的任何其他内容,该着色器显示所有内容,但您可以看到整个.fx文件 如果我能调试一下,我也许能得到它,但是。。。好吧,不管怎样,我认为这与我对着色器如何工作的有限知识有关。我想我尝试使用整数算术的效果不太好。而且,这是很多的转换,我可以相信如果值在那里的某个地方被强制为0。如果我偏离了目标

我们的游戏使用了一个“积木图集”,一个方格纹理,对应于游戏中积木的特定面。我们的目标是简化顶点数据存储,将纹理数据存储在顶点中,使其成为短裤而不是漂浮物。这是我们的顶点定义(XNA,C#):

我没有改变原始着色器的任何其他内容,该着色器显示所有内容,但您可以看到整个.fx文件

如果我能调试一下,我也许能得到它,但是。。。好吧,不管怎样,我认为这与我对着色器如何工作的有限知识有关。我想我尝试使用整数算术的效果不太好。而且,这是很多的转换,我可以相信如果值在那里的某个地方被强制为0。如果我偏离了目标,以下是我的目标:

  • 着色器获取一个顶点,该顶点存储两条短裤以及其他数据。短裤表示正方形纹理网格某个角的ID。一个用于块面,另一个用于在该面上绘制的贴花
  • 着色器使用这些ID以及一些定义纹理网格大小的常量(以下称为“图集”)来确定该特定角点的实际纹理坐标
  • 纹理坐标的X是(ID%AtlasWidth)*TexturePercent,其中TexturePercent是一个常数,表示由1个像素表示的整个纹理的百分比
  • 纹理坐标的Y是(ID/AtlasWidth)*纹理百分比
  • 我该怎么办

    更新:我在某个地方遇到一个错误“vs_1_1不支持8位或16位整数”,这可能是问题的一部分吗

    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));
    
    这两行包含以下部分:

    (input.blockanddecadId.x)/(AtlasWidth)

    (input.blockanddecadId.y)/(AtlasWidth)

    这两个都是整数除法。整数除法截断所有超过小数点的部分。我假设AtlasWidth始终大于每个坐标,因此这两个分区的结果都将始终为0。如果这个假设是不正确的,我假设你在某种程度上仍然想要十进制数据

    您可能需要浮点除法,即返回十进制结果的除法,因此您需要首先将至少一个(或两个)操作数强制转换为浮点,例如:

    ((float)input.blockanddecadId.x)/((float)AtlasWidth)


    编辑:我会用;它按最大短值(32767)缩放您的值,允许使用“类似十进制”的短值(换句话说,“0.5”=16383)。当然,如果您的目的只是将tex coord数据减半,您可以通过使用HalfVector2在仍然使用浮点的情况下实现这一点。如果您仍然坚持使用Short2,您可能必须像NormalizedShort2一样对其进行缩放,然后再将其作为坐标提交。

    好吧,在我尝试在其中一个着色器函数中创建一个short之后,遇到了一个编译器错误,该错误指出vs_1_1不支持8/16位整数(您之前为什么不告诉我??),我将函数更改为如下所示:

    float texX = ((float)((int)input.BlockAndDecalID.x % AtlasWidth) * (float)TexturePercent);
    float texY = ((float)((int)input.BlockAndDecalID.x / AtlasWidth) * (float)TexturePercent);
    output.TexCoords = float2(texX, texY);
    float decX = ((float)((int)input.BlockAndDecalID.y % AtlasWidth) * (float)TexturePercent);
    float decY = ((float)((int)input.BlockAndDecalID.y / AtlasWidth) * (float)TexturePercent);
    output.DecalCoords = float2(decX, decY);
    

    这似乎很管用。我不确定它是把东西改成整数还是前面的那个(浮动)。我想可能是浮标,这意味着斯科特肯定有什么发现。我的搭档以某种方式编写了这个着色器,以使用short2作为纹理坐标;我不知道他是怎么做到的。

    嘿,A型,我不知道你是否知道,但你应该去看看。你可以在那里找到更多的游戏开发资源,实际上,整数除法是你想要的结果。“x”和“y”是骗人的;这两个值都是描述网格上一个角的ID。网格是25平方宽。如果我的ID是58,那么ID/GridSize=2,这是Y值。。。在这一点上,我意识到我是一个该死的白痴。我为每个纹理方块的像素宽度定义了一个常量,但我从未使用过它!我的坐标是2,这很傻,应该是2*32。考虑到这一点,我将继续进行。谢谢你让我仔细思考。啊,是的,我想说的是,有些东西看起来有点遗漏:P我只是不完全知道你是如何设置的。这并没有解决我的问题,但我认为我现在走对了方向。好吧,在实验之后,我实际上把正方形的大小烘焙成了百分比。0.04=32/800(即1/25)。所以,这实际上没有什么帮助。不知怎的,一切都归零了。我必须仔细检查我的类型转换和运算符…好吧,再说一遍,shorts不能存储任何十进制信息。假设在上面的例子中,y值为2,然后乘以0.04,得到0.08。当你进行转换时,结果将是0。我不想在上面的线程中添加太多的评论,这就是为什么我将其添加到聊天中:)。但是我要解释的是,你可以让输出仍然是一个浮点,但是如果你愿意,输入可以是一个int。看来你就是这么做的。抱歉误解了这个问题,没问题。在进一步测试之后,我决定舍入错误会导致此方法出现问题,我不想修复,主要是将某些ID的角数减去1。刚刚恢复了最后一个小时的工作,哦,好吧,就这样。。。
    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));
    
    float texX = ((float)((int)input.BlockAndDecalID.x % AtlasWidth) * (float)TexturePercent);
    float texY = ((float)((int)input.BlockAndDecalID.x / AtlasWidth) * (float)TexturePercent);
    output.TexCoords = float2(texX, texY);
    float decX = ((float)((int)input.BlockAndDecalID.y % AtlasWidth) * (float)TexturePercent);
    float decY = ((float)((int)input.BlockAndDecalID.y / AtlasWidth) * (float)TexturePercent);
    output.DecalCoords = float2(decX, decY);