@woosh/meep-engine 2.40.1 → 2.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/collection/HashMap.d.ts +2 -0
- package/core/collection/HashMap.js +22 -0
- package/core/geom/3d/normal/hemioct/encode_unit3_hemioct.js +5 -0
- package/core/geom/3d/normal/octahedron/decode_octahedron_to_unit.js +31 -0
- package/core/geom/3d/normal/octahedron/encode_unit_to_octahedron.js +33 -0
- package/core/geom/3d/normal/octahedron/encoding.spec.js +29 -0
- package/core/geom/3d/topology/struct/BinaryTopology.js +112 -0
- package/core/math/sign_not_zero.js +8 -0
- package/core/parser/simple/SimpleParser.js +3 -86
- package/core/parser/simple/readUnsignedInteger.js +66 -0
- package/core/parser/simple/skipWhitespace.js +21 -0
- package/engine/EngineHarness.js +4 -0
- package/engine/asset/AssetDescription.spec.js +27 -0
- package/engine/asset/loaders/GLTFAssetLoader.js +5 -3
- package/engine/ecs/foliage/ImpostorFoliage.js +4 -0
- package/engine/graphics/ecs/mesh-v2/three_object_to_entity_composition.js +22 -7
- package/engine/graphics/filter/ImageFilter.js +2 -1
- package/engine/graphics/geometry/MikkT/MikkTSpace.spec.js +7 -1
- package/engine/{asset/loaders/geometry/geometry → graphics/geometry/buffered}/computeBufferAttributeHash.js +1 -1
- package/engine/{asset/loaders/geometry/geometry → graphics/geometry/buffered}/computeGeometryEquality.js +2 -2
- package/engine/{asset/loaders/geometry/geometry → graphics/geometry/buffered}/computeGeometryHash.js +1 -1
- package/engine/graphics/geometry/optimization/merge/merge_geometry_hierarchy.js +2 -2
- package/engine/graphics/impostors/card_cluster/FacePlaneAssignment.js +30 -0
- package/engine/graphics/impostors/card_cluster/README.md +13 -0
- package/engine/graphics/impostors/octahedral/ImpostorBaker.js +332 -0
- package/engine/graphics/impostors/octahedral/ImpostorCaptureType.js +10 -0
- package/engine/graphics/impostors/octahedral/ImpostorDescription.js +63 -0
- package/engine/graphics/impostors/octahedral/README.md +29 -0
- package/engine/graphics/impostors/octahedral/bake/compute_bounding_sphere.js +42 -0
- package/engine/graphics/impostors/octahedral/bake/prepare_bake_material.js +88 -0
- package/engine/graphics/impostors/octahedral/grid/HemiOctahedralUvEncoder.js +20 -0
- package/engine/graphics/impostors/octahedral/grid/OctahedralUvEncoder.js +25 -0
- package/engine/graphics/impostors/octahedral/grid/UvEncoder.js +21 -0
- package/engine/graphics/impostors/octahedral/prototypeBaker.js +138 -0
- package/engine/graphics/impostors/octahedral/shader/BakeShaderStandard.js +157 -0
- package/engine/graphics/impostors/octahedral/shader/ImpostorShaderStandard.js +306 -0
- package/engine/graphics/impostors/octahedral/shader/glsl/common.glsl +206 -0
- package/engine/graphics/micron/convert_three_object_to_micron.js +2 -2
- package/engine/graphics/micron/plugin/MicronRenderPlugin.js +2 -2
- package/engine/graphics/particles/node-based/codegen/CodeGenerator.js +1 -1
- package/engine/graphics/particles/node-based/nodes/noise/CurlNoiseNode.js +1 -1
- package/engine/graphics/render/visibility/hiz/buildCanvasViewFromTexture.js +32 -10
- package/engine/graphics/shaders/ScreenSpaceQuadShader.js +4 -14
- package/engine/graphics/shaders/glsl_gen_swizzled_read.js +39 -0
- package/engine/ui/GUIEngine.js +8 -1
- package/package.json +1 -1
- package/view/tooltip/gml/parser/readReferenceToken.js +1 -1
- package/engine/asset/GameAssetManager.js +0 -137
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { EngineHarness } from "../../../EngineHarness.js";
|
|
2
|
+
import { ImpostorBaker } from "./ImpostorBaker.js";
|
|
3
|
+
import { ShadedGeometry } from "../../ecs/mesh-v2/ShadedGeometry.js";
|
|
4
|
+
import sampler2D2Canvas from "../../texture/sampler/Sampler2D2Canvas.js";
|
|
5
|
+
import { CanvasView } from "../../../../view/elements/CanvasView.js";
|
|
6
|
+
import EntityBuilder from "../../../ecs/EntityBuilder.js";
|
|
7
|
+
import ViewportPosition from "../../../ecs/gui/position/ViewportPosition.js";
|
|
8
|
+
import GUIElement from "../../../ecs/gui/GUIElement.js";
|
|
9
|
+
import GUIElementSystem from "../../../ecs/gui/GUIElementSystem.js";
|
|
10
|
+
import ViewportPositionSystem from "../../../ecs/gui/position/ViewportPositionSystem.js";
|
|
11
|
+
import { WebGLRendererPool } from "../../render/RendererPool.js";
|
|
12
|
+
import { buildCanvasViewFromTexture } from "../../render/visibility/hiz/buildCanvasViewFromTexture.js";
|
|
13
|
+
import Vector2 from "../../../../core/geom/Vector2.js";
|
|
14
|
+
import { GameAssetType } from "../../../asset/GameAssetType.js";
|
|
15
|
+
import { three_object_to_entity_composition } from "../../ecs/mesh-v2/three_object_to_entity_composition.js";
|
|
16
|
+
import { Transform } from "../../../ecs/transform/Transform.js";
|
|
17
|
+
import { GLTFAssetLoader } from "../../../asset/loaders/GLTFAssetLoader.js";
|
|
18
|
+
import { ImpostorCaptureType } from "./ImpostorCaptureType.js";
|
|
19
|
+
import { PlaneBufferGeometry } from "three";
|
|
20
|
+
import { ImpostorShaderStandard } from "./shader/ImpostorShaderStandard.js";
|
|
21
|
+
import { ShadedGeometrySystem } from "../../ecs/mesh-v2/ShadedGeometrySystem.js";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
*
|
|
25
|
+
* @param {Engine} engine
|
|
26
|
+
* @return {Promise<void>}
|
|
27
|
+
*/
|
|
28
|
+
async function main(engine) {
|
|
29
|
+
await EngineHarness.buildBasics({
|
|
30
|
+
engine
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const baker = new ImpostorBaker();
|
|
34
|
+
const renderer = engine.graphics.renderer;
|
|
35
|
+
baker.renderer = renderer;
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
// const gltf_asset = await engine.assetManager.promise('data/models/RTS_Buildings_Humans/18/Building_R_18_out/Building_R_18.gltf', GameAssetType.ModelGLTF_JSON);
|
|
39
|
+
// const gltf_asset = await engine.assetManager.promise('data/models/LowPolyTownshipSet/Barrel/model.gltf', GameAssetType.ModelGLTF_JSON);
|
|
40
|
+
// const gltf_asset = await engine.assetManager.promise('data/models/LowPolyTownshipSet/Town_Hall/model.gltf', GameAssetType.ModelGLTF_JSON);
|
|
41
|
+
// const gltf_asset = await engine.assetManager.promise('data/models/LowPolyTownshipSet/Small_house/Small_house.gltf', GameAssetType.ModelGLTF_JSON);
|
|
42
|
+
const gltf_asset = await engine.assetManager.promise('data/models/MOBA and Tower Defense/Tree_03.gltf', GameAssetType.ModelGLTF_JSON);
|
|
43
|
+
// const gltf_asset = await engine.assetManager.promise('data/models/samples/transform-hierarchy.glb', GameAssetType.ModelGLTF_JSON);
|
|
44
|
+
// const gltf_asset = await engine.assetManager.promise('data/models/sponza-pbr/gltf/sponza.glb', GameAssetType.ModelGLTF_JSON);
|
|
45
|
+
// const gltf_asset = await engine.assetManager.promise('moicon/gnutti_not_optimized/model.gltf', GameAssetType.ModelGLTF_JSON);
|
|
46
|
+
// const gltf_asset = await engine.assetManager.promise('moicon/isiflow_Oct_15_21/2/model.gltf', GameAssetType.ModelGLTF_JSON);
|
|
47
|
+
// const gltf_asset = await engine.assetManager.promise('moicon/Kople/EVCharger1.gltf', GameAssetType.ModelGLTF_JSON);
|
|
48
|
+
|
|
49
|
+
const node_hierarchy = three_object_to_entity_composition(gltf_asset.create());
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
const objects = [];
|
|
53
|
+
|
|
54
|
+
node_hierarchy.traverse(n => {
|
|
55
|
+
const sg = n.entity.getComponent(ShadedGeometry);
|
|
56
|
+
if (sg !== null) {
|
|
57
|
+
objects.push({
|
|
58
|
+
mesh: sg,
|
|
59
|
+
transform: n.entity.getComponent(Transform).matrix
|
|
60
|
+
})
|
|
61
|
+
// objects.push({
|
|
62
|
+
// mesh: ShadedGeometry.from(new BoxBufferGeometry(), sg.material),
|
|
63
|
+
// transform: mat4.create()
|
|
64
|
+
// })
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// objects.push(
|
|
69
|
+
// {
|
|
70
|
+
// mesh: ShadedGeometry.from(new BoxBufferGeometry(), new MeshStandardMaterial({
|
|
71
|
+
// color: 0xFF0000
|
|
72
|
+
// })),
|
|
73
|
+
// transform: mat4.create()
|
|
74
|
+
// }
|
|
75
|
+
// );
|
|
76
|
+
|
|
77
|
+
const id = baker.bake({
|
|
78
|
+
objects,
|
|
79
|
+
frames: 12,
|
|
80
|
+
resolution: 1024,
|
|
81
|
+
type: ImpostorCaptureType.Hemisphere
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
console.log(id);
|
|
85
|
+
|
|
86
|
+
const ctrl = buildCanvasViewFromTexture({
|
|
87
|
+
texture: id.rt.texture[1],
|
|
88
|
+
renderer: renderer,
|
|
89
|
+
// swizzle: ['a', 'a', 'a', 1]
|
|
90
|
+
swizzle: ['r', 'g', 'b', 1]
|
|
91
|
+
});
|
|
92
|
+
ctrl.view.css({
|
|
93
|
+
opacity: 0.2
|
|
94
|
+
});
|
|
95
|
+
ctrl.render();
|
|
96
|
+
|
|
97
|
+
const cv = new CanvasView();
|
|
98
|
+
cv.size.set(id.atlas.width, id.atlas.height);
|
|
99
|
+
cv.css({
|
|
100
|
+
background: "rgba(0,0,0,0.1)"
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
sampler2D2Canvas(id.atlas, 255, 0, cv.el);
|
|
104
|
+
|
|
105
|
+
WebGLRendererPool.global.release(renderer);
|
|
106
|
+
|
|
107
|
+
new EntityBuilder()
|
|
108
|
+
.add(new ViewportPosition())
|
|
109
|
+
.add(GUIElement.fromView(cv))
|
|
110
|
+
// .build(engine.entityManager.dataset);
|
|
111
|
+
|
|
112
|
+
const ecd = engine.entityManager.dataset;
|
|
113
|
+
new EntityBuilder()
|
|
114
|
+
.add(new ViewportPosition({
|
|
115
|
+
offset: new Vector2(0, 0)
|
|
116
|
+
}))
|
|
117
|
+
.add(GUIElement.fromView(ctrl.view))
|
|
118
|
+
.build(ecd);
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
new EntityBuilder()
|
|
122
|
+
.add(new Transform())
|
|
123
|
+
.add(ShadedGeometry.from(new PlaneBufferGeometry(1, 1, 1), new ImpostorShaderStandard()))
|
|
124
|
+
.build(ecd);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
new EngineHarness().initialize({
|
|
128
|
+
configuration(config, engine) {
|
|
129
|
+
config.addSystem(new GUIElementSystem(engine.gui.view, engine));
|
|
130
|
+
config.addSystem(new ViewportPositionSystem(engine.graphics.viewport.size));
|
|
131
|
+
config.addSystem(new ShadedGeometrySystem(engine));
|
|
132
|
+
|
|
133
|
+
const gltfAssetLoader = new GLTFAssetLoader();
|
|
134
|
+
|
|
135
|
+
config.addLoader(GameAssetType.ModelGLTF, gltfAssetLoader);
|
|
136
|
+
config.addLoader(GameAssetType.ModelGLTF_JSON, gltfAssetLoader);
|
|
137
|
+
}
|
|
138
|
+
}).then(main);
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
//
|
|
2
|
+
|
|
3
|
+
import { Color, GLSL3, RawShaderMaterial, Vector4 } from "three";
|
|
4
|
+
|
|
5
|
+
const shader_vx = `
|
|
6
|
+
in vec3 position;
|
|
7
|
+
in vec3 normal;
|
|
8
|
+
in vec2 uv;
|
|
9
|
+
in vec3 color;
|
|
10
|
+
in vec4 tangent;
|
|
11
|
+
|
|
12
|
+
out vec3 vNormal;
|
|
13
|
+
out vec3 vTangent;
|
|
14
|
+
out vec3 vBinormal;
|
|
15
|
+
|
|
16
|
+
out vec2 vUv;
|
|
17
|
+
out mat3 TBN;
|
|
18
|
+
out vec3 vColor;
|
|
19
|
+
out float depth;
|
|
20
|
+
|
|
21
|
+
uniform mat4 modelViewMatrix;
|
|
22
|
+
uniform mat4 projectionMatrix;
|
|
23
|
+
uniform mat3 normalMatrix;
|
|
24
|
+
uniform vec4 projection_params;
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
void main() {
|
|
28
|
+
|
|
29
|
+
vUv = uv;
|
|
30
|
+
|
|
31
|
+
vColor = color;
|
|
32
|
+
|
|
33
|
+
// get smooth normals
|
|
34
|
+
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
|
|
35
|
+
|
|
36
|
+
vec3 transformedNormal = normalMatrix * normal;
|
|
37
|
+
|
|
38
|
+
vec3 T = normalize(vec3(modelViewMatrix * tangent) );
|
|
39
|
+
vNormal = normalize( transformedNormal );
|
|
40
|
+
vec3 N = vNormal;
|
|
41
|
+
vec3 B = cross(N,T);
|
|
42
|
+
|
|
43
|
+
// construct Tangent Bitangent Normal matrix
|
|
44
|
+
TBN = mat3(T,B,N);
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
gl_Position = projectionMatrix * mvPosition;
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
depth = 1.0 + (mvPosition.z * projection_params.w);
|
|
51
|
+
}
|
|
52
|
+
`;
|
|
53
|
+
|
|
54
|
+
const shader_fg = `
|
|
55
|
+
precision highp float;
|
|
56
|
+
precision highp int;
|
|
57
|
+
|
|
58
|
+
layout(location = 0) out vec4 gColor;
|
|
59
|
+
layout(location = 1) out vec4 gNormal;
|
|
60
|
+
layout(location = 2) out vec4 gORM;
|
|
61
|
+
|
|
62
|
+
uniform vec3 color;
|
|
63
|
+
|
|
64
|
+
uniform sampler2D tDiffuse;
|
|
65
|
+
uniform sampler2D tNormal;
|
|
66
|
+
uniform sampler2D tRoughness;
|
|
67
|
+
uniform sampler2D tMetalness;
|
|
68
|
+
uniform sampler2D tOcclusion;
|
|
69
|
+
uniform sampler2D tEmissive;
|
|
70
|
+
|
|
71
|
+
uniform vec2 repeat;
|
|
72
|
+
|
|
73
|
+
in vec3 vNormal;
|
|
74
|
+
in vec2 vUv;
|
|
75
|
+
in mat3 TBN;
|
|
76
|
+
in vec3 vColor;
|
|
77
|
+
in float depth;
|
|
78
|
+
|
|
79
|
+
void main() {
|
|
80
|
+
// write color to G-Buffer
|
|
81
|
+
vec4 diffuse_texture_sample = texture( tDiffuse, vUv);
|
|
82
|
+
|
|
83
|
+
if(diffuse_texture_sample.a < 0.5){
|
|
84
|
+
// alpha masking
|
|
85
|
+
discard;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
gColor = diffuse_texture_sample;
|
|
89
|
+
gColor.rgb *= vColor;
|
|
90
|
+
gColor.rgb *= color;
|
|
91
|
+
|
|
92
|
+
// write normals to G-Buffer
|
|
93
|
+
// see https://learnopengl.com/Advanced-Lighting/Normal-Mapping
|
|
94
|
+
vec3 normal_sample = texture(tNormal, vUv).rgb*2.0 - 1.0;
|
|
95
|
+
vec3 normal = normalize(TBN * normal_sample);
|
|
96
|
+
|
|
97
|
+
gNormal = vec4( normal*0.5 + 0.5, depth);
|
|
98
|
+
|
|
99
|
+
float roughness = texture(tRoughness, vUv).g;
|
|
100
|
+
float metalness = texture(tMetalness, vUv).b;
|
|
101
|
+
float occlusion = texture(tOcclusion, vUv).r;
|
|
102
|
+
vec3 emissive = texture(tEmissive, vUv).rgb;
|
|
103
|
+
|
|
104
|
+
gORM = vec4(occlusion, roughness, metalness, 1.0);
|
|
105
|
+
}
|
|
106
|
+
`;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* PBR shader:
|
|
110
|
+
* - albedo + alpha
|
|
111
|
+
* - normal
|
|
112
|
+
* - roughness
|
|
113
|
+
* - metalness
|
|
114
|
+
* - ambient occlusion
|
|
115
|
+
*/
|
|
116
|
+
export class BakeShaderStandard extends RawShaderMaterial {
|
|
117
|
+
constructor() {
|
|
118
|
+
super({
|
|
119
|
+
vertexShader: shader_vx,
|
|
120
|
+
fragmentShader: shader_fg,
|
|
121
|
+
glslVersion: GLSL3,
|
|
122
|
+
uniforms: {
|
|
123
|
+
color: {
|
|
124
|
+
value: new Color(1, 1, 1)
|
|
125
|
+
},
|
|
126
|
+
tDiffuse: {
|
|
127
|
+
value: null
|
|
128
|
+
},
|
|
129
|
+
tNormal: {
|
|
130
|
+
value: null
|
|
131
|
+
},
|
|
132
|
+
tRoughness: {
|
|
133
|
+
value: null
|
|
134
|
+
},
|
|
135
|
+
tMetalness: {
|
|
136
|
+
value: null
|
|
137
|
+
},
|
|
138
|
+
tOcclusion: {
|
|
139
|
+
value: null
|
|
140
|
+
},
|
|
141
|
+
tEmissive: {
|
|
142
|
+
value: null
|
|
143
|
+
},
|
|
144
|
+
/**
|
|
145
|
+
* @see https://docs.unity3d.com/2020.3/Documentation/Manual/SL-UnityShaderVariables.html
|
|
146
|
+
*/
|
|
147
|
+
projection_params: {
|
|
148
|
+
value: new Vector4(0, 0, 0, 0)
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
this.defaultAttributeValues.tangent = [
|
|
154
|
+
1, 0, 0, 1
|
|
155
|
+
];
|
|
156
|
+
}
|
|
157
|
+
}
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import { GLSL3, NoBlending, RawShaderMaterial, Vector3 } from "three";
|
|
2
|
+
import chunk_preamble from './glsl/common.glsl';
|
|
3
|
+
|
|
4
|
+
const shader_vx = `
|
|
5
|
+
|
|
6
|
+
in vec2 uv;
|
|
7
|
+
in vec3 position;
|
|
8
|
+
|
|
9
|
+
out vec2 vUv;
|
|
10
|
+
out vec4 plane0;
|
|
11
|
+
out vec4 plane1;
|
|
12
|
+
out vec4 plane2;
|
|
13
|
+
|
|
14
|
+
${chunk_preamble}
|
|
15
|
+
|
|
16
|
+
void ImposterVertex( inout ImposterData imp )
|
|
17
|
+
{
|
|
18
|
+
//incoming vertex, object space
|
|
19
|
+
vec4 vertex = imp.vertex;
|
|
20
|
+
|
|
21
|
+
//camera in object space
|
|
22
|
+
vec3 objectSpaceCameraPos = mul( unity_WorldToObject, float4(_WorldSpaceCameraPos.xyz,1) ).xyz;
|
|
23
|
+
vec2 texcoord = imp.uv;
|
|
24
|
+
float4x4 objectToWorld = unity_ObjectToWorld;
|
|
25
|
+
float4x4 worldToObject = unity_WorldToObject;
|
|
26
|
+
|
|
27
|
+
vec3 imposterPivotOffset = _ImposterOffset.xyz;
|
|
28
|
+
half framesMinusOne = _ImposterFrames-1;
|
|
29
|
+
|
|
30
|
+
float3 objectScale = float3(length(float3(objectToWorld[0].x, objectToWorld[1].x, objectToWorld[2].x)),
|
|
31
|
+
length(float3(objectToWorld[0].y, objectToWorld[1].y, objectToWorld[2].y)),
|
|
32
|
+
length(float3(objectToWorld[0].z, objectToWorld[1].z, objectToWorld[2].z)));
|
|
33
|
+
|
|
34
|
+
//pivot to camera ray
|
|
35
|
+
float3 pivotToCameraRay = normalize(objectSpaceCameraPos.xyz-imposterPivotOffset.xyz);
|
|
36
|
+
|
|
37
|
+
//scale uv to single frame
|
|
38
|
+
texcoord = vec2(texcoord.x,texcoord.y)*(1.0/_ImposterFrames.x);
|
|
39
|
+
|
|
40
|
+
//radius * 2 * unity scaling
|
|
41
|
+
vec2 size = _ImposterSize.xx * 2.0; // * objectScale.xx; //unity_BillboardSize.xy
|
|
42
|
+
|
|
43
|
+
vec3 projected = SpriteProjection( pivotToCameraRay, _ImposterFrames, size, texcoord.xy );
|
|
44
|
+
|
|
45
|
+
//this creates the proper offset for vertices to camera facing billboard
|
|
46
|
+
vec3 vertexOffset = projected + imposterPivotOffset;
|
|
47
|
+
//subtract from camera pos
|
|
48
|
+
vertexOffset = normalize(objectSpaceCameraPos-vertexOffset);
|
|
49
|
+
//then add the original projected world
|
|
50
|
+
vertexOffset += projected;
|
|
51
|
+
//remove position of vertex
|
|
52
|
+
vertexOffset -= vertex.xyz;
|
|
53
|
+
//add pivot
|
|
54
|
+
vertexOffset += imposterPivotOffset;
|
|
55
|
+
|
|
56
|
+
//camera to projection vector
|
|
57
|
+
vec3 rayDirectionLocal = (imposterPivotOffset + projected) - objectSpaceCameraPos;
|
|
58
|
+
|
|
59
|
+
//projected position to camera ray
|
|
60
|
+
vec3 projInterpolated = normalize( objectSpaceCameraPos - (projected + imposterPivotOffset) );
|
|
61
|
+
|
|
62
|
+
Ray rayLocal;
|
|
63
|
+
rayLocal.Origin = objectSpaceCameraPos-imposterPivotOffset;
|
|
64
|
+
rayLocal.Direction = rayDirectionLocal;
|
|
65
|
+
|
|
66
|
+
vec2 grid = VectorToGrid( pivotToCameraRay );
|
|
67
|
+
vec2 gridRaw = grid;
|
|
68
|
+
grid = saturate((grid+1.0)*0.5); //bias and scale to 0 to 1
|
|
69
|
+
grid *= framesMinusOne;
|
|
70
|
+
|
|
71
|
+
vec2 gridFrac = frac(grid);
|
|
72
|
+
|
|
73
|
+
vec2 gridFloor = floor(grid);
|
|
74
|
+
|
|
75
|
+
vec4 weights = TriangleInterpolate( gridFrac );
|
|
76
|
+
|
|
77
|
+
//3 nearest frames
|
|
78
|
+
vec2 frame0 = gridFloor;
|
|
79
|
+
vec2 frame1 = gridFloor + lerp(vec2(0,1),vec2(1,0),weights.w);
|
|
80
|
+
vec2 frame2 = gridFloor + vec2(1,1);
|
|
81
|
+
|
|
82
|
+
//convert frame coordinate to octahedron direction
|
|
83
|
+
vec3 frame0ray = FrameXYToRay(frame0, framesMinusOne.xx);
|
|
84
|
+
vec3 frame1ray = FrameXYToRay(frame1, framesMinusOne.xx);
|
|
85
|
+
vec3 frame2ray = FrameXYToRay(frame2, framesMinusOne.xx);
|
|
86
|
+
|
|
87
|
+
vec3 planeCenter = vec3(0,0,0);
|
|
88
|
+
|
|
89
|
+
vec3 plane0x;
|
|
90
|
+
vec3 plane0normal = frame0ray;
|
|
91
|
+
vec3 plane0z;
|
|
92
|
+
vec3 frame0local = FrameTransform( projInterpolated, frame0ray, plane0x, plane0z );
|
|
93
|
+
frame0local.xz = frame0local.xz/_ImposterFrames.xx; //for displacement
|
|
94
|
+
|
|
95
|
+
//virtual plane UV coordinates
|
|
96
|
+
vec2 vUv0 = VirtualPlaneUV( plane0normal, plane0x, plane0z, planeCenter, size, rayLocal );
|
|
97
|
+
vUv0 /= _ImposterFrames.xx;
|
|
98
|
+
|
|
99
|
+
vec3 plane1x;
|
|
100
|
+
vec3 plane1normal = frame1ray;
|
|
101
|
+
vec3 plane1z;
|
|
102
|
+
vec3 frame1local = FrameTransform( projInterpolated, frame1ray, plane1x, plane1z);
|
|
103
|
+
frame1local.xz = frame1local.xz/_ImposterFrames.xx; //for displacement
|
|
104
|
+
|
|
105
|
+
//virtual plane UV coordinates
|
|
106
|
+
vec2 vUv1 = VirtualPlaneUV( plane1normal, plane1x, plane1z, planeCenter, size, rayLocal );
|
|
107
|
+
vUv1 /= _ImposterFrames.xx;
|
|
108
|
+
|
|
109
|
+
vec3 plane2x;
|
|
110
|
+
vec3 plane2normal = frame2ray;
|
|
111
|
+
vec3 plane2z;
|
|
112
|
+
vec3 frame2local = FrameTransform( projInterpolated, frame2ray, plane2x, plane2z );
|
|
113
|
+
frame2local.xz = frame2local.xz/_ImposterFrames.xx; //for displacement
|
|
114
|
+
|
|
115
|
+
//virtual plane UV coordinates
|
|
116
|
+
vec2 vUv2 = VirtualPlaneUV( plane2normal, plane2x, plane2z, planeCenter, size, rayLocal );
|
|
117
|
+
vUv2 /= _ImposterFrames.xx;
|
|
118
|
+
|
|
119
|
+
//add offset here
|
|
120
|
+
imp.vertex.xyz += vertexOffset;
|
|
121
|
+
//overwrite others
|
|
122
|
+
imp.uv = texcoord;
|
|
123
|
+
imp.grid = grid;
|
|
124
|
+
imp.frame0 = vec4(vUv0.xy,frame0local.xz);
|
|
125
|
+
imp.frame1 = vec4(vUv1.xy,frame1local.xz);
|
|
126
|
+
imp.frame2 = vec4(vUv2.xy,frame2local.xz);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
void main() {
|
|
130
|
+
vUv = uv;
|
|
131
|
+
|
|
132
|
+
ImposterData imp;
|
|
133
|
+
imp.vertex = vec4(position, 1.0);
|
|
134
|
+
imp.uv = uv;
|
|
135
|
+
|
|
136
|
+
ImposterVertex(imp);
|
|
137
|
+
|
|
138
|
+
gl_Position = imp.vertex;
|
|
139
|
+
|
|
140
|
+
float3 normalWorld = UnityObjectToWorldDir(v.normal.xyz);
|
|
141
|
+
float3 tangentWorld = UnityObjectToWorldDir(v.tangent.xyz);
|
|
142
|
+
float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWorld, tangentWorld, v.tangent.w);
|
|
143
|
+
o.tangentWorld = tangentToWorld[0];
|
|
144
|
+
o.bitangentWorld = tangentToWorld[1];
|
|
145
|
+
o.normalWorld = tangentToWorld[2];
|
|
146
|
+
|
|
147
|
+
//surface
|
|
148
|
+
o.texCoord.xy = imp.uv;
|
|
149
|
+
o.texCoord.zw = imp.grid;
|
|
150
|
+
o.plane0 = imp.frame0;
|
|
151
|
+
o.plane1 = imp.frame1;
|
|
152
|
+
o.plane2 = imp.frame2;
|
|
153
|
+
}
|
|
154
|
+
`;
|
|
155
|
+
const shader_fg = `
|
|
156
|
+
|
|
157
|
+
in vec2 vUv;
|
|
158
|
+
|
|
159
|
+
in vec4 plane0;
|
|
160
|
+
in vec4 plane1;
|
|
161
|
+
in vec4 plane2;
|
|
162
|
+
|
|
163
|
+
struct Material{
|
|
164
|
+
vec3 diffuse;
|
|
165
|
+
vec3 normal;
|
|
166
|
+
float depth;
|
|
167
|
+
float occlusion;
|
|
168
|
+
float roughness;
|
|
169
|
+
float metalness;
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
void ImposterSample( in ImposterData imp, out vec4 baseTex, out vec4 worldNormal )//, out half depth )
|
|
173
|
+
{
|
|
174
|
+
vec2 fracGrid = frac(imp.grid);
|
|
175
|
+
|
|
176
|
+
vec4 weights = TriangleInterpolate( fracGrid );
|
|
177
|
+
|
|
178
|
+
vec2 gridSnap = floor(imp.grid) / _ImposterFrames.xx;
|
|
179
|
+
|
|
180
|
+
vec2 frame0 = gridSnap;
|
|
181
|
+
vec2 frame1 = gridSnap + (lerp(vec2(0,1),vec2(1,0),weights.w)/_ImposterFrames.xx);
|
|
182
|
+
vec2 frame2 = gridSnap + (vec2(1,1)/_ImposterFrames.xx);
|
|
183
|
+
|
|
184
|
+
vec2 vp0uv = frame0 + imp.frame0.xy;
|
|
185
|
+
vec2 vp1uv = frame1 + imp.frame1.xy;
|
|
186
|
+
vec2 vp2uv = frame2 + imp.frame2.xy;
|
|
187
|
+
|
|
188
|
+
//resolution of atlas (Square)
|
|
189
|
+
float textureDims = _ImposterBaseTex_TexelSize.z;
|
|
190
|
+
//fractional frame size, ex 2048/12 = 170.6
|
|
191
|
+
float frameSize = textureDims/_ImposterFrames;
|
|
192
|
+
//actual atlas resolution used, ex 170*12 = 2040
|
|
193
|
+
float actualDims = floor(frameSize) * _ImposterFrames;
|
|
194
|
+
//the scale factor to apply to UV coordinate, ex 2048/2040 = 0.99609375
|
|
195
|
+
float scaleFactor = actualDims / textureDims;
|
|
196
|
+
|
|
197
|
+
vp0uv *= scaleFactor;
|
|
198
|
+
vp1uv *= scaleFactor;
|
|
199
|
+
vp2uv *= scaleFactor;
|
|
200
|
+
|
|
201
|
+
//clamp out neighboring frames TODO maybe discard instead?
|
|
202
|
+
vec2 gridSize = 1.0/_ImposterFrames.xx;
|
|
203
|
+
gridSize *= _ImposterBaseTex_TexelSize.zw;
|
|
204
|
+
gridSize *= _ImposterBaseTex_TexelSize.xy;
|
|
205
|
+
float2 border = _ImposterBaseTex_TexelSize.xy*_ImposterBorderClamp;
|
|
206
|
+
|
|
207
|
+
//vp0uv = clamp(vp0uv,frame0+border,frame0+gridSize-border);
|
|
208
|
+
//vp1uv = clamp(vp1uv,frame1+border,frame1+gridSize-border);
|
|
209
|
+
//vp2uv = clamp(vp2uv,frame2+border,frame2+gridSize-border);
|
|
210
|
+
|
|
211
|
+
//for parallax modify
|
|
212
|
+
vec4 n0 = tex2Dlod( _ImposterWorldNormalDepthTex, vec4(vp0uv, 0, 1 ) );
|
|
213
|
+
vec4 n1 = tex2Dlod( _ImposterWorldNormalDepthTex, vec4(vp1uv, 0, 1 ) );
|
|
214
|
+
vec4 n2 = tex2Dlod( _ImposterWorldNormalDepthTex, vec4(vp2uv, 0, 1 ) );
|
|
215
|
+
|
|
216
|
+
half n0s = 0.5-n0.a;
|
|
217
|
+
half n1s = 0.5-n1.a;
|
|
218
|
+
half n2s = 0.5-n2.a;
|
|
219
|
+
|
|
220
|
+
vec2 n0p = imp.frame0.zw * n0s;
|
|
221
|
+
vec2 n1p = imp.frame1.zw * n1s;
|
|
222
|
+
vec2 n2p = imp.frame2.zw * n2s;
|
|
223
|
+
|
|
224
|
+
//add parallax shift
|
|
225
|
+
vp0uv += n0p;
|
|
226
|
+
vp1uv += n1p;
|
|
227
|
+
vp2uv += n2p;
|
|
228
|
+
|
|
229
|
+
//clamp out neighboring frames TODO maybe discard instead?
|
|
230
|
+
vp0uv = clamp(vp0uv,frame0+border,frame0+gridSize-border);
|
|
231
|
+
vp1uv = clamp(vp1uv,frame1+border,frame1+gridSize-border);
|
|
232
|
+
vp2uv = clamp(vp2uv,frame2+border,frame2+gridSize-border);
|
|
233
|
+
|
|
234
|
+
vec2 ddxy = vec2( ddx(imp.uv.x), ddy(imp.uv.y) );
|
|
235
|
+
|
|
236
|
+
worldNormal = ImposterBlendWeights( _ImposterWorldNormalDepthTex, imp.uv, vp0uv, vp1uv, vp2uv, weights, ddxy );
|
|
237
|
+
baseTex = ImposterBlendWeights( _ImposterBaseTex, imp.uv, vp0uv, vp1uv, vp2uv, weights, ddxy );
|
|
238
|
+
|
|
239
|
+
//pixel depth offset
|
|
240
|
+
//half pdo = 1-baseTex.a;
|
|
241
|
+
//float3 objectScale = float3(length(float3(unity_ObjectToWorld[0].x, unity_ObjectToWorld[1].x, unity_ObjectToWorld[2].x)),
|
|
242
|
+
// length(float3(unity_ObjectToWorld[0].y, unity_ObjectToWorld[1].y, unity_ObjectToWorld[2].y)),
|
|
243
|
+
// length(float3(unity_ObjectToWorld[0].z, unity_ObjectToWorld[1].z, unity_ObjectToWorld[2].z)));
|
|
244
|
+
//vec2 size = _ImposterSize.xx * 2.0;// * objectScale.xx;
|
|
245
|
+
//vec3 viewWorld = mul( UNITY_MATRIX_VP, float4(0,0,1,0) ).xyz;
|
|
246
|
+
//pdo *= size * abs(dot(normalize(imp.viewDirWorld.xyz),viewWorld));
|
|
247
|
+
//depth = pdo;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
void main(){
|
|
251
|
+
|
|
252
|
+
}
|
|
253
|
+
`;
|
|
254
|
+
|
|
255
|
+
export class ImpostorShaderStandard extends RawShaderMaterial {
|
|
256
|
+
constructor() {
|
|
257
|
+
super({
|
|
258
|
+
fragmentShader: shader_fg,
|
|
259
|
+
vertexShader: shader_vx,
|
|
260
|
+
uniforms: {
|
|
261
|
+
/**
|
|
262
|
+
* RGB + Alpha
|
|
263
|
+
*/
|
|
264
|
+
tBase: {
|
|
265
|
+
value: null
|
|
266
|
+
},
|
|
267
|
+
/**
|
|
268
|
+
* Normal+Depth
|
|
269
|
+
*/
|
|
270
|
+
tGeometry: {
|
|
271
|
+
value: null
|
|
272
|
+
},
|
|
273
|
+
/**
|
|
274
|
+
* Material properties: Occlusion, Roughness, Metalness
|
|
275
|
+
* Alpha unused
|
|
276
|
+
*/
|
|
277
|
+
tMaterial: {
|
|
278
|
+
value: null
|
|
279
|
+
},
|
|
280
|
+
/**
|
|
281
|
+
* Number of frames
|
|
282
|
+
*/
|
|
283
|
+
uFrames: {
|
|
284
|
+
value: 0
|
|
285
|
+
},
|
|
286
|
+
/**
|
|
287
|
+
* Radius of bounding sphere of the impostor
|
|
288
|
+
*/
|
|
289
|
+
uRadius: {
|
|
290
|
+
value: 0
|
|
291
|
+
},
|
|
292
|
+
/**
|
|
293
|
+
* Impostor offset
|
|
294
|
+
*/
|
|
295
|
+
uOffset: {
|
|
296
|
+
value: new Vector3(0, 0, 0)
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
glslVersion: GLSL3
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
// Save some effort by disabling blending
|
|
303
|
+
this.blending = NoBlending;
|
|
304
|
+
|
|
305
|
+
}
|
|
306
|
+
}
|