×

URP中如何用多个相机?

消耗积分:2 | 格式:pdf | 大小:419.84KB | 2021-02-04

123

分享资料个

作者:郑洪智

在通用渲染管线(URP)中,相机有堆栈相机、渲染到同一渲染目标、渲染为RenderTexture(渲染纹理)三种工作方式。

在通用渲染管线(URP)中,相机有以下工作方式:

  • 堆栈相机(Stack Cameras)可以将多个相机的输出合并为单个输出。通过相机堆栈,你可以在2D UI中加入3D模型,或者创建车辆驾驶舱的效果。
  • 将多个基础相机或相机堆栈渲染到同一渲染目标。这使你可以创建例如分屏渲染效果。
  • 将基础相机或相机堆栈渲染为RenderTexture(渲染纹理)。通过渲染到RenderTexture,可以创建例如CCTV监视器之类的效果。

URP中的相机堆栈

你可以结合使用这些工作方式来获得更复杂的效果。例如,你可以定义两个相机堆栈,然后将每个相机堆栈设置为渲染到同一渲染目标的不同区域。

相机堆栈

相机堆栈由基础相机和一个或多个叠加相机组成。相机堆栈使用堆栈中所有相机的组合输出叠加基础相机的输出。这样,你可以对基础相机的输出进行任何处理,也可以对相机堆栈的输出进行处理。例如,你可以将相机堆栈渲染到给定的渲染目标、应用后处理效果等等。

URP在Camera中执行了多项优化,包括渲染顺序优化以减少overdraw。但是,使用相机堆栈时,你在手动定义渲染这些相机的顺序。因此,你必须小心对相机进行排序,不要导致过度overdraw。有关URP中overdraw的信息,后面开一节专门讲。

01 将相机添加到相机堆栈

将相机添加到相机堆栈

  • 在场景中创建相机。它的Render Type默认为Base,使其成为基础相机。
  • 在场景中创建另一个相机,然后选中。
  • 在相机Inspector中,将相机的渲染类型RenderType更改为Overlay。
  • 再次选择基础相机。在相机Inspector中,滚动到Stack部分,单击加号(+)按钮,然后单击叠加相机的名称。

叠加相机现在是基础相机的相机堆栈的一部分。Unity在基础相机的输出之上渲染叠加相机的输出。

你可以通过直接操纵cameraStack基础相机的UniversalAdditionalCameraData组件的属性,将脚本中的相机添加到相机堆栈中,如下所示:

var cameraData = camera.GetUniversalAdditionalCameraData();
cameraData.cameraStack.Add(myOverlayCamera);

02 从相机堆栈中移除相机

从相机堆栈中移除相机

  • 创建一个至少包含一个叠加相机的相机堆栈。
  • 选择相机堆栈的基础相机。
  • 在相机Inspector中,滚动到Stack部分,单击要删除的叠加相机的名称,然后单击减号(-)按钮。

叠加相机保留在场景中,但不再是相机堆栈的一部分。

你可以通过直接操纵cameraStack基础相机的UniversalAdditionalCameraData组件的属性,从脚本中的相机堆栈中删除相机,如下所示:

var cameraData = camera.GetUniversalAdditionalCameraData();
cameraData.cameraStack.Remove(myOverlayCamera);

03 更改相机堆栈中相机的顺序

从相机堆栈中移除相机

  • 创建一个包含多个叠加相机的相机堆栈。
  • 在相机堆栈中选择基础相机。
  • 在相机Inspector中,滚动到“堆栈”部分。
  • 使用叠加相机名称旁边的手柄重新排列叠加相机列表。

基础相机会渲染相机堆栈的基础层,堆栈中的叠加相机会按照从上到下的列出顺序在其顶部进行渲染。

你可以通过直接操纵cameraStack基础相机的UniversalAdditionalCameraData组件的属性,在脚本中对相机堆栈进行重新排序。

04 将同一台叠加相机添加到多个堆栈

