Skip to content

Commit

Permalink
all
Browse files Browse the repository at this point in the history
  • Loading branch information
Chubbygummibear committed Feb 18, 2024
1 parent 76b94ca commit 37f43f9
Show file tree
Hide file tree
Showing 11 changed files with 303 additions and 112 deletions.
4 changes: 4 additions & 0 deletions src/main/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ export class MainMenu extends Menu {
this.ui.player.toggle_darkness();
this.close();
});
this.add_basic_button("Dump Textures", null, () => {
this.ui.player.dump_textures();
this.close();
});
}
}

Expand Down
76 changes: 56 additions & 20 deletions src/main/rendering/gl_holder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { CopyShader, get_copy_shader, get_icon_shader, IconShader, ShaderHolder
import { RenderingCmd } from "../../player/rendering/commands";
import { ViewportElement } from "../viewport";
import { render_maptext } from "./maptext";
import { BlendMode } from "../../misc/constants";

export class DemoPlayerGlHolder {
gl : WebGLRenderingContext;
Expand All @@ -16,6 +17,7 @@ export class DemoPlayerGlHolder {
max_texture_size : number;
copy_framebuffer : WebGLFramebuffer;
white_texture : WebGLTexture;
canvas_copy : WebGLTexture;

shader : IconShader;
shader_matrix : IconShader;
Expand All @@ -27,7 +29,7 @@ export class DemoPlayerGlHolder {
if(this.gl2) {
this.gl = this.gl2;
} else {
let gl = canvas.getContext("webgl", {desynchronized: true});
let gl = canvas.getContext("webgl", {desynchronized: true, alpha: false});
if(!gl) throw new Error("Could not initialize WebGL");
this.gl = gl;
}
Expand All @@ -49,11 +51,15 @@ export class DemoPlayerGlHolder {

this.white_texture = not_null(gl.createTexture());
gl.bindTexture(gl.TEXTURE_2D, this.white_texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([255,255,255,255]));
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
gl.bindTexture(gl.TEXTURE_2D, null);
this.copy_framebuffer = not_null(gl.createFramebuffer());
this.max_texture_size = Math.min(gl.getParameter(gl.MAX_TEXTURE_SIZE), 32768);

this.canvas_copy = not_null(gl.createTexture());
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, this.canvas_copy);

this.square_buffer = not_null(gl.createBuffer());
gl.bindBuffer(gl.ARRAY_BUFFER, this.square_buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1]), gl.STATIC_DRAW);
Expand Down Expand Up @@ -169,7 +175,7 @@ export class DemoPlayerGlHolder {
}
}
gl.bindTexture(gl.TEXTURE_2D, null);
} else if(cmd.cmd == "atlestexcopywithin") {
} else if(cmd.cmd == "atlastexcopywithin") {
let tex = not_null(this.atlas_textures[cmd.index]);
let shader = this.shader_copy;
this.set_shader(shader);
Expand Down Expand Up @@ -257,6 +263,8 @@ export class DemoPlayerGlHolder {
ia.vertexAttribDivisorANGLE(shader.a_layer, 1);
ia.drawArraysInstancedANGLE(gl.TRIANGLES, 0, 6, cmd.num_elements);
gl.deleteBuffer(buf);
// gl.activeTexture(gl.TEXTURE0 + 1);
// gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, gl.canvas);
} else if(cmd.cmd == "copytoviewport") {
let this_viewport_pixel = curr_viewport_pixel;
let this_viewport = curr_viewport;
Expand Down Expand Up @@ -338,26 +346,54 @@ export class DemoPlayerGlHolder {
// this one was fun - I made test cases in BYOND and took screenshots and tried to reverse-engineer the blending equations from that.
// fun fact BYOND uses premultiplied alpha. However, when you
set_blend_mode(blend_mode : number) : void{
if(blend_mode == 0) blend_mode = 1;
//if(blend_mode == 0) blend_mode = 1;
if(blend_mode == this.curr_blend_mode) return;
this.curr_blend_mode = blend_mode;
const gl = this.gl;
if(blend_mode == 2) { // BLEND_ADD
gl.blendEquation(gl.FUNC_ADD);
gl.blendFuncSeparate(gl.ONE, gl.ONE, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
} else if(blend_mode == 3) { // BLEND_SUBTRACT
gl.blendEquation(gl.FUNC_REVERSE_SUBTRACT);
gl.blendFuncSeparate(gl.ONE, gl.ONE, gl.ZERO, gl.ONE);
} else if(blend_mode == 4) { // BLEND_MULTIPLY
gl.blendEquation(gl.FUNC_ADD);
gl.blendFunc(gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA); // fun fact if you do the math everything cancels out so that the destination alpha doesn't change at all.
} else if(blend_mode == 5) { // BLEND_INSET_OVERLAY
// TODO figure out if this is actually right
gl.blendEquation(gl.FUNC_ADD);
gl.blendFuncSeparate(gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ZERO, gl.ONE)
} else { // BLEND_OVERLAY or BLEND_DEFAULT
gl.blendEquation(gl.FUNC_ADD);
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
switch(blend_mode){
case BlendMode.DEFAULT: {
gl.blendEquation(gl.FUNC_ADD);
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
break;
}
case BlendMode.ADD: {
gl.blendEquation(gl.FUNC_ADD);
gl.blendFuncSeparate(gl.ONE, gl.ONE, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
break;
}
case BlendMode.SUBTRACT: {
gl.blendEquation(gl.FUNC_REVERSE_SUBTRACT);
gl.blendFuncSeparate(gl.ONE, gl.ONE, gl.ZERO, gl.ONE);
break;
}
case BlendMode.MULTIPLY: {
gl.blendEquation(gl.FUNC_ADD);
gl.blendFunc(gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA); // fun fact if you do the math everything cancels out so that the destination alpha doesn't change at all.
break;
}
case BlendMode.INSET_OVERLAY: {
// TODO figure out if this is actually right
gl.blendEquation(gl.FUNC_ADD);
gl.blendFuncSeparate(gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ZERO, gl.ONE)
break;
}
case BlendMode.ALPHA: {
gl.blendEquation(gl.FUNC_ADD);
//gl.blendFuncSeparate(gl.DST_COLOR, gl.ZERO, gl.DST_ALPHA, gl.ZERO)
gl.blendFunc(gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA);
break;
}
case BlendMode.ALPHA_INVERTED: {
gl.blendEquation(gl.FUNC_ADD);
gl.blendFuncSeparate(gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE)
break;
}
//Just in case there's a weird value we'll use the default
default: {
gl.blendEquation(gl.FUNC_ADD);
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
break;
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/main/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,7 @@ export class DemoPlayerUi {
handle_sounds(sounds : DemoSound[]) : void {
this.sound_player.handle_sounds(sounds);
}
async dump_textures() {
this.gl_holder.dump_textures();
}
}
19 changes: 11 additions & 8 deletions src/misc/appearance.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { IconStateDir } from "../player/rendering/icon";
import { Planes, RESET_ALPHA, RESET_COLOR, RESET_TRANSFORM } from "./constants";
import { BlendMode, Planes, RESET_ALPHA, RESET_COLOR, RESET_TRANSFORM } from "./constants";
import { Matrix, matrix_invert, matrix_is_identity, matrix_multiply } from "./matrix";

export enum FilterType {
Expand Down Expand Up @@ -175,7 +175,7 @@ export type TransitionalAppearance = BaseAppearance<TransitionalAppearance|Appea

export namespace Appearance {
const empty_arr : [] = [];
export function resolve_plane(plane : number, parent_plane = 0) : number {
export function resolve_plane(plane : number, parent_plane = Planes.GAME_PLANE) : number {
if(parent_plane < Planes.LOWEST_EVER_PLANE || parent_plane > Planes.HIGHEST_EVER_PLANE) parent_plane = resolve_plane(parent_plane);
if(plane < Planes.LOWEST_EVER_PLANE || plane > Planes.HIGHEST_EVER_PLANE) {
plane = ((parent_plane + plane + 32767) << 16) >> 16;
Expand All @@ -190,7 +190,10 @@ export namespace Appearance {
* @returns TRUE if the plane value falls within the range of Byond lighting planes, FALSE if the plane is anything else
*/
export function is_lighting_plane(plane : number): boolean {
return (plane >= Planes.EMISSIVE_BLOCKER_PLANE && plane <= Planes.O_LIGHTING_VISUAL_PLANE)
if(plane < Planes.LOWEST_EVER_PLANE || plane > Planes.HIGHEST_EVER_PLANE) {
plane = plane % (Planes.HIGHEST_EVER_PLANE - Planes.LOWEST_EVER_PLANE);
}
return (plane >= Planes.LIGHTING_PLANE && plane <= Planes.LIGHT_MASK_PLANE)
}

export function get_appearance_parts(appearance : Appearance) {
Expand Down Expand Up @@ -304,10 +307,10 @@ export namespace Appearance {
}
overlay.color_alpha = color_alpha;
}
if(overlay.blend_mode == 0 && appearance.blend_mode > 0) {
clone();
overlay.blend_mode = appearance.blend_mode;
}
// if(appearance.blend_mode == BlendMode.DEFAULT && overlay.blend_mode != BlendMode.DEFAULT) {
// clone();

// }
if(overlay.plane < Planes.LOWEST_EVER_PLANE || overlay.plane > Planes.HIGHEST_EVER_PLANE) {
clone();
overlay.plane = resolve_plane(overlay.plane, appearance.plane);
Expand Down Expand Up @@ -442,7 +445,7 @@ export namespace ReaderAppearance {
pixel_y: 0,
pixel_z: 0,
pixel_w: 0,
blend_mode: 0,
blend_mode: BlendMode.DEFAULT,
glide_size: 8,
screen_loc: null,
transform: [1,0,0,0,1,0],
Expand Down
141 changes: 127 additions & 14 deletions src/misc/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,111 @@ export const SOUND_UPDATE = 16;

export const MAX_LAYER : number = 32;

export const enum AppearanceAttributeIndex{
TRANSFORMATION_MATRIX_3x3_A,
TRANSFORMATION_MATRIX_3x3_B,
TRANSFORMATION_MATRIX_3x3_C,
TRANSFORMATION_MATRIX_3x3_D,
TRANSFORMATION_MATRIX_3x3_E,
TRANSFORMATION_MATRIX_3x3_F,

ICON_BOUND_X_1,
ICON_BOUND_Y_1,
ICON_BOUND_X_2,
ICON_BOUND_Y_2,

ICON_LAYER,
//ICON_PLANE,

COLOR_MATRIX_RED,
COLOR_MATRIX_RED_GREEN,
COLOR_MATRIX_RED_BLUE,
COLOR_MATRIX_RED_ALPHA,

COLOR_MATRIX_GREEN_RED,
COLOR_MATRIX_GREEN,
COLOR_MATRIX_GREEN_BLUE,
COLOR_MATRIX_GREEN_ALPHA,

COLOR_MATRIX_BLUE_RED,
COLOR_MATRIX_BLUE_GREEN,
COLOR_MATRIX_BLUE,
COLOR_MATRIX_BLUE_ALPHA,

COLOR_MATRIX_ALPHA_RED,
COLOR_MATRIX_ALPHA_GREEN,
COLOR_MATRIX_ALPHA_BLUE,
COLOR_MATRIX_ALPHA_ALPHA,

COLOR_MATRIX_COMPONENT_RED,
COLOR_MATRIX_COMPONENT_GREEN,
COLOR_MATRIX_COMPONENT_BLUE,
COLOR_MATRIX_COMPONENT_ALPHA,

COLOR_RGBA_RED = 11,
COLOR_RGBA_GREEN,
COLOR_RGBA_BLUE,
COLOR_RGBA_ALPHA,
}

///All relevant planes used by Yogstation categorized into an enum of their values
export const enum Planes{
LOWEST_EVER_PLANE = -10000,
CLICKCATCHER_PLANE = -99,
SPACE_PLANE = -95,
FLOOR_PLANE = -2,
GAME_PLANE = -1,
BLACKNESS_PLANE = 0,
EMISSIVE_BLOCKER_PLANE = 12,
LOWEST_EVER_PLANE = -50,

FIELD_OF_VISION_BLOCKER_PLANE = -45,

CLICKCATCHER_PLANE = -40,

PLANE_SPACE = -21,
PLANE_SPACE_PARALLAX = -20,

GRAVITY_PULSE_PLANE = -12,

RENDER_PLANE_TRANSPARENT = -11,

TRANSPARENT_FLOOR_PLANE = -10,

FLOOR_PLANE = -6,
WALL_PLANE = -5,
GAME_PLANE = -4,
ABOVE_GAME_PLANE = -3,

SEETHROUGH_PLANE = -2,
RENDER_PLANE_GAME_WORLD = -1,
DEFAULT_PLANE = 0,

AREA_PLANE = 2,
MASSIVE_OBJ_PLANE = 3,
GHOST_PLANE = 4,
POINT_PLANE = 5,

LIGHTING_PLANE = 10,
O_LIGHTING_VISUAL_PLANE = 11,
EMISSIVE_PLANE = 13,
EMISSIVE_UNBLOCKABLE_PLANE = 14,
LIGHTING_PLANE = 15,
O_LIGHTING_VISUAL_PLANE = 16,
FLOOR_OPENSPACE_PLANE = 17,
BYOND_LIGHTING_PLANE = 18,
CAMERA_STATIC_PLANE = 19,
HIGHEST_EVER_PLANE = 10000,
RENDER_PLANE_LIGHTING = 15,
LIGHT_MASK_PLANE = 16,
ABOVE_LIGHTING_PLANE = 17,
PIPECRAWL_IMAGES_PLANE = 20,
CAMERA_STATIC_PLANE = 21,
HIGH_GAME_PLANE = 22,
FULLSCREEN_PLANE = 23,
RUNECHAT_PLANE = 30,
BALLOON_CHAT_PLANE = 31,
HUD_PLANE = 35,
ABOVE_HUD_PLANE = 36,
SPLASHSCREEN_PLANE = 37,
RENDER_PLANE_GAME = 40,
RENDER_PLANE_GAME_MASKED = 41,
RENDER_PLANE_GAME_UNMASKED = 42,
RENDER_PLANE_NON_GAME = 45,
ESCAPE_MENU_PLANE = 46,
RENDER_PLANE_MASTER = 50,
HIGHEST_EVER_PLANE = RENDER_PLANE_MASTER,

EMISSIVE_Z_BELOW_LAYER = 1,
EMISSIVE_FLOOR_LAYER = 2,
EMISSIVE_SPACE_LAYER = 3,
EMISSIVE_WALL_LAYER = 4,
}

export const enum SeeInvisibility{
Expand All @@ -62,4 +149,30 @@ export const enum SeeInvisibility{
SEE_INVISIBLE_OBSERVER = 60,
INVISIBILITY_MAXIMUM = 100,
INVISIBILITY_ABSTRACT = 101,
}

export const enum BlendMode {
/**
* Also called BLEND_OVERLAY by Byond
*/
DEFAULT = 1,
ADD,
SUBTRACT,
MULTIPLY,
INSET_OVERLAY,
ALPHA,
ALPHA_INVERTED,
}

export const enum RenderPlates{
CANVAS,
GAME_PLATE,
UNMASKED_GAME_PLATE,
MASKED_GAME_PLATE,
TRANSPARENT_PLATE,
GAME_WORLD_PLATE,
LIGHTING_PLATE,
EMISSIVE_SLATE,
LIGHT_MASK_PLATE,
NON_GAME_PLATE,
}
8 changes: 4 additions & 4 deletions src/parser/binary_parser.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Filter, FilterType, ReaderAppearance } from "../misc/appearance";
import { Planes, SOUND_MUTE, SOUND_PAUSED, SOUND_STREAM, SOUND_UPDATE } from "../misc/constants";
import { Appearance, Filter, FilterType, ReaderAppearance } from "../misc/appearance";
import { BlendMode, Planes, SOUND_MUTE, SOUND_PAUSED, SOUND_STREAM, SOUND_UPDATE } from "../misc/constants";
import { Matrix } from "../misc/matrix";
import { DemoParser, ReaderDemoAnimation, ReaderDemoAnimationFrame } from "./base_parser";
import { RevData } from "./interface";
Expand Down Expand Up @@ -542,14 +542,14 @@ export class DemoParserBinary extends DemoParser {
if(filter) filters.push(filter);
}
// Uncomment this once filters are actually being used somewhere
//if(filters.length) appearance.filters = filters;
if(filters.length) appearance.filters = filters;
}
appearance.override = !!(daf & 0x40000000);
if(daf & 0x80000000) {
appearance.vis_flags = p.read_uint8();
}

if(appearance.plane == Planes.LIGHTING_PLANE && !appearance.screen_loc) appearance.blend_mode = 4; // This only exists because I CBA to implement plane masters right now
if(Appearance.is_lighting_plane(appearance.plane) && !appearance.screen_loc) appearance.blend_mode = BlendMode.MULTIPLY; // This only exists because I CBA to implement plane masters right now
return this.appearance_refs[appearance_ref] = this.appearance_id(appearance);
} else {
if(appearance_ref == 0xFFFF) return null;
Expand Down
Loading

0 comments on commit 37f43f9

Please sign in to comment.