[Pages] Make directory structure lowercase.

This commit is contained in:
RHY3756547 committed 2017-09-08 17:10:13 +01:00
1 parent 3b47a86756
commit 65ca7d7455
96 files changed
+20116

No files matched your search

+244
View File
@@ -0,0 +1,244 @@
//
// nitroAnimator.js
//--------------------
// Runs nsbca animations and provides matrix stacks that can be used with nitroRender to draw them.
// by RHY3756547
//
// includes: gl-matrix.js (glMatrix 2.0)
// /formats/*
//
window.nitroAnimator = function(bmd, bca) {
var t = this;
t.bmd = bmd;
t.bca = bca;
var bmd = bmd;
var bca = bca;
t.setFrame = setFrame;
t.setAnim = setAnim;
t.getLength = getLength;
var matBufEmpty = new Float32Array(31*16);
var workingMat = mat4.create();
var temp = mat4.create();
var off=0;
var objMats = [];
for (var i=0; i<31; i++) {
matBufEmpty.set(temp, off);
objMats.push(mat4.create());
off += 16;
}
var matBuf = new Float32Array(31*16);
var matStack = {built: true, dat: matBuf};
function setAnim(b) {
bca = b;
t.bca = b;
}
function getLength(anim) {
return bca.animData.objectData[anim].frames;
}
function setFrame(anim, modelind, frame) {
var b = bca.animData.objectData[anim];
var fLow = Math.floor(frame);
var fHigh = Math.ceil(frame);
var iterp = frame%1;
var model = bmd.modelData.objectData[modelind];
var fallback = model.objects.objectData;
for (var i=0; i<b.trans.length; i++) {
var mat = objMats[i];
mat4.identity(mat);
var a = b.trans[i]; //animated transforms
var fa = fallback[i]; //fallback
var translate;
if (a.translate != null) {
translate = [];
if (a.tlExtra[0] != null) {
var f = frame * a.tlExtra[0].speed;
var fLow = Math.floor(f)%a.translate[0].length;
var fHigh = Math.ceil(f)%a.translate[0].length;
var p = f%1;
translate[0] = a.translate[0][fHigh]*(p) + a.translate[0][fLow]*(1-p);
} else translate[0] = a.translate[0][0];
if (a.tlExtra[1] != null) {
var f = frame * a.tlExtra[1].speed;
var fLow = Math.floor(f)%a.translate[1].length;
var fHigh = Math.ceil(f)%a.translate[1].length;
var p = f%1;
translate[1] = a.translate[1][fHigh]*(p) + a.translate[1][fLow]*(1-p);
} else translate[1] = a.translate[1][0];
if (a.tlExtra[2] != null) {
var f = frame * a.tlExtra[2].speed;
var fLow = Math.floor(f)%a.translate[2].length;
var fHigh = Math.ceil(f)%a.translate[2].length;
var p = f%1;
translate[2] = a.translate[2][fHigh]*(p) + a.translate[2][fLow]*(1-p);
} else translate[2] = a.translate[2][0];
} else {
translate = fa.translate;
}
var rotate;
if (a.rotate != null) {
if (a.rotExtra != null) {
var f = frame * a.rotExtra.speed;
var fLow = Math.floor(f)%a.rotate.length;
var fHigh = Math.ceil(f)%a.rotate.length;
var p = f%1;
var r1 = parseRotation(a.rotate[fLow]);
var r2 = parseRotation(a.rotate[fHigh]);
rotate = lerpMat3(r1, r2, p);
} else {
rotate = parseRotation(a.rotate[0]);
}
} else {
rotate = fa.pivot;
}
var scale;
if (a.scale != null) {
scale = [];
if (a.scExtra[0] != null) {
var f = frame * a.scExtra[0].speed;
var fLow = Math.floor(f)%a.scale[0].length;
var fHigh = Math.ceil(f)%a.scale[0].length;
var p = f%1;
scale[0] = a.scale[0][fHigh].s1*(p) + a.scale[0][fLow].s1*(1-p);
} else scale[0] = a.scale[0][0].s1;
if (a.scExtra[1] != null) {
var f = frame * a.scExtra[1].speed;
var fLow = Math.floor(f)%a.scale[1].length;
var fHigh = Math.ceil(f)%a.scale[1].length;
var p = f%1;
scale[1] = a.scale[1][fHigh].s1*(p) + a.scale[1][fLow].s1*(1-p);
} else scale[1] = a.scale[1][0].s1;
if (a.scExtra[2] != null) {
var f = frame * a.scExtra[2].speed;
var fLow = Math.floor(f)%a.scale[2].length;
var fHigh = Math.ceil(f)%a.scale[2].length;
var p = f%1;
scale[2] = a.scale[2][fHigh].s1*(p) + a.scale[2][fLow].s1*(1-p);
} else scale[2] = a.scale[2][0].s1;
} else {
scale = fa.scale;
}
mat4.translate(mat, mat, translate);
mat4.multiply(mat, mat, mat4FromMat3(rotate));
mat4.scale(mat, mat, scale);
}
generateMatrixStack(model, matBuf)
return matStack;
}
function generateMatrixStack(model, targ) {
var matrices = []
var objs = model.objects.objectData;
var cmds = model.commands;
var curMat = mat4.create();
var lastStackID = 0;
for (var i=0; i<cmds.length; i++) {
var cmd = cmds[i];
if (cmd.restoreID != null) curMat = mat4.clone(matrices[cmd.restoreID]);
var o = objs[cmd.obj];
mat4.multiply(curMat, curMat, objMats[cmd.obj]);
if (o.billboardMode == 1) mat4.multiply(curMat, curMat, nitroRender.billboardMat);
if (o.billboardMode == 2) mat4.multiply(curMat, curMat, nitroRender.yBillboardMat);
if (cmd.stackID != null) {
matrices[cmd.stackID] = mat4.clone(curMat);
lastStackID = cmd.stackID;
} else {
matrices[lastStackID] = mat4.clone(curMat);
}
}
model.lastStackID = lastStackID;
targ.set(matBufEmpty);
var off=0;
for (var i=0; i<31; i++) {
if (matrices[i] != null) targ.set(matrices[i], off);
off += 16;
}
return targ;
}
function mat4FromMat3(mat) {
dest = mat4.create();
dest[0] = mat[0];
dest[1] = mat[1];
dest[2] = mat[2];
dest[3] = 0;
dest[4] = mat[3];
dest[5] = mat[4];
dest[6] = mat[5];
dest[7] = 0;
dest[8] = mat[6];
dest[9] = mat[7];
dest[10] = mat[8];
dest[11] = 0;
dest[12] = 0;
dest[13] = 0;
dest[14] = 0;
dest[15] = 1;
return dest;
}
function parseRotation(rot) {
if (rot.pivot) {
var flag = rot.param;
var pivot = [0,0,0,0,0,0,0,0,0];
var mode = flag&15;
var neg = (flag>>4)&15;
var A = rot.a;
var B = rot.b;
pivot[mode] = (neg&1)?-1:1;
var horiz = mode%3;
var vert = Math.floor(mode/3)
var left = (horiz==0)?1:0; var top = ((vert==0)?1:0)*3;
var right = (horiz==2)?1:2; var btm = ((vert==2)?1:2)*3;
pivot[left+top] = A;
pivot[right+top] = B;
pivot[left+btm] = (neg&2)?-B:B;
pivot[right+btm] = (neg&4)?-A:A;
return pivot;
} else {
return rot.mat;
}
}
function lerpMat3(m1, m2, p) { //this is probably a dumb idea, but it's not the worst thing i've come up with...
var q = 1-p;
return [
m1[0]*q+m2[0]*p, m1[1]*q+m2[1]*p, m1[2]*q+m2[2]*p,
m1[3]*q+m2[3]*p, m1[4]*q+m2[4]*p, m1[5]*q+m2[5]*p,
m1[6]*q+m2[6]*p, m1[7]*q+m2[7]*p, m1[8]*q+m2[8]*p,
]
}
}
+741
View File
@@ -0,0 +1,741 @@
//
// nitroRender.js
//--------------------
// Provides an interface with which NSBMD models can be drawn to a fst canvas.
// by RHY3756547
//
// includes: gl-matrix.js (glMatrix 2.0)
// /formats/nitro.js --passive requirement from other nitro formats
// /formats/nsbmd.js
// /formats/nsbta.js
// /formats/nsbtx.js
//
window.nitroRender = new function() {
var gl, frag, vert, nitroShader;
var cVec, color, texCoord, norm;
var vecMode, vecPos, vecNorm, vecTx, vecCol, vecNum, vecMat, curMat;
var texWidth, texHeight, alphaMul = 1;
this.cullModes = [];
this.billboardID = 0; //incrememts every time billboards need to be updated. cycles &0xFFFFFF to avoid issues
this.lastMatStack = null; //used to check if we need to send the matStack again. will be used with a versioning system in future.
this.last = {}; //obj: the last vertex buffers drawn
var optimiseTriangles = true; //improves draw performance by >10x on most models.
var modelBuffer;
var shaders = [];
this.renderDispList = renderDispList;
this.setAlpha = setAlpha;
this.getViewWidth = getViewWidth;
this.getViewHeight = getViewHeight;
this.flagShadow = false;
var parameters = {
0: 0,
0x10:1, 0x11:0, 0x12:1, 0x13:1, 0x14:1, 0x15:0, 0x16:16, 0x17:12, 0x18:16, 0x19:12, 0x1A:9, 0x1B:3, 0x1C:3, //matrix commands
0x20:1, 0x21:1, 0x22:1, 0x23:2, 0x24:1, 0x25:1, 0x26:1, 0x27:1, 0x28:1, 0x29:1, 0x2A:1, 0x2B:1, //vertex commands
0x30:1, 0x31:1, 0x32:1, 0x33:1, 0x34:32, //material param
0x40:1, 0x41:0, //begin or end vertices
0x50:1, //swap buffers
0x60:1, //viewport
0x70:3, 0x71:2, 0x72:1 //tests
}
var instructions = {};
instructions[0x14] = function(view, off) { //restore to matrix, used constantly for bone transforms
curMat = view.getUint8(off);
}
instructions[0x20] = function(view, off) { //color
var dat = view.getUint16(off,true);
color[0] = (dat&31)/31;
color[1] = ((dat>>5)&31)/31;
color[2] = ((dat>>10)&31)/31;
}
instructions[0x21] = function(view, off) { //normal
var dat = view.getUint32(off, true);
norm[0] = tenBitSign(dat);
norm[1] = tenBitSign(dat>>10);
norm[2] = tenBitSign(dat>>20);
}
instructions[0x22] = function(view, off) { //texcoord
texCoord[0] = (view.getInt16(off, true)/16)/texWidth;
texCoord[1] = (view.getInt16(off+2, true)/16)/texHeight;
}
instructions[0x23] = function(view, off) { //xyz 16 bit
cVec[0] = view.getInt16(off, true)/4096;
cVec[1] = view.getInt16(off+2, true)/4096;
cVec[2] = view.getInt16(off+4, true)/4096;
pushVector();
}
instructions[0x24] = function(view, off) { //xyz 10 bit
var dat = view.getUint32(off, true);
cVec[0] = tenBitSign(dat);
cVec[1] = tenBitSign(dat>>10);
cVec[2] = tenBitSign(dat>>20);
pushVector();
}
instructions[0x25] = function(view, off) { //xy 16 bit
cVec[0] = view.getInt16(off, true)/4096;
cVec[1] = view.getInt16(off+2, true)/4096;
pushVector();
}
instructions[0x26] = function(view, off) { //xz 16 bit
cVec[0] = view.getInt16(off, true)/4096;
cVec[2] = view.getInt16(off+2, true)/4096;
pushVector();
}
instructions[0x27] = function(view, off) { //yz 16 bit
cVec[1] = view.getInt16(off, true)/4096;
cVec[2] = view.getInt16(off+2, true)/4096;
pushVector();
}
instructions[0x28] = function(view, off) { //xyz 10 bit relative
var dat = view.getUint32(off, true);
cVec[0] += relativeSign(dat);
cVec[1] += relativeSign(dat>>10);
cVec[2] += relativeSign(dat>>20);
pushVector();
}
instructions[0x40] = function(view, off) { //begin vtx
var dat = view.getUint32(off, true);
vecMode = dat;
if (!optimiseTriangles) {
vecPos = [];
vecNorm = [];
vecTx = [];
vecCol = [];
vecMat = [];
}
vecNum = 0;
}
instructions[0x41] = function(view, off) { //end vtx
if (!optimiseTriangles) pushStrip();
}
function setAlpha(alpha) { //for fading specific things out or whatever
alphaMul = alpha;
}
function getViewWidth(){
return gl.viewportWidth;
}
function getViewHeight() {
return gl.viewportHeight;
}
function pushStrip() { //push the last group of triangles to the buffer. Should do this on matrix change... details fourthcoming
var modes = (optimiseTriangles)?[gl.TRIANGLES, gl.TRIANGLES, gl.TRIANGLES, gl.TRIANGLES]:[gl.TRIANGLES, gl.TRIANGLES, gl.TRIANGLE_STRIP, gl.TRIANGLE_STRIP];
var pos = gl.createBuffer();
var col = gl.createBuffer();
var tx = gl.createBuffer();
var mat = gl.createBuffer();
var norm = gl.createBuffer();
var posArray = new Float32Array(vecPos);
gl.bindBuffer(gl.ARRAY_BUFFER, pos);
gl.bufferData(gl.ARRAY_BUFFER, posArray, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, tx);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vecTx), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, col);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vecCol), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, mat);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vecMat), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, norm);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vecNorm), gl.STATIC_DRAW);
modelBuffer.strips.push({
posArray: posArray,
vPos: pos,
vTx: tx,
vCol: col,
vMat: mat,
vNorm: norm,
verts: vecPos.length/3,
mode: modes[vecMode]
})
}
function pushVector() {
if (vecMode == 1 && vecNum%4 == 3) { //quads - special case
vecPos = vecPos.concat(vecPos.slice(vecPos.length-9, vecPos.length-6)).concat(vecPos.slice(vecPos.length-3));
vecNorm = vecNorm.concat(vecNorm.slice(vecNorm.length-9, vecNorm.length-6)).concat(vecNorm.slice(vecNorm.length-3));
vecTx = vecTx.concat(vecTx.slice(vecTx.length-6, vecTx.length-4)).concat(vecTx.slice(vecTx.length-2));
vecCol = vecCol.concat(vecCol.slice(vecCol.length-12, vecCol.length-8)).concat(vecCol.slice(vecCol.length-4));
vecMat = vecMat.concat(vecMat.slice(vecMat.length-3, vecMat.length-2)).concat(vecMat.slice(vecMat.length-1));
}
if (optimiseTriangles && (vecMode > 1) && (vecNum > 2)) { //convert tri strips to individual triangles so we get one buffer per polygon
vecPos = vecPos.concat(vecPos.slice(vecPos.length-6));
vecNorm = vecNorm.concat(vecNorm.slice(vecNorm.length-6));
vecTx = vecTx.concat(vecTx.slice(vecTx.length-4));
vecCol = vecCol.concat(vecCol.slice(vecCol.length-8));
vecMat = vecMat.concat(vecMat.slice(vecMat.length-2));
}
vecNum++;
vecPos = vecPos.concat(cVec);
vecTx = vecTx.concat(texCoord);
vecCol = vecCol.concat(color);
vecNorm = vecNorm.concat(norm);
vecMat.push(curMat);
}
function tenBitSign(val) {
val &= 1023;
if (val & 512) return (val-1024)/64;
else return val/64;
}
function relativeSign(val) {
val &= 1023;
if (val & 512) return (val-1024)/4096;
else return val/4096;
}
this.init = function(ctx) {
gl = ctx;
this.gl = gl;
shaders = nitroShaders.compileShaders(gl);
this.nitroShader = shaders[0];
this.cullModes = [gl.FRONT_AND_BACK, gl.FRONT, gl.BACK];
}
this.prepareShader = function() {
//prepares the shader so no redundant calls have to be made. Should be called upon every program change.
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
this.last = {};
gl.activeTexture(gl.TEXTURE0);
gl.uniform1i(this.nitroShader.samplerUniform, 0);
}
this.setShadowMode = function(sTex, fsTex, sMat, fsMat) {
this.nitroShader = shaders[1];
var shader = shaders[1];
gl.useProgram(shader);
gl.uniformMatrix4fv(shader.shadowMatUniform, false, sMat);
gl.uniformMatrix4fv(shader.farShadowMatUniform, false, fsMat);
gl.uniform1f(shader.shadOffUniform, 0.00005+((mobile)?0.0005:0));
gl.uniform1f(shader.farShadOffUniform, 0.0005);
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, sTex);
gl.uniform1i(shader.lightSamplerUniform, 1);
gl.activeTexture(gl.TEXTURE2);
gl.bindTexture(gl.TEXTURE_2D, fsTex);
gl.uniform1i(shader.farLightSamplerUniform, 2);
this.setColMult([1, 1, 1, 1]);
this.prepareShader();
}
this.unsetShadowMode = function() {
this.nitroShader = shaders[0];
gl.useProgram(this.nitroShader);
this.setColMult([1, 1, 1, 1]);
this.prepareShader();
}
this.setColMult = function(color) {
gl.useProgram(this.nitroShader);
gl.uniform4fv(this.nitroShader.colMultUniform, color);
}
this.updateBillboards = function(view) {
this.billboardID = (this.billboardID+1)%0xFFFFFF;
var nv = mat4.clone(view);
nv[12] = 0;
nv[13] = 0;
nv[14] = 0; //nullify translation
var nv2 = mat4.clone(nv);
this.billboardMat = mat4.invert(nv, nv);
nv2[4] = 0;
nv2[5] = 1; //do not invert y axis view
nv2[6] = 0;
this.yBillboardMat = mat4.invert(nv2, nv2);
}
function renderDispList(disp, tex, startStack) { //renders the display list to a form of vertex buffer. The idea is that NSBTA and NSBCA can still be applied to the buffer at little performance cost. (rather than recompiling the model)
modelBuffer = {
strips: []
/* strip entry format:
vPos: glBuffer,
vTx: glBuffer,
vCol: glBuffer,
verts: int count of vertices,
mode: (eg. gl.TRIANGLES, gl.TRIANGLESTRIP)
mat: transformation matrix to apply. unused atm as matrix functions are unimplemented
*/
} //the nitroModel will store this and use it for rendering instead of the display list in future.
curMat = startStack; //start on root bone
var shader = nitroRender.nitroShader;
var gl = nitroRender.gl;
var off=0;
var view = new DataView(disp);
texWidth = tex.width;
texHeight = tex.height;
cVec = [0,0,0];
norm = [0,1,0];
texCoord = [0,0];
color = [1,1,1,alphaMul]; //todo: polygon attributes
vecMode = 0;
vecNum = 0;
vecPos = [];
vecNorm = [];
vecTx = [];
vecCol = [];
vecMat = [];
while (off < disp.byteLength) {
var ioff = off;
off += 4;
for (var i=0; i<4; i++) {
var inst = view.getUint8(ioff++);
if (instructions[inst] != null) {
instructions[inst](view, off);
} else {
if (inst != 0) alert("invalid instruction 0x"+(inst.toString(16)));
}
var temp = parameters[inst];
off += (temp == null)?0:temp*4;
}
}
if (optimiseTriangles) pushStrip();
return modelBuffer;
}
};
function nitroModel(bmd, btx, remap) {
var bmd = bmd;
this.bmd = bmd;
var thisObj = this;
var loadedTex;
var texCanvas;
var tex;
var texAnim;
var texFrame;
var modelBuffers;
var collisionModel = [];
var matBufEmpty = new Float32Array(31*16);
var temp = mat4.create();
var off=0;
for (var i=0; i<31; i++) {
matBufEmpty.set(temp, off);
off += 16;
}
temp = null;
var texMap = { tex:{}, pal:{} };
//var matStack;
this.draw = draw;
this.drawPoly = externDrawPoly;
this.drawModel = externDrawModel;
this.getCollisionModel = getCollisionModel;
modelBuffers = []
this.modelBuffers = modelBuffers;
var matBuf = [];
for (var i=0; i<bmd.modelData.objectData.length; i++) {
modelBuffers.push(new Array(bmd.modelData.objectData[i].polys.objectData.length));
matBuf.push({built: false, dat: new Float32Array(31*16)});
}
if (remap != null) {
setTextureRemap(remap)
}
if (btx != null) {
loadTexture(btx);
} else if (bmd.tex != null) {
loadTexture(bmd.tex)
} else {
loadWhiteTex();
}
function loadWhiteTex(btx) { //examines the materials in the loaded model and generates textures for each.
var gl = nitroRender.gl; //get gl object from nitro render singleton
loadedTex = btx;
texCanvas = [];
tex = [];
var models = bmd.modelData.objectData;
for (var j=0; j<models.length; j++) {
var model = models[j];
var mat = model.materials.objectData
for (var i=0; i<mat.length; i++) {
var m = mat[i];
var fC = document.createElement("canvas");
fC.width = 2;
fC.height = 2;
var ctx = fC.getContext("2d")
ctx.fillStyle = "black";
ctx.globalAlpha=0.33;
ctx.fillRect(0,0,2,2);
texCanvas.push(fC);
var t = loadTex(fC, gl, !m.repeatX, !m.repeatY);
t.realWidth = 2;
t.realHeight = 2;
tex.push(t);
}
}
}
function loadTexture(btx) { //examines the materials in the loaded model and generates textures for each.
var gl = nitroRender.gl; //get gl object from nitro render singleton
loadedTex = btx;
texCanvas = [];
tex = [];
var models = bmd.modelData.objectData;
for (var j=0; j<models.length; j++) {
var model = models[j];
var mat = model.materials.objectData
for (var i=0; i<mat.length; i++) {
var m = mat[i];
var texI = mat[i].tex;
var palI = mat[i].pal;
//remap below
var nTex = texMap.tex[texI];
var nPal = texMap.pal[palI];
if ((texI == null && nTex == null) || (palI == null && nPal == null)) {
debugger;
console.warn("WARNING: material "+i+" in model could not be assigned a texture.")
var fC = document.createElement("canvas");
fC.width = 2;
fC.height = 2;
var ctx = fC.getContext("2d")
ctx.fillStyle = "white";
ctx.fillRect(0,0,2,2);
texCanvas.push(fC);
var t = loadTex(fC, gl, !m.repeatX, !m.repeatY);
t.realWidth = 2;
t.realHeight = 2;
tex.push(t);
continue;
}
var truetex = (nTex==null)?texI:nTex;
var truepal = (nPal==null)?palI:nPal;
var cacheID = truetex+":"+truepal;
var cached = btx.cache[cacheID];
if (cached == null) {
var canvas = btx.readTexWithPal(truetex, truepal);
if (m.flipX || m.flipY) {
var fC = document.createElement("canvas");
var ctx = fC.getContext("2d");
fC.width = (m.flipX)?canvas.width*2:canvas.width;
fC.height = (m.flipY)?canvas.height*2:canvas.height;
ctx.drawImage(canvas, 0, 0);
ctx.save();
if (m.flipX) {
ctx.translate(2*canvas.width, 0);
ctx.scale(-1, 1);
ctx.drawImage(canvas, 0, 0);
ctx.restore();
ctx.save();
}
if (m.flipY) {
ctx.translate(0, 2*canvas.height);
ctx.scale(1, -1);
ctx.drawImage(fC, 0, 0);
ctx.restore();
}
texCanvas.push(fC);
var t = loadTex(fC, gl, !m.repeatX, !m.repeatY);
t.realWidth = canvas.width;
t.realHeight = canvas.height;
tex.push(t);
btx.cache[cacheID] = t;
} else {
texCanvas.push(canvas);
var t = loadTex(canvas, gl, !m.repeatX, !m.repeatY);
t.realWidth = canvas.width;
t.realHeight = canvas.height;
tex.push(t);
btx.cache[cacheID] = t;
}
} else {
tex.push(cached);
}
}
}
}
function setTextureRemap(remap) {
texMap = remap;
if (loadedTex != null) loadTexture(loadedTex)
}
this.loadTexAnim = function(bta) {
texAnim = bta;
texFrame = 0;
}
this.setFrame = function(frame) {
texFrame = frame;
}
function externDrawModel(mv, project, mdl) {
var models = bmd.modelData.objectData;
drawModel(models[mdl], mv, project, mdl);
}
function externDrawPoly(mv, project, modelind, poly, matStack) {
var models = bmd.modelData.objectData;
var model = models[modelind];
var polys = model.polys.objectData;
var matStack = matStack;
if (matStack == null) {
matStack = matBuf[modelind];
if (((thisObj.billboardID != nitroRender.billboardID) && bmd.hasBillboards) || (!matStack.built)) {
nitroRender.lastMatStack = null;
generateMatrixStack(model, matStack.dat);
matStack.built = true;
thisObj.billboardID = nitroRender.billboardID;
}
}
var shader = nitroRender.nitroShader;
var mv = mat4.scale([], mv, [model.head.scale, model.head.scale, model.head.scale]);
gl.uniformMatrix4fv(shader.mvMatrixUniform, false, mv);
gl.uniformMatrix4fv(shader.pMatrixUniform, false, project);
if (matStack != nitroRender.lastMatStack) {
gl.uniformMatrix4fv(shader.matStackUniform, false, matStack.dat);
nitroRender.lastMatStack = matStack;
}
drawPoly(polys[poly], modelind, poly);
}
function draw(mv, project, matStack) {
var models = bmd.modelData.objectData;
for (var j=0; j<models.length; j++) {
drawModel(models[j], mv, project, j, matStack);
}
}
function getCollisionModel(modelind, polyind) { //simple func to get collision model for a model. used when I'm too lazy to define my own... REQUIRES TRI MODE ACTIVE!
if (collisionModel[modelind] == null) collisionModel[modelind] = [];
if (collisionModel[modelind][polyind] != null) return collisionModel[modelind][polyind];
var model = bmd.modelData.objectData[modelind];
var poly = model.polys.objectData[polyind];
if (modelBuffers[modelind][polyind] == null) modelBuffers[modelind][polyind] = nitroRender.renderDispList(poly.disp, tex[poly.mat], (poly.stackID == null)?model.lastStackID:poly.stackID);
var tris = modelBuffers[modelind][polyind].strips[0].posArray;
var out = [];
var tC = tris.length/9;
var off = 0;
for (var i=0; i<tC; i++) {
var t = {}
t.Vertex1 = [tris[off++], tris[off++], tris[off++]];
t.Vertex2 = [tris[off++], tris[off++], tris[off++]];
t.Vertex3 = [tris[off++], tris[off++], tris[off++]];
//calculate normal
var v = vec3.sub([], t.Vertex2, t.Vertex1);
var w = vec3.sub([], t.Vertex3, t.Vertex1);
t.Normal = vec3.cross([], v, w)
vec3.normalize(t.Normal, t.Normal);
out.push(t);
}
collisionModel[modelind][polyind] = {dat:out, scale:model.head.scale};
return collisionModel[modelind][polyind];
}
function drawModel(model, mv, project, modelind, matStack) {
var polys = model.polys.objectData;
var matStack = matStack;
if (matStack == null) {
matStack = matBuf[modelind];
if (((thisObj.billboardID != nitroRender.billboardID) && bmd.hasBillboards) || (!matStack.built)) {
nitroRender.lastMatStack = null;
generateMatrixStack(model, matStack.dat);
matStack.built = true;
thisObj.billboardID = nitroRender.billboardID;
}
}
var shader = nitroRender.nitroShader;
var mv = mat4.scale([], mv, [model.head.scale, model.head.scale, model.head.scale]);
gl.uniformMatrix4fv(shader.mvMatrixUniform, false, mv);
gl.uniformMatrix4fv(shader.pMatrixUniform, false, project);
if (matStack != nitroRender.lastMatStack) {
gl.uniformMatrix4fv(shader.matStackUniform, false, matStack.dat);
nitroRender.lastMatStack = matStack;
}
for (var i=0; i<polys.length; i++) {
drawPoly(polys[i], modelind, i);
}
}
function drawPoly(poly, modelind, polyind) {
var shader = nitroRender.nitroShader;
var model = bmd.modelData.objectData[modelind];
var gl = nitroRender.gl;
//texture 0 SHOULD be bound, assuming the nitrorender program has been prepared
if (nitroRender.last.tex != tex[poly.mat]) {
gl.bindTexture(gl.TEXTURE_2D, tex[poly.mat]); //load up material texture
nitroRender.last.tex = tex[poly.mat];
}
var material = model.materials.objectData[poly.mat];
nitroRender.setAlpha(material.alpha)
if (texAnim != null) {
//generate and send texture matrix from data
var matname = model.materials.names[poly.mat]; //attach tex anim to mat with same name
var anims = texAnim.animData.objectData[modelind].data;
var animNum = anims.names.indexOf(matname);
if (animNum != -1) {
//we got a match! it's wonderful :')
var anim = anims.objectData[animNum];
var mat = mat3.create(); //material texture mat is ignored
mat3.scale(mat, mat, [anim.scaleS[(texFrame>>anim.frameStep.scaleS)%anim.scaleS.length], anim.scaleT[(texFrame>>anim.frameStep.scaleT)%anim.scaleT.length]]);
mat3.translate(mat, mat, [-anim.translateS[(texFrame>>anim.frameStep.translateS)%anim.translateS.length], anim.translateT[(texFrame>>anim.frameStep.translateT)%anim.translateT.length]]) //for some mystery reason I need to negate the S translation
gl.uniformMatrix3fv(shader.texMatrixUniform, false, mat);
} else {
gl.uniformMatrix3fv(shader.texMatrixUniform, false, material.texMat);
}
} else gl.uniformMatrix3fv(shader.texMatrixUniform, false, material.texMat);
if (modelBuffers[modelind][polyind] == null) modelBuffers[modelind][polyind] = nitroRender.renderDispList(poly.disp, tex[poly.mat], (poly.stackID == null)?model.lastStackID:poly.stackID);
drawModelBuffer(modelBuffers[modelind][polyind], gl, shader);
}
function generateMatrixStack(model, targ) { //this generates a matrix stack with the default bones. use nitroAnimator to pass custom matrix stacks using nsbca animations.
var matrices = [];
var objs = model.objects.objectData;
var cmds = model.commands;
var curMat = mat4.create();
var lastStackID = 0;
for (var i=0; i<cmds.length; i++) {
var cmd = cmds[i];
if (cmd.restoreID != null) curMat = mat4.clone(matrices[cmd.restoreID]);
var o = objs[cmd.obj];
mat4.multiply(curMat, curMat, o.mat);
if (o.billboardMode == 1) mat4.multiply(curMat, curMat, nitroRender.billboardMat);
if (o.billboardMode == 2) mat4.multiply(curMat, curMat, nitroRender.yBillboardMat);
if (cmd.stackID != null) {
matrices[cmd.stackID] = mat4.clone(curMat);
lastStackID = cmd.stackID;
} else {
matrices[lastStackID] = mat4.clone(curMat);
}
}
model.lastStackID = lastStackID;
targ.set(matBufEmpty);
var off=0;
for (var i=0; i<31; i++) {
if (matrices[i] != null) targ.set(matrices[i], off);
off += 16;
}
return targ;
}
function drawModelBuffer(buf, gl, shader) {
for (var i=0; i<buf.strips.length; i++) {
var obj = buf.strips[i];
if (obj != nitroRender.last.obj) {
gl.bindBuffer(gl.ARRAY_BUFFER, obj.vPos);
gl.vertexAttribPointer(shader.vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, obj.vTx);
gl.vertexAttribPointer(shader.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, obj.vCol);
gl.vertexAttribPointer(shader.colorAttribute, 4, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, obj.vMat);
gl.vertexAttribPointer(shader.matAttribute, 1, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, obj.vNorm);
gl.vertexAttribPointer(shader.normAttribute, 3, gl.FLOAT, false, 0, 0);
nitroRender.last.obj = obj;
}
gl.drawArrays(obj.mode, 0, obj.verts);
}
}
}
function loadTex(img, gl, clampx, clampy) { //general purpose function for loading an image into a texture.
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
if (clampx) gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
if (clampy) gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
texture.width = img.width;
texture.height = img.height;
gl.bindTexture(gl.TEXTURE_2D, null);
return texture;
}
+357
View File
@@ -0,0 +1,357 @@
//
// nitroShaders.js
//--------------------
// Dynamically compiles all shader modes of the nitro renderer.
// by RHY3756547
//
window.nitroShaders = new (function() {
var t = this;
this.defaultFrag = "precision highp float;\n\
\n\
varying vec2 vTextureCoord;\n\
varying vec4 color;\n\
\n\
uniform sampler2D uSampler;\n\
\n\
void main(void) {\n\
gl_FragColor = texture2D(uSampler, vTextureCoord)*color;\n\
if (gl_FragColor.a == 0.0) discard;\n\
}"
this.defaultVert = "attribute vec3 aVertexPosition;\n\
attribute vec2 aTextureCoord;\n\
attribute vec4 aColor;\n\
attribute float matrixID;\n\
attribute vec3 aNormal;\n\
\n\
uniform mat4 uMVMatrix;\n\
uniform mat4 uPMatrix;\n\
uniform mat3 texMatrix;\n\
uniform mat4 matStack[16];\n\
\n\
uniform vec4 colMult;\n\
\n\
varying vec2 vTextureCoord;\n\
varying vec4 color;\n\
\n\
\n\
void main(void) {\n\
gl_Position = uPMatrix * uMVMatrix * matStack[int(matrixID)] * vec4(aVertexPosition, 1.0);\n\
vTextureCoord = (texMatrix * vec3(aTextureCoord, 1.0)).xy;\n\
vec3 adjNorm = normalize(vec3(uMVMatrix * matStack[int(matrixID)] * vec4(aNormal, 0.0)));\n\
float diffuse = 0.7-dot(adjNorm, vec3(0.0, -1.0, 0.0))*0.3;\n\
\n\
color = aColor*colMult;\n\
color = vec4(color.x*diffuse, color.y*diffuse, color.z*diffuse, color.w);\n\
}"
this.shadFrag = "precision highp float;\n\
\n\
varying vec2 vTextureCoord;\n\
varying vec4 color;\n\
varying vec4 lightDist;\n\
varying vec4 fLightDist;\n\
\n\
uniform float shadOff; \n\
uniform float farShadOff; \n\
uniform sampler2D lightDSampler;\n\
uniform sampler2D farLightDSampler;\n\
\n\
uniform sampler2D uSampler;\n\
\n\
float shadowCompare(sampler2D map, vec2 pos, float compare) {\n\
float depth = texture2D(map, pos).r;\n\
return step(compare, depth);\n\
}\n\
\n\
float shadowLerp(sampler2D depths, vec2 size, vec2 uv, float compare){\n\
vec2 texelSize = vec2(1.0)/size;\n\
vec2 f = fract(uv*size+0.5);\n\
vec2 centroidUV = floor(uv*size+0.5)/size;\n\
\n\
float lb = shadowCompare(depths, centroidUV+texelSize*vec2(0.0, 0.0), compare);\n\
float lt = shadowCompare(depths, centroidUV+texelSize*vec2(0.0, 1.0), compare);\n\
float rb = shadowCompare(depths, centroidUV+texelSize*vec2(1.0, 0.0), compare);\n\
float rt = shadowCompare(depths, centroidUV+texelSize*vec2(1.0, 1.0), compare);\n\
float a = mix(lb, lt, f.y);\n\
float b = mix(rb, rt, f.y);\n\
float c = mix(a, b, f.x);\n\
return c;\n\
}\n\
\n\
void main(void) {\n\
vec4 col = texture2D(uSampler, vTextureCoord)*color;\n\
\n\
vec2 ldNorm = abs((lightDist.xy)-vec2(0.5, 0.5));\n\
float dist = max(ldNorm.x, ldNorm.y);\n\
\n\
if (dist > 0.5) {\n\
gl_FragColor = col*mix(vec4(0.5, 0.5, 0.7, 1.0), vec4(1.0, 1.0, 1.0, 1.0), shadowLerp(farLightDSampler, vec2(4096.0, 4096.0), fLightDist.xy, fLightDist.z-farShadOff));\n\
} else if (dist > 0.4) {\n\
float lerp1 = shadowLerp(farLightDSampler, vec2(4096.0, 4096.0), fLightDist.xy, fLightDist.z-farShadOff);\n\
float lerp2 = shadowLerp(lightDSampler, vec2(2048.0, 2048.0), lightDist.xy, lightDist.z-shadOff);\n\
\n\
gl_FragColor = col*mix(vec4(0.5, 0.5, 0.7, 1.0), vec4(1.0, 1.0, 1.0, 1.0), mix(lerp2, lerp1, (dist-0.4)*10.0));\n\
} else {\n\
gl_FragColor = col*mix(vec4(0.5, 0.5, 0.7, 1.0), vec4(1.0, 1.0, 1.0, 1.0), shadowLerp(lightDSampler, vec2(2048.0, 2048.0), lightDist.xy, lightDist.z-shadOff));\n\
}\n\
\n\
if (gl_FragColor.a == 0.0) discard;\n\
}\n\
"
this.shadVert = "attribute vec3 aVertexPosition;\n\
attribute vec2 aTextureCoord;\n\
attribute vec4 aColor;\n\
attribute float matrixID;\n\
attribute vec3 aNormal;\n\
\n\
uniform mat4 uMVMatrix;\n\
uniform mat4 uPMatrix;\n\
uniform mat3 texMatrix;\n\
uniform mat4 matStack[16];\n\
\n\
uniform vec4 colMult;\n\
\n\
uniform mat4 shadowMat;\n\
uniform mat4 farShadowMat;\n\
\n\
varying vec2 vTextureCoord;\n\
varying vec4 color;\n\
varying vec4 lightDist;\n\
varying vec4 fLightDist;\n\
\n\
\n\
void main(void) {\n\
vec4 pos = uMVMatrix * matStack[int(matrixID)] * vec4(aVertexPosition, 1.0);\n\
gl_Position = uPMatrix * pos;\n\
vTextureCoord = (texMatrix * vec3(aTextureCoord, 1.0)).xy;\n\
\n\
lightDist = (shadowMat*pos + vec4(1, 1, 1, 0)) / 2.0;\n\
fLightDist = (farShadowMat*pos + vec4(1, 1, 1, 0)) / 2.0;\n\
vec3 adjNorm = normalize(vec3(uMVMatrix * matStack[int(matrixID)] * vec4(aNormal, 0.0)));\n\
float diffuse = 0.7-dot(adjNorm, vec3(0.0, -1.0, 0.0))*0.3;\n\
\n\
color = aColor*colMult;\n\
color = vec4(color.x*diffuse, color.y*diffuse, color.z*diffuse, color.w);\n\
}"
var dFrag = {
begin: "precision highp float;\n\
\n\
varying vec2 vTextureCoord;\n\
varying vec4 color;\n\
\n\
uniform sampler2D uSampler;\n",
main: "\n\
gl_FragColor = texture2D(uSampler, vTextureCoord)*color;\n\
if (gl_FragColor.a == 0.0) discard;\n",
extra: "",
}
var dVert = {
begin: "attribute vec3 aVertexPosition;\n\
attribute vec2 aTextureCoord;\n\
attribute vec4 aColor;\n\
attribute float matrixID;\n\
\n\
uniform mat4 uMVMatrix;\n\
uniform mat4 uPMatrix;\n\
uniform mat3 texMatrix;\n\
uniform mat4 matStack[16];\n\
\n\
uniform vec4 colMult;\n\
\n\
varying vec2 vTextureCoord;\n\
varying vec4 color;\n\
\n\
\n",
main: "\n\
vec4 pos = uMVMatrix * matStack[int(matrixID)] * vec4(aVertexPosition, 1.0);\n\
gl_Position = uPMatrix * pos;\n\
vTextureCoord = (texMatrix * vec3(aTextureCoord, 1.0)).xy;\n\
\n\
lightDist = (shadowMat*pos + vec4(1, 1, 1, 0)) / 2.0;\n\
fLightDist = (farShadowMat*pos + vec4(1, 1, 1, 0)) / 2.0;\n\
\n\
color = aColor*colMult;\n\
",
extra: ""
}
var lightVert = {
begin: "attribute vec3 aNormal;\n",
main: "vec3 adjNorm = normalize(vec3(uMVMatrix * matStack[int(matrixID)] * vec4(aNormal, 0.0)));\n\
float diffuse = 0.7-dot(adjNorm, vec3(0.0, -1.0, 0.0))*0.3;\n\
color = vec4(color.x*diffuse, color.y*diffuse, color.z*diffuse, color.w);\n",
extra: ""
}
var lightFrag = {
begin: "",
main:"",
end:""
}
var sdVert = {
begin: "uniform mat4 shadowMat;\n\
uniform mat4 farShadowMat;\n\
\n\
varying vec4 lightDist;\n\
varying vec4 fLightDist;\n",
main: "lightDist = (shadowMat*pos + vec4(1, 1, 1, 0)) / 2.0;\n\
fLightDist = (farShadowMat*pos + vec4(1, 1, 1, 0)) / 2.0;\n"
}
var sdFrag = {
begin: "varying vec4 lightDist;\n\
varying vec4 fLightDist;\n\
\n\
uniform float shadOff; \n\
uniform float farShadOff; \n\
uniform sampler2D lightDSampler;\n\
uniform sampler2D farLightDSampler;\n",
main: "if (lightDist.x<0.0 || lightDist.y<0.0 || lightDist.x>1.0 || lightDist.y>1.0) {\n\
if (texture2D(farLightDSampler, fLightDist.xy).r+farShadOff < fLightDist.z) {\n\
gl_FragColor = gl_FragColor*vec4(0.5, 0.5, 0.7, 1);\n\
}\n\
} else {\n\
if (texture2D(lightDSampler, lightDist.xy).r+shadOff < lightDist.z) {\n\
gl_FragColor = gl_FragColor*vec4(0.5, 0.5, 0.7, 1);\n\
}\n\
}\n",
extra: ""
}
var baseConf = {
frag: this.defaultFrag, vert: this.defaultVert,
uniforms: [
["pMatrixUniform", "uPMatrix"],
["matStackUniform", "matStack"],
["mvMatrixUniform", "uMVMatrix"],
["texMatrixUniform", "texMatrix"],
["samplerUniform", "uSampler"],
["colMultUniform", "colMult"],
],
attributes: [
["vertexPositionAttribute", "aVertexPosition"],
["textureCoordAttribute", "aTextureCoord"],
["colorAttribute", "aColor"],
["matAttribute", "matrixID"],
["normAttribute", "aNormal"]
]
};
var config = [];
var fragParts = [
dFrag,
lightFrag,
sdFrag
]
var shadUnif = [
["shadowMatUniform", "shadowMat"],
["farShadowMatUniform", "farShadowMat"],
["shadOffUniform", "shadOff"],
["farShadOffUniform", "farShadOff"],
["lightSamplerUniform", "lightDSampler"],
["farLightSamplerUniform", "farLightDSampler"]
]
config[0] = baseConf;
config[1] = {frag: this.shadFrag, vert: this.shadVert, uniforms: baseConf.uniforms.slice(0), attributes: baseConf.attributes.slice(0)};
config[1].uniforms = config[1].uniforms.concat(shadUnif);
function makeShader(source, base, id) { //makes shaders using flags
}
function combineGLSL(shaderParts) {
var out = "";
for (var i=0; i<shaderParts.length; i++) out += shaderParts[i].begin;
out += "\nvoid main(void) {\n";
for (var i=0; i<shaderParts.length; i++) out += shaderParts[i].main;
out += "\n}\n";
for (var i=0; i<shaderParts.length; i++) out += shaderParts[i].extra;
return out;
}
this.compileShaders = function(gl) {
t.shaders = [];
for (var i=0; i<config.length; i++) {
var conf = config[i];
frag = getShader(gl, conf.frag, "frag");
vert = getShader(gl, conf.vert, "vert");
var shader = gl.createProgram();
gl.attachShader(shader, vert);
gl.attachShader(shader, frag);
gl.linkProgram(shader);
if (!gl.getProgramParameter(shader, gl.LINK_STATUS)) {
alert("Could not initialise shaders");
}
for (var j=0; j<conf.attributes.length; j++) {
var a = conf.attributes[j];
shader[a[0]] = gl.getAttribLocation(shader, a[1]);
gl.enableVertexAttribArray(shader[a[0]]);
}
for (var j=0; j<conf.uniforms.length; j++) {
var a = conf.uniforms[j];
shader[a[0]] = gl.getUniformLocation(shader, a[1]);
}
t.shaders.push(shader);
}
return t.shaders;
}
function getShader(gl, str, type) {
var shader;
if (type == "frag") {
shader = gl.createShader(gl.FRAGMENT_SHADER);
} else if (type == "vert") {
shader = gl.createShader(gl.VERTEX_SHADER);
} else {
return null;
}
gl.shaderSource(shader, str);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
})();
+193
View File
@@ -0,0 +1,193 @@
//
// shadowRender.js
//--------------------
// Provides a shader to draw a shadowed scene using a depth and color texture. (plus depth texture for light source)
// by RHY3756547
//
window.shadowRender = new function() {
var shadFrag = "precision highp float;\n\
\n\
varying vec2 vTextureCoord;\n\
varying vec4 color;\n\
\n\
uniform sampler2D cSampler;\n\
uniform sampler2D depSampler;\n\
uniform sampler2D lightDSampler;\n\
uniform sampler2D farLightDSampler;\n\
\n\
uniform mat4 shadowMat;\n\
uniform mat4 farShadowMat;\n\
uniform mat4 invViewProj;\n\
\n\
\n\
vec3 positionFromDepth(vec2 vTex)\n\
{\n\
float z = texture2D(depSampler, vTex).r * 2.0 - 1.0;\n\
float x = vTex.x * 2.0 - 1.0;\n\
float y = vTex.y * 2.0 - 1.0;\n\
vec4 vProjectedPos = vec4(x, y, z, 1.0);\n\
\n\
// Transform by the inverse projection matrix\n\
vec4 vPositionVS = invViewProj*vProjectedPos;\n\
\n\
// Divide by w to get the view-space position\n\
return vPositionVS.xyz/vPositionVS.w;\n\
}\n\
\n\
void main(void) {\n\
vec3 pos = positionFromDepth(vTextureCoord);\n\
vec4 col = texture2D(cSampler, vTextureCoord);\n\
\n\
vec4 lightDist = (shadowMat*vec4(pos, 1.0) + vec4(1, 1, 1, 0)) / 2.0;\n\
if (lightDist.x<0.0 || lightDist.y<0.0 || lightDist.x>1.0 || lightDist.y>1.0) {\n\
vec4 flightDist = (farShadowMat*vec4(pos, 1.0) + vec4(1, 1, 1, 0)) / 2.0;\n\
if (texture2D(farLightDSampler, flightDist.xy).r+0.0005 < flightDist.z) {\n\
gl_FragColor = col*vec4(0.5, 0.5, 0.7, 1);\n\
} else {\n\
gl_FragColor = col;\n\
}\n\
} else {\n\
\n\
if (texture2D(lightDSampler, lightDist.xy).r+0.00005 < lightDist.z) {\n\
gl_FragColor = col*vec4(0.5, 0.5, 0.7, 1);\n\
} else {\n\
gl_FragColor = col;\n\
}\n\
}\n\
\n\
if (gl_FragColor.a == 0.0) discard;\n\
}\n\
\n\
"
var shadVert = "attribute vec3 aVertexPosition;\n\
attribute vec2 aTextureCoord;\n\
\n\
varying vec2 vTextureCoord;\n\
\n\
void main(void) {\n\
gl_Position = vec4(aVertexPosition, 1.0);\n\
vTextureCoord = vec3(aTextureCoord, 1.0).xy;\n\
}"
var shadowShader, vecPosBuffer, vecTxBuffer;
this.drawShadowed = drawShadowed;
this.init = function(ctx) {
gl = ctx;
this.gl = gl;
frag = getShader(shadFrag, "frag");
vert = getShader(shadVert, "vert");
shadowShader = gl.createProgram();
gl.attachShader(shadowShader, vert);
gl.attachShader(shadowShader, frag);
gl.linkProgram(shadowShader);
if (!gl.getProgramParameter(shadowShader, gl.LINK_STATUS)) {
alert("Could not initialise shaders");
}
shadowShader.vertexPositionAttribute = gl.getAttribLocation(shadowShader, "aVertexPosition");
gl.enableVertexAttribArray(shadowShader.vertexPositionAttribute);
shadowShader.textureCoordAttribute = gl.getAttribLocation(shadowShader, "aTextureCoord");
gl.enableVertexAttribArray(shadowShader.textureCoordAttribute);
shadowShader.colTexUniform = gl.getUniformLocation(shadowShader, "cSampler");
shadowShader.depTexUniform = gl.getUniformLocation(shadowShader, "depSampler");
shadowShader.lightTexUniform = gl.getUniformLocation(shadowShader, "lightDSampler");
shadowShader.lightFarTexUniform = gl.getUniformLocation(shadowShader, "farLightDSampler");
shadowShader.lightViewUniform = gl.getUniformLocation(shadowShader, "shadowMat");
shadowShader.lightFarViewUniform = gl.getUniformLocation(shadowShader, "farShadowMat");
shadowShader.camViewUniform = gl.getUniformLocation(shadowShader, "invViewProj");
this.shadowShader = shadowShader;
vecPosBuffer = gl.createBuffer();
vecTxBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vecPosBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(
[-1, -1, 0,
1, -1, 0,
1, 1, 0,
1, 1, 0,
-1, 1, 0,
-1, -1, 0,
]
), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, vecTxBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(
[
0, 0,
1, 0,
1, 1,
1, 1,
0, 1,
0, 0,
]
), gl.STATIC_DRAW);
}
function getShader(str, type) {
var shader;
if (type == "frag") {
shader = gl.createShader(gl.FRAGMENT_SHADER);
} else if (type == "vert") {
shader = gl.createShader(gl.VERTEX_SHADER);
} else {
return null;
}
gl.shaderSource(shader, str);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
function drawShadowed(colTex, depTex, lightTex, lightFarTex, camView, lightView, lightFarView) {
var shader = shadowShader;
gl.useProgram(shader);
gl.uniformMatrix4fv(shader.lightViewUniform, false, lightView);
gl.uniformMatrix4fv(shader.lightFarViewUniform, false, lightFarView);
gl.uniformMatrix4fv(shader.camViewUniform, false, mat4.invert(mat4.create(), camView));
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, lightTex); //load up material texture
gl.uniform1i(shader.lightTexUniform, 0);
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, colTex); //load up material texture
gl.uniform1i(shader.colTexUniform, 1);
gl.activeTexture(gl.TEXTURE2);
gl.bindTexture(gl.TEXTURE_2D, depTex); //load up material texture
gl.uniform1i(shader.depTexUniform, 2);
gl.activeTexture(gl.TEXTURE3);
gl.bindTexture(gl.TEXTURE_2D, lightFarTex); //load up material texture
gl.uniform1i(shader.lightFarTexUniform, 3);
gl.bindBuffer(gl.ARRAY_BUFFER, vecPosBuffer);
gl.vertexAttribPointer(shader.vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, vecTxBuffer);
gl.vertexAttribPointer(shader.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, 6);
}
}