@@ -615,7 +615,7 @@ uniform1i
615
615
## 概述解决方案
616
616
617
617
- 将支持各种功能的默认GLSL分解为多个小块
618
- - 用户实现GLSL的JSON配置文件,指定如何组合小块的GLSL ,以及指定在渲染时需要发送的顶点数据和Uniform数据的配置数据
618
+ - 用户实现GLSL的JSON配置文件,指定如何拼接小块的GLSL ,以及指定在渲染时需要发送的顶点数据和Uniform数据的配置数据
619
619
620
620
621
621
## 给出UML?
@@ -631,37 +631,45 @@ Client是用户
631
631
632
632
我们看下数据和ChunkConverter这两个部分:
633
633
634
- GLSL Config是的GLSL的JSON配置文件,它的内容由用户给出,它的格式(也就是类型)由ChunkHandler定义
634
+ Target GLSL是支持某些功能的一套GLSL,相当于之前的BasicMaterialShaderGLSL(Add Define)或者PBRMaterialShaderGLSL(Add Define),两者的区别是Target GLSL没有预定义的宏,它只有支持的功能的GLSL,没有分支
635
+ 一套Target GLSL包括了一个VS GLSL和一个FS GLSL
636
+ 这里最多可有8套Target GLSL,分别对应基础材质的4种情况和PBR材质的4种情况
637
+
638
+
639
+ Send Config是如何获得和发送顶点数据和Uniform数据的配置数据
640
+ 具体来说,每个Send Config包括了多个getData函数和多个sendData函数,前者获得对应的顶点数据或者Uniform数据,后者发送它们
641
+ 因为一个Send Config对应一套Target GLSL,所以最多有8个Send Config
642
+
643
+
644
+
645
+
646
+
647
+ GLSL Config是的GLSL的JSON配置文件,用来指定如何拼接Target GLSL,并包括了Send Config
648
+ 它的内容由用户给出,它的格式(也就是类型)由ChunkHandler定义
649
+
635
650
636
651
GLSL Chunk是一小块的GLSL,有多个GLSL Chunk,它们由引擎给出
637
652
一个GLSL Chunk可以是VS GLSL中一小块GLSL文件(如common_vertex.glsl),也可以是FS GLSL中一小块GLSL文件(common_fragment.glsl)
638
653
639
654
655
+ ChunkConverter负责转换GLSL Chunk
640
656
因为GLSL Chunk是自定义文件,有一些自定义的语法,不能直接使用,所以引擎需要调用gulp任务来对其预处理。
641
657
在gulp任务中,调用了ChunkConverter来处理所有的GLSL Chunk,并将其合并为一个Merged GLSL Chunk,成为一个Typescript或者Rescript文件
642
658
<!-- 这样做的原因是GLSL Chunk是自定义的文件,不能直接被Typescript或者Rescript调用,所以需要将其转换为可被调用文件;另外,需要将其集中在一个文件中,方便管理 -->
643
659
644
660
645
- Send Config是一个Shader的获得和发送顶点数据和Uniform数据的配置数据
646
- 具体来说,每个Send Config包括了多个getData函数和多个sendData函数,前者获得对应的顶点数据或者Uniform数据,后者发送它们
647
- 因为这里最多有8个Shader,所以最多有8个Send Config
648
-
649
661
650
- Target GLSL是支持某些功能的一套GLSL,相当于之前的BasicMaterialShaderGLSL(Add Define)或者PBRMaterialShaderGLSL(Add Define),两者的区别是Target GLSL没有预定义的宏,它只有支持的功能的GLSL,没有分支
651
- 一套Target GLSL包括了一个VS GLSL和一个FS GLSL
652
- 这里最多可有8套Target GLSL,分别对应基础材质的4种情况和PBR材质的4种情况
653
662
663
+ 我们看下ChunkHandler和引擎这两个部分:
654
664
665
+ ChunkHandler负责拼接Target GLSL和获得Send Config
655
666
656
- 我们看下引擎和ChunkHandler这两个部分:
657
667
658
668
Engine、Render跟之前一样
659
669
<!-- Engine是引擎的门户,负责封装API给Client -->
660
670
<!-- Engine有一个EngineState,用来保存引擎的所有数据; -->
661
671
662
672
InitMaterialShader负责初始化所有材质的Shader,它有两个函数:initBasicMaterialShader、initPBRMaterialShader,分别负责初始化所有基础材质的Shader和初始化所有PBR材质的Shader
663
-
664
-
665
673
这两个函数遍历了所有的基础材质或者PBR材质,在每次遍历中的步骤一样,具体步骤如下:
666
674
通过调用ChunkHandler的buildGLSL函数,按照GLSL Config的配置数据将Merged GLSL Chunk中对应的GLSL Chunk拼接为一个Target GLSL,然后使用它创建材质使用的shaderIndex和program;
667
675
通过调用ChunkHandler的getSendConfig函数,从GLSL Config中获得Send Config
@@ -711,7 +719,7 @@ shader_chunks.json是一个数组,其中的每个元素定义了一套GLSL Chu
711
719
712
720
713
721
这两个文件的关系是“总-分”的关系,具体如下:
714
- 因为每种Shader的GLSL由多个GLSL Chunk组合而成 ,所以shaders.json是“总”,shader_chunks.json是“分”
722
+ 因为每种Shader的GLSL由多个GLSL Chunk组合拼接而成 ,所以shaders.json是“总”,shader_chunks.json是“分”
715
723
716
724
717
725
下面我们来看下这两个文件的主要代码:
@@ -821,7 +829,7 @@ shaders字段定义了所有种类的Shader的GLSL配置数据
821
829
值得说明的是:
822
830
实际上也存在没有材质的Shader,如后处理(如绘制轮廓)的Shader、天空盒的Shader等,这些种类的Shader也定义在shaders字段,只是没有对应材质而已。这种Shader我们会在后面的扩展中讨论
823
831
824
- 每种Shader的GLSL由多个GLSL Chunk组合而成 ,它们定义在shader_chunks字段中
832
+ 每种Shader的GLSL由多个GLSL Chunk组合拼接而成 ,它们定义在shader_chunks字段中
825
833
<!-- groups字段定义了多组GLSL Chunk,每组的value字段包括了多个GLSL Chunk,它们跟shader_chunks.json的name关联 -->
826
834
<!-- 此处定义了一个名为render_basic的Shader,它包括的所有的代码块定义在shader_chunks字段中。 -->
827
835
在shader_chunks字段中,如果type为static_branch,那么就通过name关联到static_branchs字段;
@@ -990,7 +998,7 @@ export let createState = ([shaders, shaderChunks]): state => {
990
998
991
999
992
1000
引擎定义的GLSL Chunk具体是后缀名为.glsl的文件
993
- 我们通过自定义的字符:@top 、@define 、@varDeclare 、@funcDeclare 、@funcDefine 、@body 以及对应的@end ,将一个完整的GLSL分割为从上往下的不同区域的的代码片段,这样便于更细粒度的组合
1001
+ 我们通过自定义的字符:@top 、@define 、@varDeclare 、@funcDeclare 、@funcDefine 、@body 以及对应的@end ,将一个完整的GLSL分割为从上往下的不同区域的代码片段,这样便于更细粒度的组合拼接
994
1002
995
1003
一个GLSL Chunk可以包括多个区域的代码片段
996
1004
@@ -1236,7 +1244,7 @@ _initOneMaterialTypeShader函数在遍历所有的基础材质时,首先调用
1236
1244
<!-- 值得说明的是: -->
1237
1245
ChunkHandler的buildGLSL函数和getSendConfig函数都接受了引擎实现的函数,它们被用于处理shaders.json和shader_chunks.json中的一些字段,从而实现分支处理或者从中获得Send Config
1238
1246
1239
- 因为这些字段的值是离散的,它们的的范围是引擎定义的 ,用户只能从范围内选择某个具体的值,所以这些字段的类型是定义在引擎端,类型中明确了有哪些值的范围 。
1247
+ 因为这些字段的值是离散的,它们的范围是引擎定义的 ,用户只能从范围内选择某个具体的值,所以这些字段的类型是定义在引擎端,在类型中明确了有哪些值的范围 。
1240
1248
<!-- 具体是定义在引擎的GLSLConfigType.ts中,代码如下: -->
1241
1249
类型定义的部分代码如下:
1242
1250
GLSLConfigType
@@ -1402,84 +1410,129 @@ let _sendUniformData = (uniformSendConfig: Array<uniformSendConfig>, state: stat
1402
1410
## 一句话定义?
1403
1411
1404
1412
1405
- TODO continue
1406
-
1407
1413
<!-- 可配置地拼接小块数据 -->
1408
1414
1409
- 分解包括各种分支的大数据为小块单位 ,按照配置文件来拼接
1415
+ 分解有各种分支的大数据为多个小块数据 ,按照配置文件来拼接
1410
1416
1411
1417
1412
1418
## 补充说明
1413
1419
1414
- 把每个分支对应的数据都对应分解为一块数据;
1420
+ 大数据中的每个分支都可以分解为一块数据,如有下面的一个大数据:
1421
+ ``` ts
1422
+ #ifdef INSTANCE
1423
+ 数据1
1424
+ #endif
1425
+
1426
+ #ifdef NO_INSTANCE
1427
+ 数据2
1428
+ #endif
1429
+ ```
1430
+ 它有两个分支,可以将其分解为数据1、数据2这两个小块数据
1415
1431
1416
- 由用户给出配置文件来指定:有哪些分支、要构造哪些Target数据、每个Target数据包括哪些块、每块有哪些配置数据
1432
+
1433
+ 配置文件由用户给出,包括下面的内容:
1434
+ 有哪些分支、要构造哪些Target数据、每个Target数据包括哪些块、每块有哪些配置数据
1417
1435
1418
1436
1419
1437
1420
1438
1421
1439
## 通用UML?
1422
- ![ image ] ( https://img2023.cnblogs.com/blog/419321/202304/419321-20230403163737312-1241675852.png )
1440
+ TODO tu
1423
1441
1424
1442
1425
1443
1426
1444
## 分析角色?
1427
1445
1428
1446
我们来看看模式的相关角色:
1429
1447
1430
- TODO rename Main to System
1448
+ 总体来看,分为数据、ChunkConverter、ChunkHandler、系统这四个部分
1449
+
1450
+
1451
+ 我们看下数据和ChunkConverter这两个部分:
1452
+
1453
+
1454
+ - Target
1455
+ 该角色是拼接后的符合某种特定分支条件的数据,如[ 支持方向光,支持贴图,支持Instance] 的GLSL就是一个Target
1456
+
1457
+ - Runtime Config
1458
+ 该角色是如何操作运行时数据的配置数据
1459
+ 具体来说,每个Runtime Config包括了多个getData函数和多个sendData函数,前者获得对应的运行时数据,后者发送它们
1460
+ <!-- 因为一个Send Config对应一个Shader,而这里最多有8个Shader,所以最多有8个Send Config -->
1461
+
1462
+ <!-- ,它在初始化时从Target Config中获得,在运行时被使用 -->
1463
+
1431
1464
1432
1465
1433
- TODO rename Runtime Data to Runtime Config
1434
1466
1435
1467
- Target Config
1436
- 该角色是配置数据,用来指定如何拼接数据
1468
+ 该角色是配置数据,用来指定如何拼接Target,并包括了Runtime Config
1469
+ 它的内容由用户给出,它的格式(也就是类型)由ChunkHandler定义
1470
+ Target Config中某些字段的值是离散的,它们的范围是系统定义的,用户只能从范围内选择某个具体的值
1437
1471
1438
1472
- Target Chunk
1439
- 该角色是小块的数据,它是通过对原始的大数据抽象分解后得到的,一般来说大数据中的一个分支对应一个Target Chunk数据
1473
+ 该角色是小块的数据,由系统给出
1474
+ <!-- 它是通过对原始的大数据抽象分解后得到的,一般来说大数据中的一个分支对应一个Target Chunk数据 -->
1440
1475
1441
- - Merged Target Chunk
1442
- 该角色是合并了所有的Target Chunk后的数据,它将所有的Target Chunk文件合并为一个Hash Map
1443
1476
1444
- - Target
1445
- 该角色是拼接后的符合某种特定分支条件的数据,如[ 支持方向光,支持贴图,支持Instance] 的GLSL
1446
1477
1447
- - Runtime Data
1448
- 该角色是运行时数据,它在初始化时从Target Config中获得,在运行时被使用
1449
1478
1450
1479
- ChunkConverter
1451
- 该角色负责在预处理时合并所有的Target Chunk为一个Merged Target Chunk文件
1480
+ 该角色负责在系统预处理处理Target Chunk,并将其合并为一个Merged Target Chunk
1481
+
1482
+
1483
+ - Merged Target Chunk
1484
+ 该角色是合并了所有的Target Chunk后的数据,它是一个Typescript或者Rescript文件
1485
+
1486
+
1487
+
1488
+ 我们看下ChunkHandler和系统这两个部分:
1452
1489
1453
1490
- ChunkHandler
1454
- 该角色定义了Target Config的格式(也就是类型),并且实现了拼接Target和获得Runtime Data的相关函数
1491
+ 该角色负责拼接Target和获得Runtime Config
1455
1492
1456
- - Main
1493
+ - System
1457
1494
该角色为系统的门户,提供API给Client
1458
1495
1459
1496
- Init
1460
- 该角色实现系统的初始化,调用ChunkHandler->buildTarget来拼接了Target并且直接使用它,调用ChunkHandler->getRuntimeData来获得了Runtime Data
1497
+ 该角色实现系统的初始化,它包括下面的步骤:
1498
+ 调用ChunkHandler的buildTarget函数,按照Target Config的配置数据将Merged Target Chunk中对应的Target Chunk拼接为一个Target,然后使用它;
1499
+ 调用ChunkHandler的getRuntimeConfig函数,从Target Config中获得Runtime Config
1461
1500
1462
1501
- OperateWhenRuntime
1463
- 该角色进行某个在运行时的操作,使用了Runtime Data
1502
+ 该角色在运行时进行某个操作(如渲染),使用了Runtime Config
1503
+
1504
+
1505
+
1506
+ <!-- ## 与之前构造GLSL案例的UML的区别
1507
+
1508
+ TODO -->
1464
1509
1465
1510
1466
1511
## 角色之间的关系?
1467
1512
1468
- - 应该有多个Target Chunk,它们由系统给出
1513
+ - 有多个Target Chunk
1469
1514
1470
- - Target Config的格式由ChunkHandler定义。其中由系统处理的字段的类型由系统再次定义,目的是定义这些字段的所有可能的值
1515
+ <!-- - Target Config的格式由ChunkHandler定义。其中由系统处理的字段的类型由系统再次定义,目的是定义这些字段的所有可能的值 -->
1471
1516
1472
- - Target Config的内容由Client给出
1517
+ <!-- - Target Config的内容由Client给出 -->
1473
1518
1474
1519
- Target Config通常包含两个配置文件:targets_config、chunks_config
1520
+ 这两个文件的关系是“总-分”的关系,其中targets_config是“总”,chunks_config是“分”
1475
1521
1476
- - 应该有多个Target ,如[ 支持方向光,支持贴图,支持Instance] 的GLSL和 [ 支持方向光,不支持贴图,支持Instance] 的GLSL
1522
+ - 有多个Target ,如[ 支持方向光,支持贴图,支持Instance] 的GLSL是一个Target, [ 支持方向光,不支持贴图,支持Instance] 的GLSL是另外一个Target
1477
1523
1524
+ - 有多个Runtime Config,一个Runtime Config对应一个Target
1478
1525
1479
1526
## 角色的抽象代码?
1480
1527
1528
+
1529
+ 值得注意的是:
1530
+ 这里只考虑了一个Target和一个Runtime Config的情况,因此Init中也没有进行遍历
1531
+
1532
+
1481
1533
下面我们来看看各个角色的抽象代码:
1482
1534
1535
+ TODO continue
1483
1536
1484
1537
- 一个Target Chunk的抽象代码
1485
1538
``` ts
@@ -1659,7 +1712,7 @@ state = operateWhenRuntime(state)
1659
1712
` ` ` ts
1660
1713
declare function _handleConfigFunc1(state: state, someConfigData): any
1661
1714
1662
- declare function _addRuntimeDataFunc1(someRuntimeDataFromState , someConfigData): any
1715
+ declare function _addRuntimeConfigFunc1(someRuntimeConfigFromState , someConfigData): any
1663
1716
1664
1717
export let parseConfig = ChunkHandler.parseConfig
1665
1718
@@ -1683,21 +1736,21 @@ export let init = (state: state, someConfigData): state => {
1683
1736
1684
1737
console.log("使用target...")
1685
1738
1686
- let runtimeData = ChunkHandler.getRuntimeData (
1687
- [_addRuntimeDataFunc1 , ... ],
1739
+ let runtimeConfig = ChunkHandler.getRuntimeConfig (
1740
+ [_addRuntimeConfigFunc1 , ... ],
1688
1741
1689
1742
target
1690
1743
)
1691
1744
1692
1745
return {
1693
1746
...state,
1694
1747
target: target,
1695
- runtimeData: runtimeData
1748
+ runtimeConfig: runtimeConfig
1696
1749
}
1697
1750
}
1698
1751
1699
1752
export let operateWhenRuntime = (state: state): state => {
1700
- console.log("使用state.runtimeData ...")
1753
+ console.log("使用state.runtimeConfig ...")
1701
1754
1702
1755
return state
1703
1756
}
@@ -1711,9 +1764,9 @@ type target = any
1711
1764
1712
1765
export declare function buildTarget(handleConfigFuncs, parsedConfig: config, targetChunk, someConfigData): target
1713
1766
1714
- type runtimeData = any
1767
+ type runtimeConfig = any
1715
1768
1716
- export declare function getRuntimeData(addRuntimeDataFuncs , target: target): runtimeData
1769
+ export declare function getRuntimeConfig(addRuntimeConfigFuncs , target: target): runtimeConfig
1717
1770
` ` `
1718
1771
1719
1772
@@ -1734,7 +1787,7 @@ TODO finish
1734
1787
拼接后的Target 数据没有分支判断,非常精简
1735
1788
1736
1789
- 提高性能
1737
- 系统能够在初始化时一次性从配置文件中获得Runtime Data ,然后在运行时无需进行分支判断而是直接发送Runtime Data ,这样就提高了性能
1790
+ 系统能够在初始化时一次性从配置文件中获得Runtime Config ,然后在运行时无需进行分支判断而是直接发送Runtime Config ,这样就提高了性能
1738
1791
1739
1792
1740
1793
0 commit comments