用-force –opengl 指令_OpenGL-使用Tessellation技术绘制Cubic Bézier Patches
全球圖形學領域教育的領先者、自研引擎的倡導者、底層技術研究領域的技術公開者,東漢書院在致力于使得更多人群具備內核級競爭力的道路上,將帶給小伙伴們更多的公開技術教學和視頻,感謝一路以來有你的支持。我們正在用實際行動來幫助小伙伴們構建一套成體系的圖形學知識架構,你在我們這里獲得的不止于那些毫無意義的代碼,我們這里更多的是代碼背后的故事,以及精準、透徹的理解。我們不會扔給人們一本書或者給個思路讓人們去自學,我們是親自來設計出好的課程,讓人們明白到底背后還有哪些細節。
這里插播一個引擎大賽的消息,感興趣的同學可以看一眼,這也是東漢書院的立項使命:
東漢書院:自研引擎大賽?zhuanlan.zhihu.comIn the displacement mapping example, all we did was use a (very large) texture to drive displacement from a flat surface and then use tessellation to increase the number of polygons in the scene. This is a type of brute-force, data-driven approach to geometric complexity. In the cubicbezier example described here, we will use math to drive geometry—we’re going to render a cubic Bézier patch. If you revisit Chapter 4, “Math for 3D Graphics”, you’ll see that we’ve covered all the number crunching we’ll need here.
在置換貼圖的例子中,我們所做的事情就是用一個紋理去使得一個平面進行偏移并且使用tessellation技術來增加場景中的幾何形體的個數。這是一種比較簡單粗暴的玩法。在cubicbezier的例子中,我們 將會使用數學知識來構建幾何形體。如果你回顧一下第四章的內容,你將會看到我們如何來使用那些理論。
A cubic Bézier patch is a type of higher-order surface and is defined by control points that provide input to the interpolation functions that define the surface’s shape. A Bézier patch has 16 control points, laid out in a 4 × 4 grid. Very often (including in this example), those control points are equally spaced in two dimensions, varying only in distance from a shared plane. However, they don’t have to be. Free-form Bézier patches are an extremely powerful modeling tool being used natively by many pieces of modeling and design software. With OpenGL tessellation, it’s possible to render them directly.
一個cubic bezier patch是一種高階曲面,它是由一些控制點來定義的,我們可以通過這些控制點插值出來幾何體表面上的各個點。一個bezier patch有16個控制點,組成了一個4x4的網格。通常情況下, 那些控制點之間是等間距,變化的部分僅僅是到共享平面的距離。然而這并不重要。在建模軟件中,自由形式的bezier patch是非常好的建模工具。通過OpenGL的tessellation技術,我們可以直接渲染出他們來。
The simplest method of rendering a Bézier patch is to treat the four control points in each row of the patch as the control points for a single cubic Bézier curve, just as was described in Chapter 4. Given our 4 × 4 grid of control points, we have four curves; if we interpolate along each of them using the same value of t, we will end up with four new points. We use these four points as the control points for a second cubic Bézier curve. Interpolating along this second curve using a new value for t gives us a second point that lies on the patch. The two values of t (let’s call them t0 and t1) are the domain of the patch and are handed to us by the tessellation evaluation shader in http://gl_TessCoord.xy.In this example, we’ll perform tessellation in view space. That is, in our vertex shader, we’ll transform our patch’s control points into view space by multiplying their coordinates by the model–view matrix. This simple vertex shader is shown in Listing 8.12.
就如同第四章介紹的那樣,最簡單的渲染bezier patch的方法就是把每一行的四個控制點都當成是一個cubic bezier曲線的控制點。如此一來,給我們4x4個控制點之后,我們就可以得到四條曲線。如果我們 對它們進行插值的都是使用同一個插值因子t,那么我們將會得到四個新的點。我們使用這四個點產生第二個cubic bezier曲線。在我們第二條cubic bezier曲線進行插值的時候,我們使用另外的一個t值進行插值,這樣 我們就可以拿到第二批點。這倆t值是存在于patch領域下的,并且通過tessellation evaluation shader的gl_TessCoord.xy傳給我們。在本例子中,我們在視口空間進行曲面細分。也就是說,我們的vertex shader中, 我們要把我們的patch的控制點都轉到視口空間里來。清單8.12展示了我們的vertex shader。
#version 450 core in vec4 position; uniform mat4 mv_matrix; void main(void){gl_Position = mv_matrix * position; }Listing 8.12: Cubic Bézier patch vertex shader
Once our control points are in view space, they are passed to our tessellation control shader. In a more advanced algorithm, we could project the control points into screen space, determine the length of the curve, and set the tessellation factors appropriately. However, in this example, we’ll settle for a simple fixed tessellation factor. As in previous examples, we set the tessellation factor only when gl_InvocationID is zero, but pass all of the other data through once per invocation. The tessellation control shader is shown in Listing 8.13.
當我們的控制點都轉到視口空間下來了之后,他們將會被發送給tessellation control shader。在一些更進一步的算法中,我們可以把這些控制點投影到屏幕空間里去,這樣就可以求得 曲線的長度,然后就可以設置合適的細分因子了。然而在本例子中,我們只是簡單的設置一個固定的細分因子。如同前面的那些例子,我們僅當gl_InstanceID等于0的時候才去設置細分因子, 把其他數據簡單粗暴的傳給下一個shader階段。清單8.13展示了tessellation control shader。
#version 450 corelayout (vertices = 16) out; void main(void){if (gl_InvocationID == 0){gl_TessLevelInner[0] = 16.0;gl_TessLevelInner[1] = 16.0;gl_TessLevelOuter[0] = 16.0;gl_TessLevelOuter[1] = 16.0;gl_TessLevelOuter[2] = 16.0;gl_TessLevelOuter[3] = 16.0;}gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; }Listing 8.13: Cubic Bézier patch tessellation control shader
Next, we come to the tessellation evaluation shader, which is where the meat of the algorithm is found. The shader in its entirety is shown in Listing 8.14. You should recognize the cubic_bezier and quadratic_bezier functions from Chapter 4. The evaluate_patch function is responsible for evaluating the vertex’s coordinate given the input patch coordinates and the vertex’s position within the patch.
下一步,我們來到tessellation evaluation shader里面了,在這里我們實現核心的算法部分。清單8.14展示了全部的代碼清單。你應該可以看得明白cubic_bezier和quadratic_bezier 函數了,因為第4章介紹過的。evaluate_patch函數就是用來根據輸入的patch的坐標和在patch里的那些點的位置來生成頂點的坐標的。
#version 450 core layout (quads, equal_spacing, cw) in; uniform mat4 mv_matrix; uniform mat4 proj_matrix; out TES_OUT{vec3 N; } tes_out; vec4 quadratic_bezier(vec4 A, vec4 B, vec4 C, float t){vec4 D = mix(A, B, t);vec4 E = mix(B, C, t);return mix(D, E, t); } vec4 cubic_bezier(vec4 A, vec4 B, vec4 C, vec4 D, float t){vec4 E = mix(A, B, t);vec4 F = mix(B, C, t);vec4 G = mix(C, D, t);return quadratic_bezier(E, F, G, t); } vec4 evaluate_patch(vec2 at){vec4 P[4];int i;for (i = 0; i < 4; i++){P[i] = cubic_bezier(gl_in[i + 0].gl_Position,gl_in[i + 4].gl_Position,gl_in[i + 8].gl_Position,gl_in[i + 12].gl_Position,at.y);}return cubic_bezier(P[0], P[1], P[2], P[3], at.x); } const float epsilon = 0.001; void main(void){vec4 p1 = evaluate_patch(gl_TessCoord.xy);vec4 p2 = evaluate_patch(gl_TessCoord.xy + vec2(0.0, epsilon));vec4 p3 = evaluate_patch(gl_TessCoord.xy + vec2(epsilon, 0.0));vec3 v1 = normalize(p2.xyz - p1.xyz);vec3 v2 = normalize(p3.xyz - p1.xyz);tes_out.N = cross(v1, v2);gl_Position = proj_matrix * p1; }Listing 8.14: Cubic Bézier patch tessellation evaluation shader
In our tessellation evaluation shader, we calculate the surface normal to the patch by evaluating the patch position at two points very close to the point under consideration, using the additional points to calculate two vectors that lie on the patch and then taking their cross product. This result is passed to the fragment shader shown in Listing 8.15.
在我們的tessellation evaluation shader中,我們先根據patch中的兩個點計算出這種條件下額外的一個點,然后用這額外的一個點構成2個在這個patch上的向量,然后叉乘出來法線。這個結果會傳給 清單8.15展示的fragment shader。
#version 450 coreout vec4 color; in TES_OUT{vec3 N; }fs_in; void main(void){vec3 N = normalize(fs_in.N);vec4 c = vec4(1.0, -1.0, 0.0, 0.0) * N.z + vec4(0.0, 0.0, 0.0, 1.0);color = clamp(c, vec4(0.0), vec4(1.0)); }Listing 8.15: Cubic Bézier patch fragment shader
This fragment shader performs a very simple lighting calculation using the z component of the surface normal. The result of rendering with this shader is shown in Figure 8.14.
這個fragment shader根據表面的法線的z分量簡單粗暴的計算出了光照。圖8.14展示了渲染出來的結果圖像。
Because the rendered patch shown in Figure 8.14 is smooth, it is difficult to see the tessellation that has been applied to the shape. The left side of Figure 8.15 shows a wireframe representation of the tessellated patch, and the right side of Figure 8.15 shows the patch’s control points and the control cage, which is formed by creating a grid of lines between the control points.
因為圖8.14展示出來的渲染出來的patch比較光滑,所以很難看出細分效果。在圖8.15中,我們在左邊展示了線框模式下的結果畫面,右邊的圖中我們展示了那些生成畫面用的那些控制點,以及控制點之間的連線。
我們核心關注和討論的領域是引擎的底層技術以及商業化方面的信息,可能并不適合初級入門的同學。官方相關信息主要包括了對市面上的引擎的各種視角的分析以及宏觀方面的技術討論,相關領域感興趣的同學可以關注東漢書院以及圖形之心公眾號。
只言片語,無法描繪出整套圖形學領域的方方面面,只有成體系的知識結構,才能夠充分理解和掌握一門科學,這是藝術。我們已經為你準備好各式各樣的內容了,東漢書院,等你來玩。
總結
以上是生活随笔為你收集整理的用-force –opengl 指令_OpenGL-使用Tessellation技术绘制Cubic Bézier Patches的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python 调用mysql_Pytho
- 下一篇: 小米路由器设置中的外网设置怎么设置小米路