import { ImageFileData } from "../device" ; import { createProgram } from "./glUtils" ; import { m2d , Matrix2D } from "./matrix" ; const vertexShaderSource = `
attribute vec2 a_position;
attribute vec2 a_texcoord;

uniform mat3 u_matrix;
uniform mat3 u_texture_matrix;

varying vec2 v_texcoord;

const mat3 flipY = mat3(
  1.0, 0.0, 0.0,
  0.0, -1.0, 0.0,
  0.0, 1.0, 1.0
);

void main() {
  gl_Position = vec4(u_matrix * vec3(a_position, 1.0), 1.0);
  v_texcoord = (flipY * u_texture_matrix * vec3(a_texcoord, 1.0)).xy;
}` ; const fragmentShaderSource = `
precision mediump float;

varying vec2 v_texcoord;

uniform sampler2D u_texture;
uniform float u_opacity;

void main() {
  gl_FragColor = texture2D(u_texture, v_texcoord) * u_opacity;
}
` ; export function getDrawImage ( gl , glVao ) { const program = createProgram ( gl , vertexShaderSource , fragmentShaderSource ) ; const vao = glVao . createVertexArrayOES ( ) ; glVao . bindVertexArrayOES ( vao ) ; const aPositionLocation = gl . getAttribLocation ( program , "a_position" ) ; const aTexcoordLocation = gl . getAttribLocation ( program , "a_texcoord" ) ; const uMatrixLocation = gl . getUniformLocation ( program , "u_matrix" ) ; const uTextureMatrixLocation = gl . getUniformLocation ( program , "u_texture_matrix" ) ; const uTextureLocation = gl . getUniformLocation ( program , "u_texture" ) ; const uOpacityLocation = gl . getUniformLocation ( program , "u_opacity" ) ; const positionBuffer = gl . createBuffer ( ) ; gl . bindBuffer ( gl . ARRAY_BUFFER , positionBuffer ) ; gl . enableVertexAttribArray ( aPositionLocation ) ; gl . vertexAttribPointer ( aPositionLocation , 2 , gl . FLOAT , false , 0 , 0 ) ; const positions = [ - 0.5 , - 0.5 , - 0.5 , 0.5 , 0.5 , - 0.5 , 0.5 , - 0.5 , - 0.5 , 0.5 , 0.5 , 0.5 , ] ; gl . bufferData ( gl . ARRAY_BUFFER , new Float32Array ( positions ) , gl . STATIC_DRAW ) ; const texcoordBuffer = gl . createBuffer ( ) ; gl . bindBuffer ( gl . ARRAY_BUFFER , texcoordBuffer ) ; gl . enableVertexAttribArray ( aTexcoordLocation ) ; gl . vertexAttribPointer ( aTexcoordLocation , 2 , gl . FLOAT , false , 0 , 0 ) ; const texcoords = [ 0 , 0 , 0 , 1 , 1 , 0 , 1 , 0 , 0 , 1 , 1 , 1 , ] ; gl . bufferData ( gl . ARRAY_BUFFER , new Float32Array ( texcoords ) , gl . STATIC_DRAW ) ; glVao . bindVertexArrayOES ( null ) ; return function drawImage ( texture , matrix , width , height , opacity , spriteSheet , prevProgram , prevTexture ) : { program : WebGLProgram ; texture : WebGLTexture ; } { if ( texture !== prevTexture ) { gl . bindTexture ( gl . TEXTURE_2D , texture ) ; } if ( program !== prevProgram ) { gl . useProgram ( program ) ; glVao . bindVertexArrayOES ( vao ) ; } const uMatrix = m2d . scaleToUniform3fv ( matrix , width , height ) ; gl . uniformMatrix3fv ( uMatrixLocation , false , uMatrix ) ; const uTextureMatrix = spriteSheet ? m2d . toUniform3fv ( getSpriteSheetMatrix ( spriteSheet ) ) : m2d . identityMatrix3fv ; gl . uniformMatrix3fv ( uTextureMatrixLocation , false , uTextureMatrix ) ; gl . uniform1i ( uTextureLocation , 0 ) ; gl . uniform1f ( uOpacityLocation , opacity ) ; gl . drawArrays ( gl . TRIANGLES , 0 , 6 ) ; return { program , texture } ; } ; } export function createTextureInfo ( gl , img , scaleSharp ) { const tex = gl . createTexture ( ) ! ; gl . bindTexture ( gl . TEXTURE_2D , tex ) ; 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 ) ; if ( scaleSharp ) { gl . texParameteri ( gl . TEXTURE_2D , gl . TEXTURE_MIN_FILTER , gl . NEAREST ) ; gl . texParameteri ( gl . TEXTURE_2D , gl . TEXTURE_MAG_FILTER , gl . NEAREST ) ; } else { gl . texParameteri ( gl . TEXTURE_2D , gl . TEXTURE_MIN_FILTER , gl . LINEAR ) ; } const textureInfo = { texture : tex , image : img , } ; gl . texImage2D ( gl . TEXTURE_2D , 0 , gl . RGBA , gl . RGBA , gl . UNSIGNED_BYTE , img ) ; return textureInfo ; } type SpriteSheetInfo = { columns : number ; rows : number ; index : number ; } ; function getSpriteSheetMatrix ( info ) { const { columns , rows , index } = info ; const columnIndex = index % columns ; const rowIndex = Math . floor ( index / columns ) % rows ; return m2d . multiply ( m2d . getTranslateMatrix ( columnIndex / columns , ( rows - 1 - rowIndex ) / rows ) , m2d . getScaleMatrix ( 1 / columns , 1 / rows ) ) ; }