Merge pull request #10 from AlekPet/lines_update

updated styles, betters view wrappers, index.html and add Canny Edge
This commit is contained in:
lo-th
2024-12-02 21:35:57 +01:00
committed by GitHub
5 changed files with 203 additions and 59 deletions
+34 -16
View File
@@ -10,7 +10,7 @@ import { LuminosityShader } from './lib/jsm/shaders/LuminosityShader.js';
import { ExposureShader } from './lib/jsm/shaders/ExposureShader.js';
import { BrightnessContrastShader } from './lib/jsm/shaders/BrightnessContrastShader.js';
import { Outline, Inline, BlackAll, sobelShader, thresholdShader } from "./lib/Toon.js";
import { Outline, Inline, BlackAll, sobelShader, cannyEdgeShader, thresholdShader } from "./lib/Toon.js";
import { Hub } from "./lib/Hub.js";
import { Files } from "./lib/Files.js";
import { Tools } from "./lib/Tools.js";
@@ -68,7 +68,7 @@ export class ThreeCanvas {
createWrappers(canvasNames){
// Operators "Sobel", "Scharr", "Prewitt"
const linesOperators = ["Sobel", "Prewitt", "Scharr"];
const linesOperators = ["Sobel", "Prewitt", "Scharr", "Canny"];
const listLines = $el("select.linesMethod_box",{
style: {
fontSize: "0.5rem",
@@ -80,7 +80,8 @@ export class ThreeCanvas {
outline: 0
},
onchange: (e)=> {
this.sobelPassRadio = e.target.value
this.sobelPassSelect = e.target.value
this.composer = null
this.render()
},
title: "Selectd operator for lines"
@@ -150,11 +151,11 @@ export class ThreeCanvas {
$el("button.threeCanvasButton.threeCanvasViews3", {
textContent: "All Views",
onclick: (e) => {
this.VIEWS3 = !this.VIEWS3
this.VIEWS3 = !this.VIEWS3;
this.panelWrapper.querySelector(".threeCanvasViews3_camerafix").style.display = this.VIEWS3 ? "block": "none"
this.panelWrapper.querySelector(".threeCanvasViews3_camerafix").style.display = this.VIEWS3 ? "block": "none";
// threeCanvas.fixCamers = threeCanvas.VIEWS3
this.setViews3(this.wrappers)
this.setViews3(this.wrappers);
},
}),
$el("input.threeCanvasViews3_camerafix", {
@@ -166,6 +167,7 @@ export class ThreeCanvas {
},
onchange: (e)=>{
this.fixCamers = !!e.target.checked
this.composer = null
},
})]),
]
@@ -368,6 +370,12 @@ export class ThreeCanvas {
}
setViews3(){
if( this.VIEWS3 ){
this.threeWrapper.classList.add("threeWrapper3Views");
} else {
this.threeWrapper.classList.remove("threeWrapper3Views");
}
this.wrappers.slice(1).map((v)=> Object.assign(v.style, {
display: this.VIEWS3 ? "block" : "none"
}))
@@ -610,18 +618,17 @@ export class ThreeCanvas {
this.render();
}
initComposer(renderer){
initComposer(renderer, camera){
const operatorLines = this?.sobelPassSelect ?? 0
// init only one composer
if(this.composer){
// Set changed line type
this.effectSobel.uniforms.lineType.value = this?.sobelPassRadio ?? 0
return;
}
const composer = new EffectComposer(renderer);
const renderPass = new RenderPass(this.scene, this.camera);
const renderPass = new RenderPass(this.scene, camera);
composer.addPass(renderPass);
// color to grayscale conversion
@@ -633,12 +640,23 @@ export class ThreeCanvas {
effectExposure.uniforms[ 'exposure' ].value = 0.75;
composer.addPass( effectExposure )
const effectSobel = new ShaderPass( SobelOperatorShader );
effectSobel.uniforms[ 'resolution' ].value.x = this.size.w;
effectSobel.uniforms[ 'resolution' ].value.y = this.size.h;
if(operatorLines <= 2){
const effectSobel = new ShaderPass( SobelOperatorShader );
effectSobel.uniforms[ 'resolution' ].value.x = this.size.w;
effectSobel.uniforms[ 'resolution' ].value.y = this.size.h;
// Set changed line type
effectSobel.uniforms.lineType.value = operatorLines
this.effectSobel = effectSobel
composer.addPass( effectSobel )
composer.addPass( effectSobel )
} else if(operatorLines == 3){
// Canny edge
const effectCannyEdge = new ShaderPass( cannyEdgeShader );
effectCannyEdge.uniforms.resolution.value.x = this.size.w;
effectCannyEdge.uniforms.resolution.value.y = this.size.h;
composer.addPass( effectCannyEdge )
}
// this.effectSobel = new ShaderPass(sobelShader);
// composer.addPass(this.effectSobel);
@@ -669,7 +687,7 @@ export class ThreeCanvas {
if(this.useLinesComposer){
this.initComposer(data.renderer)
this.initComposer(data.renderer, camera)
return this.composer.render(this.scene)
}
+8 -2
View File
@@ -1,5 +1,11 @@
.threeWrapper {
/* wrapper all canvases */
display: grid;
grid-template-columns: 1fr;
gap: 5px;
}
.threeWrapper3Views{
grid-template-columns: 1fr 1fr;
}
.threeCanvasPanelWrapper {
@@ -35,7 +41,7 @@
}
.wrapperThreeViewCanvas {
position: absolute;
position: relative;
margin: 0px;
padding: 0px;
display: block;
+47 -16
View File
@@ -9,18 +9,33 @@
<meta name="publisher" content="lo-th"/>
<title>THREE DIRECT</title>
<meta name="description" content="test three view"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" crossorigin href="../../../../extensions/Comfyui_three_js/css/styles.css">
<link rel="stylesheet" crossorigin href="./css/styles.css">
<style>
.threeWrapper {
display: grid;
margin-top: 50px;
grid-template-columns: 1fr 1fr;
width: 1000px;
max-width: 1000px;
padding: 20px;
transition: 1s all;
}
.wrapperThreeViewCanvas {
position: relative;
@media (max-width: 1000px){
.threeWrapper{
max-width: 700px;
}
}
@media (max-width: 700px){
.threeWrapper{
max-width: 500px;
}
}
@media (max-width: 500px){
.threeWrapper{
max-width: 200px;
}
}
</style>
@@ -28,18 +43,34 @@
<body style="background-color:#000; margin:0; padding:0; overflow:hidden;">
<script type="module">
import { ThreeCanvas } from '../../../../extensions/Comfyui_three_js/ThreeCanvas.js'
const canvasNames = [
{name:"image", color: "silver"},
{name:"lines", color: "red"},
{name:"depth", color: "yellow"},
{name:"normal", color: "#8080ff"}
];
async function loadThreeCanvas({path1, path2}) {
try {
const module = await import(path1);
return module.ThreeCanvas;
} catch (error) {
console.warn('Error import module first path:', error.message);
const module = await import(path2);
return module.ThreeCanvas;
}
}
const threeCanvas = new ThreeCanvas(null, null, {views3: true});
threeCanvas.init(canvasNames);
// Использование функции
loadThreeCanvas({path1: '../../../../extensions/Comfyui_three_js/ThreeCanvas.js', path2:'./ThreeCanvas.js'})
.then(ThreeCanvas => {
const canvasNames = [
{name:"image", color: "silver"},
{name:"lines", color: "red"},
{name:"depth", color: "yellow"},
{name:"normal", color: "#8080ff"}
];
document.body.append(threeCanvas.panelWrapper, threeCanvas.threeWrapper);
const threeCanvas = new ThreeCanvas(null, null, {views3: true});
threeCanvas.init(canvasNames);
document.body.append(threeCanvas.panelWrapper, threeCanvas.threeWrapper);
}).catch(error => {
console.error('Ошибка загрузки ThreeCanvas:', error);
});
</script>
</body>
</html>
+113
View File
@@ -123,6 +123,119 @@ export const sobelShader = {
`
};
// Canny edge detection shader
export const cannyEdgeShader = {
uniforms: {
tDiffuse: { value: null },
resolution: { value: new THREE.Vector2() },
lowThreshold: { value: 0.1 },
highThreshold: { value: 0.3 }
},
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
// Canny edge detection shader (copy the GLSL code here from the previous implementation)
precision highp float;
uniform sampler2D tDiffuse;
uniform vec2 resolution;
uniform float lowThreshold;
uniform float highThreshold;
varying vec2 vUv;
const float kernel[9] = float[9](
1.0 / 16.0, 2.0 / 16.0, 1.0 / 16.0,
2.0 / 16.0, 4.0 / 16.0, 2.0 / 16.0,
1.0 / 16.0, 2.0 / 16.0, 1.0 / 16.0
);
void main() {
vec2 texel = vec2(1.0 / resolution.x, 1.0 / resolution.y);
vec3 blurred = vec3(0.0);
int k = 0;
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
blurred += texture2D(tDiffuse, vUv + vec2(i, j) * texel).rgb * kernel[k++];
}
}
float gray = dot(blurred, vec3(0.2989, 0.5870, 0.1140));
float Gx[9] = float[9](
-1.0, 0.0, 1.0,
-2.0, 0.0, 2.0,
-1.0, 0.0, 1.0
);
float Gy[9] = float[9](
-1.0, -2.0, -1.0,
0.0, 0.0, 0.0,
1.0, 2.0, 1.0
);
float gradientX = 0.0;
float gradientY = 0.0;
k = 0;
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
float xsample = texture2D(tDiffuse, vUv + vec2(i, j) * texel).r;
gradientX += xsample * Gx[k];
gradientY += xsample * Gy[k++];
}
}
float magnitude = length(vec2(gradientX, gradientY));
float direction = atan(gradientY, gradientX);
float angle = mod(direction + 3.14159265, 3.14159265) / 3.14159265 * 4.0;
float neighbor1 = 0.0;
float neighbor2 = 0.0;
if (angle <= 1.0 || angle > 3.0) {
neighbor1 = texture2D(tDiffuse, vUv + vec2(texel.x, 0.0)).r;
neighbor2 = texture2D(tDiffuse, vUv - vec2(texel.x, 0.0)).r;
} else if (angle <= 2.0) {
neighbor1 = texture2D(tDiffuse, vUv + vec2(texel.x, -texel.y)).r;
neighbor2 = texture2D(tDiffuse, vUv - vec2(texel.x, -texel.y)).r;
} else {
neighbor1 = texture2D(tDiffuse, vUv + vec2(0.0, texel.y)).r;
neighbor2 = texture2D(tDiffuse, vUv - vec2(0.0, texel.y)).r;
}
if (magnitude < neighbor1 || magnitude < neighbor2) {
magnitude = 0.0;
}
float edge = 0.0;
if (magnitude >= highThreshold) {
edge = 1.0;
} else if (magnitude >= lowThreshold) {
edge = 0.5;
}
if (edge == 0.5) {
bool connected = false;
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
if (texture2D(tDiffuse, vUv + vec2(i, j) * texel).r >= highThreshold) {
connected = true;
}
}
}
if (!connected) edge = 0.0;
}
gl_FragColor = vec4(vec3(edge), 1.0);
}
`
};
export const thresholdShader = {
uniforms: {
tDiffuse: { value: null },
+1 -25
View File
@@ -71,7 +71,7 @@ async function widgetThreeJS(node, nodeData, inputData, app, params = {}) {
origDraw?.apply(this, arguments);
const [ctx, nodeThree, widgetWidth, posY] = arguments;
const w = !threeCanvas.VIEWS3 ? widgetWidth - 25: (widgetWidth - 25)/2;
const w = widgetWidth - 25;
const aspect_ratio = threeCanvas.size.h / threeCanvas.size.w;
Object.assign(threeCanvas.threeWrapper.style, {
@@ -79,30 +79,6 @@ async function widgetThreeJS(node, nodeData, inputData, app, params = {}) {
height: w * aspect_ratio + "px",
});
if( threeCanvas.VIEWS3 ){
Object.assign(threeCanvas.getWrapper(1).style, {
width: w + "px",
height: w * aspect_ratio + "px",
left: w + 10 + "px"
});
Object.assign(threeCanvas.getWrapper(2).style, {
width: w + "px",
height: w * aspect_ratio + "px",
top: parseFloat(threeCanvas.getWrapper(1).style.height) + 10 + "px"
});
Object.assign(threeCanvas.getWrapper(3).style, {
width: w + "px",
height: w * aspect_ratio + "px",
left: w + 10 + "px",
top: parseFloat(threeCanvas.getWrapper(1).style.height) + 10 + "px"
});
}
// Update renderer
// threeCanvas.update(node.size[0]);
//app.graph.setDirtyCanvas(true, false);