mirror of
https://github.com/smallmain/cocos-enhance-kit.git
synced 2025-10-09 21:55:24 +00:00
初始化
This commit is contained in:
1396
engine/cocos2d/renderer/gfx/device.js
Normal file
1396
engine/cocos2d/renderer/gfx/device.js
Normal file
File diff suppressed because it is too large
Load Diff
363
engine/cocos2d/renderer/gfx/enums.js
Normal file
363
engine/cocos2d/renderer/gfx/enums.js
Normal file
@@ -0,0 +1,363 @@
|
||||
const GL_NEAREST = 9728; // gl.NEAREST
|
||||
const GL_LINEAR = 9729; // gl.LINEAR
|
||||
const GL_NEAREST_MIPMAP_NEAREST = 9984; // gl.NEAREST_MIPMAP_NEAREST
|
||||
const GL_LINEAR_MIPMAP_NEAREST = 9985; // gl.LINEAR_MIPMAP_NEAREST
|
||||
const GL_NEAREST_MIPMAP_LINEAR = 9986; // gl.NEAREST_MIPMAP_LINEAR
|
||||
const GL_LINEAR_MIPMAP_LINEAR = 9987; // gl.LINEAR_MIPMAP_LINEAR
|
||||
|
||||
// const GL_BYTE = 5120; // gl.BYTE
|
||||
const GL_UNSIGNED_BYTE = 5121; // gl.UNSIGNED_BYTE
|
||||
// const GL_SHORT = 5122; // gl.SHORT
|
||||
const GL_UNSIGNED_SHORT = 5123; // gl.UNSIGNED_SHORT
|
||||
const GL_UNSIGNED_INT = 5125; // gl.UNSIGNED_INT
|
||||
const GL_FLOAT = 5126; // gl.FLOAT
|
||||
const GL_UNSIGNED_SHORT_5_6_5 = 33635; // gl.UNSIGNED_SHORT_5_6_5
|
||||
const GL_UNSIGNED_SHORT_4_4_4_4 = 32819; // gl.UNSIGNED_SHORT_4_4_4_4
|
||||
const GL_UNSIGNED_SHORT_5_5_5_1 = 32820; // gl.UNSIGNED_SHORT_5_5_5_1
|
||||
const GL_HALF_FLOAT_OES = 36193; // gl.HALF_FLOAT_OES
|
||||
|
||||
const GL_DEPTH_COMPONENT = 6402; // gl.DEPTH_COMPONENT
|
||||
|
||||
const GL_ALPHA = 6406; // gl.ALPHA
|
||||
const GL_RGB = 6407; // gl.RGB
|
||||
const GL_RGBA = 6408; // gl.RGBA
|
||||
const GL_LUMINANCE = 6409; // gl.LUMINANCE
|
||||
const GL_LUMINANCE_ALPHA = 6410; // gl.LUMINANCE_ALPHA
|
||||
|
||||
const GL_COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0; // ext.COMPRESSED_RGB_S3TC_DXT1_EXT
|
||||
const GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1; // ext.COMPRESSED_RGBA_S3TC_DXT1_EXT
|
||||
const GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2; // ext.COMPRESSED_RGBA_S3TC_DXT3_EXT
|
||||
const GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3; // ext.COMPRESSED_RGBA_S3TC_DXT5_EXT
|
||||
|
||||
const GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00; // ext.COMPRESSED_RGB_PVRTC_4BPPV1_IMG
|
||||
const GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01; // ext.COMPRESSED_RGB_PVRTC_2BPPV1_IMG
|
||||
const GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02; // ext.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
|
||||
const GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03; // ext.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
|
||||
|
||||
const GL_COMPRESSED_RGB_ETC1_WEBGL = 0x8D64; // ext.COMPRESSED_RGB_ETC1_WEBGL
|
||||
|
||||
const GL_COMPRESSED_RGB8_ETC2 = 0x9274; // ext.COMPRESSED_RGB8_ETC2
|
||||
const GL_COMPRESSED_RGBA8_ETC2_EAC = 0x9278; // ext.COMPRESSED_RGBA8_ETC2_EAC
|
||||
|
||||
const _filterGL = [
|
||||
[ GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR ],
|
||||
[ GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR ],
|
||||
];
|
||||
|
||||
const _textureFmtGL = [
|
||||
// TEXTURE_FMT_RGB_DXT1: 0
|
||||
{ format: GL_RGB, internalFormat: GL_COMPRESSED_RGB_S3TC_DXT1_EXT, pixelType: null },
|
||||
|
||||
// TEXTURE_FMT_RGBA_DXT1: 1
|
||||
{ format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixelType: null },
|
||||
|
||||
// TEXTURE_FMT_RGBA_DXT3: 2
|
||||
{ format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, pixelType: null },
|
||||
|
||||
// TEXTURE_FMT_RGBA_DXT5: 3
|
||||
{ format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, pixelType: null },
|
||||
|
||||
// TEXTURE_FMT_RGB_ETC1: 4
|
||||
{ format: GL_RGB, internalFormat: GL_COMPRESSED_RGB_ETC1_WEBGL, pixelType: null },
|
||||
|
||||
// TEXTURE_FMT_RGB_PVRTC_2BPPV1: 5
|
||||
{ format: GL_RGB, internalFormat: GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, pixelType: null },
|
||||
|
||||
// TEXTURE_FMT_RGBA_PVRTC_2BPPV1: 6
|
||||
{ format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, pixelType: null },
|
||||
|
||||
// TEXTURE_FMT_RGB_PVRTC_4BPPV1: 7
|
||||
{ format: GL_RGB, internalFormat: GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, pixelType: null },
|
||||
|
||||
// TEXTURE_FMT_RGBA_PVRTC_4BPPV1: 8
|
||||
{ format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, pixelType: null },
|
||||
|
||||
// TEXTURE_FMT_A8: 9
|
||||
{ format: GL_ALPHA, internalFormat: GL_ALPHA, pixelType: GL_UNSIGNED_BYTE },
|
||||
|
||||
// TEXTURE_FMT_L8: 10
|
||||
{ format: GL_LUMINANCE, internalFormat: GL_LUMINANCE, pixelType: GL_UNSIGNED_BYTE },
|
||||
|
||||
// TEXTURE_FMT_L8_A8: 11
|
||||
{ format: GL_LUMINANCE_ALPHA, internalFormat: GL_LUMINANCE_ALPHA, pixelType: GL_UNSIGNED_BYTE },
|
||||
|
||||
// TEXTURE_FMT_R5_G6_B5: 12
|
||||
{ format: GL_RGB, internalFormat: GL_RGB, pixelType: GL_UNSIGNED_SHORT_5_6_5 },
|
||||
|
||||
// TEXTURE_FMT_R5_G5_B5_A1: 13
|
||||
{ format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_UNSIGNED_SHORT_5_5_5_1 },
|
||||
|
||||
// TEXTURE_FMT_R4_G4_B4_A4: 14
|
||||
{ format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_UNSIGNED_SHORT_4_4_4_4 },
|
||||
|
||||
// TEXTURE_FMT_RGB8: 15
|
||||
{ format: GL_RGB, internalFormat: GL_RGB, pixelType: GL_UNSIGNED_BYTE },
|
||||
|
||||
// TEXTURE_FMT_RGBA8: 16
|
||||
{ format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_UNSIGNED_BYTE },
|
||||
|
||||
// TEXTURE_FMT_RGB16F: 17
|
||||
{ format: GL_RGB, internalFormat: GL_RGB, pixelType: GL_HALF_FLOAT_OES },
|
||||
|
||||
// TEXTURE_FMT_RGBA16F: 18
|
||||
{ format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_HALF_FLOAT_OES },
|
||||
|
||||
// TEXTURE_FMT_RGB32F: 19
|
||||
{ format: GL_RGB, internalFormat: GL_RGB, pixelType: GL_FLOAT },
|
||||
|
||||
// TEXTURE_FMT_RGBA32F: 20
|
||||
{ format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_FLOAT },
|
||||
|
||||
// TEXTURE_FMT_R32F: 21
|
||||
{ format: null, internalFormat: null, pixelType: null },
|
||||
|
||||
// TEXTURE_FMT_111110F: 22
|
||||
{ format: null, internalFormat: null, pixelType: null },
|
||||
|
||||
// TEXTURE_FMT_SRGB: 23
|
||||
{ format: null, internalFormat: null, pixelType: null },
|
||||
|
||||
// TEXTURE_FMT_SRGBA: 24
|
||||
{ format: null, internalFormat: null, pixelType: null },
|
||||
|
||||
// TEXTURE_FMT_D16: 25
|
||||
{ format: GL_DEPTH_COMPONENT, internalFormat: GL_DEPTH_COMPONENT, pixelType: GL_UNSIGNED_SHORT },
|
||||
|
||||
// TEXTURE_FMT_D32: 26
|
||||
{ format: GL_DEPTH_COMPONENT, internalFormat: GL_DEPTH_COMPONENT, pixelType: GL_UNSIGNED_INT },
|
||||
|
||||
// TEXTURE_FMT_D24S8: 27
|
||||
{ format: GL_DEPTH_COMPONENT, internalFormat: GL_DEPTH_COMPONENT, pixelType: GL_UNSIGNED_INT },
|
||||
|
||||
// TEXTURE_FMT_RGB_ETC2: 28
|
||||
{ format: GL_RGB, internalFormat: GL_COMPRESSED_RGB8_ETC2, pixelType: null },
|
||||
|
||||
// TEXTURE_FMT_RGBA_ETC2: 29
|
||||
{ format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA8_ETC2_EAC, pixelType: null },
|
||||
];
|
||||
|
||||
/**
|
||||
* enums
|
||||
*/
|
||||
export const enums = {
|
||||
// buffer usage
|
||||
USAGE_STATIC: 35044, // gl.STATIC_DRAW
|
||||
USAGE_DYNAMIC: 35048, // gl.DYNAMIC_DRAW
|
||||
USAGE_STREAM: 35040, // gl.STREAM_DRAW
|
||||
|
||||
// index buffer format
|
||||
INDEX_FMT_UINT8: 5121, // gl.UNSIGNED_BYTE
|
||||
INDEX_FMT_UINT16: 5123, // gl.UNSIGNED_SHORT
|
||||
INDEX_FMT_UINT32: 5125, // gl.UNSIGNED_INT (OES_element_index_uint)
|
||||
|
||||
// vertex attribute semantic
|
||||
ATTR_POSITION: 'a_position',
|
||||
ATTR_NORMAL: 'a_normal',
|
||||
ATTR_TANGENT: 'a_tangent',
|
||||
ATTR_BITANGENT: 'a_bitangent',
|
||||
ATTR_WEIGHTS: 'a_weights',
|
||||
ATTR_JOINTS: 'a_joints',
|
||||
ATTR_COLOR: 'a_color',
|
||||
ATTR_COLOR0: 'a_color0',
|
||||
ATTR_COLOR1: 'a_color1',
|
||||
ATTR_UV: 'a_uv',
|
||||
ATTR_UV0: 'a_uv0',
|
||||
ATTR_UV1: 'a_uv1',
|
||||
ATTR_UV2: 'a_uv2',
|
||||
ATTR_UV3: 'a_uv3',
|
||||
ATTR_UV4: 'a_uv4',
|
||||
ATTR_UV5: 'a_uv5',
|
||||
ATTR_UV6: 'a_uv6',
|
||||
ATTR_UV7: 'a_uv7',
|
||||
ATTR_TEX_COORD: 'a_texCoord',
|
||||
ATTR_TEX_COORD1: 'a_texCoord1',
|
||||
ATTR_TEX_COORD2: 'a_texCoord2',
|
||||
ATTR_TEX_COORD3: 'a_texCoord3',
|
||||
ATTR_TEX_COORD4: 'a_texCoord4',
|
||||
ATTR_TEX_COORD5: 'a_texCoord5',
|
||||
ATTR_TEX_COORD6: 'a_texCoord6',
|
||||
ATTR_TEX_COORD7: 'a_texCoord7',
|
||||
ATTR_TEX_COORD8: 'a_texCoord8',
|
||||
|
||||
|
||||
// vertex attribute type
|
||||
ATTR_TYPE_INT8: 5120, // gl.BYTE
|
||||
ATTR_TYPE_UINT8: 5121, // gl.UNSIGNED_BYTE
|
||||
ATTR_TYPE_INT16: 5122, // gl.SHORT
|
||||
ATTR_TYPE_UINT16: 5123, // gl.UNSIGNED_SHORT
|
||||
ATTR_TYPE_INT32: 5124, // gl.INT
|
||||
ATTR_TYPE_UINT32: 5125, // gl.UNSIGNED_INT
|
||||
ATTR_TYPE_FLOAT32: 5126, // gl.FLOAT
|
||||
|
||||
// texture filter
|
||||
FILTER_NEAREST: 0,
|
||||
FILTER_LINEAR: 1,
|
||||
|
||||
// texture wrap mode
|
||||
WRAP_REPEAT: 10497, // gl.REPEAT
|
||||
WRAP_CLAMP: 33071, // gl.CLAMP_TO_EDGE
|
||||
WRAP_MIRROR: 33648, // gl.MIRRORED_REPEAT
|
||||
|
||||
// texture format
|
||||
// compress formats
|
||||
TEXTURE_FMT_RGB_DXT1: 0,
|
||||
TEXTURE_FMT_RGBA_DXT1: 1,
|
||||
TEXTURE_FMT_RGBA_DXT3: 2,
|
||||
TEXTURE_FMT_RGBA_DXT5: 3,
|
||||
TEXTURE_FMT_RGB_ETC1: 4,
|
||||
TEXTURE_FMT_RGB_PVRTC_2BPPV1: 5,
|
||||
TEXTURE_FMT_RGBA_PVRTC_2BPPV1: 6,
|
||||
TEXTURE_FMT_RGB_PVRTC_4BPPV1: 7,
|
||||
TEXTURE_FMT_RGBA_PVRTC_4BPPV1: 8,
|
||||
|
||||
// normal formats
|
||||
TEXTURE_FMT_A8: 9,
|
||||
TEXTURE_FMT_L8: 10,
|
||||
TEXTURE_FMT_L8_A8: 11,
|
||||
TEXTURE_FMT_R5_G6_B5: 12,
|
||||
TEXTURE_FMT_R5_G5_B5_A1: 13,
|
||||
TEXTURE_FMT_R4_G4_B4_A4: 14,
|
||||
TEXTURE_FMT_RGB8: 15,
|
||||
TEXTURE_FMT_RGBA8: 16,
|
||||
TEXTURE_FMT_RGB16F: 17,
|
||||
TEXTURE_FMT_RGBA16F: 18,
|
||||
TEXTURE_FMT_RGB32F: 19,
|
||||
TEXTURE_FMT_RGBA32F: 20,
|
||||
TEXTURE_FMT_R32F: 21,
|
||||
TEXTURE_FMT_111110F: 22,
|
||||
TEXTURE_FMT_SRGB: 23,
|
||||
TEXTURE_FMT_SRGBA: 24,
|
||||
|
||||
// depth formats
|
||||
TEXTURE_FMT_D16: 25,
|
||||
TEXTURE_FMT_D32: 26,
|
||||
TEXTURE_FMT_D24S8: 27,
|
||||
|
||||
// etc2 format
|
||||
TEXTURE_FMT_RGB_ETC2: 28,
|
||||
TEXTURE_FMT_RGBA_ETC2: 29,
|
||||
|
||||
// depth and stencil function
|
||||
DS_FUNC_NEVER: 512, // gl.NEVER
|
||||
DS_FUNC_LESS: 513, // gl.LESS
|
||||
DS_FUNC_EQUAL: 514, // gl.EQUAL
|
||||
DS_FUNC_LEQUAL: 515, // gl.LEQUAL
|
||||
DS_FUNC_GREATER: 516, // gl.GREATER
|
||||
DS_FUNC_NOTEQUAL: 517, // gl.NOTEQUAL
|
||||
DS_FUNC_GEQUAL: 518, // gl.GEQUAL
|
||||
DS_FUNC_ALWAYS: 519, // gl.ALWAYS
|
||||
|
||||
// render-buffer format
|
||||
RB_FMT_RGBA4: 32854, // gl.RGBA4
|
||||
RB_FMT_RGB5_A1: 32855, // gl.RGB5_A1
|
||||
RB_FMT_RGB565: 36194, // gl.RGB565
|
||||
RB_FMT_D16: 33189, // gl.DEPTH_COMPONENT16
|
||||
RB_FMT_S8: 36168, // gl.STENCIL_INDEX8
|
||||
RB_FMT_D24S8: 34041, // gl.DEPTH_STENCIL
|
||||
|
||||
// blend-equation
|
||||
BLEND_FUNC_ADD: 32774, // gl.FUNC_ADD
|
||||
BLEND_FUNC_SUBTRACT: 32778, // gl.FUNC_SUBTRACT
|
||||
BLEND_FUNC_REVERSE_SUBTRACT: 32779, // gl.FUNC_REVERSE_SUBTRACT
|
||||
|
||||
// blend
|
||||
BLEND_ZERO: 0, // gl.ZERO
|
||||
BLEND_ONE: 1, // gl.ONE
|
||||
BLEND_SRC_COLOR: 768, // gl.SRC_COLOR
|
||||
BLEND_ONE_MINUS_SRC_COLOR: 769, // gl.ONE_MINUS_SRC_COLOR
|
||||
BLEND_DST_COLOR: 774, // gl.DST_COLOR
|
||||
BLEND_ONE_MINUS_DST_COLOR: 775, // gl.ONE_MINUS_DST_COLOR
|
||||
BLEND_SRC_ALPHA: 770, // gl.SRC_ALPHA
|
||||
BLEND_ONE_MINUS_SRC_ALPHA: 771, // gl.ONE_MINUS_SRC_ALPHA
|
||||
BLEND_DST_ALPHA: 772, // gl.DST_ALPHA
|
||||
BLEND_ONE_MINUS_DST_ALPHA: 773, // gl.ONE_MINUS_DST_ALPHA
|
||||
BLEND_CONSTANT_COLOR: 32769, // gl.CONSTANT_COLOR
|
||||
BLEND_ONE_MINUS_CONSTANT_COLOR: 32770, // gl.ONE_MINUS_CONSTANT_COLOR
|
||||
BLEND_CONSTANT_ALPHA: 32771, // gl.CONSTANT_ALPHA
|
||||
BLEND_ONE_MINUS_CONSTANT_ALPHA: 32772, // gl.ONE_MINUS_CONSTANT_ALPHA
|
||||
BLEND_SRC_ALPHA_SATURATE: 776, // gl.SRC_ALPHA_SATURATE
|
||||
|
||||
// stencil operation
|
||||
STENCIL_DISABLE: 0, // disable stencil
|
||||
STENCIL_ENABLE: 1, // enable stencil
|
||||
STENCIL_INHERIT: 2, // inherit stencil states
|
||||
|
||||
STENCIL_OP_KEEP: 7680, // gl.KEEP
|
||||
STENCIL_OP_ZERO: 0, // gl.ZERO
|
||||
STENCIL_OP_REPLACE: 7681, // gl.REPLACE
|
||||
STENCIL_OP_INCR: 7682, // gl.INCR
|
||||
STENCIL_OP_INCR_WRAP: 34055, // gl.INCR_WRAP
|
||||
STENCIL_OP_DECR: 7683, // gl.DECR
|
||||
STENCIL_OP_DECR_WRAP: 34056, // gl.DECR_WRAP
|
||||
STENCIL_OP_INVERT: 5386, // gl.INVERT
|
||||
|
||||
// cull
|
||||
CULL_NONE: 0,
|
||||
CULL_FRONT: 1028,
|
||||
CULL_BACK: 1029,
|
||||
CULL_FRONT_AND_BACK: 1032,
|
||||
|
||||
// primitive type
|
||||
PT_POINTS: 0, // gl.POINTS
|
||||
PT_LINES: 1, // gl.LINES
|
||||
PT_LINE_LOOP: 2, // gl.LINE_LOOP
|
||||
PT_LINE_STRIP: 3, // gl.LINE_STRIP
|
||||
PT_TRIANGLES: 4, // gl.TRIANGLES
|
||||
PT_TRIANGLE_STRIP: 5, // gl.TRIANGLE_STRIP
|
||||
PT_TRIANGLE_FAN: 6, // gl.TRIANGLE_FAN
|
||||
};
|
||||
|
||||
/**
|
||||
* @method attrTypeBytes
|
||||
* @param {ATTR_TYPE_*} attrType
|
||||
*/
|
||||
export function attrTypeBytes(attrType) {
|
||||
if (attrType === enums.ATTR_TYPE_INT8) {
|
||||
return 1;
|
||||
} else if (attrType === enums.ATTR_TYPE_UINT8) {
|
||||
return 1;
|
||||
} else if (attrType === enums.ATTR_TYPE_INT16) {
|
||||
return 2;
|
||||
} else if (attrType === enums.ATTR_TYPE_UINT16) {
|
||||
return 2;
|
||||
} else if (attrType === enums.ATTR_TYPE_INT32) {
|
||||
return 4;
|
||||
} else if (attrType === enums.ATTR_TYPE_UINT32) {
|
||||
return 4;
|
||||
} else if (attrType === enums.ATTR_TYPE_FLOAT32) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
console.warn(`Unknown ATTR_TYPE: ${attrType}`);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @method glFilter
|
||||
* @param {WebGLContext} gl
|
||||
* @param {FILTER_*} filter
|
||||
* @param {FILTER_*} mipFilter
|
||||
*/
|
||||
export function glFilter(gl, filter, mipFilter = -1) {
|
||||
let result = _filterGL[filter][mipFilter+1];
|
||||
if (result === undefined) {
|
||||
console.warn(`Unknown FILTER: ${filter}`);
|
||||
return mipFilter === -1 ? gl.LINEAR : gl.LINEAR_MIPMAP_LINEAR;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @method glTextureFmt
|
||||
* @param {TEXTURE_FMT_*} fmt
|
||||
*/
|
||||
export function glTextureFmt(fmt) {
|
||||
let result = _textureFmtGL[fmt];
|
||||
if (result === undefined) {
|
||||
console.warn(`Unknown TEXTURE_FMT: ${fmt}`);
|
||||
return _textureFmtGL[enums.TEXTURE_FMT_RGBA8];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
45
engine/cocos2d/renderer/gfx/frame-buffer.js
Normal file
45
engine/cocos2d/renderer/gfx/frame-buffer.js
Normal file
@@ -0,0 +1,45 @@
|
||||
export default class FrameBuffer {
|
||||
/**
|
||||
* @constructor
|
||||
* @param {Device} device
|
||||
* @param {Number} width
|
||||
* @param {Number} height
|
||||
* @param {Object} options
|
||||
* @param {Array} options.colors
|
||||
* @param {RenderBuffer|Texture2D|TextureCube} options.depth
|
||||
* @param {RenderBuffer|Texture2D|TextureCube} options.stencil
|
||||
* @param {RenderBuffer|Texture2D|TextureCube} options.depthStencil
|
||||
*/
|
||||
constructor(device, width, height, options) {
|
||||
this._device = device;
|
||||
this._width = width;
|
||||
this._height = height;
|
||||
|
||||
this._colors = options.colors || [];
|
||||
this._depth = options.depth || null;
|
||||
this._stencil = options.stencil || null;
|
||||
this._depthStencil = options.depthStencil || null;
|
||||
|
||||
this._glID = device._gl.createFramebuffer();
|
||||
}
|
||||
|
||||
/**
|
||||
* @method destroy
|
||||
*/
|
||||
destroy() {
|
||||
if (this._glID === null) {
|
||||
console.error('The frame-buffer already destroyed');
|
||||
return;
|
||||
}
|
||||
|
||||
const gl = this._device._gl;
|
||||
|
||||
gl.deleteFramebuffer(this._glID);
|
||||
|
||||
this._glID = null;
|
||||
}
|
||||
|
||||
getHandle() {
|
||||
return this._glID;
|
||||
}
|
||||
}
|
104
engine/cocos2d/renderer/gfx/index-buffer.js
Normal file
104
engine/cocos2d/renderer/gfx/index-buffer.js
Normal file
@@ -0,0 +1,104 @@
|
||||
import { enums } from './enums';
|
||||
|
||||
const BYTES_PER_INDEX = {
|
||||
[enums.INDEX_FMT_UINT8]: 1,
|
||||
[enums.INDEX_FMT_UINT16]: 2,
|
||||
[enums.INDEX_FMT_UINT32]: 4,
|
||||
}
|
||||
|
||||
class IndexBuffer {
|
||||
/**
|
||||
* @constructor
|
||||
* @param {Device} device
|
||||
* @param {INDEX_FMT_*} format
|
||||
* @param {USAGE_*} usage
|
||||
* @param {ArrayBuffer | Uint8Array} data
|
||||
*/
|
||||
constructor(device, format, usage, data) {
|
||||
this._device = device;
|
||||
this._format = format;
|
||||
this._usage = usage;
|
||||
this._bytesPerIndex = BYTES_PER_INDEX[format];
|
||||
this._bytes = data.byteLength;
|
||||
this._numIndices = this._bytes / this._bytesPerIndex;
|
||||
|
||||
this._needExpandDataStore = true;
|
||||
|
||||
// update
|
||||
this._glID = device._gl.createBuffer();
|
||||
this.update(0, data);
|
||||
|
||||
// stats
|
||||
device._stats.ib += this._bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @method destroy
|
||||
*/
|
||||
destroy() {
|
||||
if (this._glID === -1) {
|
||||
console.error('The buffer already destroyed');
|
||||
return;
|
||||
}
|
||||
|
||||
let gl = this._device._gl;
|
||||
gl.deleteBuffer(this._glID);
|
||||
this._device._stats.ib -= this.bytes;
|
||||
|
||||
this._glID = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @method update
|
||||
* @param {Number} byteOffset
|
||||
* @param {ArrayBuffer} data
|
||||
*/
|
||||
update(byteOffset, data) {
|
||||
if (this._glID === -1) {
|
||||
console.error('The buffer is destroyed');
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.byteLength === 0) return;
|
||||
|
||||
// Need to create new buffer object when bytes exceed
|
||||
if (byteOffset + data.byteLength > this._bytes) {
|
||||
if (byteOffset) {
|
||||
// Lost data between [0, byteOffset] which is need for new buffer
|
||||
console.error('Failed to update data, bytes exceed.');
|
||||
return;
|
||||
}
|
||||
else {
|
||||
this._needExpandDataStore = true;
|
||||
this._bytes = byteOffset + data.byteLength;
|
||||
this._numIndices = this._bytes / this._bytesPerIndex;
|
||||
}
|
||||
}
|
||||
|
||||
/** @type{WebGLRenderingContext} */
|
||||
let gl = this._device._gl;
|
||||
let glUsage = this._usage;
|
||||
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._glID);
|
||||
if (this._needExpandDataStore) {
|
||||
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, data, glUsage);
|
||||
this._needExpandDataStore = false;
|
||||
}
|
||||
else {
|
||||
gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, byteOffset, data);
|
||||
}
|
||||
this._device._restoreIndexBuffer();
|
||||
}
|
||||
|
||||
get count () {
|
||||
return this._numIndices;
|
||||
}
|
||||
|
||||
setUsage (usage) {
|
||||
this._usage = usage;
|
||||
}
|
||||
}
|
||||
|
||||
IndexBuffer.BYTES_PER_INDEX = BYTES_PER_INDEX;
|
||||
|
||||
export default IndexBuffer;
|
46
engine/cocos2d/renderer/gfx/index.js
Normal file
46
engine/cocos2d/renderer/gfx/index.js
Normal file
@@ -0,0 +1,46 @@
|
||||
import {
|
||||
enums,
|
||||
attrTypeBytes,
|
||||
glFilter,
|
||||
glTextureFmt,
|
||||
} from './enums';
|
||||
|
||||
let gfx = null;
|
||||
|
||||
if (CC_JSB && CC_NATIVERENDERER) {
|
||||
gfx = window.gfx;
|
||||
} else {
|
||||
let VertexFormat = require('./vertex-format');
|
||||
let IndexBuffer = require('./index-buffer');
|
||||
let VertexBuffer = require('./vertex-buffer');
|
||||
let Program = require('./program');
|
||||
let Texture = require('./texture');
|
||||
let Texture2D = require('./texture-2d');
|
||||
let TextureCube = require('./texture-cube');
|
||||
let RenderBuffer = require('./render-buffer');
|
||||
let FrameBuffer = require('./frame-buffer');
|
||||
let Device = require('./device');
|
||||
|
||||
gfx = {
|
||||
// classes
|
||||
VertexFormat,
|
||||
IndexBuffer,
|
||||
VertexBuffer,
|
||||
Program,
|
||||
Texture,
|
||||
Texture2D,
|
||||
TextureCube,
|
||||
RenderBuffer,
|
||||
FrameBuffer,
|
||||
Device,
|
||||
|
||||
// functions
|
||||
attrTypeBytes,
|
||||
glFilter,
|
||||
glTextureFmt,
|
||||
};
|
||||
Object.assign(gfx, enums);
|
||||
}
|
||||
|
||||
export default gfx;
|
||||
cc.gfx = gfx;
|
3
engine/cocos2d/renderer/gfx/misc.js
Normal file
3
engine/cocos2d/renderer/gfx/misc.js
Normal file
@@ -0,0 +1,3 @@
|
||||
export function isPow2(v) {
|
||||
return !(v & (v - 1)) && (!!v);
|
||||
}
|
172
engine/cocos2d/renderer/gfx/program.js
Normal file
172
engine/cocos2d/renderer/gfx/program.js
Normal file
@@ -0,0 +1,172 @@
|
||||
let _genID = 0;
|
||||
|
||||
function _parseError(out, type, errorLog) {
|
||||
if(!errorLog){
|
||||
return;
|
||||
}
|
||||
errorLog.split('\n').forEach(msg => {
|
||||
if (msg.length < 5) {
|
||||
return;
|
||||
}
|
||||
|
||||
let parts = /^ERROR:\s+(\d+):(\d+):\s*(.*)$/.exec(msg);
|
||||
if (parts) {
|
||||
out.push({
|
||||
type: type,
|
||||
fileID: parts[1] | 0,
|
||||
line: parts[2] | 0,
|
||||
message: parts[3].trim()
|
||||
})
|
||||
} else if (msg.length > 0) {
|
||||
out.push({
|
||||
type: type,
|
||||
fileID: -1,
|
||||
line: 0,
|
||||
message: msg
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default class Program {
|
||||
/**
|
||||
* @param {ef.GraphicsDevice} device - graphic device
|
||||
* @param {object} options - shader definition
|
||||
* @param {string} options.vert - vertex shader source code
|
||||
* @param {string} options.frag - fragment shader shader source code
|
||||
* @example
|
||||
* let prog = new Program(device, {
|
||||
* vert: `
|
||||
* attribute vec3 a_position;
|
||||
* void main() {
|
||||
* gl_Position = vec4( a_position, 1.0 );
|
||||
* }
|
||||
* `,
|
||||
* frag: `
|
||||
* precision mediump float;
|
||||
* void main() {
|
||||
* gl_FragColor = vec4( 1.0, 1.0, 1.0, 1.0 );
|
||||
* }
|
||||
* `
|
||||
* });
|
||||
*/
|
||||
constructor(device, options) {
|
||||
this._device = device;
|
||||
|
||||
// stores gl information: { location, type }
|
||||
this._attributes = [];
|
||||
this._uniforms = [];
|
||||
this._samplers = [];
|
||||
this._errors = [];
|
||||
this._linked = false;
|
||||
this._vertSource = options.vert;
|
||||
this._fragSource = options.frag;
|
||||
this._glID = null;
|
||||
this._id = _genID++;
|
||||
}
|
||||
|
||||
get id() {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
link() {
|
||||
if (this._linked) {
|
||||
return;
|
||||
}
|
||||
|
||||
let gl = this._device._gl;
|
||||
|
||||
let vertShader = _createShader(gl, gl.VERTEX_SHADER, this._vertSource);
|
||||
let fragShader = _createShader(gl, gl.FRAGMENT_SHADER, this._fragSource);
|
||||
|
||||
let program = gl.createProgram();
|
||||
gl.attachShader(program, vertShader);
|
||||
gl.attachShader(program, fragShader);
|
||||
gl.linkProgram(program);
|
||||
|
||||
let failed = false;
|
||||
let errors = this._errors;
|
||||
|
||||
if (!gl.getShaderParameter(vertShader, gl.COMPILE_STATUS)) {
|
||||
_parseError(errors, 'vs', gl.getShaderInfoLog(vertShader));
|
||||
failed = true;
|
||||
}
|
||||
|
||||
if (!gl.getShaderParameter(fragShader, gl.COMPILE_STATUS)) {
|
||||
_parseError(errors, 'fs', gl.getShaderInfoLog(fragShader));
|
||||
failed = true;
|
||||
}
|
||||
|
||||
gl.deleteShader(vertShader);
|
||||
gl.deleteShader(fragShader);
|
||||
|
||||
if (failed) {
|
||||
return errors;
|
||||
}
|
||||
|
||||
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
||||
errors.push({info: `Failed to link shader program: ${gl.getProgramInfoLog(program)}`});
|
||||
return errors;
|
||||
}
|
||||
|
||||
this._glID = program;
|
||||
|
||||
// parse attribute
|
||||
let numAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
|
||||
for (let i = 0; i < numAttributes; ++i) {
|
||||
let info = gl.getActiveAttrib(program, i);
|
||||
let location = gl.getAttribLocation(program, info.name);
|
||||
|
||||
this._attributes.push({
|
||||
name: info.name,
|
||||
location: location,
|
||||
type: info.type,
|
||||
});
|
||||
}
|
||||
|
||||
// parse uniform
|
||||
let numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
|
||||
for (let i = 0; i < numUniforms; ++i) {
|
||||
let info = gl.getActiveUniform(program, i);
|
||||
let name = info.name;
|
||||
let location = gl.getUniformLocation(program, name);
|
||||
let isArray = name.substr(name.length - 3) === '[0]';
|
||||
if (isArray) {
|
||||
name = name.substr(0, name.length - 3);
|
||||
}
|
||||
|
||||
let uniform = {
|
||||
name: name,
|
||||
location: location,
|
||||
type: info.type,
|
||||
size: isArray ? info.size : undefined, // used when uniform is an array
|
||||
};
|
||||
this._uniforms.push(uniform);
|
||||
}
|
||||
|
||||
this._linked = true;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
let gl = this._device._gl;
|
||||
gl.deleteProgram(this._glID);
|
||||
|
||||
this._linked = false;
|
||||
this._glID = null;
|
||||
this._attributes = [];
|
||||
this._uniforms = [];
|
||||
this._samplers = [];
|
||||
}
|
||||
}
|
||||
|
||||
// ====================
|
||||
// internal
|
||||
// ====================
|
||||
|
||||
function _createShader(gl, type, src) {
|
||||
let shader = gl.createShader(type);
|
||||
gl.shaderSource(shader, src);
|
||||
gl.compileShader(shader);
|
||||
|
||||
return shader;
|
||||
}
|
43
engine/cocos2d/renderer/gfx/render-buffer.js
Normal file
43
engine/cocos2d/renderer/gfx/render-buffer.js
Normal file
@@ -0,0 +1,43 @@
|
||||
export default class RenderBuffer {
|
||||
/**
|
||||
* @constructor
|
||||
* @param {Device} device
|
||||
* @param {RB_FMT_*} format
|
||||
* @param {Number} width
|
||||
* @param {Number} height
|
||||
*/
|
||||
constructor(device, format, width, height) {
|
||||
this._device = device;
|
||||
this._format = format;
|
||||
|
||||
this._glID = device._gl.createRenderbuffer();
|
||||
this.update(width, height);
|
||||
}
|
||||
|
||||
update (width, height) {
|
||||
this._width = width;
|
||||
this._height = height;
|
||||
|
||||
const gl = this._device._gl;
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, this._glID);
|
||||
gl.renderbufferStorage(gl.RENDERBUFFER, this._format, width, height);
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @method destroy
|
||||
*/
|
||||
destroy() {
|
||||
if (this._glID === null) {
|
||||
console.error('The render-buffer already destroyed');
|
||||
return;
|
||||
}
|
||||
|
||||
const gl = this._device._gl;
|
||||
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
|
||||
gl.deleteRenderbuffer(this._glID);
|
||||
|
||||
this._glID = null;
|
||||
}
|
||||
}
|
133
engine/cocos2d/renderer/gfx/state.js
Normal file
133
engine/cocos2d/renderer/gfx/state.js
Normal file
@@ -0,0 +1,133 @@
|
||||
import { enums } from './enums';
|
||||
|
||||
const _default = {
|
||||
// blend
|
||||
blend: false,
|
||||
blendSep: false,
|
||||
blendColor: 0xffffffff,
|
||||
blendEq: enums.BLEND_FUNC_ADD,
|
||||
blendAlphaEq: enums.BLEND_FUNC_ADD,
|
||||
blendSrc: enums.BLEND_ONE,
|
||||
blendDst: enums.BLEND_ZERO,
|
||||
blendSrcAlpha: enums.BLEND_ONE,
|
||||
blendDstAlpha: enums.BLEND_ZERO,
|
||||
|
||||
// depth
|
||||
depthTest: false,
|
||||
depthWrite: false,
|
||||
depthFunc: enums.DS_FUNC_LESS,
|
||||
|
||||
// stencil
|
||||
stencilTest: false,
|
||||
stencilSep: false,
|
||||
stencilFuncFront: enums.DS_FUNC_ALWAYS,
|
||||
stencilRefFront: 0,
|
||||
stencilMaskFront: 0xff,
|
||||
stencilFailOpFront: enums.STENCIL_OP_KEEP,
|
||||
stencilZFailOpFront: enums.STENCIL_OP_KEEP,
|
||||
stencilZPassOpFront: enums.STENCIL_OP_KEEP,
|
||||
stencilWriteMaskFront: 0xff,
|
||||
stencilFuncBack: enums.DS_FUNC_ALWAYS,
|
||||
stencilRefBack: 0,
|
||||
stencilMaskBack: 0xff,
|
||||
stencilFailOpBack: enums.STENCIL_OP_KEEP,
|
||||
stencilZFailOpBack: enums.STENCIL_OP_KEEP,
|
||||
stencilZPassOpBack: enums.STENCIL_OP_KEEP,
|
||||
stencilWriteMaskBack: 0xff,
|
||||
|
||||
// cull-mode
|
||||
cullMode: enums.CULL_BACK,
|
||||
|
||||
// primitive-type
|
||||
primitiveType: enums.PT_TRIANGLES,
|
||||
|
||||
// bindings
|
||||
maxStream: -1,
|
||||
vertexBuffers: [],
|
||||
vertexBufferOffsets: [],
|
||||
indexBuffer: null,
|
||||
maxTextureSlot: -1,
|
||||
textureUnits: [],
|
||||
program: null,
|
||||
};
|
||||
|
||||
export default class State {
|
||||
constructor(device) {
|
||||
// bindings
|
||||
this.vertexBuffers = new Array(device._caps.maxVertexStreams);
|
||||
this.vertexBufferOffsets = new Array(device._caps.maxVertexStreams);
|
||||
this.textureUnits = new Array(device._caps.maxTextureUnits);
|
||||
|
||||
this.set(_default);
|
||||
}
|
||||
|
||||
static initDefault(device) {
|
||||
_default.vertexBuffers = new Array(device._caps.maxVertexStreams);
|
||||
_default.vertexBufferOffsets = new Array(device._caps.maxVertexStreams);
|
||||
_default.textureUnits = new Array(device._caps.maxTextureUnits);
|
||||
}
|
||||
|
||||
reset () {
|
||||
this.set(_default);
|
||||
}
|
||||
|
||||
set (cpy) {
|
||||
// blending
|
||||
this.blend = cpy.blend;
|
||||
this.blendSep = cpy.blendSep;
|
||||
this.blendColor = cpy.blendColor;
|
||||
this.blendEq = cpy.blendEq;
|
||||
this.blendAlphaEq = cpy.blendAlphaEq;
|
||||
this.blendSrc = cpy.blendSrc;
|
||||
this.blendDst = cpy.blendDst;
|
||||
this.blendSrcAlpha = cpy.blendSrcAlpha;
|
||||
this.blendDstAlpha = cpy.blendDstAlpha;
|
||||
|
||||
// depth
|
||||
this.depthTest = cpy.depthTest;
|
||||
this.depthWrite = cpy.depthWrite;
|
||||
this.depthFunc = cpy.depthFunc;
|
||||
|
||||
// stencil
|
||||
this.stencilTest = cpy.stencilTest;
|
||||
this.stencilSep = cpy.stencilSep;
|
||||
this.stencilFuncFront = cpy.stencilFuncFront;
|
||||
this.stencilRefFront = cpy.stencilRefFront;
|
||||
this.stencilMaskFront = cpy.stencilMaskFront;
|
||||
this.stencilFailOpFront = cpy.stencilFailOpFront;
|
||||
this.stencilZFailOpFront = cpy.stencilZFailOpFront;
|
||||
this.stencilZPassOpFront = cpy.stencilZPassOpFront;
|
||||
this.stencilWriteMaskFront = cpy.stencilWriteMaskFront;
|
||||
this.stencilFuncBack = cpy.stencilFuncBack;
|
||||
this.stencilRefBack = cpy.stencilRefBack;
|
||||
this.stencilMaskBack = cpy.stencilMaskBack;
|
||||
this.stencilFailOpBack = cpy.stencilFailOpBack;
|
||||
this.stencilZFailOpBack = cpy.stencilZFailOpBack;
|
||||
this.stencilZPassOpBack = cpy.stencilZPassOpBack;
|
||||
this.stencilWriteMaskBack = cpy.stencilWriteMaskBack;
|
||||
|
||||
// cull-mode
|
||||
this.cullMode = cpy.cullMode;
|
||||
|
||||
// primitive-type
|
||||
this.primitiveType = cpy.primitiveType;
|
||||
|
||||
// buffer bindings
|
||||
this.maxStream = cpy.maxStream;
|
||||
for (let i = 0; i < cpy.vertexBuffers.length; ++i) {
|
||||
this.vertexBuffers[i] = cpy.vertexBuffers[i];
|
||||
}
|
||||
for (let i = 0; i < cpy.vertexBufferOffsets.length; ++i) {
|
||||
this.vertexBufferOffsets[i] = cpy.vertexBufferOffsets[i];
|
||||
}
|
||||
this.indexBuffer = cpy.indexBuffer;
|
||||
|
||||
// texture bindings
|
||||
this.maxTextureSlot = cpy.maxTextureSlot;
|
||||
for (let i = 0; i < cpy.textureUnits.length; ++i) {
|
||||
this.textureUnits[i] = cpy.textureUnits[i];
|
||||
}
|
||||
|
||||
this.program = cpy.program;
|
||||
}
|
||||
}
|
330
engine/cocos2d/renderer/gfx/texture-2d.js
Normal file
330
engine/cocos2d/renderer/gfx/texture-2d.js
Normal file
@@ -0,0 +1,330 @@
|
||||
// @ts-check
|
||||
import Texture from './texture';
|
||||
import { enums, glFilter, glTextureFmt } from './enums';
|
||||
import { isPow2 } from './misc';
|
||||
|
||||
/**
|
||||
* @typedef {HTMLImageElement | HTMLCanvasElement} HTMLImageSource
|
||||
* @typedef {HTMLImageSource | ArrayBufferView} ImageSource
|
||||
* @typedef {{width?: number, height?: number, minFilter?: number, magFilter?: number, mipFilter?: number, wrapS?: number, wrapT?: number, format?: number, genMipmaps?: boolean, images?: ImageSource[], image?: ImageSource, flipY?: boolean, premultiplyAlpha?: boolean, anisotropy?: number}} TextureUpdateOpts
|
||||
* @typedef {import("../gfx/device").default} Device
|
||||
*/
|
||||
|
||||
export default class Texture2D extends Texture {
|
||||
/**
|
||||
* @constructor
|
||||
* @param {Device} device
|
||||
* @param {TextureUpdateOpts} options
|
||||
*/
|
||||
constructor(device, options) {
|
||||
super(device);
|
||||
|
||||
let gl = this._device._gl;
|
||||
this._target = gl.TEXTURE_2D;
|
||||
this._glID = gl.createTexture();
|
||||
|
||||
// always alloc texture in GPU when we create it.
|
||||
options.images = options.images || [null];
|
||||
this.update(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @method update
|
||||
* @param {TextureUpdateOpts} options
|
||||
*/
|
||||
update(options) {
|
||||
let gl = this._device._gl;
|
||||
let genMipmaps = this._genMipmap;
|
||||
|
||||
if (options) {
|
||||
if (options.width !== undefined) {
|
||||
this._width = options.width;
|
||||
}
|
||||
if (options.height !== undefined) {
|
||||
this._height = options.height;
|
||||
}
|
||||
if (options.anisotropy !== undefined) {
|
||||
this._anisotropy = options.anisotropy;
|
||||
}
|
||||
if (options.minFilter !== undefined) {
|
||||
this._minFilter = options.minFilter;
|
||||
}
|
||||
if (options.magFilter !== undefined) {
|
||||
this._magFilter = options.magFilter;
|
||||
}
|
||||
if (options.mipFilter !== undefined) {
|
||||
this._mipFilter = options.mipFilter;
|
||||
}
|
||||
if (options.wrapS !== undefined) {
|
||||
this._wrapS = options.wrapS;
|
||||
}
|
||||
if (options.wrapT !== undefined) {
|
||||
this._wrapT = options.wrapT;
|
||||
}
|
||||
if (options.format !== undefined) {
|
||||
this._format = options.format;
|
||||
this._compressed =
|
||||
(this._format >= enums.TEXTURE_FMT_RGB_DXT1 && this._format <= enums.TEXTURE_FMT_RGBA_PVRTC_4BPPV1) ||
|
||||
(this._format >= enums.TEXTURE_FMT_RGB_ETC2 && this._format <= enums.TEXTURE_FMT_RGBA_ETC2)
|
||||
;
|
||||
}
|
||||
|
||||
// check if generate mipmap
|
||||
if (options.genMipmaps !== undefined) {
|
||||
this._genMipmap = options.genMipmaps;
|
||||
genMipmaps = options.genMipmaps;
|
||||
}
|
||||
|
||||
let maxSize = this._device.caps.maxTextureSize || Number.MAX_VALUE;
|
||||
let textureMaxSize = Math.max(options.width || 0, options.height || 0);
|
||||
if (maxSize < textureMaxSize)
|
||||
console.warn(`The current texture size ${textureMaxSize} exceeds the maximum size [${maxSize}] supported on the device.`);
|
||||
|
||||
if (options.images !== undefined) {
|
||||
if (options.images.length > 1) {
|
||||
genMipmaps = false;
|
||||
let maxLength = options.width > options.height ? options.width : options.height;
|
||||
if (maxLength >> (options.images.length - 1) !== 1) {
|
||||
console.error('texture-2d mipmap is invalid, should have a 1x1 mipmap.');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: get pot after this._width, this._height has been assigned.
|
||||
let pot = isPow2(this._width) && isPow2(this._height);
|
||||
if (!pot) {
|
||||
genMipmaps = false;
|
||||
}
|
||||
|
||||
gl.activeTexture(gl.TEXTURE0);
|
||||
gl.bindTexture(gl.TEXTURE_2D, this._glID);
|
||||
if (options.images !== undefined && options.images.length > 0) {
|
||||
this._setMipmap(options.images, options.flipY, options.premultiplyAlpha);
|
||||
if (options.images.length > 1) this._genMipmap = true;
|
||||
}
|
||||
if (genMipmaps) {
|
||||
gl.hint(gl.GENERATE_MIPMAP_HINT, gl.NICEST);
|
||||
gl.generateMipmap(gl.TEXTURE_2D);
|
||||
this._genMipmap = true;
|
||||
}
|
||||
|
||||
this._setTexInfo();
|
||||
this._device._restoreTexture(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @method updateSubImage
|
||||
* @param {Object} options
|
||||
* @param {Number} options.x
|
||||
* @param {Number} options.y
|
||||
* @param {Number} options.width
|
||||
* @param {Number} options.height
|
||||
* @param {Number} options.level
|
||||
* @param {HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | ArrayBufferView} options.image
|
||||
* @param {Boolean} options.flipY
|
||||
* @param {Boolean} options.premultiplyAlpha
|
||||
*/
|
||||
updateSubImage(options) {
|
||||
let gl = this._device._gl;
|
||||
let glFmt = glTextureFmt(this._format);
|
||||
|
||||
gl.activeTexture(gl.TEXTURE0);
|
||||
gl.bindTexture(gl.TEXTURE_2D, this._glID);
|
||||
this._setSubImage(glFmt, options);
|
||||
this._device._restoreTexture(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @method updateImage
|
||||
* @param {Object} options
|
||||
* @param {Number} options.width
|
||||
* @param {Number} options.height
|
||||
* @param {Number} options.level
|
||||
* @param {HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | ArrayBufferView} options.image
|
||||
* @param {Boolean} options.flipY
|
||||
* @param {Boolean} options.premultiplyAlpha
|
||||
*/
|
||||
updateImage(options) {
|
||||
let gl = this._device._gl;
|
||||
let glFmt = glTextureFmt(this._format);
|
||||
|
||||
gl.activeTexture(gl.TEXTURE0);
|
||||
gl.bindTexture(gl.TEXTURE_2D, this._glID);
|
||||
this._setImage(glFmt, options);
|
||||
this._device._restoreTexture(0);
|
||||
}
|
||||
|
||||
_setSubImage(glFmt, options) {
|
||||
let gl = this._device._gl;
|
||||
let flipY = options.flipY;
|
||||
let premultiplyAlpha = options.premultiplyAlpha;
|
||||
let img = options.image;
|
||||
|
||||
if (img && !ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) {
|
||||
if (flipY === undefined) {
|
||||
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
|
||||
} else {
|
||||
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
|
||||
}
|
||||
|
||||
if (premultiplyAlpha === undefined) {
|
||||
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
|
||||
} else {
|
||||
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha);
|
||||
}
|
||||
|
||||
gl.texSubImage2D(gl.TEXTURE_2D, options.level, options.x, options.y, glFmt.format, glFmt.pixelType, img);
|
||||
} else {
|
||||
if (flipY === undefined) {
|
||||
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
|
||||
} else {
|
||||
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
|
||||
}
|
||||
|
||||
if (premultiplyAlpha === undefined) {
|
||||
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
|
||||
} else {
|
||||
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha);
|
||||
}
|
||||
|
||||
if (this._compressed) {
|
||||
gl.compressedTexSubImage2D(gl.TEXTURE_2D,
|
||||
options.level,
|
||||
options.x,
|
||||
options.y,
|
||||
options.width,
|
||||
options.height,
|
||||
glFmt.format,
|
||||
img
|
||||
);
|
||||
} else {
|
||||
gl.texSubImage2D(
|
||||
gl.TEXTURE_2D,
|
||||
options.level,
|
||||
options.x,
|
||||
options.y,
|
||||
options.width,
|
||||
options.height,
|
||||
glFmt.format,
|
||||
glFmt.pixelType,
|
||||
img
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_setImage(glFmt, options) {
|
||||
let gl = this._device._gl;
|
||||
let flipY = options.flipY;
|
||||
let premultiplyAlpha = options.premultiplyAlpha;
|
||||
let img = options.image;
|
||||
|
||||
if (img && !ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) {
|
||||
if (flipY === undefined) {
|
||||
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
|
||||
} else {
|
||||
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
|
||||
}
|
||||
|
||||
if (premultiplyAlpha === undefined) {
|
||||
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
|
||||
} else {
|
||||
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha);
|
||||
}
|
||||
|
||||
gl.texImage2D(
|
||||
gl.TEXTURE_2D,
|
||||
options.level,
|
||||
glFmt.internalFormat,
|
||||
glFmt.format,
|
||||
glFmt.pixelType,
|
||||
img
|
||||
);
|
||||
} else {
|
||||
if (flipY === undefined) {
|
||||
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
|
||||
} else {
|
||||
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
|
||||
}
|
||||
|
||||
if (premultiplyAlpha === undefined) {
|
||||
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
|
||||
} else {
|
||||
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha);
|
||||
}
|
||||
|
||||
if (this._compressed) {
|
||||
gl.compressedTexImage2D(
|
||||
gl.TEXTURE_2D,
|
||||
options.level,
|
||||
glFmt.internalFormat,
|
||||
options.width,
|
||||
options.height,
|
||||
0,
|
||||
img
|
||||
);
|
||||
} else {
|
||||
gl.texImage2D(
|
||||
gl.TEXTURE_2D,
|
||||
options.level,
|
||||
glFmt.internalFormat,
|
||||
options.width,
|
||||
options.height,
|
||||
0,
|
||||
glFmt.format,
|
||||
glFmt.pixelType,
|
||||
img
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_setMipmap(images, flipY, premultiplyAlpha) {
|
||||
let glFmt = glTextureFmt(this._format);
|
||||
let options = {
|
||||
width: this._width,
|
||||
height: this._height,
|
||||
flipY: flipY,
|
||||
premultiplyAlpha: premultiplyAlpha,
|
||||
level: 0,
|
||||
image: null
|
||||
};
|
||||
|
||||
for (let i = 0; i < images.length; ++i) {
|
||||
options.level = i;
|
||||
options.width = this._width >> i;
|
||||
options.height = this._height >> i;
|
||||
options.image = images[i];
|
||||
this._setImage(glFmt, options);
|
||||
}
|
||||
}
|
||||
|
||||
_setTexInfo() {
|
||||
let gl = this._device._gl;
|
||||
let pot = isPow2(this._width) && isPow2(this._height);
|
||||
|
||||
// WebGL1 doesn't support all wrap modes with NPOT textures
|
||||
if (!pot && (this._wrapS !== enums.WRAP_CLAMP || this._wrapT !== enums.WRAP_CLAMP)) {
|
||||
console.warn('WebGL1 doesn\'t support all wrap modes with NPOT textures');
|
||||
this._wrapS = enums.WRAP_CLAMP;
|
||||
this._wrapT = enums.WRAP_CLAMP;
|
||||
}
|
||||
|
||||
let mipFilter = this._genMipmap ? this._mipFilter : -1;
|
||||
if (!pot && mipFilter !== -1) {
|
||||
console.warn('NPOT textures do not support mipmap filter');
|
||||
mipFilter = -1;
|
||||
}
|
||||
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, glFilter(gl, this._minFilter, mipFilter));
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, glFilter(gl, this._magFilter, -1));
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this._wrapS);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this._wrapT);
|
||||
|
||||
let ext = this._device.ext('EXT_texture_filter_anisotropic');
|
||||
if (ext) {
|
||||
gl.texParameteri(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY_EXT, this._anisotropy);
|
||||
}
|
||||
}
|
||||
}
|
338
engine/cocos2d/renderer/gfx/texture-cube.js
Normal file
338
engine/cocos2d/renderer/gfx/texture-cube.js
Normal file
@@ -0,0 +1,338 @@
|
||||
import Texture from './texture';
|
||||
import { enums, glFilter, glTextureFmt } from './enums';
|
||||
import { isPow2 } from './misc';
|
||||
|
||||
export default class TextureCube extends Texture {
|
||||
/**
|
||||
* @constructor
|
||||
* @param {Device} device
|
||||
* @param {Object} options
|
||||
* @param {Array} options.images
|
||||
* @param {Boolean} options.genMipmaps
|
||||
* @param {Number} options.width
|
||||
* @param {Number} options.height
|
||||
* @param {TEXTURE_FMT_*} options.format
|
||||
* @param {Number} options.anisotropy
|
||||
* @param {FILTER_*} options.minFilter
|
||||
* @param {FILTER_*} options.magFilter
|
||||
* @param {FILTER_*} options.mipFilter
|
||||
* @param {WRAP_*} options.wrapS
|
||||
* @param {WRAP_*} options.wrapT
|
||||
* @param {WRAP_*} options.wrapR
|
||||
* @param {Boolean} options.flipY
|
||||
* @param {Boolean} options.premultiplyAlpha
|
||||
*/
|
||||
constructor(device, options) {
|
||||
super(device);
|
||||
let gl = this._device._gl;
|
||||
this._target = gl.TEXTURE_CUBE_MAP;
|
||||
this._glID = gl.createTexture();
|
||||
this.update(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @method update
|
||||
* @param {Object} options
|
||||
* @param {Array} options.images
|
||||
* @param {Boolean} options.genMipmaps
|
||||
* @param {Number} options.width
|
||||
* @param {Number} options.height
|
||||
* @param {TEXTURE_FMT_*} options.format
|
||||
* @param {Number} options.anisotropy
|
||||
* @param {FILTER_*} options.minFilter
|
||||
* @param {FILTER_*} options.magFilter
|
||||
* @param {FILTER_*} options.mipFilter
|
||||
* @param {WRAP_*} options.wrapS
|
||||
* @param {WRAP_*} options.wrapT
|
||||
* @param {WRAP_*} options.wrapR
|
||||
* @param {Boolean} options.flipY
|
||||
* @param {Boolean} options.premultiplyAlpha
|
||||
*/
|
||||
update(options) {
|
||||
let gl = this._device._gl;
|
||||
let genMipmaps = this._genMipmaps;
|
||||
|
||||
if (options) {
|
||||
if (options.width !== undefined) {
|
||||
this._width = options.width;
|
||||
}
|
||||
if (options.height !== undefined) {
|
||||
this._height = options.height;
|
||||
}
|
||||
if (options.anisotropy !== undefined) {
|
||||
this._anisotropy = options.anisotropy;
|
||||
}
|
||||
if (options.minFilter !== undefined) {
|
||||
this._minFilter = options.minFilter;
|
||||
}
|
||||
if (options.magFilter !== undefined) {
|
||||
this._magFilter = options.magFilter;
|
||||
}
|
||||
if (options.mipFilter !== undefined) {
|
||||
this._mipFilter = options.mipFilter;
|
||||
}
|
||||
if (options.wrapS !== undefined) {
|
||||
this._wrapS = options.wrapS;
|
||||
}
|
||||
if (options.wrapT !== undefined) {
|
||||
this._wrapT = options.wrapT;
|
||||
}
|
||||
// wrapR available in webgl2
|
||||
// if (options.wrapR !== undefined) {
|
||||
// this._wrapR = options.wrapR;
|
||||
// }
|
||||
if (options.format !== undefined) {
|
||||
this._format = options.format;
|
||||
this._compressed =
|
||||
(this._format >= enums.TEXTURE_FMT_RGB_DXT1 && this._format <= enums.TEXTURE_FMT_RGBA_PVRTC_4BPPV1) ||
|
||||
(this._format >= enums.TEXTURE_FMT_RGB_ETC2 && this._format <= enums.TEXTURE_FMT_RGBA_ETC2)
|
||||
;
|
||||
}
|
||||
|
||||
// check if generate mipmap
|
||||
if (options.genMipmaps !== undefined) {
|
||||
this._genMipmaps = options.genMipmaps;
|
||||
genMipmaps = options.genMipmaps;
|
||||
}
|
||||
|
||||
if (options.images !== undefined) {
|
||||
if (options.images.length > 1) {
|
||||
genMipmaps = false;
|
||||
if (options.width !== options.height) {
|
||||
console.warn('texture-cube width and height should be identical.');
|
||||
}
|
||||
if (options.width >> (options.images.length - 1) !== 1) {
|
||||
console.error('texture-cube mipmap is invalid. please set mipmap as 1x1, 2x2, 4x4 ... nxn');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: get pot after this._width, this._height has been assigned.
|
||||
let pot = isPow2(this._width) && isPow2(this._height);
|
||||
if (!pot) {
|
||||
genMipmaps = false;
|
||||
}
|
||||
|
||||
gl.activeTexture(gl.TEXTURE0);
|
||||
gl.bindTexture(gl.TEXTURE_CUBE_MAP, this._glID);
|
||||
if (options.images !== undefined && options.images.length > 0) {
|
||||
this._setMipmap(options.images, options.flipY, options.premultiplyAlpha);
|
||||
if (options.images.length > 1) this._genMipmaps = true;
|
||||
}
|
||||
if (genMipmaps) {
|
||||
gl.hint(gl.GENERATE_MIPMAP_HINT, gl.NICEST);
|
||||
gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
|
||||
this._genMipmaps = true;
|
||||
}
|
||||
|
||||
this._setTexInfo();
|
||||
|
||||
this._device._restoreTexture(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @method updateSubImage
|
||||
* @param {Object} options
|
||||
* @param {Number} options.x
|
||||
* @param {Number} options.y
|
||||
* @param {Number} options.width
|
||||
* @param {Number} options.height
|
||||
* @param {Number} options.level
|
||||
* @param {Number} options.faceIndex
|
||||
* @param {HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | ArrayBufferView} options.image
|
||||
* @param {Boolean} options.flipY
|
||||
* @param {Boolean} options.premultiplyAlpha
|
||||
*/
|
||||
updateSubImage(options) {
|
||||
let gl = this._device._gl;
|
||||
let glFmt = glTextureFmt(this._format);
|
||||
|
||||
gl.activeTexture(gl.TEXTURE0);
|
||||
gl.bindTexture(gl.TEXTURE_CUBE_MAP, this._glID);
|
||||
this._setSubImage(glFmt, options);
|
||||
|
||||
this._device._restoreTexture(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @method updateImage
|
||||
* @param {Object} options
|
||||
* @param {Number} options.width
|
||||
* @param {Number} options.height
|
||||
* @param {Number} options.level
|
||||
* @param {Number} options.faceIndex
|
||||
* @param {HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | ArrayBufferView} options.image
|
||||
* @param {Boolean} options.flipY
|
||||
* @param {Boolean} options.premultiplyAlpha
|
||||
*/
|
||||
updateImage(options) {
|
||||
let gl = this._device._gl;
|
||||
let glFmt = glTextureFmt(this._format);
|
||||
|
||||
gl.activeTexture(gl.TEXTURE0);
|
||||
gl.bindTexture(gl.TEXTURE_CUBE_MAP, this._glID);
|
||||
this._setImage(glFmt, options);
|
||||
this._device._restoreTexture(0);
|
||||
}
|
||||
|
||||
_setSubImage(glFmt, options) {
|
||||
let gl = this._device._gl;
|
||||
let flipY = options.flipY;
|
||||
let premultiplyAlpha = options.premultiplyAlpha;
|
||||
let faceIndex = options.faceIndex;
|
||||
let img = options.image;
|
||||
|
||||
if (flipY === undefined) {
|
||||
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
|
||||
} else {
|
||||
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
|
||||
}
|
||||
|
||||
if (premultiplyAlpha === undefined) {
|
||||
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
|
||||
} else {
|
||||
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha);
|
||||
}
|
||||
|
||||
if (img && !ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) {
|
||||
gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, options.level, options.x, options.y, glFmt.format, glFmt.pixelType, img);
|
||||
} else {
|
||||
if (this._compressed) {
|
||||
gl.compressedTexSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex,
|
||||
options.level,
|
||||
options.x,
|
||||
options.y,
|
||||
options.width,
|
||||
options.height,
|
||||
glFmt.format,
|
||||
img
|
||||
);
|
||||
} else {
|
||||
gl.texSubImage2D(
|
||||
gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex,
|
||||
options.level,
|
||||
options.x,
|
||||
options.y,
|
||||
options.width,
|
||||
options.height,
|
||||
glFmt.format,
|
||||
glFmt.pixelType,
|
||||
img
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_setImage(glFmt, options) {
|
||||
let gl = this._device._gl;
|
||||
let flipY = options.flipY;
|
||||
let premultiplyAlpha = options.premultiplyAlpha;
|
||||
let faceIndex = options.faceIndex;
|
||||
let img = options.image;
|
||||
|
||||
if (flipY === undefined) {
|
||||
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
|
||||
} else {
|
||||
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
|
||||
}
|
||||
|
||||
if (premultiplyAlpha === undefined) {
|
||||
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
|
||||
} else {
|
||||
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha);
|
||||
}
|
||||
if (img && !ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) {
|
||||
gl.texImage2D(
|
||||
gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex,
|
||||
options.level,
|
||||
glFmt.internalFormat,
|
||||
glFmt.format,
|
||||
glFmt.pixelType,
|
||||
img
|
||||
);
|
||||
} else {
|
||||
if (this._compressed) {
|
||||
gl.compressedTexImage2D(
|
||||
gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex,
|
||||
options.level,
|
||||
glFmt.internalFormat,
|
||||
options.width,
|
||||
options.height,
|
||||
0,
|
||||
img
|
||||
);
|
||||
} else {
|
||||
gl.texImage2D(
|
||||
gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex,
|
||||
options.level,
|
||||
glFmt.internalFormat,
|
||||
options.width,
|
||||
options.height,
|
||||
0,
|
||||
glFmt.format,
|
||||
glFmt.pixelType,
|
||||
img
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// levelImages = [imagePosX, imageNegX, imagePosY, imageNegY, imagePosZ, imageNegz]
|
||||
// images = [levelImages0, levelImages1, ...]
|
||||
_setMipmap(images, flipY, premultiplyAlpha) {
|
||||
let glFmt = glTextureFmt(this._format);
|
||||
let options = {
|
||||
width: this._width,
|
||||
height: this._height,
|
||||
faceIndex: 0,
|
||||
flipY: flipY,
|
||||
premultiplyAlpha: premultiplyAlpha,
|
||||
level: 0,
|
||||
image: null
|
||||
};
|
||||
|
||||
for (let i = 0; i < images.length; ++i) {
|
||||
let levelImages = images[i];
|
||||
options.level = i;
|
||||
options.width = this._width >> i;
|
||||
options.height = this._height >> i;
|
||||
|
||||
for (let face = 0; face < 6; ++face) {
|
||||
options.faceIndex = face;
|
||||
options.image = levelImages[face];
|
||||
this._setImage(glFmt, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_setTexInfo() {
|
||||
let gl = this._device._gl;
|
||||
let pot = isPow2(this._width) && isPow2(this._height);
|
||||
|
||||
// WebGL1 doesn't support all wrap modes with NPOT textures
|
||||
if (!pot && (this._wrapS !== enums.WRAP_CLAMP || this._wrapT !== enums.WRAP_CLAMP)) {
|
||||
console.warn('WebGL1 doesn\'t support all wrap modes with NPOT textures');
|
||||
this._wrapS = enums.WRAP_CLAMP;
|
||||
this._wrapT = enums.WRAP_CLAMP;
|
||||
}
|
||||
|
||||
let mipFilter = this._genMipmaps ? this._mipFilter : -1;
|
||||
if (!pot && mipFilter !== -1) {
|
||||
console.warn('NPOT textures do not support mipmap filter');
|
||||
mipFilter = -1;
|
||||
}
|
||||
|
||||
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, glFilter(gl, this._minFilter, mipFilter));
|
||||
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, glFilter(gl, this._magFilter, -1));
|
||||
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, this._wrapS);
|
||||
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, this._wrapT);
|
||||
// wrapR available in webgl2
|
||||
// gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_R, this._wrapR);
|
||||
|
||||
let ext = this._device.ext('EXT_texture_filter_anisotropic');
|
||||
if (ext) {
|
||||
gl.texParameteri(gl.TEXTURE_CUBE_MAP, ext.TEXTURE_MAX_ANISOTROPY_EXT, this._anisotropy);
|
||||
}
|
||||
}
|
||||
}
|
56
engine/cocos2d/renderer/gfx/texture.js
Normal file
56
engine/cocos2d/renderer/gfx/texture.js
Normal file
@@ -0,0 +1,56 @@
|
||||
import { enums } from './enums';
|
||||
|
||||
/**
|
||||
* @type {WebGLTexture}
|
||||
*/
|
||||
const _nullWebGLTexture = null;
|
||||
|
||||
let _textureID = 0;
|
||||
|
||||
/**
|
||||
* @typedef {import("../gfx/device").default} Device
|
||||
*/
|
||||
|
||||
export default class Texture {
|
||||
/**
|
||||
* @param {Device} device
|
||||
*/
|
||||
constructor(device) {
|
||||
this._device = device;
|
||||
|
||||
this._width = 4;
|
||||
this._height = 4;
|
||||
this._genMipmaps = false;
|
||||
this._compressed = false;
|
||||
|
||||
this._anisotropy = 1;
|
||||
this._minFilter = enums.FILTER_LINEAR;
|
||||
this._magFilter = enums.FILTER_LINEAR;
|
||||
this._mipFilter = enums.FILTER_LINEAR;
|
||||
this._wrapS = enums.WRAP_REPEAT;
|
||||
this._wrapT = enums.WRAP_REPEAT;
|
||||
// wrapR available in webgl2
|
||||
// this._wrapR = enums.WRAP_REPEAT;
|
||||
this._format = enums.TEXTURE_FMT_RGBA8;
|
||||
|
||||
this._target = -1;
|
||||
|
||||
this._id = _textureID++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @method destroy
|
||||
*/
|
||||
destroy() {
|
||||
if (this._glID === _nullWebGLTexture) {
|
||||
console.error('The texture already destroyed');
|
||||
return;
|
||||
}
|
||||
|
||||
let gl = this._device._gl;
|
||||
gl.deleteTexture(this._glID);
|
||||
|
||||
this._device._stats.tex -= this.bytes;
|
||||
this._glID = _nullWebGLTexture;
|
||||
}
|
||||
}
|
99
engine/cocos2d/renderer/gfx/vertex-buffer.js
Normal file
99
engine/cocos2d/renderer/gfx/vertex-buffer.js
Normal file
@@ -0,0 +1,99 @@
|
||||
import { enums } from './enums';
|
||||
|
||||
class VertexBuffer {
|
||||
/**
|
||||
* @constructor
|
||||
* @param {Device} device
|
||||
* @param {VertexFormat} format
|
||||
* @param {USAGE_*} usage
|
||||
* @param {ArrayBuffer | Uint8Array} data
|
||||
*/
|
||||
constructor(device, format, usage, data) {
|
||||
this._device = device;
|
||||
this._format = format;
|
||||
this._usage = usage;
|
||||
this._bytesPerVertex = this._format._bytes;
|
||||
this._bytes = data.byteLength;
|
||||
this._numVertices = this._bytes / this._bytesPerVertex;
|
||||
|
||||
this._needExpandDataStore = true;
|
||||
|
||||
// update
|
||||
this._glID = device._gl.createBuffer();
|
||||
this.update(0, data);
|
||||
|
||||
// stats
|
||||
device._stats.vb += this._bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @method destroy
|
||||
*/
|
||||
destroy() {
|
||||
if (this._glID === -1) {
|
||||
console.error('The buffer already destroyed');
|
||||
return;
|
||||
}
|
||||
|
||||
let gl = this._device._gl;
|
||||
gl.deleteBuffer(this._glID);
|
||||
this._device._stats.vb -= this.bytes;
|
||||
|
||||
this._glID = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @method update
|
||||
* @param {Number} byteOffset
|
||||
* @param {ArrayBuffer} data
|
||||
*/
|
||||
update(byteOffset, data) {
|
||||
if (this._glID === -1) {
|
||||
console.error('The buffer is destroyed');
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.byteLength === 0) return;
|
||||
|
||||
// Need to create new buffer object when bytes exceed
|
||||
if (byteOffset + data.byteLength > this._bytes) {
|
||||
if (byteOffset) {
|
||||
// Lost data between [0, byteOffset] which is need for new buffer
|
||||
console.error('Failed to update data, bytes exceed.');
|
||||
return;
|
||||
}
|
||||
else {
|
||||
this._needExpandDataStore = true;
|
||||
this._bytes = byteOffset + data.byteLength;
|
||||
this._numVertices = this._bytes / this._bytesPerVertex;
|
||||
}
|
||||
}
|
||||
|
||||
let gl = this._device._gl;
|
||||
let glUsage = this._usage;
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, this._glID);
|
||||
if (this._needExpandDataStore) {
|
||||
gl.bufferData(gl.ARRAY_BUFFER, data, glUsage);
|
||||
this._needExpandDataStore = false;
|
||||
}
|
||||
else {
|
||||
gl.bufferSubData(gl.ARRAY_BUFFER, byteOffset, data);
|
||||
}
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
||||
}
|
||||
|
||||
get count () {
|
||||
return this._numVertices;
|
||||
}
|
||||
|
||||
getFormat (name) {
|
||||
return this._format.element(name);
|
||||
}
|
||||
|
||||
setUsage (usage) {
|
||||
this._usage = usage;
|
||||
}
|
||||
}
|
||||
|
||||
export default VertexBuffer;
|
70
engine/cocos2d/renderer/gfx/vertex-format.js
Normal file
70
engine/cocos2d/renderer/gfx/vertex-format.js
Normal file
@@ -0,0 +1,70 @@
|
||||
import { attrTypeBytes } from './enums';
|
||||
import murmurhash2 from '../murmurhash2_gc';
|
||||
|
||||
// ====================
|
||||
// exports
|
||||
// ====================
|
||||
|
||||
export default class VertexFormat {
|
||||
/**
|
||||
* @constructor
|
||||
* @param {Array} infos
|
||||
*
|
||||
* @example
|
||||
* let vertexFmt = new VertexFormat([
|
||||
* { name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 3 },
|
||||
* { name: gfx.ATTR_UV0, type: gfx.ATTR_TYPE_FLOAT32, num: 2 },
|
||||
* { name: gfx.ATTR_COLOR, type: gfx.ATTR_TYPE_FLOAT32, num: 4, normalize: true },
|
||||
* ])
|
||||
*/
|
||||
constructor(infos) {
|
||||
this._attr2el = {};
|
||||
this._elements = [];
|
||||
this._bytes = 0;
|
||||
|
||||
let hash = "";
|
||||
|
||||
for (let i = 0, len = infos.length; i < len; ++i) {
|
||||
let info = infos[i];
|
||||
let el = {
|
||||
name: info.name,
|
||||
offset: this._bytes,
|
||||
stride: 0,
|
||||
stream: -1,
|
||||
type: info.type,
|
||||
num: info.num,
|
||||
normalize: (info.normalize === undefined) ? false : info.normalize,
|
||||
bytes: info.num * attrTypeBytes(info.type),
|
||||
};
|
||||
|
||||
this._attr2el[el.name] = el;
|
||||
this._elements.push(el);
|
||||
|
||||
this._bytes += el.bytes;
|
||||
|
||||
hash += `${el.name}:${el.num}:${el.type}:${el.normalize}`;
|
||||
}
|
||||
|
||||
for (let i = 0, len = this._elements.length; i < len; ++i) {
|
||||
let el = this._elements[i];
|
||||
el.stride = this._bytes;
|
||||
}
|
||||
|
||||
this._hash = murmurhash2(hash, 666);
|
||||
}
|
||||
|
||||
/**
|
||||
* @method element
|
||||
* @param {string} attrName
|
||||
*/
|
||||
element(attrName) {
|
||||
return this._attr2el[attrName];
|
||||
}
|
||||
|
||||
/**
|
||||
* @method getHash
|
||||
*/
|
||||
getHash () {
|
||||
return this._hash;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user