Cocos 3.x camera

参考
Unity3D Camera设置结合OpenGL详细解读
Unity 对Camera 属性Clear Flags 的SkyBox/Solid Color/Depth Only深度解析

一、Unity3D Camera属性
1.Clear Flags

每帧绘制完后,都需要清空各种缓冲区,最主要的是color和depth,一个负责画面最终呈现的颜色,一个负责景深。重要的是,在当前Camera范围内color和depth会有被覆盖的可能性。在范围外的color和depth有被其它Camera使用的可能性。这里的清除很多时候是为了处理,在当前Camera范围外的区域。

  • Skybox, 可以理解为Camera范围外的区域,使用SkyBox来填充。
  • Solid color,可以理解为Camera范围外的区域,使用一个纯色来填充。
  • Depth only,可以理解为Camera范围外的区域,只清空depth,而不清除color。这就保留了其它Camera范围绘制的画面,但丢失了所有景深信息。这就是为什么,当一个Camera选择Depth only的时候,其它Camera的渲染画面可以保留。没有了景深,多个Camera之间的渲染层级就依赖Camera的Depth来设置。
  • Don’t clear, 就是不清除color和depth,每次绘制都会叠加在一起。
2.Background:

就是用来填充,当前Camera范围内没有被绘制的区域。

3.Culling Mask:

没被选中的Layer会被当前Camera给剔除,不会渲染。过滤非选中层的方法有很多,可能都不会调用渲染函数,没必要使用OpenGL的剪裁功能。

4.Projection:

正交ortho和透视perspective,以及剪裁平面,就是生成一个矩阵数据。

参考正交相机与透视相机的区别
正交相机,三只羊一样大。

image.png

透视相机,三只羊大小不一样,缩小视距可以减轻这种影响。
image.png

5.Viewport Rect:

直接对应了,OpenGL的 glViewport 调用。

6.Depth:

当有多个Camera的时候,每个Camera有自己的绘制空间区域和屏幕视口。所包含的物体会通过Camera的范围渲染出来。多个Camera的层级,决定了所包含物体的渲染顺序。这个数字从小到大,越来越靠近屏幕。

7.Rendering Path:

通用的几个shader选择,主要处理光照的。

8.Target Texture:

可以把Camera渲染的画面,绘制到一个纹理上,而不是设备的显示缓冲区里。

二、Unity3D Clear Flags详解
1.内部环境裁剪(Clipped inside the environment)

这个说的是Camera的另一个属性Clipping Planes,这个属性包含两个值Near/Far。举个简单的例子,比如人眼睛,距离人眼睛太近的物体看不清、距离人眼睛太远的物体看不到,这就是Near、Far了。看下图


image.png

你看,这个观赏树的近端可以看完整,远景也OK。这个时候Clipping Planes Near == 0.3 Far == 1000


image.png

再看,近端丢了一块,远景也丢了。这个时候Near == 3 Far == 6

也就是说距Camera小于Near距离的物体被裁剪掉、距Camera大于Far距离的物体被裁剪掉。

将Far的默认值从1000改到18

那么,怎么能避免物体被裁剪掉,而且还能离摄像头Near>=3呢?那就是,把这个景观树单独用另一个摄像头来显示。具体,看下一个知识点。

2.Depth

这个深度,顾名思义,就是摄像机的深度了。当只有一个摄像机时,这个属性没有意义。当有大于两个摄像机时,就牵扯到多个摄像机的前后层叠问题了。

Depth值越大,越靠上,也就是越靠外,也就是可以遮挡值较小的摄像机的画面。比如MainCamera就默认为-1,然后新建摄像机就是0,在上边。

那么回到刚才景观树这个问题,如果想用一个摄像机专门展示景观树,而且还在主摄像机中可以看到,那么Depth必然要大一些,在主摄像机的上面喽。接下来,我们就来讨论Clear Flags 的Depth Only啦:

我们先试着把显示景观树的摄像机的Clear Flags设置为SkyBox或者Solid Color,我们会发现主摄像机镜头被天空盒或者纯色挡住了。然后将ClearFlags改为Depth only,我们会发现,景观树成功的嵌入了主摄像机的其他景色中,浑然天成。根据Depth only字面意思来讨论,也就是说,这个时候摄像机的未渲染部分的显示内容取决于深度,未渲染部分显示什么由深度小于本摄像机的内容来决定。

