'use client'
import React, { useEffect, useRef, useState } from 'react'
import maplibregl, { CustomLayerInterface, CustomRenderMethodInput, LogoControl, } from 'maplibre-gl'
import 'maplibre-gl/dist/maplibre-gl.css'
import { useMap } from '@/app/map-context'
import { useMapLocation } from '@/hooks/use-map-location'
import { getSubdivisionRecommendation, detectPerformanceLevel, RegionMeshPresets } from '@/lib/tile-mesh'
import { createColorMap, ColorMapType, } from '@/lib/color-maps'
import { Colorbar } from './colorbar'
import { useRadarTile } from '@/hooks/use-radartile'
import { format, formatInTimeZone } from 'date-fns-tz'
import vertexSource from '@/app/glsl/radar/verx.glsl'
import fragmentSource from '@/app/glsl/radar/frag.glsl'
import * as Sentry from '@sentry/nextjs'
import { logger, logWebGLError, logMapEvent, logPerformanceMetric } from '@/lib/logger'

interface MapComponentProps {
    style?: string
    center?: [number, number]
    zoom?: number
    imgBitmap?: ImageBitmap | null
    colorMapType?: ColorMapType
    onColorMapChange?: (type: ColorMapType) => void
}

export function MapComponent({
    style = 'https://api.maptiler.com/maps/019817f1-82a8-7f37-901d-4bedf68b27fb/style.json?key=hj3fxRdwF9KjEsBq8sYI',
    // style = 'https://api.maptiler.com/maps/landscape/style.json?key=hj3fxRdwF9KjEsBq8sYI',
    // style = 'https://api.maptiler.com/tiles/land-gradient-dark/tiles.json?key=hj3fxRdwF9KjEsBq8sYI',
    // center = [103.851959, 1.290270],
    // zoom = 11
    imgBitmap: propImgBitmap,
    colorMapType = 'meteorological',
    onColorMapChange
}: MapComponentProps) {

    const { fetchRadarTile, imgBitmap } = useRadarTile();
    const mapContainer = useRef<HTMLDivElement>(null)
    const { setMap, mapRef, currentDatetime, isMapReady } = useMap()
    const { location } = useMapLocation()
    const texRef = useRef<WebGLTexture | null>(null)
    const lutTexRef = useRef<WebGLTexture | null>(null)
    const glRef = useRef<WebGL2RenderingContext | null>(null)
    const customLayerRef = useRef<CustomGlLayer | null>(null)
    const [isReady, setIsReady] = useState<boolean>(false)
    const [currentColorMapType, setCurrentColorMapType] = useState<ColorMapType>(colorMapType)

    // 拖动状态
    const [colorbarPosition, setColorbarPosition] = useState({ x: 16, y: 36 }) // 从右边和下边的距离
    const [isDragging, setIsDragging] = useState(false)

    // 使用ref来避免频繁的状态更新
    const dragRef = useRef({
        startX: 0,
        startY: 0,
        startPositionX: 0,
        startPositionY: 0
    })

    useEffect(() => {
        if (!isMapReady || !currentDatetime) return;
        const utc_time_str = formatInTimeZone(currentDatetime, 'UTC', 'yyyyMMddHHmmss')
        const new_url_prefix = process.env.NEXT_PUBLIC_GRAPHQL_BACKEND_URL?.replace('/graphql', '') || 'http://localhost:3050'
        const new_url = `${new_url_prefix}/api/v1/data?datetime=${utc_time_str}&area=cn`
        fetchRadarTile(new_url)
    }, [currentDatetime, isMapReady])

    useEffect(() => {
        if (!mapContainer.current) return

        const span = Sentry.startInactiveSpan({
            op: "ui.component.load",
            name: "Map Component Initialization",
        });

        span.setAttribute("map.style", style);
        span.setAttribute("map.center", `${location.center[0]},${location.center[1]}`);
        span.setAttribute("map.zoom", location.zoom);

        const map = new maplibregl.Map({
            container: mapContainer.current,
            style: style,
            center: location.center,
            zoom: location.zoom,
            attributionControl: false, // 禁用默认的版权控制
            canvasContextAttributes: {
                contextType: 'webgl2',  // 请求 WebGL2
                antialias: true         // 打开多重采样抗锯齿
            },
        })



        map.on('style.load', () => {
            logMapEvent('style.load', {
                style: style,
                center: location.center,
                zoom: location.zoom
            });

            logger.info('Map style loaded successfully', {
                component: 'MapComponent',
                style: style
            });

            map.setProjection({
                type: 'globe'
            })

            const customGlLayer: CustomGlLayer = {
                id: 'player',
                type: 'custom',
                lastZoom: -1, // 添加缓存的缩放级别
                uniformLocations: {} as Record<string, WebGLUniformLocation | null>, // 缓存uniform位置

                prerender(gl: WebGLRenderingContext | WebGL2RenderingContext, { shaderData }: CustomRenderMethodInput) {


                    if (!this.program) {
                        glRef.current = gl as WebGL2RenderingContext;
                        if (!(gl instanceof WebGL2RenderingContext)) {
                            return;
                        }

                        // Helper function to compile shader
                        const compileShader = (source: string, type: number): WebGLShader | null => {
                            const shader = gl.createShader(type);
                            if (!shader) {
                                const error = new Error('Failed to create WebGL shader');
                                Sentry.captureException(error);
                                logWebGLError('shader_creation', 'Failed to create WebGL shader', { shaderType: type === gl.VERTEX_SHADER ? 'vertex' : 'fragment' });
                                return null;
                            }

                            gl.shaderSource(shader, source);
                            gl.compileShader(shader);

                            if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
                                const errorLog = gl.getShaderInfoLog(shader) || 'Unknown shader compilation error';
                                const error = new Error(`Shader compilation failed: ${errorLog}`);
                                Sentry.captureException(error, {
                                    tags: { component: 'MapComponent', operation: 'shader_compilation' },
                                    extra: { shaderType: type === gl.VERTEX_SHADER ? 'vertex' : 'fragment', source }
                                });
                                logWebGLError('shader_compilation', errorLog, { shaderType: type === gl.VERTEX_SHADER ? 'vertex' : 'fragment' });
                                gl.deleteShader(shader);
                                return null;
                            }
                            return shader;
                        }

                        // Compile shaders
                        const vertexShader = compileShader(vertexSource, gl.VERTEX_SHADER);
                        const fragmentShader = compileShader(fragmentSource, gl.FRAGMENT_SHADER);

                        if (!vertexShader || !fragmentShader) return;

                        // Create and link program
                        const program = gl.createProgram();
                        if (!program) return;

                        gl.attachShader(program, vertexShader);
                        gl.attachShader(program, fragmentShader);
                        gl.linkProgram(program);

                        if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
                            const errorLog = gl.getProgramInfoLog(program) || 'Unknown program linking error';
                            const error = new Error(`WebGL program linking failed: ${errorLog}`);
                            Sentry.captureException(error, {
                                tags: { component: 'MapComponent', operation: 'program_linking' },
                                extra: { programLog: errorLog }
                            });
                            logWebGLError('program_linking', errorLog);
                            return;
                        }

                        // Clean up shaders (they're now part of the program)
                        gl.deleteShader(vertexShader);
                        gl.deleteShader(fragmentShader);

                        this.program = program;

                        const tex = gl.createTexture()

                        if (!tex) {
                            const error = new Error('Failed to create WebGL texture');
                            Sentry.captureException(error, {
                                tags: { component: 'MapComponent', operation: 'texture_creation' }
                            });
                            logWebGLError('texture_creation', 'Failed to create WebGL texture');
                            return;
                        }

                        gl.bindTexture(gl.TEXTURE_2D, tex);
                        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
                        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
                        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);

                        // 初始化时不更新纹理，等待 useEffect 中的更新
                        gl.bindTexture(gl.TEXTURE_2D, null);

                        this.tex = tex;
                        texRef.current = tex;

                        // 创建 LUT 纹理
                        const lutTex = createLutTexture(gl, currentColorMapType);
                        if (!lutTex) return;

                        this.lutTex = lutTex;
                        lutTexRef.current = lutTex;

                        // 缓存uniform位置
                        this.uniformLocations = {
                            'u_projection_fallback_matrix': gl.getUniformLocation(program, 'u_projection_fallback_matrix'),
                            'u_projection_matrix': gl.getUniformLocation(program, 'u_projection_matrix'),
                            'u_projection_tile_mercator_coords': gl.getUniformLocation(program, 'u_projection_tile_mercator_coords'),
                            'u_projection_clipping_plane': gl.getUniformLocation(program, 'u_projection_clipping_plane'),
                            'u_projection_transition': gl.getUniformLocation(program, 'u_projection_transition'),
                            'u_tex': gl.getUniformLocation(program, 'u_tex'),
                            'u_lut': gl.getUniformLocation(program, 'u_lut')
                        };

                        // 创建并绑定顶点缓冲区
                        const vertexBuffer = gl.createBuffer();
                        if (!vertexBuffer) {
                            console.error('Failed to create vertex buffer');
                            return;
                        }

                        // 创建并绑定索引缓冲区
                        const indexBuffer = gl.createBuffer();
                        if (!indexBuffer) {
                            console.error('Failed to create index buffer');
                            return;
                        }

                        // Create vertex array object (WebGL2 feature)
                        const vao = gl.createVertexArray();
                        if (!vao) {
                            console.error('Failed to create VAO');
                            return;
                        }

                        gl.bindVertexArray(vao);

                        gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);

                        // 设置位置属性 (location = 0)
                        gl.enableVertexAttribArray(0);
                        gl.vertexAttribPointer(
                            0,          // attribute location
                            2,          // size (x, y)
                            gl.FLOAT,   // type
                            false,      // normalized
                            16,         // stride (4 floats * 4 bytes = 16 bytes per vertex)
                            0           // offset (位置在开始)
                        );
                        gl.vertexAttribDivisor(0, 0);

                        // 设置纹理坐标属性 (location = 1)
                        gl.enableVertexAttribArray(1);
                        gl.vertexAttribPointer(
                            1,          // attribute location
                            2,          // size (u, v)
                            gl.FLOAT,   // type
                            false,      // normalized
                            16,         // stride (4 floats * 4 bytes = 16 bytes per vertex)
                            8           // offset (纹理坐标在位置之后，2 floats * 4 bytes = 8 bytes)
                        );
                        gl.vertexAttribDivisor(1, 0);

                        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);

                        // Unbind VAO
                        gl.bindVertexArray(null);

                        this.vao = vao;
                        this.vertexBuffer = vertexBuffer;
                        this.indexBuffer = indexBuffer;

                        setIsReady(true)
                    }

                    // 只在缩放级别变化时更新网格数据
                    const currentZoom = Math.floor(map.getZoom());
                    if (currentZoom !== this.lastZoom) {
                        logMapEvent('zoom_change', {
                            previousZoom: this.lastZoom,
                            currentZoom: currentZoom
                        });

                        // 智能计算最佳细分数量
                        const performanceLevel = detectPerformanceLevel();
                        const canvas = map.getCanvas();
                        const viewportSize = canvas ? {
                            width: canvas.width,
                            height: canvas.height
                        } : undefined;

                        // 获取细分建议信息
                        const recommendation = getSubdivisionRecommendation(currentZoom, performanceLevel);

                        logger.debug(logger.fmt`Zoom level: ${currentZoom}, Performance level: ${performanceLevel}`, {
                            currentZoom,
                            performanceLevel,
                            component: 'MapComponent'
                        });

                        logger.debug(logger.fmt`Subdivision recommendation: ${recommendation.subdivisions} (${recommendation.description})`, {
                            subdivisions: recommendation.subdivisions,
                            description: recommendation.description,
                            triangleCount: recommendation.triangleCount,
                            estimatedMemoryMB: recommendation.estimatedMemoryMB
                        });

                        logPerformanceMetric('triangles', recommendation.triangleCount, 'count');
                        logPerformanceMetric('memory_estimate', recommendation.estimatedMemoryMB, 'MB');

                        const meshData = RegionMeshPresets.china(currentZoom, 32);

                        if (gl instanceof WebGL2RenderingContext && this.vertexBuffer && this.indexBuffer) {
                            // 更新顶点缓冲区
                            gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
                            gl.bufferData(gl.ARRAY_BUFFER, meshData.vertices, gl.STATIC_DRAW);
                            gl.bindBuffer(gl.ARRAY_BUFFER, null);

                            // 更新索引缓冲区
                            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
                            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, meshData.indices, gl.STATIC_DRAW);
                            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);

                            this.meshData = meshData;
                            this.lastZoom = currentZoom;
                        }
                    }

                    // 移除这里的纹理更新，避免循环更新


                },

                onAdd: function (map: maplibregl.Map, gl: WebGL2RenderingContext) {
                    logger.info('WebGL custom layer added successfully', {
                        component: 'MapComponent',
                        layer: 'custom-gl-layer'
                    });
                    customLayerRef.current = this;
                },

                onRemove: function (map: maplibregl.Map, gl: WebGL2RenderingContext) {
                    // 清理WebGL资源
                    if (this.program) {
                        if (gl) {
                            // 禁用顶点属性
                            gl.disableVertexAttribArray(0); // 位置属性
                            gl.disableVertexAttribArray(1); // 纹理坐标属性

                            gl.deleteProgram(this.program);
                            if (this.vertexBuffer) gl.deleteBuffer(this.vertexBuffer);
                            if (this.indexBuffer) gl.deleteBuffer(this.indexBuffer);
                            if (this.vao) gl.deleteVertexArray(this.vao);
                            if (this.tex) gl.deleteTexture(this.tex);
                            if (this.lutTex) gl.deleteTexture(this.lutTex);
                        }
                    }
                    logger.info('WebGL custom layer resources cleaned up successfully', {
                        component: 'MapComponent',
                        layer: 'custom-gl-layer'
                    });
                },

                render(gl: WebGL2RenderingContext | WebGLRenderingContext, { defaultProjectionData }: CustomRenderMethodInput) {

                    if (!(gl instanceof WebGL2RenderingContext) || !this.program || !this.meshData || !this.vao) {
                        return;
                    }

                    // 保存当前状态
                    const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
                    const currentVAO = gl.getParameter(gl.VERTEX_ARRAY_BINDING);
                    const blendEnabled = gl.isEnabled(gl.BLEND);
                    const currentBlendSrc = gl.getParameter(gl.BLEND_SRC_ALPHA);
                    const currentBlendDst = gl.getParameter(gl.BLEND_DST_ALPHA);

                    gl.useProgram(this.program);

                    // 使用缓存的uniform位置
                    const locations = this.uniformLocations!;

                    if (locations['u_projection_fallback_matrix']) {
                        gl.uniformMatrix4fv(
                            locations['u_projection_fallback_matrix'],
                            false,
                            defaultProjectionData.fallbackMatrix
                        );
                    }

                    if (locations['u_projection_matrix']) {
                        gl.uniformMatrix4fv(
                            locations['u_projection_matrix'],
                            false,
                            defaultProjectionData.mainMatrix
                        );
                    }

                    if (locations['u_projection_tile_mercator_coords']) {
                        gl.uniform4f(
                            locations['u_projection_tile_mercator_coords'],
                            ...defaultProjectionData.tileMercatorCoords
                        );
                    }

                    if (locations['u_projection_clipping_plane']) {
                        gl.uniform4f(
                            locations['u_projection_clipping_plane'],
                            ...defaultProjectionData.clippingPlane
                        );
                    }

                    if (locations['u_projection_transition']) {
                        gl.uniform1f(
                            locations['u_projection_transition'],
                            defaultProjectionData.projectionTransition
                        );
                    }

                    // 绑定纹理
                    if (this.tex && locations['u_tex']) {
                        gl.activeTexture(gl.TEXTURE0);
                        gl.bindTexture(gl.TEXTURE_2D, this.tex);
                        gl.uniform1i(locations['u_tex'], 0);
                    }

                    if (this.lutTex && locations['u_lut']) {
                        gl.activeTexture(gl.TEXTURE1);
                        gl.bindTexture(gl.TEXTURE_2D, this.lutTex);
                        gl.uniform1i(locations['u_lut'], 1);
                    }

                    gl.bindVertexArray(this.vao);
                    gl.enable(gl.BLEND);
                    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

                    // 使用索引绘制三角形
                    const indexType = this.meshData.uses32bitIndices ? gl.UNSIGNED_INT : gl.UNSIGNED_SHORT;
                    const indexCount = this.meshData.indices.length;
                    gl.drawElements(gl.TRIANGLES, indexCount, indexType, 0);

                    // 恢复状态
                    gl.bindVertexArray(currentVAO);
                    gl.useProgram(currentProgram);
                    if (!blendEnabled) gl.disable(gl.BLEND);
                    if (blendEnabled) gl.blendFunc(currentBlendSrc, currentBlendDst);
                }
            };

            map.addLayer(customGlLayer);
        })


        setMap(map, [])

        // 清理函数：当组件卸载或重新初始化时清理资源
        return () => {
            // console.log('Cleaning up map resources...');

            // 清理自定义图层引用
            customLayerRef.current = null;

            // 清理 WebGL 引用
            glRef.current = null;
            texRef.current = null;
            lutTexRef.current = null;

            // 重置状态
            setIsReady(false);

            // 移除地图实例
            if (map) {
                map.remove();
            }

            // 结束Sentry span
            span.end();
        }

    }, [mapContainer])

    useEffect(() => {
        if (imgBitmap && texRef.current) {
            const gl = glRef.current
            if (!gl) return;

            // console.log('Updating texture with imgBitmap:', imgBitmap);

            gl.bindTexture(gl.TEXTURE_2D, texRef.current)

            // 针对灰度图优化：使用单通道RED格式，减少内存使用和提高性能
            // 虽然ImageBitmap仍是RGBA格式，但WebGL会自动将灰度值映射到RED通道
            gl.texImage2D(
                gl.TEXTURE_2D,
                0,
                gl.RGBA,          // 内部格式：使用RGBA，兼容性更好
                gl.RGBA,          // 数据格式：ImageBitmap总是RGBA
                gl.UNSIGNED_BYTE,
                imgBitmap
            )

            // 设置纹理参数（如果还没有设置）
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
            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.bindTexture(gl.TEXTURE_2D, null);

            // Redraw the map
            mapRef.current?.triggerRepaint()

        }

    }, [imgBitmap, isReady])

    // 监听色标类型变化，更新LUT纹理
    useEffect(() => {
        if (currentColorMapType !== colorMapType) {
            setCurrentColorMapType(colorMapType);
        }
    }, [colorMapType, currentColorMapType])

    // 当色标类型改变时，重新创建LUT纹理
    useEffect(() => {
        if (isReady && lutTexRef.current && glRef.current) {
            const gl = glRef.current;
            const newLutTex = createLutTexture(gl, currentColorMapType);
            if (newLutTex) {
                // 删除旧的纹理
                gl.deleteTexture(lutTexRef.current);
                lutTexRef.current = newLutTex;

                // 通知自定义图层更新LUT纹理
                if (customLayerRef.current) {
                    customLayerRef.current.lutTex = newLutTex;
                }
            }
        }
    }, [currentColorMapType, isReady])

    // 拖动事件处理函数
    const handleMouseDown = (e: React.MouseEvent) => {
        Sentry.startSpan(
            {
                op: "ui.interaction",
                name: "Colorbar Drag Start",
            },
            (span: any) => {
                span.setAttribute("colorbar.position.x", colorbarPosition.x);
                span.setAttribute("colorbar.position.y", colorbarPosition.y);

                e.preventDefault()
                setIsDragging(true)

                // 记录拖动开始时的鼠标位置和colorbar位置
                dragRef.current = {
                    startX: e.clientX,
                    startY: e.clientY,
                    startPositionX: colorbarPosition.x,
                    startPositionY: colorbarPosition.y
                }
            }
        );
    }

    // 全局鼠标事件监听
    useEffect(() => {
        if (!isDragging) return

        let animationFrameId: number

        const handleGlobalMouseMove = (e: MouseEvent) => {
            // 使用requestAnimationFrame来优化性能
            if (animationFrameId) {
                cancelAnimationFrame(animationFrameId)
            }

            animationFrameId = requestAnimationFrame(() => {
                const mapContainer = document.querySelector('.h-full.w-full.relative') as HTMLElement
                if (!mapContainer) return

                const containerRect = mapContainer.getBoundingClientRect()

                // 计算鼠标移动的总距离
                const deltaX = dragRef.current.startX - e.clientX
                const deltaY = dragRef.current.startY - e.clientY

                // 计算新位置（相对于容器右下角的距离）
                const newX = dragRef.current.startPositionX + deltaX
                const newY = dragRef.current.startPositionY + deltaY

                // 限制在容器范围内
                const clampedX = Math.max(0, Math.min(newX, containerRect.width - 50)) // 预留colorbar宽度
                const clampedY = Math.max(0, Math.min(newY, containerRect.height - 220)) // 预留colorbar高度

                setColorbarPosition({ x: clampedX, y: clampedY })
            })
        }

        const handleGlobalMouseUp = () => {
            if (animationFrameId) {
                cancelAnimationFrame(animationFrameId)
            }
            setIsDragging(false)
        }

        document.addEventListener('mousemove', handleGlobalMouseMove)
        document.addEventListener('mouseup', handleGlobalMouseUp)

        return () => {
            if (animationFrameId) {
                cancelAnimationFrame(animationFrameId)
            }
            document.removeEventListener('mousemove', handleGlobalMouseMove)
            document.removeEventListener('mouseup', handleGlobalMouseUp)
        }
    }, [isDragging]) // 只依赖isDragging，避免频繁重新创建事件监听器

    return (
        <div className="h-full w-full relative">
            <div
                ref={mapContainer}
                className="w-full h-full"
                style={{ minHeight: '400px' }}
            />

            {/* 可拖动的 Colorbar */}
            <div
                data-colorbar
                className={`absolute select-none ${isDragging ? 'cursor-grabbing' : 'cursor-grab'}`}
                style={{
                    right: `${colorbarPosition.x}px`,
                    bottom: `${colorbarPosition.y}px`,
                    transform: isDragging ? 'scale(1.02)' : 'scale(1)',
                    transition: isDragging ? 'none' : 'transform 0.1s ease-out',
                    willChange: isDragging ? 'transform' : 'auto'
                }}
                onMouseDown={handleMouseDown}
            >
                <Colorbar
                    colorMapType={currentColorMapType}
                    width={16}
                    height={220}
                    minValue={0}
                    maxValue={75}
                    unit="dBZ"
                    orientation="vertical"
                />
            </div>
        </div>
    )
}


