Greatly improve shading model
- Directional toon lighting component on entities. (extension of the shadow light source) The shadows were doing this anyways, but with extremely bad stairstepping. Now it smoothly blends into the shadow. - Greatly reduce shadow acne via the above and a larger bias. - Respect culling mode for each model. - Two sided shading for course models. - Disable alpha for water that does not use it. - Only GBA Sky Garden's skybox receives shadows now. - Custom light positions for some maps. (you can guess which)gh-pages
parent
f583ad11b1
commit
bbb61394f4
|
@ -14,53 +14,53 @@ window.MKDSCONST = new (function() {
|
||||||
this.COURSEDIR = "/data/Course/";
|
this.COURSEDIR = "/data/Course/";
|
||||||
|
|
||||||
this.COURSES = [ //in order of course id, nitro through retro
|
this.COURSES = [ //in order of course id, nitro through retro
|
||||||
"cross_course",
|
{name:"cross_course", music: 74},
|
||||||
"bank_course",
|
{name:"bank_course", music: 16},
|
||||||
"beach_course",
|
{name:"beach_course", music: 15},
|
||||||
"mansion_course",
|
{name:"mansion_course", music: 21, lightHeight: 20/180, lightAngle: 160/180},
|
||||||
|
|
||||||
"desert_course",
|
{name:"desert_course", music: 38, lightHeight: 40/180},
|
||||||
"town_course",
|
{name:"town_course", music: 17},
|
||||||
"pinball_course",
|
{name:"pinball_course", music: 19},
|
||||||
"ridge_course",
|
{name:"ridge_course", music: 36},
|
||||||
|
|
||||||
"snow_course",
|
{name:"snow_course", music: 37},
|
||||||
"clock_course",
|
{name:"clock_course", music: 39},
|
||||||
"mario_course",
|
{name:"mario_course", music: 74},
|
||||||
"airship_course",
|
{name:"airship_course", music: 18, lightHeight: 40/180, lightAngle: 140/180},
|
||||||
|
|
||||||
"stadium_course",
|
{name:"stadium_course", music: 19},
|
||||||
"garden_course",
|
{name:"garden_course", music: 20},
|
||||||
"koopa_course",
|
{name:"koopa_course", music: 40},
|
||||||
"rainbow_course",
|
{name:"rainbow_course", music: 41},
|
||||||
|
|
||||||
|
|
||||||
"old_mario_sfc",
|
{name:"old_mario_sfc", music: 22},
|
||||||
"old_momo_64",
|
{name:"old_momo_64", music: 30},
|
||||||
"old_peach_agb",
|
{name:"old_peach_agb", music: 26},
|
||||||
"old_luigi_gc",
|
{name:"old_luigi_gc", music: 33},
|
||||||
|
|
||||||
"old_donut_sfc",
|
{name:"old_donut_sfc", music: 24},
|
||||||
"old_frappe_64",
|
{name:"old_frappe_64", music: 31},
|
||||||
"old_koopa_agb",
|
{name:"old_koopa_agb", music: 27},
|
||||||
"old_baby_gc",
|
{name:"old_baby_gc", music: 34},
|
||||||
|
|
||||||
"old_noko_sfc",
|
{name:"old_noko_sfc", music: 23},
|
||||||
"old_choco_64",
|
{name:"old_choco_64", music: 29},
|
||||||
"old_luigi_agb",
|
{name:"old_luigi_agb", music: 26},
|
||||||
"old_kinoko_gc",
|
{name:"old_kinoko_gc", music: 35},
|
||||||
|
|
||||||
"old_choco_sfc",
|
{name:"old_choco_sfc", music: 25},
|
||||||
"old_hyudoro_64",
|
{name:"old_hyudoro_64", music: 32},
|
||||||
"old_sky_agb",
|
{name:"old_sky_agb", music: 28, skyboxShadows: true},
|
||||||
"old_yoshi_gc",
|
{name:"old_yoshi_gc", music: 33, lightHeight: 30/180, lightAngle: 111/180},
|
||||||
|
|
||||||
"mini_stage1",
|
{name:"mini_stage1", music: 43, battle: true},
|
||||||
"mini_stage2",
|
{name:"mini_stage2", music: 43, battle: true, lightHeight: 20/180, lightAngle: 160/180},
|
||||||
"mini_stage3",
|
{name:"mini_stage3", music: 43, battle: true},
|
||||||
"mini_stage4",
|
{name:"mini_stage4", music: 43, battle: true},
|
||||||
"mini_block_64",
|
{name:"mini_block_64", music: 43, battle: true},
|
||||||
"mini_dokan_gc"
|
{name:"mini_dokan_gc", music: 43, battle: true}
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -88,11 +88,11 @@ window.clientScene = function(wsUrl, wsInstance, res) {
|
||||||
var mainNarc, texNarc
|
var mainNarc, texNarc
|
||||||
if (obj.c.substr(0, 5) == "mkds/") {
|
if (obj.c.substr(0, 5) == "mkds/") {
|
||||||
var cnum = Number(obj.c.substr(5));
|
var cnum = Number(obj.c.substr(5));
|
||||||
var music = MKDSCONST.COURSE_MUSIC[cnum];
|
var course = MKDSCONST.COURSE[cnum];
|
||||||
var cDir = MKDSCONST.COURSEDIR+MKDSCONST.COURSES[cnum];
|
var cDir = MKDSCONST.COURSEDIR+course.name;
|
||||||
var mainNarc = new narc(lz77.decompress(gameROM.getFile(cDir+".carc")));
|
var mainNarc = new narc(lz77.decompress(gameROM.getFile(cDir+".carc")));
|
||||||
var texNarc = new narc(lz77.decompress(gameROM.getFile(cDir+"Tex.carc")));
|
var texNarc = new narc(lz77.decompress(gameROM.getFile(cDir+"Tex.carc")));
|
||||||
setUpCourse(mainNarc, texNarc, music, obj)
|
setUpCourse(mainNarc, texNarc, course, obj)
|
||||||
}
|
}
|
||||||
else throw "custom tracks are not implemented yet!"
|
else throw "custom tracks are not implemented yet!"
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ window.clientScene = function(wsUrl, wsInstance, res) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setUpCourse(mainNarc, texNarc, music, obj) {
|
function setUpCourse(mainNarc, texNarc, course, obj) {
|
||||||
var chars = [];
|
var chars = [];
|
||||||
for (var i=0; i<obj.k.length; i++) {
|
for (var i=0; i<obj.k.length; i++) {
|
||||||
var k = obj.k[i];
|
var k = obj.k[i];
|
||||||
|
@ -142,7 +142,7 @@ window.clientScene = function(wsUrl, wsInstance, res) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
t.activeScene = new courseScene(mainNarc, texNarc, music, chars, {}, res);
|
t.activeScene = new courseScene(mainNarc, texNarc, course, chars, {}, res);
|
||||||
|
|
||||||
for (var i=0; i<obj.k.length; i++) {
|
for (var i=0; i<obj.k.length; i++) {
|
||||||
t.activeScene.karts[i].active = obj.k[i].active;
|
t.activeScene.karts[i].active = obj.k[i].active;
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
// render/*
|
// render/*
|
||||||
//
|
//
|
||||||
|
|
||||||
window.courseScene = function(mainNarc, texNarc, music, chars, options, gameRes) {
|
window.courseScene = function(mainNarc, texNarc, courseObj, chars, options, gameRes) {
|
||||||
|
var music = courseObj.music;
|
||||||
var startSetups = [
|
var startSetups = [
|
||||||
{maxplayers:12, toAline:4, xspacing:32, yspacing:32, liney:160},
|
{maxplayers:12, toAline:4, xspacing:32, yspacing:32, liney:160},
|
||||||
{maxplayers:24, toAline:4, xspacing:32, yspacing:32, liney:80},
|
{maxplayers:24, toAline:4, xspacing:32, yspacing:32, liney:80},
|
||||||
|
@ -112,12 +112,18 @@ window.courseScene = function(mainNarc, texNarc, music, chars, options, gameRes)
|
||||||
if (!shadow) {
|
if (!shadow) {
|
||||||
var skyMat = mat4.scale(mat4.create(), mvMatrix, [1/64, 1/64, 1/64]);
|
var skyMat = mat4.scale(mat4.create(), mvMatrix, [1/64, 1/64, 1/64]);
|
||||||
sky.setFrame(frame);
|
sky.setFrame(frame);
|
||||||
|
if (!courseObj.skyboxShadows) nitroRender.setLightIntensities(0, 0);
|
||||||
sky.draw(skyMat, pMatrix);
|
sky.draw(skyMat, pMatrix);
|
||||||
|
if (!courseObj.skyboxShadows) nitroRender.setLightIntensities();
|
||||||
}
|
}
|
||||||
|
|
||||||
var lvlMat = mat4.scale(mat4.create(), mvMatrix, [1/64, 1/64, 1/64]);//[2, 2, 2]);
|
var lvlMat = mat4.scale(mat4.create(), mvMatrix, [1/64, 1/64, 1/64]);//[2, 2, 2]);
|
||||||
course.setFrame(frame);
|
course.setFrame(frame);
|
||||||
|
nitroRender.forceFlatNormals = true;
|
||||||
|
nitroRender.setLightIntensities(0);
|
||||||
course.draw(lvlMat, pMatrix);
|
course.draw(lvlMat, pMatrix);
|
||||||
|
nitroRender.setLightIntensities();
|
||||||
|
nitroRender.forceFlatNormals = false;
|
||||||
|
|
||||||
var transE = [];
|
var transE = [];
|
||||||
|
|
||||||
|
@ -139,13 +145,14 @@ window.courseScene = function(mainNarc, texNarc, music, chars, options, gameRes)
|
||||||
else e.draw(mvMatrix, pMatrix, gl);
|
else e.draw(mvMatrix, pMatrix, gl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nitroRender.setLightIntensities(0);
|
||||||
for (var i=0; i<scn.particles.length; i++) {
|
for (var i=0; i<scn.particles.length; i++) {
|
||||||
var e = scn.particles[i];
|
var e = scn.particles[i];
|
||||||
e.draw(mvMatrix, pMatrix, gl);
|
e.draw(mvMatrix, pMatrix, gl);
|
||||||
}
|
}
|
||||||
|
|
||||||
scn.items.draw(mvMatrix, pMatrix, gl);
|
scn.items.draw(mvMatrix, pMatrix, gl);
|
||||||
|
nitroRender.setLightIntensities();
|
||||||
}
|
}
|
||||||
|
|
||||||
function sndUpdate(view) {
|
function sndUpdate(view) {
|
||||||
|
@ -249,8 +256,11 @@ window.courseScene = function(mainNarc, texNarc, music, chars, options, gameRes)
|
||||||
function startCourse() {
|
function startCourse() {
|
||||||
scn.lightMat = mat4.create();
|
scn.lightMat = mat4.create();
|
||||||
|
|
||||||
mat4.rotateX(scn.lightMat, scn.lightMat, Math.PI*(61/180));
|
mat4.rotateX(scn.lightMat, scn.lightMat, Math.PI*(courseObj.lightHeight || (61/180)));
|
||||||
mat4.rotateY(scn.lightMat, scn.lightMat, Math.PI*(21/180));
|
mat4.rotateY(scn.lightMat, scn.lightMat, Math.PI*(courseObj.lightAngle || (21/180)));
|
||||||
|
scn.lightDir = [0, 0, 1];
|
||||||
|
vec3.transformMat3(scn.lightDir, scn.lightDir, mat3.invert([], mat3.fromMat4([], scn.lightMat)));
|
||||||
|
|
||||||
scn.farShadMat = mat4.create();
|
scn.farShadMat = mat4.create();
|
||||||
mat4.translate(scn.farShadMat, scn.lightMat, getLightCenter());
|
mat4.translate(scn.farShadMat, scn.lightMat, getLightCenter());
|
||||||
|
|
||||||
|
@ -408,7 +418,7 @@ window.courseScene = function(mainNarc, texNarc, music, chars, options, gameRes)
|
||||||
switch (mode.id) {
|
switch (mode.id) {
|
||||||
case 0:
|
case 0:
|
||||||
//race init. fade scene in and play init music.
|
//race init. fade scene in and play init music.
|
||||||
nitroAudio.playSound(11, {volume:2}, null); //7:race (gp), 11:race2 (vs), 12:battle
|
nitroAudio.playSound((courseObj.battle)?12:11, {volume:2}, null); //7:race (gp), 11:race2 (vs), 12:battle
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
//spawn lakitu and countdown animation. allow pre-acceleration.
|
//spawn lakitu and countdown animation. allow pre-acceleration.
|
||||||
|
|
|
@ -84,7 +84,7 @@ window.sceneDrawer = new function() {
|
||||||
gl.colorMask(false, false, false, false);
|
gl.colorMask(false, false, false, false);
|
||||||
scn.draw(gl, shadMat, true);
|
scn.draw(gl, shadMat, true);
|
||||||
|
|
||||||
nitroRender.setShadowMode(shadowTarg.depth, scn.farShad.depth, shadMat, scn.farShadMat);
|
nitroRender.setShadowMode(shadowTarg.depth, scn.farShad.depth, shadMat, scn.farShadMat, scn.lightDir);
|
||||||
nitroRender.flagShadow = false;
|
nitroRender.flagShadow = false;
|
||||||
|
|
||||||
nitroRender.updateBillboards(view.mv);
|
nitroRender.updateBillboards(view.mv);
|
||||||
|
|
|
@ -52,16 +52,16 @@ window.singleScene = function(course, wsInstance, res) {
|
||||||
var mainNarc, texNarc
|
var mainNarc, texNarc
|
||||||
if (course.substr(0, 5) == "mkds/") {
|
if (course.substr(0, 5) == "mkds/") {
|
||||||
var cnum = Number(course.substr(5));
|
var cnum = Number(course.substr(5));
|
||||||
var music = MKDSCONST.COURSE_MUSIC[cnum];
|
var course = MKDSCONST.COURSES[cnum];
|
||||||
var cDir = MKDSCONST.COURSEDIR+MKDSCONST.COURSES[cnum];
|
var cDir = MKDSCONST.COURSEDIR+course.name;
|
||||||
var mainNarc = new narc(lz77.decompress(gameROM.getFile(cDir+".carc")));
|
var mainNarc = new narc(lz77.decompress(gameROM.getFile(cDir+".carc")));
|
||||||
var texNarc = new narc(lz77.decompress(gameROM.getFile(cDir+"Tex.carc")));
|
var texNarc = new narc(lz77.decompress(gameROM.getFile(cDir+"Tex.carc")));
|
||||||
setUpCourse(mainNarc, texNarc, music)
|
setUpCourse(mainNarc, texNarc, course)
|
||||||
} else throw "custom tracks are not implemented yet!"
|
} else throw "custom tracks are not implemented yet!"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function setUpCourse(mainNarc, texNarc, music) {
|
function setUpCourse(mainNarc, texNarc, course) {
|
||||||
var chars = [];
|
var chars = [];
|
||||||
chars.push({charN:mchar, kartN:mkart, controller:((window.prompt("press y for cpu controlled") == "y")?controlRaceCPU:controlDefault), raceCam:true, extraParams:[{k:"name", v:"single"}, {k:"active", v:true}]});
|
chars.push({charN:mchar, kartN:mkart, controller:((window.prompt("press y for cpu controlled") == "y")?controlRaceCPU:controlDefault), raceCam:true, extraParams:[{k:"name", v:"single"}, {k:"active", v:true}]});
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ window.singleScene = function(course, wsInstance, res) {
|
||||||
chars.push({charN:tchar, kartN:tkart, controller:controlRaceCPU, raceCam:false, extraParams:[{k:"name", v:"no"}, {k:"active", v:true}]});
|
chars.push({charN:tchar, kartN:tkart, controller:controlRaceCPU, raceCam:false, extraParams:[{k:"name", v:"no"}, {k:"active", v:true}]});
|
||||||
}
|
}
|
||||||
|
|
||||||
t.activeScene = new courseScene(mainNarc, texNarc, music, chars, {}, res);
|
t.activeScene = new courseScene(mainNarc, texNarc, course, chars, {}, res);
|
||||||
|
|
||||||
t.myKart = t.activeScene.karts[0];
|
t.myKart = t.activeScene.karts[0];
|
||||||
t.mode = {
|
t.mode = {
|
||||||
|
|
|
@ -31,6 +31,7 @@ window.ObjDecor = function(obji, scene) {
|
||||||
var animMat = null;
|
var animMat = null;
|
||||||
|
|
||||||
function draw(view, pMatrix) {
|
function draw(view, pMatrix) {
|
||||||
|
if (forceBill) nitroRender.setShadBias(0.001);
|
||||||
mat4.translate(mat, view, t.pos);
|
mat4.translate(mat, view, t.pos);
|
||||||
|
|
||||||
if (t.angle[2] != 0) mat4.rotateZ(mat, mat, t.angle[2]*(Math.PI/180));
|
if (t.angle[2] != 0) mat4.rotateZ(mat, mat, t.angle[2]*(Math.PI/180));
|
||||||
|
@ -39,6 +40,7 @@ window.ObjDecor = function(obji, scene) {
|
||||||
|
|
||||||
mat4.scale(mat, mat, vec3.scale([], t.scale, 16));
|
mat4.scale(mat, mat, vec3.scale([], t.scale, 16));
|
||||||
res.mdl[0].draw(mat, pMatrix, animMat);
|
res.mdl[0].draw(mat, pMatrix, animMat);
|
||||||
|
if (forceBill) nitroRender.resetShadOff();
|
||||||
}
|
}
|
||||||
|
|
||||||
function update() {
|
function update() {
|
||||||
|
|
|
@ -322,9 +322,9 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
k.items.update(input);
|
k.items.update(input);
|
||||||
|
|
||||||
if (input.turn > 0.3) {
|
if (input.turn > 0.3) {
|
||||||
if (k.driveAnimF < 28) k.driveAnimF++;
|
|
||||||
} else if (input.turn < -0.3) {
|
|
||||||
if (k.driveAnimF > 0) k.driveAnimF--;
|
if (k.driveAnimF > 0) k.driveAnimF--;
|
||||||
|
} else if (input.turn < -0.3) {
|
||||||
|
if (k.driveAnimF < 28) k.driveAnimF++;
|
||||||
} else {
|
} else {
|
||||||
if (k.driveAnimF > 14) k.driveAnimF--;
|
if (k.driveAnimF > 14) k.driveAnimF--;
|
||||||
else if (k.driveAnimF < 14) k.driveAnimF++;
|
else if (k.driveAnimF < 14) k.driveAnimF++;
|
||||||
|
@ -725,8 +725,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
}
|
}
|
||||||
var velSeg = vec3.clone(baseVel);
|
var velSeg = vec3.clone(baseVel);
|
||||||
if (k.kartColTimer > 0) {
|
if (k.kartColTimer > 0) {
|
||||||
vec3.scale([], k.kartColVel, k.kartColTimer/COLBOUNCE_TIME);
|
vec3.add(velSeg, velSeg, vec3.scale([], k.kartColVel, k.kartColTimer/COLBOUNCE_TIME));
|
||||||
vec3.add(velSeg, velSeg, k.kartColVel);
|
|
||||||
}
|
}
|
||||||
var posSeg = vec3.clone(k.pos);
|
var posSeg = vec3.clone(k.pos);
|
||||||
var ignoreList = [];
|
var ignoreList = [];
|
||||||
|
@ -1046,7 +1045,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
//order y, x, z
|
//order y, x, z
|
||||||
var dir = k.physicalDir+k.driftOff+(Math.sin((COLBOUNCE_TIME-k.kartColTimer)/3)*(Math.PI/6)*(k.kartColTimer/COLBOUNCE_TIME));
|
var dir = k.physicalDir+k.driftOff+(Math.sin((COLBOUNCE_TIME-k.kartColTimer)/3)*(Math.PI/6)*(k.kartColTimer/COLBOUNCE_TIME));
|
||||||
var forward = [Math.sin(dir), 0, -Math.cos(dir)];
|
var forward = [Math.sin(dir), 0, -Math.cos(dir)];
|
||||||
var side = [Math.cos(dir), 0, Math.sin(dir)];
|
var side = [-Math.cos(dir), 0, -Math.sin(dir)];
|
||||||
if (k.physBasis != null) {
|
if (k.physBasis != null) {
|
||||||
vec3.transformMat4(forward, forward, k.physBasis.mat);
|
vec3.transformMat4(forward, forward, k.physBasis.mat);
|
||||||
vec3.transformMat4(side, side, k.physBasis.mat);
|
vec3.transformMat4(side, side, k.physBasis.mat);
|
||||||
|
|
|
@ -27,6 +27,7 @@ window.ObjWater = function(obji, scene) {
|
||||||
var wosc = 12.288;
|
var wosc = 12.288;
|
||||||
var wstay = 5*60;
|
var wstay = 5*60;
|
||||||
var wchange = 4*60;
|
var wchange = 4*60;
|
||||||
|
var useAlpha = true; //probably a crutch - this should be defined in the water material (though it might be in nsbma)
|
||||||
|
|
||||||
function draw(view, pMatrix) {
|
function draw(view, pMatrix) {
|
||||||
if (nitroRender.flagShadow) return;
|
if (nitroRender.flagShadow) return;
|
||||||
|
@ -41,7 +42,7 @@ window.ObjWater = function(obji, scene) {
|
||||||
var height = (t.pos[1])+wheight+Math.sin(frame/150)*wosc //0.106
|
var height = (t.pos[1])+wheight+Math.sin(frame/150)*wosc //0.106
|
||||||
|
|
||||||
mat4.translate(waterM, view, [Math.sin(frame/180)*96, height, Math.cos(frame/146)*96])
|
mat4.translate(waterM, view, [Math.sin(frame/180)*96, height, Math.cos(frame/146)*96])
|
||||||
nitroRender.setColMult([1, 1, 1, 0x0A/31]);
|
if (useAlpha) nitroRender.setColMult([1, 1, 1, 0x0A/31]);
|
||||||
res.mdl[0].drawPoly(mat4.scale([], waterM, [16, 16, 16]), pMatrix, 0, 0); //water
|
res.mdl[0].drawPoly(mat4.scale([], waterM, [16, 16, 16]), pMatrix, 0, 0); //water
|
||||||
|
|
||||||
gl.stencilFunc(gl.EQUAL, 0, 0xFF);
|
gl.stencilFunc(gl.EQUAL, 0, 0xFF);
|
||||||
|
@ -49,7 +50,7 @@ window.ObjWater = function(obji, scene) {
|
||||||
|
|
||||||
if (obji.ID != 9) {
|
if (obji.ID != 9) {
|
||||||
mat4.translate(waterM, view, [0, height, 0])
|
mat4.translate(waterM, view, [0, height, 0])
|
||||||
nitroRender.setColMult([1, 1, 1, 0x10/31]);
|
if (useAlpha) nitroRender.setColMult([1, 1, 1, 0x10/31]);
|
||||||
res.mdl[0].drawPoly(mat4.scale([], waterM, [16, 16, 16]), pMatrix, 0, 1); //white shore wash part, water is stencil masked out
|
res.mdl[0].drawPoly(mat4.scale([], waterM, [16, 16, 16]), pMatrix, 0, 1); //white shore wash part, water is stencil masked out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +58,7 @@ window.ObjWater = function(obji, scene) {
|
||||||
|
|
||||||
if (res.mdl[1] != null) {
|
if (res.mdl[1] != null) {
|
||||||
mat4.translate(waterM, view, [-Math.sin((frame+30)/180)*96, height, Math.cos((frame+100)/146)*96])
|
mat4.translate(waterM, view, [-Math.sin((frame+30)/180)*96, height, Math.cos((frame+100)/146)*96])
|
||||||
nitroRender.setColMult([1, 1, 1, 0x04/31]);
|
if (useAlpha) nitroRender.setColMult([1, 1, 1, 0x04/31]);
|
||||||
res.mdl[1].draw(mat4.scale([], waterM, [16, 16, 16]), pMatrix); //water white detail part. stencil should do nothing here, since it's in the same position as the above.
|
res.mdl[1].draw(mat4.scale([], waterM, [16, 16, 16]), pMatrix); //water white detail part. stencil should do nothing here, since it's in the same position as the above.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,10 +75,13 @@ window.ObjWater = function(obji, scene) {
|
||||||
case 0x0001:
|
case 0x0001:
|
||||||
return {mdl:[{nsbmd:"beach_waterC.nsbmd"}, {nsbmd:"beach_waterA.nsbmd"}]};
|
return {mdl:[{nsbmd:"beach_waterC.nsbmd"}, {nsbmd:"beach_waterA.nsbmd"}]};
|
||||||
case 0x0003:
|
case 0x0003:
|
||||||
|
useAlpha = false;
|
||||||
return {mdl:[{nsbmd:"town_waterC.nsbmd"}, {nsbmd:"town_waterA.nsbmd"}]};
|
return {mdl:[{nsbmd:"town_waterC.nsbmd"}, {nsbmd:"town_waterA.nsbmd"}]};
|
||||||
case 0x0006:
|
case 0x0006:
|
||||||
|
useAlpha = false;
|
||||||
return {mdl:[{nsbmd:"yoshi_waterC.nsbmd"}]};
|
return {mdl:[{nsbmd:"yoshi_waterC.nsbmd"}]};
|
||||||
case 0x0009:
|
case 0x0009:
|
||||||
|
useAlpha = false;
|
||||||
return {mdl:[{nsbmd:"hyudoro_waterC.nsbmd"}, {nsbmd:"hyudoro_waterA.nsbmd"}]};
|
return {mdl:[{nsbmd:"hyudoro_waterC.nsbmd"}, {nsbmd:"hyudoro_waterA.nsbmd"}]};
|
||||||
case 0x000C:
|
case 0x000C:
|
||||||
wheight = 38;
|
wheight = 38;
|
||||||
|
|
|
@ -199,6 +199,7 @@ window.NitroParticle = function(scene, emitter, pos, vel, dir, dirVel, duration,
|
||||||
nitroRender.last.obj = obj;
|
nitroRender.last.obj = obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gl.disable(gl.CULL_FACE);
|
||||||
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
||||||
|
|
||||||
nitroRender.setColMult([1, 1, 1, 1]);
|
nitroRender.setColMult([1, 1, 1, 1]);
|
||||||
|
|
|
@ -14,8 +14,9 @@
|
||||||
window.nitroRender = new function() {
|
window.nitroRender = new function() {
|
||||||
var gl, frag, vert, nitroShader;
|
var gl, frag, vert, nitroShader;
|
||||||
var cVec, color, texCoord, norm;
|
var cVec, color, texCoord, norm;
|
||||||
var vecMode, vecPos, vecNorm, vecTx, vecCol, vecNum, vecMat, curMat;
|
var vecMode, vecPos, vecNorm, vecTx, vecCol, vecNum, vecMat, curMat, stripAlt;
|
||||||
var texWidth, texHeight, alphaMul = 1;
|
var texWidth, texHeight, alphaMul = 1;
|
||||||
|
var t = this;
|
||||||
|
|
||||||
this.cullModes = [];
|
this.cullModes = [];
|
||||||
|
|
||||||
|
@ -35,6 +36,7 @@ window.nitroRender = new function() {
|
||||||
this.getViewHeight = getViewHeight;
|
this.getViewHeight = getViewHeight;
|
||||||
|
|
||||||
this.flagShadow = false;
|
this.flagShadow = false;
|
||||||
|
this.forceFlatNormals = false; //generate flat normals for this mesh. Used for course model for better shadows.
|
||||||
|
|
||||||
var parameters = {
|
var parameters = {
|
||||||
0: 0,
|
0: 0,
|
||||||
|
@ -127,6 +129,7 @@ window.nitroRender = new function() {
|
||||||
vecMat = [];
|
vecMat = [];
|
||||||
}
|
}
|
||||||
vecNum = 0;
|
vecNum = 0;
|
||||||
|
stripAlt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
instructions[0x41] = function(view, off) { //end vtx
|
instructions[0x41] = function(view, off) { //end vtx
|
||||||
|
@ -154,6 +157,24 @@ window.nitroRender = new function() {
|
||||||
var norm = gl.createBuffer();
|
var norm = gl.createBuffer();
|
||||||
|
|
||||||
var posArray = new Float32Array(vecPos);
|
var posArray = new Float32Array(vecPos);
|
||||||
|
if (t.forceFlatNormals && modes[vecMode] == gl.TRIANGLES) {
|
||||||
|
//calculate new flat normals for each triangle
|
||||||
|
for (var i=0; i<vecPos.length; i+=9) {
|
||||||
|
var v1 = [vecPos[i], vecPos[i+1], vecPos[i+2]];
|
||||||
|
var v2 = [vecPos[i+3], vecPos[i+4], vecPos[i+5]];
|
||||||
|
var v3 = [vecPos[i+6], vecPos[i+7], vecPos[i+8]];
|
||||||
|
|
||||||
|
vec3.sub(v2, v2, v1);
|
||||||
|
vec3.sub(v3, v3, v1);
|
||||||
|
var newNorm = vec3.cross([], v2, v3);
|
||||||
|
vec3.normalize(newNorm, newNorm);
|
||||||
|
for (var j=0; j<3; j++) {
|
||||||
|
for (var k=0; k<3; k++) {
|
||||||
|
vecNorm[i+(j*3)+k] = newNorm[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, pos);
|
gl.bindBuffer(gl.ARRAY_BUFFER, pos);
|
||||||
gl.bufferData(gl.ARRAY_BUFFER, posArray, gl.STATIC_DRAW);
|
gl.bufferData(gl.ARRAY_BUFFER, posArray, gl.STATIC_DRAW);
|
||||||
|
@ -192,11 +213,14 @@ window.nitroRender = new function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optimiseTriangles && (vecMode > 1) && (vecNum > 2)) { //convert tri strips to individual triangles so we get one buffer per polygon
|
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));
|
var b = vecMat.length - (((stripAlt % 2) == 0)?1:3);
|
||||||
vecNorm = vecNorm.concat(vecNorm.slice(vecNorm.length-6));
|
var s2 = vecMat.length - (((stripAlt % 2) == 0)?2:1);
|
||||||
vecTx = vecTx.concat(vecTx.slice(vecTx.length-4));
|
vecPos = vecPos.concat(vecPos.slice(b*3, b*3+3)).concat(vecPos.slice(s2*3, s2*3+3));
|
||||||
vecCol = vecCol.concat(vecCol.slice(vecCol.length-8));
|
vecNorm = vecNorm.concat(vecNorm.slice(b*3, b*3+3)).concat(vecNorm.slice(s2*3, s2*3+3));
|
||||||
vecMat = vecMat.concat(vecMat.slice(vecMat.length-2));
|
vecTx = vecTx.concat(vecTx.slice(b*2, b*2+2)).concat(vecTx.slice(s2*2, s2*2+2));
|
||||||
|
vecCol = vecCol.concat(vecCol.slice(b*4, b*4+4)).concat(vecCol.slice(s2*4, s2*4+4));
|
||||||
|
vecMat = vecMat.concat(vecMat.slice(b, b+1)).concat(vecMat.slice(s2, s2+1));
|
||||||
|
stripAlt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
vecNum++;
|
vecNum++;
|
||||||
|
@ -206,7 +230,6 @@ window.nitroRender = new function() {
|
||||||
vecCol = vecCol.concat(color);
|
vecCol = vecCol.concat(color);
|
||||||
vecNorm = vecNorm.concat(norm);
|
vecNorm = vecNorm.concat(norm);
|
||||||
vecMat.push(curMat);
|
vecMat.push(curMat);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function tenBitSign(val) {
|
function tenBitSign(val) {
|
||||||
|
@ -241,16 +264,19 @@ window.nitroRender = new function() {
|
||||||
gl.uniform1i(this.nitroShader.samplerUniform, 0);
|
gl.uniform1i(this.nitroShader.samplerUniform, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setShadowMode = function(sTex, fsTex, sMat, fsMat) {
|
this.setShadowMode = function(sTex, fsTex, sMat, fsMat, dir) {
|
||||||
this.nitroShader = shaders[1];
|
this.nitroShader = shaders[1];
|
||||||
var shader = shaders[1];
|
var shader = shaders[1];
|
||||||
gl.useProgram(shader);
|
gl.useProgram(shader);
|
||||||
|
|
||||||
|
vec3.normalize(dir, dir);
|
||||||
|
gl.uniform3fv(shader.lightDirUniform, dir);
|
||||||
gl.uniformMatrix4fv(shader.shadowMatUniform, false, sMat);
|
gl.uniformMatrix4fv(shader.shadowMatUniform, false, sMat);
|
||||||
gl.uniformMatrix4fv(shader.farShadowMatUniform, false, fsMat);
|
gl.uniformMatrix4fv(shader.farShadowMatUniform, false, fsMat);
|
||||||
gl.uniform1f(shader.lightIntensityUniform, 0.3);
|
gl.uniform1f(shader.lightIntensityUniform, 0.3);
|
||||||
|
|
||||||
this.resetShadOff();
|
this.resetShadOff();
|
||||||
|
this.setNormalFlip(1);
|
||||||
gl.activeTexture(gl.TEXTURE1);
|
gl.activeTexture(gl.TEXTURE1);
|
||||||
gl.bindTexture(gl.TEXTURE_2D, sTex);
|
gl.bindTexture(gl.TEXTURE_2D, sTex);
|
||||||
gl.uniform1i(shader.lightSamplerUniform, 1);
|
gl.uniform1i(shader.lightSamplerUniform, 1);
|
||||||
|
@ -263,16 +289,33 @@ window.nitroRender = new function() {
|
||||||
this.prepareShader();
|
this.prepareShader();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.setLightIntensities = function(intensity, shadIntensity) {
|
||||||
|
if (intensity == null) intensity = 0.3;
|
||||||
|
if (shadIntensity == null) shadIntensity = 1;
|
||||||
|
var shader = this.nitroShader;
|
||||||
|
gl.useProgram(this.nitroShader);
|
||||||
|
gl.uniform1f(shader.lightIntensityUniform, intensity);
|
||||||
|
gl.uniform1f(shader.shadLightenUniform, 1-shadIntensity);
|
||||||
|
}
|
||||||
|
|
||||||
this.setShadBias = function(bias) {
|
this.setShadBias = function(bias) {
|
||||||
var shader = shaders[1];
|
var shader = this.nitroShader;
|
||||||
|
gl.useProgram(this.nitroShader);
|
||||||
gl.uniform1f(shader.shadOffUniform, bias);
|
gl.uniform1f(shader.shadOffUniform, bias);
|
||||||
gl.uniform1f(shader.farShadOffUniform, bias);
|
gl.uniform1f(shader.farShadOffUniform, bias);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.setNormalFlip = function(flip) {
|
||||||
|
var shader = this.nitroShader;
|
||||||
|
gl.useProgram(this.nitroShader);
|
||||||
|
gl.uniform1f(shader.normalFlipUniform, flip);
|
||||||
|
}
|
||||||
|
|
||||||
this.resetShadOff = function() {
|
this.resetShadOff = function() {
|
||||||
var shader = shaders[1];
|
var shader = this.nitroShader;
|
||||||
gl.uniform1f(shader.shadOffUniform, 0.00005+((mobile)?0.0005:0));
|
gl.useProgram(this.nitroShader);
|
||||||
gl.uniform1f(shader.farShadOffUniform, 0.0005);
|
gl.uniform1f(shader.shadOffUniform, 0.0005+((mobile)?0.0005:0));
|
||||||
|
gl.uniform1f(shader.farShadOffUniform, 0.0020);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.unsetShadowMode = function() {
|
this.unsetShadowMode = function() {
|
||||||
|
@ -352,6 +395,7 @@ window.nitroRender = new function() {
|
||||||
|
|
||||||
vecMode = 0;
|
vecMode = 0;
|
||||||
vecNum = 0;
|
vecNum = 0;
|
||||||
|
stripAlt = 0;
|
||||||
vecPos = [];
|
vecPos = [];
|
||||||
vecNorm = [];
|
vecNorm = [];
|
||||||
vecTx = [];
|
vecTx = [];
|
||||||
|
@ -808,6 +852,24 @@ function nitroModel(bmd, btx) {
|
||||||
} 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);
|
if (modelBuffers[modelind][polyind] == null) modelBuffers[modelind][polyind] = nitroRender.renderDispList(poly.disp, tex[poly.mat], (poly.stackID == null)?model.lastStackID:poly.stackID);
|
||||||
|
|
||||||
|
if (material.cullMode < 3) {
|
||||||
|
gl.enable(gl.CULL_FACE);
|
||||||
|
gl.cullFace(nitroRender.cullModes[material.cullMode]);
|
||||||
|
} else {
|
||||||
|
if (nitroRender.forceFlatNormals) {
|
||||||
|
//dual side lighting model, course render mode essentially
|
||||||
|
gl.enable(gl.CULL_FACE);
|
||||||
|
gl.cullFace(gl.BACK);
|
||||||
|
drawModelBuffer(modelBuffers[modelind][polyind], gl, shader);
|
||||||
|
nitroRender.setNormalFlip(-1);
|
||||||
|
gl.cullFace(gl.FRONT);
|
||||||
|
drawModelBuffer(modelBuffers[modelind][polyind], gl, shader);
|
||||||
|
nitroRender.setNormalFlip(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gl.disable(gl.CULL_FACE);
|
||||||
|
}
|
||||||
drawModelBuffer(modelBuffers[modelind][polyind], gl, shader);
|
drawModelBuffer(modelBuffers[modelind][polyind], gl, shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,13 +84,16 @@ window.nitroShaders = new (function() {
|
||||||
varying vec4 color;\n\
|
varying vec4 color;\n\
|
||||||
varying vec4 lightDist;\n\
|
varying vec4 lightDist;\n\
|
||||||
varying vec4 fLightDist;\n\
|
varying vec4 fLightDist;\n\
|
||||||
|
varying vec3 normal;\n\
|
||||||
\n\
|
\n\
|
||||||
uniform float shadOff; \n\
|
uniform float shadOff; \n\
|
||||||
uniform float farShadOff; \n\
|
uniform float farShadOff; \n\
|
||||||
uniform sampler2D lightDSampler;\n\
|
uniform sampler2D lightDSampler;\n\
|
||||||
uniform sampler2D farLightDSampler;\n\
|
uniform sampler2D farLightDSampler;\n\
|
||||||
|
uniform float shadLighten; \n\
|
||||||
\n\
|
\n\
|
||||||
uniform sampler2D uSampler;\n\
|
uniform sampler2D uSampler;\n\
|
||||||
|
uniform vec3 lightDir;\n\
|
||||||
\n\
|
\n\
|
||||||
float shadowCompare(sampler2D map, vec2 pos, float compare, float so) {\n\
|
float shadowCompare(sampler2D map, vec2 pos, float compare, float so) {\n\
|
||||||
float depth = texture2D(map, pos).r;\n\
|
float depth = texture2D(map, pos).r;\n\
|
||||||
|
@ -118,17 +121,20 @@ window.nitroShaders = new (function() {
|
||||||
\n\
|
\n\
|
||||||
vec2 ldNorm = abs((lightDist.xy)-vec2(0.5, 0.5));\n\
|
vec2 ldNorm = abs((lightDist.xy)-vec2(0.5, 0.5));\n\
|
||||||
float dist = max(ldNorm.x, ldNorm.y);\n\
|
float dist = max(ldNorm.x, ldNorm.y);\n\
|
||||||
|
float shadIntensity;\n\
|
||||||
\n\
|
\n\
|
||||||
if (dist > 0.5) {\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, farShadOff*2.0));\n\
|
shadIntensity = shadowLerp(farLightDSampler, vec2(4096.0, 4096.0), fLightDist.xy, fLightDist.z-farShadOff, farShadOff*0.5);\n\
|
||||||
} else if (dist > 0.4) {\n\
|
} else if (dist > 0.4) {\n\
|
||||||
float lerp1 = shadowLerp(farLightDSampler, vec2(4096.0, 4096.0), fLightDist.xy, fLightDist.z-farShadOff, farShadOff*2.0);\n\
|
float lerp1 = shadowLerp(farLightDSampler, vec2(4096.0, 4096.0), fLightDist.xy, fLightDist.z-farShadOff, farShadOff*0.5);\n\
|
||||||
float lerp2 = shadowLerp(lightDSampler, vec2(2048.0, 2048.0), lightDist.xy, lightDist.z-shadOff, shadOff*4.0);\n\
|
float lerp2 = shadowLerp(lightDSampler, vec2(2048.0, 2048.0), lightDist.xy, lightDist.z-shadOff, shadOff*0.5);\n\
|
||||||
\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\
|
shadIntensity = mix(lerp2, lerp1, (dist-0.4)*10.0);\n\
|
||||||
} else {\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, shadOff*4.0));\n\
|
shadIntensity = shadowLerp(lightDSampler, vec2(2048.0, 2048.0), lightDist.xy, lightDist.z-shadOff, shadOff*0.5);\n\
|
||||||
}\n\
|
}\n\
|
||||||
|
shadIntensity = min(shadIntensity, max(0.0, dot(normalize(normal), lightDir) * 5.0));\n\
|
||||||
|
gl_FragColor = col*mix(vec4(0.5, 0.5, 0.7, 1.0), vec4(1.0, 1.0, 1.0, 1.0), min(1.0, shadIntensity + shadLighten));\n\
|
||||||
\n\
|
\n\
|
||||||
if (gl_FragColor.a == 0.0) discard;\n\
|
if (gl_FragColor.a == 0.0) discard;\n\
|
||||||
}\n\
|
}\n\
|
||||||
|
@ -144,6 +150,7 @@ window.nitroShaders = new (function() {
|
||||||
uniform mat4 uPMatrix;\n\
|
uniform mat4 uPMatrix;\n\
|
||||||
uniform mat3 texMatrix;\n\
|
uniform mat3 texMatrix;\n\
|
||||||
uniform mat4 matStack[16];\n\
|
uniform mat4 matStack[16];\n\
|
||||||
|
uniform float normalFlip;\n\
|
||||||
\n\
|
\n\
|
||||||
uniform vec4 colMult;\n\
|
uniform vec4 colMult;\n\
|
||||||
\n\
|
\n\
|
||||||
|
@ -155,6 +162,7 @@ window.nitroShaders = new (function() {
|
||||||
varying vec4 color;\n\
|
varying vec4 color;\n\
|
||||||
varying vec4 lightDist;\n\
|
varying vec4 lightDist;\n\
|
||||||
varying vec4 fLightDist;\n\
|
varying vec4 fLightDist;\n\
|
||||||
|
varying vec3 normal;\n\
|
||||||
\n\
|
\n\
|
||||||
\n\
|
\n\
|
||||||
void main(void) {\n\
|
void main(void) {\n\
|
||||||
|
@ -164,7 +172,8 @@ window.nitroShaders = new (function() {
|
||||||
\n\
|
\n\
|
||||||
lightDist = (shadowMat*pos + vec4(1, 1, 1, 0)) / 2.0;\n\
|
lightDist = (shadowMat*pos + vec4(1, 1, 1, 0)) / 2.0;\n\
|
||||||
fLightDist = (farShadowMat*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\
|
vec3 adjNorm = normalize(vec3(uMVMatrix * matStack[int(matrixID)] * vec4(aNormal, 0.0))) * normalFlip;\n\
|
||||||
|
normal = adjNorm; \n\
|
||||||
float diffuse = (1.0-lightIntensity)-dot(adjNorm, vec3(0.0, -1.0, 0.0))*lightIntensity;\n\
|
float diffuse = (1.0-lightIntensity)-dot(adjNorm, vec3(0.0, -1.0, 0.0))*lightIntensity;\n\
|
||||||
\n\
|
\n\
|
||||||
color = aColor*colMult;\n\
|
color = aColor*colMult;\n\
|
||||||
|
@ -303,12 +312,15 @@ window.nitroShaders = new (function() {
|
||||||
["shadowMatUniform", "shadowMat"],
|
["shadowMatUniform", "shadowMat"],
|
||||||
["farShadowMatUniform", "farShadowMat"],
|
["farShadowMatUniform", "farShadowMat"],
|
||||||
["lightIntensityUniform", "lightIntensity"],
|
["lightIntensityUniform", "lightIntensity"],
|
||||||
|
["shadLightenUniform", "shadLighten"],
|
||||||
|
["lightDirUniform", "lightDir"],
|
||||||
|
["normalFlipUniform", "normalFlip"],
|
||||||
|
|
||||||
["shadOffUniform", "shadOff"],
|
["shadOffUniform", "shadOff"],
|
||||||
["farShadOffUniform", "farShadOff"],
|
["farShadOffUniform", "farShadOff"],
|
||||||
|
|
||||||
["lightSamplerUniform", "lightDSampler"],
|
["lightSamplerUniform", "lightDSampler"],
|
||||||
["farLightSamplerUniform", "farLightDSampler"]
|
["farLightSamplerUniform", "farLightDSampler"],
|
||||||
]
|
]
|
||||||
|
|
||||||
config[0] = baseConf;
|
config[0] = baseConf;
|
||||||
|
|
Loading…
Reference in New Issue