要将叠加相机添加到多个相机堆栈:

  • 创建一个至少包含一个叠加相机的相机堆栈。
  • 在场景中创建相机。它的渲染类型默认为Base,使其成为基础相机。
  • 选择新的基础相机。
  • 在相机Inspector中,滚动到堆栈部分,单击加号(+)按钮,然后单击要在两个相机堆栈中使用的叠加相机的名称。

现在,叠加相机将同时在两个相机堆栈中渲染。

你还可以通过直接操纵cameraStack基础相机的UniversalAdditionalCameraData组件的属性,将脚本中的相机添加到相机堆栈中,如下所示:

var cameraData = camera.GetUniversalAdditionalCameraData();
cameraData.cameraStack.Add(myOverlayCamera);

将多个相机渲染到一个目标

在通用渲染管线(URP)中,多个基础相机或相机堆栈可以渲染到同一渲染目标。这使你可以创建例如分屏渲染的效果。

如果有多个基础相机或相机堆栈渲染到渲染目标的同一区域,则Unity会多次绘制重叠区域中的每个像素。最高优先级的基础相机或相机堆栈最后绘制。

你可以使用基础相机的输出目标属性来定义渲染目标,并使用视口矩形(Viewport Rect)属性来定义要渲染到的渲染目标的区域。

设置分屏渲染

在URP中设置分屏渲染

  • 在场景中创建相机。其渲染模式默认为Base,使其成为Base Camera。
  • 选择相机。在Inspector中,滚动到Output部分。将Viewport的值更改为以下值:
    X:0
    Y:0
    Width:0.5
    Height:1
  • 在场景中创建另一个相机。其渲染模式默认为Base,使其成为Base Camera。
  • 选择相机。在Inspector中,滚动到Output部分。将Viewport Rect的值更改为以下值:
    X:0.5
    Y:0
    Width:0.5
    Height:1

Unity将第一个Camera渲染到屏幕的左侧,将第二个Camera渲染到屏幕的右侧。

你可以通过设置其rect属性,在脚本中更改相机的视口矩形,如下所示:

myUniversalAdditionalCameraData.rect = new Rect(0.5f, 0f, 0.5f, 0f);

渲染到RenderTexture

在通用渲染管线(URP)中,相机可以渲染到屏幕或RenderTexture(渲染纹理)。渲染到屏幕是默认设置,也是最常见的用例,但是渲染到RenderTexture可让你创建如CCTV相机监视器的效果。

如果你有要渲染为RenderTexture的相机,则必须有第二个相机,然后再将该RenderTexture渲染到屏幕上。在URP中,所有渲染到RenderTexture的相机都在所有渲染到屏幕的相机之前执行其渲染循环。这样可以确保RenderTexture已准备好渲染到屏幕上。

渲染到RenderTexture,然后将该RenderTexture渲染到屏幕。

在URP中渲染到RenderTexture

  • 使用Assets > Create > Render Texture在项目中创建Render Texture资产。
  • 在场景中创建一个Quad。
  • 在你的项目中创建一个材质,然后选择它。在Inspector中,将RenderTexture拖动到材质的BaseMap字段。
  • 在Scene视图中,将材质拖到Quad上。
  • 在场景中创建相机,其渲染模式默认为Base,使其成为Base Camera。
  • 选择基础相机。在Inspector中,滚动到Output部分,然后将Render Texture拖到Output Texture字段。
  • 在场景中创建另一个相机。它的渲染模式默认为Base,使其成为Base Camera,将Quad放置在新Base Camera的视图内。

第一台Camera将其视图渲染到RenderTexture。第二台相机将包括RenderTexture的场景渲染到屏幕上。

你可以通过设置cameraOutput相机的UniversalAdditionalCameraData组件的属性,在脚本中设置相机的Output,如下所示:

myUniversalAdditionalCameraData.cameraOutput = CameraOutput.Texture;
myCamera.targetTexture = myRenderTexture;


