Enero 27, 2015, 02:39:23 PM Ultima modificación: Enero 30, 2015, 07:05:55 PM por DarkKRuleR
Buenash! Pues dibujo un wall en 3D, pero necesito aplicarle un Skew (función de transform que tiene el editor de GM) vertical mediante código (mediante el editor le baja la calidad MUCHO, y no puedo estar haciendo skews constantemente). Alguien tiene idea?

Exactamente esto: Quizás alguna forma "eficiente" de pre-tratar la textura (sprite) antes de mandarla a la función de dibujo? (no sé nada del tema ni por dónde iniciar)

Y una duda auxiliar: cómo podría, quizás con el método anterior, fusionar dos sprites en una misma textura, para mandarla al d3d_draw_wall? (no quiero dibujar dos walls, problemas de z-fighting y eficiencia) Aprovechando que, quizás, aplico un skew por código al sprite ANTES de ponerlo en la textura (o antes de mandar la textura a dibujo) podría también añadir otro sprite encima del anterior, y hacer una textura con ambos sprites.

La forma más rápida sería dibujar el muro 3D con esa forma y aplicarle una textura normal. Otro método sería usar surfaces y primitivas 2D para transformar la textura y combinar sprites, algo así:
[gml]
///Evento Create

sf = surface_create( 64, 128 ); //crear superficie (es más alta que ancha)
tx = sprite_get_texture( spr, 0 ); //usar un sprite como textura (suponemos que mide 64x64)
texture_set_interpolation( true ); //para que la textura resultante no se vea pixelada

surface_set_target( sf );
draw_clear_alpha( 0, 0 ); //hacer la superficie transparente

    //Dibujar la textura con efecto "skew"
    draw_primitive_begin_texture( pr_trianglestrip, tx );
        draw_vertex_texture( 0,  64,  0,0 );
        draw_vertex_texture( 64, 0,   1,0 );
        draw_vertex_texture( 0,  128, 0,1 );
        draw_vertex_texture( 64, 64,  1,1 );
    draw_primitive_end();
   
    //Dibujar otro sprite en la superficie
    draw_sprite( spr, 0, x,y );
   
surface_reset_target();
[/gml]
Después obtienes el id de la textura transformada con surface_get_texture. Para evitar los inconvenientes de las surfaces, puedes crear un sprite o background a partir de esta superfice con sprite_create_from_surface ó background_create_from_surface.

#2 Enero 27, 2015, 10:03:37 PM Ultima modificación: Enero 27, 2015, 10:06:41 PM por DarkKRuleR
Muchas gracias! Lo de dibujar el muro 3D con esa forma usando primitiva y 4 vértices... era realmente fácil y se me pasó por alto, estaba demasiado enfocado en detalles >_< me abriste los ojos. Me he estado peleando unas buenas horas pero ya me funciona.

Respecto a lo otro ya tengo problemas.

var srf, text; srf = surface_create(64, 64);
surface_set_target(srf);
draw_clear_alpha(0, 0); //hacer la superficie transparente
draw_sprite(sprEliCabeza, 6, 0, 0);
draw_sprite(sprEliCabeza, 8, 0, 0);
text = surface_get_texture(srf);
surface_reset_target();


Tengo eso antes de dibujar, en teoría usando la textura text debería tener AMBOS sprites (subimagenes 6 y 8 ) a la vez, pero en su lugar no me dibuja nada ("ignora" las siguientes líneas de dibujo). Qué hago mal? Uso "text" tal cual donde debo introducir una textura.

#3 Enero 28, 2015, 01:54:13 AM Ultima modificación: Enero 28, 2015, 01:58:45 AM por Clamud
La variable text es local porque es declarada con var, al terminar la pieza de código se borra, y sería mejor usar surface_get_texture después de surface_reset_target. Si sigue sin funcionar, tal vez sea necesario desactivar el "culling" con d3d_set_culling( false ); antes de dibujar en la superficie.

#4 Enero 28, 2015, 10:12:53 PM Ultima modificación: Enero 28, 2015, 10:14:48 PM por DarkKRuleR
Sep, sé que text es local, la uso en la MISMA pieza de código en que la declaro. El problema es que no sólo ignora todos los dibujos de esa pieza, ignora las piezas siguientes...

Ya cambié a surface_get_textura DESPUÉS del reset_target, y el d3d_set_culling está a false desde el principio (para no preocuparme por el sentido de los vértices para los personajes, ya que para ellos desactivo la iluminación, así que no se calculará iluminación en sus vértices, así que no es costoso, por lo que no necesito el culling activo, creo). Sigue sin funcionar, qué puede pasar?

Ah, el código anterior lo tengo en draw, justo antes de usar la textura. Leí que las surfaces no se guardaban en memoria al hacer game_save y nosequé rollos, así que crearla en Create podría traer problemas... afecta?

