├── .git.meta ├── custom-forward-pipeline.rpp ├── custom-forward-pipeline.rpp.meta ├── defines.meta ├── defines ├── layer.ts ├── layer.ts.meta ├── pipeline.ts ├── pipeline.ts.meta ├── ubo.ts └── ubo.ts.meta ├── materials.meta ├── materials ├── builtin.meta ├── builtin │ ├── standard.effect │ ├── standard.effect.meta │ ├── standard.mtl │ ├── standard.mtl.meta │ ├── terrain.effect │ ├── terrain.effect.meta │ ├── unlit-cast-shadow.effect │ ├── unlit-cast-shadow.effect.meta │ ├── unlit-cast-shadow.mtl │ └── unlit-cast-shadow.mtl.meta ├── chunks.meta ├── chunks │ ├── phong.chunk │ ├── phong.chunk.meta │ ├── ubo-custom-common.chunk │ └── ubo-custom-common.chunk.meta ├── grass.meta ├── grass │ ├── grass-bend.meta │ ├── grass-bend │ │ ├── debug-bend.mtl │ │ ├── debug-bend.mtl.meta │ │ ├── grass-bend.effect │ │ ├── grass-bend.effect.meta │ │ ├── grass-bend.mtl │ │ └── grass-bend.mtl.meta │ ├── grass.meta │ └── grass │ │ ├── bend.chunk │ │ ├── bend.chunk.meta │ │ ├── color.chunk │ │ ├── color.chunk.meta │ │ ├── grass.effect │ │ ├── grass.effect.meta │ │ ├── wind.chunk │ │ └── wind.chunk.meta ├── tests.meta ├── tests │ ├── normal-color.effect │ ├── normal-color.effect.meta │ ├── normal-color.mtl │ ├── normal-color.mtl.meta │ ├── vertex-color.effect │ ├── vertex-color.effect.meta │ ├── vertex-color.mtl │ └── vertex-color.mtl.meta ├── water.meta └── water │ ├── textures.meta │ ├── textures │ ├── Caustics 1.png │ ├── Caustics 1.png.meta │ ├── Foam 4.png │ ├── Foam 4.png.meta │ ├── NormalMap.png │ ├── NormalMap.png.meta │ ├── cloudnoise_1.png │ ├── cloudnoise_1.png.meta │ ├── normals.jpg │ └── normals.jpg.meta │ ├── water.effect │ └── water.effect.meta ├── stages.meta ├── stages ├── advanced-flow.ts ├── advanced-flow.ts.meta ├── advanced-pipeline.ts ├── advanced-pipeline.ts.meta ├── depth-buffer.meta ├── depth-buffer │ ├── depth-buffer-object.ts │ ├── depth-buffer-object.ts.meta │ ├── depth-buffer-stage.ts │ └── depth-buffer-stage.ts.meta ├── grass.meta ├── grass │ ├── grass-bend-render-stage.ts │ ├── grass-bend-render-stage.ts.meta │ ├── src.meta │ └── src │ │ ├── grass-bender-renderer.ts │ │ ├── grass-bender-renderer.ts.meta │ │ ├── grass-bender.ts │ │ └── grass-bender.ts.meta ├── instance.meta ├── instance │ ├── instace-manager.ts │ ├── instace-manager.ts.meta │ ├── instance-block-stage.ts.meta │ ├── instance-block.ts │ ├── instance-block.ts.meta │ ├── instance-forward-stage.ts │ ├── instance-forward-stage.ts.meta │ ├── instance-object.ts │ ├── instance-object.ts.meta │ ├── instance-shadow-stage.ts │ ├── instance-shadow-stage.ts.meta │ ├── instanced-object-queue.ts │ └── instanced-object-queue.ts.meta ├── post-process.meta └── post-process │ ├── editor.meta │ ├── editor │ ├── post-process-renderer-materials.ts │ └── post-process-renderer-materials.ts.meta │ ├── effects.meta │ ├── effects │ ├── bloom.effect │ ├── bloom.effect.meta │ ├── bloom.mtl │ ├── bloom.mtl.meta │ ├── bloom.ts │ ├── bloom.ts.meta │ ├── chunk.meta │ ├── color-grading.effect │ ├── color-grading.effect.meta │ ├── color-grading.mtl │ ├── color-grading.mtl.meta │ ├── color-grading.ts │ ├── color-grading.ts.meta │ ├── fxaa.effect │ ├── fxaa.effect.meta │ ├── fxaa.mtl │ ├── fxaa.mtl.meta │ ├── post-process-vs.chunk │ ├── post-process-vs.chunk.meta │ ├── post-process.chunk │ ├── post-process.chunk.meta │ ├── tonemap.effect │ ├── tonemap.effect.meta │ ├── tonemap.mtl │ ├── tonemap.mtl.meta │ ├── tonemap.ts │ ├── tonemap.ts.meta │ ├── vignette.effect │ ├── vignette.effect.meta │ ├── vignette.mtl │ ├── vignette.mtl.meta │ ├── vignette.ts │ └── vignette.ts.meta │ ├── post-effect-base.ts │ ├── post-effect-base.ts.meta │ ├── post-process-command.ts │ ├── post-process-command.ts.meta │ ├── post-process-stage.ts │ ├── post-process-stage.ts.meta │ ├── post-process.ts │ ├── post-process.ts.meta │ ├── quad-mesh.ts │ ├── quad-mesh.ts.meta │ ├── renderers.meta │ └── shadowmap-queue.ts.meta ├── utils.meta └── utils ├── draw.ts ├── draw.ts.meta ├── editor.ts ├── editor.ts.meta ├── path.ts ├── path.ts.meta ├── stage.ts └── stage.ts.meta /.git.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.1.0", 3 | "importer": "directory", 4 | "imported": true, 5 | "uuid": "1c53ec85-48b1-4990-882a-7abee10fccaa", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "compressionType": {}, 10 | "isRemoteBundle": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /custom-forward-pipeline.rpp: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "__type__": "AdvancedPipeline", 4 | "_name": "", 5 | "_objFlags": 0, 6 | "_native": "", 7 | "_tag": 0, 8 | "_flows": [ 9 | { 10 | "__id__": 1 11 | }, 12 | { 13 | "__id__": 3 14 | } 15 | ], 16 | "renderTextures": [], 17 | "materials": [], 18 | "usePostProcess": false 19 | }, 20 | { 21 | "__type__": "ShadowFlow", 22 | "_name": "", 23 | "_priority": 0, 24 | "_tag": 0, 25 | "_stages": [ 26 | { 27 | "__id__": 2 28 | } 29 | ] 30 | }, 31 | { 32 | "__type__": "ShadowStage", 33 | "_name": "", 34 | "_priority": 0, 35 | "_tag": 0 36 | }, 37 | { 38 | "__type__": "AdvancedFlow", 39 | "_name": "AdvancedFlow", 40 | "_priority": 0, 41 | "_tag": 0, 42 | "_stages": [] 43 | } 44 | ] -------------------------------------------------------------------------------- /custom-forward-pipeline.rpp.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "0.0.1", 3 | "importer": "render-pipeline", 4 | "imported": true, 5 | "uuid": "66ca256a-5401-407d-a57b-f0cec17c86a4", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /defines.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.1.0", 3 | "importer": "directory", 4 | "imported": true, 5 | "uuid": "716b1727-43db-4552-9268-8d24c5dab548", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "compressionType": {}, 10 | "isRemoteBundle": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /defines/layer.ts: -------------------------------------------------------------------------------- 1 | 2 | export enum Layers { 3 | DepthBuffer = 1 << 0, 4 | GrassBend = 1 << 1, 5 | Instance = 1 << 2, 6 | } 7 | -------------------------------------------------------------------------------- /defines/layer.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "b17452f4-e663-41b8-a42e-120dcc4e6cb1", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "importAsPlugin": false, 10 | "moduleId": "project:///assets/libs/advanced-pipeline/defines/layer.js", 11 | "importerSettings": 4 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /defines/pipeline.ts: -------------------------------------------------------------------------------- 1 | import { pipeline as _pipeline, getPhaseID as _getPhaseID } from 'cc'; 2 | 3 | let SetIndex, PipelineGlobalBindings, globalDescriptorSetLayout, bindingMappingInfo, UBOShadow; 4 | 5 | // fixed native 6 | if (typeof _pipeline === 'undefined') { 7 | SetIndex = {} as any; 8 | PipelineGlobalBindings = {} as any; 9 | globalDescriptorSetLayout = { 10 | layouts: {}, 11 | bindings: {} 12 | } as any; 13 | bindingMappingInfo = { 14 | samplerOffsets: [] 15 | } as any; 16 | } 17 | else { 18 | SetIndex = _pipeline.SetIndex; 19 | PipelineGlobalBindings = _pipeline.PipelineGlobalBindings; 20 | globalDescriptorSetLayout = _pipeline.globalDescriptorSetLayout; 21 | bindingMappingInfo = _pipeline.bindingMappingInfo; 22 | UBOShadow = _pipeline.UBOShadow; 23 | } 24 | 25 | 26 | export const pipeline = { 27 | SetIndex, 28 | PipelineGlobalBindings, 29 | globalDescriptorSetLayout, 30 | bindingMappingInfo, 31 | UBOShadow, 32 | }; 33 | 34 | 35 | export function getPhaseID (phase: string | number) { 36 | if (_getPhaseID !== undefined) { 37 | return _getPhaseID(phase); 38 | } 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /defines/pipeline.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "a3b07e60-e4be-4c9b-8d01-e31a6a61faa6", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "importAsPlugin": false, 10 | "moduleId": "project:///assets/libs/advanced-pipeline/defines/pipeline.js", 11 | "importerSettings": 4 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /defines/ubo.ts: -------------------------------------------------------------------------------- 1 | import { GFXUniformSampler, GFXDescriptorSetLayoutBinding, GFXDescriptorType, GFXShaderStageFlagBit, GFXUniformBlock, GFXUniform, GFXType } from "cc"; 2 | import { pipeline } from './pipeline'; 3 | 4 | const { SetIndex, PipelineGlobalBindings, globalDescriptorSetLayout, bindingMappingInfo } = pipeline; 5 | 6 | let BindingStart = PipelineGlobalBindings.COUNT; 7 | let BindingIndex = 0; 8 | 9 | export class UBOGrassBend { 10 | public static UVOffset: number = 0; 11 | public static COUNT: number = UBOGrassBend.UVOffset + 4; 12 | public static SIZE: number = UBOGrassBend.COUNT * 4; 13 | 14 | public static readonly NAME = 'CCGrassBend'; 15 | public static readonly BINDING = BindingStart + BindingIndex++; 16 | public static readonly DESCRIPTOR = new GFXDescriptorSetLayoutBinding(UBOGrassBend.BINDING, GFXDescriptorType.UNIFORM_BUFFER, 1, GFXShaderStageFlagBit.ALL); 17 | 18 | public static readonly LAYOUT = new GFXUniformBlock(SetIndex.GLOBAL, UBOGrassBend.BINDING, UBOGrassBend.NAME, [ 19 | new GFXUniform('cc_grass_bend_uv', GFXType.FLOAT4, 1), 20 | ], 1) 21 | } 22 | globalDescriptorSetLayout.layouts[UBOGrassBend.NAME] = UBOGrassBend.LAYOUT; 23 | globalDescriptorSetLayout.bindings[UBOGrassBend.BINDING] = UBOGrassBend.DESCRIPTOR; 24 | 25 | 26 | export class UBOCustomCommon { 27 | public static ProjectionParamsOffset: number = 0; 28 | public static COUNT: number = UBOCustomCommon.ProjectionParamsOffset + 4; 29 | public static SIZE: number = UBOCustomCommon.COUNT * 4; 30 | 31 | public static readonly NAME = 'CCCustomCommon'; 32 | public static readonly BINDING = BindingStart + BindingIndex++; 33 | public static readonly DESCRIPTOR = new GFXDescriptorSetLayoutBinding(UBOCustomCommon.BINDING, GFXDescriptorType.UNIFORM_BUFFER, 1, GFXShaderStageFlagBit.ALL); 34 | 35 | public static readonly LAYOUT = new GFXUniformBlock(SetIndex.GLOBAL, UBOCustomCommon.BINDING, UBOCustomCommon.NAME, [ 36 | new GFXUniform('cc_projection_params', GFXType.FLOAT4, 1), 37 | ], 1) 38 | } 39 | globalDescriptorSetLayout.layouts[UBOCustomCommon.NAME] = UBOCustomCommon.LAYOUT; 40 | globalDescriptorSetLayout.bindings[UBOCustomCommon.BINDING] = UBOCustomCommon.DESCRIPTOR; 41 | 42 | 43 | export const UNIFORM_GRASS_BEND_MAP_BINDING = BindingStart + BindingIndex++; 44 | export const UNIFORM_GRASS_BEND_MAP_NAME = 'cc_grass_bend_map' 45 | export const UNIFORM_GRASS_BEND_MAP_LAYOUT = new GFXUniformSampler(SetIndex.GLOBAL, UNIFORM_GRASS_BEND_MAP_BINDING, UNIFORM_GRASS_BEND_MAP_NAME, GFXType.SAMPLER2D, 1); 46 | export const UNIFORM_GRASS_BEND_MAP_DESCRIPTOR = new GFXDescriptorSetLayoutBinding(UNIFORM_GRASS_BEND_MAP_BINDING, GFXDescriptorType.SAMPLER, 1, GFXShaderStageFlagBit.FRAGMENT); 47 | globalDescriptorSetLayout.layouts[UNIFORM_GRASS_BEND_MAP_NAME] = UNIFORM_GRASS_BEND_MAP_LAYOUT; 48 | globalDescriptorSetLayout.bindings[UNIFORM_GRASS_BEND_MAP_BINDING] = UNIFORM_GRASS_BEND_MAP_DESCRIPTOR; 49 | 50 | export const UNIFORM_DEPTH_BUFFER_MAP_BINDING = BindingStart + BindingIndex++; 51 | export const UNIFORM_DEPTH_BUFFER_MAP_NAME = 'cc_depth_buffer_map'; 52 | export const UNIFORM_DEPTH_BUFFER_MAP_LAYOUT = new GFXUniformSampler(SetIndex.GLOBAL, UNIFORM_DEPTH_BUFFER_MAP_BINDING, UNIFORM_DEPTH_BUFFER_MAP_NAME, GFXType.SAMPLER2D, 1); 53 | export const UNIFORM_DEPTH_BUFFER_MAP_DESCRIPTOR = new GFXDescriptorSetLayoutBinding(UNIFORM_DEPTH_BUFFER_MAP_BINDING, GFXDescriptorType.SAMPLER, 1, GFXShaderStageFlagBit.FRAGMENT); 54 | globalDescriptorSetLayout.layouts[UNIFORM_DEPTH_BUFFER_MAP_NAME] = UNIFORM_DEPTH_BUFFER_MAP_LAYOUT; 55 | globalDescriptorSetLayout.bindings[UNIFORM_DEPTH_BUFFER_MAP_BINDING] = UNIFORM_DEPTH_BUFFER_MAP_DESCRIPTOR; 56 | 57 | // final 58 | bindingMappingInfo.samplerOffsets[1] += BindingIndex; 59 | bindingMappingInfo.samplerOffsets[2] += BindingIndex; 60 | -------------------------------------------------------------------------------- /defines/ubo.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "76f55004-697b-4a5a-a93e-4aa0b50803dc", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "importAsPlugin": false, 10 | "moduleId": "project:///assets/libs/advanced-pipeline/defines/ubo.js", 11 | "importerSettings": 4 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /materials.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.1.0", 3 | "importer": "directory", 4 | "imported": true, 5 | "uuid": "33d0898c-4cd7-4e69-9039-40c07d984f34", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "compressionType": {}, 10 | "isRemoteBundle": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /materials/builtin.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.1.0", 3 | "importer": "directory", 4 | "imported": true, 5 | "uuid": "64e87111-97e6-401f-8b57-c76d7f16e372", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "compressionType": {}, 10 | "isRemoteBundle": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /materials/builtin/standard.effect: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd. 2 | 3 | CCEffect %{ 4 | techniques: 5 | - name: opaque 6 | passes: 7 | - vert: standard-vs:vert 8 | frag: standard-fs:frag 9 | properties: &props 10 | tilingOffset: { value: [1.0, 1.0, 0.0, 0.0] } 11 | mainColor: { value: [1.0, 1.0, 1.0, 1.0], target: albedo, editor: { displayName: Albedo, type: color } } 12 | albedoScale: { value: [1.0, 1.0, 1.0], target: albedoScaleAndCutoff.xyz } 13 | alphaThreshold: { value: 0.5, target: albedoScaleAndCutoff.w, editor: { parent: USE_ALPHA_TEST } } 14 | occlusion: { value: 1.0, target: pbrParams.x } 15 | roughness: { value: 0.8, target: pbrParams.y } 16 | metallic: { value: 0.6, target: pbrParams.z } 17 | normalStrenth: { value: 1.0, target: pbrParams.w, editor: { parent: USE_NORMAL_MAP } } 18 | emissive: { value: [0.0, 0.0, 0.0, 1.0], editor: { type: color } } 19 | emissiveScale: { value: [1.0, 1.0, 1.0], target: emissiveScaleParam.xyz } 20 | mainTexture: { value: grey, target: albedoMap, editor: { displayName: AlbedoMap } } 21 | normalMap: { value: normal } 22 | pbrMap: { value: grey } 23 | metallicRoughnessMap: { value: grey } 24 | occlusionMap: { value: white } 25 | emissiveMap: { value: grey } 26 | migrations: &migs # existing material data migration 27 | properties: 28 | mainColor: { formerlySerializedAs: albedo } 29 | alphaThreshold: { formerlySerializedAs: albedoScale.w } 30 | normalStrenth: { formerlySerializedAs: pbrScale.w } 31 | mainTexture: { formerlySerializedAs: albedoMap } 32 | - vert: standard-vs:vert 33 | frag: standard-fs:frag 34 | phase: forward-add 35 | propertyIndex: 0 36 | embeddedMacros: { CC_FORWARD_ADD: true } 37 | depthStencilState: 38 | depthFunc: equal 39 | depthTest: true 40 | depthWrite: false 41 | blendState: 42 | targets: 43 | - blend: true 44 | blendSrc: one 45 | blendDst: one 46 | blendSrcAlpha: zero 47 | blendDstAlpha: one 48 | properties: *props 49 | - vert: depth-buffer-vs:vert 50 | frag: depth-buffer-fs:frag 51 | phase: depth-buffer 52 | propertyIndex: 0 53 | rasterizerState: 54 | cullMode: front 55 | - name: transparent 56 | passes: 57 | - vert: standard-vs:vert 58 | frag: standard-fs:frag 59 | depthStencilState: 60 | depthTest: true 61 | depthWrite: false 62 | blendState: 63 | targets: 64 | - blend: true 65 | blendSrc: src_alpha 66 | blendDst: one_minus_src_alpha 67 | blendDstAlpha: one_minus_src_alpha 68 | properties: *props 69 | migrations: *migs 70 | - vert: standard-vs:vert 71 | frag: standard-fs:frag 72 | phase: forward-add 73 | propertyIndex: 0 74 | depthStencilState: 75 | depthTest: true 76 | depthWrite: false 77 | blendState: 78 | targets: 79 | - blend: true 80 | blendSrc: one 81 | blendDst: one 82 | properties: *props 83 | - vert: depth-buffer-vs:vert 84 | frag: depth-buffer-fs:frag 85 | phase: depth-buffer 86 | propertyIndex: 0 87 | rasterizerState: 88 | cullMode: front 89 | }% 90 | 91 | CCProgram shared-ubos %{ 92 | uniform Constants { 93 | vec4 tilingOffset; 94 | vec4 albedo; 95 | vec4 albedoScaleAndCutoff; 96 | vec4 pbrParams; 97 | vec4 emissive; 98 | vec4 emissiveScaleParam; 99 | }; 100 | }% 101 | 102 | CCProgram standard-vs %{ 103 | precision highp float; 104 | #include 105 | #include 106 | #include 107 | #include 108 | #include 109 | #include 110 | 111 | #if USE_VERTEX_COLOR 112 | in vec3 a_color; 113 | out vec3 v_color; 114 | #endif 115 | 116 | out vec3 v_position; 117 | out vec3 v_normal; 118 | out vec2 v_uv; 119 | out vec2 v_uv1; 120 | out float v_fog_factor; 121 | 122 | #if USE_NORMAL_MAP 123 | out vec3 v_tangent; 124 | out vec3 v_bitangent; 125 | #endif 126 | 127 | #if HAS_SECOND_UV || USE_LIGHTMAP 128 | in vec2 a_texCoord1; 129 | #endif 130 | 131 | #if USE_LIGHTMAP && !USE_BATCHING && !CC_FORWARD_ADD 132 | #include 133 | #endif 134 | 135 | vec4 vert () { 136 | StandardVertInput In; 137 | CCVertInput(In); 138 | 139 | mat4 matWorld, matWorldIT; 140 | CCGetWorldMatrixFull(matWorld, matWorldIT); 141 | 142 | vec4 pos = matWorld * In.position; 143 | 144 | v_position = pos.xyz; 145 | v_normal = normalize((matWorldIT * vec4(In.normal, 0.0)).xyz); 146 | #if USE_NORMAL_MAP 147 | v_tangent = normalize((matWorld * vec4(In.tangent.xyz, 0.0)).xyz); 148 | v_bitangent = cross(v_normal, v_tangent) * In.tangent.w; // note the cross order 149 | #endif 150 | 151 | v_uv = a_texCoord * tilingOffset.xy + tilingOffset.zw; 152 | #if HAS_SECOND_UV 153 | v_uv1 = a_texCoord1 * tilingOffset.xy + tilingOffset.zw; 154 | #endif 155 | 156 | #if USE_VERTEX_COLOR 157 | v_color = a_color; 158 | #endif 159 | v_fog_factor = CC_TRANSFER_FOG(pos); 160 | 161 | #if USE_LIGHTMAP && !USE_BATCHING && !CC_FORWARD_ADD 162 | CCLightingMapCaclUV(); 163 | #endif 164 | 165 | CCPassShadowParams(pos); 166 | 167 | return cc_matProj * (cc_matView * matWorld) * In.position; 168 | } 169 | }% 170 | 171 | CCProgram standard-fs %{ 172 | precision highp float; 173 | #include 174 | #include 175 | #include 176 | #include 177 | #include 178 | #include 179 | 180 | in vec3 v_position; 181 | in vec2 v_uv; 182 | in vec2 v_uv1; 183 | in vec3 v_normal; 184 | in float v_fog_factor; 185 | 186 | #if USE_VERTEX_COLOR 187 | in vec3 v_color; 188 | #endif 189 | 190 | #if USE_ALBEDO_MAP 191 | uniform sampler2D albedoMap; 192 | #pragma define ALBEDO_UV options([v_uv, v_uv1]) 193 | #endif 194 | #if USE_NORMAL_MAP 195 | in vec3 v_tangent; 196 | in vec3 v_bitangent; 197 | uniform sampler2D normalMap; 198 | #pragma define NORMAL_UV options([v_uv, v_uv1]) 199 | #endif 200 | #pragma define PBR_UV options([v_uv, v_uv1]) 201 | #if USE_PBR_MAP 202 | uniform sampler2D pbrMap; 203 | #endif 204 | #if USE_METALLIC_ROUGHNESS_MAP 205 | uniform sampler2D metallicRoughnessMap; 206 | #endif 207 | #if USE_OCCLUSION_MAP 208 | uniform sampler2D occlusionMap; 209 | #endif 210 | #if USE_EMISSIVE_MAP 211 | uniform sampler2D emissiveMap; 212 | #pragma define EMISSIVE_UV options([v_uv, v_uv1]) 213 | #endif 214 | 215 | #define OCCLUSION_CHANNEL r 216 | #define ROUGHNESS_CHANNEL g 217 | #define METALLIC_CHANNEL b 218 | 219 | #if USE_ALPHA_TEST 220 | #pragma define ALPHA_TEST_CHANNEL options([a, r]) 221 | #endif 222 | 223 | void surf (out StandardSurface s) { 224 | vec4 baseColor = albedo; 225 | #if USE_VERTEX_COLOR 226 | baseColor.rgb *= v_color; 227 | #endif 228 | #if USE_ALBEDO_MAP 229 | vec4 texColor = texture(albedoMap, ALBEDO_UV); 230 | texColor.rgb = SRGBToLinear(texColor.rgb); 231 | baseColor *= texColor; 232 | #endif 233 | s.albedo = baseColor; 234 | s.albedo.rgb *= albedoScaleAndCutoff.xyz; 235 | 236 | #if USE_ALPHA_TEST 237 | if (s.albedo.ALPHA_TEST_CHANNEL < albedoScaleAndCutoff.w) discard; 238 | #endif 239 | 240 | s.normal = v_normal; 241 | #if USE_NORMAL_MAP 242 | vec3 nmmp = texture(normalMap, NORMAL_UV).xyz - vec3(0.5); 243 | s.normal = 244 | (nmmp.x * pbrParams.w) * normalize(v_tangent) + 245 | (nmmp.y * pbrParams.w) * normalize(v_bitangent) + 246 | nmmp.z * normalize(s.normal); 247 | #endif 248 | 249 | s.position = v_position; 250 | 251 | vec4 pbr = pbrParams; 252 | #if USE_PBR_MAP 253 | vec4 res = texture(pbrMap, PBR_UV); 254 | pbr.x *= res.OCCLUSION_CHANNEL; 255 | pbr.y *= res.ROUGHNESS_CHANNEL; 256 | pbr.z *= res.METALLIC_CHANNEL; 257 | #endif 258 | #if USE_METALLIC_ROUGHNESS_MAP 259 | vec4 metallicRoughness = texture(metallicRoughnessMap, PBR_UV); 260 | pbr.z *= metallicRoughness.METALLIC_CHANNEL; 261 | pbr.y *= metallicRoughness.ROUGHNESS_CHANNEL; 262 | #endif 263 | #if USE_OCCLUSION_MAP 264 | pbr.x *= texture(occlusionMap, PBR_UV).OCCLUSION_CHANNEL; 265 | #endif 266 | s.occlusion = clamp(pbr.x, 0.0, 0.96); 267 | s.roughness = clamp(pbr.y, 0.04, 1.0); 268 | s.metallic = pbr.z; 269 | 270 | s.emissive = emissive.rgb * emissiveScaleParam.xyz; 271 | #if USE_EMISSIVE_MAP 272 | s.emissive *= SRGBToLinear(texture(emissiveMap, EMISSIVE_UV).rgb); 273 | #endif 274 | } 275 | 276 | vec4 frag () { 277 | StandardSurface s; surf(s); 278 | vec4 color = CCStandardShading(s); 279 | color = CC_APPLY_FOG(color, v_fog_factor); 280 | return CCFragOutput(color); 281 | } 282 | }% 283 | 284 | CCProgram depth-buffer-vs %{ 285 | precision highp float; 286 | #include 287 | #include 288 | #include 289 | #include 290 | #include 291 | 292 | #include <../chunks/ubo-custom-common> 293 | 294 | #if HAS_SECOND_UV || USE_LIGHTMAP 295 | in vec2 a_texCoord1; 296 | #endif 297 | 298 | out vec2 v_uv; 299 | out vec2 v_uv1; 300 | 301 | out float v_clip_depth; 302 | 303 | vec4 vert () { 304 | StandardVertInput In; 305 | CCVertInput(In); 306 | 307 | mat4 matWorld, matWorldIT; 308 | CCGetWorldMatrixFull(matWorld, matWorldIT); 309 | 310 | vec4 worldPos = matWorld * In.position; 311 | vec4 viewPos = cc_matView * worldPos; 312 | 313 | v_uv = a_texCoord * tilingOffset.xy + tilingOffset.zw; 314 | #if HAS_SECOND_UV 315 | v_uv1 = a_texCoord1 * tilingOffset.xy + tilingOffset.zw; 316 | #endif 317 | 318 | v_clip_depth = -viewPos.z / cc_projection_params.y; 319 | 320 | return cc_matProj * viewPos; 321 | } 322 | }% 323 | 324 | CCProgram depth-buffer-fs %{ 325 | precision highp float; 326 | #include 327 | #include 328 | 329 | in vec2 v_uv; 330 | in vec2 v_uv1; 331 | in float v_clip_depth; 332 | 333 | #if USE_ALBEDO_MAP 334 | uniform sampler2D albedoMap; 335 | #pragma define ALBEDO_UV options([v_uv, v_uv1]) 336 | #endif 337 | 338 | #if USE_ALPHA_TEST 339 | #pragma define ALPHA_TEST_CHANNEL options([a, r]) 340 | #endif 341 | 342 | vec4 frag () { 343 | vec4 baseColor = albedo; 344 | 345 | #if USE_ALBEDO_MAP 346 | baseColor *= texture(albedoMap, ALBEDO_UV); 347 | #endif 348 | 349 | #if USE_ALPHA_TEST 350 | if (baseColor.ALPHA_TEST_CHANNEL < albedoScaleAndCutoff.w) discard; 351 | #endif 352 | 353 | return packDepthToRGBA(v_clip_depth); 354 | } 355 | }% 356 | -------------------------------------------------------------------------------- /materials/builtin/standard.effect.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.4.4", 3 | "importer": "effect", 4 | "imported": true, 5 | "uuid": "38da03f3-3e4d-4b86-81d0-27975d38a645", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /materials/builtin/standard.mtl: -------------------------------------------------------------------------------- 1 | { 2 | "__type__": "cc.Material", 3 | "_name": "", 4 | "_objFlags": 0, 5 | "_native": "", 6 | "_effectAsset": { 7 | "__uuid__": "38da03f3-3e4d-4b86-81d0-27975d38a645" 8 | }, 9 | "_techIdx": 0, 10 | "_defines": [ 11 | {}, 12 | {}, 13 | {} 14 | ], 15 | "_states": [ 16 | { 17 | "blendState": { 18 | "targets": [ 19 | {} 20 | ] 21 | }, 22 | "depthStencilState": {}, 23 | "rasterizerState": {} 24 | }, 25 | { 26 | "blendState": { 27 | "targets": [ 28 | {} 29 | ] 30 | }, 31 | "depthStencilState": {}, 32 | "rasterizerState": {} 33 | }, 34 | { 35 | "blendState": { 36 | "targets": [ 37 | {} 38 | ] 39 | }, 40 | "depthStencilState": {}, 41 | "rasterizerState": {} 42 | } 43 | ], 44 | "_props": [ 45 | {}, 46 | {}, 47 | {} 48 | ] 49 | } -------------------------------------------------------------------------------- /materials/builtin/standard.mtl.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.9", 3 | "importer": "material", 4 | "imported": true, 5 | "uuid": "169a9bf5-bcf5-4ed7-9203-0d961e530574", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /materials/builtin/terrain.effect: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd. 2 | CCEffect %{ 3 | techniques: 4 | - name: opaque 5 | passes: 6 | - vert: terrain-vs:vert 7 | frag: terrain-fs:frag 8 | properties: &props 9 | UVScale: { value: [1, 1, 1, 1] } 10 | lightMapUVParam: { value: [0, 0, 0, 0] } 11 | weightMap: { value: black } 12 | detailMap0: { value: grey } 13 | detailMap1: { value: grey } 14 | detailMap2: { value: grey } 15 | detailMap3: { value: grey } 16 | lightMap: { value: grey } 17 | - vert: terrain-vs:vert 18 | frag: terrain-fs:frag 19 | phase: forward-add 20 | propertyIndex: 0 21 | embeddedMacros: { CC_FORWARD_ADD: true } 22 | depthStencilState: 23 | depthFunc: equal 24 | depthTest: true 25 | depthWrite: false 26 | blendState: 27 | targets: 28 | - blend: true 29 | blendSrc: one 30 | blendDst: one 31 | blendSrcAlpha: zero 32 | blendDstAlpha: one 33 | properties: *props 34 | - vert: depth-buffer-vs:vert 35 | frag: depth-buffer-fs:frag 36 | phase: depth-buffer 37 | propertyIndex: 0 38 | rasterizerState: 39 | cullMode: front 40 | }% 41 | 42 | CCProgram terrain-vs %{ 43 | precision mediump float; 44 | #include 45 | #include 46 | #include 47 | #include 48 | 49 | in vec3 a_position; 50 | in vec3 a_normal; 51 | in vec2 a_texCoord; 52 | 53 | out highp vec3 v_position; 54 | out mediump vec3 v_normal; 55 | #if USE_NORMALMAP 56 | out mediump vec3 v_tangent; 57 | out mediump vec3 v_binormal; 58 | #endif 59 | out mediump vec2 uvw; 60 | out mediump vec2 uv0; 61 | out mediump vec2 uv1; 62 | out mediump vec2 uv2; 63 | out mediump vec2 uv3; 64 | out mediump vec2 luv; 65 | out mediump vec3 diffuse; 66 | out mediump float v_fog_factor; 67 | 68 | uniform TexCoords { 69 | vec4 UVScale; 70 | vec4 lightMapUVParam; 71 | }; 72 | 73 | vec4 vert () { 74 | vec3 worldPos; 75 | worldPos.x = cc_matWorld[3][0] + a_position.x; 76 | worldPos.y = cc_matWorld[3][1] + a_position.y; 77 | worldPos.z = cc_matWorld[3][2] + a_position.z; 78 | 79 | vec4 pos = vec4(worldPos, 1.0); 80 | pos = cc_matViewProj * pos; 81 | 82 | uvw = a_texCoord; 83 | uv0 = a_position.xz * UVScale.x; 84 | uv1 = a_position.xz * UVScale.y; 85 | uv2 = a_position.xz * UVScale.z; 86 | uv3 = a_position.xz * UVScale.w; 87 | #if USE_LIGHTMAP 88 | luv = lightMapUVParam.xy + a_texCoord * lightMapUVParam.zw; 89 | #endif 90 | 91 | v_position = worldPos; 92 | v_normal = a_normal; 93 | v_fog_factor = CC_TRANSFER_FOG(vec4(worldPos, 1.0)); 94 | 95 | #if USE_NORMALMAP 96 | v_tangent = vec3(1.0, 0.0, 0.0); 97 | v_binormal = vec3(0.0, 0.0, 1.0); 98 | 99 | v_binormal = cross(v_tangent, a_normal); 100 | v_tangent = cross(a_normal, v_binormal); 101 | #endif 102 | 103 | CCPassShadowParams(vec4(worldPos, 1.0)); 104 | 105 | return pos; 106 | } 107 | }% 108 | 109 | CCProgram terrain-fs %{ 110 | precision highp float; 111 | #include 112 | #include 113 | #include 114 | #include 115 | #include 116 | #pragma define LAYERS range([0, 4]) 117 | 118 | in highp vec3 v_position; 119 | in mediump vec3 v_normal; 120 | #if USE_NORMALMAP 121 | in mediump vec3 v_tangent; 122 | in mediump vec3 v_binormal; 123 | #endif 124 | in mediump vec2 uvw; 125 | in mediump vec2 uv0; 126 | in mediump vec2 uv1; 127 | in mediump vec2 uv2; 128 | in mediump vec2 uv3; 129 | in mediump vec3 diffuse; 130 | in mediump vec2 luv; 131 | in mediump float v_fog_factor; 132 | 133 | uniform PbrParams { 134 | vec4 metallic; 135 | vec4 roughness; 136 | }; 137 | 138 | uniform sampler2D weightMap; 139 | uniform sampler2D detailMap0; 140 | uniform sampler2D detailMap1; 141 | uniform sampler2D detailMap2; 142 | uniform sampler2D detailMap3; 143 | uniform sampler2D normalMap0; 144 | uniform sampler2D normalMap1; 145 | uniform sampler2D normalMap2; 146 | uniform sampler2D normalMap3; 147 | uniform sampler2D lightMap; 148 | 149 | void surf (out StandardSurface s) { 150 | #if LAYERS > 1 151 | vec4 w = texture(weightMap, uvw); 152 | #endif 153 | 154 | vec4 baseColor = vec4(0, 0, 0, 0); 155 | #if LAYERS == 1 156 | baseColor = texture(detailMap0, uv0); 157 | #elif LAYERS == 2 158 | baseColor += texture(detailMap0, uv0) * w.r; 159 | baseColor += texture(detailMap1, uv1) * w.g; 160 | #elif LAYERS == 3 161 | baseColor += texture(detailMap0, uv0) * w.r; 162 | baseColor += texture(detailMap1, uv1) * w.g; 163 | baseColor += texture(detailMap2, uv2) * w.b; 164 | #elif LAYERS == 4 165 | baseColor += texture(detailMap0, uv0) * w.r; 166 | baseColor += texture(detailMap1, uv1) * w.g; 167 | baseColor += texture(detailMap2, uv2) * w.b; 168 | baseColor += texture(detailMap3, uv3) * w.a; 169 | #else 170 | baseColor = texture(detailMap0, uv0); 171 | #endif 172 | 173 | s.position = v_position; 174 | #if USE_NORMALMAP 175 | vec4 baseNormal = vec4(0, 0, 0, 0); 176 | #if LAYERS == 1 177 | baseNormal = texture(normalMap0, uv0); 178 | #elif LAYERS == 2 179 | baseNormal += texture(normalMap0, uv0) * w.r; 180 | baseNormal += texture(normalMap1, uv1) * w.g; 181 | #elif LAYERS == 3 182 | baseNormal += texture(normalMap0, uv0) * w.r; 183 | baseNormal += texture(normalMap1, uv1) * w.g; 184 | baseNormal += texture(normalMap2, uv2) * w.b; 185 | #elif LAYERS == 4 186 | baseNormal += texture(normalMap0, uv0) * w.r; 187 | baseNormal += texture(normalMap1, uv1) * w.g; 188 | baseNormal += texture(normalMap2, uv2) * w.b; 189 | baseNormal += texture(normalMap3, uv3) * w.a; 190 | #else 191 | baseNormal = texture(normalMap0, uv0); 192 | #endif 193 | 194 | vec3 nmmp = baseNormal.xyz - vec3(0.5); 195 | s.normal = 196 | nmmp.x * normalize(v_tangent) + 197 | nmmp.y * normalize(v_binormal) + 198 | nmmp.z * normalize(v_normal); 199 | #else 200 | s.normal = v_normal; 201 | #endif 202 | 203 | s.albedo = vec4(SRGBToLinear(baseColor.rgb), 1.0); 204 | s.occlusion = 1.0; 205 | #if USE_PBR 206 | s.roughness = 0.0; 207 | #if LAYERS == 1 208 | s.roughness = roughness.x; 209 | #elif LAYERS == 2 210 | s.roughness += roughness.x * w.r; 211 | s.roughness += roughness.y * w.g; 212 | #elif LAYERS == 3 213 | s.roughness += roughness.x * w.r; 214 | s.roughness += roughness.y * w.g; 215 | s.roughness += roughness.z * w.b; 216 | #elif LAYERS == 4 217 | s.roughness += roughness.x * w.r; 218 | s.roughness += roughness.y * w.g; 219 | s.roughness += roughness.z * w.b; 220 | s.roughness += roughness.w * w.a; 221 | #else 222 | s.roughness = 1.0; 223 | #endif 224 | 225 | s.metallic = 0.0; 226 | #if LAYERS == 1 227 | s.metallic = metallic.x; 228 | #elif LAYERS == 2 229 | s.metallic += metallic.x * w.r; 230 | s.metallic += metallic.y * w.g; 231 | #elif LAYERS == 3 232 | s.metallic += metallic.x * w.r; 233 | s.metallic += metallic.y * w.g; 234 | s.metallic += metallic.z * w.b; 235 | #elif LAYERS == 4 236 | s.metallic += metallic.x * w.r; 237 | s.metallic += metallic.y * w.g; 238 | s.metallic += metallic.z * w.b; 239 | s.metallic += metallic.w * w.a; 240 | #else 241 | s.metallic = 0.0; 242 | #endif 243 | #else 244 | s.roughness = 1.0; 245 | s.metallic = 0.0; 246 | #endif 247 | s.emissive = vec3(0.0, 0.0, 0.0); 248 | 249 | #if USE_LIGHTMAP && !USE_BATCHING && !CC_FORWARD_ADD 250 | s.lightmap = texture(lightMap, luv); 251 | #else 252 | s.lightmap = vec4(0.0, 0.0, 0.0, 0.0); 253 | #endif 254 | } 255 | 256 | vec4 frag () { 257 | StandardSurface s; surf(s); 258 | vec4 color = CCStandardShading(s); 259 | color = CC_APPLY_FOG(color, v_fog_factor); 260 | return CCFragOutput(color); 261 | } 262 | }% 263 | 264 | CCProgram depth-buffer-vs %{ 265 | precision highp float; 266 | #include 267 | #include 268 | #include 269 | 270 | #include <../chunks/ubo-custom-common> 271 | 272 | in vec3 a_position; 273 | in vec3 a_normal; 274 | 275 | out float v_clip_depth; 276 | 277 | vec4 vert () { 278 | vec4 worldPos; 279 | worldPos.x = cc_matWorld[3][0] + a_position.x; 280 | worldPos.y = cc_matWorld[3][1] + a_position.y; 281 | worldPos.z = cc_matWorld[3][2] + a_position.z; 282 | worldPos.w = 1.0; 283 | 284 | vec4 viewPos = cc_matView * worldPos; 285 | 286 | v_clip_depth = -viewPos.z / cc_projection_params.y; 287 | 288 | return cc_matProj * viewPos; 289 | } 290 | }% 291 | 292 | CCProgram depth-buffer-fs %{ 293 | precision highp float; 294 | #include 295 | 296 | in float v_clip_depth; 297 | 298 | vec4 frag () { 299 | return packDepthToRGBA(v_clip_depth); 300 | } 301 | }% 302 | -------------------------------------------------------------------------------- /materials/builtin/terrain.effect.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.4.4", 3 | "importer": "effect", 4 | "imported": true, 5 | "uuid": "c4637090-842c-46b9-93b9-8c12924ce87b", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /materials/builtin/unlit-cast-shadow.effect: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd. 2 | CCEffect %{ 3 | techniques: 4 | - name: opaque 5 | passes: 6 | - vert: unlit-vs:vert 7 | frag: unlit-fs:frag 8 | properties: &props 9 | mainTexture: { value: grey } 10 | tilingOffset: { value: [1, 1, 0, 0] } 11 | mainColor: { value: [1, 1, 1, 1], editor: { type: color } } 12 | colorScale: { value: [1, 1, 1], target: colorScaleAndCutoff.xyz } 13 | alphaThreshold: { value: 0.5, target: colorScaleAndCutoff.w, editor: { parent: USE_ALPHA_TEST } } 14 | color: { target: mainColor, editor: { visible: false } } # backward compability 15 | migrations: &migs 16 | properties: 17 | mainColor: { formerlySerializedAs: color } 18 | - vert: shadow-caster-vs:vert 19 | frag: shadow-caster-fs:frag 20 | phase: shadow-caster 21 | propertyIndex: 0 22 | rasterizerState: 23 | cullMode: back 24 | - name: transparent 25 | passes: 26 | - vert: unlit-vs:vert 27 | frag: unlit-fs:frag 28 | depthStencilState: &d1 29 | depthTest: true 30 | depthWrite: false 31 | blendState: 32 | targets: 33 | - blend: true 34 | blendSrc: src_alpha 35 | blendDst: one_minus_src_alpha 36 | blendDstAlpha: one_minus_src_alpha 37 | properties: *props 38 | migrations: *migs 39 | - vert: shadow-caster-vs:vert 40 | frag: shadow-caster-fs:frag 41 | phase: shadow-caster 42 | propertyIndex: 0 43 | rasterizerState: 44 | cullMode: back 45 | - name: add 46 | passes: 47 | - vert: unlit-vs:vert 48 | frag: unlit-fs:frag 49 | rasterizerState: &r1 { cullMode: none } 50 | depthStencilState: *d1 51 | blendState: 52 | targets: 53 | - blend: true 54 | blendSrc: src_alpha 55 | blendDst: one 56 | blendSrcAlpha: src_alpha 57 | blendDstAlpha: one 58 | properties: *props 59 | migrations: *migs 60 | - name: alpha-blend 61 | passes: 62 | - vert: unlit-vs:vert 63 | frag: unlit-fs:frag 64 | rasterizerState: *r1 65 | depthStencilState: *d1 66 | blendState: 67 | targets: 68 | - blend: true 69 | blendSrc: src_alpha 70 | blendDst: one_minus_src_alpha 71 | blendSrcAlpha: src_alpha 72 | blendDstAlpha: one_minus_src_alpha 73 | properties: *props 74 | migrations: *migs 75 | }% 76 | 77 | CCProgram shared-ubos %{ 78 | #if USE_TEXTURE 79 | uniform TexCoords { 80 | vec4 tilingOffset; 81 | }; 82 | 83 | uniform sampler2D mainTexture; 84 | #endif 85 | 86 | uniform Constant { 87 | vec4 mainColor; 88 | vec4 colorScaleAndCutoff; 89 | }; 90 | }% 91 | 92 | CCProgram unlit-vs %{ 93 | precision highp float; 94 | #include 95 | #include 96 | #include 97 | #include 98 | #include 99 | #include 100 | 101 | #if USE_VERTEX_COLOR 102 | in lowp vec4 a_color; 103 | out lowp vec4 v_color; 104 | #endif 105 | 106 | #if USE_TEXTURE 107 | out vec2 v_uv; 108 | 109 | #endif 110 | out float factor_fog; 111 | vec4 vert () { 112 | vec4 position; 113 | CCVertInput(position); 114 | 115 | mat4 matWorld; 116 | CCGetWorldMatrix(matWorld); 117 | 118 | #if USE_TEXTURE 119 | v_uv = a_texCoord * tilingOffset.xy + tilingOffset.zw; 120 | #endif 121 | 122 | #if USE_VERTEX_COLOR 123 | v_color = a_color; 124 | #endif 125 | factor_fog = CC_TRANSFER_FOG(matWorld * position); 126 | return cc_matProj * (cc_matView * matWorld) * position; 127 | } 128 | }% 129 | 130 | CCProgram unlit-fs %{ 131 | precision highp float; 132 | #include 133 | #include 134 | #include 135 | 136 | #if USE_ALPHA_TEST 137 | #pragma define ALPHA_TEST_CHANNEL options([a, r, g, b]) 138 | #endif 139 | 140 | #if USE_TEXTURE 141 | in vec2 v_uv; 142 | #endif 143 | 144 | 145 | #if USE_VERTEX_COLOR 146 | in lowp vec4 v_color; 147 | #endif 148 | in float factor_fog; 149 | vec4 frag () { 150 | vec4 o = mainColor; 151 | o.rgb *= colorScaleAndCutoff.xyz; 152 | 153 | #if USE_VERTEX_COLOR 154 | o *= v_color; 155 | #endif 156 | 157 | #if USE_TEXTURE 158 | o *= texture(mainTexture, v_uv); 159 | #endif 160 | 161 | #if USE_ALPHA_TEST 162 | if (o.ALPHA_TEST_CHANNEL < colorScaleAndCutoff.w) discard; 163 | #endif 164 | o = CC_APPLY_FOG(o, factor_fog); 165 | return CCFragOutput(o); 166 | } 167 | }% 168 | 169 | 170 | CCProgram shadow-caster-vs %{ 171 | precision highp float; 172 | #include 173 | #include 174 | #include 175 | #include 176 | 177 | #if HAS_SECOND_UV || USE_LIGHTMAP 178 | in vec2 a_texCoord1; 179 | #endif 180 | 181 | out vec2 v_uv; 182 | out vec2 v_uv1; 183 | 184 | out vec2 v_clip_depth; 185 | 186 | vec4 vert () { 187 | StandardVertInput In; 188 | CCVertInput(In); 189 | 190 | mat4 matWorld, matWorldIT; 191 | CCGetWorldMatrixFull(matWorld, matWorldIT); 192 | 193 | vec4 worldPos = matWorld * In.position; 194 | vec4 clipPos = cc_matLightViewProj * worldPos; 195 | 196 | #if USE_TEXTURE 197 | v_uv = a_texCoord * tilingOffset.xy + tilingOffset.zw; 198 | #endif 199 | 200 | v_clip_depth = clipPos.zw; 201 | 202 | return clipPos; 203 | } 204 | }% 205 | 206 | CCProgram shadow-caster-fs %{ 207 | precision highp float; 208 | #include 209 | #include 210 | 211 | in vec2 v_uv; 212 | in vec2 v_clip_depth; 213 | 214 | #if USE_ALPHA_TEST 215 | #pragma define ALPHA_TEST_CHANNEL options([a, r]) 216 | #endif 217 | 218 | vec4 frag () { 219 | vec4 baseColor = vec4(1.); 220 | 221 | #if USE_TEXTURE 222 | baseColor *= texture(mainTexture, v_uv); 223 | #endif 224 | 225 | #if USE_ALPHA_TEST 226 | if (baseColor.ALPHA_TEST_CHANNEL < colorScaleAndCutoff.w) discard; 227 | #endif 228 | 229 | return packDepthToRGBA(v_clip_depth.x / v_clip_depth.y * 0.5 + 0.5); 230 | } 231 | }% 232 | -------------------------------------------------------------------------------- /materials/builtin/unlit-cast-shadow.effect.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.4.4", 3 | "importer": "effect", 4 | "imported": true, 5 | "uuid": "37298cca-e82c-440c-90b0-a9d5135ae4a8", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /materials/builtin/unlit-cast-shadow.mtl: -------------------------------------------------------------------------------- 1 | { 2 | "__type__": "cc.Material", 3 | "_name": "", 4 | "_objFlags": 0, 5 | "_native": "", 6 | "_effectAsset": { 7 | "__uuid__": "37298cca-e82c-440c-90b0-a9d5135ae4a8" 8 | }, 9 | "_techIdx": 0, 10 | "_defines": [ 11 | {}, 12 | {} 13 | ], 14 | "_states": [ 15 | { 16 | "blendState": { 17 | "targets": [ 18 | {} 19 | ] 20 | }, 21 | "depthStencilState": {}, 22 | "rasterizerState": {} 23 | }, 24 | { 25 | "blendState": { 26 | "targets": [ 27 | {} 28 | ] 29 | }, 30 | "depthStencilState": {}, 31 | "rasterizerState": {} 32 | } 33 | ], 34 | "_props": [ 35 | {}, 36 | {} 37 | ] 38 | } -------------------------------------------------------------------------------- /materials/builtin/unlit-cast-shadow.mtl.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.9", 3 | "importer": "material", 4 | "imported": true, 5 | "uuid": "d0c5d7b3-464b-4fb5-b227-a881666932ef", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /materials/chunks.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.1.0", 3 | "importer": "directory", 4 | "imported": true, 5 | "uuid": "7b3f4c8a-55a8-40f6-9389-937725621b46", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "compressionType": {}, 10 | "isRemoteBundle": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /materials/chunks/phong.chunk: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | struct LightInfo { 5 | vec3 lightDir; 6 | vec3 radiance; 7 | vec3 lightColor; 8 | float attenuation; 9 | }; 10 | 11 | // directional light 12 | LightInfo computeDirectionalLighting( 13 | vec3 lightDirection, 14 | vec3 lightColor 15 | ) { 16 | LightInfo ret; 17 | ret.lightDir = -normalize(lightDirection); 18 | ret.radiance = lightColor; 19 | ret.lightColor = lightColor; 20 | ret.attenuation = 1.; 21 | return ret; 22 | } 23 | 24 | // point light 25 | LightInfo computePointLighting( 26 | vec3 worldPosition, 27 | vec3 lightPosition, 28 | float radius, 29 | float range, 30 | vec3 lightColor 31 | ) { 32 | vec3 lightDir = lightPosition - worldPosition; 33 | 34 | // #if USE_FAKE_POINT_LIGHT 35 | // float attenuation = 1.; 36 | // #else 37 | float attenuation = max(0., 1.0 - length(lightDir) / range); 38 | // #endif 39 | 40 | LightInfo ret; 41 | ret.lightDir = normalize(lightDir); 42 | ret.radiance = lightColor.rgb * attenuation; 43 | ret.lightColor = lightColor; 44 | ret.attenuation = attenuation; 45 | 46 | return ret; 47 | } 48 | 49 | // spot light 50 | LightInfo computeSpotLighting( 51 | vec3 worldPosition, 52 | vec4 lightPositionAndRange, 53 | vec4 lightDirection, 54 | vec3 lightColor 55 | ) { 56 | vec3 lightDir = lightPositionAndRange.xyz - worldPosition; 57 | float attenuation = max(0., 1.0 - length(lightDir) / lightPositionAndRange.w); 58 | lightDir = normalize(lightDir); 59 | float cosConeAngle = max(0., dot(lightDirection.xyz, -lightDir)); 60 | cosConeAngle = cosConeAngle < lightDirection.w ? 0. : cosConeAngle; 61 | cosConeAngle = pow(cosConeAngle, lightColor.w); 62 | 63 | LightInfo ret; 64 | ret.lightDir = lightDir; 65 | ret.radiance = lightColor.rgb * attenuation * cosConeAngle; 66 | ret.lightColor = lightColor; 67 | ret.attenuation = attenuation; 68 | 69 | return ret; 70 | } 71 | 72 | 73 | struct PhongSurface { 74 | vec3 diffuse; 75 | vec3 emissive; 76 | vec3 specular; 77 | float opacity; 78 | 79 | float glossiness; 80 | 81 | vec3 position; 82 | vec3 normal; 83 | vec3 viewDirection; 84 | }; 85 | 86 | struct Lighting { 87 | vec3 diffuse; 88 | vec3 specular; 89 | }; 90 | 91 | Lighting brdf (PhongSurface s, LightInfo info) { 92 | float glossiness = s.glossiness; 93 | 94 | Lighting result; 95 | float ndh = 0.0; 96 | // Get the half direction in world space 97 | vec3 halfDir = normalize(s.viewDirection + info.lightDir); 98 | float NdotH = max(0.0, dot(s.normal, halfDir)); 99 | NdotH = pow(NdotH, max(1.0, glossiness)); 100 | 101 | result.diffuse = info.radiance * max(0.001, dot(s.normal, info.lightDir)); 102 | 103 | float specularNormalization = ( glossiness + 2.0 ) / 8.0; 104 | vec3 schlick = s.specular + vec3( 1.0 - s.specular ) * pow( max( 1.0 - dot( info.lightDir, halfDir ), 0.0 ), 5.0 ); 105 | result.specular = info.radiance * NdotH * specularNormalization * schlick; 106 | 107 | return result; 108 | } 109 | 110 | vec4 composePhongShading (Lighting lighting, PhongSurface s) { 111 | vec4 o = vec4(0.0, 0.0, 0.0, 1.0); 112 | 113 | //diffuse is always calculated 114 | o.rgb = lighting.diffuse * s.diffuse; 115 | 116 | o.rgb += s.emissive; 117 | o.rgb += lighting.specular * s.specular; 118 | 119 | o.a = s.opacity; 120 | 121 | return o; 122 | } 123 | 124 | vec4 CCPhongShading (in PhongSurface s) { 125 | Lighting result; 126 | result.diffuse = vec3(0.); 127 | result.specular = vec3(0.); 128 | 129 | LightInfo info = computeDirectionalLighting(cc_mainLitDir.xyz, cc_mainLitColor.rgb * cc_mainLitColor.w); 130 | Lighting res = brdf(s, info); 131 | 132 | result.diffuse += res.diffuse; 133 | result.specular += res.specular; 134 | 135 | // #if CC_FORWARD_ADD 136 | // for (int i = 0; i < LIGHTS_PER_PASS; i++) { 137 | // info = computePointLighting(s.position, cc_lightPos[i].xyz, cc_lightSizeRangeAngle[i].x, cc_lightSizeRangeAngle[i].y, cc_lightColor[i].rgb/* * cc_sphereLitColor[i].w*/); 138 | // res = brdf(s, info); 139 | 140 | // result.diffuse += res.diffuse; 141 | // result.specular += res.specular; 142 | // } 143 | // #endif 144 | 145 | vec4 color = composePhongShading(result, s); 146 | 147 | // #if USE_ENVMAP 148 | // vec3 reflectVec = reflect(-s.viewDirection, s.normal); 149 | // vec4 envColor = texCube( envMap, vec3( -1. * reflectVec.x, reflectVec.yz ) ); 150 | 151 | // float specularStrength = 1.; 152 | // color.rgb = mix( color.rgb, envColor.xyz, specularStrength * reflectivity ); 153 | // // color.rgb += envColor.xyz * specularStrength * reflectivity; 154 | // #endif 155 | 156 | return color; 157 | } 158 | -------------------------------------------------------------------------------- /materials/chunks/phong.chunk.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.0", 3 | "importer": "effect-header", 4 | "imported": true, 5 | "uuid": "976137e5-81da-450f-91c1-c652f3bb22db", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": {} 9 | } 10 | -------------------------------------------------------------------------------- /materials/chunks/ubo-custom-common.chunk: -------------------------------------------------------------------------------- 1 | 2 | #pragma builtin(global) 3 | layout(set = 0, binding = 5) uniform CCCustomCommon { 4 | vec4 cc_projection_params; // near, far, 1/near, 1/far 5 | }; 6 | -------------------------------------------------------------------------------- /materials/chunks/ubo-custom-common.chunk.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.0", 3 | "importer": "effect-header", 4 | "imported": true, 5 | "uuid": "29009a24-aaca-4fc4-9e53-92fd1c58d57f", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": {} 9 | } 10 | -------------------------------------------------------------------------------- /materials/grass.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.1.0", 3 | "importer": "directory", 4 | "imported": true, 5 | "uuid": "8e971aa0-c6db-42de-83bf-5b2816fd8f68", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "compressionType": {}, 10 | "isRemoteBundle": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /materials/grass/grass-bend.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.1.0", 3 | "importer": "directory", 4 | "imported": true, 5 | "uuid": "e7f7c41c-241e-43f5-80a2-795b39883677", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "compressionType": {}, 10 | "isRemoteBundle": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /materials/grass/grass-bend/debug-bend.mtl: -------------------------------------------------------------------------------- 1 | { 2 | "__type__": "cc.Material", 3 | "_name": "", 4 | "_objFlags": 0, 5 | "_native": "", 6 | "_effectAsset": { 7 | "__uuid__": "1baf0fc9-befa-459c-8bdd-af1a450a0319" 8 | }, 9 | "_techIdx": 1, 10 | "_defines": [ 11 | {}, 12 | {}, 13 | {} 14 | ], 15 | "_states": [ 16 | { 17 | "blendState": { 18 | "targets": [ 19 | {} 20 | ] 21 | }, 22 | "depthStencilState": {}, 23 | "rasterizerState": {} 24 | }, 25 | { 26 | "blendState": { 27 | "targets": [ 28 | {} 29 | ] 30 | }, 31 | "depthStencilState": {}, 32 | "rasterizerState": {} 33 | }, 34 | { 35 | "blendState": { 36 | "targets": [ 37 | {} 38 | ] 39 | }, 40 | "depthStencilState": {}, 41 | "rasterizerState": {} 42 | } 43 | ], 44 | "_props": [ 45 | { 46 | "mainColor": { 47 | "__type__": "cc.Color", 48 | "r": 255, 49 | "g": 255, 50 | "b": 255, 51 | "a": 51 52 | } 53 | }, 54 | {}, 55 | {} 56 | ] 57 | } -------------------------------------------------------------------------------- /materials/grass/grass-bend/debug-bend.mtl.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.9", 3 | "importer": "material", 4 | "imported": true, 5 | "uuid": "b27e49d4-fcca-4232-9693-ee1c47b387a9", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /materials/grass/grass-bend/grass-bend.effect: -------------------------------------------------------------------------------- 1 | // Effect Syntax Guide: https://github.com/cocos-creator/docs-3d/blob/master/zh/material-system/effect-syntax.md 2 | 3 | CCEffect %{ 4 | techniques: 5 | - name: opaque 6 | passes: 7 | - vert: grass-bend-vs:vert 8 | frag: grass-bend-fs:frag 9 | phase: grass-bend 10 | properties: &props 11 | boundScale: { value: 1, target: params.x } 12 | heightOffset: { value: 0, target: params.y } 13 | heightStrength: { value: 1, target: params.z } 14 | extendStrength: { value: 1, target: params.w } 15 | rasterizerState: 16 | cullMode: front 17 | }% 18 | 19 | CCProgram shared-ubo %{ 20 | uniform Params { 21 | vec4 params; 22 | }; 23 | }% 24 | 25 | CCProgram grass-bend-vs %{ 26 | 27 | precision highp float; 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | 35 | in vec3 a_color; 36 | 37 | out vec3 v_position; 38 | out vec3 v_normal; 39 | out vec2 v_uv; 40 | out vec3 v_color; 41 | 42 | vec4 vert () { 43 | StandardVertInput In; 44 | CCVertInput(In); 45 | 46 | mat4 matWorld, matWorldIT; 47 | CCGetWorldMatrixFull(matWorld, matWorldIT); 48 | 49 | vec4 lPos = In.position;; 50 | 51 | lPos.xyz *= params.x; 52 | 53 | vec4 wPos = matWorld * lPos; 54 | 55 | // v_color = a_color; 56 | v_position = wPos.xyz; 57 | v_normal = normalize((matWorldIT * vec4(In.normal, 0.0)).xyz); 58 | 59 | v_uv = a_texCoord; 60 | 61 | return cc_matProj * cc_matView * wPos; 62 | } 63 | 64 | }% 65 | 66 | CCProgram grass-bend-fs %{ 67 | precision highp float; 68 | 69 | #include 70 | 71 | in vec2 v_uv; 72 | in vec3 v_normal; 73 | in vec3 v_position; 74 | // in vec3 v_color; 75 | 76 | vec4 frag () { 77 | //Bottom-facing normals 78 | float mask = -v_normal.y * params.z;// * v_color.r; 79 | 80 | float height = ((v_position.y) + params.y); 81 | vec2 dir = (v_normal.xz * params.w) * 0.5 + 0.5; 82 | 83 | return vec4(dir.x, height, dir.y, mask); 84 | } 85 | }% 86 | -------------------------------------------------------------------------------- /materials/grass/grass-bend/grass-bend.effect.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.4.4", 3 | "importer": "effect", 4 | "imported": true, 5 | "uuid": "229a7b5e-5a6c-43a1-bbe2-cd9c1d10a1f8", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /materials/grass/grass-bend/grass-bend.mtl: -------------------------------------------------------------------------------- 1 | { 2 | "__type__": "cc.Material", 3 | "_name": "", 4 | "_objFlags": 0, 5 | "_native": "", 6 | "_effectAsset": { 7 | "__uuid__": "229a7b5e-5a6c-43a1-bbe2-cd9c1d10a1f8" 8 | }, 9 | "_techIdx": 0, 10 | "_defines": [ 11 | {} 12 | ], 13 | "_states": [ 14 | { 15 | "blendState": { 16 | "targets": [ 17 | {} 18 | ] 19 | }, 20 | "depthStencilState": {}, 21 | "rasterizerState": {} 22 | } 23 | ], 24 | "_props": [ 25 | { 26 | "boundScale": 1.2, 27 | "heightOffset": -0.2 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /materials/grass/grass-bend/grass-bend.mtl.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.9", 3 | "importer": "material", 4 | "imported": true, 5 | "uuid": "f0835bbd-0ebb-4cde-a698-137cbcf146fe", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /materials/grass/grass.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.1.0", 3 | "importer": "directory", 4 | "imported": true, 5 | "uuid": "f0ba0624-8378-45ba-a0fc-6cb78a12151d", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "compressionType": {}, 10 | "isRemoteBundle": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /materials/grass/grass/bend.chunk: -------------------------------------------------------------------------------- 1 | 2 | #pragma builtin(global) 3 | layout(set = 0, binding = 6) uniform sampler2D cc_grass_bend_map; 4 | 5 | #pragma builtin(global) 6 | layout(set = 0, binding = 4) uniform CCGrassBend { 7 | vec4 cc_grass_bend_uv; 8 | }; 9 | 10 | uniform Bend { 11 | float bendPushStrength; 12 | float bendFlattenStrength; 13 | float bendPerspectiveCorrection; 14 | }; 15 | 16 | 17 | struct BendSettings 18 | { 19 | int mode; 20 | float mask; 21 | float pushStrength; 22 | float flattenStrength; 23 | float perspectiveCorrection; 24 | }; 25 | 26 | //Bend map UV 27 | vec2 getBendMapUV(in vec3 wPos) { 28 | vec2 uv = (wPos.xz - cc_grass_bend_uv.xy) / cc_grass_bend_uv.z + 0.5; 29 | return uv; 30 | } 31 | 32 | vec4 getBendVector(vec3 wPos) { 33 | if (cc_grass_bend_uv.w == 0.) { 34 | return vec4(0.5, wPos.y, 0.5, 0.0); 35 | } 36 | 37 | vec2 uv = getBendMapUV(wPos); 38 | 39 | vec4 v = texture(cc_grass_bend_map, uv); 40 | 41 | //Remap from 0.1 to -1.1 42 | v.x = v.x * 2.0 - 1.0; 43 | v.z = v.z * 2.0 - 1.0; 44 | 45 | return v; 46 | } 47 | 48 | 49 | vec4 getBendOffset(vec3 wPos, BendSettings b) { 50 | vec4 vec = getBendVector(wPos); 51 | 52 | vec4 offset = vec4(wPos, vec.a); 53 | 54 | float grassHeight = wPos.y; 55 | float bendHeight = vec.y; 56 | float dist = grassHeight - bendHeight; 57 | 58 | float weight = clamp(dist, 0., 1.); 59 | 60 | offset.xz = vec.xz * b.mask * weight * b.pushStrength; 61 | offset.y = b.mask * (vec.a * 0.75) * weight * b.flattenStrength; 62 | 63 | float influence = 1.; 64 | 65 | //Pass the mask, so it can be used to lerp between wind and bend offset vectors 66 | offset.a = vec.a * weight * influence; 67 | 68 | //Apply mask 69 | offset.xyz *= offset.a; 70 | 71 | return offset; 72 | } 73 | -------------------------------------------------------------------------------- /materials/grass/grass/bend.chunk.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.0", 3 | "importer": "effect-header", 4 | "imported": true, 5 | "uuid": "e938fb7c-1946-494a-a249-71a819718fe4", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": {} 9 | } 10 | -------------------------------------------------------------------------------- /materials/grass/grass/color.chunk: -------------------------------------------------------------------------------- 1 | uniform Color { 2 | vec4 hueColor; 3 | float ambientOcclusion; 4 | float randomDarken; 5 | 6 | float translucency; 7 | }; 8 | 9 | //Single channel overlay 10 | float BlendOverlay(float a, float b) 11 | { 12 | return (b < 0.5) ? 2.0 * a * b : 1.0 - 2.0 * (1.0 - a) * (1.0 - b); 13 | } 14 | 15 | //RGB overlay 16 | vec3 BlendOverlay(vec3 a, vec3 b) 17 | { 18 | vec3 color; 19 | color.r = BlendOverlay(a.r, b.r); 20 | color.g = BlendOverlay(a.g, b.g); 21 | color.b = BlendOverlay(a.b, b.b); 22 | return color; 23 | } 24 | 25 | 26 | void Translucency(vec3 viewDirectionWS, float amount, float shadowAttenuation, inout vec3 color) { 27 | vec3 ld = normalize(cc_mainLitDir.xyz); 28 | float VdotL = max(0., dot(viewDirectionWS, ld)) * amount; 29 | 30 | //TODO: Incorperate size parameter 31 | VdotL = pow(VdotL, 4.) * 8.; 32 | 33 | //Translucency masked by shadows and grass mesh bottom 34 | float tMask = VdotL * shadowAttenuation;// * light.distanceAttenuation; 35 | 36 | //Fade the effect out as the sun approaches the horizon (75 to 90 degrees) 37 | // float sunAngle = dot(vec3(0., 1., 0.), ld); 38 | // float angleMask = clamp(sunAngle * 6.666, 0., 1.); /* 1.0/0.15 = 6.666 */ 39 | 40 | // tMask *= angleMask; 41 | 42 | vec3 tColor = color + BlendOverlay(cc_mainLitColor.rgb * cc_mainLitColor.w, color); 43 | 44 | color = mix(color, tColor, tMask); 45 | } 46 | 47 | 48 | //Shading (RGB=hue - A=brightness) 49 | vec4 applyVertexColor(in vec3 vertexPos, in vec3 wPos, in vec3 baseColor, in float mask, in float aoAmount, in float darkening, in vec4 hue, in float posOffset) 50 | { 51 | vec4 col = vec4(baseColor, 1.); 52 | 53 | //Apply hue 54 | col.rgb = mix(col.rgb, hue.rgb, posOffset * hue.a); 55 | //Apply darkening 56 | float rand = fract(vertexPos.r * 4.); 57 | 58 | float vertexDarkening = mix(col.a, col.a * rand, darkening * mask); //Only apply to top vertices 59 | //Apply ambient occlusion 60 | float ambientOcclusion = mix(col.a, col.a * mask, aoAmount); 61 | 62 | col.rgb *= vertexDarkening * ambientOcclusion; 63 | 64 | //Pass vertex color alpha-channel to fragment stage. Used in some shading functions such as translucency 65 | col.a = mask; 66 | 67 | return col; 68 | } -------------------------------------------------------------------------------- /materials/grass/grass/color.chunk.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.0", 3 | "importer": "effect-header", 4 | "imported": true, 5 | "uuid": "bd88d2e6-b7ac-4332-aa55-d91a0a2678bf", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": {} 9 | } 10 | -------------------------------------------------------------------------------- /materials/grass/grass/grass.effect: -------------------------------------------------------------------------------- 1 | // Effect Syntax Guide: https://github.com/cocos-creator/docs-3d/blob/master/zh/material-system/effect-syntax.md 2 | 3 | CCEffect %{ 4 | techniques: 5 | - name: opaque 6 | passes: 7 | - vert: vs:vert 8 | frag: fs:frag 9 | properties: &props 10 | alphaTest: { value: 0.5, target: params.x } 11 | shadowIntensity: { value: 0.4, target: params.y } 12 | 13 | randMap: { value: black } 14 | randMapTiling: { value: 1, target: params.z } 15 | 16 | windMap: { value: black } 17 | windDirection: { value: [1, 1] } 18 | windSpeed: { value: 4 } 19 | windStrength: { value: 0.2 } 20 | windSwinging: { value: 0.17 } 21 | windRandObject: { value: 1 } 22 | windRandVertex: { value: 1 } 23 | windRandObjectStrength: { value: 0.709 } 24 | windGustStrength: { value: 0.196 } 25 | windGustFrequency: { value: 2.27 } 26 | windGustTint: { value: 2.27 } 27 | 28 | bendPushStrength: { value: 1, editor: { parent: USE_BEND } } 29 | bendFlattenStrength: { value: 1, editor: { parent: USE_BEND } } 30 | bendPerspectiveCorrection: { value: 1, editor: { parent: USE_BEND } } 31 | 32 | mainTexture: { value: white, editor: { parent: USE_MAIN_TXTURE } } 33 | mainTiling: { value: [0, 0, 1, 1] } 34 | mainColor: { value: [1, 1, 1, 1], editor: { type: color } } 35 | mainColorScale: { value: [1, 1, 1, 1] } 36 | hueColor: { value: [1, 1, 1, 1], editor: { type: color } } 37 | ambientOcclusion: { value: 0.704 } 38 | randomDarken: { value: 0.287 } 39 | 40 | translucency: { value: 1 } 41 | fixedNormal: { value: [0.5, 0.5, 1, 1], editor: { parent: USE_FIXED_NORMAL } } 42 | - vert: shadow-caster-vs:vert 43 | frag: shadow-caster-fs:frag 44 | phase: shadow-caster 45 | propertyIndex: 0 46 | rasterizerState: 47 | cullMode: back 48 | properties: *props 49 | }% 50 | 51 | CCProgram shared-ubos %{ 52 | 53 | #if USE_MAIN_TXTURE 54 | uniform sampler2D mainTexture; 55 | #endif 56 | 57 | uniform Shared { 58 | vec4 mainColor; 59 | vec4 mainTiling; 60 | vec4 mainColorScale; 61 | vec4 fixedNormal; 62 | 63 | vec4 params; 64 | }; 65 | 66 | #include <./wind> 67 | #include <./color> 68 | 69 | #if USE_BEND 70 | #include <./bend> 71 | #endif 72 | 73 | }% 74 | 75 | CCProgram get-mask %{ 76 | float getMask () { 77 | #if Mask_Type == Mask_Channel_Color 78 | return a_color.r; 79 | #elif Mask_Type == Mask_Channel_Uv 80 | return 1. - a_texCoord.y; 81 | #else 82 | return 0.; 83 | #endif 84 | } 85 | }% 86 | 87 | CCProgram get-rand %{ 88 | #include 89 | 90 | uniform sampler2D randMap; 91 | 92 | float objectPosRand01(mat4 mat) { 93 | return fract(mat[3][0] + mat[3][1] + mat[3][2]); 94 | } 95 | 96 | float getRand (mat4 mat) { 97 | return objectPosRand01(mat); 98 | } 99 | 100 | float getRand (vec3 pos) { 101 | return texture(randMap, pos.xz * params.z).r; 102 | } 103 | 104 | }% 105 | 106 | CCProgram shared-funcs %{ 107 | #include 108 | 109 | #define Mask_Channel_Color 1 110 | #define Mask_Channel_Uv 2 111 | 112 | #pragma define Mask_Type options([Mask_Channel_Color, Mask_Channel_Uv]) 113 | 114 | #if USE_BEND 115 | BendSettings getBendSettings (float mask) { 116 | BendSettings s; 117 | s.mode = 0; 118 | s.mask = mask; 119 | s.pushStrength = bendPushStrength; 120 | s.flattenStrength = bendFlattenStrength; 121 | s.perspectiveCorrection = bendPerspectiveCorrection; 122 | return s; 123 | } 124 | #endif 125 | 126 | float randomRange (vec2 seed, float minv, float maxv) { 127 | float randomno = fract(sin(dot(seed, vec2(12.9898, 78.233)))*43758.5453); 128 | return mix(minv, maxv, randomno); 129 | } 130 | 131 | void calcGrassOffset (in vec4 lPos, inout vec4 wPos, float rand, float mask) { 132 | WindSettings w = getWinSettings(mask); 133 | vec4 windOffset = getWindOffset(lPos.xyz, wPos.xyz, rand, w, windMap); 134 | 135 | #if USE_BEND 136 | BendSettings b = getBendSettings(mask); 137 | vec4 bendOffset = getBendOffset(wPos.xyz, b); 138 | 139 | vec3 offsets = mix(windOffset.xyz, bendOffset.xyz, bendOffset.a).xyz; 140 | float bendCorrection = b.mask * b.perspectiveCorrection; 141 | #else 142 | vec3 offsets = windOffset.xyz; 143 | float bendCorrection = 1.; 144 | #endif 145 | 146 | vec3 viewDirectionWS = normalize(cc_cameraPos.xyz - wPos.xyz); 147 | float NdotV = dot(vec3(0, 1, 0), viewDirectionWS); 148 | 149 | //Avoid pushing grass straight underneath the camera in a falloff of 4 units (1/0.25) 150 | float dist = clamp(distance(wPos.xz, cc_cameraPos.xz) * 0.25, 0., 1.); 151 | 152 | //Push grass away from camera position 153 | vec2 pushVec = -viewDirectionWS.xz; 154 | float perspMask = bendCorrection * dist * NdotV; 155 | offsets.xz += pushVec.xy * perspMask; 156 | 157 | //Apply bend offset 158 | wPos.xz += offsets.xz; 159 | wPos.y -= offsets.y; 160 | } 161 | 162 | vec4 calcGrassVertexColor(in vec4 lPos, in vec4 wPos, float rand, float mask) { 163 | return applyVertexColor(lPos.xyz, wPos.xyz, mainColor.xyz * mainColorScale.xyz, mask, ambientOcclusion, randomDarken, hueColor, rand); 164 | } 165 | }% 166 | 167 | 168 | CCProgram vs %{ 169 | precision highp float; 170 | #include 171 | #include 172 | #include 173 | #include 174 | #include 175 | #include 176 | 177 | in vec3 a_color; 178 | 179 | #include 180 | #include 181 | 182 | #include 183 | #include 184 | 185 | out vec3 v_wPos; 186 | out vec2 v_uv; 187 | out vec4 v_color; 188 | out float factor_fog; 189 | 190 | #if !USE_FIXED_NORMAL 191 | out vec3 v_normal; 192 | #endif 193 | 194 | vec4 vert () { 195 | StandardVertInput In; 196 | CCVertInput(In); 197 | 198 | mat4 matWorld, matWorldIT; 199 | CCGetWorldMatrixFull(matWorld, matWorldIT); 200 | 201 | vec4 lPos = In.position; 202 | vec4 wPos = matWorld * lPos; 203 | 204 | float mask = getMask(); 205 | 206 | float rand = getRand(wPos.xyz); 207 | calcGrassOffset(lPos, wPos, rand, mask); 208 | 209 | v_color = calcGrassVertexColor(lPos, wPos, rand, mask); 210 | 211 | // debug mask 212 | // v_color = vec4(mask); 213 | 214 | // debug bend map 215 | // vec2 uv = getBendMapUV(wPos.xyz); 216 | // v_color = texture(cc_grass_bend_map, uv); 217 | 218 | v_wPos = wPos.xyz; 219 | 220 | #if !USE_FIXED_NORMAL 221 | v_normal = normalize((matWorldIT * vec4(In.normal, 0.0)).xyz); 222 | #endif 223 | 224 | v_uv = a_texCoord; 225 | factor_fog = CC_TRANSFER_FOG(wPos); 226 | 227 | CCPassShadowParams(wPos); 228 | 229 | return cc_matProj * cc_matView * wPos; 230 | } 231 | 232 | }% 233 | 234 | CCProgram fs %{ 235 | precision highp float; 236 | #include 237 | #include 238 | #include 239 | 240 | #if CC_RECEIVE_SHADOW 241 | #include 242 | #endif 243 | 244 | #include 245 | #include 246 | 247 | #include <../../chunks/phong> 248 | 249 | in vec2 v_uv; 250 | in vec4 v_color; 251 | in float factor_fog; 252 | 253 | in vec3 v_wPos; 254 | 255 | #if !USE_FIXED_NORMAL 256 | in vec3 v_normal; 257 | #endif 258 | 259 | float getShadowAttenuation () { 260 | float shadowAttenuation = 0.0; 261 | 262 | #if CC_RECEIVE_SHADOW 263 | float pcf = cc_shadowInfo.x + 0.001; 264 | if (pcf > 3.0) {shadowAttenuation = CCGetShadowFactorX25();} 265 | else if (3.0 > pcf && pcf > 2.0) {shadowAttenuation = CCGetShadowFactorX9();} 266 | else if (2.0 > pcf && pcf > 1.0) {shadowAttenuation = CCGetShadowFactorX5();} 267 | else {shadowAttenuation = CCGetShadowFactorX1();} 268 | #endif 269 | 270 | return shadowAttenuation; 271 | } 272 | 273 | vec4 frag () { 274 | #if USE_MAIN_TXTURE 275 | vec2 uv = mainTiling.xy + mainTiling.zw * v_uv; 276 | vec4 col = texture(mainTexture, uv); 277 | #else 278 | vec4 col = vec4(1.); 279 | #endif 280 | 281 | float alpha = col.a; 282 | vec3 albedo = col.rgb; 283 | 284 | if (alpha < params.x) { 285 | discard; 286 | } 287 | 288 | // apply vertex color 289 | albedo *= v_color.rgb; 290 | 291 | // shadow 292 | float shadowAttenuation = getShadowAttenuation(); 293 | shadowAttenuation = 1. - min(shadowAttenuation, params.y); 294 | 295 | // lighting 296 | vec3 viewDirection = normalize(cc_cameraPos.xyz - v_wPos); 297 | 298 | #if USE_LIGHT 299 | 300 | PhongSurface s; 301 | s.diffuse = albedo; 302 | s.specular = vec3(0.); 303 | s.emissive = vec3(0.); 304 | s.opacity = alpha; 305 | s.glossiness = 10.; 306 | s.position = v_wPos; 307 | 308 | #if USE_FIXED_NORMAL 309 | s.normal = fixedNormal.xyz; 310 | #else 311 | s.normal = v_normal; 312 | #endif 313 | 314 | s.viewDirection = viewDirection; 315 | 316 | vec4 final = CCPhongShading(s); 317 | final.rgb = final.rgb * shadowAttenuation; 318 | 319 | #else 320 | vec4 final = vec4(albedo * shadowAttenuation, alpha); 321 | #endif 322 | 323 | // translucency 324 | Translucency(viewDirection, translucency, shadowAttenuation, final.rgb); 325 | 326 | // wind gust color 327 | WindSettings wind = getWinSettings(v_color.r); 328 | wind.gustStrength = 1.; 329 | float gust = sampleGustMap(v_wPos, wind, windMap, 0.02, 2.); 330 | final += (gust * v_color.a * windGustTint); 331 | 332 | final = CC_APPLY_FOG(final, factor_fog); 333 | 334 | // debug 335 | // return vec4(s.normal, 1.); 336 | // return v_color; 337 | 338 | return final; 339 | } 340 | }% 341 | 342 | CCProgram shadow-caster-vs %{ 343 | precision highp float; 344 | #include 345 | #include 346 | #include 347 | 348 | in vec3 a_color; 349 | 350 | #include 351 | #include 352 | 353 | #include 354 | #include 355 | 356 | out vec2 v_uv; 357 | 358 | out vec2 v_clip_depth; 359 | 360 | vec4 vert () { 361 | StandardVertInput In; 362 | CCVertInput(In); 363 | 364 | mat4 matWorld, matWorldIT; 365 | CCGetWorldMatrixFull(matWorld, matWorldIT); 366 | 367 | vec4 lPos = In.position; 368 | vec4 wPos = matWorld * lPos; 369 | 370 | float mask = getMask(); 371 | 372 | float rand = getRand(wPos.xyz); 373 | calcGrassOffset(lPos, wPos, rand, mask); 374 | 375 | vec4 clipPos = cc_matLightViewProj * wPos; 376 | 377 | v_uv = a_texCoord; 378 | 379 | v_clip_depth = clipPos.zw; 380 | 381 | return clipPos; 382 | } 383 | }% 384 | 385 | CCProgram shadow-caster-fs %{ 386 | precision highp float; 387 | #include 388 | 389 | #include 390 | 391 | in vec2 v_uv; 392 | in vec2 v_clip_depth; 393 | 394 | 395 | vec4 frag () { 396 | #if USE_MAIN_TXTURE 397 | vec2 uv = mainTiling.xy + mainTiling.zw * v_uv; 398 | vec4 baseColor = texture(mainTexture, uv); 399 | #else 400 | vec4 baseColor = vec4(1.); 401 | #endif 402 | 403 | if (baseColor.a < params.x) discard; 404 | 405 | return packDepthToRGBA(v_clip_depth.x / v_clip_depth.y * 0.5 + 0.5); 406 | } 407 | }% 408 | -------------------------------------------------------------------------------- /materials/grass/grass/grass.effect.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.4.4", 3 | "importer": "effect", 4 | "imported": true, 5 | "uuid": "6344a1ee-c7fd-4789-be43-f6e278dd25f9", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /materials/grass/grass/wind.chunk: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | uniform sampler2D windMap; 4 | uniform Wind { 5 | vec2 windDirection; 6 | float windStrength; 7 | float windSpeed; 8 | float windSwinging; 9 | float windRandObject; 10 | float windRandVertex; 11 | float windRandObjectStrength; 12 | float windGustStrength; 13 | float windGustFrequency; 14 | float windGustTint; 15 | }; 16 | 17 | struct WindSettings 18 | { 19 | float mask; 20 | float ambientStrength; 21 | float speed; 22 | vec2 direction; 23 | float swinging; 24 | 25 | float randObject; 26 | float randVertex; 27 | float randObjectStrength; 28 | 29 | float gustStrength; 30 | float gustFrequency; 31 | }; 32 | 33 | WindSettings getWinSettings (float mask) { 34 | WindSettings s; 35 | 36 | s.ambientStrength = windStrength; 37 | s.speed = windSpeed; 38 | s.direction = windDirection; 39 | s.swinging = windSwinging; 40 | s.mask = mask; 41 | s.randObject = windRandObject; 42 | s.randVertex = windRandVertex; 43 | s.randObjectStrength = windRandObjectStrength; 44 | s.gustStrength = windGustStrength; 45 | s.gustFrequency = windGustFrequency; 46 | 47 | return s; 48 | } 49 | 50 | //World-align UV moving in wind direction 51 | vec2 getGustingUV(vec3 wPos, WindSettings s, float speed) { 52 | return (wPos.xz * s.gustFrequency * speed) + (cc_time.x * s.speed * s.gustFrequency * speed) * -s.direction.xy; 53 | } 54 | 55 | float sampleGustMap(vec3 wPos, WindSettings s, sampler2D windMap, float speed, float uvScale) { 56 | vec2 gustUV = getGustingUV(wPos, s, speed) * uvScale; 57 | float gust = texture(windMap, gustUV).r; 58 | 59 | gust *= s.gustStrength * s.mask; 60 | 61 | return gust; 62 | } 63 | 64 | vec4 getWindOffset (in vec3 positionOS, in vec3 wPos, float randOffset, WindSettings s, sampler2D windMap) { 65 | vec4 offset = vec4(0.); 66 | 67 | //Random offset per vertex 68 | float f = length(positionOS.xz) * s.randVertex; 69 | float strength = s.ambientStrength * 0.5 * mix(1., randOffset, s.randObjectStrength); 70 | //Combine 71 | float sine = sin(s.speed * (cc_time.x + (randOffset * s.randObject) + f)); 72 | //Remap from -1/1 to 0/1 73 | sine = mix(sine * 0.5 + 0.5, sine, s.swinging); 74 | 75 | //Apply gusting 76 | float gust = sampleGustMap(wPos, s, windMap, 0.01, 1.); 77 | 78 | //Scale sine 79 | sine = sine * s.mask * strength; 80 | 81 | //Mask by direction vector + gusting push 82 | offset.xz = vec2(sine + gust); 83 | 84 | //Summed offset strength 85 | float windWeight = length(offset.xz) + 0.0001; 86 | //Slightly negate the triangle-shape curve 87 | windWeight = pow(windWeight, 1.5); 88 | offset.y = windWeight * s.mask; 89 | 90 | //Wind strength in alpha 91 | offset.a = sine + gust; 92 | 93 | return offset; 94 | } 95 | -------------------------------------------------------------------------------- /materials/grass/grass/wind.chunk.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.0", 3 | "importer": "effect-header", 4 | "imported": true, 5 | "uuid": "3261e375-f5f5-49ce-9421-fff568c60b37", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": {} 9 | } 10 | -------------------------------------------------------------------------------- /materials/tests.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.1.0", 3 | "importer": "directory", 4 | "imported": true, 5 | "uuid": "6a4f4809-8b2a-4fc2-a9d0-5f774bc4048f", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "compressionType": {}, 10 | "isRemoteBundle": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /materials/tests/normal-color.effect: -------------------------------------------------------------------------------- 1 | // Effect Syntax Guide: https://github.com/cocos-creator/docs-3d/blob/master/zh/material-system/effect-syntax.md 2 | 3 | CCEffect %{ 4 | techniques: 5 | - name: opaque 6 | passes: 7 | - vert: vs:vert 8 | frag: fs:frag 9 | }% 10 | 11 | CCProgram vs %{ 12 | precision highp float; 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | out vec3 v_normal; 19 | 20 | vec4 vert () { 21 | StandardVertInput In; 22 | CCVertInput(In); 23 | 24 | mat4 matWorld, matWorldIT; 25 | CCGetWorldMatrixFull(matWorld, matWorldIT); 26 | 27 | v_normal = In.normal; 28 | 29 | return cc_matProj * cc_matView * matWorld * In.position; 30 | } 31 | 32 | }% 33 | 34 | CCProgram fs %{ 35 | precision highp float; 36 | #include 37 | 38 | in vec3 v_normal; 39 | 40 | vec4 frag () { 41 | return vec4(v_normal, 1.); 42 | } 43 | }% 44 | -------------------------------------------------------------------------------- /materials/tests/normal-color.effect.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.4.4", 3 | "importer": "effect", 4 | "imported": true, 5 | "uuid": "67dddedd-cffb-4815-885c-e660b36ce7d1", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /materials/tests/normal-color.mtl: -------------------------------------------------------------------------------- 1 | { 2 | "__type__": "cc.Material", 3 | "_name": "", 4 | "_objFlags": 0, 5 | "_native": "", 6 | "_effectAsset": { 7 | "__uuid__": "67dddedd-cffb-4815-885c-e660b36ce7d1" 8 | }, 9 | "_techIdx": 0, 10 | "_defines": [ 11 | {} 12 | ], 13 | "_states": [ 14 | { 15 | "blendState": { 16 | "targets": [ 17 | {} 18 | ] 19 | }, 20 | "depthStencilState": {}, 21 | "rasterizerState": {} 22 | } 23 | ], 24 | "_props": [ 25 | {} 26 | ] 27 | } -------------------------------------------------------------------------------- /materials/tests/normal-color.mtl.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.9", 3 | "importer": "material", 4 | "imported": true, 5 | "uuid": "6515853e-341b-4174-8c15-cf17f1a42196", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /materials/tests/vertex-color.effect: -------------------------------------------------------------------------------- 1 | // Effect Syntax Guide: https://github.com/cocos-creator/docs-3d/blob/master/zh/material-system/effect-syntax.md 2 | 3 | CCEffect %{ 4 | techniques: 5 | - name: opaque 6 | passes: 7 | - vert: vs:vert 8 | frag: fs:frag 9 | }% 10 | 11 | CCProgram vs %{ 12 | precision highp float; 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | in vec3 a_color; 19 | out vec3 v_color; 20 | 21 | vec4 vert () { 22 | StandardVertInput In; 23 | CCVertInput(In); 24 | 25 | mat4 matWorld, matWorldIT; 26 | CCGetWorldMatrixFull(matWorld, matWorldIT); 27 | 28 | v_color = a_color; 29 | 30 | return cc_matProj * cc_matView * matWorld * In.position; 31 | } 32 | 33 | }% 34 | 35 | CCProgram fs %{ 36 | precision highp float; 37 | #include 38 | 39 | in vec3 v_color; 40 | 41 | vec4 frag () { 42 | return vec4(v_color, 1.); 43 | } 44 | }% 45 | -------------------------------------------------------------------------------- /materials/tests/vertex-color.effect.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.4.4", 3 | "importer": "effect", 4 | "imported": true, 5 | "uuid": "dde629f0-f194-4bc7-83d5-69354e2960f0", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /materials/tests/vertex-color.mtl: -------------------------------------------------------------------------------- 1 | { 2 | "__type__": "cc.Material", 3 | "_name": "", 4 | "_objFlags": 0, 5 | "_native": "", 6 | "_effectAsset": { 7 | "__uuid__": "dde629f0-f194-4bc7-83d5-69354e2960f0" 8 | }, 9 | "_techIdx": 0, 10 | "_defines": [ 11 | {} 12 | ], 13 | "_states": [ 14 | { 15 | "blendState": { 16 | "targets": [ 17 | {} 18 | ] 19 | }, 20 | "depthStencilState": {}, 21 | "rasterizerState": {} 22 | } 23 | ], 24 | "_props": [ 25 | {} 26 | ] 27 | } -------------------------------------------------------------------------------- /materials/tests/vertex-color.mtl.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.9", 3 | "importer": "material", 4 | "imported": true, 5 | "uuid": "01aba3db-1bba-4645-a2be-375c09217470", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /materials/water.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.1.0", 3 | "importer": "directory", 4 | "imported": true, 5 | "uuid": "1e4ed836-7dbf-48ae-9577-bf6561d04bbc", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "compressionType": {}, 10 | "isRemoteBundle": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /materials/water/textures.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.1.0", 3 | "importer": "directory", 4 | "imported": true, 5 | "uuid": "b9d09ef4-317d-460e-960f-307b421e71f6", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "compressionType": {}, 10 | "isRemoteBundle": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /materials/water/textures/Caustics 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2youyou2/advanced-pipeline/20922aaadea7a85a35ddf809b857bdb0e60b6fed/materials/water/textures/Caustics 1.png -------------------------------------------------------------------------------- /materials/water/textures/Caustics 1.png.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.21", 3 | "importer": "image", 4 | "imported": true, 5 | "uuid": "04f9f064-9886-42a8-b856-4af0f3e3422a", 6 | "files": [ 7 | ".png", 8 | ".json" 9 | ], 10 | "subMetas": { 11 | "6c48a": { 12 | "importer": "texture", 13 | "uuid": "04f9f064-9886-42a8-b856-4af0f3e3422a@6c48a", 14 | "displayName": "Caustics 1", 15 | "id": "6c48a", 16 | "name": "texture", 17 | "ver": "1.0.20", 18 | "imported": true, 19 | "files": [ 20 | ".json" 21 | ], 22 | "subMetas": {}, 23 | "userData": { 24 | "wrapModeS": "repeat", 25 | "wrapModeT": "repeat", 26 | "minfilter": "linear", 27 | "magfilter": "linear", 28 | "mipfilter": "none", 29 | "premultiplyAlpha": false, 30 | "anisotropy": 1, 31 | "isUuid": true, 32 | "imageUuidOrDatabaseUri": "04f9f064-9886-42a8-b856-4af0f3e3422a" 33 | } 34 | } 35 | }, 36 | "userData": { 37 | "type": "texture", 38 | "redirect": "04f9f064-9886-42a8-b856-4af0f3e3422a@6c48a", 39 | "hasAlpha": false 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /materials/water/textures/Foam 4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2youyou2/advanced-pipeline/20922aaadea7a85a35ddf809b857bdb0e60b6fed/materials/water/textures/Foam 4.png -------------------------------------------------------------------------------- /materials/water/textures/Foam 4.png.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.21", 3 | "importer": "image", 4 | "imported": true, 5 | "uuid": "d353a211-064a-4253-ac5a-01cb7d8b3ad6", 6 | "files": [ 7 | ".png", 8 | ".json" 9 | ], 10 | "subMetas": { 11 | "6c48a": { 12 | "importer": "texture", 13 | "uuid": "d353a211-064a-4253-ac5a-01cb7d8b3ad6@6c48a", 14 | "displayName": "Foam 4", 15 | "id": "6c48a", 16 | "name": "texture", 17 | "ver": "1.0.20", 18 | "imported": true, 19 | "files": [ 20 | ".json" 21 | ], 22 | "subMetas": {}, 23 | "userData": { 24 | "wrapModeS": "repeat", 25 | "wrapModeT": "repeat", 26 | "minfilter": "linear", 27 | "magfilter": "linear", 28 | "mipfilter": "linear", 29 | "premultiplyAlpha": false, 30 | "anisotropy": 1, 31 | "isUuid": true, 32 | "imageUuidOrDatabaseUri": "d353a211-064a-4253-ac5a-01cb7d8b3ad6" 33 | } 34 | } 35 | }, 36 | "userData": { 37 | "type": "texture", 38 | "redirect": "d353a211-064a-4253-ac5a-01cb7d8b3ad6@6c48a", 39 | "hasAlpha": false 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /materials/water/textures/NormalMap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2youyou2/advanced-pipeline/20922aaadea7a85a35ddf809b857bdb0e60b6fed/materials/water/textures/NormalMap.png -------------------------------------------------------------------------------- /materials/water/textures/NormalMap.png.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.21", 3 | "importer": "image", 4 | "imported": true, 5 | "uuid": "82e9a463-dd11-4f1d-9cab-763ef20b9c22", 6 | "files": [ 7 | ".png", 8 | ".json" 9 | ], 10 | "subMetas": { 11 | "6c48a": { 12 | "importer": "texture", 13 | "uuid": "82e9a463-dd11-4f1d-9cab-763ef20b9c22@6c48a", 14 | "displayName": "NormalMap", 15 | "id": "6c48a", 16 | "name": "texture", 17 | "ver": "1.0.20", 18 | "imported": true, 19 | "files": [ 20 | ".json" 21 | ], 22 | "subMetas": {}, 23 | "userData": { 24 | "wrapModeS": "repeat", 25 | "wrapModeT": "repeat", 26 | "minfilter": "linear", 27 | "magfilter": "linear", 28 | "mipfilter": "linear", 29 | "premultiplyAlpha": false, 30 | "anisotropy": 1, 31 | "isUuid": true, 32 | "imageUuidOrDatabaseUri": "82e9a463-dd11-4f1d-9cab-763ef20b9c22" 33 | } 34 | } 35 | }, 36 | "userData": { 37 | "type": "texture", 38 | "redirect": "82e9a463-dd11-4f1d-9cab-763ef20b9c22@6c48a", 39 | "hasAlpha": true 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /materials/water/textures/cloudnoise_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2youyou2/advanced-pipeline/20922aaadea7a85a35ddf809b857bdb0e60b6fed/materials/water/textures/cloudnoise_1.png -------------------------------------------------------------------------------- /materials/water/textures/cloudnoise_1.png.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.21", 3 | "importer": "image", 4 | "imported": true, 5 | "uuid": "ccd2ea38-f1bb-4838-9e17-45f9a906c0ef", 6 | "files": [ 7 | ".png", 8 | ".json" 9 | ], 10 | "subMetas": { 11 | "6c48a": { 12 | "importer": "texture", 13 | "uuid": "ccd2ea38-f1bb-4838-9e17-45f9a906c0ef@6c48a", 14 | "displayName": "cloudnoise_1", 15 | "id": "6c48a", 16 | "name": "texture", 17 | "ver": "1.0.20", 18 | "imported": true, 19 | "files": [ 20 | ".json" 21 | ], 22 | "subMetas": {}, 23 | "userData": { 24 | "wrapModeS": "repeat", 25 | "wrapModeT": "repeat", 26 | "minfilter": "linear", 27 | "magfilter": "linear", 28 | "mipfilter": "linear", 29 | "premultiplyAlpha": false, 30 | "anisotropy": 1, 31 | "isUuid": true, 32 | "imageUuidOrDatabaseUri": "ccd2ea38-f1bb-4838-9e17-45f9a906c0ef" 33 | } 34 | } 35 | }, 36 | "userData": { 37 | "type": "texture", 38 | "redirect": "ccd2ea38-f1bb-4838-9e17-45f9a906c0ef@6c48a", 39 | "hasAlpha": false 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /materials/water/textures/normals.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2youyou2/advanced-pipeline/20922aaadea7a85a35ddf809b857bdb0e60b6fed/materials/water/textures/normals.jpg -------------------------------------------------------------------------------- /materials/water/textures/normals.jpg.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.21", 3 | "importer": "image", 4 | "imported": true, 5 | "uuid": "2e63dd87-468d-4161-9df0-b426cf7520de", 6 | "files": [ 7 | ".jpg", 8 | ".json" 9 | ], 10 | "subMetas": { 11 | "3c318": { 12 | "importer": "texture", 13 | "uuid": "2e63dd87-468d-4161-9df0-b426cf7520de@3c318", 14 | "displayName": "normals", 15 | "id": "3c318", 16 | "name": "normalMap", 17 | "ver": "1.0.20", 18 | "imported": true, 19 | "files": [ 20 | ".json" 21 | ], 22 | "subMetas": {}, 23 | "userData": { 24 | "wrapModeS": "repeat", 25 | "wrapModeT": "repeat", 26 | "minfilter": "linear", 27 | "magfilter": "linear", 28 | "mipfilter": "linear", 29 | "premultiplyAlpha": false, 30 | "anisotropy": 1, 31 | "isUuid": true, 32 | "imageUuidOrDatabaseUri": "2e63dd87-468d-4161-9df0-b426cf7520de" 33 | } 34 | } 35 | }, 36 | "userData": { 37 | "type": "normal map", 38 | "redirect": "2e63dd87-468d-4161-9df0-b426cf7520de@3c318", 39 | "hasAlpha": false 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /materials/water/water.effect.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.4.4", 3 | "importer": "effect", 4 | "imported": true, 5 | "uuid": "82d116d6-8fb5-4e89-b885-01703ee5926c", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /stages.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.1.0", 3 | "importer": "directory", 4 | "imported": true, 5 | "uuid": "3ff37378-b1b4-49ba-ae65-96d3a26af9d9", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "compressionType": {}, 10 | "isRemoteBundle": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /stages/advanced-flow.ts: -------------------------------------------------------------------------------- 1 | import { _decorator, RenderFlow, renderer, ForwardStage, __private, ForwardPipeline, ForwardFlow, ShadowStage, GFXRect, RenderStage, Rect, GFXClearFlag, RenderPipeline, geometry, Pool, pipeline, Vec3 } from "cc"; 2 | import { Camera } from "cc"; 3 | import { EDITOR } from 'cc/env'; 4 | import { AdvancedPipeline } from './advanced-pipeline'; 5 | import { DepthBufferStage } from './depth-buffer/depth-buffer-stage'; 6 | import { GrassBendRenderStage } from './grass/grass-bend-render-stage'; 7 | import { InstanceForwardStage } from './instance/instance-forward-stage'; 8 | import { InstanceShadowStage } from './instance/instance-shadow-stage'; 9 | import { PostProcessStage } from './post-process/post-process-stage'; 10 | const { ccclass, property } = _decorator; 11 | 12 | let _tempVec3 = new Vec3 13 | const roPool = new Pool(() => ({ model: null!, depth: 0 }), 128); 14 | function getRenderObject (model: renderer.scene.Model, camera: renderer.scene.Camera) { 15 | let depth = 0; 16 | if (model.node) { 17 | Vec3.subtract(_tempVec3, model.node.worldPosition, camera.position); 18 | depth = Vec3.dot(_tempVec3, camera.forward); 19 | } 20 | const ro = roPool.alloc(); 21 | ro.model = model; 22 | ro.depth = depth; 23 | return ro; 24 | } 25 | 26 | export enum ClearFlag { 27 | NONE = 0, 28 | COLOR = 1, 29 | DEPTH = 2, 30 | STENCIL = 4, 31 | DEPTH_STENCIL = DEPTH | STENCIL, 32 | ALL = COLOR | DEPTH | STENCIL, 33 | } 34 | const SKYBOX_FLAG = ClearFlag.STENCIL << 1; 35 | 36 | 37 | function sceneCulling (pipeline: ForwardPipeline, camera: renderer.scene.Camera) { 38 | const scene = camera.scene!; 39 | const models = scene.models; 40 | 41 | const renderObjects = pipeline.renderObjects; 42 | roPool.freeArray(renderObjects); renderObjects.length = 0; 43 | 44 | if (pipeline.skybox.enabled && pipeline.skybox.model && (camera.clearFlag & SKYBOX_FLAG)) { 45 | renderObjects.push(getRenderObject(pipeline.skybox.model, camera)); 46 | } 47 | 48 | 49 | for (let i = 0; i < models.length; i++) { 50 | const model = models[i]; 51 | 52 | // filter model by view visibility 53 | if (model.enabled) { 54 | if (model.node && ((camera.visibility & model.node.layer) === model.node.layer) 55 | || (camera.visibility & model.visFlags)) { 56 | // frustum culling 57 | if (model.worldBounds && !geometry.intersect.aabbFrustum(model.worldBounds, camera.frustum)) { 58 | continue; 59 | } 60 | 61 | renderObjects.push(getRenderObject(model, camera)); 62 | } 63 | } 64 | } 65 | } 66 | 67 | @ccclass("AdvancedFlow") 68 | export class AdvancedFlow extends ForwardFlow { 69 | _name = "AdvancedFlow"; 70 | 71 | _depthStage: DepthBufferStage | undefined; 72 | _grassBendStage: GrassBendRenderStage | undefined; 73 | _instanceForwardStage: InstanceForwardStage | undefined; 74 | _postProcessStage: PostProcessStage | undefined; 75 | 76 | _oldViewPort = new Rect; 77 | 78 | _clearFlag = 0; 79 | 80 | get depthStage () { 81 | return this.depthStage; 82 | } 83 | get grassBendStage () { 84 | return this.grassBendStage; 85 | } 86 | get instanceForwardStage () { 87 | return this._instanceForwardStage; 88 | } 89 | get postProcessStage () { 90 | return this._postProcessStage; 91 | } 92 | 93 | constructor () { 94 | super(); 95 | 96 | this._depthStage = new DepthBufferStage(); 97 | this._grassBendStage = new GrassBendRenderStage(); 98 | 99 | this._instanceForwardStage = new InstanceForwardStage(); 100 | this._instanceForwardStage.initialize(ForwardStage.initInfo); 101 | 102 | this._postProcessStage = new PostProcessStage(); 103 | 104 | this._stages.push(this._depthStage); 105 | this._stages.push(this._grassBendStage); 106 | this._stages.push(this._instanceForwardStage); 107 | this._stages.push(this._postProcessStage); 108 | } 109 | 110 | public activate (pipeline: RenderPipeline) { 111 | this._stages.length = 0; 112 | 113 | this._stages.push(this._depthStage!); 114 | this._stages.push(this._grassBendStage!); 115 | this._stages.push(this._instanceForwardStage!); 116 | this._stages.push(this._postProcessStage!); 117 | 118 | super.activate(pipeline); 119 | } 120 | 121 | public render (camera: renderer.scene.Camera) { 122 | let hasRenderThings = Number(camera.visibility) !== 0; 123 | if (!hasRenderThings) { 124 | return; 125 | } 126 | 127 | let oldClearFlag = camera.clearFlag; 128 | if (EDITOR) { 129 | if (camera.name === 'Editor Camera') { 130 | this._clearFlag = camera.clearFlag; 131 | return; 132 | } 133 | 134 | // TODO: hack 135 | if (camera.name === 'Editor UICamera') { 136 | camera.clearFlag = this._clearFlag; 137 | } 138 | } 139 | 140 | 141 | const pipeline = this._pipeline as AdvancedPipeline; 142 | // pipeline.updateCameraUBO(camera); 143 | 144 | // TODO: hack sceneCulling 145 | // @ts-ignore 146 | if (super.sceneCulling) { 147 | // @ts-ignore 148 | super.sceneCulling(camera); 149 | } 150 | else { 151 | sceneCulling(pipeline, camera); 152 | } 153 | 154 | this._grassBendStage?.render(camera); 155 | 156 | let postProcessStage = this._postProcessStage!; 157 | let usePostProcess = pipeline.usePostProcess && postProcessStage && postProcessStage._renderCommands.length !== 0; 158 | if (!EDITOR || camera.name === 'Editor UICamera') { 159 | this._depthStage?.render(camera); 160 | 161 | if (usePostProcess) { 162 | postProcessStage.oldCameraSetting.set(camera); 163 | postProcessStage.postProcessCameraSetting.setToCamera(camera); 164 | } 165 | } 166 | 167 | this._instanceForwardStage?.render(camera); 168 | 169 | if (!EDITOR || camera.name === 'Editor UICamera') { 170 | if (usePostProcess) { 171 | postProcessStage.render(camera); 172 | } 173 | } 174 | 175 | if (EDITOR) { 176 | // TODO: hack 177 | if (camera.name === 'Editor UICamera') { 178 | camera.clearFlag = oldClearFlag; 179 | } 180 | } 181 | } 182 | 183 | rebuild () { 184 | 185 | } 186 | 187 | destroy () { 188 | 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /stages/advanced-flow.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "c2a2bc8a-a5d6-4b87-b8e2-b65a33d659b4", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": {} 9 | } 10 | -------------------------------------------------------------------------------- /stages/advanced-pipeline.ts: -------------------------------------------------------------------------------- 1 | import { director, ForwardPipeline, GFXFeature, _decorator } from 'cc'; 2 | 3 | const { ccclass, property } = _decorator; 4 | 5 | @ccclass('AdvancedPipeline') 6 | export class AdvancedPipeline extends ForwardPipeline { 7 | 8 | @property 9 | usePostProcess = true; 10 | 11 | _isHDR = false; 12 | _isHDRSupported = false; 13 | 14 | activate (): boolean { 15 | let device = this._device || director.root?.device; 16 | if (device.hasFeature(GFXFeature.FORMAT_R11G11B10F) || 17 | device.hasFeature(GFXFeature.TEXTURE_HALF_FLOAT) || 18 | device.hasFeature(GFXFeature.TEXTURE_FLOAT)) { 19 | this._isHDRSupported = true; 20 | } 21 | 22 | // this._isHDR = this._isHDRSupported; 23 | 24 | let res = super.activate(); 25 | 26 | this.macros.CC_USE_HDR = this._isHDRSupported && this.usePostProcess; 27 | 28 | return res; 29 | } 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /stages/advanced-pipeline.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "00ae3c06-6783-4176-8b59-647978e6a6a8", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": {} 9 | } 10 | -------------------------------------------------------------------------------- /stages/depth-buffer.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.1.0", 3 | "importer": "directory", 4 | "imported": true, 5 | "uuid": "ef3f232c-c328-44ad-84f0-74d7799e01d2", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "compressionType": {}, 10 | "isRemoteBundle": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /stages/depth-buffer/depth-buffer-object.ts: -------------------------------------------------------------------------------- 1 | import { _decorator, Component, Node } from 'cc'; 2 | import { DepthBufferStage } from './depth-buffer-stage'; 3 | const { ccclass, executeInEditMode, property } = _decorator; 4 | 5 | @ccclass('DepthBufferObject') 6 | @executeInEditMode 7 | export class DepthBufferObject extends Component { 8 | onEnable () { 9 | if (DepthBufferStage.instance) { 10 | DepthBufferStage.instance.addObject(this); 11 | } 12 | } 13 | onDisable () { 14 | if (DepthBufferStage.instance) { 15 | DepthBufferStage.instance.removeObject(this); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /stages/depth-buffer/depth-buffer-object.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "00b5e54a-3037-438d-9efb-7b41d6872325", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "importAsPlugin": false, 10 | "moduleId": "project:///assets/libs/advanced-pipeline/stages/depth-buffer/depth-buffer-object.js", 11 | "importerSettings": 4 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /stages/depth-buffer/depth-buffer-stage.ts: -------------------------------------------------------------------------------- 1 | import { _decorator, RenderStage, GFXRect, GFXColor, ForwardPipeline, ModelComponent, renderer, GFXLoadOp, GFXTextureLayout, GFXFilter, GFXAddress, RenderFlow, RenderPipeline, director, GFXBufferUsageBit, GFXMemoryUsageBit, GFXClearFlag, GFXCullMode, RenderTexture, GFXBufferInfo, GFXRenderPassInfo, GFXColorAttachment, GFXDepthStencilAttachment, Terrain, geometry } from "cc"; 2 | import { DepthBufferObject } from './depth-buffer-object'; 3 | import { UNIFORM_DEPTH_BUFFER_MAP_BINDING, UBOCustomCommon } from '../../defines/ubo'; 4 | import { commitBuffer } from "../../utils/stage"; 5 | import { getPhaseID, pipeline } from '../../defines/pipeline'; 6 | import { EDITOR } from 'cc/env'; 7 | import { Layers } from '../../defines/layer'; 8 | 9 | const { ccclass, type, property } = _decorator; 10 | const { SetIndex } = pipeline; 11 | 12 | const colors: GFXColor[] = [{ x: 1, y: 1, z: 1, w: 1 }]; 13 | 14 | 15 | const _colorAttachment = new GFXColorAttachment(); 16 | _colorAttachment.endLayout = GFXTextureLayout.SHADER_READONLY_OPTIMAL; 17 | const _depthStencilAttachment = new GFXDepthStencilAttachment(); 18 | const _renderPassInfo = new GFXRenderPassInfo([_colorAttachment], _depthStencilAttachment); 19 | 20 | const _phaseID = getPhaseID('depth-buffer'); 21 | 22 | 23 | @ccclass("DepthBufferStage") 24 | export class DepthBufferStage extends RenderStage { 25 | static get instance (): DepthBufferStage | null { 26 | let flow = director.root!.pipeline.flows.find(f => f.name === 'AdvancedFlow'); 27 | if (!flow) return null; 28 | return flow.stages.find(s => s.name === 'DepthBufferStage') as DepthBufferStage; 29 | } 30 | 31 | _name = 'DepthBufferStage' 32 | 33 | private _renderTexture: RenderTexture | null = null; 34 | private _renderArea: GFXRect = { x: 0, y: 0, width: 0, height: 0 }; 35 | 36 | protected _pipelineStates = { rasterizerState: { cullMode: GFXCullMode.BACK } }; 37 | 38 | protected _buffer = new Float32Array(UBOCustomCommon.COUNT); 39 | 40 | 41 | depthBufferObjects: DepthBufferObject[] = []; 42 | 43 | @property 44 | enabled = true; 45 | 46 | activate (pipeline: RenderPipeline, flow: RenderFlow) { 47 | super.activate(pipeline, flow); 48 | 49 | this.bindUBO(); 50 | this.updateUBO(); 51 | } 52 | 53 | addObject (obj: DepthBufferObject) { 54 | this.depthBufferObjects.push(obj); 55 | } 56 | 57 | removeObject (obj: DepthBufferObject) { 58 | let index = this.depthBufferObjects.indexOf(obj); 59 | if (index === -1) return; 60 | this.depthBufferObjects.splice(index, 1); 61 | } 62 | 63 | bindUBO () { 64 | const pipeline = this._pipeline as ForwardPipeline; 65 | const device = pipeline.device; 66 | 67 | let width = device.width, height = device.height; 68 | 69 | let renderTexture = this._renderTexture; 70 | if (!renderTexture) { 71 | renderTexture = new RenderTexture(); 72 | renderTexture.reset({ width, height, passInfo: _renderPassInfo }) 73 | this._renderTexture = renderTexture; 74 | 75 | pipeline.descriptorSet.bindSampler(UNIFORM_DEPTH_BUFFER_MAP_BINDING, renderTexture.getGFXSampler()); 76 | pipeline.descriptorSet.bindTexture(UNIFORM_DEPTH_BUFFER_MAP_BINDING, renderTexture.getGFXTexture()!); 77 | } 78 | 79 | let buffer = pipeline.descriptorSet.getBuffer(UBOCustomCommon.BINDING); 80 | if (!buffer) { 81 | buffer = pipeline.device.createBuffer(new GFXBufferInfo( 82 | GFXBufferUsageBit.UNIFORM | GFXBufferUsageBit.TRANSFER_DST, 83 | GFXMemoryUsageBit.HOST | GFXMemoryUsageBit.DEVICE, 84 | UBOCustomCommon.SIZE, 85 | )); 86 | pipeline.descriptorSet.bindBuffer(UBOCustomCommon.BINDING, buffer); 87 | } 88 | } 89 | 90 | updateUBO (camera?: renderer.scene.Camera) { 91 | const pipeline = this._pipeline as ForwardPipeline; 92 | const device = pipeline.device; 93 | 94 | let width = device.width, height = device.height; 95 | // let shadingWidth = pipelineAny._shadingWidth * scale; 96 | // let shadingHeight = pipelineAny._shadingHeight * scale; 97 | // if (CC_EDITOR) { 98 | // shadingWidth = device.width; 99 | // shadingHeight = device.height; 100 | // } 101 | 102 | let renderTexture = this._renderTexture!; 103 | if (renderTexture.width !== width || renderTexture.height !== height) { 104 | renderTexture.resize(width, height); 105 | } 106 | 107 | if (camera) { 108 | // let shadowUBO: Float32Array = (pipeline as any)._shadowUBO; 109 | // Mat4.toArray(shadowUBO, view.camera.matViewProj, UBOShadow.MAT_LIGHT_VIEW_PROJ_OFFSET); 110 | // pipeline.commandBuffers[0].updateBuffer(pipeline.descriptorSet.getBuffer(UBOShadow.BINDING), shadowUBO); 111 | 112 | let commonUBO = this._buffer; 113 | commonUBO[UBOCustomCommon.ProjectionParamsOffset] = camera.nearClip; 114 | commonUBO[UBOCustomCommon.ProjectionParamsOffset + 1] = camera.farClip; 115 | commonUBO[UBOCustomCommon.ProjectionParamsOffset + 3] = 1 / camera.nearClip; 116 | commonUBO[UBOCustomCommon.ProjectionParamsOffset + 2] = 1 / camera.farClip; 117 | pipeline.commandBuffers[0].updateBuffer(pipeline.descriptorSet.getBuffer(UBOCustomCommon.BINDING), commonUBO); 118 | } 119 | } 120 | 121 | render (camera: renderer.scene.Camera) { 122 | if (!this.enabled || this.depthBufferObjects.length === 0) { 123 | return; 124 | } 125 | 126 | if (!(camera.visibility & Layers.DepthBuffer)) { 127 | return; 128 | } 129 | 130 | if (EDITOR) { 131 | if (camera.node.name !== 'Editor Camera') { 132 | return; 133 | } 134 | } 135 | 136 | this.updateUBO(camera); 137 | 138 | let renderTexture = this._renderTexture!; 139 | 140 | const pipeline = this._pipeline as ForwardPipeline; 141 | const device = pipeline.device; 142 | 143 | // command buffer 144 | const cmdBuff = pipeline.commandBuffers[0]; 145 | 146 | const vp = camera.viewport; 147 | this._renderArea!.x = vp.x * renderTexture.width; 148 | this._renderArea!.y = vp.y * renderTexture.height; 149 | this._renderArea!.width = vp.width * renderTexture.width * pipeline.shadingScale; 150 | this._renderArea!.height = vp.height * renderTexture.height * pipeline.shadingScale; 151 | 152 | const frameBuffer = renderTexture.window!.framebuffer; 153 | const renderPass = frameBuffer.renderPass; 154 | 155 | _colorAttachment.loadOp = GFXLoadOp.CLEAR; 156 | 157 | cmdBuff.beginRenderPass(renderPass, frameBuffer, this._renderArea!, 158 | colors, camera.clearDepth, camera.clearStencil); 159 | 160 | cmdBuff.bindDescriptorSet(SetIndex.GLOBAL, pipeline.descriptorSet); 161 | 162 | const depthBufferObjects = this.depthBufferObjects; 163 | for (let i = 0; i < depthBufferObjects.length; ++i) { 164 | const mc = depthBufferObjects[i].getComponent(ModelComponent); 165 | if (mc && mc.model) { 166 | commitBuffer(mc.model, cmdBuff, device, renderPass, _phaseID); 167 | continue; 168 | } 169 | 170 | const tr = depthBufferObjects[i].getComponent(Terrain); 171 | if (tr) { 172 | const blocks = tr.getBlocks(); 173 | for (let bi = 0; bi < blocks.length; bi++) { 174 | let model = (blocks[bi] as any)._renderable._model as renderer.scene.Model; 175 | if (!model.modelBounds) { 176 | continue; 177 | } 178 | camera.frustum.accurate = true; 179 | if (!geometry.intersect.aabbFrustumAccurate(model.modelBounds, camera.frustum)) { 180 | continue; 181 | } 182 | commitBuffer(model, cmdBuff, device, renderPass, _phaseID); 183 | continue; 184 | } 185 | } 186 | 187 | } 188 | 189 | cmdBuff.endRenderPass(); 190 | 191 | _colorAttachment.loadOp = GFXLoadOp.LOAD; 192 | } 193 | 194 | rebuild () { 195 | this.clear(); 196 | } 197 | resize () { 198 | } 199 | destroy () { 200 | this.clear(); 201 | } 202 | clear () { 203 | if (this._renderTexture) { 204 | this._renderTexture.destroy(); 205 | } 206 | this._renderTexture = null; 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /stages/depth-buffer/depth-buffer-stage.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "2d387e19-26a5-4f3e-a159-9ab2fc3ea946", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "importAsPlugin": false, 10 | "moduleId": "project:///assets/libs/advanced-pipeline/stages/depth-buffer/depth-buffer-stage.js", 11 | "importerSettings": 4 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /stages/grass.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.1.0", 3 | "importer": "directory", 4 | "imported": true, 5 | "uuid": "47f5fc5f-b8a1-4897-bb9a-7c6fd151e1e3", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "compressionType": {}, 10 | "isRemoteBundle": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /stages/grass/grass-bend-render-stage.ts: -------------------------------------------------------------------------------- 1 | import { _decorator, RenderStage, GFXRect, GFXColor, ForwardPipeline, ModelComponent, renderer, GFXFormat, GFXLoadOp, GFXTextureLayout, GFXFilter, GFXAddress, RenderFlow, RenderPipeline, director, Vec4, GFXBufferUsageBit, GFXMemoryUsageBit, GFXCullMode, RenderTexture, GFXBufferInfo, GFXRenderPassInfo, GFXColorAttachment, GFXDepthStencilAttachment } from "cc"; 2 | 3 | import { GrassBender } from "./src/grass-bender"; 4 | import { GrassBenderRenderer } from "./src/grass-bender-renderer"; 5 | import { UBOGrassBend, UNIFORM_GRASS_BEND_MAP_BINDING } from '../../defines/ubo'; 6 | import { commitBuffer } from "../../utils/stage"; 7 | import { getPhaseID, pipeline } from '../../defines/pipeline'; 8 | 9 | const { SetIndex } = pipeline; 10 | const { ccclass, type } = _decorator; 11 | 12 | const tempVec4 = new Vec4; 13 | 14 | const colors: GFXColor[] = [{ x: 1, y: 1, z: 1, w: 1 }]; 15 | 16 | const _samplerInfo = [ 17 | GFXFilter.LINEAR, 18 | GFXFilter.LINEAR, 19 | GFXFilter.NONE, 20 | GFXAddress.CLAMP, 21 | GFXAddress.CLAMP, 22 | GFXAddress.CLAMP, 23 | ]; 24 | 25 | 26 | const _colorAttachment = new GFXColorAttachment(); 27 | _colorAttachment.endLayout = GFXTextureLayout.SHADER_READONLY_OPTIMAL; 28 | _colorAttachment.format = GFXFormat.RGBA32F; 29 | const _depthStencilAttachment = new GFXDepthStencilAttachment(); 30 | const _renderPassInfo = new GFXRenderPassInfo([_colorAttachment], _depthStencilAttachment); 31 | 32 | const _phaseID = getPhaseID('grass-bend'); 33 | 34 | 35 | @ccclass("GrassBendRenderStage") 36 | export class GrassBendRenderStage extends RenderStage { 37 | static get instance (): GrassBendRenderStage | null { 38 | let flow = director.root!.pipeline.flows.find(f => f.name === 'AdvancedFlow'); 39 | if (!flow) return null; 40 | return flow.stages.find(s => s.name === 'GrassBendRenderStage') as GrassBendRenderStage; 41 | } 42 | 43 | _name = 'GrassBendRenderStage' 44 | 45 | private _renderTexture: RenderTexture | null = null; 46 | private _renderArea: GFXRect = { x: 0, y: 0, width: 0, height: 0 }; 47 | 48 | private _grassBendRenderer: GrassBenderRenderer | null = null; 49 | 50 | protected _bendUBO = new Float32Array(UBOGrassBend.COUNT); 51 | 52 | protected _pipelineStates = { rasterizerState: { cullMode: GFXCullMode.BACK } }; 53 | 54 | 55 | grassBenders: GrassBender[] = []; 56 | 57 | activate (pipeline: RenderPipeline, flow: RenderFlow) { 58 | super.activate(pipeline, flow); 59 | 60 | this.updateUBO(); 61 | } 62 | 63 | addGrassBender (bender: GrassBender) { 64 | this.grassBenders.push(bender); 65 | } 66 | 67 | removeGrassBender (bender: GrassBender) { 68 | let index = this.grassBenders.indexOf(bender); 69 | if (index === -1) return; 70 | this.grassBenders.splice(index, 1); 71 | } 72 | 73 | setGrassBendRenderer (renderer: GrassBenderRenderer | null) { 74 | this._grassBendRenderer = renderer; 75 | } 76 | 77 | updateUBO () { 78 | const pipeline = this._pipeline as ForwardPipeline; 79 | const device = pipeline.device; 80 | 81 | let width = 512, height = 512; 82 | if (this._grassBendRenderer) { 83 | width = height = this._grassBendRenderer.resolution; 84 | } 85 | 86 | let renderTexture = this._renderTexture; 87 | if (!renderTexture) { 88 | renderTexture = new RenderTexture(); 89 | renderTexture.reset({ width, height, passInfo: _renderPassInfo }) 90 | this._renderTexture = renderTexture; 91 | 92 | const samplerHash = renderer.genSamplerHash(_samplerInfo); 93 | const sampler = renderer.samplerLib.getSampler(device, samplerHash); 94 | pipeline.descriptorSet.bindSampler(UNIFORM_GRASS_BEND_MAP_BINDING, sampler); 95 | pipeline.descriptorSet.bindTexture(UNIFORM_GRASS_BEND_MAP_BINDING, renderTexture.getGFXTexture()!); 96 | } 97 | else if (renderTexture.width !== width || renderTexture.height !== height) { 98 | renderTexture.resize(width, height); 99 | } 100 | 101 | let bendRenderer = this._grassBendRenderer; 102 | if (bendRenderer) { 103 | let pos = bendRenderer.renderCamera!.node.worldPosition; 104 | tempVec4.set( 105 | pos.x, 106 | pos.z, 107 | bendRenderer.range * 2, 108 | 1 109 | ) 110 | Vec4.toArray(this._bendUBO, tempVec4, UBOGrassBend.UVOffset); 111 | } 112 | 113 | let buffer = pipeline.descriptorSet.getBuffer(UBOGrassBend.BINDING); 114 | if (!buffer) { 115 | buffer = pipeline.device.createBuffer(new GFXBufferInfo( 116 | GFXBufferUsageBit.UNIFORM | GFXBufferUsageBit.TRANSFER_DST, 117 | GFXMemoryUsageBit.HOST | GFXMemoryUsageBit.DEVICE, 118 | UBOGrassBend.SIZE, 119 | )); 120 | pipeline.descriptorSet.bindBuffer(UBOGrassBend.BINDING, buffer); 121 | } 122 | buffer.update(this._bendUBO); 123 | } 124 | 125 | render (camera: renderer.scene.Camera) { 126 | if (!this._grassBendRenderer) { 127 | return; 128 | } 129 | if (camera.node !== this._grassBendRenderer.renderCamera!.node) { 130 | return; 131 | } 132 | let renderTexture = this._renderTexture; 133 | if (!renderTexture) { 134 | return; 135 | } 136 | 137 | this.updateUBO(); 138 | 139 | this._grassBendRenderer.renderCamera!.targetTexture = renderTexture; 140 | 141 | const pipeline = this._pipeline as ForwardPipeline; 142 | const device = pipeline.device; 143 | 144 | // command buffer 145 | const cmdBuff = pipeline.commandBuffers[0]; 146 | 147 | const vp = camera.viewport; 148 | this._renderArea!.x = vp.x * renderTexture.width; 149 | this._renderArea!.y = vp.y * renderTexture.height; 150 | this._renderArea!.width = vp.width * renderTexture.width * pipeline.shadingScale; 151 | this._renderArea!.height = vp.height * renderTexture.height * pipeline.shadingScale; 152 | 153 | const frameBuffer = renderTexture.window!.framebuffer; 154 | const renderPass = frameBuffer.renderPass; 155 | 156 | colors[0].x = camera.clearColor.x; 157 | colors[0].y = camera.clearColor.y; 158 | colors[0].z = camera.clearColor.z; 159 | colors[0].w = camera.clearColor.w; 160 | 161 | _colorAttachment.loadOp = GFXLoadOp.CLEAR; 162 | 163 | cmdBuff.beginRenderPass(renderPass, frameBuffer, this._renderArea!, 164 | colors, camera.clearDepth, camera.clearStencil); 165 | 166 | cmdBuff.bindDescriptorSet(SetIndex.GLOBAL, pipeline.descriptorSet); 167 | 168 | const grassBenders = this.grassBenders; 169 | let m = 0; let p = 0; 170 | for (let i = 0; i < grassBenders.length; ++i) { 171 | const ro = grassBenders[i].getComponent(ModelComponent); 172 | if (!ro || !ro.model) continue; 173 | commitBuffer(ro.model, cmdBuff, device, renderPass, _phaseID); 174 | } 175 | 176 | cmdBuff.endRenderPass(); 177 | 178 | _colorAttachment.loadOp = GFXLoadOp.LOAD; 179 | } 180 | 181 | rebuild () { 182 | this.clear(); 183 | } 184 | resize () { 185 | } 186 | destroy () { 187 | this.clear(); 188 | } 189 | clear () { 190 | if (this._renderTexture) { 191 | this._renderTexture.destroy(); 192 | } 193 | this._renderTexture = null; 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /stages/grass/grass-bend-render-stage.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "5f9a4583-dc11-49d2-bba9-417d1784a7ca", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "importAsPlugin": false, 10 | "moduleId": "project:///assets/libs/advanced-pipeline/stages/grass/grass-bend-render-stage.js", 11 | "importerSettings": 4 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /stages/grass/src.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.1.0", 3 | "importer": "directory", 4 | "imported": true, 5 | "uuid": "6ddff083-045e-4a1e-b3c6-2254e593668e", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "compressionType": {}, 10 | "isRemoteBundle": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /stages/grass/src/grass-bender-renderer.ts: -------------------------------------------------------------------------------- 1 | import { _decorator, Component, Node, Camera, renderer, Color, CCObject, Vec3, GFXClearFlag } from 'cc'; 2 | import { Layers } from '../../../defines/layer'; 3 | import { GrassBendRenderStage } from '../grass-bend-render-stage'; 4 | const { ccclass, property, executeInEditMode, type } = _decorator; 5 | 6 | const neutralVector = new Color(0.5 * 255, 0, 0.5 * 255, 0); 7 | 8 | @ccclass('GrassBenderRenderer') 9 | @executeInEditMode 10 | export class GrassBenderRenderer extends Component { 11 | 12 | @type(Node) 13 | followTarget: Node | null = null; 14 | 15 | @property 16 | _range = 32 17 | @property 18 | get range () { 19 | return this._range; 20 | } 21 | set range (v) { 22 | this._range = v; 23 | if (this._renderCamera) { 24 | this._renderCamera.orthoHeight = this.range; 25 | } 26 | } 27 | 28 | @property 29 | _resolution = 512; 30 | @property 31 | get resolution () { 32 | return this._resolution; 33 | } 34 | set resolution (v) { 35 | if (v === this._resolution) { 36 | return; 37 | } 38 | this._resolution = v; 39 | if (GrassBendRenderStage.instance) { 40 | GrassBendRenderStage.instance.rebuild(); 41 | } 42 | } 43 | 44 | _renderCamera: Camera | null = null; 45 | get renderCamera () { 46 | return this._renderCamera; 47 | } 48 | 49 | start () { 50 | if (!this._renderCamera) { 51 | let node = new Node('GrassBendCamera'); 52 | node._objFlags |= CCObject.Flags.DontSave | CCObject.Flags.HideInHierarchy; 53 | node.parent = this.node; 54 | node.eulerAngles = new Vec3(-90, 0, 0); 55 | 56 | let camera = node.addComponent(Camera); 57 | camera.projection = renderer.scene.CameraProjection.ORTHO; 58 | camera.orthoHeight = this.range; 59 | camera.far = this.range * 2; 60 | camera.clearColor = neutralVector; 61 | camera.clearFlags = GFXClearFlag.NONE; 62 | camera.visibility = Layers.GrassBend; 63 | camera.priority = -100; 64 | 65 | this._renderCamera = camera; 66 | } 67 | } 68 | 69 | onEnable () { 70 | if (GrassBendRenderStage.instance) { 71 | GrassBendRenderStage.instance.setGrassBendRenderer(this); 72 | } 73 | } 74 | onDisable () { 75 | if (GrassBendRenderStage.instance) { 76 | GrassBendRenderStage.instance.setGrassBendRenderer(null); 77 | } 78 | } 79 | 80 | update (deltaTime: number) { 81 | if (this.followTarget && this._renderCamera) { 82 | let followPosition = this.followTarget.worldPosition; 83 | let worldPosition = this._renderCamera.node.worldPosition; 84 | if (followPosition.x !== worldPosition.x || followPosition.y + this.range !== worldPosition.y || followPosition.z !== worldPosition.z) { 85 | this._renderCamera.node.setWorldPosition(followPosition.x, followPosition.y + this.range, followPosition.z); 86 | } 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /stages/grass/src/grass-bender-renderer.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "dd671742-064c-4f70-8ea0-f711e4938c84", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "importAsPlugin": false, 10 | "moduleId": "project:///assets/libs/advanced-pipeline/stages/grass/src/grass-bender-renderer.js", 11 | "importerSettings": 4 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /stages/grass/src/grass-bender.ts: -------------------------------------------------------------------------------- 1 | import { _decorator, Component, Node } from 'cc'; 2 | import { GrassBendRenderStage } from '../grass-bend-render-stage'; 3 | const { ccclass, property, executeInEditMode } = _decorator; 4 | 5 | @ccclass('GrassBender') 6 | @executeInEditMode 7 | export class GrassBender extends Component { 8 | /* class member could be defined like this */ 9 | // dummy = ''; 10 | 11 | /* use `property` decorator if your want the member to be serializable */ 12 | // @property 13 | // serializableDummy = 0; 14 | 15 | start () { 16 | // Your initialization goes here. 17 | } 18 | 19 | onEnable () { 20 | if (GrassBendRenderStage.instance) { 21 | GrassBendRenderStage.instance.addGrassBender(this); 22 | } 23 | } 24 | 25 | onDisable () { 26 | if (GrassBendRenderStage.instance) { 27 | GrassBendRenderStage.instance.removeGrassBender(this); 28 | } 29 | } 30 | 31 | // update (deltaTime: number) { 32 | // // Your update function goes here. 33 | // } 34 | } 35 | -------------------------------------------------------------------------------- /stages/grass/src/grass-bender.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "ddff1e5b-4912-4c88-93c7-cf6692bf4efa", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "importAsPlugin": false, 10 | "moduleId": "project:///assets/libs/advanced-pipeline/stages/grass/src/grass-bender.js", 11 | "importerSettings": 4 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /stages/instance.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.1.0", 3 | "importer": "directory", 4 | "imported": true, 5 | "uuid": "1e11925b-9daf-4427-9766-82792a6cf9d6", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "compressionType": {}, 10 | "isRemoteBundle": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /stages/instance/instace-manager.ts: -------------------------------------------------------------------------------- 1 | import { CCObject, Component, director, find, InstancedBuffer, Mat4, Material, Mesh, MeshRenderer, Node, Quat, Vec3, _decorator } from 'cc'; 2 | import { getPhaseID } from '../../defines/pipeline'; 3 | import { debug, TechniqueNams } from '../../utils/draw'; 4 | import { InstanceBlockData } from './instance-block'; 5 | import { InstanceObject } from './instance-object'; 6 | 7 | const { ccclass, property, type, executeInEditMode } = _decorator 8 | 9 | let _tempVec3 = new Vec3; 10 | const _shadowCasterPhaseID = getPhaseID('shadow-caster'); 11 | 12 | export class InstanceManager { 13 | static _instance: InstanceManager; 14 | static get instance () { 15 | if (!this._instance) { 16 | this._instance = new InstanceManager; 17 | } 18 | return this._instance; 19 | } 20 | 21 | private objects: InstanceObject[] = []; 22 | 23 | private blocks: InstanceBlockData[] = []; 24 | private blockMap: Map = new Map; 25 | 26 | private _blockSize = new Vec3(100, 100, 100); 27 | get blockSize () { 28 | return this._blockSize; 29 | } 30 | set blockSize (val) { 31 | if (this._blockSize.equals(val)) { 32 | return; 33 | } 34 | this._blockSize.set(val); 35 | this.dirty = true; 36 | } 37 | 38 | _dirty = true; 39 | get dirty () { 40 | return this._dirty; 41 | } 42 | set dirty (value) { 43 | this._dirty = value; 44 | } 45 | 46 | addObject (object: InstanceObject) { 47 | if (this.objects.indexOf(object) === -1) { 48 | this.objects.push(object); 49 | } 50 | this.dirty = true; 51 | } 52 | removeObject (object: InstanceObject) { 53 | let index = this.objects.indexOf(object); 54 | if (index !== -1) { 55 | this.objects.splice(index, 1); 56 | } 57 | this.dirty = true; 58 | } 59 | 60 | getBlocks () { 61 | if (!this._dirty) { 62 | return this.blocks; 63 | } 64 | this._dirty = false; 65 | 66 | console.time('Generate Instance Blocks'); 67 | 68 | let blocks = this.blocks; 69 | let blockMap = this.blockMap; 70 | 71 | blocks.length = 0; 72 | blockMap.clear(); 73 | 74 | let tempNode = find('InstanceTemplate'); 75 | if (tempNode) { 76 | tempNode.destroy(); 77 | } 78 | tempNode = new Node('InstanceTemplate'); 79 | tempNode._objFlags |= CCObject.Flags.HideInHierarchy | CCObject.Flags.DontSave; 80 | tempNode.parent = director.getScene() as any; 81 | 82 | let tempRender: Map = new Map; 83 | 84 | for (let i = 0; i < this.objects.length; i++) { 85 | let object = this.objects[i]; 86 | let datas = object.datas; 87 | for (let di = 0; di < datas.length; di++) { 88 | let data = datas[di]; 89 | let matrices = data._matrices; 90 | let assetID = data.assetId; 91 | 92 | let meshRenderer = tempRender.get(assetID); 93 | if (!meshRenderer) { 94 | let node = new Node(); 95 | node.parent = tempNode; 96 | 97 | meshRenderer = node.addComponent(MeshRenderer); 98 | meshRenderer.mesh = data.mesh; 99 | meshRenderer.shadowCastingMode = data.casterShadow; 100 | 101 | for (let mi = 0; mi < data.materials.length; mi++) { 102 | meshRenderer.setMaterial(data.materials[mi], mi); 103 | } 104 | 105 | meshRenderer.enabled = false; 106 | tempRender.set(assetID, meshRenderer); 107 | } 108 | 109 | let model = meshRenderer.model!; 110 | let subModels = model.subModels!; 111 | for (let i = 0; i < subModels.length; i++) { 112 | let instanceID = assetID + '_' + i; 113 | 114 | let subModel = subModels[i]; 115 | let passes = subModel.passes 116 | for (let pi = 0; pi < passes.length; pi++) { 117 | let pass = passes[pi]; 118 | if (pass.phase === _shadowCasterPhaseID) { 119 | if (!model.castShadow) { 120 | continue; 121 | } 122 | } 123 | 124 | for (let mi = 0; mi < matrices.length; mi++) { 125 | let matrix = matrices[mi]; 126 | 127 | // 128 | Mat4.getTranslation(_tempVec3, matrix); 129 | let x = Math.floor(_tempVec3.x / this.blockSize.x); 130 | let z = Math.floor(_tempVec3.z / this.blockSize.z); 131 | let blockName = `${x}_${z}`; 132 | 133 | let block = blockMap.get(blockName); 134 | if (!block) { 135 | block = new InstanceBlockData; 136 | block.blockName = blockName; 137 | block.worldBound.center.set((x + 0.5) * this.blockSize.x, 0, (z + 0.5) * this.blockSize.z); 138 | block.worldBound.halfExtents.set(this.blockSize.x / 2, this.blockSize.y / 2, this.blockSize.z / 2); 139 | 140 | blocks.push(block); 141 | blockMap.set(blockName, block); 142 | } 143 | 144 | // 145 | let phaseBundle = block._instances.get(pass.phase); 146 | if (!phaseBundle) { 147 | phaseBundle = new Map; 148 | block._instances.set(pass.phase, phaseBundle); 149 | } 150 | 151 | // 152 | let instance = phaseBundle.get(instanceID); 153 | if (!instance) { 154 | instance = new InstancedBuffer(pass); 155 | phaseBundle.set(instanceID, instance); 156 | } 157 | 158 | // 159 | meshRenderer.node.worldMatrix.set(matrix); 160 | (model as any)._transformUpdated = true; 161 | model.updateUBOs(0); 162 | 163 | instance.merge(subModel, model.instancedAttributes, pi); 164 | } 165 | } 166 | } 167 | } 168 | } 169 | 170 | console.timeEnd('Generate Instance Blocks'); 171 | 172 | return this.blocks; 173 | } 174 | 175 | drawdDebug () { 176 | let drawer = debug.drawer; 177 | 178 | drawer.technique = TechniqueNams.transparent; 179 | drawer.color.set(255, 255, 255, 50); 180 | 181 | let blocks = this.blocks; 182 | for (let bbi = 0; bbi < blocks.length; bbi++) { 183 | let block = blocks[bbi]; 184 | drawer.matrix.fromRTS(Quat.IDENTITY, block.worldBound.center, Vec3.ONE); 185 | drawer.box({ 186 | width: block.worldBound.halfExtents.x * 2, 187 | height: block.worldBound.halfExtents.y * 2, 188 | length: block.worldBound.halfExtents.z * 2, 189 | }) 190 | } 191 | } 192 | } 193 | 194 | @ccclass('InstanceManagerComponent') 195 | @executeInEditMode 196 | class InstanceManagerComponent extends Component { 197 | @type(Vec3) 198 | private _blockSize = new Vec3; 199 | @type(Vec3) 200 | get blockSize () { 201 | return this._blockSize; 202 | } 203 | set blockSize (val) { 204 | this._blockSize.set(val); 205 | InstanceManager.instance.blockSize = this.blockSize; 206 | } 207 | 208 | @property 209 | debug = false; 210 | 211 | onEnable () { 212 | InstanceManager.instance.blockSize = this.blockSize; 213 | } 214 | 215 | update () { 216 | if (this.debug) { 217 | InstanceManager.instance.drawdDebug(); 218 | } 219 | } 220 | } 221 | 222 | (globalThis as any).InstanceManager = InstanceManager; 223 | -------------------------------------------------------------------------------- /stages/instance/instace-manager.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "4a46346d-ae84-45dd-9826-b7cb2a418973", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "importAsPlugin": false, 10 | "moduleId": "project:///assets/libs/advanced-pipeline/stages/instance/instace-manager.js", 11 | "importerSettings": 4 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /stages/instance/instance-block-stage.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.10", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "a59888c3-8194-4522-9ded-d12de0792dec", 6 | "files": [ 7 | ".js", 8 | "editor.js", 9 | ".trans" 10 | ], 11 | "subMetas": {}, 12 | "userData": { 13 | "importAsPlugin": false, 14 | "moduleId": "project:///assets/libs/advanced-pipeline/stages/folige/instance-block-stage.js", 15 | "importerSettings": 4 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /stages/instance/instance-block.ts: -------------------------------------------------------------------------------- 1 | import { geometry, InstancedBuffer, Mat4, Material, Mesh } from 'cc'; 2 | 3 | type InstanceBundle = Map // mesh and materials id 4 | type InstancePhase = Map // phase 5 | 6 | export class InstanceBlockData { 7 | 8 | blockName = ''; 9 | 10 | _instances: InstancePhase = new Map; 11 | 12 | worldBound = new geometry.AABB 13 | } 14 | -------------------------------------------------------------------------------- /stages/instance/instance-block.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "8d456013-9c64-44ba-b988-08f67acf8cfb", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "importAsPlugin": false, 10 | "moduleId": "project:///assets/libs/advanced-pipeline/stages/instance/instance-block.js", 11 | "importerSettings": 4 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /stages/instance/instance-forward-stage.ts: -------------------------------------------------------------------------------- 1 | import { _decorator, ForwardStage, ForwardPipeline, gfx, renderer, GFXColor, __private } from "cc"; 2 | import { Layers } from '../../defines/layer'; 3 | import { getPhaseID, pipeline } from '../../defines/pipeline'; 4 | import { InstanceManager } from './instace-manager'; 5 | import { InstanceObjectQueue } from './instanced-object-queue'; 6 | 7 | const { ccclass, property } = _decorator; 8 | const { SetIndex } = pipeline; 9 | 10 | const colors: GFXColor[] = [{ x: 0, y: 0, z: 0, w: 1 }]; 11 | 12 | let _phase = getPhaseID('default'); 13 | 14 | 15 | @ccclass("InstanceForwardStage") 16 | export class InstanceForwardStage extends ForwardStage { 17 | _name = 'InstanceForwardStage' 18 | 19 | _instanceObjectQueue = new InstanceObjectQueue(); 20 | 21 | resize () { 22 | 23 | } 24 | 25 | updateQueue (cmdBuff: gfx.CommandBuffer, camera: renderer.scene.Camera) { 26 | let instancedQueue = this._instanceObjectQueue; 27 | instancedQueue.queue.clear(); 28 | 29 | instancedQueue.addBlocks(((globalThis as any).InstanceManager as typeof InstanceManager).instance.getBlocks(), [camera.frustum], _phase); 30 | 31 | instancedQueue.uploadBuffers(cmdBuff); 32 | } 33 | 34 | renderInstances (camera: renderer.scene.Camera): boolean { 35 | if (!(camera.visibility & Layers.Instance)) { 36 | return false; 37 | } 38 | 39 | const pipeline = this._pipeline as ForwardPipeline; 40 | const cmdBuff = pipeline.commandBuffers[0]; 41 | const device = pipeline.device; 42 | 43 | this.updateQueue(cmdBuff, camera); 44 | 45 | this._instanceObjectQueue.uploadBuffers(cmdBuff); 46 | if (!this._instanceObjectQueue.queue.size) { 47 | return false; 48 | } 49 | 50 | (this as any)._additiveLightQueue.gatherLightPasses(camera, cmdBuff); 51 | 52 | const vp = camera.viewport; 53 | const window = camera.window! as any as __private.cocos_core_renderer_core_render_window_RenderWindow; 54 | // render area is not oriented 55 | const w = window.hasOnScreenAttachments && device.surfaceTransform % 2 ? camera.height : camera.width; 56 | const h = window.hasOnScreenAttachments && device.surfaceTransform % 2 ? camera.width : camera.height; 57 | 58 | let renderArea = (this as any)._renderArea!; 59 | renderArea.x = vp.x * w; 60 | renderArea.y = vp.y * h; 61 | renderArea.width = vp.width * w * pipeline.shadingScale; 62 | renderArea.height = vp.height * h * pipeline.shadingScale; 63 | 64 | const framebuffer = window.framebuffer; 65 | const renderPass = framebuffer.colorTextures[0] ? framebuffer.renderPass : pipeline.getRenderPass(camera.clearFlag); 66 | 67 | if (camera.clearFlag & gfx.ClearFlag.COLOR) { 68 | // if (pipeline.isHDR) { 69 | // SRGBToLinear(colors[0], camera.clearColor); 70 | // const scale = pipeline.fpScale / camera.exposure; 71 | // colors[0].x *= scale; 72 | // colors[0].y *= scale; 73 | // colors[0].z *= scale; 74 | // } else { 75 | colors[0].x = camera.clearColor.x; 76 | colors[0].y = camera.clearColor.y; 77 | colors[0].z = camera.clearColor.z; 78 | // } 79 | } 80 | 81 | colors[0].w = camera.clearColor.w; 82 | 83 | cmdBuff.beginRenderPass(renderPass, framebuffer, renderArea, 84 | colors, camera.clearDepth, camera.clearStencil); 85 | 86 | cmdBuff.bindDescriptorSet(SetIndex.GLOBAL, pipeline.descriptorSet); 87 | 88 | this._instanceObjectQueue.recordCommandBuffer(device, renderPass, cmdBuff); 89 | 90 | cmdBuff.endRenderPass(); 91 | 92 | return true; 93 | } 94 | 95 | render (camera: renderer.scene.Camera) { 96 | let renderred = this.renderInstances(camera); 97 | 98 | // should not clear the already draw content 99 | let clearFlag = camera.clearFlag; 100 | if (renderred) { 101 | camera.clearFlag = 0; 102 | } 103 | 104 | super.render(camera); 105 | 106 | if (renderred) { 107 | camera.clearFlag = clearFlag; 108 | } 109 | } 110 | 111 | rebuild () { 112 | 113 | } 114 | 115 | destroy () { 116 | 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /stages/instance/instance-forward-stage.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "daa94191-1700-47f6-8586-2a8bab2793c3", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "importAsPlugin": false, 10 | "moduleId": "project:///assets/libs/advanced-pipeline/stages/instance/instance-forward-stage.js", 11 | "importerSettings": 4 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /stages/instance/instance-object.ts: -------------------------------------------------------------------------------- 1 | 2 | import { Asset, CCObject, Component, geometry, InstancedBuffer, instantiate, log, mat4, Mat4, Material, Mesh, MeshRenderer, Node, Quat, Vec3, _decorator } from 'cc'; 3 | import { EDITOR } from 'cc/env'; 4 | import { getPhaseID } from '../../defines/pipeline'; 5 | import { debug, TechniqueNams } from '../../utils/draw'; 6 | import { InstanceManager } from './instace-manager'; 7 | import { InstanceForwardStage } from './instance-forward-stage'; 8 | const { ccclass, executeInEditMode, property, type } = _decorator; 9 | 10 | // const _shadowCasterPhaseID = getPhaseID('shadow-caster'); 11 | // const _tempVec3 = new Vec3; 12 | 13 | // @ccclass('InstanceBlockData') 14 | // export class InstanceBlockData extends CCObject { 15 | // @property 16 | // blockName = ''; 17 | 18 | // @property 19 | // _matrices: Mat4[] = []; 20 | 21 | // @property 22 | // get count () { 23 | // return this._matrices.length; 24 | // } 25 | 26 | // _instances: Map = new Map; 27 | 28 | // worldBound = new geometry.AABB 29 | // } 30 | 31 | @ccclass('InstanceData') 32 | export class InstanceData extends CCObject { 33 | @type(Mesh) 34 | mesh: Mesh | null = null; 35 | 36 | @type(Material) 37 | materials: Material[] = []; 38 | 39 | @property 40 | casterShadow = MeshRenderer.ShadowCastingMode.OFF; 41 | 42 | @property 43 | assetId = ''; 44 | 45 | @property 46 | _matrices: Mat4[] = []; 47 | } 48 | 49 | let _instanceID = 0; 50 | let _instanceTime = Date.now(); 51 | function getAssetID (asset: any) { 52 | if (!asset._instanceID_) { 53 | if (asset._uuid) { 54 | if (_instanceTime !== Date.now()) { 55 | _instanceID = 0; 56 | _instanceTime = Date.now(); 57 | } 58 | asset._instanceID_ = `${_instanceTime}_${_instanceID++}`; 59 | } 60 | else { 61 | asset._instanceID_ = asset._uuid; 62 | } 63 | } 64 | return asset._instanceID_; 65 | } 66 | 67 | interface IMeshRenderer { 68 | mesh: Mesh 69 | sharedMaterials: Material[] 70 | shadowCastingMode: MeshRenderer.ShadowCastingMode 71 | } 72 | 73 | @ccclass('InstanceObject') 74 | @executeInEditMode 75 | export class InstanceObject extends Component { 76 | @property 77 | blockSize = 100; 78 | 79 | @type(InstanceData) 80 | datas: InstanceData[] = []; 81 | 82 | addData (meshRenderer: IMeshRenderer, matrix: Mat4) { 83 | let mesh = meshRenderer.mesh; 84 | let materials = meshRenderer.sharedMaterials; 85 | let casterShadow = meshRenderer.shadowCastingMode; 86 | 87 | let datas = this.datas; 88 | let data: InstanceData | null = null; 89 | for (let i = 0; i < datas.length; i++) { 90 | let canMerge = true; 91 | if (datas[i].mesh !== mesh) { 92 | canMerge = false; 93 | continue; 94 | } 95 | 96 | if (materials.length !== datas[i].materials.length) { 97 | continue; 98 | } 99 | 100 | for (let mi = 0; mi < materials.length; mi++) { 101 | if (datas[i].materials[mi] !== materials[mi]) { 102 | canMerge = false; 103 | break; 104 | } 105 | } 106 | 107 | if (canMerge) { 108 | data = datas[i]; 109 | break; 110 | } 111 | 112 | } 113 | 114 | if (!data) { 115 | data = new InstanceData(); 116 | data.mesh = mesh; 117 | data.materials = materials as any; 118 | data.casterShadow = casterShadow; 119 | data.assetId = getAssetID(mesh); 120 | for (let i = 0; i < materials.length; i++) { 121 | data.assetId += '_' + getAssetID(materials[i]); 122 | } 123 | this.datas.push(data); 124 | } 125 | 126 | data._matrices.push(new Mat4(matrix)); 127 | 128 | InstanceManager.instance.dirty = true; 129 | } 130 | 131 | clear () { 132 | this.datas.length = 0; 133 | } 134 | 135 | // _rebuildIndex = 0; 136 | // _blockIndex = 0; 137 | 138 | // _startTime = 0; 139 | 140 | rebuild () { 141 | // log('Start rebuild instances...'); 142 | 143 | this.node.removeAllChildren(); 144 | 145 | // this._startTime = Date.now(); 146 | 147 | // this._rebuildIndex = 0; 148 | // this._blockIndex = 0; 149 | } 150 | 151 | start () { 152 | this.rebuild(); 153 | } 154 | 155 | onEnable () { 156 | if (InstanceManager.instance) { 157 | InstanceManager.instance.addObject(this); 158 | } 159 | } 160 | onDisable () { 161 | if (InstanceManager.instance) { 162 | InstanceManager.instance.removeObject(this); 163 | } 164 | } 165 | 166 | // update () { 167 | // let drawer = debug.drawer; 168 | 169 | // drawer.technique = TechniqueNams.transparent; 170 | // drawer.color.set(255, 255, 255, 30); 171 | 172 | // let object = this; 173 | // for (let di = 0; di < object.datas.length; di++) { 174 | // let blocks = object.datas[di].blocks; 175 | // for (let bbi = 0; bbi < blocks.length; bbi++) { 176 | // let block = blocks[bbi]; 177 | // // drawer.matrix.identity(); 178 | // // Mat4.translate(drawer.matrix, drawer.matrix, block.worldBound.center) 179 | // drawer.matrix.fromRTS(Quat.IDENTITY, block.worldBound.center, Vec3.ONE); 180 | // drawer.box({ 181 | // width: this.blockSize, 182 | // height: this.blockSize, 183 | // length: this.blockSize, 184 | // }) 185 | // } 186 | // } 187 | 188 | // if (this._rebuildIndex >= this.datas.length) { 189 | // if (this._startTime !== 0) { 190 | // log(`End rebuild instances : ${(Date.now() - this._startTime) / 1000}s.`); 191 | // this._startTime = 0; 192 | // } 193 | // return; 194 | // } 195 | 196 | // if (EDITOR) { 197 | // (window as any).cce.Engine.repaintInEditMode(); 198 | // } 199 | 200 | // let data = this.datas[this._rebuildIndex]; 201 | 202 | // log(`Merge Statics Mesh : ${this._rebuildIndex} - ${this.datas.length}, ${this._blockIndex} - ${data.blocks.length}`); 203 | 204 | // let mesh = data.mesh; 205 | // let meshName = mesh ? (mesh.name + '_' + mesh._uuid) : ''; 206 | 207 | // if (!mesh || !mesh.loaded) { 208 | // let failedNode = new Node('Failed - ' + meshName); 209 | // failedNode.parent = this.node; 210 | 211 | // this._rebuildIndex++; 212 | // this._blockIndex = 0; 213 | // return; 214 | // } 215 | 216 | // let meshChild = this.node.children[this._rebuildIndex]; 217 | // if (!meshChild) { 218 | // meshChild = new Node(meshName); 219 | 220 | // meshChild.parent = this.node; 221 | 222 | // let mr = meshChild.addComponent(MeshRenderer); 223 | // mr.mesh = mesh; 224 | 225 | // for (let mi = 0; mi < data.materials.length; mi++) { 226 | // mr.setMaterial(data.materials[mi], mi); 227 | // } 228 | 229 | // mr.enabled = false; 230 | // } 231 | 232 | // let block = data.blocks[this._blockIndex++]; 233 | // if (!block) { 234 | // this._rebuildIndex++; 235 | // this._blockIndex = 0; 236 | // return; 237 | // } 238 | 239 | // let mr = meshChild.getComponent(MeshRenderer); 240 | // let model = mr!.model!; 241 | // let subModels = model.subModels!; 242 | // for (let i = 0; i < subModels.length; i++) { 243 | // let subModel = subModels[i]; 244 | // let passes = subModel.passes 245 | // for (let pi = 0; pi < passes.length; pi++) { 246 | // let pass = passes[pi]; 247 | // if (pass.phase === _shadowCasterPhaseID) { 248 | // if (!model.castShadow) { 249 | // continue; 250 | // } 251 | // } 252 | // let instance = new InstancedBuffer(passes[pi]); 253 | 254 | // let matrices = block._matrices; 255 | // for (let mi = 0; mi < matrices.length; mi++) { 256 | // let matrix = matrices[mi]; 257 | // meshChild.worldMatrix.set(matrix); 258 | 259 | // (model as any)._transformUpdated = true; 260 | // model.updateUBOs(0); 261 | 262 | // instance.merge(subModel, model.instancedAttributes, pi); 263 | // } 264 | 265 | // let phase = passes[pi].phase; 266 | // let instances = block._instances.get(phase); 267 | // if (!instances) { 268 | // instances = []; 269 | // block._instances.set(phase, instances); 270 | // } 271 | // instances.push(instance); 272 | // } 273 | // } 274 | // } 275 | } 276 | -------------------------------------------------------------------------------- /stages/instance/instance-object.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "95521f78-e4bf-425a-a8ce-46558ec53a8e", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "importAsPlugin": false, 10 | "moduleId": "project:///assets/libs/advanced-pipeline/stages/instance/instance-object.js", 11 | "importerSettings": 4 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /stages/instance/instance-shadow-stage.ts: -------------------------------------------------------------------------------- 1 | import { _decorator, ShadowStage, ForwardPipeline, gfx, renderer, GFXColor } from "cc"; 2 | import { Layers } from '../../defines/layer'; 3 | import { getPhaseID, pipeline } from '../../defines/pipeline'; 4 | import { InstanceManager } from './instace-manager'; 5 | import { InstanceObjectQueue } from './instanced-object-queue'; 6 | 7 | const { ccclass, property } = _decorator; 8 | const { SetIndex, UBOShadow } = pipeline; 9 | 10 | const colors: GFXColor[] = [{ x: 1, y: 1, z: 1, w: 1 }]; 11 | 12 | const _phase = getPhaseID('shadow-caster'); 13 | 14 | 15 | @ccclass("InstanceShadowStage") 16 | export class InstanceShadowStage extends ShadowStage { 17 | _name = 'InstanceShadowStage' 18 | 19 | _instanceObjectQueue = new InstanceObjectQueue(); 20 | 21 | resize () { 22 | 23 | } 24 | 25 | updateQueue (cmdBuff: gfx.CommandBuffer, camera: renderer.scene.Camera) { 26 | if (!(camera.visibility & Layers.Instance)) { 27 | return; 28 | } 29 | 30 | let instancedQueue = this._instanceObjectQueue; 31 | instancedQueue.queue.clear(); 32 | 33 | instancedQueue.addBlocks(((globalThis as any).InstanceManager as typeof InstanceManager).instance.getBlocks(), [camera.frustum], _phase); 34 | 35 | instancedQueue.uploadBuffers(cmdBuff); 36 | } 37 | 38 | render (camera: renderer.scene.Camera) { 39 | if (!(this as any)._light || !(this as any)._shadowFrameBuffer) { return; } 40 | 41 | const pipeline = this._pipeline as ForwardPipeline; 42 | const device = pipeline.device; 43 | const cmdBuff = pipeline.commandBuffers[0]; 44 | 45 | const additiveShadowQueue = (this as any)._additiveShadowQueue; 46 | additiveShadowQueue.gatherLightPasses((this as any)._light, cmdBuff); 47 | 48 | this.updateQueue(cmdBuff, camera); 49 | 50 | const vp = camera.viewport; 51 | 52 | // render area is not oriented 53 | const shadowInfo = pipeline.shadows; 54 | const shadowMapSize = shadowInfo.size; 55 | const w = shadowMapSize.x; 56 | const h = shadowMapSize.y; 57 | 58 | let renderArea = (this as any)._renderArea!; 59 | renderArea.x = vp.x * w; 60 | renderArea.y = vp.y * h; 61 | renderArea.width = vp.width * w * pipeline.shadingScale; 62 | renderArea.height = vp.height * h * pipeline.shadingScale; 63 | 64 | const shadowFrameBuffer = (this as any)._shadowFrameBuffer as gfx.Framebuffer; 65 | const renderPass = shadowFrameBuffer.renderPass; 66 | 67 | cmdBuff.beginRenderPass(renderPass, shadowFrameBuffer, renderArea, 68 | colors, camera.clearDepth, camera.clearStencil); 69 | 70 | cmdBuff.bindDescriptorSet(SetIndex.GLOBAL, pipeline.descriptorSet); 71 | 72 | additiveShadowQueue.recordCommandBuffer(device, renderPass, cmdBuff); 73 | this._instanceObjectQueue.recordCommandBuffer(device, renderPass, cmdBuff); 74 | 75 | cmdBuff.endRenderPass(); 76 | } 77 | 78 | rebuild () { 79 | 80 | } 81 | 82 | destroy () { 83 | 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /stages/instance/instance-shadow-stage.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "8e31f6c9-ae7c-498f-813d-acd9faa7725a", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "importAsPlugin": false, 10 | "moduleId": "project:///assets/libs/advanced-pipeline/stages/instance/instance-shadow-stage.js", 11 | "importerSettings": 4 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /stages/instance/instanced-object-queue.ts: -------------------------------------------------------------------------------- 1 | import { geometry, gfx, InstancedBuffer, PipelineStateManager, renderer } from 'cc'; 2 | import { pipeline } from '../../defines/pipeline'; 3 | import { InstanceBlockData } from './instance-block'; 4 | 5 | const { DSPool, ShaderPool } = renderer; 6 | const { SetIndex } = pipeline; 7 | 8 | 9 | export class InstanceObjectQueue { 10 | 11 | /** 12 | * @en A set of instanced buffer 13 | * @zh Instance 合批缓存集合。 14 | */ 15 | public queue = new Set(); 16 | 17 | /** 18 | * @en Clear the render queue 19 | * @zh 清空渲染队列。 20 | */ 21 | public clear () { 22 | const it = this.queue.values(); let res = it.next(); 23 | while (!res.done) { 24 | res.value.clear(); 25 | res = it.next(); 26 | } 27 | this.queue.clear(); 28 | } 29 | 30 | public uploadBuffers (cmdBuff: gfx.CommandBuffer) { 31 | const it = this.queue.values(); let res = it.next(); 32 | while (!res.done) { 33 | if (res.value.hasPendingModels) res.value.uploadBuffers(cmdBuff); 34 | res = it.next(); 35 | } 36 | } 37 | 38 | /** 39 | * @en Record command buffer for the current queue 40 | * @zh 记录命令缓冲。 41 | * @param cmdBuff The command buffer to store the result 42 | */ 43 | public recordCommandBuffer (device: gfx.Device, renderPass: gfx.RenderPass, cmdBuff: gfx.CommandBuffer) { 44 | const it = this.queue.values(); let res = it.next(); 45 | while (!res.done) { 46 | const { instances, pass, hasPendingModels } = res.value; 47 | if (hasPendingModels) { 48 | cmdBuff.bindDescriptorSet(SetIndex.MATERIAL, pass.descriptorSet); 49 | let lastPSO: gfx.PipelineState | null = null; 50 | for (let b = 0; b < instances.length; ++b) { 51 | const instance = instances[b]; 52 | if (!instance.count) { continue; } 53 | const shader = ShaderPool.get(instance.hShader); 54 | const pso = PipelineStateManager.getOrCreatePipelineState(device, pass, shader, renderPass, instance.ia); 55 | if (lastPSO !== pso) { 56 | cmdBuff.bindPipelineState(pso); 57 | lastPSO = pso; 58 | } 59 | cmdBuff.bindDescriptorSet(SetIndex.LOCAL, DSPool.get(instance.hDescriptorSet), res.value.dynamicOffsets); 60 | cmdBuff.bindInputAssembler(instance.ia); 61 | cmdBuff.draw(instance.ia); 62 | } 63 | } 64 | res = it.next(); 65 | } 66 | } 67 | 68 | public addBlocks (blocks: InstanceBlockData[], frustums: geometry.Frustum[], phase: number) { 69 | for (let bbi = 0; bbi < blocks.length; bbi++) { 70 | let block = blocks[bbi]; 71 | 72 | let phaseBundle = block._instances.get(phase); 73 | if (!phaseBundle) { 74 | continue; 75 | } 76 | 77 | let shouldAdd = true; 78 | for (let fi = 0; fi < frustums.length; fi++) { 79 | frustums[fi].accurate = true; 80 | if (!geometry.intersect.aabbFrustumAccurate(block.worldBound, frustums[fi])) { 81 | shouldAdd = false; 82 | break; 83 | } 84 | } 85 | 86 | if (!shouldAdd) { 87 | continue; 88 | } 89 | 90 | phaseBundle.forEach(instance => { 91 | this.queue.add(instance); 92 | }); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /stages/instance/instanced-object-queue.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "fd9db788-7820-44fc-9eeb-7cb6fe65ab7e", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "importAsPlugin": false, 10 | "moduleId": "project:///assets/libs/advanced-pipeline/stages/instance/instanced-object-queue.js", 11 | "importerSettings": 4 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /stages/post-process.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.1.0", 3 | "importer": "directory", 4 | "imported": true, 5 | "uuid": "1ae86b41-47f7-4eea-9051-808a503e6b9c", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "compressionType": {}, 10 | "isRemoteBundle": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /stages/post-process/editor.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.1.0", 3 | "importer": "directory", 4 | "imported": true, 5 | "uuid": "6b27b4f4-890a-4d01-986e-f058f0975351", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "compressionType": {}, 10 | "isRemoteBundle": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /stages/post-process/editor/post-process-renderer-materials.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | 3 | import { ccenum, Material, AssetLibrary, game, Game, assetManager, error } from "cc"; 4 | import { fse, globby, path, projectPath } from '../../../utils/editor'; 5 | 6 | let postProcessMaterials: Map = new Map; 7 | 8 | function load (name: string, uuid: string) { 9 | game.on(Game.EVENT_ENGINE_INITED, () => { 10 | assetManager.loadAny(uuid, (err, asset) => { 11 | if (err) { 12 | error(err); 13 | return; 14 | } 15 | postProcessMaterials.set(name, asset); 16 | }) 17 | }) 18 | } 19 | 20 | if (CC_EDITOR) { 21 | let postProcessMaterialPaths = globby.sync(path.join(projectPath, '**/post-process/**/*.mtl')); 22 | for (let i = 0; i < postProcessMaterialPaths.length; i++) { 23 | let mp = postProcessMaterialPaths[i]; 24 | let name = path.basename(mp).replace(path.extname(mp), ''); 25 | 26 | let metaPath = mp + '.meta'; 27 | if (!fse.existsSync(metaPath)) { 28 | continue; 29 | } 30 | let json; 31 | try { 32 | json = fse.readJSONSync(metaPath); 33 | } 34 | catch (err) { 35 | error(err); 36 | } 37 | if (!json) { 38 | continue; 39 | } 40 | postProcessMaterials.set(name, null); 41 | 42 | let uuid = json.uuid; 43 | load(name, uuid); 44 | } 45 | } 46 | 47 | export default postProcessMaterials; 48 | -------------------------------------------------------------------------------- /stages/post-process/editor/post-process-renderer-materials.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "c949724f-7b17-4805-a81a-c5c913e20b02", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "importAsPlugin": false, 10 | "moduleId": "project:///assets/shader-lib/post-process/editor/post-process-renderer-materials.js" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /stages/post-process/effects.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.1.0", 3 | "importer": "directory", 4 | "imported": true, 5 | "uuid": "56b3ca66-a0d2-4bba-8df7-302b20ffd18c", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "compressionType": {}, 10 | "isRemoteBundle": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /stages/post-process/effects/bloom.effect: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. 2 | 3 | CCEffect %{ 4 | temporaries: 5 | d1: &d1 { depthTest: false, depthWrite: false } 6 | b1: &b1 7 | targets: 8 | - blend: true 9 | blendSrc: src_alpha 10 | blendDst: one_minus_src_alpha 11 | blendSrcAlpha: src_alpha 12 | blendDstAlpha: one_minus_src_alpha 13 | 14 | techniques: 15 | - name: normal 16 | passes: 17 | - name: prefilter 18 | vert: post-process-vs:vert 19 | frag: prefilter4:frag 20 | properties: 21 | threshold: { value: 0.5 } 22 | softKnee: { value: 0.5 } 23 | rasterizerState: 24 | cullMode: none 25 | - name: downsample 26 | vert: post-process-vs:vert 27 | frag: downsample4:frag 28 | postEffect: 29 | output: { size: [0.5, 0.5], name: pe_custom_texture_1 } 30 | rasterizerState: 31 | cullMode: none 32 | - name: upsample 33 | vert: post-process-vs:vert 34 | frag: upsample:frag 35 | depthStencilState: *d1 36 | blendState: *b1 37 | properties: 38 | sampleScale: { value: 1 } 39 | rasterizerState: 40 | cullMode: none 41 | - name: high 42 | passes: 43 | - name: prefilter 44 | vert: post-process-vs:vert 45 | frag: prefilter13:frag 46 | properties: 47 | threshold: { value: 0.5 } 48 | softKnee: { value: 0.5 } 49 | rasterizerState: 50 | cullMode: none 51 | - name: downsample 52 | vert: post-process-vs:vert 53 | frag: downsample13:frag 54 | postEffect: 55 | output: { size: [0.5, 0.5], name: pe_custom_texture_1 } 56 | rasterizerState: 57 | cullMode: none 58 | - name: upsample 59 | vert: post-process-vs:vert 60 | frag: upsample:frag 61 | depthStencilState: *d1 62 | blendState: *b1 63 | properties: 64 | sampleScale: { value: 1 } 65 | rasterizerState: 66 | cullMode: none 67 | }% 68 | 69 | CCProgram bloom %{ 70 | #include 71 | 72 | #define EPSILON 1.0e-4 73 | 74 | vec4 QuadraticThreshold(vec4 color, float threshold, float softKnee) 75 | { 76 | vec3 curve = vec3(threshold - softKnee, softKnee * 2.0, 0.25 / softKnee); 77 | 78 | // Pixel brightness 79 | float br = max(max(color.r, color.g), color.b); 80 | 81 | // Under-threshold part: quadratic curve 82 | float rq = clamp(br - curve.x, 0.0, curve.y); 83 | rq = curve.z * rq * rq; 84 | 85 | // Combine and apply the brightness response curve. 86 | color *= max(rq, br - threshold) / max(br, EPSILON); 87 | 88 | // color *= clamp(br - threshold, 0.0, 1.0); 89 | 90 | return color; 91 | } 92 | 93 | // Better, temporally stable box filtering 94 | // [Jimenez14] http://goo.gl/eomGso 95 | // . . . . . . . 96 | // . A . B . C . 97 | // . . D . E . . 98 | // . F . G . H . 99 | // . . I . J . . 100 | // . K . L . M . 101 | // . . . . . . . 102 | vec4 DownsampleBox13Tap(sampler2D tex, vec2 uv, vec2 texelSize) 103 | { 104 | vec4 A = texture(tex, uv + texelSize * vec2(-1.0, -1.0)); 105 | vec4 B = texture(tex, uv + texelSize * vec2( 0.0, -1.0)); 106 | vec4 C = texture(tex, uv + texelSize * vec2( 1.0, -1.0)); 107 | vec4 D = texture(tex, uv + texelSize * vec2(-0.5, -0.5)); 108 | vec4 E = texture(tex, uv + texelSize * vec2( 0.5, -0.5)); 109 | vec4 F = texture(tex, uv + texelSize * vec2(-1.0, 0.0)); 110 | vec4 G = texture(tex, uv ); 111 | vec4 H = texture(tex, uv + texelSize * vec2( 1.0, 0.0)); 112 | vec4 I = texture(tex, uv + texelSize * vec2(-0.5, 0.5)); 113 | vec4 J = texture(tex, uv + texelSize * vec2( 0.5, 0.5)); 114 | vec4 K = texture(tex, uv + texelSize * vec2(-1.0, 1.0)); 115 | vec4 L = texture(tex, uv + texelSize * vec2( 0.0, 1.0)); 116 | vec4 M = texture(tex, uv + texelSize * vec2( 1.0, 1.0)); 117 | 118 | vec2 div = (1.0 / 4.0) * vec2(0.5, 0.125); 119 | 120 | vec4 o = (D + E + I + J) * div.x; 121 | o += (A + B + G + F) * div.y; 122 | o += (B + C + H + G) * div.y; 123 | o += (F + G + L + K) * div.y; 124 | o += (G + H + M + L) * div.y; 125 | 126 | return o; 127 | } 128 | 129 | // Standard box filtering 130 | vec4 DownsampleBox4Tap(sampler2D tex, vec2 uv, vec2 texelSize) 131 | { 132 | vec4 d = texelSize.xyxy * vec4(-1.0, -1.0, 1.0, 1.0); 133 | 134 | vec4 s; 135 | s = texture(tex, uv + d.xy); 136 | s += texture(tex, uv + d.zy); 137 | s += texture(tex, uv + d.xw); 138 | s += texture(tex, uv + d.zw); 139 | 140 | return s * (1.0 / 4.0); 141 | } 142 | 143 | vec4 Prefilter(vec4 color, vec2 uv, float threshold, float softKnee) 144 | { 145 | // color = min(65472.0, color); // clamp to max 146 | color = QuadraticThreshold(color, threshold, softKnee); 147 | return color; 148 | } 149 | 150 | // Standard box filtering 151 | vec4 UpsampleBox(sampler2D tex, vec2 uv, vec2 texelSize, float sampleScale) 152 | { 153 | vec4 d = texelSize.xyxy * vec4(-1.0, -1.0, 1.0, 1.0) * sampleScale; 154 | 155 | vec4 s; 156 | s = texture(tex, uv + d.xy); 157 | s += texture(tex, uv + d.zy); 158 | s += texture(tex, uv + d.xw); 159 | s += texture(tex, uv + d.zw); 160 | 161 | return s * (1.0 / 4.0); 162 | } 163 | 164 | vec4 Combine(vec4 color, sampler2D originTexture, vec2 uv) 165 | { 166 | return color + texture(originTexture, uv); 167 | } 168 | }% 169 | 170 | CCProgram prefilter4 %{ 171 | precision highp float; 172 | #include 173 | 174 | in vec2 v_uv; 175 | 176 | uniform Bloom { 177 | float threshold; 178 | float softKnee; 179 | }; 180 | 181 | vec4 frag () { 182 | vec4 color = DownsampleBox4Tap(pe_input_texture, v_uv, cc_screenSize.zw); 183 | return Prefilter(color, v_uv, threshold, softKnee); 184 | } 185 | }% 186 | 187 | CCProgram downsample4 %{ 188 | precision highp float; 189 | #include 190 | 191 | in vec2 v_uv; 192 | 193 | vec4 frag () { 194 | return DownsampleBox4Tap(pe_input_texture, v_uv, cc_screenSize.zw); 195 | } 196 | }% 197 | 198 | CCProgram prefilter13 %{ 199 | precision highp float; 200 | #include 201 | 202 | in vec2 v_uv; 203 | 204 | uniform Bloom { 205 | float threshold; 206 | float softKnee; 207 | }; 208 | 209 | vec4 frag () { 210 | vec4 color = DownsampleBox13Tap(pe_input_texture, v_uv, cc_screenSize.zw); 211 | return Prefilter(color, v_uv, threshold, softKnee); 212 | } 213 | }% 214 | 215 | CCProgram downsample13 %{ 216 | precision highp float; 217 | #include 218 | 219 | in vec2 v_uv; 220 | 221 | vec4 frag () { 222 | return DownsampleBox13Tap(pe_input_texture, v_uv, cc_screenSize.zw); 223 | } 224 | }% 225 | 226 | CCProgram upsample %{ 227 | precision highp float; 228 | #include 229 | 230 | in vec2 v_uv; 231 | 232 | uniform Bloom { 233 | float sampleScale; 234 | }; 235 | 236 | vec4 frag () { 237 | vec4 bloom = UpsampleBox(pe_custom_texture_1, v_uv, cc_screenSize.zw, sampleScale); 238 | return Combine(bloom, pe_origin_texture, v_uv); 239 | } 240 | }% -------------------------------------------------------------------------------- /stages/post-process/effects/bloom.effect.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.4.4", 3 | "importer": "effect", 4 | "imported": true, 5 | "uuid": "7778c69f-63d0-4539-8f34-c7a0368174e6", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /stages/post-process/effects/bloom.mtl: -------------------------------------------------------------------------------- 1 | { 2 | "__type__": "cc.Material", 3 | "_name": "", 4 | "_objFlags": 0, 5 | "_native": "", 6 | "_effectAsset": { 7 | "__uuid__": "7778c69f-63d0-4539-8f34-c7a0368174e6" 8 | }, 9 | "_techIdx": 0, 10 | "_defines": [ 11 | {}, 12 | {}, 13 | {} 14 | ], 15 | "_states": [ 16 | { 17 | "blendState": { 18 | "targets": [ 19 | {} 20 | ] 21 | }, 22 | "depthStencilState": {}, 23 | "rasterizerState": {} 24 | }, 25 | { 26 | "blendState": { 27 | "targets": [ 28 | {} 29 | ] 30 | }, 31 | "depthStencilState": {}, 32 | "rasterizerState": {} 33 | }, 34 | { 35 | "blendState": { 36 | "targets": [ 37 | {} 38 | ] 39 | }, 40 | "depthStencilState": {}, 41 | "rasterizerState": {} 42 | } 43 | ], 44 | "_props": [ 45 | {}, 46 | {}, 47 | {} 48 | ] 49 | } -------------------------------------------------------------------------------- /stages/post-process/effects/bloom.mtl.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.9", 3 | "importer": "material", 4 | "imported": true, 5 | "uuid": "93e2307f-8d59-4af6-9ec7-370a8917055c", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /stages/post-process/effects/bloom.ts: -------------------------------------------------------------------------------- 1 | import { Color, _decorator } from 'cc'; 2 | import { PostEffectBase, effect, PassDefine, effectProperty } from '../post-effect-base'; 3 | const { property, ccclass } = _decorator 4 | 5 | let bloomDefines = new Map() 6 | bloomDefines.set(1, new PassDefine('pe_custom_texture_1')) 7 | bloomDefines.set(2, new PassDefine('', ['pe_custom_texture_1'])) 8 | 9 | @effect 10 | @ccclass('BloomEffect') 11 | export class BloomEffect extends PostEffectBase { 12 | static effectName = 'bloom'; 13 | static passDefines = bloomDefines; 14 | 15 | @property 16 | @effectProperty 17 | _threshold = 0.5; 18 | 19 | @property 20 | @effectProperty 21 | _softKnee = 0.5; 22 | 23 | @property 24 | @effectProperty 25 | _sampleScale = 1 26 | } 27 | -------------------------------------------------------------------------------- /stages/post-process/effects/bloom.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "50a8e9cb-3722-43a6-b6cc-776d482f4c8b", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": {} 9 | } 10 | -------------------------------------------------------------------------------- /stages/post-process/effects/chunk.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "0.0.1", 3 | "importer": "*", 4 | "imported": true, 5 | "uuid": "fa91001c-d4c5-4bfb-be50-398fff28b2ad", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": {} 9 | } 10 | -------------------------------------------------------------------------------- /stages/post-process/effects/color-grading.effect: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. 2 | 3 | CCEffect %{ 4 | temporaries: 5 | d1: &d1 { depthTest: false, depthWrite: false } 6 | b1: &b1 7 | targets: 8 | - blend: true 9 | blendSrc: src_alpha 10 | blendDst: one_minus_src_alpha 11 | blendSrcAlpha: src_alpha 12 | blendDstAlpha: one_minus_src_alpha 13 | techniques: 14 | - passes: 15 | - vert: post-process-vs:vert 16 | frag: fs:frag 17 | properties: 18 | brightness: { value: 1.0 } 19 | saturation: { value: 1.0 } 20 | contrast: { value: 1.0 } 21 | depthStencilState: *d1 22 | blendState: *b1 23 | rasterizerState: 24 | cullMode: none 25 | }% 26 | 27 | 28 | CCProgram fs %{ 29 | precision highp float; 30 | #include 31 | in vec2 v_uv; 32 | 33 | uniform Vignette { 34 | float brightness; 35 | float saturation; 36 | float contrast; 37 | }; 38 | 39 | float vignette(vec2 uv, float a, float b) { 40 | float len = length(uv - 0.5); 41 | return smoothstep(a, b, len); 42 | } 43 | 44 | vec4 frag () { 45 | vec4 color = texture(pe_input_texture, v_uv); 46 | 47 | // brightness 48 | color.rgb *= brightness; 49 | 50 | // saturation 51 | vec3 luminance = vec3(dot(color.rgb, vec3(0.2126729, 0.7151522, 0.0721750))); 52 | color.rgb = mix(luminance, color.rgb, saturation); 53 | 54 | // contrast 55 | vec3 grayColor = vec3(0.5, 0.5, 0.5); 56 | color.rgb = mix(grayColor, color.rgb, contrast); 57 | 58 | return color; 59 | } 60 | }% -------------------------------------------------------------------------------- /stages/post-process/effects/color-grading.effect.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.4.4", 3 | "importer": "effect", 4 | "imported": true, 5 | "uuid": "bae430bf-87a2-4118-be48-d658287e8f75", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /stages/post-process/effects/color-grading.mtl: -------------------------------------------------------------------------------- 1 | { 2 | "__type__": "cc.Material", 3 | "_name": "", 4 | "_objFlags": 0, 5 | "_native": "", 6 | "_effectAsset": { 7 | "__uuid__": "bae430bf-87a2-4118-be48-d658287e8f75" 8 | }, 9 | "_techIdx": 0, 10 | "_defines": [ 11 | {} 12 | ], 13 | "_states": [ 14 | { 15 | "blendState": { 16 | "targets": [ 17 | {} 18 | ] 19 | }, 20 | "depthStencilState": {}, 21 | "rasterizerState": {} 22 | } 23 | ], 24 | "_props": [ 25 | { 26 | "brightness": 2, 27 | "saturation": 3 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /stages/post-process/effects/color-grading.mtl.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.9", 3 | "importer": "material", 4 | "imported": true, 5 | "uuid": "083cb309-fa26-4e9f-8c30-de33a7a81051", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /stages/post-process/effects/color-grading.ts: -------------------------------------------------------------------------------- 1 | import { Color, _decorator } from 'cc'; 2 | import { PostEffectBase, effect, effectProperty } from '../post-effect-base'; 3 | const { property, ccclass } = _decorator 4 | 5 | @effect 6 | @ccclass('ColorGradingEffect') 7 | export class ColorGradingEffect extends PostEffectBase { 8 | static effectName = 'color-grading'; 9 | 10 | @property 11 | @effectProperty 12 | _brightness = 1.0; 13 | 14 | @property 15 | @effectProperty 16 | _saturation = 1.0; 17 | 18 | @property 19 | @effectProperty 20 | _contrast = 1.0; 21 | } 22 | -------------------------------------------------------------------------------- /stages/post-process/effects/color-grading.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "a4a6e38c-2a91-44b4-be49-dedf8e868d85", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": {} 9 | } 10 | -------------------------------------------------------------------------------- /stages/post-process/effects/fxaa.effect: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. 2 | 3 | CCEffect %{ 4 | techniques: 5 | - name: normal 6 | passes: 7 | - vert: normal-vs:vert 8 | frag: normal-fs:frag 9 | - name: high 10 | passes: 11 | - vert: post-process-vs:vert 12 | frag: better-fs:frag 13 | }% 14 | 15 | 16 | CCProgram fxaa %{ 17 | // https://github.com/mattdesl/glsl-fxaa/blob/master/index.glsl 18 | 19 | void texcoords(vec2 fragCoord, vec2 resolution, 20 | out vec2 v_rgbNW, out vec2 v_rgbNE, 21 | out vec2 v_rgbSW, out vec2 v_rgbSE, 22 | out vec2 v_rgbM) { 23 | vec2 inverseVP = 1.0 / resolution.xy; 24 | v_rgbNW = (fragCoord + vec2(-1.0, -1.0)) * inverseVP; 25 | v_rgbNE = (fragCoord + vec2(1.0, -1.0)) * inverseVP; 26 | v_rgbSW = (fragCoord + vec2(-1.0, 1.0)) * inverseVP; 27 | v_rgbSE = (fragCoord + vec2(1.0, 1.0)) * inverseVP; 28 | v_rgbM = vec2(fragCoord * inverseVP); 29 | } 30 | 31 | #define FXAA_REDUCE_MIN (1.0/ 128.0) 32 | #define FXAA_REDUCE_MUL (1.0 / 8.0) 33 | #define FXAA_SPAN_MAX 8.0 34 | 35 | //optimized version for mobile, where dependent 36 | //texture reads can be a bottleneck 37 | vec4 fxaa(sampler2D tex, vec2 fragCoord, vec2 resolution, 38 | vec2 v_rgbNW, vec2 v_rgbNE, 39 | vec2 v_rgbSW, vec2 v_rgbSE, 40 | vec2 v_rgbM) { 41 | vec4 color; 42 | mediump vec2 inverseVP = vec2(1.0 / resolution.x, 1.0 / resolution.y); 43 | vec3 rgbNW = texture(tex, v_rgbNW).xyz; 44 | vec3 rgbNE = texture(tex, v_rgbNE).xyz; 45 | vec3 rgbSW = texture(tex, v_rgbSW).xyz; 46 | vec3 rgbSE = texture(tex, v_rgbSE).xyz; 47 | vec4 texColor = texture(tex, v_rgbM); 48 | vec3 rgbM = texColor.xyz; 49 | vec3 luma = vec3(0.299, 0.587, 0.114); 50 | float lumaNW = dot(rgbNW, luma); 51 | float lumaNE = dot(rgbNE, luma); 52 | float lumaSW = dot(rgbSW, luma); 53 | float lumaSE = dot(rgbSE, luma); 54 | float lumaM = dot(rgbM, luma); 55 | float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); 56 | float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); 57 | 58 | mediump vec2 dir; 59 | dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); 60 | dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); 61 | 62 | float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * 63 | (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); 64 | 65 | float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce); 66 | dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), 67 | max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), 68 | dir * rcpDirMin)) * inverseVP; 69 | 70 | vec3 rgbA = 0.5 * ( 71 | texture(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz + 72 | texture(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz); 73 | vec3 rgbB = rgbA * 0.5 + 0.25 * ( 74 | texture(tex, fragCoord * inverseVP + dir * -0.5).xyz + 75 | texture(tex, fragCoord * inverseVP + dir * 0.5).xyz); 76 | 77 | float lumaB = dot(rgbB, luma); 78 | if ((lumaB < lumaMin) || (lumaB > lumaMax)) 79 | color = vec4(rgbA, texColor.a); 80 | else 81 | color = vec4(rgbB, texColor.a); 82 | return color; 83 | } 84 | }% 85 | 86 | CCProgram normal-vs %{ 87 | precision highp float; 88 | 89 | #include 90 | #include 91 | #include 92 | 93 | #include 94 | 95 | in vec3 a_position; 96 | 97 | in vec2 a_texCoord; 98 | out vec2 v_uv; 99 | 100 | out vec2 v_rgbNW; 101 | out vec2 v_rgbNE; 102 | out vec2 v_rgbSW; 103 | out vec2 v_rgbSE; 104 | out vec2 v_rgbM; 105 | 106 | vec4 vert () { 107 | v_uv = a_texCoord; 108 | vec2 fragCoord = v_uv * cc_screenSize.xy; 109 | texcoords(fragCoord, cc_screenSize.xy, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM); 110 | return vec4(a_position, 1); 111 | } 112 | }% 113 | 114 | 115 | CCProgram normal-fs %{ 116 | precision highp float; 117 | 118 | #include 119 | #include 120 | 121 | in vec2 v_uv; 122 | 123 | in vec2 v_rgbNW; 124 | in vec2 v_rgbNE; 125 | in vec2 v_rgbSW; 126 | in vec2 v_rgbSE; 127 | in vec2 v_rgbM; 128 | 129 | vec4 frag () { 130 | vec2 fragCoord = v_uv * cc_screenSize.xy; 131 | return fxaa(pe_input_texture, fragCoord, cc_screenSize.xy, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM); 132 | } 133 | }% 134 | 135 | CCProgram better-fs %{ 136 | precision highp float; 137 | 138 | #include 139 | #include 140 | 141 | in vec2 v_uv; 142 | 143 | vec4 frag () { 144 | mediump vec2 v_rgbNW; 145 | mediump vec2 v_rgbNE; 146 | mediump vec2 v_rgbSW; 147 | mediump vec2 v_rgbSE; 148 | mediump vec2 v_rgbM; 149 | vec2 fragCoord = v_uv * cc_screenSize.xy; 150 | texcoords(fragCoord, cc_screenSize.xy, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM); 151 | return fxaa(pe_input_texture, fragCoord, cc_screenSize.xy, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM); 152 | } 153 | }% -------------------------------------------------------------------------------- /stages/post-process/effects/fxaa.effect.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.4.4", 3 | "importer": "effect", 4 | "imported": true, 5 | "uuid": "aa921365-3c8e-43dc-a86f-24b5bb87cdf4", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /stages/post-process/effects/fxaa.mtl: -------------------------------------------------------------------------------- 1 | { 2 | "__type__": "cc.Material", 3 | "_name": "", 4 | "_objFlags": 0, 5 | "_native": "", 6 | "_effectAsset": { 7 | "__uuid__": "aa921365-3c8e-43dc-a86f-24b5bb87cdf4" 8 | }, 9 | "_techIdx": 0, 10 | "_defines": [ 11 | {} 12 | ], 13 | "_states": [ 14 | { 15 | "blendState": { 16 | "targets": [ 17 | {} 18 | ] 19 | }, 20 | "depthStencilState": {}, 21 | "rasterizerState": {} 22 | } 23 | ], 24 | "_props": [ 25 | {} 26 | ] 27 | } -------------------------------------------------------------------------------- /stages/post-process/effects/fxaa.mtl.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.9", 3 | "importer": "material", 4 | "imported": true, 5 | "uuid": "5344e891-ab14-48a3-9be8-d79b34b85925", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /stages/post-process/effects/post-process-vs.chunk: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | #include 3 | #include 4 | 5 | in vec3 a_position; 6 | in vec2 a_texCoord; 7 | out vec2 v_uv; 8 | 9 | vec4 vert () { 10 | vec4 pos = vec4(a_position, 1); 11 | v_uv = a_texCoord * cc_screenScale.xy; 12 | 13 | return pos; 14 | } 15 | -------------------------------------------------------------------------------- /stages/post-process/effects/post-process-vs.chunk.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.0", 3 | "importer": "effect-header", 4 | "imported": true, 5 | "uuid": "8f320cc2-3731-4ff1-b2e8-486c7d9cc101", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": {} 9 | } 10 | -------------------------------------------------------------------------------- /stages/post-process/effects/post-process.chunk: -------------------------------------------------------------------------------- 1 | 2 | uniform sampler2D pe_origin_texture; 3 | uniform sampler2D pe_input_texture; 4 | uniform sampler2D pe_custom_texture_1; 5 | uniform sampler2D pe_custom_texture_2; 6 | 7 | #include 8 | -------------------------------------------------------------------------------- /stages/post-process/effects/post-process.chunk.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.0", 3 | "importer": "effect-header", 4 | "imported": true, 5 | "uuid": "06c5f51e-0d87-4c3e-8520-bb7e8a0958b3", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": {} 9 | } 10 | -------------------------------------------------------------------------------- /stages/post-process/effects/tonemap.effect: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. 2 | 3 | CCEffect %{ 4 | temporaries: 5 | d1: &d1 { depthTest: false, depthWrite: false } 6 | b1: &b1 7 | targets: 8 | - blend: true 9 | blendSrc: src_alpha 10 | blendDst: one_minus_src_alpha 11 | blendSrcAlpha: src_alpha 12 | blendDstAlpha: one_minus_src_alpha 13 | 14 | 15 | techniques: 16 | - passes: 17 | - vert: post-process-vs:vert 18 | frag: fs:frag 19 | depthStencilState: *d1 20 | blendState: *b1 21 | rasterizerState: 22 | cullMode: none 23 | }% 24 | 25 | CCProgram fs %{ 26 | precision highp float; 27 | #include 28 | #include 29 | #include 30 | in vec2 v_uv; 31 | 32 | vec4 frag () { 33 | vec4 color = texture(pe_input_texture, v_uv); 34 | 35 | #if CC_USE_HDR 36 | color.rgb = ACESToneMap(color.rgb); 37 | color.rgb = LinearToSRGB(color.rgb); 38 | #endif 39 | 40 | return color; 41 | } 42 | }% 43 | -------------------------------------------------------------------------------- /stages/post-process/effects/tonemap.effect.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.4.4", 3 | "importer": "effect", 4 | "imported": true, 5 | "uuid": "0263e173-ada4-4e9a-ab6f-48dc3ce49a24", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /stages/post-process/effects/tonemap.mtl: -------------------------------------------------------------------------------- 1 | { 2 | "__type__": "cc.Material", 3 | "_name": "", 4 | "_objFlags": 0, 5 | "_native": "", 6 | "_effectAsset": { 7 | "__uuid__": "0263e173-ada4-4e9a-ab6f-48dc3ce49a24" 8 | }, 9 | "_techIdx": 0, 10 | "_defines": [ 11 | {} 12 | ], 13 | "_states": [ 14 | { 15 | "rasterizerState": {}, 16 | "depthStencilState": {}, 17 | "blendState": { 18 | "targets": [ 19 | {} 20 | ] 21 | } 22 | } 23 | ], 24 | "_props": [ 25 | {} 26 | ] 27 | } -------------------------------------------------------------------------------- /stages/post-process/effects/tonemap.mtl.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.9", 3 | "importer": "material", 4 | "imported": true, 5 | "uuid": "5e119378-ba5b-4e9d-9182-6f2bde47eae1", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /stages/post-process/effects/tonemap.ts: -------------------------------------------------------------------------------- 1 | import { Color, _decorator } from 'cc'; 2 | import { PostEffectBase, effect } from '../post-effect-base'; 3 | const { property, ccclass } = _decorator 4 | 5 | @effect 6 | @ccclass('TonemapEffect') 7 | export class TonemapEffect extends PostEffectBase { 8 | static effectName = 'tonemap'; 9 | } 10 | -------------------------------------------------------------------------------- /stages/post-process/effects/tonemap.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "4d8018e3-29fb-4cc8-a916-2cbd073eb284", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": {} 9 | } 10 | -------------------------------------------------------------------------------- /stages/post-process/effects/vignette.effect: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. 2 | 3 | CCEffect %{ 4 | temporaries: 5 | d1: &d1 { depthTest: false, depthWrite: false } 6 | b1: &b1 7 | targets: 8 | - blend: true 9 | blendSrc: src_alpha 10 | blendDst: one_minus_src_alpha 11 | blendSrcAlpha: src_alpha 12 | blendDstAlpha: one_minus_src_alpha 13 | 14 | 15 | techniques: 16 | - passes: 17 | - vert: post-process-vs:vert 18 | frag: fs:frag 19 | depthStencilState: *d1 20 | blendState: *b1 21 | rasterizerState: 22 | cullMode: none 23 | properties: 24 | radius: { value: 1 } 25 | smoothness: { value: 0.3 } 26 | intensity: { value: 1.0 } 27 | color: { value: [0, 0, 0, 1], editor: { type: color } } 28 | }% 29 | 30 | CCProgram fs %{ 31 | precision highp float; 32 | #include 33 | in vec2 v_uv; 34 | 35 | uniform Vignette { 36 | vec4 color; 37 | float radius; 38 | float smoothness; 39 | float intensity; 40 | }; 41 | 42 | float vignette(vec2 uv, float a, float b) { 43 | float len = length(uv - 0.5); 44 | return smoothstep(a, b, len); 45 | } 46 | 47 | vec4 frag () { 48 | vec4 final = texture(pe_input_texture, v_uv); 49 | 50 | float v = vignette(v_uv, radius, smoothness); 51 | vec3 vignetteColor = final.rgb * v; 52 | vignetteColor += color.rgb * (1.0 - v); 53 | final.rgb = mix(final.rgb, vignetteColor, intensity); 54 | final.a += v; 55 | 56 | return final; 57 | } 58 | }% 59 | -------------------------------------------------------------------------------- /stages/post-process/effects/vignette.effect.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.4.4", 3 | "importer": "effect", 4 | "imported": true, 5 | "uuid": "a7facdb2-d7a2-4f8f-8106-10586a2963b7", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /stages/post-process/effects/vignette.mtl: -------------------------------------------------------------------------------- 1 | { 2 | "__type__": "cc.Material", 3 | "_name": "", 4 | "_objFlags": 0, 5 | "_native": "", 6 | "_effectAsset": { 7 | "__uuid__": "a7facdb2-d7a2-4f8f-8106-10586a2963b7" 8 | }, 9 | "_techIdx": 0, 10 | "_defines": [ 11 | {} 12 | ], 13 | "_states": [ 14 | { 15 | "blendState": { 16 | "targets": [ 17 | {} 18 | ] 19 | }, 20 | "depthStencilState": {}, 21 | "rasterizerState": {} 22 | } 23 | ], 24 | "_props": [ 25 | { 26 | "radius": 0.8, 27 | "smoothness": 0.4, 28 | "intensity": 0.6 29 | } 30 | ] 31 | } -------------------------------------------------------------------------------- /stages/post-process/effects/vignette.mtl.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.9", 3 | "importer": "material", 4 | "imported": true, 5 | "uuid": "51c4205c-e682-4aed-a507-7fdc1b2c5d7f", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /stages/post-process/effects/vignette.ts: -------------------------------------------------------------------------------- 1 | import { Color, _decorator } from 'cc'; 2 | import { PostEffectBase, effect, effectProperty } from '../post-effect-base'; 3 | const { property, ccclass } = _decorator 4 | 5 | @effect 6 | @ccclass('VignetteEffect') 7 | export class VignetteEffect extends PostEffectBase { 8 | static effectName = 'vignette'; 9 | 10 | @property 11 | @effectProperty 12 | _radius = 1; 13 | 14 | @property 15 | @effectProperty 16 | _smoothness = 0.3; 17 | 18 | @property 19 | @effectProperty 20 | _intensity = 1.0; 21 | 22 | @property 23 | @effectProperty 24 | _color = Color.BLACK.clone(); 25 | } 26 | -------------------------------------------------------------------------------- /stages/post-process/effects/vignette.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "fb09a989-70ec-43db-aca8-fdf607aab835", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": {} 9 | } 10 | -------------------------------------------------------------------------------- /stages/post-process/post-effect-base.ts: -------------------------------------------------------------------------------- 1 | import { CCObject, Color, Material, MeshRenderer, Node, utils, warn, _decorator } from 'cc'; 2 | import { cce, EDITOR } from '../../utils/editor'; 3 | import postProcessMaterials from './editor/post-process-renderer-materials'; 4 | import { PostProcess } from './post-process'; 5 | import PostProcessCommand from './post-process-command'; 6 | import { getMesh } from './quad-mesh'; 7 | const { property, ccclass, type } = _decorator 8 | 9 | export const postEffects: Map = new Map(); 10 | export function effect (cls: typeof PostEffectBase) { 11 | postEffects.set(cls.effectName, cls); 12 | } 13 | 14 | export function effectProperty (cls: PostEffectBase, privateName: string) { 15 | let publicName = privateName; 16 | if (publicName[0] === '_') { 17 | publicName = publicName.substring(1); 18 | } 19 | 20 | if (!cls._effectProperties) { 21 | cls._effectProperties = []; 22 | } 23 | cls._effectProperties.push(publicName); 24 | let descriptor: any = { 25 | get () { 26 | return this[privateName]; 27 | }, 28 | set (v: any) { 29 | this[privateName] = v; 30 | this._updateProperty(publicName, v); 31 | } 32 | 33 | } 34 | Object.defineProperty(cls, publicName, descriptor) 35 | property(cls, publicName, descriptor); 36 | } 37 | 38 | export function getEffect (effectName: string) { 39 | return postEffects.get(effectName); 40 | } 41 | 42 | export class PassDefine { 43 | 44 | outputName = ''; 45 | inputNames: string[] = [] 46 | 47 | constructor (outputName?: string, inputNames?: string[]) { 48 | if (outputName !== undefined) { 49 | this.outputName = outputName; 50 | } 51 | if (inputNames !== undefined) { 52 | this.inputNames = inputNames; 53 | } 54 | } 55 | } 56 | 57 | 58 | @ccclass('PostEffectBase') 59 | export class PostEffectBase { 60 | static effectName = ''; 61 | static passDefines: Map | undefined = new Map; 62 | 63 | _effectProperties!: string[]; 64 | 65 | isReverse = false; 66 | postProcess: PostProcess | undefined; 67 | 68 | _commands: PostProcessCommand[] = []; 69 | get commands () { 70 | this.init(); 71 | return this._commands; 72 | } 73 | 74 | _materialInstance: Material | undefined; 75 | 76 | @property 77 | _enabled = true; 78 | @property 79 | get enabled () { 80 | return this._enabled; 81 | } 82 | set enabled (v) { 83 | this._enabled = v; 84 | if (this.postProcess) { 85 | this.postProcess.rebuild(); 86 | } 87 | } 88 | 89 | @type(Material) 90 | _material: Material | undefined; 91 | @type(Material) 92 | get material () { 93 | return this._material; 94 | } 95 | 96 | _inited = false; 97 | init () { 98 | if (this._inited) return; 99 | this._inited = true; 100 | this._updateType(); 101 | } 102 | 103 | _updateProperty (name: string, val: any) { 104 | if (!this._materialInstance) return; 105 | this._materialInstance.setProperty(name, val); 106 | this._updatePasses(); 107 | if (EDITOR) { 108 | cce.Engine.repaintInEditMode(); 109 | } 110 | } 111 | _updatePasses () { 112 | if (!this._materialInstance) return; 113 | let passes = this._materialInstance.passes; 114 | for (let i = 0; i < passes.length; i++) { 115 | passes[i].update(); 116 | } 117 | } 118 | 119 | _updateType () { 120 | if (EDITOR) { 121 | let materialName = (this.constructor as typeof PostEffectBase).effectName; 122 | this._material = postProcessMaterials.get(materialName); 123 | } 124 | this._updateCommands(); 125 | } 126 | 127 | _updateCommands () { 128 | let commandMap: Map = new Map; 129 | let commands = this._commands; 130 | commands.length = 0; 131 | commandMap.clear(); 132 | 133 | let material = this._material; 134 | if (!material) return; 135 | 136 | let postProcess = this.postProcess; 137 | if (!postProcess) return; 138 | 139 | let isReverse = this.isReverse; 140 | if (!(this._material!.passes.length % 2)) { 141 | isReverse = !isReverse; 142 | } 143 | 144 | let mesh = getMesh(isReverse); 145 | 146 | let node = new Node(); 147 | node._objFlags = CCObject.Flags.DontSave; 148 | 149 | let mr = node.addComponent(MeshRenderer); 150 | mr.mesh = mesh; 151 | mr.material = this._material!; 152 | node.parent = postProcess.node; 153 | 154 | this._materialInstance = mr.getMaterialInstance(0)!; 155 | 156 | let subModels = mr.model?.subModels!; 157 | let passDefines = (this.constructor as typeof PostEffectBase).passDefines; 158 | 159 | for (let i = 0; i < subModels.length; i++) { 160 | let submodel = subModels[i]; 161 | 162 | let passes = submodel.passes; 163 | for (let pi = 0; pi < passes.length; pi++) { 164 | let pass = passes[pi]; 165 | let cmd = new PostProcessCommand(submodel, pass); 166 | 167 | let define = passDefines && passDefines.get(pi); 168 | if (define) { 169 | if (define.outputName) { 170 | cmd.outputName = define.outputName; 171 | commandMap.set(cmd.outputName, cmd); 172 | } 173 | if (define.inputNames && define.inputNames.length > 0) { 174 | for (let j = 0; j < define.inputNames.length; j++) { 175 | let name = define.inputNames[j]; 176 | let inputCmd = commandMap.get(name); 177 | if (!inputCmd) { 178 | warn(`Can not find input command with name ${name}`); 179 | continue; 180 | } 181 | cmd.inputCommands.push(inputCmd); 182 | } 183 | } 184 | } 185 | 186 | commands.push(cmd); 187 | } 188 | } 189 | 190 | node.active = false; 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /stages/post-process/post-effect-base.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "c9b5941e-fad9-44fe-9af2-f79b3970d2d3", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": {} 9 | } 10 | -------------------------------------------------------------------------------- /stages/post-process/post-process-command.ts: -------------------------------------------------------------------------------- 1 | import { renderer, GFXFramebuffer } from "cc"; 2 | 3 | export default class PostProcessCommand { 4 | pass: renderer.Pass | undefined = undefined; 5 | submodel: renderer.scene.SubModel | undefined; 6 | 7 | inputCommands: PostProcessCommand[] = []; 8 | outputName: string = ''; 9 | 10 | constructor (submodel: renderer.scene.SubModel, pass: renderer.Pass) { 11 | this.submodel = submodel; 12 | this.pass = pass; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /stages/post-process/post-process-command.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "2050cc5b-7104-40fc-b4d9-dc8b118424b8", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "importAsPlugin": false, 10 | "moduleId": "project:///assets/shader-lib/post-process/post-process-command.js" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /stages/post-process/post-process-stage.ts: -------------------------------------------------------------------------------- 1 | import { _decorator, renderer, GFXPipelineState, GFXCommandBuffer, GFXFramebuffer, pipeline, GFXColor, ForwardStage, ForwardPipeline, RenderTexture, GFXRect, __private, warn, GFXColorAttachment, GFXTextureLayout, GFXDepthStencilAttachment, GFXRenderPassInfo, gfx, GFXFilter, GFXAddress, PipelineStateManager, Camera, GFXClearFlag, Rect, Color, Vec4, director, Director, view } from "cc"; 2 | import { PostEffectBase } from './post-effect-base'; 3 | 4 | const { SetIndex } = pipeline; 5 | const { ccclass, property } = _decorator; 6 | 7 | class PostEffectRenderCommand { 8 | subModel: renderer.scene.SubModel | undefined; 9 | pass: renderer.Pass | undefined; 10 | input: RenderTexture | undefined; 11 | output: RenderTexture | undefined; 12 | 13 | constructor (subModel: renderer.scene.SubModel, pass: renderer.Pass, input: RenderTexture, output: RenderTexture) { 14 | this.subModel = subModel; 15 | this.pass = pass; 16 | this.input = input; 17 | this.output = output; 18 | } 19 | } 20 | 21 | const _colors: GFXColor[] = []; 22 | 23 | const _colorAttachment = new GFXColorAttachment(); 24 | _colorAttachment.endLayout = GFXTextureLayout.SHADER_READONLY_OPTIMAL; 25 | _colorAttachment.format = gfx.Format.RGBA16F; 26 | const _depthStencilAttachment = new GFXDepthStencilAttachment(); 27 | const _renderPassInfo = new GFXRenderPassInfo([_colorAttachment], _depthStencilAttachment); 28 | 29 | export class PostProcessCameraSetting { 30 | window = undefined as __private.cocos_core_renderer_core_render_window_RenderWindow | undefined; 31 | clearDepth = 1; 32 | clearStencil = 0; 33 | clearFlag = GFXClearFlag.ALL; 34 | viewport = new Rect(0, 0, 1, 1); 35 | clearColor = new Color(0, 0, 0, 0); 36 | 37 | set (camera: renderer.scene.Camera) { 38 | this.window = camera.window! as any as __private.cocos_core_renderer_core_render_window_RenderWindow; 39 | this.clearDepth = camera.clearDepth; 40 | this.clearStencil = camera.clearStencil; 41 | this.clearFlag = camera.clearFlag; 42 | this.viewport.set(camera.viewport); 43 | 44 | Vec4.copy(this.clearColor, camera.clearColor); 45 | } 46 | 47 | setToCamera (camera: renderer.scene.Camera) { 48 | camera.changeTargetWindow(this.window as any); 49 | 50 | camera.clearDepth = this.clearDepth; 51 | camera.clearStencil = this.clearStencil; 52 | camera.clearFlag = this.clearFlag; 53 | camera.viewport.set(this.viewport); 54 | 55 | camera.update(true); 56 | (director.root?.pipeline as ForwardPipeline).updateCameraUBO(camera); 57 | 58 | Vec4.copy(camera.clearColor, this.clearColor); 59 | } 60 | } 61 | 62 | @ccclass("PostProcessStage") 63 | export class PostProcessStage extends ForwardStage { 64 | _name = "PostProcessStage"; 65 | 66 | private _renderArea: GFXRect = { x: 0, y: 0, width: 0, height: 0 }; 67 | 68 | postProcessCameraSetting = new PostProcessCameraSetting 69 | oldCameraSetting = new PostProcessCameraSetting 70 | 71 | initialize (info: any) { 72 | view.on('design-resolution-changed', () => { 73 | let divice = director.root?.device!; 74 | this.resize(divice.width, divice.height); 75 | }, this); 76 | return super.initialize(info); 77 | } 78 | 79 | render (camera: renderer.scene.Camera) { 80 | const pipeline = this._pipeline as ForwardPipeline; 81 | const cmdBuff = pipeline.commandBuffers[0]; 82 | const device = pipeline.device; 83 | 84 | const vp = camera.viewport; 85 | 86 | // draw post process 87 | let commands = this._renderCommands; 88 | if (commands.length !== 0) { 89 | let pipeline = this._pipeline!; 90 | 91 | for (let i = 0; i < commands.length; i++) { 92 | let renderTexture = commands[i].output; 93 | 94 | let framebuffer: GFXFramebuffer; 95 | if (renderTexture) { 96 | framebuffer = renderTexture.window!.framebuffer 97 | } 98 | else { 99 | framebuffer = this.oldCameraSetting.window!.framebuffer; 100 | } 101 | 102 | this._renderArea!.width = camera.width; 103 | this._renderArea!.height = camera.height; 104 | 105 | if (!renderTexture) { 106 | this._renderArea!.x = vp.x * camera.width; 107 | this._renderArea!.y = vp.y * camera.height; 108 | this._renderArea!.width *= vp.width; 109 | this._renderArea!.height *= vp.height; 110 | 111 | this.oldCameraSetting.setToCamera(camera); 112 | } 113 | else { 114 | this._renderArea!.x = 0; 115 | this._renderArea!.y = 0; 116 | } 117 | 118 | _colors[0] = camera.clearColor; 119 | 120 | const renderPass = framebuffer.colorTextures[0] ? framebuffer.renderPass : (pipeline as ForwardPipeline).getRenderPass(camera.clearFlag); 121 | cmdBuff.beginRenderPass(renderPass, framebuffer, this._renderArea!, 122 | _colors, camera.clearDepth, camera.clearStencil); 123 | 124 | let pass = commands[i].pass!; 125 | let subModel = commands[i].subModel!; 126 | 127 | let ia = subModel.inputAssembler; 128 | 129 | // let passIdx = subModel.passes.indexOf(pass); 130 | // const shader = ShaderPool.get(SubModelPool.get(subModel.handle, SubModelView.SHADER_0 + passIdx) as renderer.ShaderHandle); 131 | const shader = renderer.ShaderPool.get(pass.getShaderVariant()); 132 | 133 | const pso = PipelineStateManager.getOrCreatePipelineState(device, pass, shader, framebuffer.renderPass, ia); 134 | cmdBuff.bindPipelineState(pso); 135 | cmdBuff.bindDescriptorSet(SetIndex.MATERIAL, pass.descriptorSet); 136 | cmdBuff.bindDescriptorSet(SetIndex.LOCAL, subModel.descriptorSet); 137 | cmdBuff.bindInputAssembler(ia); 138 | cmdBuff.draw(ia); 139 | 140 | cmdBuff.endRenderPass(); 141 | } 142 | } 143 | } 144 | 145 | _effects: PostEffectBase[] = []; 146 | get effects () { 147 | return this._effects; 148 | } 149 | set effects (value) { 150 | this._effects = value; 151 | this.rebuild(); 152 | } 153 | 154 | _renderCommands: PostEffectRenderCommand[] = []; 155 | 156 | clear () { 157 | this._effects.length = 0; 158 | this._renderCommands.length = 0; 159 | } 160 | 161 | get usedTextures () { 162 | let usedTextures: (RenderTexture | undefined)[] = []; 163 | let renderCommands = this._renderCommands; 164 | for (let i = 0; i < renderCommands.length; i++) { 165 | if (renderCommands[i].input && !usedTextures.includes(renderCommands[i].input)) { 166 | if (renderCommands[i].input !== this._originRenderTexture) { 167 | usedTextures.push(renderCommands[i].input) 168 | } 169 | } 170 | if (renderCommands[i].output && !usedTextures.includes(renderCommands[i].output)) { 171 | usedTextures.push(renderCommands[i].output) 172 | } 173 | } 174 | return usedTextures; 175 | } 176 | 177 | _originRenderTexture: RenderTexture | undefined; 178 | rebuild () { 179 | let frameBuffersToDestroy = this.usedTextures; 180 | for (let i = 0; i < frameBuffersToDestroy.length; i++) { 181 | if (frameBuffersToDestroy[i]) { 182 | frameBuffersToDestroy[i]!.destroy(); 183 | } 184 | } 185 | 186 | let renderCommands = this._renderCommands; 187 | renderCommands.length = 0; 188 | 189 | let hasCommand = false; 190 | let effects = this._effects; 191 | for (let ri = 0; ri < effects.length; ri++) { 192 | let renderer = effects[ri]; 193 | if (!renderer || !renderer.enabled) { 194 | continue; 195 | } 196 | hasCommand = true; 197 | break; 198 | } 199 | 200 | if (!hasCommand) return; 201 | 202 | let pipeline = this._pipeline! as ForwardPipeline; 203 | 204 | const device = pipeline.device; 205 | let width = device.width, height = device.height; 206 | 207 | if (!this._originRenderTexture) { 208 | this._originRenderTexture = new RenderTexture(); 209 | this._originRenderTexture.reset({ width, height, passInfo: _renderPassInfo }) 210 | } 211 | 212 | this.postProcessCameraSetting.window = this._originRenderTexture.window!; 213 | 214 | let flip: RenderTexture | null = null, flop: RenderTexture | null = null, tmp: RenderTexture | null = null; 215 | let renderTextureMap: Map = new Map(); 216 | 217 | for (let ri = 0; ri < effects.length; ri++) { 218 | let r = effects[ri]; 219 | if (!r || !r.enabled) { 220 | continue; 221 | } 222 | 223 | let commands = r.commands; 224 | for (let ci = 0; ci < commands.length; ci++) { 225 | let command = commands[ci]; 226 | let pass = command.pass; 227 | 228 | if (!pass) { 229 | continue; 230 | } 231 | 232 | let originBinding = pass.getBinding('pe_origin_texture'); 233 | if (originBinding) { 234 | pass.bindSampler(originBinding, this._originRenderTexture.getGFXSampler()); 235 | pass.bindTexture(originBinding, this._originRenderTexture.getGFXTexture()!); 236 | } 237 | 238 | if (command.inputCommands) { 239 | for (let ii = 0; ii < command.inputCommands.length; ii++) { 240 | let inputName = command.inputCommands[ii].outputName; 241 | 242 | let inputTexture = renderTextureMap.get(inputName); 243 | if (!inputTexture) { 244 | warn(`Can not find input frame buffer for input name [${inputName}] in post process renderer [${typeof renderer}]`); 245 | continue; 246 | } 247 | 248 | let inputBinding = pass.getBinding(inputName); 249 | if (inputBinding) { 250 | pass.bindSampler(inputBinding, inputTexture.getGFXSampler()); 251 | pass.bindTexture(inputBinding, inputTexture.getGFXTexture()!); 252 | } 253 | } 254 | } 255 | 256 | let input = flip || this._originRenderTexture; 257 | 258 | let inputBinding = pass.getBinding('pe_input_texture'); 259 | if (inputBinding) { 260 | pass.bindSampler(inputBinding, input.getGFXSampler()); 261 | pass.bindTexture(inputBinding, input.getGFXTexture()!); 262 | } 263 | 264 | pass.update(); 265 | 266 | if (!flop) { 267 | flop = new RenderTexture(); 268 | flop.reset({ width, height, passInfo: _renderPassInfo }) 269 | } 270 | 271 | renderCommands.push(new PostEffectRenderCommand(command.submodel!, pass, input, flop)); 272 | 273 | if (command.outputName) { 274 | renderTextureMap.set(command.outputName, flop); 275 | flop = null; 276 | } 277 | 278 | tmp = flip; 279 | flip = flop; 280 | flop = tmp; 281 | } 282 | } 283 | 284 | // last command should output to screen 285 | if (renderCommands.length > 0) { 286 | renderCommands[renderCommands.length - 1].output = undefined; 287 | } 288 | } 289 | 290 | resize (width: number, height: number) { 291 | // if (this._originRenderTexture) { 292 | // this._originRenderTexture.resize(width, height); 293 | // } 294 | // this.usedTextures.forEach(t => { 295 | // t?.resize(width, height); 296 | // }) 297 | 298 | if (this._originRenderTexture) { 299 | this._originRenderTexture.destroy(); 300 | this._originRenderTexture = undefined; 301 | } 302 | this.rebuild(); 303 | } 304 | } 305 | 306 | director.on(Director.EVENT_BEFORE_SCENE_LAUNCH, () => { 307 | director.root!.pipeline.flows.forEach(flow => { 308 | let stage = flow.stages.find(s => s.name === "PostProcessStage") as PostProcessStage | undefined; 309 | if (stage) { 310 | stage.clear(); 311 | return; 312 | } 313 | }) 314 | }) 315 | -------------------------------------------------------------------------------- /stages/post-process/post-process-stage.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "7f67c466-65e2-487c-9ef9-626617975a75", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "importAsPlugin": false, 10 | "moduleId": "project:///assets/shader-lib/post-process/post-process-stage.js" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /stages/post-process/post-process.ts: -------------------------------------------------------------------------------- 1 | import { _decorator, Component, director, Material } from 'cc'; 2 | const { ccclass, property, type, executeInEditMode } = _decorator; 3 | 4 | import { PostProcessStage } from './post-process-stage'; 5 | 6 | import { TonemapEffect } from './effects/tonemap'; 7 | import { VignetteEffect } from './effects/vignette'; 8 | import { PostEffectBase } from './post-effect-base'; 9 | import { BloomEffect } from './effects/bloom'; 10 | import { ColorGradingEffect } from './effects/color-grading'; 11 | 12 | function effectOrder (pp: PostProcess, name: string) { 13 | if (!pp._effectsOrder) { 14 | pp._effectsOrder = []; 15 | } 16 | pp._effectsOrder.push(name); 17 | } 18 | 19 | @ccclass('PostProcess') 20 | @executeInEditMode 21 | export class PostProcess extends Component { 22 | _stage: PostProcessStage | undefined; 23 | 24 | _effects: PostEffectBase[] = []; 25 | _effectsOrder!: string[]; 26 | 27 | @type(BloomEffect) 28 | @effectOrder 29 | bloom = new BloomEffect 30 | 31 | @type(ColorGradingEffect) 32 | @effectOrder 33 | colorGrading = new ColorGradingEffect 34 | 35 | @type(TonemapEffect) 36 | @effectOrder 37 | tonemap = new TonemapEffect 38 | 39 | @type(VignetteEffect) 40 | @effectOrder 41 | vignette = new VignetteEffect 42 | 43 | onEnable () { 44 | this._stage = undefined; 45 | director.root!.pipeline.flows.forEach(flow => { 46 | this._stage = flow.stages.find(s => s.name === "PostProcessStage") as PostProcessStage | undefined; 47 | if (this._stage) { 48 | return; 49 | } 50 | }) 51 | 52 | this.rebuild(); 53 | } 54 | 55 | onDisable () { 56 | this._clearStage(); 57 | } 58 | 59 | rebuild () { 60 | this._updateRenderers(); 61 | this._updateStage(); 62 | } 63 | 64 | private _updateRenderers () { 65 | this.node.removeAllChildren(); 66 | 67 | this._effects.length = 0; 68 | let isReverse = false; 69 | this._effectsOrder.forEach(name => { 70 | let effect = (this as any)[name] as PostEffectBase; 71 | effect.postProcess = this; 72 | 73 | if (effect && effect.enabled) { 74 | 75 | effect._inited = false; 76 | 77 | if (this._effects.length >= 2) { 78 | isReverse = !isReverse; 79 | } 80 | effect.isReverse = isReverse; 81 | isReverse = !isReverse; 82 | 83 | 84 | this._effects.push(effect); 85 | } 86 | }) 87 | } 88 | 89 | private _updateStage () { 90 | if (this._stage) { 91 | this._stage.effects = this.enabledInHierarchy ? this._effects : []; 92 | } 93 | } 94 | private _clearStage () { 95 | if (this._stage) { 96 | this._stage.clear(); 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /stages/post-process/post-process.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "a903f134-5be5-46b6-b481-7b906698e2fe", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "importAsPlugin": false, 10 | "moduleId": "project:///assets/shader-lib/post-process/post-process.js" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /stages/post-process/quad-mesh.ts: -------------------------------------------------------------------------------- 1 | import { Mesh, utils } from 'cc'; 2 | 3 | let _quadMesh: Mesh; 4 | let _reverseQuadMesh: Mesh; 5 | 6 | export function getMesh (reverse: boolean) { 7 | if (!reverse) { 8 | if (!_reverseQuadMesh) { 9 | _reverseQuadMesh = utils.createMesh({ 10 | positions: [ 11 | -1, -1, 0, 1, -1, 0, 12 | -1, 1, 0, 1, 1, 0, 13 | ], 14 | uvs: [ 15 | 0, 1, 1, 1, 16 | 0, 0, 1, 0 17 | ], 18 | indices: [ 19 | 0, 1, 2, 1, 3, 2 20 | ] 21 | }); 22 | } 23 | return _reverseQuadMesh; 24 | } 25 | else { 26 | if (!_quadMesh) { 27 | _quadMesh = utils.createMesh({ 28 | positions: [ 29 | -1, -1, 0, 1, -1, 0, 30 | -1, 1, 0, 1, 1, 0, 31 | ], 32 | uvs: [ 33 | 0, 0, 1, 0, 34 | 0, 1, 1, 1 35 | ], 36 | indices: [ 37 | 0, 1, 2, 1, 3, 2 38 | ] 39 | }); 40 | } 41 | return _quadMesh; 42 | } 43 | } -------------------------------------------------------------------------------- /stages/post-process/quad-mesh.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "3863c255-e9e8-4957-99fb-068194fb4342", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": {} 9 | } 10 | -------------------------------------------------------------------------------- /stages/post-process/renderers.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "0.0.1", 3 | "importer": "*", 4 | "imported": true, 5 | "uuid": "495cdd32-d4fd-4ca6-a998-35bd403a9e23", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": {} 9 | } 10 | -------------------------------------------------------------------------------- /stages/post-process/shadowmap-queue.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "2.0.14", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "d7878579-16e1-4ddf-996d-8711097da558", 6 | "files": [ 7 | ".js", 8 | ".trans" 9 | ], 10 | "subMetas": {}, 11 | "userData": { 12 | "importAsPlugin": false, 13 | "moduleId": "project:///assets/shader-lib/post-process/shadowmap-queue.js" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /utils.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.1.0", 3 | "importer": "directory", 4 | "imported": true, 5 | "uuid": "463f61b6-0647-4293-94b7-6a01c7ac91b4", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "compressionType": {}, 10 | "isRemoteBundle": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /utils/draw.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "29532a54-8ff2-45d3-ab61-d81af0b31698", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "importAsPlugin": false, 10 | "moduleId": "project:///assets/libs/advanced-pipeline/utils/draw.js", 11 | "importerSettings": 4 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /utils/editor.ts: -------------------------------------------------------------------------------- 1 | import { EDITOR as _EDITOR } from 'cc/env'; 2 | import { formatPath } from "./path"; 3 | 4 | export const EDITOR = _EDITOR; 5 | 6 | export const cce = EDITOR && (window as any).cce; 7 | export const io = EDITOR && (window as any).require('socket.io'); 8 | export const path = EDITOR && (window as any).require('path'); 9 | export const fse = EDITOR && (window as any).require('fs-extra'); 10 | export const base642arraybuffer = EDITOR && (window as any).require('base64-arraybuffer'); 11 | export const Sharp = EDITOR && (window as any).require('sharp'); 12 | export const globby = EDITOR && (window as any).require('globby'); 13 | 14 | export const Editor = EDITOR && (window as any).Editor; 15 | export const projectPath = EDITOR && formatPath(Editor.Project.path); 16 | export const projectAssetPath = EDITOR && formatPath(path.join(projectPath, 'assets')); 17 | -------------------------------------------------------------------------------- /utils/editor.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "901c1c98-51eb-46ee-825b-68cb8a18cc16", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": {} 9 | } 10 | -------------------------------------------------------------------------------- /utils/path.ts: -------------------------------------------------------------------------------- 1 | export function formatPath (p: string) { 2 | return p.replace(/\\/g, '/'); 3 | } 4 | -------------------------------------------------------------------------------- /utils/path.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "40f9010d-92b1-4c70-9af1-3ae3cfaee43c", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": {} 9 | } 10 | -------------------------------------------------------------------------------- /utils/stage.ts: -------------------------------------------------------------------------------- 1 | import { GFXCommandBuffer, GFXDevice, GFXRenderPass, PipelineStateManager, renderer } from "cc"; 2 | import { pipeline } from '../defines/pipeline'; 3 | 4 | const { SetIndex } = pipeline; 5 | 6 | export function commitBuffer (model: renderer.scene.Model, cmdBuff: GFXCommandBuffer, device: GFXDevice, renderPass: GFXRenderPass, phaseID: number) { 7 | let subModels = model.subModels; 8 | for (let m = 0; m < subModels.length; m++) { 9 | const subModel = subModels[m]; 10 | 11 | for (let pi = 0; pi < subModel.passes.length; pi++) { 12 | const pass = subModel.passes[pi]; 13 | if (pass.phase !== phaseID) { 14 | continue; 15 | } 16 | 17 | const shaderHandle = renderer.SubModelPool.get(subModel.handle, renderer.SubModelView.SHADER_0 + pi); 18 | const shader = renderer.ShaderPool.get(shaderHandle as any); 19 | if (!shader) { 20 | continue; 21 | } 22 | 23 | const hPass = pass.handle; 24 | const ia = subModel.inputAssembler; 25 | const pso = PipelineStateManager.getOrCreatePipelineState(device, pass, shader, renderPass, ia); 26 | 27 | const descriptorSet = renderer.DSPool.get(renderer.PassPool.get(hPass, renderer.PassView.DESCRIPTOR_SET)); 28 | cmdBuff.bindPipelineState(pso); 29 | cmdBuff.bindDescriptorSet(SetIndex.MATERIAL, descriptorSet); 30 | cmdBuff.bindDescriptorSet(SetIndex.LOCAL, subModel.descriptorSet); 31 | cmdBuff.bindInputAssembler(ia); 32 | cmdBuff.draw(ia); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /utils/stage.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.21", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "0815c115-9262-4ca0-b55b-b84f25d51e03", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "importAsPlugin": false, 10 | "moduleId": "project:///assets/libs/advanced-pipeline/utils/stage.js", 11 | "importerSettings": 4 12 | } 13 | } 14 | --------------------------------------------------------------------------------