1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189import * as THREE from "three"
// Non-Euclidean vertex shader for spherical geometry warping
export const vertexShader = `
uniform float time;
uniform float curvature; // Controls the amount of non-Euclidean warping
varying vec2 vUv;
varying vec3 vPosition;
varying vec3 vNormal;
varying float vDistortion;
// Function to apply spherical warping
vec3 applySphericalWarping(vec3 position) {
float radius = 10.0; // Radius of the spherical space
float distFromCenter = length(position);
// Apply non-linear warping based on distance from center
float warpFactor = 1.0 + curvature * (distFromCenter / radius) * (distFromCenter / radius);
// Apply time-based subtle warping with cyberpunk pulsing
float timeFactor = sin(time * 0.5) * 0.5 + 0.5;
warpFactor += sin(time * 0.3 + position.x * 0.1 + position.z * 0.1) * 0.03 * curvature * timeFactor;
// Pass distortion factor to fragment shader
vDistortion = warpFactor - 1.0;
return position * warpFactor;
}
void main() {
vUv = uv;
vPosition = position;
vNormal = normal;
// Apply non-Euclidean warping
vec3 warpedPosition = applySphericalWarping(position);
// Project the warped position
gl_Position = projectionMatrix * modelViewMatrix * vec4(warpedPosition, 1.0);
}
`
// Fragment shader compatible with warped geometry
export const fragmentShader = `
uniform float time;
uniform vec3 color;
uniform vec3 emissiveColor;
uniform float emissiveIntensity;
varying vec2 vUv;
varying vec3 vPosition;
varying vec3 vNormal;
varying float vDistortion;
void main() {
// Calculate lighting based on normal
vec3 light = normalize(vec3(1.0, 1.0, 1.0));
float diffuse = max(0.0, dot(vNormal, light)) * 0.7 + 0.3;
// Apply color with lighting
vec3 finalColor = color * diffuse;
// Add cyberpunk edge glow based on distortion
float edgeGlow = smoothstep(0.0, 0.5, vDistortion) * emissiveIntensity;
// Add time-based pulsing to the glow
edgeGlow *= 0.8 + 0.2 * sin(time * 2.0 + vPosition.x * 0.5 + vPosition.z * 0.5);
// Apply emissive glow
finalColor += emissiveColor * edgeGlow;
// Add subtle scan lines
float scanLine = sin(vUv.y * 100.0 + time * 5.0) * 0.03 + 0.97;
finalColor *= scanLine;
gl_FragColor = vec4(finalColor, 1.0);
}
`
// Create a non-Euclidean material using the shaders with cyberpunk styling
export function createNonEuclideanMaterial(
color = new THREE.Color(0x121624),
emissiveColor = new THREE.Color(0x00ffff),
emissiveIntensity = 1.0,
) {
return new THREE.ShaderMaterial({
uniforms: {
time: { value: 0 },
curvature: { value: 0.2 }, // Adjust for more or less warping
color: { value: color },
emissiveColor: { value: emissiveColor },
emissiveIntensity: { value: emissiveIntensity },
},
vertexShader,
fragmentShader,
side: THREE.DoubleSide,
})
}
// Create a holographic material
export function createHolographicMaterial(color = new THREE.Color(0x00ffff), opacity = 0.7) {
return new THREE.ShaderMaterial({
uniforms: {
time: { value: 0 },
color: { value: color },
opacity: { value: opacity },
},
vertexShader: `
uniform float time;
varying vec2 vUv;
varying float vElevation;
void main() {
vUv = uv;
// Add some vertex displacement for holographic effect
vec3 pos = position;
float elevation = sin(pos.x * 5.0 + time * 2.0) * sin(pos.z * 5.0 + time * 2.0) * 0.05;
pos.y += elevation;
vElevation = elevation;
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}
`,
fragmentShader: `
uniform float time;
uniform vec3 color;
uniform float opacity;
varying vec2 vUv;
varying float vElevation;
void main() {
// Create holographic scan lines
float scanLine = sin(vUv.y * 50.0 + time * 5.0) * 0.15 + 0.85;
// Horizontal scan line
float horizontalScan = smoothstep(0.0, 0.1, abs(fract(time * 0.5) - vUv.y)) * 0.15 + 0.85;
// Edge highlighting
float edge = 1.0 - smoothstep(0.0, 0.05, abs(vUv.y - 0.95)) * 0.5;
edge *= 1.0 - smoothstep(0.0, 0.05, abs(vUv.y - 0.05)) * 0.5;
edge *= 1.0 - smoothstep(0.0, 0.05, abs(vUv.x - 0.95)) * 0.5;
edge *= 1.0 - smoothstep(0.0, 0.05, abs(vUv.x - 0.05)) * 0.5;
// Final color calculation
vec3 finalColor = color * scanLine * horizontalScan;
finalColor += color * edge * 0.5;
finalColor += color * vElevation * 10.0;
// Add time-based flicker
float flicker = 0.95 + 0.05 * sin(time * 20.0);
finalColor *= flicker;
// Calculate alpha with scan lines and edges
float alpha = opacity * scanLine * horizontalScan * (1.0 + edge * 0.5);
gl_FragColor = vec4(finalColor, alpha);
}
`,
transparent: true,
side: THREE.DoubleSide,
})
}
// Create a neon material
export function createNeonMaterial(color = new THREE.Color(0xff00ff)) {
return new THREE.MeshStandardMaterial({
color: color,
emissive: color,
emissiveIntensity: 2.0,
roughness: 0.2,
metalness: 0.8,
})
}
// Update shader uniforms
export function updateShaderUniforms(scene: THREE.Object3D, time: number) {
scene.traverse((object) => {
if (object instanceof THREE.Mesh && object.material instanceof THREE.ShaderMaterial) {
if (object.material.uniforms.time !== undefined) {
object.material.uniforms.time.value = time
}
}
})
}