本文转自:Unity官方平台 ,作者:郑洪智,转载此文目的在于传递更多信息,版权归原作者所有。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !

'+ '

'+ '

'+ ''+ '
'+ ''+ ''+ '
'+ ''+ '' ); $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code ==5){ $(pop_this).attr('href',"/login/index.html"); return false } if(data.code == 2){ //跳转到VIP升级页面 window.location.href="//m.obk20.com/vip/index?aid=" + webid return false } //是会员 if (data.code > 0) { $('body').append(htmlSetNormalDownload); var getWidth=$("#poplayer").width(); $("#poplayer").css("margin-left","-"+getWidth/2+"px"); $('#tips').html(data.msg) $('.download_confirm').click(function(){ $('#dialog').remove(); }) } else { var down_url = $('#vipdownload').attr('data-url'); isBindAnalysisForm(pop_this, down_url, 1) } }); }); //是否开通VIP $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code == 2 || data.code ==5){ //跳转到VIP升级页面 $('#vipdownload>span').text("开通VIP 免费下载") return false }else{ // 待续费 if(data.code == 3) { vipExpiredInfo.ifVipExpired = true vipExpiredInfo.vipExpiredDate = data.data.endoftime } $('#vipdownload .icon-vip-tips').remove() $('#vipdownload>span').text("VIP免积分下载") } }); }).on("click",".download_cancel",function(){ $('#dialog').remove(); }) var setWeixinShare={};//定义默认的微信分享信息,页面如果要自定义分享,直接更改此变量即可 if(window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger'){ var d={ title:'URP中如何用多个相机?',//标题 desc:$('[name=description]').attr("content"), //描述 imgUrl:'https://'+location.host+'/static/images/ele-logo.png',// 分享图标,默认是logo link:'',//链接 type:'',// 分享类型,music、video或link,不填默认为link dataUrl:'',//如果type是music或video,则要提供数据链接,默认为空 success:'', // 用户确认分享后执行的回调函数 cancel:''// 用户取消分享后执行的回调函数 } setWeixinShare=$.extend(d,setWeixinShare); $.ajax({ url:"//www.obk20.com/app/wechat/index.php?s=Home/ShareConfig/index", data:"share_url="+encodeURIComponent(location.href)+"&format=jsonp&domain=m", type:'get', dataType:'jsonp', success:function(res){ if(res.status!="successed"){ return false; } $.getScript('https://res.wx.qq.com/open/js/jweixin-1.0.0.js',function(result,status){ if(status!="success"){ return false; } var getWxCfg=res.data; wx.config({ //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:getWxCfg.appId, // 必填,公众号的唯一标识 timestamp:getWxCfg.timestamp, // 必填,生成签名的时间戳 nonceStr:getWxCfg.nonceStr, // 必填,生成签名的随机串 signature:getWxCfg.signature,// 必填,签名,见附录1 jsApiList:['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 wx.onMenuShareTimeline({ title: setWeixinShare.title, // 分享标题 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享给朋友”按钮点击状态及自定义分享内容接口 wx.onMenuShareAppMessage({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 type: setWeixinShare.type, // 分享类型,music、video或link,不填默认为link dataUrl: setWeixinShare.dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ”按钮点击状态及自定义分享内容接口 wx.onMenuShareQQ({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口 wx.onMenuShareWeibo({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ空间”按钮点击状态及自定义分享内容接口 wx.onMenuShareQZone({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); }); }); } }); } function openX_ad(posterid, htmlid, width, height) { if ($(htmlid).length > 0) { var randomnumber = Math.random(); var now_url = encodeURIComponent(window.location.href); var ga = document.createElement('iframe'); ga.src = 'https://www1.elecfans.com/www/delivery/myafr.php?target=_blank&cb=' + randomnumber + '&zoneid=' + posterid+'&prefer='+now_url; ga.width = width; ga.height = height; ga.frameBorder = 0; ga.scrolling = 'no'; var s = $(htmlid).append(ga); } } openX_ad(828, '#berry-300', 300, 250);