El punto flotante siempre ha sido problemático para la precisión en mundos grandes.
Este artículo explica detrás de escena y ofrece la alternativa obvia: números de punto fijo. Algunos hechos son realmente impresionantes, como:
"Bueno, 64 bits de precisión te llevan a la mayor distancia de Plutón desde el Sol (7,4 mil millones de km) con precisión submicrométrica".
Bueno, la precisión submicrométrica es más que cualquier necesidad de fps (para posiciones e incluso velocidades), y le permitiría construir mundos realmente grandes.
Mi pregunta es, ¿por qué todavía usamos coma flotante si el punto fijo tiene tales ventajas? La mayoría de las API de renderizado y las bibliotecas de física usan coma flotante (y sufren sus desventajas, por lo que los desarrolladores deben evitarlas).
¿Son mucho más lentos?
Además, ¿cómo crees que los motores planetarios escalables como outerra o infinity manejan a gran escala? ¿Utilizan puntos fijos para las posiciones o tienen algún algoritmo de división de espacio?
Respuestas:
Si me permites un complemento descarado, te daré un ejemplo de un juego real en el que estoy trabajando (enlace de video de YouTube).
El juego tiene un mundo infinito generado por procedimientos en un motor de física. Utiliza punto flotante de precisión simple. Después de unos pocos cientos de metros de espacio de juego, comienzan a surgir problemas de precisión (y empeoran progresivamente a medida que te alejas del origen).
¿Mi solución? Cada 200 m aproximadamente, muevo el mundo entero 200 m hacia el origen (si te interesa encontrar y probar uno de los prototipos en mi sitio y aparece la superposición de depuración [w] orld, puedes ver que esto sucede).
¿Por qué no usar punto fijo? ¿O doble precisión? En lugar de precisión simple? ¡Porque todo lo demás está usando un punto flotante de precisión simple!
El motor de física que estoy usando lo usa, XNA lo usa, los datos que se cargan en la tarjeta gráfica están formateados como punto flotante de precisión simple. Incluso el lenguaje en sí está diseñado para trabajar con números de punto flotante: escribir y (más importante) leer
0.5f
es mucho más fácil que0x80000000L
.Es simplemente una cuestión de lo que es más fácil en la práctica. Y el claro ganador es ser consciente de los problemas de precisión del punto flotante y escribir funciones bastante simples de "mover el mundo de regreso a cero" (o implementar la partición del espacio o lo que se adapte a su juego).
Y finalmente otro ejemplo: Orbiter es un juego (simulación, realmente) que realmente necesita preocuparse por la precisión. No solo en el espacio sino también en el tiempo (aceleración del tiempo más cuerpos en órbita, no quiero que se caigan del cielo, ahora). También utiliza números de coma flotante y emplea un truco para mantener la estabilidad.
fuente
Primero, sí, son significativamente más rápidos. Incluso si puede hacer que el punto fijo funcione tan rápido como una FPU "normal", el punto flotante real tiene instrucciones ventajosas como fsel para detener la ramificación o SIMD para trabajar en muchos flotadores a la vez. Las GPU también usan coma flotante, al menos en sus interfaces orientadas al usuario.
En segundo lugar, 64 bits también lo llevan bastante lejos en coma flotante: la mayoría de las personas todavía usan 32, pero la ventaja principal es que escala. Esa escala de punto fijo tiene una precisión fija. Ya sea que esté midiendo el sol a Plutón, o al otro lado de la calle, obtiene la misma precisión. El punto flotante le dará resultados mucho más precisos cuando todos los valores involucrados sean más pequeños. Dado que se espera que las bibliotecas de física genéricas funcionen, al menos de manera aceptable, con muchos juegos a diferentes escalas, y algunos juegos en sí pueden tener escalas muy diferentes, necesitan usar un tipo de número que funcione en muchas escalas.
fuente
Otro punto importante es que las carrozas no son tan imprecisas como parece pensar la gente de aquí. Un flotante de 32 bits tiene 24 bits de precisión entera completa. Esto significa que es al menos tan preciso como un valor de punto fijo de 24 bits para cualquier rango dado. Si bien los flotadores se vuelven menos precisos cuanto mayor sea el valor, un valor de punto fijo simplemente se desbordará y se ajustará en algún momento. Reducir la precisión es una mejor alternativa. Los flotadores también pueden desbordarse, pero mucho, mucho más tarde. Me gustaría ver tus caras cuando tu mundo de repente se envuelva a -2 ^ 31 debido al desbordamiento de punto fijo.
Los valores de coma flotante de 64 bits tienen una precisión entera de 53 bits, por lo que son realmente precisos.
fuente
En un contexto de FPS, los valores de punto fijo en realidad podrían ser un pasivo. El punto flotante cercano a cero es más preciso. Es solo a grandes distancias, el punto fijo se vuelve más preferible. La respuesta es simplemente que depende del contexto.
En algo así como una galaxia, puedes usar marcos de referencia. Use una escala enorme para los sistemas solares y luego use el centro del Sol (o un punto similar) como punto de origen para cualquier cosa dentro del sistema. Usando este sistema puedes tener tu pastel y comértelo, por así decirlo, y no es difícil de imaginar.
IIRC, el desarrollador de Infinity declaró que estaba continuamente iterando sobre problemas de escala en una de sus entrevistas.
fuente
Si aún no lo hiciste, definitivamente deberías consultar el tutorial de Planet Rendering en GameDev.net. En cuanto a la división espacial, una solución es mantener dos variables de posición separadas: una macroescala y una microescala. Esto funciona bastante bien (probado).
La solución exacta depende de cómo planea manejar distancias extremas en el motor: ¿planea puertas de salto o compresión de tiempo?
fuente
Una de las razones es que la aritmética de coma flotante es "suficientemente buena" (o al menos lo ha sido), produce resultados bastante precisos rápidamente.
Siempre y cuando conozca las limitaciones de la aritmética de coma flotante y cambie sus algoritmos para hacerles frente (ver la respuesta de Andrew Russell), producirá un código que "funciona".
fuente
Estoy escribiendo un juego En mi juego / programa, dibujo una nave espacial en el origen usando una cámara bastante fija y mi planeta dibujo con una cámara separada. Y estas dos cosas se encargan del problema para mí, pero mi planeta aún no está muy detallado. En cuanto a la solución que Andrew Russell mencionó sobre mover el mundo (y supongo que la cámara y sus habitantes volverán al origen), realmente no lo intentaría si alguna vez planea hacer del juego un juego en red. Si movió el mundo en la aplicación del servidor en función de los movimientos de cada cliente, el mundo terminaría luchando por un puesto. Y tomaría su posición todo el tiempo de todos los que juegan, lo que sería un gran problema.
fuente