Cesium中使用Sampler3D,3D纹理,实现体渲染

news2024/11/15 14:08:07

Cesium中使用Sampler3D,3D纹理,实现体渲染

Cesium目前(20221231)还不支持直接使用3D纹理,但是其实内部已经可以WebGL2,而且内置常量也有3DTexture。所以,可以通过仿Texture,来实现3D纹理的使用。

在这里插入图片描述

修改Cesium源码

引入Cesium后,需要修改@cesium\engine\Source\Renderer\createUniform.js中的createUniform方法,在case gl.SAMPLER_CUBE后增加gl.SAMPLER_3D.

WebGL基本函数

就是常用的WebGL的纹理函数,不再赘述。只说明一下Texture3D的选用参数,目前仅使用了ALPHA一个通道,且数据类型对应为UNSIGNED_BYTE,即Uint8Array.

texImage3D

WebGL2RenderingContext.texImage3D(target, level, internalformat, width, height, depth, border, format, type, srcData)

  • target: gl.TEXTURE_3D

  • level: level of detail

  • internalformat: gl.ALPHA, discards the red, green and blue components and reads the alpha component.

  • width: width of the texture

  • height: height of the texture

  • depth: depth of the texture

  • border: Must be 0

  • format: ALPHA=ALPHA. The correct combinations with internalformat are listed in this table

  • type: gl.UNSIGNED_BYTE

Texture3D实现

import {
    Cartesian2,
    Cartesian3,
    Check,
    createGuid,
    defaultValue,
    defined,
    destroyObject,
    DeveloperError,
    CesiumMath,
    PixelFormat,
    ContextLimits,
    MipmapHint,
    PixelDatatype,
    Sampler,
    TextureMagnificationFilter,
    TextureMinificationFilter
} from "cesium";

function Texture3D(options) {
    options = defaultValue(options, defaultValue.EMPTY_OBJECT);

    Check.defined("options.context", options.context);

    const context = options.context;
    let width = options.width;
    let height = options.height;
    let depth = options.depth;
    let source = options.source;

    const pixelFormat = defaultValue(options.pixelFormat, PixelFormat.RGBA);
    const pixelDatatype = defaultValue(options.pixelDataType, PixelDatatype.UNSIGNED_BYTE);
    const internalFormat = PixelFormat.toInternalFormat(pixelFormat, pixelDatatype, context);

    if (!defined(width) || !defined(height) || !defined(depth)) {
        throw new DeveloperError(
            "options requires a source field to create an 3d texture. width or height or dimension fileds"
        )
    }

    Check.typeOf.number.greaterThan("width", width, 0);

    if (width > ContextLimits.maximumTextureSize) {
        throw new DeveloperError(
            "width must be less than or equal to the maximum texture size"
        );
    }

    Check.typeOf.number.greaterThan("height", height, 0);

    if (height > ContextLimits.maximumTextureSize) {
        throw new DeveloperError(
            "height must be less than or equal to the maximum texture size"
        );
    }

    Check.typeOf.number.greaterThan("dimensions", depth, 0);

    if (depth > ContextLimits.maximumTextureSize) {
        throw new DeveloperError(
            "dimension must be less than or equal to the maximum texture size"
        );
    }

    if (!PixelFormat.validate(pixelFormat)) {
        throw new DeveloperError("Invalid options.pixelFormat.");
    }

    if (!PixelDatatype.validate(pixelDatatype)) {
        throw new DeveloperError("Invalid options.pixelDatatype.");
    }

    let initialized = true;
    const gl = context._gl;
    const textureTarget = gl.TEXTURE_3D;
    const texture = gl.createTexture();

    const lxs= gl.getParameter(gl.ACTIVE_TEXTURE);
    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(textureTarget, texture);
    let unpackAlignment = 4;
    if (defined(source) && defined(source.arrayBufferView)) {
        unpackAlignment = PixelFormat.alignmentInBytes(pixelFormat, pixelDatatype, width);//??
    }

    gl.pixelStorei(gl.UNPACK_ALIGNMENT, unpackAlignment);
    gl.pixelStorei(
        gl.UNPACK_COLORSPACE_CONVERSION_WEBGL,
        gl.BROWSER_DEFAULT_WEBGL
    );

    if (defined(source)) {
        if (defined(source.arrayBufferView)) {
            let arrayBufferView = source.arrayBufferView;
            gl.texImage3D(
                textureTarget,
                0,
                internalFormat,
                width,
                height,
                depth,
                0,//border
                pixelFormat,
                PixelDatatype.toWebGLConstant(pixelDatatype, context),
                arrayBufferView
            );
            initialized = true;
        }
    }
    gl.bindTexture(textureTarget, null);
    this._id = createGuid();
    this._context = context;
    this._textureFilterAnisotropic = context._textureFilterAnisotropic;
    this._textureTarget = textureTarget;
    this._texture = texture;
    this._internalFormat = internalFormat;
    this._pixelFormat = pixelFormat;
    this._pixelDatatype = pixelDatatype;
    this._width = width;
    this._height = height;
    this._depth = depth;
    this._dimensions = new Cartesian3(width, height, depth);
    this._hasMinmap = false;
    this._sizeInBytes = 4;
    this._preMultiplyAlpha = false;
    this._flipY = false;
    this._initialized = initialized;
    this._sampler = undefined;

    this.sampler = defined(options.sampler) ? options.sampler : new Sampler();
}

