以前曾经有过这个问题的一两个问题,但是我再也找不到了,所以我走了。
使用BasicEffect渲染具有部分透明纹理的模型时,基本解决方案是按照距离相机的距离对所有内容进行排序,然后从后向前绘制它们以获得正确的图像。然而,当模型彼此交叉时,较近的一部分将落后于另一部分,并且透明度将呈现不完整。
示例:
两个相交的项目只有一个带纹理的矩形模型。 由于游戏最终将包含必须具有更多3维形状并且必须穿过其他物体的指示器,这对我来说是一个大问题,我找不到解决方案。
请帮助。谢谢,
zoliking
编辑:这是非常基本的,但为了完整起见,这里是绘图代码(减去不相关的绒毛):
private void sortDrawables()
{
float[] distances = new float[drawables.Length];
for (int i=0; i<drawables.Length; i++)
{
if (drawables[i] is Character)
{
distances[i] = Vector3.Distance(cameraPosition, ((Character) drawables[i]).marker.position);
}
else if (drawables[i] is FixObject)
{
distances[i] = Vector3.Distance(cameraPosition, ((FixObject) drawables[i]).marker.position);
}
else if (drawables[i] is PositionSpike)
{
distances[i] = Vector3.Distance(cameraPosition, ((PositionSpike) drawables[i]).position);
}
}
for (int i=0; i<drawables.Length; i++)
{
int largestIndex = i;
float largestDistance = -1f;
for (int j=i; j<drawables.Length; j++)
{
if (drawables[j] is Character)
{
if (Vector3.Distance(((Character) drawables[j]).marker.position, cameraPosition) > largestDistance)
{
largestDistance = Vector3.Distance(((Character) drawables[j]).marker.position, cameraPosition);
largestIndex = j;
}
}
else if (drawables[j] is FixObject)
{
if (Vector3.Distance(((FixObject) drawables[j]).marker.position, cameraPosition) > largestDistance)
{
largestDistance = Vector3.Distance(((FixObject) drawables[j]).marker.position, cameraPosition);
largestIndex = j;
}
}
}
float tempDistance = distances[i];
distances[i] = distances[largestIndex];
distances[largestIndex] = tempDistance;
Object tempCharacter = drawables[i];
drawables[i] = drawables[largestIndex];
drawables[largestIndex] = tempCharacter;
}
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
sb.GraphicsDevice.BlendState = BlendState.AlphaBlend;
foreach (ModelMesh mesh in board.Meshes)
{
foreach (BasicEffect be in mesh.Effects)
{
UniversalLighting.MatchEffect(be);
be.View = view;
be.Projection = projection;
be.World = Matrix.CreateTranslation(new Vector3(0, 0, 0));
}
mesh.Draw();
}
sortDrawables();
foreach (Object c in drawables)
{
if (c is Character)
{
((Character) c).Draw(projection, view, cameraPosition, animMatrix, sources);
}
else if (c is FixObject)
{
((FixObject) c).Draw(projection, view, cameraPosition, sources, Matrix.Identity);
}
else if (c is PositionSpike)
{
((PositionSpike) c).Draw(projection, view, orangePixel);
}
}
Character和FixObject类调用的绘图代码:
public void Draw(Matrix projection, Matrix view, Texture2D texture, Texture2D[] frontLights, Texture2D[] backLights, LightSource[] sources, GraphicsDevice gd, Vector3 cameraPosition, Matrix animMatrix, float rotation = 0f, Texture2D otherSide = null)
{
foreach (ModelMesh m in model.Meshes)
{
foreach (BasicEffect be in m.Effects)
{
UniversalLighting.MatchEffect(be);
be.TextureEnabled = true;
be.Texture = texture;
be.View = view;
be.Projection = projection;
be.World = Matrix.CreateScale(new Vector3(stretch.X*-1, stretch.Y*-1, 1)) *
Matrix.CreateRotationY(rotation) *
animMatrix *
Matrix.CreateTranslation(position - new Vector3(0, stretch.Y/-2*MODEL_SIZE, 0) + rotNormal * 0.0005f * orderify);
}
m.Draw();
}
if (otherSide != null)
{
foreach (ModelMesh m in model.Meshes)
{
foreach (BasicEffect be in m.Effects)
{
UniversalLighting.MatchEffect(be);
be.TextureEnabled = true;
be.Texture = otherSide;
be.View = view;
be.Projection = projection;
be.World = Matrix.CreateScale(new Vector3(stretch.X, stretch.Y*-1, 1)) *
Matrix.CreateRotationY(rotation + (float) Math.PI * 2) *
animMatrix *
Matrix.CreateTranslation(position - new Vector3(0, stretch.Y/-2*MODEL_SIZE, 0) + rotNormal * -0.0005f * orderify);
}
m.Draw();
}
}
}
编辑2:所以我刚刚发现了一篇文章,它解决了这个问题,因为它不能通过排序(duh)来解决,但必须有某种渲染技巧才能允许这样做。图形应用程序在编辑器窗口中实时渲染这样的情况,任何使用纹理平面模型的3D粒子效果都必须处理这个问题。
基本上所有需要做的就是检测冲突像素的位置(如必须在已经绘制透明度的对象后面绘制的东西),并且在重叠区域中执行较慢的基于光线的方法来确定像素颜色。如果内置任何内容,我会很乐意手动编写,但我不知道如何深入了解渲染细节。