Looks like I have to clean this out...
This commit is contained in:
1 parent
7e213690c8
commit
a16ba9a907
192 files changed
-40154
No files matched your search
@@ -1,244 +0,0 @@
|
||||
//
|
||||
// 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,
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,741 +0,0 @@
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
@@ -1,357 +0,0 @@
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
|
||||
})();
|
||||
@@ -1,193 +0,0 @@
|
||||
//
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user