// Creates a texture, and copies a subimage of the framebuffer to it.
Texture3D.fromFramebuffer = function (options) {
    options = defaultValue(options, defaultValue.EMPTY_OBJECT);
    Check.defined("options.context", options.context);

    const context = options.context;
    const gl = context._gl;

    const pixelFormat = defaultValue(options.pixelFormat, PixelFormat.RGB);
    const framebufferXOffset = defaultValue(options.framebufferXOffset, 0);
    const framebufferYOffset = defaultValue(options.framebufferYOffset, 0);
    const width = defaultValue(options.width, gl.drawingBufferWidth);
    const height = defaultValue(options.height, gl.drawingBufferHeight);
    const depth = defaultValue(options.depth, 128);
    const framebuffer = options.framebuffer;

    const texture=new Texture3D({
        context:context,
        width:width,
        height:height,
        pixelFormat:pixelFormat,
        source:{
            framebuffer:defined(framebuffer)?framebuffer:context.defaultFramebuffer,
            width:width,
            height:height,
            depth:depth,
        }
    });
    return texture;
};

Object.defineProperties(Texture3D.prototype,{
    id:{
        get:function(){
            return this._id;
        }
    },
    sampler:{
        get:function(){
            return this._sampler;
        },
        set:function(sampler){
            let minificationFilter=sampler.minificationFilter;
            let magnificationFilter=sampler.magnificationFilter;
            const context=this._context;
            const pixelFormat=this._pixelFormat;
            const pixelDatatype=this._pixelDatatype;

            const gl=context._gl;
            const target=this._textureTarget;

            gl.activeTexture(gl.TEXTURE0);
            gl.bindTexture(target,this._texture);
            // 3D 纹理不设置放大,缩小,重采样
            gl.texParameteri(target,gl.TEXTURE_MIN_FILTER,minificationFilter);
            gl.texParameteri(target,gl.TEXTURE_MAG_FILTER,magnificationFilter);
            gl.bindTexture(target,null);

            this._sampler=sampler;
        }
    },
    dimensions:{
        get:function(){
            return this._dimensions;
        }
    },
    width:{
        get:function(){
            return this._width;
        }
    },
    height:{
        get:function(){
            return this._height;
        }
    },
    depth:{
        get:function(){
            return this._depth;
        }
    },
    _target:{
        get:function(){
            return this._textureTarget;
        }
    }
});

Texture3D.prototype.isDestroyed=function(){
    return false;
}

Texture3D.prototype.destory=function(){
    this._context._gl.deleteTexture(this._texture);
    return destroyObject(this);
};

export {Texture3D};

使用示例

自定义Primitive参考[这篇文章](Cesium Volumn 体渲染_Bro_Of_Nagi的博客-CSDN博客_cesium噪声)

