Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines
(1 edit)

Originally, I believed it was the draw event, because it seemed like the lighting was applying normals. But I just commented out the draw event, while keeping the draw_sprite_pos in normal and material events, and nothing is being drawn. So for some reason draw_sprite_pos() doesn't appear to work in the normal and material draw events. If you want to try yourself, I just copied the "shadow_military_crate" obj and replaced the normal draw code with draw_sprite_pos in all of the draw events. 

 The manual says draw_sprite_pos has some limitations. Auto-crop and 9-slice should be disabled. I have done this.

It also says:

"WARNING! The image above is only for illustrative purposes, and if you use this function on a sprite, you will get different results and may experience texture "shearing" due to the way that a sprite is constructed from a quad of primitives."


I know there are a bunch of vertex buffers, so perhaps the failure to draw_sprite_pos  function has something to do with this?


{edit: I saw that an alternative to draw_sprite_pos is to draw primitives/vertex buffers, so I tried doing that too, and nothing is being drawn also]

Ah... looking at the function, I can tell it will not work.  It doesn't have an image_blend parameter.  Eclipse needs that to pack the other material or normal information.

It probably uses the default image_blend of the instance, so if you set image_blend to the right material or normal values like in the other user events before calling draw_sprite_pos it should work.  Just make sure to set image_blend back when doing the normal drawing.

Also the alpha value needs to be the same as in the other normal and material drawing events.

I added in the image_blend = material / image_blend = normal into the corresponding user events before draw_sprite_pos and it still does not work. I also tried draw_set_color before as well, but no success. Draw_sprite_pos() only works in the draw event.

(+1)

Those user events are being called by another draw event of the light engine, so they are called in draw event.

It sounds like they straight up do not use any vertex color with draw_sprite_pos then.  So, it is not possible to use as is.

Instead a primitive or vertex buffer would need to be used which supplies the correct vertex color as the same as image_blend for vertex color.

I can add the feature in the future.

It would be a great feature! Using draw_sprite_pos can create a parallax effect by modifying sprites based on camera position. It really creates an additional sense of depth for the top down perspective.

(+1)

Gotcha.  I'm currently in Hawaii and have no access to my dev computer, but I'll look into it when I get back in a few weeks.  

You could try using a vertex buffer or primitive in the meantime.  If you look at the shadow caster objects and the one that is like "textured" or something.  It is setup to use a path to define its polygon.  It won't do a stretch or skew, but it should use a vertex buffer which would use the format you need and there should be enough info there to make a version like draw_sprite_pos.

Also, it is worth confirming that there is no vertex color used in draw_sprite_pos.  Just make a blank project and draw with it while setting the global draw color or something.  See if you can get it to actually do different image blends or something.  If it actually does blend, then it is possible I just need to add something to get it working with the normal and material sprites.  

I checked, there is no draw_sprite_pos_ext or anything... that seems like it should exist though.  The extended version of most draw calls have image_blend, rotation, and alpha.  When I add the feature I'll basically just be adding that exact function since I'd say its simply a missing feature of GM itself.

(1 edit)

I used the __le_game object as a parent, then overrode the create/normal/material events with additional vertex buffer drawing, AND IT WORKED!

I'm very new to writing my own vertex buffers, but I understand that if you have dynamic shapes, you can't just store the data once since you are recalculating the coordinates. Is this correct for the normals draw event or do I have too much that could be moved to the create event (obviously I would make some of the vars into local variables)? (I just want to make sure I'm doing this efficiently, because it dips below 45 fps if I have like 8 objects drawing this on screen)

CREATE

////

event_inherited()

vertex_format_begin();

vertex_format_add_position_3d();

vertex_format_add_colour();

vertex_format_add_texcoord();

format = vertex_format_end();


USER EVENT 15

////


var _uv_data = sprite_get_uvs(normal_map, 0);

var _umin = _uv_data[0], _vmin = _uv_data[1], _umax = _uv_data[2], _vmax = _uv_data[3];

var vb = vertex_create_buffer();

vertex_begin(vb, format);

vertex_position_3d(vb,  bbox_left,  bbox_top, 0); vertex_color(vb, normal, LE_NORMAL_ANGLE); vertex_texcoord(vb, _umin, _vmin);

vertex_position_3d(vb, bbox_right,bbox_top, 0); vertex_color(vb, normal, LE_NORMAL_ANGLE); vertex_texcoord(vb, _umax, _vmin);

vertex_position_3d(vb,  mouse_x, mouse_y, 0); vertex_color(vb, normal, LE_NORMAL_ANGLE); vertex_texcoord(vb, _umin, _vmax);

vertex_position_3d(vb, mouse_x+100, mouse_y, 0); vertex_color(vb, normal, LE_NORMAL_ANGLE); vertex_texcoord(vb, _umax, _vmax);

vertex_end(vb);

var _tex = sprite_get_texture(normal_map, 0);

vertex_submit(vb, pr_trianglestrip, _tex);

That's good to hear.

So, this does mean that the default draw_sprite_pos does not include vertex color information.

There are things you can do to optimize a bit and I'll write a better function at some point as well. 

One thing that is important to check first though, is that you do not seem to be destroying the vertex buffer which will lead to a memory leak for sure.  You can destroy it and create a new one, or if the object is not moving or anything you can create the vertex buffer on create only once and then submit it in the user event like you have.  Then add some code to destroy the vertex buffer on the clean-up event.

Another thing is the macro LE_NORMAL_ANGLE performs some calculations, so instead of calling it for each vertex you should declare a local variable like "var _angle = LE_NORMAL_ANGLE;" and then use that local for the argument.

I can make the whole thing into a new object or function in the future with other optimizations.

Are you also having this cast shadow too?  Given the shape I would assume you need to use something like the shadow path object to get the correct polygon shape.  This might be a new object I should add that also is a shadow caster.  The shadow path object type is for more complex polygon shapes, and I never considered just a skewed/stretched rectangle which is more simple.

I was destroying the buffer in the clean-up, but then I switched to creating the buffer as a temporary var which I assumed wouldn't work in a separate event. I switched to a local variable for the buffer, so I don't have to keep creating and destroying it every draw event (which I assume is not efficient). I also used the var _angle suggestion for normal events. Still seeing a frame drop even with these modifications, but it seems better. There is a frame dip from 60 to 50 if I make the scale of the object bigger or place 6 of them on screen at once.

Yes! I plan on utilizing shadows if possible. A shadow path object that has the functionality of draw_sprite_pos would be incredibly helpful.

Creating a buffer with "var" does not matter, it is still a memory leak if you do not destroy it.  Having it created every single frame in the draw event is going to be much slower.  If it does not move then create it once and freeze the buffer.  If it moves you can create it, use and then destroy it.  Or use primitive drawing if it provides the right format for the vertex...I'd have to check.  

When you create any type of dynamic memory such as buffers, ds_lists, other ds structures, or surfaces, they are in memory until you destroy them manually.  Declaring a local variable with "var" only holds a reference to the memory, it still exists and still needs to be managed or you'll have a memory leak.  Even vertex formats can be destroyed, but those usually are very tiny and you make a couple that never need deleted until the game closes.

Note, that if something uses memory that will always persist until the game closes then you really do not have to destroy it.  When the game closes the entire heap will be freed by the OS.