irpas技术客

图形学摘要_lyyiangang

未知 6334

vertex shader vs fragment shader

vertex shader 又叫gouraud shader fragment shader 又叫Phong shader

vertex shader的任务是转换顶点坐标和准备frag shader需要的数据, frag shader的任务是决定当前像素是否需 要绘制以及如果绘制,要以雯么颜色绘制。 OpenGL中的渲染过程:

flat shading - gouraud shading - phong shading(从渲染粒度和流程上分) #mermaid-svg-2xZbSX3spe20r1Z7 .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-2xZbSX3spe20r1Z7 .label text{fill:#333}#mermaid-svg-2xZbSX3spe20r1Z7 .node rect,#mermaid-svg-2xZbSX3spe20r1Z7 .node circle,#mermaid-svg-2xZbSX3spe20r1Z7 .node ellipse,#mermaid-svg-2xZbSX3spe20r1Z7 .node polygon,#mermaid-svg-2xZbSX3spe20r1Z7 .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-2xZbSX3spe20r1Z7 .node .label{text-align:center;fill:#333}#mermaid-svg-2xZbSX3spe20r1Z7 .node.clickable{cursor:pointer}#mermaid-svg-2xZbSX3spe20r1Z7 .arrowheadPath{fill:#333}#mermaid-svg-2xZbSX3spe20r1Z7 .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-2xZbSX3spe20r1Z7 .flowchart-link{stroke:#333;fill:none}#mermaid-svg-2xZbSX3spe20r1Z7 .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-2xZbSX3spe20r1Z7 .edgeLabel rect{opacity:0.9}#mermaid-svg-2xZbSX3spe20r1Z7 .edgeLabel span{color:#333}#mermaid-svg-2xZbSX3spe20r1Z7 .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-2xZbSX3spe20r1Z7 .cluster text{fill:#333}#mermaid-svg-2xZbSX3spe20r1Z7 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-2xZbSX3spe20r1Z7 .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-2xZbSX3spe20r1Z7 text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-2xZbSX3spe20r1Z7 .actor-line{stroke:grey}#mermaid-svg-2xZbSX3spe20r1Z7 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-2xZbSX3spe20r1Z7 .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-2xZbSX3spe20r1Z7 #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-2xZbSX3spe20r1Z7 .sequenceNumber{fill:#fff}#mermaid-svg-2xZbSX3spe20r1Z7 #sequencenumber{fill:#333}#mermaid-svg-2xZbSX3spe20r1Z7 #crosshead path{fill:#333;stroke:#333}#mermaid-svg-2xZbSX3spe20r1Z7 .messageText{fill:#333;stroke:#333}#mermaid-svg-2xZbSX3spe20r1Z7 .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-2xZbSX3spe20r1Z7 .labelText,#mermaid-svg-2xZbSX3spe20r1Z7 .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-2xZbSX3spe20r1Z7 .loopText,#mermaid-svg-2xZbSX3spe20r1Z7 .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-2xZbSX3spe20r1Z7 .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-2xZbSX3spe20r1Z7 .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-2xZbSX3spe20r1Z7 .noteText,#mermaid-svg-2xZbSX3spe20r1Z7 .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-2xZbSX3spe20r1Z7 .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-2xZbSX3spe20r1Z7 .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-2xZbSX3spe20r1Z7 .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-2xZbSX3spe20r1Z7 .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-2xZbSX3spe20r1Z7 .section{stroke:none;opacity:0.2}#mermaid-svg-2xZbSX3spe20r1Z7 .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-2xZbSX3spe20r1Z7 .section2{fill:#fff400}#mermaid-svg-2xZbSX3spe20r1Z7 .section1,#mermaid-svg-2xZbSX3spe20r1Z7 .section3{fill:#fff;opacity:0.2}#mermaid-svg-2xZbSX3spe20r1Z7 .sectionTitle0{fill:#333}#mermaid-svg-2xZbSX3spe20r1Z7 .sectionTitle1{fill:#333}#mermaid-svg-2xZbSX3spe20r1Z7 .sectionTitle2{fill:#333}#mermaid-svg-2xZbSX3spe20r1Z7 .sectionTitle3{fill:#333}#mermaid-svg-2xZbSX3spe20r1Z7 .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-2xZbSX3spe20r1Z7 .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-2xZbSX3spe20r1Z7 .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-2xZbSX3spe20r1Z7 .grid path{stroke-width:0}#mermaid-svg-2xZbSX3spe20r1Z7 .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-2xZbSX3spe20r1Z7 .task{stroke-width:2}#mermaid-svg-2xZbSX3spe20r1Z7 .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-2xZbSX3spe20r1Z7 .taskText:not([font-size]){font-size:11px}#mermaid-svg-2xZbSX3spe20r1Z7 .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-2xZbSX3spe20r1Z7 .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-2xZbSX3spe20r1Z7 .task.clickable{cursor:pointer}#mermaid-svg-2xZbSX3spe20r1Z7 .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-2xZbSX3spe20r1Z7 .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-2xZbSX3spe20r1Z7 .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-2xZbSX3spe20r1Z7 .taskText0,#mermaid-svg-2xZbSX3spe20r1Z7 .taskText1,#mermaid-svg-2xZbSX3spe20r1Z7 .taskText2,#mermaid-svg-2xZbSX3spe20r1Z7 .taskText3{fill:#fff}#mermaid-svg-2xZbSX3spe20r1Z7 .task0,#mermaid-svg-2xZbSX3spe20r1Z7 .task1,#mermaid-svg-2xZbSX3spe20r1Z7 .task2,#mermaid-svg-2xZbSX3spe20r1Z7 .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-2xZbSX3spe20r1Z7 .taskTextOutside0,#mermaid-svg-2xZbSX3spe20r1Z7 .taskTextOutside2{fill:#000}#mermaid-svg-2xZbSX3spe20r1Z7 .taskTextOutside1,#mermaid-svg-2xZbSX3spe20r1Z7 .taskTextOutside3{fill:#000}#mermaid-svg-2xZbSX3spe20r1Z7 .active0,#mermaid-svg-2xZbSX3spe20r1Z7 .active1,#mermaid-svg-2xZbSX3spe20r1Z7 .active2,#mermaid-svg-2xZbSX3spe20r1Z7 .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-2xZbSX3spe20r1Z7 .activeText0,#mermaid-svg-2xZbSX3spe20r1Z7 .activeText1,#mermaid-svg-2xZbSX3spe20r1Z7 .activeText2,#mermaid-svg-2xZbSX3spe20r1Z7 .activeText3{fill:#000 !important}#mermaid-svg-2xZbSX3spe20r1Z7 .done0,#mermaid-svg-2xZbSX3spe20r1Z7 .done1,#mermaid-svg-2xZbSX3spe20r1Z7 .done2,#mermaid-svg-2xZbSX3spe20r1Z7 .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-2xZbSX3spe20r1Z7 .doneText0,#mermaid-svg-2xZbSX3spe20r1Z7 .doneText1,#mermaid-svg-2xZbSX3spe20r1Z7 .doneText2,#mermaid-svg-2xZbSX3spe20r1Z7 .doneText3{fill:#000 !important}#mermaid-svg-2xZbSX3spe20r1Z7 .crit0,#mermaid-svg-2xZbSX3spe20r1Z7 .crit1,#mermaid-svg-2xZbSX3spe20r1Z7 .crit2,#mermaid-svg-2xZbSX3spe20r1Z7 .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-2xZbSX3spe20r1Z7 .activeCrit0,#mermaid-svg-2xZbSX3spe20r1Z7 .activeCrit1,#mermaid-svg-2xZbSX3spe20r1Z7 .activeCrit2,#mermaid-svg-2xZbSX3spe20r1Z7 .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-2xZbSX3spe20r1Z7 .doneCrit0,#mermaid-svg-2xZbSX3spe20r1Z7 .doneCrit1,#mermaid-svg-2xZbSX3spe20r1Z7 .doneCrit2,#mermaid-svg-2xZbSX3spe20r1Z7 .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-2xZbSX3spe20r1Z7 .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-2xZbSX3spe20r1Z7 .milestoneText{font-style:italic}#mermaid-svg-2xZbSX3spe20r1Z7 .doneCritText0,#mermaid-svg-2xZbSX3spe20r1Z7 .doneCritText1,#mermaid-svg-2xZbSX3spe20r1Z7 .doneCritText2,#mermaid-svg-2xZbSX3spe20r1Z7 .doneCritText3{fill:#000 !important}#mermaid-svg-2xZbSX3spe20r1Z7 .activeCritText0,#mermaid-svg-2xZbSX3spe20r1Z7 .activeCritText1,#mermaid-svg-2xZbSX3spe20r1Z7 .activeCritText2,#mermaid-svg-2xZbSX3spe20r1Z7 .activeCritText3{fill:#000 !important}#mermaid-svg-2xZbSX3spe20r1Z7 .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-2xZbSX3spe20r1Z7 g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-2xZbSX3spe20r1Z7 g.classGroup text .title{font-weight:bolder}#mermaid-svg-2xZbSX3spe20r1Z7 g.clickable{cursor:pointer}#mermaid-svg-2xZbSX3spe20r1Z7 g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-2xZbSX3spe20r1Z7 g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-2xZbSX3spe20r1Z7 .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-2xZbSX3spe20r1Z7 .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-2xZbSX3spe20r1Z7 .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-2xZbSX3spe20r1Z7 .dashed-line{stroke-dasharray:3}#mermaid-svg-2xZbSX3spe20r1Z7 #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-2xZbSX3spe20r1Z7 #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-2xZbSX3spe20r1Z7 #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-2xZbSX3spe20r1Z7 #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-2xZbSX3spe20r1Z7 #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-2xZbSX3spe20r1Z7 #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-2xZbSX3spe20r1Z7 #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-2xZbSX3spe20r1Z7 #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-2xZbSX3spe20r1Z7 .commit-id,#mermaid-svg-2xZbSX3spe20r1Z7 .commit-msg,#mermaid-svg-2xZbSX3spe20r1Z7 .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-2xZbSX3spe20r1Z7 .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-2xZbSX3spe20r1Z7 .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-2xZbSX3spe20r1Z7 g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-2xZbSX3spe20r1Z7 g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-2xZbSX3spe20r1Z7 g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-2xZbSX3spe20r1Z7 g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-2xZbSX3spe20r1Z7 g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-2xZbSX3spe20r1Z7 g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-2xZbSX3spe20r1Z7 .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-2xZbSX3spe20r1Z7 .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-2xZbSX3spe20r1Z7 .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-2xZbSX3spe20r1Z7 .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-2xZbSX3spe20r1Z7 .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-2xZbSX3spe20r1Z7 .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-2xZbSX3spe20r1Z7 .edgeLabel text{fill:#333}#mermaid-svg-2xZbSX3spe20r1Z7 .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-2xZbSX3spe20r1Z7 .node circle.state-start{fill:black;stroke:black}#mermaid-svg-2xZbSX3spe20r1Z7 .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-2xZbSX3spe20r1Z7 #statediagram-barbEnd{fill:#9370db}#mermaid-svg-2xZbSX3spe20r1Z7 .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-2xZbSX3spe20r1Z7 .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-2xZbSX3spe20r1Z7 .statediagram-state .divider{stroke:#9370db}#mermaid-svg-2xZbSX3spe20r1Z7 .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-2xZbSX3spe20r1Z7 .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-2xZbSX3spe20r1Z7 .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-2xZbSX3spe20r1Z7 .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-2xZbSX3spe20r1Z7 .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-2xZbSX3spe20r1Z7 .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-2xZbSX3spe20r1Z7 .note-edge{stroke-dasharray:5}#mermaid-svg-2xZbSX3spe20r1Z7 .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-2xZbSX3spe20r1Z7 .error-icon{fill:#522}#mermaid-svg-2xZbSX3spe20r1Z7 .error-text{fill:#522;stroke:#522}#mermaid-svg-2xZbSX3spe20r1Z7 .edge-thickness-normal{stroke-width:2px}#mermaid-svg-2xZbSX3spe20r1Z7 .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-2xZbSX3spe20r1Z7 .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-2xZbSX3spe20r1Z7 .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-2xZbSX3spe20r1Z7 .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-2xZbSX3spe20r1Z7 .marker{fill:#333}#mermaid-svg-2xZbSX3spe20r1Z7 .marker.cross{stroke:#333} :root { --mermaid-font-family: "trebuchet ms", verdana, arial;} #mermaid-svg-2xZbSX3spe20r1Z7 { color: rgba(0, 0, 0, 0.75); font: ; } shader flat shader vertex shader(Gouraud shader) fragment shader(Phong shader) flat shading 三角形内的每个点渲染时使用同一个法向量, 所以结果很粗糙。