Lo que puede causar problemas es que se usa la función surface_create en cada evento Draw, se están creando nuevas superficies sin borrar las anteriores, esto puede ralentizar el juego o llenar toda la memoria, si la nueva textura no cambia con el tiempo, conviene crearla una sola vez en el evento Create, o por lo menos usar la función surface_free antes de crear otra.

Lo demás parece estar bien, pero tal vez hay otra pieza de código que está borrando la textura (tal vez no hay suficiente memoria de textura y se sobrescribe), el manual recomienda verificar que la superficie existe antes de usarla con la función surface_exists.

Puede ser que el objeto que crea la surface tenga menor depth que los otros objetos que usan esa surface, entonces usan una surface creada en el step anterior y está corrupta, eso se solucionaría creándola en el evento Create.

Si persisten los problemas, lo mejor será convertir la surface en un sprite o background usando las funciones que mencioné anteriormente.

#6 Enero 30, 2015, 02:17:24 AM Ultima modificación: Enero 30, 2015, 02:59:42 AM por DarkKRuleR
Gracias, probé todo lo que me dijiste pero nada funcionó, hasta que hice este cambio.
text = sprite_get_texture(sprBlack, 0);
srf = surface_create(64, 64);

d3d_end();

surface_set_target(srf);
draw_clear_alpha(c_white, 0);
draw_sprite(sprEliCabeza, 6, 32, 32);
draw_sprite(sprEliCabeza, 8, 32, 32);
surface_reset_target();
text = surface_get_texture(srf);
//surface_free(srf);

d3d_start();


Tengo eso en CREATE, y usando text en el evento draw FUNCIONA!! Era clave (creo) desactivar el 3D, y declarar text ANTES de crear la surface, pero no lo entiendo... si descomento el surface_free LA TEXTURA NO SE... es decir, hace como si text fuera transparente, sin nada... no suelta error, dibuja todo igual, pero no dibuja la textura.. como si fuera transparente... cuando DEBERÍA hacerle free... ya que este código es probable que lo use en otro sitio, y deberé efectivamente ir liberando las surfaces... alguna idea sobre por qué pasa?

#7 Enero 30, 2015, 05:00:38 AM Ultima modificación: Enero 30, 2015, 05:02:37 AM por Clamud
¡Es cierto!, no contemplé el hecho de que el juego ya estuviera en modo 3D, mil disculpas, en ese caso lo recomendable es usar d3d_set_projection_ortho en vez de d3d_end, no estoy seguro pero es probable que esa maniobra también borre la surface. Si el código está en el evento Create no necesitas poner surface_free porque esa función borra la superficie, y no creo que importe el orden en el que se definen las variables text y srf.

#8 Enero 30, 2015, 07:05:39 PM Ultima modificación: Enero 30, 2015, 07:07:41 PM por DarkKRuleR
Muchas gracias por tu ayuda :D Bueno, no hice eso del projection_ortho, lo veía raro y no sabía volver al original. Tengo esto en Step:

// Pruebas
if (keyP(ord('P'))) {
    if (!surface_exists(surface64)) surface64 = surface_create(64, 64);
    d3d_end(); d3d_set_lighting(false);
   
    surface_set_target(surface64);
    draw_clear_alpha(c_white, 0);
    draw_sprite(sprEliCabeza, 6, 32, 32);
    draw_sprite(sprEliCabeza, 8, 32, 32);
    surface_reset_target();
    txtCabezaD = surface_get_texture(surface64);
   
    d3d_start(); d3d_set_lighting(true);
}


No logré darme cuenta que tenía que desactivar la iluminación, aún cuando se veía todo el sprite negro pero con el borde definido (sho ser tonto) pero ya funciona a la perfección. La surface la creo en el evento Create, y nunca hago free, ya uqe no hace falta: sólo habrá ESA y la usaré constantemente. En el caso en que el usuario, digamos, se equipa una armadura o un accesorio, el sprite de la parte del cuerpo cambia por ese mismo sprite + el accesorio, eso lo hago con la surface, chequeando si existe, si no la vuelvo a crear... y todo el rollo.

txtCabezaD es la textura que uso al dibujar. Declararé todas las texturas en Create, las usaré para dibujar, y cuando haga falta las cambio de esta manera.

En este caso espero que sólo el personaje principal usará la surface, y como mucho crearé 2-3, pero si más objetos, como otros personajes, necesitaran usar las surfaces.. bueno, no habría tanto problema, qué puede pasar por tener 3- 6 o 9 surfaces activas al mismo tiempo? Todas de tamaño 64x64 y 128x128. Mientras no tenga más de 10, eso sí

Problema resuelto y gracias :D!