"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module WebGL
 */
Object.defineProperty(exports, "__esModule", { value: true });
const RenderSystem_1 = require("../../RenderSystem");
const AttributeMap_1 = require("../AttributeMap");
const ShaderBuilder_1 = require("../ShaderBuilder");
const System_1 = require("../System");
const Common_1 = require("./Common");
const Decode_1 = require("./Decode");
const LogarithmicDepthBuffer_1 = require("./LogarithmicDepthBuffer");
const Translucency_1 = require("./Translucency");
const Vertex_1 = require("./Vertex");
const computePosition = "gl_PointSize = 1.0; return MAT_MVP * rawPos;";
const computeTexCoord = "return unquantize2d(a_uvParam, u_qTexCoordParams);";
const computeBaseColor = `
  // u_gridProps - x = gridsPerRef, y - planeAlpha, z = line alpha, w = ref alpha.
  vec4 color = vec4(u_gridColor, u_gridProps.y);
  float refsPerGrid = u_gridProps.x;
  if (0.0 == refsPerGrid || !drawGridLine(color, 1.0 / refsPerGrid, u_gridProps.w - color.a))
    drawGridLine(color, 1.0, u_gridProps.z - color.a);

  return color;
`;
const drawGridLine = `
  bool drawGridLine(inout vec4 color, float mult, float alphaScale) {
    vec2 scaledTexCoord = v_texCoord * mult;
    vec2 deriv = mult * screenSpaceDeriv(v_texCoord);
    if (deriv.x != 0.0 && deriv.y != 0.0) {
      vec2 grid = abs(fract(mult * v_texCoord - 0.5) - 0.5) / deriv;
      float line = min(grid.x, grid.y);
      if (line < 1.0) {
        color.a += alphaScale * (1.0 - min(line, 1.0)) / max(1.0, length(deriv));
        return true;
        }
      }
    return false;
   }
`;
const fwidth2d = `\nvec2 screenSpaceDeriv(vec2 screenXY) { return fwidth(screenXY); }\n`;
const defaultTransparency = new RenderSystem_1.PlanarGridTransparency();
/** @internal */
function createPlanarGridProgram(context) {
    const builder = new ShaderBuilder_1.ProgramBuilder(AttributeMap_1.AttributeMap.findAttributeMap(8 /* TechniqueId.PlanarGrid */, false));
    const vert = builder.vert;
    const frag = builder.frag;
    vert.set(10 /* VertexShaderComponent.ComputePosition */, computePosition);
    (0, Vertex_1.addModelViewProjectionMatrix)(vert);
    (0, Common_1.addShaderFlags)(builder);
    (0, Translucency_1.addTranslucency)(builder);
    frag.addFunction(fwidth2d);
    if (System_1.System.instance.supportsLogZBuffer)
        (0, LogarithmicDepthBuffer_1.addLogDepth)(builder);
    frag.addFunction(drawGridLine);
    frag.set(1 /* FragmentShaderComponent.ComputeBaseColor */, computeBaseColor);
    vert.headerComment = `//!V! PlanarGrid`;
    frag.headerComment = `//!F! PlanarGrid`;
    vert.addFunction(Decode_1.unquantize2d);
    builder.addFunctionComputedVarying("v_texCoord", 3 /* VariableType.Vec2 */, "computeTexCoord", computeTexCoord);
    vert.addUniform("u_qTexCoordParams", 5 /* VariableType.Vec4 */, (prog) => {
        prog.addGraphicUniform("u_qTexCoordParams", (uniform, params) => {
            const planarGrid = params.geometry.asPlanarGrid;
            uniform.setUniform4fv(planarGrid.uvParams.params);
        });
    });
    frag.addUniform("u_gridColor", 4 /* VariableType.Vec3 */, (prog) => {
        prog.addGraphicUniform("u_gridColor", (uniform, params) => {
            const planarGrid = params.geometry.asPlanarGrid;
            const color = planarGrid.props.color.colors;
            uniform.setUniform3fv([color.r / 255, color.g / 255, color.b / 255]);
        });
    });
    frag.addUniform("u_gridProps", 5 /* VariableType.Vec4 */, (prog) => {
        prog.addGraphicUniform("u_gridProps", (uniform, params) => {
            const planarGridProps = params.geometry.asPlanarGrid.props;
            const transparency = planarGridProps.transparency ? planarGridProps.transparency : defaultTransparency;
            uniform.setUniform4fv([planarGridProps.gridsPerRef, 1.0 - transparency.planeTransparency, 1.0 - transparency.lineTransparency, 1.0 - transparency.refTransparency]);
        });
    });
    return builder.buildProgram(context);
}
exports.default = createPlanarGridProgram;
//# sourceMappingURL=PlanarGrid.js.map