Skip to content

Commit 5aec875

Browse files
committed
added post cmyk halftone
1 parent 0e76c83 commit 5aec875

File tree

5 files changed

+490
-0
lines changed

5 files changed

+490
-0
lines changed

post-cmyk-halftone-i/Material.js

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
import {
2+
MeshStandardMaterial,
3+
Vector2,
4+
Color,
5+
} from "../third_party/three.module.js";
6+
7+
class Material extends MeshStandardMaterial {
8+
constructor(options) {
9+
super(options);
10+
11+
this.params = {
12+
roughness: 0.4,
13+
metalness: 0.1,
14+
scale: 100,
15+
inkColor: 0x1831d3,
16+
min: 0.1,
17+
max: 0.9,
18+
e: 0.1,
19+
};
20+
21+
this.uniforms = {
22+
resolution: { value: new Vector2(1, 1) },
23+
paperTexture: { value: null },
24+
scale: { value: this.params.scale },
25+
inkColor: { value: new Color(this.params.inkColor) },
26+
range: { value: new Vector2(this.params.min, this.params.max) },
27+
e: { value: this.params.e },
28+
};
29+
30+
this.onBeforeCompile = (shader, renderer) => {
31+
for (const uniformName of Object.keys(this.uniforms)) {
32+
shader.uniforms[uniformName] = this.uniforms[uniformName];
33+
}
34+
35+
shader.vertexShader = shader.vertexShader.replace(
36+
`#include <common>`,
37+
`#include <common>
38+
out vec2 vCoords;
39+
out vec3 vPosition;
40+
out vec4 vWorldPosition;`
41+
);
42+
shader.vertexShader = shader.vertexShader.replace(
43+
`#include <uv_vertex>`,
44+
`#include <uv_vertex>
45+
vCoords = uv;
46+
vPosition = position;
47+
vWorldPosition = modelMatrix * vec4(position, 1.);// + vec4(normal.xyz, 0.);`
48+
);
49+
50+
shader.fragmentShader = shader.fragmentShader.replace(
51+
`#include <common>`,
52+
`#include <common>
53+
uniform vec2 resolution;
54+
uniform sampler2D paperTexture;
55+
uniform vec3 inkColor;
56+
uniform vec2 range;
57+
uniform float scale;
58+
uniform float e;
59+
in vec2 vCoords;
60+
in vec3 vPosition;
61+
in vec4 vWorldPosition;
62+
#define TAU 6.28318530718
63+
64+
// Classic Perlin 3D Noise
65+
// by Stefan Gustavson
66+
//
67+
vec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);}
68+
vec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;}
69+
vec3 fade(vec3 t) {return t*t*t*(t*(t*6.0-15.0)+10.0);}
70+
71+
float cnoise(vec3 P){
72+
vec3 Pi0 = floor(P); // Integer part for indexing
73+
vec3 Pi1 = Pi0 + vec3(1.0); // Integer part + 1
74+
Pi0 = mod(Pi0, 289.0);
75+
Pi1 = mod(Pi1, 289.0);
76+
vec3 Pf0 = fract(P); // Fractional part for interpolation
77+
vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0
78+
vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
79+
vec4 iy = vec4(Pi0.yy, Pi1.yy);
80+
vec4 iz0 = Pi0.zzzz;
81+
vec4 iz1 = Pi1.zzzz;
82+
83+
vec4 ixy = permute(permute(ix) + iy);
84+
vec4 ixy0 = permute(ixy + iz0);
85+
vec4 ixy1 = permute(ixy + iz1);
86+
87+
vec4 gx0 = ixy0 / 7.0;
88+
vec4 gy0 = fract(floor(gx0) / 7.0) - 0.5;
89+
gx0 = fract(gx0);
90+
vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0);
91+
vec4 sz0 = step(gz0, vec4(0.0));
92+
gx0 -= sz0 * (step(0.0, gx0) - 0.5);
93+
gy0 -= sz0 * (step(0.0, gy0) - 0.5);
94+
95+
vec4 gx1 = ixy1 / 7.0;
96+
vec4 gy1 = fract(floor(gx1) / 7.0) - 0.5;
97+
gx1 = fract(gx1);
98+
vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1);
99+
vec4 sz1 = step(gz1, vec4(0.0));
100+
gx1 -= sz1 * (step(0.0, gx1) - 0.5);
101+
gy1 -= sz1 * (step(0.0, gy1) - 0.5);
102+
103+
vec3 g000 = vec3(gx0.x,gy0.x,gz0.x);
104+
vec3 g100 = vec3(gx0.y,gy0.y,gz0.y);
105+
vec3 g010 = vec3(gx0.z,gy0.z,gz0.z);
106+
vec3 g110 = vec3(gx0.w,gy0.w,gz0.w);
107+
vec3 g001 = vec3(gx1.x,gy1.x,gz1.x);
108+
vec3 g101 = vec3(gx1.y,gy1.y,gz1.y);
109+
vec3 g011 = vec3(gx1.z,gy1.z,gz1.z);
110+
vec3 g111 = vec3(gx1.w,gy1.w,gz1.w);
111+
112+
vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110)));
113+
g000 *= norm0.x;
114+
g010 *= norm0.y;
115+
g100 *= norm0.z;
116+
g110 *= norm0.w;
117+
vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111)));
118+
g001 *= norm1.x;
119+
g011 *= norm1.y;
120+
g101 *= norm1.z;
121+
g111 *= norm1.w;
122+
123+
float n000 = dot(g000, Pf0);
124+
float n100 = dot(g100, vec3(Pf1.x, Pf0.yz));
125+
float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z));
126+
float n110 = dot(g110, vec3(Pf1.xy, Pf0.z));
127+
float n001 = dot(g001, vec3(Pf0.xy, Pf1.z));
128+
float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z));
129+
float n011 = dot(g011, vec3(Pf0.x, Pf1.yz));
130+
float n111 = dot(g111, Pf1);
131+
132+
vec3 fade_xyz = fade(Pf0);
133+
vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z);
134+
vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y);
135+
float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x);
136+
return 2.2 * n_xyz;
137+
}
138+
139+
// from https://www.shadertoy.com/view/ltfXR4
140+
vec3 catmul_rom(vec3 p0, vec3 p1, vec3 p2, vec3 p3, float t)
141+
{
142+
return 0.5 * (
143+
(2.0 * p1) +
144+
(-p0 + p2) * t +
145+
(2.0 * p0 - 5.0 * p1 + 4.0 * p2 - p3) * t * t +
146+
(-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t * t * t);
147+
}
148+
149+
vec3 color_spline(float t, bool wrap)
150+
{
151+
t = clamp(t, 0.0, 1.0);
152+
153+
const int s = 7;
154+
155+
vec3 p[s];
156+
p[0] = vec3(238, 64, 53) / 255.0;
157+
p[1] = vec3(243, 119, 54) / 255.0;
158+
p[2] = vec3(253, 244, 152) / 255.0;
159+
p[3] = vec3(123, 192, 67) / 255.0;
160+
p[4] = vec3(3, 146, 207) / 255.0;
161+
162+
p[s-2] = p[0];
163+
p[s-1] = p[1];
164+
165+
float m = wrap ? float(s - 2) : float(s - 3);
166+
float d = m * t;
167+
168+
int b = int(d);
169+
float dt = d - floor(d);
170+
171+
return catmul_rom(p[((b-1)+s)%s], p[b], p[b+1], p[(b+2)%s], dt);
172+
}
173+
174+
`
175+
);
176+
shader.fragmentShader = shader.fragmentShader.replace(
177+
"#include <dithering_fragment>",
178+
`#include <dithering_fragment>
179+
float w = .5;
180+
float n = smoothstep(.5-w, .5+w, .5 + .5 * cnoise(.1*vWorldPosition.xyz));
181+
gl_FragColor.rgb *= 2.;
182+
gl_FragColor.rgb *= color_spline(n, true);//mix(col, col2, n2);
183+
`
184+
);
185+
};
186+
}
187+
}
188+
189+
function generateParams(gui, material) {
190+
const params = material.params;
191+
gui.add(params, "roughness", 0, 1).onChange((v) => (material.roughness = v));
192+
gui.add(params, "metalness", 0, 1).onChange((v) => (material.metalness = v));
193+
}
194+
195+
export { Material, generateParams };

