<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Polygon Engine Blog</title>
        <link>https://polygonengine.com/es/blog</link>
        <description>Polygon Engine Blog</description>
        <lastBuildDate>Thu, 17 Sep 2026 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>es</language>
        <item>
            <title><![CDATA[Lo que he aprendido al desarrollar Polygon Engine]]></title>
            <link>https://polygonengine.com/es/blog/building-a-shippable-ps1-package</link>
            <guid>https://polygonengine.com/es/blog/building-a-shippable-ps1-package</guid>
            <pubDate>Thu, 17 Sep 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Un repaso del desarrollo del editor, la integración de sus sistemas y el flujo de trabajo para crear juegos de PlayStation.]]></description>
            <content:encoded><![CDATA[<p>Empecé Polygon Engine porque quería crear juegos de PlayStation con un flujo de trabajo que me resultara familiar como desarrollador de Unity. La estética de Windows 95 formaba parte de esa idea desde el principio: buscaba recuperar algo de la experiencia de trabajar con herramientas de aquella época, pero con las facilidades de un editor basado en escenas y componentes.</p>
<p>Después de varios meses de desarrollo, esa idea se ha convertido en un conjunto de herramientas para crear un proyecto, construir niveles, programar interacciones y exportar el juego a PS1. En los artículos anteriores fui repasando las partes de ese proceso. Para cerrar esta serie, quería reunir lo que aprendí al conectarlas y explicar cómo ha cambiado mi forma de trabajar en el engine.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="familiarity">Adaptar un flujo de trabajo conocido a PS1<a href="https://polygonengine.com/es/blog/building-a-shippable-ps1-package#familiarity" class="hash-link" aria-label="Enlace directo al Adaptar un flujo de trabajo conocido a PS1" title="Enlace directo al Adaptar un flujo de trabajo conocido a PS1" translate="no">​</a></h2>
<p>Hierarchy, Inspector, los componentes y Play Mode me dan una forma conocida de organizar el trabajo. Reducen la cantidad de conceptos nuevos que alguien necesita aprender antes de colocar su primer objeto o asignar un script.</p>
<p>Al mismo tiempo, el editor necesita mostrar las restricciones de PS1 durante la preparación del contenido. La memoria de texturas, el orden de dibujo, los formatos numéricos, el audio y la lectura del disco influyen en el resultado. Cuanto antes puedo revisar esos aspectos, más fácil es ajustar un recurso o una escena sin rehacer gran parte del proyecto.</p>
<p>Mantener la estética de Windows 95 también ha requerido decisiones prácticas. Los paneles y controles deben ser fáciles de reconocer, pero además necesitan texto legible y espacio suficiente para trabajar en una computadora actual. Me interesa conservar esa apariencia sin que dificulte las tareas habituales, como editar una propiedad o encontrar un recurso.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="integration">Conectar los sistemas del engine<a href="https://polygonengine.com/es/blog/building-a-shippable-ps1-package#integration" class="hash-link" aria-label="Enlace directo al Conectar los sistemas del engine" title="Enlace directo al Conectar los sistemas del engine" translate="no">​</a></h2>
<p>Durante el desarrollo fui agregando edición de escenas, importación de recursos, Lua, audio y herramientas de interfaz. Tener cada módulo por separado era un avance, pero después necesitaba comprobar que los datos y las interacciones se conservaran al pasar de uno a otro.</p>
<p>Por ejemplo, un botón de UI Canvas debe conservar su callback después de guardar y volver a abrir el proyecto. Un script necesita encontrar la misma API pública al ejecutarse en PS1, y una malla debe mantener su escala y las referencias a sus materiales durante la conversión. Las transiciones entre escenas reúnen todavía más trabajo, porque coordinan la entrada, la carga y el sonido.</p>
<p>Revisar esas conexiones también implica considerar cambios y errores habituales: renombrar un recurso, intentar guardar en una tarjeta llena o cargar una escena que no se incluyó en la compilación. En esos casos, los mensajes y las validaciones necesitan indicar qué ocurrió y dónde corregirlo. Eso es especialmente importante cuando alguien está aprendiendo a usar la herramienta.</p>
<p>Actualmente, Polygon Engine reúne creación de escenas, Level Builder, edición de UVs, importación de recursos, Lua Behaviours, UI Canvas, audio, mandos, guardado y empaquetado para PS1. También incluye animación esquelética con límites definidos, navegación y visibilidad mediante Rooms y Portals. Al documentar cada sistema, necesito explicar su alcance para que los usuarios sepan qué pueden construir con él y cómo prepararlo.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="examples">El tutorial y el ejemplo incluido<a href="https://polygonengine.com/es/blog/building-a-shippable-ps1-package#examples" class="hash-link" aria-label="Enlace directo al El tutorial y el ejemplo incluido" title="Enlace directo al El tutorial y el ejemplo incluido" translate="no">​</a></h2>
<p>El tutorial <a class="" href="https://polygonengine.com/es/docs/tutorials/two-room-relay/overview">Two-Room Relay</a> permite recorrer ese flujo desde un proyecto vacío. Propone una interacción en primera persona con dos habitaciones, una puerta, un trigger, un HUD, sonido y guardado. Su tamaño permite explicar cómo se configura cada parte y seguir la relación entre las acciones del jugador y los sistemas que las resuelven.</p>
<p>El <a class="" href="https://polygonengine.com/es/docs/getting-started/first-person-example">ejemplo incluido Polygon: Signal Station</a> permite explorar un proyecto que ya está armado. Su menú, área central y estaciones de demostración sirven para revisar cómo se organizan varias funciones en una misma escena o proyecto. Es otra forma de aprender: abrir un objeto, revisar sus componentes y seguir sus referencias.</p>
<p>Los dos proyectos me ayudan a revisar aspectos distintos del engine. El tutorial permite comprobar si los pasos para crear un juego se pueden explicar y repetir. El ejemplo permite explorar una combinación más amplia de herramientas. Cuando cambia un sistema, ambos ofrecen casos concretos para revisar cómo afecta al trabajo del usuario.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="exported-game">Probar el juego exportado<a href="https://polygonengine.com/es/blog/building-a-shippable-ps1-package#exported-game" class="hash-link" aria-label="Enlace directo al Probar el juego exportado" title="Enlace directo al Probar el juego exportado" translate="no">​</a></h2>
<p>Play Mode facilita probar cambios mientras se edita. Al exportar, también intervienen el entorno de ejecución de PS1, los datos convertidos y la organización del disco. Por eso las pruebas del proyecto necesitan continuar después de generar la compilación.</p>
<p>Generar el paquete confirma que terminó la compilación. Ejecutarlo en un emulador permite revisar el arranque y el comportamiento del juego, mientras que probarlo en una consola aporta información sobre el hardware y sus periféricos. Al describir el estado del proyecto, necesito indicar cuáles de esas pruebas se hicieron, porque cada una comprueba algo diferente.</p>
<p>Con el rendimiento ocurre algo similar. Los reportes de capacidad ayudan a detectar escenas que exceden los límites definidos, pero para conocer los cuadros por segundo hace falta ejecutar y medir el juego. El tamaño reducido del tutorial facilita revisar su comportamiento y localizar problemas; aun así, necesita esas mediciones.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="distribution">Preparar el editor para su distribución<a href="https://polygonengine.com/es/blog/building-a-shippable-ps1-package#distribution" class="hash-link" aria-label="Enlace directo al Preparar el editor para su distribución" title="Enlace directo al Preparar el editor para su distribución" translate="no">​</a></h2>
<p>Polygon Engine se distribuye como un editor instalable con un entorno de ejecución precompilado. El usuario no necesita el código interno del engine para trabajar en su juego, así que la instalación, los ejemplos, la configuración de herramientas externas y la documentación deben permitirle completar el proceso desde su propia computadora.</p>
<p>La configuración de arranque también forma parte de la documentación. El splash de Polygon Engine identifica la herramienta con la que se creó el juego, pero no otorga una licencia de Sony, sustituye el BIOS de un emulador ni permite por sí mismo ejecutar un disco homebrew en una consola comercial. La <a class="" href="https://polygonengine.com/es/docs/editor/boot-data-and-splash">guía de datos de arranque y splash</a> explica esa diferencia. Las exportaciones no contienen datos de arranque de Sony e incluyen los avisos del entorno de ejecución junto a la imagen de disco y dentro de ella; la <a class="" href="https://polygonengine.com/es/docs/getting-started/publishing-and-licenses">guía de publicación</a> explica qué debes conservar al compartir un juego.</p>
<p>Usar un SDK y herramientas de empaquetado existentes me ha permitido concentrar más trabajo en el editor y sus sistemas. Al preparar la distribución, también necesito mantener claras sus versiones, licencias, avisos y procedencia, además de explicar cómo se instalan las dependencias externas.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="next-iteration">Qué quiero mejorar después<a href="https://polygonengine.com/es/blog/building-a-shippable-ps1-package#next-iteration" class="hash-link" aria-label="Enlace directo al Qué quiero mejorar después" title="Enlace directo al Qué quiero mejorar después" translate="no">​</a></h2>
<p>Quiero dedicar las siguientes iteraciones a mejorar los diagnósticos, hacer más predecible el rendimiento y ampliar las pruebas con proyectos y configuraciones de destino distintas. Esas mejoras afectan directamente al proceso de crear y exportar un juego. También me ayudan a decidir qué herramientas nuevas hacen falta y cuáles necesitan ajustes antes de seguir creciendo.</p>
<p>El curso de Pikuma, las referencias de hardware y las herramientas existentes me dieron una base para empezar. Aplicar ese conocimiento en Polygon Engine me ha obligado a conectar temas que antes estudiaba por separado: memoria, gráficos, audio, scripts y diseño del editor. Esa parte del desarrollo sigue siendo de las que más disfruto.</p>
<p>La intención inicial sigue siendo la misma: hacer juegos de PlayStation en un entorno que resulte cómodo para alguien acostumbrado a Unity. Ahora puedo trabajar sobre un flujo completo y ver con más claridad qué necesita mejorar. Me gustaría que estos artículos también sirvan para compartir lo que he aprendido y facilitar que otras personas empiecen sus propios proyectos para PS1.</p>]]></content:encoded>
            <category>PS1</category>
            <category>Flujo de trabajo</category>
            <category>Ejecución</category>
            <category>Empaquetado</category>
        </item>
        <item>
            <title><![CDATA[Mandos y guardado en Memory Card]]></title>
            <link>https://polygonengine.com/es/blog/controller-polling-and-memory-cards</link>
            <guid>https://polygonengine.com/es/blog/controller-polling-and-memory-cards</guid>
            <pubDate>Tue, 11 Aug 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Los detalles de la entrada del mando, la interacción con menús y el guardado en Memory Card durante el desarrollo de Polygon Engine.]]></description>
            <content:encoded><![CDATA[<p>Al trabajar en las interacciones del juego, necesitaba que la entrada del mando funcionara de forma consistente en los scripts y la interfaz. También hacía falta guardar el progreso y recuperarlo en otra sesión. Son dos sistemas que se utilizan constantemente, pero que requieren considerar más situaciones que la configuración habitual de mi computadora de desarrollo.</p>
<p>Un jugador puede iniciar sin el mando conectado o usar uno con capacidades distintas. La Memory Card puede estar llena, faltar o contener datos dañados. Al integrar estos sistemas en Polygon Engine, tuve que tener en cuenta esos casos y ofrecer información suficiente para que cada juego pueda responder a ellos.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="button-transitions">Detectar cuándo se presiona y se suelta un botón<a href="https://polygonengine.com/es/blog/controller-polling-and-memory-cards#button-transitions" class="hash-link" aria-label="Enlace directo al Detectar cuándo se presiona y se suelta un botón" title="Enlace directo al Detectar cuándo se presiona y se suelta un botón" translate="no">​</a></h2>
<p>Para implementar la entrada, necesitaba distinguir entre mantener un botón presionado y presionarlo por primera vez. El primer caso se obtiene del estado actual; el segundo requiere compararlo con el estado anterior. Esa comparación debe dar el mismo resultado para todos los sistemas que consulten la entrada durante una actualización.</p>
<p>Por ejemplo, si un script consulta el botón de confirmar y después lo consulta la interfaz, ambos necesitan recibir información de la misma lectura del mando. Si cada consulta también avanza el estado anterior, el resultado puede cambiar según el orden en que se ejecuten los sistemas.</p>
<p>Por eso la lectura del dispositivo debe realizarse en un momento definido de la actualización, conservando el estado anterior para las comparaciones. Con esa información, los scripts pueden distinguir una pulsación, un botón mantenido y una liberación sin modificar la lectura que recibirán los demás.</p>
<p>La comunicación con el mando también tiene detalles que la API necesita resolver, como identificar el dispositivo e interpretar los bits activos en bajo, donde un cero indica que el botón está presionado. La <a href="https://psx-spx.consoledev.net/controllersandmemorycards/" target="_blank" rel="noopener noreferrer" class="">referencia de mandos y tarjetas de memoria</a> explica el protocolo. Entenderlo me permite ofrecer consultas sencillas desde Lua sin trasladar esos detalles a cada script.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="controller-capabilities">Mandos digitales y analógicos<a href="https://polygonengine.com/es/blog/controller-polling-and-memory-cards#controller-capabilities" class="hash-link" aria-label="Enlace directo al Mandos digitales y analógicos" title="Enlace directo al Mandos digitales y analógicos" translate="no">​</a></h2>
<p>Un mando digital y uno analógico no entregan la misma información. Además, conectar un gamepad a la computadora mediante el sistema operativo utiliza una vía distinta a la comunicación del mando con PS1. Para interpretar los valores correctamente, hay que conocer el tipo de dispositivo y el modo en que está funcionando.</p>
<p>En los sticks también hay que definir una zona muerta. Si es demasiado pequeña, un stick ligeramente fuera del centro puede mover al personaje o la cámara sin intención del jugador. Si es demasiado grande, cuesta realizar movimientos pequeños. Ajustarla y normalizar los valores facilita usar la entrada desde el juego.</p>
<p>El teclado facilita las pruebas rápidas en el editor, pero las interacciones con mando necesitan su propia revisión. Una tecla no reproduce el rango de un stick, y una prueba en computadora no comprueba la comunicación del mando con PS1. Por eso conviene probar la misma acción con los dispositivos y entornos a los que se destina el juego.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="input-ownership">Coordinar la entrada del juego y los menús<a href="https://polygonengine.com/es/blog/controller-polling-and-memory-cards#input-ownership" class="hash-link" aria-label="Enlace directo al Coordinar la entrada del juego y los menús" title="Enlace directo al Coordinar la entrada del juego y los menús" translate="no">​</a></h2>
<p>La consistencia de entrada no decide por sí sola quién debería reaccionar. Si un menú está abierto, la misma pulsación no debería confirmar por accidente una opción y activar una puerta detrás de él.</p>
<p>Para evitarlo, el juego necesita definir cuándo acepta movimiento, interacción o navegación del menú. El engine proporciona la entrada y los mecanismos de UI, mientras que los scripts coordinan su uso según el estado actual de la partida.</p>
<p>Un proyecto pequeño que combina movimiento, interacción e interfaz permite revisar esa coordinación. Al probarlos juntos, se puede detectar si una acción sigue llegando al personaje cuando debería atenderla el menú, algo que no aparece al probar únicamente un script de movimiento.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="save-result">Comprobar el resultado del guardado<a href="https://polygonengine.com/es/blog/controller-polling-and-memory-cards#save-result" class="hash-link" aria-label="Enlace directo al Comprobar el resultado del guardado" title="Enlace directo al Comprobar el resultado del guardado" translate="no">​</a></h2>
<p>Con el guardado, la primera distinción es entre actualizar los datos de la sesión y escribirlos en la tarjeta. En Polygon Engine, asignar un valor de PlayerPrefs modifica los datos en memoria. Guardarlos requiere una operación explícita y comprobar su resultado.</p>
<p>Esa diferencia también debe reflejarse en la interfaz. Abrir una puerta puede actualizar el progreso de la partida, pero el mensaje de guardado solo debería mostrarse cuando termine correctamente la escritura. Si aparece antes, el jugador podría cerrar el juego creyendo que ya se conservó su progreso.</p>
<p>Prefiero un flujo que conserve el progreso actual si falla la escritura, explique el problema de manera útil y permita reintentar. La carga también necesita comprobar su resultado antes de aplicar el estado guardado. De lo contrario, una lectura fallida puede convertirse en un problema aparentemente distinto, como mover al jugador al punto de control equivocado.</p>
<p>La <a class="" href="https://polygonengine.com/es/docs/scripting/savedata">guía de persistencia</a> describe las APIs. El principio detrás de ellas es sencillo: lo que comunica el juego debe corresponder con la operación que realmente terminó bien.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="compact-state">Elegir qué progreso guardar<a href="https://polygonengine.com/es/blog/controller-polling-and-memory-cards#compact-state" class="hash-link" aria-label="Enlace directo al Elegir qué progreso guardar" title="Enlace directo al Elegir qué progreso guardar" translate="no">​</a></h2>
<p>Una Memory Card estándar de PS1 tiene 128 KiB organizados en dieciséis bloques de 8 KiB, con uno reservado para estructuras del sistema. El almacenamiento actual de Polygon Engine utiliza un bloque del juego y un conjunto limitado de entradas. Dentro de ese espacio, necesito elegir los datos que permitan reconstruir el progreso al cargar la partida.</p>
<p>Para una interacción sencilla, puede bastar con guardar el identificador del punto de control y el estado de una puerta. Así se evita copiar todas las propiedades de cada objeto, muchas de las cuales ya se recuperan al cargar la escena. Además de ocupar menos espacio, esos datos resultan más fáciles de mantener cuando cambia el nivel.</p>
<p>También hay que cuidar la identidad del archivo de guardado para que dos proyectos no utilicen la misma por accidente. Los valores deben respetar la codificación y los límites de longitud, y cualquier cambio en su estructura requiere decidir cómo leer las partidas anteriores. El tamaño reducido del archivo no elimina esas necesidades.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="failure-testing">Probar tarjetas ausentes, llenas y dañadas<a href="https://polygonengine.com/es/blog/controller-polling-and-memory-cards#failure-testing" class="hash-link" aria-label="Enlace directo al Probar tarjetas ausentes, llenas y dañadas" title="Enlace directo al Probar tarjetas ausentes, llenas y dañadas" translate="no">​</a></h2>
<p>Save Data Simulator permite probar desde el editor qué ocurre cuando falta la tarjeta, está llena o tiene datos dañados. Me resulta útil para revisar el mensaje que recibirá el jugador, la posibilidad de reintentar y la conservación del progreso de la sesión mientras se resuelve el problema.</p>
<!-- -->
<figure class="figure_cZR6"><a href="https://polygonengine.com/es/img/docs/current/save-data-simulator.png" target="_blank" rel="noopener noreferrer" aria-label="Save Data Simulator con selector de simulación de fallas, límites de entradas y controles de persistencia. Abrir la captura a tamaño completo en una pestaña nueva."><img src="https://polygonengine.com/es/img/docs/current/save-data-simulator.png" alt="Save Data Simulator con selector de simulación de fallas, límites de entradas y controles de persistencia" width="1920" height="1080" loading="lazy"></a><figcaption><p>Save Data Simulator en la versión documentada del editor. Ilustra el flujo de pruebas de fallas, no una prueba con una tarjeta física.</p> <span>Abre la imagen para verla a tamaño completo.</span></figcaption></figure>
<p>Estas pruebas ayudan a revisar la respuesta del juego, pero la simulación no reproduce todos los fallos de una tarjeta física ni las interrupciones eléctricas. Para evaluar esos casos hacen falta pruebas adicionales en emulador y hardware. Cada entorno permite comprobar una parte del comportamiento.</p>
<p>Trabajar en la entrada y el guardado me ha llevado a prestar más atención a lo que ocurre entre una acción y su confirmación. Necesito que el juego responda una vez a cada pulsación cuando corresponde, que los menús no activen otras interacciones y que el mensaje de guardado coincida con el resultado. Son detalles que conviene probar como parte de la partida completa.</p>]]></content:encoded>
            <category>PS1</category>
            <category>Entrada</category>
            <category>Tarjeta de memoria</category>
            <category>Datos guardados</category>
        </item>
        <item>
            <title><![CDATA[Rendimiento en PS1: gráficos, animación y sonido]]></title>
            <link>https://polygonengine.com/es/blog/audio-lighting-and-runtime-budgets</link>
            <guid>https://polygonengine.com/es/blog/audio-lighting-and-runtime-budgets</guid>
            <pubDate>Wed, 15 Jul 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Cómo integrar gráficos, scripts, animación y audio en Polygon Engine me ayudó a entender el uso de memoria y tiempo de procesamiento en un juego de PS1.]]></description>
            <content:encoded><![CDATA[<p>Conforme fui integrando gráficos, scripts, colisiones, animación y audio en Polygon Engine, tuve que revisar el trabajo que realizan en conjunto. Contar los polígonos de una escena ayuda a entender parte de ese trabajo, pero deja fuera muchas operaciones necesarias para que el juego funcione.</p>
<p>Incluso una habitación pequeña puede tener scripts que se ejecutan constantemente, objetos animados, luces y varios sonidos activos. Además, algunas superficies pueden dibujarse unas sobre otras y ocupar gran parte de la pantalla. Para decidir qué conviene optimizar, necesitaba distinguir el costo de cada sistema y la forma en que se combinan.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="bytes-and-time">Tiempo por cuadro y uso de memoria<a href="https://polygonengine.com/es/blog/audio-lighting-and-runtime-budgets#bytes-and-time" class="hash-link" aria-label="Enlace directo al Tiempo por cuadro y uso de memoria" title="Enlace directo al Tiempo por cuadro y uso de memoria" translate="no">​</a></h2>
<p>Una de las primeras distinciones es entre ocupar memoria y consumir tiempo de procesamiento. Una escena puede respetar todos los límites de memoria y aun así tardar demasiado en actualizarse o dibujarse. La validación de capacidad permite revisar los datos almacenados; para conocer el rendimiento también hay que medir el trabajo de la CPU y la GPU.</p>
<p>A una frecuencia nominal de video de 60 Hz, el intervalo entre actualizaciones de pantalla es de aproximadamente 16.7 milisegundos; a 50 Hz, es de 20 milisegundos. El juego puede renderizar a una frecuencia menor. Por eso, al revisar una medición, distingo entre la frecuencia de video, el paso de simulación y los cuadros que el juego alcanza a completar.</p>
<p>También necesito saber si el tiempo medido corresponde a procesamiento o a una espera. Si mido una sección de código que incluye la sincronización gráfica, parte del resultado puede ser tiempo en que la CPU espera a la GPU. Atribuirlo todo a la lógica del juego me llevaría a optimizar el sistema equivocado. Para interpretar el dato, necesito conocer dónde comienza y termina la medición.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pixel-coverage">Sobredibujado y visibilidad<a href="https://polygonengine.com/es/blog/audio-lighting-and-runtime-budgets#pixel-coverage" class="hash-link" aria-label="Enlace directo al Sobredibujado y visibilidad" title="Enlace directo al Sobredibujado y visibilidad" translate="no">​</a></h2>
<p>Dos escenas con la misma cantidad de triángulos pueden exigir un trabajo muy distinto a la GPU. Unos objetos pequeños a lo lejos cubren pocos píxeles. En cambio, varias superficies grandes superpuestas obligan a dibujar repetidamente la misma zona de la pantalla, aunque el número de triángulos sea igual.</p>
<p>Dibujar repetidamente píxeles que después quedarán cubiertos produce sobredibujado. La transparencia y ciertas distribuciones de superficies pueden dificultar evitarlo. Reducir los triángulos enviados solo ayuda si esos triángulos representaban una parte significativa del cuello de botella.</p>
<p>Las herramientas de visibilidad ayudan a reducir ese trabajo. Rooms y Portals permiten limitar qué partes del nivel se envían a dibujar según el espacio desde el que se observa. Para que funcionen bien, las conexiones entre habitaciones deben estar configuradas correctamente. Su función es controlar la visibilidad; no cargan ni descargan automáticamente el mundo por streaming.</p>
<p>Al ajustar un portal, necesito comprobar que siga mostrando todo lo que el jugador puede ver. Si restringe demasiado la visibilidad, aparecerán huecos o desaparecerán objetos; si permite demasiado, la reducción de trabajo será pequeña. Las herramientas de inspección son útiles para encontrar ese equilibrio sin introducir errores en la imagen.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="lighting-work">El costo de la iluminación<a href="https://polygonengine.com/es/blog/audio-lighting-and-runtime-budgets#lighting-work" class="hash-link" aria-label="Enlace directo al El costo de la iluminación" title="Enlace directo al El costo de la iluminación" translate="no">​</a></h2>
<p>Con la iluminación también tuve que relacionar los controles del editor con los cálculos disponibles en PS1. El trabajo se apoya en iluminación por vértice y colores preparados, con resultados y costos distintos a los de los shaders por píxel y mapas de sombras habituales en engines modernos.</p>
<p>El GTE ofrece operaciones útiles para iluminación, pero el engine todavía decide qué superficies se ven afectadas, prepara los datos de entrada y maneja sus tipos de luz compatibles. Más luces y más vértices afectados pueden significar más trabajo antes de empezar a dibujar.</p>
<p>En un pasillo con lámparas fijas, por ejemplo, algunos colores pueden prepararse de antemano para sugerir la iluminación. Una luz que cambia o se mueve durante la partida sí necesita actualizarse. Separar esos casos permite reservar los cálculos durante la ejecución para los cambios que realmente se verán en el juego.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="animation-work">Datos de animación y deformación<a href="https://polygonengine.com/es/blog/audio-lighting-and-runtime-budgets#animation-work" class="hash-link" aria-label="Enlace directo al Datos de animación y deformación" title="Enlace directo al Datos de animación y deformación" translate="no">​</a></h2>
<p>Un clip de animación necesita poses almacenadas u otros datos, y el entorno de ejecución necesita evaluar la pose actual. Después, deformar la malla agrega trabajo que un objeto estático no requiere.</p>
<p>El sistema de animación esquelética de Polygon Engine usa hard skinning: una influencia de hueso por vértice. Esto limita el trabajo de deformación, pero también influye en cómo se prepara el modelo. Funciona bien para articulaciones rígidas; una zona que necesita deformarse suavemente, como un hombro, requiere más cuidado porque no dispone de pesos mezclados entre varios huesos.</p>
<p>Al revisar una animación, necesito considerar la cantidad de huesos, la duración del clip, la frecuencia de muestreo y los vértices animados visibles. Reducir los triángulos de la malla puede ayudar al renderizado, pero no reduce por sí solo los datos del clip. La <a class="" href="https://polygonengine.com/es/docs/assets/skeletal-animation">guía de animación esquelética</a> explica el proceso de importación y sus restricciones.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="sound-work">Memoria de sonido y voces de reproducción<a href="https://polygonengine.com/es/blog/audio-lighting-and-runtime-budgets#sound-work" class="hash-link" aria-label="Enlace directo al Memoria de sonido y voces de reproducción" title="Enlace directo al Memoria de sonido y voces de reproducción" translate="no">​</a></h2>
<p>La SPU dispone de 24 voces ADPCM y 512 KiB de memoria de sonido. Las voces permiten reproducir muestras de audio, mientras que la memoria limita cuántas pueden mantenerse cargadas y cuánto espacio queda para la reverberación. La <a href="https://psx-spx.consoledev.net/soundprocessingunitspu/" target="_blank" rel="noopener noreferrer" class="">referencia de la SPU</a> explica cómo se utilizan ambos recursos.</p>
<p>Una misma muestra corta puede reproducirse simultáneamente en varias voces. También puede haber muchas muestras cargadas aunque solo suenen unas cuantas. Por eso necesito revisar tanto la memoria ocupada como la cantidad de reproducciones simultáneas; contar archivos de audio no alcanza para evaluar esos límites.</p>
<p>La función de cada sonido también influye en su preparación. El efecto de una puerta necesita responder rápidamente, mientras que una pista larga de fondo requiere planear su almacenamiento y reproducción continua. Desde los scripts, conviene activar cada efecto cuando sucede el evento: pedirlo en cada cuadro puede ocupar varias voces y repetir el sonido de forma accidental.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="measurement">Comparar mediciones de rendimiento<a href="https://polygonengine.com/es/blog/audio-lighting-and-runtime-budgets#measurement" class="hash-link" aria-label="Enlace directo al Comparar mediciones de rendimiento" title="Enlace directo al Comparar mediciones de rendimiento" translate="no">​</a></h2>
<p>Para comparar resultados, procuro mantener la misma cámara, la misma interacción y los mismos ajustes de ejecución. Después puedo variar un aspecto concreto: reducir las luces que afectan a una superficie, limitar el área visible, espaciar una operación de scripting o simplificar una animación. Así puedo relacionar el cambio con la medición.</p>
<p>Estas comparaciones también dependen de dónde se ejecuta el juego. El editor permite revisar la escena durante el trabajo, el emulador permite probar la compilación de PS1 y la consola permite medir su comportamiento en hardware real. El rendimiento de la computadora y los reportes de capacidad aportan información útil, pero necesito mediciones en el destino para evaluar cómo corre ahí.</p>
<p>Por eso me interesa que las herramientas del engine muestren tanto el uso de recursos como los tiempos de ejecución. Al relacionar ambos datos, puedo decidir si conviene cambiar un recurso, ajustar una escena o revisar un sistema. Integrar todos estos módulos me ha ayudado a mirar el rendimiento de esa forma, con cambios concretos cuyo efecto pueda comprobar.</p>]]></content:encoded>
            <category>PS1</category>
            <category>Optimización</category>
            <category>Audio</category>
            <category>Iluminación</category>
        </item>
        <item>
            <title><![CDATA[Integrar Lua para programar la lógica del juego]]></title>
            <link>https://polygonengine.com/es/blog/lua-gameplay-save-data-and-ui</link>
            <guid>https://polygonengine.com/es/blog/lua-gameplay-save-data-and-ui</guid>
            <pubDate>Tue, 09 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Las decisiones detrás de Lua Behaviours, las APIs nativas, los límites de memoria y la preparación de bytecode en Polygon Engine.]]></description>
            <content:encoded><![CDATA[<p>Quería que los usuarios pudieran programar el comportamiento de sus juegos sin modificar ni recompilar el código del engine. Una puerta, por ejemplo, necesita reaccionar a la entrada, recordar su estado, reproducir un sonido y actualizar un mensaje. Lua me permitía ofrecer una forma de conectar esas acciones desde el proyecto.</p>
<p>Al integrarlo, tuve que decidir qué trabajo quedaría en los scripts y qué sistemas seguirían implementados en código nativo. La facilidad para probar una idea era importante, pero también necesitaba controlar el uso de memoria y el tiempo de ejecución en PS1. Esa división define buena parte de la API de Polygon Engine.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="gameplay-intent">Repartir el trabajo entre scripts y sistemas nativos<a href="https://polygonengine.com/es/blog/lua-gameplay-save-data-and-ui#gameplay-intent" class="hash-link" aria-label="Enlace directo al Repartir el trabajo entre scripts y sistemas nativos" title="Enlace directo al Repartir el trabajo entre scripts y sistemas nativos" translate="no">​</a></h2>
<p>Para una puerta, el script puede decidir si el jugador tiene permiso de abrirla, elegir su siguiente estado, solicitar movimiento y actualizar la interfaz. Esas decisiones están muy relacionadas con las reglas de ese juego en particular.</p>
<p>Los cálculos que se repiten sobre muchos datos, como transformar vértices o consultar geometría de colisión, conviene resolverlos en sistemas nativos con estructuras preparadas para ese trabajo. La API permite utilizarlos desde Lua. Así, el script puede solicitar una acción sin implementar de nuevo los cálculos que ya realiza el engine.</p>
<p>Aun así, una llamada nativa puede requerir bastante trabajo. Si una función realiza una búsqueda amplia y el script la invoca en cada actualización, su costo se acumula. Por eso, al revisar un comportamiento, necesito considerar tanto la frecuencia de las llamadas como lo que hace cada función.</p>
<p>El <a href="https://www.lua.org/manual/5.4/manual.html" target="_blank" rel="noopener noreferrer" class="">manual de Lua</a> explica el modelo de integración del lenguaje. Polygon Engine proporciona la API del juego y decide qué capacidades están disponibles en ese entorno. Un script escrito para otra aplicación con Lua no tiene automáticamente las mismas librerías ni funciones del engine aquí.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="lifecycle">El ciclo de vida de los scripts<a href="https://polygonengine.com/es/blog/lua-gameplay-save-data-and-ui#lifecycle" class="hash-link" aria-label="Enlace directo al El ciclo de vida de los scripts" title="Enlace directo al El ciclo de vida de los scripts" translate="no">​</a></h2>
<p>Para organizar los comportamientos utilicé callbacks que resultan familiares si se viene de Unity. <code>Awake</code> se encarga de la preparación inicial, <code>Start</code> se ejecuta antes de la primera actualización y <code>Update</code> se utiliza para el comportamiento de cada cuadro. <code>FixedUpdate</code> trabaja con el paso de simulación acotado de 30 Hz del engine.</p>
<p>Ese paso fijo define cómo avanza la simulación, pero no garantiza que el juego dibuje treinta cuadros por segundo con cualquier carga. Si la máquina se retrasa, intentar recuperar todas las actualizaciones pendientes puede empeorar el problema. Por eso el engine limita la cantidad de trabajo de recuperación.</p>
<p>También busco que los scripts actualicen cada sistema cuando hace falta. Al abrir una puerta, su sonido debería activarse una vez; una etiqueta solo necesita cambiar cuando cambia el mensaje. Repetir esas operaciones en cada cuadro consume recursos y puede producir errores de audio o interfaz difíciles de relacionar con el script que los provoca.</p>
<p>La <a class="" href="https://polygonengine.com/es/docs/scripting/overview">introducción a scripting</a> documenta los callbacks y las propiedades expuestas. Esa estructura me permite separar la inicialización de las actualizaciones y de los eventos de interacción. Al volver a un script, resulta más fácil encontrar dónde se configura el estado inicial y qué funciones lo modifican durante el juego.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="allocation-life">Controlar el uso de memoria y la ejecución<a href="https://polygonengine.com/es/blog/lua-gameplay-save-data-and-ui#allocation-life" class="hash-link" aria-label="Enlace directo al Controlar el uso de memoria y la ejecución" title="Enlace directo al Controlar el uso de memoria y la ejecución" translate="no">​</a></h2>
<p>El manejo de memoria también necesita atención. Cada tabla temporal requiere espacio y después debe ser liberada por el recolector de Lua. Si un script reconstruye tablas o genera cadenas de diagnóstico en cada actualización, esas asignaciones se repiten durante toda la partida y pueden afectar al rendimiento.</p>
<p>Cuando un comportamiento lo permite, prefiero preparar sus datos al inicializarlo y reutilizarlos durante el juego. Algunas funciones necesitan crear valores nuevos, así que la intención no es prohibir las asignaciones. Lo que reviso es si ese trabajo realmente necesita repetirse con tanta frecuencia.</p>
<p>Polygon Engine establece un límite para la memoria dinámica de Lua. Si un script lo alcanza, el error debe ayudar a localizar el comportamiento que está consumiendo demasiado. Además de contener el problema, necesito que la información permita corregirlo desde el proyecto.</p>
<p>El engine también limita las instrucciones para contener ciclos de Lua que no terminan o ejecuciones excesivas. Esa protección no sustituye la medición de rendimiento: el número de instrucciones no representa directamente el tiempo transcurrido, y las llamadas nativas pueden realizar trabajo adicional. Son dos aspectos que hay que revisar por separado.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="bytecode">Preparar el bytecode de Lua para PS1<a href="https://polygonengine.com/es/blog/lua-gameplay-save-data-and-ui#bytecode" class="hash-link" aria-label="Enlace directo al Preparar el bytecode de Lua para PS1" title="Enlace directo al Preparar el bytecode de Lua para PS1" translate="no">​</a></h2>
<p>Durante la compilación del juego se prepara el bytecode de Lua que utilizará PS1. Esto evita compilar el código fuente en la consola y permite que la versión de distribución prescinda del analizador completo. El resultado sigue ejecutándose en la máquina virtual de Lua; no se convierte en instrucciones MIPS nativas.</p>
<p>Para que funcione, el bytecode debe generarse con la versión de Lua y la configuración numérica que espera el entorno de ejecución. Un archivo compilado con una instalación cualquiera de Lua en la computadora podría no ser compatible. Por eso la preparación del bytecode forma parte del proceso de compilación del engine.</p>
<p>La configuración numérica también influye en el rendimiento. La CPU de PS1 no tiene una unidad de punto flotante por hardware, aunque puede realizar esas operaciones mediante software. Son operaciones posibles, pero su costo importa cuando se repiten muchas veces. Los sistemas geométricos pueden utilizar punto fijo y gestionar las conversiones al recibir datos desde la API de scripting.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="door-test">Conectar los scripts con una interacción jugable<a href="https://polygonengine.com/es/blog/lua-gameplay-save-data-and-ui#door-test" class="hash-link" aria-label="Enlace directo al Conectar los scripts con una interacción jugable" title="Enlace directo al Conectar los scripts con una interacción jugable" translate="no">​</a></h2>
<p>El tutorial de dos habitaciones permite revisar esa integración en un caso pequeño. Conecta la entrada, un trigger, una puerta móvil, sonido, mensajes de interfaz y progreso guardado. Cada parte tiene una función concreta y se puede seguir el recorrido desde el evento del jugador hasta el cambio que aparece en pantalla.</p>
<p>Al revisar un script así, puedo identificar qué funciones de la API facilitan la interacción y dónde todavía hay trabajo innecesario. Si hace falta repetir mucho código para una operación habitual, conviene revisar qué debería resolver el engine. Si una llamada consume demasiado, necesito reducir su frecuencia o mejorar el sistema que la implementa.</p>
<p>Integrar Lua me permitió acercarme al flujo de trabajo que quería: cambiar las reglas de una interacción desde el proyecto y probarlas rápidamente. Para mantener esa comodidad en PS1, la API y los sistemas nativos necesitan resolver bien el trabajo repetitivo, mientras los scripts se concentran en el comportamiento de cada juego.</p>]]></content:encoded>
            <category>PS1</category>
            <category>Lua</category>
            <category>Programación</category>
            <category>Arquitectura</category>
        </item>
        <item>
            <title><![CDATA[Carga de escenas y música desde el CD-ROM]]></title>
            <link>https://polygonengine.com/es/blog/cd-rom-data-paths-and-xa-audio</link>
            <guid>https://polygonengine.com/es/blog/cd-rom-data-paths-and-xa-audio</guid>
            <pubDate>Tue, 12 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Los tiempos de acceso al disco, la lectura secuencial y la reproducción XA al implementar transiciones de escena en Polygon Engine.]]></description>
            <content:encoded><![CDATA[<p>Al trabajar en la carga de escenas de Polygon Engine, el CD-ROM fue una de las diferencias más claras respecto al desarrollo para una computadora actual. El disco ofrece mucho más espacio que la RAM de PS1, pero los datos tienen que leerse y prepararse antes de que el juego pueda utilizarlos. La velocidad de la unidad y la ubicación de los archivos influyen en ese tiempo.</p>
<p>Esto también afecta a las transiciones del juego. Antes de entrar a otra zona hay que decidir qué recursos estarán cargados, qué se mostrará durante la espera y qué ocurrirá con la música. Para implementar ese flujo necesitaba considerar juntas la carga de datos y la reproducción desde el disco.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="capacity-and-latency">Estimar los tiempos de carga del disco<a href="https://polygonengine.com/es/blog/cd-rom-data-paths-and-xa-audio#capacity-and-latency" class="hash-link" aria-label="Enlace directo al Estimar los tiempos de carga del disco" title="Enlace directo al Estimar los tiempos de carga del disco" translate="no">​</a></h2>
<p>Primero tuve que distinguir la capacidad del disco de su velocidad de lectura. La capacidad indica cuánto contenido se puede almacenar; la transferencia indica cuántos datos se leen por segundo en un modo determinado. A ese tiempo se agregan la búsqueda de los sectores y el procesamiento necesario para utilizar lo que se leyó.</p>
<p>Como referencia sencilla, leer 150 sectores por segundo con 2,048 bytes de datos de usuario por sector da 307,200 bytes por segundo, o 300 KiB/s. Es la velocidad nominal conocida de doble velocidad para esa carga útil. Excluye búsquedas, comandos y procesamiento, y otros formatos de sector distribuyen sus datos de otra manera.</p>
<p>Si un área necesita 600 KiB mediante ese recorrido, la transferencia por sí sola tiene un mínimo nominal de dos segundos antes de agregar los demás costos. Es un ejemplo para planear, no una medición de una escena específica de Polygon Engine. La <a href="https://psx-spx.consoledev.net/cdromdrive/" target="_blank" rel="noopener noreferrer" class="">referencia del CD-ROM</a> explica los modos y la estructura de sectores detrás del cálculo.</p>
<p>Con esa estimación ya se puede planear la transición. Una opción es mantener cargados los recursos que se utilizarán enseguida; otra, reducir los datos necesarios o mostrar una pantalla de carga. La elección depende del espacio disponible y de cómo estén organizadas las áreas del juego.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="sequential-reads">Agrupar recursos para leerlos de forma secuencial<a href="https://polygonengine.com/es/blog/cd-rom-data-paths-and-xa-audio#sequential-reads" class="hash-link" aria-label="Enlace directo al Agrupar recursos para leerlos de forma secuencial" title="Enlace directo al Agrupar recursos para leerlos de forma secuencial" translate="no">​</a></h2>
<p>Supongamos que una habitación necesita una malla, varias texturas, materiales, scripts y efectos de sonido. Cargar cada dependencia como un archivo independiente puede implicar cambiar repetidamente el lugar donde lee la unidad. Aunque el tamaño total sea modesto, el patrón de acceso puede agregar espera.</p>
<p>Agrupar recursos que se utilizarán juntos permite leerlos de manera secuencial y reducir los cambios de ubicación del lector. Esa es la razón de los paquetes de dependencias por escena de Polygon Engine: preparar en la compilación una distribución más conveniente para la carga.</p>
<p>Al organizar esos paquetes hay que decidir cómo manejar los recursos compartidos. Repetir uno en varias escenas puede simplificar la lectura, a cambio de ocupar más disco. Mantener una sola copia ahorra espacio, pero exige coordinar cuándo se carga y cuánto tiempo permanece en memoria. Un paquete más pequeño no necesariamente se carga más rápido.</p>
<p>La memoria agrega otra restricción. Leer un paquete grande en un búfer temporal no es automáticamente una buena idea si la escena final ya ocupa casi toda la RAM. El acceso secuencial y una memoria de trabajo acotada necesitan considerarse juntos.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="music-and-data">Coordinar la música XA con la carga de escenas<a href="https://polygonengine.com/es/blog/cd-rom-data-paths-and-xa-audio#music-and-data" class="hash-link" aria-label="Enlace directo al Coordinar la música XA con la carga de escenas" title="Enlace directo al Coordinar la música XA con la carga de escenas" translate="no">​</a></h2>
<p>La música larga necesita otro tratamiento porque mantener una grabación completa en la RAM de la SPU consumiría demasiado espacio. CD-XA permite reproducirla conforme llegan sus datos desde el disco. Los efectos cortos, en cambio, pueden permanecer cargados para responder de inmediato a una interacción.</p>
<p>La lectura de música y la carga de escenas utilizan la misma unidad. Si ambas necesitan datos, el engine tiene que coordinar el acceso. Algunas arquitecturas resuelven esto con sectores entrelazados y búferes organizados para alternar lecturas, pero ese comportamiento requiere una implementación específica.</p>
<p>En la implementación actual de Polygon Engine, la música XA se suspende durante la carga de datos de escena y, al reanudarse, empieza desde el principio. Es una limitación que hay que considerar al elegir las pistas y diseñar las transiciones. El reinicio será más evidente en una canción con una entrada reconocible que en un ambiente sonoro de inicio suave.</p>
<p>La <a class="" href="https://polygonengine.com/es/docs/assets/audio">guía de audio</a> describe cómo configurar este flujo. Al preparar un cambio de escena, se puede aprovechar una pausa, utilizar música distinta en el destino o acompañar la transición con un efecto residente. Lo importante es diseñarla teniendo en cuenta el comportamiento de reproducción que ofrece actualmente el engine.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="loading-presentation">Preparar la pantalla de carga<a href="https://polygonengine.com/es/blog/cd-rom-data-paths-and-xa-audio#loading-presentation" class="hash-link" aria-label="Enlace directo al Preparar la pantalla de carga" title="Enlace directo al Preparar la pantalla de carga" translate="no">​</a></h2>
<p>La pantalla de carga también necesita prepararse a tiempo. Si sus datos solo están disponibles después de cargar la escena de destino, no podrá mostrarse durante la espera. El sistema de transición debe tener lo necesario para dibujarla antes de iniciar la parte más lenta del proceso.</p>
<p>Eso implica disponer de la presentación de carga, mantener la imagen estable y cambiar a la escena nueva cuando esté lista. No hace falta una pantalla elaborada, pero sí que aparezca desde el inicio de la transición y no después de varios segundos sin información.</p>
<p>Además, hay que definir quién controla la cámara, el audio y la entrada en cada etapa. La escena anterior deja de estar activa, la transición muestra el progreso y la nueva escena toma el control al terminar. Coordinar esos cambios evita que el jugador siga moviéndose o interactuando mientras se reemplazan los datos del nivel.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="level-rhythm">Diseñar las transiciones considerando la carga<a href="https://polygonengine.com/es/blog/cd-rom-data-paths-and-xa-audio#level-rhythm" class="hash-link" aria-label="Enlace directo al Diseñar las transiciones considerando la carga" title="Enlace directo al Diseñar las transiciones considerando la carga" translate="no">​</a></h2>
<p>Al diseñar niveles, esta información permite elegir dónde conviene cargar contenido nuevo. No todas las puertas tienen que provocar una carga ni todas las áreas necesitan estar residentes. El tamaño de cada zona y la memoria disponible ayudan a decidir cómo dividir el juego.</p>
<p>Un conjunto pequeño de habitaciones puede permanecer cargado, mientras que un cambio importante de ubicación puede usar una transición explícita. Los pasillos también ayudan a controlar lo que se ve, aunque eso por sí solo no resuelve la carga de archivos. Conviene separar las decisiones de visibilidad de las de almacenamiento y lectura.</p>
<p>Entender estos tiempos me ayudó a relacionar el sistema de carga con el diseño de las escenas. La distribución de archivos influye en cuánto espera el jugador, y la presentación de la transición influye en cómo se percibe esa espera. Por eso ambas partes necesitan revisarse al probar el juego exportado.</p>]]></content:encoded>
            <category>PS1</category>
            <category>CD-ROM</category>
            <category>Audio</category>
            <category>Flujo de trabajo</category>
        </item>
        <item>
            <title><![CDATA[Del proyecto del editor a una compilación para PS1]]></title>
            <link>https://polygonengine.com/es/blog/editor-to-runtime-pipeline</link>
            <guid>https://polygonengine.com/es/blog/editor-to-runtime-pipeline</guid>
            <pubDate>Tue, 07 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[La preparación de recursos, las referencias y los errores de compilación que hay que resolver para ejecutar un proyecto en PlayStation 1.]]></description>
            <content:encoded><![CDATA[<p>Para exportar un juego desde Polygon Engine, primero necesitaba convertir el proyecto del editor en datos que pudiera utilizar la consola. Las escenas, las imágenes y los sonidos se guardan en formatos cómodos para trabajar, pero PS1 necesita versiones adaptadas a su memoria y a sus sistemas de renderizado y audio.</p>
<p>Esa conversión se volvió una parte importante del desarrollo. Cada vez que agregaba un tipo de recurso o un componente, también tenía que considerar cómo guardarlo, comprobar sus referencias y cargarlo en el juego. Generar la imagen de disco es el último paso de ese proceso.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="source-and-runtime">Convertir los recursos de origen para la consola<a href="https://polygonengine.com/es/blog/editor-to-runtime-pipeline#source-and-runtime" class="hash-link" aria-label="Enlace directo al Convertir los recursos de origen para la consola" title="Enlace directo al Convertir los recursos de origen para la consola" translate="no">​</a></h2>
<p>Una textura comienza como una imagen cómoda de editar. El juego necesita una representación que la GPU pueda utilizar, con dimensiones, modo de color y datos de paleta compatibles con sus restricciones. Un sonido comienza como una grabación de origen; un efecto corto residente necesita una representación distinta a la de música transmitida desde el disco.</p>
<p>Las mallas y las escenas tienen la misma separación. Los datos de selección y los ajustes editables son útiles en la computadora. Los vértices compactos, los datos de componentes y las dependencias resueltas son útiles en la consola. Llevar cada comodidad de edición al entorno de ejecución gastaría memoria en información que el jugador nunca utiliza.</p>
<p>Preparar los recursos en la computadora permite resolver una parte del trabajo antes de ejecutar el juego. Si un cálculo depende de contenido que no cambiará durante la partida, muchas veces se puede guardar su resultado en la compilación. Así se prepara parte de la geometría y de los datos de navegación. Los objetos móviles y los cambios de estado, por supuesto, siguen necesitando actualizarse durante la ejecución.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="asset-identity">Mantener las referencias entre recursos<a href="https://polygonengine.com/es/blog/editor-to-runtime-pipeline#asset-identity" class="hash-link" aria-label="Enlace directo al Mantener las referencias entre recursos" title="Enlace directo al Mantener las referencias entre recursos" translate="no">​</a></h2>
<p>Al organizar los recursos también necesitaba conservar sus referencias. Por ejemplo, si un material utiliza una textura y después cambio el nombre de esa imagen, el material debería seguir apuntando al mismo recurso. Depender únicamente de una ruta vuelve más frágiles esas relaciones cuando se reorganizan las carpetas.</p>
<p>Polygon Engine usa referencias de recursos basadas en GUID para separar la identidad de la presentación. El nombre ayuda a una persona a encontrar el recurso; el identificador ayuda al proyecto a seguir apuntando a él. La compilación resuelve después esas referencias en los datos preparados para la consola.</p>
<p>Además del identificador, hay que mantener actualizada la base de recursos y detectar las dependencias ausentes. También es necesario comprobar que el archivo convertido corresponda al origen y a sus ajustes de importación. Si cambio el modo de color de una textura y reutilizo una copia anterior, la referencia puede ser correcta mientras el contenido ya está desactualizado.</p>
<p>Por eso la compilación también revisa las importaciones desactualizadas. La existencia del archivo no basta: hace falta comprobar que representa los ajustes actuales del proyecto antes de incluirlo en el juego.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="desktop-work">Preparar los datos durante la compilación<a href="https://polygonengine.com/es/blog/editor-to-runtime-pipeline#desktop-work" class="hash-link" aria-label="Enlace directo al Preparar los datos durante la compilación" title="Enlace directo al Preparar los datos durante la compilación" translate="no">​</a></h2>
<p>Con las referencias resueltas, el siguiente paso es organizar los datos para cargarlos en PS1. Las escenas se pueden escribir en registros binarios con límites definidos y sus dependencias se pueden agrupar. Esto aprovecha la información que ya tiene el editor y reduce el trabajo necesario al iniciar una escena.</p>
<p>En el proceso actual, las escenas se escriben como datos <code>.BSN</code>, y los paquetes <code>.PGB</code> de cada escena organizan sus dependencias para una carga secuencial. Estas decisiones de implementación tienen un propósito práctico: reducir la interpretación y evitar accesos innecesarios al disco, archivo por archivo, al entrar a una escena.</p>
<p>Estos formatos son más adecuados para la ejecución, aunque resultan menos cómodos de inspeccionar manualmente que los archivos del proyecto. Por eso necesito reportes que permitan relacionar los datos generados con su origen. Si un objeto no aparece, debo poder revisar qué escena o recurso produjo esos datos.</p>
<p>La preparación también debe considerar la memoria temporal de la carga. Aunque la escena final quepa, leer sus archivos y construir sus objetos puede requerir espacio adicional. Para estimar el máximo consumo hay que tener en cuenta los datos anteriores, los nuevos y los búferes que puedan coincidir durante la transición.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="useful-errors">Reportar errores antes del empaquetado<a href="https://polygonengine.com/es/blog/editor-to-runtime-pipeline#useful-errors" class="hash-link" aria-label="Enlace directo al Reportar errores antes del empaquetado" title="Enlace directo al Reportar errores antes del empaquetado" translate="no">​</a></h2>
<p>Al desarrollar este proceso, me interesaba que los errores indicaran qué revisar. Un mensaje genérico de compilación fallida sirve de poco si el problema es un script ausente, una escena inicial inválida o una herramienta externa mal configurada. El diagnóstico necesita identificar el recurso o el ajuste correspondiente para poder corregirlo desde el proyecto.</p>
<p>El orden también importa. Encontrar esos problemas antes de empaquetar cuesta mucho menos que descubrirlos mediante una pantalla vacía. Al mismo tiempo, un validador exitoso no puede demostrar todos los comportamientos del juego. Puede rechazar entradas que sabe inválidas; no garantiza que un acertijo tenga solución ni que todos los ángulos de cámara se ejecuten con fluidez.</p>
<p>Por eso utilizo la validación para detectar problemas conocidos del contenido y reservo las pruebas del juego para comprobar su comportamiento. Ambas son necesarias: una compilación correcta todavía puede contener una interacción mal configurada o una zona con bajo rendimiento.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="tool-responsibilities">Integrar el entorno de ejecución y las herramientas de disco<a href="https://polygonengine.com/es/blog/editor-to-runtime-pipeline#tool-responsibilities" class="hash-link" aria-label="Enlace directo al Integrar el entorno de ejecución y las herramientas de disco" title="Enlace directo al Integrar el entorno de ejecución y las herramientas de disco" translate="no">​</a></h2>
<p>Para completar el proceso, Polygon Engine se apoya en PSn00bSDK para el entorno de ejecución de PS1 y en <a href="https://github.com/Lameguy64/mkpsxiso" target="_blank" rel="noopener noreferrer" class="">mkpsxiso</a> para crear las imágenes de disco. El engine prepara y valida el contenido, y mkpsxiso lo organiza según la distribución indicada. Separar esas tareas también ayuda a identificar si una falla está en los datos del juego o en el empaquetado.</p>
<p>El editor distribuido utiliza un entorno de ejecución precompilado, así que el flujo normal del usuario no requiere recibir el código privado del engine ni recompilar su código C. Las herramientas externas siguen necesitando una configuración correcta y un tratamiento adecuado de su redistribución. La comodidad de la interfaz no elimina el mantenimiento de dependencias ni las responsabilidades de licencia.</p>
<p>Trabajar en la exportación me llevó a revisar las funciones de principio a fin. Agregar un componente a Inspector también implica guardar sus valores, recuperarlos al abrir el proyecto, convertirlos y utilizarlos correctamente en PS1. Al mantener conectadas esas etapas, puedo seguir agregando herramientas sin perder de vista cómo llegará su resultado al juego.</p>]]></content:encoded>
            <category>PS1</category>
            <category>Flujo de trabajo</category>
            <category>Compilación</category>
            <category>Preprocesamiento</category>
        </item>
        <item>
            <title><![CDATA[Construir niveles para PS1 con Level Builder]]></title>
            <link>https://polygonengine.com/es/blog/ps1-safe-level-authoring</link>
            <guid>https://polygonengine.com/es/blog/ps1-safe-level-authoring</guid>
            <pubDate>Wed, 11 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Cómo se relacionan la geometría, las colisiones, la subdivisión y la edición de mallas al construir niveles en Polygon Engine.]]></description>
            <content:encoded><![CDATA[<p>Además de dibujar modelos, Polygon Engine necesitaba herramientas para construir espacios que se pudieran recorrer. Una habitación sencilla reúne varios de los problemas que quería resolver: pisos vistos en perspectiva, paredes cercanas a la cámara, puertas y colisiones que permitan moverse sin atravesar la geometría.</p>
<p>Trabajar con ese tipo de espacio me permitió relacionar el renderizado con la edición del nivel. Al cambiar el tamaño de una pared o la forma de una entrada, también tenía que considerar cómo se vería en PS1 y qué volumen de colisión necesitaría. Level Builder forma parte de ese flujo de creación y revisión.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="player-path">Probar el recorrido del jugador<a href="https://polygonengine.com/es/blog/ps1-safe-level-authoring#player-path" class="hash-link" aria-label="Enlace directo al Probar el recorrido del jugador" title="Enlace directo al Probar el recorrido del jugador" translate="no">​</a></h2>
<p>Para revisar una habitación de prueba, me sirve definir un recorrido sencillo antes de agregar detalles: entrar, mirar el piso, acercarse a una esquina, cruzar una puerta y dar la vuelta. Son movimientos normales durante el juego, pero cada uno permite observar un aspecto distinto del nivel.</p>
<p>Al mirar hacia abajo se aprecia mejor el mapeo de la textura del piso. Acercarse a una pared permite revisar la geometría cerca de la cámara, y atravesar una puerta ayuda a comprobar las colisiones. Al regresar por el mismo camino también se pueden encontrar superficies que solo presentan problemas desde ciertos ángulos.</p>
<p>Para hacer esos ajustes quería conservar las operaciones habituales de Unity: seleccionar, mover, rotar, escalar y asignar componentes. La diferencia estaba en preparar el resultado para PS1. Un plano grande puede ser cómodo para construir el piso, por ejemplo, pero necesitar subdivisión para que su textura se vea mejor de cerca.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="subdivision-tradeoff">Elegir dónde subdividir la geometría<a href="https://polygonengine.com/es/blog/ps1-safe-level-authoring#subdivision-tradeoff" class="hash-link" aria-label="Enlace directo al Elegir dónde subdividir la geometría" title="Enlace directo al Elegir dónde subdividir la geometría" translate="no">​</a></h2>
<p>El piso de un pasillo largo puede construirse con solo dos triángulos. Eso mantiene baja la cantidad de geometría, aunque la textura puede deformarse bastante cuando la cámara está cerca del suelo y la superficie se extiende hacia el fondo.</p>
<p>Dividir el piso en secciones más cortas puede reducir la deformación afín y darle al proceso de ordenamiento superficies más pequeñas. Pero una cuadrícula densa tiene un costo real. Aumenta los vértices transformados, los paquetes generados y el trabajo de ordenamiento. Si el jugador puede ver muchas secciones al mismo tiempo, el presupuesto vuelve a cambiar.</p>
<p>Por eso prefiero ajustar la subdivisión según la ubicación y el tamaño de cada superficie. Un piso cercano ocupa mucho más espacio en pantalla que un panel decorativo lejano. Una pared vista en ángulo puede necesitar otro tratamiento. Revisar el nivel desde la cámara del jugador ayuda a decidir dónde los triángulos adicionales mejoran lo suficiente la imagen para justificar su costo.</p>
<p>Las piezas contiguas también necesitan coincidir en sus bordes. Una división descuidada puede introducir grietas o límites desalineados. El sistema de renderizado y la herramienta de edición deben compartir criterios sobre la representación de posiciones y la preparación de la geometría.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="collision-room">Ajustar las colisiones al nivel visible<a href="https://polygonengine.com/es/blog/ps1-safe-level-authoring#collision-room" class="hash-link" aria-label="Enlace directo al Ajustar las colisiones al nivel visible" title="Enlace directo al Ajustar las colisiones al nivel visible" translate="no">​</a></h2>
<p>Al agregar movimiento al nivel, también necesito revisar los volúmenes de colisión. La malla define la apariencia de una pared o una puerta; su colisión determina dónde puede moverse el personaje. Ambas representaciones deben coincidir en lo que afecta al recorrido, aunque no tengan el mismo nivel de detalle.</p>
<p>El marco de una puerta puede incluir biseles decorativos, paneles hundidos y una silueta complicada. Esos detalles no justifican automáticamente una colisión igual de compleja. Una distribución más sencilla puede ofrecer movimiento predecible y consultas menos costosas. Por otro lado, simplificar demasiado puede hacer que una abertura parezca transitable mientras una barrera invisible la bloquea.</p>
<p>En primera persona, una diferencia entre la entrada visible y su colisión se nota de inmediato: parece que el personaje cabe, pero no puede pasar. Para evitarlo hay que revisar juntas las dimensiones de la abertura, la forma del controlador, la altura de escalón y la ubicación de los colliders.</p>
<p>En Polygon Engine las colisiones se configuran mediante componentes, de modo que se pueden ajustar por separado de la malla. Eso permite conservar el detalle visual y usar formas de colisión más sencillas cuando son suficientes. También deja al usuario decidir qué partes del nivel deben bloquear el paso o funcionar como triggers.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="level-builder">Editar mallas en Level Builder<a href="https://polygonengine.com/es/blog/ps1-safe-level-authoring#level-builder" class="hash-link" aria-label="Enlace directo al Editar mallas en Level Builder" title="Enlace directo al Editar mallas en Level Builder" translate="no">​</a></h2>
<p>Level Builder reúne las herramientas de edición de mallas dentro del editor. Permite trabajar con vértices, aristas, caras y UVs, y guardar el resultado como un recurso para utilizarlo en la escena. Quería que fuera posible construir y ajustar una habitación sin tener que cambiar de aplicación para cada modificación de la geometría.</p>
<!-- -->
<figure class="figure_cZR6"><a href="https://polygonengine.com/es/img/docs/current/level-builder.png" target="_blank" rel="noopener noreferrer" aria-label="Level Builder de Polygon Engine con herramientas de edición de mallas, un cubo y estadísticas de preparación para PS1. Abrir la captura a tamaño completo en una pestaña nueva."><img src="https://polygonengine.com/es/img/docs/current/level-builder.png" alt="Level Builder de Polygon Engine con herramientas de edición de mallas, un cubo y estadísticas de preparación para PS1" width="1920" height="1080" loading="lazy"></a><figcaption><p>Level Builder en la versión documentada del editor. Esta captura posterior ilustra el flujo descrito; no es una imagen histórica de la fecha de la entrada.</p> <span>Abre la imagen para verla a tamaño completo.</span></figcaption></figure>
<p>Durante esa edición también resulta útil ver los límites de la malla. Sin embargo, revisar un recurso aislado no alcanza para conocer el consumo de la escena completa: colocar varias copias aumenta el trabajo de renderizado. Por eso las estadísticas de Level Builder se complementan con el presupuesto del proyecto.</p>
<p>La <a class="" href="https://polygonengine.com/es/docs/editor/level-builder">guía de Level Builder</a> explica los controles disponibles. Al integrarlos, me interesaba que la edición fuera cómoda y que hubiera información suficiente para revisar el resultado antes de exportar. Poder generar una forma rápidamente es útil, pero también necesito saber cómo afectará al juego.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="useful-room">Trabajar con un nivel pequeño de prueba<a href="https://polygonengine.com/es/blog/ps1-safe-level-authoring#useful-room" class="hash-link" aria-label="Enlace directo al Trabajar con un nivel pequeño de prueba" title="Enlace directo al Trabajar con un nivel pequeño de prueba" translate="no">​</a></h2>
<p>Para revisar estos detalles, prefiero mantener el nivel de prueba pequeño y fácil de modificar. Puedo cambiar las secciones del piso, bajar la cámara, quitar una textura o simplificar un collider y comparar el resultado. En una escena más elaborada cuesta distinguir cuál de esos cambios explica la diferencia.</p>
<p>Eso también explica por qué un tutorial compacto puede enseñar más que una demostración enorme. Dos habitaciones y una puerta ofrecen suficiente estructura para ejercitar movimiento, visibilidad, interacción y organización de escenas, sin dejar de ser comprensibles.</p>
<p>Con esas pruebas busco comprobar el proceso completo: modificar la habitación, guardarla, volver a abrirla y exportarla. La geometría, los materiales y las colisiones deben conservar los ajustes realizados. Ese es el resultado que necesito para poder seguir construyendo el nivel sin repetir trabajo en cada compilación.</p>]]></content:encoded>
            <category>PS1</category>
            <category>Creación de contenido</category>
            <category>Editor</category>
            <category>Recorte</category>
        </item>
        <item>
            <title><![CDATA[Renderizado en PS1: texturas, vértices y orden de dibujo]]></title>
            <link>https://polygonengine.com/es/blog/ps1-rendering-constraints</link>
            <guid>https://polygonengine.com/es/blog/ps1-rendering-constraints</guid>
            <pubDate>Thu, 05 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Cómo se relacionan la interpolación de texturas, la precisión de los vértices y el orden de los polígonos con el renderizado de Polygon Engine.]]></description>
            <content:encoded><![CDATA[<p>Al trabajar en el renderizado de Polygon Engine, necesitaba entender cuáles de los defectos visuales asociados con PS1 venían del hardware y cuáles podían ser errores de implementación. La deformación de las texturas, los pequeños saltos de los vértices y los polígonos que aparecen en un orden incorrecto pueden coincidir en una escena, pero tienen causas distintas.</p>
<p>Separarlos me ayudó a revisar cada etapa del renderizado con más claridad. Para explicar cómo se relacionan, primero conviene seguir el proceso que convierte los vértices de un modelo en una imagen. Después se puede ver dónde aparece cada problema y qué opciones hay para reducirlo.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="triangle-journey">De los vértices del modelo a las coordenadas de pantalla<a href="https://polygonengine.com/es/blog/ps1-rendering-constraints#triangle-journey" class="hash-link" aria-label="Enlace directo al De los vértices del modelo a las coordenadas de pantalla" title="Enlace directo al De los vértices del modelo a las coordenadas de pantalla" translate="no">​</a></h2>
<p>El proceso comienza con las posiciones de los vértices del modelo. Esas posiciones se transforman respecto a la cámara y se proyectan en la pantalla. En PS1, el GTE acelera operaciones de transformación y proyección; después, la GPU recibe comandos con las primitivas que debe dibujar en coordenadas de pantalla.</p>
<p>Por lo tanto, antes de enviar una primitiva a la GPU, el engine ya debe haber preparado su geometría y decidido cómo organizar el dibujo. La <a href="https://psx-spx.consoledev.net/geometrytransformationenginegte/" target="_blank" rel="noopener noreferrer" class="">referencia del GTE</a> me sirve para consultar qué cálculos puede realizar el coprocesador y cuáles debe resolver el código del engine.</p>
<p>Al revisar estas transformaciones también hay que considerar la precisión de los datos. Una posición puede estar bien calculada en el modelo y perder precisión al convertirse a coordenadas de pantalla. Durante un movimiento lento de cámara, esa diferencia puede volverse visible en los bordes de los polígonos.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="affine-textures">La interpolación afín de texturas<a href="https://polygonengine.com/es/blog/ps1-rendering-constraints#affine-textures" class="hash-link" aria-label="Enlace directo al La interpolación afín de texturas" title="Enlace directo al La interpolación afín de texturas" translate="no">​</a></h2>
<p>Un piso con mosaicos permite observar con facilidad la deformación de las texturas. La parte cercana a la cámara ocupa más espacio en pantalla que la parte lejana. Para representar esa perspectiva correctamente, la interpolación de las coordenadas de textura tendría que considerar la diferencia de profundidad a lo largo de la superficie.</p>
<p>La GPU de PS1 utiliza interpolación afín de texturas. Interpola las coordenadas de textura en el espacio de pantalla sin la corrección de perspectiva que normalmente aplica un sistema moderno. Por eso un triángulo grande con diferencias importantes de profundidad puede mostrar mosaicos que se doblan o deslizan cuando se mueve la cámara.</p>
<p>Eso es independiente de que el triángulo se haya dibujado en el orden correcto. Ordenarlo perfectamente no cambia cómo se interpolan las coordenadas de textura en su interior. La <a href="https://psx-spx.consoledev.net/graphicsprocessingunitgpu/" target="_blank" rel="noopener noreferrer" class="">documentación de la GPU</a> describe el comportamiento de primitivas y texturas detrás de esta diferencia.</p>
<p>La subdivisión ayuda a reducir ese efecto al dividir la superficie en piezas más pequeñas. Cada pieza abarca una diferencia menor de profundidad, de modo que la aproximación afín suele verse mejor. Al incorporarla al flujo del engine, también hay que considerar su costo: aumenta la cantidad de vértices y de paquetes de primitivas que se preparan y ordenan.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="vertex-jitter">La precisión y la inestabilidad de los vértices<a href="https://polygonengine.com/es/blog/ps1-rendering-constraints#vertex-jitter" class="hash-link" aria-label="Enlace directo al La precisión y la inestabilidad de los vértices" title="Enlace directo al La precisión y la inestabilidad de los vértices" translate="no">​</a></h2>
<p>La inestabilidad de los vértices se puede observar incluso en una superficie sin textura. Si el contorno da pequeños saltos durante un movimiento lento de cámara, conviene revisar la precisión de las coordenadas en lugar de modificar el mapeo de la imagen.</p>
<p>Las coordenadas de pantalla tienen precisión limitada, y los cálculos geométricos utilizan formatos numéricos finitos. Un movimiento suave en una representación de mayor precisión termina convertido en pasos discretos en una imagen de baja resolución. Pequeños cambios cerca de un límite de redondeo pueden ser muy visibles en un borde de alto contraste.</p>
<p>Eso no significa que cada salto visible sea una característica inevitable del hardware. Un engine puede introducir errores propios mediante redondeos inconsistentes, una escala inadecuada o una transformación que excede su rango numérico. Necesito distinguir la cuantización esperada de los errores que ocurren antes de que la GPU reciba la primitiva.</p>
<p>Esta diferencia también afecta cómo uso la vista previa de Polygon Engine. Simular la inestabilidad de vértices en el editor ayuda a evaluar la apariencia de una escena, pero el juego exportado utiliza su propio proceso de transformación. Necesito revisar ese resultado para saber si el comportamiento es el esperado en la consola.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="drawing-order">El orden de los polígonos y el recorte<a href="https://polygonengine.com/es/blog/ps1-rendering-constraints#drawing-order" class="hash-link" aria-label="Enlace directo al El orden de los polígonos y el recorte" title="Enlace directo al El orden de los polígonos y el recorte" translate="no">​</a></h2>
<p>La GPU de PS1 no tiene un búfer de profundidad de propósito general que resuelva la superficie más cercana para cada píxel. Una estrategia común es organizar las primitivas en una tabla de ordenamiento para enviar la geometría lejana antes que la cercana.</p>
<p>La dificultad está en asignar un orden de profundidad a un polígono completo cuando sus partes están a profundidades distintas. Dos superficies que se cruzan pueden exigir órdenes contradictorios. Un valor promedio de profundidad no describe qué superficie está delante en cada punto de la intersección.</p>
<p>Una tabla de ordenamiento más precisa puede reducir las coincidencias entre grupos de profundidad, pero no resuelve esa ambigüedad geométrica. Dividir superficies problemáticas puede ayudar. También ayuda diseñar la geometría y los recorridos de cámara para reducir los traslapes ambiguos. Ninguna de esas estrategias convierte una tabla de ordenamiento en un búfer de profundidad.</p>
<p>Otro caso que reviso por separado es el recorte contra el plano cercano de la cámara. Cuando un polígono cruza ese plano, hace falta tratarlo antes de proyectarlo y dibujarlo. Las instrucciones del GTE no sustituyen un algoritmo completo de recorte, así que una superficie que se estira o desaparece al acercarse puede señalar un problema en esa parte del engine.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="diagnostic-scene">Probar cada problema de renderizado por separado<a href="https://polygonengine.com/es/blog/ps1-rendering-constraints#diagnostic-scene" class="hash-link" aria-label="Enlace directo al Probar cada problema de renderizado por separado" title="Enlace directo al Probar cada problema de renderizado por separado" translate="no">​</a></h2>
<p>Para distinguir estos casos, una escena de prueba puede incluir un piso cuadriculado, dos superficies sin textura que se crucen y una cámara con movimiento lento. Con pocos elementos es más fácil observar qué cambia al ajustar la geometría o el renderizado.</p>
<p>El patrón cuadriculado permite evaluar la deformación de la textura. Los contornos sin textura muestran los saltos de coordenadas, y las superficies cruzadas permiten revisar el orden de dibujo. Así se puede comprobar, por ejemplo, si una subdivisión mejoró el mapeo o si únicamente cambió la forma en que se superponen los polígonos.</p>
<p>Entender estas diferencias me ayudó a decidir qué resolver en el renderizado y qué apoyar desde las herramientas de creación de niveles. Algunos comportamientos requieren corregir cálculos; otros se pueden reducir al dividir una superficie o ajustar la geometría. Tener clara la causa evita modificar partes del engine que no están relacionadas con el problema.</p>]]></content:encoded>
            <category>PS1</category>
            <category>Renderizado</category>
            <category>Ordenamiento</category>
            <category>GPU</category>
        </item>
        <item>
            <title><![CDATA[Memoria, texturas y paletas en PlayStation 1]]></title>
            <link>https://polygonengine.com/es/blog/ps1-vram-texture-pages-and-cluts</link>
            <guid>https://polygonengine.com/es/blog/ps1-vram-texture-pages-and-cluts</guid>
            <pubDate>Fri, 09 Jan 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Cómo influyen las distintas memorias, los búferes de imagen y los formatos de textura en la preparación de recursos de Polygon Engine.]]></description>
            <content:encoded><![CDATA[<p>Al estudiar la memoria de PlayStation 1 para preparar la importación de recursos, tuve que separar tres cosas: los datos del juego, los gráficos y el sonido. Cada uno utiliza una memoria distinta, así que no bastaba con calcular cuánto ocupaba una escena en total.</p>
<p>Por ejemplo, una escena puede dejar espacio disponible en la RAM principal y aun así superar la capacidad de VRAM con sus texturas. Lo mismo ocurre con los sonidos que se mantienen cargados. Esa separación me ayudó a definir qué información debía mostrar el engine para revisar los recursos antes de exportar.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="separate-budgets">RAM principal, VRAM y memoria de sonido<a href="https://polygonengine.com/es/blog/ps1-vram-texture-pages-and-cluts#separate-budgets" class="hash-link" aria-label="Enlace directo al RAM principal, VRAM y memoria de sonido" title="Enlace directo al RAM principal, VRAM y memoria de sonido" translate="no">​</a></h2>
<p>El PS1 original tiene 2 MiB de RAM principal, 1 MiB de VRAM y 512 KiB de RAM de la SPU. Aquí uso MiB y KiB para indicar las cantidades exactas: un KiB equivale a 1,024 bytes. Con tan poca memoria disponible, conviene mantener esas unidades al hacer las cuentas.</p>
<p>La RAM principal contiene el programa y buena parte de sus datos de trabajo. La VRAM contiene los búferes de imagen, las texturas y las paletas. La RAM de la SPU contiene datos de sonido y el espacio que necesitan funciones como la reverberación. No son secciones intercambiables de una misma reserva de propósito general. El <a href="https://psx-spx.consoledev.net/memorymap/" target="_blank" rel="noopener noreferrer" class="">mapa de memoria de PS1</a> es una referencia útil para distinguir esas regiones.</p>
<p>En el editor necesitaba mostrar el consumo de cada memoria por separado. Así es posible identificar qué recurso se acerca a su límite y qué cambio puede ayudar. Reducir la memoria que usa Lua, por ejemplo, no libera VRAM para una textura, porque ambos datos se almacenan en regiones diferentes.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="framebuffer-cost">La memoria que ocupan los búferes de imagen<a href="https://polygonengine.com/es/blog/ps1-vram-texture-pages-and-cluts#framebuffer-cost" class="hash-link" aria-label="Enlace directo al La memoria que ocupan los búferes de imagen" title="Enlace directo al La memoria que ocupan los búferes de imagen" translate="no">​</a></h2>
<p>Antes de agregar una textura, la propia imagen necesita almacenamiento. Tomemos un ejemplo común: una imagen de 320 × 240 guardada con dos bytes por píxel. Un búfer ocupa 153,600 bytes, es decir, 150 KiB. Mantener dos búferes de ese tipo ocupa 300 KiB.</p>
<p>Quedan 724 KiB de los 1,024 KiB originales, antes de considerar paletas, otras asignaciones y restricciones de ubicación. Es una configuración ilustrativa, no una distribución universal de PS1: los modos de video y las estrategias de almacenamiento de cuadros pueden cambiarla.</p>
<p>Esto relaciona la resolución con la cantidad de texturas que pueden permanecer cargadas. Un búfer de imagen más grande deja menos espacio para ellas. Por eso, al elegir la resolución también hay que considerar si será necesario reducir las imágenes o cargar conjuntos distintos en cada área.</p>
<p>Hacer estas cuentas me ayudó a entender por qué la resolución debía considerarse desde la preparación del contenido. Antes de importar las texturas de un nivel, ya se puede estimar cuánto espacio ocuparán los búferes y cuánto quedará para el resto de los gráficos.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="texture-sizes">Dimensiones y formatos de color de las texturas<a href="https://polygonengine.com/es/blog/ps1-vram-texture-pages-and-cluts#texture-sizes" class="hash-link" aria-label="Enlace directo al Dimensiones y formatos de color de las texturas" title="Enlace directo al Dimensiones y formatos de color de las texturas" translate="no">​</a></h2>
<p>Las dimensiones de una textura no describen por completo su almacenamiento. Una imagen de 256 × 256 tiene 65,536 texeles, pero la cantidad de bits por texel cambia mucho su costo.</p>
<table><thead><tr><th>Representación de la textura</th><th style="text-align:right">Datos de imagen</th><th style="text-align:right">Datos de paleta</th></tr></thead><tbody><tr><td>Indexada de 4 bits</td><td style="text-align:right">32 KiB</td><td style="text-align:right">32 bytes para 16 entradas</td></tr><tr><td>Indexada de 8 bits</td><td style="text-align:right">64 KiB</td><td style="text-align:right">512 bytes para 256 entradas</td></tr><tr><td>Almacenamiento de 16 bits</td><td style="text-align:right">128 KiB</td><td style="text-align:right">Sin paleta indexada</td></tr></tbody></table>
<p>Los valores de la tabla corresponden a los datos de la imagen y su paleta. La distribución real en VRAM también depende de las reglas de ubicación y alineación. En el formato de 16 bits, además, parte de la información corresponde a un bit de control de la GPU; no son dieciséis bits dedicados únicamente al color RGB.</p>
<p>En una imagen indexada, cada texel selecciona una entrada en una tabla de colores, o CLUT. Por eso una paleta es más que una opción de importación. Es otro conjunto de datos gráficos que necesita ubicarse y referenciarse correctamente. La <a href="https://psx-spx.consoledev.net/graphicsprocessingunitgpu/" target="_blank" rel="noopener noreferrer" class="">referencia de la GPU</a> describe estos modos de textura y sus reglas de direccionamiento.</p>
<p>Para un pasillo industrial, por ejemplo, una paleta de 16 colores bien elegida puede ser suficiente para distinguir metal, suciedad y pintura de advertencia. Usar color directo ocupa cuatro veces más memoria de imagen, así que vale la pena comparar el resultado a la resolución del juego antes de elegirlo. La paleta afecta tanto al tamaño del recurso como a su apariencia.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="placement">La distribución de las texturas en VRAM<a href="https://polygonengine.com/es/blog/ps1-vram-texture-pages-and-cluts#placement" class="hash-link" aria-label="Enlace directo al La distribución de las texturas en VRAM" title="Enlace directo al La distribución de las texturas en VRAM" translate="no">​</a></h2>
<p>La VRAM está organizada en una superficie de 1024 × 512 palabras de 16 bits. Además de conocer cuántos bytes ocupa una textura, necesito saber en qué parte de esa superficie puede colocarse.</p>
<p>Las páginas de textura definen regiones de direccionamiento dentro de esa superficie. Como una palabra puede almacenar cuatro texeles de 4 bits, una textura de 256 texeles de ancho ocupa menos palabras en ese formato que en el de 16 bits. La ubicación de las páginas, la alineación de las paletas y los rectángulos ya ocupados determinan dónde puede colocarse cada recurso.</p>
<p>Esto puede dejar espacios libres que, sumados, parecen suficientes para otra textura, aunque no exista una región continua donde quepa. Es un problema de distribución: sumar los bytes disponibles no siempre permite saber si una nueva imagen puede colocarse correctamente.</p>
<p>Por eso me resultó importante tener una vista de esa distribución. VRAM Inspector permite relacionar una textura importada con la región que ocupa y revisar qué está utilizando el resto del espacio. Con esa información se puede decidir si conviene reducir una imagen, cambiar su modo de color o cargar menos recursos al mismo tiempo.</p>
<!-- -->
<figure class="figure_cZR6"><a href="https://polygonengine.com/es/img/docs/current/vram-inspector.png" target="_blank" rel="noopener noreferrer" aria-label="VRAM Inspector muestra dos búferes de imagen, asignaciones de texturas y paletas, y uso de memoria. Abrir la captura a tamaño completo en una pestaña nueva."><img src="https://polygonengine.com/es/img/docs/current/vram-inspector.png" alt="VRAM Inspector muestra dos búferes de imagen, asignaciones de texturas y paletas, y uso de memoria" width="1920" height="1080" loading="lazy"></a><figcaption><p>Una captura posterior del editor hace visible la distribución compartida: los búferes de imagen ocupan regiones grandes antes de agregar texturas y paletas. Los valores pertenecen a este proyecto de ejemplo.</p> <span>Abre la imagen para verla a tamaño completo.</span></figcaption></figure>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="room-budget">Planear las texturas de una habitación<a href="https://polygonengine.com/es/blog/ps1-vram-texture-pages-and-cluts#room-budget" class="hash-link" aria-label="Enlace directo al Planear las texturas de una habitación" title="Enlace directo al Planear las texturas de una habitación" translate="no">​</a></h2>
<p>Al preparar las texturas de una habitación, me sirve empezar por sus elementos principales: paredes, piso, puerta, objetos e interfaz. A partir de ahí puedo revisar qué imágenes se repiten, cuáles podrían compartir paleta y cuáles necesitan detalle propio. Así, la selección de formatos responde a un conjunto concreto de recursos.</p>
<p>El peligro está en optimizar lo menos visible e ignorar la distribución completa. Ahorrar unos bytes de paleta no compensa una textura grande innecesaria. Por otro lado, reducir todas las imágenes puede perjudicar su legibilidad sin solucionar una mala distribución.</p>
<p>Entender esa relación entre los recursos y su distribución fue importante para el diseño de las herramientas de importación. Quería poder revisar una escena visualmente y, en el mismo proyecto, consultar cuánto espacio ocupaban sus gráficos y cómo estaban acomodados. Esa información permite ajustar el contenido con una razón concreta.</p>]]></content:encoded>
            <category>PS1</category>
            <category>VRAM</category>
            <category>GPU</category>
            <category>Optimización</category>
        </item>
        <item>
            <title><![CDATA[Cómo empezó Polygon Engine]]></title>
            <link>https://polygonengine.com/es/blog/practical-map-of-the-original-playstation</link>
            <guid>https://polygonengine.com/es/blog/practical-map-of-the-original-playstation</guid>
            <pubDate>Thu, 04 Dec 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Cómo surgió la idea de crear un engine para PS1 con un flujo inspirado en Unity y una interfaz de Windows 95, y qué aprendí al estudiar el hardware.]]></description>
            <content:encoded><![CDATA[<p>Desde hace mucho tiempo he querido hacer juegos para PlayStation 1. Como desarrollador de Unity, imaginaba poder hacerlo con un flujo parecido al que uso habitualmente: crear una escena, colocar objetos, asignar componentes y programar su comportamiento. De ahí surgió la idea de Polygon Engine.</p>
<p>Quería reunir ese flujo de trabajo con una interfaz inspirada en Windows 95. Me gustaba la idea de abrir el editor y sentir que estaba desarrollando un juego en aquella época, pero con las comodidades de una herramienta actual. Para conseguirlo, primero tenía que entender cómo llevar una escena creada en la computadora a un juego que pudiera ejecutarse en PS1.</p>
<p><em>Este es el primer capítulo de un diario retrospectivo de desarrollo. Las fechas organizan las etapas de ese recorrido; no son un historial de versiones ni las fechas de publicación de funciones específicas.</em></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="gray-windows">La elección de la estética de Windows 95<a href="https://polygonengine.com/es/blog/practical-map-of-the-original-playstation#gray-windows" class="hash-link" aria-label="Enlace directo al La elección de la estética de Windows 95" title="Enlace directo al La elección de la estética de Windows 95" translate="no">​</a></h2>
<p>La apariencia de Windows 95 fue una de las primeras decisiones del proyecto. Los paneles grises, los bordes marcados y los menús compactos eran parte de la experiencia que quería recrear. No se trataba solamente de que el juego tuviera una estética retro; también quería disfrutar esa sensación mientras lo desarrollaba.</p>
<p>Al diseñar la interfaz, también tuve que pensar en su uso diario. Los valores de Inspector debían leerse con claridad, la selección de objetos tenía que distinguirse y los controles más frecuentes necesitaban estar a la mano. La referencia visual me ayudaba a definir el estilo, pero no debía volver incómodo el trabajo de editar una escena.</p>
<p>El editor funciona en Windows moderno, con una apariencia inspirada en Windows 95. Así puedo aprovechar una computadora actual para editar y preparar los recursos, mientras que el juego exportado está pensado para el hardware de PlayStation 1.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="familiar-gestures">Adaptar el flujo de trabajo de Unity<a href="https://polygonengine.com/es/blog/practical-map-of-the-original-playstation#familiar-gestures" class="hash-link" aria-label="Enlace directo al Adaptar el flujo de trabajo de Unity" title="Enlace directo al Adaptar el flujo de trabajo de Unity" translate="no">​</a></h2>
<p>Mi experiencia con Unity me sirvió para organizar el editor alrededor de escenas, GameObjects, componentes y scripts. Es una forma de trabajar que ya conozco y que me permite probar interacciones sin tener que resolver todos los detalles técnicos cada vez. Quería conservar esa facilidad al crear, por ejemplo, una puerta con movimiento, colisión y sonido.</p>
<p>Lo que sí necesitaba adaptar era el alcance de cada sistema. Aunque Inspector y los componentes resulten familiares, el renderizado, la física y el scripting tienen que funcionar dentro de los límites de PS1. La interfaz puede facilitar ese trabajo, pero también necesita mostrar las restricciones que afectan al proyecto.</p>
<p>Las texturas son un buen ejemplo. Al crear una habitación, no basta con asignar imágenes a sus materiales: también hay que comprobar que quepan en VRAM junto con los búferes de imagen y los demás datos gráficos. Preferí que esa información estuviera disponible durante la edición, cuando todavía es fácil reducir una textura o cambiar su formato, en lugar de descubrir el problema al exportar.</p>
<p>A partir de ahí fui definiendo qué tareas podía automatizar el engine y cuáles necesitaban información visible para el usuario. Esa decisión ha influido tanto en las herramientas de importación como en los paneles de memoria y validación.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="learning-the-machine">Entender cómo funciona el hardware de PlayStation<a href="https://polygonengine.com/es/blog/practical-map-of-the-original-playstation#learning-the-machine" class="hash-link" aria-label="Enlace directo al Entender cómo funciona el hardware de PlayStation" title="Enlace directo al Entender cómo funciona el hardware de PlayStation" translate="no">​</a></h2>
<p>El <a href="https://pikuma.com/courses/ps1-programming-mips-assembly-language" target="_blank" rel="noopener noreferrer" class="">curso de programación de PS1 de Pikuma</a> me ayudó mucho en este proceso. En Unity, buena parte del trabajo de renderizado y manejo de recursos ya está resuelto por el engine. Al desarrollar una herramienta para PS1, necesitaba entender esos procesos con más detalle: cómo se transforman los vértices, cómo llegan los comandos a la GPU y dónde se guardan las texturas antes de dibujarlas.</p>
<p>Estudiar esas etapas me ayudó a ubicar la función de cada parte de la consola. La CPU ejecuta la lógica del juego y coordina el trabajo; el GTE acelera cálculos geométricos, y la GPU dibuja las primitivas que recibe. El sonido tiene su propio procesador y memoria. Además, cargar datos desde el CD-ROM requiere considerar los tiempos de lectura de la unidad.</p>
<p>Con esa base fue más fácil entender por qué dos problemas que aparecen en la misma escena pueden necesitar soluciones distintas. La deformación de una textura tiene que ver con su interpolación; un polígono que aparece delante de otro puede deberse al orden de dibujo. Una pausa al cambiar de habitación, en cambio, puede estar relacionada con la carga de datos.</p>
<p>En estas entradas quiero contar cómo fui relacionando lo que aprendía con las necesidades del engine. Entender el hardware me ayudó a tomar decisiones sobre las herramientas, desde la información que necesita un importador de texturas hasta los errores que conviene detectar antes de generar un juego.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="three-places">Separar la edición, la compilación y la ejecución<a href="https://polygonengine.com/es/blog/practical-map-of-the-original-playstation#three-places" class="hash-link" aria-label="Enlace directo al Separar la edición, la compilación y la ejecución" title="Enlace directo al Separar la edición, la compilación y la ejecución" translate="no">​</a></h2>
<p>Para organizar ese trabajo, separé tres responsabilidades: editar el proyecto, preparar la compilación y ejecutar el juego en la consola.</p>
<p>El editor puede permitirse datos de origen detallados, manipulación interactiva y paneles explicativos. El proceso de compilación puede dedicar tiempo a comprobar referencias, convertir recursos y preparar datos. El entorno de ejecución necesita una representación compacta que pueda cargar y utilizar con un presupuesto muy reducido.</p>
<p>Una malla editable muestra bien esa separación. En el editor necesito información para seleccionar caras, modificar vértices y guardar los cambios. La consola necesita los datos necesarios para dibujarla. Preparar esa versión durante la compilación evita que el juego tenga que reconstruir información que solo era útil para editar.</p>
<p>Con ese mismo criterio decidí apoyarme en herramientas y librerías existentes. Me permitían avanzar en el editor y en el flujo de creación de juegos mientras aprendía cómo funcionaba cada parte. Integrarlas también ha requerido entender qué resuelven, qué limitaciones tienen y cómo revisar los problemas que aparecen al utilizarlas.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-tool">Completar el flujo de trabajo<a href="https://polygonengine.com/es/blog/practical-map-of-the-original-playstation#the-tool" class="hash-link" aria-label="Enlace directo al Completar el flujo de trabajo" title="Enlace directo al Completar el flujo de trabajo" translate="no">​</a></h2>
<p>Mi objetivo era poder completar un proyecto pequeño: crear una escena, construir un espacio, agregar comportamiento y exportarlo. Después tenía que poder volver al editor, hacer cambios y repetir el proceso. Para que esa forma de trabajar fuera práctica, el guardado, la importación y la compilación necesitaban funcionar juntos.</p>
<p>La estética de Windows 95 sigue siendo una parte del proyecto que disfruto mucho. Conforme fui avanzando, también me interesó cada vez más resolver esa integración entre herramientas y hardware. Las siguientes entradas recorren ese proceso: memoria, gráficos, creación de niveles y los sistemas necesarios para convertir una escena en un juego de PS1.</p>]]></content:encoded>
            <category>PS1</category>
            <category>Editor</category>
            <category>Hardware</category>
            <category>Flujo de trabajo</category>
        </item>
    </channel>
</rss>