Compare commits
2 Commits
1535d3ae35
...
5cb2875ba6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5cb2875ba6 | ||
|
|
c7130cbb07 |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 39 KiB |
@ -23,25 +23,6 @@ if(OBS_PARENT_ARCHITECTURE STREQUAL CMAKE_VS_PLATFORM_NAME)
|
|||||||
RESULT_VARIABLE _process_result
|
RESULT_VARIABLE _process_result
|
||||||
COMMAND_ERROR_IS_FATAL ANY
|
COMMAND_ERROR_IS_FATAL ANY
|
||||||
)
|
)
|
||||||
execute_process(
|
|
||||||
COMMAND
|
|
||||||
"${CMAKE_COMMAND}" -S ${CMAKE_CURRENT_SOURCE_DIR} -B ${CMAKE_SOURCE_DIR}/build_x86 -A
|
|
||||||
"Win32,version=${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}" -G "${CMAKE_GENERATOR}"
|
|
||||||
-DCMAKE_SYSTEM_VERSION:STRING='${CMAKE_SYSTEM_VERSION}' -DVIRTUALCAM_GUID:STRING=${VIRTUALCAM_GUID}
|
|
||||||
-DCMAKE_MESSAGE_LOG_LEVEL:STRING=${CMAKE_MESSAGE_LOG_LEVEL} -DOBS_PARENT_ARCHITECTURE:STRING=ARM64
|
|
||||||
RESULT_VARIABLE _process_result
|
|
||||||
COMMAND_ERROR_IS_FATAL ANY
|
|
||||||
)
|
|
||||||
elseif(OBS_PARENT_ARCHITECTURE STREQUAL x64)
|
|
||||||
execute_process(
|
|
||||||
COMMAND
|
|
||||||
"${CMAKE_COMMAND}" -S ${CMAKE_CURRENT_SOURCE_DIR} -B ${CMAKE_SOURCE_DIR}/build_x86 -A
|
|
||||||
"Win32,version=${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}" -G "${CMAKE_GENERATOR}"
|
|
||||||
-DCMAKE_SYSTEM_VERSION:STRING='${CMAKE_SYSTEM_VERSION}' -DVIRTUALCAM_GUID:STRING=${VIRTUALCAM_GUID}
|
|
||||||
-DCMAKE_MESSAGE_LOG_LEVEL:STRING=${CMAKE_MESSAGE_LOG_LEVEL} -DOBS_PARENT_ARCHITECTURE:STRING=x64
|
|
||||||
RESULT_VARIABLE _process_result
|
|
||||||
COMMAND_ERROR_IS_FATAL ANY
|
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
# target_disable_feature: Stub macro for child architecture builds
|
# target_disable_feature: Stub macro for child architecture builds
|
||||||
|
|||||||
@ -26,8 +26,6 @@ function(set_target_properties_obs target)
|
|||||||
elseif(target STREQUAL inject-helper OR target STREQUAL get-graphics-offsets)
|
elseif(target STREQUAL inject-helper OR target STREQUAL get-graphics-offsets)
|
||||||
set(OBS_EXECUTABLE_DESTINATION "${OBS_DATA_DESTINATION}/obs-plugins/win-capture")
|
set(OBS_EXECUTABLE_DESTINATION "${OBS_DATA_DESTINATION}/obs-plugins/win-capture")
|
||||||
|
|
||||||
_target_install_obs(${target} DESTINATION ${OBS_EXECUTABLE_DESTINATION} x86)
|
|
||||||
|
|
||||||
if(CMAKE_VS_PLATFORM_NAME STREQUAL ARM64)
|
if(CMAKE_VS_PLATFORM_NAME STREQUAL ARM64)
|
||||||
_target_install_obs(${target} DESTINATION ${OBS_EXECUTABLE_DESTINATION} x64)
|
_target_install_obs(${target} DESTINATION ${OBS_EXECUTABLE_DESTINATION} x64)
|
||||||
endif()
|
endif()
|
||||||
@ -70,16 +68,12 @@ function(set_target_properties_obs target)
|
|||||||
target_add_resource(graphics-hook "${CMAKE_CURRENT_SOURCE_DIR}/obs-vulkan64.json" "${target_destination}")
|
target_add_resource(graphics-hook "${CMAKE_CURRENT_SOURCE_DIR}/obs-vulkan64.json" "${target_destination}")
|
||||||
target_add_resource(graphics-hook "${CMAKE_CURRENT_SOURCE_DIR}/obs-vulkan32.json" "${target_destination}")
|
target_add_resource(graphics-hook "${CMAKE_CURRENT_SOURCE_DIR}/obs-vulkan32.json" "${target_destination}")
|
||||||
|
|
||||||
_target_install_obs(${target} DESTINATION ${target_destination} x86)
|
|
||||||
|
|
||||||
if(CMAKE_VS_PLATFORM_NAME STREQUAL ARM64)
|
if(CMAKE_VS_PLATFORM_NAME STREQUAL ARM64)
|
||||||
_target_install_obs(${target} DESTINATION ${target_destination} x64)
|
_target_install_obs(${target} DESTINATION ${target_destination} x64)
|
||||||
endif()
|
endif()
|
||||||
elseif(target STREQUAL obs-virtualcam-module)
|
elseif(target STREQUAL obs-virtualcam-module)
|
||||||
set(target_destination "${OBS_DATA_DESTINATION}/obs-plugins/win-dshow")
|
set(target_destination "${OBS_DATA_DESTINATION}/obs-plugins/win-dshow")
|
||||||
|
|
||||||
_target_install_obs(${target} DESTINATION ${target_destination} x86)
|
|
||||||
|
|
||||||
if(CMAKE_VS_PLATFORM_NAME STREQUAL ARM64)
|
if(CMAKE_VS_PLATFORM_NAME STREQUAL ARM64)
|
||||||
_target_install_obs(${target} DESTINATION ${target_destination} x64)
|
_target_install_obs(${target} DESTINATION ${target_destination} x64)
|
||||||
endif()
|
endif()
|
||||||
@ -182,33 +176,12 @@ endfunction()
|
|||||||
|
|
||||||
# _target_install_obs: Helper function to install build artifacts to rundir and install location
|
# _target_install_obs: Helper function to install build artifacts to rundir and install location
|
||||||
function(_target_install_obs target)
|
function(_target_install_obs target)
|
||||||
set(options "x86" "x64")
|
set(options "x64")
|
||||||
set(oneValueArgs "DESTINATION" "LIBRARY_DESTINATION" "HEADER_DESTINATION")
|
set(oneValueArgs "DESTINATION" "LIBRARY_DESTINATION" "HEADER_DESTINATION")
|
||||||
set(multiValueArgs "")
|
set(multiValueArgs "")
|
||||||
cmake_parse_arguments(PARSE_ARGV 0 _TIO "${options}" "${oneValueArgs}" "${multiValueArgs}")
|
cmake_parse_arguments(PARSE_ARGV 0 _TIO "${options}" "${oneValueArgs}" "${multiValueArgs}")
|
||||||
|
|
||||||
if(_TIO_x86)
|
if(_TIO_x64)
|
||||||
get_target_property(target_type ${target} TYPE)
|
|
||||||
if(target_type STREQUAL EXECUTABLE)
|
|
||||||
set(suffix exe)
|
|
||||||
else()
|
|
||||||
set(suffix dll)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
cmake_path(RELATIVE_PATH CMAKE_CURRENT_SOURCE_DIR BASE_DIRECTORY "${OBS_SOURCE_DIR}" OUTPUT_VARIABLE project_path)
|
|
||||||
|
|
||||||
set(32bit_project_path "${OBS_SOURCE_DIR}/build_x86/${project_path}")
|
|
||||||
set(target_file "${32bit_project_path}/$<CONFIG>/${target}32.${suffix}")
|
|
||||||
set(target_pdb_file "${32bit_project_path}/$<CONFIG>/${target}32.pdb")
|
|
||||||
set(comment "Copy ${target} (x86) to destination")
|
|
||||||
|
|
||||||
install(
|
|
||||||
FILES "${32bit_project_path}/$<CONFIG>/${target}32.${suffix}"
|
|
||||||
DESTINATION "${_TIO_DESTINATION}"
|
|
||||||
COMPONENT Runtime
|
|
||||||
OPTIONAL
|
|
||||||
)
|
|
||||||
elseif(_TIO_x64)
|
|
||||||
get_target_property(target_type ${target} TYPE)
|
get_target_property(target_type ${target} TYPE)
|
||||||
if(target_type STREQUAL EXECUTABLE)
|
if(target_type STREQUAL EXECUTABLE)
|
||||||
set(suffix exe)
|
set(suffix exe)
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 39 KiB |
@ -7,7 +7,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>520</width>
|
<width>520</width>
|
||||||
<height>300</height>
|
<height>340</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@ -73,6 +73,22 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="basedOn">
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true">Based on <a href="https://obsproject.com">OBS Studio</a> (GPLv2)<br/>Secondary development by CAIIC</string>
|
||||||
|
</property>
|
||||||
|
<property name="openExternalLinks">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::TextBrowserInteraction</set>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="verticalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 21 KiB |
@ -29,15 +29,6 @@ if(OBS_PARENT_ARCHITECTURE STREQUAL CMAKE_VS_PLATFORM_NAME)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_VS_PLATFORM_NAME MATCHES "(ARM64|x64)")
|
|
||||||
add_custom_command(
|
|
||||||
TARGET get-graphics-offsets
|
|
||||||
POST_BUILD
|
|
||||||
COMMAND "${CMAKE_COMMAND}" --build ${CMAKE_SOURCE_DIR}/build_x86 --config $<CONFIG> -t get-graphics-offsets
|
|
||||||
COMMENT "Build x86 get-graphics-offsets"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_dependencies(win-capture get-graphics-offsets)
|
add_dependencies(win-capture get-graphics-offsets)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
@ -64,15 +64,6 @@ if(OBS_PARENT_ARCHITECTURE STREQUAL CMAKE_VS_PLATFORM_NAME)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_VS_PLATFORM_NAME MATCHES "(ARM64|x64)")
|
|
||||||
add_custom_command(
|
|
||||||
TARGET graphics-hook
|
|
||||||
POST_BUILD
|
|
||||||
COMMAND "${CMAKE_COMMAND}" --build ${CMAKE_SOURCE_DIR}/build_x86 --config $<CONFIG> -t graphics-hook
|
|
||||||
COMMENT "Build x86 graphics-hook"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_dependencies(win-capture graphics-hook)
|
add_dependencies(win-capture graphics-hook)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
@ -24,15 +24,6 @@ if(OBS_PARENT_ARCHITECTURE STREQUAL CMAKE_VS_PLATFORM_NAME)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_VS_PLATFORM_NAME MATCHES "(ARM64|x64)")
|
|
||||||
add_custom_command(
|
|
||||||
TARGET inject-helper
|
|
||||||
POST_BUILD
|
|
||||||
COMMAND "${CMAKE_COMMAND}" --build ${CMAKE_SOURCE_DIR}/build_x86 --config $<CONFIG> -t inject-helper
|
|
||||||
COMMENT "Build x86 inject-helper"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_dependencies(win-capture inject-helper)
|
add_dependencies(win-capture inject-helper)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
@ -114,15 +114,6 @@ if(OBS_PARENT_ARCHITECTURE STREQUAL CMAKE_VS_PLATFORM_NAME)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_VS_PLATFORM_NAME MATCHES "(ARM64|x64)")
|
|
||||||
add_custom_command(
|
|
||||||
TARGET obs-virtualcam-module
|
|
||||||
POST_BUILD
|
|
||||||
COMMAND "${CMAKE_COMMAND}" --build ${CMAKE_SOURCE_DIR}/build_x86 --config $<CONFIG> -t obs-virtualcam-module
|
|
||||||
COMMENT "Build x86 obs-virtualcam-module"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_dependencies(win-dshow obs-virtualcam-module)
|
add_dependencies(win-dshow obs-virtualcam-module)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
206
tools/dome-icon-gen.js
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
// DOME-style icon generator for the CAIIC OBS fork.
|
||||||
|
// Renders a blue observatory/planetarium dome with a white three-blade
|
||||||
|
// aperture (nod to the OBS logo) wrapped by three CAIIC-colored arcs
|
||||||
|
// (orange top, green lower-left, yellow lower-right).
|
||||||
|
// Usage: node dome-icon-gen.js <out-dir>
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const zlib = require('zlib');
|
||||||
|
|
||||||
|
const DEG = Math.PI / 180;
|
||||||
|
|
||||||
|
// ---------- CRC32 / PNG ----------
|
||||||
|
const crcTable = (() => {
|
||||||
|
const t = new Uint32Array(256);
|
||||||
|
for (let n = 0; n < 256; n++) {
|
||||||
|
let c = n;
|
||||||
|
for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
|
||||||
|
t[n] = c >>> 0;
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
})();
|
||||||
|
function crc32(buf) {
|
||||||
|
let c = 0xffffffff;
|
||||||
|
for (let i = 0; i < buf.length; i++) c = crcTable[(c ^ buf[i]) & 0xff] ^ (c >>> 8);
|
||||||
|
return (c ^ 0xffffffff) >>> 0;
|
||||||
|
}
|
||||||
|
function chunk(type, data) {
|
||||||
|
const out = Buffer.alloc(8 + data.length + 4);
|
||||||
|
out.writeUInt32BE(data.length, 0);
|
||||||
|
out.write(type, 4, 'ascii');
|
||||||
|
data.copy(out, 8);
|
||||||
|
out.writeUInt32BE(crc32(out.subarray(4, 8 + data.length)), 8 + data.length);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function pngEncode(width, height, rgba) {
|
||||||
|
const stride = width * 4;
|
||||||
|
const raw = Buffer.alloc((stride + 1) * height);
|
||||||
|
for (let y = 0; y < height; y++) {
|
||||||
|
raw[y * (stride + 1)] = 0;
|
||||||
|
rgba.copy(raw, y * (stride + 1) + 1, y * stride, (y + 1) * stride);
|
||||||
|
}
|
||||||
|
const ihdr = Buffer.alloc(13);
|
||||||
|
ihdr.writeUInt32BE(width, 0);
|
||||||
|
ihdr.writeUInt32BE(height, 4);
|
||||||
|
ihdr[8] = 8; // bit depth
|
||||||
|
ihdr[9] = 6; // RGBA
|
||||||
|
return Buffer.concat([
|
||||||
|
Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]),
|
||||||
|
chunk('IHDR', ihdr),
|
||||||
|
chunk('IDAT', zlib.deflateSync(raw, { level: 9 })),
|
||||||
|
chunk('IEND', Buffer.alloc(0)),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
function icoEncode(images) {
|
||||||
|
// images: [{size, png}]
|
||||||
|
const header = Buffer.alloc(6);
|
||||||
|
header.writeUInt16LE(1, 2);
|
||||||
|
header.writeUInt16LE(images.length, 4);
|
||||||
|
let offset = 6 + images.length * 16;
|
||||||
|
const entries = [];
|
||||||
|
for (const img of images) {
|
||||||
|
const e = Buffer.alloc(16);
|
||||||
|
e[0] = img.size >= 256 ? 0 : img.size;
|
||||||
|
e[1] = img.size >= 256 ? 0 : img.size;
|
||||||
|
e[4] = 1; // planes
|
||||||
|
e.writeUInt16LE(32, 6);
|
||||||
|
e.writeUInt32LE(img.png.length, 8);
|
||||||
|
e.writeUInt32LE(offset, 12);
|
||||||
|
offset += img.png.length;
|
||||||
|
entries.push(e);
|
||||||
|
}
|
||||||
|
return Buffer.concat([header, ...entries, ...images.map((i) => i.png)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- geometry ----------
|
||||||
|
function clamp(x, a, b) { return Math.min(Math.max(x, a), b); }
|
||||||
|
function mix(a, b, t) { return a + (b - a) * t; }
|
||||||
|
function mix3(c1, c2, t) { return [mix(c1[0], c2[0], t), mix(c1[1], c2[1], t), mix(c1[2], c2[2], t)]; }
|
||||||
|
|
||||||
|
// signed distance to a circular arc stroke (rounded caps), angles in radians
|
||||||
|
function arcSDF(px, py, cx, cy, r, a0, a1, w) {
|
||||||
|
const dx = px - cx, dy = py - cy;
|
||||||
|
const d = Math.hypot(dx, dy);
|
||||||
|
let ang = Math.atan2(dy, dx);
|
||||||
|
// normalize ang into [a0, a0 + 2PI)
|
||||||
|
const TWO_PI = Math.PI * 2;
|
||||||
|
while (ang < a0) ang += TWO_PI;
|
||||||
|
while (ang >= a0 + TWO_PI) ang -= TWO_PI;
|
||||||
|
let dist;
|
||||||
|
if (ang <= a1) {
|
||||||
|
dist = Math.abs(d - r);
|
||||||
|
} else {
|
||||||
|
const e0x = cx + r * Math.cos(a0), e0y = cy + r * Math.sin(a0);
|
||||||
|
const e1x = cx + r * Math.cos(a1), e1y = cy + r * Math.sin(a1);
|
||||||
|
dist = Math.min(Math.hypot(px - e0x, py - e0y), Math.hypot(px - e1x, py - e1y));
|
||||||
|
}
|
||||||
|
return dist - w / 2;
|
||||||
|
}
|
||||||
|
// rounded rect sdf
|
||||||
|
function rrSDF(px, py, cx, cy, hw, hh, r) {
|
||||||
|
const qx = Math.abs(px - cx) - (hw - r);
|
||||||
|
const qy = Math.abs(py - cy) - (hh - r);
|
||||||
|
const ax = Math.max(qx, 0), ay = Math.max(qy, 0);
|
||||||
|
return Math.hypot(ax, ay) + Math.min(Math.max(qx, qy), 0) - r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- design ----------
|
||||||
|
const DOME_C = [0.5, 0.56]; // dome circle center
|
||||||
|
const DOME_R = 0.295; // dome radius
|
||||||
|
const BLADE_C = [0.5, 0.475]; // aperture center
|
||||||
|
const BLADE_R = 0.155;
|
||||||
|
const BLADE_W = 0.048;
|
||||||
|
const ARC_C = [0.5, 0.53];
|
||||||
|
const ARC_R = 0.4;
|
||||||
|
const ARC_W = 0.036;
|
||||||
|
|
||||||
|
const NAVY = [10, 52, 128];
|
||||||
|
const BLUE_HI = [110, 196, 250];
|
||||||
|
const BLUE_LO = [9, 68, 152];
|
||||||
|
const WHITE = [248, 252, 255];
|
||||||
|
const ORANGE = [240, 128, 60];
|
||||||
|
const GREEN = [110, 190, 74];
|
||||||
|
const YELLOW = [240, 204, 60];
|
||||||
|
|
||||||
|
function domeColor(px, py) {
|
||||||
|
const t = Math.pow(clamp(Math.hypot(px - 0.34, py - 0.36) / 0.5, 0, 1), 0.8);
|
||||||
|
let c = mix3(BLUE_HI, BLUE_LO, t);
|
||||||
|
// darken slightly toward the base for depth
|
||||||
|
const base = clamp((py - 0.42) / 0.16, 0, 1) * 0.18;
|
||||||
|
return [c[0] * (1 - base), c[1] * (1 - base), c[2] * (1 - base)];
|
||||||
|
}
|
||||||
|
|
||||||
|
function bladeSDF(px, py) {
|
||||||
|
let best = 1e9;
|
||||||
|
const span = 100 * DEG;
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
const a0 = (-90 + i * 120) * DEG;
|
||||||
|
best = Math.min(best, arcSDF(px, py, BLADE_C[0], BLADE_C[1], BLADE_R, a0, a0 + span, BLADE_W));
|
||||||
|
}
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
function arcsSDF(px, py) {
|
||||||
|
return [
|
||||||
|
{ sdf: arcSDF(px, py, ARC_C[0], ARC_C[1], ARC_R, -160 * DEG, -20 * DEG, ARC_W), color: ORANGE },
|
||||||
|
{ sdf: arcSDF(px, py, ARC_C[0], ARC_C[1], ARC_R, 105 * DEG, 170 * DEG, ARC_W), color: GREEN },
|
||||||
|
{ sdf: arcSDF(px, py, ARC_C[0], ARC_C[1], ARC_R, 10 * DEG, 75 * DEG, ARC_W), color: YELLOW },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function render(size) {
|
||||||
|
const SS = 4;
|
||||||
|
const R = size * SS;
|
||||||
|
const out = Buffer.alloc(size * size * 4);
|
||||||
|
const px = 1 / R;
|
||||||
|
|
||||||
|
for (let y = 0; y < size; y++) {
|
||||||
|
for (let x = 0; x < size; x++) {
|
||||||
|
let r = 0, g = 0, b = 0, a = 0;
|
||||||
|
for (let sy = 0; sy < SS; sy++) {
|
||||||
|
for (let sx = 0; sx < SS; sx++) {
|
||||||
|
const nx = (x * SS + sx + 0.5) / R;
|
||||||
|
const ny = (y * SS + sy + 0.5) / R;
|
||||||
|
const aa = (sdf) => clamp(0.5 - sdf / px, 0, 1);
|
||||||
|
|
||||||
|
let cr = 0, cg = 0, cb = 0, ca = 0;
|
||||||
|
const over = (sdf, col, opacity) => {
|
||||||
|
const cov = aa(sdf) * opacity;
|
||||||
|
cr = cr * (1 - cov) + col[0] * cov;
|
||||||
|
cg = cg * (1 - cov) + col[1] * cov;
|
||||||
|
cb = cb * (1 - cov) + col[2] * cov;
|
||||||
|
ca = ca * (1 - cov) + cov;
|
||||||
|
};
|
||||||
|
|
||||||
|
// base bar
|
||||||
|
over(rrSDF(nx, ny, 0.5, DOME_C[1] + 0.022, DOME_R + 0.045, 0.028, 0.026), NAVY, 1);
|
||||||
|
// dome (upper half of circle)
|
||||||
|
const dd = Math.max(Math.hypot(nx - DOME_C[0], ny - DOME_C[1]) - DOME_R, ny - DOME_C[1]);
|
||||||
|
over(dd, domeColor(nx, ny), 1);
|
||||||
|
// aperture blades
|
||||||
|
over(bladeSDF(nx, ny), WHITE, 0.95);
|
||||||
|
// colored arcs
|
||||||
|
for (const arc of arcsSDF(nx, ny)) over(arc.sdf, arc.color, 1);
|
||||||
|
|
||||||
|
r += cr; g += cg; b += cb; a += ca;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const n = SS * SS;
|
||||||
|
const o = (y * size + x) * 4;
|
||||||
|
out[o] = Math.round(clamp(r / n, 0, 255));
|
||||||
|
out[o + 1] = Math.round(clamp(g / n, 0, 255));
|
||||||
|
out[o + 2] = Math.round(clamp(b / n, 0, 255));
|
||||||
|
out[o + 3] = Math.round(clamp(a / n, 0, 1) * 255);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- main ----------
|
||||||
|
const outDir = process.argv[2] || '.';
|
||||||
|
const sizes = [16, 24, 32, 48, 64, 128, 256];
|
||||||
|
const images = sizes.map((s) => ({ size: s, png: pngEncode(s, s, render(s)) }));
|
||||||
|
|
||||||
|
fs.writeFileSync(path.join(outDir, 'obs.png'), images[images.length - 1].png);
|
||||||
|
fs.writeFileSync(path.join(outDir, 'obs-studio.ico'), icoEncode(images));
|
||||||
|
console.log('wrote obs.png (256x256) and obs-studio.ico (' + sizes.join(',') + ') to ' + outDir);
|
||||||