123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- import envFragSource from "./shader-env.frag?raw";
- import envCubeFragSource from "./shader-env-cube.frag?raw";
- import envVertSource from "./shader-env.vert?raw";
- import { loadImage } from "@/util";
- import { createFPSCamera, createProgram, generateVao, useTex } from "@/util/gl";
- import { mat4, glMatrix } from "gl-matrix";
- import { setUniforms } from "./setUniform";
- const generatePreset = (gl: WebGL2RenderingContext) => {
- const skyCubeTex = gl.createTexture();
- const skyCubeTex1 = gl.createTexture();
- const updateSky1 = (images: HTMLImageElement[]) => {
- gl.bindTexture(gl.TEXTURE_CUBE_MAP, skyCubeTex1);
- const mapper = [2, 4, 0, 5, 1, 3];
- for (let i = 0; i < 6; i++) {
- gl.texImage2D(
- gl.TEXTURE_CUBE_MAP_POSITIVE_X + i,
- 0,
- gl.RGB,
- gl.RGB,
- gl.UNSIGNED_BYTE,
- images[mapper[i]]
- );
- }
- gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
- gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
- gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE);
- gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
- gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
- gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
- gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
- };
- const updateSky = (image: HTMLImageElement) => {
- gl.bindTexture(gl.TEXTURE_2D, skyCubeTex);
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
- gl.bindTexture(gl.TEXTURE_2D, null);
- };
- return {
- skyCubeTex,
- skyCubeTex1,
- // async preset(urls: string[]) {
- // const images = await Promise.all(urls.map(loadImage));
- // updateSky(images);
- // },
- async preset(url: string | string[]) {
- if (Array.isArray(url)) {
- const images = await Promise.all(url.map(loadImage));
- updateSky1(images);
- } else {
- const image = await loadImage(url);
- updateSky(image);
- }
- },
- };
- };
- const getDrawVaring = (gl: WebGL2RenderingContext) => {
- const positions = new Float32Array([
- -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1,
- ]);
- const vao = generateVao(gl, { positions }, [
- {
- loc: 0,
- key: "positions",
- size: 2,
- type: gl.FLOAT,
- stride: 0,
- offset: 0,
- },
- ]);
- return {
- ...generatePreset(gl),
- vao,
- numArrays: positions.length / 2,
- };
- };
- export const init = (canvas: HTMLCanvasElement) => {
- let activeTex: "skyCubeTex1" | "skyCubeTex" = "skyCubeTex1";
- const gl = canvas.getContext("webgl2", { preserveDrawingBuffer: true })!;
- const program = createProgram(gl, envVertSource, envFragSource);
- const program1 = createProgram(gl, envVertSource, envCubeFragSource);
- const setSize = (size: number[]) => {
- mat4.perspective(
- projectionMat,
- glMatrix.toRadian(70),
- size[0] / size[1],
- 0.1,
- 100
- );
- gl.viewport(0, 0, size[0], size[1]);
- updateInv();
- redraw();
- };
- const projectionMat = mat4.create();
- const invProjectionViewMat = mat4.create();
- const viewMat = mat4.create();
- const varing = getDrawVaring(gl);
- const updateInv = () => {
- mat4.multiply(invProjectionViewMat, projectionMat, viewMat);
- mat4.invert(invProjectionViewMat, invProjectionViewMat);
- };
- const redraw = () => {
- gl.clear(gl.COLOR_BUFFER_BIT);
- gl.enable(gl.DEPTH_TEST);
- gl.depthFunc(gl.LEQUAL);
- const g = activeTex === "skyCubeTex" ? program : program1;
- gl.useProgram(g);
- gl.bindVertexArray(varing.vao);
- setUniforms(gl, g, {
- invProjectionViewMat,
- envTex:
- activeTex === "skyCubeTex1"
- ? useTex(gl, varing.skyCubeTex1!, gl.TEXTURE_CUBE_MAP, 1)
- : useTex(gl, varing.skyCubeTex!, gl.TEXTURE_2D),
- });
- gl.drawArrays(gl.TRIANGLES, 0, varing.numArrays);
- };
- setSize([canvas.width, canvas.height]);
- const fps = createFPSCamera(
- canvas.parentElement!,
- (nViewMat) => {
- mat4.copy(viewMat, nViewMat);
- updateInv();
- redraw();
- },
- [0, 1, 0],
- [0, 0, 0],
- { yaw: glMatrix.toRadian(-180) },
- 80
- );
- return {
- setSize,
- redraw,
- changeUrls(urls: string | string[]) {
- fps.recovery();
- return varing.preset(urls).then(() => {
- activeTex = Array.isArray(urls) ? "skyCubeTex1" : "skyCubeTex";
- redraw();
- });
- },
- destory: fps.destory,
- };
- };
|