3.Depth only应用实例

现在回到枪的话题。我做了一个小例子,如图就是场景,其中有三个Enemy,一个Player(蓝色),一个Gun(绿色):


image.png

然后先是只有一个Camera,我们看看效果:


image.png

看,由于枪离人物太近,导致从人物的视角观察时,最近的一部分被裁剪掉了。那怎么办?我总不能把枪再朝外吧?再朝外就不自然了呢。

那么我把枪的Layer设置成GunLayer,然后在MainCamera中CullingMask中取消对GunLayer的显示。然后新建Camera,把深度设置为0(因为MainCamera的深度为-1),Clear Flags设置成Depth only,把CullingMask中只勾选GunLayer,那么这个新的Camera就只显示Gun了。调整Camera的位置到适合位置。看效果:


image.png

人物举枪的姿势,很自然吧?

接下来,我将专门解析这段话的含义,觉得上面的翻译有些不好,我自己尝试翻译了下

This will keep the graphical display of the environment on the screen, but discard all information about where each object exists in 3-D space. When the gun is drawn, the opaque parts will completely cover anything drawn, regardless of how close the gun is to the wall.(设置深度的这个操作)将会保持环境中的图形显示的完整,但是,会丢弃所有其他物体在3D空间中存放位置的信息。当枪被绘制时,它的透明部分会完整的覆盖其他任何绘制,不管这把枪到底离墙有多近。

那么我理解的意思就是设置成Depth only的Camera中的物体,将会凌驾在其他任何物体上,当然,只能凌驾在Depth比他小的物体上。不受3D位置的前后影响。能够完整的呈现在观察者面前。

我做实验如下:

我先将一个Enemy顶进了枪里:


image.png

再来观察效果:


image.png

枪还在外面,没有顶进去。很明显,其他物体的3D位置信息没有体现出来,不然就不是这个效果了。

至此,这个Depth Only,的含义已经很传神了。

三、cocos3.0 camera

参考
cocos3.0官方文档 camera
cocos3.0官方文档 渲染排序说明

1.相机分组渲染

Visibility 属性用于设置哪些层级(Layer)的节点应该被相机观察到,可同时选择多个 Layer。注意:从 Cocos Creator 3.0 开始,2D 元素(例如 Sprite)的渲染也遵从 Layer 与 Visibility 的判断,开发者可以根据需要自行调整 Layer 与 Visibility。

当开发者在 Visibility 属性中勾选了多个 Layer 时,Visibility 属性值便是通过将多个 Layer 的属性值执行 | 操作计算得出。

2.Clear Flags
image.png
  • DONT_CLEAR:不清空;
  • DEPTH_ONLY:只清空深度;
  • SOLID_COLOR:清空颜色、深度与模板缓冲;
  • SKYBOX:启用天空盒,只清空深度

排序是一个很简单的功能,但是最终的呈现却是根据不同平台提供的渲染能力来的。因此,在这里说明一下,如果遇到了 UI 渲染出错,花屏,闪屏等现象,首先要检查的就是场景里所有相机(Camera 和 Canvas)的 ClearFlag,确保场景里必须有一个相机要执行 Solid_Color 清屏操作。

具体如何设置 ClearFlag,可参考以下几种情况:

如果场景中只有一个 UI Canvas 或者 3D Camera,那么 ClearFlag 属性设置为 Solid_Color。
如果场景中包含 UI 背景层、3D 场景层、 UI 操作层,则:

  • 2D 背景层:ClearFlag 属性设置为 Solid_Color。
  • 3D 场景层:ClearFlag 属性设置为 Depth_Only。
  • 2D UI 层:若有模型,ClearFlag 属性设置为 Depth_Only 以避免出现模型闪屏或者穿透的情况。若没有模型,ClearFlag 属性可设置为 Dont_Clear 或 Depth_Only。
image.png
3.canvas自带的摄像机属性
image.png

image.png

如图,设计分辨率1080*2000时,默认canvas的camera属性。其中orthoHeight是高度2000的一半。如果设计分辨率是1080*1920,则orthoHeight就是960了。

上图摄像机盒子的厚度是由far来控制的,默认摄像机位置Z是1000,默认Far是2000。如果将far改为1000,则刚好看到canvas的内容。

