| // Copyright (C) 2026 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| export function getUniformLocation( |
| gl: WebGL2RenderingContext, |
| program: WebGLProgram, |
| name: string, |
| ): WebGLUniformLocation { |
| const loc = gl.getUniformLocation(program, name); |
| if (loc === null) { |
| throw new Error(`Uniform "${name}" not found (optimized out or typo?)`); |
| } |
| return loc; |
| } |
| |
| export function getAttribLocation( |
| gl: WebGL2RenderingContext, |
| program: WebGLProgram, |
| name: string, |
| ): number { |
| const loc = gl.getAttribLocation(program, name); |
| if (loc === -1) { |
| throw new Error(`Attribute "${name}" not found (optimized out or typo?)`); |
| } |
| return loc; |
| } |
| |
| export function compileShader( |
| gl: WebGL2RenderingContext, |
| type: number, |
| source: string, |
| ): WebGLShader { |
| const shader = gl.createShader(type); |
| if (!shader) throw new Error('Failed to create shader'); |
| |
| gl.shaderSource(shader, source); |
| gl.compileShader(shader); |
| |
| const status = gl.getShaderParameter(shader, gl.COMPILE_STATUS) as GLboolean; |
| |
| if (!status) { |
| const info = gl.getShaderInfoLog(shader); |
| gl.deleteShader(shader); |
| throw new Error(`Shader compile error: ${info}`); |
| } |
| |
| return shader; |
| } |
| |
| export function linkProgram( |
| gl: WebGL2RenderingContext, |
| vertexShader: WebGLShader, |
| fragmentShader: WebGLShader, |
| ): WebGLProgram { |
| const program = gl.createProgram(); |
| |
| gl.attachShader(program, vertexShader); |
| gl.attachShader(program, fragmentShader); |
| gl.linkProgram(program); |
| |
| const status = gl.getProgramParameter(program, gl.LINK_STATUS) as GLboolean; |
| |
| if (!status) { |
| const info = gl.getProgramInfoLog(program); |
| gl.deleteProgram(program); |
| throw new Error(`Program link error: ${info}`); |
| } |
| |
| return program; |
| } |
| |
| // Convenience - compile both and link in one go |
| export function createProgram( |
| gl: WebGL2RenderingContext, |
| vertSource: string, |
| fragSource: string, |
| ): WebGLProgram { |
| const vert = compileShader(gl, gl.VERTEX_SHADER, vertSource); |
| const frag = compileShader(gl, gl.FRAGMENT_SHADER, fragSource); |
| return linkProgram(gl, vert, frag); |
| } |