From c901292ca0b21946bc9a7c115ac2882c0bf5a5b9 Mon Sep 17 00:00:00 2001 From: wuyize Date: Tue, 9 Aug 2022 12:31:39 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BA=8C=E7=BA=A7=E7=BC=96=E7=A0=81=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E9=A2=9C=E8=89=B2=E6=9D=90=E8=B4=A8=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 2st_encode/2st_encode.md | 140 +++++++++++++++++++++++++++++++++------ 1 file changed, 120 insertions(+), 20 deletions(-) diff --git a/2st_encode/2st_encode.md b/2st_encode/2st_encode.md index 93b38b6..9bfeea4 100644 --- a/2st_encode/2st_encode.md +++ b/2st_encode/2st_encode.md @@ -1,22 +1,47 @@ -二级编码大体结构及渲染流程如下: +目标:实现分辨率无关的、具有较高随机访问性能、相对节省显存的矢量图渲染,使得其使用方式与传统texture类似,便于在任意形状mesh中应用矢量图贴图。 -首先分为图元和索引两大块,图元内坐标范围为-1到1,一张图中可能有多个相同的图元,这些图元只需在图元缓存中保存一次,为了记录图元的位置和变换信息,对图元建立一个索引结构,同时为了方便求交,使用BVH层次包围盒结构,BVH每个结点包含leftChild,rightChild和bound即包围盒坐标,BVH的最后一个结点的leftChild为图元索引加上BVH数组长度,rightChild特殊处理为逆时针旋转角度。 +# 渲染流程 -图元由轮廓包围的封闭图形和线条构成,轮廓可以由直线、二阶贝塞尔曲线和三阶贝塞尔曲线组成,支持任意数量轮廓围成的图形的渲染,轮廓围成的图形中不能含有空腔,对于一个复杂的含有许多轮廓的封闭图形而言,应当尽可能将其分割成数个由三段轮廓线包围的广义三角形,并对这些广义三角形以及不构成图形的线条建立BVH索引,图元内BVH索引存储在外部BVH数组后。 +## 总体流程 -着色器接收的5个buffer: +1. 普通mesh将基础色、世界坐标、法线、金属度和粗糙度、彩绘编号(0)输出到gbuffer,彩绘mesh将世界坐标、法线、彩绘编号、彩绘纹理坐标输出到gbuffer; + +2. compute shader根据彩绘编号、彩绘纹理坐标gbuffer来计算彩绘纹理,更新基础色、金属度和粗糙度gbuffer; + +3. 根据基础色、世界坐标、法线、金属度和粗糙度gbuffer,以及光源计算光照。 + +后续计划实现shadow mapping。 + +## 计算彩绘纹理流程 + +彩绘由许多不同的图元组成,一个图元可以由一系列贝塞尔曲线和贝塞尔曲线封闭的图形组成,同一图元可能在彩绘中反复出现,故计算彩绘纹理的过程就是根据矢量图纹理坐标,计算像素点对应哪个图元的哪个部位,得到颜色和材质,相当于在二维平面中做光线追踪。为了加速这一过程,将图元中的一个由数条曲线围成的封闭图形拆成多个由三条曲线围成的封闭图形,对每个图形和每段不构成封闭图形的贝塞尔曲线建立BVH层次包围盒加速结构,再对每个图元建立BVH。由此,计算每个像素点的过程即为遍历两个BVH找到像素点对应的图形或曲线,对于图形,判断点是否在图形内;对于线条,判断点到曲线的距离是否小于一定值,然后根据指定的样式计算其颜色和材质。 + +# 二级编码结构 + +首先分为图元和索引两大块,图元内坐标范围为-1到1,一张图中可能有多个相同的图元,这些图元只需在图元缓存中保存一次,为了记录图元的位置和变换信息,对图元建立一个索引结构,同时为了方便求交,使用BVH层次包围盒结构,BVH每个结点包含bvhChildren(每个结点的两个儿子,x分量为左儿子,y分量为右儿子)和bound(包围盒坐标,QVector4D(左下角x,左下角y,右上角x,右上角y)),BVH的最后一个结点的左儿子为图元索引加上BVH数组长度,右儿子特殊处理为图元zIndex和逆时针旋转角度。 + +图元由轮廓包围的封闭图形和线条构成,轮廓可以由直线、二阶贝塞尔曲线和三阶贝塞尔曲线组成,支持任意数量轮廓围成的图形的渲染,轮廓围成的图形中不能含有空腔,对于一个复杂的含有许多轮廓的封闭图形而言,应当将其分割成数个由三段轮廓线包围的广义三角形,并对这些广义三角形以及不构成图形的线条建立BVH索引,图元内BVH索引存储在外部BVH数组后。 + +compute shader接收的6个buffer: ```glsl -layout(std430, binding = 1) buffer bvhBuffer +layout(std430, binding = 1) buffer paintingOffsetBuffer +{ + /********************** + ** @[0] paintingBvhRoot + ** @[1] paintingBvhLength + **********************/ + uint paintingOffsets[][2]; +}; +layout(std430, binding = 2) buffer bvhBuffer { - uint bvhLength; uvec2 bvhChildren[]; }; -layout(std430, binding = 2) buffer bvhBoundBuffer +layout(std430, binding = 3) buffer bvhBoundBuffer { vec4 bvhBound[]; }; -layout(std430, binding = 3) buffer elementOffsetBuffer +layout(std430, binding = 4) buffer elementOffsetBuffer { /********************** ** @x elementBvhRoot @@ -26,30 +51,29 @@ layout(std430, binding = 3) buffer elementOffsetBuffer **********************/ uvec4 elementOffsets[]; }; -layout(std430, binding = 4) buffer elementIndexBuffer +layout(std430, binding = 5) buffer elementIndexBuffer { uint elementIndex[]; //线和面 }; -layout(std430, binding = 5) buffer elementDataBuffer +layout(std430, binding = 6) buffer elementDataBuffer { float elementData[]; //点和Style }; ``` -bvhLength为外部索引数组长度,bvhChildren为每个结点的两个儿子,x分量为左儿子,y分量为右儿子。 - -传入示例: +提供工具类合并多张彩绘的buffer,一张彩绘的参数示例: ```c++ - GLuint bvhChildren[] = {7/*rootBVH长度*/,0/*与显存对齐*/, + GLuint paintingBvhLength = 7; + GLuint bvhChildren[] = { //root 1,2, 3,4, 5,6, 7,0, 7,30./360* 4294967296 /*右儿子用来表示旋转角度*/, 8,0, 7,0, //elememt0 1,2, - 5+28/*contour索引,由于contour不定长,这里需要给到contour在elementIndex中位置*/,5+12/*style索引,在elementData中位置*/, 3,4, - 5+36,5+12, 5+32,5+12, + 5+0/*contour索引*/,5+12/*style索引,在elementData中位置*/, 3,4, + 5+2,5+12, 5+1,5+12, //elememt1 1+0/*line索引,element中第几条*/,1 + 25 @@ -90,10 +114,10 @@ bvhLength为外部索引数组长度,bvhChildren为每个结点的两个儿子 4,4,5,5, 1,1,3,3, 3,3,5,5, - //contours, 第一个元素指明轮廓段数,后面为lines索引 - 3, 0,1,2, - 3, 2,3,4, - 3, 3,5,6, + //contours, 每个轮廓三个线索引 + 0,1,2, + 2,3,4, + 3,5,6, //element2 //lines @@ -130,3 +154,79 @@ bvhLength为外部索引数组长度,bvhChildren为每个结点的两个儿子 }; ``` +fillStyle格式: + +第一个元素:0,代表填充封闭图形 + +第二个元素:填充方式 + +​ 0,单色 + +​ 1,按直线渐变 + +​ 2,按点渐变 + +后续元素: + +对于单色:5个元素分别为R,G,B,Metallic,Roughness + +对于按直线渐变:起点坐标,终点坐标,段数,[{在直线中相对位置,颜色材质}, ...] + +对于按点渐变:点数,[{坐标,权重,颜色材质}, ...] + + + +strokeStyle格式: + +第一个元素:1,代表画线 + +第二个元素:线宽 + +第三个元素:0,圆角 + +​ 1,直角 + +​ 2,起点圆角终点直角 + +​ 3,起点直角终点圆角 + +第四个元素:线内填充方式 + +​ 0,单色 + +​ 1,按直线渐变 + +​ 2,按点渐变 + +​ 3,按当前线条渐变 + +第五个元素:线外描边宽度 + +第六个元素:线外描边方式 + +​ 0,单色 + +​ 1,分层设色 + +​ 2,渐变 + +后续元素: + +线内填充数据: + +对于单色:5个元素分别为R,G,B,Metallic,Roughness + +对于按直线渐变:起点坐标,终点坐标,段数,[{在直线中相对位置,权重,颜色材质}, ...] + +对于按点渐变:点数,[{坐标,权重,颜色材质}, ...] + +对于按当前线条渐变:段数,[{在线条中相对位置,权重,颜色材质}, ...] + +线外描边数据: + +对于单色:5个元素分别为R,G,B,Metallic,Roughness + +对于分层设色:层数,[{相对宽度,颜色材质}, ...] + +对于渐变:层数,[{相对位置(由里到外0~1),权重,颜色材质}, ...] +