默认的正交摄像机,改fov没影响。在透视摄像机中,改Fov和摄像机的坐标以及旋转角度,就能得到合适的画面。


image.png
3.测试实例
image.png

新建一个Scene,以下操作全部使用默认配置:

  • 添加一个胶囊,默认LAYER是DEFAULT
  • scene中默认的相机ClearFlag使用SOLID_COLOR,visibility设置为IGNORE_RAYCAST|UI_3D|DEFAULT,注意为透视投影
  • 添加一个Button,会自动生成CANVAS父节点和相应的CAMERA,CANVAS和BUTTON的LAYER全是UI_2D
  • CANVAS下的CAMERA,其visibility设置为UI_3D|UI_2D,ClearFlag使用DEPTH_ONLY,注意为正交投影
  • Priority 相机的渲染优先级,值越小越优先渲染。所以这里CANVAS下的CAMERA的Priority值非常大(1073741824),而SCENE中的CAMERA的Priority为0(简单记忆为,值大的盖在上面)

分析:
BUTTON以及CANVAS的LAYER全是UI_2D,其相应的CAMERA,设置的VISIBILITY确保只看到这些,然后使用的DEPTH_ONLY会叠加到场景中的主摄像机上。

场景里所有相机(Camera 和 Canvas)的 ClearFlag,确保 场景里必须有一个相机要执行 Solid_Color 清屏操作。

根据官方文档所说,场景中的Camera 设置为Solid_Color即可。

4.【Cocos Creator3.0教程】小地图的实现方式
  • TargetTexture 指定相机的渲染输出目标贴图,默认为空,直接渲染到屏幕,本例将副摄像机看到的内容动态输出到一个sprite中
  • ClearColor 指定清空颜色,本例中将颜色值和透明度全部清0
//MiniMap.ts:
import { _decorator, Component, Node, Camera, Sprite, RenderTexture, UITransform, SpriteFrame } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('Minimap')
export class Minimap extends Component {
    @property(Camera)
    private minimapCamera: Camera = null!;
    @property(Sprite)
    private contentSprite: Sprite = null!;

    start() {
        //新建一个和当前contentSprite大小一样的rendertexture
        const size = this.contentSprite.getComponent(UITransform)!.contentSize;
        const renderTexture = new RenderTexture();
        renderTexture.reset(size);
        //把摄像机看到的内容输出到这个rendertexture
        this.minimapCamera.targetTexture = renderTexture;

        //把这个rendertexture包装到SpriteFrame中,然后呈现给当前contentSprite
        const spriteFrame = new SpriteFrame();
        spriteFrame.texture = renderTexture;
        this.contentSprite.spriteFrame = spriteFrame;
    }

}
5.near
image.png

如上图,当把模型的scale调大后,会出现面部贴图糊掉。此时改一下camera的near属性即可。

6.固定角度的3D场景适配

参考
各位大佬,3D模型怎么做适配呀
急!creator3d的适配问题
Creator 3D Camera按宽度适配的解决方案

import { _decorator, Component, Node, CameraComponent, view, SystemEventType, systemEvent } from "cc";
const { ccclass, property, requireComponent } = _decorator;

@ccclass
@requireComponent(CameraComponent)
export class FitWidthCamerats extends Component {

    private _camera!: CameraComponent;
    private _defaultTanHalfFov!: number;

    onLoad() {
        this._camera = this.getComponent(CameraComponent)!;
        this._defaultTanHalfFov = Math.tan(this._camera.fov * 0.5 / 180 * Math.PI);
        this.updateFov();
        window.addEventListener('resize', this.updateFov);
    }

    updateFov = () => {
        console.log(view.getVisibleSize().height, view.getDesignResolutionSize().height)
        let tanHalfFov2 = view.getVisibleSize().height / view.getDesignResolutionSize().height * this._defaultTanHalfFov;
        this._camera.fov = Math.atan(tanHalfFov2) / Math.PI * 180 * 2;
    }

    onDestroy() {
        window.removeEventListener('resize', this.updateFov);
    }

}

这里要注意,增加fov会导致屏幕宽高的可视区域都会加大。在特别瘦长的手机屏幕上,为了保证屏幕宽度范围内看到所有模型,就会导致额外看到屏幕顶部和底部更多内容。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容