diff --git a/cocos/core/3d/framework/model-component.ts b/cocos/core/3d/framework/model-component.ts index 2293d52f9e3..8234c579b5c 100644 --- a/cocos/core/3d/framework/model-component.ts +++ b/cocos/core/3d/framework/model-component.ts @@ -268,7 +268,9 @@ export class ModelComponent extends RenderableComponent { this._model.isDynamicBatching = this._enableDynamicBatching; // should pass this in before create PSO const meshCount = this._mesh ? this._mesh.subMeshCount : 0; for (let i = 0; i < meshCount; ++i) { - const material = this.getRenderMaterial(i); + // warning:这里先改成model总是使用材质实例,等model中的createPipelineState修改完后再替换成getRenderMaterial + const material = this.getMaterialInstance(i); + // const material = this.getRenderMaterial(i); const renderingMesh = this._mesh.renderingMesh; if (renderingMesh) { const subMeshData = renderingMesh.getSubmesh(i); diff --git a/cocos/core/assets/effect-asset.ts b/cocos/core/assets/effect-asset.ts index 4b7a4c445cc..5bfec5f4783 100644 --- a/cocos/core/assets/effect-asset.ts +++ b/cocos/core/assets/effect-asset.ts @@ -33,7 +33,7 @@ import { GFXDynamicState, GFXPrimitiveMode } from '../gfx/define'; import { GFXBlendState, GFXDepthStencilState, GFXRasterizerState } from '../gfx/pipeline-state'; import { GFXUniformBlock, GFXUniformSampler } from '../gfx/shader'; import { RenderPassStage } from '../pipeline/define'; -import { IDefineMap } from '../renderer/core/pass'; +import { IDefineMap } from '../renderer/core/pass-utils'; import { programLib } from '../renderer/core/program-lib'; import { Asset } from './asset'; diff --git a/cocos/core/assets/material.ts b/cocos/core/assets/material.ts index 1df1ffb50bc..00316e19acf 100644 --- a/cocos/core/assets/material.ts +++ b/cocos/core/assets/material.ts @@ -31,7 +31,8 @@ import { ccclass, property } from '../../core/data/class-decorator'; import { builtinResMgr } from '../3d/builtin/init'; import { RenderableComponent } from '../3d/framework/renderable-component'; -import { IDefineMap, Pass, PassOverrides } from '../renderer/core/pass'; +import { Pass, PassOverrides } from '../renderer/core/pass'; +import { IDefineMap } from '../renderer/core/pass-utils'; import { _uploadProperty, generateMaterailHash, IMaterial } from '../utils/material-interface'; import { Asset } from './asset'; import { EffectAsset } from './effect-asset'; @@ -222,18 +223,7 @@ export class Material extends Asset implements IMaterial { * @param passIdx 要重载的 pass 索引,默认重载所有 pass。 */ public overridePipelineStates (overrides: PassOverrides, passIdx?: number) { - if (!this._passes || !this._effectAsset) { return; } - const passInfos = this._effectAsset.techniques[this._techIdx].passes; - if (passIdx === undefined) { - for (let i = 0; i < this._passes.length; i++) { - const pass = this._passes[i]; - this._states[i] = overrides; - pass.overridePipelineStates(passInfos[pass.idxInTech], overrides); - } - } else { - this._states[passIdx] = overrides; - this._passes[passIdx].overridePipelineStates(passInfos[passIdx], overrides); - } + console.error('Material:' + this.effectName + ' cann\'t be overwritten.Please use pass instance to do so.'); } /** diff --git a/cocos/core/pipeline/render-pipeline.ts b/cocos/core/pipeline/render-pipeline.ts index eb3559e40a0..0b44f5c84de 100644 --- a/cocos/core/pipeline/render-pipeline.ts +++ b/cocos/core/pipeline/render-pipeline.ts @@ -20,7 +20,7 @@ import { GFXTexture } from '../gfx/texture'; import { GFXTextureView } from '../gfx/texture-view'; import { Mat4, Vec3, Vec4 } from '../math'; import { Camera, Model } from '../renderer'; -import { IDefineMap } from '../renderer/core/pass'; +import { IDefineMap } from '../renderer/core/pass-utils'; import { programLib } from '../renderer/core/program-lib'; import { SKYBOX_FLAG } from '../renderer/scene/camera'; import { Root } from '../root'; diff --git a/cocos/core/renderer/core/material-instance.ts b/cocos/core/renderer/core/material-instance.ts index 187d2744265..e321f3d6753 100644 --- a/cocos/core/renderer/core/material-instance.ts +++ b/cocos/core/renderer/core/material-instance.ts @@ -3,8 +3,9 @@ import { EffectAsset, Material } from '../../assets'; import { _uploadProperty, IMaterial } from '../../utils/material-interface'; import { murmurhash2_32_gc } from '../../utils/murmurhash2_gc'; import { IPass } from '../../utils/pass-interface'; -import { IDefineMap, PassOverrides } from './pass'; +import { PassOverrides } from './pass'; import { PassInstance } from './pass-instance'; +import { IDefineMap } from './pass-utils'; export class MaterialInstance implements IMaterial { diff --git a/cocos/core/renderer/core/pass-instance.ts b/cocos/core/renderer/core/pass-instance.ts index 606254f4404..67cacd757ef 100644 --- a/cocos/core/renderer/core/pass-instance.ts +++ b/cocos/core/renderer/core/pass-instance.ts @@ -11,8 +11,8 @@ import { isBuiltinBinding, RenderPassStage, RenderPriority } from '../../pipelin import { getPhaseID } from '../../pipeline/pass-phase'; import { IMaterial } from '../../utils/material-interface'; import { generatePassPSOHash, IBlock, IPass, IPassDynamics, IPSOHashInfo } from '../../utils/pass-interface'; -import { IDefineMap, Pass } from './pass'; -import { getBindingFromHandle, getOffsetFromHandle, getTypeFromHandle, type2default, type2reader, type2writer } from './pass-utils'; +import { Pass } from './pass'; +import { assignDefines, getBindingFromHandle, getOffsetFromHandle, getTypeFromHandle, IDefineMap, type2default, type2reader, type2writer } from './pass-utils'; import { IProgramInfo, programLib } from './program-lib'; import { samplerLib } from './sampler-lib'; @@ -360,7 +360,10 @@ export class PassInstance implements IPass { } } - public tryCompile (defineOverrides?: IDefineMap, saveOverrides?: boolean): any { + public tryCompile (defineOverrides?: IDefineMap): any { + if (defineOverrides && !assignDefines(this._defines, defineOverrides)) { + return null; + } const pipeline = cc.director.root.pipeline; if (!pipeline) { return null; @@ -369,25 +372,13 @@ export class PassInstance implements IPass { if (!this._renderPass) { console.warn(`illegal pass stage.`); return null; } - let defines = this._defines; - if (defineOverrides) { - if (saveOverrides) { - Object.assign(this._defines, defineOverrides); - } - else { - Object.assign(defineOverrides, this._defines); - defines = defineOverrides; - } - } - const res = programLib.getGFXShader(this.device, this.program, defines, pipeline); + const res = programLib.getGFXShader(this.device, this.program, this._defines, pipeline); if (!res.shader) { console.warn(`create shader ${this.program} failed`); return null; } - if (saveOverrides) { - this._shader = res.shader; - this._bindings = res.bindings; - } + this._shader = res.shader; + this._bindings = res.bindings; this._hash = generatePassPSOHash(this); this._onPipelineStateChanged(); return res; diff --git a/cocos/core/renderer/core/pass-utils.ts b/cocos/core/renderer/core/pass-utils.ts index aa4ca44004c..85ff97f7cf0 100644 --- a/cocos/core/renderer/core/pass-utils.ts +++ b/cocos/core/renderer/core/pass-utils.ts @@ -85,3 +85,17 @@ export const type2default = { [GFXType.SAMPLER2D]: 'default-texture', [GFXType.SAMPLER_CUBE]: 'default-cube-texture', }; + +export interface IDefineMap { [name: string]: number | boolean | string; } + +export function assignDefines (target: IDefineMap, source: IDefineMap): boolean { + const entries = Object.entries(source); + let isDifferent: boolean = false; + for (let i = 0; i < entries.length; i++) { + if (target[entries[i][0]] !== entries[i][1]) { + target[entries[i][0]] = entries[i][1]; + isDifferent = true; + } + } + return isDifferent; +} diff --git a/cocos/core/renderer/core/pass.ts b/cocos/core/renderer/core/pass.ts index a9215a7862f..10b0882a1cc 100644 --- a/cocos/core/renderer/core/pass.ts +++ b/cocos/core/renderer/core/pass.ts @@ -45,11 +45,11 @@ import { isBuiltinBinding, RenderPassStage, RenderPriority } from '../../pipelin import { getPhaseID } from '../../pipeline/pass-phase'; import { Root } from '../../root'; import { generatePassPSOHash, IBlock, IPass, IPassDynamics, IPSOHashInfo } from '../../utils/pass-interface'; -import { customizeType, getBindingFromHandle, getBindingTypeFromHandle, getOffsetFromHandle, getTypeFromHandle, type2default, type2reader, type2writer } from './pass-utils'; +// tslint:disable-next-line: max-line-length +import { assignDefines, customizeType, getBindingFromHandle, getBindingTypeFromHandle, getOffsetFromHandle, getTypeFromHandle, IDefineMap, type2default, type2reader, type2writer } from './pass-utils'; import { IProgramInfo, IShaderResources, programLib } from './program-lib'; import { samplerLib } from './sampler-lib'; -export interface IDefineMap { [name: string]: number | boolean | string; } export interface IPassInfoFull extends IPassInfo { // generated part idxInTech: number; @@ -500,15 +500,18 @@ export class Pass implements IPass { */ public tryCompile ( defineOverrides?: IDefineMap, - saveOverrides = true, ): IShaderResources | null /* TODO: Explicit since TS4053 bug , changes required once the issue is fixed. */ { + if (defineOverrides && !assignDefines(this._defines, defineOverrides)) { + return null; + } const pipeline = (cc.director.root as Root).pipeline; if (!pipeline) { return null; } this._renderPass = pipeline.getRenderPass(this._stage); if (!this._renderPass) { console.warn(`illegal pass stage.`); return null; } const res = programLib.getGFXShader(this._device, this._programName, this._defines, pipeline); if (!res.shader) { console.warn(`create shader ${this._programName} failed`); return null; } - if (saveOverrides) { this._shader = res.shader; this._bindings = res.bindings; } + this._shader = res.shader; + this._bindings = res.bindings; this._hash = generatePassPSOHash(this); return res; } diff --git a/cocos/core/renderer/core/program-lib.ts b/cocos/core/renderer/core/program-lib.ts index 99983bc995b..17f4c3605bf 100644 --- a/cocos/core/renderer/core/program-lib.ts +++ b/cocos/core/renderer/core/program-lib.ts @@ -34,8 +34,7 @@ import { GFXAPI, GFXDevice } from '../../gfx/device'; import { GFXShader, GFXUniformBlock } from '../../gfx/shader'; import { IInternalBindingDesc, localBindingsDesc } from '../../pipeline/define'; import { RenderPipeline } from '../../pipeline/render-pipeline'; -import { IDefineMap } from './pass'; -import { genHandle } from './pass-utils'; +import { genHandle, IDefineMap } from './pass-utils'; interface IDefineRecord extends IDefineInfo { _map: (value: any) => number; diff --git a/cocos/core/renderer/scene/model.ts b/cocos/core/renderer/scene/model.ts index 171205dec5e..a2594ad93e8 100644 --- a/cocos/core/renderer/scene/model.ts +++ b/cocos/core/renderer/scene/model.ts @@ -14,10 +14,10 @@ import { Node } from '../../scene-graph'; import { Layers } from '../../scene-graph/layers'; import { IMaterial } from '../../utils/material-interface'; import { IPass } from '../../utils/pass-interface'; -import { IDefineMap } from '../core/pass'; import { customizationManager } from './customization-manager'; import { RenderScene } from './render-scene'; import { SubModel } from './submodel'; +import { IDefineMap } from '../core/pass-utils'; const m4_1 = new Mat4(); @@ -360,7 +360,7 @@ export class Model { } } - protected createPipelineState (pass: IPass, defineOverrides?: IDefineMap, stateOverrides?: IPassStates) { + protected createPipelineState (pass: IPass, defineOverrides?: IDefineMap) { defineOverrides = defineOverrides || {}; if (pass.blendState.targets[0].blend) { this._isDynamicBatching = false; diff --git a/cocos/core/utils/material-interface.ts b/cocos/core/utils/material-interface.ts index a0dfcbc5430..430f1840faf 100644 --- a/cocos/core/utils/material-interface.ts +++ b/cocos/core/utils/material-interface.ts @@ -3,8 +3,8 @@ import { EffectAsset } from '../assets/effect-asset'; import { SpriteFrame } from '../assets/sprite-frame'; import { TextureBase } from '../assets/texture-base'; import { GFXBindingType, GFXTextureView } from '../gfx'; -import { IDefineMap, PassOverrides } from '../renderer/core/pass'; -import { getBindingFromHandle, getBindingTypeFromHandle } from '../renderer/core/pass-utils'; +import { PassOverrides } from '../renderer/core/pass'; +import { getBindingFromHandle, getBindingTypeFromHandle, IDefineMap } from '../renderer/core/pass-utils'; import { samplerLib } from '../renderer/core/sampler-lib'; import { murmurhash2_32_gc } from './murmurhash2_gc'; import { IPass } from './pass-interface'; diff --git a/cocos/core/utils/pass-interface.ts b/cocos/core/utils/pass-interface.ts index 7a3fee6ba79..e6963101b54 100644 --- a/cocos/core/utils/pass-interface.ts +++ b/cocos/core/utils/pass-interface.ts @@ -5,7 +5,8 @@ import { IGFXBinding } from '../gfx/binding-layout'; import { GFXBlendState, GFXDepthStencilState, GFXRasterizerState } from '../gfx/pipeline-state'; import { BatchedBuffer } from '../pipeline/batched-buffer'; import { RenderPassStage, RenderPriority } from '../pipeline/define'; -import { IDefineMap, PassOverrides } from '../renderer/core/pass'; +import { PassOverrides } from '../renderer/core/pass'; +import { IDefineMap } from '../renderer/core/pass-utils'; import { murmurhash2_32_gc } from './murmurhash2_gc'; export interface IBlock { @@ -211,7 +212,7 @@ export interface IPass { * 尝试编译 shader 并获取相关资源引用。 * @param defineOverrides shader 预处理宏定义重载 */ - tryCompile (defineOverrides?: IDefineMap, saveOverrides?: boolean): any; + tryCompile (defineOverrides?: IDefineMap): any; /** * @zh diff --git a/cocos/particle/renderer/particle-system-renderer.ts b/cocos/particle/renderer/particle-system-renderer.ts index 0ddbec55bcd..aadc3b6bdca 100644 --- a/cocos/particle/renderer/particle-system-renderer.ts +++ b/cocos/particle/renderer/particle-system-renderer.ts @@ -6,8 +6,8 @@ import { GFXAttributeName, GFXFormat } from '../../core/gfx/define'; import { IGFXAttribute } from '../../core/gfx/input-assembler'; import { Mat4, Vec2, Vec3, Vec4 } from '../../core/math'; import { RecyclePool } from '../../core/memop'; -import { MaterialInstance } from '../../core/renderer'; -import { IDefineMap } from '../../core/renderer/core/pass'; +import { MaterialInstance } from '../../core/renderer/core/material-instance'; +import { IDefineMap } from '../../core/renderer/core/pass-utils'; import { IMaterial } from '../../core/utils/material-interface'; import { RenderMode, Space } from '../enum'; import ParticleBatchModel from '../models/particle-batch-model'; diff --git a/cocos/terrain/terrain.ts b/cocos/terrain/terrain.ts index d86f932cc9d..3e0781a92f8 100644 --- a/cocos/terrain/terrain.ts +++ b/cocos/terrain/terrain.ts @@ -16,7 +16,7 @@ import { GFXAttributeName, GFXBufferUsageBit, GFXFormat, GFXMemoryUsageBit, GFXP import { GFXDevice } from '../core/gfx/device'; import { IGFXAttribute } from '../core/gfx/input-assembler'; import { clamp, Rect, Size, Vec2, Vec3, Vec4 } from '../core/math'; -import { IDefineMap } from '../core/renderer/core/pass'; +import { IDefineMap } from '../core/renderer/core/pass-utils'; import { Model } from '../core/renderer/scene/model'; import { Root } from '../core/root'; import { PrivateNode } from '../core/scene-graph/private-node';