gouraud shading(高洛德shading) vertex shader负责计算每个顶点颜色,颜色会传给frag shader, frag shader再用顶点的颜色插值出每个pixel的颜色。该方法优点是只对vertex做光照计算, 所以计算量较小。 phong shading(冯氏shading) phong shading会在vertex shader中计算顶点的normal和位置信息,送给frag shader后, frag shader通过这些信息来计算像素点颜色。 phong shading 显示效果要比gouraud更细腻, 但是由于每个像素点都要重新计算下光照,所以计算量比gouraud大。 gouraud shading 例子

face3d项目提供了渲染3d模型的功能,可以拿这份代码窥探下3维模型是如何渲染成二维图片的,代码如下,可以看出,直接用每个顶点的颜色插值出三角形内部的颜色,所以他属于gouraud shading,原始代码, 这里贴下简化流程

def render_colors(vertices, triangles, colors, h, w, c = 3): ''' render mesh with colors Args: vertices: [nver, 3] triangles: [ntri, 3] colors: [nver, 3] h: height w: width Returns: image: [h, w, c]. ''' assert vertices.shape[0] == colors.shape[0] # initial image = np.zeros((h, w, c)) depth_buffer = np.zeros([h, w]) - 999999. # 遍历所有三角形 for i in range(triangles.shape[0]): tri = triangles[i, :] # 3 vertex indices # 计算当前三角形的bbox umin = max(int(np.ceil(np.min(vertices[tri, 0]))), 0) umax = min(int(np.floor(np.max(vertices[tri, 0]))), w-1) vmin = max(int(np.ceil(np.min(vertices[tri, 1]))), 0) vmax = min(int(np.floor(np.max(vertices[tri, 1]))), h-1) if umax<umin or vmax<vmin: continue for u in range(umin, umax+1): for v in range(vmin, vmax+1): # 对于bbox内的所有像素点遍历, 如果当前点不在三角形内则进入下一阶段循环 if not isPointInTri([u,v], vertices[tri, :2]): continue # 获取当前像素点在三角形中的重心坐标 w0, w1, w2 = get_point_weight([u, v], vertices[tri, :2]) point_depth = w0*vertices[tri[0], 2] + w1*vertices[tri[1], 2] + w2*vertices[tri[2], 2] # 如果该点没有绘制过则直接绘制,如果已经绘制过,比较下第二次绘制点的深度值是否大于 # 前一个深度值, 如果深度值更大(离相机更近)则继续绘制该点,并更新深度值。 if point_depth > depth_buffer[v, u]: depth_buffer[v, u] = point_depth image[v, u, :] = w0*colors[tri[0], :] + w1*colors[tri[1], :] + w2*colors[tri[2], :] return image

