c# - textura - materiales en autocad 2018
Al transformar texturas(dibujadas como objetos planos en 3D) para imitar la profundidad, las líneas negras aparecen aleatoriamente (5)
Estamos desarrollando un juego de rol descendente usando XNA. Recientemente nos topamos con un revés al escribir el código para mostrar nuestros mapas. Al dibujar el mapa, vista de arriba hacia abajo con una matriz de transformación normal, todo parece estar bien. Al usar una matriz de transformación no plana, como apretar la parte superior o inferior para imitar la profundidad, aparecen líneas negras (filas cuando arriba o abajo, columna cuando se aprieta izquierda o derecha) que se mueven cuando la cámara cambia de posición. El movimiento y la colocación parecen ser aleatorios. (Imagen proporcionada más abajo.)
Información de fondo
Los mapas consisten en fichas. La textura original tiene mosaicos que consisten en 32x32 píxeles. Dibujamos los mosaicos creando 2 triángulos y mostrando parte de la textura original en estos triángulos. Un sombreador hace esto por nosotros. Hay tres capas de triángulos. Primero dibujamos todos los mosaicos opacos y todos los píxeles opacos de todos los mosaicos semiopacos y parcialmente transparentes, luego todos los mosaicos y píxeles parcialmente semiopacos y parcialmente transparentes. Esto funciona bien (pero cuando hacemos zoom por un factor de punto flotante, algunas veces las líneas mezcladas por colores se encuentran entre las filas y / o columnas de los mosaicos).
Renderstates
Usamos el mismo rasterizerState para todas las teselas y cambiamos entre dos cuando dibujamos mosaicos sólidos o semitransparentes.
_rasterizerState = new RasterizerState();
_rasterizerState.CullMode = CullMode.CullCounterClockwiseFace;
_solidDepthState = new DepthStencilState();
_solidDepthState.DepthBufferEnable = true;
_solidDepthState.DepthBufferWriteEnable = true;
_alphaDepthState = new DepthStencilState();
_alphaDepthState.DepthBufferEnable = true;
_alphaDepthState.DepthBufferWriteEnable = false;
A la sombra, configuramos el SpriteBlendMode de la siguiente manera:
La primera capa sólida 1 usa
AlphaBlendEnable = False;
SrcBlend = One;
DestBlend = Zero;
Todas las otras capas sólidas y transparentes (dibujadas después) usan
AlphaBlendEnable = True;
SrcBlend = SrcAlpha;
DestBlend = InvSrcAlpha;
Otros sombreadores usan esto también. El SpriteBatch
para SpriteFonts
utilizado, usa la configuración predeterminada.
Textura generada
Algunas fichas se generan sobre la marcha y se guardan en un archivo. El archivo se carga cuando se carga el mapa. Esto se hace usando un RenderTarget
creado de la siguiente manera:
RenderTarget2D rt = new RenderTarget2D(sb.GraphicsDevice, 768, 1792, false,
SurfaceFormat.Color, DepthFormat.None);
sb.GraphicsDevice.SetRenderTarget(rt);
Cuando se genera, el archivo se guarda y se carga (para que no lo perdamos cuando el dispositivo se reinicia, porque ya no estará en un RenderTarget
). Intenté usar mipmapping, pero es una hoja de sprites. No hay información sobre dónde se colocan los mosaicos, por lo que mipmapping es inútil y no resolvió el problema.
Vértices
Recorrimos todas las posiciones. No hay puntos flotantes aquí todavía, pero la posición es un Vector3 (Float3).
for (UInt16 x = 0; x < _width; x++)
{
for (UInt16 y = 0; y < _heigth; y++)
{
[...]
position.z = priority; // this is a byte 0-5
Para colocar las fichas, se usa el siguiente código:
tilePosition.X = position.X;
tilePosition.Y = position.Y + position.Z;
tilePosition.Z = position.Z;
Como sabes, los flotadores son de 32 bits, con 24 bits para mayor precisión. El valor máximo de z de z es 8 bits (5 = 00000101). Los valores máximos para X e Y son 16 bits resp. 24 bits Supuse que nada podría salir mal en términos de puntos flotantes.
this.Position = tilePosition;
Cuando se establecen los vértices, lo hace de la siguiente manera (para que todos compartan la misma posición de mosaico)
Vector3[] offsets = new Vector3[] { Vector3.Zero, Vector3.Right,
Vector3.Right + (this.IsVertical ? Vector3.Forward : Vector3.Up),
(this.IsVertical ? Vector3.Forward : Vector3.Up) };
Vector2[] texOffset = new Vector2[] { Vector2.Zero, Vector2.UnitX,
Vector2.One, Vector2.UnitY };
for (int i = 0; i < 4; i++)
{
SetVertex(out arr[start + i]);
arr[start + i].vertexPosition = Position + offsets[i];
if (this.Tiles[0] != null)
arr[start + i].texturePos1 += texOffset[i] * this.Tiles[0].TextureWidth;
if (this.Tiles[1] != null)
arr[start + i].texturePos2 += texOffset[i] * this.Tiles[1].TextureWidth;
if (this.Tiles[2] != null)
arr[start + i].texturePos3 += texOffset[i] * this.Tiles[2].TextureWidth;
}
Shader
El sombreador puede dibujar mosaicos animados y estáticos. Ambos usan el siguiente estado de muestra:
sampler2D staticTilesSampler = sampler_state {
texture = <staticTiles> ; magfilter = POINT; minfilter = POINT;
mipfilter = POINT; AddressU = clamp; AddressV = clamp;};
El sombreador no establece ningún estado de muestra diferente, tampoco lo hacemos en nuestro código.
En cada pasada, recortamos el valor alfa (para que no obtengamos píxeles negros) usando la siguiente línea
clip(color.a - alpha)
Alpha es 1 para la capa sólida 1, y casi 0 para cualquier otra capa. Esto significa que si hay una fracción de alfa, se dibujará, a menos que esté en la capa inferior (porque no sabríamos qué hacer con ella).
Cámara
Utilizamos una cámara para imitar la búsqueda desde arriba hacia abajo en las teselas, haciendo que parezcan planas, usando el valor z para superponerlas mediante datos de estratificación externos (las 3 capas no siempre están en el orden correcto). Esto también funciona bien. La cámara actualiza la matriz de transformación. Si se pregunta por qué tiene una estructura tan extraña como esta. Add Change - el código es Double Buffered (esto también funciona). La matriz de transformación se forma de la siguiente manera:
// First get the position we will be looking at. Zoom is normally 32
Single x = (Single)Math.Round((newPosition.X + newShakeOffset.X) *
this.Zoom) / this.Zoom;
Single y = (Single)Math.Round((newPosition.Y + newShakeOffset.Y) *
this.Zoom) / this.Zoom;
// Translation
Matrix translation = Matrix.CreateTranslation(-x, -y, 0);
// Projection
Matrix obliqueProjection = new Matrix(1, 0, 0, 0,
0, 1, 1, 0,
0, -1, 0, 0,
0, 0, 0, 1);
Matrix taper = Matrix.Identity;
// Base it of center screen
Matrix orthographic = Matrix.CreateOrthographicOffCenter(
-_resolution.X / this.Zoom / 2,
_resolution.X / this.Zoom / 2,
_resolution.Y / this.Zoom / 2,
-_resolution.Y / this.Zoom / 2,
-10000, 10000);
// Shake rotation. This works fine
Matrix shakeRotation = Matrix.CreateRotationZ(
newShakeOffset.Z > 0.01 ? newShakeOffset.Z / 20 : 0);
// Projection is used in Draw/Render
this.AddChange(() => {
this.Projection = translation * obliqueProjection *
orthographic * taper * shakeRotation; });
Razonamiento y flujo
Hay 3 capas de datos de mosaico. Cada mosaico está definido por IsSemiTransparent
. Cuando un mosaico es IsSemiTransparent
, debe dibujarse después de algo que no sea IsSemiTransparent
. Los datos de SplattedTile
se apilan cuando se cargan en una instancia de SplattedTile
. Por lo tanto, incluso si la capa uno de los datos de mosaico está vacía, la capa uno de SplattedTile
tendrá datos de mosaico en la primera capa (dado que al menos una capa tiene datos de mosaico). La razón es que el Z-buffer
no sabe con qué mezclarse si se dibujan en orden, ya que puede que no haya píxeles sólidos detrás de él.
Las capas NO tienen un valor de az, tienen datos de teselas individuales. Cuando es una loseta de tierra, tiene Priority = 0
. Por lo tanto, las fichas con la misma Priority
se ordenan en la capa (orden de dibujo) y opacidad (semitransparente, después de opaco). Las fichas con diferente prioridad se dibujarán según su prioridad.
La primera capa sólida no tiene píxeles de destino, por lo que la configuré en DestinationBlend.Zero
. Tampoco necesita AlphaBlending
, ya que no hay nada con alfablending. Las otras capas (5, 2 sólido, 3 transparente) pueden dibujarse cuando ya hay datos de color y es necesario mezclarlos en consecuencia.
Antes de iterar a través de los 6 pasos, se establece la projection matrix
. Cuando no se utiliza la reducción, esto funciona. Cuando se utiliza un cono, no es así.
El problema
Queremos imitar un poco más de profundidad mediante la aplicación de la reducción, utilizando alguna matriz. Probamos varios valores pero este es un ejemplo:
new Matrix(1, 0, 0, 0,
0, 1, 0, 0.1f,
0, 0, 1, 0,
0, 0, 0, 1);
La pantalla (todo con un valor de altura 0, todo lo plano) se comprimirá. Cuanto menor sea la y (más alta en la pantalla), más se aprieta. Esto realmente funciona, pero ahora aparecen líneas negras al azar en casi todas partes. Parece excluir algunas fichas, pero no veo cuál es la correlación. Creemos que podría tener algo que ver con la interpolación o mipmaps.
Y aquí hay una imagen para mostrarte de lo que estoy hablando: .
Las fichas no afectadas parecen ser fichas estáticas NO en la capa inferior. Sin embargo, los mosaicos transparentes encima de esos muestran otros artefactos gráficos. Extrañan líneas (por lo que las filas solo se eliminan). Marqué este texto porque creo que es una pista de lo que está sucediendo. Las líneas verticales aparecen si coloco el mip mag and minfilter
en Linear
.
Aquí hay una imagen ampliada (en el zoom del juego), que muestra el artefacto en los mosaicos en la capa 2 o 3
Ya lo intentamos
-
mipfilter
enPoint
oLinear
- Configuración de
GenerateMipMaps
en las texturas originales - Estableciendo
GenerateMipMaps
en las texturas generadas (verdadero constructor deRenderTarget
deRenderTarget
) - Activando mipmapping (solo dio más artefactos cuando se alejó , porque estaba mipmapping una hoja de sprites .
- No dibujar la capa 2 y 3 (esto realmente hace que TODAS las fichas tengan líneas negras)
-
DepthBufferEnable = false
- Configurando todas las capas sólidas a
SrcBlend = One;
DestBlend = Zero;
- Configurando todas las capas sólidas a
ScrBlend = SrcAlpha;
DestBlend = InvSrcAlpha;
- No dibujar capa transparente (las líneas aún están allí).
- Extracción de
clip(opacity)
en elshader
. Esto solo elimina algunas líneas. Estamos investigando esto más a fondo. - Buscando el mismo problema en msdn, stackoverflow y usando google (sin suerte).
¿Alguien reconoce este problema? Como nota final, llamamos al SpriteBatch
DESPUÉS de dibujar los mosaicos, y usamos otro Shader
para los avatares (no muestran problemas, porque tienen altura> 0). ¿Esto deshace nuestro sampler state
? O...?
Con lo que nos has dado, sería extremadamente desconfiado de tu código de capas. Esto realmente parece que la capa inferior a veces se asoma entre las capas que se supone que están arriba y las oculta, dependiendo del redondeo de punto flotante. Las rayas perpendiculares al ángulo de visión son un efecto muy común cuando tienes dos triángulos que se supone que son exactamente coplanares, pero por cualquier razón no tienen exactamente las mismas coordenadas de vértice (por ejemplo, uno es más grande que el otro). ¿Qué sucede si dibujas las varias capas una cantidad muy pequeña aparte una de la otra? Al igual, dibuja la capa sólida inferior en -0.00002, y la siguiente en -0.00001, y la capa superior en 0 exactamente (suponiendo que las tres estén siendo dibujadas en 0 ahora).
No sé específicamente acerca de XNA, pero el problema de la superposición es siempre un problema fundamental de utilizar el punto flotante para representar la geometría, y me sorprendería si XNA "mágicamente" lo evita por usted. No estoy seguro de por qué algunos de los azulejos están bien, pero la mayoría están atornillados. Probablemente esas fichas tuvieron suerte, o algo. Los problemas causados por el error de coma flotante a menudo actúan de forma muy extraña.
Si separar las capas un poco no ayuda, entonces está prácticamente reducido a la depuración basada en comentarios estándar; pruébalo sin sprites, sin fichas animadas, sin capa transparente, & c. Cuando deja de suceder, lo que acabas de comentar es romperlo: P
El problema está en tu sombreador SplattedTileShader.fx.
Las líneas negras aparecen debido a los píxeles desechados.
es difícil seguir el código del sombreador sin más información, pero el problema está ahí.
Creo que la forma en que se está haciendo una composición múltiple es demasiado complicada.
tal vez sea más fácil hacer un sombreador que admita multitextura en una sola pasada.
en su vértice puede pasar cuatro valores de peso para cada textura y hacer la mezcla usted mismo en el sombreador.
http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series4/Multitexturing.php
Mira la roca del fondo de la última imagen, tiene líneas de color arena que la atraviesan. Presumiblemente, estás dibujando la arena primero, luego la roca en la parte superior.
Esto me dice que no se trata de "trazar líneas negras" a través de las texturas, sino que partes de las texturas no se dibujan. Dado que ocurre cuando se estira verticalmente, esto casi seguramente significa que está creando una asignación de píxeles antiguos a píxeles nuevos, sin interpolar los valores entremedias en la nueva textura.
Por ejemplo, usando el mapeo (x,y) --> (x, 2y)
, los puntos se mapearán como (0,0) --> (0,0)
, (0,1) --> (0,2)
y (0,2) --> (0, 4)
. Tenga en cuenta que no hay puntos en el mapa de textura fuente en (0,1)
o (0,3)
. Esto provocaría que el fondo se filtre. Apuesto a que si lo cambias para estirar horizontalmente, verás líneas verticales.
Lo que tendría que hacer es mapear de la otra manera: dado cada píxel en la textura objetivo, encuentre su valor en la imagen fuente usando el inverso de la transformación anterior. Probablemente obtendrá valores fraccionarios de coordenadas de píxeles, por lo que querrá interpolar valores.
No estoy familiarizado en absoluto con XNA, pero probablemente haya una forma más conveniente de hacerlo que a mano.
No puedo entender por qué están apareciendo las líneas negras, pero puedo darte otra forma de renderizar el paisaje que podría hacer que se vea correcto (y, con un poco de suerte, darte un pequeño aumento de velocidad).
Sprites
Necesitarás un atlas de textura (también conocido como hoja de sprite) para que funcione. Podrías dividir tus alturas en múltiples atlas y usar texturas múltiples.
Buffer de Vertex
Lo que haría es rascar el SpriteBatch, siempre sabrás dónde estarán tus sprites: crea un VertexBuffer
al inicio (posiblemente uno por capa) y VertexBuffer
para dibujar las capas. Algo como esto ( este es un búfer 2D, simplemente ''se ve'' en 3D como el tuyo ):
La definición del vértice probablemente consistiría en:
- Posición (
Vector2
) - Textura coordinada (
Vector2
) - Color (
Vector4/Color
)
Cada vez que el paisaje necesita ser "ciclado" (más sobre esto más adelante), usted pasará por el mapa debajo de la cámara y actualizará las coordenadas de textura y / o color en VertexBuffer
. No actualice el búfer en cada fotograma. No enviaría las coordenadas de textura a la GPU en el rango [0, 1]
, sino [0, Number of Sprites]
- calcule [0, 1]
en su sombreador de vértices.
Importante: No comparta vértices (es decir, use un IndexBuffer
) porque los vértices que comparten más de dos caras deben permanecer distintos (tienen distintas coordenadas de textura): construya el búfer como si IndexBuffer
no existiera . Usar un IndexBuffer
es un desperdicio en este escenario, así que simplemente VertexBuffer
con un VertexBuffer
solo.
Representación
La matriz mundial que utilice correlacionará [0, 1]
con el tamaño de la pantalla más el tamaño de un mosaico (es decir, una escala simple x = Viewport.Width + 32
e y = Viewport.Height + 32
). Su matriz de proyección sería una matriz de identidad.
La matriz de vista es engañosa. Imagine que su mapa está mirando un bloque actual de las teselas (que es) en {0,0}
, lo que necesita hacer es calcular el desfase (en píxeles) desde donde mira la cámara. Entonces, esencialmente será una matriz de compensación con x = Camera.X - LeftTile.X * (Viewport.Width / NumTiles.X)
y similar para y
.
Las matrices son las únicas difíciles, una vez que las tienes configuradas es una simple llamada DrawUserPrimitives()
y listo.
Tenga en cuenta que esto solo trata con su paisaje, dibuje sus otros sprites como lo hace hoy.
Paisaje Ciclismo
Cuando cambia la posición de la cámara, básicamente debe determinar si está mirando un nuevo bloque de mosaicos y actualizar los VertexBuffer
adecuada (las coordenadas de textura y el color: deje la posición sola, sin necesidad de volver a calcularla).
Alternativamente
Otra opción es representar cada capa en un RenderTarget2D
y usar su transformación actual una vez contra toda la capa. Esto resolvería su problema o haría que la verdadera razón sea muy evidente.
Nota al margen: proporcionaría el código de muestra si no fuera 00h40 aquí, esta pregunta lo merece. Veré cuánto tiempo tengo mañana por la noche.
El problema tiene que ver con los tipos numéricos en HLSL.
Primero, limpiemos ese sombreador. Lo haré, porque así es como encontramos el problema real. Aquí hay un diff unificado para SplattedTileShader.fx antes de poner taperfix:
@@ -37,76 +37,31 @@
data.Position = mul(worldPosition, viewProjection);
-
return data;
}
-float4 PixelLayer1(VertexShaderOutput input, uniform float alpha) : COLOR0
+float4 PixelLayer(VertexShaderOutput input, uniform uint layer, uniform float alpha) : COLOR0
{
- if(input.TextureInfo[0] < 1)
+ if(input.TextureInfo[0] < layer)
discard;
- float4 color;
+ float4 color;
+ float2 coord;
+ if(layer == 1)
+ coord = input.TexCoord1;
+ else if(layer == 2)
+ coord = input.TexCoord2;
+ else if(layer == 3)
+ coord = input.TexCoord3;
- switch (input.TextureInfo[1])
+ switch (input.TextureInfo[layer])
{
case 0:
- color = tex2D(staticTilesSampler, input.TexCoord1);
+ color = tex2D(staticTilesSampler, coord);
break;
case 1:
- color = tex2D(autoTilesSampler, input.TexCoord1);
+ color = tex2D(autoTilesSampler, coord);
break;
case 2:
- color = tex2D(autoTilesSampler, input.TexCoord1 + float2(frame, 0) * animOffset) * (1 - frameBlend) + tex2D(autoTilesSampler, input.TexCoord1 + float2(nextframe, 0) * animOffset) * frameBlend;
- break;
- }
-
- clip(color.a - alpha);
-
- return color;
-}
-
-float4 PixelLayer2(VertexShaderOutput input, uniform float alpha) : COLOR0
-{
- if(input.TextureInfo[0] < 2)
- discard;
-
- float4 color;
-
- switch (input.TextureInfo[2])
- {
- case 0:
- color = tex2D(staticTilesSampler, input.TexCoord2);
- break;
- case 1:
- color = tex2D(autoTilesSampler, input.TexCoord2);
- break;
- case 2:
- color = tex2D(autoTilesSampler, input.TexCoord2 + float2(frame, 0) * animOffset) * (1 - frameBlend) + tex2D(autoTilesSampler, input.TexCoord2 + float2(nextframe, 0) * animOffset) * frameBlend;
- break;
- }
-
- clip(color.a - alpha);
-
- return color;
-}
-
-float4 PixelLayer3(VertexShaderOutput input, uniform float alpha) : COLOR0
-{
- if(input.TextureInfo[0] < 3)
- discard;
-
- float4 color;
-
- switch (input.TextureInfo[3])
- {
- case 0:
- color = tex2D(staticTilesSampler, input.TexCoord3);
- break;
- case 1:
- color = tex2D(autoTilesSampler, input.TexCoord3);
- //color = float4(0,1,0,1);
- break;
- case 2:
- color = tex2D(autoTilesSampler, input.TexCoord3 + float2(frame, 0) * animOffset) * (1 - frameBlend) + tex2D(autoTilesSampler, input.TexCoord3 + float2(nextframe, 0) * animOffset) * frameBlend;
+ color = tex2D(autoTilesSampler, coord + float2(frame, 0) * animOffset) * (1 - frameBlend) + tex2D(autoTilesSampler, coord + float2(nextframe, 0) * animOffset) * frameBlend;
break;
}
@@ -125,5 +80,5 @@
DestBlend = Zero;
VertexShader = compile vs_3_0 VertexShaderFunction();
- PixelShader = compile ps_3_0 PixelLayer1(1);
+ PixelShader = compile ps_3_0 PixelLayer(1,1);
}
@@ -134,5 +89,5 @@
DestBlend = InvSrcAlpha;
VertexShader = compile vs_3_0 VertexShaderFunction();
- PixelShader = compile ps_3_0 PixelLayer2(0.00001);
+ PixelShader = compile ps_3_0 PixelLayer(2,0.00001);
}
@@ -143,5 +98,5 @@
DestBlend = InvSrcAlpha;
VertexShader = compile vs_3_0 VertexShaderFunction();
- PixelShader = compile ps_3_0 PixelLayer3(0.00001);
+ PixelShader = compile ps_3_0 PixelLayer(3,0.00001);
}
}
@@ -155,5 +110,5 @@
DestBlend = InvSrcAlpha;
VertexShader = compile vs_3_0 VertexShaderFunction();
- PixelShader = compile ps_3_0 PixelLayer1(0.000001);
+ PixelShader = compile ps_3_0 PixelLayer(1,0.000001);
}
@@ -164,5 +119,5 @@
DestBlend = InvSrcAlpha;
VertexShader = compile vs_3_0 VertexShaderFunction();
- PixelShader = compile ps_3_0 PixelLayer2(0.000001);
+ PixelShader = compile ps_3_0 PixelLayer(2,0.000001);
}
@@ -173,5 +128,5 @@
DestBlend = InvSrcAlpha;
VertexShader = compile vs_3_0 VertexShaderFunction();
- PixelShader = compile ps_3_0 PixelLayer3(0.00001);
+ PixelShader = compile ps_3_0 PixelLayer(3,0.00001);
}
}
`
Como puede ver, hay una nueva variable de entrada llamada layer (type = uint). Y ahora hay una función PixelLayer en lugar de tres.
El siguiente es el diff unificado para SplattedTileVertex.cs
@@ -11,5 +11,5 @@
{
internal Vector3 vertexPosition;
- internal byte textures;
+ internal float textures;
/// <summary>
/// Texture 0 is static tiles
@@ -17,7 +17,7 @@
/// Texture 2 is animated autotiles
/// </summary>
- internal byte texture1;
- internal byte texture2;
- internal byte texture3;
+ internal float texture1;
+ internal float texture2;
+ internal float texture3;
internal Vector2 texturePos1;
internal Vector2 texturePos2;
@@ -27,8 +27,8 @@
(
new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0),
- new VertexElement(12, VertexElementFormat.Byte4, VertexElementUsage.PointSize, 0),
- new VertexElement(16, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0),
- new VertexElement(24, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 1),
- new VertexElement(32, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 2)
+ new VertexElement(12, VertexElementFormat.Vector4, VertexElementUsage.PointSize, 0),
+ new VertexElement(28, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0),
+ new VertexElement(36, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 1),
+ new VertexElement(44, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 2)
);
Sí, ¡cambiamos los tipos!
Y ahora los problemas salen a la luz. Parece que, debido a la forma en que se procesa la entrada, los flotantes nunca serán exactamente los mismos que el valor entero. El razonamiento detrás de esto va más allá de este hilo, pero tal vez debería hacer una wiki comunitaria en él.
Entonces, ¿qué estaba pasando?
Ok, entonces solíamos descartar los valores que no estaban en la capa (if input.TextureInfo[0] < layer -> discard)
. Inside input.TextInfo [layer] hay un float. Ahora comparamos ese flotador con nuestro valor de capa uint. Y aquí sucede la magia. Algunos píxeles serán simplemente una coincidencia exacta (o tal vez justo por encima del valor de esa capa) y eso estaría bien, en cuanto al código, si el tipo fuera un (u) int, pero no lo es.
Entonces, ¿cómo solucionarlo? Bueno, ve con eso a la mitad probablemente haya una regla. El código móvil representa un píxel en un mosaico, si está a medio camino de allí. Hacemos lo mismo con las capas.
Aquí está la solución (diff unificado) para SplattedTileShader.fx
@@ -42,28 +42,24 @@
float4 PixelLayer(VertexShaderOutput input, uniform uint layer, uniform float alpha) : COLOR0
{
- if(input.TextureInfo[0] < layer)
+ if(input.TextureInfo[0] < (float)layer - 0.5)
discard;
float4 color;
float2 coord;
- if(layer == 1)
+ if(layer < 1.5)
coord = input.TexCoord1;
- else if(layer == 2)
+ else if(layer < 2.5)
coord = input.TexCoord2;
- else if(layer == 3)
+ else
coord = input.TexCoord3;
- switch (input.TextureInfo[layer])
- {
- case 0:
- color = tex2D(staticTilesSampler, coord);
- break;
- case 1:
- color = tex2D(autoTilesSampler, coord);
- break;
- case 2:
- color = tex2D(autoTilesSampler, coord + float2(frame, 0) * animOffset) * (1 - frameBlend) + tex2D(autoTilesSampler, coord + float2(nextframe, 0) * animOffset) * frameBlend;
- break;
- }
+ float type = input.TextureInfo[layer];
+
+ if (type < 0.5)
+ color = tex2D(staticTilesSampler, coord);
+ else if (type < 1.5)
+ color = tex2D(autoTilesSampler, coord);
+ else
+ color = tex2D(autoTilesSampler, coord + float2(frame, 0) * animOffset) * (1 - frameBlend) + tex2D(autoTilesSampler, coord + float2(nextframe, 0) * animOffset) * frameBlend;
clip(color.a - alpha);
Ahora todos los tipos son correctos. El código funciona como debería y el problema está resuelto. No tenía nada que hacer con el código de discard(...)
, lo que inicialmente señalé.
Gracias a todos los que participaron en ayudarnos a resolver esto.