Miku texture

This commit is contained in:
Greg Shuflin 2025-02-15 03:53:33 -08:00
parent 004c1b9d64
commit 3bff125eaf
3 changed files with 54 additions and 9 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 KiB

View File

@ -1,14 +1,40 @@
import psychadelicColors from './psychadelicColors.frag.glsl'; import psychadelicColors from './psychadelicColors.frag.glsl';
import mikuImageUrl from './Hatsune-Miku-vocaloids-30622078-935-1023.jpg';
const canvas = document.getElementById('canvas') as HTMLCanvasElement; const canvas = document.getElementById('canvas') as HTMLCanvasElement;
const gl = canvas.getContext('webgl2')!; const gl = canvas.getContext('webgl2')!;
// Basic vertex shader (just passes coordinates) // Load Miku texture
const mikuTexture = gl.createTexture();
// Create a single pixel as initial texture to avoid errors before image loads
gl.bindTexture(gl.TEXTURE_2D, mikuTexture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([255, 0, 255, 255]));
const mikuImage = new Image();
mikuImage.src = mikuImageUrl;
mikuImage.onload = () => {
console.log('Miku image loaded successfully');
gl.bindTexture(gl.TEXTURE_2D, mikuTexture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, mikuImage);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
};
mikuImage.onerror = (err) => {
console.error('Failed to load Miku image:', err);
};
// Basic vertex shader (just passes coordinates and texture coordinates)
const vertexShaderSource = `#version 300 es const vertexShaderSource = `#version 300 es
in vec4 a_position; in vec4 a_position;
out vec2 v_texCoord;
void main() { void main() {
gl_Position = a_position; gl_Position = a_position;
// Convert position from clip space (-1 to +1) to texture coordinates (0 to 1)
v_texCoord = a_position.xy * -0.5 + 0.5;
}`; }`;
// Compile shader // Compile shader
@ -58,6 +84,7 @@ gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);
const timeUniformLocation = gl.getUniformLocation(program, 'u_time'); const timeUniformLocation = gl.getUniformLocation(program, 'u_time');
const canvasWidthLocation = gl.getUniformLocation(program, 'u_canvasWidth'); const canvasWidthLocation = gl.getUniformLocation(program, 'u_canvasWidth');
const canvasHeightLocation = gl.getUniformLocation(program, 'u_canvasHeight'); const canvasHeightLocation = gl.getUniformLocation(program, 'u_canvasHeight');
const mikuTextureLocation = gl.getUniformLocation(program, 'u_mikuTexture');
// Set up resize handler // Set up resize handler
function resize() { function resize() {
@ -72,8 +99,13 @@ resize();
function draw(time: number) { function draw(time: number) {
gl.useProgram(program); gl.useProgram(program);
gl.uniform1f(timeUniformLocation, time * 0.001); // Convert to seconds gl.uniform1f(timeUniformLocation, time * 0.001); // Convert to seconds
gl.uniform1f(canvasWidthLocation, canvas.width); // Convert to seconds gl.uniform1f(canvasWidthLocation, canvas.width);
gl.uniform1f(canvasHeightLocation, canvas.height); // Convert to seconds gl.uniform1f(canvasHeightLocation, canvas.height);
// Bind Miku texture to texture unit 0
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, mikuTexture);
gl.uniform1i(mikuTextureLocation, 0);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
requestAnimationFrame(draw); requestAnimationFrame(draw);

View File

@ -2,11 +2,11 @@
precision highp float; precision highp float;
uniform float u_time; uniform float u_time;
uniform float u_canvasWidth; uniform float u_canvasWidth;
uniform float u_canvasHeight; uniform float u_canvasHeight;
uniform sampler2D u_mikuTexture;
in vec2 v_texCoord;
out vec4 fragColor; out vec4 fragColor;
// See https://thebookofshaders.com/10/ // See https://thebookofshaders.com/10/
@ -34,7 +34,7 @@ vec2 pixellate(vec2 inputVec, float size) {
); );
} }
void pixelatedSinWave() { vec4 pixelatedSinWave() {
vec2 uv = gl_FragCoord.xy/vec2(u_canvasWidth, u_canvasHeight); vec2 uv = gl_FragCoord.xy/vec2(u_canvasWidth, u_canvasHeight);
float amount = 1.0/(u_time * 9.0); float amount = 1.0/(u_time * 9.0);
@ -45,17 +45,30 @@ void pixelatedSinWave() {
float dist = distance(uv, vec2(0.5, 0.5)); float dist = distance(uv, vec2(0.5, 0.5));
float curve = sin(dist * 60.0); float curve = sin(dist * 60.0);
vec4 outputColor = vec4(0.5, 0.1, curve, 1.0); vec4 outputColor = vec4(0.5, 0.1, curve, 1.0);
return outputColor;
float size = 0.01; float size = 0.01;
float period = 1.0; float period = 1.0;
fragColor = boxFade(outputColor, size, period); fragColor = boxFade(outputColor, size, period);
} }
vec4 miku() {
// Get base texture color
vec2 uv = v_texCoord;
// Sample the texture first without effects
vec4 texColor = texture(u_mikuTexture, uv);
return texColor;
}
void main() { void main() {
pixelatedSinWave(); vec4 texColor = miku();
// Apply box fade effect
float boxSize = 0.02;
float period = 2.0;
fragColor = boxFade(texColor, boxSize, period);
} }