Initial commit
This commit is contained in:
commit
dd58a721ec
8 changed files with 617 additions and 0 deletions
4
README.md
Normal file
4
README.md
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
Custom projectile system for GameMaker.
|
||||||
|
Makes it easier to make 3d particles.
|
||||||
|
|
||||||
|

|
||||||
6
build-linux.sh
Executable file
6
build-linux.sh
Executable file
|
|
@ -0,0 +1,6 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euxo pipefail
|
||||||
|
|
||||||
|
odin build . -build-mode:shared -target:linux_amd64 -o:speed -extra-linker-flags:-fPIC \
|
||||||
|
-out:../../project/extensions/exK3PlusProjectileEffectManager/libk3plus_projectile_effect_manager.so
|
||||||
|
../bin/regenerate_extension . ../../project/extensions/exK3PlusProjectileEffectManager/exK3PlusProjectileEffectManager.yy
|
||||||
4
build-windows.bat
Normal file
4
build-windows.bat
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
set OUT="..\..\project\extensions\exK3PlusProjectileEffectManager\libk3plus_projectile_effect_manager.dll"
|
||||||
|
set EXTENSION="..\..\project\extensions\exK3PlusProjectileEffectManager\exK3PlusProjectileEffectManager.yy"
|
||||||
|
odin build . -build-mode:shared -target:windows_amd64 -o:speed -out:%OUT%
|
||||||
|
..\bin\regenerate_extension.exe . %EXTENSION%
|
||||||
BIN
images/demo.mp4
Normal file
BIN
images/demo.mp4
Normal file
Binary file not shown.
347
main.odin
Normal file
347
main.odin
Normal file
|
|
@ -0,0 +1,347 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "base:runtime"
|
||||||
|
import "core:fmt"
|
||||||
|
import "core:math"
|
||||||
|
|
||||||
|
double :: f64
|
||||||
|
v2 :: [2]f32
|
||||||
|
v3 :: [3]f32
|
||||||
|
v4 :: [4]f32
|
||||||
|
Color :: [4]byte
|
||||||
|
|
||||||
|
System :: struct {
|
||||||
|
particle_number: int,
|
||||||
|
index: int,
|
||||||
|
tpage_size: int,
|
||||||
|
vertices: [^]Vertex,
|
||||||
|
instances: [^]Instance,
|
||||||
|
}
|
||||||
|
|
||||||
|
Instance :: struct {
|
||||||
|
life: int,
|
||||||
|
image_uv_width: f32,
|
||||||
|
image_index, image_speed, image_number: f32,
|
||||||
|
position, speed, gravity: v3,
|
||||||
|
image_blend, image_blend_add: v4,
|
||||||
|
scale, grow: v2,
|
||||||
|
image_angle, image_angle_speed: f32,
|
||||||
|
hsv, hsv_add: v3,
|
||||||
|
}
|
||||||
|
|
||||||
|
Vertex :: struct {
|
||||||
|
position: v3,
|
||||||
|
color: Color,
|
||||||
|
texcoord: v2,
|
||||||
|
offset: v3,
|
||||||
|
scale: v2,
|
||||||
|
angle: f32,
|
||||||
|
rotation_direction: v3,
|
||||||
|
animation: f32,
|
||||||
|
hsv: v3,
|
||||||
|
}
|
||||||
|
|
||||||
|
system_current: ^System
|
||||||
|
|
||||||
|
pem_show_error :: proc(message: string, loc: runtime.Source_Code_Location) {
|
||||||
|
context = context
|
||||||
|
fmt.println("Error (", loc.procedure, ") L", loc.line, ": ", message, sep = "")
|
||||||
|
}
|
||||||
|
|
||||||
|
@(export)
|
||||||
|
pem_get_size :: proc "c" (number: double) -> double {
|
||||||
|
number := int(number)
|
||||||
|
system := size_of(System)
|
||||||
|
vertices := _projectile_system_get_vertex_buffer_size(number)
|
||||||
|
instances := size_of(Instance) * number
|
||||||
|
return double(system + vertices + instances)
|
||||||
|
}
|
||||||
|
|
||||||
|
@(export)
|
||||||
|
pem_get_vertex_buffer_size :: proc "c" (number: double) -> double {
|
||||||
|
return double(_projectile_system_get_vertex_buffer_size(int(number)))
|
||||||
|
}
|
||||||
|
|
||||||
|
_projectile_system_get_vertex_buffer_size :: proc "c" (number: int) -> int {
|
||||||
|
return size_of(Vertex) * 6 * number
|
||||||
|
}
|
||||||
|
|
||||||
|
@(export)
|
||||||
|
pem_get_vertex_buffer_offset :: proc "c" () -> double {
|
||||||
|
return double(_projectile_system_get_vertex_buffer_offset())
|
||||||
|
}
|
||||||
|
|
||||||
|
_projectile_system_get_vertex_buffer_offset :: proc "c" () -> int {
|
||||||
|
return size_of(System)
|
||||||
|
}
|
||||||
|
|
||||||
|
@(export)
|
||||||
|
pem_init :: proc "c" (memory: [^]byte, particle_number, tpage_size: double) {
|
||||||
|
context = runtime.default_context()
|
||||||
|
particle_number := int(particle_number)
|
||||||
|
system := cast(^System)memory
|
||||||
|
system.particle_number = particle_number
|
||||||
|
system.tpage_size = int(tpage_size)
|
||||||
|
system.index = 0
|
||||||
|
vertex_buffer_offset := _projectile_system_get_vertex_buffer_offset()
|
||||||
|
system.vertices = cast([^]Vertex)&memory[vertex_buffer_offset]
|
||||||
|
instance_buffer_offset := vertex_buffer_offset + _projectile_system_get_vertex_buffer_size(particle_number)
|
||||||
|
system.instances = cast([^]Instance)&memory[instance_buffer_offset]
|
||||||
|
}
|
||||||
|
|
||||||
|
@(export)
|
||||||
|
_pem_update :: proc "c" (system: ^System) {
|
||||||
|
vertices := system.vertices
|
||||||
|
instances := system.instances
|
||||||
|
for i in 0 ..< system.particle_number {
|
||||||
|
instances[i].life = max(instances[i].life - 1, -1)
|
||||||
|
if instances[i].life == 0 {
|
||||||
|
instances[i].grow = v2{0.0, 0.0}
|
||||||
|
instances[i].image_blend.a = 0.0
|
||||||
|
instances[i].image_blend_add.a = 0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
instances[i].speed += instances[i].gravity
|
||||||
|
instances[i].position += instances[i].speed
|
||||||
|
instances[i].image_blend += instances[i].image_blend_add
|
||||||
|
instances[i].scale += instances[i].grow
|
||||||
|
instances[i].image_angle += instances[i].image_angle_speed
|
||||||
|
instances[i].image_index = math.wrap(instances[i].image_index + instances[i].image_speed, instances[i].image_number)
|
||||||
|
instances[i].hsv = v3 {
|
||||||
|
instances[i].hsv.x + instances[i].hsv_add.x,
|
||||||
|
clamp(instances[i].hsv.y + instances[i].hsv_add.y, 0.0, 2.0),
|
||||||
|
clamp(instances[i].hsv.z + instances[i].hsv_add.z, 0.0, 2.0),
|
||||||
|
}
|
||||||
|
offset := i * 6
|
||||||
|
#unroll for j in 0 ..< 6 {
|
||||||
|
vertices[offset + j].color = {
|
||||||
|
u8(clamp(instances[i].image_blend.r, 0, 255)),
|
||||||
|
u8(clamp(instances[i].image_blend.g, 0, 255)),
|
||||||
|
u8(clamp(instances[i].image_blend.b, 0, 255)),
|
||||||
|
u8(clamp(instances[i].image_blend.a, 0, 255)),
|
||||||
|
}
|
||||||
|
vertices[offset + j].offset = instances[i].position
|
||||||
|
vertices[offset + j].scale = instances[i].scale
|
||||||
|
vertices[offset + j].angle = instances[i].image_angle
|
||||||
|
vertices[offset + j].animation = math.floor(instances[i].image_index) * instances[i].image_uv_width
|
||||||
|
vertices[offset + j].hsv = instances[i].hsv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@(export)
|
||||||
|
_pem_set :: proc "c" (system: ^System) {
|
||||||
|
system_current = system
|
||||||
|
}
|
||||||
|
|
||||||
|
Origin :: enum {
|
||||||
|
TopLeft,
|
||||||
|
TopMiddle,
|
||||||
|
TopRight,
|
||||||
|
MiddleLeft,
|
||||||
|
Middle,
|
||||||
|
MiddleRight,
|
||||||
|
BottomLeft,
|
||||||
|
BottomMiddle,
|
||||||
|
BottomRight,
|
||||||
|
}
|
||||||
|
|
||||||
|
@(export)
|
||||||
|
pem_instance_create_origin :: proc "c" (x, y, w, h, origin, uv_left, uv_top, uv_right, uv_bottom, image_number: double) -> double {
|
||||||
|
xorigin, yorigin: double
|
||||||
|
origin := Origin(int(origin))
|
||||||
|
switch origin {
|
||||||
|
case .TopLeft:
|
||||||
|
xorigin = 0.0; yorigin = 0.0
|
||||||
|
case .TopMiddle:
|
||||||
|
xorigin = w / 2.0; yorigin = 0.0
|
||||||
|
case .TopRight:
|
||||||
|
xorigin = w; yorigin = 0.0
|
||||||
|
case .MiddleLeft:
|
||||||
|
xorigin = 0.0; yorigin = h / 2.0
|
||||||
|
case .Middle:
|
||||||
|
xorigin = w / 2.0; yorigin = h / 2.0
|
||||||
|
case .MiddleRight:
|
||||||
|
xorigin = w; yorigin = h / 2.0
|
||||||
|
case .BottomLeft:
|
||||||
|
xorigin = 0.0; yorigin = h
|
||||||
|
case .BottomMiddle:
|
||||||
|
xorigin = w; yorigin = h
|
||||||
|
case .BottomRight:
|
||||||
|
xorigin = w / 2.0; yorigin = h
|
||||||
|
}
|
||||||
|
return pem_instance_create(x, y, w, h, xorigin, yorigin, uv_left, uv_top, uv_right, uv_bottom, image_number)
|
||||||
|
}
|
||||||
|
|
||||||
|
@(export)
|
||||||
|
pem_instance_create :: proc "c" (x, y, w, h, xorigin, yorigin, uv_left, uv_top, uv_right, uv_bottom, image_number: double) -> double {
|
||||||
|
position := v3{f32(x), f32(y), 1.0}
|
||||||
|
size := v3{f32(w), f32(h), 1.0}
|
||||||
|
origin := v3{f32(xorigin), f32(yorigin), 0.0}
|
||||||
|
uv_left := f32(uv_left)
|
||||||
|
uv_right := f32(uv_right)
|
||||||
|
uv_top := f32(uv_top)
|
||||||
|
uv_bottom := f32(uv_bottom)
|
||||||
|
image_number := f32(max(0.0, image_number))
|
||||||
|
|
||||||
|
uv_tl := v2{uv_left, uv_top}
|
||||||
|
uv_br := v2{uv_left + (uv_right - uv_left) / image_number, uv_bottom}
|
||||||
|
|
||||||
|
index := system_current.index
|
||||||
|
offset := system_current.index * 6
|
||||||
|
system_current.index = (system_current.index + 1) % system_current.particle_number
|
||||||
|
system_current.instances[index] = {
|
||||||
|
life = -1,
|
||||||
|
image_uv_width = (uv_right - uv_left) / image_number,
|
||||||
|
image_index = 0.0,
|
||||||
|
image_number = image_number,
|
||||||
|
image_speed = 1.0,
|
||||||
|
position = position,
|
||||||
|
image_blend = {255.0, 255.0, 255.0, 255.0},
|
||||||
|
scale = {1.0, 1.0},
|
||||||
|
image_angle = 0.0,
|
||||||
|
hsv = {0.0, 1.0, 1.0},
|
||||||
|
}
|
||||||
|
|
||||||
|
tl := v3{0.0, 0.0, 1.0}
|
||||||
|
tr := v3{1.0, 0.0, 1.0}
|
||||||
|
bl := v3{0.0, 1.0, 1.0}
|
||||||
|
br := v3{1.0, 1.0, 1.0}
|
||||||
|
pos := [6]v3{tl, bl, tr, tr, bl, br}
|
||||||
|
#unroll for i in 0 ..< 6 {
|
||||||
|
system_current.vertices[offset + i] = {
|
||||||
|
position = pos[i] * size - origin,
|
||||||
|
color = {255, 255, 255, 255},
|
||||||
|
texcoord = math.lerp(uv_tl, uv_br, pos[i].xy),
|
||||||
|
offset = system_current.instances[index].position,
|
||||||
|
scale = system_current.instances[index].scale,
|
||||||
|
angle = system_current.instances[index].image_angle,
|
||||||
|
rotation_direction = v3{0.0, 0.0, -1.0},
|
||||||
|
hsv = system_current.instances[index].hsv,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return double(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
@(export)
|
||||||
|
pem_instance_set_life :: proc "c" (id, life: double) {
|
||||||
|
system_current.instances[int(id)].life = int(life)
|
||||||
|
}
|
||||||
|
|
||||||
|
@(export)
|
||||||
|
pem_instance_set_life_to_animation :: proc "c" (id, animation_count: double) {
|
||||||
|
id := int(id)
|
||||||
|
image_number_from_index := system_current.instances[id].image_number - system_current.instances[id].image_index
|
||||||
|
if image_number_from_index <= 0.0 {
|
||||||
|
context = runtime.default_context()
|
||||||
|
pem_show_error("image number left is 0", #location())
|
||||||
|
system_current.instances[id].life = -1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
system_current.instances[id].life = int(image_number_from_index / system_current.instances[id].image_speed) * int(animation_count)
|
||||||
|
}
|
||||||
|
|
||||||
|
@(export)
|
||||||
|
pem_instance_set_life_to_alpha_fade :: proc "c" (id: double) {
|
||||||
|
id := int(id)
|
||||||
|
a := system_current.instances[id].image_blend.a
|
||||||
|
a_add := system_current.instances[id].image_blend_add.a
|
||||||
|
if a <= 0.0 {
|
||||||
|
context = runtime.default_context()
|
||||||
|
pem_show_error("alpha started at 0.0 or lower", #location())
|
||||||
|
system_current.instances[id].life = -1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
frames := int((a / a_add) * -1.0)
|
||||||
|
if frames <= 0 {
|
||||||
|
context = runtime.default_context()
|
||||||
|
pem_show_error("alpha never reaches 0.0", #location())
|
||||||
|
system_current.instances[id].life = -1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
system_current.instances[id].life = frames
|
||||||
|
}
|
||||||
|
|
||||||
|
@(export)
|
||||||
|
pem_instance_set_life_to_shrink :: proc "c" (id: double) {
|
||||||
|
id := int(id)
|
||||||
|
scale := v2{system_current.instances[id].scale.x, system_current.instances[id].scale.y}
|
||||||
|
grow := v2{system_current.instances[id].grow.x, system_current.instances[id].grow.y}
|
||||||
|
frames := v2{scale.x / grow.x * -1.0, scale.y / grow.y * -1.0}
|
||||||
|
frames_max := max(frames.x, frames.y)
|
||||||
|
if frames_max <= 0.0 {
|
||||||
|
context = runtime.default_context()
|
||||||
|
pem_show_error("instance never shrinks in on itself", #location())
|
||||||
|
system_current.instances[id].life = -1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
system_current.instances[id].life = int(frames_max)
|
||||||
|
}
|
||||||
|
|
||||||
|
@(export)
|
||||||
|
pem_instance_set_image_blend :: proc "c" (id, r, g, b, a: double) {
|
||||||
|
system_current.instances[int(id)].image_blend = {f32(r), f32(g), f32(b), f32(a)} * 255.0
|
||||||
|
}
|
||||||
|
|
||||||
|
@(export)
|
||||||
|
pem_instance_set_image_blend_add :: proc "c" (id, r, g, b, a: double) {
|
||||||
|
system_current.instances[int(id)].image_blend_add = {f32(r), f32(g), f32(b), f32(a)} * 255.0
|
||||||
|
}
|
||||||
|
|
||||||
|
@(export)
|
||||||
|
pem_instance_set_speed :: proc "c" (id, hspeed, vspeed: double) {
|
||||||
|
system_current.instances[int(id)].speed = {f32(hspeed), f32(vspeed), 0.0}
|
||||||
|
}
|
||||||
|
|
||||||
|
@(export)
|
||||||
|
pem_instance_set_gravity :: proc "c" (id, x, y: double) {
|
||||||
|
system_current.instances[int(id)].gravity = {f32(x), f32(y), 0.0}
|
||||||
|
}
|
||||||
|
|
||||||
|
@(export)
|
||||||
|
pem_instance_set_scale :: proc "c" (id, xscale, yscale: double) {
|
||||||
|
system_current.instances[int(id)].scale = {f32(xscale), f32(yscale)}
|
||||||
|
}
|
||||||
|
|
||||||
|
@(export)
|
||||||
|
pem_instance_set_grow :: proc "c" (id, xgrow, ygrow: double) {
|
||||||
|
system_current.instances[int(id)].grow = {f32(xgrow), f32(ygrow)}
|
||||||
|
}
|
||||||
|
|
||||||
|
@(export)
|
||||||
|
pem_instance_set_image_angle :: proc "c" (id, angle: double) {
|
||||||
|
system_current.instances[int(id)].image_angle = f32(angle) * math.RAD_PER_DEG
|
||||||
|
}
|
||||||
|
|
||||||
|
@(export)
|
||||||
|
pem_instance_set_image_angle_speed :: proc "c" (id, angular_velocity: double) {
|
||||||
|
system_current.instances[int(id)].image_angle_speed = f32(angular_velocity) * math.RAD_PER_DEG
|
||||||
|
}
|
||||||
|
|
||||||
|
@(export)
|
||||||
|
pem_instance_set_image_angle_direction :: proc "c" (id, x, y, z: double) {
|
||||||
|
offset := int(id) * 6
|
||||||
|
#unroll for i in 0 ..< 6 {
|
||||||
|
system_current.vertices[offset + i].rotation_direction = {f32(x), f32(y), f32(z)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@(export)
|
||||||
|
pem_instance_set_image_index :: proc "c" (id, index: double) {
|
||||||
|
system_current.instances[int(id)].image_index = f32(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
@(export)
|
||||||
|
pem_instance_set_image_speed :: proc "c" (id, speed: double) {
|
||||||
|
system_current.instances[int(id)].image_speed = f32(speed)
|
||||||
|
}
|
||||||
|
|
||||||
|
@(export)
|
||||||
|
pem_instance_set_hsv :: proc "c" (id, h, s, v: double) {
|
||||||
|
system_current.instances[int(id)].hsv = v3{f32(h) / 360.0, f32(s) / 100.0, f32(v) / 100.0}
|
||||||
|
}
|
||||||
|
|
||||||
|
@(export)
|
||||||
|
pem_instance_set_hsv_add :: proc "c" (id, h, s, v: double) {
|
||||||
|
system_current.instances[int(id)].hsv_add = v3{f32(h) / 360.0, f32(s) / 100.0, f32(v) / 100.0}
|
||||||
|
}
|
||||||
184
scrProjectileEffectManager.gml
Normal file
184
scrProjectileEffectManager.gml
Normal file
|
|
@ -0,0 +1,184 @@
|
||||||
|
///@param {Id.Buffer} memory
|
||||||
|
///@param {Pointer} system
|
||||||
|
///@param {Id.vertex_format} vertex_format
|
||||||
|
///@param {Id.vertex_buffer} vertex_buffer
|
||||||
|
///@param {Real} projectile_count
|
||||||
|
///@param {Struct.Texturepage} texturepage
|
||||||
|
///@param {Id.DsList} effects
|
||||||
|
function _ProjectileEffectSystem(memory, system, vertex_format, vertex_buffer, projectile_count, texturepage, effects) constructor {
|
||||||
|
self.memory = memory;
|
||||||
|
self.system = system;
|
||||||
|
self.vertex_format = vertex_format;
|
||||||
|
self.vertex_buffer = vertex_buffer;
|
||||||
|
self.projectile_count = projectile_count;
|
||||||
|
self.texturepage = texturepage;
|
||||||
|
self.effects = effects;
|
||||||
|
}
|
||||||
|
|
||||||
|
///@param {Function} create_func
|
||||||
|
///@param {Real} interval
|
||||||
|
///@param {Id.DsList} list
|
||||||
|
function _ProjectileEffectSystemEffect(create_func, interval, list) constructor {
|
||||||
|
self.interval = interval;
|
||||||
|
self.time = 0;
|
||||||
|
self.instances = list;
|
||||||
|
self.create_func = create_func;
|
||||||
|
}
|
||||||
|
|
||||||
|
///@param {Real} projectile_count
|
||||||
|
///@return {_ProjectileEffectSystem}
|
||||||
|
function pem_create(projectile_count, texturepage) {
|
||||||
|
vertex_format_begin();
|
||||||
|
vertex_format_add_position_3d();
|
||||||
|
vertex_format_add_color();
|
||||||
|
vertex_format_add_texcoord();
|
||||||
|
vertex_format_add_custom(vertex_type_float3, vertex_usage_color); // Position
|
||||||
|
vertex_format_add_custom(vertex_type_float2, vertex_usage_color); // Scale
|
||||||
|
vertex_format_add_custom(vertex_type_float1, vertex_usage_color); // Angle
|
||||||
|
vertex_format_add_custom(vertex_type_float3, vertex_usage_color); // Rotation direction
|
||||||
|
vertex_format_add_custom(vertex_type_float1, vertex_usage_color); // Animation
|
||||||
|
vertex_format_add_custom(vertex_type_float3, vertex_usage_color); // Hue saturation value
|
||||||
|
var _vertex_format = vertex_format_end();
|
||||||
|
|
||||||
|
var _buffer = buffer_create(pem_get_size(projectile_count), buffer_fixed, 1);
|
||||||
|
buffer_fill(_buffer, 0, buffer_u32, 0, buffer_get_size(_buffer));
|
||||||
|
var _ptr = buffer_get_address(_buffer);
|
||||||
|
pem_init(_ptr, projectile_count, TEXTUREPAGE_SIZE);
|
||||||
|
var _vertex_buffer = vertex_create_buffer_from_buffer_ext(
|
||||||
|
_buffer,
|
||||||
|
_vertex_format,
|
||||||
|
pem_get_vertex_buffer_offset(),
|
||||||
|
projectile_count * 6);
|
||||||
|
return new _ProjectileEffectSystem(_buffer, _ptr, _vertex_format, _vertex_buffer, projectile_count, texturepage, ds_list_create());
|
||||||
|
}
|
||||||
|
|
||||||
|
///@param {Struct._ProjectileEffectSystem} system
|
||||||
|
///@param {Function} create_func
|
||||||
|
///@param {Real} interval
|
||||||
|
function pem_effect_add(system, create_func, interval) {
|
||||||
|
if (interval <= 0.0) {
|
||||||
|
printerr("Interval cannot be equal or lower than 0.0", ERROR_LOC);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var _effect = new _ProjectileEffectSystemEffect(create_func, interval, ds_list_create());
|
||||||
|
ds_list_add(system.effects, _effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
///@param {Struct._ProjectileEffectSystem} system
|
||||||
|
///@param {Real} index
|
||||||
|
///@param {Id.Instance} inst
|
||||||
|
function pem_effect_instance_add(system, index, inst) {
|
||||||
|
ds_list_add(system.effects[|index].instances, inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
///@param {Struct._ProjectileEffectSystemEffect} effect
|
||||||
|
function _pem_effect_destroy(effect) {
|
||||||
|
ds_list_destroy(effect.instances);
|
||||||
|
}
|
||||||
|
|
||||||
|
///@param {Struct._ProjectileEffectSystem} system
|
||||||
|
function pem_update_vertex_buffer(system) {
|
||||||
|
vertex_update_buffer_from_buffer(
|
||||||
|
system.vertex_buffer,
|
||||||
|
0,
|
||||||
|
system.memory,
|
||||||
|
pem_get_vertex_buffer_offset(),
|
||||||
|
pem_get_vertex_buffer_size(system.projectile_count));
|
||||||
|
}
|
||||||
|
|
||||||
|
///@param {Struct._ProjectileEffectSystem} system
|
||||||
|
function pem_destroy(system) {
|
||||||
|
buffer_delete(system.memory);
|
||||||
|
vertex_format_delete(system.vertex_format);
|
||||||
|
vertex_delete_buffer(system.vertex_buffer);
|
||||||
|
for (var i = 0, n = ds_list_size(system.effects); i < n; i++) {
|
||||||
|
_pem_effect_destroy(system.effects[|i]);
|
||||||
|
}
|
||||||
|
ds_list_destroy(system.effects);
|
||||||
|
}
|
||||||
|
|
||||||
|
///@param {Struct._ProjectileEffectSystem} system
|
||||||
|
function pem_update(system) {
|
||||||
|
for (var i = 0, n = ds_list_size(system.effects); i < n; i++) {
|
||||||
|
var _effect = system.effects[|i];
|
||||||
|
_effect.time += 1.0;
|
||||||
|
while (_effect.time >= _effect.interval) {
|
||||||
|
_effect.time -= _effect.interval;
|
||||||
|
for (var j = 0, nn = ds_list_size(_effect.instances); j < nn; j++) {
|
||||||
|
if (!instance_exists(_effect.instances[|j])) {
|
||||||
|
ds_list_delete(_effect.instances, j);
|
||||||
|
j--;
|
||||||
|
nn--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_effect.create_func(system, _effect.instances[|j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_pem_update(system.system);
|
||||||
|
pem_update_vertex_buffer(system);
|
||||||
|
}
|
||||||
|
|
||||||
|
///@param {Struct._ProjectileEffectSystem} system
|
||||||
|
function pem_set(system) {
|
||||||
|
_pem_set(system.system);
|
||||||
|
}
|
||||||
|
|
||||||
|
///@param {Struct._ProjectileEffectSystem} system
|
||||||
|
function pem_draw(system) {
|
||||||
|
shader_set(shdProjectileEffect);
|
||||||
|
vertex_submit(system.vertex_buffer, pr_trianglelist, system.texturepage.texture);
|
||||||
|
shader_reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
///@param {Struct._ProjectileEffectSystem} system
|
||||||
|
///@param {Real} x
|
||||||
|
///@param {Real} y
|
||||||
|
///@param {Asset.GMSprite} sprite_index
|
||||||
|
function pem_instance_create_from_sprite(system, x, y, sprite_index) {
|
||||||
|
var _info = texturepage_sprite_get_info(system.texturepage, sprite_index);
|
||||||
|
if (_info == -1) {
|
||||||
|
printerr($"Couldn't create effect instance with sprite {sprite_get_name(sprite_index)}. It wasn't on the texture page", ERROR_LOC);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return pem_instance_create_from_info(x, y, _info);
|
||||||
|
}
|
||||||
|
|
||||||
|
///@param {Struct._ProjectileEffectSystem} system
|
||||||
|
///@param {Real} x
|
||||||
|
///@param {Real} y
|
||||||
|
///@param {Real} sprite_origin
|
||||||
|
///@param {Asset.GMSprite} sprite_index
|
||||||
|
function pem_instance_create_from_sprite_ext(system, x, y, origin, sprite_index) {
|
||||||
|
var _info = texturepage_sprite_get_info(system.texturepage, sprite_index);
|
||||||
|
if (_info == -1) {
|
||||||
|
printerr("Couldn't create effect instance with sprite {sprite_get_name(sprite_index)}. It wasn't on the texture page", ERROR_LOC);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return pem_instance_create_from_info_ext(x, y, origin, _info);
|
||||||
|
}
|
||||||
|
|
||||||
|
///@param {Real} x
|
||||||
|
///@param {Real} y
|
||||||
|
///@param {Struct.TexturepageEntryInfo} info
|
||||||
|
function pem_instance_create_from_info(x, y, info) {
|
||||||
|
return pem_instance_create(
|
||||||
|
x, y,
|
||||||
|
sprite_get_width(info.sprite_index), sprite_get_height(info.sprite_index),
|
||||||
|
sprite_get_xoffset(info.sprite_index), sprite_get_yoffset(info.sprite_index),
|
||||||
|
info.uvs[UvData.Left], info.uvs[UvData.Top], info.uvs[UvData.Right], info.uvs[UvData.Bottom],
|
||||||
|
sprite_get_number(info.sprite_index));
|
||||||
|
}
|
||||||
|
|
||||||
|
///@param {Real} x
|
||||||
|
///@param {Real} y
|
||||||
|
///@param {Real} sprite_origin
|
||||||
|
///@param {Struct.TexturepageEntryInfo} info
|
||||||
|
function pem_instance_create_from_info_ext(x, y, sprite_origin, info) {
|
||||||
|
return pem_instance_create_origin(
|
||||||
|
x, y,
|
||||||
|
sprite_get_width(info.sprite_index), sprite_get_height(info.sprite_index),
|
||||||
|
sprite_origin,
|
||||||
|
info.uvs[UvData.Left], info.uvs[UvData.Top], info.uvs[UvData.Right], info.uvs[UvData.Bottom],
|
||||||
|
sprite_get_number(info.sprite_index));
|
||||||
|
}
|
||||||
31
shdProjectileEffect.fsh
Normal file
31
shdProjectileEffect.fsh
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
varying vec2 v_vTexcoord;
|
||||||
|
varying vec4 v_vColour;
|
||||||
|
varying vec3 v_vHsv;
|
||||||
|
|
||||||
|
vec3 rgb2hsv(vec3 c) {
|
||||||
|
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
||||||
|
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
|
||||||
|
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
|
||||||
|
float d = q.x - min(q.w, q.y);
|
||||||
|
float e = 1.0e-10;
|
||||||
|
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 hsv2rgb(vec3 c) {
|
||||||
|
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||||
|
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
|
||||||
|
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec4 col = v_vColour * texture2D(gm_BaseTexture, v_vTexcoord);
|
||||||
|
vec3 hsv = rgb2hsv(col.rgb);
|
||||||
|
hsv = vec3(
|
||||||
|
fract(hsv.r + v_vHsv.r),
|
||||||
|
clamp(hsv.g + v_vHsv.g, 0.0, 1.0),
|
||||||
|
clamp(hsv.b + v_vHsv.b, 0.0, 1.0)
|
||||||
|
);
|
||||||
|
|
||||||
|
col.rgb = hsv2rgb(hsv);
|
||||||
|
gl_FragColor = col;
|
||||||
|
}
|
||||||
41
shdProjectileEffect.vsh
Normal file
41
shdProjectileEffect.vsh
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
attribute vec3 in_Position;
|
||||||
|
attribute vec4 in_Colour;
|
||||||
|
attribute vec2 in_TextureCoord;
|
||||||
|
attribute vec3 in_Colour0;
|
||||||
|
attribute vec2 in_Colour1;
|
||||||
|
attribute float in_Colour2;
|
||||||
|
attribute vec3 in_Colour3;
|
||||||
|
attribute float in_Colour4;
|
||||||
|
attribute vec3 in_Colour5;
|
||||||
|
|
||||||
|
#define in_Offset in_Colour0
|
||||||
|
#define in_Scale in_Colour1
|
||||||
|
#define in_Angle in_Colour2
|
||||||
|
#define in_RotationDirection in_Colour3
|
||||||
|
#define in_Animation in_Colour4
|
||||||
|
#define in_Hsv in_Colour5
|
||||||
|
|
||||||
|
varying vec2 v_vTexcoord;
|
||||||
|
varying vec4 v_vColour;
|
||||||
|
varying vec3 v_vHsv;
|
||||||
|
|
||||||
|
mat4 rotation_matrix_3d(vec3 axis, float angle) {
|
||||||
|
float s = sin(angle);
|
||||||
|
float c = cos(angle);
|
||||||
|
float oc = 1.0 - c;
|
||||||
|
|
||||||
|
return mat4(
|
||||||
|
oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0,
|
||||||
|
oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0,
|
||||||
|
oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0,
|
||||||
|
0.0, 0.0, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
mat4 rotmat = rotation_matrix_3d(in_RotationDirection, in_Angle);
|
||||||
|
vec4 pos = vec4(in_Position.xy * in_Scale, in_Position.z, 1.0) * rotmat + vec4(in_Offset, 0.0);
|
||||||
|
gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * pos;
|
||||||
|
v_vColour = in_Colour;
|
||||||
|
v_vTexcoord = in_TextureCoord + vec2(in_Animation, 0.0);
|
||||||
|
v_vHsv = in_Hsv;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue