2017-07-04 13:48:18 +00:00
|
|
|
var Class = require('../../utils/Class');
|
2017-04-05 22:01:44 +00:00
|
|
|
var Resources = require('./resources');
|
|
|
|
|
2017-07-04 13:48:18 +00:00
|
|
|
var ResourceManager = new Class({
|
2017-04-05 22:01:44 +00:00
|
|
|
|
2017-07-04 13:48:18 +00:00
|
|
|
initialize:
|
2017-04-05 22:01:44 +00:00
|
|
|
|
2017-07-04 13:48:18 +00:00
|
|
|
function ResourceManager (gl)
|
|
|
|
{
|
|
|
|
this.gl = gl;
|
|
|
|
|
|
|
|
// Maybe add pooling here?
|
|
|
|
this.shaderCache = {};
|
|
|
|
this.shaderCount = 0;
|
|
|
|
},
|
2017-04-05 22:01:44 +00:00
|
|
|
|
2017-07-04 13:48:18 +00:00
|
|
|
createRenderTarget: function (width, height, colorBuffer, depthStencilBuffer)
|
2017-04-05 22:01:44 +00:00
|
|
|
{
|
|
|
|
var gl = this.gl;
|
|
|
|
var framebufferObject = gl.createFramebuffer();
|
|
|
|
var depthStencilRenderbufferObject = null;
|
|
|
|
var colorRenderbufferObject = null;
|
|
|
|
var complete = 0;
|
|
|
|
|
2017-07-04 13:48:18 +00:00
|
|
|
gl.bindFramebuffer(gl.FRAMEBUFFER, framebufferObject);
|
2017-04-05 22:01:44 +00:00
|
|
|
|
2017-07-04 13:48:18 +00:00
|
|
|
if (depthStencilBuffer !== undefined && depthStencilBuffer !== null)
|
2017-04-05 22:01:44 +00:00
|
|
|
{
|
|
|
|
depthStencilBuffer.isRenderTexture = true;
|
2017-04-07 01:49:15 +00:00
|
|
|
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.TEXTURE_2D, depthStencilBuffer.texture, depthStencilBuffer.mipLevel);
|
2017-04-05 22:01:44 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
depthStencilRenderbufferObject = gl.createRenderbuffer();
|
2017-04-07 01:49:15 +00:00
|
|
|
gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencilRenderbufferObject);
|
|
|
|
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height);
|
|
|
|
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilRenderbufferObject);
|
2017-04-05 22:01:44 +00:00
|
|
|
}
|
|
|
|
|
2017-07-04 13:48:18 +00:00
|
|
|
if (colorBuffer !== undefined && colorBuffer !== null)
|
2017-04-05 22:01:44 +00:00
|
|
|
{
|
|
|
|
colorBuffer.isRenderTexture = true;
|
2017-04-07 01:49:15 +00:00
|
|
|
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorBuffer.texture, colorBuffer.mipLevel);
|
2017-07-04 13:48:18 +00:00
|
|
|
}
|
2017-04-05 22:01:44 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
colorRenderbufferObject = gl.createRenderbuffer();
|
2017-04-07 01:49:15 +00:00
|
|
|
gl.bindRenderbuffer(gl.RENDERBUFFER, colorRenderbufferObject);
|
|
|
|
gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, width, height);
|
|
|
|
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorRenderbufferObject);
|
2017-04-05 22:01:44 +00:00
|
|
|
}
|
|
|
|
|
2017-04-07 01:49:15 +00:00
|
|
|
complete = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
|
2017-04-05 22:01:44 +00:00
|
|
|
|
2017-07-04 13:48:18 +00:00
|
|
|
if (complete !== gl.FRAMEBUFFER_COMPLETE)
|
2017-04-05 22:01:44 +00:00
|
|
|
{
|
|
|
|
var errors = {
|
|
|
|
36054: 'Incomplete Attachment',
|
|
|
|
36055: 'Missing Attachment',
|
|
|
|
36057: 'Incomplete Dimensions',
|
|
|
|
36061: 'Framebuffer Unsupported'
|
|
|
|
};
|
|
|
|
throw new Error('Framebuffer incomplete. Framebuffer status: ' + errors[complete]);
|
|
|
|
}
|
|
|
|
|
2017-04-07 01:49:15 +00:00
|
|
|
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
2017-04-05 22:01:44 +00:00
|
|
|
|
|
|
|
return new Resources.RenderTarget(
|
|
|
|
framebufferObject,
|
|
|
|
width, height,
|
|
|
|
(colorBuffer === undefined ? null : colorBuffer),
|
|
|
|
(depthStencilBuffer === undefined ? null : depthStencilBuffer)
|
|
|
|
);
|
|
|
|
},
|
|
|
|
|
2017-07-04 13:48:18 +00:00
|
|
|
createBuffer: function (target, initialDataOrSize, bufferUsage)
|
2017-04-05 22:01:44 +00:00
|
|
|
{
|
|
|
|
var gl = this.gl;
|
|
|
|
var bufferObject = gl.createBuffer();
|
|
|
|
gl.bindBuffer(target, bufferObject);
|
|
|
|
gl.bufferData(target, initialDataOrSize, bufferUsage);
|
|
|
|
|
2017-07-04 13:48:18 +00:00
|
|
|
switch (target)
|
2017-04-05 22:01:44 +00:00
|
|
|
{
|
2017-04-07 01:49:15 +00:00
|
|
|
case gl.ARRAY_BUFFER:
|
2017-04-05 22:01:44 +00:00
|
|
|
return new Resources.VertexBuffer(gl, bufferObject);
|
2017-07-04 13:48:18 +00:00
|
|
|
|
2017-04-07 01:49:15 +00:00
|
|
|
case gl.ELEMENT_ARRAY_BUFFER:
|
2017-04-05 22:01:44 +00:00
|
|
|
return new Resources.IndexBuffer(gl, bufferObject);
|
2017-07-04 13:48:18 +00:00
|
|
|
|
2017-04-05 22:01:44 +00:00
|
|
|
default:
|
|
|
|
throw new Error('Invalid Buffer Target');
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2017-07-04 13:48:18 +00:00
|
|
|
createTexture: function (mipLevel, minFilter, magFilter, wrapT, wrapS, format, pixels, width, height)
|
2017-04-05 22:01:44 +00:00
|
|
|
{
|
|
|
|
var gl = this.gl;
|
|
|
|
var texture = gl.createTexture();
|
|
|
|
|
2017-04-07 01:49:15 +00:00
|
|
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter);
|
|
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter);
|
|
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS);
|
|
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT);
|
2017-04-05 22:01:44 +00:00
|
|
|
|
2017-07-04 13:48:18 +00:00
|
|
|
if (pixels === null || pixels === undefined)
|
2017-04-05 22:01:44 +00:00
|
|
|
{
|
2017-04-07 01:49:15 +00:00
|
|
|
gl.texImage2D(gl.TEXTURE_2D, mipLevel, format, width, height, 0, format, gl.UNSIGNED_BYTE, null);
|
2017-07-04 13:48:18 +00:00
|
|
|
}
|
|
|
|
else
|
2017-04-05 22:01:44 +00:00
|
|
|
{
|
2017-04-07 01:49:15 +00:00
|
|
|
gl.texImage2D(gl.TEXTURE_2D, mipLevel, format, format, gl.UNSIGNED_BYTE, pixels);
|
2017-04-05 22:01:44 +00:00
|
|
|
width = pixels.width;
|
|
|
|
height = pixels.height;
|
|
|
|
}
|
2017-07-04 13:48:18 +00:00
|
|
|
|
2017-04-07 01:49:15 +00:00
|
|
|
gl.bindTexture(gl.TEXTURE_2D, null);
|
2017-04-05 22:01:44 +00:00
|
|
|
|
|
|
|
return new Resources.Texture(texture, width, height);
|
|
|
|
},
|
|
|
|
|
2017-07-04 13:48:18 +00:00
|
|
|
createShader: function (shaderName, shaderSources)
|
2017-04-05 22:01:44 +00:00
|
|
|
{
|
2017-04-07 01:49:15 +00:00
|
|
|
if (shaderName === null || shaderName === undefined)
|
|
|
|
{
|
|
|
|
shaderName += 'Shader' + this.shaderCount;
|
|
|
|
this.shaderCount += 1;
|
|
|
|
}
|
2017-07-04 13:48:18 +00:00
|
|
|
|
2017-04-05 22:01:44 +00:00
|
|
|
if (!(shaderName in this.shaderCache))
|
|
|
|
{
|
|
|
|
var gl = this.gl;
|
2017-04-07 03:42:06 +00:00
|
|
|
var program;
|
|
|
|
var vertShader;
|
|
|
|
var fragShader;
|
|
|
|
var status;
|
2017-04-05 22:01:44 +00:00
|
|
|
var error;
|
|
|
|
var shader;
|
|
|
|
|
2017-04-07 03:42:06 +00:00
|
|
|
vertShader = gl.createShader(gl.VERTEX_SHADER);
|
2017-04-05 22:01:44 +00:00
|
|
|
gl.shaderSource(vertShader, shaderSources.vert);
|
|
|
|
gl.compileShader(vertShader);
|
|
|
|
|
|
|
|
error = gl.getShaderInfoLog(vertShader);
|
2017-04-07 03:42:06 +00:00
|
|
|
status = gl.getShaderParameter(vertShader, gl.COMPILE_STATUS);
|
2017-04-05 22:01:44 +00:00
|
|
|
|
2017-07-04 13:48:18 +00:00
|
|
|
if (!status && error && error.length > 0)
|
2017-04-05 22:01:44 +00:00
|
|
|
{
|
2017-04-07 03:42:06 +00:00
|
|
|
throw new Error('Vertex Shader Compilation Error. Shader name: ' + shaderName + '.\n' + error + '\n\n Shader source:\n' + shaderSources.vert);
|
2017-04-05 22:01:44 +00:00
|
|
|
}
|
2017-04-07 03:42:06 +00:00
|
|
|
else if (error && error.length > 0)
|
|
|
|
{
|
|
|
|
console.warn('Vertex Shader Compilation Warning. Shader name: ' + shaderName + '.\n' + error + '\n\n Shader source:\n' + shaderSources.vert);
|
|
|
|
}
|
|
|
|
|
|
|
|
fragShader = gl.createShader(gl.FRAGMENT_SHADER);
|
|
|
|
gl.shaderSource(fragShader, shaderSources.frag);
|
|
|
|
gl.compileShader(fragShader);
|
2017-04-05 22:01:44 +00:00
|
|
|
|
|
|
|
error = gl.getShaderInfoLog(fragShader);
|
2017-04-07 03:42:06 +00:00
|
|
|
status = gl.getShaderParameter(fragShader, gl.COMPILE_STATUS);
|
2017-04-05 22:01:44 +00:00
|
|
|
|
2017-07-04 13:48:18 +00:00
|
|
|
if (!status && error && error.length > 0)
|
2017-04-07 03:42:06 +00:00
|
|
|
{
|
|
|
|
throw new Error('Fragment Shader Compilation Error. Shader name: ' + shaderName + '.\n' + error + '\n\n Shader source:\n' + shaderSources.frag);
|
|
|
|
}
|
|
|
|
else if (error && error.length > 0)
|
2017-04-05 22:01:44 +00:00
|
|
|
{
|
2017-04-07 03:42:06 +00:00
|
|
|
console.warn('Fragment Shader Compilation Warning. Shader name: ' + shaderName + '.\n' + error + '\n\n Shader source:\n' + shaderSources.frag);
|
2017-04-05 22:01:44 +00:00
|
|
|
}
|
|
|
|
|
2017-04-07 03:42:06 +00:00
|
|
|
program = gl.createProgram();
|
2017-04-05 22:01:44 +00:00
|
|
|
gl.attachShader(program, vertShader);
|
|
|
|
gl.attachShader(program, fragShader);
|
|
|
|
gl.linkProgram(program);
|
2017-04-07 03:42:06 +00:00
|
|
|
gl.validateProgram(program);
|
2017-04-05 22:01:44 +00:00
|
|
|
|
2017-04-07 01:49:15 +00:00
|
|
|
error = gl.getProgramParameter(program, gl.LINK_STATUS);
|
2017-04-05 22:01:44 +00:00
|
|
|
|
|
|
|
if (error === 0)
|
|
|
|
{
|
|
|
|
error = gl.getProgramInfoLog(program);
|
|
|
|
|
2017-04-07 03:42:06 +00:00
|
|
|
throw new Error('Program Linking Error. Shader name: ' + shaderName + '.\n' + error);
|
|
|
|
}
|
|
|
|
|
|
|
|
error = gl.getProgramParameter(program, gl.VALIDATE_STATUS);
|
2017-07-04 13:48:18 +00:00
|
|
|
|
2017-04-07 03:42:06 +00:00
|
|
|
if (error === 0)
|
|
|
|
{
|
|
|
|
error = gl.getProgramInfoLog(program);
|
|
|
|
throw new Error('Program Validation Error. Shader name: ' + shaderName + '.\n' + error);
|
2017-04-05 22:01:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
shader = new Resources.Shader(shaderName, gl, program, vertShader, fragShader);
|
2017-07-04 13:48:18 +00:00
|
|
|
|
2017-04-05 22:01:44 +00:00
|
|
|
this.shaderCache[shaderName] = shader;
|
2017-07-04 13:48:18 +00:00
|
|
|
|
|
|
|
return shader;
|
2017-04-05 22:01:44 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-07-04 13:48:18 +00:00
|
|
|
return this.shaderCache[shaderName];
|
2017-04-05 22:01:44 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
deleteShader: function (shader)
|
|
|
|
{
|
2017-07-04 13:48:18 +00:00
|
|
|
var storedShader = this.shaderCache[shader.name];
|
|
|
|
|
2017-04-05 22:01:44 +00:00
|
|
|
var gl = this.gl;
|
2017-07-04 13:48:18 +00:00
|
|
|
|
2017-04-05 22:01:44 +00:00
|
|
|
if (storedShader !== undefined)
|
|
|
|
{
|
|
|
|
delete this.shaderCache;
|
|
|
|
}
|
2017-07-04 13:48:18 +00:00
|
|
|
|
2017-04-05 22:01:44 +00:00
|
|
|
gl.deleteShader(shader.vertexShader);
|
|
|
|
gl.deleteShader(shader.fragmentShader);
|
|
|
|
gl.deleteProgram(shader.program);
|
2017-07-04 13:48:18 +00:00
|
|
|
|
2017-04-05 22:01:44 +00:00
|
|
|
shader.vertexShader = null;
|
|
|
|
shader.fragmentShader = null;
|
|
|
|
shader.program = null;
|
|
|
|
shader.name = null;
|
|
|
|
},
|
|
|
|
|
|
|
|
deleteBuffer: function (buffer)
|
|
|
|
{
|
|
|
|
var gl = this.gl;
|
|
|
|
|
|
|
|
gl.deleteBuffer(buffer.bufferObject);
|
|
|
|
}
|
|
|
|
|
2017-07-04 13:48:18 +00:00
|
|
|
});
|
2017-04-05 22:01:44 +00:00
|
|
|
|
|
|
|
module.exports = ResourceManager;
|