
import { DEG_TO_RAD, RAD_TO_DEG } from "../../2d/const";
import { Matrix } from "../../2d/math";
import { WebglRenderer } from "../../2d/renderers/WebglRenderer";
import { Texture } from "../../2d/texture";
import { GLShader } from "../../glCore";
import { Vector2 } from "../math/Vector2";
import { ShaderMaterial, UniformType } from "./ShaderMaterial";

const points3dVertexShader =
    `precision mediump float;
attribute vec3 aPosition;

uniform mat4 uViewMatrix;
uniform mat4 uProjectionMatrix;
uniform mat4 uModelMatrix;

uniform float size;
uniform float scale;

void main() {
    vec4 mvPosition =  uViewMatrix * uModelMatrix * vec4( aPosition, 1.0 );

    gl_Position = uProjectionMatrix * mvPosition;
    
    gl_PointSize = size;

    #ifdef USE_SIZEATTENUATION
        bool isPerspective = ( uProjectionMatrix[ 2 ][ 3 ] == - 1.0 );
        if ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );
    #endif
}`;
const points3dFragmentShader =
    `precision mediump float;
uniform vec3 color;
uniform float alpha;
uniform sampler2D map;
uniform mat3 uvTransform;
void main() {
    vec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;
	vec4 mapColor = texture2D( map, uv );
    gl_FragColor = vec4( color*alpha, alpha )*mapColor;
}`;

/**
 * 为了粒子系统的点材料，其实也可能是顶点变形动画网格，
 * 暂时只用作粒子系统，到时候glsl都规范后仿three的chunk写，通通可以拼，
 * 所以暂时命名为ParticlesMaterial，不用point，
 * 新版three的Points是支持变形动画的
 * three貌似是分开的，考虑按three的方式来，网格点分开，材质也分开
 * 暂时按照自定义着色器来
 * 透明度和深度检测是个大问题，到时候大改的时候再用，暂时不用
 */
export class Points3dMaterial extends ShaderMaterial {
    sizeAttenuation: boolean = true;
    get isPointsMaterial() {
        return true
    }
    constructor() {
        super(points3dVertexShader, points3dFragmentShader, {
            color: { type: UniformType.color, value: 0xffffff },
            alpha: { type: UniformType.float, value: 1.0 },
            map: { type: UniformType.texture, value: Texture.WHITE },
            uvTransform: { type: UniformType.matrix3, value: new Matrix() },
            scale: { type: UniformType.float, value: 100.0 },//一般是一半的画布高度
            size: { type: UniformType.float, value: 1.0 }
        })
    }
    getShader(renderer: WebglRenderer): GLShader {
        const id = "" + renderer.CONTEXT_UID + this.sizeAttenuation;
        if (!this.shaders[id]) {
            //生成
            this.shaders[id] = new GLShader(
                renderer.gl,
                (this.sizeAttenuation ? '#define USE_SIZEATTENUATION\n' : "") + this.vertexShader,
                this.fragmentShader
            );
            this.shaders[id]["_glShaderKey"] = `customShader${"id" + id}${"instanceId" + this.instanceId}${"sizeAttenuation" + this.sizeAttenuation}`;
        };
        return this.shaders[id];
    }
}