上面说的detph buffer就是z buffer, cs184有个图很详细的描述了z buffer算法流程:

光照类型

物体受到的光照可以分为:Specular highlights(高光),Diffuse reflection(漫反射),Ambient lighting(环境光).

#mermaid-svg-lAOVQBTxwwDNOF5S .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-lAOVQBTxwwDNOF5S .label text{fill:#333}#mermaid-svg-lAOVQBTxwwDNOF5S .node rect,#mermaid-svg-lAOVQBTxwwDNOF5S .node circle,#mermaid-svg-lAOVQBTxwwDNOF5S .node ellipse,#mermaid-svg-lAOVQBTxwwDNOF5S .node polygon,#mermaid-svg-lAOVQBTxwwDNOF5S .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-lAOVQBTxwwDNOF5S .node .label{text-align:center;fill:#333}#mermaid-svg-lAOVQBTxwwDNOF5S .node.clickable{cursor:pointer}#mermaid-svg-lAOVQBTxwwDNOF5S .arrowheadPath{fill:#333}#mermaid-svg-lAOVQBTxwwDNOF5S .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-lAOVQBTxwwDNOF5S .flowchart-link{stroke:#333;fill:none}#mermaid-svg-lAOVQBTxwwDNOF5S .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-lAOVQBTxwwDNOF5S .edgeLabel rect{opacity:0.9}#mermaid-svg-lAOVQBTxwwDNOF5S .edgeLabel span{color:#333}#mermaid-svg-lAOVQBTxwwDNOF5S .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-lAOVQBTxwwDNOF5S .cluster text{fill:#333}#mermaid-svg-lAOVQBTxwwDNOF5S div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-lAOVQBTxwwDNOF5S .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-lAOVQBTxwwDNOF5S text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-lAOVQBTxwwDNOF5S .actor-line{stroke:grey}#mermaid-svg-lAOVQBTxwwDNOF5S .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-lAOVQBTxwwDNOF5S .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-lAOVQBTxwwDNOF5S #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-lAOVQBTxwwDNOF5S .sequenceNumber{fill:#fff}#mermaid-svg-lAOVQBTxwwDNOF5S #sequencenumber{fill:#333}#mermaid-svg-lAOVQBTxwwDNOF5S #crosshead path{fill:#333;stroke:#333}#mermaid-svg-lAOVQBTxwwDNOF5S .messageText{fill:#333;stroke:#333}#mermaid-svg-lAOVQBTxwwDNOF5S .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-lAOVQBTxwwDNOF5S .labelText,#mermaid-svg-lAOVQBTxwwDNOF5S .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-lAOVQBTxwwDNOF5S .loopText,#mermaid-svg-lAOVQBTxwwDNOF5S .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-lAOVQBTxwwDNOF5S .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-lAOVQBTxwwDNOF5S .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-lAOVQBTxwwDNOF5S .noteText,#mermaid-svg-lAOVQBTxwwDNOF5S .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-lAOVQBTxwwDNOF5S .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-lAOVQBTxwwDNOF5S .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-lAOVQBTxwwDNOF5S .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-lAOVQBTxwwDNOF5S .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-lAOVQBTxwwDNOF5S .section{stroke:none;opacity:0.2}#mermaid-svg-lAOVQBTxwwDNOF5S .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-lAOVQBTxwwDNOF5S .section2{fill:#fff400}#mermaid-svg-lAOVQBTxwwDNOF5S .section1,#mermaid-svg-lAOVQBTxwwDNOF5S .section3{fill:#fff;opacity:0.2}#mermaid-svg-lAOVQBTxwwDNOF5S .sectionTitle0{fill:#333}#mermaid-svg-lAOVQBTxwwDNOF5S .sectionTitle1{fill:#333}#mermaid-svg-lAOVQBTxwwDNOF5S .sectionTitle2{fill:#333}#mermaid-svg-lAOVQBTxwwDNOF5S .sectionTitle3{fill:#333}#mermaid-svg-lAOVQBTxwwDNOF5S .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-lAOVQBTxwwDNOF5S .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-lAOVQBTxwwDNOF5S .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-lAOVQBTxwwDNOF5S .grid path{stroke-width:0}#mermaid-svg-lAOVQBTxwwDNOF5S .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-lAOVQBTxwwDNOF5S .task{stroke-width:2}#mermaid-svg-lAOVQBTxwwDNOF5S .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-lAOVQBTxwwDNOF5S .taskText:not([font-size]){font-size:11px}#mermaid-svg-lAOVQBTxwwDNOF5S .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-lAOVQBTxwwDNOF5S .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-lAOVQBTxwwDNOF5S .task.clickable{cursor:pointer}#mermaid-svg-lAOVQBTxwwDNOF5S .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-lAOVQBTxwwDNOF5S .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-lAOVQBTxwwDNOF5S .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-lAOVQBTxwwDNOF5S .taskText0,#mermaid-svg-lAOVQBTxwwDNOF5S .taskText1,#mermaid-svg-lAOVQBTxwwDNOF5S .taskText2,#mermaid-svg-lAOVQBTxwwDNOF5S .taskText3{fill:#fff}#mermaid-svg-lAOVQBTxwwDNOF5S .task0,#mermaid-svg-lAOVQBTxwwDNOF5S .task1,#mermaid-svg-lAOVQBTxwwDNOF5S .task2,#mermaid-svg-lAOVQBTxwwDNOF5S .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-lAOVQBTxwwDNOF5S .taskTextOutside0,#mermaid-svg-lAOVQBTxwwDNOF5S .taskTextOutside2{fill:#000}#mermaid-svg-lAOVQBTxwwDNOF5S .taskTextOutside1,#mermaid-svg-lAOVQBTxwwDNOF5S .taskTextOutside3{fill:#000}#mermaid-svg-lAOVQBTxwwDNOF5S .active0,#mermaid-svg-lAOVQBTxwwDNOF5S .active1,#mermaid-svg-lAOVQBTxwwDNOF5S .active2,#mermaid-svg-lAOVQBTxwwDNOF5S .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-lAOVQBTxwwDNOF5S .activeText0,#mermaid-svg-lAOVQBTxwwDNOF5S .activeText1,#mermaid-svg-lAOVQBTxwwDNOF5S .activeText2,#mermaid-svg-lAOVQBTxwwDNOF5S .activeText3{fill:#000 !important}#mermaid-svg-lAOVQBTxwwDNOF5S .done0,#mermaid-svg-lAOVQBTxwwDNOF5S .done1,#mermaid-svg-lAOVQBTxwwDNOF5S .done2,#mermaid-svg-lAOVQBTxwwDNOF5S .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-lAOVQBTxwwDNOF5S .doneText0,#mermaid-svg-lAOVQBTxwwDNOF5S .doneText1,#mermaid-svg-lAOVQBTxwwDNOF5S .doneText2,#mermaid-svg-lAOVQBTxwwDNOF5S .doneText3{fill:#000 !important}#mermaid-svg-lAOVQBTxwwDNOF5S .crit0,#mermaid-svg-lAOVQBTxwwDNOF5S .crit1,#mermaid-svg-lAOVQBTxwwDNOF5S .crit2,#mermaid-svg-lAOVQBTxwwDNOF5S .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-lAOVQBTxwwDNOF5S .activeCrit0,#mermaid-svg-lAOVQBTxwwDNOF5S .activeCrit1,#mermaid-svg-lAOVQBTxwwDNOF5S .activeCrit2,#mermaid-svg-lAOVQBTxwwDNOF5S .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-lAOVQBTxwwDNOF5S .doneCrit0,#mermaid-svg-lAOVQBTxwwDNOF5S .doneCrit1,#mermaid-svg-lAOVQBTxwwDNOF5S .doneCrit2,#mermaid-svg-lAOVQBTxwwDNOF5S .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-lAOVQBTxwwDNOF5S .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-lAOVQBTxwwDNOF5S .milestoneText{font-style:italic}#mermaid-svg-lAOVQBTxwwDNOF5S .doneCritText0,#mermaid-svg-lAOVQBTxwwDNOF5S .doneCritText1,#mermaid-svg-lAOVQBTxwwDNOF5S .doneCritText2,#mermaid-svg-lAOVQBTxwwDNOF5S .doneCritText3{fill:#000 !important}#mermaid-svg-lAOVQBTxwwDNOF5S .activeCritText0,#mermaid-svg-lAOVQBTxwwDNOF5S .activeCritText1,#mermaid-svg-lAOVQBTxwwDNOF5S .activeCritText2,#mermaid-svg-lAOVQBTxwwDNOF5S .activeCritText3{fill:#000 !important}#mermaid-svg-lAOVQBTxwwDNOF5S .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-lAOVQBTxwwDNOF5S g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-lAOVQBTxwwDNOF5S g.classGroup text .title{font-weight:bolder}#mermaid-svg-lAOVQBTxwwDNOF5S g.clickable{cursor:pointer}#mermaid-svg-lAOVQBTxwwDNOF5S g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-lAOVQBTxwwDNOF5S g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-lAOVQBTxwwDNOF5S .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-lAOVQBTxwwDNOF5S .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-lAOVQBTxwwDNOF5S .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-lAOVQBTxwwDNOF5S .dashed-line{stroke-dasharray:3}#mermaid-svg-lAOVQBTxwwDNOF5S #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-lAOVQBTxwwDNOF5S #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-lAOVQBTxwwDNOF5S #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-lAOVQBTxwwDNOF5S #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-lAOVQBTxwwDNOF5S #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-lAOVQBTxwwDNOF5S #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-lAOVQBTxwwDNOF5S #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-lAOVQBTxwwDNOF5S #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-lAOVQBTxwwDNOF5S .commit-id,#mermaid-svg-lAOVQBTxwwDNOF5S .commit-msg,#mermaid-svg-lAOVQBTxwwDNOF5S .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-lAOVQBTxwwDNOF5S .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-lAOVQBTxwwDNOF5S .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-lAOVQBTxwwDNOF5S g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-lAOVQBTxwwDNOF5S g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-lAOVQBTxwwDNOF5S g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-lAOVQBTxwwDNOF5S g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-lAOVQBTxwwDNOF5S g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-lAOVQBTxwwDNOF5S g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-lAOVQBTxwwDNOF5S .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-lAOVQBTxwwDNOF5S .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-lAOVQBTxwwDNOF5S .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-lAOVQBTxwwDNOF5S .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-lAOVQBTxwwDNOF5S .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-lAOVQBTxwwDNOF5S .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-lAOVQBTxwwDNOF5S .edgeLabel text{fill:#333}#mermaid-svg-lAOVQBTxwwDNOF5S .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-lAOVQBTxwwDNOF5S .node circle.state-start{fill:black;stroke:black}#mermaid-svg-lAOVQBTxwwDNOF5S .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-lAOVQBTxwwDNOF5S #statediagram-barbEnd{fill:#9370db}#mermaid-svg-lAOVQBTxwwDNOF5S .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-lAOVQBTxwwDNOF5S .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-lAOVQBTxwwDNOF5S .statediagram-state .divider{stroke:#9370db}#mermaid-svg-lAOVQBTxwwDNOF5S .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-lAOVQBTxwwDNOF5S .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-lAOVQBTxwwDNOF5S .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-lAOVQBTxwwDNOF5S .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-lAOVQBTxwwDNOF5S .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-lAOVQBTxwwDNOF5S .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-lAOVQBTxwwDNOF5S .note-edge{stroke-dasharray:5}#mermaid-svg-lAOVQBTxwwDNOF5S .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-lAOVQBTxwwDNOF5S .error-icon{fill:#522}#mermaid-svg-lAOVQBTxwwDNOF5S .error-text{fill:#522;stroke:#522}#mermaid-svg-lAOVQBTxwwDNOF5S .edge-thickness-normal{stroke-width:2px}#mermaid-svg-lAOVQBTxwwDNOF5S .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-lAOVQBTxwwDNOF5S .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-lAOVQBTxwwDNOF5S .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-lAOVQBTxwwDNOF5S .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-lAOVQBTxwwDNOF5S .marker{fill:#333}#mermaid-svg-lAOVQBTxwwDNOF5S .marker.cross{stroke:#333} :root { --mermaid-font-family: "trebuchet ms", verdana, arial;} #mermaid-svg-lAOVQBTxwwDNOF5S { color: rgba(0, 0, 0, 0.75); font: ; } 光照 高光 漫反射 环境光 phong blinn-phong 兰伯特光照模型 半兰伯特光照模型

