diff --git a/src/App.tsx b/src/App.tsx
index c8212b77..30e5e23f 100755
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,18 +1,9 @@
import React from 'react';
import './App.css';
import { vec3, vec4 } from "./render/math";
-import {} from "./render/webgl/WebGLTexture";
-// eslint-disable-next-line
-function App() {
-
- let a: vec3 = new vec3([1, 1, 1]);
- let b: vec3 = new vec3([3, 2, 1]);
- let c: vec3 = new vec3([2, 3, 1]);
- let d: vec3 = new vec3([1, 2, 3]);
- let ab: vec3 = vec3.difference(b, a);
+function App() {
- ab.print();
return (
sasa
diff --git a/src/render/math/Util.ts b/src/render/math/Util.ts
new file mode 100755
index 00000000..1f3cd2e6
--- /dev/null
+++ b/src/render/math/Util.ts
@@ -0,0 +1,29 @@
+export class Util {
+ /**
+ * 判断参数x是否是2的n次方,即x是不是1、2、4、8、16、32、64、.....
+ * @param x
+ * @returns
+ */
+ public static isPowerOfTwo(x: number) {
+ return (x & (x - 1)) === 0;
+ }
+
+ /**
+ * 取下一个2的n次方数
+ * 如果x为3,则返回4
+ * 如果x为4,则返回4
+ * 如果x为5,则返回8
+ * @param x
+ * @returns
+ */
+ public static getNextPowerOfTwo(x: number): number {
+ if (x <= 0) {
+ throw new Error("参数必须要大于0!")
+ }
+ --x;
+ for (var i = 1; i < 32; i <<= 1) {
+ x = x | x >> i;
+ }
+ return x + 1;
+ }
+}
\ No newline at end of file
diff --git a/src/render/math/index.ts b/src/render/math/index.ts
index 70ee1c92..3bb2a9ef 100755
--- a/src/render/math/index.ts
+++ b/src/render/math/index.ts
@@ -2,4 +2,5 @@ export * from './Vec2';
export * from './Vec3';
export * from './Vec4';
export * from './Mat4';
-export * from './Quat';
\ No newline at end of file
+export * from './Quat';
+export * from './Util';
\ No newline at end of file
diff --git a/src/render/webgl/WebGLTexture.ts b/src/render/webgl/WebGLTexture.ts
index 10d5d2ff..46677804 100755
--- a/src/render/webgl/WebGLTexture.ts
+++ b/src/render/webgl/WebGLTexture.ts
@@ -1,4 +1,5 @@
import { EGLTexWrapType } from "../common";
+import { Util } from "../math";
import { GLHelper } from "./WebGLHepler";
@@ -14,6 +15,29 @@ export class GLTexture {
public target: number; //gl.TEXTURE_2D
public name: string; //纹理的名称
+ /**
+ * @var
+ */
+ public static readonly Colors: string[] = [
+ 'aqua', //浅绿色
+ 'black', //黑色
+ 'blue', //蓝色
+ 'fuchsia', //紫红色
+ 'gray', //灰色
+ 'green', //绿色
+ 'lime', //绿黄色
+ 'maroon', //褐红色
+ 'navy', //海军蓝
+ 'olive', //橄榄色
+ 'orange', //橙色
+ 'purple', //紫色
+ 'red', //红色
+ 'silver', //银灰色
+ 'teal', //蓝绿色
+ 'yellow', //黄色
+ 'white' //白色
+ ];
+
public constructor(gl: WebGLRenderingContext, name: string = '') {
this.gl = gl;
this.isMipmap = false;
@@ -32,12 +56,91 @@ export class GLTexture {
}
/**
- * 判断是否是2的倍数
- * @param x
+ * 将非2的n次方的srcImage转换成2的n次方的CanvasRenderingContext2D对象
+ * 然后后续用来生成mipmap纹理
+ * @param srcImage
* @returns
*/
- public static isPowerOfTwo(x: number) {
- return (x & (x - 1)) === 0;
+ public static createPowerOfTwoCanvas(srcImage: HTMLImageElement | HTMLCanvasElement): HTMLCanvasElement {
+ let canvas: HTMLCanvasElement = document.createElement("canvas");
+ canvas.width = Util.getNextPowerOfTwo(srcImage.width);
+ canvas.height = Util.getNextPowerOfTwo(srcImage.height);
+
+ let ctx: CanvasRenderingContext2D | null = canvas.getContext("2d");
+ if (ctx === null) {
+ throw new Error("create canvasRenderingContext2D failed!");
+ }
+ ctx.drawImage(srcImage, 0, 0, srcImage.width, srcImage.height, 0, 0, canvas.width, canvas.height);
+ return canvas;
+ }
+
+ /**
+ * 发送纹理到显卡
+ * @param source
+ * @param unit
+ * @param mipmap
+ */
+ public upload(source: HTMLImageElement | HTMLCanvasElement, unit: number = 0, mipmap: boolean = false): void {
+
+ //绑定要操作的texture,默认是0号texture
+ this.bind(unit);
+
+ //翻转texture
+ this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, 1);
+
+ this.width = source.width;
+ this.height = source.height;
+
+ //生成mipmap纹理
+ if (mipmap === true) {
+ let isWidthPowerOfTwo: boolean = Util.isPowerOfTwo(this.width);
+ let isHeightPowerOfTwo: boolean = Util.isPowerOfTwo(this.height);
+ if (isWidthPowerOfTwo === true && isHeightPowerOfTwo === true) {
+ this.gl.texImage2D(this.target, 0, this.format, this.format, this.type, source);
+ this.gl.generateMipmap(this.target);
+ } else {
+ let canvas: HTMLCanvasElement = GLTexture.createPowerOfTwoCanvas(source);
+ this.gl.texImage2D(this.target, 0, this.format, this.format, this.type, canvas);
+ GLHelper.checkGLError(this.gl);
+ this.gl.generateMipmap(this.target);
+ GLHelper.checkGLError(this.gl);
+ this.width = canvas.width;
+ this.height = canvas.height;
+ }
+ this.isMipmap = true;
+ } else {
+ this.isMipmap = false;
+ this.gl.texImage2D(this.target, 0, this.format, this.format, this.type, source);
+ }
+ this.unbind();
+ }
+
+ public static createDefaultTexture(gl: WebGLRenderingContext): GLTexture {
+ let step: number = 4;
+ let canvas: HTMLCanvasElement = document.createElement('canvas') as HTMLCanvasElement;
+ canvas.width = 32 * step;
+ canvas.height = 32 * step;
+
+ let context: CanvasRenderingContext2D | null = canvas.getContext("2d");
+ if (context === null) {
+ alert("离屏Canvas获取渲染上下文失败!")
+ throw new Error("离屏Canvas获取渲染上下文失败!");
+ }
+
+ for (let i: number = 0; i < step; i++) {
+ for (let j: number = 0; j < step; j++) {
+ let idx: number = step * i + j;
+ context.save();
+ context.fillStyle = GLTexture.Colors[idx];
+ context.fillRect(i * 32, j * 32, 32, 32);
+ context.restore();
+ }
+ }
+
+ let tex: GLTexture = new GLTexture(gl);
+ tex.wrap();
+ tex.upload(canvas);
+ return tex;
}
/**
@@ -72,4 +175,31 @@ export class GLTexture {
}
this.gl.texParameteri(this.target, this.gl.TEXTURE_MIN_FILTER, magLinear ? this.gl.LINEAR : this.gl.NEAREST);
}
+
+ /**
+ * 绑定texture
+ * @param uint
+ */
+ public bind(uint: number = 0): void {
+ if (this.texture !== null) {
+ this.gl.activeTexture(this.gl.TEXTURE0 + uint);
+ this.gl.bindTexture(this.target, this.texture);
+ }
+ }
+
+ /**
+ * 解除textture绑定
+ */
+ public unbind(): void {
+ if (this.texture) {
+ this.gl.bindTexture(this.target, null);
+ }
+ }
+
+ /**
+ * 清除纹理
+ */
+ public destory(): void {
+ this.gl.deleteTexture(this.texture);
+ }
}
\ No newline at end of file