精华内容
下载资源
问答
  • [转]效果器及音箱术语中英文对比

    千次阅读 2010-05-31 12:41:00
      <br />instrument cable:乐器线,在电声领域特指高阻抗低电流的信号过线,必须有完善的屏蔽结构及坚固的外壳,大家常用的并不是这种线,由于这种线的要求太高,价格也非常贵。  <br />signal cable:...

    cable:连线或过线,意思就是连接一个输出到另一个输入,但根据信号的不同,cable分的很细的种类。  

    instrument cable:乐器线,在电声领域特指高阻抗低电流的信号过线,必须有完善的屏蔽结构及坚固的外壳,大家常用的并不是这种线,由于这种线的要求太高,价格也非常贵。  

    signal cable:信号线,大家通常用来连接吉他的是这种线,一般这种线是用做低阻信号的传输。  

    speaker cable:音箱线,在吉他领域经常被忽视的一种线材,在功率放大信号和喇叭之间传递信号的就是音箱线。最常用的地方就是音箱头到箱体之间的连接线,此线是不能带屏蔽的(不然烧了放大器)。是传输大电流的线材,质量一定要好!  

    power cable:电源线,这个一般都是玩hifi音响的人才去烧的线材,吉他领域一般不会去更换电源线。  

    effect:直接翻译是效果的意思,而这个词在国内的意义有很大的歧义,广义的来说,只要不是琴和音箱,其他的设备都叫做效果器,而在国外的定义中,是 分的很细的,下面会提到。在标准的乐器界,效果这个词一般是指合唱,飘忽,延时,混响等空间效果,而不包括失真,均衡,压缩等  

    preset:预设,这个词几乎被音色而取代,国内几乎没有人说预设这个词,而都说是音色,所以之前提到的音色这个词在乐器领域是有很多误解的。所谓预 设,就是你把你所有相关的参数都调节好,固定不动,这整个系统参数就称为预设。在合成效果器中,这个词特指把所有参数都调节好后储存在某个位置,方便实时 调用的一个文件。  

    foot switch:脚踏开关,这个有时候被乱翻译成踏板,控制某个参数或者预设的开关或者调用的装置。比如合成效果器中对库的选择,对库中预设的选择都是由脚踏开关来完成的。  

    pedal:踏板,这个才是真正被称为踏板的东西,只要是可以前后踩的都称为踏板,包括音量踏板,蛙音踏板,表情踏板等,在高档合成中几乎所有参数都可以 用踏板来控制,需要设置对所要控制参数的最小值和最大值。用可变电阻控制来工作,但由于可变电阻会劳损,所以过一段时间就需要对踏板的最小最大值进行重新 设置。  

    bank:库。在某些高档效果器中,预设是按照库来储存的,也就是整个效果器可以储存若干个库,一个库可以储存若干个音色。方便的是在转换库的时候演奏的音色还是保持上一个预设,切换到别的库再选择预设的时候,演奏的音色才转换过去。也就是说你在演奏的同时可以任意选择效果器中每一个预设作为下一个切换音色。  

    wah wah:蛙音,对特定频段的电平进行抬高和降低,来制造类似小孩哭的效果,一般结合踏板使用。  

    level:电平,很多人误解成音量,在某个放大电路中电平可以理解成音量,而在效果中,电平就是效果使用程度的表述,也是原始信号和效果信号混合的程度,所以也有用mix来表示的,电平是对处理后信号的增减  

    gain:增益,失真度,在一个非失真电路中,gain表示对输入此级别的原始信号进行增大或衰减的控制。在一个失真电路中,原理和之前说的是一样,但在 表述方面就是失真度,因为失真电路本来就是至少两个级别的放大,而失真的多少就看之前一级的放大率问题,所以gain的多少也就是失真度的多少了!增益是 对原始信号的增减(相对于电平来说) drive:字面理解是驱动的意思,但在过载电路中就类似于失真度。  

    overdrive:过载,一种弱性的失真,温暖,平滑  

    distortion:失真,特指烈性失真,刺耳,失真幅度教大。  

    crunch:一般意义上介于过载与失真之间的音色,特别在英式音色中常出现,  

    tone:音色,在失真电路中特指音色的明暗,软/硬。一般常见于过载。  

    channel:通道,一般是说音箱,但现在很多效果器其实都在模拟音箱,所以在效果器中也能见到这个词,通道特指一组对信号进行处理的组合(里面一般包 括gain eq level )在效果器中通道其实就是对一种失真类型或者清音类型的模拟。一般都是用通道调节好要的音色再进行其他效果的处理。在音箱中就是指一组前级处理,或清音, 或失真。  

    compressor:压缩,在吉他中压缩最常见的用处是对动态的限制,但这只是压缩的一方面用途,在录音领域,压缩还有很多别的用途。很复杂,我也不是 很清楚,但建议大家慎用压缩,如果你不知道压缩是什么,或则说不知道自己要的是什么音色,不如不开压缩。建议在清音中用比较好,压缩的质量对音色是起绝对 意义的,一定要用高档次的,而且不要开的过大。  

    eq:全称equalizer,中文均衡,台湾叫等化器,均衡也是大学问,最少两段,多到几十段的均衡,吉他中一般用三到四段均衡,单块式均衡一般6到 10段,均衡不是越多越好,越多就越难调,均衡没调好只会劣化音质,而且这个概率远远高过调出好音色。均衡是对特定频段进行电平上的提高或者衰减,根据Q 值的大小对周边频率也有影响,所以胡乱的调均衡会造成音色的毛刺感,这也是调效果器最难和最关键的地方,专业级别的效果器会提供尽量多的参数控制,而越便宜的越贴近傻瓜操作,就是为了避免由于均衡的操作不当而劣化音质。另外舞台音响方面使用的多段均衡不是为了调节音色,而是为了避免某频段的反馈,和声音的 驻波,或者是弥补场地的声学环境,千万不要以为均衡越多越好。  

    boost:激励,在用电子管音箱的人中非常关心的是这个激励器的选择,激励器是为了弥补电子管自带失真的不足,修补频段,让音色更饱满而产生,当初是为 了弥补电子管失真度的不足而想在前面增加一个放大级别,但现在基本上是用做对音色的修饰而并非增加失真度,现在电子管失真技术已经可以做到非常大的失真度 了。

    single pedal:指单块式效果器  

    stomp box:同上,某些时候特指过载失真类单块效果器。 传统的合成效果器基本上都是失真源再过诸如均衡,压缩这样的波形处理,再进效果处理。 而现代的效果器就不只是上面说的那么简单的步骤,而是完全模拟一个专业成音的过程,当初出现这种效果器的时候称为音箱模拟器,而现在效果器与音箱模拟器的 界限是越来越模糊。 用个最好的比喻来说,传统的合成效果器对失真的描述往往是bluse,distortion,metal,fuzz这些对音乐或者音色本身的描述 而现代的合成效果器或者音箱模拟器对失真类型的描述就习惯于用历史上经典的设备名称来命名,比如清音不在叫clean而是用black face或者vox或者ac30之类常用于做清音的设备来命名,而一个金属失真不再叫metal,而是用mesa,rectifier,5150等来定 义,所以要玩转这些效果器,你就必须明白这些历史上具有代表意义的设备本身是个什么风格或者倾向。下面是一些合成效果器的名词解释:  

    MODES:模式,这个词出现在合成效果器上代表非常多的意思,可以是输出模式,可以是输入模式,或者单块模式,或者预设模式,关键是看用在什么地方。  

    AMP CHANNEL:这就是对音箱模拟的表述,是对放大器前级通道的模拟,往往包括,GAIN,EQ,LEVEL这些,这也是调出清音还是失真的位置,音色的关键部分。  

    DATA WHEEL:数据轮,现代的高档效果器基本上都有这个数据轮,也就是你在对某一个具体参数进行调节的时候,就是使用数据轮来进行定点设定(增大或减少)  

    AMP SAVE:这不是所有效果器上都有的,意思是音箱储存,也就是对你所设定的一个音箱模拟音色的单独储存,而不是对整个音色,其实也就是对清音类型或者失真类型的设定储存。 STORE:储存,这个就是对预设的储存,也就是对你调节好的一个整体参数的储存。  

    PATTERN:种类,往往是对类型的选择,一般常用在鼓机节奏类型上面。  

    TEMPO:速度,一般指鼓机的速度,或者延时效果的时间。  

    TAP:一般是指实时控制延迟时间的一个装置,也就是用手或者脚对延时时间的把握。根据你触发此开关的时间,而定义节拍。  

    EXPRESSION PEDAL表情踏板,这个踏板可以是哇音可以是音量,通常高档合成里面所有可调节的音色参数都可以用表情踏板来进行脚踏控制,而且一般可以设定几个参数同时改变。  

    BALANCED:平衡输入或者输出,平衡信号是信号传输中最标准最好的一种信号传输方式,采用的是火线,零线,地线单独传输的方式,在乐器领域不常用, 但在PA系统,也就是舞台音响领域是最标准的信号进出标准,由于现在的大型合成效果器基本上都需要和调音台连接进行录音,演出,所以在效果器上也越来越多 的出现平衡输入或者输出。一般都是用XLR来作为接口标准,但有时也用双声道6。5作为接口。  

    UNBALANCED:对比上面的平衡信号,非平衡信号就是吉他,乐器领域常用的信号协议,单声道非平衡只需要两个信号端口,一个火线,一个是零线地线合并。双声道非平衡需要三个信号端口,两声道各占用一个火线端口,零线,地线共四个信号合并,注意:平衡的双声道需要6个端口。  

    STEREO:立体声  

    MONO:单声道  

    1/4:也就是我们常用的6.5插头或者接口,国际标准是说1/4,也就是0.25英寸。  

    XLR:MIC的接口标准,也是平衡信号的接口标准,国内一般叫卡农。 

    BYPASS:旁通,也就是经过此设备,但此设备不做处理,让信号保持原样出去。  

    true bypass:同理于上面,但此旁通采用的是真实的连接线输出,而不经过任何电路部分,所以最完整的保存输入的信号,高档单块必备的一个特点。  

    hand made:手工制造的意思,但有些厂商混淆视听,把手工组装写成手工制造。  

    hand wired:真正意义上的手工制作,在单块效果器里,此意思为手工焊接,手工过线等真正意义上的人手制作。而意义远不止这些,手工制作意味着,人工筛选元件,人工测试,等一系列人性化的制作过程,拿到手的基本上都是经过人耳测试的艺术品,而不是工业产品,所以也意味着天价!此单词在音箱中同理。 音箱方面:  

    preamp:前级,广义的来说,进后级之前的都可称为前级,包括拾音器也可以是前级的一部分。狭义的来说,放大器上对吉他输入的微弱信号处理成可经电路 处理放大部分---进后级之前的部分称为前级。 前级分:电子管(tube),模拟(solid state),数码(digital)三种根据不同的技术分类。

     

    power amp:后级,或功率放大。把前级信号放大到足够推动喇叭的放大级别称为后级。 后级也和上面前级一样分类,但电子管后级分CLASS A和CLASS A/B,根据喜好可以有多种不同的电子管搭配,这个太专业的物理问题也是等SLAYEST来解释。  

    CABINET:箱体,装有喇叭的箱子称为箱体  

    SPEAKER OR LOUD SPEAKER:扬声器或者喇叭,将电信号转化成声波的装置。  

    COMBO;一体箱,前级,后级,喇叭在一个装置里的设备  

    FULL STACK:特指两个412箱体搭配一个HEAD的成套设备  

    HALF STACK:一个412箱体的设备。  

    HEAD:前级后级合并机。  

    AMPLIFIER:放大器,同上,或者是以上的统称。  

    RMS:额定功率,指放大器在长时间工作状态下的功率  

    peak value:峰值功率,放大器允许的瞬间放大功率。  

    FX LOOP:效果回路,前后级之间的通道,可允许将设备接在前级之后,后级之前,在运用前级失真的情况下,需要接周边效果的时使用,也可作为直接输入后级而使用。  

    IMPEDANCE:阻抗,也就是电阻,在电子管放大器上,所接箱体的阻抗的大小绝对不能低于放大器标定的阻抗,所以电子管放大器不能不接箱体而开机,有烧毁的危险。  

    VALVE:电子管,英国说法

     

    TUBE:同上,美国说法。  

    BIAS:栅极电压调整,电子管工作原理之一,请何教授解释。  

    SCOOP:特指对中音的衰减型均衡,也称V形均衡。  

    BRIGHT:明亮,一般出现在清音通道,为一个按钮,指增加此通道的明亮度  

    PRESENCE:临场度,一般可以理解成比高音还高的均衡调节,是一种对声音远近的诠释。  

    STANDBY:待命,在电子管放大器上,一般先开电源开关,等电子管预热后才打开STANDBY开关,电子管在进入工作电压之前,如果外部输入过强信号容易导致损毁,所以STANDBY是个保护措施,关音箱时先关STANDBY,再关电源。

     

    转自 http://www.9songs.com.cn/article-128.html

    展开全文
  • 开关电源及PWM端反激式充电

    千次阅读 多人点赞 2019-01-14 22:55:37
    PWM端反激式充电 主要应用在电瓶车充电(电动自行车上) 本设计方案及报告 来自——淮海工学院——电气工程及其自动化——G电气161,朱奎春和余某整理设计及编撰。本文章中后半部份采用截图方式。 ** 以下为...

    PWM单端反激式充电器

    主要应用在电瓶车充电器(电动自行车上)

    本设计方案及报告

    来自——淮海工学院——电气工程及其自动化——G电气161,朱奎春和余某整理设计及编撰。本文章中后半部份采用截图方式。


    以下为详细内容:

    引言

    开关电源按控制方式分为两种基本形式:一种是脉冲宽度调制(PWM),其特点是固定的开关频率,通过改变脉冲宽度来调节占空比;另一种是频率调节(PFM),其特征是固定宽度,利用改变开关频率的方法来调节占空比。二者的电路不同,但都属于时间比率控制(TGC)方式,其作用效果一样,均可达到稳定的目的。目前开关电源大多数采用PWM方式。
    随着电子技术的发展,出现了多种PWM技术,其中包括:相电压控制PWM、脉宽PWM法、随机PWM、SPWM法、线电压控制PWM等,而在镍氢电池智能充电器中采用的脉宽PWM法,它是把每一脉冲宽度均相等的脉冲列作为PWM波形,通过改变脉冲列的周期可以调频,改变脉冲的宽度或占空比可以调压,采用适当控制方法即可使电压与频率协调变化。可以通过调整PWM的周期、PWM的占空比而达到控制充电电流的目的。
    电动车充电器是专门为电动自行车的电瓶配置的一个充电设备!充电器的分类: 用有、无工频(50赫兹)变压器区分,可分为两大类。货运三轮充电器一般使用带工频变压器的充电机,体积大、重量大、费电,但是可靠,便宜;电动自行车和电摩则使用所谓开关电源式充电器,省电,效率高,但是易坏。

    1 设计内容

    本次课程设计为PWM脉冲宽 度调制充电器,用单端反激变换器。课程设计主要步骤有方案选择,方案设计,充电器分析,主电路分析,相关计算。在市面上,现在有许多的充电设计方案,如:正负式、二段式、三段式和全智能脉冲充电器等,其中三段智能充电器用户较多。我们本次方案为三段式的。

    1.1 参数指标

    目前市面上充电器输出电压及规格的主要的分为以下几种:
    1.1.1 36V10-12Ah:
    恒流1.8A±0.1A,最高限压:44.4V,转灯电流:300mA±20mA,浮充电压:41.4-41.7V。
    1.1.2 48V10-12Ah:
    恒流1.8A±0.1A,最高限压:59.2V,转灯电流:300mA±20mA,浮充电压:55.2-55.6V。
    1.1.3 48V14-16Ah:
    恒流2.0A±0.1A,最高限压:59.2V,转灯电流:350mA±20mA,浮充电压:55.2-55.6V。
    1.1.4 48V17Ah:
    恒流2.7A±0.2A,最高限压:59.2V,转灯电流:500mA±20mA,浮充电压:55.2-55.6V。
    1.1.5 48V20Ah:
    恒流3.0A±0.2A,最高限压:59.2V,转灯电流:600mA±30mA,浮充电压:55.2-55.6V。
    1.1.6 48V28Ah:
    恒流4.5A±0.3A,最高限压:59.2V,转灯电流:800mA±50mA,浮充电压:55.2-55.6V。
    由于我们设计的事物与相关的资料整理,这里我们选择48V28Ah的充电器参数,作为我们本次课程设计的参数指标。

    1.2 技术要求

    对于这次充电器我们要能够对电瓶车的进行三段式,三段式充电器的充电模式是把充电过程分为恒流、恒压、浮充三个充电阶段。并且具有电池检测部分和电网电压波动的保护电路,可以进行过流保护,和输出端短路保护。
    电动自行车是集蓄电池技术,电力电子技术,电动机技术,和精密传动技术于一体的新型特种自行车,因其无污染,低噪音,低能耗,占道少,方便快捷等特点而成为国际上流行和大力推广的绿色私人交通工具。

    2 方案选择

    电瓶车充电器总体框图
    图2  电瓶车充电器总体框图

    2.1 方案设计

    2.1.1 整流滤波电路
    整流滤波电路,有半波整流,桥式整流,变压器中心抽头式整流。还分有的器件的类型不控型、半控型、全控型。滤波有电容滤波,电感滤波,还有Π型滤波。
    为了可以的到较好的整流我们采用不控型桥式电容滤波整流。由于电瓶车充电器充电功率一般回有200W左右。所以二极管我们就不用堆栈式的,采用直插式的,能够更好的扇热。
    2.1.2 开关管的选择
    开关管的的类型主要分半控型、全控型。如晶闸管,GTO, GTR, IGBT, MOSFET等。而IGBT是绝缘栅双极场效应管,为电压控制电流,栅控器件,其工作频率比普通的双极器件高,电流处理能力比MOSFET要强,一般用于中高频中高压领域。功率MOSFET由于是单极型器件,电流处理能力相对较弱,但由于其在开关过程中,没有载流子存储的建立与抽取,其频率特性好,用于高频低压领域。
    本次电瓶车充电器是高频变压的,在对管子选择,我们选择频率性好的MOSFET开关管。价格也较为合适。
    图2-1-2  MOSFET管图及内部结构

    2.1.3 高频变压电路
    常用的开关电源式充电器又分半桥式和单激式两大类,单激类又分为正激式和反激式两类。半桥式成本高,性能好,常用于带负脉冲的充电器;单激式成本低,市场占有率高。但也有少数采用PFM方式。PWM方式电路的工作原理:
    图1-2-3  PWM方式电路的工作原理
    若用T表示开关的脉冲周期,t_(on )表示其导通时间,n表示高频变压器的变比,在脉冲周期一定的前提下,功率变换器的最后输出电压U_(o ) 和输入电压U_(i )的关系可用式(2-1)表示:
    U_O=1/n t_on/T U_S=1/n DU_S (2-1)
    式(2-1)表明,开电源的输入电压或输出电压发生变化时,如电网电压升高或负载变化使输出电压升高或降低时,只要适当控制占空比,可以使输出电压Uo保持不变。控制电路的作用就是实现这个功能,脉宽调制器是这类开关电源的核心,它能产生频率固定而脉冲宽度可调的驱动信号,以控制开关器件的通断状态,从而调节输出电压的高低,达到稳压的目的。锯齿波发生器用于提供恒定的时钟频率信号。利用误差放大器和PWM比较器形成闭环调压系统。如果由于某种原因使Uo升高,脉宽调制器就改变驱动信号的脉冲宽度,亦即改变开关的占空比D,使斩波后的平均住电压下降,反之亦然。
    图2-1-3 变换器与单端正激
    buck变换器与单端正激。图2-1-3中(a)图为buck电路。但是我们充电器的输入电压整流后电压约为300V,对蓄电池和人都有潜在的危险,因此需要对buck变换器进行改变,改为图2-1-3中(b),加入隔离变压器,进行电的隔离,只有磁的联系。图2-1-3中(b)为单端正激变换器。由我们学习过的电力电子技术课本得到单端正激:
    U_O=N_2/N_1 t_on/T U_S=N_2/N_1 DU_S (5-1)
    而单端反激DC/DC变换器图2-1-3(c)如下
    图2-1-3(c) 单端反激DC/DC变换器

    在图2-1-3(c)中,变压器T1起隔离和传递储存能量的作用,即在开关管Q开通时Np储存能量,开关管Q关断时Np向Ns释放能量。在输出端要加由电感器L和电容C。组成一个低通滤波器,变压器初级有Cr、Rr和〖VD〗_r组成的RCD漏感尖峰吸收电路。输出回路需有一个整流二极管VD1。若变压器使用有气隙的磁芯,其铜损较大,变压器的温度相对较高,并且其输出的纹波电压比较大。但其优点是电路结构简单,适用于200W以下的电源,且多路输出交调特性相对较好。
    本次课程方案我们选择为单端反激变换器。首先选择变压器可以进行隔离,把高压侧和低压侧进行变压器隔离。防止因为外界等因素影响,造成爆炸等危害。变压器既具有储能,变压和隔离的功能。其次因为反激式的优点是电路简单,体积也相对来说比较小。主要的是反激式的电源输出电压受占空比的调节幅度,相对于正激式开关电源来说要高很多。反激式开关电源多用于多路输出的场合。
    2.1.4 控制电路
    控制电路是对控制这电路的运行状态的部分。主要是产生脉冲控制开关管的通断,三端式充电恒流、稳压和涓流充电。也能对充电电量的显示,及电源的各种保护,如电网电压的波动,负载短路,负载不匹配(不是对应充电器的蓄电池组)等检测。
    采用集成元件,体积小,电路结构简单,便于设计。控制电路对功率要求不大。产生PWM脉冲调制相关的的集成器件有UC3842,UC3843等。
    为了设计简单我们采用UC3843集成块,来控制MOSFET管的通断。对检测蓄电池组集成块有LM339为4个电压比较器。价格也较为合适。
    图 2-1-4 (a)UC3843管脚图
    图2-1-4(b)LM339管脚图

    3 充电器相关参数设计

    3.1 整流电路的计算、元件参数选择:

    图3-1 整流电路
    而滤波电容的大小选取如下:
    对于整流滤波电路,桥式全波整流滤波带负载的输出电压公式:
    U_L=1.2×U_2=1.2×220=264V
    每个二极管承受的最大反向电压:
    U_VTM=√2 U=√2×220≈311V
    为了考虑1.5~2的余量:
    U_VTM=(1.52)×311=466622V
    为得到平滑的负载电压:
    τ=RE1=4T/2=2T=2/50=0.04s
    由此得到滤波电容:
    E1=0.04/1320=30μF
    若考虑电网电压波动,则电容承受的最高电压为:
    V_cm=264×(1+0.1)=290.4V
    根据上面的计算结果,滤波电容应选用标称为68uF 400V的电解电容。经过工频交流电滤波电路滤波后的工频电压通过整流二极管D1~D4全桥整流,再经过滤波电容E1滤波。通过查找二极管的参数可以了解到IN5399的最高反向峰值电压为1000V,平均整流电流为5A,最大峰值浪涌电压一般为1.5A,最大反向漏电流为5A,通过比较发现,符合作为充电器的高速整流用。

    3.2 RCD箝位电路作用,参数计算与选择

    图3-2 RCD箝位电路
    该电路用于限制MOSFET关断时,高频变压器漏感的能量引起的尖峰电位和次级线圈反射电压的叠加,叠加的电压产生在MOS管由饱和转向关断的过程中,漏感中的能量通过VD向C6充电,C6上的电压可能冲到反电动势与漏感电压的叠加值。
    C6作用:将该部分的能量吸收掉,其容量大小:
    单端反激电路漏感Le一般在40uH到100uH之间,这里取60uH计算。
    C6=((Le×Isc×2))/((Vr+△Vpp))×2-Vr×2=22nF
    R6=0.63×((Vr+△Vpp))/((△Vpp×f×C))=100kΩ
    VD的选择:耐压值要超过叠加值的10%。电流要大于输入电流的平均值的10%。因此,选择800V,3A的二极管。选择为IN5399二极管。

    3.3 UC3842各管脚电位、元件参数的计算、选择

    图3-3 UC3842各管脚电位
    1脚:1脚是误差放大器的输出端,误差放大输出约为3.4V。
    2脚:反馈电压输入端,此脚电压与误差放大器同相端的2.5V基准电压进行比较,产生误差电压,从而控制脉冲宽度。误差放大器反相输入端约为2.4V。
    因为电路原因,UC3842的2脚和1脚之间通常会有补偿网络,通过电阻和电容来补偿。
    两者大小不会太大,所以C1=10nF,R3=10kΩ。
    3脚:电流检测输入端,当检测电压超过1V时,缩小脉冲宽度,使电源处于间歇工作状态,该脚产生大概0.1V的电压。
    因为干扰问题,所以UC3842的电流取样端3脚为防止干扰,在后面接RC滤波器。
    由于3脚干扰信号为高频,若选用电容较大,那在使用中,会因它电解液的频繁极化而产生较大热量,而较高的温度将使电容内部的电解液气化,电容内压力升高,最终导致电容的鼓包和爆裂。所以这里我们选用100pF的电解电容作为滤波。
    4脚:定时端,内部振荡器的工作频率由外接阻容时间常数决定:
    f=1.72/((R_4×C_3))
    为了使频率在300kHz,所以电阻R4选择如下:
    R_4=1.72/(f×C_3 )=1.72/(300×〖10〗3×4.7×〖10〗(-9) )≈1.2KΩ
    6脚:6脚为推挽输出端,内部为图腾柱式,上升、下降时间仅为50ns,驱动能力为正负1A,根据电路可知,该电流为正,假设此时电流正好为1A,驱动输出电压为2V,根据N沟道结型场效应的特性:Vgs大于一定的值就会导通,适用于源极接地。因为6脚电位本身就不高,那么Rg的阻值要远大于R8,才能分去更多的电压,才能满足MOS管的导通要求。所以R8、R9的取值分别为15Ω、10kΩ。
    7脚:国产的电源PWM控制电路最常用的集成电路型号就是UC3842,经查阅它的7脚电压在10V到17V之间波动,因为整流滤波电路供给的电压达到近300V左右,又因为让芯片UC3842启动的电流在0.5mA到1mA之间,那么在电阻R5上的电流必须大于它既可,而它的电流又不能太大,则可推断出R5的阻值必定很大,若取1.5mA的电流供给芯片启动,则:
    R5=300V/1.5mA=200kΩ
    8脚:基准电压输出,可以输出的精确的+5V电压,电流可达0.05A
    C2是个滤除8脚与4脚之间产生的不必要信号,这里取100nF。

    3.4 MOSFET管的选择

    图3-4 MOSFET管
    最大占空比D_max因为不能超过50%,因此这里取40%用于计算,后面同样。
    耐压选择:
    V_dss=V_dcmax=600V
    耐电流选择:
    I_d=I_out 1.2(PoVdmin)1-D_max=1.5A
    所以这里选择SSS5N80的MOSFET管,额定值分别为:800V 2.7A 42W

    3.5 变压器的选择、计算

    图3-5 高频变压器
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    7 参考文献

    1. 周志敏、周纪海,《高频开关电源设计与应用实例》,人民邮电出版社,电气工程应用技术从书,2008年
    2. 周渊深、宋永英、吴迪,《电力电子技术》,普通高等教育电气信息类规划教材,2011年
    3. 刘遂俊,《精修电动车充电器与控制器》,机械工业出版社,全行业优秀畅销品种,2008年
    4. 吴祥兴,《深入浅出电源设计》,卓越工程师培养计划从书,2014年
    5. 张天星、张慧玲,《电动自行车电气原理与维修》,电子科技大学出版社,电子教图书编委会系列从书,2006年
    6. 吴文琳,《电动自行车结构与使用维修》,机械工业出版社,2005年
    展开全文
  • 简介这是一篇没有什么实际作用的文章,因为没有任何shader效果实现,整篇文章到最后,我只实现了一个旋转的立方体(o(╯□╰)o),和Unity渲染的万紫千红的3D世界显得有很大落差,仿佛一切都回到了最初的起点。...

    简介

    这是可能一篇没有什么实际作用的文章,因为没有任何shader效果实现,整篇文章到最后,我只实现了一个旋转的立方体(o(╯□╰)o,好弱),和游戏引擎渲染的万紫千红的3D世界显得有很大落差,仿佛一切都回到了最初的起点(不知道有没有人能猜出来左侧的是哪部游戏大作的截图(*^▽^*))。


    不过实时渲染繁华的背后,还是这看似简单的光栅化。今天,本人打算学习一下基本的光栅化渲染的过程,看一下怎样把一个模型从一些顶点数据,变成最终显示在屏幕上的图像,也就是所谓的渲染流水线。

    所谓SoftRenderer(软渲染),就是用纯代码逻辑模拟OpenGL或者D3D渲染流水线,当然,只是实现了冰山一角,软渲染没有什么实际运用意义,但是对学习渲染原理来说应该是一个比较有效的手段了。之前开了个SoftRenderer的小坑,只是实现了基本的3D变换,三角形图元绘制,仿射纹理映射,最近本想写一篇深度相关的blog的,奈何写了一半发现好多内容需要推导计算,于是乎索性先把软渲染的坑补完,正好这几天把透视校正纹理映射加上了,顺便修了几个bug,基本可以运行起来了(然而我只画了个正方体,帧率还惨不忍睹)。一些高级的特性,比如法线贴图,复杂光照,双线性采样,RT之类的就等之后再慢慢填坑啦(恩,这很有可能是个弃坑-_-)。

    简单介绍一下,项目使用的是C++,类似D3D的3D模式,左手坐标系,NDC中Z是(0,1)区间,向量为行向量,左乘矩阵,没有第三方库,只用到了Windows GDI相关,工程VS2015。基本实现了模型->世界->齐次裁剪空间->裁剪->透视除法->视口映射->ZBuffer深度测试->透视校正纹理映射等功能。实现过程中参考了知乎大佬们的各种回答。本人才疏学浅,尤其是渲染这里,很可能只是“看起来是对的“,再加上哥们600多的近视,所以如果有错误,还望各位高手批评指正。

    渲染流水线

    《Real Time Renderering》中把渲染流水线的功能简要描述如下:给定一个虚拟相机,一些三维物体,灯光,着色方程,贴图等资源,最终生成一张二维图片的过程。所谓流水线Pipline,也就是把原本线性执行的工作,改为并行执行,这样可以极大地提高效率。流水线的瓶颈也就是流水线中最弱的(耗时最长的)。渲染流水线在《RTR》中定义为三个基本阶段,而每一个阶段里面,又分为一些具体的操作步骤,下面分别看一下。

    Application(应用程序阶段):字面意思即可,就是相对于渲染来说,其他的内容基本都可以定义在这个阶段。比如游戏逻辑,物理等等。个人理解为在调用DrawCall之前的阶段,该阶段主要在CPU上进行。

    Geometry(几何阶段):主要是顶点着色器(MVP变换),裁剪,屏幕映射。处理上一阶段传递进来的图元和位置等信息,计算变换位置,最终决定物体在屏幕上的哪个位置,过程中还需进行裁剪,计算一些需要传递给下一阶段的数据。下图是《RTR3》中定义的Gemmetry阶段:


    Rasterizer(光栅化阶段):光栅化阶段是将上一阶段变换投影映射后屏幕空间的顶点(包括顶点包含的各种数据),转化为屏幕上像素的一个过程。在该阶段主要进行的是三角形数据的设置,数据插值,像素着色(包括纹理采样),Alpha测试,深度测试,模板测试,混合。


    为了更好地显示,一般会采用双缓冲技术,即在backbuffer渲染,完成后swap到前台。

    上面的流水线,可能并不是很全面,新版本的有可能有Geometry Shader,Early-Z,Tiled Based等等,而且这个东西每个厂商可能都不太一样,但是上面的应该算是比较经典的一个流水线,并且都是必不可少的阶段(曾经以为裁剪可以不用,偷一点懒,大不了性能差点,后来发现自己真是太天真)。

    下面本人就来大致实现基本的渲染流水线,本文的顺序是绘制直线,三角形,MVP矩阵变换,裁剪,视口映射,深度测试,透视校正纹理采样,是以复杂度作为顺序,并非真正的渲染顺序。

    绘制直线

    首先来研究一下怎么绘制直线,软渲染中每一个阶段其实都有多种方法进行实现,只不过有些是比较公认的通用方案。我这里只是找了一个适合我的方案。

    我们显示在屏幕上的图像,其实就是一幅二维图片,而图片其实是离散的,换句话说,就是一个二维数组,屏幕的坐标就是数组的索引。所以,实际上我们在光栅化阶段绘制的时候,直接使用int型数据即可。俗话说得好,两点确定一条直线,那么,这一个步骤的输入就是两个二维坐标,输出就是一条直线。

    实现画线有几种算法,DDA(最易理解,直接算斜率,有除法,不利于硬件实现,慢),Bresenham算法(没有除法和浮点数,快),吴小林算法(带抗锯齿,比Bresenham慢)。这里,我采用了Bresenham算法进行绘制:

    //斜率k = dy / dx
    //以斜率小于1为例,x轴方向每单位都应该绘制一个像素,x累加即可,而y需要判断。
    //误差项errorValue = errorValue + k,一旦k > 1,errorValue = errorValue - 1,保证0 < errorValue < 1
    //errorValue > 0.5时,距离y + 1点较近,因而y++,否则y不变。
    int dx = x1 - x0;
    int dy = y1 - y0;
    float errorValue = 0;
    for (int x = x0, y = y0; x <= x1; x++)
    {
    	DrawPixel(x, y);
    	errorValue += (float)dy / dx;
    	if (errorValue > 0.5)
    	{
    		errorValue = errorValue - 1;
    		y++;
    	}
    }

    上面算法的主要思想是,按照直线的一个方向,以斜率小于1为例的话,在x轴方向每次步进一个像素,y判断离哪个像素近。通过y方向增加一个累计误差值,当误差值超过1了,说明y方向应该上移一个像素,否则仍然是距离当前y值近。不过上面的算法还是没有避免掉除法的问题,我们可以通过修改一下判断的条件,去掉除法和浮点数,并完善各种情况:

    void ApcDevice::DrawLine(int x0, int y0, int x1, int y1)
    {
    	int dx = x1 - x0;
    	int dy = y1 - y0;
    
    	int stepx = 1;
    	int stepy = 1;
    	
    	if (dx < 0)
    	{
    		stepx = -1;
    		dx = -dx;
    	}
    
    	if (dy < 0)
    	{
    		stepy = -1;
    		dy = -dy;
    	}
    
    	int dy2 = dy << 1;
    	int dx2 = dx << 1;
    
    	int x = x0;
    	int y = y0;
    	int errorValue;
    
    	//改为整数计算,去掉除法
    	if (dy < dx)
    	{
    		errorValue = dy2 - dx;
    		for (int i = 0; i <= dx; i++)
    		{
    			DrawPixel(x, y);
    			x += stepx;
    			errorValue += dy2;
    			if (errorValue >= 0)
    			{
    				errorValue -= dx2;
    				y += stepy;
    			}
    		}
    	}
    	else
    	{
    		errorValue = dx2 - dy;
    		for (int i = 0; i <= dy; i++)
    		{
    			DrawPixel(x, y);
    			y += stepy;
    			errorValue += dx2;
    			if (errorValue >= 0)
    			{
    				errorValue -= dy2;
    				x += stepx;
    			}
    		}
    	}
    }

    那么,我们随机在屏幕上画两条线的效果如下,分辨率是600*450,仔细看锯齿还是挺严重的,也让我深刻地意识到了抗锯齿的重要性o(╯□╰)o:


    绘制三角形

    迈出了最难的第一步,接下来就会好很多了。点,线,面,三个点确定一个三角形,所以我们再加一个参数,绘制一个三角形看一下。但是此处并非直接给三个点,连在一起,而是要把三角形内部填充上颜色。最简单的填充就是扫描线填充,换句话说我们按照屏幕的y轴方向,从上向下,每一行进行绘制,直到把三角形全部填充上为止。首先要把三角形分一下类:


    我们已知的是y的方向,那么就需要带入三角形边的直线方程求得x的坐标,然后在两个点之间画线。如果三角形是平顶的或者是平底的,那么我们只需要考虑两条边即可,但是如果是一般的三角形,我们就需要做一下拆分,把三角形划分成一个平顶三角形和一个平底三角形,以上图为例,三角形GHI,以H的y值带入GI直线方程求得J的x坐标,生成GHJ和HJI两个三角形,这两个三角形就可以按照平顶和平底的方式进行光栅化了。

    以平底三角形ABC为例,假设A(x0,y0),B(x1,y1),C(x2,y2),AB直线上随机一点(x,y),那么直线方程如下:

    (y - y1) / (x - x1) = (y0 - y1) / (x0 - x1),我们已知y(从y0到y1循环),则x值为: x = (y - y0) * (x0 - x1) /  (y0 - y1) + x1。AC边类似得到x值,那么循环中我们就可以根据y值得到每条扫描线左右的x值。平底和平顶三角形的绘制代码如下:

    void ApcDevice::DrawBottomFlatTrangle(int x0, int y0, int x1, int y1, int x2, int y2)
    {
    	for (int y = y0; y <= y1; y++)
    	{
    		int xl = (y - y1) * (x0 - x1) / (y0 - y1) + x1;
    		int xr = (y - y2) * (x0 - x2) / (y0 - y2) + x2;
    		DrawLine(xl, y, xr, y);
    	}
    }
    
    void ApcDevice::DrawTopFlatTrangle(int x0, int y0, int x1, int y1, int x2, int y2)
    {
    	for (int y = y0; y <= y2; y++)
    	{
    		int xl = (y - y0) * (x2 - x0) / (y2 - y0) + x0;
    		int xr = (y - y1) * (x2 - x1) / (y2 - y1) + x1;
    		DrawLine(xl, y, xr, y);
    	}
    }

    知道了平顶和平底,我们只要根据拐点计算出拐点y轴对应另一边的x值,生成新的三角形即可。但是此处我们为了代码简单一些,先对传入的三个顶点进行一下排序:、

    void ApcDevice::DrawTrangle(int x0, int y0, int x1, int y1, int x2, int y2)
    {
    	//按照y进行排序,使y0 < y1 < y2
    	if (y1 < y0)
    	{
    		std::swap(x0, x1);
    		std::swap(y0, y1);
    	}
    	if (y2 < y0)
    	{
    		std::swap(x0, x2);
    		std::swap(y0, y2);
    	}
    	if (y2 < y1)
    	{
    		std::swap(x1, x2);
    		std::swap(y1, y2);
    	}
    
    	if (y0 == y1)	//平顶三角形
    	{
    		DrawTopFlatTrangle(x0, y0, x1, y1, x2, y2);
    	}
    	else if (y1 == y2) //平底三角形
    	{
    		DrawBottomFlatTrangle(x0, y0, x1, y1, x2, y2);
    	}
    	else			//拆分为一个平顶三角形和一个平底三角形
    	{
    		//中心点为直线(x0, y0),(x2, y2)上取y1的点
    		int x3 = (y1 - y0) * (x2 - x0) / (y2 - y0) + x0;
    		int y3 = y1;
    
    		//进行x排序,此处约定x2较小
    		if (x1 > x3)
    		{
    			std::swap(x1, x3);
    			std::swap(y1, y3);
    		}
    		DrawBottomFlatTrangle(x0, y0, x1, y1, x3, y3);
    		DrawTopFlatTrangle(x1, y1, x3, y3, x2, y2);
    	}
    }

    通过上面的步骤,我们就可以在屏幕上绘制一个填充好的三角形啦,如下图:


    ObjectToWorld矩阵构建

    下面就是3D相关的操作了,这也是软渲染中最有意思的部分。首先就是MVP变换,具体来说就是将模型空间坐标通过ObjectToWorld矩阵(M)变换到世界空间,然后通过WorldToView矩阵(V)变换到相机空间,最后通过透视投影矩阵(P)变换到裁剪空间。上述的几个变换都是由矩阵完成的。关于矩阵,简单点来说就是一个二维数组,只是为了更加方便地表达变换的过程,并且这些计算通过矩阵更加容易用硬件进行实现。下面主要用到的是矩阵的乘法,向量与矩阵的乘法,矩阵的转置等特性。

    如果把矩阵的行解释为坐标系的基向量,那么乘以该矩阵就相当于做了一次坐标变换,vM = w,称之为M将v变换到w。用基向量[1,0,0]与任意矩阵M相乘,得到[m11,m12,m13],得出的结论是矩阵的每一行都可以解释为转化后的基向量。根据该结论,就可以通过一个期望的变换,反向构造出一个矩阵来代表这个变换。首先来看一下MVP的M,也就是模型空间转世界空间的变换,这个变换也是分为三个子变换,分别是缩放,旋转,平移。下面分别推导一下几个变换的矩阵。

    缩放矩阵

    缩放是最简单的变换,假设顶点为(x, y, z),缩放系数为(sx, sy, sz),那么缩放希望的就是(sx *x, sy * y, sz * z),我们用一个矩阵来表示的话就是:

                                                               

    代码如下:

    Matrix ApcDevice::GenScaleMatrix(const Vector3& v)
    {
    	Matrix m;
    	m.Identity();
    	m.value[0][0] = v.x;
    	m.value[1][1] = v.y;
    	m.value[2][2] = v.z;
    	return m;
    }

    旋转矩阵

    接下来是旋转矩阵,看起来有点麻烦,而且x,y,z三个方向需要单独实现,其实又是三个矩阵相乘,这篇文章推导的比较明了,借用一张图:


    到这个时候,我才意识到,哇塞,原来三角函数展开的实际应用竟然这么重要。。。我们要表示一个旋转,比如绕Z轴旋转,那么这个时候,Z轴的坐标是不会变化的,所以只考虑X,Y轴坐标即可,比如上图,A为原始坐标(x,y),角度为β,旋转角度α变换到B点(x’,y'),半径为r。此时,左右手坐标系的差别就有了,我使用的是左手坐标系,所以用左手拇指指向Z轴正方向(指向屏幕内),另外四指环绕的方向就是旋转的正方向了。如果用右手坐标系,那么就得换成右手了。

    那么x’= r * cos(α + β) = cos(α) * cos(β) * r - sin(α) * sin(β) * r = cos(α) * x - sin(α) * y

    同理y’= r * sin(α + β) = sin(α) * cos(β) * r + cos(α) * sin(β) * r = sin(α) * x + cos(α) * y

    根据上面的两个等式,我们就可以构建出一个矩阵,Z方向不变,置为1即可,矩阵如下:

                                                             

    绕X轴旋转的矩阵:

                                                             

    绕Y轴旋转的矩阵:

                                                             

    最终,这样,每个轴上我们给定一个角度即可得到旋转的矩阵,最终矩阵为三者相乘,绕三个轴旋转值按一个Vector传递进来:

    Matrix ApcDevice::GenRotationMatrix(const Vector3& rotAngle)
    {
    	Matrix rotX = GenRotationXMatrix(rotAngle.x);
    	Matrix rotY = GenRotationYMatrix(rotAngle.y);
    	Matrix rotZ = GenRotationZMatrix(rotAngle.z);
    	return rotX * rotY * rotZ;
    }
    
    Matrix ApcDevice::GenRotationXMatrix(float angle)
    {
    	Matrix m;
    	m.Identity();
    	float cosValue = cos(angle);
    	float sinValue = sin(angle);
    	m.value[1][1] = cosValue;
    	m.value[1][2] = sinValue;
    	m.value[2][1] = -sinValue;
    	m.value[2][2] = cosValue;
    	return m;
    }
    
    Matrix ApcDevice::GenRotationYMatrix(float angle)
    {
    	Matrix m;
    	m.Identity();
    	float cosValue = cos(angle);
    	float sinValue = sin(angle);
    	m.value[0][0] = cosValue;
    	m.value[0][2] = -sinValue;
    	m.value[2][0] = sinValue;
    	m.value[2][2] = cosValue;
    	return m;
    }
    
    Matrix ApcDevice::GenRotationZMatrix(float angle)
    {
    	Matrix m;
    	m.Identity();
    	float cosValue = cos(angle);
    	float sinValue = sin(angle);
    	m.value[0][0] = cosValue;
    	m.value[0][1] = sinValue;
    	m.value[1][0] = -sinValue;
    	m.value[1][1] = cosValue;
    	return m;
    }

    上面,我们只考虑物体绕自身轴旋转,如果需要绕任意一点旋转的话,我们就可以先进行平移,平移到该点,然后再旋转,旋转后再平移回去。即v = vTRT^-1

    平移矩阵

    原本而言,我们用3x3的矩阵即可表示上面两种变换,然而平移不行,所以就需要引入一个4x4的矩阵来表达平移变换,比如一个顶点(x,y,z)我们希望它平移(tx,ty,tz)距离,那么实际上就是(x + tx,y + ty,z + tz)。使用矩阵来表示的话就是:

                                                                         

    而如果用4x4矩阵,Vector3显然也不够用了,为了能达到上述的变换,我们就需要给Vector增加一个w维度,w = 1时,Vector表示点,与上述矩阵相乘后得到变换的结果,而w = 0时,Vector表示向量,上述变换的结果仍然是Vector自身,平移变换对方向变换不生效。

    平移矩阵的代码如下:

    Matrix ApcDevice::GenTranslateMatrix(const Vector3& v)
    {
    	Matrix m;
    	m.Identity();
    	m.value[3][0] = v.x;
    	m.value[3][1] = v.y;
    	m.value[3][2] = v.z;
    	return m;
    }

    ObjectToWorld矩阵整合

    经过上面的步骤,我们得到了缩放矩阵,旋转矩阵,平移矩阵,最终将三者使用矩阵乘法相乘即可得到完整的ObjectToWorld矩阵,由于我们采用了行向量表示坐标,所以相当于左乘,即我们用vSRT的顺序进行变换。

    我们可以根据矩阵连乘结合律把几个变换通过矩阵相乘的方法,先计算出一个结果矩阵再用该矩阵去变换顶点,这有一个很大的好处,就是我们可以逐对象计算一次变换整体的变换矩阵,然后这个对象的所有的顶点都应用这个变换。这样就把变换的时间从n次MVP计算+n次矩阵与顶点相乘变成了1次矩阵MVP计算+n次矩阵与顶点相乘,而且可以避免浮点计算误差(尝试了一下逐图元计算变换矩阵,最后正方形边界对不上,改为统一计算后效果正常)。我们不需要一些特殊的效果(固定管线),所以我们直接把这个SRT矩阵与后续的VP矩阵相乘,结果再来进行坐标的变换。

    WorldToCamera矩阵构建 

    上一阶段,我们把顶点从模型空间转换到了世界空间,但是有一个很重要的问题,相机才是我们观察世界的窗口,后续的投影,裁剪,深度等如果都在世界空间做的话就太复杂了,如果我们把这些操作的坐标原点改为相机,就会大大降低后续操作的复杂性。所以,下一步就是如何将一个世界空间的对象转化到相机空间。要定义一个相机,首先要有相机位置,还要有相机看的方向,一种方法是给出相机的旋转角度,也就是Raw,Pitch,Roll这三个值,如下图:


    另一种方案就是给一个相机注视点以及一个控制相机Y轴方向的向量,也就是UVN相机模型,UVN比较容易定义相机的朝向,类似LookAt的功能,所以这里我们采用这种方式定义我们的相机位置和朝向。给定了相机位置和注视点位置,我们就能求得视方向向量N,然后我们根据给定的上向量V(只是输入临时用的,不是最终的V,输入的V在VN平面没有权重,因为N已经确定了视方向,只有UV平面上可能有权重,所以需要重新计算一个仅影响Roll的角),通过向量叉乘得到一个Cross(N,V)得到右向量U,最终我们再用Cross(N,U)得到真正的V,三者都需要Normalize。这样,我们就构建出了相机所在的空间基准坐标系。

    我们要的是WorldToCamera的变换,不过,对一个点做一个变换,相当于对其所在坐标系做逆变换,所以我们只要求出整体变换的逆矩阵即可。比如上面的变换称之为WTC,上面的变换包括一个旋转R和平移T,那么我们要求的WTC^-1 (表示逆)=(RT)^-1 = (T^-1)( R^-1)。我们拆开来看:

    先是旋转矩阵的逆,其实上面的计算,我们构建的UVN就是R矩阵了(把相机转换到世界空间,但是在第四行没有分量,换句话说就是3X3的矩阵,没有位移,也没有缩放,那么就只有旋转),下面一步就是求R的逆。矩阵正常求逆的运算是很费的,所以一般来说要避免直接求逆,因为3X3的旋转矩阵其实是一个正交矩阵(各行各列都是单位向量,并且两两正交,可以把上一节的旋转矩阵每个看一遍,抽出左上角3X3部分)。正交矩阵的重要性质就是MM^T (转置)= E(单位矩阵),进一步推导就是M ^ T = M ^ -1,所以上面的旋转矩阵的逆实际上就是它的转置。转置的话,我们只需要沿着对角线把数据互换一下,计算量比起求逆要小得多。 

    接下来是平移矩阵的逆,这个其实不需要去推导,比如向量按照(tx,ty,tz)进行了平移变换,那么对它的逆变换其实就是取反(-tx,-ty,-tz)。

    最终两个矩阵以及相乘结果如下,其中T = (tx,ty,tz),UVN同理:


    我们直接结果构建最终的矩阵,避免多一次矩阵运算,代码如下:

    Matrix ApcDevice::GenCameraMatrix(const Vector3& eyePos, const Vector3& lookPos, const Vector3& upAxis)
    {
    	Vector3 lookDir = lookPos - eyePos;
    	lookDir.Normalize();
    
    	Vector3 rightDir = Vector3::Cross(upAxis, lookDir);
    	rightDir.Normalize();
    
    	Vector3 upDir = Vector3::Cross(lookDir, rightDir);
    	upDir.Normalize();
    
    	//构建一个坐标系,将vector转化到该坐标系,相当于对坐标系进行逆变换
    	//C = RT,C^-1 = (RT)^-1 = (T^-1) * (R^-1),Translate矩阵逆矩阵直接对x,y,z取反即可;R矩阵为正交矩阵,故T^-1 = Transpose(T)
    	//最终Camera矩阵为(T^-1) * Transpose(T),此处可以直接给出矩阵乘法后的结果,减少运行时计算
    	float transX = -Vector3::Dot(rightDir, eyePos);
    	float transY = -Vector3::Dot(upDir, eyePos);
    	float transZ = -Vector3::Dot(lookDir, eyePos);
    	Matrix m;
    	m.value[0][0] = rightDir.x;  m.value[0][1] = upDir.x;  m.value[0][2] = lookDir.x;  m.value[0][3] = 0;
    	m.value[1][0] = rightDir.y;	 m.value[1][1] = upDir.y;  m.value[1][2] = lookDir.y;  m.value[1][3] = 0;
    	m.value[2][0] = rightDir.z;  m.value[2][1] = upDir.z;  m.value[2][2] = lookDir.z;  m.value[2][3] = 0;
    	m.value[3][0] = transX;		 m.value[3][1] = transY;   m.value[3][2] = transZ;	   m.value[3][3] = 1;
    	return m;
    }

    透视投影矩阵构建

    接下来的投影阶段是3D向2D转换的一个重要的步骤(并不是这一步就转),同时也是后续CVV裁剪,ZBuffer,透视纹理校正的基础,这里我们暂且不考虑正交投影,直接来看透视投影。上文我们提到,为了更好地变换,用4X4矩阵,进而引入齐次坐标的概念,但是实际上,齐次坐标系真正的作用在于透视投影变换。

    透视投影的主要知识点在于三角形相似以及小孔呈像,透视投影实现的就是一种“近大远小”的效果,其实投影后的大小(x,y坐标)也刚好就和1/Z呈线性关系。首先看下面一张图:


    上图是一个视锥体的截面图(只看x,z方向),P为空间中一点(x,y,z),那么它在近裁剪面处的投影坐标假设为P’(x',y',z’),理论上来说,呈像的面应该在眼睛后方才更符合真正的小孔呈像原理,但是那样会增加复杂度,没必要额外引入一个负号(此处有一个裁剪的注意要点,下文再说),只考虑三角形相似即可。即三角形EAP’相似于三角形EGP,我们可以得到两个等式:

    x’/ x = z’/ z => x’= xz’/ z  

    y’/ y = z’/ z => y’= yz’/ z

    由于投影面就是近裁剪面,那么近裁剪面是我们可以定义的,我们设其为N,远裁剪面为F,那么实际上最终的投影坐标就是:

    (Nx/z,Ny/z,N)。

    投影后的Z坐标,实际上已经失去作用了,只用N表示就可以了,但是这个每个顶点都一样,每个顶点带一个的话简直是暴殄天物,浪费了一个珍贵的维度,所以这个Z值会被存储一个用于后续深度测试,透视校正纹理映射的变换后的Z值。

    这个Z值,还是比较有说道的。在透视投影变换之前,我们的Z实际上是相机空间的Z值,直接把这个Z存下来也无可厚非,但是后续计算会比较麻烦,毕竟没有一个统一的标准。既然我们有了远近裁剪面,有了Z值的上下限,我们就可以把这个Z值映射到[0,1]区间,即当在近裁剪面时,Z值为0,远裁剪面时,Z值为1(暂时不考虑reverse-z的情况)。首先,能想到的最简单的映射方法就是depth = (Z(eye) - N)/ F - N。but,这种方案是不正确的(需要参考下文关于光栅化数据插值的内容,此处先给出结论,我认为这个1/z在光栅化阶段解释更为合适):透视投影变换之后,在屏幕空间进行插值的数据,与Z值不成正比,而是与1/Z成正比。所以,我们需要一个表达式,可以使Z = N时,depth = 0,Z = F时,depth = 1,并且需要有一个z作为分母,可以写成(az + b)/z,带入上述两个条件:

    (N * a  + b) / N = 0   =>  b = -an

    (F * a  +  b) / F = 0   =>   aF + b = F => aF - aN = F

    进而得到: a = F / (F - N) b = NF / (N - F)

    最终其实视锥体被变换为NDC,但是实际上我们一般是先不进行透视除法,那么就称之为CVV(此处不要过度纠结这两个概念,下文再去解释)过程如下图(DX文档附图)所示(下图是DX模式,左手系,NDC中Z区间是0到1,也是本文使用的模式;GL的话NDC中Z是-1到1,而且是右手系,二者最终推导出的透视投影矩阵是有差异的),主要思想就都是映射,把一个区间映射到另一个区间:

    我们已经把Z值,进行了映射,秉承着映射大法好的观点,我们再把X和Y进行一下映射,上面我们已经计算出投影后的坐标值是(Nx/z,Ny/z,N)。假设近裁剪面上下分别为U,B,左右分别为L,R,我们要把原始的区间映射到[-1,1]区间。我们以X轴为例进行推导,最终X投影点映射到NDC的坐标假设为Xndc,那么映射公式如下:

    Xndc - (-1) / (1 - (-1)) = (XN / Z - L) / (R - L)

    计算该公式得到Xndc = 2XN / Z(R - L) - (R + L)/ (R - L)

    同理Yndc  = 2YN / Z(T - B) - (T + B) / (T - B)

    这样,我们就可以得到了XYZ三个方向在NDC空间的坐标。

    下面在来解释一下NDC和CVV,所谓NDC,全称为Normalized Device Coordinates,也就是标准设备空间,为何要引入这样一个空间呢,主要在于我们使用不同的设备,分辨率可能都不一样,实际在写shader的时候,没办法根据分辨率进行调整,而通过这样一个空间,把x,y映射到(-1,1)区间,z映射到(0,1)区间(OpenGL是(-1,1)),在下一步屏幕坐标映射时再根据屏幕分辨率生成像素真正应该在的位置,这样可以省掉很多设备适配的问题,让我们在写shader的时候一般不需要考虑屏幕分辨率的问题(有时候有,主要是全屏后处理时屏幕宽高的比例,我之前在屏幕水波纹效果中实现就遇到了这样的问题)。

    再来看一下CVV,CVV全称为Canonical View Volume,即规则观察体。其实上面的变换最终的坐标应该是NDC的,但是为了更方便地做一些其他的操作,主要是CVV裁剪,引入了一个新的空间,这个空间主要是没有NDC空间的坐标没进行除以w计算,也就是说CVV空间的顶点还是齐次空间下的,除了w之后才会变为NDC空间,两者的差距主要是是否除以了w。个人理解:CVV只是用齐次坐标系表示了的NDC(如果我的理解不正确,还希望您及时指出我的错误)。

    关于CVV裁剪,下文再讲,我们还是回到透视投影矩阵:

    我们既然要CVV空间,也就是齐次裁剪空间下的顶点,所以我们刚好可以把上文得到的投影点坐标的每个元素的除以Z变换成W分量的Z,然后XYZ分量下的除以Z就可以去掉了,也就是说用齐次空间表示一下最终的投影点坐标:

    P’(NX,NY,aZ + b,Z)带入上面的推导结果得到透视投影矩阵:

                                                                 

    上面的矩阵是一个通用的矩阵,但是实际上我们绝大多数情况用的矩阵都是一个特殊情况的矩阵,也就是我们的相机刚好在视锥体中间,上下左右对称,那么R和L对称,T和B对称,两者相加都等于0,而R-L和T-B我们就可以用一个宽度和高度来表示,简化后的矩阵如下:

                                                                     

    下面我们再考虑一下怎样更加优雅地表示这个矩阵(换句话说就是参考一下DX和GL真正的接口)。我们一般来说,给定一个

    FOV角度,N近裁剪面,F远裁剪面,Aspect屏幕宽高比即可,如下图:


    那么BF也就是的高度就是tan(0.5*fov)* N 最终的H = 2 tan(0.5fov)*N,最终的W = Aspect * H。带入上述矩阵:

    2N/H = 2N/2tan(0.5fov)N = 1/tan(0.5fov) = cot(0.5fov)

    2N/W = 1/(Aspect * tan(0.5fov)) = cot(0.5fov)/Aspect

    最终矩阵结果如下,暂且还是以tan表示:

                                                           

    代码如下:

    Matrix ApcDevice::GenProjectionMatrix(float fov, float aspect, float nearPanel, float farPanel)
    {
    	float tanValue = tan(0.5f * fov * 3.1415 / 180);
    
    	Matrix proj;
    	proj.value[0][0] = 1.0f / (tanValue * aspect);
    	proj.value[1][1] = 1.0f / (tanValue);
    	proj.value[2][2] = farPanel / (farPanel - nearPanel);
    	proj.value[3][2] = -nearPanel * farPanel / (farPanel - nearPanel);
    	proj.value[2][3] = 1;
    	return proj;
    }

    这里,我们只是进行了透视投影变换的第一步,将顶点转化到齐次裁剪空间,因为并没有进行透视除法,所以还没有所谓的投影。第二步是透视除法,但是中间一般还会穿插一步,CVV裁剪。

    啊,终于写完了透视投影矩阵的变换,实际上这个矩阵结果只有几个数,然而背后的数学推导还是比较复杂的。有了P矩阵,我们最终用来变换的矩阵就都完成了。

    CVV裁剪

    经过了透视变换,坐标被变换到CVV空间,此时仍然是齐次坐标,我们正常应该是判断在裁剪的立方体内,不过齐次坐标我们也就是直接比较xyz值和w的值即可,DX模式的话,z需要比较0和w。这个是非常重要的,因为我们默认为了方便是把投影平面放到了眼睛前面,但是真的有在投影平面后面的东西,如果不剔除z<0的内容,就会导致这一部分按照不对的透视公式进行计算导致结果错误。而且更重要的一点在于,相机空间z = 0的时候(也就是齐次空间的w = 0)的这种情况,在我们透视除法的时候会有除0的问题。所以要把这个剔除掉。

    比如一个齐次空间的顶点,我们可以按照上述方式判断其是否在CVV内:

    inline bool ApcDevice::SimpleCVVCullCheck(const Vertex& vertex)
    {
    	float w = vertex.pos.w;
    	if (vertex.pos.x < -w || vertex.pos.x > w)
    		return true;
    	if (vertex.pos.y < -w || vertex.pos.y > w)
    		return true;
    	if (vertex.pos.z < 0.0f || vertex.pos.z > w)
    		return true;
    	return false;
    }

    CVV裁剪个人感觉是一个比较有争议的地方,现代的GPU到底如何去做裁剪,我不敢妄加推测,看了知乎上大佬们的讨论,也是分为几个派别。有认为裁剪的,有人为只剔除不裁剪的。不过个人倒比较赞同,重新构建一个三角形对于GPU来说还不如把整个三角形都画了好,毕竟实际运用时,三角形的密度很大,面积很小,都绘制了也要比裁剪可能还省。对于CVV中比较好处理的主要在于我们可以在透视除法前就把完全不可见的三角形直接剔除掉。所以我只实现了最简单的三顶点均不在CVV内剔除的方案(好吧,为偷懒找了个理由o(╯□╰)o)。

    实现了CVV裁剪,其实还是蛮爽的,尤其是本身没有场景管理,视锥体裁剪的话,提交上来的所有内容都要绘制,如果本身不可见的话,那直接就咔掉了。测试的话,直接渲染立方体,帧率25左右,立方体在CVV外不开裁剪,帧率100多些(有视口范围判断),立方体在CVV外开裁剪,帧率999+直接爆表 。

    透视除法与屏幕坐标映射

    经过了透视投影变换,CVV裁剪,现在我们的顶点坐标都在齐次裁剪空间,下一步就是真正地进行透视除法了,经过了这一步才真正算是完成了透视投影变换。其实这个操作比较简单,因为计算在透视投影矩阵的构建中我们都推导过了,乘过Project矩阵的顶点,w坐标就不会是默认的1了。因为我们把Z值存了进去,此时我们将三个分量都除以Z,就得到了透视变换后的NDC坐标了。

    马上就可以和我们之前进行的在屏幕上绘制三角形联系起来了,中间只差了一步,那就是屏幕坐标映射。上文介绍过,NDC的作用就是为了让我们计算时不需要考虑屏幕分辨率相关的问题,因为DX或者GL替我们做了,软渲染的话,我们就需要自己做这一步。

    我们创建窗口的时候,会给一个窗口的宽度和高度(RT类似),既然我们得到了NDC空间的坐标值了,并且知道了屏幕的长和宽(分辨率),那么,是时候进行一波映射了。映射大法好啊!

    NDC是(-1,1)区间(现在暂时只考虑X,Y),我们要把它映射到屏幕的(0,width)和(0,height)区间即可。先看X方向:首先,我们从(-1,1)区间映射到(0,1)区间,也就是(v.x / v.w + 1)* 0.5 * deviceWidth。Y方向,屏幕实际的坐标是左上角为(0,0)点,与我们的NDC是反过来的,所以映射到(0,1)区间后,还需要反向一下,改为(1-screendCoord)* deviceHeight。代码如下,进行了透视除法&屏幕空间映射:

    float reciprocalW = 1.0f / v.w;
    float x = (v.x * reciprocalW + 1.0f) * 0.5f * deviceWidth;
    float y = (1.0f - v.y * reciprocalW) * 0.5f * deviceHeight;

    这里的x,y就是经过了上述所有变换后,最终在屏幕上的坐标点。下面我们整合一下整个3D变换的过程,最终屏幕坐标v' = vFinalMatrix => vMVP => vSRTVP => vSRxRyRzTVP,代码如下:

    Matrix ApcDevice::GenMVPMatrix()
    {
    	Matrix scaleM = GenScaleMatrix(Vector3(1.0f, 1.0f, 1.0f));
    	Matrix rotM = GenRotationMatrix(Vector3(0, 0, 0));
    	Matrix transM = GenTranslateMatrix(Vector3(0, 0, 0));
    	Matrix worldM = scaleM * rotM * transM;
    	Matrix cameraM = GenCameraMatrix(Vector3(0, 0, -5), Vector3(0, 0, 0), Vector3(0, 1, 0));
    	Matrix projM = GenProjectionMatrix(60.0f, (float)deviceWidth / deviceHeight, 0.1f, 30.0f);
    
    	return worldM * cameraM * projM;
    }
    
    void ApcDevice::DrawTrangle3D(const Vector3& v1, const Vector3& v2, const Vector3& v3, const Matrix& mvp)
    {
    	Vector3 vt1 = mvp.MultiplyVector3(v1);
    	Vector3 vt2 = mvp.MultiplyVector3(v2);
    	Vector3 vt3 = mvp.MultiplyVector3(v3);
    
    	Vector3 vs1 = GetScreenCoord(vt1);
    	Vector3 vs2 = GetScreenCoord(vt2);
    	Vector3 vs3 = GetScreenCoord(vt3);
    
    	DrawTrangle(vs1.x, vs1.y, vs2.x, vs2.y, vs3.x, vs3.y);
    }

    我们把MVP的计算整个抽取出来,每个对象计算一次即可,对象所有的三角形运用同一个MVP变换,即每个三角形逐顶点与MVP矩阵相乘,然后进行视口映射即可。这样,我们就得到了一个可以变换的三角形(虽然看起来和上面一样,然而这的确是一个有故事的三角形,因为他不是直接显示在屏幕上的,而是历经了无数次计算,才显示到了屏幕上):


    来一张动图,应用了旋转和平移变换(有故事的三角形自然多了一些能力,比如移动,旋转,缩放,随着相机位置移动的近大远小效应):


    光栅化数据插值与仿射纹理映射

    直到目前为止,我们虽然可以在屏幕上看到三角形了,并且可以运用各种变换,但是我们的三角形没有任何其他数据,仅有一个位置信息,这是十分令人不爽的,尤其是我这个视觉动物,憋了半天终于画出了个三角形,然而还木有颜色,简直是不能忍了!我们要给它加点料!要有更好的表现,我们就要给顶点加一些属性,最常见的,也是最容易的,就是颜色啦。我们给每个顶点增加一个顶点色,存储在顶点中。but,我们这时候应该意识到一个问题,我们的三角形只有三个点,而最终显示在屏幕上的可是无数个像素啊,其中的数据要怎么样得到呢?

    比如我们正常写shader的时候,经常会定义一个v2f之类的结构体,用来从vertex阶段传递到fragment阶段,vertex阶段我们只考虑逐顶点计算的值就可以了,传递v2f,到fragment阶段,自动就可以在输入时取到每个v2f在fragment阶段的值,这个数据实际上是渲染管线帮我们自动处理了。所运用到的知识点其实也是非常简单的,就是插值(Lerp)。

    来看一维的插值代码,也就是我们经常用的Lerp函数:

    float LerpFloat(float v1, float v2, float t){ return v1 + (v2 - v1) * t;}

    其实非常简单,我们给一个(0,1)的插值控制函数,就可以完成从v1,v2之间的插值了,当t=0时,为v1,当t=1时为v2。

    那么,在三角形设置好之后,三个顶点的数据是一定的,接下来要从上到下绘制扫描线,我们每次要绘制扫描线的时候,首先要获得扫描线两侧端点的数据值,扫描线的两侧端点的值在我们求解方程的时候可以得到,也就能求出该点在端点所在的边所处的值,此处是从上到下,那么我们就用y作为插值系数,以即每一点的t = (y - y0)/ (y2 - y0),然后我们就可以用这个系数去在顶点和底点两个点之间插值得到当前线上扫描线起始点和结束点的颜色值。扫描线本身也是同理,已知左右两点的颜色值,每次前进一个像素,都可以求出当前t = (x - x0) / (x1 - x0)作为插值系数。比如我们给上面的三角形增加一个顶点色,通过插值就可以得到如下的效果:


    有了颜色,我们的三角形就好看了不少。需求总是有的,能不能再好看一点呢?既然代码写不出来,那就贴张图上去吧!(我想这应该也是前辈们发明纹理映射的初衷吧)。还是同一个问题,我们只有顶点数据,也就是美术同学展uv得到的坐标值,存在顶点中。像素上全靠插值,那么要想贴上一张图,我们应该有的其实是这一个像素点应该采样的纹理坐标也就是uv值,还是一样的思路,我们补全插值的计算和顶点上的uv数据。然后用windows自带的功能读入一张bmp贴图,然后构建一个二维数组,把这个贴图的每个像素逐步拷入数组就可以了。采样时,我们计算出uv值,然后依然是映射大法好,因为uv是(0,1)区间,我们把这个区间映射到像素数组的大小,然后就可以用这个index去纹理数组中采样该点的颜色了。其实在这一步也可以做一点小文章,比如传过来的uv是非(0,1)区间的,那么边界的颜色怎么给,如果我们直接截断,那么就是clamp,也可以取余数那就是repeat,还可以实现mirror等模式。这里我就直接Clamp了。下面是Texture类中两个主要的函数:

    void Texture::LoadTexture(const char* path)
    {
    	HBITMAP bitmap = (HBITMAP)LoadImage(NULL, path, IMAGE_BITMAP, width, height, LR_LOADFROMFILE);
    	
    	HDC hdc = CreateCompatibleDC(NULL);
    	SelectObject(hdc, bitmap);
    	
    	for (int i = 0; i < width; i++)
    	{
    		for (int j = 0; j < height; j++)
    		{
    			COLORREF color = GetPixel(hdc, i, j);
    			int r = color % 256;
    			int g = (color >> 8) % 256;
    			int b = (color >> 16) % 256;
    			Color c((float)r / 256, (float)g / 256, (float)b / 256, 1);
    			textureData[i][j] = c;
    		}
    	}
    }
    
    Color Texture::Sample(float u, float v)
    {
    	u = Clamp(0, 1.0f, u);
    	v = Clamp(0, 1.0f, v);
    	//暂时直接采用clamp01的方式采样
    	int intu = width * u;
    	int intv = height * v;
    	return textureData[intu][intv];
    }

    搞一个自己的头像试一下纹理映射:


    看起来好多了,是不是大功告成了呢?其实并不是,因为这一节忽略了一个重要的问题,导致我们所有的插值其实都是错误的,上面看起来没有问题,是因为仅仅看起来可能是对的。

    1/Z的问题与透视校正纹理映射

    我们把上面的面片,沿着Y轴旋转45度,再看一下效果:


    哦,伟大的蝎同志肿么变成了小短腿。。。简直玷污了我的偶像(我得赶快改好)。如果我们换一个贴图,那么这个问题将暴露得更加明显:


    这是个什么鬼。。。我贴上去的可是一个方方正正的网格贴图:


    那么,问题应该比较明确了,就出在透视上。来看一张图解释一下上面的现象:


    右侧的三角形是我直接复制过去的,唯一的区别就在于左侧CFE平面平行于近裁剪面,而右侧把CFE整个一条线拉歪,使C接近近裁剪面。二者在最终投影在近裁剪面的位置完全相同,但是实际上在三维空间位置是相差甚远的。

    先祭出两篇大佬的推导:一篇几何证明,一篇代数证明。我数学不好,只能膜拜这些大佬了。主要证明的就是在投影空间的值与1/z成正比。

    我们存在顶点中的数据,顶点颜色,顶点上uv的坐标等内容,其实都是在模型空间下制作的,换句话说,这些值实际上应该在模型空间下进行插值计算,但是投影是一个损失维度的变换,我们单纯地用最终二维屏幕上的位置距离去插值,如果Z全都一致,那没有影响,在投影平面均匀变换的值,对应相机空间(推回模型空间也一样)也是均匀变换的。但是像右图,在投影平面两段相同距离对应相机空间的距离就不同了。

    我们在推导投影矩阵的时候,得到过投影点的坐标(Nx/z,Ny/z,N),换句话说,投影后的X’本身就是与1/Z呈线性关系的,然后我们还知道uv坐标与x呈线性关系,实际上就是uv坐标与1/z呈线性关系,那么通过这样一个方式,我们在三角形进行设置时,强行把uv除以一个z,那么此时uv就变成了uv/z,这个值是与投影后的nx/z呈线性关系的,也就是说我们可以在屏幕空间根据距离进行线性插值得到一点上的确切的uv/z值。不过还有一个问题,我们得到了uv/z,还需要把uv还原,也就是得到uv,我们还需要再求出当前点的1/z值,这个值被我们存在了z坐标上,我们在每个点采样的时候,再把z乘回去,就得到了这一点真正的uv坐标值(最后除以z和w其实效果差不多,两者其实也是线性关系)。

    inline void ApcDevice::PrepareRasterization(Vertex& vertex)
    {
    	//透视除法&视口映射
    	//齐次坐标转化,除以w,然后从-1,1区间转化到0,1区间,+ 1然后/2 再乘以屏幕长宽
    	float reciprocalW = 1.0f / vertex.pos.w;
    	vertex.pos.x = (vertex.pos.x * reciprocalW + 1.0f) * 0.5f * deviceWidth;
    	vertex.pos.y = (1.0f - vertex.pos.y * reciprocalW) * 0.5f * deviceHeight;
    	//将其他数据转化为1/z
    	vertex.pos.z *= reciprocalW;
    	vertex.u *= vertex.pos.z;
    	vertex.v *= vertex.pos.z;
    }

    在采样时,使用了:

    int errorValue = dy2 - dx;
    for (int i = 0; i <= dx; i++)
    {
    	float t = (x - x0) / (x1 - x0);
    	float z = Vertex::LerpFloat(v0.pos.z, v1.pos.z, t);
    	float realz = 1.0f / z;
    	float u = Vertex::LerpFloat(v0.u, v1.u, t);
    	float v = Vertex::LerpFloat(v0.v, v1.v, t);	
    	Color c = tex->Sample(u * realz, v * realz);
    	DrawPixel(x, y, c);
    	x += stepx;
    	errorValue += dy2;
    	if (errorValue >= 0)
    	{
    		errorValue -= dx2;
    		y += stepy;
    	}
    }

    经过透视校正纹理采样后的效果:


    logo的效果也正常啦:


    ZBuffer算法

    人的需求总是无限的,贴上了图,还是感觉不够爽,毕竟不是一个立体的东西,只是个面片,下面我决定搞个模型进来。不过我不打算引入第三方库,导入fbx那不是软渲染干的事儿了,这个东西在opengl玩更好。所以我手撸了个立方体数据,直接写个顶点缓存,每个点加个uv数据。然后坐等我的立方体出现:


    额,好像。。。哪里不太对。。。立方体面之间的遮挡关系错乱了。换句话说,我们没有深度测试,没有办法保证立方体面渲染的顺序,我们需要的是像素精度的深度保证。下面来加一个ZBuffer。

    其实ZBuffer的思想比较简单,就是在逐像素增加一个缓存,每次绘制的时候,把当前深度也存储进这个buffer,下次再绘制该像素的时候,先判断一下当前像素的z值,如果比该值小或相等的话,说明离得更近(仅考虑ZTest LEqual)。这种情况下就可以更新当前像素点的颜色值,并且可以选择更新深度缓存。

    我们先申请一块屏幕大小的float类型内存:

    zBuffer = new float*[deviceHeight];
    for (int i = 0; i < deviceHeight; i++)
    {
    	zBuffer[i] = new float[deviceWidth];
    }

    然后每次渲染之前,除掉ClearColorBuffer外,还要把DepthBuffer也Clear掉:

    void ApcDevice::Clear()
    {
    	BitBlt(screenHDC, 0, 0, deviceWidth, deviceHeight, NULL, NULL, NULL, BLACKNESS);
    	//ClearZ
    	for (int i = 0; i < deviceHeight; i++)
    	{
    		for (int j = 0; j < deviceWidth; j++)
    		{
    			zBuffer[i][j] = 0.0f;
    		}
    	}
    }

    每次绘制时进行深度判断,深度检测失败不进行绘制,深度检测成功此处默认开启ZWrite:

    bool ApcDevice::ZTestAndWrite(int x, int y, float depth)
    {
    	//上面只进行了简单CVV剔除,所以还是有可能有超限制的点,此处增加判断
    	if (x >= 0 && x < deviceWidth && y >= 0 && y < deviceHeight)
    	{
    		if (zBuffer[y][x] <= depth)
    		{
    			zBuffer[y][x] = depth;
    			return true;
    		}
    	}
    	return false;
    }

    有了深度缓存,我们的立方体就完整啦:


    深度缓存,我采用的是1/Z,所以上面的深度默认为0表示无限远。为了更好的效率,我的ZTest实际上放在了计算扫描线时每次插值计算出Z之后立刻就进行深度检测,其实类似于Early-Z,而不是实际上真正渲染时的ZCheck,因为我没有考虑Alpha Test的情况,也不需要考虑分支的问题,直接Cull掉是性能最好的。

    int errorValue = dy2 - dx;
    for (int i = 0; i <= dx; i++)
    {
    	float t = (x - x0) / (x1 - x0);
    	float z = Vertex::LerpFloat(v0.pos.z, v1.pos.z, t);
    	float realz = 1.0f / z;
    	if (ZTestAndWrite(x, y, realz))
    	{
    		float u = Vertex::LerpFloat(v0.u, v1.u, t);
    		float v = Vertex::LerpFloat(v0.v, v1.v, t);
    		//Color c = Color::Lerp(v0.color, v1.color, t);
    		Color c = tex->Sample(u * realz, v * realz);
    		DrawPixel(x, y, c);
    	}
    
    	x += stepx;
    	errorValue += dy2;
    	if (errorValue >= 0)
    	{
    		errorValue -= dx2;
    		y += stepy;
    	}
    }

    关于深度,其实还有很多可以玩的,不过这么好玩的东西,还是另起一篇blog吧。

    最后,再来一张动图:


    总结

    本文主要实现了基本的光栅化渲染器的一些常见的特性,MVP矩阵变换,简单CVV剔除,视口映射,光栅化,透视校正纹理采样等等。目前还有基本的光照,背面剔除,线框渲染,相机控制等几个是我打算加的。有些算法肯定很古老,而且GPU的具体实现我不敢妄加揣测,填软渲染的坑主要是为了学习的目的,加深一下对渲染知识的理解。其实实现的过程还是蛮有意思的(有点找到了几年前写了第一个命令行版本的2048的那种乐趣,当时自己玩了半宿,一边玩一边手舞足蹈,室友以为我疯了呢),很久不写的C++又温习了一下,再一个方面就是需要考虑优化了,让我清晰地意识到逐像素计算是真的很费很费,面片贴脸的时候基本就跑不动啦!!!项目从开始写的时候,只有一个三角形没经过变换,没有采样,FPS上百,逐渐增加特性之后帧率一度掉到了个位数,后来稍微优化了一下,稳定在了20-25帧,还是有很大的优化的空间的。

    代码的话直接开源吧,第一次用Git,如果能您赏个星星什么的就更好啦。本人才疏学浅,如果您发现了什么问题,还望批评指正。


    展开全文
  • 双绞线传输的常见问题解析

    千次阅读 2018-07-21 00:15:02
    双绞线传输在工程实际中的常见问题分析 双绞线传输在工程实际中的常见问题分析(一)   1、 图像有时候会丢失:一般情况下是由于线路中各接触点的接触不良引起的,请检查各端子接线是否拧紧,BNC头要用纯铜...

    双绞线传输器在工程实际中的常见问题分析


    双绞线传输器在工程实际中的常见问题分析(一)
     

    1、  图像有时候会丢失:一般情况下是由于线路中各接触点的接触不良引起的,请检查各端子接线是否拧紧,BNC头要用纯铜的优质品,双绞线的驳接处需要用电烙铁焊接良好后作防水密封处理。


    2、为了充分利用线缆,工程实际中可以将附近的监控点的信号,用视频线连接到同一个位置,然后经过转换器接入双绞线传输,但由于信号的损失会使整体的传输距离缩短。一条网线可以同时传输4路视频信号,为防止线间串扰,剩下空着的双绞线,可参照下一条的方法进行处理。


    3、图像有斜纹状干扰:
    (1)尽量使用更好得直流电源变压器,以降低电源的波纹系数,减少供电问题带来的干扰;
    (2)视频信号尽量不要经过更多的设备如分配器等的处理而是出来后直接接入变换器传输;
    (3)如果同一条网线里的四对双绞线中尚有空着无用的线对,请在前端将其中一条或二条空的双绞线接地线,没有地线的可以接到与摄像机输出端的同轴电缆的屏蔽网层相连的端子上;


    4、调试期间,接收器后面最好是直接接监视器观看效果。如果后面连接的是分割器等图像处理器材时,由于它们内部的自动增益电路的作用,会造成调节电位器的时候在相当一段行程中图像基本无变化的现象,此时可以将电位器调在处于这段基本无变化的行程的中间位置。


    5、如果调不出满意的效果,请与你的供应商联络取得技术支持。设备内部并无用户可以维修的部件,不要打开外壳及撕掉标贴,否则不予免费保修。
     

     

    6、 以为屏蔽线能够增强抗干扰能力,布线时选择屏蔽线。由于工程商长期使用同轴线进行传输,把在使用同轴线作为传输介质的经验不自觉地运用到双绞线传输上来,认为使用屏蔽双绞线在抗干扰上有更佳的表现。当然用屏蔽线确实增强了一些抗干扰能力,但却将高频信号严重受损,传输出来的效果色彩变差,距离远是甚至没有彩色图像,传输质量和传输距离大打折扣。同时屏蔽双绞线价格高,也增加了工程成本,因此布线时特别要注意不要用屏蔽线。而应使用非屏蔽的双绞线UTP。

     


    7、高估产品的防水、抗干扰和防雷能力。实际上,电子产品都怕受潮、怕电磁干扰、更怕雷击。双绞线传输设备,由于双绞线的平衡传输特性,对共模干扰有较强的抑制能力,但也不是万能的,防雷更是其中的一个小小的功能,内置的放电电路,只能对一些电压不高、电流不大的雷电起到释放作用,并且一定要接地才有用!当几万伏的雷电击中时,能把大树劈成板材,小小的双绞线传输器,机壳都可以被融掉,防雷管还能起到什么作用?所以工程布线时,应该绕开多雨水、强干扰和有直接雷击可能的区域,如果有室外露天走线的情形,应该尽量做专用的接地,以加强防雷。同时改善产品安装处的环境,让设备工作在一个清洁、干燥的环境下,更能稳定可靠地工作。


    8、布线与安装的工艺太差,导致效果不佳。我们在市面上购买的非屏蔽双绞线,大都是305米一箱,但是工程中的点左一个右一个,远远近近,因此,小于305米处的短的地方就需要破开网线的包皮,将线挑出来接摄像头,长的地方就需要把两箱甚至更多箱的线接起来,在接线时最好用焊锡焊接来牢靠,包扎好做好防水,同时注意双绞线的颜色配对,才能保证传输线路不出问题。另外,用在前端的转换器,特别是无源转换器,体积细小,很多工程商接好线后将它放进护罩内,对于固定的摄像机,问题还不大,但如果是带云台的,由于双绞线比较细、比较脆,云台旋转时很容易折断双绞线。所以这时应该将信号用柔软的视频线接出来,在固定的地方安装转换器,保持双绞线和转换器固定。双绞线视频传输设备在接线时一般有两种接线方式,一种是直接将一对线中的两根线拨开皮套后分别接到设备的两个接线端子上;一种是采用RJ45水晶头来接。两者方式各有优缺点,用接线柱的方式在接触上较好,可以结点间确保接触良好,但是双绞线的线较细,没有专门的工具不容易处理,如果线材的质量不好,拨开的导线可能十分脆,经不起折腾;使用水晶头来接,看上去十分可靠,但是实际效果不好,因为水晶头的接触片的弹性非常有限,时间长了很容易接触不良。我们建议使用接线端子的方式,虽然麻烦一点看上去不先进,但胜在可靠。注意采购线材时,把好质量关,尽可能选用品牌线材。剥线时如果没有好的工具经验不足,可以用火烧后拉掉外皮的方法确保幼细的线芯不受伤。另外在线缆对接或者接入设备时的接线头附近,最好将整根双绞线做一个固定,以增强线缆的抗拉能力,提高系统的工作可靠性。


    9、选择适应较长距离的型号,造成不必要的浪费,效果还比一定更好。将长距离的传输设备使用在短距离上,或者将短距离的传输设备使用在较长距离上,都是不合理的选择。一些工程商为了让视频效果更好,往往不惜成本将1200米的传输设备运用在500米上,其实这样做大可不必,是一种浪费。中短距离有更为节约的产品,前端的转换器还不需要电源,稳定性更强,更加经济。但将用于短距离的设备用在长距离的监控点,效果也会不佳,这个应该比较容易理解。


    另外,有些厂商推出的价格低廉的发射接收双无源的传输器产品,很多工程商使用之后效果不佳,因此判定双绞线传输不实用。实际上是过于相信销售者的介绍了。不错,理论上双无源的产品是可以传输200多甚至300米,但附加的条件很多厂商没有讲清楚:现场的电磁环境必须很好,布线要避开强电,最好走弱电专用线槽、摄像机的信号幅度必须达标(实际很多都是偏低的)等等,由于这些原因,这类设备的实际应用是很受局限的。


    10、交给传输器的信号源本身质量差,造成传输效果差。使用质量太差的输出信号幅度不足的摄像机,或者布线时从摄像头到双绞线发射器的同轴线缆布得过长造成衰减过大,都会造成进入转换器的信号不足,从而到达接收器的信号幅度低于设备的处理范围引起图像比较差。一般情况下,从摄像头到双绞线发射器的同轴线缆应该在100米以内,越短越好。另外有一种情况是:有的红外摄像头在白天时红外功能没有启动,消耗功率较低,一般的电源变压器供电就能满足要求,但是到了晚上,红外功能启动了,供电的功率不够,此时红外摄像头产生的信号质量就急剧下降,出现大量的雪花,甚至干脆就没有视频信号输出了。这种情况根本就跟传输器设备无关,必须处理好摄像头本身的供电才能解决问题。
     

     

    11.不重视调试,不够耐心细心,未能调至最佳效果。特别是第一次使用双绞线传输设备的用户,看到小小的传输器,觉得安装调试会很简单,没有认真阅读说明书,然而实际调节时发现远不是那么回事,特别是对于发射接收双有源的设备,发射器和接收器都要调节,而发射器所在的位置往往在几百米上千米之外,两边的人员需要不断协调工作,容易让人心烦意乱,很容易就会胡乱调出一点基本的图像出来就交差,回去就报告说设备不好。解决这个问题必须:具体施工人员首先要通读说明书,首次使用者必须在公司进行测试模拟现场的距离和环境,用一箱网线头尾相接的方法,很容易就可以得到300米、600米、900米、1200米等四种距离的双绞线,已经覆盖了大部分的工程监控点。二端的调试人员模拟几次在现场调试时的顺序、方法、双方沟通协调习惯了,才能在现场尽快调出最佳的效果。关键要注意调节的顺序,可以参考上面的调试指南,同时要抱着研究的态度,耐心、全面、细致地做多几次,对设备的工作原理有了基本的认识,累积了经验,后面的实地调试就容易办了。
     
     

    非屏蔽双绞线传输设备工程使用中常见的几个问题(二)
     

    在非屏蔽双绞线使用过程中的常见问题注:以下的“双绞线”都指的是“非屏蔽双绞线”
    1、问:双绞线传输视频能抗干扰的原理是什么?
    答:视频信号输入时,通过发射端在输出的双绞线分别产生极性相反且幅度相等的差分信号,在传输过程中肯定会有一定的干扰信号介入,会产生同极性且幅度相等的信号,在接收端同极性幅度相等的干扰信号将会相互抵消,而极性相反且幅度相等的差分信号将被还原为视频信号,整个传输过程抑制了干扰信号,保证视频信号的高质量传输。


    2、问:图像有时候会丢失
    答:一般情况下是由于线路中各接触点的接触不良引起的,请检查各端子接线是否拧紧,BNC头要用纯铜的优质品,双绞线的驳接处需要用电烙铁焊接良好后作防水密封处理。


    3、问:图像有斜纹状干扰
    答:(1)尽量使用更好得直流电源变压器,以降低电源的波纹系数,减少供电问题带来的干扰;
           (2)视频信号尽量不要经过更多的设备如分配器等的处理而是出来后直接接入变换器传输;
           (3)如果同一条网线里的四对双绞线中尚有空着无用的线对,请在前端将其中一条或二条空的双绞线接地线,没有地线的可以接到与摄像机输出端的同轴电缆的


    4、问:双绞线传输器可以传输有线电视天线信号吗?
    答:不能。双绞线传输器只能传输通常的基带视频信号,而有线电视天线的信号是射频信号,不可以通过双绞线传输。


    5、问:用了双绞线传输器,控制信号怎么办?
    答:该怎办还怎办。传输器只不过是帮你利用双绞线代替了你原来的视频线,来传输视频信号而与,跟系统的控制是没有直接关系的。所以你的控制还是按你原来的思路去办,如果控制信号是低压的,也可以跟传输视频的双绞线是同一条网线里的不同的线对。


    6、问:双绞线传输器是数字传输的吗?
    答:不是。双绞线传输器不对信号进行任何数模变换,只进行放大和补偿二种信号处理。并且,几百块那来的数字传输产品呢?对一些一无所知的终端用户这样宣传还可以理解。


    7、问:多路视频信号在同一条网线内传输,不会有干扰吗?
    答:不会的。双绞线传输本身具有较强的共模干扰抑制能力,同时内部电路也有相应的预防,工程实践也证明是可行的。同一条网线内,可以是视频信号和其他的低电压信号如控制信号等的任意组合,但不可以将220伏电源接到网线内,先不管会不会有干扰,安全性就已经很成问题了。


    8、问:可以用视频线将信号传输一段距离后,再用双绞线传输吗?
    答:可以,但应该尽量短,最好不超过100米。同时由于视频线对信号的衰减,传输距离会
    缩短。是不同的视频线,缩短的距离约在视频线长的2倍到3倍。例如:本身可以传输600米的设备,如果你拉了100米视频线再进双绞线传输,那么双绞线部分就只能传输300-400米左右了。


    9、问:我使用双绞线传输时,有一个吉林长春生产的牌子的枪机不能使用,换其他牌子的枪就可以使用,更换其他厂家的传输器也不行,为什么?
    答:这是由于该牌子的枪机内部输出电路比较特别,属于直流直接输出的方式,直接将它的输出信号与传输器连接后,它的信号会不正常。你可以试一试,将它的信号进入一个分配器之类的内部带输入耦合电容的器材后,出来的信号再用双绞线传输器传输,会很正常。解决的办法,你可以找一个10uf-22uf/50v的电解电容,串在枪机的视频输出的信号极与传输器的输入端之间,一般可以很好的解决问题。
     

     

    10、问:双绞线传输的抗干扰能力如何?我有一个工地,其中一段线路想与高压电缆沟(10000伏,进甲方的电房再变压的)一起走100米左右,可以吗?
       答:不可以。前面已经谈过,不要盲目相信双绞线传输的抗干扰能力和什么防雷能力,我们认为:双绞线传输最大的用场还是降低中长距离的监控点的布线成本。双绞线与220伏一起走还问题不大,但与高压电一起走,特别是平行走线,肯定会受到干扰,轻则图像变形扭曲,严重的可能会一点图像都出不来。解决的方法是避免跟高压同沟,最好不要并行,宁愿走远一点距离。与高压线缆相交处,最好是成90度直角。 这类与高压电很近的布线环境,如果用的是视频同轴电缆,必须使用双层屏蔽的高编电缆,并且将外面的屏蔽层做一个良好的接地。无论用何种线缆的传输方式,离高压线缆越远越好。资料或取得厂商的技术支持。

     


    11、问:听说用双绞线传输的图像刚装上去时很好,过几个月后就会变差的,是不是这样?
    答:的确如此。但这不是双绞线传输所特有的。做监控工程有带点经验的技术人员都会知道:不管用是用视频线还是双绞线,装上去一段时间之后,短则数月,长则一、二年(时间与线材、安装使用环境、设备等相关),图像效果会逐渐变差。这里既有摄像机的CCD疲劳、老化的原因,也有线路受潮进水、老化,各种电参数、传输特性变差所造成的原因。使用同轴电缆,这些变化是无法修正的。反而使用双绞线时,虽然线缆参数变化来得更早些,但这些参数变化的影响是可以通过调节传输设备的增益和补偿量,来得到最大限度的修正的。所以,双绞线使用一段时间后变差的图像可以调整回来,但视频线倒是没得可调了。


    12、问:双绞线在长度不够的情况下接线会不会影响传输质量?另外双绞线在接线时候很容易留下故障隐患,有什么解决办法?
    答:不管双绞线也好,视频同轴电缆也好,中间的接头对信号都有一定的影响。所以很多要求比较高的工程会根据工程实际情况订购线材,减少中间接线的损耗和发射干扰。但是很多工程实际是很难做到这样的,只能用接线的办法处理。双绞线的连接要尽量保持双绞状态,分开的线尽可能短,用焊锡焊接好,线头线尾去掉,然后做好防护。工程中最好取适当的点集中接线,放进同一个配线箱中,据有利于防护也方便后面的维护。


    13、问:我们在用双绞线传输视频信号工程中出现了双绞线传输监控信号出现重影干扰如何解决?         
    答:有二种可能:一是产品设计不完善,这个你没有办法了,只能换一种试试。二是施工布线中造成的,请检查:
    (1)双绞线传输只支持点对点,中间不能并线,有的话将所有分线拆掉;
    (2)当线路中间有接驳的时候,请检查是否接驳时分开的线太多了,接驳要用焊锡焊接牢靠,多出线头剪掉。
    (3)线材参数偏差太大所致,换一种好一点的线试试。
    (4)将网线中没有用的线对接地处理。


    14、问:我们做了一个工程,只要打雷就会烧双绞线转换器,有的是发射端,有的是接收端。请教这是什么问题。(两端都接地了)
    答:相比同轴线,双绞线的确更加容易招雷。所以工程上一是注意选择防雷设计比较完善的产品,另一个是施工必须注意避开容易感应雷电的线路,包括空旷外露架空等的布线等都是不那么好的布线方法,同时做好接地。实在没有办法改善而现场又频遭雷击,就只能再加上良好的信号及电源避雷器了(大部分传输器的售价都比避雷器要低,避雷的效果,肯定不一样的).


    15、工程实施中发现:100米左右的监控点,用双无源的时色彩很淡并有些少干扰,用单有源的,就算将VR1调到最左边,亮度还是太高,图像发白,如何解决?
    答:使用双无源设备时,由于它没有放大补偿能力,所以传输过程中的线路衰减必须靠后级器材来补偿,所以我们一再强调,使用双无源设备的后级一定要有:亮度、对比度、彩色调节功能。出现的干扰纹,你可以将空着无用的网线接地处理,一般可以解决。如果线材达标的话,就算用双无源设备,200米左右也应该不会出现后级调不回来的亮度色彩衰减,请检查线材。另外,这么短的距离使用单有源设备时出现图像发白,排除了摄像机本身故障以及设置的原因造成的信号不正常外(用监视器直接在摄像机下面接上去看,来判断),一般是由于经过放大之后的信号过强所至,可以在有源的双绞线输入端,各串一个30欧1/2瓦的电阻,再接入双绞线信号一般可以解决。

    注意:上述摄像机设置的原因造成的信号不正常外,主要是指电子快门、光圈等设置,不当的设置会造成看室内正常,看室外或者光亮的地方图像发白的情况,你可以参考摄像机的资料或取得厂商的技术支持。


    16、无源转换器有没有可以直接连BNC头的?
    答:你要的这种无源端直接和摄像机进行连接的,可以直接套在枪机的BNC头后面使用,使用方便还省了一个BNC头。注意这一款只能用在固定的不带云台的监控点(因为双绞线不耐折,老是动的话很快就断线了),相对而言,用端子连接的的可靠性会更好(这种无源前端我的印象之中装上去之后没几个会坏的,元件被树脂灌封起来后几乎不可能进水受潮,端子接触也很好,甚至可以焊接后再做防水处理,简直就是万寿无疆了)。


    17、一条网线实际上只可以用其中二对双绞线传输视频,另外二对就算有图像,效果也很差。不是说同时传四路都不会有干扰的吗?
    答:这应该不是干扰。可能是你买了那种由二对纯铜线和二对铜包铁的线构成的低价网线。由于平时做网络时一般使用2对双绞线就可以了,所以没什么感觉,但传输视频必须用纯铜芯的双绞线,比较一下不能用的那二对线,应该比较硬,电阻也较正常的线高一些。以后要传视频的话,不要用这种二、三百多块/箱的廉价劣质线了。


    18、为什么不做成拨码开关的方式来设定传输距离?调试会简单点吧?
    答:的确是这样,用拨码开关的方式设定增益补偿量会简化调试过程。但由于这种方法将电路的增益和补偿量设定在有限的几个点上,所以很少机会能够刚好切合当时的线路状况,而能使图像效果达到最优状态的。我们自己的工程使用经验也证实了这一点,所以我们定型生产的对外销售的产品,接收器的增益补偿调整都采用可变电阻来进行无级的连续调整,使用调整多几次,以后就很容易地可以将图像调整到拨码设定所无法达到的最优状态了。我们认为:监控工程的技术人员,应该学习一点有关图像的亮度、彩色、对比度、分辨率、色散、色拖尾、重影等概念的基本常识,经过认真调整对比,是完全可以做到经过长距离传输的图像,和一百几十米视频线传输的图像,几乎没有肉眼可以观察的差别的程度的。希望广大工程用户都到能够达到降低成本的同时,改善图像质量的效果,但这同样有赖于施工人员的努力和配合。
     

     

    19、经过视频双绞线传输后的视频信号实时性如何?
    答:不存在实时性的问题,视频双绞线传输,只不过是将传统的非平衡传输方式变成抗干扰能力更强、造价更低的平衡传输方式罢了,其有源发射接收设备的作用是放大补偿,仍然属于视频基带信号的模拟传输方式,绝非数字方式(哪个工程师能设计出一百多块钱的数字视频传输设备?),不存在压缩编码之类的过程,所以信号100%的实时连续,跟视频线一样的连续实时。至于某些情况下,出现信号时断时续的现象,那是故障,正如视频线接触不良时出现的信号短断续续一样,是故障,而非实时性问题,排除故障即可。
     

     

    20、可不可以将摄像机电源(低压12伏)跟视频信号一起通过网线传输?
    答:这里有二个问题:一是电源与视频信号一起走会不会对视频有干扰?答案是这个干扰完全可以忽略不计。工程实践中,低压信号包括485控制信号、12伏直流电压等,完全可以与视频信号使用同一条网线传输。相反另外一个问题到是个问题:12伏的电源经过直径只有0.5MM的双绞线传输,线路阻抗的电压损失不小,到底传得了多远?工程经验表明,对普通枪机,100-150米左右基本上是可行的,再远恐怕就不那么可靠了。这个跟线材质量、前端机器的耗电、对电源要求等有关,必须实际带负载模拟测试来确认。


    21、双绞线的传输距离,各厂家的宣传不一,有的厂家说双无源的可以传300-600米的都有,我想问:到底传输距离跟那些因素有关?
    答:双绞线的传输距离跟下列因素有关:线材、前端设备、后端设备、双绞线传输设备等等。首要是线材,推荐使用超五类,纯铜的线芯、0.5MM的线径。使用五类线会降低距离。前端的摄像机,后端的录像机监视器等设备越好,输出的信号越好同时对输入信号的适应能力也越强,传输距离也就越长。我们的标称传输距离,实际是相当保守的,大部分工程商,可以将我们的单有源套装用到800-900米的距离,甚至有用到1200米以上仍然色彩、亮度都基本正常的工程实例,这已经是双有源设备的实际使用极限了。由于传输距离的影响因素很多,如果超出标称距离应用的,最好布线前使用同样的线材同样的设备,模拟效果并留有富余(工地实际和实验室模拟是有区别的),以免误事。  




    双绞线传输器使用疑问解答
     

    22、双绞线传输器使用何种线缆?

    答:请选用五类或五类以上的非屏蔽双绞线UTP,线缆类别越高,传输效果越好。五类屏蔽双绞线(STP CAT5 24AWG)可以在一些特殊的情况下使用。三、四类非屏蔽双绞线也可以使用,但效果和作用距离有一点影响。平行不绞合在一起(例如平行电话线)的线缆及两根各自屏蔽的线缆,不建议使用。

     

    23、在综合布线时可否把双绞线和其它线缆放在一起(例如捆在一起)?

    答:在施工布线时可与一般电话线,计算机网络线,同轴电缆线,光纤一起传输,请勿与电源线一起避免强电磁干扰。

     

    24、可否利用现有计算机网络线来传送视频、音频、数据信号?

    答:只要使用没有使用到的一对绞线就可以用来传送视频、音频、数据;一般计算机都利用网络线中的两对绞线来传输以太网等信号,另外两对线就可以传送视频、音频、数据。但传送的信号不可以经过HUB、交换机等其它设备.

     

    25、双绞线接头处是否可以直接拧在一起?

    答:最好不要直接拧在一起,如果连接不好,接触电阻过大,影响传输效果,甚至无法传输。连结处要用烙铁焊在一起,外面用热缩套管包好,防止各种短路,或者用电话接线端子,里面有油可防水防锈。

     

    26、如何模拟真实使用环境来试验双绞线传输设备?

    答:可以使用一箱线来模拟真实环境。一箱线一般为300米左右,可以分别连成300米、600米、900米、1200米(一根共有4对线,最长1200米,若再长需两箱线)。应使信号在一根线里处于同一个方向。

     

    27、一根双绞线可以传哪种组合的信号?

    答:一根线一般有四对双绞线,可以传输4路视频;总之1对线可以传输一路信号,4对线可以传输4路信号(例如可以传输4路视频或4路音频或4路数据或这三个信号的任意组合),另外大对数双绞线还可以传输更多的信号。

     

    28、双绞线可以传电源吗?

    答:可以。但是你要保证传过来的电源符合设备的要求。如设备工作电源是10-12VDC,电流是50MA,双绞线内阻为10Ω/100米(实际使用要测量),若传送的电源是12VDC,要保证设备的使用正常,你只好传送电源在200米以内

     

    29、你们的产品是走网络的吗?

    答:不是,我们的产品只是利用双绞线来代替同轴电缆作为传输介质,传输距离远远超过同轴电缆,它与普通计算机之间的网络传输不一样,它不可以穿过集线器和交换机,但可用现有网络的网线取其另2对作为视频传输2路视频图像,不用另外布线。

     

    30、你们的产品走的是数字信号吗?

    答:不是,我们的产品虽然用双绞线进行信号传输,但传输的是一种平衡信号,它抗干扰能力很强,属于一种模拟信号。再有,数字信号在普通网线中只能传输180米左右,根本不可能达到数千米的传输距离,所以我们的产品传输也不可能采用数字信号。

     

    31、你们说的一根线传输四路信号是什么意思?

    答:我们产品对线材的最低要求是普通5类双绞线。在普通5类双绞线中,有8芯线分成4对,我们的产品只需一对芯线便可传输一路图像,因此4对线芯便可传输4路图像信号。

     

    32、你们传输的音频和控制怎么解决?

    答:在普通网线中的4对线中,标准系统是一对线用来传输视频,一对传输音频,一对传输控制,还有一路预留备用,由于我们的产品只是为传输视频而设计,所以产品上并没有音频和控制的接口,如要传输控制可用双绞线的其中一对线来传输解码器的信号,也就是说用双绞线来代替控制线。如要传输音频,在对音质要求不高的情况下,把前端采集音频信号经过功放后直接由双绞线传至后端设备即可。

     

    33、你们的传输是实时的吗?

    答:是的,由于采用模拟信号进行传输,图像传输速率是每秒25帧秒,不会象数字信号那样存在缓冲和延迟的问题。

     

    34、你们的双绞线中可以传输电源吗?

    答:如果距离较近(200-300米)并且传输的是低压直流电源,则可以传输。在距离较远(1500米左右)且前端不好取电时,也可以用其中一对线传输220V50Hz交流电,不过不建议用户在同一根双绞线中既传视频又传电源,如实在要走电源,请用专用电源线,并且和双绞线保持一定距离。

     

    35、我可以用屏蔽双绞线吗?

    答:在传输中,应采用非屏蔽的双绞线,以达到最佳传输效果。由于屏蔽双绞线间存在分布电容,对平衡信号传输有一定影响,在电磁干扰较严重地区或雷电较多地区,可以采用屏蔽双绞线。

     

    36、我可以把双绞线的两对线并起来增加传输距离吗?

    答:有的用户可能会把双绞线的两对线并起来使用(例如橙线和绿线相连,橙白和绿白相连),或许用户觉得这样会减小传输的电阻而会获得更大的传输距离。在这里我非常佩服用户的聪明才智,这至少表明用户已经比较深入的了解我们的产品了,但遗憾的是,这样做是不行的,它不但不会增加传输的距离,相反由于干扰有可能还会降低传输距离。在我们的产品中走的是平衡信号,这种平衡信号依赖双绞线的双绞特性来抵消外界的干扰,由于双绞线距离相互之间线距很近并且相互缠绕,这样他们所受的干扰基本相同,经过后端接收处理便可完全去掉干扰。如果把两对线并接使用,电阻虽然减小了,但分布电容增大了,而且因它们不再具备双绞特性而受到的干扰会增大很多,严重影响信号传输,所以在普通双绞线中,一对线用来传输一路视频信号是效果最好的。

     

    37、双绞线的每一对线线芯纽距不同,对传输有影响吗?

    答:没有,的确,双绞线每一对线线芯纽距都不同,这本来是针对数字信号的传输而设计的。但在我们的产品看来,它只是产生了一些轻微的级间电容的变化,而这些变化完全可由后端的波阻抗匹配电路抵消,所以,使用我们的收发器在双绞线的任意一对线芯上传输视频信号都是没有问题的。

     

    38、我可以在发射器连接摄像机部分或接收器连接后端监控设备的部分上使用较长(如300米)来增加传输距离吗?

    答:不行。发射器只有在摄像机发射的的信号最小的失真和衰减输入后,才能达到最好的传输效果。距离较长的同轴电缆不仅信号衰减大,还有可能混入各种干扰,这样的信号通过发射器后,在接收端一定接收不到好的图像的,同理,接收端也不能连接过长的双绞线。我们推荐产品两端连接的同轴电缆最好不要超过20米,如实在需要加长,应尽量选择质量好编数大的同轴缆,且尽量做好屏蔽,远离干扰源。

     

    39、监视器没有信号?

    答:请检查各设备是否正常供电,各接头是否接触良好。先将摄像机输出信号直接连接监视器(或硬盘录像机),检测图像是否输出正常,图像正常输出后,按说明书连接设备,检查电源是否接通,双绞线是否有接触不良或断开,如是ete型需检查水晶头压线是否正确,与设备是否良好接触。

     

    40、图像出现麻点,图像暗淡?

    答:信号过弱,调节亮度和对比度电位器,适当增强增益信号。

     

    41、图像某一物体出现亮边和白色拖影?

    答:信号过强,调节亮度和对比度电位器,适当减弱信号。

     

    42、整个图像偏红,并有红条向下移动?

    答:检查BNC头是否接触良好,设备是否正常接地。

     

    43、整个图像出现大面积网纹干扰?

    答:调节电位器,若图像仍无改善检查同轴电缆编数是否足够,铜网与芯线是否隔离。

     

    44、图像不够稳定,时有时无,时好时坏?

    答:检查BNC头是否接触良好,设备是否正常接地,压线端子和各线路接头部分是否接触良好

    展开全文
  • 遥控从红外线向RF发展

    千次阅读 2012-08-22 14:03:45
    索尼公司业务执行董事、SVP电视业务本部长福田隆志表示:“遥控的通信方式从红外线改为RF以后,人们在使用遥控时就不用再考虑电视的位置和遥控的指向了。”  很长时间以来,电视遥控基本上都是利用红外线...
  • 发声单元的原理/扬声的工作原理

    千次阅读 2018-10-09 10:34:51
    当电子音频信号通过扬声器线传送到扬声器时,它实际上通过了每个驱动器的分频器件。为了让电流能流到高音扩音器,期间,必须通过一个电容器。因 此,大体上来说,高频信号产生的电流将会流到高音扩音器的音圈。为了...
  • 实现效果:3张图片进行轮播显示   制作思路: 1、制作一个展示动画效果的盒子,这个盒子里会一次展示3张图片。因此展示盒子和3张图片的宽高要设置一样。 2、把3张图片横向排列在一个图片盒子里,使用float属性...
  • PS曲线-进阶教程(深入理解PS曲线)

    千次阅读 2018-12-25 18:36:08
    灰色管(灰场)则是平衡色之间杠杆的支点,这很容易理解,它就是类似一个杆子上的滑动,向哪边滑动就会压缩哪边的空间,选择蓝色部分那么蓝色部分的空间就被压缩了,红色就会凸显出来些。 原图如下: 我们选择偏...
  • 浏览器的多线程与js引擎的线程

    千次阅读 2018-04-10 14:53:43
    ,在本地查看这个例子的时候,具体的数字是我调的,是想达到下面图示的效果。 //index.html <!DOCTYPE html> <title>webWorker var worker = new Worker("worker.js"); worker.postMessage(123456);...
  • 从下面的对比中,你将会发现哪一UV镜的抗眩光效果最好。笔者使用的相机为尼康D100,所搭配的镜头是腾龙的AF28-75mm F2.8 Di变焦镜头。 笔者的保谷1号 保谷2号 肯高Pro1 数码版 B+W 多膜 ...
  • 用声卡实现的存储示波

    万次阅读 2018-09-29 09:50:45
    wxPython应用实例:用声卡实现的存储示波 文章目录wxPython应用实例:用声卡实现的存储示波背景知识采样频率量化精度生产者/消费者模式从声卡采集数据声音采集类的定义消费者/生产者实例总体规划设计目标功能...
  • Android 贝塞尔曲线的魅力

    千次阅读 热门讨论 2015-11-25 17:50:02
    还有一个指示效果,那个一时半会找不见了。UC浏览器新闻那一的下拉刷新也是用了贝塞尔曲线的。 什么是贝塞尔曲线 在数学的数值分析领域中,贝塞尔曲线, 又称贝赛尔曲线(Bézier曲线)是电脑图形学中
  • cocos creator 模拟重力爆炸效果

    千次阅读 2018-07-13 14:56:21
    最近在写一个用collider和rigidbody来模拟...四个T1就是这四个白。最后效果是:四个物体往下掉,同时往各自方向炸飞,略微旋转。思路:掉落跟爆炸效果分开。1.掉落 代码很简单 //定义a放在start或者onload里面 ...
  • 反射效果,是一个渲染中很重要的一个效果。在表现光滑表面(金属,光滑地面),水面(湖面,地面积水)等材质的时候,加上反射,都可以画面效果有很大的提升。来看几张图: 先来张最近比较火爆的国产大作《逆水寒...
  • 前面的博文介绍了基于传统视觉的车道线检测方法,传统视觉车道线检测方法主要分为提取特征、车道像素聚类和车道线多项式拟合三个步骤。然而,无论是颜色特征还是梯度特征,人为设计的特征阈值存在鲁棒性差的问题,...
  • ATA(Advanced Technology Attachment, 高级技术附加装置)起源于 IBM,是一个单纯的磁盘驱动接口,不支持其他的接口设备,适配的是 IDE(Integrated Drive Electronics,电子集成驱动)磁盘驱动。...
  • PCB布线技巧

    千次阅读 2013-11-19 15:46:48
    、在一普通的有一 MCU 控制的 PCB 电路板中,但没大电流高速信号等要求不是很高,那么在 PCB 的四周最外的边沿是否铺一层地线把整个电路板包起来会比较好? 答:一般来讲,就铺一个完整的地就可以了。 ...
  • PCB布局布线技巧

    千次阅读 2015-07-23 00:36:32
    3.对于数字高频信号,差分线效果会更好; 2、[问]在布板时,如果线密,过孔就可能要多,当然就会影响板子的电气性能,请问怎样提高板子的电气性能? [答] 对于低频信号,过孔不要紧,高频信号尽量减少过孔。如果线...
  • 结合我之前已经写过一个随机颜色生成,就想将这个随机颜色生成写出来,作为一个工具使用,虽然实际应用场景不大,就当练练手了。 本示例中使用了大量的Generator,在写的过程发现ES6所提供的Generator在这个场景...
  • 分割分支的最后一层输出通道图像,用于二值化分割;而实例分割分支的最后一层输出N通道图像,其中N是实例维度。每个分支的损失项都是相等加权的,并通过网络反向传播。 1.4 H-Net 网络结构 LaneNet网络输出的是每...
  • 手势识别(二)--目手势识别算法总结

    万次阅读 多人点赞 2016-10-07 13:50:34
    本文参考:...一个基于视觉手势识别系统的构成应包括:图像的采集,预处理,特征提取和选择,分类的设计,以及手势识别。其流程大致如下: 其中有三个步骤是识别系统的关键,分别是预处理时手势的分
  • 老规矩,让颜色可调,来一个Properties属性,替换掉Hard encoding硬编码的颜色。所以,代码如下:   //颜色可以调版单色透明Shader Shader "浅墨Shader编程/Volume13/2.ColorChangeAlpha" { //---------------...
  • 鱼眼索引控件详解之一 —— 自定义索引

    千次阅读 多人点赞 2016-01-04 22:17:38
    1、《鱼眼索引控件详解之一 —— 自定义索引》2、《鱼眼索引控件详解之二 —— 快速索引实现》 有些同学,想要多我出些有关自定义控件的知识,我也就顺应民意吧,在总结其它知识的同时,夹杂着出些有关自定义...
  • STM32系列微控制入门介绍

    万次阅读 多人点赞 2019-07-26 10:11:24
    如果手头没有仿真的话也可以通过串口打印运行关键信息等其它方式来进行调试,不过效果可能差点,关键是没法一步步运行追踪。 固件烧录 STM32固件烧录不管是方式还是软件都挺多的,我个人一般通过UART进行烧录...
  • 函数、符号及特殊字符 声调 语法 效果 语法 效果 语法 效果 \bar{x} \acute{\eta} \check{\alpha} \grave{\eta} \breve{a} \ddot{y} \dot{x} \hat{\alpha} \t...
  • 表60亿记录等大数据场景的MySQL优化和运维之道
  • GPU图形流水线

    千次阅读 2016-02-19 20:31:02
    图形处理器的作用 在了解GPU所起的作用之前,先来看看它在计算机里的位置。图1-3是计算机系统的简易图,其中只包含了GPU周围...内存集线器(Memory Hub)在北桥芯片中,连接着内存。GPU和北桥芯片用PCIe或者AGP总线相
  • Jenkins 流水线语法

    万次阅读 多人点赞 2018-06-21 09:44:23
    虽然Groovy支持使用引号或双引号来声明一个字符串,例如: def singlyQuoted = 'Hello' def doublyQuoted = &amp;quot;World&amp;quot; 只有后一个字符串将支持基于美元符号($)的字符串插值,例如:...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 73,687
精华内容 29,474
关键字:

单块效果器线