Shading中的插值技术

提要

在Per Vertex shader中处理着色计算的情况计算出的是每个顶点上shading的结果,通常模型都是由三角面来构成,面上的颜色如何处理,就是今天要探讨的。常用的三种方法是Flat Shading, Gouraud Shading, Phong Shading,对于渲染一个小球,结果对比如下,从左到右依次是Flat Shading, Gouraud Shading, Phong Shading。

Flat Shading

这个最简单,整个面片的颜色都是一致的,没有平滑,只有很硬的边缘,面的颜色由面片的第一顶点或者最后一个顶点的颜色决定。OpenGL中相关的语句是

glShadeModel(GL_FLAT);
glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);
glProvokingVertex(GL_LAST_VERTEX_CONVENTION);

在一些为了节省时间的渲染,比如CG动画的草稿等,可能会用到这种Shading技术。

Gouraud Shading

Gouraud Shading 中,首先要计算的是每个顶点的法线,这里的法线求法是通过包含该顶点的面的法线取平局求得,求得法线之后,就可以通过局部光照模型求得该顶点的颜色。

对于一个四边形面片,顶点颜色信息已经求出,当一条扫描线要对这个面片进行着色的时候,首先可以求出的是扫描线和四面体边的交点a,b的颜色。

那么s点的根据重心坐标插值,可以得出

由于是线性插值,所以可以通过上一个像素点的值求得,简化了计算

则整个计算的伪代码如下

  deltaI = (i2 - i1) / (x2 - x1);
   for (xx = x1; xx < x2; xx++) 

    	  {	int offset = row * CScene.screenW + xx;
    	    	if (z < CScene.zBuf[offset])
    	    	{   CScene.zBuf[offset] = z;
    	    	    CScene.frameBuf[offset] = i1;
    	    	}
    	    	z += deltaZ;
                i1 += deltaI;
    	    }

Phong Shading

在Phong Shading中,首先要计算的也是多边形顶点的法线,但是在扫描线对颜色进行填充的时候,不是对颜色插值,而是对法线进行了插值。

已知多边形顶点的法线N1,N2,N4,扫描线与多边形交于a,b点,则a,b的法线为

由于是线性插值,同样可以用增量计算来进行优化

到这一步,只计算出了法线,已经比Gouraud Shading复杂了三倍了。

计算出法线之后,还需要对每一个像素进行光照计算,比如Phong光照模型,Blinn-Phong等,这个性能相比于直接插值可就不是一个数量级了。

还是给出伪代码

for (xx = x1; xx < x2; xx++) 

    	    {	int offset = row * CScene.screenW + xx; 

    	    	if (z < CScene.zBuf[offset])	

    	    	{   CScene.zBuf[offset] = z;   

		    pt = face.findPtInWC(u,v); 

		    float Ival = face.ptIntensity; 

		    CScene.frameBuf[offset] = Ival;< BR>
    	    	} 

		u += deltaU; 

    	    	z += deltaZ; 

		p1.add(deltaPt); 

    	    	n1.add(deltaN); 

             }

Gouraud shading VS Phong shading

相对于Flat shading, Gouraud shading已经有了长足的进步。通常,物体的表面都是光滑的,当用mesh网格来表示,所有的物体都变成了有棱有角的东西,当然网格越密,棱角感就越小,渲染的代价也就越大。Gouraud shading就解决了mesh渲染中的棱角感。相比于Phong shading,由于不用计算每个ppixel的值。它的代价也非常的小,但问题也是存在的,就是specular表现并不尽如人意,特别是当specular非常小的时候,假如真实情况中,specular是处于一个多边形的中间,由于这个specular很小,所以多边形的顶点是没有specular的,那么按照Gouraud shading的插值方法,specular就不存在了。同时,如果真实情况中specular出现在多边形的顶点上,那么按照Gouraud shading的插值方法,包含顶点的多边形上会有线性分布的specular。

解决这两个问题的方法是适当增加顶点的密度。另一个解决方案就是Phong shading了。Phong shading 最大的缺点应该就是性能上的代价了(当然是相对Gouraud shading),因为每个像素都要计算光照,对应于OpenGL 的 Fragment shader.

参考

Gouraud shading wiki - http://en.wikipedia.org/wiki/Gouraud_shading

Phong shading wiki - http://en.wikipedia.org/wiki/Phong_shading

Phong Shading and Gouraud Shading - http://www.nbb.cornell.edu/neurobio/land/OldStudentProjects/cs490-95to96/guo/report.html

时间: 2024-11-08 19:06:04

Shading中的插值技术的相关文章

插值技术之Bezier插值(1) -- Bezier Curve

作者:i_dovelemon 来源:CSDN 日期:2015 / 7 / 11 主题:Interpolate,Bezier Curve 引言 在游戏开发中,诸如动画系统,路径计算等等操作,都会遇到对数值进行插值的问题.从今天开始,将会陆陆续续的向大家介绍什么是插值技术?以及在计算机视频游戏开发中经常使用的插值技术有哪些. 插值技术(Interpolate Technology),是通过数学计算的方式,将两个值之间的部分进行平滑过渡的一种技术方案.这样的技术可以在诸如动画系统等游戏内容中得到使用.

