buffer_copy_stride

此函数将给定数量的项目从源缓冲区复制到目标缓冲区,其中所有项目都具有相同的字节大小,并且在源缓冲区和目标缓冲区中均匀地间隔开不同数量的字节。

您可以将此函数与以结构化方式存储项目及其属性的缓冲区一起使用,例如游戏数据、顶点数据或任何其他已知格式的数据。

注意 您不能复制到同一缓冲区。

属于上图的函数调用如下所示:buffer_copy_stride(src_buffer, 6, 2, 6, 3, dest_buffer, 8, 2);

您可以将源偏移量解释为两个偏移量的总和:项目数据开头的偏移量和项目内的偏移量 (即要复制项目的哪个属性)。

Stride

步幅是从一个项目到下一个项目的字节数。正值向前移动,负值向后移动。

例如,对于 GameMaker默认顶点格式 ,步幅值为 24(3*4+4*1+2*​​4)。从缓冲区中的一个 (x, y, z) 位置移动到下一个位置的字节数为 24,从一个颜色值移动到下一个颜色值的字节数也是 24,以及从一个 UV 移动到下一个 UV 的字节数。

您可以通过更改偏移量 " 选择 " 要复制的属性,同时步幅保持不变:

怎么运行的

使用说明

 

语法:

buffer_copy_stride(src_buffer, src_offset, src_size, src_stride, src_count, dest_buffer, dest_offset, dest_stride);

参数类型描述
src_bufferBuffer包含源数据的缓冲区
src_offsetReal源缓冲区中开始复制字节的偏移量 (以字节为单位)。如果为负数,则从缓冲区大小中减去它。
src_sizeReal要复制的单个项目的大小 (以字节为单位)
src_strideReal两个项目之间的字节数。该值可以为负数并设置为 0。
src_countReal要复制的项目数
dest_bufferBuffer将数据复制到的缓冲区
dest_offsetReal用于写入数据的目标缓冲区中的偏移量 (以字节为单位)。该偏移量可以是负值。
dest_strideReal目标缓冲区中两个项目之间的字节数。该值可以为负值。

 

返回:

N/A

 

示例 1:基本用法

var _num_items = 200;
var _attribute_size = buffer_sizeof(buffer_u16);
var _itemsize_source = buffer_sizeof(buffer_f32) + _attribute_size;
buff_source = buffer_create(_num_items * _itemsize_source, buffer_fixed, 1);
buff_destination = buffer_create(_num_items * _attribute_size, buffer_fixed, 1);

var _i = 0;
repeat(_num_items)
{
    buffer_write(buff_source, buffer_f32, random_range(-100, 100));
    buffer_write(buff_source, buffer_u16, _i++);
}

buffer_copy_stride(buff_source, 4, _attribute_size, _itemsize_source, _num_items, buff_destination, 0, _attribute_size);

上面的代码显示了 buffer_copy_stride 函数的基本用法。首先,定义几个临时变量,用于存储源缓冲区和目标缓冲区中的项目数、源缓冲区的步幅和项目的大小。然后创建两个固定大小的缓冲区,一个用于存储源数据,一个用于存储目标数据。对它们的引用分别存储在变量 buff_sourcebuff_destination 中。接下来,使用 buffer_write 将 200 个项目写入源缓冲区。每一项都包含一个介于 -100 到 100 之间的随机 buffer_f32 值,后跟一个存储索引的 buffer_f16 值。最后,使用 buffer_copy_stride 将每个项目的第二个 buffer_f16 元素复制到目标缓冲区。第一个 buffer_f16 值写入字节 0( 因为 dest_offset 设置为 0),下一个值写入字节 2(dest_stride 设置为 _itemsize,即 2)、下一个到字节 4,依此类推。函数调用后,buff_destination 将依次包含 buff_source 中的 200 个 buffer_f16 值,中间没有字节。

 

示例 2:负偏移量和负偏移量跨步

var _item_size = buffer_sizeof(buffer_f32);
var _num_items = 100;

var _i = 0;
buff_numbers = buffer_create(_num_items * _item_size, buffer_fixed, 4);
repeat(_num_items) buffer_write(buff_numbers, buffer_f32, _i++);

buff_data = buffer_create(2048, buffer_fixed, 4);
buffer_copy_stride(buff_numbers, -_item_size, _item_size, -_item_size, _num_items, buff_data, 0, 12);