post-cmyk-halftone-i/index.html

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<title>Sketch</title>
6+
<meta
7+
name="viewport"
8+
content="width=device-width, initial-scale=1.0, user-scalable=no"
9+
/>
10+
<style>
11+
*{
12+
box-sizing: border-box;
13+
margin: 0;
14+
padding: 0;
15+
}
16+
canvas {
17+
position: absolute;
18+
left: 0;
19+
top: 0;
20+
right: 0;
21+
bottom: 0;
22+
width: 100%;
23+
height: 100%;
24+
}
25+
</style>
26+
</head>
27+
<body>
28+
<canvas id="canvas"></canvas>
29+
</body>
30+
<script type="module" src="./main.js"></script>
31+
</html>

post-cmyk-halftone-i/main.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { DoubleSide } from "../third_party/three.module.js";
2+
import { Material, generateParams } from "./Material.js";
3+
import * as dat from "../third_party/dat.gui.module.js";
4+
import { initScene, update } from "../js/scene.js";
5+
import { renderer, scene, camera, resize, onResize } from "../js/renderer.js";
6+
import { generateParams as generateEnvParams } from "../js/envMap.js";
7+
import { Post } from "./post.js";
8+
9+
const post = new Post(renderer);
10+
11+
const gui = new dat.GUI();
12+
const materialFolder = gui.addFolder("Material");
13+
materialFolder.open();
14+
15+
const material = new Material({
16+
color: 0x808080,
17+
roughness: 0.2,
18+
metalness: 0.1,
19+
side: DoubleSide,
20+
});
21+
generateParams(materialFolder, material);
22+
const postController = post.generateParams(materialFolder);
23+
postController["paper"].setValue("Parchment");
24+
const envMapController = generateEnvParams(materialFolder, material);
25+
envMapController.setValue("bridge");
26+
27+
function render() {
28+
update();
29+
post.render(scene, camera);
30+
renderer.setAnimationLoop(render);
31+
}
32+
33+
async function init() {
34+
const controllers = await initScene(scene, material, gui);
35+
controllers.torus.setValue(true);
36+
controllers.spheres.setValue(true);
37+
resize();
38+
render();
39+
}
40+
41+
onResize(() => {
42+
const width = window.innerWidth;
43+
const height = window.innerHeight;
44+
const dPR = window.devicePixelRatio;
45+
post.setSize(width * dPR, height * dPR);
46+
});
47+
48+
init();

0 commit comments

Comments
 (0)