.net中对象序列化技术浅谈

.net中对象序列化技术浅谈 2009-03-11 阅读2756评论2 序列化是将对象状态转换为可保持或传输的格式的过程.与序列化相对的是反序列化,它将流转换为对象.这两个过程结合起来,可以轻松地存储和传输数 据.例如,可以序列化一个对象,然后使用 HTTP 通过 Internet 在客户端和服务器之间传输该对象.反之,反序列化根据流重新构造对象.此外还可以将对象序列化后保存到本地,再次运行的时候可以从本地文件 中“恢复”对象到序列化之前的状态.在.net中有提供了几种序列化的方式:二进制序列化

OS X 和iOS 中的多线程技术(上)

OS X 和iOS 中的多线程技术(上) 本文梳理了OS X 和iOS 系统中提供的多线程技术.并且对这些技术的使用给出了一些实用的建议. 多线程的目的:通过并发执行提高 CPU 的使用效率,进而提供程序运行效率. 1.线程和进程 进程 什么是进程 进程是指在计算机系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行中其专用且受保护的内存空间内 比如同时打开 Xcode .Safari ,系统就会分别启动两个进程 通过活动监视器可以查看Mac系统中所开启的进程 线程 什么是线程 一

Android中直播视频技术探究之---基础核心类ByteBuffer解析

一.前言 前一篇文章我们介绍了Android中直播视频技术的基础大纲知识,这里就开始一一讲解各个知识点,首先主要来看一下视频直播中的一个重要的基础核心类:ByteBuffer,这个类看上去都知道了,是字节缓冲区处理字节的,这个类的功能非常强大,也在各个场景都有用到,比如网络数据底层处理,特别是结合网络通道信息处理的时候,还有就是后面要说到的OpenGL技术也要用到,当然在视频处理中也是很重要的,因为要处理视频流信息,比如在使用MediaCodec进行底层的视频流编码的时候,处理的就是字节,我们如

在 PHP 中结合 Ajax 技术进行图片上传

前面几则日志中讲述了在 PHP 中上传文件,相信大家对 PHP 中如何进行文件上传已经初步掌握.本文来继续探讨在 PHP 中上传文件的技术,不同的是,本次上传将仅限于图片文件的上传,并且将采用 Ajax 技术. 本例将要实现这样的效果:当用户选择图片,开始上传后,后台上传完成时,随即会显示到当前页面.由于,从开始上传到上传完成,再到图片显示均在一个页面上 完成(从表面上看).所以使用 Ajax 技术是必须的.但如何使用这些操作在一个页面上来完成呢?考虑到这样的情况,当文件开始上传后,便开始打开

VC中利用多线程技术实现线程之间的通信

文章来源:[url]http://www.programfan.com/article/showarticle.asp?id=2951[/url] 当前流行的Windows操作系统能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程提供了多任务处理的能力.用进程和线程的观点来研究软件是当今普遍采用的方法,进程和线程的概念的出现,对提高软件的并行性有着重要的意义.现在的大型应用软件无一不是多线程多任务处理,单线程的软件是不可想象的.

终于把区块链与物流的关联搞清楚了 区块链的分类 物流业中区块链技术应用的案例

原文 区块链的分类 区块链可以分为三类:公有链.私有链.联盟链. 1.公有链无官方组织及管理机构,无中心服务器,参与的节点按照系统规则自由接入网络.不受控制,节点间基于共识机制开展工作. 2.私有链建立在某个企业内部,系统的运作规则根据企业要求进行设定,修改甚至是读取权限仅限于少数节点,同时仍保留着区块链的真实性和部分去中心化的特性. 3.联盟链由若干机构联合发起,介于公有链和私有链之间,兼具部分去中心化的特性. 去中心化是区块链的最重要特征 区块链技术提供了一种无需信任单个节点.还能创建共识网

如何在Spring框架中使用RMI技术

在博客<RMI远程方法调用技术>中使用纯Java代码演示了RMI技术的使用,本篇博客将介绍如何在Spring中使用RMI技术. 正如博客<RMI远程方法调用技术>提到的那样--RMI技术的应用通常包括在两个独立的应用程序中:RMI服务端应用程序和RMI客户端应用程序.本博客也从这两方面入手:        RMI服务端应用程序: 1.自定义远程接口 代码如下: package com.ghj.packageofrmi; /** * 定义远程接口. * * @author 高焕杰 *

django 中的延迟加载技术,python中的lazy技术

---恢复内容开始--- 说起lazy_object,首先想到的是django orm中的query_set.fn.Stream这两个类. query_set只在需要数据库中的数据的时候才 产生db hits.Stream对象只有在用到index时才会去一次次next. 例子: f = Stream() fib = f << [0, 1] << iters.map(add, f, iters.drop(1, f)) 1行生成了斐波那契数列. 说明: f是个lazy的对象,f首先放入