上述代码首先初始化以下代码中使用的两个临时变量:单个项目的大小 _item_size 和项目数量 _num_items。然后,它创建一个固定大小的新缓冲区,为该数量的项目提供空间。字节对齐可以设置为 4,因为每个项目都以 4 字节的整数倍存储。接下来,repeat 循环使用 buffer_write 将 0 到 100 的值写入缓冲区。之后,创建另一个 2048 字节的固定大小缓冲区并将其存储在变量 buff_data 中。最后,调用 buffer_copy_stride 将源缓冲区 buff_numbers 中的数字写入目标缓冲区 buff_data。由于源偏移量为负值,缓冲区中的最后一个数字是第一个要写入的数字。此外,由于源步幅为负值,数字会向后遍历。目标步幅为 12 可确保 buff_data 中的数字间隔 12 个字节。因此,buff_data 包含相反顺序的数字,每个数字之间有 12 个字节。

 

示例 3:步幅设置为 0

var _item_size = buffer_sizeof(buffer_f32);
buff_source = buffer_create(_item_size, buffer_fixed, 4);
buff_destination = buffer_create(16 * _item_size, buffer_fixed, 4);

buffer_write(buff_source, buffer_f32, 1);

buffer_copy_stride(buff_source, 0, _item_size, 0, 4, buff_destination, 0, 5 * _item_size);

上面的代码显示了如何使用步长值 0 来多次将相同的值复制到目标缓冲区。

首先,项目的大小设置为浮点数 (buffer_f32) 的大小并存储在 _item_size 中。接下来,使用固定大小和 4 对齐方式创建源缓冲区和目标缓冲区 (因为浮点数始终与 4 字节的倍数对齐)。源缓冲区只能存储单个浮点数,目标缓冲区可以存储 16 个浮点数。然后,值 1 被写入源缓冲区。最后,使用 buffer_copy_stride 将该值总共复制 4 次,目标步幅值为项目大小的 5 倍。函数完成后,buff_destination 将包含 单位矩阵 的值。

 

示例 4:交错来自多个缓冲区的数据

Create Event

vertex_format_begin();
array_foreach([vertex_format_add_position_3d, vertex_format_add_colour, vertex_format_add_texcoord], script_execute);
vertex_format = vertex_format_end();

buff_positions_xyz = buffer_base64_decode("JqwCQwuLi0J5DIBBcQc3Q27Ar0NNpBZD+WSqQ8B9OEPB0YtD");
buff_colours_rgba = buffer_base64_decode("Ud93/wghI//D2cr/");
buff_uvs = buffer_base64_decode("9KQyP69/UT9Uxak+ybENPzKNZzwxS1A9");

buff_vertex_data = buffer_create(3 * 24, buffer_fixed, 1);
buffer_copy_stride(buff_positions_xyz, 0, 3 * 4, 3 * 4, 3, buff_vertex_data, 0, 24);
buffer_copy_stride(buff_colours_rgba, 0, 4 * 1, 4 * 1, 3, buff_vertex_data, 12, 24);
buffer_copy_stride(buff_uvs, 0, 2 * 4, 2 * 4, 3, buff_vertex_data, 16, 24);
vb = vertex_create_buffer_from_buffer(buff_vertex_data, vertex_format);

Draw Event

vertex_submit(vb, pr_trianglelist, -1);

上面的示例展示了如何将作为属性存储在单独缓冲区中的数据连接在一起。数据被组合到单个缓冲区中,其中数据是 交错 的。

首先,在 Create 事件中,创建默认顶点格式并将其分配给实例变量 vertex_format。然后,根据 Base64 编码数据创建包含属性数据的三个缓冲区:buff_positions_xyz 存储 3 个顶点的 (x, y, z) 位置数据,buff_colours_rgba 存储其 RGBA 颜色数据,buff_uvs 他们的 UV 数据。每个属性的值依次存储,例如 buff_positions_xyz 存储第一个顶点的 (x, y, z) 位置,然后是第二个顶点的 (x, y, z) 位置,然后是第三个顶点的位置,依此类推。

之后,创建另一个缓冲区 buff_vertex_data 来存储交错的顶点数据。然后,对 buffer_copy_stride 的三个调用中的每一个都会读取每个属性的值 (位置、颜色和 uv),并将它们放置在目标缓冲区中的正确位置,为要写入的其他属性留出空间通过下一次调用该函数。最后根据缓冲区中的数据创建顶点缓冲区。

在 Draw 事件中,顶点缓冲区被提交。这将绘制一个三角形。