diff --git a/docs/custom-material.md b/docs/custom-material.md index 625a8b7ed..a440d5e81 100644 --- a/docs/custom-material.md +++ b/docs/custom-material.md @@ -226,12 +226,18 @@ For more options about the rendering state, please refer to the corresponding [A ## Rendering queue -So far, the custom material has been very perfect, but maybe we need to do some processing on the rendering order of the objects. For example, the transparent objects is generally rendered behind the opaque queue. Therefore, the engine provides [RenderQueueType](${api}core/RenderQueueType), the rendering queue of the material can determine the rendering order of this material in the current scene, and the bottom layer of the engine will perform some special processing on the rendering queue of different ranges, such as [RenderQueueType.Transparent](${api}core/RenderQueueType#transparent) will render **from far to near**. It is worth noting that the value of the render queue can be an enumerated value plus any custom number. +So far, the custom material has been very perfect, but maybe we need to do some processing on the rendering order of the objects. For example, the transparent objects is generally rendered behind the opaque queue. Therefore, the engine provides [RenderQueueType](${api}core/RenderQueueType), the rendering queue of the material can determine the rendering order of this material in the current scene, and the bottom layer of the engine will perform some special processing on the rendering queue of different ranges, such as [RenderQueueType.Transparent](${api}core/RenderQueueType#transparent) will render **from far to near**. i.e. ```typescript -material.renderQueueType = RenderQueueType.Opaque + 1; +material.renderQueueType = RenderQueueType.Opaque; +``` + +For the same rendering queue, we can also set the `priority` property of [Renderer](${api}core/Renderer) to force the rendering order, the default is 0, the higher the number, the later rendering, such as: + +```typescript +renderer.priority = -1; // render first ``` ## Package custom material diff --git a/docs/custom-material.zh-CN.md b/docs/custom-material.zh-CN.md index 3844e41db..2f680ee7a 100644 --- a/docs/custom-material.zh-CN.md +++ b/docs/custom-material.zh-CN.md @@ -222,9 +222,15 @@ material.renderQueueType = RenderQueueType.Transparent; ## 渲染队列 -至此,自定义材质已经非常完善了,但是也许我们还需要对物体的渲染顺序做一些处理,比如透明物体的渲染一般都是放在非透明队列后面的,因此,引擎提供了 [渲染队列(RenderQueueType)](${api}core/RenderQueueType) ,我们设置材质的渲染队列,可以决定这个材质在当前场景中的渲染顺序,引擎底层会对不同范围的渲染队列进行一些特殊处理,如 [RenderQueueType.Transparent](${api}core/RenderQueueType#transparent) 会从远到近进行渲染。值得注意的是渲染队列的值可以是枚举值加上任何自定义数字。 +至此,自定义材质已经非常完善了,但是也许我们还需要对物体的渲染顺序做一些处理,比如透明物体的渲染一般都是放在非透明队列后面的,因此,引擎提供了 [渲染队列(RenderQueueType)](${api}core/RenderQueueType) ,我们设置材质的渲染队列,可以决定这个材质在当前场景中的渲染顺序,引擎底层会对不同范围的渲染队列进行一些特殊处理,如 [RenderQueueType.Transparent](${api}core/RenderQueueType#transparent) 会从远到近进行渲染。 + +```typescript +material.renderQueueType = RenderQueueType.Opaque; +``` + +针对相同的渲染队列,我们还可以设置 [Renderer](${api}core/Renderer) 的 `priority` 属性来强制决定渲染顺序,默认为0,数字越大越后面渲染,如: ```typescript -material.renderQueueType = RenderQueueType.Opaque + 1; +renderer.priority = -1; // 优先渲染 ``` diff --git a/docs/gltf.md b/docs/gltf.md index eeda6f594..dc5aae29a 100644 --- a/docs/gltf.md +++ b/docs/gltf.md @@ -2,12 +2,15 @@ order: 3 title: glTF type: Resource - --- ## What is glTF? -As [glTF Official Website](https://www.khronos.org/gltf/) described, **glTF**(GL Transmission Format)It is a specification that can efficiently transmit and load 3D scenes in [khronos ](https://www.khronos.org/), which is a "JPEG" format in the 3D field, which features traditional models such as FBX, OBJ. Format, basically support all features in 3D scenes,Its [Plug-in mechanism](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos) also enables users to flexibly customize the desired features. glTF is currently the preferred 3D scene transmission format recommended by Oasis. Oasis has made good support for the core functions and plugins of glTF. +As [glTF Official Website](https://www.khronos.org/gltf/) described, **glTF**(GL Transmission Format)It is a specification that can efficiently transmit and load 3D scenes in [khronos ](https://www.khronos.org/), which is a "JPEG" format in the 3D field, which features traditional models such as FBX, OBJ. Format, basically support all features in 3D scenes,Its [Plug-in mechanism](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos) also enables users to flexibly customize the desired features. + +The products of glTF are generally divided into (.gltf + .bin + png) or (.glb), the former is suitable for scenes with large pictures, so the pictures and models are separated, and models and textures can be loaded asynchronously; the latter is suitable for models For scenarios with large files, all data will be stored in binary, and the model needs to be parsed after all data is parsed. + +glTF is currently the preferred 3D scene transmission format recommended by Oasis. Oasis has made good support for the core functions and plugins of glTF. diff --git a/docs/gltf.zh-CN.md b/docs/gltf.zh-CN.md index f1df4add4..2e39383f3 100644 --- a/docs/gltf.zh-CN.md +++ b/docs/gltf.zh-CN.md @@ -8,6 +8,8 @@ type: 资源 正如 [glTF 官网](https://www.khronos.org/gltf/) 所介绍,**glTF**(GL Transmission Format)是 [khronos ](https://www.khronos.org/)发布的一种能高效传输和加载 3D 场景的规范,是 3D 领域中的 "JPEG" 格式,其功能涵盖了 FBX、OBJ 等传统模型格式,基本支持 3D 场景中的所有特性,其[插件机制](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos)也使用户可以灵活地自定义实现想要的功能。 +glTF 的产物一般分为(.gltf + .bin + png)或者 (.glb),前者适合图片体积大的场景,所以将图片和模型拆分开来,可以异步加载模型和纹理;后者适合模型文件较大的场景,会将所有数据进行二进制保存,需要等所有数据解析完毕才能展示模型。 + glTF 是目前 Oasis 推荐的首选 3D 场景传输格式,Oasis 对 glTF 的核心功能和插件都做了很好的支持。 diff --git a/docs/model.md b/docs/model.md index b686aacc7..031decf8e 100644 --- a/docs/model.md +++ b/docs/model.md @@ -7,6 +7,8 @@ group: Basic glTF (GL Transmission Format) is a specification released by [khronos](https://www.khronos.org/) that can efficiently transmit and load 3D scenes. Like traditional model formats such as FBX and OBJ, it basically supports 3D scenes. All the features in Oasis are currently the preferred 3D file format recommended by Oasis. +The products of glTF are generally divided into (.gltf + .bin + png) or (.glb), the former is suitable for scenes with large pictures, so the pictures and models are separated, and models and textures can be loaded asynchronously; the latter is suitable for models For scenarios with large files, all data will be stored in binary, and the model needs to be parsed after all data is parsed. + ## Basic usage To load a 3D model, just call the [load](${api}core/ResourceManager/#load) method of the engine [ResourceManager](${docs}resource-manager) instance, as follows: diff --git a/docs/model.zh-CN.md b/docs/model.zh-CN.md index 04da47e70..a42fd8e40 100644 --- a/docs/model.zh-CN.md +++ b/docs/model.zh-CN.md @@ -7,6 +7,8 @@ group: 基础 glTF(GL Transmission Format)是 [khronos](https://www.khronos.org/) 发布的一种能高效传输和加载 3D 场景的规范,与 FBX、OBJ 等传统模型格式一样,基本支持 3D 场景中的所有特性,也是目前 Oasis 推荐的首选 3D 文件格式。 +glTF 的产物一般分为(.gltf + .bin + png)或者 (.glb),前者适合图片体积大的场景,所以将图片和模型拆分开来,可以异步加载模型和纹理;后者适合模型文件较大的场景,会将所有数据进行二进制保存,需要等所有数据解析完毕才能展示模型。 + ## 基本使用 加载一个 3D 模型只要调用引擎 [ResourceManager](${docs}resource-manager-cn) 实例的 [load](${api}core/ResourceManager/#load) 方法即可,如下: diff --git a/docs/texture-compression.md b/docs/texture-compression.md index 12beb3e06..280d09a43 100644 --- a/docs/texture-compression.md +++ b/docs/texture-compression.md @@ -5,24 +5,16 @@ type: Graphics group: Texture --- -Oasis supports compressed textures in **DXT/PVR/ETC/ASTC** format, and supports the use of **KTX**([Khronos Texture](https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/)) container format loading. +Oasis supports compressed textures in **DXT/PVR/ETC/ASTC** format, and supports the use of **KTX**([Khronos Texture](https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/)) container format loading. ## How to use Because each hardware supports different compression formats, please check whether a certain format is supported before use: ```typescript -const engine = new Engine(); -const cameraEntity = rootEntity.createChild("camera"); -cameraEntity.addComponent(Camera); -const rhi = engine.renderhardware; - -// GLCapabilityType.s3tc -// GLCapabilityType.etc1 -// GLCapabilityType.etc -// GLCapabilityType.astc -// GLCapabilityType.pvrtc -if (rhi.canIUse(GLCapabilityType.s3tc)) { +const rhi = engine._hardwareRenderer as WebGLRenderer; + +if (rhi.canIUse(GLCompressedTextureInternalFormat.RGBA_S3TC_DXT5_EXT)) { // ... } ``` @@ -30,18 +22,20 @@ if (rhi.canIUse(GLCapabilityType.s3tc)) { After confirming that a certain format is supported, use [ResourceManager](${docs}resource-manager) to load resources: ```typescript -const resource = { - type: AssetType.KTX, - url: "https://gw.alipayobjects.com/os/bmw-prod/b38cb09e-154c-430e-98c8-81dc19d4fb8e.ktx" -}; - -engine.resourceManager.load(resource).then((res) => { - const compressedTexture = res; - material.baseTexture = compressedTexture; - // ... -}); +engine.resourceManager + .load({ + type: AssetType.KTX, + url: "https://gw.alipayobjects.com/os/bmw-prod/b38cb09e-154c-430e-98c8-81dc19d4fb8e.ktx" + }) + .then((res) => { + const compressedTexture = res; + material.baseTexture = compressedTexture; + // ... + }); ``` + + ## Compatibility In order to ensure the compatibility of your settings, you can refer to the following steps: @@ -49,5 +43,3 @@ In order to ensure the compatibility of your settings, you can refer to the foll 1. Check the website through [canIUse](https://caniuse.com/) 、 [webglStats](https://webglstats.com/)、[webglReport](https://webglreport.com/?v=2) and other capabilities to know the compatibility differences of different devices. 2. Through the [RHI#canIUse](${api}rhi-webgl/WebGLRenderer#canIUse) interface provided by the engine, check whether the capability can be used. 3. Project downgrades and forced downgrades are carried out through engineering means. - - diff --git a/docs/texture-compression.zh-CN.md b/docs/texture-compression.zh-CN.md index 67eb56800..333ad0e14 100644 --- a/docs/texture-compression.zh-CN.md +++ b/docs/texture-compression.zh-CN.md @@ -5,23 +5,16 @@ type: 图形 group: 纹理 --- -Oasis 支持 **DXT/PVR/ETC/ASTC** 格式的压缩纹理,并且支持通过 **KTX**([Khronos Texture](https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/))容器格式加载。 +Oasis 支持 **DXT/PVR/ETC/ASTC** 格式的压缩纹理,并且支持通过 [KTX1.0](https://registry.khronos.org/KTX/specs/1.0/ktxspec_v1.html) 容器格式加载。 ## 使用 + 因为各个硬件支持的压缩格式不一样,所以在使用前请先查询是否支持某种格式: ```typescript -const engine = new Engine(); -const cameraEntity = rootEntity.createChild("camera"); -cameraEntity.addComponent(Camera); -const rhi = engine.renderhardware; - -// GLCapabilityType.s3tc -// GLCapabilityType.etc1 -// GLCapabilityType.etc -// GLCapabilityType.astc -// GLCapabilityType.pvrtc -if (rhi.canIUse(GLCapabilityType.s3tc)) { +const rhi = engine._hardwareRenderer as WebGLRenderer; + +if (rhi.canIUse(GLCompressedTextureInternalFormat.RGBA_S3TC_DXT5_EXT)) { // ... } ``` @@ -29,18 +22,20 @@ if (rhi.canIUse(GLCapabilityType.s3tc)) { 确定支持某种格式后,使用 [ResourceManager](${docs}resource-manager-cn) 进行资源加载 ```typescript -const resource = { - type: AssetType.KTX, - url: "https://gw.alipayobjects.com/os/bmw-prod/b38cb09e-154c-430e-98c8-81dc19d4fb8e.ktx" -}; - -engine.resourceManager.load(resource).then((res) => { - const compressedTexture = res; - material.baseTexture = compressedTexture; - // ... -}); +engine.resourceManager + .load({ + type: AssetType.KTX, + url: "https://gw.alipayobjects.com/os/bmw-prod/b38cb09e-154c-430e-98c8-81dc19d4fb8e.ktx" + }) + .then((res) => { + const compressedTexture = res; + material.baseTexture = compressedTexture; + // ... + }); ``` + + ## 机型适配 引擎不能保证压缩纹理在所有设备上都能支持,为了保证兼容性,建议尝试以下步骤: @@ -48,5 +43,3 @@ engine.resourceManager.load(resource).then((res) => { 1. 通过 [canIUse](https://caniuse.com/) 、 [webglStats](https://webglstats.com/)、[webglReport](https://webglreport.com/?v=2) 等能力检测网站,知晓不同设备的兼容性差异。 2. 通过引擎提供的 RHI#canIUse 接口,检测能力是否可以使用。 3. 通过工程手段进行方案降级和强制降级。 - - diff --git a/docs/texture.md b/docs/texture.md index a70e9f4ea..643812b74 100644 --- a/docs/texture.md +++ b/docs/texture.md @@ -16,6 +16,13 @@ It is worth noting that pictures, Canvas, raw data, videos, etc. can be used as | [2D Texture](${docs}texture-2d) | The most commonly used art resource, which uses two-dimensional UV coordinates for sampling | | [Cube Texture](${docs}texture-cube) | A cube texture is composed of 6 2D textures | | 2D Texture Arrays | Occupies only one texture unit, which is very suitable for the need to switch texture atlases | + +## Texture coordinates +We need to use texture coordinates to sample textures in the fragment shader, which we generally call UV coordinates. The center of the picture can be sampled using (0.5, 0.5): +``` +vec4 color = texture2D(u_texture, vec2(0.5, 0.5)); +``` + ## General properties After uploading the texture, we need to understand some basic properties of the texture: @@ -73,7 +80,7 @@ texture.filterMode = TextureFilterMode.Bilinear; ### 3. Anisotropic level -Anisotropic filtering technology can make the texture clearer when viewed at an oblique angle. As shown in the figure below, the end of the texture will become clearer as the anisotropic filtering level increases. +Anisotropic filtering technology can make the texture clearer when viewed at an oblique angle. As shown in the figure below, the end of the texture will become clearer as the anisotropic filtering level increases. but please use it carefully, the larger the value, the greater the amount of GPU computation. ![image.png](https://gw.alipayobjects.com/mdn/rms_d27172/afts/img/A*oqkqSJMAe7cAAAAAAAAAAAAAARQnAQ) @@ -121,4 +128,11 @@ texture.setImageSource(img, 0, true); // 3th parameters ```typescript const texture = new Texture2D(engine, width, height); texture.setImageSource(img, 0, undefined, true); // 4th parameters +``` + +## Texture format +The engine uses `TextureFormat.R8G8B8A8` as the texture format by default, that is, the red, blue, green and transparent channels each use 1 byte, and each channel is allowed to save the color value of the size of [0~255]. The engine supports configuring different texture formats. For details, please refer to [TextureFormat](${api}core/TextureFormat). For example, we don't need to use the transparent channel, that is, the A channel, then we can use `TextureFormat.R8G8B8`: + +```typescript +const texture = new Texture2D(engine, width, height, TextureFormat.R8G8B8); ``` \ No newline at end of file diff --git a/docs/texture.zh-CN.md b/docs/texture.zh-CN.md index b04bc2388..b895ef379 100644 --- a/docs/texture.zh-CN.md +++ b/docs/texture.zh-CN.md @@ -16,6 +16,13 @@ group: 纹理 | [立方纹理](${docs}texture-cube-cn) | 6 张 2D 纹理组成了一个立方纹理,可以用来实现天空盒、环境反射等特效 | | 2D 纹理数组| 只占用一个纹理单元,非常适合用来实现需要切换纹理图集的需求 | + +## 纹理坐标 +我们在片元着色器中采样纹理需要用到纹理坐标,我们一般称之 UV坐标,纹理坐标的(0,0)位于图片的左下角,(1,1)对应于图片的右上角,比如我们可以使用 (0.5,0.5)对图片的中心进行采样: +``` +vec4 color = texture2D(u_texture, vec2(0.5, 0.5)); +``` + ## 通用属性 > 虽然纹理类型多样,但他们都有一些相似的基本属性与设置: @@ -73,7 +80,7 @@ texture.filterMode = TextureFilterMode.Bilinear; ### 3. 各向异性过滤等级 -各向异性过滤技术可以使纹理在倾斜角度下观看会更加清晰。如下图,纹理的尽头随着各向异性过滤等级的增加会愈加清晰。 +各向异性过滤技术可以使纹理在倾斜角度下观看会更加清晰。如下图,纹理的尽头随着各向异性过滤等级的增加会愈加清晰。但请慎重使用,数值越大,GPU的计算量就会越大。 ![image.png](https://gw.alipayobjects.com/mdn/rms_d27172/afts/img/A*oqkqSJMAe7cAAAAAAAAAAAAAARQnAQ) @@ -128,3 +135,10 @@ premultiplyAlpha 用来控制纹理是否预乘 alpha(透明) 通道,**引擎 const texture = new Texture2D(engine, width, height); texture.setImageSource(img, 0, undefined, true); // 第 4 个参数 ``` + +## 纹理格式 +引擎默认使用 `TextureFormat.R8G8B8A8` 作为纹理格式, 即红蓝绿、透明通道分别使用1个字节,每个通道允许保存 【0~255】 大小的颜色值。引擎支持配置不同的纹理格式,具体可以参考 [TextureFormat](${api}core/TextureFormat)。比如我们不需要使用透明通道,即 A 通道,那么我们可以使用 `TextureFormat.R8G8B8`: + +```typescript +const texture = new Texture2D(engine, width, height, TextureFormat.R8G8B8); +``` \ No newline at end of file diff --git a/playground/compressed-texture.ts b/playground/compressed-texture.ts new file mode 100644 index 000000000..2c8eef8df --- /dev/null +++ b/playground/compressed-texture.ts @@ -0,0 +1,119 @@ +/** + * @title Compressed Texture + * @category Texture + */ +import * as dat from "dat.gui"; +import { + AssetType, + BackgroundMode, + Camera, + DirectLight, + GLCompressedTextureInternalFormat, + Logger, + MeshRenderer, + PrimitiveMesh, + SkyBoxMaterial, + Texture2D, + UnlitMaterial, + Vector3, + WebGLEngine, + WebGLRenderer +} from "oasis-engine"; +import { OrbitControl } from "oasis-engine-toolkit"; +Logger.enable(); +const engine = new WebGLEngine("canvas"); +engine.canvas.resizeByClientSize(); + +const scene = engine.sceneManager.activeScene; +const rootEntity = scene.createRootEntity(); + +// Create camera +const cameraNode = rootEntity.createChild("camera_node"); +cameraNode.transform.position = new Vector3(0, 0, 3); +cameraNode.addComponent(Camera); +cameraNode.addComponent(OrbitControl); + +// Create sky +const sky = scene.background.sky; +const skyMaterial = new SkyBoxMaterial(engine); +scene.background.mode = BackgroundMode.Sky; +sky.material = skyMaterial; +sky.mesh = PrimitiveMesh.createCuboid(engine, 1, 1, 1); + +const lightEntity = rootEntity.createChild(); +lightEntity.addComponent(DirectLight).intensity = 0.5; +lightEntity.transform.setPosition(-5, 5, 5); +lightEntity.transform.lookAt(new Vector3(0, 0, 0)); + +// material ball +const ball = rootEntity.createChild("ball"); +const ballRender = ball.addComponent(MeshRenderer); +const material = new UnlitMaterial(engine); +ball.transform.setRotation(90, 0, 0); +ballRender.mesh = PrimitiveMesh.createPlane(engine, 1, 1); +ballRender.setMaterial(material); + +// debug +const gui = new dat.GUI(); + +const fileList = { + [GLCompressedTextureInternalFormat.RGB_S3TC_DXT1_EXT]: + "https://gw.alipayobjects.com/os/bmw-prod/b38cb09e-154c-430e-98c8-81dc19d4fb8e.ktx", + [GLCompressedTextureInternalFormat.RGBA_S3TC_DXT5_EXT]: + "https://gw.alipayobjects.com/os/bmw-prod/269eae01-13d9-43fc-80a5-cc5a784eae7a.ktx", + [GLCompressedTextureInternalFormat.RGB_ETC1_WEBGL]: + "https://gw.alipayobjects.com/os/bmw-prod/a704b7a6-b9b1-48ed-a215-04745a90b003.ktx", + [GLCompressedTextureInternalFormat.RGB8_ETC2]: + "https://gw.alipayobjects.com/os/bmw-prod/e03d0d5f-be29-412c-b412-2d8e583b7a5a.ktx", + [GLCompressedTextureInternalFormat.RGBA8_ETC2_EAC]: + "https://gw.alipayobjects.com/os/bmw-prod/24406406-bfa4-4e08-b5da-b26056fdea62.ktx", + [GLCompressedTextureInternalFormat.RGBA_ASTC_4X4_KHR]: + "https://gw.alipayobjects.com/os/bmw-prod/3fb9b745-e02b-425b-98e5-df6a0a058b47.ktx", + [GLCompressedTextureInternalFormat.RGBA_ASTC_12X12_KHR]: + "https://gw.alipayobjects.com/os/bmw-prod/6465388f-81b4-45d1-86a4-731344af220b.ktx", + [GLCompressedTextureInternalFormat.RGB_PVRTC_2BPPV1_IMG]: + "https://gw.alipayobjects.com/os/bmw-prod/c8883997-3616-4811-a9bf-4d4c07015fb7.ktx", + [GLCompressedTextureInternalFormat.RGB_PVRTC_4BPPV1_IMG]: + "https://gw.alipayobjects.com/os/bmw-prod/3de8467b-f626-48e3-8dd4-8cb4e7acbe4f.ktx", + [GLCompressedTextureInternalFormat.RGBA_PVRTC_2BPPV1_IMG]: + "https://gw.alipayobjects.com/os/bmw-prod/7955549e-ee62-4982-a810-d118e2fce6dd.ktx", + [GLCompressedTextureInternalFormat.RGBA_PVRTC_4BPPV1_IMG]: + "https://gw.alipayobjects.com/os/bmw-prod/dc02693a-f416-4b2e-bf7b-9553c4038ce8.ktx" +}; + +const rhi = engine._hardwareRenderer as WebGLRenderer; +const formats = []; +const debugInfo = { + format: "" +}; +for (let format in fileList) { + const can = rhi.canIUseCompressedTextureInternalFormat(format as any); + const formatDes = `${GLCompressedTextureInternalFormat[format]} ${can}`; + formats.push(formatDes); + if (can && !debugInfo.format) { + debugInfo.format = formatDes; + } +} + +function loadTexture(formatDes: string) { + const format = formatDes.split(" ")[0]; + const url = fileList[GLCompressedTextureInternalFormat[format]]; + engine.resourceManager + .load({ + type: AssetType.KTX, + url + }) + .then((res) => { + const compressedTexture = res; + material.baseTexture = compressedTexture; + }); +} + +if (debugInfo.format) { + loadTexture(debugInfo.format); +} +gui.add(debugInfo, "format", formats).onChange((v) => { + loadTexture(v); +}); + +engine.run();