Files
2024-12-04 11:45:56 +01:00

300 lines
9.2 KiB
JavaScript

import * as THREE from "./three.module.js"
export const Depth = new THREE.ShaderMaterial({
uniforms: {
u_abcd: { value: new THREE.Vector4(0, -1, 0, 10) },
u_unitLength: { value: 5.0 }
},
vertexShader:/* glsl */ `
varying vec4 v_worldPosition;
void main()
{
v_worldPosition = modelMatrix * vec4( position, 1.0 );
vec4 mvPosition = viewMatrix * v_worldPosition;
gl_Position = projectionMatrix * mvPosition;
}
`,
fragmentShader:/* glsl */ `
uniform vec4 u_abcd;
uniform float u_unitLength;
varying vec4 v_worldPosition;
void main( void )
{
float depth = dot(u_abcd.xyz, v_worldPosition.xyz) + u_abcd.w;
vec3 color = vec3(depth / u_unitLength);
gl_FragColor = vec4( color, 1.0 );
}
`,
});
export const Outline = new THREE.ShaderMaterial({
uniforms: {
color: { value: new THREE.Color(0xffFFFF) },
power: { value: 0.002 },
},
vertexShader:/* glsl */ `
uniform float power;
void main(){
vec3 pos = position + normal * power;
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos,1.0);
}
`,
fragmentShader:/* glsl */ `
uniform vec3 color;
void main(){
gl_FragColor = vec4( color, 1.0 );
}
`,
depthTest:false,
depthWrite:false,
side:THREE.DoubleSide
});
export const Inline = new THREE.ShaderMaterial({
uniforms: {
color: { value: new THREE.Color(0xFFFFFF) },
power: { value: 0.001 },
},
vertexShader:/* glsl */ `
uniform float power;
void main(){
vec3 pos = position + normal * power;
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos,1.0);
}
`,
fragmentShader:/* glsl */ `
uniform vec3 color;
void main(){
gl_FragColor = vec4( color, 1.0 );
}
`,
side:THREE.BackSide
});
export const BlackAll = new THREE.MeshBasicMaterial({color:0x000000});
export const sobelShader = {
uniforms: {
tDiffuse: { value: null }, // Входное изображение
resolution: { value: new THREE.Vector2(window.innerWidth, window.innerHeight) },
lineaType: {value: 0}
},
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
varying vec2 vUv;
uniform sampler2D tDiffuse;
uniform vec2 resolution;
uniform int lineaType;
void main() {
vec2 texel = vec2(1.0 / resolution.x, 1.0 / resolution.y);
// sobel filter
float kernelX[9];
float kernelY[9];
if(lineaType == 2){
kernelX[0] = -1.0; kernelX[1] = 0.0; kernelX[2] = 1.0;
kernelX[3] = -1.0; kernelX[4] = 0.0; kernelX[5] = 1.0;
kernelX[6] = -1.0; kernelX[7] = 0.0; kernelX[8] = 1.0;
kernelY[0] = -1.0; kernelY[1] = -1.0; kernelY[2] = -1.0;
kernelY[3] = 0.0; kernelY[4] = 0.0; kernelY[5] = 0.0;
kernelY[6] = 1.0; kernelY[7] = 1.0; kernelY[8] = 1.0;
} else if (lineaType == 1){
kernelX[0] = 3.0; kernelX[1] = 10.0; kernelX[2] = 3.0;
kernelX[3] = 0.0; kernelX[4] = 0.0; kernelX[5] = 0.0;
kernelX[6] = -3.0; kernelX[7] = -10.0; kernelX[8] = -3.0;
kernelY[0] = 3.0; kernelY[1] = 0.0; kernelY[2] = -3.0;
kernelY[3] = 10.0; kernelY[4] = 0.0; kernelY[5] = -10.0;
kernelY[6] = 3.0; kernelY[7] = 0.0; kernelY[8] = -3.0;
} else {
kernelX[0] = -1.0; kernelX[1] = 0.0; kernelX[2] = 1.0;
kernelX[3] = -2.0; kernelX[4] = 0.0; kernelX[5] = 2.0;
kernelX[6] = -1.0; kernelX[7] = 0.0; kernelX[8] = 1.0;
kernelY[0] = -1.0; kernelY[1] = -2.0; kernelY[2] = -1.0;
kernelY[3] = 0.0; kernelY[4] = 0.0; kernelY[5] = 0.0;
kernelY[6] = 1.0; kernelY[7] = 2.0; kernelY[8] = 1.0;
}
vec3 xsample[9];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
xsample[i * 3 + j] = texture2D(tDiffuse, vUv + texel * vec2(i - 1, j - 1)).rgb;
}
}
float gx = 0.0;
float gy = 0.0;
for (int i = 0; i < 9; i++) {
gx += kernelX[i] * xsample[i].r;
gy += kernelY[i] * xsample[i].r;
}
float g = sqrt(gx * gx + gy * gy);
gl_FragColor = vec4(vec3(g), 1.0);
}
`
};
// 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 },
threshold: { value: 0.4 }
},
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
varying vec2 vUv;
uniform sampler2D tDiffuse;
uniform float threshold;
void main() {
float value = texture2D(tDiffuse, vUv).r;
//gl_FragColor = vec4(vec3(value > threshold ? 1.0 : 0.0), 1.0);
gl_FragColor = vec4(vec3(value > threshold ? value*1.5 : 0.0), 1.0);
}
`
};
export class Toon {
}