Created
February 3, 2025 09:17
-
-
Save oivoodoo/8479c562af435eeeed008c4a42c483f7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from "react"; | |
import { Dimensions } from "react-native"; | |
import { GLView } from "expo-gl"; | |
const ANIMATION_SPEED = 0.08; | |
const vertexShaderSource = ` | |
attribute vec2 a_position; | |
void main() { | |
gl_Position = vec4(a_position, 0, 1); | |
} | |
`; | |
const fragmentShaderSource = ` | |
precision highp float; | |
uniform float u_time; | |
uniform vec2 u_resolution; | |
float random(vec2 st) { | |
return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453); | |
} | |
void main() { | |
vec2 uv = gl_FragCoord.xy / u_resolution.xy; | |
uv.x *= u_resolution.x / u_resolution.y; | |
float starValue = 0.0; | |
for (int i = 0; i < 100; i++) { | |
vec2 starPos = vec2(random(vec2(float(i), 0.0)), random(vec2(0.0, float(i)))); | |
float starSize = random(vec2(float(i), 1.0)) * 0.025; | |
float starBrightness = random(vec2(float(i), 2.0)); | |
float dist = distance(uv, starPos); | |
starValue += smoothstep(starSize, 0.0, dist) * starBrightness; | |
} | |
float twinkle = sin(u_time * 5.0 + uv.x * 10.0) * 0.5 + 0.5; | |
starValue *= twinkle; | |
gl_FragColor = vec4(vec3(starValue), 1.0); | |
} | |
`; | |
const StarryBackground = () => { | |
const onContextCreate = (gl: WebGLRenderingContext) => { | |
// Compile vertex shader | |
const vertexShader = gl.createShader(gl.VERTEX_SHADER); | |
if (!vertexShader) { | |
throw new Error("Failed to create vertex shader"); | |
} | |
gl.shaderSource(vertexShader, vertexShaderSource); | |
gl.compileShader(vertexShader); | |
// Compile fragment shader | |
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); | |
if (!fragmentShader) { | |
throw new Error("Failed to create fragment shader"); | |
} | |
gl.shaderSource(fragmentShader, fragmentShaderSource); | |
gl.compileShader(fragmentShader); | |
// Create and link program | |
const program = gl.createProgram(); | |
gl.attachShader(program, vertexShader); | |
gl.attachShader(program, fragmentShader); | |
gl.linkProgram(program); | |
gl.useProgram(program); | |
// Set up geometry | |
const positionBuffer = gl.createBuffer(); | |
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); | |
const positions = [-1, -1, 1, -1, -1, 1, 1, 1]; // Full-screen quad | |
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW); | |
// Set up attributes | |
const positionLocation = gl.getAttribLocation(program, "a_position"); | |
gl.enableVertexAttribArray(positionLocation); | |
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); | |
// Set up uniforms | |
const resolutionLocation = gl.getUniformLocation(program, "u_resolution"); | |
const timeLocation = gl.getUniformLocation(program, "u_time"); | |
const render = (time: number) => { | |
gl.uniform2f(resolutionLocation, gl.drawingBufferWidth, gl.drawingBufferHeight); | |
gl.uniform1f(timeLocation, (time * ANIMATION_SPEED) / 1000); | |
gl.clearColor(0, 0, 0, 1); | |
gl.clear(gl.COLOR_BUFFER_BIT); | |
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); | |
gl.flush(); | |
gl.endFrameEXP(); | |
requestAnimationFrame(render); | |
}; | |
requestAnimationFrame(render); | |
}; | |
return ( | |
<GLView | |
style={{ | |
zIndex: -1, | |
position: "absolute", | |
width: Dimensions.get("window").width, | |
height: Dimensions.get("window").height, | |
top: 0, | |
left: 0, | |
backgroundColor: "white", | |
}} | |
onContextCreate={onContextCreate} | |
/> | |
); | |
}; | |
export default StarryBackground; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment