on load: set {hex::*} to split "0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|k|l|m|n|o|r" at "|" set {RTX::settings::output} to location(0, 64, 0, world "world") # location of the output hologram set {RTX::settings::dim::*} to 256 and 256 # output resolution set {RTX::settings::mb} to 2 # max reflection bounces (you should keep this low) set {RTX::sky::color::*} to 0, 150 and 209 # sky color set {RTX::light::vec} to vector(-1, -1, -1) # light direction (doesn't do anything (yet)) set {RTX::light::loc} to location(149.6, 17.7, 82.4, world "world") # light location set {RTX::light::sh} to 1 # shadow harshness (closer to 0 = sharper the shadows) set {RTX::camera::loc} to location(152.8, 9.7, 75.1, world "world") # camera location set {RTX::camera::rd} to 20 # render distance (in blocks) set {RTX::camera::yaw} to 106 # camera yaw (horizontal rotation) set {RTX::camera::pitch} to 11 # camera pitch (vertical rotation) # block, (reflective (0 or 1), (color)) raytraceAddBlock(white concrete, (0, 255, 255 and 255)) raytraceAddBlock(stone, (0, 128, 128 and 128)) raytraceAddBlock(iron block, (1, 0, 0 and 0)) raytraceAddBlock(blue wool, (0, 0, 0 and 255)) raytraceAddBlock(yellow wool, (0, 255, 255 and 0)) raytraceAddBlock(red wool, (0, 255, 0 and 0)) raytraceAddBlock(lime wool, (0, 0, 255 and 0)) clear {RTX::uv::*} # size of all texture maps (does not need to be square), said block's texture will appear improperly scaled if this does not match the actual texture dimensions set {RTX::uv::dim::*} to 8 and 8 # texture id, row, (color placeholder) raytraceAddTex("grass_side", 1, (1, 1, 1, 1, 1, 1, 1 and 1)) raytraceAddTex("grass_side", 2, (1, 1, 0, 1, 1, 1, 1 and 0)) raytraceAddTex("grass_side", 3, (1, 0, 1, 1, 0, 1, 0 and 1)) raytraceAddTex("grass_side", 4, (0, 0, 0, 0, 0, 0, 0 and 0)) raytraceAddTex("grass_side", 5, (0, 0, 0, 0, 0, 0, 0 and 0)) raytraceAddTex("grass_side", 6, (0, 0, 0, 0, 0, 0, 0 and 0)) raytraceAddTex("grass_side", 7, (0, 0, 0, 0, 0, 0, 0 and 0)) raytraceAddTex("grass_side", 8, (0, 0, 0, 0, 0, 0, 0 and 0)) # texture id, color placeholder, color raytraceAddTexMap("grass_side", 0, (87, 64, and 0)) raytraceAddTexMap("grass_side", 1, (39, 166, and 0)) raytraceAddTex("grass_top", 1, (0, 0, 0, 0, 0, 0, 0 and 0)) raytraceAddTex("grass_top", 2, (0, 0, 0, 0, 0, 0, 0 and 0)) raytraceAddTex("grass_top", 3, (0, 0, 0, 0, 0, 0, 0 and 0)) raytraceAddTex("grass_top", 4, (0, 0, 0, 0, 0, 0, 0 and 0)) raytraceAddTex("grass_top", 5, (0, 0, 0, 0, 0, 0, 0 and 0)) raytraceAddTex("grass_top", 6, (0, 0, 0, 0, 0, 0, 0 and 0)) raytraceAddTex("grass_top", 7, (0, 0, 0, 0, 0, 0, 0 and 0)) raytraceAddTex("grass_top", 8, (0, 0, 0, 0, 0, 0, 0 and 0)) raytraceAddTexMap("grass_top", 0, (39, 166, and 0)) raytraceAddTex("grass_bottom", 1, (0, 0, 0, 0, 0, 0, 0 and 0)) raytraceAddTex("grass_bottom", 2, (0, 0, 0, 0, 0, 0, 0 and 0)) raytraceAddTex("grass_bottom", 3, (0, 0, 0, 0, 0, 0, 0 and 0)) raytraceAddTex("grass_bottom", 4, (0, 0, 0, 0, 0, 0, 0 and 0)) raytraceAddTex("grass_bottom", 5, (0, 0, 0, 0, 0, 0, 0 and 0)) raytraceAddTex("grass_bottom", 6, (0, 0, 0, 0, 0, 0, 0 and 0)) raytraceAddTex("grass_bottom", 7, (0, 0, 0, 0, 0, 0, 0 and 0)) raytraceAddTex("grass_bottom", 8, (0, 0, 0, 0, 0, 0, 0 and 0)) raytraceAddTexMap("grass_bottom", 0, (39, 166, and 0)) # block, (texture top, bottom, north, east, south, west) raytraceMapBlockTex(grass block, ("grass_top", "grass_bottom", "grass_side", "grass_side", "grass_side" and "grass_side")) # # Remaining code below is recommended to not be touched but feel free to do so anyway # # START OF CUSTOM EFFECT option NMS: get: return 4th element out of ((class "org.bukkit.Bukkit").getServer().getClass().getPackage().getName() split at ".") import: org.bukkit.craftbukkit.{@NMS}.util.CraftChatMessage effect set fancy colored name of %entity% to %string%: trigger: expr-1.getHandle().setCustomName(CraftChatMessage.fromStringOrNull(expr-2)) expr-1.getHandle().setCustomNameVisible(true) # END OF CUSTOM EFFECT function pLine(l: location, v: vector, c: integers): loop 10 times: set vector length of {_v} to loop-value / 10 play 5 of dust using dustOption(rgb({_c::1}, {_c::2}, {_c::3}), .5) at {_l} ~ {_v} function raytraceAddBlock(b: material, c: integers): set {_i} to raw name of {_b} set {RTX::map::%{_i}%::*} to {_c::*} function raytraceAddTex(i: text, r: integer, rc: integers): set {RTX::uv::img::%{_i}%::%{_r}%::*} to {_rc::*} function raytraceAddTexMap(i: text, id: integer, c: integers): set {RTX::uv::map::%{_i}%::%{_id}%::*} to {_c::*} function raytraceMapBlockTex(b: material, f: texts): set {_bn} to raw name of {_b} set {RTX::uv::lookup::%{_bn}%::*} to {_f::*} function raytraceGetMatProperties(b: material) :: objects: set {_bn} to raw name of {_b} return {RTX::map::%{_bn}%::*} function raytraceCalcInShadow(l: location, o: vector) :: boolean: set {_v} to vector from {_l} to {RTX::light::loc} ~ {_o} loop round(distance between {_l} and {RTX::light::loc} ~ {_o}) / .1 times: set vector length of {_v} to loop-value * .1 if block at ({_l} ~ {_v}) is not air: return true return false function raytraceCalcLightAndColor(b: material, l: location, nv: vector) :: objects: set {_bn} to raw name of {_b} set {_lv} to vector between {RTX::light::loc} and {_l} set {_dv} to -1 * (normalized {_nv} dot normalized {_lv}) set {_c::*} to raytraceGetMatProperties({_b}) set {_c::2} to round({_c::2} * mapRange({_dv}, (-1, 1), (0, 1))) set {_c::3} to round({_c::3} * mapRange({_dv}, (-1, 1), (0, 1))) set {_c::4} to round({_c::4} * mapRange({_dv}, (-1, 1), (0, 1))) if {_b} is command block: set {_fp} to vector from block at {_l} -- vector from {_l} set {_r} to round(mapRange(x of {_fp}, (-.5, .5), (0, 255))) set {_g} to round(mapRange(y of {_fp}, (-.5, .5), (0, 255))) set {_b} to round(mapRange(z of {_fp}, (-.5, .5), (0, 255))) set {_c::*} to 0, {_r}, {_g} and {_b} set {_lookup::*} to {RTX::uv::lookup::%{_bn}%::*} if {_lookup::*} is set: set {_fp} to vector from block at {_l} -- vector from {_l} set {_w} to round({RTX::uv::dim::1}) set {_h} to round({RTX::uv::dim::2}) if abs(x of {_nv}) = 1: set {_u} to round(mapRange(z of {_fp}, (-.5, .5), (1, {_w}))) set {_v} to round(mapRange(y of {_fp}, (-.5, .5), (1, {_h}))) else if abs(y of {_nv}) = 1: set {_u} to round(mapRange(x of {_fp}, (-.5, .5), (1, {_w}))) set {_v} to round(mapRange(z of {_fp}, (-.5, .5), (1, {_h}))) else: set {_u} to round(mapRange(x of {_fp}, (-.5, .5), (1, {_w}))) set {_v} to round(mapRange(y of {_fp}, (-.5, .5), (1, {_h}))) set {_f::*} to {RTX::uv::lookup::%{_bn}%::*} if y of {_nv} = 1: set {_r} to {RTX::uv::img::%{_f::1}%::%{_v}%::%{_u}%} set {_c::*} to 0 and {RTX::uv::map::%{_f::1}%::%{_r}%::*} else if y of {_nv} = -1: set {_r} to {RTX::uv::img::%{_f::2}%::%{_v}%::%{_u}%} set {_c::*} to 0 and {RTX::uv::map::%{_f::2}%::%{_r}%::*} else if z of {_nv} = -1: set {_r} to {RTX::uv::img::%{_f::3}%::%{_v}%::%{_u}%} set {_c::*} to 0 and {RTX::uv::map::%{_f::3}%::%{_r}%::*} else if z of {_nv} = 1: set {_r} to {RTX::uv::img::%{_f::4}%::%{_v}%::%{_u}%} set {_c::*} to 0 and {RTX::uv::map::%{_f::4}%::%{_r}%::*} else if x of {_nv} = 1: set {_r} to {RTX::uv::img::%{_f::5}%::%{_v}%::%{_u}%} set {_c::*} to 0 and {RTX::uv::map::%{_f::5}%::%{_r}%::*} else: set {_r} to {RTX::uv::img::%{_f::6}%::%{_v}%::%{_u}%} set {_c::*} to 0 and {RTX::uv::map::%{_f::6}%::%{_r}%::*} set {_ls} to 1 set {_v} to spherical vector radius {RTX::light::sh}, yaw (vector yaw of (vector from {_l} to {RTX::light::loc}) + 90), pitch 0 remove .2 from {_ls} if raytraceCalcInShadow({_l}, vector(0, 0, 0)) is true remove .2 from {_ls} if raytraceCalcInShadow({_l}, {_v}) is true remove .2 from {_ls} if raytraceCalcInShadow({_l}, {_v} ** vector(-1, -1, -1)) is true set {_c::2} to round({_c::2} * {_ls}) set {_c::3} to round({_c::3} * {_ls}) set {_c::4} to round({_c::4} * {_ls}) if size of {_c::*} < 4: set {_c::*} to 0, 255, 0 and 255 return {_c::*} function raytraceFireRay(l: location, v: vector, b: number) :: objects: set {_rd} to round({RTX::camera::rd}) add 1 to {RTX::count} if {_b} > 0: loop round({RTX::camera::rd} * 10) times: set vector length of {_v} to loop-value * {_rd} / ({_rd} * 10) #play 1 of dust using dustOption(rgb(255, 0, 0), .5) at {_l} ~ {_v} if block at ({_l} ~ {_v}) is not air: set {_bt} to block at ({_l} ~ {_v}) set {_l1} to location of block at ({_l} ~ {_v}) set vector length of {_v} to (loop-value - 1) * {_rd} / ({_rd} * 10) set {_hl} to {_l} ~ {_v} set {_l2} to location of block at ({_l} ~ {_v}) set {_nv} to vector((x-loc of {_l2} - x-loc of {_l1}), (y-loc of {_l2} - y-loc of {_l1}), (z-loc of {_l2} - z-loc of {_l1})) set {_b::*} to raytraceCalcLightAndColor({_bt}, {_hl}, {_nv}) if {_b::1} = 1: set vector length of {_v} to 1 set {_v} to {_v} ** vector(-1, -1, -1) rotate {_v} around {_nv} by 180 set {_c::*} to raytraceFireRay({_hl}, {_v}, {_b} - 1) set {_cl::*} to raytraceGetMatProperties({_bt}) set {_c::*} to {_c::1}, round(({_c::2} + {_cl::2}) / 2), round(({_c::3} + {_cl::3}) / 2) and round(({_c::4} + {_cl::4}) / 2) else: set {_c::*} to {_b::*} exit 1 loop set {_c::*} to 0 and {RTX::sky::color::*} if {_c::*} is not set return {_c::*} command /render: trigger: clear {RTX::out::*} set {RTX::count} to 0 set {_l} to {RTX::camera::loc} set {_y} to {RTX::camera::yaw} set {_p} to {RTX::camera::pitch} set {_mb} to {RTX::settings::mb} set {_n} to now loop {RTX::settings::dim::2} times: set {_rt} to unix timestamp of now loop {RTX::settings::dim::1} times: set {_x} to (2 * (loop-value-2 + 0.5) / {RTX::settings::dim::1} - 1) set {_y} to (1 - 2 * (loop-value-1 + 0.5) / {RTX::settings::dim::2}) set {_v} to vector({_x}, {_y}, -1) rotate {_v} around (vector from yaw {_y} + 90 and pitch 0) by {_p} rotate {_v} around y axis by (90 + {_y}) set {_p::*} to raytraceFireRay({_l}, {_v}, {_mb}) add 1 to {_i} set {RTX::out::p::%loop-value-1%::%loop-value-2%::*} to {_p::*} send action bar "%{_i}% prc | row %loop-value-1% @ %unix timestamp of now - {_rt}% s/r" to all players wait 1 tick raytracingLiveRender(loop-value-1) send "%{RTX::count}% total rays cast in %difference between now and {_n}%" wait 25 seconds loop {RTX::out::e::*}: kill loop-value function raytracingLiveRender(y: number): set {_l} to {RTX::settings::output} set y-loc of {_l} to -.21 * {_y} + 32 loop indices of {RTX::out::p::%{_y}%::*}: set {_r} to {RTX::out::p::%{_y}%::%loop-value%::2} set {_g} to {RTX::out::p::%{_y}%::%loop-value%::3} set {_b} to {RTX::out::p::%{_y}%::%loop-value%::4} add "%raytracingRgbToHex(({_r}, {_g}, {_b}))%█" to {_row::*} add "%{_r}%,%{_g}%,%{_b}%" to {_row::*} spawn 1 armor stand at {_l} with nbt "{CustomNameVisible:1,NoGravity:1,Marker:1,Invisible:1}" add last spawned entity to {RTX::out::e::*} set fancy colored name of last spawned entity to colored (join {_row::*} by "") function raytracingRgbToHex(values: integers) :: string: loop {_values::*}: set {_r} to "%{_r} ? ""<##""%%{hex::%(( (round(loop-value)) - mod((round(loop-value)), 16)) / 16 + 1)%} ? """"%%{hex::%mod((round(loop-value)), 16) + 1%} ? """"%" return "%{_r}%>" every 5 ticks: set {_l} to {RTX::camera::loc} set {_y} to {RTX::camera::yaw} set {_p} to {RTX::camera::pitch} set {_v} to vector from yaw {_y} and pitch {_p} pLine({_l}, {_v}, (255, 0, 0)) play 5 of dust using dustOption(rgb(255, 255, 255), 1) at {_l} set {_l} to {RTX::light::loc} set {_v} to {RTX::light::vec} pLine({_l}, {_v}, (255, 255, 0)) play 5 of dust using dustOption(rgb(255, 255, 255), 1) at {_l}