Ambient shading

diffuse reflection 常见漫反射模型有兰伯特光照模型(Lambert's law)和半兰伯特光照模型 其中兰伯特定律定义:散射到所有方向的光线都是一样的(和视角无关,所以L_d计算和v无关) 兰伯特光照模型中光无法照射的地方是全黑的,没有任何明暗变化,而半兰伯特光照模型则可以cover住这个问题,具体如何实现的这里就不展开了。

Specular Shading 对于高光的计算,常见的有Phong光照模型和Blinn-Phong光照模型。

Phong光照模型 L指向光源方向,N为平面发向量,R为反射光方向 那么可以通过已知的L和N计算出来反射光R: Blinn-Phong光照模型 由于phong模型计算量大(r的计算需要3次点乘),所以Blinn提出的Blinn-Phong模型来解决这个问题。这个方法需要计算出v和l的平均向量:

最后将上面的三个光照结果相加

光照代码示例

对应的,可以参考face3d中计算光照的代码,着色过程使用的gouraud模型,直接算出每个顶点的颜色,漫反射模型为Lambert’s law,高光为blinn-phong.(注意, 代码只实现了漫反射光照)

def add_light(vertices, triangles, colors, light_positions = 0, light_intensities = 0): ''' Gouraud shading. add point lights. In 3d face, usually assume: 1. The surface of face is Lambertian(reflect only the low frequencies of lighting) 2. Lighting can be an arbitrary combination of point sources 3. No specular (unless skin is oil, 23333) Ref: https://cs184.eecs.berkeley.edu/lecture/pipeline Args: vertices: [nver, 3] triangles: [ntri, 3] light_positions: [nlight, 3] light_intensities: [nlight, 3] Returns: lit_colors: [nver, 3] ''' nver = vertices.shape[0] normals = get_normal(vertices, triangles) # [nver, 3] # ambient # La = ka*Ia # diffuse # Ld = kd*(I/r^2)max(0, nxl) # n: surf norm, l:light vec, direction_to_lights = vertices[np.newaxis, :, :] - light_positions[:, np.newaxis, :] # [nlight, nver, 3] direction_to_lights_n = np.sqrt(np.sum(direction_to_lights**2, axis = 2)) # [nlight, nver] direction_to_lights = direction_to_lights/direction_to_lights_n[:, :, np.newaxis] normals_dot_lights = normals[np.newaxis, :, :]*direction_to_lights # [nlight, nver, 3] normals_dot_lights = np.sum(normals_dot_lights, axis = 2) # [nlight, nver] diffuse_output = colors[np.newaxis, :, :]*normals_dot_lights[:, :, np.newaxis]*light_intensities[:, np.newaxis, :] diffuse_output = np.sum(diffuse_output, axis = 0) # [nver, 3] # specular # h = (v + l)/(|v + l|) bisector # Ls = ks*(I/r^2)max(0, nxh)^p # increasing p narrows the reflectionlob lit_colors = diffuse_output # only diffuse part here. lit_colors = np.minimum(np.maximum(lit_colors, 0), 1) return lit_colors 纹理

漫反射纹理 可以使用漫反射纹理替换前面提到漫反射光照计算

镜面光纹理 类似的,镜面光的计算也可以不用计算,直接用镜面光纹理替代

法线纹理 每个fragment都有自己的法线向量,可以实现凹凸不平的效果。

投影

常见的投影分为透视投影和正交投影。

正交投影 当物体离相机的距离远大于物体本身的尺寸时可以使用正交投影来近似。face3d中的缩放正交投影代码(缩放已经做过了): ## --------- 3d-2d project. from camera space to image plane # generally, image plane only keeps x,y channels, here reserve z channel for calculating z-buffer. def orthographic_project(vertices): ''' scaled orthographic projection(just delete z) assumes: variations in depth over the object is small relative to the mean distance from camera to object x -> x*f/z, y -> x*f/z, z -> f. for point i,j. zi~=zj. so just delete z ** often used in face Homo: P = [[1,0,0,0], [0,1,0,0], [0,0,1,0]] Args: vertices: [nver, 3] Returns: projected_vertices: [nver, 3] if isKeepZ=True. [nver, 2] if isKeepZ=False. ''' return vertices.copy() 透视投影 图形学的透视投影作用其实不是投影,而是为投影做预处理,透视投影后的顶点会被映射到NDC空间,xyz都处于[-1, 1]之间,投影后的点依然是3维的。投影矩阵有两种计算方式 通过远&近裁剪平面计算 通过fov计算 关于这两种计算有篇文章描述的很详细。对应代码: def perspective_project(vertices, fovy, aspect_ratio = 1., near = 0.1, far = 1000.): ''' perspective projection. Args: vertices: [nver, 3] fovy: vertical angular field of view. degree. aspect_ratio : width / height of field of view near : depth of near clipping plane far : depth of far clipping plane Returns: projected_vertices: [nver, 3] ''' fovy = np.deg2rad(fovy) top = near*np.tan(fovy) bottom = -top right = top*aspect_ratio left = -right #-- homo P = np.array([[near/right, 0, 0, 0], [0, near/top, 0, 0], [0, 0, -(far+near)/(far-near), -2*far*near/(far-near)], [0, 0, -1, 0]]) vertices_homo = np.hstack((vertices, np.ones((vertices.shape[0], 1)))) # [nver, 4] projected_vertices = vertices_homo.dot(P.T) projected_vertices = projected_vertices/projected_vertices[:,3:] projected_vertices = projected_vertices[:,:3] projected_vertices[:,2] = -projected_vertices[:,2] #-- non homo. only fovy # projected_vertices = vertices.copy() # projected_vertices[:,0] = -(near/right)*vertices[:,0]/vertices[:,2] # projected_vertices[:,1] = -(near/top)*vertices[:,1]/vertices[:,2] return projected_vertices


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #图形学摘要 #记录一些图形学相关的东西