;
};
-const webglcanvas = document.createElement("canvas");
-webglcanvas.id = "glcanvas";
-webglcanvas.style.position = "fixed";
-webglcanvas.style.left = "0px";
-webglcanvas.style.top = "0px";
-webglcanvas.style.width = "100%";
-webglcanvas.style.height = "100%";
-document.body.appendChild(webglcanvas);
+const canvas = document.createElement("canvas");
+canvas.id = "glcanvas";
+canvas.width = window.innerWidth;
+canvas.height = window.innerHeight;
+document.body.appendChild(canvas);
const webgl = new WebGL({ canvasId: "glcanvas" });
-const renderObject: IGLRenderObject = {
- vertexArray: {
- vertices: {
- position: {
- buffer: {
- target: "ARRAY_BUFFER",
- data: new Float32Array([
- -1, 0,
- 0, -1,
- 1, 1
- ])
- }, numComponents: 2
- },
- }
+const renderObject: IRenderObject = {
+ vertices: {
+ position: {
+ data: new Float32Array([
+ -1, 0,
+ 0, -1,
+ 1, 1
+ ]),
+ format: "float32x2",
+ },
},
uniforms: { color: [1, 0, 0, 1] },
pipeline: {
@@ -53,17 +47,25 @@ const renderObject: IGLRenderObject = {
`,
targets: [{ blend: {} }],
},
- depthStencil: { depth: { depthtest: true } },
- }
+ depthStencil: {},
+ },
+ drawVertex: { vertexCount: 3 },
};
function draw()
{
- webglcanvas.width = webglcanvas.clientWidth;
- webglcanvas.height = webglcanvas.clientHeight;
+ canvas.width = canvas.clientWidth;
+ canvas.height = canvas.clientHeight;
- webgl.runRenderPass({
- renderObjects: [renderObject]
+ webgl.submit({
+ commandEncoders: [{
+ passEncoders: [
+ {
+ descriptor: { colorAttachments: [{ clearValue: [0, 0, 0, 1] }], depthStencilAttachment: { depthClearValue: 1 } },
+ renderObjects: [renderObject]
+ }
+ ]
+ }]
});
requestAnimationFrame(draw);
diff --git a/examples/src/regl-examples/batch.ts b/examples/src/regl-examples/batch.ts
index 61ea0aa2e225bf738d2e4d0ff3f0b9da9845071a..aa974ad8aacd6154dedd252a3cc0e73c1bdb5d6c 100644
--- a/examples/src/regl-examples/batch.ts
+++ b/examples/src/regl-examples/batch.ts
@@ -1,13 +1,11 @@
-import { IGLRenderObject, IGLRenderPipeline, IGLVertexArrayObject, WebGL } from "@feng3d/webgl";
+import { IRenderObject, IRenderPipeline, ISubmit, IVertexAttributes } from "@feng3d/render-api";
+import { WebGL } from "@feng3d/webgl";
-const webglcanvas = document.createElement("canvas");
-webglcanvas.id = "glcanvas";
-webglcanvas.style.position = "fixed";
-webglcanvas.style.left = "0px";
-webglcanvas.style.top = "0px";
-webglcanvas.style.width = "100%";
-webglcanvas.style.height = "100%";
-document.body.appendChild(webglcanvas);
+const canvas = document.createElement("canvas");
+canvas.id = "glcanvas";
+canvas.width = window.innerWidth;
+canvas.height = window.innerHeight;
+document.body.appendChild(canvas);
const webgl = new WebGL({ canvasId: "glcanvas" });
@@ -23,7 +21,7 @@ const offsets = [{ offset: [-1, -1] },
{ offset: [1, 0] },
{ offset: [1, 1] }];
-const pipeline: IGLRenderPipeline = {
+const pipeline: IRenderPipeline = {
vertex: {
code: `precision mediump float;
attribute vec2 position;
@@ -40,57 +38,74 @@ const pipeline: IGLRenderPipeline = {
void main() {
gl_FragColor = color;
}` },
- depthStencil: { depth: { depthtest: true } },
+ depthStencil: { depthWriteEnabled: false },
};
-const vertexArray: IGLVertexArrayObject = {
+const vertexArray: { vertices?: IVertexAttributes } = {
vertices: {
position: {
- buffer: {
- target: "ARRAY_BUFFER",
- data: new Float32Array([
- 0.5, 0,
- 0, 0.5,
- 1, 1
- ])
- }, numComponents: 2
+ data: new Float32Array([
+ 0.5, 0,
+ 0, 0.5,
+ 1, 1
+ ]),
+ format: "float32x2",
},
}
};
-function getRenderObject(tick: number, batchId: number)
+function getRenderObject(batchId: number)
{
- const renderObject: IGLRenderObject = {
- vertexArray,
+ const renderObject: IRenderObject = {
+ vertices: vertexArray.vertices,
uniforms: {
- color: () => [
- Math.sin(0.02 * ((0.1 + Math.sin(batchId)) * tick + 3.0 * batchId)),
- Math.cos(0.02 * (0.02 * tick + 0.1 * batchId)),
- Math.sin(0.02 * ((0.3 + Math.cos(2.0 * batchId)) * tick + 0.8 * batchId)),
- 1],
- angle: () => 0.01 * tick,
- offset: () => offsets[batchId].offset,
+ offset: offsets[batchId].offset,
},
pipeline,
+ drawVertex: { vertexCount: 3 }
};
return renderObject;
}
+const renderObjects: IRenderObject[] = [];
+for (let i = 0; i < offsets.length; i++)
+{
+ renderObjects.push(getRenderObject(i));
+}
+
+const submit: ISubmit = {
+ commandEncoders: [{
+ passEncoders: [
+ {
+ descriptor: { colorAttachments: [{ clearValue: [0, 0, 0, 1] }] },
+ renderObjects
+ }
+ ]
+ }]
+};
+
function draw()
{
- webglcanvas.width = webglcanvas.clientWidth;
- webglcanvas.height = webglcanvas.clientHeight;
+ canvas.width = canvas.clientWidth;
+ canvas.height = canvas.clientHeight;
tick++;
- const renderObjects: IGLRenderObject[] = [];
+
for (let i = 0; i < offsets.length; i++)
{
batchId = i;
- renderObjects.push(getRenderObject(tick, batchId));
+ //
+ const ro = renderObjects[i];
+ ro.uniforms.color = [
+ Math.sin(0.02 * ((0.1 + Math.sin(batchId)) * tick + 3.0 * batchId)),
+ Math.cos(0.02 * (0.02 * tick + 0.1 * batchId)),
+ Math.sin(0.02 * ((0.3 + Math.cos(2.0 * batchId)) * tick + 0.8 * batchId)),
+ 1];
+ ro.uniforms.angle = 0.01 * tick;
}
- webgl.runRenderPass({ renderObjects });
+ webgl.submit(submit);
requestAnimationFrame(draw);
}
diff --git a/examples/src/regl-examples/blur.html b/examples/src/regl-examples/blur.html
deleted file mode 100644
index a02dea9e56b297c5aeb5b7197046e47e14d5ff21..0000000000000000000000000000000000000000
--- a/examples/src/regl-examples/blur.html
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
- feng3d examples
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/examples/src/regl-examples/blur.ts b/examples/src/regl-examples/blur.ts
deleted file mode 100644
index f4c048de3540e797938d333748c6caa9113599ea..0000000000000000000000000000000000000000
--- a/examples/src/regl-examples/blur.ts
+++ /dev/null
@@ -1,106 +0,0 @@
-import { IGLRenderObject, IGLRenderPipeline, IGLVertexArrayObject, WebGL } from "@feng3d/webgl";
-
-import { fit } from "./hughsk/canvas-fit";
-import { attachCamera } from "./hughsk/canvas-orbit-camera";
-
-const canvas = document.body.appendChild(document.createElement("canvas"));
-canvas.id = "glcanvas";
-window.addEventListener("resize", fit(canvas), false);
-
-const webgl = new WebGL({ canvasId: "glcanvas" });
-
-const camera = attachCamera(canvas);
-
-// increase and decrease the blur amount by modifying this value.
-const FILTER_RADIUS = 1;
-
-// configure intial camera view.
-camera.rotate([0.0, 0.0], [0.0, -0.4]);
-camera.zoom(300.0);
-
-let batchId = 0;
-let tick = 0;
-const offsets = [{ offset: [-1, -1] },
-{ offset: [-1, 0] },
-{ offset: [-1, 1] },
-{ offset: [0, -1] },
-{ offset: [0, 0] },
-{ offset: [0, 1] },
-{ offset: [1, -1] },
-{ offset: [1, 0] },
-{ offset: [1, 1] }];
-
-const vertexArray: IGLVertexArrayObject = {
- vertices: {
- position: {
- buffer: {
- target: "ARRAY_BUFFER",
- data: new Float32Array([
- 0.5, 0,
- 0, 0.5,
- 1, 1
- ])
- }, numComponents: 2
- },
- }
-};
-
-const pipeline: IGLRenderPipeline = {
- vertex: {
- code: `precision mediump float;
- attribute vec2 position;
- uniform float angle;
- uniform vec2 offset;
- void main() {
- gl_Position = vec4(
- cos(angle) * position.x + sin(angle) * position.y + offset.x,
- -sin(angle) * position.x + cos(angle) * position.y + offset.y, 0, 1);
- }` },
- fragment: {
- code: `precision mediump float;
- uniform vec4 color;
- void main() {
- gl_FragColor = color;
- }`,
- targets: [{ blend: {} }],
- },
- depthStencil: { depth: { depthtest: true } },
-};
-
-function getRenderObject(tick: number, batchId: number)
-{
- const renderObject: IGLRenderObject = {
- vertexArray,
- uniforms: {
- color: () => [
- Math.sin(0.02 * ((0.1 + Math.sin(batchId)) * tick + 3.0 * batchId)),
- Math.cos(0.02 * (0.02 * tick + 0.1 * batchId)),
- Math.sin(0.02 * ((0.3 + Math.cos(2.0 * batchId)) * tick + 0.8 * batchId)),
- 1],
- angle: () => 0.01 * tick,
- offset: () => offsets[batchId].offset,
- },
- pipeline,
- };
-
- return renderObject;
-}
-
-function draw()
-{
- canvas.width = canvas.clientWidth;
- canvas.height = canvas.clientHeight;
-
- tick++;
- const renderObjects: IGLRenderObject[] = [];
- for (let i = 0; i < offsets.length; i++)
- {
- batchId = i;
- renderObjects.push(getRenderObject(tick, batchId));
- }
-
- webgl.runRenderPass({ renderObjects });
-
- requestAnimationFrame(draw);
-}
-draw();
diff --git a/examples/src/regl-examples/bunny.ts b/examples/src/regl-examples/bunny.ts
index f0474ce34328ce69fb392b26854d9f62ac07cb67..2fb76c82a77c9bc660c67b6a044b2074cf6037f0 100644
--- a/examples/src/regl-examples/bunny.ts
+++ b/examples/src/regl-examples/bunny.ts
@@ -1,16 +1,14 @@
-import { IGLRenderObject, WebGL } from "@feng3d/webgl";
+import { IRenderObject, ISubmit } from "@feng3d/render-api";
+import { WebGL } from "@feng3d/webgl";
import * as bunny from "./mikolalysenko/bunny";
import * as mat4 from "./stackgl/gl-mat4";
-const webglcanvas = document.createElement("canvas");
-webglcanvas.id = "glcanvas";
-webglcanvas.style.position = "fixed";
-webglcanvas.style.left = "0px";
-webglcanvas.style.top = "0px";
-webglcanvas.style.width = "100%";
-webglcanvas.style.height = "100%";
-document.body.appendChild(webglcanvas);
+const canvas = document.createElement("canvas");
+canvas.id = "glcanvas";
+canvas.width = window.innerWidth;
+canvas.height = window.innerHeight;
+document.body.appendChild(canvas);
const webgl = new WebGL({ canvasId: "glcanvas", antialias: true });
@@ -29,33 +27,17 @@ const indices = bunny.cells.reduce((pv: number[], cv: number[]) =>
}, []);
let tick = 0;
-let viewportWidth = webglcanvas.clientWidth;
-let viewportHeight = webglcanvas.clientHeight;
+let viewportWidth = canvas.clientWidth;
+let viewportHeight = canvas.clientHeight;
-const renderObject: IGLRenderObject = {
- vertexArray: {
- vertices: {
- position: { buffer: { target: "ARRAY_BUFFER", data: new Float32Array(positions) }, numComponents: 3 },
- },
- index: { target: "ELEMENT_ARRAY_BUFFER", data: new Uint16Array(indices) }
+const renderObject: IRenderObject = {
+ vertices: {
+ position: { data: new Float32Array(positions), format: "float32x3" },
},
+ indices: new Uint16Array(indices),
+ drawIndexed: { indexCount: indices.length },
uniforms: {
model: mat4.identity([]),
- view: () =>
- {
- const t = 0.01 * tick;
-
- return mat4.lookAt([],
- [30 * Math.cos(t), 2.5, 30 * Math.sin(t)],
- [0, 2.5, 0],
- [0, 1, 0]);
- },
- projection: () =>
- mat4.perspective([],
- Math.PI / 4,
- viewportWidth / viewportHeight,
- 0.01,
- 1000),
},
pipeline: {
vertex: {
@@ -72,17 +54,42 @@ const renderObject: IGLRenderObject = {
}`,
targets: [{ blend: {} }],
},
- depthStencil: { depth: { depthtest: true } },
+ depthStencil: {},
}
};
+const submit: ISubmit = {
+ commandEncoders: [{
+ passEncoders: [
+ {
+ descriptor: { colorAttachments: [{ clearValue: [0, 0, 0, 1] }], depthStencilAttachment: { depthClearValue: 1 } },
+ renderObjects: [renderObject]
+ }
+ ]
+ }]
+};
+
function draw()
{
- viewportWidth = webglcanvas.width = webglcanvas.clientWidth;
- viewportHeight = webglcanvas.height = webglcanvas.clientHeight;
+ viewportWidth = canvas.width = canvas.clientWidth;
+ viewportHeight = canvas.height = canvas.clientHeight;
tick++;
- webgl.runRenderPass({ renderObjects: [renderObject] });
+ const t = 0.01 * tick;
+
+ renderObject.uniforms.view = mat4.lookAt([],
+ [30 * Math.cos(t), 2.5, 30 * Math.sin(t)],
+ [0, 2.5, 0],
+ [0, 1, 0]);
+
+ renderObject.uniforms.projection =
+ mat4.perspective([],
+ Math.PI / 4,
+ viewportWidth / viewportHeight,
+ 0.01,
+ 1000);
+
+ webgl.submit(submit);
requestAnimationFrame(draw);
}
diff --git a/examples/src/regl-examples/camera.ts b/examples/src/regl-examples/camera.ts
index ee0069b1e320cde5bebe84d87bdadc3c635e8f50..ae5f99ab83847731f9b63e55dc09e4d7ebdb5b6a 100644
--- a/examples/src/regl-examples/camera.ts
+++ b/examples/src/regl-examples/camera.ts
@@ -1,17 +1,15 @@
-import { IGLRenderObject, WebGL } from "@feng3d/webgl";
+import { IRenderObject } from "@feng3d/render-api";
+import { WebGL } from "@feng3d/webgl";
import { angleNormals } from "./mikolalysenko/angle-normals";
import * as bunny from "./mikolalysenko/bunny";
import { createCamera } from "./util/camera";
-const webglcanvas = document.createElement("canvas");
-webglcanvas.id = "glcanvas";
-webglcanvas.style.position = "fixed";
-webglcanvas.style.left = "0px";
-webglcanvas.style.top = "0px";
-webglcanvas.style.width = "100%";
-webglcanvas.style.height = "100%";
-document.body.appendChild(webglcanvas);
+const canvas = document.createElement("canvas");
+canvas.id = "glcanvas";
+canvas.width = window.innerWidth;
+canvas.height = window.innerHeight;
+document.body.appendChild(canvas);
const webgl = new WebGL({ canvasId: "glcanvas", antialias: true });
@@ -19,35 +17,17 @@ const camera = createCamera({
center: [0, 2.5, 0]
});
-const positions = bunny.positions.reduce((pv: number[], cv: number[]) =>
-{
- cv.forEach((v) => { pv.push(v); });
-
- return pv;
-}, []);
-
-const indices = bunny.cells.reduce((pv: number[], cv: number[]) =>
-{
- cv.forEach((v) => { pv.push(v); });
-
- return pv;
-}, []);
+const positions = bunny.positions.flat();
+const indices = bunny.cells.flat();
+const normals = angleNormals(bunny.cells, bunny.positions).flat();
-const normals = angleNormals(bunny.cells, bunny.positions).reduce((pv: number[], cv: number[]) =>
-{
- cv.forEach((v) => { pv.push(v); });
-
- return pv;
-}, []);
-
-const renderObject: IGLRenderObject = {
- vertexArray: {
- vertices: {
- position: { buffer: { target: "ARRAY_BUFFER", data: new Float32Array(positions) }, numComponents: 3 },
- normal: { buffer: { target: "ARRAY_BUFFER", data: new Float32Array(normals) }, numComponents: 3 },
- },
- index: { target: "ELEMENT_ARRAY_BUFFER", data: new Uint16Array(indices) }
+const renderObject: IRenderObject = {
+ vertices: {
+ position: { data: new Float32Array(positions), format: "float32x3" },
+ normal: { data: new Float32Array(normals), format: "float32x3" },
},
+ indices: new Uint16Array(indices),
+ drawIndexed: { indexCount: indices.length },
uniforms: {},
pipeline: {
vertex: {
@@ -67,18 +47,27 @@ const renderObject: IGLRenderObject = {
}`,
targets: [{ blend: {} }],
},
- depthStencil: { depth: { depthtest: true } },
+ depthStencil: { depthWriteEnabled: true },
}
};
function draw()
{
- webglcanvas.width = webglcanvas.clientWidth;
- webglcanvas.height = webglcanvas.clientHeight;
+ canvas.width = canvas.clientWidth;
+ canvas.height = canvas.clientHeight;
- camera(renderObject, webglcanvas.width, webglcanvas.height);
+ camera(renderObject, canvas.width, canvas.height);
- webgl.runRenderPass({ renderObjects: [renderObject] });
+ webgl.submit({
+ commandEncoders: [{
+ passEncoders: [
+ {
+ descriptor: { colorAttachments: [{ clearValue: [0, 0, 0, 1] }] },
+ renderObjects: [renderObject]
+ }
+ ]
+ }]
+ });
requestAnimationFrame(draw);
}
diff --git a/examples/src/regl-examples/cloth.ts b/examples/src/regl-examples/cloth.ts
index ba5792b6e9c9dae5c935eddf3a0a4dae0afb6c23..e4cf4d71c99f63ef8d5afe31a641ce2af8acb000 100644
--- a/examples/src/regl-examples/cloth.ts
+++ b/examples/src/regl-examples/cloth.ts
@@ -1,4 +1,5 @@
-import { IGLRenderObject, IGLSamplerTexture, WebGL } from "@feng3d/webgl";
+import { IRenderObject, ISubmit } from "@feng3d/render-api";
+import { getIGLVertexBuffer, IGLSamplerTexture, WebGL } from "@feng3d/webgl";
import { fit } from "./hughsk/canvas-fit";
import { attachCamera } from "./hughsk/canvas-orbit-camera";
@@ -9,11 +10,8 @@ import * as vec3 from "./stackgl/gl-vec3";
{
const canvas = document.createElement("canvas");
canvas.id = "glcanvas";
- canvas.style.position = "fixed";
- canvas.style.left = "0px";
- canvas.style.top = "0px";
- canvas.style.width = "100%";
- canvas.style.height = "100%";
+ canvas.width = window.innerWidth;
+ canvas.height = window.innerHeight;
document.body.appendChild(canvas);
const webgl = new WebGL({ canvasId: "glcanvas" });
@@ -166,25 +164,15 @@ import * as vec3 from "./stackgl/gl-vec3";
let viewportWidth = 1;
let viewportHeight = 1;
- const renderObject: IGLRenderObject = {
- vertexArray: {
- vertices: {
- position: { buffer: { target: "ARRAY_BUFFER", data: new Float32Array(positions) }, numComponents: 3 },
- normal: { buffer: { target: "ARRAY_BUFFER", data: new Float32Array(normals) }, numComponents: 3 },
- uv: { buffer: { target: "ARRAY_BUFFER", data: new Float32Array(uvs) }, numComponents: 2 },
- },
- index: { target: "ELEMENT_ARRAY_BUFFER", data: new Uint16Array(indices) }
- },
- uniforms: {
- view: () => camera.view(),
- projection: () =>
- mat4.perspective([],
- Math.PI / 4,
- viewportWidth / viewportHeight,
- 0.01,
- 1000),
- texture: () => diffuse,
+ const renderObject: IRenderObject = {
+ vertices: {
+ position: { data: new Float32Array(positions), format: "float32x3" },
+ normal: { data: new Float32Array(normals), format: "float32x3" },
+ uv: { data: new Float32Array(uvs), format: "float32x2" },
},
+ indices: new Uint16Array(indices),
+ drawIndexed: { indexCount: indices.length },
+ uniforms: {},
pipeline: {
vertex: {
code: `precision mediump float;
@@ -229,10 +217,20 @@ import * as vec3 from "./stackgl/gl-vec3";
}`,
targets: [{ blend: {} }],
},
- depthStencil: { depth: { depthtest: true } },
+ depthStencil: {},
}
};
+ const submit: ISubmit = {
+ commandEncoders: [{
+ passEncoders: [
+ {
+ renderObjects: [renderObject]
+ }
+ ]
+ }]
+ };
+
function draw()
{
const deltaTime = 0.017;
@@ -361,8 +359,8 @@ import * as vec3 from "./stackgl/gl-vec3";
return pv;
}, []);
- renderObject.vertexArray.vertices.position.buffer.data = new Float32Array(positions);
- renderObject.vertexArray.vertices.normal.buffer.data = new Float32Array(normals);
+ getIGLVertexBuffer(renderObject.vertices.position.data).data = new Float32Array(positions);
+ getIGLVertexBuffer(renderObject.vertices.normal.data).data = new Float32Array(normals);
tick++;
@@ -371,7 +369,15 @@ import * as vec3 from "./stackgl/gl-vec3";
camera.tick();
- webgl.runRenderPass({ renderObjects: [renderObject] });
+ renderObject.uniforms.view = camera.view();
+ renderObject.uniforms.projection =
+ mat4.perspective([],
+ Math.PI / 4,
+ viewportWidth / viewportHeight,
+ 0.01,
+ 1000);
+
+ webgl.submit(submit);
requestAnimationFrame(draw);
}
@@ -380,7 +386,14 @@ import * as vec3 from "./stackgl/gl-vec3";
img.src = "../../assets/cloth.png";
await img.decode();
- const diffuse: IGLSamplerTexture = { texture: { generateMipmap: true, sources: [{ source: img }] }, sampler: { minFilter: "LINEAR_MIPMAP_LINEAR", wrapS: "REPEAT", wrapT: "REPEAT" } };
+ const diffuse: IGLSamplerTexture = {
+ texture: {
+ size: [img.width, img.height],
+ generateMipmap: true,
+ sources: [{ image: img }]
+ }, sampler: { minFilter: "linear", mipmapFilter: "linear", addressModeU: "repeat", addressModeV: "repeat" }
+ };
+ renderObject.uniforms.texture = diffuse;
draw();
})();
\ No newline at end of file
diff --git a/examples/src/regl-examples/cube.ts b/examples/src/regl-examples/cube.ts
index 854a4c5d5f3d752bb0a4849e8dfe8327f8634ef3..7c53d43e8d2a86671c808b7d177a488570c696f1 100644
--- a/examples/src/regl-examples/cube.ts
+++ b/examples/src/regl-examples/cube.ts
@@ -1,16 +1,14 @@
-import { IGLRenderObject, IGLSamplerTexture, WebGL } from "@feng3d/webgl";
+import { IRenderObject, ISubmit } from "@feng3d/render-api";
+import { IGLSamplerTexture, WebGL } from "@feng3d/webgl";
import * as mat4 from "./stackgl/gl-mat4";
(async () =>
{
- const webglcanvas = document.createElement("canvas");
- webglcanvas.id = "glcanvas";
- webglcanvas.style.position = "fixed";
- webglcanvas.style.left = "0px";
- webglcanvas.style.top = "0px";
- webglcanvas.style.width = "100%";
- webglcanvas.style.height = "100%";
- document.body.appendChild(webglcanvas);
+ const canvas = document.createElement("canvas");
+ canvas.id = "glcanvas";
+ canvas.width = window.innerWidth;
+ canvas.height = window.innerHeight;
+ document.body.appendChild(canvas);
const webgl = new WebGL({ canvasId: "glcanvas" });
@@ -66,32 +64,14 @@ import * as mat4 from "./stackgl/gl-mat4";
let viewportWidth = 1;
let viewportHeight = 1;
- const renderObject: IGLRenderObject = {
- vertexArray: {
- vertices: {
- position: { buffer: { target: "ARRAY_BUFFER", data: new Float32Array(positions) }, numComponents: 3 },
- uv: { buffer: { target: "ARRAY_BUFFER", data: new Float32Array(uvs) }, numComponents: 2 },
- },
- index: { target: "ELEMENT_ARRAY_BUFFER", data: new Uint16Array(indices) }
- },
- uniforms: {
- view: () =>
- {
- const t = 0.01 * tick;
-
- return mat4.lookAt([],
- [5 * Math.cos(t), 2.5 * Math.sin(t), 5 * Math.sin(t)],
- [0, 0.0, 0],
- [0, 1, 0]);
- },
- projection: () =>
- mat4.perspective([],
- Math.PI / 4,
- viewportWidth / viewportHeight,
- 0.01,
- 10),
- tex: () => diffuse,
+ const renderObject: IRenderObject = {
+ vertices: {
+ position: { data: new Float32Array(positions), format: "float32x3" },
+ uv: { data: new Float32Array(uvs), format: "float32x2" },
},
+ indices: new Uint16Array(indices),
+ drawIndexed: { indexCount: indices.length },
+ uniforms: {},
pipeline: {
vertex: {
code: `precision mediump float;
@@ -112,18 +92,41 @@ import * as mat4 from "./stackgl/gl-mat4";
}`,
targets: [{ blend: {} }],
},
- depthStencil: { depth: { depthtest: true } },
+ depthStencil: { depthWriteEnabled: true },
}
};
+ const submit: ISubmit = {
+ commandEncoders: [{
+ passEncoders: [
+ {
+ renderObjects: [renderObject]
+ }
+ ]
+ }]
+ };
+
function draw()
{
tick++;
- viewportWidth = webglcanvas.width = webglcanvas.clientWidth;
- viewportHeight = webglcanvas.height = webglcanvas.clientHeight;
+ viewportWidth = canvas.width = canvas.clientWidth;
+ viewportHeight = canvas.height = canvas.clientHeight;
+
+ const t = 0.01 * tick;
+ renderObject.uniforms.view = mat4.lookAt([],
+ [5 * Math.cos(t), 2.5 * Math.sin(t), 5 * Math.sin(t)],
+ [0, 0.0, 0],
+ [0, 1, 0]);
+ renderObject.uniforms.projection =
+ mat4.perspective([],
+ Math.PI / 4,
+ viewportWidth / viewportHeight,
+ 0.01,
+ 10);
+
+ webgl.submit(submit);
- webgl.runRenderPass({ renderObjects: [renderObject] });
requestAnimationFrame(draw);
}
@@ -131,7 +134,13 @@ import * as mat4 from "./stackgl/gl-mat4";
img.src = "../../assets/peppers.png";
await img.decode();
- const diffuse: IGLSamplerTexture = { texture: { sources: [{ source: img }] }, sampler: { minFilter: "LINEAR" } };
+ const diffuse: IGLSamplerTexture = {
+ texture: {
+ size: [img.width, img.height],
+ sources: [{ image: img }]
+ }, sampler: { minFilter: "linear" }
+ };
+ renderObject.uniforms.tex = diffuse;
draw();
})();
\ No newline at end of file
diff --git a/examples/src/regl-examples/util/camera.ts b/examples/src/regl-examples/util/camera.ts
index ac1fdfd696820d77d1b63a3885f17a1245c1f7ca..c477f796089b728274880217bf1091f4c339c5e4 100644
--- a/examples/src/regl-examples/util/camera.ts
+++ b/examples/src/regl-examples/util/camera.ts
@@ -1,4 +1,4 @@
-import { IGLRenderObject } from "@feng3d/webgl";
+import { IRenderObject } from "@feng3d/render-api";
import { mouseListen as mouseChange } from "../mikolalysenko/mouse-change";
import { mouseWheelListen as mouseWheel } from "../mikolalysenko/mouse-wheel";
@@ -101,22 +101,21 @@ export function createCamera(props)
lookAt(cameraState.view, eye, center, up);
}
- const injectContext = (renderObject: IGLRenderObject, viewportWidth: number, viewportHeight: number) =>
+ const injectContext = (renderObject: IRenderObject, viewportWidth: number, viewportHeight: number) =>
{
Object.keys(cameraState).forEach(function (name)
{
- renderObject.uniforms[name] = () => setupCamera[name];
+ renderObject.uniforms[name] = setupCamera[name];
});
- renderObject.uniforms["projection"] = () =>
- perspective(cameraState.projection,
- Math.PI / 4.0,
- viewportWidth / viewportHeight,
- 0.01,
- 1000.0);
+ renderObject.uniforms["projection"] = perspective(cameraState.projection,
+ Math.PI / 4.0,
+ viewportWidth / viewportHeight,
+ 0.01,
+ 1000.0);
};
- function setupCamera(renderObject: IGLRenderObject, viewportWidth: number, viewportHeight: number)
+ function setupCamera(renderObject: IRenderObject, viewportWidth: number, viewportHeight: number)
{
updateCamera();
injectContext(renderObject, viewportWidth, viewportHeight);
diff --git a/examples/src/test/fractalCube.html b/examples/src/test/fractalCube.html
new file mode 100644
index 0000000000000000000000000000000000000000..6693a177808106351cafe81fca4fab70998d9628
--- /dev/null
+++ b/examples/src/test/fractalCube.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+ 分形立方体-测试纹理拷贝
+
+
+
+
+
+ 测试纹理之间拷贝,把前一帧的渲染结果作为纹理渲染到下一帧中。
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/src/test/fractalCube.ts b/examples/src/test/fractalCube.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c9841d974f908494e907bcd271aa92865bd24333
--- /dev/null
+++ b/examples/src/test/fractalCube.ts
@@ -0,0 +1,277 @@
+import { IRenderObject, ISampler, ISubmit, ITexture } from "@feng3d/render-api";
+import { IGLCanvasContext, WebGL } from "@feng3d/webgl";
+import { mat4 } from "gl-matrix";
+
+let cubeRotation = 0.0;
+
+main();
+
+//
+// Start here
+//
+async function main()
+{
+ const canvas = document.querySelector("#glcanvas") as HTMLCanvasElement;
+
+ const renderingContext: IGLCanvasContext = { canvasId: "glcanvas", contextId: "webgl2" };
+
+ const webgl = new WebGL(renderingContext);
+
+ // Here's where we call the routine that builds all the
+ // objects we'll be drawing.
+ const buffers = initBuffers();
+
+ const texture: {
+ texture: ITexture;
+ sampler: ISampler;
+ } = { texture: { size: [canvas.width, canvas.height] }, sampler: {} };
+
+ const renderObject: IRenderObject = {
+ pipeline: {
+ primitive: { topology: "triangle-list" },
+ vertex: {
+ code: `
+ attribute vec4 aVertexPosition;
+ attribute vec2 aTextureCoord;
+
+ uniform mat4 uModelViewMatrix;
+ uniform mat4 uProjectionMatrix;
+
+ varying highp vec2 vTextureCoord;
+ varying highp vec4 v_fragPosition;
+
+ void main(void) {
+ gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
+ vTextureCoord = aTextureCoord;
+ v_fragPosition = 0.5 * (aVertexPosition + vec4(1.0, 1.0, 1.0, 1.0));
+ }
+ ` }, fragment: {
+ code: `
+ precision highp float;
+ precision highp int;
+
+ varying highp vec2 vTextureCoord;
+ varying highp vec4 v_fragPosition;
+
+ uniform sampler2D uSampler;
+
+ void main(void) {
+ vec4 color = texture2D(uSampler, vTextureCoord) * v_fragPosition;
+ gl_FragColor = color;
+ }
+ ` },
+ depthStencil: { depthCompare: "less-equal" }
+ },
+ vertices: {
+ aVertexPosition: {
+ format: "float32x3",
+ data: buffers.position,
+ },
+ aTextureCoord: {
+ format: "float32x2",
+ data: buffers.textureCoord,
+ },
+ },
+ indices: buffers.indices,
+ uniforms: { uSampler: texture },
+ drawIndexed: { firstIndex: 0, indexCount: 36 },
+ };
+
+ const submit: ISubmit = {
+ commandEncoders: [{
+ passEncoders: [
+ // 绘制
+ {
+ descriptor: {
+ colorAttachments: [{ clearValue: [0.5, 0.5, 0.5, 1.0], loadOp: "clear" }],
+ depthStencilAttachment: { depthClearValue: 1.0, depthLoadOp: "clear" },
+ },
+ renderObjects: [renderObject],
+ },
+ // 从画布中拷贝到纹理。
+ {
+ __type: "CopyTextureToTexture",
+ source: { texture: null }, // 当值设置为 null或者undefined时表示当前画布。
+ destination: { texture: texture.texture },
+ copySize: [canvas.width, canvas.height],
+ },
+ ]
+ }]
+ }
+
+ let then = 0;
+
+ // Draw the scene repeatedly
+ function render()
+ {
+ let now = Date.now();
+ now *= 0.001; // convert to seconds
+ const deltaTime = now - then;
+ then = now;
+
+ const { projectionMatrix, modelViewMatrix } = drawScene(canvas, deltaTime);
+
+ renderObject.uniforms.uProjectionMatrix = projectionMatrix;
+ renderObject.uniforms.uModelViewMatrix = modelViewMatrix;
+
+ webgl.submit(submit);
+
+ requestAnimationFrame(render);
+ }
+ requestAnimationFrame(render);
+}
+
+//
+// initBuffers
+//
+// Initialize the buffers we'll need. For this demo, we just
+// have one object -- a simple three-dimensional cube.
+//
+function initBuffers()
+{
+ // Now create an array of positions for the cube.
+
+ const positions = [
+ // Front face
+ -1.0, -1.0, 1.0,
+ 1.0, -1.0, 1.0,
+ 1.0, 1.0, 1.0,
+ -1.0, 1.0, 1.0,
+
+ // Back face
+ -1.0, -1.0, -1.0,
+ -1.0, 1.0, -1.0,
+ 1.0, 1.0, -1.0,
+ 1.0, -1.0, -1.0,
+
+ // Top face
+ -1.0, 1.0, -1.0,
+ -1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0,
+ 1.0, 1.0, -1.0,
+
+ // Bottom face
+ -1.0, -1.0, -1.0,
+ 1.0, -1.0, -1.0,
+ 1.0, -1.0, 1.0,
+ -1.0, -1.0, 1.0,
+
+ // Right face
+ 1.0, -1.0, -1.0,
+ 1.0, 1.0, -1.0,
+ 1.0, 1.0, 1.0,
+ 1.0, -1.0, 1.0,
+
+ // Left face
+ -1.0, -1.0, -1.0,
+ -1.0, -1.0, 1.0,
+ -1.0, 1.0, 1.0,
+ -1.0, 1.0, -1.0,
+ ];
+
+ // Now set up the texture coordinates for the faces.
+
+ const textureCoordinates = [
+ // Front
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ // Back
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ // Top
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ // Bottom
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ // Right
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ // Left
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ ];
+
+ // This array defines each face as two triangles, using the
+ // indices into the vertex array to specify each triangle's
+ // position.
+
+ const indices = [
+ 0, 1, 2, 0, 2, 3, // front
+ 4, 5, 6, 4, 6, 7, // back
+ 8, 9, 10, 8, 10, 11, // top
+ 12, 13, 14, 12, 14, 15, // bottom
+ 16, 17, 18, 16, 18, 19, // right
+ 20, 21, 22, 20, 22, 23, // left
+ ];
+
+ return {
+ position: new Float32Array(positions),
+ textureCoord: new Float32Array(textureCoordinates),
+ indices: new Uint16Array(indices),
+ };
+}
+
+//
+// Draw the scene.
+//
+function drawScene(canvas: HTMLCanvasElement, deltaTime: number)
+{
+ // Create a perspective matrix, a special matrix that is
+ // used to simulate the distortion of perspective in a camera.
+ // Our field of view is 45 degrees, with a width/height
+ // ratio that matches the display size of the canvas
+ // and we only want to see objects between 0.1 units
+ // and 100 units away from the camera.
+
+ const fieldOfView = 45 * Math.PI / 180; // in radians
+ const aspect = canvas.clientWidth / canvas.clientHeight;
+ const zNear = 0.1;
+ const zFar = 100.0;
+ const projectionMatrix = mat4.create();
+
+ // note: glmatrix.js always has the first argument
+ // as the destination to receive the result.
+ mat4.perspective(projectionMatrix,
+ fieldOfView,
+ aspect,
+ zNear,
+ zFar);
+
+ // Set the drawing position to the "identity" point, which is
+ // the center of the scene.
+ const modelViewMatrix = mat4.create();
+
+ // Now move the drawing position a bit to where we want to
+ // start drawing the square.
+
+ mat4.translate(modelViewMatrix, // destination matrix
+ modelViewMatrix, // matrix to translate
+ [-0.0, 0.0, -6.0]); // amount to translate
+ mat4.rotate(modelViewMatrix, // destination matrix
+ modelViewMatrix, // matrix to rotate
+ cubeRotation, // amount to rotate in radians
+ [0, 0, 1]); // axis to rotate around (Z)
+ mat4.rotate(modelViewMatrix, // destination matrix
+ modelViewMatrix, // matrix to rotate
+ cubeRotation * 0.7, // amount to rotate in radians
+ [0, 1, 0]); // axis to rotate around (X)
+
+ // Update the rotation for the next draw
+
+ cubeRotation += deltaTime;
+
+ return { projectionMatrix, modelViewMatrix };
+}
diff --git a/examples/src/webgl-examples/sample1.ts b/examples/src/webgl-examples/sample1.ts
index b9a171d21efc473c5a09bba6d8d4aa01e30049a0..e42a861f509943fe6a85dcd75571196d8c8b4bab 100644
--- a/examples/src/webgl-examples/sample1.ts
+++ b/examples/src/webgl-examples/sample1.ts
@@ -1,20 +1,32 @@
// see https://github.com/mdn/dom-examples/blob/main/webgl-examples/tutorial/sample1/webgl-demo.js
// https://mdn.github.io/dom-examples/webgl-examples/tutorial/sample1/
-import { WebGL } from "@feng3d/webgl";
+import { ISubmit } from "@feng3d/render-api";
+import { IGLCanvasContext, WebGL } from "@feng3d/webgl";
-function main()
+async function main()
{
- const webgl = new WebGL({ canvasId: "glcanvas", contextId: "webgl" });
- webgl.runRenderPass({
- descriptor: {
- colorAttachments: [{
- clearValue: [1, 0, 0, 0.5],
- loadOp: "clear",
- }],
- },
- }
- );
+ const renderingContext: IGLCanvasContext = { canvasId: "glcanvas", contextId: "webgl" };
+
+ const webgl = new WebGL(renderingContext);
+
+ const submit: ISubmit = {
+ commandEncoders: [{
+ passEncoders: [
+ {
+ descriptor: {
+ colorAttachments: [{
+ // view: { texture: {} },
+ clearValue: [1, 0, 0, 0.5],
+ loadOp: "clear",
+ }],
+ },
+ }
+ ]
+ }]
+ };
+
+ webgl.submit(submit);
}
window.onload = main;
diff --git a/examples/src/webgl-examples/sample2.ts b/examples/src/webgl-examples/sample2.ts
index c1e0c1738780f35c0e07c756803911d71b9f36c3..d24120bceb3709fb6ede2cd80d2324c026f27016 100644
--- a/examples/src/webgl-examples/sample2.ts
+++ b/examples/src/webgl-examples/sample2.ts
@@ -1,4 +1,5 @@
-import { IGLRenderPass, WebGL } from "@feng3d/webgl";
+import { IRenderPass } from "@feng3d/render-api";
+import { WebGL } from "@feng3d/webgl";
import { mat4 } from "gl-matrix";
main();
@@ -11,7 +12,7 @@ function main()
const webgl = new WebGL({ canvasId: "glcanvas", contextId: "webgl" });
- const renderPasss: IGLRenderPass = {
+ const renderPass: IRenderPass = {
descriptor: {
colorAttachments: [{
clearValue: [0, 0, 0, 1],
@@ -24,7 +25,7 @@ function main()
},
renderObjects: [{
pipeline: {
- primitive: { topology: "TRIANGLE_STRIP" },
+ primitive: { topology: "triangle-strip" },
vertex: {
code: `
attribute vec4 aVertexPosition;
@@ -39,34 +40,28 @@ function main()
void main() {
gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);
}` },
- depthStencil: { depth: { depthCompare: "LEQUAL" } }
+ depthStencil: { depthCompare: "less-equal" }
},
- vertexArray: {
- vertices: {
- aVertexPosition: {
- type: "FLOAT",
- buffer: {
- target: "ARRAY_BUFFER",
- data: new Float32Array([
- 1.0, 1.0,
- -1.0, 1.0,
- 1.0, -1.0,
- -1.0, -1.0,
- ]), usage: "STATIC_DRAW"
- },
- numComponents: 2,
- }
- },
+ vertices: {
+ aVertexPosition: {
+ format:"float32x2",
+ data: new Float32Array([
+ 1.0, 1.0,
+ -1.0, 1.0,
+ 1.0, -1.0,
+ -1.0, -1.0,
+ ]),
+ }
},
uniforms: {
uProjectionMatrix: projectionMatrix,
uModelViewMatrix: modelViewMatrix,
},
- drawArrays: { firstVertex: 0, vertexCount: 4 },
+ drawVertex: { firstVertex: 0, vertexCount: 4 },
}],
};
- webgl.runRenderPass(renderPasss);
+ webgl.submit({ commandEncoders: [{ passEncoders: [renderPass] }] });
}
function drawScene(canvas: HTMLCanvasElement)
diff --git a/examples/src/webgl-examples/sample3.ts b/examples/src/webgl-examples/sample3.ts
index 2a15a711770f9cea89a1327b0ef3f619ad05e386..b666ea90f45effc850ccfc70360f114250e8a562 100644
--- a/examples/src/webgl-examples/sample3.ts
+++ b/examples/src/webgl-examples/sample3.ts
@@ -1,4 +1,5 @@
-import { IGLRenderPass, WebGL } from "@feng3d/webgl";
+import { IRenderPass } from "@feng3d/render-api";
+import { WebGL } from "@feng3d/webgl";
import { mat4 } from "gl-matrix";
main();
@@ -15,7 +16,7 @@ function main()
const webgl = new WebGL({ canvasId: "glcanvas", contextId: "webgl" });
- const renderPasss: IGLRenderPass = {
+ const renderPass: IRenderPass = {
descriptor: {
colorAttachments: [{
clearValue: [0.0, 0.0, 0.0, 1.0],
@@ -28,7 +29,7 @@ function main()
},
renderObjects: [{
pipeline: {
- primitive: { topology: "TRIANGLE_STRIP" },
+ primitive: { topology: "triangle-strip" },
vertex: {
code: `
attribute vec4 aVertexPosition;
@@ -51,50 +52,37 @@ function main()
gl_FragColor = vColor;
}
` },
- depthStencil: { depth: { depthtest: true, depthCompare: "LEQUAL" } }
+ depthStencil: { depthCompare: "less-equal" }
},
- vertexArray: {
- vertices: {
- aVertexPosition: {
- type: "FLOAT",
- buffer: {
- target: "ARRAY_BUFFER",
- data: new Float32Array([
- 1.0, 1.0,
- -1.0, 1.0,
- 1.0, -1.0,
- -1.0, -1.0,
- ]), usage: "STATIC_DRAW",
- },
- numComponents: 2,
- normalized: false,
- },
- aVertexColor: {
- type: "FLOAT",
- buffer: {
- target: "ARRAY_BUFFER",
- data: new Float32Array([
- 1.0, 1.0, 1.0, 1.0, // white
- 1.0, 0.0, 0.0, 1.0, // red
- 0.0, 1.0, 0.0, 1.0, // green
- 0.0, 0.0, 1.0, 1.0, // blue
- ]),
- usage: "STATIC_DRAW",
- },
- numComponents: 4,
- normalized: false,
- },
+ vertices: {
+ aVertexPosition: {
+ format: "float32x2",
+ data: new Float32Array([
+ 1.0, 1.0,
+ -1.0, 1.0,
+ 1.0, -1.0,
+ -1.0, -1.0,
+ ]),
+ },
+ aVertexColor: {
+ format: "float32x4",
+ data: new Float32Array([
+ 1.0, 1.0, 1.0, 1.0, // white
+ 1.0, 0.0, 0.0, 1.0, // red
+ 0.0, 1.0, 0.0, 1.0, // green
+ 0.0, 0.0, 1.0, 1.0, // blue
+ ]),
},
},
uniforms: {
uProjectionMatrix: projectionMatrix,
uModelViewMatrix: modelViewMatrix,
},
- drawArrays: { firstVertex: 0, vertexCount: 4 },
+ drawVertex: { firstVertex: 0, vertexCount: 4 },
}],
};
- webgl.runRenderPass(renderPasss);
+ webgl.submit({ commandEncoders: [{ passEncoders: [renderPass] }] });
}
//
diff --git a/examples/src/webgl-examples/sample4.ts b/examples/src/webgl-examples/sample4.ts
index b3629e6f58470fc16f6f8cbe195fbafdb7364365..bf89c1f6e748764bfc449eaaaed35a99fddbf8c4 100644
--- a/examples/src/webgl-examples/sample4.ts
+++ b/examples/src/webgl-examples/sample4.ts
@@ -1,4 +1,5 @@
-import { IGLRenderObject, IGLRenderPass, WebGL } from "@feng3d/webgl";
+import { IRenderObject, IRenderPass } from "@feng3d/render-api";
+import { WebGL } from "@feng3d/webgl";
import { mat4 } from "gl-matrix";
let squareRotation = 0.0;
@@ -14,9 +15,9 @@ function main()
const webgl = new WebGL({ canvasId: "glcanvas", contextId: "webgl" });
- const renderObject: IGLRenderObject = {
+ const renderObject: IRenderObject = {
pipeline: {
- primitive: { topology: "TRIANGLE_STRIP" },
+ primitive: { topology: "triangle-strip" },
vertex: {
code: `
attribute vec4 aVertexPosition;
@@ -39,46 +40,33 @@ function main()
gl_FragColor = vColor;
}
` },
- depthStencil: { depth: { depthtest: true, depthCompare: "LEQUAL" } }
+ depthStencil: { depthCompare: "less-equal" }
},
- vertexArray: {
- vertices: {
- aVertexPosition: {
- type: "FLOAT",
- buffer: {
- target: "ARRAY_BUFFER",
- data: new Float32Array([
- 1.0, 1.0,
- -1.0, 1.0,
- 1.0, -1.0,
- -1.0, -1.0,
- ]), usage: "STATIC_DRAW",
- },
- numComponents: 2,
- normalized: false,
- },
- aVertexColor: {
- type: "FLOAT",
- buffer: {
- target: "ARRAY_BUFFER",
- data: new Float32Array([
- 1.0, 1.0, 1.0, 1.0, // white
- 1.0, 0.0, 0.0, 1.0, // red
- 0.0, 1.0, 0.0, 1.0, // green
- 0.0, 0.0, 1.0, 1.0, // blue
- ]),
- usage: "STATIC_DRAW",
- },
- numComponents: 4,
- normalized: false,
- },
- }
+ vertices: {
+ aVertexPosition: {
+ format: "float32x2",
+ data: new Float32Array([
+ 1.0, 1.0,
+ -1.0, 1.0,
+ 1.0, -1.0,
+ -1.0, -1.0,
+ ]),
+ },
+ aVertexColor: {
+ format: "float32x4",
+ data: new Float32Array([
+ 1.0, 1.0, 1.0, 1.0, // white
+ 1.0, 0.0, 0.0, 1.0, // red
+ 0.0, 1.0, 0.0, 1.0, // green
+ 0.0, 0.0, 1.0, 1.0, // blue
+ ]),
+ },
},
uniforms: {},
- drawArrays: { firstVertex: 0, vertexCount: 4 },
+ drawVertex: { firstVertex: 0, vertexCount: 4 },
};
- const renderPasss: IGLRenderPass = {
+ const renderPass: IRenderPass = {
descriptor: {
colorAttachments: [{
clearValue: [0.0, 0.0, 0.0, 1.0],
@@ -106,7 +94,7 @@ function main()
renderObject.uniforms.uProjectionMatrix = projectionMatrix;
renderObject.uniforms.uModelViewMatrix = modelViewMatrix;
- webgl.runRenderPass(renderPasss);
+ webgl.submit({ commandEncoders: [{ passEncoders: [renderPass] }] });
requestAnimationFrame(render);
}
diff --git a/examples/src/webgl-examples/sample5.ts b/examples/src/webgl-examples/sample5.ts
index c9f96337842e4483a6e4c89501392e6e4f58500a..b05b586c89a2d5ebb03295ff4cc90e2faf2a8f4d 100644
--- a/examples/src/webgl-examples/sample5.ts
+++ b/examples/src/webgl-examples/sample5.ts
@@ -1,4 +1,5 @@
-import { IGLRenderObject, IGLRenderPass, WebGL } from "@feng3d/webgl";
+import { IRenderObject, IRenderPass } from "@feng3d/render-api";
+import { WebGL } from "@feng3d/webgl";
import { mat4 } from "gl-matrix";
let cubeRotation = 0.0;
@@ -18,9 +19,9 @@ function main()
// objects we'll be drawing.
const buffers = initBuffers();
- const renderObject: IGLRenderObject = {
+ const renderObject: IRenderObject = {
pipeline: {
- primitive: { topology: "TRIANGLES" },
+ primitive: { topology: "triangle-list" },
vertex: {
code: `
attribute vec4 aVertexPosition;
@@ -43,38 +44,24 @@ function main()
gl_FragColor = vColor;
}
` },
- depthStencil: { depth: { depthtest: true, depthCompare: "LEQUAL" } }
+ depthStencil: { depthCompare: "less-equal" }
},
- vertexArray: {
- vertices: {
- aVertexPosition: {
- type: "FLOAT",
- buffer: {
- target: "ARRAY_BUFFER",
- data: buffers.position,
- usage: "STATIC_DRAW",
- },
- numComponents: 3,
- normalized: false,
- },
- aVertexColor: {
- type: "FLOAT",
- buffer: {
- target: "ARRAY_BUFFER",
- data: buffers.color,
- usage: "STATIC_DRAW",
- },
- numComponents: 4,
- normalized: false,
- },
+ vertices: {
+ aVertexPosition: {
+ format: "float32x3",
+ data: buffers.position,
+ },
+ aVertexColor: {
+ format: "float32x4",
+ data: buffers.color,
},
- index: { target: "ELEMENT_ARRAY_BUFFER", data: buffers.indices }
},
+ indices: buffers.indices,
uniforms: {},
- drawElements: { firstIndex: 0, indexCount: 36 },
+ drawIndexed: { firstIndex: 0, indexCount: 36 },
};
- const renderPasss: IGLRenderPass = {
+ const renderPass: IRenderPass = {
descriptor: {
colorAttachments: [{
clearValue: [0.0, 0.0, 0.0, 1.0],
@@ -102,7 +89,7 @@ function main()
renderObject.uniforms.uProjectionMatrix = projectionMatrix;
renderObject.uniforms.uModelViewMatrix = modelViewMatrix;
- webgl.runRenderPass(renderPasss);
+ webgl.submit({ commandEncoders: [{ passEncoders: [renderPass] }] });
requestAnimationFrame(render);
}
diff --git a/examples/src/webgl-examples/sample6.ts b/examples/src/webgl-examples/sample6.ts
index f16c76fa75ba2fecb3f22c4a57c0a3571a726530..847c71c9b8b03f05325b2ae1b5a934fbaa793c23 100644
--- a/examples/src/webgl-examples/sample6.ts
+++ b/examples/src/webgl-examples/sample6.ts
@@ -1,4 +1,5 @@
-import { IGLRenderObject, IGLRenderPass, IGLSampler, IGLTexture, WebGL } from "@feng3d/webgl";
+import { IRenderObject, IRenderPass, ISampler, ITexture } from "@feng3d/render-api";
+import { WebGL } from "@feng3d/webgl";
import { mat4 } from "gl-matrix";
let cubeRotation = 0.0;
@@ -20,9 +21,9 @@ async function main()
const texture = await loadTexture("../../cubetexture.png");
- const renderObject: IGLRenderObject = {
+ const renderObject: IRenderObject = {
pipeline: {
- primitive: { topology: "TRIANGLES" },
+ primitive: { topology: "triangle-list" },
vertex: {
code: `
attribute vec4 aVertexPosition;
@@ -47,38 +48,24 @@ async function main()
gl_FragColor = texture2D(uSampler, vTextureCoord);
}
` },
- depthStencil: { depth: { depthtest: true, depthCompare: "LEQUAL" } }
+ depthStencil: { depthCompare: "less-equal" }
},
- vertexArray: {
- vertices: {
- aVertexPosition: {
- type: "FLOAT",
- buffer: {
- target: "ARRAY_BUFFER",
- data: buffers.position,
- usage: "STATIC_DRAW",
- },
- numComponents: 3,
- normalized: false,
- },
- aTextureCoord: {
- type: "FLOAT",
- buffer: {
- target: "ARRAY_BUFFER",
- data: buffers.textureCoord,
- usage: "STATIC_DRAW",
- },
- numComponents: 2,
- normalized: false,
- },
+ vertices: {
+ aVertexPosition: {
+ format: "float32x3",
+ data: buffers.position,
+ },
+ aTextureCoord: {
+ format: "float32x2",
+ data: buffers.textureCoord,
},
- index: { target: "ELEMENT_ARRAY_BUFFER", data: buffers.indices }
},
+ indices: buffers.indices,
uniforms: { uSampler: texture },
- drawElements: { firstIndex: 0, indexCount: 36 },
+ drawIndexed: { firstIndex: 0, indexCount: 36 },
};
- const renderPasss: IGLRenderPass = {
+ const renderPass: IRenderPass = {
descriptor: {
colorAttachments: [{
clearValue: [0.0, 0.0, 0.0, 1.0],
@@ -106,7 +93,7 @@ async function main()
renderObject.uniforms.uProjectionMatrix = projectionMatrix;
renderObject.uniforms.uModelViewMatrix = modelViewMatrix;
- webgl.runRenderPass(renderPasss);
+ webgl.submit({ commandEncoders: [{ passEncoders: [renderPass] }] });
requestAnimationFrame(render);
}
@@ -233,19 +220,17 @@ async function loadTexture(url: string)
const generateMipmap = isPowerOf2(img.width) && isPowerOf2(img.height);
- const texture: IGLTexture = {
- target: "TEXTURE_2D", internalformat: "RGBA", format: "RGBA", type: "UNSIGNED_BYTE",
- sources: [{ source: img }],
+ const texture: ITexture = {
+ size: [img.width, img.height],
+ format: "rgba8unorm",
+ sources: [{ image: img }],
+ generateMipmap,
};
- let sampler: IGLSampler = {};
+ let sampler: ISampler = {};
if (generateMipmap)
{
- texture.generateMipmap = generateMipmap;
- }
- else
- {
- sampler = { wrapS: "CLAMP_TO_EDGE", wrapT: "CLAMP_TO_EDGE", minFilter: "LINEAR" };
+ sampler = { addressModeU: "clamp-to-edge", addressModeV: "clamp-to-edge", minFilter: "linear" };
}
return { texture, sampler };
diff --git a/examples/src/webgl-examples/sample7.ts b/examples/src/webgl-examples/sample7.ts
index 9d8c13d7f1edbbb25f9d46607d6e452dbfc8f83b..a171f9c2689c80028c6dd44bdebfdf6292ec8e79 100644
--- a/examples/src/webgl-examples/sample7.ts
+++ b/examples/src/webgl-examples/sample7.ts
@@ -1,4 +1,5 @@
-import { IGLRenderObject, IGLRenderPass, IGLSampler, IGLSamplerTexture, IGLTexture, WebGL } from "@feng3d/webgl";
+import { IRenderObject, IRenderPass, ISampler, ITexture } from "@feng3d/render-api";
+import { IGLSamplerTexture, WebGL } from "@feng3d/webgl";
import { mat4 } from "gl-matrix";
let cubeRotation = 0.0;
@@ -10,21 +11,21 @@ main();
//
async function main()
{
- const canvas = document.querySelector("#glcanvas") as HTMLCanvasElement;
+ const canvas = document.querySelector("#glcanvas") as HTMLCanvasElement;
- const webgl = new WebGL({ canvasId: "glcanvas", contextId: "webgl" });
+ const webgl = new WebGL({ canvasId: "glcanvas", contextId: "webgl" });
- // Here's where we call the routine that builds all the
- // objects we'll be drawing.
- const buffers = initBuffers();
+ // Here's where we call the routine that builds all the
+ // objects we'll be drawing.
+ const buffers = initBuffers();
- const texture = await loadTexture("../../cubetexture.png");
+ const texture = await loadTexture("../../cubetexture.png");
- const renderObject: IGLRenderObject = {
- pipeline: {
- primitive: { topology: "TRIANGLES" },
- vertex: {
- code: `
+ const renderObject: IRenderObject = {
+ pipeline: {
+ primitive: { topology: "triangle-list" },
+ vertex: {
+ code: `
attribute vec4 aVertexPosition;
attribute vec3 aVertexNormal;
attribute vec2 aTextureCoord;
@@ -52,7 +53,7 @@ async function main()
vLighting = ambientLight + (directionalLightColor * directional);
}
` }, fragment: {
- code: `
+ code: `
varying highp vec2 vTextureCoord;
varying highp vec3 vLighting;
@@ -64,81 +65,61 @@ async function main()
gl_FragColor = vec4(texelColor.rgb * vLighting, texelColor.a);
}
` },
- depthStencil: { depth: { depthtest: true, depthCompare: "LEQUAL" } }
- },
- vertexArray: {
- vertices: {
- aVertexPosition: {
- type: "FLOAT",
- buffer: {
- target: "ARRAY_BUFFER",
- data: buffers.position,
- usage: "STATIC_DRAW",
- },
- numComponents: 3,
- normalized: false,
+ depthStencil: { depthCompare: "less-equal" }
},
- aVertexNormal: {
- type: "FLOAT",
- buffer: {
- target: "ARRAY_BUFFER",
- data: buffers.normal,
- usage: "STATIC_DRAW",
- },
- numComponents: 3,
- normalized: false,
+ vertices: {
+ aVertexPosition: {
+ format: "float32x3",
+ data: buffers.position,
+ },
+ aVertexNormal: {
+ format: "float32x3",
+ data: buffers.normal,
+ },
+ aTextureCoord: {
+ format: "float32x2",
+ data: buffers.textureCoord,
+ },
},
- aTextureCoord: {
- type: "FLOAT",
- buffer: {
- target: "ARRAY_BUFFER",
- data: buffers.textureCoord,
- usage: "STATIC_DRAW",
- },
- numComponents: 2,
- normalized: false,
+ indices: buffers.indices,
+ uniforms: { uSampler: texture },
+ drawIndexed: { firstIndex: 0, indexCount: 36 },
+ };
+
+ const renderPass: IRenderPass = {
+ descriptor: {
+ colorAttachments: [{
+ clearValue: [0.0, 0.0, 0.0, 1.0],
+ loadOp: "clear",
+ }],
+ depthStencilAttachment: {
+ depthClearValue: 1.0,
+ depthLoadOp: "clear",
+ },
},
- },
- index: { target: "ELEMENT_ARRAY_BUFFER", data: buffers.indices }
- },
- uniforms: { uSampler: texture },
- drawElements: { firstIndex: 0, indexCount: 36 },
- };
-
- const renderPasss: IGLRenderPass = {
- descriptor: {
- colorAttachments: [{
- clearValue: [0.0, 0.0, 0.0, 1.0],
- loadOp: "clear",
- }],
- depthStencilAttachment: {
- depthClearValue: 1.0,
- depthLoadOp: "clear",
- },
- },
- renderObjects: [renderObject],
- };
-
- let then = 0;
-
- // Draw the scene repeatedly
- function render(now: number)
- {
- now *= 0.001; // convert to seconds
- const deltaTime = now - then;
- then = now;
-
- const { projectionMatrix, modelViewMatrix, normalMatrix } = drawScene(canvas, deltaTime);
-
- renderObject.uniforms.uProjectionMatrix = projectionMatrix;
- renderObject.uniforms.uModelViewMatrix = modelViewMatrix;
- renderObject.uniforms.uNormalMatrix = normalMatrix;
-
- webgl.runRenderPass(renderPasss);
+ renderObjects: [renderObject],
+ };
+ let then = 0;
+
+ // Draw the scene repeatedly
+ function render(now: number)
+ {
+ now *= 0.001; // convert to seconds
+ const deltaTime = now - then;
+ then = now;
+
+ const { projectionMatrix, modelViewMatrix, normalMatrix } = drawScene(canvas, deltaTime);
+
+ renderObject.uniforms.uProjectionMatrix = projectionMatrix;
+ renderObject.uniforms.uModelViewMatrix = modelViewMatrix;
+ renderObject.uniforms.uNormalMatrix = normalMatrix;
+
+ webgl.submit({ commandEncoders: [{ passEncoders: [renderPass] }] });
+
+ requestAnimationFrame(render);
+ }
requestAnimationFrame(render);
- }
- requestAnimationFrame(render);
}
//
@@ -149,145 +130,145 @@ async function main()
//
function initBuffers()
{
- // Now create an array of positions for the cube.
-
- const positions = [
- // Front face
- -1.0, -1.0, 1.0,
- 1.0, -1.0, 1.0,
- 1.0, 1.0, 1.0,
- -1.0, 1.0, 1.0,
-
- // Back face
- -1.0, -1.0, -1.0,
- -1.0, 1.0, -1.0,
- 1.0, 1.0, -1.0,
- 1.0, -1.0, -1.0,
-
- // Top face
- -1.0, 1.0, -1.0,
- -1.0, 1.0, 1.0,
- 1.0, 1.0, 1.0,
- 1.0, 1.0, -1.0,
-
- // Bottom face
- -1.0, -1.0, -1.0,
- 1.0, -1.0, -1.0,
- 1.0, -1.0, 1.0,
- -1.0, -1.0, 1.0,
-
- // Right face
- 1.0, -1.0, -1.0,
- 1.0, 1.0, -1.0,
- 1.0, 1.0, 1.0,
- 1.0, -1.0, 1.0,
-
- // Left face
- -1.0, -1.0, -1.0,
- -1.0, -1.0, 1.0,
- -1.0, 1.0, 1.0,
- -1.0, 1.0, -1.0,
- ];
-
- // Set up the normals for the vertices, so that we can compute lighting.
-
- const vertexNormals = [
- // Front
- 0.0, 0.0, 1.0,
- 0.0, 0.0, 1.0,
- 0.0, 0.0, 1.0,
- 0.0, 0.0, 1.0,
-
- // Back
- 0.0, 0.0, -1.0,
- 0.0, 0.0, -1.0,
- 0.0, 0.0, -1.0,
- 0.0, 0.0, -1.0,
-
- // Top
- 0.0, 1.0, 0.0,
- 0.0, 1.0, 0.0,
- 0.0, 1.0, 0.0,
- 0.0, 1.0, 0.0,
-
- // Bottom
- 0.0, -1.0, 0.0,
- 0.0, -1.0, 0.0,
- 0.0, -1.0, 0.0,
- 0.0, -1.0, 0.0,
-
- // Right
- 1.0, 0.0, 0.0,
- 1.0, 0.0, 0.0,
- 1.0, 0.0, 0.0,
- 1.0, 0.0, 0.0,
-
- // Left
- -1.0, 0.0, 0.0,
- -1.0, 0.0, 0.0,
- -1.0, 0.0, 0.0,
- -1.0, 0.0, 0.0
- ];
-
- // Now set up the texture coordinates for the faces.
-
- const textureCoordinates = [
- // Front
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0,
- // Back
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0,
- // Top
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0,
- // Bottom
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0,
- // Right
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0,
- // Left
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0,
- ];
-
- // Build the element array buffer; this specifies the indices
- // into the vertex arrays for each face's vertices.
-
- // This array defines each face as two triangles, using the
- // indices into the vertex array to specify each triangle's
- // position.
-
- const indices = [
- 0, 1, 2, 0, 2, 3, // front
- 4, 5, 6, 4, 6, 7, // back
- 8, 9, 10, 8, 10, 11, // top
- 12, 13, 14, 12, 14, 15, // bottom
- 16, 17, 18, 16, 18, 19, // right
- 20, 21, 22, 20, 22, 23, // left
- ];
-
- // Now send the element array to GL
-
- return {
- position: new Float32Array(positions),
- normal: new Float32Array(vertexNormals),
- textureCoord: new Float32Array(textureCoordinates),
- indices: new Uint16Array(indices),
- };
+ // Now create an array of positions for the cube.
+
+ const positions = [
+ // Front face
+ -1.0, -1.0, 1.0,
+ 1.0, -1.0, 1.0,
+ 1.0, 1.0, 1.0,
+ -1.0, 1.0, 1.0,
+
+ // Back face
+ -1.0, -1.0, -1.0,
+ -1.0, 1.0, -1.0,
+ 1.0, 1.0, -1.0,
+ 1.0, -1.0, -1.0,
+
+ // Top face
+ -1.0, 1.0, -1.0,
+ -1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0,
+ 1.0, 1.0, -1.0,
+
+ // Bottom face
+ -1.0, -1.0, -1.0,
+ 1.0, -1.0, -1.0,
+ 1.0, -1.0, 1.0,
+ -1.0, -1.0, 1.0,
+
+ // Right face
+ 1.0, -1.0, -1.0,
+ 1.0, 1.0, -1.0,
+ 1.0, 1.0, 1.0,
+ 1.0, -1.0, 1.0,
+
+ // Left face
+ -1.0, -1.0, -1.0,
+ -1.0, -1.0, 1.0,
+ -1.0, 1.0, 1.0,
+ -1.0, 1.0, -1.0,
+ ];
+
+ // Set up the normals for the vertices, so that we can compute lighting.
+
+ const vertexNormals = [
+ // Front
+ 0.0, 0.0, 1.0,
+ 0.0, 0.0, 1.0,
+ 0.0, 0.0, 1.0,
+ 0.0, 0.0, 1.0,
+
+ // Back
+ 0.0, 0.0, -1.0,
+ 0.0, 0.0, -1.0,
+ 0.0, 0.0, -1.0,
+ 0.0, 0.0, -1.0,
+
+ // Top
+ 0.0, 1.0, 0.0,
+ 0.0, 1.0, 0.0,
+ 0.0, 1.0, 0.0,
+ 0.0, 1.0, 0.0,
+
+ // Bottom
+ 0.0, -1.0, 0.0,
+ 0.0, -1.0, 0.0,
+ 0.0, -1.0, 0.0,
+ 0.0, -1.0, 0.0,
+
+ // Right
+ 1.0, 0.0, 0.0,
+ 1.0, 0.0, 0.0,
+ 1.0, 0.0, 0.0,
+ 1.0, 0.0, 0.0,
+
+ // Left
+ -1.0, 0.0, 0.0,
+ -1.0, 0.0, 0.0,
+ -1.0, 0.0, 0.0,
+ -1.0, 0.0, 0.0
+ ];
+
+ // Now set up the texture coordinates for the faces.
+
+ const textureCoordinates = [
+ // Front
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ // Back
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ // Top
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ // Bottom
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ // Right
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ // Left
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ ];
+
+ // Build the element array buffer; this specifies the indices
+ // into the vertex arrays for each face's vertices.
+
+ // This array defines each face as two triangles, using the
+ // indices into the vertex array to specify each triangle's
+ // position.
+
+ const indices = [
+ 0, 1, 2, 0, 2, 3, // front
+ 4, 5, 6, 4, 6, 7, // back
+ 8, 9, 10, 8, 10, 11, // top
+ 12, 13, 14, 12, 14, 15, // bottom
+ 16, 17, 18, 16, 18, 19, // right
+ 20, 21, 22, 20, 22, 23, // left
+ ];
+
+ // Now send the element array to GL
+
+ return {
+ position: new Float32Array(positions),
+ normal: new Float32Array(vertexNormals),
+ textureCoord: new Float32Array(textureCoordinates),
+ indices: new Uint16Array(indices),
+ };
}
//
@@ -296,39 +277,37 @@ function initBuffers()
//
async function loadTexture(url: string)
{
- // Because images have to be download over the internet
- // they might take a moment until they are ready.
- // Until then put a single pixel in the texture so we can
- // use it immediately. When the image has finished downloading
- // we'll update the texture with the contents of the image.
- const img = new Image();
- img.src = url;
- await img.decode();
-
- const generateMipmap = isPowerOf2(img.width) && isPowerOf2(img.height);
-
- const texture: IGLTexture = {
- target: "TEXTURE_2D", internalformat: "RGBA", format: "RGBA", type: "UNSIGNED_BYTE",
- sources: [{ source: img }],
- };
-
- let sampler: IGLSampler = {};
-
- if (generateMipmap)
- {
- texture.generateMipmap = generateMipmap;
- }
- else
- {
- sampler = { wrapS: "CLAMP_TO_EDGE", wrapT: "CLAMP_TO_EDGE", minFilter: "LINEAR" };
- }
-
- return { texture, sampler } as IGLSamplerTexture;
+ // Because images have to be download over the internet
+ // they might take a moment until they are ready.
+ // Until then put a single pixel in the texture so we can
+ // use it immediately. When the image has finished downloading
+ // we'll update the texture with the contents of the image.
+ const img = new Image();
+ img.src = url;
+ await img.decode();
+
+ const generateMipmap = isPowerOf2(img.width) && isPowerOf2(img.height);
+
+ const texture: ITexture = {
+ size: [img.width, img.height],
+ format: "rgba8unorm",
+ sources: [{ image: img }],
+ generateMipmap,
+ };
+
+ let sampler: ISampler = {};
+
+ if (!generateMipmap)
+ {
+ sampler = { addressModeU: "clamp-to-edge", addressModeV: "clamp-to-edge", minFilter: "linear" };
+ }
+
+ return { texture, sampler } as IGLSamplerTexture;
}
function isPowerOf2(value: number)
{
- return (value & (value - 1)) === 0;
+ return (value & (value - 1)) === 0;
}
//
@@ -336,53 +315,53 @@ function isPowerOf2(value: number)
//
function drawScene(canvas: HTMLCanvasElement, deltaTime: number)
{
- // Create a perspective matrix, a special matrix that is
- // used to simulate the distortion of perspective in a camera.
- // Our field of view is 45 degrees, with a width/height
- // ratio that matches the display size of the canvas
- // and we only want to see objects between 0.1 units
- // and 100 units away from the camera.
-
- const fieldOfView = 45 * Math.PI / 180; // in radians
- const aspect = canvas.clientWidth / canvas.clientHeight;
- const zNear = 0.1;
- const zFar = 100.0;
- const projectionMatrix = mat4.create();
-
- // note: glmatrix.js always has the first argument
- // as the destination to receive the result.
- mat4.perspective(projectionMatrix,
- fieldOfView,
- aspect,
- zNear,
- zFar);
-
- // Set the drawing position to the "identity" point, which is
- // the center of the scene.
- const modelViewMatrix = mat4.create();
-
- // Now move the drawing position a bit to where we want to
- // start drawing the square.
-
- mat4.translate(modelViewMatrix, // destination matrix
- modelViewMatrix, // matrix to translate
- [-0.0, 0.0, -6.0]); // amount to translate
- mat4.rotate(modelViewMatrix, // destination matrix
- modelViewMatrix, // matrix to rotate
- cubeRotation, // amount to rotate in radians
- [0, 0, 1]); // axis to rotate around (Z)
- mat4.rotate(modelViewMatrix, // destination matrix
- modelViewMatrix, // matrix to rotate
- cubeRotation * 0.7, // amount to rotate in radians
- [0, 1, 0]); // axis to rotate around (X)
-
- const normalMatrix = mat4.create();
- mat4.invert(normalMatrix, modelViewMatrix);
- mat4.transpose(normalMatrix, normalMatrix);
-
- // Update the rotation for the next draw
-
- cubeRotation += deltaTime;
-
- return { projectionMatrix, modelViewMatrix, normalMatrix };
+ // Create a perspective matrix, a special matrix that is
+ // used to simulate the distortion of perspective in a camera.
+ // Our field of view is 45 degrees, with a width/height
+ // ratio that matches the display size of the canvas
+ // and we only want to see objects between 0.1 units
+ // and 100 units away from the camera.
+
+ const fieldOfView = 45 * Math.PI / 180; // in radians
+ const aspect = canvas.clientWidth / canvas.clientHeight;
+ const zNear = 0.1;
+ const zFar = 100.0;
+ const projectionMatrix = mat4.create();
+
+ // note: glmatrix.js always has the first argument
+ // as the destination to receive the result.
+ mat4.perspective(projectionMatrix,
+ fieldOfView,
+ aspect,
+ zNear,
+ zFar);
+
+ // Set the drawing position to the "identity" point, which is
+ // the center of the scene.
+ const modelViewMatrix = mat4.create();
+
+ // Now move the drawing position a bit to where we want to
+ // start drawing the square.
+
+ mat4.translate(modelViewMatrix, // destination matrix
+ modelViewMatrix, // matrix to translate
+ [-0.0, 0.0, -6.0]); // amount to translate
+ mat4.rotate(modelViewMatrix, // destination matrix
+ modelViewMatrix, // matrix to rotate
+ cubeRotation, // amount to rotate in radians
+ [0, 0, 1]); // axis to rotate around (Z)
+ mat4.rotate(modelViewMatrix, // destination matrix
+ modelViewMatrix, // matrix to rotate
+ cubeRotation * 0.7, // amount to rotate in radians
+ [0, 1, 0]); // axis to rotate around (X)
+
+ const normalMatrix = mat4.create();
+ mat4.invert(normalMatrix, modelViewMatrix);
+ mat4.transpose(normalMatrix, normalMatrix);
+
+ // Update the rotation for the next draw
+
+ cubeRotation += deltaTime;
+
+ return { projectionMatrix, modelViewMatrix, normalMatrix };
}
diff --git a/examples/src/webgl-examples/sample8.ts b/examples/src/webgl-examples/sample8.ts
index 8b12c3e906af8352c6b185842357fc062ff93719..4369f56f6003eedef56279f4680b670324878743 100644
--- a/examples/src/webgl-examples/sample8.ts
+++ b/examples/src/webgl-examples/sample8.ts
@@ -1,4 +1,5 @@
-import { IGLRenderObject, IGLRenderPass, IGLSampler, IGLSamplerTexture, IGLTexture, WebGL } from "@feng3d/webgl";
+import { IRenderObject, IRenderPass, ISampler, ITexture } from "@feng3d/render-api";
+import { IGLSamplerTexture, WebGL } from "@feng3d/webgl";
import { mat4 } from "gl-matrix";
let cubeRotation = 0.0;
@@ -12,23 +13,23 @@ main();
//
function main()
{
- const canvas = document.querySelector("#glcanvas") as HTMLCanvasElement;
+ const canvas = document.querySelector("#glcanvas") as HTMLCanvasElement;
- const webgl = new WebGL({ canvasId: "glcanvas", contextId: "webgl" });
+ const webgl = new WebGL({ canvasId: "glcanvas", contextId: "webgl" });
- // Here's where we call the routine that builds all the
- // objects we'll be drawing.
- const buffers = initBuffers();
+ // Here's where we call the routine that builds all the
+ // objects we'll be drawing.
+ const buffers = initBuffers();
- const texture = initTexture();
+ const texture = initTexture();
- const video = setupVideo("../../Firefox.mp4");
+ const video = setupVideo("../../Firefox.mp4");
- const renderObject: IGLRenderObject = {
- pipeline: {
- primitive: { topology: "TRIANGLES" },
- vertex: {
- code: `
+ const renderObject: IRenderObject = {
+ pipeline: {
+ primitive: { topology: "triangle-list" },
+ vertex: {
+ code: `
attribute vec4 aVertexPosition;
attribute vec3 aVertexNormal;
attribute vec2 aTextureCoord;
@@ -56,7 +57,7 @@ function main()
vLighting = ambientLight + (directionalLightColor * directional);
}
` }, fragment: {
- code: `
+ code: `
varying highp vec2 vTextureCoord;
varying highp vec3 vLighting;
@@ -68,126 +69,106 @@ function main()
gl_FragColor = vec4(texelColor.rgb * vLighting, texelColor.a);
}
` },
- depthStencil: { depth: { depthtest: true, depthCompare: "LEQUAL" } }
- },
- vertexArray: {
- vertices: {
- aVertexPosition: {
- type: "FLOAT",
- buffer: {
- target: "ARRAY_BUFFER",
- data: buffers.position,
- usage: "STATIC_DRAW",
- },
- numComponents: 3,
- normalized: false,
+ depthStencil: { depthCompare: "less-equal" }
},
- aVertexNormal: {
- type: "FLOAT",
- buffer: {
- target: "ARRAY_BUFFER",
- data: buffers.normal,
- usage: "STATIC_DRAW",
- },
- numComponents: 3,
- normalized: false,
+ vertices: {
+ aVertexPosition: {
+ format: "float32x3",
+ data: buffers.position,
+ },
+ aVertexNormal: {
+ format: "float32x3",
+ data: buffers.normal,
+ },
+ aTextureCoord: {
+ format: "float32x2",
+ data: buffers.textureCoord,
+ },
},
- aTextureCoord: {
- type: "FLOAT",
- buffer: {
- target: "ARRAY_BUFFER",
- data: buffers.textureCoord,
- usage: "STATIC_DRAW",
- },
- numComponents: 2,
- normalized: false,
+ indices: buffers.indices,
+ uniforms: { uSampler: texture },
+ drawIndexed: { firstIndex: 0, indexCount: 36 },
+ };
+
+ const renderPass: IRenderPass = {
+ descriptor: {
+ colorAttachments: [{
+ clearValue: [0.0, 0.0, 0.0, 1.0],
+ loadOp: "clear",
+ }],
+ depthStencilAttachment: {
+ depthClearValue: 1.0,
+ depthLoadOp: "clear",
+ },
},
- },
- index: { target: "ELEMENT_ARRAY_BUFFER", data: buffers.indices }
- },
- uniforms: { uSampler: texture },
- drawElements: { firstIndex: 0, indexCount: 36 },
- };
-
- const renderPasss: IGLRenderPass = {
- descriptor: {
- colorAttachments: [{
- clearValue: [0.0, 0.0, 0.0, 1.0],
- loadOp: "clear",
- }],
- depthStencilAttachment: {
- depthClearValue: 1.0,
- depthLoadOp: "clear",
- },
- },
- renderObjects: [renderObject],
- };
-
- let then = 0;
-
- // Draw the scene repeatedly
- function render(now: number)
- {
- now *= 0.001; // convert to seconds
- const deltaTime = now - then;
- then = now;
-
- if (copyVideo)
+ renderObjects: [renderObject],
+ };
+
+ let then = 0;
+
+ // Draw the scene repeatedly
+ function render(now: number)
{
- updateTexture(texture.texture, video);
- }
+ now *= 0.001; // convert to seconds
+ const deltaTime = now - then;
+ then = now;
- const { projectionMatrix, modelViewMatrix, normalMatrix } = drawScene(canvas, deltaTime);
+ if (copyVideo)
+ {
+ updateTexture(texture.texture, video);
+ }
- renderObject.uniforms.uProjectionMatrix = projectionMatrix;
- renderObject.uniforms.uModelViewMatrix = modelViewMatrix;
- renderObject.uniforms.uNormalMatrix = normalMatrix;
+ const { projectionMatrix, modelViewMatrix, normalMatrix } = drawScene(canvas, deltaTime);
- webgl.runRenderPass(renderPasss);
+ renderObject.uniforms.uProjectionMatrix = projectionMatrix;
+ renderObject.uniforms.uModelViewMatrix = modelViewMatrix;
+ renderObject.uniforms.uNormalMatrix = normalMatrix;
+ webgl.submit({ commandEncoders: [{ passEncoders: [renderPass] }] });
+
+ requestAnimationFrame(render);
+ }
requestAnimationFrame(render);
- }
- requestAnimationFrame(render);
}
-function setupVideo(url)
+function setupVideo(url: string)
{
- const video = document.createElement("video");
+ const video = document.createElement("video");
- let playing = false;
- let timeupdate = false;
+ let playing = false;
+ let timeupdate = false;
- video.autoplay = true;
- video.muted = true;
- video.loop = true;
+ video.autoplay = true;
+ video.muted = true;
+ video.loop = true;
- // Waiting for these 2 events ensures
- // there is data in the video
+ // Waiting for these 2 events ensures
+ // there is data in the video
- video.addEventListener("playing", function ()
- {
- playing = true;
- checkReady();
- }, true);
+ video.addEventListener("playing", function ()
+ {
+ playing = true;
+ checkReady();
+ }, true);
- video.addEventListener("timeupdate", function ()
- {
- timeupdate = true;
- checkReady();
- }, true);
+ video.addEventListener("timeupdate", function ()
+ {
+ timeupdate = true;
+ checkReady();
+ }, true);
- video.src = url;
- video.play();
+ video.src = url;
+ video.play();
- function checkReady()
- {
- if (playing && timeupdate)
+ function checkReady()
{
- copyVideo = true;
+ if (playing && timeupdate)
+ {
+ copyVideo = true;
+ }
}
- }
- return video;
+ return video;
}
//
@@ -198,140 +179,140 @@ function setupVideo(url)
//
function initBuffers()
{
- // Now create an array of positions for the cube.
-
- const positions = [
- // Front face
- -1.0, -1.0, 1.0,
- 1.0, -1.0, 1.0,
- 1.0, 1.0, 1.0,
- -1.0, 1.0, 1.0,
-
- // Back face
- -1.0, -1.0, -1.0,
- -1.0, 1.0, -1.0,
- 1.0, 1.0, -1.0,
- 1.0, -1.0, -1.0,
-
- // Top face
- -1.0, 1.0, -1.0,
- -1.0, 1.0, 1.0,
- 1.0, 1.0, 1.0,
- 1.0, 1.0, -1.0,
-
- // Bottom face
- -1.0, -1.0, -1.0,
- 1.0, -1.0, -1.0,
- 1.0, -1.0, 1.0,
- -1.0, -1.0, 1.0,
-
- // Right face
- 1.0, -1.0, -1.0,
- 1.0, 1.0, -1.0,
- 1.0, 1.0, 1.0,
- 1.0, -1.0, 1.0,
-
- // Left face
- -1.0, -1.0, -1.0,
- -1.0, -1.0, 1.0,
- -1.0, 1.0, 1.0,
- -1.0, 1.0, -1.0,
- ];
-
- // Set up the normals for the vertices, so that we can compute lighting.
-
- const vertexNormals = [
- // Front
- 0.0, 0.0, 1.0,
- 0.0, 0.0, 1.0,
- 0.0, 0.0, 1.0,
- 0.0, 0.0, 1.0,
-
- // Back
- 0.0, 0.0, -1.0,
- 0.0, 0.0, -1.0,
- 0.0, 0.0, -1.0,
- 0.0, 0.0, -1.0,
-
- // Top
- 0.0, 1.0, 0.0,
- 0.0, 1.0, 0.0,
- 0.0, 1.0, 0.0,
- 0.0, 1.0, 0.0,
-
- // Bottom
- 0.0, -1.0, 0.0,
- 0.0, -1.0, 0.0,
- 0.0, -1.0, 0.0,
- 0.0, -1.0, 0.0,
-
- // Right
- 1.0, 0.0, 0.0,
- 1.0, 0.0, 0.0,
- 1.0, 0.0, 0.0,
- 1.0, 0.0, 0.0,
-
- // Left
- -1.0, 0.0, 0.0,
- -1.0, 0.0, 0.0,
- -1.0, 0.0, 0.0,
- -1.0, 0.0, 0.0,
- ];
-
- // Now set up the texture coordinates for the faces.
-
- const textureCoordinates = [
- // Front
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0,
- // Back
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0,
- // Top
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0,
- // Bottom
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0,
- // Right
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0,
- // Left
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0,
- ];
-
- // This array defines each face as two triangles, using the
- // indices into the vertex array to specify each triangle's
- // position.
-
- const indices = [
- 0, 1, 2, 0, 2, 3, // front
- 4, 5, 6, 4, 6, 7, // back
- 8, 9, 10, 8, 10, 11, // top
- 12, 13, 14, 12, 14, 15, // bottom
- 16, 17, 18, 16, 18, 19, // right
- 20, 21, 22, 20, 22, 23, // left
- ];
-
- return {
- position: new Float32Array(positions),
- normal: new Float32Array(vertexNormals),
- textureCoord: new Float32Array(textureCoordinates),
- indices: new Uint16Array(indices),
- };
+ // Now create an array of positions for the cube.
+
+ const positions = [
+ // Front face
+ -1.0, -1.0, 1.0,
+ 1.0, -1.0, 1.0,
+ 1.0, 1.0, 1.0,
+ -1.0, 1.0, 1.0,
+
+ // Back face
+ -1.0, -1.0, -1.0,
+ -1.0, 1.0, -1.0,
+ 1.0, 1.0, -1.0,
+ 1.0, -1.0, -1.0,
+
+ // Top face
+ -1.0, 1.0, -1.0,
+ -1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0,
+ 1.0, 1.0, -1.0,
+
+ // Bottom face
+ -1.0, -1.0, -1.0,
+ 1.0, -1.0, -1.0,
+ 1.0, -1.0, 1.0,
+ -1.0, -1.0, 1.0,
+
+ // Right face
+ 1.0, -1.0, -1.0,
+ 1.0, 1.0, -1.0,
+ 1.0, 1.0, 1.0,
+ 1.0, -1.0, 1.0,
+
+ // Left face
+ -1.0, -1.0, -1.0,
+ -1.0, -1.0, 1.0,
+ -1.0, 1.0, 1.0,
+ -1.0, 1.0, -1.0,
+ ];
+
+ // Set up the normals for the vertices, so that we can compute lighting.
+
+ const vertexNormals = [
+ // Front
+ 0.0, 0.0, 1.0,
+ 0.0, 0.0, 1.0,
+ 0.0, 0.0, 1.0,
+ 0.0, 0.0, 1.0,
+
+ // Back
+ 0.0, 0.0, -1.0,
+ 0.0, 0.0, -1.0,
+ 0.0, 0.0, -1.0,
+ 0.0, 0.0, -1.0,
+
+ // Top
+ 0.0, 1.0, 0.0,
+ 0.0, 1.0, 0.0,
+ 0.0, 1.0, 0.0,
+ 0.0, 1.0, 0.0,
+
+ // Bottom
+ 0.0, -1.0, 0.0,
+ 0.0, -1.0, 0.0,
+ 0.0, -1.0, 0.0,
+ 0.0, -1.0, 0.0,
+
+ // Right
+ 1.0, 0.0, 0.0,
+ 1.0, 0.0, 0.0,
+ 1.0, 0.0, 0.0,
+ 1.0, 0.0, 0.0,
+
+ // Left
+ -1.0, 0.0, 0.0,
+ -1.0, 0.0, 0.0,
+ -1.0, 0.0, 0.0,
+ -1.0, 0.0, 0.0,
+ ];
+
+ // Now set up the texture coordinates for the faces.
+
+ const textureCoordinates = [
+ // Front
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ // Back
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ // Top
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ // Bottom
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ // Right
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ // Left
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ ];
+
+ // This array defines each face as two triangles, using the
+ // indices into the vertex array to specify each triangle's
+ // position.
+
+ const indices = [
+ 0, 1, 2, 0, 2, 3, // front
+ 4, 5, 6, 4, 6, 7, // back
+ 8, 9, 10, 8, 10, 11, // top
+ 12, 13, 14, 12, 14, 15, // bottom
+ 16, 17, 18, 16, 18, 19, // right
+ 20, 21, 22, 20, 22, 23, // left
+ ];
+
+ return {
+ position: new Float32Array(positions),
+ normal: new Float32Array(vertexNormals),
+ textureCoord: new Float32Array(textureCoordinates),
+ indices: new Uint16Array(indices),
+ };
}
//
@@ -339,21 +320,28 @@ function initBuffers()
//
function initTexture(): IGLSamplerTexture
{
- const texture: IGLTexture = {
- target: "TEXTURE_2D", internalformat: "RGBA", format: "RGBA", type: "UNSIGNED_BYTE",
- sources: [{ width: 1, height: 1, pixels: new Uint8Array([0, 0, 255, 255]) }],
- };
- const sampler: IGLSampler = { wrapS: "CLAMP_TO_EDGE", wrapT: "CLAMP_TO_EDGE", minFilter: "LINEAR" };
-
- return { texture, sampler };
+ const texture: ITexture = {
+ size: [1, 1],
+ format: "rgba8unorm",
+ sources: [{ __type: "TextureDataSource", size: [1, 1], data: new Uint8Array([0, 0, 255, 255]) }],
+ };
+ const sampler: ISampler = { addressModeU: "clamp-to-edge", addressModeV: "clamp-to-edge", minFilter: "linear" };
+
+ return { texture, sampler };
}
//
// copy the video texture
//
-function updateTexture(texture: IGLTexture, video: HTMLVideoElement)
+function updateTexture(texture: ITexture, video: HTMLVideoElement)
{
- texture.sources = [{ source: video }];
+ // 修改纹理尺寸
+ if (texture.size[0] !== video.videoWidth || texture.size[1] !== video.videoHeight)
+ {
+ texture.size = [video.videoWidth, video.videoHeight];
+ }
+
+ texture.sources = [{ image: video }];
}
//
@@ -361,54 +349,54 @@ function updateTexture(texture: IGLTexture, video: HTMLVideoElement)
//
function drawScene(canvas: HTMLCanvasElement, deltaTime: number)
{
- // Create a perspective matrix, a special matrix that is
- // used to simulate the distortion of perspective in a camera.
- // Our field of view is 45 degrees, with a width/height
- // ratio that matches the display size of the canvas
- // and we only want to see objects between 0.1 units
- // and 100 units away from the camera.
-
- const fieldOfView = 45 * Math.PI / 180; // in radians
- const aspect = canvas.clientWidth / canvas.clientHeight;
- const zNear = 0.1;
- const zFar = 100.0;
- const projectionMatrix = mat4.create();
-
- // note: glmatrix.js always has the first argument
- // as the destination to receive the result.
- mat4.perspective(projectionMatrix,
- fieldOfView,
- aspect,
- zNear,
- zFar);
-
- // Set the drawing position to the "identity" point, which is
- // the center of the scene.
- const modelViewMatrix = mat4.create();
-
- // Now move the drawing position a bit to where we want to
- // start drawing the square.
-
- mat4.translate(modelViewMatrix, // destination matrix
- modelViewMatrix, // matrix to translate
- [-0.0, 0.0, -6.0]); // amount to translate
- mat4.rotate(modelViewMatrix, // destination matrix
- modelViewMatrix, // matrix to rotate
- cubeRotation, // amount to rotate in radians
- [0, 0, 1]); // axis to rotate around (Z)
- mat4.rotate(modelViewMatrix, // destination matrix
- modelViewMatrix, // matrix to rotate
- cubeRotation * 0.7, // amount to rotate in radians
- [0, 1, 0]); // axis to rotate around (X)
-
- const normalMatrix = mat4.create();
- mat4.invert(normalMatrix, modelViewMatrix);
- mat4.transpose(normalMatrix, normalMatrix);
-
- // Update the rotation for the next draw
-
- cubeRotation += deltaTime;
-
- return { projectionMatrix, modelViewMatrix, normalMatrix };
+ // Create a perspective matrix, a special matrix that is
+ // used to simulate the distortion of perspective in a camera.
+ // Our field of view is 45 degrees, with a width/height
+ // ratio that matches the display size of the canvas
+ // and we only want to see objects between 0.1 units
+ // and 100 units away from the camera.
+
+ const fieldOfView = 45 * Math.PI / 180; // in radians
+ const aspect = canvas.clientWidth / canvas.clientHeight;
+ const zNear = 0.1;
+ const zFar = 100.0;
+ const projectionMatrix = mat4.create();
+
+ // note: glmatrix.js always has the first argument
+ // as the destination to receive the result.
+ mat4.perspective(projectionMatrix,
+ fieldOfView,
+ aspect,
+ zNear,
+ zFar);
+
+ // Set the drawing position to the "identity" point, which is
+ // the center of the scene.
+ const modelViewMatrix = mat4.create();
+
+ // Now move the drawing position a bit to where we want to
+ // start drawing the square.
+
+ mat4.translate(modelViewMatrix, // destination matrix
+ modelViewMatrix, // matrix to translate
+ [-0.0, 0.0, -6.0]); // amount to translate
+ mat4.rotate(modelViewMatrix, // destination matrix
+ modelViewMatrix, // matrix to rotate
+ cubeRotation, // amount to rotate in radians
+ [0, 0, 1]); // axis to rotate around (Z)
+ mat4.rotate(modelViewMatrix, // destination matrix
+ modelViewMatrix, // matrix to rotate
+ cubeRotation * 0.7, // amount to rotate in radians
+ [0, 1, 0]); // axis to rotate around (X)
+
+ const normalMatrix = mat4.create();
+ mat4.invert(normalMatrix, modelViewMatrix);
+ mat4.transpose(normalMatrix, normalMatrix);
+
+ // Update the rotation for the next draw
+
+ cubeRotation += deltaTime;
+
+ return { projectionMatrix, modelViewMatrix, normalMatrix };
}
diff --git a/package.json b/package.json
index ebaad3b5fd2adc5068412dcd3159f3c8f643f381..8e7a92214036ea657c47c6ec60143a4b4b0caef5 100644
--- a/package.json
+++ b/package.json
@@ -3,7 +3,6 @@
"version": "0.0.2",
"description": "渲染库",
"author": "feng",
- "license": "MIT",
"type": "module",
"main": "./src/index.ts",
"types": "./src/index.ts",
@@ -61,7 +60,8 @@
"vitest": "^0.32.2"
},
"dependencies": {
+ "@feng3d/render-api": "0.0.1",
"@feng3d/serialization": "^0.8.1",
- "@feng3d/watcher": "^0.8.3"
+ "@feng3d/watcher": "^0.8.7"
}
}
\ No newline at end of file
diff --git a/src/RunWebGL.ts b/src/RunWebGL.ts
new file mode 100644
index 0000000000000000000000000000000000000000..051166be24c979849d944d6283fc7f1be2f9d5e9
--- /dev/null
+++ b/src/RunWebGL.ts
@@ -0,0 +1,942 @@
+import { getBlendConstantColor, IBlendComponent, IBufferBinding, IColorTargetState, ICommandEncoder, ICopyBufferToBuffer, ICopyTextureToTexture, ICullFace, IDepthStencilState, IDrawIndexed, IDrawVertex, IFrontFace, IIndicesDataTypes, IPrimitiveState, IRenderObject, IRenderPass, IRenderPassColorAttachment, IRenderPassDepthStencilAttachment, IRenderPassDescriptor, IRenderPassObject, IRenderPipeline, ISampler, IScissorRect, ISubmit, ITextureView, IUniforms, IVertexAttribute, IVertexAttributes, IViewport, TypedArray, UnReadonly } from "@feng3d/render-api";
+
+import { getGLBuffer } from "./caches/getGLBuffer";
+import { getGLFramebuffer } from "./caches/getGLFramebuffer";
+import { getGLProgram } from "./caches/getGLProgram";
+import { getGLRenderOcclusionQuery } from "./caches/getGLRenderOcclusionQuery";
+import { getGLSampler, getIGLTextureMagFilter, getIGLTextureMinFilter, getIGLTextureWrap } from "./caches/getGLSampler";
+import { getGLTransformFeedback } from "./caches/getGLTransformFeedback";
+import { getIGLBlitFramebuffer } from "./caches/getIGLBlitFramebuffer";
+import { getIGLDrawMode, IGLDrawMode } from "./caches/getIGLDrawMode";
+import { getIGLRenderPassDescriptorWithMultisample } from "./caches/getIGLRenderPassDescriptorWithMultisample";
+import { getIGLTextureTarget } from "./caches/getIGLTextureTarget";
+import { _GL_Submit_Times } from "./const/const";
+import { IGLUniformBufferType } from "./const/IGLUniformType";
+import { IGLBlitFramebuffer } from "./data/IGLBlitFramebuffer";
+import { IGLDrawElementType, IGLUniformBuffer } from "./data/IGLBuffer";
+import { IGLCompareFunction, IGLStencilFunc, IGLStencilOp } from "./data/IGLDepthStencilState";
+import { IGLOcclusionQuery } from "./data/IGLOcclusionQuery";
+import { IGLTextureMagFilter, IGLTextureMinFilter, IGLTextureWrap } from "./data/IGLSampler";
+import { IGLSamplerTexture } from "./data/IGLSamplerTexture";
+import { IGLTextureTarget } from "./data/IGLTexture";
+import { IGLTransformFeedback } from "./data/IGLTransformFeedback";
+import { IGLTransformFeedbackObject, IGLTransformFeedbackPass, IGLTransformFeedbackPipeline } from "./data/IGLTransformFeedbackPass";
+import { IUniformItemInfo } from "./data/IGLUniformInfo";
+import { getGLTexture } from "./internal";
+import { getIGLIndexBuffer, getIGLUniformBuffer, getIGLVertexBuffer } from "./runs/getIGLBuffer";
+import { getIGLBlendEquation, getIGLBlendFactor, IGLBlendEquation, IGLBlendFactor } from "./runs/runColorTargetStates";
+import { getIGLCompareFunction } from "./runs/runDepthState";
+import { getIGLStencilFunc, getIGLStencilOp } from "./runs/runStencilState";
+import { ChainMap } from "./utils/ChainMap";
+import { getGLRenderPassAttachmentSize } from "./utils/getGLRenderPassAttachmentSize";
+import { getIGLCullFace, IGLCullFace } from "./utils/getIGLCullFace";
+import { getIGLFrontFace, IGLFrontFace } from "./utils/getIGLFrontFace";
+import { getIGLVertexFormat } from "./utils/getIVertexFormat";
+import { updateBufferBinding } from "./utils/updateBufferBinding";
+
+declare global
+{
+ interface WebGLRenderingContext
+ {
+ _vertexArrays: ChainMap<[IRenderPipeline, IVertexAttributes, IIndicesDataTypes], WebGLVertexArrayObject>;
+ }
+}
+
+declare global
+{
+ interface WebGLTexture
+ {
+ minFilter?: IGLTextureMinFilter,
+ magFilter?: IGLTextureMagFilter,
+ wrapS?: IGLTextureWrap,
+ wrapT?: IGLTextureWrap,
+ wrapR?: IGLTextureWrap,
+ maxAnisotropy?: number,
+ lodMinClamp?: number;
+ lodMaxClamp?: number;
+ }
+}
+
+export class RunWebGL
+{
+ runSubmit(gl: WebGLRenderingContext, submit: ISubmit)
+ {
+ const commandBuffers = submit.commandEncoders.map((v) =>
+ {
+ const commandBuffer = this.runCommandEncoder(gl, v);
+
+ return commandBuffer;
+ });
+
+ // 派发提交WebGPU事件
+ gl[_GL_Submit_Times] = ~~gl[_GL_Submit_Times] + 1;
+ }
+
+ protected runCommandEncoder(gl: WebGLRenderingContext, commandEncoder: ICommandEncoder)
+ {
+ commandEncoder.passEncoders.forEach((passEncoder) =>
+ {
+ if (!passEncoder.__type)
+ {
+ this.runRenderPass(gl, passEncoder as IRenderPass);
+ }
+ else if (passEncoder.__type === "RenderPass")
+ {
+ this.runRenderPass(gl, passEncoder);
+ }
+ else if (passEncoder.__type === "TransformFeedbackPass")
+ {
+ this.runTransformFeedbackPass(gl, passEncoder);
+ }
+ else if (passEncoder.__type === "BlitFramebuffer")
+ {
+ this.runBlitFramebuffer(gl, passEncoder);
+ }
+ else if (passEncoder.__type === "CopyTextureToTexture")
+ {
+ this.runCopyTextureToTexture(gl, passEncoder);
+ }
+ else if (passEncoder.__type === "CopyBufferToBuffer")
+ {
+ this.runCopyBuffer(gl, passEncoder);
+ }
+ else
+ {
+ console.error(`未处理 passEncoder ${passEncoder}`);
+ }
+ });
+ }
+
+ protected runTransformFeedbackPass(gl: WebGLRenderingContext, transformFeedbackPass: IGLTransformFeedbackPass)
+ {
+ // 执行变换反馈通道时关闭光栅化功能
+ if (gl instanceof WebGL2RenderingContext)
+ {
+ gl.enable(gl.RASTERIZER_DISCARD);
+ }
+ transformFeedbackPass.transformFeedbackObjects.forEach((transformFeedbackObject) =>
+ {
+ this.runTransformFeedbackObject(gl, transformFeedbackObject);
+ });
+ if (gl instanceof WebGL2RenderingContext)
+ {
+ gl.disable(gl.RASTERIZER_DISCARD);
+ }
+ }
+
+ protected runRenderPass(gl: WebGLRenderingContext, renderPass: IRenderPass)
+ {
+ // 获取附件尺寸
+ const attachmentSize = getGLRenderPassAttachmentSize(gl, renderPass.descriptor);
+
+ // 处理不被遮挡查询
+ const occlusionQuery = getGLRenderOcclusionQuery(gl, renderPass.renderObjects);
+ //
+ occlusionQuery.init();
+
+ if (renderPass.descriptor?.sampleCount && (renderPass.descriptor.colorAttachments[0].view as ITextureView).texture)
+ {
+ const { passDescriptor, blitFramebuffer } = getIGLRenderPassDescriptorWithMultisample(renderPass.descriptor);
+
+ this.runRenderPassDescriptor(gl, passDescriptor);
+
+ this.runRenderObjects(gl, attachmentSize, renderPass.renderObjects);
+
+ this.runBlitFramebuffer(gl, blitFramebuffer);
+ }
+ else
+ {
+ this.runRenderPassDescriptor(gl, renderPass.descriptor);
+
+ this.runRenderObjects(gl, attachmentSize, renderPass.renderObjects);
+ }
+
+ occlusionQuery.resolve(renderPass);
+ }
+
+ private runRenderPassDescriptor(gl: WebGLRenderingContext, passDescriptor: IRenderPassDescriptor)
+ {
+ passDescriptor = passDescriptor || {};
+
+ //
+ const colorAttachment = Object.assign({}, defaultRenderPassColorAttachment, passDescriptor.colorAttachments?.[0]);
+
+ //
+ const framebuffer = getGLFramebuffer(gl, passDescriptor);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+
+ //
+ const { clearValue, loadOp } = colorAttachment;
+ gl.clearColor(clearValue[0], clearValue[1], clearValue[2], clearValue[3]);
+
+ //
+ const depthStencilAttachment = Object.assign({}, defaultDepthStencilAttachment, passDescriptor.depthStencilAttachment);
+ const { depthClearValue, depthLoadOp, stencilClearValue, stencilLoadOp } = depthStencilAttachment;
+
+ gl.clearDepth(depthClearValue);
+ gl.clearStencil(stencilClearValue);
+
+ //
+ gl.clear((loadOp === "clear" ? gl.COLOR_BUFFER_BIT : 0)
+ | (depthLoadOp === "clear" ? gl.DEPTH_BUFFER_BIT : 0)
+ | (stencilLoadOp === "clear" ? gl.STENCIL_BUFFER_BIT : 0)
+ );
+ }
+
+ private runRenderObjects(gl: WebGLRenderingContext, attachmentSize: { width: number, height: number }, renderObjects?: readonly IRenderPassObject[])
+ {
+ renderObjects?.forEach((renderObject) =>
+ {
+ if (renderObject.__type === "OcclusionQuery")
+ {
+ this.runOcclusionQuery(gl, attachmentSize, renderObject);
+ }
+ else
+ {
+ this.runRenderObject(gl, attachmentSize, renderObject);
+ }
+ });
+ }
+
+ private runRenderObject(gl: WebGLRenderingContext, attachmentSize: { width: number, height: number }, renderObject: IRenderObject)
+ {
+ const { viewport, scissorRect, pipeline, vertices, indices, uniforms, drawIndexed, drawVertex } = renderObject;
+
+ const topology = pipeline.primitive?.topology || "triangle-list";
+ const drawMode = getIGLDrawMode(topology);
+
+ this.runViewPort(gl, attachmentSize, viewport);
+
+ this.runScissor(gl, attachmentSize, scissorRect);
+
+ this.runRenderPipeline(gl, pipeline);
+
+ this.runVertexArray(gl, pipeline, vertices, indices);
+
+ this.runUniforms(gl, pipeline, uniforms);
+
+ if (drawVertex)
+ {
+ this.runDrawVertex(gl, drawMode, drawVertex);
+ }
+ if (drawIndexed)
+ {
+ this.runDrawIndexed(gl, drawMode, indices, drawIndexed);
+ }
+ }
+
+ private runTransformFeedbackObject(gl: WebGLRenderingContext, renderObject: IGLTransformFeedbackObject)
+ {
+ const { pipeline, vertices, uniforms, transformFeedback, drawVertex } = renderObject;
+
+ const drawMode = getIGLDrawMode("point-list");
+
+ this.runTransformFeedbackPipeline(gl, pipeline);
+
+ this.runVertexArray(gl, pipeline, vertices, undefined);
+
+ this.runUniforms(gl, pipeline, uniforms);
+
+ this.runTransformFeedback(gl, transformFeedback, drawMode);
+
+ this.runDrawVertex(gl, drawMode, drawVertex);
+
+ this.endTransformFeedback(gl, transformFeedback);
+ }
+
+ private endTransformFeedback(gl: WebGLRenderingContext, transformFeedback: IGLTransformFeedback)
+ {
+ //
+ if (transformFeedback)
+ {
+ if (gl instanceof WebGL2RenderingContext)
+ {
+ gl.endTransformFeedback();
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, null);
+ }
+ }
+ }
+
+ private runDrawIndexed(gl: WebGLRenderingContext, drawMode: IGLDrawMode, indices: IIndicesDataTypes, drawIndexed: IDrawIndexed)
+ {
+ const type: IGLDrawElementType = indices.BYTES_PER_ELEMENT === 2 ? "UNSIGNED_SHORT" : "UNSIGNED_INT";
+ //
+ const indexCount = drawIndexed.indexCount;
+ const firstIndex = drawIndexed.firstIndex || 0;
+ const instanceCount = drawIndexed.instanceCount || 1;
+ //
+ const offset = firstIndex * indices.BYTES_PER_ELEMENT;
+
+ //
+ if (instanceCount > 1)
+ {
+ if (gl instanceof WebGL2RenderingContext)
+ {
+ gl.drawElementsInstanced(gl[drawMode], indexCount, gl[type], offset, instanceCount);
+ }
+ else
+ {
+ const extension = gl.getExtension("ANGLE_instanced_arrays");
+ extension.drawElementsInstancedANGLE(gl[drawMode], indexCount, gl[type], offset, instanceCount);
+ }
+ }
+ else
+ {
+ gl.drawElements(gl[drawMode], indexCount, gl[type], offset);
+ }
+ }
+
+ private runDrawVertex(gl: WebGLRenderingContext, drawMode: IGLDrawMode, drawArrays: IDrawVertex)
+ {
+ //
+ const vertexCount = drawArrays.vertexCount;
+ const firstVertex = drawArrays.firstVertex || 0;
+ const instanceCount = drawArrays.instanceCount || 1;
+
+ if (instanceCount > 1)
+ {
+ if (gl instanceof WebGL2RenderingContext)
+ {
+ gl.drawArraysInstanced(gl[drawMode], firstVertex, vertexCount, instanceCount);
+ }
+ else
+ {
+ const extension = gl.getExtension("ANGLE_instanced_arrays");
+ extension.drawArraysInstancedANGLE(gl[drawMode], firstVertex, vertexCount, instanceCount);
+ }
+ }
+ else
+ {
+ gl.drawArrays(gl[drawMode], firstVertex, vertexCount);
+ }
+ }
+
+ /**
+ * 激活常量
+ */
+ private runUniforms(gl: WebGLRenderingContext, pipeline: IRenderPipeline, uniforms: IUniforms)
+ {
+ const webGLProgram = getGLProgram(gl, pipeline);
+
+ webGLProgram.uniforms.forEach((uniformInfo) =>
+ {
+ const { name, type, items, isTexture, inBlock } = uniformInfo;
+ if (inBlock) return;
+
+ items.forEach((v) =>
+ {
+ const { paths } = v;
+
+ let uniformData = uniforms[paths[0]];
+ for (let i = 1; i < paths.length; i++)
+ {
+ uniformData = uniformData[paths[i]];
+ }
+ if (uniformData === undefined)
+ {
+ console.error(`沒有找到Uniform ${name} 數據!`);
+ }
+
+ if (isTexture)
+ {
+ this.runSamplerTexture(gl, v, uniformData as IGLSamplerTexture);
+ }
+ else
+ {
+ this.runUniform(gl, type as IGLUniformBufferType, v, uniformData);
+ }
+ });
+ });
+
+ if (gl instanceof WebGL2RenderingContext)
+ {
+ webGLProgram.uniformBlocks.forEach((uniformBlock) =>
+ {
+ const { name, index } = uniformBlock;
+ const uniformData = uniforms[name] as TypedArray | IBufferBinding;
+
+ //
+ let buffer: IGLUniformBuffer;
+ const typedArray = uniformData as TypedArray;
+ if (typedArray.buffer && typedArray.BYTES_PER_ELEMENT)
+ {
+ buffer = getIGLUniformBuffer(typedArray);
+ }
+ else
+ {
+ const bufferBinding = uniforms[name] as IBufferBinding;
+ updateBufferBinding(uniformBlock.bufferBindingInfo, bufferBinding);
+ buffer = getIGLUniformBuffer(bufferBinding.bufferView);
+ }
+ (buffer as UnReadonly).label = buffer.label || (`UniformBuffer ${name}`);
+
+ //
+ const webGLBuffer = getGLBuffer(gl, buffer);
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, index, webGLBuffer);
+ });
+ }
+ }
+
+ private runSamplerTexture(gl: WebGLRenderingContext, uniformInfo: IUniformItemInfo, samplerTexture: IGLSamplerTexture)
+ {
+ const { texture, sampler } = samplerTexture;
+ const { location, textureID } = uniformInfo;
+
+ const textureTarget = getIGLTextureTarget(texture.dimension);
+
+ // 设置纹理所在采样编号
+ gl.uniform1i(location, textureID);
+ //
+ const webGLTexture = getGLTexture(gl, texture);
+ gl.activeTexture(gl[`TEXTURE${textureID}`]);
+ // 绑定纹理
+ gl.bindTexture(gl[textureTarget], webGLTexture);
+
+ // 运行采样器
+ this.runSampler(gl, textureTarget, webGLTexture, sampler, textureID);
+
+ return webGLTexture;
+ }
+
+ /**
+ * 设置采样参数
+ */
+ private runSampler(gl: WebGLRenderingContext, textureTarget: IGLTextureTarget, webGLTexture: WebGLTexture, sampler: ISampler, textureID: number)
+ {
+ if (gl instanceof WebGL2RenderingContext)
+ {
+ const webGLSampler = getGLSampler(gl, sampler);
+ gl.bindSampler(textureID, webGLSampler);
+ }
+ else
+ {
+ const minFilter: IGLTextureMinFilter = getIGLTextureMinFilter(sampler.minFilter, sampler.mipmapFilter);
+ const magFilter: IGLTextureMagFilter = getIGLTextureMagFilter(sampler.magFilter);
+ const wrapS: IGLTextureWrap = getIGLTextureWrap(sampler.addressModeU);
+ const wrapT: IGLTextureWrap = getIGLTextureWrap(sampler.addressModeV);
+
+ // 设置纹理参数
+ if (webGLTexture.minFilter !== minFilter)
+ {
+ gl.texParameteri(gl[textureTarget], gl.TEXTURE_MIN_FILTER, gl[minFilter]);
+ webGLTexture.minFilter = minFilter;
+ }
+ if (webGLTexture.magFilter !== magFilter)
+ {
+ gl.texParameteri(gl[textureTarget], gl.TEXTURE_MAG_FILTER, gl[magFilter]);
+ webGLTexture.magFilter = magFilter;
+ }
+ if (webGLTexture.wrapS !== wrapS)
+ {
+ gl.texParameteri(gl[textureTarget], gl.TEXTURE_WRAP_S, gl[wrapS]);
+ webGLTexture.wrapS = wrapS;
+ }
+ if (webGLTexture.wrapT !== wrapT)
+ {
+ gl.texParameteri(gl[textureTarget], gl.TEXTURE_WRAP_T, gl[wrapT]);
+ webGLTexture.wrapT = wrapT;
+ }
+ }
+
+ //
+ const maxAnisotropy = sampler?.maxAnisotropy || 1;
+ if (webGLTexture.maxAnisotropy !== maxAnisotropy)
+ {
+ const extension = gl.getExtension("EXT_texture_filter_anisotropic");
+ if (extension)
+ {
+ gl.texParameterf(gl[textureTarget], extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min(maxAnisotropy, gl._capabilities.maxAnisotropy));
+ }
+ webGLTexture.maxAnisotropy = maxAnisotropy;
+ }
+ }
+
+ /**
+ * 设置环境Uniform数据
+ */
+ private runUniform(gl: WebGLRenderingContext, type: IGLUniformBufferType, uniformInfo: IUniformItemInfo, data: any)
+ {
+ if (typeof data === 'number')
+ {
+ data = [data];
+ }
+ const location = uniformInfo.location;
+ switch (type)
+ {
+ case "BOOL":
+ case "INT":
+ gl.uniform1iv(location, data);
+ break;
+ case "BOOL_VEC2":
+ case "INT_VEC2":
+ gl.uniform2iv(location, data);
+ break;
+ case "BOOL_VEC3":
+ case "INT_VEC3":
+ gl.uniform3iv(location, data);
+ break;
+ case "BOOL_VEC4":
+ case "INT_VEC4":
+ gl.uniform4iv(location, data);
+ break;
+ case "FLOAT":
+ gl.uniform1fv(location, [data]);
+ break;
+ case "FLOAT_VEC2":
+ gl.uniform2fv(location, data);
+ break;
+ case "FLOAT_VEC3":
+ gl.uniform3fv(location, data);
+ break;
+ case "FLOAT_VEC4":
+ gl.uniform4fv(location, data);
+ break;
+ case "FLOAT_MAT2":
+ gl.uniformMatrix2fv(location, false, data);
+ break;
+ case "FLOAT_MAT3":
+ gl.uniformMatrix3fv(location, false, data);
+ break;
+ case "FLOAT_MAT4":
+ gl.uniformMatrix4fv(location, false, data);
+ break;
+ case "UNSIGNED_INT":
+ (gl as any as WebGL2RenderingContext).uniform1uiv(location, data);
+ break;
+ case "UNSIGNED_INT_VEC2":
+ (gl as any as WebGL2RenderingContext).uniform2uiv(location, data);
+ break;
+ case "UNSIGNED_INT_VEC3":
+ (gl as any as WebGL2RenderingContext).uniform3uiv(location, data);
+ break;
+ case "UNSIGNED_INT_VEC4":
+ (gl as any as WebGL2RenderingContext).uniform4uiv(location, data);
+ break;
+ case "FLOAT_MAT2x3":
+ (gl as any as WebGL2RenderingContext).uniformMatrix2x3fv(location, false, data);
+ break;
+ case "FLOAT_MAT2x4":
+ (gl as any as WebGL2RenderingContext).uniformMatrix2x4fv(location, false, data);
+ break;
+ case "FLOAT_MAT3x2":
+ (gl as any as WebGL2RenderingContext).uniformMatrix3x2fv(location, false, data);
+ break;
+ case "FLOAT_MAT3x4":
+ (gl as any as WebGL2RenderingContext).uniformMatrix3x4fv(location, false, data);
+ break;
+ case "FLOAT_MAT4x2":
+ (gl as any as WebGL2RenderingContext).uniformMatrix4x2fv(location, false, data);
+ break;
+ case "FLOAT_MAT4x3":
+ (gl as any as WebGL2RenderingContext).uniformMatrix4x3fv(location, false, data);
+ break;
+ default:
+ console.error(`无法识别的uniform类型 ${uniformInfo.paths} ${type}`);
+ }
+ }
+
+ /**
+ * 执行设置或者上传渲染对象的顶点以及索引数据。
+ */
+ private runVertexArray(gl: WebGLRenderingContext, pipeline: IRenderPipeline, vertices: IVertexAttributes, indices: IIndicesDataTypes)
+ {
+ if (!vertices && !indices) return;
+
+ let webGLVertexArrayObject: WebGLVertexArrayObject;
+ if (gl instanceof WebGL2RenderingContext)
+ {
+ webGLVertexArrayObject = gl._vertexArrays.get([pipeline, vertices, indices]);
+ if (webGLVertexArrayObject)
+ {
+ gl.bindVertexArray(webGLVertexArrayObject);
+
+ return;
+ }
+
+ webGLVertexArrayObject = gl.createVertexArray();
+ gl.bindVertexArray(webGLVertexArrayObject);
+ gl._vertexArrays.set([pipeline, vertices, indices], webGLVertexArrayObject);
+ }
+
+ const shaderResult = getGLProgram(gl, pipeline);
+
+ //
+ shaderResult.attributes.forEach((activeInfo) =>
+ {
+ const { name, location } = activeInfo;
+ // 处理 WebGL 内置属性 gl_VertexID 等
+ if (location < 0) return;
+
+ const attribute = vertices[name];
+ if (!attribute)
+ {
+ console.error(`缺少顶点 ${name} 数据!`);
+ }
+
+ this.runVertexAttribute(gl, location, attribute);
+ });
+
+ this.runIndexBuffer(gl, indices);
+ }
+
+ private runIndexBuffer(gl: WebGLRenderingContext, indices?: IIndicesDataTypes)
+ {
+ if (!indices) return;
+
+ const indexBuffer = getIGLIndexBuffer(indices);
+
+ const buffer = getGLBuffer(gl, indexBuffer);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer);
+ }
+
+ private runVertexAttribute(gl: WebGLRenderingContext, location: number, attribute: IVertexAttribute)
+ {
+ const { stepMode, format } = attribute;
+ let { arrayStride, offset } = attribute;
+
+ const glVertexFormat = getIGLVertexFormat(format);
+ const { numComponents, normalized, type } = glVertexFormat;
+
+ gl.enableVertexAttribArray(location);
+
+ if (stepMode === "instance")
+ {
+ if (gl instanceof WebGL2RenderingContext)
+ {
+ gl.vertexAttribDivisor(location, 1);
+ }
+ else
+ {
+ const extension = gl.getExtension("ANGLE_instanced_arrays");
+ extension.vertexAttribDivisorANGLE(location, 1);
+ }
+ }
+
+ //
+ arrayStride = arrayStride || 0;
+ offset = offset || 0;
+
+ //
+ const buffer = getIGLVertexBuffer(attribute.data);
+ const webGLBuffer = getGLBuffer(gl, buffer);
+ gl.bindBuffer(gl.ARRAY_BUFFER, webGLBuffer);
+
+ //
+ if (gl instanceof WebGL2RenderingContext && (type === "INT" || type === "UNSIGNED_INT"))
+ {
+ gl.vertexAttribIPointer(location, numComponents, gl[type], arrayStride, offset);
+ }
+ else
+ {
+ gl.vertexAttribPointer(location, numComponents, gl[type], normalized, arrayStride, offset);
+ }
+ }
+
+ private runTransformFeedback(gl: WebGLRenderingContext, transformFeedback: IGLTransformFeedback, topology: IGLDrawMode)
+ {
+ if (gl instanceof WebGL2RenderingContext)
+ {
+ if (transformFeedback)
+ {
+ const webGLTransformFeedback = getGLTransformFeedback(gl, transformFeedback);
+
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, webGLTransformFeedback);
+
+ gl.beginTransformFeedback(gl[topology]);
+ }
+ else
+ {
+ gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
+ }
+ }
+ else if (transformFeedback)
+ {
+ console.log(`WebGL1 不支持顶点着色器回写数据功能!`);
+ }
+ }
+
+ private runTransformFeedbackPipeline(gl: WebGLRenderingContext, renderPipeline: IGLTransformFeedbackPipeline)
+ {
+ const program = getGLProgram(gl, renderPipeline);
+ gl.useProgram(program);
+ }
+
+ private runRenderPipeline(gl: WebGLRenderingContext, renderPipeline: IRenderPipeline)
+ {
+ this.runProgram(gl, renderPipeline);
+
+ this.runPrimitiveState(gl, renderPipeline?.primitive);
+
+ this.runDepthState(gl, renderPipeline.depthStencil);
+ this.runStencilState(gl, renderPipeline.depthStencil);
+ }
+
+ private runStencilState(gl: WebGLRenderingContext, depthStencil?: IDepthStencilState)
+ {
+ const { stencilFront, stencilBack } = { ...depthStencil };
+ //
+ if (stencilFront || stencilBack)
+ {
+ const ref: number = depthStencil.stencilReference ?? 0;
+ const readMask = depthStencil.stencilReadMask ?? 0xFFFFFFFF;
+ const writeMask = depthStencil.stencilWriteMask ?? 0xFFFFFFFF;
+
+ gl.enable(gl.STENCIL_TEST);
+
+ if (stencilFront)
+ {
+ const func: IGLStencilFunc = getIGLStencilFunc(stencilFront.compare ?? "always");
+ const fail: IGLStencilOp = getIGLStencilOp(stencilFront.failOp);
+ const zfail: IGLStencilOp = getIGLStencilOp(stencilFront.depthFailOp);
+ const zpass: IGLStencilOp = getIGLStencilOp(stencilFront.passOp);
+ //
+ gl.stencilFuncSeparate(gl.FRONT, gl[func], ref, readMask);
+ gl.stencilOpSeparate(gl.FRONT, gl[fail], gl[zfail], gl[zpass]);
+ gl.stencilMaskSeparate(gl.FRONT, writeMask);
+ }
+ if (stencilBack)
+ {
+ const func: IGLStencilFunc = getIGLStencilFunc(stencilBack.compare ?? "always");
+ const fail: IGLStencilOp = getIGLStencilOp(stencilBack.failOp);
+ const zfail: IGLStencilOp = getIGLStencilOp(stencilBack.depthFailOp);
+ const zpass: IGLStencilOp = getIGLStencilOp(stencilBack.passOp);
+ //
+ gl.stencilFuncSeparate(gl.BACK, gl[func], ref, readMask);
+ gl.stencilOpSeparate(gl.BACK, gl[fail], gl[zfail], gl[zpass]);
+ gl.stencilMaskSeparate(gl.BACK, writeMask);
+ }
+ }
+ else
+ {
+ gl.disable(gl.STENCIL_TEST);
+ }
+ }
+
+ private runDepthState(gl: WebGLRenderingContext, depthStencil?: IDepthStencilState)
+ {
+ if (depthStencil && (depthStencil.depthWriteEnabled || depthStencil.depthCompare !== "always"))
+ {
+ const depthCompare: IGLCompareFunction = getIGLCompareFunction(depthStencil.depthCompare ?? 'less');
+ const depthWriteEnabled = depthStencil.depthWriteEnabled ?? true;
+ //
+ gl.enable(gl.DEPTH_TEST);
+ //
+ gl.depthFunc(gl[depthCompare]);
+ gl.depthMask(depthWriteEnabled);
+
+ //
+ if (depthStencil.depthBias || depthStencil.depthBiasSlopeScale)
+ {
+ const factor = depthStencil.depthBiasSlopeScale ?? 0;
+ const units = depthStencil.depthBias ?? 0;
+ //
+ gl.enable(gl.POLYGON_OFFSET_FILL);
+ gl.polygonOffset(factor, units);
+ }
+ else
+ {
+ gl.disable(gl.POLYGON_OFFSET_FILL);
+ }
+ }
+ else
+ {
+ gl.disable(gl.DEPTH_TEST);
+ }
+ }
+
+ private runPrimitiveState(gl: WebGLRenderingContext, primitive?: IPrimitiveState)
+ {
+ const cullFace: ICullFace = primitive?.cullFace || "none";
+ const frontFace: IFrontFace = primitive?.frontFace || "ccw";
+
+ const enableCullFace = cullFace !== "none";
+ const glCullMode: IGLCullFace = getIGLCullFace(cullFace);
+ const glFrontFace: IGLFrontFace = getIGLFrontFace(frontFace);
+
+ if (enableCullFace)
+ {
+ gl.enable(gl.CULL_FACE);
+ gl.cullFace(gl[glCullMode]);
+ gl.frontFace(gl[glFrontFace]);
+ }
+ else
+ {
+ gl.disable(gl.CULL_FACE);
+ }
+ }
+
+ private runProgram(gl: WebGLRenderingContext, pipeline: IRenderPipeline)
+ {
+ const program = getGLProgram(gl, pipeline);
+ gl.useProgram(program);
+
+ //
+ this.runColorTargetStates(gl, pipeline.fragment.targets);
+ }
+
+ private runColorTargetStates(gl: WebGLRenderingContext, targets?: readonly IColorTargetState[])
+ {
+ //
+ const colorMask = targets?.[0]?.writeMask || [true, true, true, true];
+ gl.colorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]);
+
+ //
+ let blend = targets?.[0]?.blend;
+ if (blend)
+ {
+ const color: IBlendComponent = blend.color;
+ const alpha: IBlendComponent = blend.alpha;
+
+ const colorOperation: IGLBlendEquation = getIGLBlendEquation(color?.operation) || "FUNC_ADD";
+ const colorSrcFactor: IGLBlendFactor = getIGLBlendFactor(color?.srcFactor, color?.operation) || "SRC_ALPHA";
+ const colorDstFactor: IGLBlendFactor = getIGLBlendFactor(color?.dstFactor, color?.operation) || "ONE_MINUS_SRC_ALPHA";
+ //
+ const alphaOperation: IGLBlendEquation = getIGLBlendEquation(alpha?.operation) || colorOperation;
+ const alphaSrcFactor: IGLBlendFactor = getIGLBlendFactor(alpha?.srcFactor, color?.operation) || colorSrcFactor;
+ const alphaDstFactor: IGLBlendFactor = getIGLBlendFactor(alpha?.dstFactor, color?.operation) || colorDstFactor;
+
+ // 当混合系数用到了混合常量值时设置混合常量值。
+ const constantColor = getBlendConstantColor(blend);
+ if (constantColor)
+ {
+ const constantColor = blend.constantColor ?? [0, 0, 0, 0];
+ gl.blendColor(constantColor[0], constantColor[1], constantColor[2], constantColor[3]);
+ }
+
+ //
+ gl.enable(gl.BLEND);
+ gl.blendEquationSeparate(gl[colorOperation], gl[alphaOperation]);
+ gl.blendFuncSeparate(gl[colorSrcFactor], gl[colorDstFactor], gl[alphaSrcFactor], gl[alphaDstFactor]);
+ }
+ else
+ {
+ gl.disable(gl.BLEND);
+ }
+ }
+
+ private runOcclusionQuery(gl: WebGLRenderingContext, attachmentSize: { width: number, height: number }, occlusionQuery: IGLOcclusionQuery)
+ {
+ // 开始查询
+ occlusionQuery._step.begin();
+
+ // 正常渲染对象列表
+ occlusionQuery.renderObjects.forEach((renderObject) =>
+ {
+ this.runRenderObject(gl, attachmentSize, renderObject);
+ });
+
+ // 结束查询
+ occlusionQuery._step.end();
+ }
+
+ private runViewPort(gl: WebGLRenderingContext, attachmentSize: { width: number, height: number }, viewport: IViewport)
+ {
+ if (viewport)
+ {
+ const isYup = viewport.isYup ?? true;
+ const x = viewport.x ?? 0;
+ let y = viewport.y ?? 0;
+ const width = viewport.width ?? attachmentSize.width;
+ const height = viewport.height ?? attachmentSize.height;
+
+ if (!isYup)
+ {
+ y = attachmentSize.height - y - height;
+ }
+
+ gl.viewport(x, y, width, height);
+ }
+ else
+ {
+ gl.viewport(0, 0, attachmentSize.width, attachmentSize.height);
+ }
+ }
+
+ private runScissor(gl: WebGLRenderingContext, attachmentSize: { width: number, height: number }, scissor: IScissorRect)
+ {
+ if (scissor)
+ {
+ const isYup = scissor.isYup ?? true;
+ const x = scissor.x ?? 0;
+ let y = scissor.y ?? 0;
+ const width = scissor.width ?? attachmentSize.width;
+ const height = scissor.height ?? attachmentSize.height;
+
+ if (!isYup)
+ {
+ y = attachmentSize.height - y - height;
+ }
+
+ gl.enable(gl.SCISSOR_TEST);
+ gl.scissor(x, y, width, height);
+ }
+ else
+ {
+ gl.disable(gl.SCISSOR_TEST);
+ }
+ }
+
+ private runCopyTextureToTexture(gl: WebGLRenderingContext, copyTextureToTexture: ICopyTextureToTexture)
+ {
+ const blitFramebuffer = getIGLBlitFramebuffer(copyTextureToTexture);
+ this.runBlitFramebuffer(gl, blitFramebuffer);
+ }
+
+ private runBlitFramebuffer(gl: WebGLRenderingContext, blitFramebuffer: IGLBlitFramebuffer)
+ {
+ const { read, draw, blitFramebuffers } = blitFramebuffer;
+
+ const readFramebuffer = getGLFramebuffer(gl, read);
+ const drawFramebuffer = getGLFramebuffer(gl, draw);
+
+ if (gl instanceof WebGL2RenderingContext)
+ {
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFramebuffer);
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, drawFramebuffer);
+
+ draw.colorAttachments.forEach((item, i) =>
+ {
+ const clearValue = draw.colorAttachments[i]?.clearValue;
+ if (clearValue)
+ {
+ gl.clearBufferfv(gl.COLOR, i, clearValue);
+ }
+ });
+
+ blitFramebuffers.forEach((item) =>
+ {
+ const [srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter] = item;
+
+ gl.blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, gl[mask], gl[filter]);
+ });
+ }
+ }
+
+ private runCopyBuffer(gl: WebGLRenderingContext, copyBuffer: ICopyBufferToBuffer)
+ {
+ if (gl instanceof WebGL2RenderingContext)
+ {
+ const { source: read, destination: write, sourceOffset: readOffset, destinationOffset: writeOffset, size } = copyBuffer;
+
+ const rb = getGLBuffer(gl, read);
+ const wb = getGLBuffer(gl, write);
+
+ gl.bindBuffer(gl.COPY_READ_BUFFER, rb);
+ gl.bindBuffer(gl.COPY_WRITE_BUFFER, wb);
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, readOffset, writeOffset, size);
+
+ //
+ gl.bindBuffer(gl.COPY_READ_BUFFER, null);
+ gl.bindBuffer(gl.COPY_WRITE_BUFFER, null);
+ }
+ else
+ {
+ console.error(`WebGL1 不支持拷贝缓冲区功能!`);
+ }
+ }
+}
+
+export const defaultRenderPassColorAttachment: IRenderPassColorAttachment = { clearValue: [0, 0, 0, 0], loadOp: "clear" };
+export const defaultDepthStencilAttachment: IRenderPassDepthStencilAttachment = { depthClearValue: 1, depthLoadOp: "load", stencilClearValue: 0, stencilLoadOp: "load" };
diff --git a/src/WebGL.ts b/src/WebGL.ts
index 9f19c71e8dda1f1c2124dc8fd521c488746b968a..00cceefba66ca4b1cb4ab7c881e35a41f15394d4 100644
--- a/src/WebGL.ts
+++ b/src/WebGL.ts
@@ -1,88 +1,54 @@
-import { deleteFramebuffer } from "./caches/getFramebuffer";
-import { deleteProgram } from "./caches/getProgram";
-import { deleteRenderbuffer } from "./caches/getRenderbuffer";
-import { getRenderingContext } from "./caches/getRenderingContext";
-import { deleteSampler } from "./caches/getSampler";
-import { deleteTexture } from "./caches/getTexture";
-import { deleteBuffer } from "./caches/getWebGLBuffer";
-import { deleteTransformFeedback } from "./caches/getWebGLTransformFeedback";
-import { IGLBlitFramebuffer } from "./data/IGLBlitFramebuffer";
-import { IGLBuffer } from "./data/IGLBuffer";
-import { IGLCopyBuffer } from "./data/IGLCopyBuffer";
-import { IGLRenderPassDescriptor } from "./data/IGLPassDescriptor";
-import { IGLQuery } from "./data/IGLQueryAction";
+import { IBuffer, IRenderPassDescriptor, IRenderPipeline, ISampler, ISubmit, ITexture } from "@feng3d/render-api";
+
+import { RunWebGL } from "./RunWebGL";
+import { deleteBuffer } from "./caches/getGLBuffer";
+import { getGLCanvasContext } from "./caches/getGLCanvasContext";
+import { deleteFramebuffer } from "./caches/getGLFramebuffer";
+import { deleteProgram } from "./caches/getGLProgram";
+import { deleteRenderbuffer } from "./caches/getGLRenderbuffer";
+import { deleteSampler } from "./caches/getGLSampler";
+import { deleteTexture } from "./caches/getGLTexture";
+import { deleteTransformFeedback } from "./caches/getGLTransformFeedback";
+import { IGLCanvasContext } from "./data/IGLCanvasContext";
import { IGLReadPixels } from "./data/IGLReadPixels";
-import { IGLRenderObject } from "./data/IGLRenderObject";
-import { IGLRenderPass } from "./data/IGLRenderPass";
-import { IGLRenderPipeline } from "./data/IGLRenderPipeline";
import { IGLRenderbuffer } from "./data/IGLRenderbuffer";
-import { IGLRenderingContext } from "./data/IGLRenderingContext";
-import { IGLSampler } from "./data/IGLSampler";
-import { IGLTexture } from "./data/IGLTexture";
import { IGLTransformFeedback } from "./data/IGLTransformFeedback";
-import { IGLVertexArrayObject } from "./data/IGLVertexArrayObject";
-import { runBlitFramebuffer } from "./runs/runBlitFramebuffer";
-import { runCopyBuffer } from "./runs/runCopyBuffer";
-import { getQueryResult } from "./runs/runQueryAction";
-import { runReadPixels } from "./runs/runReadPixels";
-import { runRenderObject } from "./runs/runRenderObject";
-import { runRenderPass } from "./runs/runRenderPass";
-import { deleteVertexArray } from "./runs/runVertexArray";
+import { readPixels } from "./utils/readPixels";
/**
- * WEBGL 渲染器
+ * WEBGL 对象。
*
* 所有渲染都由该渲染器执行。與2D、3D場景無關,屬於更加底層的API。針對每一個 RenderObject 渲染數據進行渲染。
*/
export class WebGL
{
- private _renderingContext: IGLRenderingContext;
+ private _runWebGL: RunWebGL = new RunWebGL();
+ private _renderingContext: IGLCanvasContext;
private _gl: WebGLRenderingContext;
- constructor(renderingContext: IGLRenderingContext)
+ constructor(renderingContext?: IGLCanvasContext)
{
this._renderingContext = renderingContext;
- this._gl = getRenderingContext(this._renderingContext);
+ this._gl = getGLCanvasContext(this._renderingContext);
}
/**
- * 提交一次渲染通道数据。
+ * 提交 GPU 。
*
- * @param renderingContext 渲染画布上下文描述。
- * @param renderPass 渲染通道数据。
- * @returns
- */
- runRenderPass(renderPass: IGLRenderPass)
- {
- runRenderPass(this._gl, renderPass);
- }
-
- /**
- * 渲染一次。
+ * @param submit 一次 GPU 提交内容。
*
- * @param renderObject 渲染原子,包含渲染所需的所有数据。
*/
- runRenderObject(renderObject: IGLRenderObject)
+ submit(submit: ISubmit)
{
- runRenderObject(this._gl, renderObject);
+ this._runWebGL.runSubmit(this._gl, submit);
}
- runBlitFramebuffer(blitFramebuffer: IGLBlitFramebuffer)
+ runReadPixels(glReadPixels: IGLReadPixels)
{
- runBlitFramebuffer(this._gl, blitFramebuffer);
+ readPixels(this._gl, glReadPixels);
}
- runCopyBuffer(copyBuffer: IGLCopyBuffer)
- {
- runCopyBuffer(this._gl, copyBuffer);
- }
-
- runReadPixels(readPixels: IGLReadPixels)
- {
- runReadPixels(this._gl, readPixels);
- }
-
- deleteFramebuffer(passDescriptor: IGLRenderPassDescriptor)
+ deleteFramebuffer(passDescriptor: IRenderPassDescriptor)
{
deleteFramebuffer(this._gl, passDescriptor);
}
@@ -92,38 +58,28 @@ export class WebGL
deleteRenderbuffer(this._gl, renderbuffer);
}
- deleteBuffer(buffer: IGLBuffer)
+ deleteBuffer(buffer: IBuffer)
{
deleteBuffer(this._gl, buffer);
}
- deleteTexture(texture: IGLTexture)
+ deleteTexture(texture: ITexture)
{
deleteTexture(this._gl, texture);
}
- deleteSampler(sampler: IGLSampler)
+ deleteSampler(sampler: ISampler)
{
deleteSampler(this._gl, sampler);
}
- deleteProgram(pipeline: IGLRenderPipeline)
+ deleteProgram(pipeline: IRenderPipeline)
{
deleteProgram(this._gl, pipeline);
}
- deleteVertexArray(vertexArray: IGLVertexArrayObject)
- {
- deleteVertexArray(this._gl, vertexArray);
- }
-
deleteTransformFeedback(transformFeedback: IGLTransformFeedback)
{
deleteTransformFeedback(this._gl, transformFeedback);
}
-
- getQueryResult(query: IGLQuery)
- {
- return getQueryResult(this._gl, query);
- }
}
diff --git a/src/caches/getWebGLBuffer.ts b/src/caches/getGLBuffer.ts
similarity index 46%
rename from src/caches/getWebGLBuffer.ts
rename to src/caches/getGLBuffer.ts
index 5003fba4a6a109fa54f337ad94004bbf2f53b8f9..1cfd4da6c999c2c2eeb5e46059c045b3b87d35e0 100644
--- a/src/caches/getWebGLBuffer.ts
+++ b/src/caches/getGLBuffer.ts
@@ -1,11 +1,11 @@
+import { IBuffer } from "@feng3d/render-api";
import { watcher } from "@feng3d/watcher";
-import { IAttributeBufferSourceTypes, IGLBuffer } from "../data/IGLBuffer";
declare global
{
interface WebGLRenderingContext
{
- _buffers: Map
+ _buffers: Map
}
interface WebGLBuffer
@@ -17,7 +17,7 @@ declare global
}
}
-export function getWebGLBuffer(gl: WebGLRenderingContext, buffer: IGLBuffer)
+export function getGLBuffer(gl: WebGLRenderingContext, buffer: IBuffer)
{
let webGLBuffer = gl._buffers.get(buffer);
if (webGLBuffer) return webGLBuffer;
@@ -27,56 +27,59 @@ export function getWebGLBuffer(gl: WebGLRenderingContext, buffer: IGLBuffer)
const target = buffer.target;
- const updateBuffer = () =>
- {
- // 获取
- const data = buffer.data;
- const size = buffer.size;
- const usage = buffer.usage || "STATIC_DRAW";
-
- // 上传数据到WebGL
- gl.bindBuffer(gl[target], webGLBuffer);
+ const size = buffer.size;
+ const usage = buffer.usage || "STATIC_DRAW";
- if (data)
- {
- gl.bufferData(gl[target], data, gl[usage]);
- }
- else if (size)
- {
- gl.bufferData(gl[target], size, gl[usage]);
- }
- else
- {
- console.log(`初始化缓冲区时必须提供数据或者尺寸!`);
- }
- };
+ // 上传数据到WebGL
+ gl.bindBuffer(gl[target], webGLBuffer);
+ gl.bufferData(gl[target], size, gl[usage]);
const writeBuffer = () =>
{
const writeBuffers = buffer.writeBuffers;
- if (writeBuffers)
+ if (!writeBuffers) return;
+
+ gl.bindBuffer(gl[target], webGLBuffer);
+ writeBuffers.forEach((writeBuffer) =>
{
- gl.bindBuffer(gl[target], webGLBuffer);
- writeBuffers.forEach((writeBuffer) =>
+ const bufferOffset = writeBuffer.bufferOffset ?? 0;
+ const data = writeBuffer.data;
+ const dataOffset = writeBuffer.dataOffset ?? 0;
+ //
+ let arrayBufferView: Uint8Array;
+ if ("buffer" in data)
{
- const bufferOffset = writeBuffer.bufferOffset || 0;
- const data = writeBuffer.data;
-
- gl.bufferSubData(gl[target], bufferOffset, data);
- });
- buffer.writeBuffers = null;
- }
+ arrayBufferView = new Uint8Array(
+ data.buffer,
+ data.byteOffset + dataOffset * data.BYTES_PER_ELEMENT,
+ (data.length - dataOffset) * data.BYTES_PER_ELEMENT
+ );
+ }
+ else
+ {
+ arrayBufferView = new Uint8Array(
+ data,
+ dataOffset,
+ data.byteLength - dataOffset
+ );
+ }
+ gl.bufferSubData(gl[target], bufferOffset, arrayBufferView);
+ });
+ buffer.writeBuffers = null;
};
const dataChange = () =>
{
+ if (!buffer.data) return;
+
const writeBuffers = buffer.writeBuffers || [];
- writeBuffers.push({ data: buffer.data });
+ writeBuffers.unshift({ data: buffer.data });
buffer.writeBuffers = writeBuffers;
};
- updateBuffer();
+ dataChange();
+ writeBuffer();
//
watcher.watch(buffer, "data", dataChange);
@@ -92,7 +95,7 @@ export function getWebGLBuffer(gl: WebGLRenderingContext, buffer: IGLBuffer)
return webGLBuffer;
}
-export function deleteBuffer(gl: WebGLRenderingContext, buffer: IGLBuffer)
+export function deleteBuffer(gl: WebGLRenderingContext, buffer: IBuffer)
{
const webGLBuffer = gl._buffers.get(buffer);
if (webGLBuffer)
@@ -104,19 +107,3 @@ export function deleteBuffer(gl: WebGLRenderingContext, buffer: IGLBuffer)
gl.deleteBuffer(webGLBuffer);
}
}
-
-export function getBufferType(data?: IAttributeBufferSourceTypes)
-{
- return bufferTypeMap[data?.constructor.name];
-}
-
-const bufferTypeMap = {
- Float32Array: "FLOAT",
- Uint32Array: "UNSIGNED_INT",
- Int32Array: "INT",
- Uint16Array: "UNSIGNED_SHORT",
- Int16Array: "SHORT",
- Uint8Array: "UNSIGNED_BYTE",
- Int8Array: "BYTE",
- Uint8ClampedArray: "BYTE",
-};
diff --git a/src/caches/getRenderingContext.ts b/src/caches/getGLCanvasContext.ts
similarity index 85%
rename from src/caches/getRenderingContext.ts
rename to src/caches/getGLCanvasContext.ts
index 969f0a2b4f378075fbb320e284ecff255c8ca6e3..f2ad55ca6a0c80e59dcca4e95982c9572bc52d99 100644
--- a/src/caches/getRenderingContext.ts
+++ b/src/caches/getGLCanvasContext.ts
@@ -1,5 +1,6 @@
-import { IGLRenderingContext } from "../data/IGLRenderingContext";
-import { defaults } from "../defaults/defaults";
+import { IGLCanvasContext } from "../data/IGLCanvasContext";
+import { defaultCanvasContext } from "../defaults/defaults";
+import { ChainMap } from "../utils/ChainMap";
import { getCapabilities } from "./getCapabilities";
/**
@@ -8,7 +9,7 @@ import { getCapabilities } from "./getCapabilities";
* @param renderingContext
* @returns
*/
-export function getRenderingContext(renderingContext: IGLRenderingContext)
+export function getGLCanvasContext(renderingContext: IGLCanvasContext)
{
const key = renderingContext.canvasId;
let value = canvasContextMap.get(key);
@@ -38,9 +39,8 @@ function initMap(gl: WebGLRenderingContext)
gl._textures = new Map();
gl._renderbuffers = new Map();
gl._framebuffers = new Map();
- gl._vertexArrays = new Map();
+ gl._vertexArrays = new ChainMap();
gl._samplers = new Map();
- gl._querys = new Map();
gl._transforms = new Map();
gl._programs = {};
gl._shaders = {};
@@ -72,7 +72,7 @@ function autoCreateCanvas(canvasId: string)
return canvas;
}
-function getCanvas(canvasContext: IGLRenderingContext)
+export function getCanvas(canvasContext: IGLCanvasContext)
{
let canvas = document.getElementById(canvasContext.canvasId) as HTMLCanvasElement;
if (!canvas || !(canvas instanceof HTMLCanvasElement))
@@ -83,9 +83,9 @@ function getCanvas(canvasContext: IGLRenderingContext)
return canvas;
}
-function getWebGLContext(canvas: HTMLCanvasElement, canvasContext: IGLRenderingContext)
+function getWebGLContext(canvas: HTMLCanvasElement, canvasContext: IGLCanvasContext)
{
- const contextAttributes = Object.assign({}, defaults.webGLCanvasContext, canvasContext);
+ const contextAttributes = Object.assign({}, defaultCanvasContext, canvasContext);
// 使用用户提供参数获取WebGL上下文
let gl = canvas.getContext(contextAttributes.contextId, contextAttributes) as any;
diff --git a/src/caches/getFramebuffer.ts b/src/caches/getGLFramebuffer.ts
similarity index 41%
rename from src/caches/getFramebuffer.ts
rename to src/caches/getGLFramebuffer.ts
index c4df381272c2c751e77385af08bf3b4019ec1401..7c31e009cb27ba337321e1066e8ace773d463115 100644
--- a/src/caches/getFramebuffer.ts
+++ b/src/caches/getGLFramebuffer.ts
@@ -1,23 +1,22 @@
-import { IGLRenderPassDescriptor } from "../data/IGLPassDescriptor";
+import { IRenderPassDescriptor, ITextureView } from "@feng3d/render-api";
import { IGLRenderbuffer } from "../data/IGLRenderbuffer";
-import { IGLTextureView } from "../data/IGLTexture";
-import { getRenderbuffer } from "./getRenderbuffer";
-import { getTexture } from "./getTexture";
+import { deleteRenderbuffer, getGLRenderbuffer } from "./getGLRenderbuffer";
+import { getGLTexture } from "./getGLTexture";
+import { _IGLRenderPassDescriptorWithMultisample, IGLRenderPassDescriptorWithMultisample } from "./getIGLRenderPassDescriptorWithMultisample";
+import { getIGLTextureTarget } from "./getIGLTextureTarget";
declare global
{
interface WebGLRenderingContext
{
- _framebuffers: Map;
+ _framebuffers: Map;
}
}
-const defaultTextureView: Partial = { level: 0, layer: 0 };
-
/**
* 获取帧缓冲区
*/
-export function getFramebuffer(gl: WebGLRenderingContext, passDescriptor: IGLRenderPassDescriptor)
+export function getGLFramebuffer(gl: WebGLRenderingContext, passDescriptor: IRenderPassDescriptor)
{
const view = passDescriptor?.colorAttachments?.[0]?.view || passDescriptor?.depthStencilAttachment?.view;
if (!view) return null;
@@ -25,7 +24,7 @@ export function getFramebuffer(gl: WebGLRenderingContext, passDescriptor: IGLRen
let webGLFramebuffer = gl._framebuffers.get(passDescriptor);
if (webGLFramebuffer) return webGLFramebuffer;
- const multisample = passDescriptor.multisample;
+ const sampleCount = passDescriptor.sampleCount;
webGLFramebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, webGLFramebuffer);
@@ -35,25 +34,27 @@ export function getFramebuffer(gl: WebGLRenderingContext, passDescriptor: IGLRen
const drawBuffers: number[] = [];
passDescriptor.colorAttachments?.forEach((item, i) =>
{
- const { view } = item;
+ const view = item.view as (ITextureView | IGLRenderbuffer);
const attachment = gl[`COLOR_ATTACHMENT${i}`];
drawBuffers.push(attachment);
if ("texture" in view)
{
- const { texture, level, layer } = { ...defaultTextureView, ...view };
+ const texture = view.texture;
+ const baseMipLevel = view.baseMipLevel || 0;
+ const baseArrayLayer = view.baseArrayLayer || 0;
- const webGLTexture = getTexture(gl, texture);
- const textureTarget = webGLTexture.textureTarget;
+ const webGLTexture = getGLTexture(gl, texture);
+ const textureTarget = getIGLTextureTarget(texture.dimension);
if (textureTarget === "TEXTURE_2D")
{
- gl.framebufferTexture2D(gl.FRAMEBUFFER, attachment, gl[textureTarget], webGLTexture, level);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, attachment, gl[textureTarget], webGLTexture, baseMipLevel);
}
else if (textureTarget === "TEXTURE_2D_ARRAY")
{
if (gl instanceof WebGL2RenderingContext)
{
- gl.framebufferTextureLayer(gl.DRAW_FRAMEBUFFER, attachment, webGLTexture, level, layer);
+ gl.framebufferTextureLayer(gl.DRAW_FRAMEBUFFER, attachment, webGLTexture, baseMipLevel, baseArrayLayer);
}
}
else
@@ -63,7 +64,7 @@ export function getFramebuffer(gl: WebGLRenderingContext, passDescriptor: IGLRen
}
else
{
- const renderbuffer = getRenderbuffer(gl, view as IGLRenderbuffer, multisample);
+ const renderbuffer = getGLRenderbuffer(gl, view, sampleCount);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, renderbuffer);
}
});
@@ -78,46 +79,65 @@ export function getFramebuffer(gl: WebGLRenderingContext, passDescriptor: IGLRen
}
// 处理深度模板附件
- if (passDescriptor.depthStencilAttachment)
+ if (passDescriptor.depthStencilAttachment?.view)
{
- const { view } = passDescriptor.depthStencilAttachment;
- if ("texture" in view)
- {
- const { texture, level, layer } = { ...defaultTextureView, ...view };
+ const view = passDescriptor.depthStencilAttachment.view;
- const webGLTexture = getTexture(gl, texture);
- const textureTarget = webGLTexture.textureTarget;
+ const texture = view.texture;
+ const baseMipLevel = view.baseMipLevel || 0;
+ const baseArrayLayer = view.baseArrayLayer || 0;
- if (textureTarget === "TEXTURE_2D")
- {
- gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl[textureTarget], webGLTexture, level);
- }
- else if (textureTarget === "TEXTURE_2D_ARRAY")
- {
- if (gl instanceof WebGL2RenderingContext)
- {
- gl.framebufferTextureLayer(gl.DRAW_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, webGLTexture, level, layer);
- }
- }
- else
+ const webGLTexture = getGLTexture(gl, texture);
+ const textureTarget = getIGLTextureTarget(texture.dimension);
+
+ if (textureTarget === "TEXTURE_2D")
+ {
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl[textureTarget], webGLTexture, baseMipLevel);
+ }
+ else if (textureTarget === "TEXTURE_2D_ARRAY")
+ {
+ if (gl instanceof WebGL2RenderingContext)
{
- console.error(`未处理 ${textureTarget} 的深度模板附件纹理设置!`);
+ gl.framebufferTextureLayer(gl.DRAW_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, webGLTexture, baseMipLevel, baseArrayLayer);
}
}
else
{
- const renderbuffer = getRenderbuffer(gl, view as IGLRenderbuffer);
- gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderbuffer);
+ console.error(`未处理 ${textureTarget} 的深度模板附件纹理设置!`);
}
}
return webGLFramebuffer;
}
-export function deleteFramebuffer(gl: WebGLRenderingContext, passDescriptor: IGLRenderPassDescriptor)
+/**
+ *
+ * @param gl
+ * @param passDescriptor
+ * @param handleMultisample 处理存在多重采样的渲染通道描述。
+ * @returns
+ */
+export function deleteFramebuffer(gl: WebGLRenderingContext, passDescriptor: IRenderPassDescriptor, handleMultisample = true)
{
+ if (handleMultisample && passDescriptor?.[_IGLRenderPassDescriptorWithMultisample])
+ {
+ deleteRenderPassDescriptorWithMultisample(gl, passDescriptor[_IGLRenderPassDescriptorWithMultisample]);
+ return;
+ }
+
const webGLFramebuffer = gl._framebuffers.get(passDescriptor);
gl._framebuffers.delete(passDescriptor);
//
gl.deleteFramebuffer(webGLFramebuffer);
+}
+
+function deleteRenderPassDescriptorWithMultisample(gl: WebGLRenderingContext, renderPassDescriptorWithMultisample: IGLRenderPassDescriptorWithMultisample)
+{
+ deleteFramebuffer(gl, renderPassDescriptorWithMultisample.blitFramebuffer.read, false);
+ deleteFramebuffer(gl, renderPassDescriptorWithMultisample.blitFramebuffer.draw, false);
+
+ renderPassDescriptorWithMultisample.renderbuffers.forEach((v) =>
+ {
+ deleteRenderbuffer(gl, v);
+ })
}
\ No newline at end of file
diff --git a/src/caches/getProgram.ts b/src/caches/getGLProgram.ts
similarity index 57%
rename from src/caches/getProgram.ts
rename to src/caches/getGLProgram.ts
index ab18d3d4922a52b69cb11739a315260a72a751d0..d15247b08e27e2212419a2fd561aa0fac02ac0aa 100644
--- a/src/caches/getProgram.ts
+++ b/src/caches/getGLProgram.ts
@@ -1,8 +1,9 @@
-import { getWebGLUniformType, isWebGLUniformTextureType } from "../const/WebGLUniformType";
+import { IRenderPipeline } from "@feng3d/render-api";
+import { getWebGLUniformType, IGLUniformBufferType, isWebGLUniformTextureType } from "../const/IGLUniformType";
import { IGLAttributeInfo } from "../data/IGLAttributeInfo";
-import { IGLRenderPipeline, ITransformFeedbackVaryings } from "../data/IGLRenderPipeline";
+import { IGLTransformFeedbackPipeline, IGLTransformFeedbackVaryings } from "../data/IGLTransformFeedbackPass";
import { IGLUniformInfo, IUniformItemInfo } from "../data/IGLUniformInfo";
-import { getWebGLAttributeValueType } from "./getWebGLAttributeType";
+import { getIGLAttributeType } from "./getIGLAttributeType";
declare global
{
@@ -37,15 +38,22 @@ declare global
/**
* 激活渲染程序
*/
-export function getProgram(gl: WebGLRenderingContext, pipeline: IGLRenderPipeline)
+export function getGLProgram(gl: WebGLRenderingContext, pipeline: IRenderPipeline | IGLTransformFeedbackPipeline)
{
const shaderKey = getKey(pipeline);
let result = gl._programs[shaderKey];
if (result) return result;
const vertex = pipeline.vertex.code;
- const fragment = pipeline.fragment.code;
- const transformFeedbackVaryings = pipeline.transformFeedbackVaryings;
+ const fragment = (pipeline as IRenderPipeline).fragment?.code || `#version 300 es
+ precision highp float;
+ precision highp int;
+
+ void main()
+ {
+ }
+ `;
+ const transformFeedbackVaryings = (pipeline as IGLTransformFeedbackPipeline).transformFeedbackVaryings;
result = getWebGLProgram(gl, vertex, fragment, transformFeedbackVaryings);
gl._programs[shaderKey] = result;
@@ -53,11 +61,8 @@ export function getProgram(gl: WebGLRenderingContext, pipeline: IGLRenderPipelin
return result;
}
-export function deleteProgram(gl: WebGLRenderingContext, pipeline: IGLRenderPipeline)
+export function deleteProgram(gl: WebGLRenderingContext, pipeline: IRenderPipeline)
{
- const vertex = pipeline.vertex.code;
- const fragment = pipeline.fragment.code;
-
const shaderKey = getKey(pipeline);
const result = gl._programs[shaderKey];
if (result)
@@ -67,16 +72,16 @@ export function deleteProgram(gl: WebGLRenderingContext, pipeline: IGLRenderPipe
}
}
-function getKey(pipeline: IGLRenderPipeline)
+function getKey(pipeline: IRenderPipeline | IGLTransformFeedbackPipeline)
{
const vertex = pipeline.vertex.code;
- const fragment = pipeline.fragment.code;
- const transformFeedbackVaryings = pipeline.transformFeedbackVaryings;
+ const fragment = (pipeline as IRenderPipeline).fragment?.code;
+ const transformFeedbackVaryings = (pipeline as IGLTransformFeedbackPipeline).transformFeedbackVaryings;
return `---vertexShader---\n${vertex}\n---fragment---\n${fragment}\n---feedback---${transformFeedbackVaryings?.varyings.toString()} ${transformFeedbackVaryings?.bufferMode}`;
}
-function getWebGLProgram(gl: WebGLRenderingContext, vshader: string, fshader: string, transformFeedbackVaryings: ITransformFeedbackVaryings)
+function getWebGLProgram(gl: WebGLRenderingContext, vshader: string, fshader: string, transformFeedbackVaryings: IGLTransformFeedbackVaryings)
{
// 编译顶点着色器
const vertexShader = getWebGLShader(gl, "VERTEX_SHADER", vshader);
@@ -95,7 +100,7 @@ function getWebGLProgram(gl: WebGLRenderingContext, vshader: string, fshader: st
const activeInfo = gl.getActiveAttrib(program, i);
const { name, size, type } = activeInfo;
const location = gl.getAttribLocation(program, name);
- const typeString = getWebGLAttributeValueType(type as any);
+ const typeString = getIGLAttributeType(type as any);
attributes.push({ name, size, type: typeString, location });
}
// 获取uniform信息
@@ -170,8 +175,12 @@ function getWebGLProgram(gl: WebGLRenderingContext, vshader: string, fshader: st
index: i,
dataSize: gl.getActiveUniformBlockParameter(program, i, gl.UNIFORM_BLOCK_DATA_SIZE),
uniforms: uniformList,
+ bufferBindingInfo: undefined,
};
+ //
+ info.bufferBindingInfo = getBufferBindingInfo(info);
+
return info;
});
program.uniformBlocks = uniformBlockActiveInfos;
@@ -210,6 +219,11 @@ export interface IUniformBlockInfo
* 包含的统一变量列表。
*/
uniforms: IGLUniformInfo[];
+
+ /**
+ * 缓冲区绑定信息。
+ */
+ bufferBindingInfo: IBufferBindingInfo;
}
/**
@@ -242,7 +256,7 @@ function getWebGLShader(gl: WebGLRenderingContext, type: ShaderType, code: strin
return shader;
}
-function createLinkProgram(gl: WebGLRenderingContext, vertexShader: WebGLShader, fragmentShader: WebGLShader, transformFeedbackVaryings: ITransformFeedbackVaryings)
+function createLinkProgram(gl: WebGLRenderingContext, vertexShader: WebGLShader, fragmentShader: WebGLShader, transformFeedbackVaryings: IGLTransformFeedbackVaryings)
{
// 创建程序对象
const program = gl.createProgram();
@@ -286,3 +300,110 @@ function createLinkProgram(gl: WebGLRenderingContext, vertexShader: WebGLShader,
* Either a gl.FRAGMENT_SHADER or a gl.VERTEX_SHADER.
*/
export type ShaderType = "FRAGMENT_SHADER" | "VERTEX_SHADER";
+
+/**
+ * 缓冲区绑定信息。
+ */
+export interface IBufferBindingInfo
+{
+ size: number;
+ items: {
+ paths: string[];
+ offset: number;
+ size: number;
+ Cls: Float32ArrayConstructor | Int32ArrayConstructor | Uint32ArrayConstructor;
+ }[]
+}
+
+function getBufferBindingInfo(uniformBlock: IUniformBlockInfo): IBufferBindingInfo
+{
+ const size = uniformBlock.dataSize;
+ //
+ let currentSize = 0;
+ let structName: string;
+
+ const items: { paths: string[], offset: number, size: number, Cls: Float32ArrayConstructor | Int32ArrayConstructor | Uint32ArrayConstructor }[] = [];
+ uniformBlock.uniforms.forEach((uniformInfo) =>
+ {
+ const uniformBufferType = uniformInfo.type as IGLUniformBufferType;
+ const alignSize = uniformBufferTypeAlignSizeMap[uniformBufferType];
+ console.assert(alignSize, `没有找到 ${uniformBufferType} 统一缓冲类型对应的对齐与尺寸。`);
+
+ //
+ const currentstructName = uniformInfo.name.substring(0, uniformInfo.name.lastIndexOf("."));
+ if (structName !== currentstructName)
+ {
+ currentSize = roundUp(16, currentSize); // 结构体之间对齐
+ structName = currentstructName;
+ }
+
+ //
+ uniformInfo.items.forEach((itemInfo) =>
+ {
+ currentSize = roundUp(alignSize.align, currentSize); // 结构体成员对齐
+ const itemInfoOffset = currentSize;
+ const itemInfoSize = alignSize.size;
+ //
+ currentSize += alignSize.size;
+ const Cls = alignSize.clsType;
+ //
+ const paths = itemInfo.paths.slice(1);
+ //
+ items.push({ paths, offset: itemInfoOffset, size: itemInfoSize, Cls: Cls });
+ });
+ });
+ currentSize = roundUp(16, currentSize); // 整个统一块数据对齐
+
+ console.assert(size === currentSize, `uniformBlock映射尺寸出现错误( ${size} ${currentSize} )!`);
+
+ const bufferBindingInfo: IBufferBindingInfo = {
+ size: uniformBlock.dataSize,
+ items,
+ };
+
+ return bufferBindingInfo;
+}
+
+function roundUp(k: number, n: number): number
+{
+ return Math.ceil(n / k) * k;
+}
+
+/**
+ *
+ * @see https://github.com/brendan-duncan/wgsl_reflect/blob/main/src/wgsl_reflect.ts#L1206
+ * @see https://www.orillusion.com/zh/wgsl.html#memory-layouts
+ */
+const uniformBufferTypeAlignSizeMap: {
+ [key: string]: {
+ align: number,
+ size: number,
+ clsType: Float32ArrayConstructor | Int32ArrayConstructor | Uint32ArrayConstructor,
+ }
+} = {
+ "FLOAT": { align: 4, size: 4, clsType: Float32Array },
+ "FLOAT_VEC2": { align: 8, size: 8, clsType: Float32Array },
+ "FLOAT_VEC3": { align: 16, size: 12, clsType: Float32Array },
+ "FLOAT_VEC4": { align: 16, size: 16, clsType: Float32Array },
+ "INT": { align: 4, size: 4, clsType: Int32Array },
+ "INT_VEC2": { align: 8, size: 8, clsType: Int32Array },
+ "INT_VEC3": { align: 16, size: 12, clsType: Int32Array },
+ "INT_VEC4": { align: 16, size: 16, clsType: Int32Array },
+ "BOOL": { align: 4, size: 4, clsType: Int32Array },
+ "BOOL_VEC2": { align: 8, size: 8, clsType: Int32Array },
+ "BOOL_VEC3": { align: 16, size: 12, clsType: Int32Array },
+ "BOOL_VEC4": { align: 16, size: 16, clsType: Int32Array },
+ "FLOAT_MAT2": { align: 8, size: 16, clsType: Float32Array },
+ "FLOAT_MAT3": { align: 16, size: 48, clsType: Float32Array },
+ "FLOAT_MAT4": { align: 16, size: 64, clsType: Float32Array },
+ "UNSIGNED_INT": { align: 4, size: 4, clsType: Uint32Array },
+ "UNSIGNED_INT_VEC2": { align: 8, size: 8, clsType: Uint32Array },
+ "UNSIGNED_INT_VEC3": { align: 16, size: 12, clsType: Uint32Array },
+ "UNSIGNED_INT_VEC4": { align: 16, size: 16, clsType: Uint32Array },
+ "FLOAT_MAT2x3": { align: 16, size: 32, clsType: Float32Array },
+ "FLOAT_MAT2x4": { align: 16, size: 32, clsType: Float32Array },
+ "FLOAT_MAT3x2": { align: 8, size: 24, clsType: Float32Array },
+ "FLOAT_MAT3x4": { align: 16, size: 48, clsType: Float32Array },
+ "FLOAT_MAT4x2": { align: 8, size: 32, clsType: Float32Array },
+ "FLOAT_MAT4x3": { align: 16, size: 64, clsType: Float32Array },
+};
\ No newline at end of file
diff --git a/src/caches/getGLRenderOcclusionQuery.ts b/src/caches/getGLRenderOcclusionQuery.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cc8c974ac81d3de68b77514e637ebd594056ddc8
--- /dev/null
+++ b/src/caches/getGLRenderOcclusionQuery.ts
@@ -0,0 +1,135 @@
+import { IRenderPass, IRenderPassObject } from "@feng3d/render-api";
+import { IGLOcclusionQuery, IGLQuery } from "../data/IGLOcclusionQuery";
+
+export function getGLRenderOcclusionQuery(gl: WebGLRenderingContext, renderObjects?: readonly IRenderPassObject[])
+{
+ if (!renderObjects) return defautRenderOcclusionQuery;
+ if (!(gl instanceof WebGL2RenderingContext)) return defautRenderOcclusionQuery;
+ let renderOcclusionQuery: GLRenderOcclusionQuery = renderObjects["_GLRenderOcclusionQuery"];
+ if (renderOcclusionQuery) return renderOcclusionQuery;
+
+ const occlusionQueryObjects: IGLOcclusionQuery[] = renderObjects.filter((cv) => cv.__type === "OcclusionQuery") as any;
+ if (occlusionQueryObjects.length === 0)
+ {
+ renderObjects["_GLRenderOcclusionQuery"] = defautRenderOcclusionQuery;
+
+ return defautRenderOcclusionQuery;
+ }
+
+ /**
+ * 初始化。
+ */
+ const init = () =>
+ {
+ occlusionQueryObjects.forEach((v, i) =>
+ {
+ v._step = getGLOcclusionQueryStep(gl, v);
+ });
+ };
+
+ /**
+ * 查询结果。
+ */
+ const resolve = (renderPass: IRenderPass) =>
+ {
+ const results = occlusionQueryObjects.map((v) => v._step.resolve());
+
+ Promise.all(results).then((v) =>
+ {
+ renderPass.occlusionQueryResults = v;
+ });
+ };
+
+ renderObjects["_GLRenderOcclusionQuery"] = renderOcclusionQuery = { init, resolve };
+
+ return renderOcclusionQuery;
+}
+
+interface GLRenderOcclusionQuery
+{
+ init: () => void
+ resolve: (renderPass: IRenderPass) => void
+}
+
+const defautRenderOcclusionQuery = { init: () => { }, resolve: () => { } };
+
+export function getGLOcclusionQueryStep(gl: WebGL2RenderingContext, occlusionQuery: IGLOcclusionQuery)
+{
+ const query: IGLQuery = {} as any;
+ let webGLQuery: WebGLQuery;
+
+ // 开始查询
+ const begin = () =>
+ {
+ webGLQuery = gl.createQuery();
+
+ gl.beginQuery(gl.ANY_SAMPLES_PASSED, webGLQuery);
+ };
+
+ const end = () =>
+ {
+ // 结束查询
+ gl.endQuery(gl.ANY_SAMPLES_PASSED);
+ };
+
+ /**
+ * 获取查询结果。
+ */
+ const resolve = async () =>
+ {
+ if (query.result !== undefined) return occlusionQuery;
+
+ if (gl instanceof WebGL2RenderingContext)
+ {
+ const result: IGLOcclusionQuery = await new Promise((resolve, reject) =>
+ {
+ (function tick()
+ {
+ if (!gl.getQueryParameter(webGLQuery, gl.QUERY_RESULT_AVAILABLE))
+ {
+ // A query's result is never available in the same frame
+ // the query was issued. Try in the next frame.
+ requestAnimationFrame(tick);
+
+ return;
+ }
+
+ query.result = gl.getQueryParameter(webGLQuery, gl.QUERY_RESULT);
+
+ occlusionQuery.result = query;
+
+ resolve(occlusionQuery);
+
+ gl.deleteQuery(webGLQuery);
+ })();
+ });
+
+ return result;
+ }
+
+ return undefined;
+ }
+
+ return { begin, end, resolve } as IGLOcclusionQueryStep;
+}
+
+/**
+ * 不被遮挡查询步骤。
+ */
+export interface IGLOcclusionQueryStep
+{
+ /**
+ * 开始查询
+ */
+ begin: () => void;
+
+ /**
+ * 结束查询
+ */
+ end: () => void;
+
+ /**
+ * 获取查询结果,将获取被赋值新结果的遮挡查询对象。
+ */
+ resolve: () => Promise
+}
\ No newline at end of file
diff --git a/src/caches/getRenderbuffer.ts b/src/caches/getGLRenderbuffer.ts
similarity index 77%
rename from src/caches/getRenderbuffer.ts
rename to src/caches/getGLRenderbuffer.ts
index 3180b8b7cafc73568b2536c34aadb0bf2e1e4f8b..3fe8b023977f96e1fa143d767b019fc273ee6362 100644
--- a/src/caches/getRenderbuffer.ts
+++ b/src/caches/getGLRenderbuffer.ts
@@ -8,7 +8,7 @@ declare global
}
}
-export function getRenderbuffer(gl: WebGLRenderingContext, renderbuffer: IGLRenderbuffer, multisample?: 4)
+export function getGLRenderbuffer(gl: WebGLRenderingContext, renderbuffer: IGLRenderbuffer, sampleCount?: 4)
{
let webGLRenderbuffer = gl._renderbuffers.get(renderbuffer);
if (webGLRenderbuffer) return webGLRenderbuffer;
@@ -19,9 +19,9 @@ export function getRenderbuffer(gl: WebGLRenderingContext, renderbuffer: IGLRend
const { internalformat, width, height } = renderbuffer;
gl.bindRenderbuffer(gl.RENDERBUFFER, webGLRenderbuffer);
- if (multisample === 4 && gl instanceof WebGL2RenderingContext)
+ if (sampleCount === 4 && gl instanceof WebGL2RenderingContext)
{
- gl.renderbufferStorageMultisample(gl.RENDERBUFFER, multisample, gl[internalformat], width, height);
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, sampleCount, gl[internalformat], width, height);
}
else
{
diff --git a/src/caches/getSampler.ts b/src/caches/getGLSampler.ts
similarity index 30%
rename from src/caches/getSampler.ts
rename to src/caches/getGLSampler.ts
index 55adf857931d7362ca48829d12afb5b4d2ace36b..dca0041a2e2eb2de8bba3d289113eb57af65ce7b 100644
--- a/src/caches/getSampler.ts
+++ b/src/caches/getGLSampler.ts
@@ -1,15 +1,17 @@
-import { IGLSampler } from "../data/IGLSampler";
-import { defaultGLSampler } from "../runs/runSampler";
+import { IAddressMode, IFilterMode, ISampler } from "@feng3d/render-api";
+import { IGLCompareFunction } from "../data/IGLDepthStencilState";
+import { IGLSamplerCompareMode, IGLTextureMagFilter, IGLTextureMinFilter, IGLTextureWrap } from "../data/IGLSampler";
+import { getIGLCompareFunction } from "../runs/runDepthState";
declare global
{
interface WebGLRenderingContext
{
- _samplers: Map;
+ _samplers: Map;
}
}
-export function getSampler(gl: WebGLRenderingContext, sampler?: IGLSampler)
+export function getGLSampler(gl: WebGLRenderingContext, sampler?: ISampler)
{
let webGLSampler = gl._samplers.get(sampler);
if (webGLSampler) return webGLSampler;
@@ -19,8 +21,17 @@ export function getSampler(gl: WebGLRenderingContext, sampler?: IGLSampler)
webGLSampler = gl.createSampler();
gl._samplers.set(sampler, webGLSampler);
- const { minFilter, magFilter, wrapS, wrapT, wrapR, lodMinClamp, lodMaxClamp, compareMode, compare } = { ...defaultGLSampler, ...sampler };
+ const minFilter: IGLTextureMinFilter = getIGLTextureMinFilter(sampler.minFilter, sampler.mipmapFilter);
+ const magFilter: IGLTextureMagFilter = getIGLTextureMagFilter(sampler.magFilter);
+ const wrapS: IGLTextureWrap = getIGLTextureWrap(sampler.addressModeU);
+ const wrapT: IGLTextureWrap = getIGLTextureWrap(sampler.addressModeV);
+ const wrapR: IGLTextureWrap = getIGLTextureWrap(sampler.addressModeW);
+ const lodMinClamp = sampler.lodMinClamp || 0;
+ const lodMaxClamp = sampler.lodMaxClamp || 16;
+ const compareMode: IGLSamplerCompareMode = sampler.compare ? "COMPARE_REF_TO_TEXTURE" : "NONE";
+ const compare: IGLCompareFunction = getIGLCompareFunction(sampler.compare ?? "less-equal");
+ //
gl.samplerParameteri(webGLSampler, gl.TEXTURE_MIN_FILTER, gl[minFilter]);
gl.samplerParameteri(webGLSampler, gl.TEXTURE_MAG_FILTER, gl[magFilter]);
gl.samplerParameteri(webGLSampler, gl.TEXTURE_WRAP_S, gl[wrapS]);
@@ -35,7 +46,7 @@ export function getSampler(gl: WebGLRenderingContext, sampler?: IGLSampler)
return webGLSampler;
}
-export function deleteSampler(gl: WebGLRenderingContext, sampler?: IGLSampler)
+export function deleteSampler(gl: WebGLRenderingContext, sampler?: ISampler)
{
if (gl instanceof WebGL2RenderingContext)
{
@@ -43,4 +54,70 @@ export function deleteSampler(gl: WebGLRenderingContext, sampler?: IGLSampler)
gl._samplers.delete(sampler);
gl.deleteSampler(webGLSampler);
}
-}
\ No newline at end of file
+}
+
+export function getIGLTextureWrap(addressMode: IAddressMode = "repeat")
+{
+ const textureWrap: IGLTextureWrap = addressModeMap[addressMode];
+
+ console.assert(!!textureWrap, `接收到错误值,请从 ${Object.keys(addressModeMap).toString()} 中取值!`);
+
+ return textureWrap;
+}
+
+const addressModeMap: { [key: string]: IGLTextureWrap } = {
+ "clamp-to-edge": "CLAMP_TO_EDGE",
+ "repeat": "REPEAT",
+ "mirror-repeat": "MIRRORED_REPEAT",
+};
+
+export function getIGLTextureMinFilter(minFilter: IFilterMode = "nearest", mipmapFilter?: IFilterMode): IGLTextureMinFilter
+{
+ let glMinFilter: IGLTextureMinFilter;
+ if (minFilter === "linear")
+ {
+ if (mipmapFilter === "linear")
+ {
+ glMinFilter = "LINEAR_MIPMAP_LINEAR";
+ }
+ else if (mipmapFilter === "nearest")
+ {
+ glMinFilter = "LINEAR_MIPMAP_NEAREST";
+ }
+ else
+ {
+ glMinFilter = "LINEAR";
+ }
+ }
+ else
+ {
+ if (mipmapFilter === "linear")
+ {
+ glMinFilter = "NEAREST_MIPMAP_LINEAR";
+ }
+ else if (mipmapFilter === "nearest")
+ {
+ glMinFilter = "NEAREST_MIPMAP_NEAREST";
+ }
+ else
+ {
+ glMinFilter = "NEAREST";
+ }
+ }
+
+ return glMinFilter;
+}
+
+export function getIGLTextureMagFilter(magFilter: IFilterMode = "nearest")
+{
+ const glMagFilter: IGLTextureMagFilter = magFilterMap[magFilter];
+
+ console.assert(!!glMagFilter, `接收到错误值,请从 ${Object.keys(magFilterMap).toString()} 中取值!`);
+
+ return glMagFilter;
+}
+
+const magFilterMap: { [key: string]: IGLTextureMagFilter } = {
+ "nearest": "NEAREST",
+ "linear": "LINEAR",
+};
\ No newline at end of file
diff --git a/src/caches/getGLTexture.ts b/src/caches/getGLTexture.ts
new file mode 100644
index 0000000000000000000000000000000000000000..126b568ff95e27919a00d53ccc6bc7e1492078e5
--- /dev/null
+++ b/src/caches/getGLTexture.ts
@@ -0,0 +1,475 @@
+import { ITexture, ITextureDataSource, ITextureImageSource, ITextureSize } from "@feng3d/render-api";
+import { watcher } from "@feng3d/watcher";
+import { IGLTexturePixelStore } from "../data/IGLTexturePixelStore";
+import { getTextureCubeMapTarget } from "../utils/getTextureCubeMapTarget";
+import { getIGLTextureFormats } from "./getIGLTextureFormats";
+import { getIGLTextureTarget } from "./getIGLTextureTarget";
+
+declare global
+{
+ interface WebGLRenderingContext
+ {
+ _textures: Map
+ }
+
+ interface WebGLTexture
+ {
+ /**
+ * 销毁WebGL纹理。
+ */
+ destroy: () => void;
+ }
+}
+
+export const defaultTexturePixelStore: IGLTexturePixelStore = {
+ packAlignment: 4,
+ unpackAlignment: 4,
+ unpackFlipY: false,
+ unpackPremulAlpha: false,
+ unpackColorSpaceConversion: "BROWSER_DEFAULT_WEBGL",
+ packRowLength: 0,
+ packSkipPixels: 0,
+ packSkipRows: 0,
+ unpackRowLength: 0,
+ unpackImageHeight: 0,
+ unpackSkipPixels: 0,
+ unpackSkipRows: 0,
+ unpackSkipImages: 0,
+};
+
+export function getGLTexture(gl: WebGLRenderingContext, texture: ITexture)
+{
+ let webGLTexture = gl._textures.get(texture);
+ if (webGLTexture) return webGLTexture;
+
+ // 创建纹理
+ const createTexture = () =>
+ {
+ const target = getIGLTextureTarget(texture.dimension);
+ const { internalformat, format, type } = getIGLTextureFormats(texture.format);
+
+ webGLTexture = gl.createTexture(); // Create a texture object
+ gl._textures.set(texture, webGLTexture);
+
+ gl.bindTexture(gl[target], webGLTexture);
+
+ //
+ const { sources, generateMipmap } = texture;
+
+ // 设置纹理尺寸
+ const [width, height, depth] = texture.size;
+ const mipLevelCount = texture.mipLevelCount || 1;
+
+ if (sources)
+ {
+ sources.forEach((v) =>
+ {
+ const { textureOrigin, size } = v;
+ //
+ const mipLevel = v.mipLevel ?? 0;
+ const width = size?.[0];
+ const height = size?.[1];
+ const depthOrArrayLayers = size?.[2];
+ const xoffset = textureOrigin?.[0];
+ const yoffset = textureOrigin?.[1];
+ const zoffset = textureOrigin?.[2];
+ if (gl instanceof WebGL2RenderingContext)
+ {
+ const imageSource = v as ITextureImageSource;
+ if (imageSource.image)
+ {
+ const { image, imageOrigin, flipY, premultipliedAlpha } = imageSource;
+
+ //
+ const pixelStore: IGLTexturePixelStore = {};
+ pixelStore.unpackSkipPixels = imageOrigin?.[0] || 0;
+ pixelStore.unpackSkipRows = imageOrigin?.[1] || 0;
+ pixelStore.unpackFlipY = flipY || false;
+ pixelStore.unpackPremulAlpha = premultipliedAlpha || false;
+
+ setTexturePixelStore(gl, pixelStore);
+
+ if (target === "TEXTURE_2D" || target === "TEXTURE_CUBE_MAP")
+ {
+ const bindTarget = target === "TEXTURE_CUBE_MAP" ? getTextureCubeMapTarget(depthOrArrayLayers) : target;
+ if (width && height)
+ {
+ gl.texImage2D(gl[bindTarget], mipLevel, gl[internalformat], width, height, 0, gl[format], gl[type], image);
+ }
+ else
+ {
+ gl.texImage2D(gl[bindTarget], mipLevel, gl[internalformat], gl[format], gl[type], image);
+ }
+ }
+ else if (target === "TEXTURE_3D" || target === "TEXTURE_2D_ARRAY")
+ {
+ gl.texImage3D(gl[target], mipLevel, gl[internalformat], width, height, depth, 0, gl[format], gl[type], image);
+ }
+ else
+ {
+ console.error(`未处理 ${target} 纹理初始化存储!`);
+ }
+ }
+ else
+ {
+ const bufferSource = v as ITextureDataSource;
+ const { data, dataLayout, dataImageOrigin } = bufferSource;
+
+ //
+ const offset = dataLayout?.offset || 0;
+
+ //
+ const pixelStore: IGLTexturePixelStore = {};
+ pixelStore.unpackSkipPixels = dataImageOrigin?.[0] || 0;
+ pixelStore.unpackSkipRows = dataImageOrigin?.[1] || 0;
+ pixelStore.unpackSkipImages = dataImageOrigin?.[2] || 0;
+ pixelStore.unpackRowLength = dataLayout?.width;
+ pixelStore.unpackImageHeight = dataLayout?.height;
+
+ setTexturePixelStore(gl, pixelStore);
+
+ if (target === "TEXTURE_2D" || target === "TEXTURE_CUBE_MAP")
+ {
+ const bindTarget = target === "TEXTURE_CUBE_MAP" ? getTextureCubeMapTarget(depthOrArrayLayers) : target;
+ gl.texImage2D(gl[bindTarget], mipLevel, gl[internalformat], width, height, 0, gl[format], gl[type], data, offset);
+ }
+ else if (target === "TEXTURE_3D" || target === "TEXTURE_2D_ARRAY")
+ {
+ gl.texImage3D(gl[target], mipLevel, gl[internalformat], width, height, depth, 0, gl[format], gl[type], data, offset);
+ }
+ else
+ {
+ console.error(`未处理 ${target} 纹理初始化存储!`);
+ }
+ }
+ }
+ else
+ {
+ const imageSource = v as ITextureImageSource;
+ if (imageSource.image)
+ {
+ const { image, imageOrigin, flipY, premultipliedAlpha } = imageSource;
+
+ //
+ const pixelStore: IGLTexturePixelStore = {};
+ pixelStore.unpackSkipPixels = imageOrigin?.[0] || 0;
+ pixelStore.unpackSkipRows = imageOrigin?.[1] || 0;
+ pixelStore.unpackFlipY = flipY || false;
+ pixelStore.unpackPremulAlpha = premultipliedAlpha || false;
+
+ setTexturePixelStore(gl, pixelStore);
+
+ if (target === "TEXTURE_2D" || target === "TEXTURE_CUBE_MAP")
+ {
+ const bindTarget = target === "TEXTURE_CUBE_MAP" ? getTextureCubeMapTarget(depthOrArrayLayers) : target;
+ gl.texImage2D(gl[bindTarget], mipLevel, gl[format], gl[format], gl[type], image);
+ }
+ else
+ {
+ console.error(`未处理 ${target} 纹理初始化存储!`);
+ }
+ }
+ else
+ {
+ const bufferSource = v as ITextureDataSource;
+ const { data, dataLayout, dataImageOrigin } = bufferSource;
+
+ //
+ const offset = dataLayout?.offset || 0;
+
+ //
+ const pixelStore: IGLTexturePixelStore = {};
+ pixelStore.unpackSkipPixels = dataImageOrigin?.[0] || 0;
+ pixelStore.unpackSkipRows = dataImageOrigin?.[1] || 0;
+ pixelStore.unpackSkipImages = dataImageOrigin?.[2] || 0;
+ pixelStore.unpackRowLength = dataLayout?.width;
+ pixelStore.unpackImageHeight = dataLayout?.height;
+
+ setTexturePixelStore(gl, pixelStore);
+
+ if (target === "TEXTURE_2D" || target === "TEXTURE_CUBE_MAP")
+ {
+ const bindTarget = target === "TEXTURE_CUBE_MAP" ? getTextureCubeMapTarget(depthOrArrayLayers) : target;
+ console.assert(offset === 0, `WebGL1中ITextureDataLayout.offset必须为0`);
+ gl.texImage2D(gl[bindTarget], mipLevel, gl[format], width, height, 0, gl[format], gl[type], data);
+ }
+ else
+ {
+ console.error(`未处理 ${target} 纹理初始化存储!`);
+ }
+ }
+ }
+ });
+
+ //
+ if (generateMipmap)
+ {
+ gl.generateMipmap(gl[target]);
+ }
+ }
+ else
+ {
+ if (gl instanceof WebGL2RenderingContext)
+ {
+ if (target === "TEXTURE_2D" || target === "TEXTURE_CUBE_MAP")
+ {
+ gl.texStorage2D(gl[target], mipLevelCount, gl[internalformat], width, height);
+ }
+ else if (target === "TEXTURE_3D" || target === "TEXTURE_2D_ARRAY")
+ {
+ gl.texStorage3D(gl[target], mipLevelCount, gl[internalformat], width, height, depth);
+ }
+ else
+ {
+ console.error(`未处理 ${target} 纹理初始化存储!`);
+ }
+ }
+ else
+ {
+ if (target === "TEXTURE_2D" || target === "TEXTURE_CUBE_MAP")
+ {
+ for (let i = 0; i < mipLevelCount; i++)
+ {
+ gl.texImage2D(gl[target], i, gl[format], width, height, 0, gl[format], gl[type], null)
+ }
+ }
+ else
+ {
+ console.error(`未处理 ${target} 纹理初始化存储!`);
+ }
+ }
+ }
+ }
+ createTexture();
+
+ const updateSources = () =>
+ {
+ webGLTexture.destroy();
+ };
+
+ watcher.watch(texture, "sources", updateSources);
+
+ // 更新纹理
+ const updateTexture = () =>
+ {
+ const { writeTextures } = texture;
+ if (!writeTextures || writeTextures.length === 0) return;
+
+ const target = getIGLTextureTarget(texture.dimension);
+ const { format, type } = getIGLTextureFormats(texture.format);
+
+ gl.bindTexture(gl[target], webGLTexture);
+
+ writeTextures.forEach((v) =>
+ {
+ const { mipLevel, textureOrigin, size } = v;
+ //
+ const width = size?.[0];
+ const height = size?.[1];
+ const depthOrArrayLayers = size?.[2];
+ const xoffset = textureOrigin?.[0];
+ const yoffset = textureOrigin?.[1];
+ const zoffset = textureOrigin?.[2];
+
+ // 处理图片资源
+ const imageSource = v as ITextureImageSource;
+ if (imageSource.image)
+ {
+ const { image, imageOrigin, flipY, premultipliedAlpha } = imageSource;
+
+ //
+ const pixelStore: IGLTexturePixelStore = {};
+ pixelStore.unpackSkipPixels = imageOrigin?.[0] || 0;
+ pixelStore.unpackSkipRows = imageOrigin?.[1] || 0;
+ pixelStore.unpackFlipY = flipY || false;
+ pixelStore.unpackPremulAlpha = premultipliedAlpha || false;
+
+ setTexturePixelStore(gl, pixelStore);
+
+ if (gl instanceof WebGL2RenderingContext)
+ {
+ if (target === "TEXTURE_2D" || target === "TEXTURE_CUBE_MAP")
+ {
+ const bindTarget = target === "TEXTURE_CUBE_MAP" ? getTextureCubeMapTarget(depthOrArrayLayers) : target;
+
+ if (width && height)
+ {
+ gl.texSubImage2D(gl[bindTarget], mipLevel, xoffset, yoffset, width, height, gl[format], gl[type], image);
+ }
+ else
+ {
+ gl.texSubImage2D(gl[bindTarget], mipLevel, xoffset, yoffset, gl[format], gl[type], image);
+ }
+ }
+ else if (target === "TEXTURE_3D" || target === "TEXTURE_2D_ARRAY")
+ {
+ gl.texSubImage3D(gl[target], mipLevel, xoffset, yoffset, zoffset, width, height, depthOrArrayLayers, gl[format], gl[type], image);
+ }
+ else
+ {
+ console.error(`未处理 WebGL1 中 ${target} 纹理类型的图片资源上传!`);
+ }
+ }
+ // 处理 WebGL1
+ else
+ {
+ // eslint-disable-next-line no-lonely-if
+ if (target === "TEXTURE_2D" || target === "TEXTURE_CUBE_MAP")
+ {
+ const bindTarget = target === "TEXTURE_CUBE_MAP" ? getTextureCubeMapTarget(depthOrArrayLayers) : target;
+
+ gl.texSubImage2D(gl[bindTarget], mipLevel, xoffset, yoffset, gl[format], gl[type], image);
+ }
+ else
+ {
+ console.error(`WebGL1 中 不支持 ${target} 纹理类型!`);
+ }
+ }
+ return;
+ }
+
+ // 处理数据资源
+ const bufferSource = v as ITextureDataSource;
+ const { data, dataLayout, dataImageOrigin } = bufferSource;
+
+ //
+ const offset = dataLayout?.offset || 0;
+
+ //
+ const pixelStore: IGLTexturePixelStore = {};
+ pixelStore.unpackSkipPixels = dataImageOrigin?.[0] || 0;
+ pixelStore.unpackSkipRows = dataImageOrigin?.[1] || 0;
+ pixelStore.unpackSkipImages = dataImageOrigin?.[2] || 0;
+ pixelStore.unpackRowLength = dataLayout?.width;
+ pixelStore.unpackImageHeight = dataLayout?.height;
+
+ setTexturePixelStore(gl, pixelStore);
+
+ if (gl instanceof WebGL2RenderingContext)
+ {
+ // eslint-disable-next-line no-lonely-if
+ if (target === "TEXTURE_2D" || target === "TEXTURE_CUBE_MAP")
+ {
+ const bindTarget = target === "TEXTURE_CUBE_MAP" ? getTextureCubeMapTarget(depthOrArrayLayers) : target;
+
+ gl.texSubImage2D(gl[bindTarget], mipLevel, xoffset, yoffset, width, height, gl[format], gl[type], data, offset);
+ }
+ else if (target === "TEXTURE_3D" || target === "TEXTURE_2D_ARRAY")
+ {
+ gl.texSubImage3D(gl[target], mipLevel, xoffset, yoffset, zoffset, width, height, depthOrArrayLayers, gl[format], gl[type], data, offset);
+ }
+ else
+ {
+ console.error(`未处理 WebGL1 中 ${target} 纹理类型的像素资源上传。`);
+ }
+ }
+ // 处理 WebGL1
+ else
+ {
+ // eslint-disable-next-line no-lonely-if
+ if (target === "TEXTURE_2D" || target === "TEXTURE_CUBE_MAP")
+ {
+ const bindTarget = target === "TEXTURE_CUBE_MAP" ? getTextureCubeMapTarget(depthOrArrayLayers) : target;
+
+ gl.texSubImage2D(gl[bindTarget], mipLevel, xoffset, yoffset, width, height, gl[format], gl[type], data);
+
+ console.assert(!offset, `WebGL1 不支持 IGLTextureDataSource.dataLayout.offset !`)
+ }
+ else
+ {
+ console.error(`WebGL1 中 不支持 ${target} 纹理类型!`);
+ }
+ }
+ });
+ };
+ updateTexture();
+
+ watcher.watchs(texture, ["generateMipmap"], updateTexture);
+ watcher.watch(texture, "writeTextures", updateTexture);
+
+ // 监听纹理尺寸发生变化
+ const resize = (newValue: ITextureSize, oldValue: ITextureSize) =>
+ {
+ if (!!newValue && !!oldValue)
+ {
+ if (newValue[0] === oldValue[0]
+ && newValue[1] === oldValue[1]
+ && (newValue[2] || 1) === (oldValue[2] || 1)
+ )
+ {
+ return;
+ }
+ }
+
+ webGLTexture.destroy();
+ };
+ watcher.watch(texture, "size", resize);
+
+ webGLTexture.destroy = () =>
+ {
+ //
+ gl.deleteTexture(webGLTexture);
+ gl._textures.delete(texture);
+ //
+ watcher.unwatchs(texture, ["generateMipmap"], updateTexture);
+ watcher.unwatch(texture, "sources", updateSources);
+ watcher.unwatch(texture, "writeTextures", updateTexture);
+ watcher.unwatch(texture, "size", resize);
+ //
+ delete webGLTexture.destroy;
+ };
+
+ return webGLTexture;
+}
+
+export function deleteTexture(gl: WebGLRenderingContext, texture: ITexture)
+{
+ const webGLTexture = gl._textures.get(texture);
+ if (!webGLTexture) return;
+
+ webGLTexture.destroy();
+}
+
+/**
+ * 设置像素解包打包时参数。
+ *
+ * @param gl
+ * @param pixelStore 像素解包打包时参数。
+ */
+function setTexturePixelStore(gl: WebGLRenderingContext, pixelStore: IGLTexturePixelStore)
+{
+ const {
+ packAlignment,
+ unpackAlignment,
+ unpackFlipY,
+ unpackPremulAlpha,
+ unpackColorSpaceConversion,
+ packRowLength,
+ packSkipPixels,
+ packSkipRows,
+ unpackRowLength,
+ unpackImageHeight,
+ unpackSkipPixels,
+ unpackSkipRows,
+ unpackSkipImages,
+ } = { ...defaultTexturePixelStore, ...pixelStore };
+
+ //
+ gl.pixelStorei(gl.PACK_ALIGNMENT, packAlignment);
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, unpackAlignment);
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, unpackFlipY);
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, unpackPremulAlpha);
+ gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl[unpackColorSpaceConversion]);
+
+ if (gl instanceof WebGL2RenderingContext)
+ {
+ gl.pixelStorei(gl.PACK_ROW_LENGTH, packRowLength);
+ gl.pixelStorei(gl.PACK_SKIP_PIXELS, packSkipPixels);
+ gl.pixelStorei(gl.PACK_SKIP_ROWS, packSkipRows);
+ gl.pixelStorei(gl.UNPACK_ROW_LENGTH, unpackRowLength);
+ gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, unpackImageHeight);
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, unpackSkipPixels);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, unpackSkipRows);
+ gl.pixelStorei(gl.UNPACK_SKIP_IMAGES, unpackSkipImages);
+ }
+}
\ No newline at end of file
diff --git a/src/caches/getWebGLTransformFeedback.ts b/src/caches/getGLTransformFeedback.ts
similarity index 77%
rename from src/caches/getWebGLTransformFeedback.ts
rename to src/caches/getGLTransformFeedback.ts
index 1fde8baa5911b97a5446d011b1674a76efbdf1bb..d18e3ad93ccd131fd2cc5f5e712004ce4c28bd59 100644
--- a/src/caches/getWebGLTransformFeedback.ts
+++ b/src/caches/getGLTransformFeedback.ts
@@ -1,5 +1,6 @@
import { IGLTransformFeedback } from "../data/IGLTransformFeedback";
-import { getWebGLBuffer } from "./getWebGLBuffer";
+import { getIGLVertexBuffer } from "../runs/getIGLBuffer";
+import { getGLBuffer } from "./getGLBuffer";
declare global
{
@@ -9,7 +10,7 @@ declare global
}
}
-export function getWebGLTransformFeedback(gl: WebGLRenderingContext, transformFeedback: IGLTransformFeedback)
+export function getGLTransformFeedback(gl: WebGLRenderingContext, transformFeedback: IGLTransformFeedback)
{
let webGLTransformFeedback = gl._transforms.get(transformFeedback);
if (webGLTransformFeedback) return webGLTransformFeedback;
@@ -22,8 +23,9 @@ export function getWebGLTransformFeedback(gl: WebGLRenderingContext, transformFe
gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, webGLTransformFeedback);
transformFeedback.bindBuffers.forEach((v) =>
{
- const { index, buffer } = v;
- const webGLBuffer = getWebGLBuffer(gl, buffer);
+ const { index, data } = v;
+ const buffer = getIGLVertexBuffer(data, "STREAM_COPY");
+ const webGLBuffer = getGLBuffer(gl, buffer);
gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, index, webGLBuffer);
});
diff --git a/src/caches/getWebGLAttributeType.ts b/src/caches/getIGLAttributeType.ts
similarity index 76%
rename from src/caches/getWebGLAttributeType.ts
rename to src/caches/getIGLAttributeType.ts
index 44645adf4ee51696f5c2dc53e81ef5ab777a7936..d2d18ce8cdb0ea2b84c6f67a098abd8d1b8615fa 100644
--- a/src/caches/getWebGLAttributeType.ts
+++ b/src/caches/getIGLAttributeType.ts
@@ -1,7 +1,7 @@
/**
* WebGL 属性类型。
*/
-export type IWebGLAttributeType = keyof typeof webglAttributeTypeValue;
+export type IGLAttributeType = keyof typeof webglAttributeTypeValue;
/**
* 获取顶点数据类型名称。
@@ -9,7 +9,7 @@ export type IWebGLAttributeType = keyof typeof webglAttributeTypeValue;
* @param gl
* @param value
*/
-export function getWebGLAttributeValueType(value: keyof typeof webglAttributeValueType)
+export function getIGLAttributeType(value: keyof typeof webglAttributeValueType): IGLAttributeType
{
return webglAttributeValueType[value];
}
diff --git a/src/caches/getIGLBlitFramebuffer.ts b/src/caches/getIGLBlitFramebuffer.ts
new file mode 100644
index 0000000000000000000000000000000000000000..42755ab243b54f5c62bcaa143bec42bf2e7cc62c
--- /dev/null
+++ b/src/caches/getIGLBlitFramebuffer.ts
@@ -0,0 +1,81 @@
+import { ICopyTextureToTexture, IImageCopyTexture, IRenderPassColorAttachment, IRenderPassDepthStencilAttachment, ITextureView } from "@feng3d/render-api";
+import { IGLBlitFramebuffer, IGLBlitFramebufferItem } from "../data/IGLBlitFramebuffer";
+
+/**
+ * 通过 IGLBlitFramebuffer 实现纹理之间拷贝并不靠谱。
+ *
+ * @param copyTextureToTexture GL纹理之间拷贝。
+ * @returns
+ */
+export function getIGLBlitFramebuffer(copyTextureToTexture: ICopyTextureToTexture)
+{
+ const { source, destination, copySize } = copyTextureToTexture;
+
+ const sourceAspect = source.aspect || "all";
+ const destinationAspect = destination.aspect || "all";
+
+ console.assert(sourceAspect === destinationAspect, `拷贝纹理时两个纹理的 aspect 必须相同!`);
+
+ const sourceColorAttachments: IRenderPassColorAttachment[] = [];
+ let sourceDepthStencilAttachment: IRenderPassDepthStencilAttachment;
+ const destinationColorAttachments: IRenderPassColorAttachment[] = [];
+ let destinationDepthStencilAttachment: IRenderPassDepthStencilAttachment;
+
+ //
+ let mask: "COLOR_BUFFER_BIT" | "DEPTH_BUFFER_BIT" | "STENCIL_BUFFER_BIT";
+ if (sourceAspect === "all")
+ {
+ mask = "COLOR_BUFFER_BIT";
+ sourceColorAttachments.push({ view: getIGLTextureView(source) });
+ destinationColorAttachments.push({ view: getIGLTextureView(destination) });
+ }
+ else if (sourceAspect === "depth-only")
+ {
+ mask = "DEPTH_BUFFER_BIT";
+ sourceDepthStencilAttachment = { view: getIGLTextureView(source) };
+ destinationDepthStencilAttachment = { view: getIGLTextureView(destination) };
+ }
+ else if (sourceAspect === "stencil-only")
+ {
+ mask = "STENCIL_BUFFER_BIT";
+ sourceDepthStencilAttachment = { view: getIGLTextureView(source) };
+ destinationDepthStencilAttachment = { view: getIGLTextureView(destination) };
+ }
+
+ const sourceOrigin = source.origin || [0, 0];
+ const destinationOrigin = destination.origin || [0, 0];
+ //
+ const blitFramebufferItem: IGLBlitFramebufferItem = [
+ sourceOrigin[0], sourceOrigin[1], sourceOrigin[0] + copySize[0], sourceOrigin[1] + copySize[1],
+ destinationOrigin[0], destinationOrigin[1], destinationOrigin[0] + copySize[0], destinationOrigin[1] + copySize[1],
+ mask, "NEAREST",
+ ];
+
+ const blitFramebuffer: IGLBlitFramebuffer = {
+ __type: "BlitFramebuffer",
+ read: {
+ colorAttachments: sourceColorAttachments,
+ depthStencilAttachment: sourceDepthStencilAttachment,
+ },
+ draw: {
+ colorAttachments: destinationColorAttachments,
+ depthStencilAttachment: destinationDepthStencilAttachment,
+ },
+ blitFramebuffers: [blitFramebufferItem]
+ };
+
+ return blitFramebuffer;
+}
+
+function getIGLTextureView(source: IImageCopyTexture)
+{
+ if (!source.texture) return undefined;
+
+ const textureView: ITextureView = {
+ texture: source.texture,
+ baseMipLevel: source.mipLevel,
+ baseArrayLayer: source.origin?.[2],
+ };
+
+ return textureView;
+}
\ No newline at end of file
diff --git a/src/caches/getIGLDrawMode.ts b/src/caches/getIGLDrawMode.ts
new file mode 100644
index 0000000000000000000000000000000000000000..529e35b6eb06f4685c0416e34af0a5f04fbcacda
--- /dev/null
+++ b/src/caches/getIGLDrawMode.ts
@@ -0,0 +1,47 @@
+import { IPrimitiveTopology } from "@feng3d/render-api";
+
+export function getIGLDrawMode(topology: IPrimitiveTopology): IGLDrawMode
+{
+ let drawMode = drawModeMap[topology];
+
+ console.assert(!!drawMode, `WebGL 不支持参数 IPrimitiveTopology ${topology} !`);
+
+ drawMode = drawMode || topology as any;
+
+ return drawMode;
+}
+
+const drawModeMap: { [key: string]: IGLDrawMode } = {
+ "point-list": "POINTS",
+ "line-list": "LINES",
+ "line-strip": "LINE_STRIP",
+ "triangle-list": "TRIANGLES",
+ "triangle-strip": "TRIANGLE_STRIP",
+ "LINE_LOOP": "LINE_LOOP",
+ "TRIANGLE_FAN": "TRIANGLE_FAN",
+};
+
+/**
+ * 渲染模式,默认 TRIANGLES,每三个顶点绘制一个三角形。
+ *
+ * * POINTS 绘制单个点。
+ * * LINE_LOOP 绘制循环连线。
+ * * LINE_STRIP 绘制连线
+ * * LINES 每两个顶点绘制一条线段。
+ * * TRIANGLES 每三个顶点绘制一个三角形。
+ * * TRIANGLE_STRIP 绘制三角形条带。
+ * * TRIANGLE_FAN 绘制三角扇形。
+ *
+ * A GLenum specifying the type primitive to render. Possible values are:
+ *
+ * * gl.POINTS: Draws a single dot.
+ * * gl.LINE_STRIP: Draws a straight line to the next vertex.
+ * * gl.LINE_LOOP: Draws a straight line to the next vertex, and connects the last vertex back to the first.
+ * * gl.LINES: Draws a line between a pair of vertices.
+ * * gl.TRIANGLE_STRIP
+ * * gl.TRIANGLE_FAN
+ * * gl.TRIANGLES: Draws a triangle for a group of three vertices.
+ *
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/drawElements
+ */
+export type IGLDrawMode = "POINTS" | "LINE_STRIP" | "LINE_LOOP" | "LINES" | "TRIANGLE_STRIP" | "TRIANGLE_FAN" | "TRIANGLES";
diff --git a/src/caches/getIGLRenderPassDescriptorWithMultisample.ts b/src/caches/getIGLRenderPassDescriptorWithMultisample.ts
new file mode 100644
index 0000000000000000000000000000000000000000..326c3430bdc1396b4f19f02a7a347a961473cfc4
--- /dev/null
+++ b/src/caches/getIGLRenderPassDescriptorWithMultisample.ts
@@ -0,0 +1,88 @@
+import { IRenderPassColorAttachment, IRenderPassDescriptor, ITextureFormat, ITextureView } from "@feng3d/render-api";
+import { IGLBlitFramebuffer } from "../data/IGLBlitFramebuffer";
+import { GLRenderbufferInternalformat, IGLRenderbuffer } from "../data/IGLRenderbuffer";
+import { getIGLTextureFormats } from "./getIGLTextureFormats";
+
+/**
+ *
+ * 当需要渲染到纹理并且开启多重采样时,就必须使用支持多重采样的渲染缓冲区来进行接受中间结果再拷贝到模板纹理上。
+ *
+ * 当`passDescriptor.multisample`值存在时,引擎将会自动创建支持`multisample`的`IGLRenderbuffer`用于接收颜色附件的结果。在渲染通道执行结束后在由`IGLRenderbuffer`拷贝到对应纹理上。
+ *
+ * @param sourcePassDescriptor 需要渲染到纹理并且开启多重采样的渲染通道描述。
+ */
+export function getIGLRenderPassDescriptorWithMultisample(sourcePassDescriptor: IRenderPassDescriptor): IGLRenderPassDescriptorWithMultisample
+{
+ if (sourcePassDescriptor[_IGLRenderPassDescriptorWithMultisample]) return sourcePassDescriptor[_IGLRenderPassDescriptorWithMultisample];
+
+ const texture = (sourcePassDescriptor.colorAttachments[0].view as ITextureView).texture;
+
+ const textureSize = texture.size;
+
+ const renderbuffers: IGLRenderbuffer[] = [];
+
+ // 创建支持 多重采样的 渲染通道
+ const passDescriptor: IRenderPassDescriptor = {
+ colorAttachments: sourcePassDescriptor.colorAttachments.map((v) =>
+ {
+ const texture = v.view.texture;
+
+ const renderbuffer: IGLRenderbuffer = {
+ internalformat: getGLRenderbufferInternalformat(texture.format),
+ width: textureSize[0],
+ height: textureSize[1],
+ };
+ renderbuffers.push(renderbuffer);
+
+ const colorAttachment: IRenderPassColorAttachment = {
+ ...v,
+ view: renderbuffer as any,
+ };
+ return colorAttachment;
+ }),
+ depthStencilAttachment: sourcePassDescriptor.depthStencilAttachment,
+ sampleCount: sourcePassDescriptor.sampleCount,
+ };
+
+ // 拷贝 渲染缓冲区到 IGLTexture
+ const blitFramebuffer: IGLBlitFramebuffer = {
+ __type: "BlitFramebuffer",
+ read: passDescriptor,
+ draw: sourcePassDescriptor,
+ blitFramebuffers: [[0, 0, textureSize[0], textureSize[1],
+ 0, 0, textureSize[0], textureSize[1],
+ "COLOR_BUFFER_BIT", "NEAREST"]],
+ };
+
+ sourcePassDescriptor[_IGLRenderPassDescriptorWithMultisample] = { passDescriptor, blitFramebuffer, renderbuffers } as IGLRenderPassDescriptorWithMultisample;
+
+ return sourcePassDescriptor[_IGLRenderPassDescriptorWithMultisample];
+}
+
+function getGLRenderbufferInternalformat(format?: ITextureFormat)
+{
+ const { internalformat } = getIGLTextureFormats(format);
+
+ return internalformat as GLRenderbufferInternalformat;
+}
+
+export const _IGLRenderPassDescriptorWithMultisample = "_IGLRenderPassDescriptorWithMultisample";
+
+/**
+ * 由`passDescriptor.multisample`值存在的IGLRenderPassDescriptor生成。
+ */
+export interface IGLRenderPassDescriptorWithMultisample
+{
+ /**
+ * 渲染到渲染缓冲区上。
+ */
+ passDescriptor: IRenderPassDescriptor;
+ /**
+ * 拷贝渲染缓冲区到目标纹理中。
+ */
+ blitFramebuffer: IGLBlitFramebuffer;
+ /**
+ * 需要销毁的临时渲染缓冲区。
+ */
+ renderbuffers: IGLRenderbuffer[];
+}
\ No newline at end of file
diff --git a/src/caches/getIGLTextureFormats.ts b/src/caches/getIGLTextureFormats.ts
new file mode 100644
index 0000000000000000000000000000000000000000..995dfaea4b9f09541bfe33be6f30831c71e7be94
--- /dev/null
+++ b/src/caches/getIGLTextureFormats.ts
@@ -0,0 +1,109 @@
+import { ITextureFormat } from "@feng3d/render-api";
+import { IGLTextureFormats } from "../data/IGLTextureFormats";
+
+export function getIGLTextureFormats(format: ITextureFormat = "rgba8unorm")
+{
+ const glTextureFormat: IGLTextureFormats = formatMap[format];
+
+ console.assert(!!glTextureFormat, `未处理格式 ${format};或者WebGL不支持纹理, 该格式只在WebGPU中支持!`);
+
+ return glTextureFormat;
+}
+
+const formatMap: { [key: string]: IGLTextureFormats } = {
+ "r8unorm": { internalformat: "R8", format: "RED", type: "UNSIGNED_BYTE", },
+ "r8snorm": undefined,
+ "r8uint": { internalformat: "R8", format: "RED", type: "UNSIGNED_BYTE", },
+ "r8sint": undefined,
+ "r16uint": undefined,
+ "r16sint": undefined,
+ "r16float": { internalformat: "R16F", format: "RED", type: "HALF_FLOAT" },
+ "rg8unorm": undefined,
+ "rg8snorm": undefined,
+ "rg8uint": undefined,
+ "rg8sint": undefined,
+ "r32uint": undefined,
+ "r32sint": undefined,
+ "r32float": undefined,
+ "rg16uint": undefined,
+ "rg16sint": undefined,
+ "rg16float": { internalformat: "RG16F", format: "RG", type: "HALF_FLOAT" },
+ "rgba8unorm": { internalformat: "RGBA8", format: "RGBA", type: "UNSIGNED_BYTE" },
+ "rgba8unorm-srgb": { internalformat: "SRGB8", format: "RGB", type: "UNSIGNED_BYTE", },
+ "rgba8snorm": undefined,
+ "rgba8uint": { internalformat: "RGBA8UI", format: "RGBA_INTEGER", type: "UNSIGNED_BYTE", },
+ "rgba8sint": undefined,
+ "bgra8unorm": undefined,
+ "bgra8unorm-srgb": undefined,
+ "rgb9e5ufloat": undefined,
+ "rgb10a2uint": undefined,
+ "rgb10a2unorm": undefined,
+ "rg11b10ufloat": undefined,
+ "rg32uint": undefined,
+ "rg32sint": undefined,
+ "rg32float": undefined,
+ "rgba16uint": undefined,
+ "rgba16sint": undefined,
+ "rgba16float": { internalformat: "RGB16F", format: "RGB", type: "HALF_FLOAT" },
+ "rgba32uint": undefined,
+ "rgba32sint": undefined,
+ "rgba32float": { internalformat: "RGBA32F", format: "RGBA", type: "FLOAT" },
+ "stencil8": undefined,
+ "depth16unorm": { internalformat: "DEPTH_COMPONENT16", format: "DEPTH_COMPONENT", type: "UNSIGNED_SHORT", },
+ "depth24plus": undefined,
+ "depth24plus-stencil8": undefined,
+ "depth32float": undefined,
+ "depth32float-stencil8": undefined,
+ "bc1-rgba-unorm": undefined,
+ "bc1-rgba-unorm-srgb": undefined,
+ "bc2-rgba-unorm": undefined,
+ "bc2-rgba-unorm-srgb": undefined,
+ "bc3-rgba-unorm": undefined,
+ "bc3-rgba-unorm-srgb": undefined,
+ "bc4-r-unorm": undefined,
+ "bc4-r-snorm": undefined,
+ "bc5-rg-unorm": undefined,
+ "bc5-rg-snorm": undefined,
+ "bc6h-rgb-ufloat": undefined,
+ "bc6h-rgb-float": undefined,
+ "bc7-rgba-unorm": undefined,
+ "bc7-rgba-unorm-srgb": undefined,
+ "etc2-rgb8unorm": undefined,
+ "etc2-rgb8unorm-srgb": undefined,
+ "etc2-rgb8a1unorm": undefined,
+ "etc2-rgb8a1unorm-srgb": undefined,
+ "etc2-rgba8unorm": undefined,
+ "etc2-rgba8unorm-srgb": undefined,
+ "eac-r11unorm": undefined,
+ "eac-r11snorm": undefined,
+ "eac-rg11unorm": undefined,
+ "eac-rg11snorm": undefined,
+ "astc-4x4-unorm": undefined,
+ "astc-4x4-unorm-srgb": undefined,
+ "astc-5x4-unorm": undefined,
+ "astc-5x4-unorm-srgb": undefined,
+ "astc-5x5-unorm": undefined,
+ "astc-5x5-unorm-srgb": undefined,
+ "astc-6x5-unorm": undefined,
+ "astc-6x5-unorm-srgb": undefined,
+ "astc-6x6-unorm": undefined,
+ "astc-6x6-unorm-srgb": undefined,
+ "astc-8x5-unorm": undefined,
+ "astc-8x5-unorm-srgb": undefined,
+ "astc-8x6-unorm": undefined,
+ "astc-8x6-unorm-srgb": undefined,
+ "astc-8x8-unorm": undefined,
+ "astc-8x8-unorm-srgb": undefined,
+ "astc-10x5-unorm": undefined,
+ "astc-10x5-unorm-srgb": undefined,
+ "astc-10x6-unorm": undefined,
+ "astc-10x6-unorm-srgb": undefined,
+ "astc-10x8-unorm": undefined,
+ "astc-10x8-unorm-srgb": undefined,
+ "astc-10x10-unorm": undefined,
+ "astc-10x10-unorm-srgb": undefined,
+ "astc-12x10-unorm": undefined,
+ "astc-12x10-unorm-srgb": undefined,
+ "astc-12x12-unorm": undefined,
+ "astc-12x12-unorm-srgb": undefined,
+};
\ No newline at end of file
diff --git a/src/caches/getIGLTextureSize.ts b/src/caches/getIGLTextureSize.ts
deleted file mode 100644
index a79b381fe915db0104fdaac6fca97d2fba3819f8..0000000000000000000000000000000000000000
--- a/src/caches/getIGLTextureSize.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { IGLTexture } from "@feng3d/webgl";
-import { getIGLTextureSourceSize } from "./getIGLTextureSourceSize";
-
-export function getIGLTextureSize(glTexture: IGLTexture)
-{
- let size: [width: number, height?: number, depthOrArrayLayers?: number];
- if (glTexture.storage)
- {
- size = [glTexture.storage.width, glTexture.storage.height];
- if (glTexture.storage.depth)
- {
- size.push(glTexture.storage.depth);
- }
- }
-
- //
- if (glTexture.sources)
- {
- size = getIGLTextureSourceSize(glTexture.sources[0]);
- }
-
- return size;
-}
\ No newline at end of file
diff --git a/src/caches/getIGLTextureSourceSize.ts b/src/caches/getIGLTextureSourceSize.ts
deleted file mode 100644
index 72583a636e983babf8652601ab324449da6c3479..0000000000000000000000000000000000000000
--- a/src/caches/getIGLTextureSourceSize.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import { IGLBufferSource, IGLImageSource, IGLTextureSource } from "../data/IGLTexture";
-import { getTexImageSourceSize } from "./getTexImageSourceSize";
-
-export function getIGLTextureSourceSize(glTextureSource: IGLTextureSource)
-{
- const size: [width: number, height?: number, depthOrArrayLayers?: number] = [] as any;
-
- //
- const glImageSource = glTextureSource as IGLImageSource;
- const glBufferSource = glTextureSource as IGLBufferSource;
- const source = glImageSource.source;
- if (source)
- {
- const texImageSourceSize = getTexImageSourceSize(source);
- size[0] = texImageSourceSize.width;
- size[1] = texImageSourceSize.height;
- }
- else
- {
- size[0] = glBufferSource.width;
- size[1] = glBufferSource.height;
- }
-
- if (glTextureSource.depth)
- {
- size[2] = glTextureSource.depth;
- }
-
- return size;
-}
diff --git a/src/caches/getIGLTextureTarget.ts b/src/caches/getIGLTextureTarget.ts
new file mode 100644
index 0000000000000000000000000000000000000000..284df9a46865e38c44bf59145380d48c8708472d
--- /dev/null
+++ b/src/caches/getIGLTextureTarget.ts
@@ -0,0 +1,19 @@
+import { ITextureDimension } from "@feng3d/render-api";
+import { IGLTextureTarget } from "../data/IGLTexture";
+
+export function getIGLTextureTarget(dimension: ITextureDimension = "2d")
+{
+ const target: IGLTextureTarget = dimensionMap[dimension];
+
+ console.assert(!!target, `WebGL 不支持纹理维度 ${dimension} , 该维度只在WebGPU中支持!`);
+
+ return target;
+}
+const dimensionMap: { [key: string]: IGLTextureTarget } = {
+ "1d": undefined,
+ "2d": "TEXTURE_2D",
+ "2d-array": "TEXTURE_2D_ARRAY",
+ "cube": "TEXTURE_CUBE_MAP",
+ "cube-array": undefined,
+ "3d": "TEXTURE_3D",
+};
\ No newline at end of file
diff --git a/src/caches/getTexImageSourceSize.ts b/src/caches/getTexImageSourceSize.ts
deleted file mode 100644
index 235ae20cd6924f8f2cbd72537f2711751115cb77..0000000000000000000000000000000000000000
--- a/src/caches/getTexImageSourceSize.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-export function getTexImageSourceSize(texImageSource: TexImageSource)
-{
- let width: number;
- let height: number;
- if (texImageSource instanceof VideoFrame)
- {
- width = texImageSource.codedWidth;
- height = texImageSource.codedHeight;
- }
- else if (texImageSource instanceof HTMLVideoElement)
- {
- width = texImageSource.videoWidth;
- height = texImageSource.videoHeight;
- }
- else
- {
- width = texImageSource.width;
- height = texImageSource.height;
- }
- return { width, height };
-}
\ No newline at end of file
diff --git a/src/caches/getTexture.ts b/src/caches/getTexture.ts
deleted file mode 100644
index caa96236bf32fba03dbb6794477b6e16bff43dda..0000000000000000000000000000000000000000
--- a/src/caches/getTexture.ts
+++ /dev/null
@@ -1,308 +0,0 @@
-import { watcher } from "@feng3d/watcher";
-import { GLTextureTarget, IGLTexture } from "../data/IGLTexture";
-import { IGLTexturePixelStore } from "../data/IGLTexturePixelStore";
-import { defaultBufferSource, defaultImageSource, defaultTexture } from "../runs/runTexture";
-
-declare global
-{
- interface WebGLRenderingContext
- {
- _textures: Map
- }
-
- interface WebGLTexture
- {
- /**
- * 纹理绑定点。
- *
- * 默认"TEXTURE_2D"。
- */
- textureTarget: GLTextureTarget;
-
- /**
- * 销毁WebGL纹理。
- */
- destroy: () => void;
- }
-}
-
-export const defaultTexturePixelStore: IGLTexturePixelStore = {
- packAlignment: 4,
- unpackAlignment: 4,
- unpackFlipY: false,
- unpackPremulAlpha: false,
- unpackColorSpaceConversion: "BROWSER_DEFAULT_WEBGL",
- packRowLength: 0,
- packSkipPixels: 0,
- packSkipRows: 0,
- unpackRowLength: 0,
- unpackImageHeight: 0,
- unpackSkipPixels: 0,
- unpackSkipRows: 0,
- unpackSkipImages: 0,
-};
-
-export function getTexture(gl: WebGLRenderingContext, texture: IGLTexture)
-{
- let webGLTexture = gl._textures.get(texture);
- if (webGLTexture) return webGLTexture;
-
- webGLTexture = gl.createTexture(); // Create a texture object
- gl._textures.set(texture, webGLTexture);
-
- //
- const internalformat = texture.internalformat || defaultTexture.internalformat;
- const storage = texture.storage;
- if (gl instanceof WebGL2RenderingContext)
- {
- if (storage)
- {
- const { target } = { ...defaultTexture, ...texture };
- const { levels, width, height, depth } = storage;
-
- gl.bindTexture(gl[target], webGLTexture);
-
- if (target === "TEXTURE_2D" || target === "TEXTURE_CUBE_MAP")
- {
- gl.texStorage2D(gl[target], levels, gl[internalformat], width, height);
- }
- else if (target === "TEXTURE_3D" || target === "TEXTURE_2D_ARRAY")
- {
- gl.texStorage3D(gl[target], levels, gl[internalformat], width, height, depth);
- }
- else
- {
- console.error(`未处理 ${target} 纹理初始化存储!`);
- }
- }
- }
-
- const updateTexture = () =>
- {
- const { target, generateMipmap, format, type, sources, pixelStore } = { ...defaultTexture, ...texture };
-
- setTexturePixelStore(gl, pixelStore);
- // 绑定纹理
- gl.bindTexture(gl[target], webGLTexture);
-
- webGLTexture.textureTarget = target;
-
- sources?.forEach((sourceItem) =>
- {
- // 设置纹理图片
- if (target === "TEXTURE_2D" || target === "TEXTURE_CUBE_MAP")
- {
- const bindTarget = target === "TEXTURE_CUBE_MAP" ? sourceItem.cubeTarget : target;
-
- if ("source" in sourceItem)
- {
- const { level, source, width, height, border } = { ...defaultImageSource, ...sourceItem };
- if (width && height)
- {
- (gl as any as WebGL2RenderingContext).texImage2D(gl[bindTarget], level, gl[internalformat], width, height, border, gl[format], gl[type], source);
- }
- else
- {
- gl.texImage2D(gl[bindTarget], level, gl[internalformat], gl[format], gl[type], source);
- }
- }
- else
- {
- const { level, width, height, border, pixels, srcOffset } = { ...defaultBufferSource, ...sourceItem };
- if (srcOffset)
- {
- (gl as any as WebGL2RenderingContext).texImage2D(gl[bindTarget], level, gl[internalformat], width, height, border, gl[format], gl[type], pixels, srcOffset);
- }
- else
- {
- gl.texImage2D(gl[bindTarget], level, gl[internalformat], width, height, border, gl[format], gl[type], pixels);
- }
- }
- }
- else if (target === "TEXTURE_2D_ARRAY" || target === "TEXTURE_3D")
- {
- if (gl instanceof WebGL2RenderingContext)
- {
- if ("source" in sourceItem)
- {
- const { level, width, height, depth, border, source } = { ...defaultBufferSource, ...sourceItem };
- gl.texImage3D(gl[target], level, gl[internalformat], width, height, depth, border, gl[format], gl[type], source);
- }
- else
- {
- const { level, width, height, depth, border, pixels, srcOffset } = { ...defaultBufferSource, ...sourceItem };
- if (srcOffset)
- {
- gl.texImage3D(gl[target], level, gl[internalformat], width, height, depth, border, gl[format], gl[type], pixels, srcOffset);
- }
- else
- {
- gl.texImage3D(gl[target], level, gl[internalformat], width, height, depth, border, gl[format], gl[type], pixels);
- }
- }
- }
- }
- else
- {
- throw `未处理 ${target}`;
- }
- });
-
- if (generateMipmap)
- {
- gl.generateMipmap(gl[target]);
- }
- };
- updateTexture();
- watcher.watchobject(texture, { pixelStore: { unpackFlipY: undefined, unpackPremulAlpha: undefined } }, updateTexture);
- watcher.watchs(texture, ["sources", "generateMipmap", "internalformat", "format", "type"], updateTexture);
-
- const writeTexture = () =>
- {
- const { writeTextures } = texture;
- writeTextures?.forEach((v) =>
- {
- const { target, format, type } = { ...defaultTexture, ...texture };
- gl.bindTexture(gl[target], webGLTexture);
-
- const { level, xoffset, yoffset, zoffset, width, height, depth, source, srcData, srcOffset, cubeTarget } = v;
-
- if (gl instanceof WebGL2RenderingContext)
- {
- if (source)
- {
- if (target === "TEXTURE_2D" || target === "TEXTURE_CUBE_MAP")
- {
- const bindTarget = target === "TEXTURE_CUBE_MAP" ? cubeTarget : target;
-
- if (width && height)
- {
- gl.texSubImage2D(gl[bindTarget], level, xoffset, yoffset, width, height, gl[format], gl[type], source);
- }
- else
- {
- gl.texSubImage2D(gl[bindTarget], level, xoffset, yoffset, gl[format], gl[type], source);
- }
- }
- else if (target === "TEXTURE_3D" || target === "TEXTURE_2D_ARRAY")
- {
- gl.texSubImage3D(gl[target], level, xoffset, yoffset, zoffset, width, height, depth, gl[format], gl[type], source);
- }
- else
- {
- console.error(`未处理 WebGL1 中 ${target} 纹理类型的图片资源上传!`);
- }
- }
- else
- {
- // eslint-disable-next-line no-lonely-if
- if (target === "TEXTURE_2D" || target === "TEXTURE_CUBE_MAP")
- {
- const bindTarget = target === "TEXTURE_CUBE_MAP" ? cubeTarget : target;
-
- gl.texSubImage2D(gl[bindTarget], level, xoffset, yoffset, width, height, gl[format], gl[type], srcData, srcOffset || 0);
- }
- else if (target === "TEXTURE_3D" || target === "TEXTURE_2D_ARRAY")
- {
- gl.texSubImage3D(gl[target], level, xoffset, yoffset, zoffset, width, height, depth, gl[format], gl[type], srcData, srcOffset || 0);
- }
- else
- {
- console.error(`未处理 WebGL1 中 ${target} 纹理类型的像素资源上传。`);
- }
- }
- }
- // 处理 WebGL1
- else
- {
- // eslint-disable-next-line no-lonely-if
- if (target === "TEXTURE_2D" || target === "TEXTURE_CUBE_MAP")
- {
- const bindTarget = target === "TEXTURE_CUBE_MAP" ? cubeTarget : target;
- if (source)
- {
- gl.texSubImage2D(gl[bindTarget], level, xoffset, yoffset, gl[format], gl[type], source);
- }
- else
- {
- gl.texSubImage2D(gl[bindTarget], level, xoffset, yoffset, width, height, gl[format], gl[type], srcData);
- }
- }
- else
- {
- console.error(`WebGL1 中 不支持 ${target} 纹理类型!`);
- }
- }
- });
- };
- writeTexture();
- watcher.watch(texture, "writeTextures", writeTexture);
-
- // watcher.watch(this as RenderTargetTexture2D, "width", this.invalidate, this);
- // watcher.watch(this as RenderTargetTexture2D, "height", this.invalidate, this);
-
- webGLTexture.destroy = () =>
- {
- watcher.unwatchobject(texture, { pixelStore: { unpackFlipY: undefined, unpackPremulAlpha: undefined } }, updateTexture);
- watcher.unwatchs(texture, ["sources", "generateMipmap", "internalformat", "format", "type"], updateTexture);
- watcher.unwatch(texture, "writeTextures", writeTexture);
- };
-
- return webGLTexture;
-}
-
-export function deleteTexture(gl: WebGLRenderingContext, texture: IGLTexture)
-{
- const webGLTexture = gl._textures.get(texture);
- if (!webGLTexture) return;
-
- gl._textures.delete(texture);
- webGLTexture.destroy();
- delete webGLTexture.destroy;
- //
- gl.deleteTexture(webGLTexture);
-}
-
-/**
- * 设置像素解包打包时参数。
- *
- * @param gl
- * @param pixelStore 像素解包打包时参数。
- */
-function setTexturePixelStore(gl: WebGLRenderingContext, pixelStore: IGLTexturePixelStore)
-{
- const {
- packAlignment,
- unpackAlignment,
- unpackFlipY,
- unpackPremulAlpha,
- unpackColorSpaceConversion,
- packRowLength,
- packSkipPixels,
- packSkipRows,
- unpackRowLength,
- unpackImageHeight,
- unpackSkipPixels,
- unpackSkipRows,
- unpackSkipImages,
- } = { ...defaultTexturePixelStore, ...pixelStore };
-
- // 设置图片y轴方向
- gl.pixelStorei(gl.PACK_ALIGNMENT, packAlignment);
- gl.pixelStorei(gl.UNPACK_ALIGNMENT, unpackAlignment);
- gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, unpackFlipY);
- gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, unpackPremulAlpha);
- gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl[unpackColorSpaceConversion]);
-
- if (gl instanceof WebGL2RenderingContext)
- {
- gl.pixelStorei(gl.PACK_ROW_LENGTH, packRowLength);
- gl.pixelStorei(gl.PACK_SKIP_PIXELS, packSkipPixels);
- gl.pixelStorei(gl.PACK_SKIP_ROWS, packSkipRows);
- gl.pixelStorei(gl.UNPACK_ROW_LENGTH, unpackRowLength);
- gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, unpackImageHeight);
- gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, unpackSkipPixels);
- gl.pixelStorei(gl.UNPACK_SKIP_ROWS, unpackSkipRows);
- gl.pixelStorei(gl.UNPACK_SKIP_IMAGES, unpackSkipImages);
- }
-}
\ No newline at end of file
diff --git a/src/caches/getWebGLQuery.ts b/src/caches/getWebGLQuery.ts
deleted file mode 100644
index 32e71be564d9afe5d9c4aa15422662ef005a43a7..0000000000000000000000000000000000000000
--- a/src/caches/getWebGLQuery.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import { IGLQuery } from "../data/IGLQueryAction";
-
-declare global
-{
- interface WebGLRenderingContext
- {
- _querys: Map
- }
-}
-
-export function getWebGLQuery(gl: WebGLRenderingContext, query: IGLQuery)
-{
- if (gl instanceof WebGL2RenderingContext)
- {
- let webGLQuery = gl._querys.get(query);
- if (webGLQuery) return webGLQuery;
-
- webGLQuery = (gl as any as WebGL2RenderingContext).createQuery();
- gl._querys.set(query, webGLQuery);
-
- return webGLQuery;
- }
-
- return null;
-}
-
-export function deleteWebGLQuery(gl: WebGLRenderingContext, query: IGLQuery)
-{
- if (gl instanceof WebGL2RenderingContext)
- {
- const webGLQuery = gl._querys.get(query);
-
- gl._querys.delete(query);
-
- gl.deleteQuery(webGLQuery);
- }
-}
\ No newline at end of file
diff --git a/src/const/WebGLUniformType.ts b/src/const/IGLUniformType.ts
similarity index 93%
rename from src/const/WebGLUniformType.ts
rename to src/const/IGLUniformType.ts
index da831af27a1bdc3ccce90e9ffbe758dff96d7298..488c4a9d5903b0dbea7b32cd92d8066839f0b6f5 100644
--- a/src/const/WebGLUniformType.ts
+++ b/src/const/IGLUniformType.ts
@@ -67,7 +67,7 @@ const webGLUniformTypeValue = { ...webGL1UniformBufferTypeValue, ...webGL1Unifor
const webGLUniformTextureTypeValue = { ...webGL1UniformTextureTypeValue, ...webGL2OnlyUniformTextureTypeValue };
/**
- * WebGL Uniform 纹理类型与值的映射。
+ * WebGL Uniform 缓冲区数据与值的映射。
*/
const webGLUniformBufferTypeValue = { ...webGL1UniformBufferTypeValue, ...webGL2OnlyUniformBufferTypeValue };
@@ -80,12 +80,3 @@ const webGLUniformValueType = Object.keys(webGLUniformTypeValue).reduce((pv, cv)
return pv;
}, {});
-
-/**
- * 顶点索引数据类型对应的字节数量。
- */
-export const ElementTypeMap = {
- UNSIGNED_BYTE: 1,
- UNSIGNED_SHORT: 2,
- UNSIGNED_INT: 4,
-};
\ No newline at end of file
diff --git a/src/const/const.ts b/src/const/const.ts
new file mode 100644
index 0000000000000000000000000000000000000000..92970cbd4c5fa25ef888e4c93e4d7b91fd36c92e
--- /dev/null
+++ b/src/const/const.ts
@@ -0,0 +1,4 @@
+/**
+ * 用于标记 GL 提交次数。更改时触发回调。
+ */
+export const _GL_Submit_Times = "_GL_Submit_Times";
\ No newline at end of file
diff --git a/src/data/IGLAttributeInfo.ts b/src/data/IGLAttributeInfo.ts
index 9b98d900fb5ee17fa0bae2e050c0dd39152db8a3..38fc6c339682be214a4a1b1694eeebe14805c758 100644
--- a/src/data/IGLAttributeInfo.ts
+++ b/src/data/IGLAttributeInfo.ts
@@ -1,4 +1,4 @@
-import { VertexAttributeTypes } from "./IGLVertexAttribute";
+import { IGLVertexAttributeTypes } from "../utils/getIVertexFormat";
export interface IGLAttributeInfo
{
@@ -15,7 +15,7 @@ export interface IGLAttributeInfo
/**
* 属性缓冲数据类型
*/
- type?: VertexAttributeTypes;
+ type?: IGLVertexAttributeTypes;
/**
* 属性地址
diff --git a/src/data/IGLBlendState.ts b/src/data/IGLBlendState.ts
deleted file mode 100644
index 928f35bfc87cd0dbde9c5c0adb86d2c305230d8c..0000000000000000000000000000000000000000
--- a/src/data/IGLBlendState.ts
+++ /dev/null
@@ -1,100 +0,0 @@
-/**
- * 混合状态。
- */
-export interface IGLBlendState
-{
- /**
- * 为颜色通道定义相应渲染目标的混合行为。
- */
- color?: IGLBlendComponent;
-
- /**
- * 为alpha通道定义相应渲染目标的混合行为。
- */
- alpha?: IGLBlendComponent;
-}
-
-/**
- * 为颜色或alpha通道定义相应渲染目标的混合行为。
- */
-export interface IGLBlendComponent
-{
- /**
- * 混合方式,默认 FUNC_ADD,源 + 目标。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/blendEquation
- */
- operation?: GLBlendEquation;
-
- /**
- * 源混合因子,默认 SRC_ALPHA,将所有颜色乘以源alpha值。
- *
- * @see GLBlendFactor
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/blendFunc
- */
- srcFactor?: GLBlendFactor;
-
- /**
- * 目标混合因子,默认 ONE_MINUS_SRC_ALPHA,将所有颜色乘以1减去源alpha值。
- *
- * @see GLBlendFactor
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/blendFunc
- */
- dstFactor?: GLBlendFactor;
-}
-
-/**
- * 混合因子(R分量系数,G分量系数,B分量系数)
- *
- * 混合颜色的公式可以这样描述:color(RGBA) = (sourceColor * sfactor) + (destinationColor * dfactor)。这里的 RGBA 值均在0与1之间。
- *
- * The formula for the blending color can be described like this: color(RGBA) = (sourceColor * sfactor) + (destinationColor * dfactor). The RBGA values are between 0 and 1.
- *
- * * `ZERO` Factor: (0,0,0,0); 把所有颜色都乘以0。
- * * `ONE` Factor: (1,1,1,1); 把所有颜色都乘以1。
- * * `SRC_COLOR` Factor: (Rs, Gs, Bs, As); 将所有颜色乘以源颜色。
- * * `ONE_MINUS_SRC_COLOR` Factor: (1-Rs, 1-Gs, 1-Bs, 1-As); 将所有颜色乘以1减去每个源颜色。
- * * `DST_COLOR` Factor: (Rd, Gd, Bd, Ad); 将所有颜色乘以目标颜色。
- * * `ONE_MINUS_DST_COLOR` Factor: (1-Rd, 1-Gd, 1-Bd, 1-Ad); 将所有颜色乘以1减去每个目标颜色。
- * * `SRC_ALPHA` Factor: (As, As, As, As); 将所有颜色乘以源alpha值。
- * * `ONE_MINUS_SRC_ALPHA` Factor: (1-As, 1-As, 1-As, 1-As); 将所有颜色乘以1减去源alpha值。
- * * `DST_ALPHA` Factor: (Ad, Ad, Ad, Ad); 将所有颜色乘以目标alpha值。
- * * `ONE_MINUS_DST_ALPHA` Factor: (1-Ad, 1-Ad, 1-Ad, 1-Ad); 将所有颜色乘以1减去目标alpha值。
- * * `CONSTANT_COLOR` Factor: (Rc, Gc, Bc, Ac); 将所有颜色乘以一个常数颜色。
- * * `ONE_MINUS_CONSTANT_COLOR` Factor: (1-Rc, 1-Gc, 1-Bc, 1-Ac); 所有颜色乘以1减去一个常数颜色。
- * * `CONSTANT_ALPHA` Factor: (Ac, Ac, Ac, Ac); 将所有颜色乘以一个常量alpha值。
- * * `ONE_MINUS_CONSTANT_ALPHA` Factor: (1-Ac, 1-Ac, 1-Ac, 1-Ac); 将所有颜色乘以1减去一个常数alpha值。
- * * `SRC_ALPHA_SATURATE` Factor: (min(As, 1 - Ad), min(As, 1 - Ad), min(As, 1 - Ad), 1); 将RGB颜色乘以源alpha值与1减去目标alpha值的较小值。alpha值乘以1。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/blendFunc
- */
-export type GLBlendFactor = "ZERO" | "ONE" | "SRC_COLOR" | "ONE_MINUS_SRC_COLOR" | "DST_COLOR" | "ONE_MINUS_DST_COLOR" | "SRC_ALPHA" | "ONE_MINUS_SRC_ALPHA" | "DST_ALPHA" | "ONE_MINUS_DST_ALPHA" | "SRC_ALPHA_SATURATE" | "CONSTANT_COLOR" | "ONE_MINUS_CONSTANT_COLOR" | "CONSTANT_ALPHA" | "ONE_MINUS_CONSTANT_ALPHA";
-
-/**
- * 混合方法
- *
- * * FUNC_ADD 源 + 目标
- * * FUNC_SUBTRACT 源 - 目标
- * * FUNC_REVERSE_SUBTRACT 目标 - 源
- * * MIN 源与目标的最小值,在 WebGL 2 中可使用。在 WebGL 1 时,自动使用 EXT_blend_minmax 扩展中 MIN_EXT 值。
- * * MAX 源与目标的最大值,在 WebGL 2 中可使用。在 WebGL 1 时,自动使用 EXT_blend_minmax 扩展中 MAX_EXT 值。
- *
- * A GLenum specifying how source and destination colors are combined. Must be either:
- *
- * * gl.FUNC_ADD: source + destination (default value)
- * * gl.FUNC_SUBTRACT: source - destination
- * * gl.FUNC_REVERSE_SUBTRACT: destination - source
- *
- * When using the EXT_blend_minmax extension:
- *
- * * ext.MIN_EXT: Minimum of source and destination
- * * ext.MAX_EXT: Maximum of source and destination
- *
- * When using a WebGL 2 context, the following values are available additionally:
- *
- * * gl.MIN: Minimum of source and destination
- * * gl.MAX: Maximum of source and destination
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/blendEquation
- */
-export type GLBlendEquation = "FUNC_ADD" | "FUNC_SUBTRACT" | "FUNC_REVERSE_SUBTRACT" | "MIN" | "MAX";
diff --git a/src/data/IGLBlitFramebuffer.ts b/src/data/IGLBlitFramebuffer.ts
index fa4fdef9613822bf88a629ed9be5976257c128fe..2bd6b55712bc4b0e12ce558fba27c93618d1122c 100644
--- a/src/data/IGLBlitFramebuffer.ts
+++ b/src/data/IGLBlitFramebuffer.ts
@@ -1,12 +1,17 @@
-import { IGLRenderPassDescriptor } from "./IGLPassDescriptor";
+import { IRenderPassDescriptor } from "@feng3d/render-api";
/**
* 拷贝渲染缓冲与纹理直接拷贝数据。
*/
export interface IGLBlitFramebuffer
{
- read: IGLRenderPassDescriptor;
- draw: IGLRenderPassDescriptor;
+ /**
+ * 数据类型。
+ */
+ readonly __type: "BlitFramebuffer";
+
+ read: IRenderPassDescriptor;
+ draw: IRenderPassDescriptor;
blitFramebuffers: IGLBlitFramebufferItem[];
}
diff --git a/src/data/IGLBuffer.ts b/src/data/IGLBuffer.ts
index 720cde95e3129254b226afc559923b5b3ec64c33..46a93367ca1af63a60213300063584142bae9792 100644
--- a/src/data/IGLBuffer.ts
+++ b/src/data/IGLBuffer.ts
@@ -1,67 +1,73 @@
-/**
- * WebGL缓冲区
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferData
- */
-export interface IGLBuffer
-{
- target: GLBufferTarget;
-
- /**
- * 被bindBuffer多次绑定到不同位置时,需要填入多个值。
- *
- * [MDN Reference](https://developer.mozilla.org/docs/Web/API/WebGLRenderingContext/bindBuffer)
- */
- targets?: GLBufferTarget[];
+import { IBuffer, IIndicesDataTypes, IVertexDataTypes } from "@feng3d/render-api";
+declare module "@feng3d/render-api"
+{
/**
- * 缓冲区数据。
+ * WebGL缓冲区
+ *
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferData
*/
- data?: BufferSource;
+ export interface IBuffer
+ {
+ target: IGLBufferTarget;
- /**
- * 创建指定尺寸的空缓冲区。
- */
- size?: number;
+ /**
+ * 为优化目的指定数据存储的预期使用模式的GLenum。
+ *
+ * 默认为 "STATIC_DRAW"。
+ */
+ usage?: IGLBufferUsage;
+ }
+}
- /**
- * 为优化目的指定数据存储的预期使用模式的GLenum。
- *
- * 默认为 "STATIC_DRAW"。
- */
- usage?: GLBufferUsage;
+export interface IGLVertexBuffer extends IBuffer
+{
+ target: "ARRAY_BUFFER";
/**
- * 写缓冲区。
+ * 缓冲区数据。
*/
- writeBuffers?: IGLWriteBuffer[];
+ data?: IVertexDataTypes;
}
-export interface IGLWriteBuffer
+/**
+ * WebGL元素缓冲,顶点索引缓冲。
+ *
+ * 使用 gl.ELEMENT_ARRAY_BUFFER 进行绑定数据。
+ *
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bindBuffer
+ *
+ */
+export interface IGLIndexBuffer extends IBuffer
{
- bufferOffset?: number;
+ target: "ELEMENT_ARRAY_BUFFER";
/**
- * 写入缓冲区数据。
+ * 顶点索引数据。
*/
- data: BufferSource;
-
- dataOffset?: number
+ data: IIndicesDataTypes;
+}
- size?: number
+export interface IGLUniformBuffer extends IBuffer
+{
+ target: "UNIFORM_BUFFER";
}
/**
- * 属性缓冲数据类型。
+ * 元素缓冲数据类型。
+ *
+ * A GLenum specifying the type of the values in the element array buffer. Possible values are:
+ *
+ * * gl.UNSIGNED_BYTE
+ * * gl.UNSIGNED_SHORT
+ *
+ * When using the OES_element_index_uint extension:
+ *
+ * * gl.UNSIGNED_INT
+ *
+ * @see https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLRenderingContext/drawElements
*/
-export type IAttributeBufferSourceTypes =
- | Float32Array
- | Uint32Array
- | Int32Array
- | Uint16Array
- | Int16Array | Uint8ClampedArray
- | Uint8Array
- | Int8Array;
+export type IGLDrawElementType = "UNSIGNED_BYTE" | "UNSIGNED_SHORT" | "UNSIGNED_INT";
/**
* A GLenum specifying the intended usage pattern of the data store for optimization purposes. Possible values:
@@ -81,7 +87,7 @@ export type IAttributeBufferSourceTypes =
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferData
*/
-export type GLBufferUsage = "STATIC_DRAW" | "DYNAMIC_DRAW" | "STREAM_DRAW" // WebGL1
+export type IGLBufferUsage = "STATIC_DRAW" | "DYNAMIC_DRAW" | "STREAM_DRAW" // WebGL1
| "STATIC_READ" | "DYNAMIC_READ" | "STREAM_READ" | "STATIC_COPY" | "DYNAMIC_COPY" | "STREAM_COPY" // WebGL2
;
@@ -100,7 +106,6 @@ export type GLBufferUsage = "STATIC_DRAW" | "DYNAMIC_DRAW" | "STREAM_DRAW" // We
* * gl.PIXEL_UNPACK_BUFFER: Buffer used for pixel transfer operations.
*
*/
-export type GLBufferTarget = "ARRAY_BUFFER" | "ELEMENT_ARRAY_BUFFER" // WebGL1
+export type IGLBufferTarget = "ARRAY_BUFFER" | "ELEMENT_ARRAY_BUFFER" // WebGL1
| "COPY_READ_BUFFER" | "COPY_WRITE_BUFFER" | "TRANSFORM_FEEDBACK_BUFFER"// WebGL2
| "UNIFORM_BUFFER" | "PIXEL_PACK_BUFFER" | "PIXEL_UNPACK_BUFFER"; // WebGL2
-// export type GLBufferTarget = "ARRAY_BUFFER" | "ELEMENT_ARRAY_BUFFER" | "UNIFORM_BUFFER";
\ No newline at end of file
diff --git a/src/data/IGLRenderingContext.ts b/src/data/IGLCanvasContext.ts
similarity index 70%
rename from src/data/IGLRenderingContext.ts
rename to src/data/IGLCanvasContext.ts
index 5eefa50fb47e5880dfefc4238c4a21b8bbc1a44c..0c0a8e6117446b26aed391d0bb0c3a779f5355fe 100644
--- a/src/data/IGLRenderingContext.ts
+++ b/src/data/IGLCanvasContext.ts
@@ -1,14 +1,15 @@
/**
- * WebGL上下文信息。
+ * 画布(WebGL)上下文信息。
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext
*/
-export interface IGLRenderingContext extends WebGLContextAttributes
+export interface IGLCanvasContext extends WebGLContextAttributes
{
/**
* 画布编号。
*/
canvasId?: string
+
/**
* WebGL上下文类型
*/
diff --git a/src/data/IGLCanvasTexture.ts b/src/data/IGLCanvasTexture.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f18c25fc4cf2d8428c337c004c31bb6f3753954c
--- /dev/null
+++ b/src/data/IGLCanvasTexture.ts
@@ -0,0 +1,9 @@
+import { IGLCanvasContext } from "./IGLCanvasContext";
+
+/**
+ * 画布纹理,从画布的WebGPU上下文获取纹理
+ */
+export interface IGLCanvasTexture
+{
+ context: IGLCanvasContext;
+}
\ No newline at end of file
diff --git a/src/data/IGLColorTargetState.ts b/src/data/IGLColorTargetState.ts
deleted file mode 100644
index cfab0e7346a0ea100269bab006363b98ad1357d2..0000000000000000000000000000000000000000
--- a/src/data/IGLColorTargetState.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import { IGLBlendState } from "./IGLBlendState";
-
-export interface IGLColorTargetState
-{
- /**
- * 混合状态。
- */
- blend?: IGLBlendState;
-
- /**
- * 控制那些颜色分量是否可以被写入到帧缓冲器。
- *
- * [red: boolean, green: boolean, blue: boolean, alpha: boolean]
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/colorMask
- */
- writeMask?: IGLWriteMask;
-}
-
-export type IGLWriteMask = [red: boolean, green: boolean, blue: boolean, alpha: boolean];
\ No newline at end of file
diff --git a/src/data/IGLCommandEncoder.ts b/src/data/IGLCommandEncoder.ts
new file mode 100644
index 0000000000000000000000000000000000000000..bbcfa7bc63e365e16e2e28a5a25d538e0f194f06
--- /dev/null
+++ b/src/data/IGLCommandEncoder.ts
@@ -0,0 +1,25 @@
+import { ITextureLike } from "@feng3d/render-api";
+import { IGLBlitFramebuffer } from "./IGLBlitFramebuffer";
+
+declare module "@feng3d/render-api"
+{
+ export interface IPassEncoderMap
+ {
+ IGLBlitFramebuffer: IGLBlitFramebuffer;
+ }
+
+ /**
+ * 被操作的纹理相关信息。
+ *
+ * {@link GPUCommandEncoder.copyTextureToTexture}
+ * {@link GPUImageCopyTexture}
+ */
+ export interface IImageCopyTexture
+ {
+ /**
+ *
+ * 注:当值设置为 null或者undefined时表示当前画布。
+ */
+ texture: ITextureLike;
+ }
+}
diff --git a/src/data/IGLCopyBuffer.ts b/src/data/IGLCopyBuffer.ts
deleted file mode 100644
index 6fc683113a2b6a56e24b923957403a2c5cda88ad..0000000000000000000000000000000000000000
--- a/src/data/IGLCopyBuffer.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { IGLBuffer } from "./IGLBuffer";
-
-export interface IGLCopyBuffer
-{
- read: IGLBuffer,
- write: IGLBuffer,
- readOffset: number
- writeOffset: number
- size: number
-}
\ No newline at end of file
diff --git a/src/data/IGLCullFace.ts b/src/data/IGLCullFace.ts
deleted file mode 100644
index 4ffee6e28da1c38e11da242c28540001a1039367..0000000000000000000000000000000000000000
--- a/src/data/IGLCullFace.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * 面剔除。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/cullFace
- */
-export interface IGLCullFace
-{
- /**
- * 是否开启面剔除。
- *
- * 默认为 false。
- */
- enableCullFace?: boolean;
-
- /**
- * 剔除面,默认 BACK,剔除背面。
- *
- * 默认情况下,逆时针的顶点连接顺序被定义为三角形的正面。
- * 使用gl.frontFace(gl.CW);调整顺时针为正面
- *
- * * NONE 关闭裁剪面
- * * FRONT 正面
- * * BACK 背面
- * * FRONT_AND_BACK 正面与背面
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/cullFace
- */
- cullMode?: GLCullFace;
-
- /**
- * 正向方向,默认 CCW。三角形逆时针方向为正面。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/frontFace
- */
- frontFace?: GLFrontFace;
-}
-
-/**
- * 正面方向枚举
- *
- * * CW 顺时钟方向
- * * CCW 逆时钟方向
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/frontFace
- */
-export type GLFrontFace = "CW" | "CCW";
-
-/**
- * 剔除面,默认 BACK,剔除背面。
- *
- * 默认情况下,逆时针的顶点连接顺序被定义为三角形的正面。
- * 使用gl.frontFace(gl.CW);调整顺时针为正面
- *
- * * FRONT 正面
- * * BACK 背面
- * * FRONT_AND_BACK 正面与背面
- *
- * @see http://www.jianshu.com/p/ee04165f2a02
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/cullFace
- */
-export type GLCullFace = "FRONT" | "BACK" | "FRONT_AND_BACK";
\ No newline at end of file
diff --git a/src/data/IGLDepthStencilState.ts b/src/data/IGLDepthStencilState.ts
index 18f0a9a5d7e23c01c61999ae8bf3deb440ece687..dc5f10134a8032659353a224524db13f63afa378 100644
--- a/src/data/IGLDepthStencilState.ts
+++ b/src/data/IGLDepthStencilState.ts
@@ -1,18 +1,3 @@
-/**
- * 深度模板状态。
- */
-export interface IGLDepthStencilState
-{
- /**
- * 深度状态。
- */
- depth?: IGLDepthState;
-
- /**
- * 模板状态。
- */
- stencil?: IGLStencilState;
-}
/**
* 深度状态。
@@ -40,10 +25,10 @@ export interface IGLDepthState
*
* A GLenum specifying the depth comparison function, which sets the conditions under which the pixel will be drawn. The default value is gl.LESS.
*
- * @see GLCompareFunction
+ * @see IGLCompareFunction
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/depthFunc
*/
- depthCompare?: GLCompareFunction;
+ depthCompare?: IGLCompareFunction;
/**
* 深度偏移。
@@ -110,31 +95,40 @@ export interface IGLStencilState
export interface IStencilFaceState
{
/**
- * 描述模板测试的方法。默认ALWAYS,总是通过。
+ * 一个为模板测试指定参考值。这个值被限制在0到2^n -1的范围内,其中n是模板缓冲区中的位数。默认0。
*
- * A GLenum specifying the test function. The default function is gl.ALWAYS.
+ * A GLint specifying the reference value for the stencil test. This value is clamped to the range 0 to 2^n -1 where n is the number of bitplanes in the stencil buffer. The default value is 0.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/stencilFunc
*/
- stencilFunc?: GLStencilFunc;
+ stencilFuncRef?: number;
/**
- * 一个为模板测试指定参考值。这个值被限制在0到2^n -1的范围内,其中n是模板缓冲区中的位数。默认0。
+ * 模板测试时使用的mask值,默认全为1(0xFFFFFFFF)。
*
- * A GLint specifying the reference value for the stencil test. This value is clamped to the range 0 to 2^n -1 where n is the number of bitplanes in the stencil buffer. The default value is 0.
+ * A GLuint specifying a bit-wise mask that is used to AND the reference value and the stored stencil value when the test is done. The default value is all 1.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/stencilFunc
*/
- stencilFuncRef?: number;
+ stencilFuncMask?: number;
/**
- * 模板测试时使用的mask值,默认全为1(0b11111111)。
+ * 指定位掩码以启用或禁用在模板平面中写入单个位的正整数。默认全为1(0xFFFFFFFF)。
*
- * A GLuint specifying a bit-wise mask that is used to AND the reference value and the stored stencil value when the test is done. The default value is all 1.
+ * A GLuint specifying a bit mask to enable or disable writing of individual bits in the stencil planes. By default, the mask is all 1.
+ *
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/stencilMask
+ */
+ stencilMask?: number;
+
+ /**
+ * 描述模板测试的方法。默认ALWAYS,总是通过。
+ *
+ * A GLenum specifying the test function. The default function is gl.ALWAYS.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/stencilFunc
*/
- stencilFuncMask?: number;
+ stencilFunc?: IGLStencilFunc;
/**
* 指定模板测试失败时使用的函数的枚举。默认KEEP,保持当前值。
@@ -143,7 +137,7 @@ export interface IStencilFaceState
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/stencilOp
*/
- stencilOpFail?: GLStencilOp;
+ stencilOpFail?: IGLStencilOp;
/**
* 指定在模板测试通过但深度测试失败时使用的函数枚举。默认KEEP,保持当前值。
@@ -152,7 +146,7 @@ export interface IStencilFaceState
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/stencilOp
*/
- stencilOpZFail?: GLStencilOp;
+ stencilOpZFail?: IGLStencilOp;
/**
* 指定在模板测试和深度测试通过时使用的函数枚举,或在模板测试通过且没有深度缓冲或禁用深度测试时使用的函数枚举。默认KEEP,保持当前值。
@@ -161,16 +155,7 @@ export interface IStencilFaceState
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/stencilOp
*/
- stencilOpZPass?: GLStencilOp;
-
- /**
- * 指定位掩码以启用或禁用在模板平面中写入单个位的正整数。默认全为1(0b11111111)。
- *
- * A GLuint specifying a bit mask to enable or disable writing of individual bits in the stencil planes. By default, the mask is all 1.
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/stencilMask
- */
- stencilMask?: number;
+ stencilOpZPass?: IGLStencilOp;
}
/**
@@ -189,7 +174,7 @@ export interface IStencilFaceState
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/depthFunc
*/
-export type GLCompareFunction = "NEVER" | "LESS" | "EQUAL" | "LEQUAL" | "GREATER" | "NOTEQUAL" | "GEQUAL" | "ALWAYS";
+export type IGLCompareFunction = "NEVER" | "LESS" | "EQUAL" | "LEQUAL" | "GREATER" | "NOTEQUAL" | "GEQUAL" | "ALWAYS";
/**
* A GLenum specifying the test function. The default function is gl.ALWAYS.
@@ -205,7 +190,7 @@ export type GLCompareFunction = "NEVER" | "LESS" | "EQUAL" | "LEQUAL" | "GREATER
*
* https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/stencilFunc
*/
-export type GLStencilFunc = "NEVER" | "LESS" | "EQUAL" | "LEQUAL" | "GREATER" | "NOTEQUAL" | "GEQUAL" | "ALWAYS";
+export type IGLStencilFunc = "NEVER" | "LESS" | "EQUAL" | "LEQUAL" | "GREATER" | "NOTEQUAL" | "GEQUAL" | "ALWAYS";
/**
* The WebGLRenderingContext.stencilOp() method of the WebGL API sets both the front and back-facing stencil test actions.
@@ -221,4 +206,4 @@ export type GLStencilFunc = "NEVER" | "LESS" | "EQUAL" | "LEQUAL" | "GREATER" |
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/stencilOp
*/
-export type GLStencilOp = "KEEP" | "ZERO" | "REPLACE" | "INCR" | "INCR_WRAP" | "DECR" | "DECR_WRAP" | "INVERT";
+export type IGLStencilOp = "KEEP" | "ZERO" | "REPLACE" | "INCR" | "INCR_WRAP" | "DECR" | "DECR_WRAP" | "INVERT";
diff --git a/src/data/IGLDrawArrays.ts b/src/data/IGLDrawArrays.ts
deleted file mode 100644
index cb5ee596a14d7bcecb549626f95fab30cf0c9a0e..0000000000000000000000000000000000000000
--- a/src/data/IGLDrawArrays.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-/**
- * 绘制一定数量顶点。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/drawArrays
- */
-export interface IGLDrawArrays
-{
- /**
- * 绘制顶点数量。
- */
- vertexCount?: number;
- /**
- * 渲染实例数量
- */
- instanceCount?: number;
- /**
- * 第一个顶点索引。
- */
- firstVertex?: number;
-}
diff --git a/src/data/IGLDrawElements.ts b/src/data/IGLDrawElements.ts
deleted file mode 100644
index 6ee9363090f6234388c7a302f5147e4e4f353e5d..0000000000000000000000000000000000000000
--- a/src/data/IGLDrawElements.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-export interface IGLDrawElements
-{
- /**
- * 默认渲染所有顶点索引。
- */
- indexCount?: number;
- instanceCount?: number;
- firstIndex?: number;
-}
\ No newline at end of file
diff --git a/src/data/IGLFramebuffer.ts b/src/data/IGLFramebuffer.ts
deleted file mode 100644
index f4043ca08fc5fd1f60968901080ddd4116fee3b4..0000000000000000000000000000000000000000
--- a/src/data/IGLFramebuffer.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { IGLRenderPassDescriptor } from "./IGLPassDescriptor";
-
-/**
- * 等价于 IPassDescriptor 。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/framebufferRenderbuffer
- *
- * @deprecated 请使用 IPassDescriptor 。
- */
-export interface IGLFramebuffer extends IGLRenderPassDescriptor { }
diff --git a/src/data/IGLIndexBuffer.ts b/src/data/IGLIndexBuffer.ts
deleted file mode 100644
index 632586bba54b04ea4812e567090756cf21131f01..0000000000000000000000000000000000000000
--- a/src/data/IGLIndexBuffer.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import { IGLBuffer } from "./IGLBuffer";
-
-/**
- * WebGL元素缓冲,顶点索引缓冲。
- *
- * 使用 gl.ELEMENT_ARRAY_BUFFER 进行绑定数据。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bindBuffer
- *
- */
-export interface IGLIndexBuffer extends IGLBuffer
-{
- target: "ELEMENT_ARRAY_BUFFER";
-
- /**
- * 顶点索引数据。
- */
- data: IElementBufferSourceTypes;
-}
-
-/**
- * 元素缓冲数据类型
- */
-export type IElementBufferSourceTypes = Uint16Array | Uint32Array | Uint8Array;
-
-/**
- * 元素缓冲数据类型。
- *
- * A GLenum specifying the type of the values in the element array buffer. Possible values are:
- *
- * * gl.UNSIGNED_BYTE
- * * gl.UNSIGNED_SHORT
- *
- * When using the OES_element_index_uint extension:
- *
- * * gl.UNSIGNED_INT
- *
- * @see https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLRenderingContext/drawElements
- */
-export type IGLDrawElementType = "UNSIGNED_BYTE" | "UNSIGNED_SHORT" | "UNSIGNED_INT";
diff --git a/src/data/IGLOcclusionQuery.ts b/src/data/IGLOcclusionQuery.ts
new file mode 100644
index 0000000000000000000000000000000000000000..416155e40aea26f61c302fea5a345942ec95da46
--- /dev/null
+++ b/src/data/IGLOcclusionQuery.ts
@@ -0,0 +1,41 @@
+import { IRenderObject } from "@feng3d/render-api";
+import { IGLOcclusionQueryStep } from "../caches/getGLRenderOcclusionQuery";
+
+export interface IGLOcclusionQuery
+{
+ /**
+ * 数据类型。
+ */
+ readonly __type: "OcclusionQuery";
+ /**
+ * 渲染对象列表。
+ */
+ renderObjects: IRenderObject[];
+
+ /**
+ * 临时变量, 执行过程中由引擎自动填充。
+ *
+ * @internal
+ */
+ _step?: IGLOcclusionQueryStep;
+
+ /**
+ * 渲染完成后由引擎自动填充。
+ */
+ result?: IGLQuery;
+}
+
+/**
+ * 查询对象。
+ *
+ * 一次查询周期。
+ *
+ * 仅 WebGL2 支持。
+ */
+export interface IGLQuery
+{
+ /**
+ * 查询结果。
+ */
+ result: number;
+}
\ No newline at end of file
diff --git a/src/data/IGLPassDescriptor.ts b/src/data/IGLPassDescriptor.ts
deleted file mode 100644
index 8abc5ed10f92ea9be5a5864a59ef2dcf9ae7a88a..0000000000000000000000000000000000000000
--- a/src/data/IGLPassDescriptor.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { IGLRenderPassColorAttachment } from "./IGLRenderPassColorAttachment";
-import { IGLRenderPassDepthStencilAttachment } from "./IGLRenderPassDepthStencilAttachment";
-
-/**
- * WebGL渲染通道描述
- */
-export interface IGLRenderPassDescriptor
-{
- /**
- * 颜色附件
- */
- colorAttachments?: IGLRenderPassColorAttachment[];
-
- /**
- * 深度模板附件。
- */
- depthStencilAttachment?: IGLRenderPassDepthStencilAttachment;
-
- /**
- * 采用次数。
- *
- * 注意: WebGL2 支持。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/renderbufferStorageMultisample
- */
- multisample?: 4;
-}
\ No newline at end of file
diff --git a/src/data/IGLPrimitiveState.ts b/src/data/IGLPrimitiveState.ts
index 1d508ffa97e8383860e1df6d425971cce35a6461..e1e876ef41759b64c71da742cfce4205c37be179 100644
--- a/src/data/IGLPrimitiveState.ts
+++ b/src/data/IGLPrimitiveState.ts
@@ -1,49 +1,46 @@
-import { IGLCullFace } from "./IGLCullFace";
+import { ICullFace, IFrontFace, IPrimitiveTopology } from "@feng3d/render-api";
-export interface IGLPrimitiveState
+declare module "@feng3d/render-api"
{
- /**
- * 图形拓扑结构。
- *
- * 默认 TRIANGLES,每三个顶点绘制一个三角形。
- *
- * * POINTS 绘制单个点。
- * * LINE_LOOP 绘制循环连线。
- * * LINE_STRIP 绘制连线
- * * LINES 每两个顶点绘制一条线段。
- * * TRIANGLES 每三个顶点绘制一个三角形。
- * * TRIANGLE_STRIP 绘制三角形条带。
- * * TRIANGLE_FAN 绘制三角扇形。
- *
- * A GLenum specifying the type primitive to render. Possible values are:
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/drawArrays
- */
- topology?: IGLDrawMode;
+ export interface IPrimitiveTopologyMap
+ {
+ /**
+ * 绘制循环连线。
+ */
+ "LINE_LOOP": "LINE_LOOP",
- cullFace?: IGLCullFace;
-}
+ /**
+ * 绘制三角扇形。
+ */
+ "TRIANGLE_FAN": "TRIANGLE_FAN",
+ }
+
+ export interface ICullFaceMap
+ {
+ "FRONT_AND_BACK": "FRONT_AND_BACK";
+ }
+
+ export interface IPrimitiveState
+ {
+ /**
+ * 图形拓扑结构。
+ *
+ * 以下仅在WebGL生效
+ * * LINE_LOOP 绘制循环连线。
+ * * TRIANGLE_FAN 绘制三角扇形。
+ */
+ readonly topology?: IPrimitiveTopology;
-/**
- * 渲染模式,默认 TRIANGLES,每三个顶点绘制一个三角形。
- *
- * * POINTS 绘制单个点。
- * * LINE_LOOP 绘制循环连线。
- * * LINE_STRIP 绘制连线
- * * LINES 每两个顶点绘制一条线段。
- * * TRIANGLES 每三个顶点绘制一个三角形。
- * * TRIANGLE_STRIP 绘制三角形条带。
- * * TRIANGLE_FAN 绘制三角扇形。
- *
- * A GLenum specifying the type primitive to render. Possible values are:
- *
- * * gl.POINTS: Draws a single dot.
- * * gl.LINE_STRIP: Draws a straight line to the next vertex.
- * * gl.LINE_LOOP: Draws a straight line to the next vertex, and connects the last vertex back to the first.
- * * gl.LINES: Draws a line between a pair of vertices.
- * * gl.TRIANGLE_STRIP
- * * gl.TRIANGLE_FAN
- * * gl.TRIANGLES: Draws a triangle for a group of three vertices.
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/drawElements
- */
-export type IGLDrawMode = "POINTS" | "LINE_STRIP" | "LINE_LOOP" | "LINES" | "TRIANGLE_STRIP" | "TRIANGLE_FAN" | "TRIANGLES";
+ /**
+ * * `FRONT_AND_BACK` 剔除正面与背面,仅在WebGL中生效!
+ *
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/cullFace
+ */
+ readonly cullFace?: ICullFace;
+
+ /**
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/frontFace
+ */
+ readonly frontFace?: IFrontFace;
+ }
+}
diff --git a/src/data/IGLQueryAction.ts b/src/data/IGLQueryAction.ts
deleted file mode 100644
index a6efb33881b637df959f305c6212e8a9d0d4e065..0000000000000000000000000000000000000000
--- a/src/data/IGLQueryAction.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * 查询操作。
- *
- * 仅 WebGL2 支持。
- */
-export interface IGLQueryAction
-{
- /**
- * 开始查询或者结束查询。
- */
- action: "beginQuery" | "endQuery";
-
- /**
- * 查询内容。
- */
- target: "ANY_SAMPLES_PASSED" | "ANY_SAMPLES_PASSED_CONSERVATIVE" | "TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN";
-
- /**
- * 查询uid。
- *
- * 通过该对象获取查询结果。
- */
- query: IGLQuery;
-}
-
-/**
- * 查询对象。
- *
- * 一次查询周期。
- *
- * 仅 WebGL2 支持。
- */
-export interface IGLQuery
-{
- /**
- * 当前状态。
- *
- * "beginQuery" 表示已开始查询。
- * "endQuery" 表示已结束查询。
- * ""
- */
- state?: "beginQuery" | "endQuery";
-
- /**
- * 查询内容。
- *
- * 开始查询时被赋值。
- */
- target?: "ANY_SAMPLES_PASSED" | "ANY_SAMPLES_PASSED_CONSERVATIVE" | "TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN";
-
- /**
- * 查询结果。
- */
- result?: number;
-}
\ No newline at end of file
diff --git a/src/data/IGLReadPixels.ts b/src/data/IGLReadPixels.ts
index 615dc181891b839a9f610537e98fc29df365de55..e697deb6487a831aa105986e01b18f07213da850 100644
--- a/src/data/IGLReadPixels.ts
+++ b/src/data/IGLReadPixels.ts
@@ -1,5 +1,5 @@
+import { IRenderPassDescriptor } from "@feng3d/render-api";
import { GLAttachmentPoint } from "../gl/WebGLEnums";
-import { IGLFramebuffer } from "./IGLFramebuffer";
import { IGLTextureDataType, IGLTextureFormat } from "./IGLTexture";
/**
@@ -9,7 +9,7 @@ import { IGLTextureDataType, IGLTextureFormat } from "./IGLTexture";
*/
export interface IGLReadPixels
{
- frameBuffer: IGLFramebuffer;
+ frameBuffer: IRenderPassDescriptor;
/**
* 读取那个附件。
diff --git a/src/data/IGLRenderObject.ts b/src/data/IGLRenderObject.ts
deleted file mode 100644
index 91bbbd6f5afbe3ac6a6e47e5dcd6eee7305febc8..0000000000000000000000000000000000000000
--- a/src/data/IGLRenderObject.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-import { LazyObject } from "../types";
-import { IGLDrawArrays } from "./IGLDrawArrays";
-import { IGLDrawElements } from "./IGLDrawElements";
-import { IGLRenderPipeline } from "./IGLRenderPipeline";
-import { IGLScissor } from "./IGLScissor";
-import { IGLTransformFeedback } from "./IGLTransformFeedback";
-import { IGLUniforms } from "./IGLUniforms";
-import { IGLVertexArrayObject } from "./IGLVertexArrayObject";
-import { IGLViewport } from "./IGLViewport";
-
-/**
- * 渲染原子(该对象会收集一切渲染所需数据以及参数)
- */
-export interface IGLRenderObject
-{
- /**
- * 渲染程序
- */
- pipeline: IGLRenderPipeline;
-
- /**
- * 顶点属性以及索引数据。
- */
- vertexArray?: IGLVertexArrayObject;
-
- /**
- * Uniform渲染数据
- */
- uniforms?: LazyObject;
-
- /**
- * 绘制一定数量顶点。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/drawArrays
- */
- drawArrays?: IGLDrawArrays;
-
- /**
- * 绘制一定数量顶点索引。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/drawElements
- */
- drawElements?: IGLDrawElements;
-
- /**
- * 视窗,显示在画布上的区域。
- *
- * 指定了x和y从标准化设备坐标到窗口坐标的仿射变换。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/viewport
- */
- viewport?: IGLViewport;
-
- /**
- * 剪刀盒。
- *
- * 设置了一个剪刀盒,它将绘图限制为一个指定的矩形。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/scissor
- */
- scissor?: IGLScissor;
-
- /**
- * 回写顶点着色器中输出到缓冲区。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/bindTransformFeedback
- */
- transformFeedback?: IGLTransformFeedback;
-}
diff --git a/src/data/IGLRenderPass.ts b/src/data/IGLRenderPass.ts
index 6c79e4a916cf8cad04f800dbc1b22f3fa775ec0d..f115ef8c58fa433557a1abf17c65a4fadf712fd0 100644
--- a/src/data/IGLRenderPass.ts
+++ b/src/data/IGLRenderPass.ts
@@ -1,21 +1,25 @@
-import { IGLRenderPassDescriptor } from "./IGLPassDescriptor";
-import { IGLQueryAction } from "./IGLQueryAction";
-import { IGLRenderObject } from "./IGLRenderObject";
+import { IRenderPass, IRenderPassObject } from "@feng3d/render-api";
+import { IGLOcclusionQuery } from "./IGLOcclusionQuery";
-/**
- * WebGL渲染通道
- *
- * 包含渲染通道描述以及需要渲染的对象列表。
- */
-export interface IGLRenderPass
+declare module "@feng3d/render-api"
{
/**
- * WebGL渲染通道描述
+ * WebGL渲染通道
+ *
+ * 包含渲染通道描述以及需要渲染的对象列表。
*/
- descriptor?: IGLRenderPassDescriptor;
+ export interface IRenderPass
+ {
+ /**
+ * 渲染不被遮挡查询结果。具体数据保存在各子项的"result"属性中。
+ *
+ * 当提交WebGL后自动获取结果后填充该属性。
+ */
+ occlusionQueryResults?: IGLOcclusionQuery[];
+ }
- /**
- * 渲染对象列表,默认为 []。
- */
- renderObjects?: (IGLRenderObject | IGLQueryAction)[];
+ export interface IRenderPassObjectMap
+ {
+ IGLOcclusionQuery: IGLOcclusionQuery
+ }
}
diff --git a/src/data/IGLRenderPassColorAttachment.ts b/src/data/IGLRenderPassColorAttachment.ts
deleted file mode 100644
index b9d43b4526dfac49c1ee35f8f6b5ebca3414e9f4..0000000000000000000000000000000000000000
--- a/src/data/IGLRenderPassColorAttachment.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import { IGLRenderbuffer } from "./IGLRenderbuffer";
-import { IGLTextureView } from "./IGLTexture";
-
-export interface IGLRenderPassColorAttachment
-{
- /**
- * 颜色附件视图。
- *
- * 如果没有设置,默认为画布;否则使用 帧缓冲 。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/framebufferRenderbuffer
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/framebufferTexture2D
- */
- view?: IGLAttachmentView;
-
- /**
- * 清除后填充值。
- *
- * 默认为 [0,0,0,0]。
- *
- * @see https://developer.mozilla.org/docs/Web/API/WebGLRenderingContext/clearColor
- */
- clearValue?: [red: number, green: number, blue: number, alpha: number];
-
- /**
- * 是否清除颜色附件。
- *
- * 默认 `"clear"` 。
- *
- * @see https://developer.mozilla.org/docs/Web/API/WebGLRenderingContext/clear
- */
- loadOp?: "load" | "clear";
-}
-
-export type IGLAttachmentView = IGLRenderbuffer | IGLTextureView;
diff --git a/src/data/IGLRenderPassDepthStencilAttachment.ts b/src/data/IGLRenderPassDepthStencilAttachment.ts
deleted file mode 100644
index 00d342739e44e0a9a8d3646c4ecbb6078a37c3e9..0000000000000000000000000000000000000000
--- a/src/data/IGLRenderPassDepthStencilAttachment.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-import { IGLAttachmentView } from "./IGLRenderPassColorAttachment";
-
-/**
- * 深度模板附件。
- */
-export interface IGLRenderPassDepthStencilAttachment
-{
- /**
- * 深度附件视图。
- *
- * 如果没有设置,默认为画布;否则使用 帧缓冲 。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/framebufferRenderbuffer
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/framebufferTexture2D
- */
- view?: IGLAttachmentView;
-
- /**
- * 清除后填充深度值。
- *
- * 默认为 1。
- *
- * @see https://developer.mozilla.org/docs/Web/API/WebGLRenderingContext/clearDepth
- */
- depthClearValue?: number;
-
- /**
- * 是否清除深度值。
- *
- * 默认为 "load"。
- *
- * @see https://developer.mozilla.org/docs/Web/API/WebGLRenderingContext/clear
- */
- depthLoadOp?: "load" | "clear";
-
- /**
- * 清除后填充模板值。
- *
- * 默认为 0。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/clearStencil
- */
- stencilClearValue?: number;
-
- /**
- * 是否清除模板值。
- *
- * 默认为 "load"。
- *
- * @see https://developer.mozilla.org/docs/Web/API/WebGLRenderingContext/clear
- */
- stencilLoadOp?: "load" | "clear";
-}
\ No newline at end of file
diff --git a/src/data/IGLRenderPipeline.ts b/src/data/IGLRenderPipeline.ts
deleted file mode 100644
index 50c19bc7023acf58eaa78cc51aaae82df61a157d..0000000000000000000000000000000000000000
--- a/src/data/IGLRenderPipeline.ts
+++ /dev/null
@@ -1,85 +0,0 @@
-import { IGLColorTargetState } from "./IGLColorTargetState";
-import { IGLDepthStencilState } from "./IGLDepthStencilState";
-import { IGLPrimitiveState } from "./IGLPrimitiveState";
-
-/**
- * @deprecated 请使用 `IRenderPipeline` 。
- */
-export type IGLProgram = IGLRenderPipeline;
-
-/**
- * 渲染管线。
- */
-export interface IGLRenderPipeline
-{
- /**
- * 顶点着色器代码
- */
- vertex: IVertexState;
-
- /**
- * 片段着色器代码
- */
- fragment: IFragmentState;
-
- /**
- * 回写变量。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/transformFeedbackVaryings
- */
- transformFeedbackVaryings?: ITransformFeedbackVaryings;
-
- /**
- * 图元拓扑结构。
- */
- primitive?: IGLPrimitiveState;
-
- /**
- * 描述可选的深度模板的测试、运算以及偏差。
- */
- depthStencil?: IGLDepthStencilState;
-
- /**
- * 是否丢弃后续光栅化阶段。
- *
- * gl.RASTERIZER_DISCARD
- */
- rasterizerDiscard?: boolean;
-}
-
-export interface ITransformFeedbackVaryings
-{
- /**
- * 回写变量列表。
- */
- varyings: string[];
-
- /**
- * 交叉或者分离。
- */
- bufferMode: "INTERLEAVED_ATTRIBS" | "SEPARATE_ATTRIBS";
-}
-
-/**
- * 顶点程序阶段。
- */
-export interface IVertexState
-{
- code: string;
-}
-
-/**
- * GPU片元程序阶段。
- */
-export interface IFragmentState
-{
- /**
- * 着色器源码。
- */
- code: string,
-
- /**
- * 定义了该管道写入的颜色目标的格式和行为。
- */
- targets?: IGLColorTargetState[]
-}
\ No newline at end of file
diff --git a/src/data/IGLRenderbuffer.ts b/src/data/IGLRenderbuffer.ts
index 798c790b76cc7a3788a46a6ca8c4c8a3e3d6bba6..ddc6f190000854adb5ba9cdb4ceaf7a4d24a4b4c 100644
--- a/src/data/IGLRenderbuffer.ts
+++ b/src/data/IGLRenderbuffer.ts
@@ -9,17 +9,17 @@ export interface IGLRenderbuffer
/**
* 渲染缓冲区内部格式。
*/
- internalformat: GLRenderbufferInternalformat,
+ readonly internalformat: GLRenderbufferInternalformat,
/**
* 宽度。
*/
- width: number,
+ readonly width: number,
/**
* 高度。
*/
- height: number
+ readonly height: number
}
/**
diff --git a/src/data/IGLSampler.ts b/src/data/IGLSampler.ts
index 31a080bcda7ff73fb2b92a9e54fbf115f8040f3a..681070da45ad78b86d83a183586a7147ca679179 100644
--- a/src/data/IGLSampler.ts
+++ b/src/data/IGLSampler.ts
@@ -1,50 +1,4 @@
-import { GLCompareFunction } from "./IGLDepthStencilState";
-
-export interface IGLSampler
-{
-
- minFilter?: GLTextureMinFilter;
-
- magFilter?: TextureMagFilter;
-
- /**
- * 表示x轴的纹理的回环方式,就是当纹理的宽度小于需要贴图的平面的宽度的时候,平面剩下的部分应该p以何种方式贴图的问题。
- */
- wrapS?: GLTextureWrap;
-
- /**
- * 表示y轴的纹理回环方式。 magFilter和minFilter表示过滤的方式。
- */
- wrapT?: GLTextureWrap;
-
- /**
- * 表示y轴的纹理回环方式。 magFilter和minFilter表示过滤的方式。
- */
- wrapR?: GLTextureWrap;
-
- /**
- * 各向异性过滤。使用各向异性过滤能够使纹理的效果更好,但是会消耗更多的内存、CPU、GPU时间。默认为1。
- */
- anisotropy?: number;
-
- /**
- * 采样时使用的最小Lod等级。
- */
- lodMinClamp?: number;
-
- /**
- * 采样时使用的最大Lod等级。
- */
- lodMaxClamp?: number;
-
- compareMode?: GLSamplerCompareMode;
- /**
- * 比较函数。
- */
- compare?: GLCompareFunction;
-}
-
-export type GLSamplerCompareMode = "NONE" | "COMPARE_REF_TO_TEXTURE";
+export type IGLSamplerCompareMode = "NONE" | "COMPARE_REF_TO_TEXTURE";
/**
* 纹理放大滤波器
@@ -55,7 +9,7 @@ export type GLSamplerCompareMode = "NONE" | "COMPARE_REF_TO_TEXTURE";
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/texParameter
*/
-export type TextureMagFilter = "LINEAR" | "NEAREST";
+export type IGLTextureMagFilter = "LINEAR" | "NEAREST";
/**
* 纹理缩小过滤器
@@ -70,7 +24,7 @@ export type TextureMagFilter = "LINEAR" | "NEAREST";
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/texParameter
*/
-export type GLTextureMinFilter = "LINEAR" | "NEAREST" | "NEAREST_MIPMAP_NEAREST" | "LINEAR_MIPMAP_NEAREST" | "NEAREST_MIPMAP_LINEAR" | "LINEAR_MIPMAP_LINEAR";
+export type IGLTextureMinFilter = "LINEAR" | "NEAREST" | "NEAREST_MIPMAP_NEAREST" | "LINEAR_MIPMAP_NEAREST" | "NEAREST_MIPMAP_LINEAR" | "LINEAR_MIPMAP_LINEAR";
/**
* 纹理坐标s包装函数枚举
@@ -82,4 +36,4 @@ export type GLTextureMinFilter = "LINEAR" | "NEAREST" | "NEAREST_MIPMAP_NEAREST"
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/texParameter
*/
-export type GLTextureWrap = "REPEAT" | "CLAMP_TO_EDGE" | "MIRRORED_REPEAT";
\ No newline at end of file
+export type IGLTextureWrap = "REPEAT" | "CLAMP_TO_EDGE" | "MIRRORED_REPEAT";
\ No newline at end of file
diff --git a/src/data/IGLSamplerTexture.ts b/src/data/IGLSamplerTexture.ts
index 253635842eaa0ada587a11d4fdf4ad59edda794d..2a1bb572b0e117f453ecb7cfe3ae02dac38cca72 100644
--- a/src/data/IGLSamplerTexture.ts
+++ b/src/data/IGLSamplerTexture.ts
@@ -1,5 +1,4 @@
-import { IGLSampler } from "./IGLSampler";
-import { IGLTexture } from "./IGLTexture";
+import { ISampler, ITexture } from "@feng3d/render-api";
/**
* 采样纹理。
@@ -8,10 +7,13 @@ import { IGLTexture } from "./IGLTexture";
*/
export interface IGLSamplerTexture
{
- texture: IGLTexture;
+ /**
+ * 纹理。
+ */
+ texture: ITexture;
/**
* 采样器。
*/
- sampler?: IGLSampler;
-}
\ No newline at end of file
+ sampler?: ISampler;
+}
diff --git a/src/data/IGLScissor.ts b/src/data/IGLScissor.ts
deleted file mode 100644
index 0f0b3f3fe5b82044fa30d461dede154e5e6b417e..0000000000000000000000000000000000000000
--- a/src/data/IGLScissor.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * 剪刀盒。
- *
- * 设置了一个剪刀盒,它将绘图限制为一个指定的矩形。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/scissor
- */
-export interface IGLScissor
-{
- /**
- * 是否开启
- */
- enable?: boolean;
-
- /**
- * 剪刀盒X轴最小值(像素)。
- */
- x: number,
-
- /**
- * 剪刀盒Y轴最小值(像素)。
- */
- y: number,
-
- /**
- * 剪刀盒宽度(像素)。
- */
- width: number,
-
- /**
- * 剪刀盒高度(像素)。
- */
- height: number,
-}
\ No newline at end of file
diff --git a/src/data/IGLTexture.ts b/src/data/IGLTexture.ts
index ed06c313df5d7a113b1cb85f75ab3c45e5dcfe41..bd1c0c203be78835a9474ccabe86222358e75888 100644
--- a/src/data/IGLTexture.ts
+++ b/src/data/IGLTexture.ts
@@ -1,278 +1,10 @@
-import { IGLTexturePixelStore } from "./IGLTexturePixelStore";
-import { IGLTextureStorage } from "./IGLTextureStorage";
+import { ITexture } from "@feng3d/render-api";
+import { IGLCanvasTexture } from "./IGLCanvasTexture";
/**
- * 纹理视图。
+ * 类似纹理,包含画布纹理以及正常纹理。
*/
-export interface IGLTextureView
-{
- /**
- * 纹理。
- */
- texture: IGLTexture,
-
- /**
- * mipmap级别。
- */
- level: number;
-
- /**
- * 纹理数组中的层次。
- */
- layer?: number;
-}
-
-/**
- * 纹理
- */
-export interface IGLTexture
-{
- /**
- * 纹理绑定点。
- *
- * 默认"TEXTURE_2D"。
- */
- target?: GLTextureTarget;
-
- /**
- * 纹理资源。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/texImage2D
- */
- sources?: IGLTextureSource[];
-
- /**
- * 初始纹理时指定纹理存储的各个级别。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/texStorage2D
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/texStorage3D
- */
- storage?: IGLTextureStorage;
-
- /**
- * 写入纹理。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/texSubImage2D
- */
- writeTextures?: IGLWriteTexture[];
-
- /**
- * 是否生成mipmap
- */
- generateMipmap?: boolean;
-
- /**
- * 像素解包打包时参数。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/pixelStorei
- */
- pixelStore?: IGLTexturePixelStore;
-
- /**
- * 内部纹理格式。
- *
- * 默认 "RGBA"。
- */
- internalformat?: IGLTextureInternalFormat,
-
- /**
- * 纹理格式。
- *
- * 默认 "RGBA"。
- */
- format?: IGLTextureFormat;
-
- /**
- * 数据类型。
- *
- * 默认 "UNSIGNED_BYTE"。
- */
- type?: IGLTextureDataType;
-}
-
-/**
- * 纹理资源。
- */
-export type IGLTextureSource = IGLImageSource | IGLBufferSource;
-
-/**
- * 纹理图片资源。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/texImage2D
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/texImage3D
- */
-export interface IGLImageSource
-{
- /**
- * 当上传CubeMap纹理数据时指定位置。
- */
- cubeTarget?: TextureCubeMapTarget;
-
- /**
- * mipmap级别。
- *
- * 默认为 0。
- */
- level?: number,
-
- /**
- * 纹理图片资源。
- */
- source: TexImageSource
-
- /**
- * WebGL2支持
- */
- width?: number;
-
- /**
- * WebGL2支持
- */
- height?: number;
-
- /**
- * 纹理深度,默认为 1。
- *
- * WebGL2 支持。
- */
- depth?: number;
-
- /**
- * WebGL2支持
- */
- border?: number;
-}
-
-/**
- * 纹理数据资源。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/texImage2D
- */
-export interface IGLBufferSource
-{
- /**
- * 当上传CubeMap纹理数据时指定位置。
- */
- cubeTarget?: TextureCubeMapTarget;
-
- /**
- * mipmap级别
- *
- * 默认为 0。
- */
- level?: number,
-
- /**
- * 纹理宽度。
- *
- * 默认为 1。
- */
- width?: number,
-
- /**
- * 纹理高度。
- *
- * 默认为 1。
- */
- height?: number,
-
- /**
- * 纹理深度,默认为 1。
- *
- * WebGL2 支持。
- */
- depth?: number;
-
- /**
- * 默认为 0。
- */
- border?: number,
-
- /**
- * 像素数据。
- *
- * 默认为 undefined。
- */
- pixels?: ArrayBufferView;
-
- /**
- * 默认为 0。
- */
- srcOffset?: number;
-}
-
-/**
- * A GLenum specifying the texture target.
- *
- * gl.TEXTURE_CUBE_MAP_POSITIVE_X: Positive X face for a cube-mapped texture.
- * gl.TEXTURE_CUBE_MAP_NEGATIVE_X: Negative X face for a cube-mapped texture.
- * gl.TEXTURE_CUBE_MAP_POSITIVE_Y: Positive Y face for a cube-mapped texture.
- * gl.TEXTURE_CUBE_MAP_NEGATIVE_Y: Negative Y face for a cube-mapped texture.
- * gl.TEXTURE_CUBE_MAP_POSITIVE_Z: Positive Z face for a cube-mapped texture.
- * gl.TEXTURE_CUBE_MAP_NEGATIVE_Z: Negative Z face for a cube-mapped texture.
- *
- * https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/texImage2D
- */
-export type TextureCubeMapTarget =
- | "TEXTURE_CUBE_MAP_POSITIVE_X"
- | "TEXTURE_CUBE_MAP_NEGATIVE_X"
- | "TEXTURE_CUBE_MAP_POSITIVE_Y"
- | "TEXTURE_CUBE_MAP_NEGATIVE_Y"
- | "TEXTURE_CUBE_MAP_POSITIVE_Z"
- | "TEXTURE_CUBE_MAP_NEGATIVE_Z";
-
-/**
- * 写入纹理。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/texSubImage2D
- */
-export interface IGLWriteTexture
-{
- /**
- * 当上传CubeMap纹理数据时指定位置。
- */
- cubeTarget?: TextureCubeMapTarget;
- /**
- * mipmap级别。
- */
- level: number,
- /**
- * 写入x轴偏移。
- */
- xoffset: number,
- /**
- * 写入Y轴偏移。
- */
- yoffset: number,
- /**
- * 写入3D纹理时深度偏移。
- */
- zoffset?: number;
- /**
- * 写入宽度。
- */
- width?: number,
- /**
- * 写入高度。
- */
- height?: number,
- /**
- * 写入3D纹理深度。
- */
- depth?: number,
- /**
- * 纹理图源数据。
- */
- source?: TexImageSource
- /**
- * 写入像素数据。
- */
- srcData?: ArrayBufferView,
- /**
- * 写入像素数据偏移。
- */
- srcOffset?: number
-}
+export type IGLTextureLike = IGLCanvasTexture | ITexture;
/**
* 纹理绑定点。
@@ -287,14 +19,14 @@ export interface IGLWriteTexture
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bindTexture
*/
-export type GLTextureTarget = "TEXTURE_2D" | "TEXTURE_CUBE_MAP" | "TEXTURE_3D" | "TEXTURE_2D_ARRAY";
+export type IGLTextureTarget = "TEXTURE_2D" | "TEXTURE_CUBE_MAP" | "TEXTURE_3D" | "TEXTURE_2D_ARRAY";
/**
* internalformat format type
*
* @see https://registry.khronos.org/webgl/specs/latest/2.0/#TEXTURE_TYPES_FORMATS_FROM_DOM_ELEMENTS_TABLE
*/
-export type GLTextureTypes =
+export type IGLTextureTypes =
| { internalformat: "RGB", format: "RGB", type: "UNSIGNED_BYTE" | "UNSIGNED_SHORT_5_6_5" }
| { internalformat: "RGBA", format: "RGBA", type: "UNSIGNED_BYTE" | "UNSIGNED_SHORT_4_4_4_4" | "UNSIGNED_SHORT_5_5_5_1" }
| { internalformat: "LUMINANCE_ALPHA", format: "LUMINANCE_ALPHA", type: "UNSIGNED_BYTE" }
@@ -328,6 +60,6 @@ export type GLTextureTypes =
| { internalformat: "DEPTH_COMPONENT16", format: "DEPTH_COMPONENT", type: "UNSIGNED_SHORT", }
;
-export type IGLTextureInternalFormat = GLTextureTypes["internalformat"];
-export type IGLTextureFormat = GLTextureTypes["format"];
-export type IGLTextureDataType = GLTextureTypes["type"];
+export type IGLTextureInternalFormat = IGLTextureTypes["internalformat"];
+export type IGLTextureFormat = IGLTextureTypes["format"];
+export type IGLTextureDataType = IGLTextureTypes["type"];
diff --git a/src/data/IGLTextureFormats.ts b/src/data/IGLTextureFormats.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5c2dc144110d14fdf1ff67e0c1dfc45f9e50c0ca
--- /dev/null
+++ b/src/data/IGLTextureFormats.ts
@@ -0,0 +1,25 @@
+import { IGLTextureDataType, IGLTextureFormat, IGLTextureInternalFormat } from "./IGLTexture";
+
+export interface IGLTextureFormats
+{
+ /**
+ * 内部纹理格式。
+ *
+ * 默认 "RGBA"。
+ */
+ readonly internalformat?: IGLTextureInternalFormat,
+
+ /**
+ * 纹理格式。
+ *
+ * 默认 "RGBA"。
+ */
+ readonly format?: IGLTextureFormat;
+
+ /**
+ * 数据类型。
+ *
+ * 默认 "UNSIGNED_BYTE"。
+ */
+ readonly type?: IGLTextureDataType;
+}
\ No newline at end of file
diff --git a/src/data/IGLTexturePixelStore.ts b/src/data/IGLTexturePixelStore.ts
index ec6ce4271060bb8cd3e150b056a6e4a0af1ad36b..346ffc349252159c28503e9b3630cea6ac1ce419 100644
--- a/src/data/IGLTexturePixelStore.ts
+++ b/src/data/IGLTexturePixelStore.ts
@@ -1,4 +1,106 @@
+/**
+ * 像素解包打包时参数。
+ *
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/pixelStorei
+ */
+export interface IGLTexturePixelStore1
+{
+ /**
+ * Packing of pixel data into memory
+ *
+ * gl.PACK_ALIGNMENT
+ *
+ * 默认值为 4 。
+ */
+ packAlignment?: 1 | 2 | 4 | 8;
+
+ /**
+ * Unpacking of pixel data from memory.
+ *
+ * gl.UNPACK_ALIGNMENT
+ *
+ * 默认值为 4 。
+ */
+ unpackAlignment?: 1 | 2 | 4 | 8;
+
+ /**
+ * Default color space conversion or no color space conversion.
+ *
+ * gl.UNPACK_COLORSPACE_CONVERSION_WEBGL
+ *
+ * 默认为 "BROWSER_DEFAULT_WEBGL" 。
+ */
+ unpackColorSpaceConversion?: "BROWSER_DEFAULT_WEBGL" | "NONE";
+
+ /**
+ * Number of pixels in a row.
+ *
+ * gl.PACK_ROW_LENGTH
+ *
+ * 默认值为 0 。
+ *
+ * 仅 WebGL2。
+ */
+ packRowLength?: number;
+
+ /**
+ * Number of pixel locations skipped before the first pixel is written into memory.
+ *
+ * gl.PACK_SKIP_PIXELS
+ *
+ * 默认值为 0 。
+ *
+ * 仅 WebGL2。
+ */
+ packSkipPixels?: number;
+
+ /**
+ * Number of rows of pixel locations skipped before the first pixel is written into memory
+ *
+ * gl.PACK_SKIP_ROWS
+ *
+ * 默认值为 0 。
+ *
+ * 仅 WebGL2。
+ */
+ packSkipRows?: number;
+
+ /**
+ * Number of pixels in a row.
+ *
+ * gl.UNPACK_ROW_LENGTH
+ *
+ * 默认值为 0 。
+ *
+ * 仅 WebGL2。
+ */
+ unpackRowLength?: number;
+
+ /**
+ * Image height used for reading pixel data from memory
+ *
+ * gl.UNPACK_IMAGE_HEIGHT
+ *
+ * 默认值为 0 。
+ *
+ * 仅 WebGL2。
+ */
+ unpackImageHeight?: number;
+
+ /**
+ *
+ * Number of pixel images skipped before the first pixel is read from memory
+ *
+ * gl.UNPACK_SKIP_IMAGES
+ *
+ * 默认值为 0 。
+ *
+ * 仅 WebGL2。
+ */
+ unpackSkipImages?: number;
+}
+
/**
* 像素解包打包时参数。
*
diff --git a/src/data/IGLTextureStorage.ts b/src/data/IGLTextureStorage.ts
deleted file mode 100644
index 417f1342876a6134d6c5c67d20b59f06d164fe3c..0000000000000000000000000000000000000000
--- a/src/data/IGLTextureStorage.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-/**
- * 初始纹理时指定纹理存储的各个级别。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/texStorage2D
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/texStorage3D
- */
-export interface IGLTextureStorage
-{
- levels: number, width: number, height: number;
- /**
- * 3D纹理深度。
- */
- depth?: number
-}
\ No newline at end of file
diff --git a/src/data/IGLTransformFeedback.ts b/src/data/IGLTransformFeedback.ts
index a9a32a43682e8fcafe1a076f7fef598987ff6c2f..8ad75046ab3ecb6e24c429790964b3d0dd8c415a 100644
--- a/src/data/IGLTransformFeedback.ts
+++ b/src/data/IGLTransformFeedback.ts
@@ -1,4 +1,4 @@
-import { IGLBuffer } from "./IGLBuffer";
+import { IVertexDataTypes } from "@feng3d/render-api";
/**
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/createTransformFeedback
@@ -15,5 +15,5 @@ export interface IGLTransformFeedbacBindBuffer
{
index: number;
- buffer: IGLBuffer;
+ data: IVertexDataTypes;
}
\ No newline at end of file
diff --git a/src/data/IGLTransformFeedbackPass.ts b/src/data/IGLTransformFeedbackPass.ts
new file mode 100644
index 0000000000000000000000000000000000000000..413eb17296f65561876166521cf26fc531913f94
--- /dev/null
+++ b/src/data/IGLTransformFeedbackPass.ts
@@ -0,0 +1,83 @@
+import { IDrawVertex, IUniforms, IVertexAttributes, IVertexState } from "@feng3d/render-api";
+import { IGLTransformFeedback } from "./IGLTransformFeedback";
+
+declare module "@feng3d/render-api"
+{
+ export interface IPassEncoderMap
+ {
+ IGLTransformFeedbackPass: IGLTransformFeedbackPass,
+ }
+}
+
+export interface IGLTransformFeedbackPass
+{
+ /**
+ * 数据类型。
+ */
+ readonly __type: "TransformFeedbackPass";
+
+ /**
+ * 变换反馈对象列表。
+ */
+ transformFeedbackObjects: IGLTransformFeedbackObject[];
+}
+
+export interface IGLTransformFeedbackObject
+{
+ /**
+ * 渲染管线描述。
+ */
+ readonly pipeline: IGLTransformFeedbackPipeline;
+
+ /**
+ * 顶点属性数据映射。
+ */
+ vertices: IVertexAttributes;
+
+ /**
+ * 根据顶点数据绘制图元。
+ *
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/drawVertex
+ */
+ readonly drawVertex: IDrawVertex;
+
+ /**
+ * Uniform渲染数据
+ */
+ uniforms?: IUniforms;
+
+ /**
+ * 回写顶点着色器中输出到缓冲区。
+ *
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/bindTransformFeedback
+ */
+ transformFeedback: IGLTransformFeedback;
+}
+
+export interface IGLTransformFeedbackPipeline
+{
+ /**
+ * 顶点着色器阶段描述。
+ */
+ readonly vertex: IVertexState;
+
+ /**
+ * 回写变量。
+ *
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/transformFeedbackVaryings
+ */
+ transformFeedbackVaryings: IGLTransformFeedbackVaryings;
+}
+
+export interface IGLTransformFeedbackVaryings
+{
+ /**
+ * 回写变量列表。
+ */
+ varyings: string[];
+
+ /**
+ * 交叉或者分离。
+ */
+ bufferMode: "INTERLEAVED_ATTRIBS" | "SEPARATE_ATTRIBS";
+}
diff --git a/src/data/IGLUniformInfo.ts b/src/data/IGLUniformInfo.ts
index cf059c5318828aae9395c9734b467d7112b2efc1..45c6883727ac81f6f8bdf37949413da69ed9f29c 100644
--- a/src/data/IGLUniformInfo.ts
+++ b/src/data/IGLUniformInfo.ts
@@ -1,4 +1,4 @@
-import { IGLUniformType } from "../const/WebGLUniformType";
+import { IGLUniformType } from "../const/IGLUniformType";
/**
* WebGL统一变量
diff --git a/src/data/IGLUniforms.ts b/src/data/IGLUniforms.ts
index ff2cac45b283dd38f9bd09854b651b61d2f879a2..a1bf151bd7f33e72e2147280c30cbd777cfc84ee 100644
--- a/src/data/IGLUniforms.ts
+++ b/src/data/IGLUniforms.ts
@@ -1,20 +1,11 @@
-import { IGLBuffer } from "./IGLBuffer";
+import { IUniformDataItem } from "@feng3d/render-api";
import { IGLSamplerTexture } from "./IGLSamplerTexture";
-/**
- * Uniform 类型
- */
-export type IGLUniformType = IGLSamplerTexture | IGLSamplerTexture[] | number | number[] | Float32Array | (number[] | Float32Array)[] | Int32Array | IGLUniformBuffer | IGLUniforms;
-
-export interface IGLUniformBuffer extends IGLBuffer
-{
- target: "UNIFORM_BUFFER";
-}
-
-/**
- * Uniform 数据
- */
-export interface IGLUniforms
+declare module "@feng3d/render-api"
{
- [key: string]: IGLUniformType;
+ export interface IUniformTypeMap
+ {
+ IGLSamplerTexture: IGLSamplerTexture;
+ IUniformDataItem: IUniformDataItem;
+ }
}
diff --git a/src/data/IGLVertexArrayObject.ts b/src/data/IGLVertexArrayObject.ts
deleted file mode 100644
index d433ca230a1aa47b57c11d635c95f552b8f94b01..0000000000000000000000000000000000000000
--- a/src/data/IGLVertexArrayObject.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import { IGLIndexBuffer } from "./IGLIndexBuffer";
-import { IGLVertexAttributes } from "./IGLVertexAttributes";
-
-export interface IGLVertexArrayObject
-{
- /**
- * 顶点索引缓冲
- */
- index?: IGLIndexBuffer;
-
- /**
- * 顶点属性数据列表
- */
- vertices: IGLVertexAttributes;
-}
\ No newline at end of file
diff --git a/src/data/IGLVertexAttributes.ts b/src/data/IGLVertexAttributes.ts
deleted file mode 100644
index b004dcf5b5aacfcb7a48c0330e26e29fd8b6c9e7..0000000000000000000000000000000000000000
--- a/src/data/IGLVertexAttributes.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { IGLVertexAttribute } from "./IGLVertexAttribute";
-
-/**
- * 顶点属性数据映射。
- */
-export interface IGLVertexAttributes
-{
- [name: string]: IGLVertexAttribute;
-}
\ No newline at end of file
diff --git a/src/data/IGLViewport.ts b/src/data/IGLViewport.ts
deleted file mode 100644
index 66bcf5d1ec24e0aec55d1ba737f0907fee94c5f4..0000000000000000000000000000000000000000
--- a/src/data/IGLViewport.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * 视窗。
- */
-export interface IGLViewport
-{
- /**
- * 视窗X轴最小值(像素)。
- */
- x: number,
-
- /**
- * 视窗Y轴最小值(像素)。
- */
- y: number,
-
- /**
- * 视窗宽度(像素)。
- */
- width: number,
-
- /**
- * 视窗高度(像素)。
- */
- height: number,
-}
diff --git a/src/defaults/defaultWebGLCanvasContext.ts b/src/defaults/defaultWebGLCanvasContext.ts
deleted file mode 100644
index 001f1e577d4a990faa2a5f203ffdabdeb1b1fe31..0000000000000000000000000000000000000000
--- a/src/defaults/defaultWebGLCanvasContext.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import { IGLRenderingContext } from "../data/IGLRenderingContext";
-
-/**
- * 默认WebGL上下文信息。
- */
-export const defaultCanvasContext: IGLRenderingContext = Object.freeze({
- contextId: "webgl2",
- depth: true,
- stencil: true,
- antialias: false,
- premultipliedAlpha: true,
- preserveDrawingBuffer: false,
- powerPreference: "default",
- failIfMajorPerformanceCaveat: false,
-});
diff --git a/src/defaults/defaults.ts b/src/defaults/defaults.ts
index 9859396d5092662d479a6dfa6ab3c80460ee30a3..158527760a22f3626d288fe5b0b5c986c294e72e 100644
--- a/src/defaults/defaults.ts
+++ b/src/defaults/defaults.ts
@@ -1,8 +1,15 @@
-import { defaultCanvasContext } from "./defaultWebGLCanvasContext";
+import { IGLCanvasContext } from "../data/IGLCanvasContext";
/**
- * 默认值
+ * 默认WebGL上下文信息。
*/
-export const defaults = Object.freeze({
- webGLCanvasContext: defaultCanvasContext,
-});
\ No newline at end of file
+export const defaultCanvasContext: IGLCanvasContext = Object.freeze({
+ contextId: "webgl2",
+ depth: true,
+ stencil: true,
+ antialias: false,
+ premultipliedAlpha: true,
+ preserveDrawingBuffer: false,
+ powerPreference: "default",
+ failIfMajorPerformanceCaveat: false,
+});
diff --git a/src/gl/WebGLEnums.ts b/src/gl/WebGLEnums.ts
index c48b39179a92d88232e909505333f8a4657dc24b..52d94500a2e72ab80c5434ba1725e213eb7860c3 100644
--- a/src/gl/WebGLEnums.ts
+++ b/src/gl/WebGLEnums.ts
@@ -1,4 +1,4 @@
-import { TextureMagFilter, GLTextureMinFilter, GLTextureWrap } from "../data/IGLSampler";
+import { IGLTextureMagFilter, IGLTextureMinFilter, IGLTextureWrap } from "../data/IGLSampler";
/**
* A GLenum specifying which WebGL capability to enable. Possible values:
@@ -95,22 +95,22 @@ export interface TexParameteri extends TexParameteri_WebGL2
/**
* Texture magnification filter
*/
- TEXTURE_MAG_FILTER: TextureMagFilter;
+ TEXTURE_MAG_FILTER: IGLTextureMagFilter;
/**
* Texture minification filter
*/
- TEXTURE_MIN_FILTER: GLTextureMinFilter;
+ TEXTURE_MIN_FILTER: IGLTextureMinFilter;
/**
* Wrapping function for texture coordinate s
*/
- TEXTURE_WRAP_S: GLTextureWrap;
+ TEXTURE_WRAP_S: IGLTextureWrap;
/**
* Wrapping function for texture coordinate t
*/
- TEXTURE_WRAP_T: GLTextureWrap;
+ TEXTURE_WRAP_T: IGLTextureWrap;
}
/**
@@ -163,7 +163,7 @@ export interface TexParameteri_WebGL2
/**
* Wrapping function for texture coordinate r
*/
- TEXTURE_WRAP_R: GLTextureWrap;
+ TEXTURE_WRAP_R: IGLTextureWrap;
}
/**
diff --git a/src/index.ts b/src/index.ts
index 4257138d5db906aaedd1a2cfbcda66730c0db90b..fc06b9c5ff4de6eb6830d320a4de6391e8f82882 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,41 +1,27 @@
-export * from "./data/IGLBlendState";
export * from "./data/IGLBlitFramebuffer";
export * from "./data/IGLBuffer";
+export * from "./data/IGLCanvasContext";
export * from "./data/IGLCapabilities";
-export * from "./data/IGLColorTargetState";
-export * from "./data/IGLCopyBuffer";
-export * from "./data/IGLCullFace";
+export * from "./data/IGLCommandEncoder";
export * from "./data/IGLDepthStencilState";
-export * from "./data/IGLDrawArrays";
-export * from "./data/IGLDrawElements";
-export * from "./data/IGLFramebuffer";
-export * from "./data/IGLIndexBuffer";
-export * from "./data/IGLPassDescriptor";
+export * from "./data/IGLOcclusionQuery";
export * from "./data/IGLPrimitiveState";
-export * from "./data/IGLQueryAction";
export * from "./data/IGLReadPixels";
export * from "./data/IGLRenderbuffer";
-export * from "./data/IGLRenderingContext";
-export * from "./data/IGLRenderObject";
export * from "./data/IGLRenderPass";
-export * from "./data/IGLRenderPassColorAttachment";
-export * from "./data/IGLRenderPassDepthStencilAttachment";
-export * from "./data/IGLRenderPipeline";
export * from "./data/IGLSampler";
export * from "./data/IGLSamplerTexture";
-export * from "./data/IGLScissor";
export * from "./data/IGLTexture";
export * from "./data/IGLTexturePixelStore";
-export * from "./data/IGLTextureStorage";
export * from "./data/IGLTransformFeedback";
+export * from "./data/IGLTransformFeedbackPass";
export * from "./data/IGLUniforms";
-export * from "./data/IGLVertexArrayObject";
-export * from "./data/IGLVertexAttribute";
-export * from "./data/IGLVertexAttributes";
-export * from "./data/IGLViewport";
+export * from "./runs/getIGLBuffer";
export * from "./runs/runColorTargetStates";
-export * from "./runs/runPassDescriptor";
+export * from "./RunWebGL";
+
+export * from "./defaults/defaults";
export * from "./gl/WebGLEnums";
@@ -45,7 +31,9 @@ export * from "./shader/ShaderMacroUtils";
export * from "./WebGL";
-export * from "./runs/runDrawCall";
-
export * as internal from "./internal";
+export * from "./caches/getGLBuffer";
+
+export * from "./utils/getIVertexFormat";
+
diff --git a/src/internal.ts b/src/internal.ts
index c038fe1446a8ea8d7e747e1e8cec45775a797577..c59cd7d4bc78cf31d6c2e75967e21d668b6195df 100644
--- a/src/internal.ts
+++ b/src/internal.ts
@@ -1,6 +1,2 @@
-export { defaultGLSampler } from "./runs/runSampler";
-
-export * from "./caches/getIGLTextureSize";
-export * from "./caches/getTexImageSourceSize";
-export * from "./caches/getTexture";
+export * from "./caches/getGLTexture";
diff --git a/src/runs/getIGLBuffer.ts b/src/runs/getIGLBuffer.ts
new file mode 100644
index 0000000000000000000000000000000000000000..646fc3243171ba891b9830df70d63953b9e2b080
--- /dev/null
+++ b/src/runs/getIGLBuffer.ts
@@ -0,0 +1,41 @@
+import { IBuffer, IIndicesDataTypes, IVertexDataTypes, TypedArray } from "@feng3d/render-api";
+import { IGLBufferTarget, IGLBufferUsage, IGLIndexBuffer, IGLUniformBuffer, IGLVertexBuffer } from "../data/IGLBuffer";
+
+export function getIGLBuffer(data: TypedArray, target?: IGLBufferTarget, usage: IGLBufferUsage = "STATIC_DRAW"): IBuffer
+{
+ if (data[_IGLBuffer]) return data[_IGLBuffer];
+
+ const buffer: IBuffer = {
+ size: Math.ceil(data.byteLength / 4) * 4,
+ target: target,
+ usage: usage,
+ data: data,
+ };
+ data[_IGLBuffer] = buffer;
+
+ return buffer;
+}
+
+export function getIGLUniformBuffer(data: TypedArray, usage?: "DYNAMIC_DRAW")
+{
+ const vertexBuffer: IGLUniformBuffer = data[_IGLBuffer] = data[_IGLBuffer] || getIGLBuffer(data, "UNIFORM_BUFFER", usage);
+ vertexBuffer.target = vertexBuffer.target || "UNIFORM_BUFFER";
+
+ return vertexBuffer;
+}
+
+export function getIGLVertexBuffer(data: IVertexDataTypes, usage?: "STREAM_COPY")
+{
+ const vertexBuffer: IGLVertexBuffer = data[_IGLBuffer] = data[_IGLBuffer] || getIGLBuffer(data, "ARRAY_BUFFER", usage);
+
+ return vertexBuffer;
+}
+
+export function getIGLIndexBuffer(indices: IIndicesDataTypes)
+{
+ const indexBuffer: IGLIndexBuffer = indices[_IGLBuffer] = indices[_IGLBuffer] || getIGLBuffer(indices, "ELEMENT_ARRAY_BUFFER");
+
+ return indexBuffer;
+}
+
+const _IGLBuffer = "IGLBuffer";
\ No newline at end of file
diff --git a/src/runs/runBlitFramebuffer.ts b/src/runs/runBlitFramebuffer.ts
deleted file mode 100644
index ce8edfc8dd1e1d0d747a40ef0ca04c67e154556d..0000000000000000000000000000000000000000
--- a/src/runs/runBlitFramebuffer.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import { getFramebuffer } from "../caches/getFramebuffer";
-import { IGLBlitFramebuffer } from "../data/IGLBlitFramebuffer";
-
-export function runBlitFramebuffer(gl: WebGLRenderingContext, blitFramebuffer: IGLBlitFramebuffer)
-{
- const { read, draw, blitFramebuffers } = blitFramebuffer;
-
- const readFramebuffer = getFramebuffer(gl, read);
- const drawFramebuffer = getFramebuffer(gl, draw);
-
- if (gl instanceof WebGL2RenderingContext)
- {
- gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFramebuffer);
- gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, drawFramebuffer);
-
- draw.colorAttachments.forEach((item, i) =>
- {
- const clearValue = draw.colorAttachments[i]?.clearValue;
- if (clearValue)
- {
- gl.clearBufferfv(gl.COLOR, i, clearValue);
- }
- });
-
- blitFramebuffers.forEach((item) =>
- {
- const [srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter] = item;
-
- gl.blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, gl[mask], gl[filter]);
- });
- }
-}
diff --git a/src/runs/runColorTargetStates.ts b/src/runs/runColorTargetStates.ts
index 0aaa0d2a63299ff9f7490a8aad1eac0db5c57940..e46060acba73cecff21a75aa6294d8f3edde8fe3 100644
--- a/src/runs/runColorTargetStates.ts
+++ b/src/runs/runColorTargetStates.ts
@@ -1,33 +1,105 @@
-import { IGLBlendComponent, IGLBlendState } from "../data/IGLBlendState";
-import { IGLColorTargetState, IGLWriteMask } from "../data/IGLColorTargetState";
+import { IBlendFactor, IBlendOperation } from "@feng3d/render-api";
-export function runColorTargetStates(gl: WebGLRenderingContext, targets?: IGLColorTargetState[])
+export function getIGLBlendEquation(operation?: IBlendOperation)
{
- //
- const colorMask = targets?.[0]?.writeMask || defaultWriteMask;
- gl.colorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]);
-
- //
- let blend = targets?.[0]?.blend;
- if (blend)
- {
- blend = {
- color: { ...defaultBlendState.color, ...blend?.color },
- alpha: { ...defaultBlendState.alpha, ...blend?.color, ...blend?.alpha },
- };
- //
- gl.enable(gl.BLEND);
- gl.blendEquationSeparate(gl[blend.color.operation], gl[blend.alpha.operation]);
- gl.blendFuncSeparate(gl[blend.color.srcFactor], gl[blend.color.dstFactor], gl[blend.alpha.srcFactor], gl[blend.alpha.dstFactor]);
- }
- else
- {
- gl.disable(gl.BLEND);
- }
+ if (!operation) return undefined;
+
+ const glBlendEquation: IGLBlendEquation = operationMap[operation];
+
+ console.assert(!!glBlendEquation, `接收到错误值,请从 ${Object.keys(operationMap).toString()} 中取值!`);
+
+ return glBlendEquation;
}
-const defaultWriteMask: IGLWriteMask = Object.freeze([true, true, true, true]) as any;
-const defaultBlendComponent: IGLBlendComponent = Object.freeze({ operation: "FUNC_ADD", srcFactor: "SRC_ALPHA", dstFactor: "ONE_MINUS_SRC_ALPHA" });
-export const defaultBlendState: IGLBlendState = Object.freeze({ color: defaultBlendComponent, alpha: defaultBlendComponent });
-const defaultColorTargetState: IGLColorTargetState = Object.freeze({ writeMask: defaultWriteMask, blend: defaultBlendState });
-export const defaultColorTargetStates: IGLColorTargetState[] = Object.freeze([defaultColorTargetState]) as any;
\ No newline at end of file
+const operationMap: { [key: string]: IGLBlendEquation } = {
+ "add": "FUNC_ADD",
+ "subtract": "FUNC_SUBTRACT",
+ "reverse-subtract": "FUNC_REVERSE_SUBTRACT",
+ "min": "MIN",
+ "max": "MAX",
+};
+
+export function getIGLBlendFactor(blendFactor: IBlendFactor, operation: IBlendOperation)
+{
+ if (!blendFactor) return undefined;
+
+ if (operation === "max" || operation === "min") blendFactor = "one";
+
+ const glBlendFactor: IGLBlendFactor = blendFactorMap[blendFactor];
+
+ console.assert(!!glBlendFactor, `接收到错误值,请从 ${Object.keys(blendFactorMap).toString()} 中取值!`);
+
+ return glBlendFactor;
+}
+
+const blendFactorMap: { [key: string]: IGLBlendFactor } = {
+ "zero": "ZERO",
+ "one": "ONE",
+ "src": "SRC_COLOR",
+ "one-minus-src": "ONE_MINUS_SRC_COLOR",
+ "src-alpha": "SRC_ALPHA",
+ "one-minus-src-alpha": "ONE_MINUS_SRC_ALPHA",
+ "dst": "DST_COLOR",
+ "one-minus-dst": "ONE_MINUS_DST_COLOR",
+ "dst-alpha": "DST_ALPHA",
+ "one-minus-dst-alpha": "ONE_MINUS_DST_ALPHA",
+ "src-alpha-saturated": "SRC_ALPHA_SATURATE",
+ "constant": "CONSTANT_COLOR",
+ "one-minus-constant": "ONE_MINUS_CONSTANT_COLOR",
+};
+
+/**
+ * 混合因子(R分量系数,G分量系数,B分量系数)
+ *
+ * 混合颜色的公式可以这样描述:color(RGBA) = (sourceColor * sfactor) + (destinationColor * dfactor)。这里的 RGBA 值均在0与1之间。
+ *
+ * The formula for the blending color can be described like this: color(RGBA) = (sourceColor * sfactor) + (destinationColor * dfactor). The RBGA values are between 0 and 1.
+ *
+ * * `ZERO` Factor: (0,0,0,0); 把所有颜色都乘以0。
+ * * `ONE` Factor: (1,1,1,1); 把所有颜色都乘以1。
+ * * `SRC_COLOR` Factor: (Rs, Gs, Bs, As); 将所有颜色乘以源颜色。
+ * * `ONE_MINUS_SRC_COLOR` Factor: (1-Rs, 1-Gs, 1-Bs, 1-As); 将所有颜色乘以1减去每个源颜色。
+ * * `DST_COLOR` Factor: (Rd, Gd, Bd, Ad); 将所有颜色乘以目标颜色。
+ * * `ONE_MINUS_DST_COLOR` Factor: (1-Rd, 1-Gd, 1-Bd, 1-Ad); 将所有颜色乘以1减去每个目标颜色。
+ * * `SRC_ALPHA` Factor: (As, As, As, As); 将所有颜色乘以源alpha值。
+ * * `ONE_MINUS_SRC_ALPHA` Factor: (1-As, 1-As, 1-As, 1-As); 将所有颜色乘以1减去源alpha值。
+ * * `DST_ALPHA` Factor: (Ad, Ad, Ad, Ad); 将所有颜色乘以目标alpha值。
+ * * `ONE_MINUS_DST_ALPHA` Factor: (1-Ad, 1-Ad, 1-Ad, 1-Ad); 将所有颜色乘以1减去目标alpha值。
+ * * `CONSTANT_COLOR` Factor: (Rc, Gc, Bc, Ac); 将所有颜色乘以一个常数颜色。
+ * * `ONE_MINUS_CONSTANT_COLOR` Factor: (1-Rc, 1-Gc, 1-Bc, 1-Ac); 所有颜色乘以1减去一个常数颜色。
+ * * `CONSTANT_ALPHA` Factor: (Ac, Ac, Ac, Ac); 将所有颜色乘以一个常量alpha值。
+ * * `ONE_MINUS_CONSTANT_ALPHA` Factor: (1-Ac, 1-Ac, 1-Ac, 1-Ac); 将所有颜色乘以1减去一个常数alpha值。
+ * * `SRC_ALPHA_SATURATE` Factor: (min(As, 1 - Ad), min(As, 1 - Ad), min(As, 1 - Ad), 1); 将RGB颜色乘以源alpha值与1减去目标alpha值的较小值。alpha值乘以1。
+ *
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/blendFunc
+ */
+export type IGLBlendFactor = "ZERO" | "ONE" | "SRC_COLOR" | "ONE_MINUS_SRC_COLOR" | "DST_COLOR" | "ONE_MINUS_DST_COLOR" | "SRC_ALPHA" | "ONE_MINUS_SRC_ALPHA" | "DST_ALPHA" | "ONE_MINUS_DST_ALPHA" | "SRC_ALPHA_SATURATE" | "CONSTANT_COLOR" | "ONE_MINUS_CONSTANT_COLOR" | "CONSTANT_ALPHA" | "ONE_MINUS_CONSTANT_ALPHA";
+
+/**
+ * 混合方法
+ *
+ * * FUNC_ADD 源 + 目标
+ * * FUNC_SUBTRACT 源 - 目标
+ * * FUNC_REVERSE_SUBTRACT 目标 - 源
+ * * MIN 源与目标的最小值,在 WebGL 2 中可使用。在 WebGL 1 时,自动使用 EXT_blend_minmax 扩展中 MIN_EXT 值。
+ * * MAX 源与目标的最大值,在 WebGL 2 中可使用。在 WebGL 1 时,自动使用 EXT_blend_minmax 扩展中 MAX_EXT 值。
+ *
+ * A GLenum specifying how source and destination colors are combined. Must be either:
+ *
+ * * gl.FUNC_ADD: source + destination (default value)
+ * * gl.FUNC_SUBTRACT: source - destination
+ * * gl.FUNC_REVERSE_SUBTRACT: destination - source
+ *
+ * When using the EXT_blend_minmax extension:
+ *
+ * * ext.MIN_EXT: Minimum of source and destination
+ * * ext.MAX_EXT: Maximum of source and destination
+ *
+ * When using a WebGL 2 context, the following values are available additionally:
+ *
+ * * gl.MIN: Minimum of source and destination
+ * * gl.MAX: Maximum of source and destination
+ *
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/blendEquation
+ */
+export type IGLBlendEquation = "FUNC_ADD" | "FUNC_SUBTRACT" | "FUNC_REVERSE_SUBTRACT" | "MIN" | "MAX";
diff --git a/src/runs/runCopyBuffer.ts b/src/runs/runCopyBuffer.ts
deleted file mode 100644
index aa4c582c6941396fbaff6ca982ae0fbc5cd172f2..0000000000000000000000000000000000000000
--- a/src/runs/runCopyBuffer.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { getWebGLBuffer } from "../caches/getWebGLBuffer";
-import { IGLCopyBuffer } from "../data/IGLCopyBuffer";
-
-export function runCopyBuffer(gl: WebGLRenderingContext, copyBuffer: IGLCopyBuffer)
-{
- if (gl instanceof WebGL2RenderingContext)
- {
- const { read, write, readOffset, writeOffset, size } = copyBuffer;
-
- const rb = getWebGLBuffer(gl, read);
- const wb = getWebGLBuffer(gl, write);
-
- gl.bindBuffer(gl.COPY_READ_BUFFER, rb);
- gl.bindBuffer(gl.COPY_WRITE_BUFFER, wb);
- gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, readOffset, writeOffset, size);
- }
- else
- {
- console.error(`WebGL1 不支持拷贝缓冲区功能!`);
- }
-}
\ No newline at end of file
diff --git a/src/runs/runDepthState.ts b/src/runs/runDepthState.ts
index 0cf91f19011fc4b7dae108e40b44f41624243690..9d99e8bdfbcc43c438caa7a98325805b5dd77933 100644
--- a/src/runs/runDepthState.ts
+++ b/src/runs/runDepthState.ts
@@ -1,34 +1,22 @@
-import { IGLDepthState } from "../data/IGLDepthStencilState";
+import { ICompareFunction, IDepthStencilState } from "@feng3d/render-api";
+import { IGLCompareFunction } from "../data/IGLDepthStencilState";
-export function runDepthState(gl: WebGLRenderingContext, depth: IGLDepthState)
+export function getIGLCompareFunction(depthCompare: ICompareFunction)
{
- const { depthtest, depthCompare, depthWriteEnabled, depthBias } = { ...defaultDepthState, ...depth };
+ const glDepthCompare: IGLCompareFunction = depthCompareMap[depthCompare];
- if (depthtest)
- {
- gl.enable(gl.DEPTH_TEST);
- //
- gl.depthFunc(gl[depthCompare]);
- gl.depthMask(depthWriteEnabled);
-
- //
- if (depthBias)
- {
- const { factor, units } = depthBias;
-
- gl.enable(gl.POLYGON_OFFSET_FILL);
- gl.polygonOffset(factor, units);
- }
- else
- {
- gl.disable(gl.POLYGON_OFFSET_FILL);
- }
- }
- else
- {
- gl.disable(gl.DEPTH_TEST);
- }
+ console.assert(!!glDepthCompare, `接收到错误值,请从 ${Object.keys(depthCompareMap).toString()} 中取值!`);
+
+ return glDepthCompare;
}
-export const defaultDepthState: IGLDepthState = { depthtest: false, depthWriteEnabled: true, depthCompare: "LESS" };
-Object.freeze(defaultDepthState);
\ No newline at end of file
+const depthCompareMap: { [key: string]: IGLCompareFunction } = {
+ "never": "NEVER",
+ "less": "LESS",
+ "equal": "EQUAL",
+ "less-equal": "LEQUAL",
+ "greater": "GREATER",
+ "not-equal": "NOTEQUAL",
+ "greater-equal": "GEQUAL",
+ "always": "ALWAYS",
+};
\ No newline at end of file
diff --git a/src/runs/runDepthStencilState.ts b/src/runs/runDepthStencilState.ts
deleted file mode 100644
index 33f966971dfac797a3e1f77f5e3b4f1777621336..0000000000000000000000000000000000000000
--- a/src/runs/runDepthStencilState.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { IGLDepthStencilState } from "../data/IGLDepthStencilState";
-import { defaultDepthState, runDepthState } from "./runDepthState";
-import { defaultStencilState, runStencilState } from "./runStencilState";
-
-export const defaultDepthStencilState: IGLDepthStencilState = Object.freeze({ depth: defaultDepthState, stencil: defaultStencilState });
-
-export function runDepthStencilState(gl: WebGLRenderingContext, depthStencil?: IGLDepthStencilState)
-{
- runDepthState(gl, depthStencil?.depth || defaultDepthStencilState.depth);
- runStencilState(gl, depthStencil?.stencil || defaultDepthStencilState.stencil);
-}
diff --git a/src/runs/runDrawCall.ts b/src/runs/runDrawCall.ts
deleted file mode 100644
index 61b0ab9708ff8a334bb207b0b2af1a93d534ea5e..0000000000000000000000000000000000000000
--- a/src/runs/runDrawCall.ts
+++ /dev/null
@@ -1,115 +0,0 @@
-import { getBufferType } from "../caches/getWebGLBuffer";
-import { ElementTypeMap } from "../const/WebGLUniformType";
-import { IGLDrawArrays } from "../data/IGLDrawArrays";
-import { IGLDrawElements } from "../data/IGLDrawElements";
-import { IGLIndexBuffer } from "../data/IGLIndexBuffer";
-import { IGLDrawMode } from "../data/IGLPrimitiveState";
-import { IGLRenderObject } from "../data/IGLRenderObject";
-import { IGLVertexAttributes } from "../data/IGLVertexAttributes";
-import { defaultPrimitiveState } from "./runPrimitiveState";
-
-export function runDrawCall(gl: WebGLRenderingContext, renderObject: IGLRenderObject)
-{
- const { pipeline, vertexArray, drawElements, drawArrays } = renderObject;
- const { vertices, index } = { ...vertexArray };
-
- const topology = pipeline.primitive?.topology || defaultPrimitiveState.topology;
-
- if (drawArrays)
- {
- _runDrawArrays(gl, topology, vertices, drawArrays);
- }
- else if (drawElements)
- {
- _runDrawElements(gl, topology, index, drawElements);
- }
- else if (index)
- {
- _runDrawElements(gl, topology, index, drawElements);
- }
- else
- {
- _runDrawArrays(gl, topology, vertices, drawArrays);
- }
-}
-
-export const defaultDrawIndexed: IGLDrawElements = Object.freeze({ firstIndex: 0, instanceCount: 1 });
-
-function _runDrawElements(gl: WebGLRenderingContext, drawMode: IGLDrawMode, index: IGLIndexBuffer, drawElements: IGLDrawElements)
-{
- const type = getBufferType(index.data);
- const dataLength = index.data.length;
- //
- let { indexCount, instanceCount, firstIndex } = drawElements || {};
- firstIndex = firstIndex || defaultDrawIndexed.firstIndex;
- instanceCount = instanceCount || defaultDrawIndexed.instanceCount;
- indexCount = indexCount || (dataLength - firstIndex);
-
- //
- if (instanceCount > 1)
- {
- if (gl instanceof WebGL2RenderingContext)
- {
- gl.drawElementsInstanced(gl[drawMode], indexCount, gl[type], firstIndex * ElementTypeMap[type], instanceCount);
- }
- else
- {
- const extension = gl.getExtension("ANGLE_instanced_arrays");
- extension.drawElementsInstancedANGLE(gl[drawMode], indexCount, gl[type], firstIndex * ElementTypeMap[type], instanceCount);
- }
- }
- else
- {
- gl.drawElements(gl[drawMode], indexCount, gl[type], firstIndex * ElementTypeMap[type]);
- }
-}
-
-export const defaultDrawVertex: IGLDrawArrays = Object.freeze({ vertexCount: 6, instanceCount: 1, firstVertex: 0 });
-
-function _runDrawArrays(gl: WebGLRenderingContext, drawMode: IGLDrawMode, vertices: IGLVertexAttributes, drawArrays: IGLDrawArrays)
-{
- //
- let { firstVertex, vertexCount, instanceCount } = drawArrays || {};
- //
- firstVertex = firstVertex || defaultDrawVertex.firstVertex;
- vertexCount = vertexCount || getAttributeVertexNum(vertices) || defaultDrawVertex.vertexCount;
- instanceCount = instanceCount || defaultDrawVertex.instanceCount;
-
- if (instanceCount > 1)
- {
- if (gl instanceof WebGL2RenderingContext)
- {
- gl.drawArraysInstanced(gl[drawMode], firstVertex, vertexCount, instanceCount);
- }
- else
- {
- const extension = gl.getExtension("ANGLE_instanced_arrays");
- extension.drawArraysInstancedANGLE(gl[drawMode], firstVertex, vertexCount, instanceCount);
- }
- }
- else
- {
- gl.drawArrays(gl[drawMode], firstVertex, vertexCount);
- }
-}
-
-/**
- * 获取属性顶点属性。
- */
-export function getAttributeVertexNum(vertices: IGLVertexAttributes)
-{
- const vertexNum = ((vertices) =>
- {
- for (const attr in vertices)
- {
- if (vertices.hasOwnProperty(attr))
- {
- return vertices[attr].buffer.data.length;
- }
- }
-
- return 0;
- })(vertices);
-
- return vertexNum;
-}
\ No newline at end of file
diff --git a/src/runs/runFramebuffer.ts b/src/runs/runFramebuffer.ts
deleted file mode 100644
index 177bc3a302ed5bdae4c578a76e2a1459713eb44d..0000000000000000000000000000000000000000
--- a/src/runs/runFramebuffer.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { getFramebuffer } from "../caches/getFramebuffer";
-import { IGLRenderPassDescriptor } from "../data/IGLPassDescriptor";
-
-/**
- * 运行帧缓冲区
- */
-export function runFramebuffer(gl: WebGLRenderingContext, passDescriptor: IGLRenderPassDescriptor)
-{
- const framebuffer = getFramebuffer(gl, passDescriptor);
- gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
-}
\ No newline at end of file
diff --git a/src/runs/runIndexBuffer.ts b/src/runs/runIndexBuffer.ts
deleted file mode 100644
index b50b9e474029436e50c0155f67b9ebac49fc638e..0000000000000000000000000000000000000000
--- a/src/runs/runIndexBuffer.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { getWebGLBuffer } from "../caches/getWebGLBuffer";
-import { IGLIndexBuffer } from "../data/IGLIndexBuffer";
-
-export function runIndexBuffer(gl: WebGLRenderingContext, index?: IGLIndexBuffer)
-{
- if (index)
- {
- const buffer = getWebGLBuffer(gl, index);
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer);
- }
-}
-
-export const defaultIndexBuffer: IGLIndexBuffer = {
- target: "ELEMENT_ARRAY_BUFFER", usage: "STATIC_DRAW",
- data: new Uint16Array([0, 1, 2, 2, 1, 3])
-};
-Object.freeze(defaultIndexBuffer);
diff --git a/src/runs/runPassDescriptor.ts b/src/runs/runPassDescriptor.ts
deleted file mode 100644
index 1f558bb584f86463e9add6ef9d5083d40aa93111..0000000000000000000000000000000000000000
--- a/src/runs/runPassDescriptor.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { IGLRenderPassColorAttachment } from "../data/IGLRenderPassColorAttachment";
-import { IGLRenderPassDepthStencilAttachment } from "../data/IGLRenderPassDepthStencilAttachment";
-import { IGLRenderPassDescriptor } from "../data/IGLPassDescriptor";
-import { runFramebuffer } from "./runFramebuffer";
-
-export const defaultRenderPassColorAttachment: IGLRenderPassColorAttachment = { clearValue: [0, 0, 0, 0], loadOp: "clear" };
-export const defaultDepthStencilAttachment: IGLRenderPassDepthStencilAttachment = { depthClearValue: 1, depthLoadOp: "load", stencilClearValue: 0, stencilLoadOp: "load" };
-
-export function runPassDescriptor(gl: WebGLRenderingContext, passDescriptor: IGLRenderPassDescriptor)
-{
- passDescriptor = passDescriptor || {};
-
- //
- const colorAttachment = Object.assign({}, defaultRenderPassColorAttachment, passDescriptor.colorAttachments?.[0]);
-
- //
- runFramebuffer(gl, passDescriptor);
-
- //
- const { clearValue, loadOp } = colorAttachment;
- gl.clearColor(clearValue[0], clearValue[1], clearValue[2], clearValue[3]);
-
- //
- const depthStencilAttachment = Object.assign({}, defaultDepthStencilAttachment, passDescriptor.depthStencilAttachment);
- const { depthClearValue, depthLoadOp, stencilClearValue, stencilLoadOp } = depthStencilAttachment;
- gl.clearDepth(depthClearValue);
- gl.clearStencil(stencilClearValue);
-
- //
- gl.clear((loadOp === "clear" ? gl.COLOR_BUFFER_BIT : 0)
- | (depthLoadOp === "clear" ? gl.DEPTH_BUFFER_BIT : 0)
- | (stencilLoadOp === "clear" ? gl.STENCIL_BUFFER_BIT : 0)
- );
-}
diff --git a/src/runs/runPrimitiveState.ts b/src/runs/runPrimitiveState.ts
deleted file mode 100644
index 43de6346f88a33b08034d853d4675243a9eab024..0000000000000000000000000000000000000000
--- a/src/runs/runPrimitiveState.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { IGLCullFace } from "../data/IGLCullFace";
-import { IGLPrimitiveState } from "../data/IGLPrimitiveState";
-
-export function runPrimitiveState(gl: WebGLRenderingContext, cullFace?: IGLCullFace)
-{
- //
- const { enableCullFace: enableCullMode, cullMode, frontFace } = { ...defaultCullFace, ...cullFace };
- if (enableCullMode)
- {
- gl.enable(gl.CULL_FACE);
- gl.cullFace(gl[cullMode]);
- gl.frontFace(gl[frontFace]);
- }
- else
- {
- gl.disable(gl.CULL_FACE);
- }
-}
-
-const defaultCullFace: IGLCullFace = { enableCullFace: false, cullMode: "BACK", frontFace: "CCW" };
-export const defaultPrimitiveState: IGLPrimitiveState = { topology: "TRIANGLES", cullFace: defaultCullFace };
-
-Object.freeze(defaultCullFace);
-Object.freeze(defaultPrimitiveState);
\ No newline at end of file
diff --git a/src/runs/runProgram.ts b/src/runs/runProgram.ts
deleted file mode 100644
index 0c0e9ff8416cc04f1ef15575d1b84e091a57b92f..0000000000000000000000000000000000000000
--- a/src/runs/runProgram.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import { getProgram } from "../caches/getProgram";
-import { IFragmentState, IGLRenderPipeline, IVertexState } from "../data/IGLRenderPipeline";
-import { defaultColorTargetStates, runColorTargetStates } from "./runColorTargetStates";
-
-export function runProgram(gl: WebGLRenderingContext, pipeline: IGLRenderPipeline)
-{
- const program = getProgram(gl, pipeline);
- gl.useProgram(program);
-
- //
- if (gl instanceof WebGL2RenderingContext)
- {
- if (pipeline.rasterizerDiscard)
- {
- gl.enable(gl.RASTERIZER_DISCARD);
- }
- else
- {
- gl.disable(gl.RASTERIZER_DISCARD);
- }
- }
-
- //
- runColorTargetStates(gl, pipeline.fragment.targets);
-}
-
-export const defaultVertexState: IVertexState = Object.freeze({ code: "" });
-export const defaultFragmentState: IFragmentState = Object.freeze({ code: "", targets: defaultColorTargetStates });
\ No newline at end of file
diff --git a/src/runs/runQueryAction.ts b/src/runs/runQueryAction.ts
deleted file mode 100644
index da8693da4a45c023c48d6a243d1def9f81ae4359..0000000000000000000000000000000000000000
--- a/src/runs/runQueryAction.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-import { deleteWebGLQuery, getWebGLQuery } from "../caches/getWebGLQuery";
-import { IGLQuery, IGLQueryAction } from "../data/IGLQueryAction";
-
-export function runQueryAction(gl: WebGLRenderingContext, queryAction: IGLQueryAction)
-{
- if (gl instanceof WebGL2RenderingContext)
- {
- const { action, target, query } = queryAction;
-
- // 该查询对象生命周期已结束,不再进行第二次查询。
- if (query.state === "endQuery") return;
-
- const webGLQuery = getWebGLQuery(gl, query);
- gl[action](gl[target], webGLQuery);
- //
- query.state = action;
- query.target = target;
- }
-}
-
-/**
- * 获取查询结果。
- */
-export async function getQueryResult(gl: WebGLRenderingContext, query: IGLQuery)
-{
- if (query.result !== undefined) return query.result;
-
- if (gl instanceof WebGL2RenderingContext)
- {
- const webGLQuery = getWebGLQuery(gl, query);
- const result: number = await new Promise((resolve, reject) =>
- {
- (function tick()
- {
- if (!gl.getQueryParameter(webGLQuery, gl.QUERY_RESULT_AVAILABLE))
- {
- // A query's result is never available in the same frame
- // the query was issued. Try in the next frame.
- requestAnimationFrame(tick);
-
- return;
- }
-
- query.result = gl.getQueryParameter(webGLQuery, gl.QUERY_RESULT);
-
- resolve(query.result);
-
- deleteWebGLQuery(gl, query);
- })();
- });
-
- return result;
- }
-
- return 0;
-}
\ No newline at end of file
diff --git a/src/runs/runRenderObject.ts b/src/runs/runRenderObject.ts
deleted file mode 100644
index 5eaa8763b251ac39d5e9d6bda166676f8d617d47..0000000000000000000000000000000000000000
--- a/src/runs/runRenderObject.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import { IGLRenderObject } from "../data/IGLRenderObject";
-import { runDrawCall } from "./runDrawCall";
-import { defaultPrimitiveState } from "./runPrimitiveState";
-import { runRenderPipeline } from "./runRenderPipeline";
-import { runScissor } from "./runScissor";
-import { endTransformFeedback, runTransformFeedback } from "./runTransformFeedback";
-import { runUniforms } from "./runUniforms";
-import { runVertexArray } from "./runVertexArray";
-import { runViewPort } from "./runViewPort";
-
-export function runRenderObject(gl: WebGLRenderingContext, renderObject: IGLRenderObject)
-{
- const { viewport, scissor, pipeline, vertexArray, uniforms, transformFeedback } = renderObject;
-
- const topology = pipeline.primitive?.topology || defaultPrimitiveState.topology;
-
- runViewPort(gl, viewport);
-
- runScissor(gl, scissor);
-
- runRenderPipeline(gl, pipeline);
-
- runVertexArray(gl, pipeline, vertexArray);
-
- runUniforms(gl, pipeline, uniforms);
-
- runTransformFeedback(gl, transformFeedback, topology);
-
- runDrawCall(gl, renderObject);
-
- endTransformFeedback(gl, transformFeedback);
-}
diff --git a/src/runs/runRenderPass.ts b/src/runs/runRenderPass.ts
deleted file mode 100644
index 561e295ca9991390e07fbd1d20f68d47c6549c72..0000000000000000000000000000000000000000
--- a/src/runs/runRenderPass.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { IGLRenderPass } from "../data/IGLRenderPass";
-import { runPassDescriptor } from "./runPassDescriptor";
-import { runQueryAction } from "./runQueryAction";
-import { runRenderObject } from "./runRenderObject";
-
-export function runRenderPass(gl: WebGLRenderingContext, renderPass: IGLRenderPass)
-{
- runPassDescriptor(gl, renderPass.descriptor);
-
- renderPass.renderObjects?.forEach((renderObject) =>
- {
- if ("action" in renderObject)
- {
- runQueryAction(gl, renderObject);
- }
- else
- {
- runRenderObject(gl, renderObject);
- }
- });
-}
diff --git a/src/runs/runRenderPipeline.ts b/src/runs/runRenderPipeline.ts
deleted file mode 100644
index 0d09f7786d51802140c01522aa3bf83c156fc2a7..0000000000000000000000000000000000000000
--- a/src/runs/runRenderPipeline.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { IGLRenderPipeline } from "../data/IGLRenderPipeline";
-import { defaultDepthStencilState, runDepthStencilState } from "./runDepthStencilState";
-import { defaultPrimitiveState, runPrimitiveState } from "./runPrimitiveState";
-import { defaultFragmentState, defaultVertexState, runProgram } from "./runProgram";
-
-export function runRenderPipeline(gl: WebGLRenderingContext, renderPipeline: IGLRenderPipeline)
-{
- runProgram(gl, renderPipeline);
-
- runPrimitiveState(gl, renderPipeline?.primitive?.cullFace);
-
- runDepthStencilState(gl, renderPipeline.depthStencil);
-}
-
-export const defaultRenderPipeline: IGLRenderPipeline = Object.freeze({
- vertex: defaultVertexState, fragment: defaultFragmentState, primitive: defaultPrimitiveState,
- depthStencil: defaultDepthStencilState
-});
\ No newline at end of file
diff --git a/src/runs/runSampler.ts b/src/runs/runSampler.ts
deleted file mode 100644
index 786bd4389a1e9edf261ab3a67f42dacd0e517a28..0000000000000000000000000000000000000000
--- a/src/runs/runSampler.ts
+++ /dev/null
@@ -1,78 +0,0 @@
-import { getSampler } from "../caches/getSampler";
-import { IGLSampler, TextureMagFilter, GLTextureMinFilter, GLTextureWrap } from "../data/IGLSampler";
-
-declare global
-{
- interface WebGLTexture
- {
- minFilter?: GLTextureMinFilter,
- magFilter?: TextureMagFilter,
- wrapS?: GLTextureWrap,
- wrapT?: GLTextureWrap,
- wrapR?: GLTextureWrap,
- anisotropy?: number,
- lodMinClamp?: number;
- lodMaxClamp?: number;
- }
-}
-
-export const defaultGLSampler: IGLSampler = {
- minFilter: "LINEAR_MIPMAP_LINEAR", magFilter: "LINEAR",
- wrapS: "REPEAT", wrapT: "REPEAT", wrapR: "REPEAT",
- lodMinClamp: 0, lodMaxClamp: 16,
- compareMode: "NONE",
- compare: "LEQUAL",
- anisotropy: 1,
-};
-
-/**
- * 设置采样参数
- */
-export function runSampler(gl: WebGLRenderingContext, webGLTexture: WebGLTexture, sampler: IGLSampler, textureID: number)
-{
- const textureTarget = webGLTexture.textureTarget;
-
- if (gl instanceof WebGL2RenderingContext)
- {
- const webGLSampler = getSampler(gl, sampler);
- gl.bindSampler(textureID, webGLSampler);
- }
- else
- {
- const { minFilter, magFilter, wrapS, wrapT } = { ...defaultGLSampler, ...sampler };
-
- // 设置纹理参数
- if (webGLTexture.minFilter !== minFilter)
- {
- gl.texParameteri(gl[textureTarget], gl.TEXTURE_MIN_FILTER, gl[minFilter]);
- webGLTexture.minFilter = minFilter;
- }
- if (webGLTexture.magFilter !== magFilter)
- {
- gl.texParameteri(gl[textureTarget], gl.TEXTURE_MAG_FILTER, gl[magFilter]);
- webGLTexture.magFilter = magFilter;
- }
- if (webGLTexture.wrapS !== wrapS)
- {
- gl.texParameteri(gl[textureTarget], gl.TEXTURE_WRAP_S, gl[wrapS]);
- webGLTexture.wrapS = wrapS;
- }
- if (webGLTexture.wrapT !== wrapT)
- {
- gl.texParameteri(gl[textureTarget], gl.TEXTURE_WRAP_T, gl[wrapT]);
- webGLTexture.wrapT = wrapT;
- }
- }
-
- //
- const anisotropy = sampler?.anisotropy || defaultGLSampler.anisotropy;
- if (webGLTexture.anisotropy !== anisotropy)
- {
- const extension = gl.getExtension("EXT_texture_filter_anisotropic");
- if (extension)
- {
- gl.texParameterf(gl[textureTarget], extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min(anisotropy, gl._capabilities.maxAnisotropy));
- }
- webGLTexture.anisotropy = anisotropy;
- }
-}
diff --git a/src/runs/runScissor.ts b/src/runs/runScissor.ts
deleted file mode 100644
index f39703dcb72bae5b6b433298ce2c9de81ee08ebd..0000000000000000000000000000000000000000
--- a/src/runs/runScissor.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { IGLScissor } from "../data/IGLScissor";
-
-export function runScissor(gl: WebGLRenderingContext, scissor?: IGLScissor)
-{
- if (scissor)
- {
- gl.enable(gl.SCISSOR_TEST);
- gl.scissor(scissor.x, scissor.y, scissor.width, scissor.height);
- }
- else
- {
- gl.disable(gl.SCISSOR_TEST);
- }
-}
\ No newline at end of file
diff --git a/src/runs/runStencilState.ts b/src/runs/runStencilState.ts
index a570907611ac2452513311fa85b437bcb43c149b..39ab87965cb566b6e260477ca24593c41e97b17d 100644
--- a/src/runs/runStencilState.ts
+++ b/src/runs/runStencilState.ts
@@ -1,33 +1,36 @@
-import { IStencilFaceState, IGLStencilState } from "../data/IGLDepthStencilState";
+import { ICompareFunction, IDepthStencilState, IStencilOperation } from "@feng3d/render-api";
+import { IGLStencilFunc, IGLStencilOp } from "../data/IGLDepthStencilState";
-const defaultStencilFaceState: IStencilFaceState = { stencilFunc: "ALWAYS", stencilFuncRef: 0, stencilFuncMask: 0b11111111, stencilOpFail: "KEEP", stencilOpZFail: "KEEP", stencilOpZPass: "KEEP", stencilMask: 0b11111111 };
-export const defaultStencilState: IGLStencilState = { useStencil: false, stencilFront: defaultStencilFaceState, stencilBack: defaultStencilFaceState };
+export function getIGLStencilFunc(compare: ICompareFunction)
+{
+ const stencilFunc: IGLStencilFunc = compareMap[compare];
+
+ return stencilFunc;
+}
+const compareMap: { [key: string]: IGLStencilFunc } = {
+ "never": "NEVER",
+ "less": "LESS",
+ "equal": "EQUAL",
+ "less-equal": "LEQUAL",
+ "greater": "GREATER",
+ "not-equal": "NOTEQUAL",
+ "greater-equal": "GEQUAL",
+ "always": "ALWAYS",
+};
-export function runStencilState(gl: WebGLRenderingContext, stencil: IGLStencilState)
+export function getIGLStencilOp(stencilOperation?: IStencilOperation)
{
- //
- const {
- useStencil, stencilFront, stencilBack,
- } = { ...defaultStencilState, ...stencil };
+ const glStencilOp: IGLStencilOp = stencilOperationMap[stencilOperation];
- if (useStencil)
- {
- gl.enable(gl.STENCIL_TEST);
- {
- const { stencilFunc, stencilFuncRef, stencilFuncMask, stencilOpFail, stencilOpZFail, stencilOpZPass, stencilMask } = { ...defaultStencilFaceState, ...stencilFront };
- gl.stencilFuncSeparate(gl.FRONT, gl[stencilFunc], stencilFuncRef, stencilFuncMask);
- gl.stencilOpSeparate(gl.FRONT, gl[stencilOpFail], gl[stencilOpZFail], gl[stencilOpZPass]);
- gl.stencilMaskSeparate(gl.FRONT, stencilMask);
- }
- {
- const { stencilFunc, stencilFuncRef, stencilFuncMask, stencilOpFail, stencilOpZFail, stencilOpZPass, stencilMask } = { ...defaultStencilFaceState, ...stencilBack };
- gl.stencilFuncSeparate(gl.BACK, gl[stencilFunc], stencilFuncRef, stencilFuncMask);
- gl.stencilOpSeparate(gl.BACK, gl[stencilOpFail], gl[stencilOpZFail], gl[stencilOpZPass]);
- gl.stencilMaskSeparate(gl.BACK, stencilMask);
- }
- }
- else
- {
- gl.disable(gl.STENCIL_TEST);
- }
-}
\ No newline at end of file
+ return glStencilOp;
+}
+const stencilOperationMap: { [key: string]: IGLStencilOp } = {
+ "keep": "KEEP",
+ "zero": "ZERO",
+ "replace": "REPLACE",
+ "invert": "INVERT",
+ "increment-clamp": "INCR",
+ "decrement-clamp": "DECR",
+ "increment-wrap": "INCR_WRAP",
+ "decrement-wrap": "DECR_WRAP",
+};
\ No newline at end of file
diff --git a/src/runs/runTexture.ts b/src/runs/runTexture.ts
deleted file mode 100644
index a1b10012cf401a919442277ec6db540a6b83163f..0000000000000000000000000000000000000000
--- a/src/runs/runTexture.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { getTexture } from "../caches/getTexture";
-import { IGLSamplerTexture } from "../data/IGLSamplerTexture";
-import { IGLBufferSource, IGLImageSource, IGLTexture, IGLTextureSource } from "../data/IGLTexture";
-import { IUniformItemInfo } from "../data/IGLUniformInfo";
-import { runSampler } from "./runSampler";
-
-export const defaultImageSource: IGLImageSource = { level: 0, source: new ImageData(1, 1) };
-export const defaultBufferSource: IGLBufferSource = { level: 0, width: 1, height: 1, depth: 1, border: 0 };
-export const defaultTextureSources: IGLTextureSource[] = [defaultBufferSource];
-export const defaultTexture: IGLTexture = { target: "TEXTURE_2D", generateMipmap: false, internalformat: "RGBA", format: "RGBA", type: "UNSIGNED_BYTE" };
-
-Object.freeze(defaultImageSource);
-Object.freeze(defaultBufferSource);
-Object.freeze(defaultTextureSources);
-Object.freeze(defaultTexture);
-
-export function runSamplerTexture(gl: WebGLRenderingContext, uniformInfo: IUniformItemInfo, samplerTexture: IGLSamplerTexture)
-{
- const { texture, sampler } = samplerTexture;
- const { location, textureID } = uniformInfo;
-
- // 设置纹理所在采样编号
- gl.uniform1i(location, textureID);
- //
- const webGLTexture = getTexture(gl, texture);
- gl.activeTexture(gl[`TEXTURE${textureID}`]);
- // 绑定纹理
- gl.bindTexture(gl[webGLTexture.textureTarget], webGLTexture);
-
- // 运行采样器
- runSampler(gl, webGLTexture, sampler, textureID);
-
- return webGLTexture;
-}
diff --git a/src/runs/runTransformFeedback.ts b/src/runs/runTransformFeedback.ts
deleted file mode 100644
index 9b5397219520677b2ef1773177d3fd9c9cf8aead..0000000000000000000000000000000000000000
--- a/src/runs/runTransformFeedback.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import { getWebGLTransformFeedback } from "../caches/getWebGLTransformFeedback";
-import { IGLDrawMode } from "../data/IGLPrimitiveState";
-import { IGLTransformFeedback } from "../data/IGLTransformFeedback";
-
-export function runTransformFeedback(gl: WebGLRenderingContext, transformFeedback: IGLTransformFeedback, topology: IGLDrawMode)
-{
- if (gl instanceof WebGL2RenderingContext)
- {
- if (transformFeedback)
- {
- const webGLTransformFeedback = getWebGLTransformFeedback(gl, transformFeedback);
-
- gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, webGLTransformFeedback);
-
- gl.beginTransformFeedback(gl[topology]);
- }
- else
- {
- gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
- }
- }
- else if (transformFeedback)
- {
- console.log(`WebGL1 不支持顶点着色器回写数据功能!`);
- }
-}
-
-export function endTransformFeedback(gl: WebGLRenderingContext, transformFeedback: IGLTransformFeedback)
-{
- //
- if (transformFeedback)
- {
- if (gl instanceof WebGL2RenderingContext)
- {
- gl.endTransformFeedback();
- gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
- }
- }
-}
diff --git a/src/runs/runUniforms.ts b/src/runs/runUniforms.ts
deleted file mode 100644
index c8852ed14a3aa56dfdd613893cb615f9cb04e311..0000000000000000000000000000000000000000
--- a/src/runs/runUniforms.ts
+++ /dev/null
@@ -1,153 +0,0 @@
-import { getWebGLBuffer } from "../caches/getWebGLBuffer";
-import { getProgram } from "../caches/getProgram";
-import { IGLUniformBufferType } from "../const/WebGLUniformType";
-import { IGLBuffer } from "../data/IGLBuffer";
-import { IGLRenderPipeline } from "../data/IGLRenderPipeline";
-import { IGLSamplerTexture } from "../data/IGLSamplerTexture";
-import { IUniformItemInfo } from "../data/IGLUniformInfo";
-import { IGLUniforms } from "../data/IGLUniforms";
-import { LazyObject, lazy } from "../types";
-import { runSamplerTexture } from "./runTexture";
-
-/**
- * 激活常量
- */
-export function runUniforms(gl: WebGLRenderingContext, pipeline: IGLRenderPipeline, uniforms: LazyObject)
-{
- const webGLProgram = getProgram(gl, pipeline);
-
- webGLProgram.uniforms.forEach((uniformInfo) =>
- {
- const { name, type, items, isTexture, inBlock } = uniformInfo;
- if (inBlock) return;
-
- items.forEach((v) =>
- {
- const { paths } = v;
-
- let uniformData = lazy.getValue(uniforms[paths[0]], uniforms);
- for (let i = 1; i < paths.length; i++)
- {
- uniformData = uniformData[paths[i]];
- }
- if (uniformData === undefined)
- {
- console.error(`沒有找到Uniform ${name} 數據!`);
- }
-
- if (isTexture)
- {
- runSamplerTexture(gl, v, uniformData as IGLSamplerTexture);
- }
- else
- {
- runUniform(gl, type as IGLUniformBufferType, v, uniformData);
- }
- });
- });
-
- if (gl instanceof WebGL2RenderingContext)
- {
- webGLProgram.uniformBlocks.forEach((uniformBlock) =>
- {
- const { name, index } = uniformBlock;
- const uniformData = lazy.getValue(uniforms[name], uniforms);
-
- //
- const webGLBuffer = getWebGLBuffer(gl, uniformData as IGLBuffer);
- gl.bindBufferBase(gl.UNIFORM_BUFFER, index, webGLBuffer);
- });
- }
-}
-
-/**
- * 设置环境Uniform数据
- */
-function runUniform(gl: WebGLRenderingContext, type: IGLUniformBufferType, uniformInfo: IUniformItemInfo, data: any)
-{
- const location = uniformInfo.location;
- switch (type)
- {
- case "BOOL":
- case "INT":
- // gl.uniform1i(location, data);
- gl.uniform1iv(location, [data]);
- break;
- case "BOOL_VEC2":
- case "INT_VEC2":
- // gl.uniform2i(location, data[0], data[1]);
- gl.uniform2iv(location, data);
- break;
- case "BOOL_VEC3":
- case "INT_VEC3":
- // gl.uniform3i(location, data[0], data[1], data[2]);
- gl.uniform3iv(location, data);
- break;
- case "BOOL_VEC4":
- case "INT_VEC4":
- // gl.uniform4i(location, data[0], data[1], data[2], data[3]);
- gl.uniform4iv(location, data);
- break;
- case "FLOAT":
- // gl.uniform1f(location, data);
- gl.uniform1fv(location, [data]);
- break;
- case "FLOAT_VEC2":
- // gl.uniform2f(location, data[0], data[1]);
- gl.uniform2fv(location, data);
- break;
- case "FLOAT_VEC3":
- // gl.uniform3f(location, data[0], data[1], data[2]);
- gl.uniform3fv(location, data);
- break;
- case "FLOAT_VEC4":
- // gl.uniform4f(location, data[0], data[1], data[2], data[3]);
- gl.uniform4fv(location, data);
- break;
- case "FLOAT_MAT2":
- gl.uniformMatrix2fv(location, false, data);
- break;
- case "FLOAT_MAT3":
- gl.uniformMatrix3fv(location, false, data);
- break;
- case "FLOAT_MAT4":
- gl.uniformMatrix4fv(location, false, data);
- break;
- case "UNSIGNED_INT":
- (gl as any as WebGL2RenderingContext).uniform1ui(location, data);
- (gl as any as WebGL2RenderingContext).uniform1uiv(location, [data]);
- break;
- case "UNSIGNED_INT_VEC2":
- // (gl as any as WebGL2RenderingContext).uniform2ui(location, data[0], data[1]);
- (gl as any as WebGL2RenderingContext).uniform2uiv(location, data);
- break;
- case "UNSIGNED_INT_VEC3":
- // (gl as any as WebGL2RenderingContext).uniform3ui(location, data[0], data[1], data[2]);
- (gl as any as WebGL2RenderingContext).uniform3uiv(location, data);
- break;
- case "UNSIGNED_INT_VEC4":
- // (gl as any as WebGL2RenderingContext).uniform4ui(location, data[0], data[1], data[2], data[3]);
- (gl as any as WebGL2RenderingContext).uniform4uiv(location, data);
- break;
- case "FLOAT_MAT2x3":
- (gl as any as WebGL2RenderingContext).uniformMatrix2x3fv(location, false, data);
- break;
- case "FLOAT_MAT2x4":
- (gl as any as WebGL2RenderingContext).uniformMatrix2x4fv(location, false, data);
- break;
- case "FLOAT_MAT3x2":
- (gl as any as WebGL2RenderingContext).uniformMatrix3x2fv(location, false, data);
- break;
- case "FLOAT_MAT3x4":
- (gl as any as WebGL2RenderingContext).uniformMatrix3x4fv(location, false, data);
- break;
- case "FLOAT_MAT4x2":
- (gl as any as WebGL2RenderingContext).uniformMatrix4x2fv(location, false, data);
- break;
- case "FLOAT_MAT4x3":
- (gl as any as WebGL2RenderingContext).uniformMatrix4x3fv(location, false, data);
- break;
- default:
- console.error(`无法识别的uniform类型 ${uniformInfo.paths} ${type}`);
- }
-}
diff --git a/src/runs/runVertexArray.ts b/src/runs/runVertexArray.ts
deleted file mode 100644
index 49e076341f62355bc7a8046f9d7480aad562f572..0000000000000000000000000000000000000000
--- a/src/runs/runVertexArray.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-import { getProgram } from "../caches/getProgram";
-import { IGLRenderPipeline } from "../data/IGLRenderPipeline";
-import { IGLVertexArrayObject } from "../data/IGLVertexArrayObject";
-import { runIndexBuffer } from "./runIndexBuffer";
-import { runVertexAttribute } from "./runVertexAttribute";
-
-declare global
-{
- interface WebGLRenderingContext
- {
- _vertexArrays: Map;
- }
-}
-
-/**
- * 执行设置或者上传渲染对象的顶点以及索引数据。
- */
-export function runVertexArray(gl: WebGLRenderingContext, pipeline: IGLRenderPipeline, vertexArray: IGLVertexArrayObject)
-{
- if (!vertexArray) return;
-
- let webGLVertexArrayObject: WebGLVertexArrayObject;
- if (gl instanceof WebGL2RenderingContext)
- {
- webGLVertexArrayObject = gl._vertexArrays.get(vertexArray);
- if (webGLVertexArrayObject)
- {
- gl.bindVertexArray(webGLVertexArrayObject);
-
- return;
- }
-
- webGLVertexArrayObject = gl.createVertexArray();
- gl.bindVertexArray(webGLVertexArrayObject);
- gl._vertexArrays.set(vertexArray, webGLVertexArrayObject);
- }
-
- //
- const { vertices, index } = vertexArray;
-
- const shaderResult = getProgram(gl, pipeline);
-
- //
- shaderResult.attributes.forEach((activeInfo) =>
- {
- const { name, location } = activeInfo;
- // 处理 WebGL 内置属性 gl_VertexID 等
- if (location < 0) return;
-
- const attribute = vertices[name];
- if (!attribute)
- {
- console.error(`缺少顶点 ${name} 数据!`);
- }
-
- runVertexAttribute(gl, location, attribute);
- });
-
- runIndexBuffer(gl, index);
-}
-
-export function deleteVertexArray(gl: WebGLRenderingContext, vertexArray: IGLVertexArrayObject)
-{
- if (gl instanceof WebGL2RenderingContext)
- {
- const webGLVertexArrayObject = gl._vertexArrays.get(vertexArray);
- gl._vertexArrays.delete(vertexArray);
- gl.deleteVertexArray(webGLVertexArrayObject);
- }
-}
\ No newline at end of file
diff --git a/src/runs/runVertexAttribute.ts b/src/runs/runVertexAttribute.ts
deleted file mode 100644
index 53ee6f061134fc45424c61dd4737129064c5c2cc..0000000000000000000000000000000000000000
--- a/src/runs/runVertexAttribute.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import { getBufferType, getWebGLBuffer } from "../caches/getWebGLBuffer";
-import { IGLVertexAttribute } from "../data/IGLVertexAttribute";
-
-export function runVertexAttribute(gl: WebGLRenderingContext, location: number, attribute: IGLVertexAttribute)
-{
- const { numComponents, normalized, divisor } = attribute;
- let { vertexSize, offset } = attribute;
-
- gl.enableVertexAttribArray(location);
-
- if (divisor !== undefined)
- {
- if (gl instanceof WebGL2RenderingContext)
- {
- gl.vertexAttribDivisor(location, divisor);
- }
- else
- {
- const extension = gl.getExtension("ANGLE_instanced_arrays");
- extension.vertexAttribDivisorANGLE(location, divisor);
- }
- }
-
- //
- const type = attribute.type || getBufferType(attribute.buffer.data) || "FLOAT";
-
- //
- vertexSize = vertexSize || 0;
- offset = offset || 0;
-
- //
- const webGLBuffer = getWebGLBuffer(gl, attribute.buffer);
- gl.bindBuffer(gl.ARRAY_BUFFER, webGLBuffer);
-
- //
- if (gl instanceof WebGL2RenderingContext && (type === "INT" || type === "UNSIGNED_INT"))
- {
- gl.vertexAttribIPointer(location, numComponents, gl[type], vertexSize, offset);
- }
- else
- {
- gl.vertexAttribPointer(location, numComponents, gl[type], normalized, vertexSize, offset);
- }
-}
diff --git a/src/runs/runViewPort.ts b/src/runs/runViewPort.ts
deleted file mode 100644
index 1c1d6f97c9a3ecb325d1af250b7a4988d384452f..0000000000000000000000000000000000000000
--- a/src/runs/runViewPort.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { IGLViewport } from "../data/IGLViewport";
-
-export function runViewPort(gl: WebGLRenderingContext, viewport?: IGLViewport)
-{
- if (viewport)
- {
- gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
- }
- else
- {
- gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
- }
-}
diff --git a/src/shader/ShaderLib.ts b/src/shader/ShaderLib.ts
index 27526d18f501d343afc92f3fa304054bf57b2490..84ba3af9f62fb3b8569d2be0bbc3570cad4fd7bf 100644
--- a/src/shader/ShaderLib.ts
+++ b/src/shader/ShaderLib.ts
@@ -30,7 +30,6 @@ export interface ShaderConfig
/**
* 渲染代码库
-
*/
export class ShaderLib
{
diff --git a/src/types.ts b/src/types.ts
deleted file mode 100644
index e0bde5c160e7a741fee486b3dd6fdc96668ea985..0000000000000000000000000000000000000000
--- a/src/types.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * 构造函数
- *
- * @example
- * ```
- * const Vector2Constructor: Constructor = Vector2;
- * ```
- */
-export type Constructor = (new (...args: any[]) => T);
-
-/**
- * 映射每个属性的类定义
- *
- * @example
- * ```
- * const classmap: ConstructorOf<{ Vector2: Vector2 }> = { Vector2: Vector2 };
- * ```
- */
-export type ConstructorOf = { [P in keyof T]: Constructor; };
-
-/**
- * 让T中以及所有键值中的所有键都是可选的
- */
-export type gPartial = {
- [P in keyof T]?: T[P] | gPartial;
-};
-
-export type Lazy = T | ((...args: any[]) => T);
-
-export type LazyObject = { [P in keyof T]: Lazy; };
-
-export const lazy = {
- getValue(lazyItem: Lazy, ...args: any[]): T
- {
- if (typeof lazyItem === "function")
- {
- // eslint-disable-next-line prefer-spread
- return (lazyItem as Function).apply(undefined, args);
- }
-
- return lazyItem;
- }
-};
diff --git a/src/utils/ChainMap.ts b/src/utils/ChainMap.ts
new file mode 100644
index 0000000000000000000000000000000000000000..14e069d664f642d2d84c2c604fbdb892f2947c59
--- /dev/null
+++ b/src/utils/ChainMap.ts
@@ -0,0 +1,74 @@
+/**
+ * 链式Map。
+ *
+ * 多个key数组对应一个值。
+ *
+ * 由于键值可能是字面值也可能是对象,因此无法使用 {@link WeakMap} 来构建{@link ChainMap},只能使用 {@link Map}。
+ */
+export class ChainMap, V>
+{
+ private _map = new Map();
+
+ /**
+ * 获取键对应的值。
+ *
+ * @param keys 键。
+ * @returns 值。
+ */
+ get(keys: K): V
+ {
+ let map = this._map;
+
+ for (let i = 0, n = keys.length - 1; i < n; i++)
+ {
+ map = map.get(keys[i]);
+
+ if (map === undefined) return undefined;
+ }
+
+ return map.get(keys[keys.length - 1]);
+ }
+
+ /**
+ * 设置映射。
+ *
+ * @param keys 键。
+ * @param value 值。
+ */
+ set(keys: K, value: V)
+ {
+ let map = this._map;
+
+ for (let i = 0; i < keys.length - 1; i++)
+ {
+ const key = keys[i];
+
+ if (map.has(key) === false) map.set(key, new Map());
+
+ map = map.get(key);
+ }
+
+ map.set(keys[keys.length - 1], value);
+ }
+
+ /**
+ * 删除映射。
+ *
+ * @param keys 键。
+ * @returns 如果找到目标值且被删除返回 `true` ,否则返回 `false` 。
+ */
+ delete(keys: K): boolean
+ {
+ let map = this._map;
+
+ for (let i = 0; i < keys.length - 1; i++)
+ {
+ map = map.get(keys[i]);
+
+ if (map === undefined) return false;
+ }
+
+ return map.delete(keys[keys.length - 1]);
+ }
+}
+
diff --git a/src/utils/getGLRenderPassAttachmentSize.ts b/src/utils/getGLRenderPassAttachmentSize.ts
new file mode 100644
index 0000000000000000000000000000000000000000..94e52b1455115af9f933ce255568a0b5022f39eb
--- /dev/null
+++ b/src/utils/getGLRenderPassAttachmentSize.ts
@@ -0,0 +1,45 @@
+import { IRenderPassDescriptor } from "@feng3d/render-api";
+
+/**
+ * 获取渲染通道附件尺寸。
+ *
+ * @param gl
+ * @param descriptor
+ */
+export function getGLRenderPassAttachmentSize(gl: WebGLRenderingContext, descriptor: IRenderPassDescriptor): { readonly width: number; readonly height: number; }
+{
+ if (!descriptor) return { width: gl.drawingBufferWidth, height: gl.drawingBufferHeight };
+
+ const colorAttachments = descriptor.colorAttachments;
+ if (colorAttachments)
+ {
+ for (let i = 0; i < colorAttachments.length; i++)
+ {
+ const view = colorAttachments[i].view;
+ if (view)
+ {
+ return { width: view.texture.size[0], height: view.texture.size[1] };
+ }
+ else
+ {
+ return { width: gl.drawingBufferWidth, height: gl.drawingBufferHeight };
+ }
+ }
+ }
+
+ const depthStencilAttachment = descriptor.depthStencilAttachment;
+ if (depthStencilAttachment)
+ {
+ const view = depthStencilAttachment.view;
+ if (view)
+ {
+ return { width: view.texture.size[0], height: view.texture.size[1] };
+ }
+ else
+ {
+ return { width: gl.drawingBufferWidth, height: gl.drawingBufferHeight };
+ }
+ }
+
+ return { width: gl.drawingBufferWidth, height: gl.drawingBufferHeight };
+}
\ No newline at end of file
diff --git a/src/utils/getIGLCullFace.ts b/src/utils/getIGLCullFace.ts
new file mode 100644
index 0000000000000000000000000000000000000000..eaff6985d8d3a03f6ac4baaa77f0b8498b0aa0c3
--- /dev/null
+++ b/src/utils/getIGLCullFace.ts
@@ -0,0 +1,32 @@
+import { ICullFace } from "@feng3d/render-api";
+
+export function getIGLCullFace(cullFace: ICullFace)
+{
+ const glCullMode: IGLCullFace = cullFaceMap[cullFace];
+
+ console.assert(!!glCullMode, `接收到错误值,请从 ${Object.keys(cullFaceMap).toString()} 中取值!`);
+
+ return glCullMode;
+}
+
+const cullFaceMap: { [key: string]: IGLCullFace } = {
+ "FRONT_AND_BACK": "FRONT_AND_BACK",
+ "none": "BACK", // 不会开启剔除面功能,什么值无所谓。
+ "front": "FRONT",
+ "back": "BACK",
+};
+
+/**
+ * 剔除面,默认 BACK,剔除背面。
+ *
+ * 默认情况下,逆时针的顶点连接顺序被定义为三角形的正面。
+ * 使用gl.frontFace(gl.CW);调整顺时针为正面
+ *
+ * * FRONT 正面
+ * * BACK 背面
+ * * FRONT_AND_BACK 正面与背面
+ *
+ * @see http://www.jianshu.com/p/ee04165f2a02
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/cullFace
+ */
+export type IGLCullFace = "FRONT" | "BACK" | "FRONT_AND_BACK";
\ No newline at end of file
diff --git a/src/utils/getIGLFrontFace.ts b/src/utils/getIGLFrontFace.ts
new file mode 100644
index 0000000000000000000000000000000000000000..144f380449fb05df44ad05e4cdfb49a4cad4c2ea
--- /dev/null
+++ b/src/utils/getIGLFrontFace.ts
@@ -0,0 +1,24 @@
+import { IFrontFace } from "@feng3d/render-api";
+
+export function getIGLFrontFace(frontFace: IFrontFace)
+{
+ const glFrontFace: IGLFrontFace = frontFaceMap[frontFace];
+
+ console.assert(!!glFrontFace, `接收到错误 IFrontFace 值,请从 ${Object.keys(frontFaceMap).toString()} 中取值!`);
+
+ return glFrontFace;
+}
+const frontFaceMap: { [key: string]: IGLFrontFace } = {
+ "ccw": "CCW",
+ "cw": "CW",
+};
+
+/**
+ * 正面方向枚举
+ *
+ * * CW 顺时钟方向
+ * * CCW 逆时钟方向
+ *
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/frontFace
+ */
+export type IGLFrontFace = "CW" | "CCW";
diff --git a/src/data/IGLVertexAttribute.ts b/src/utils/getIVertexFormat.ts
similarity index 31%
rename from src/data/IGLVertexAttribute.ts
rename to src/utils/getIVertexFormat.ts
index d7dbbcf156736a678a57884d67343c828778bd29..1474fa158e9296e92b6fe58d1c5c52e0b5273ce2 100644
--- a/src/data/IGLVertexAttribute.ts
+++ b/src/utils/getIVertexFormat.ts
@@ -1,20 +1,72 @@
-import { IAttributeBufferSourceTypes, IGLBuffer } from "./IGLBuffer";
+import { IVertexFormat } from "@feng3d/render-api";
-/**
- * 顶点属性数据。
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/vertexAttribPointer
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/vertexAttribIPointer
- */
-export interface IGLVertexAttribute
+export function getIVertexFormat(numComponents: 1 | 2 | 3 | 4, type: IGLVertexAttributeTypes = "FLOAT", normalized = false): IVertexFormat
{
- /**
- * WebGL缓冲区
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferData
- */
- buffer: IGLVertexBuffer;
+ for (const key in formatMap)
+ {
+ const element = formatMap[key];
+ if (
+ element.numComponents === numComponents &&
+ element.type === type &&
+ !element.normalized === !normalized
+ )
+ {
+ return key as IVertexFormat;
+ }
+ }
+
+ console.error(`没有找到与 ${JSON.stringify({ numComponents, type, normalized })} 对应的顶点数据格式!`);
+
+ return undefined;
+}
+
+export function getIGLVertexFormat(format: IVertexFormat): IGLVertexFormat
+{
+ const glVertexFormat = formatMap[format];
+
+ console.assert(!!glVertexFormat, `接收到错误值,请从 ${Object.keys(formatMap).toString()} 中取值!`);
+
+ return glVertexFormat;
+}
+
+export const formatMap: { [key: string]: IGLVertexFormat } = {
+
+ "uint8x2": { numComponents: 2, type: "UNSIGNED_BYTE", normalized: false },
+ "uint8x4": { numComponents: 4, type: "UNSIGNED_BYTE", normalized: false },
+ "sint8x2": { numComponents: 2, type: "BYTE", normalized: false },
+ "sint8x4": { numComponents: 4, type: "BYTE", normalized: false },
+ "unorm8x2": { numComponents: 2, type: "UNSIGNED_BYTE", normalized: true },
+ "unorm8x4": { numComponents: 4, type: "UNSIGNED_BYTE", normalized: true },
+ "snorm8x2": { numComponents: 2, type: "BYTE", normalized: true },
+ "snorm8x4": { numComponents: 4, type: "BYTE", normalized: true },
+ "uint16x2": { numComponents: 2, type: "UNSIGNED_SHORT", normalized: false },
+ "uint16x4": { numComponents: 4, type: "UNSIGNED_SHORT", normalized: false },
+ "sint16x2": { numComponents: 2, type: "SHORT", normalized: false },
+ "sint16x4": { numComponents: 4, type: "SHORT", normalized: false },
+ "unorm16x2": { numComponents: 2, type: "UNSIGNED_SHORT", normalized: true },
+ "unorm16x4": { numComponents: 4, type: "UNSIGNED_SHORT", normalized: true },
+ "snorm16x2": { numComponents: 2, type: "SHORT", normalized: true },
+ "snorm16x4": { numComponents: 4, type: "SHORT", normalized: true },
+ "float16x2": { numComponents: 2, type: "HALF_FLOAT", normalized: false },
+ "float16x4": { numComponents: 4, type: "HALF_FLOAT", normalized: false },
+ "float32": { numComponents: 1, type: "FLOAT", normalized: false },
+ "float32x2": { numComponents: 2, type: "FLOAT", normalized: false },
+ "float32x3": { numComponents: 3, type: "FLOAT", normalized: false },
+ "float32x4": { numComponents: 4, type: "FLOAT", normalized: false },
+ "uint32": { numComponents: 1, type: "UNSIGNED_INT", normalized: false },
+ "uint32x2": { numComponents: 2, type: "UNSIGNED_INT", normalized: false },
+ "uint32x3": { numComponents: 3, type: "UNSIGNED_INT", normalized: false },
+ "uint32x4": { numComponents: 4, type: "UNSIGNED_INT", normalized: false },
+ "sint32": { numComponents: 1, type: "INT", normalized: false },
+ "sint32x2": { numComponents: 2, type: "INT", normalized: false },
+ "sint32x3": { numComponents: 3, type: "INT", normalized: false },
+ "sint32x4": { numComponents: 4, type: "INT", normalized: false },
+ "unorm10-10-10-2": { numComponents: 4, type: "UNSIGNED_INT_2_10_10_10_REV", normalized: true },
+};
+
+interface IGLVertexFormat
+{
/**
* 顶点数据元素数量。
*/
@@ -25,40 +77,12 @@ export interface IGLVertexAttribute
*
* 默认从Buffer数据中获取,如果未取到则默认为 "FLOAT" 。
*/
- type?: VertexAttributeTypes;
+ type: IGLVertexAttributeTypes;
/**
* 是否标准化。
*/
- normalized?: boolean;
-
- /**
- * drawElementsInstanced时将会用到的因子,表示divisor个geometry共用一个数据
- *
- * A GLuint specifying the number of instances that will pass between updates of the generic attribute.
- * @see https://developer.mozilla.org/en-US/docs/Web/API/ANGLE_instanced_arrays/vertexAttribDivisorANGLE
- */
- divisor?: number;
-
- /**
- * 所在顶点数据中的偏移字节数。
- */
- offset?: number;
-
- /**
- * 单个顶点数据尺寸。比如单个数据包含position与uv那么值可能为(3+2)*4=20。
- */
- vertexSize?: number;
-}
-
-export interface IGLVertexBuffer extends IGLBuffer
-{
- target: "ARRAY_BUFFER";
-
- /**
- * 缓冲区数据。
- */
- data?: IAttributeBufferSourceTypes;
+ normalized: boolean;
}
/**
@@ -82,7 +106,7 @@ export interface IGLVertexBuffer extends IGLBuffer
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/vertexAttribPointer
*/
-export type VertexAttributeTypes = "FLOAT" | "BYTE" | "SHORT" | "UNSIGNED_BYTE" | "UNSIGNED_SHORT" // WebGL1
+export type IGLVertexAttributeTypes = "FLOAT" | "BYTE" | "SHORT" | "UNSIGNED_BYTE" | "UNSIGNED_SHORT" // WebGL1
| "HALF_FLOAT" | "INT" | "UNSIGNED_INT" | "INT_2_10_10_10_REV" | "UNSIGNED_INT_2_10_10_10_REV"; // WebGL2
/**
@@ -96,4 +120,4 @@ export type VertexAttributeTypes = "FLOAT" | "BYTE" | "SHORT" | "UNSIGNED_BYTE"
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/vertexAttribIPointer
*/
-export type VertexAttributeIntegerTypes = "BYTE" | "UNSIGNED_BYTE" | "SHORT" | "UNSIGNED_SHORT" | "INT" | "UNSIGNED_INT";
+export type IGLVertexAttributeIntegerTypes = "BYTE" | "UNSIGNED_BYTE" | "SHORT" | "UNSIGNED_SHORT" | "INT" | "UNSIGNED_INT";
\ No newline at end of file
diff --git a/src/utils/getTextureCubeMapTarget.ts b/src/utils/getTextureCubeMapTarget.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fbdd30653d4cef5cd743b89c82242b021a2236b5
--- /dev/null
+++ b/src/utils/getTextureCubeMapTarget.ts
@@ -0,0 +1,37 @@
+export function getTextureCubeMapTarget(depthOrArrayLayers: number)
+{
+ const textureCubeMapTarget: IGLTextureCubeMapTarget = textureCubeMapTargetMap[depthOrArrayLayers];
+
+ console.assert(!!textureCubeMapTarget, `CubeMap的depthOrArrayLayers值应在[0-5]之间!`);
+
+ return textureCubeMapTarget;
+}
+
+const textureCubeMapTargetMap: IGLTextureCubeMapTarget[] = [
+ "TEXTURE_CUBE_MAP_POSITIVE_X",
+ "TEXTURE_CUBE_MAP_NEGATIVE_X",
+ "TEXTURE_CUBE_MAP_POSITIVE_Y",
+ "TEXTURE_CUBE_MAP_NEGATIVE_Y",
+ "TEXTURE_CUBE_MAP_POSITIVE_Z",
+ "TEXTURE_CUBE_MAP_NEGATIVE_Z",
+];
+
+/**
+ * A GLenum specifying the texture target.
+ *
+ * gl.TEXTURE_CUBE_MAP_POSITIVE_X: Positive X face for a cube-mapped texture.
+ * gl.TEXTURE_CUBE_MAP_NEGATIVE_X: Negative X face for a cube-mapped texture.
+ * gl.TEXTURE_CUBE_MAP_POSITIVE_Y: Positive Y face for a cube-mapped texture.
+ * gl.TEXTURE_CUBE_MAP_NEGATIVE_Y: Negative Y face for a cube-mapped texture.
+ * gl.TEXTURE_CUBE_MAP_POSITIVE_Z: Positive Z face for a cube-mapped texture.
+ * gl.TEXTURE_CUBE_MAP_NEGATIVE_Z: Negative Z face for a cube-mapped texture.
+ *
+ * https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/texImage2D
+ */
+export type IGLTextureCubeMapTarget =
+ | "TEXTURE_CUBE_MAP_POSITIVE_X"
+ | "TEXTURE_CUBE_MAP_NEGATIVE_X"
+ | "TEXTURE_CUBE_MAP_POSITIVE_Y"
+ | "TEXTURE_CUBE_MAP_NEGATIVE_Y"
+ | "TEXTURE_CUBE_MAP_POSITIVE_Z"
+ | "TEXTURE_CUBE_MAP_NEGATIVE_Z";
diff --git a/src/runs/runReadPixels.ts b/src/utils/readPixels.ts
similarity index 70%
rename from src/runs/runReadPixels.ts
rename to src/utils/readPixels.ts
index 213fab69346d575f18b0f3c2dd2cb6002201efb0..058272dd365a63e4e77ea8b10bd952578495cc25 100644
--- a/src/runs/runReadPixels.ts
+++ b/src/utils/readPixels.ts
@@ -1,13 +1,13 @@
-import { getFramebuffer } from "../caches/getFramebuffer";
+import { getGLFramebuffer } from "../caches/getGLFramebuffer";
import { IGLReadPixels } from "../data/IGLReadPixels";
-export function runReadPixels(gl: WebGLRenderingContext, readPixels: IGLReadPixels)
+export function readPixels(gl: WebGLRenderingContext, readPixels: IGLReadPixels)
{
if (gl instanceof WebGL2RenderingContext)
{
const { frameBuffer, attachmentPoint, x, y, width, height, format, type, dstData, dstOffset } = readPixels;
- const webGLFramebuffer = getFramebuffer(gl, frameBuffer);
+ const webGLFramebuffer = getGLFramebuffer(gl, frameBuffer);
gl.bindFramebuffer(gl.FRAMEBUFFER, webGLFramebuffer);
gl.readBuffer(gl[attachmentPoint]);
@@ -17,4 +17,4 @@ export function runReadPixels(gl: WebGLRenderingContext, readPixels: IGLReadPixe
{
console.error(`WebGL1 不支持 readBuffer/readPixels !`);
}
-}
\ No newline at end of file
+}
diff --git a/src/utils/updateBufferBinding.ts b/src/utils/updateBufferBinding.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f7cb79abdd933d38e56b14e1d98fbde0696aebc3
--- /dev/null
+++ b/src/utils/updateBufferBinding.ts
@@ -0,0 +1,86 @@
+import { IBufferBinding, UnReadonly } from "@feng3d/render-api";
+import { watcher } from "@feng3d/watcher";
+import { IBufferBindingInfo } from "../caches/getGLProgram";
+import { getIGLBuffer } from "../runs/getIGLBuffer";
+
+/**
+ *
+ * @param uniformBlock
+ * @param uniformData
+ *
+ * @see https://learnopengl-cn.readthedocs.io/zh/latest/04%20Advanced%20OpenGL/08%20Advanced%20GLSL/#uniform_1
+ */
+export function updateBufferBinding(bufferBindingInfo: IBufferBindingInfo, uniformData: IBufferBinding)
+{
+ if (uniformData["_bufferBindingInfo"] !== undefined)
+ {
+ const preVariableInfo = uniformData["_bufferBindingInfo"] as any as IBufferBindingInfo;
+ if (preVariableInfo.size !== bufferBindingInfo.size)
+ {
+ console.warn(`updateBufferBinding 出现一份数据对应多个 variableInfo`, { uniformData, bufferBindingInfo, preVariableInfo });
+ }
+
+ return;
+ }
+
+ uniformData["_bufferBindingInfo"] = bufferBindingInfo as any;
+
+ const size = bufferBindingInfo.size;
+ // 是否存在默认值。
+ const hasDefautValue = !!uniformData.bufferView;
+ if (!hasDefautValue)
+ {
+ (uniformData as UnReadonly).bufferView = new Uint8Array(size);
+ }
+ else
+ {
+ console.assert(uniformData.bufferView.byteLength === size, `uniformData.bufferView 统一块数据提供数据尺寸不对!`);
+ }
+
+ //
+ const buffer = getIGLBuffer(uniformData.bufferView);
+ const offset = uniformData.bufferView.byteOffset;
+
+ //
+ bufferBindingInfo.items.forEach((v) =>
+ {
+ const { paths, offset: itemInfoOffset, size: itemInfoSize, Cls } = v;
+ const update = () =>
+ {
+ let value: any = uniformData;
+ for (let i = 0; i < paths.length; i++)
+ {
+ value = value[paths[i]];
+ if (value === undefined)
+ {
+ if (!hasDefautValue)
+ {
+ console.warn(`没有找到 统一块变量属性 ${paths.join(".")} 的值!`);
+ }
+ return;
+ }
+ }
+
+ let data: Float32Array | Int32Array | Uint32Array;
+ if (typeof value === "number")
+ {
+ data = new Cls([value]);
+ }
+ else if (value.constructor.name !== Cls.name)
+ {
+ data = new Cls(value as ArrayLike);
+ }
+ else
+ {
+ data = value as any;
+ }
+
+ const writeBuffers = buffer.writeBuffers ?? [];
+ writeBuffers.push({ data: data.buffer, bufferOffset: offset + itemInfoOffset, size: Math.min(itemInfoSize, data.byteLength) });
+ buffer.writeBuffers = writeBuffers;
+ }
+
+ update();
+ watcher.watchchain(uniformData, paths.join("."), update, undefined, false);
+ });
+}