修改getTexture

图元返回3D纹理,直接返回Texture3D

getTexture(context) {
        if(!this.texture){
            const texture_size = Math.ceil(Math.sqrt(this.data.length));
            this.texture=new Texture3D({
                width:size,
                height:size,
                depth:size,
                context: context,
                flipY: false,
                pixelFormat: Cesium.PixelFormat.ALPHA,
                pixelDataType: Cesium.ComponentDatatype.fromTypedArray(
                    this.data
                ),
                source: {
                    width: texture_size,
                    height: texture_size,
                    arrayBufferView: this.data,
                },
                sampler: new Cesium.Sampler({
                    minificationFilter: Cesium.TextureMinificationFilter.NEAREST,
                    magnificationFilter: Cesium.TextureMagnificationFilter.NEAREST,
                }),
            })
        }

        return this.texture;
    }

添加自定义Primitive

构造好Uint8array数据data,代理几何体依旧是单位立方体

const options = {
    modelMatrix: primitive_modelMatrix,
    geometry_lxs: geometry,
    data: data,
    dim: dim_lxs
};

const lxs = viewer.scene.primitives.add(
    new lxs_primitive(options)
);

在这里插入图片描述

代码地址

其中texture3D分支为以上代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/132151.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何彻底的理解需求,做出更好的软件

背景: 最近接到了一个需求,大概的需求就是我们有一些数据,默认分为了两类。如果变多的话,用户找起来非常的困难,针对这个现象我们提出了两点解决方案。1:添加搜索。2:添加分组。 第一波设计&…

Android的adb命令实战篇-1

2023年 —— 是充满希望的一年. 对于Android开发者而言,ADB命令或多或少都使用过,今天我们就一起来整体回顾一下吧。 ADB的全称:Android Debug Bridge 1. ADB(Android Debug Bridge) 在实际工作中,周围同事会抱怨记不住常用的a…

过寒假

小时候,每到一放假就被父亲送回奶奶家。除了寒假作业,我还会带一堆书回去看。我小时候特别喜欢到邮电局大厅去订阅报刊杂志,就连学校也会报名订阅报刊。我小学时看完梁羽生的《七剑下天山》就是翻日报上每天的小说连载看完的。那时候过年时家…

Unity AR小游戏(玩具小车)踩坑记

最近对AR产生了兴趣。先科普一下什么是AR吧。AR是Augmented Reality(增强现实)的简称,是基于摄像头对现实世界的实时图像采集、分析和理解,然后在此基础上融入虚拟物体(信息),以达到增强体验的目…

Three.js学习(一)初识three.js

文章目录1.基本配置2.基本概念3.Api4.实现一个旋转动画1.基本配置 (1)安装 ​ npm install three (2)引入 import * as THREE from three2.基本概念 Three.js是基于原生WebGL封装运行的三维引擎。 (1)一…

【Linux】实验四 进程信号通信

文章目录一、实验目的二、 实验内容三、 实验原理1、信号3.1.1 信号的基本概念3.1.2、信号的发送2、所涉及的系统函数调用3.2.1 fork()3.2.2 kill( )This is my question.3.2.3 signal( )代码例子3.2.4 getpid()3.2.5 wait()四、 实验内容五、程序代码运行结果六、实验总结及心…

来玩,前端性能优化(+面试必问:宏任务和微任务)

前端性能优化相关的“技能点”笔者之前也写过几篇,但是大多都是小打小闹。我重新整理了曾经使用过的性能优化手段。本文介绍三种方案:页面资源预加载、服务请求优化和非首屏视图延迟加载。 页面资源预加载 页面是不可能真正预加载的,但是有…

Linux | PCIe Hotplug | 概念及工作原理的不完全总结

本文对 PCIe 热插拔的概念及工作原理进行不完全总结。 更新: 2022 / 12 / 31 Linux | PCIe Hotplug | 概念及工作原理的不完全总结热插拔组成部件实现代码通知式热插拔线程中断功耗管理意外移除错误处理整合移除BAR参考链接参考这里 1’ 2’ 3‘ 4’ 5 1992年初始…

