import { applyMaterialMixins, MeshMaterial } from './meshmaterial.js';
import { mixinVertexColor } from './mixins/vertexcolor.js';
import { mixinBlinnPhong } from './mixins/lightmodel/blinnphong.js';
import { ShaderHelper } from './shader/helper.js';
import { RENDER_PASS_TYPE_LIGHT, MaterialVaryingFlags } from '../values.js';

/**
 * Blinn material
 * @public
 */ class BlinnMaterial extends applyMaterialMixins(MeshMaterial, mixinBlinnPhong, mixinVertexColor) {
    /** @internal */ static FEATURE_VERTEX_NORMAL = this.defineFeature();
    /** @internal */ static FEATURE_VERTEX_TANGENT = this.defineFeature();
    /**
   * Creates an instance of BlinnMaterial class
   */ constructor(){
        super();
        this.useFeature(BlinnMaterial.FEATURE_VERTEX_NORMAL, true);
    }
    clone() {
        const other = new BlinnMaterial();
        other.copyFrom(this);
        return other;
    }
    /** true if vertex normal attribute presents */ get vertexNormal() {
        return this.featureUsed(BlinnMaterial.FEATURE_VERTEX_NORMAL);
    }
    set vertexNormal(val) {
        this.useFeature(BlinnMaterial.FEATURE_VERTEX_NORMAL, !!val);
    }
    /** true if vertex normal attribute presents */ get vertexTangent() {
        return this.featureUsed(BlinnMaterial.FEATURE_VERTEX_TANGENT);
    }
    set vertexTangent(val) {
        this.useFeature(BlinnMaterial.FEATURE_VERTEX_TANGENT, !!val);
    }
    vertexShader(scope) {
        super.vertexShader(scope);
        const pb = scope.$builder;
        scope.$l.oPos = ShaderHelper.resolveVertexPosition(scope);
        scope.$outputs.worldPos = pb.mul(ShaderHelper.getWorldMatrix(scope), pb.vec4(scope.oPos, 1)).xyz;
        ShaderHelper.setClipSpacePosition(scope, pb.mul(ShaderHelper.getViewProjectionMatrix(scope), pb.vec4(scope.$outputs.worldPos, 1)));
        if (this.vertexNormal) {
            scope.$l.oNorm = ShaderHelper.resolveVertexNormal(scope);
            scope.$outputs.wNorm = pb.mul(ShaderHelper.getNormalMatrix(scope), pb.vec4(scope.oNorm, 0)).xyz;
            if (this.vertexTangent) {
                scope.$l.oTangent = ShaderHelper.resolveVertexTangent(scope);
                scope.$outputs.wTangent = pb.mul(ShaderHelper.getNormalMatrix(scope), pb.vec4(scope.oTangent.xyz, 0)).xyz;
                scope.$outputs.wBinormal = pb.mul(pb.cross(scope.$outputs.wNorm, scope.$outputs.wTangent), scope.oTangent.w);
            }
        }
    }
    fragmentShader(scope) {
        super.fragmentShader(scope);
        const pb = scope.$builder;
        if (this.needFragmentColor()) {
            scope.$l.albedo = this.calculateAlbedoColor(scope);
            if (this.vertexColor) {
                scope.albedo = pb.mul(scope.albedo, this.getVertexColor(scope));
            }
            if (this.drawContext.renderPass.type === RENDER_PASS_TYPE_LIGHT) {
                scope.$l.normal = this.calculateNormal(scope, scope.$inputs.worldPos, scope.$inputs.wNorm, scope.$inputs.wTangent, scope.$inputs.wBinormal);
                scope.$l.viewVec = this.calculateViewVector(scope, scope.$inputs.worldPos);
                if (this.drawContext.materialFlags & MaterialVaryingFlags.SSR_STORE_ROUGHNESS) {
                    scope.$l.outRoughness = pb.vec4();
                    scope.$l.litColor = this.blinnPhongLight(scope, scope.$inputs.worldPos, scope.normal, scope.viewVec, scope.albedo, scope.outRoughness);
                    this.outputFragmentColor(scope, scope.$inputs.worldPos, pb.vec4(scope.litColor, scope.albedo.a), scope.outRoughness, pb.vec4(pb.add(pb.mul(scope.normal, 0.5), pb.vec3(0.5)), 1));
                } else {
                    scope.$l.litColor = this.blinnPhongLight(scope, scope.$inputs.worldPos, scope.normal, scope.viewVec, scope.albedo);
                    this.outputFragmentColor(scope, scope.$inputs.worldPos, pb.vec4(scope.litColor, scope.albedo.a));
                }
            } else {
                this.outputFragmentColor(scope, scope.$inputs.worldPos, scope.albedo);
            }
        } else {
            this.outputFragmentColor(scope, scope.$inputs.worldPos, null);
        }
    }
}

export { BlinnMaterial };
//# sourceMappingURL=blinn.js.map