interface CustomGlLayer extends CustomLayerInterface {
    program?: WebGLProgram;
    aPos?: number;
    buffer?: WebGLBuffer | null;
    vao?: WebGLVertexArrayObject | null;
    meshData?: { vertices: Float32Array; indices: Uint16Array | Uint32Array; uses32bitIndices: boolean; vertexCount: number; triangleCount: number; };
    vertexBuffer?: WebGLBuffer | null;
    indexBuffer?: WebGLBuffer | null;
    lastZoom?: number; // 缓存的缩放级别
    uniformLocations?: Record<string, WebGLUniformLocation | null>; // 缓存uniform位置

    tex?: WebGLTexture | null;
    lutTex?: WebGLTexture | null;
}



function createLutTexture(gl: WebGL2RenderingContext, colorMapType: ColorMapType = 'radar') {
    // 使用统一的色标创建函数
    const lut = createColorMap(colorMapType);

    const tex = gl.createTexture()
    if (!tex) {
        console.error('Failed to create texture');
        return;
    }

    gl.bindTexture(gl.TEXTURE_2D, tex)
    gl.texImage2D(
        gl.TEXTURE_2D,
        0,
        gl.RGBA,
        256,
        1,
        0,
        gl.RGBA,
        gl.UNSIGNED_BYTE,
        lut
    )

    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    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.bindTexture(gl.TEXTURE_2D, null);

    return tex;
}