Cesium高级教程-反射水面-使用反射相机进行离屏渲染

Cesium高级教程-反射水面-使用反射相机进行离屏渲染

应用反射相机

前面一节我们验证了创建的反射相机,这一节我们使用反射相机进行离屏渲染,关于离屏渲染的知识可以参见离屏渲染相关章节。我们将离屏渲染封装成一个方法renderToFboByReflectCamera

 function renderToFboByReflectCamera(fbo, scene, reflectCamera) {
    ...
    const us = context.uniformState;
    const view = scene._defaultView;
    scene._view = view;
    scene.updateFrameState();
    frameState.passes.render = true;
    frameState.passes.postProcess = scene.postProcessStages.hasSelected;
    frameState.tilesetPassState = renderTilesetPassState;
    let backgroundColor = Cesium.defaultValue(scene.backgroundColor, Cesium.Color.BLACK);
    if (scene._hdr) {
        backgroundColor = Cesium.Color.clone(backgroundColor, scratchBackgroundColor);
        backgroundColor.red = Cesium.Math.pow(backgroundColor.red, scene.gamma);
        backgroundColor.green = Cesium.Math.pow(backgroundColor.green, scene.gamma);
        backgroundColor.blue = Cesium.Math.pow(backgroundColor.blue, scene.gamma);
    }
    frameState.backgroundColor = backgroundColor;
    frameState.atmosphere = scene.atmosphere;
    //scene.fog.update(frameState);
    us.update(frameState);
    // const shadowMap = scene.shadowMap;
    // if (Cesium.defined(shadowMap) && shadowMap.enabled) {
    //     if (!Cesium.defined(scene.light) || scene.light instanceof SunLight) {
    //         // Negate the sun direction so that it is from the Sun, not to the Sun
    //         Cesium.Cartesian3.negate(us.sunDirectionWC, scene._shadowMapCamera.direction);
    //     } else {
    //         Cesium.Cartesian3.clone(scene.light.direction, scene._shadowMapCamera.direction);
    //     }
    //     frameState.shadowMaps.push(shadowMap);
    // }
    scene._computeCommandList.length = 0;
    scene._overlayCommandList.length = 0;
    const viewport = view.viewport;
    viewport.x = 0;
    viewport.y = 0;
    viewport.width = context.drawingBufferWidth;
    viewport.height = context.drawingBufferHeight;
    const passState = view.passState;
    passState.framebuffer = fbo;
    passState.blendingEnabled = undefined;
    passState.scissorTest = undefined;
    passState.viewport = Cesium.BoundingRectangle.clone(viewport, passState.viewport);
    // if (Cesium.defined(scene.globe)) {
    //     scene.globe.beginFrame(frameState);
    // }
    scene.updateEnvironment();
    scene.updateAndExecuteCommands(passState, backgroundColor);
    scene.resolveFramebuffers(passState);
    passState.framebuffer = undefined;
    //executeOverlayCommands(scene, passState);
    // if (Cesium.defined(scene.globe)) {
    //     scene.globe.endFrame(frameState);
    //     if (!scene.globe.tilesLoaded) {
    //         scene._renderRequested = true;
    //     }
    // }
    context.endFrame();
    scene.globe.show = true;
    scene._defaultView.camera = camera;
}

离屏渲染的方法中,我们隐藏了地球,并注释了一些不需要的渲染。

创建FBO

离屏渲染方法需要传入对应的FBO,所以我们先创建一个FBO

 function createFrameBuffer(context) {
     let width = context.drawingBufferWidth;
     let height = context.drawingBufferHeight;
     let framebuffer = new Cesium.Framebuffer({
         context: context,
         colorTextures: [
             new Cesium.Texture({
                 context: context,
                 width: width,
                 height: height,
                 pixelFormat: Cesium.PixelFormat.RGBA, 
             }),
         ], 
     });
     return framebuffer;
 }

创建FBO并调用封装的离屏渲染方法,将FBO对象作为参数传入方法中

 let fbo = createFrameBuffer(viewer.scene.context);
 renderToFboByReflectCamera(fbo, viewer.scene, reflectCamera);

此时渲染结果已经存储到FBO对象中,我们可以按照离屏渲染章节中的方法将其可视化出来

let width = viewer.scene.context.drawingBufferWidth;
let height = viewer.scene.context.drawingBufferHeight;
let pixels = viewer.scene.context.readPixels({
    x: 0,
    y: 0,
    width: width,
    height: height,
    framebuffer: fbo,
});
let cavs = document.getElementById("canvas");
cavs.width = width;
cavs.height = height;
let imgData = new ImageData(new Uint8ClampedArray(pixels), width, height);
let ctx = cavs.getContext("2d");
ctx.putImageData(imgData, 0, 0, 0, 0, width, height);
ctx.translate(0, height);
ctx.scale(1, -1);
ctx.drawImage(cavs, 0, 0);
cavs.style.height = (height * 0.3) + "px";
cavs.style.width = (width * 0.3) + "px";

在这里插入图片描述

示例效果可到 xt3d 官网 运行查看

结果如上图所示,抛开细节不谈,我们可以看到结果大概是正确的,不过好像左右是反的,这是正常的,因为反射是从底下往上看那肯定是反的。

更多内容见 Cesium高级教程-教程简介

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xt3d

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值