mirror of
https://github.com/smallmain/cocos-enhance-kit.git
synced 2025-01-15 07:21:07 +00:00
172 lines
4.1 KiB
JavaScript
172 lines
4.1 KiB
JavaScript
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;
|
|
} |