postgresql数据库安装,备份还原

一.postgresql数据库安装 1.下载软件包 地址:PostgreSQL: File Browser 2.解压安装 [rootpostgresql u01]# tar -zxf postgresql-14.2.tar.gz安装环境 yum install -y perl-ExtUtils-Embed readline-devel zlib-devel pam-devel libxml2-devel libxslt-devel op…

(深度学习快速入门)第一章:深度学习概述、应用、学习路线和框架选择

文章目录一:基本概念(1)神经网络(2)感知器(3)深度学习(4)前向运算和反向传播二:DeepLearning学习路线三:深度学习应用(1)生…

基于Stream的Redis消息队列

目录一、消息队列二、基于List结构模拟消息队列基于List的消息队列的优点:基于List的消息队列的缺点:三、基于PubSub的消息队列基于PubSub的消息队列的优点:基于PubSub的消息队列的缺点:四、基于Stream的消息队列1、XADD语法2、XR…

C++ Primer笔记——allocator、unique_ptr和release、智能指针与动态数组、阻止拷贝

目录 一.P418 unique_ptr和release 二.P426 智能指针与动态数组 (一).unique_ptr (二).shared_ptr 三.P428 allocator (一).申请空间 (二).初始化构造 (三&#…

活动星投票少儿模特大赛网络评选制作一次图文分组投票怎么制作

关于微信投票,我们现在用的最多的就是小程序投票,今天的网络投票,在这里会教大家如何用“活动星投票”小程序来进行投票。我们现在要以“国际车展少儿模特大赛”为主题进行一次投票活动,我们可以在在微信小程序搜索,“…

aws cloudformation 使用模板配置 ecs 蓝绿部署

参考资料 Perform ECS blue/green deployments through CodeDeploy using AWS CloudFormationAWS::CodeDeployBlueGreen 在之前的文章中,使用codepipeline中通过控制台的方式创建了ecs蓝绿部署的demo。实际上可以单独通过codedeploy完成ecs服务的蓝绿部署 参考官…

【ARMv8 SIMD和浮点指令编程】Libyuv I420 转 ARGB 流程分析

Libyuv 可以说是做图形图像相关从业者绕不开的一个常用库,它使用了单指令多数据流提升性能。以 ARM 处理为主线,通过 I420 转 ARGB 流程来分析它是如何流转的。 Libyuv 是一个开源项目,包括 YUV 的缩放和转换功能。 使用邻近、双线性或 box…

QThread、moveToThread用法详述

1.吐槽 QThread类提供了一种平台无关的方法对线程进行管理。但对于QThread类的熟练使用,即使是从事Qt开发多年的程序猿们,往往也会踩雷、入坑。总之:QThread类不好用、如果对该类理解不透,很容易导致程序崩溃。本人强烈建议&#…

(函数介绍)puts()函数

功能介绍 1. puts()函数用来向标准输出设备屏幕输出字符串并换行。 2. 函数的参数就是一个起始的地址,然后就从这个地址开始一直输出字符串,直到碰到\0就停止,然后这个\0是不进行输出的,是不能够算在里面的。与此同时&#xff…

十、字节缓冲流、字符流、转换流、对象操作流、对象序列化流

字节缓冲流 构造方法 字节缓冲流介绍 BufferedOutputStream:该类实现缓冲输出流.通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用BufferedInputStream:创建BufferedInputStream将创建一个内部缓冲区数…

2022年为什么要学习C语言?

为什么学习c语言 为什么学C语言逻辑? 为什么要学习C语言? 学习C语言的主要理由有以下几点: C语言可以作为学习计算机程序设计语言的入门语言; C语言是编写操作系统的首选语言,与计算机硬件打交道时灵巧且高效&…

labelImag安装与使用及构造数据集

在做目标检测任务时,需要进行标注,选择了LabelImg作为标注工具,下面是安装及使用过程。 我们使用Anconda的虚拟环境进行安装,激活环境后,执行: pip install labelimg -i https://pypi.tuna.tsinghua.edu.c…