C++博客 联系 聚合 管理  

Blog Stats

随笔档案

好友圈

脚踏实地

心 勿噪

----------------------------------
一段光线求交的场景!
----------------------------------
<canvas id="nes_screen" width="200" height="120">
</canvas>
<script>

var iGlobalTime = 0.0;
var iGlobalStartTime = 0.0;
// 向量
var vec2 = function (x, y) {
    
this.x = x;
    
this.y = y;
}

vec2.prototype 
= {
    Length: 
function () {
        
return Math.sqrt(this.x * this.x + this.y * this.y);
    }
    ,
    Add: 
function (other) {
        
return new vec2(this.x + other.x, this.y + other.y);
    }
    ,
    Sub: 
function (other) {
        
return new vec2(this.x - other.x, this.y - other.y);
    }
    ,
    Mul: 
function (scale) {
        
return new vec2(this.x * scale, this.y * scale);
    }
    ,
    Div: 
function (scale) {
        
return new vec2(this.x / scale, this.y / scale);
    }
    ,
    Dot: 
function (other) {
        
return this.x * other.x + this.y * other.y;
    }
}

vec2.zore 
= new vec2(0.00.0);

var vec3 = function (x, y, z) {
    
this.x = x;
    
this.y = y;
    
this.z = z;
}

vec3.prototype 
= {
    Length: 
function () {
        
return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
    }
    ,
    Add: 
function (other) {
        
return new vec3(this.x + other.x, this.y + other.y, this.y + other.y);
    }
    ,
    Sub: 
function (other) {
        
return new vec3(this.x - other.x, this.y - other.y, this.z - other.z);
    }
    ,
    Mul: 
function (scale) {
        
return new vec3(this.x * scale, this.y * scale, this.z * scale);
    }
    ,
    Div: 
function (scale) {
        
return new vec3(this.x / scale, this.y / scale, this.z / scale);
    }
    ,
    Dot: 
function (other) {
        
return this.x * other.x + this.y * other.y + this.z * other.z;
    }
    ,
    Cross: 
function (other) {
        
return new vec3(this.y * other.z - this.z * other.y,
            
this.z * other.x - this.x * other.z,
            
this.x * other.y - this.y * other.x);
    }
    ,
    Normalize: 
function () {
        
var len = this.Length();
        
if (len > 0.0) {
            
var invLen = 1 / len;
            
return new vec3(this.x * invLen, this.y * invLen, this.z * invLen)
        }
        
return new vec3(0.00.00.0);
    }
}

vec3.zore 
= new vec3(0.00.00.0);


function radians(angle) {
    
return (Math.PI / 180.0* angle;
}

function cos(delta) {
    
return Math.cos(delta);
}

function sin(delta) {
    
return Math.sin(delta);
}

function clamp(v, min, max) {
    
return (v > max) ? max : ((v < min) ? min : v);
}

// 颜色
var Color = function (r, g, b, a) {
    
this.r = r;
    
this.g = g;
    
this.b = b;
    
this.a = a;
}

Color.prototype 
= {
    Add: 
function (oterh) {
        
this.r += oterh.r;
        
this.g += oterh.g;
        
this.b += oterh.b;
        
this.a += oterh.a;
        
return this;
    }
    ,
    Sub: 
function (oterh) {
        
this.r -= oterh.r;
        
this.g -= oterh.g;
        
this.b -= oterh.b;
        
this.a -= oterh.a;
        
return this;
    }
    ,
    Mul: 
function (scale) {
        
this.r *= scale;
        
this.g *= scale;
        
this.b *= scale;
        
this.a *= scale;
        
return this;
    }
    ,
    Div: 
function (oterh) {
        
this.r /= scale;
        
this.g /= scale;
        
this.b /= scale;
        
this.a /= scale;
        
return this;
    }
}

Color.balck 
= new Color(0.00.00.0255.0);
Color.white 
= new Color(255.0255.0255.0255.0);

var mat4 = function (m11, m12, m13, m14,
    m21, m22, m23, m24,
    m31, m32, m33, m34,
    m41, m42, m43, m44) {
    
this.m11 = m11; this.m12 = m12; this.m13 = m13; this.m14 = m14;
    
this.m21 = m21; this.m22 = m22; this.m23 = m23; this.m24 = m24;
    
this.m31 = m31; this.m32 = m32; this.m33 = m33; this.m34 = m34;
    
this.m41 = m41; this.m42 = m42; this.m43 = m43; this.m44 = m44;
}

mat4.prototype 
= {
    Mul: 
function (other) {
        
var new_m11 = other.m11 * this.m11 + other.m12 * this.m21 + other.m13 * this.m31 + other.m14 * this.m41;
        
var new_m12 = other.m11 * this.m12 + other.m12 * this.m22 + other.m13 * this.m32 + other.m14 * this.m42;
        
var new_m13 = other.m11 * this.m13 + other.m12 * this.m23 + other.m13 * this.m33 + other.m14 * this.m43;
        
var new_m14 = other.m11 * this.m14 + other.m12 * this.m24 + other.m13 * this.m34 + other.m14 * this.m44;

        
var new_m21 = other.m21 * this.m11 + other.m22 * this.m21 + other.m23 * this.m31 + other.m24 * this.m41;
        
var new_m22 = other.m21 * this.m12 + other.m22 * this.m22 + other.m23 * this.m32 + other.m24 * this.m42;
        
var new_m23 = other.m21 * this.m13 + other.m22 * this.m23 + other.m23 * this.m33 + other.m24 * this.m43;
        
var new_m24 = other.m21 * this.m14 + other.m22 * this.m24 + other.m23 * this.m34 + other.m24 * this.m44;

        
var new_m31 = other.m31 * this.m11 + other.m32 * this.m21 + other.m33 * this.m31 + other.m34 * this.m41;
        
var new_m32 = other.m31 * this.m12 + other.m32 * this.m22 + other.m33 * this.m32 + other.m34 * this.m42;
        
var new_m33 = other.m31 * this.m13 + other.m32 * this.m23 + other.m33 * this.m33 + other.m34 * this.m43;
        
var new_m34 = other.m31 * this.m14 + other.m32 * this.m24 + other.m33 * this.m34 + other.m34 * this.m44;

        
var new_m41 = other.m41 * this.m11 + other.m42 * this.m21 + other.m43 * this.m31 + other.m44 * this.m41;
        
var new_m42 = other.m41 * this.m12 + other.m42 * this.m22 + other.m43 * this.m32 + other.m44 * this.m42;
        
var new_m43 = other.m41 * this.m13 + other.m42 * this.m23 + other.m43 * this.m33 + other.m44 * this.m43;
        
var new_m44 = other.m41 * this.m14 + other.m42 * this.m24 + other.m43 * this.m34 + other.m44 * this.m44;

        
return new mat4(new_m11, new_m12, new_m13, new_m14,
            new_m21, new_m22, new_m23, new_m24,
            new_m31, new_m32, new_m33, new_m34,
            new_m41, new_m42, new_m43, new_m44);
    },

    MulVec3: 
function (vec3_a) {

        
var new_x = vec3_a.x * this.m11 + vec3_a.y * this.m21 + vec3_a.z * this.m31 + 1.0 * this.m41;
        
var new_y = vec3_a.x * this.m12 + vec3_a.y * this.m22 + vec3_a.z * this.m32 + 1.0 * this.m42;
        
var new_z = vec3_a.x * this.m13 + vec3_a.y * this.m23 + vec3_a.z * this.m33 + 1.0 * this.m43;

        
return new vec3(new_x, new_y, new_z);
    }
    ,
    MulNormal: 
function (vec3_a) {

        
var new_x = vec3_a.x * this.m11 + vec3_a.y * this.m21 + vec3_a.z * this.m31;
        
var new_y = vec3_a.x * this.m12 + vec3_a.y * this.m22 + vec3_a.z * this.m32;
        
var new_z = vec3_a.x * this.m13 + vec3_a.y * this.m23 + vec3_a.z * this.m33;

        
return new vec3(new_x, new_y, new_z);
    }
}

function setRotation(float_x, float_y, float_z) {
    
var a = sin(float_x); var b = cos(float_x);
    
var c = sin(float_y); var d = cos(float_y);
    
var e = sin(float_z); var f = cos(float_z);

    
var ac = a * c;
    
var bc = b * c;

    
return new mat4(d * f, d * e, -c, 0.0,
        ac 
* f - b * e, ac * e + b * f, a * d, 0.0,
        bc 
* f + a * e, bc * e - a * f, b * d, 0.0,
        
0.00.00.01.0);
}


function setTranslation(float_x, float_y, float_z) {
    
return new mat4(1.00.00.00.0,
        
0.01.00.00.0,
        
0.00.01.00.0,
        float_x, float_y, float_z, 
1.0);
}

var Triangle = function () {
    
this.vec3_a = vec3.zore; this.vec2_aUV = vec2.zore;
    
this.vec3_b = vec3.zore; this.vec2_bUV = vec2.zore;
    
this.vec3_c = vec3.zore; this.vec2_cUV = vec2.zore;
    
this.vec3_n = vec3.zore;
};

triangles 
= new Array();
triangles[
0= new Triangle();
triangles[
1= new Triangle();
triangles[
2= new Triangle();
triangles[
3= new Triangle();
triangles[
4= new Triangle();
triangles[
5= new Triangle();
triangles[
6= new Triangle();
triangles[
7= new Triangle();
triangles[
8= new Triangle();
triangles[
9= new Triangle();
triangles[
10= new Triangle();
triangles[
11= new Triangle();
triangles[
12= new Triangle();
triangles[
13= new Triangle();

function createCube() {
    verts 
= new Array();

    verts[
0= new vec3(-1.0-1.0-1.0);
    verts[
1= new vec3(-1.0-1.01.0);
    verts[
2= new vec3(-1.01.0-1.0);
    verts[
3= new vec3(-1.01.01.0);
    verts[
4= new vec3(1.0-1.0-1.0);
    verts[
5= new vec3(1.0-1.01.0);
    verts[
6= new vec3(1.01.0-1.0);
    verts[
7= new vec3(1.01.01.0);

    triangles[
0].vec3_a = verts[1]; triangles[0].vec2_aUV = new vec2(0.00.0);
    triangles[
0].vec3_b = verts[5]; triangles[0].vec2_bUV = new vec2(1.00.0);
    triangles[
0].vec3_c = verts[7]; triangles[0].vec2_cUV = new vec2(1.01.0);
    triangles[
0].vec3_n = new vec3(0.00.01.0);
    triangles[
1].vec3_a = verts[1]; triangles[1].vec2_aUV = new vec2(0.00.0);
    triangles[
1].vec3_b = verts[7]; triangles[1].vec2_bUV = new vec2(1.01.0);
    triangles[
1].vec3_c = verts[3]; triangles[1].vec2_cUV = new vec2(0.01.0);
    triangles[
1].vec3_n = new vec3(0.00.01.0);

    triangles[
2].vec3_a = verts[5]; triangles[2].vec2_aUV = new vec2(0.00.0);
    triangles[
2].vec3_b = verts[4]; triangles[2].vec2_bUV = new vec2(1.00.0);
    triangles[
2].vec3_c = verts[6]; triangles[2].vec2_cUV = new vec2(1.01.0);
    triangles[
2].vec3_n = new vec3(1.00.00.0);
    triangles[
3].vec3_a = verts[5]; triangles[3].vec2_aUV = new vec2(0.00.0);
    triangles[
3].vec3_b = verts[6]; triangles[3].vec2_bUV = new vec2(1.01.0);
    triangles[
3].vec3_c = verts[7]; triangles[3].vec2_cUV = new vec2(0.01.0);
    triangles[
3].vec3_n = new vec3(1.00.00.0);

    triangles[
4].vec3_a = verts[3]; triangles[4].vec2_aUV = new vec2(0.00.0);
    triangles[
4].vec3_b = verts[7]; triangles[4].vec2_bUV = new vec2(1.00.0);
    triangles[
4].vec3_c = verts[6];; triangles[4].vec2_cUV = new vec2(1.01.0);
    triangles[
4].vec3_n = new vec3(0.01.00.0);
    triangles[
5].vec3_a = verts[3]; triangles[5].vec2_aUV = new vec2(0.00.0);
    triangles[
5].vec3_b = verts[6]; triangles[5].vec2_bUV = new vec2(1.01.0);
    triangles[
5].vec3_c = verts[2]; triangles[5].vec2_cUV = new vec2(0.01.0);
    triangles[
5].vec3_n = new vec3(0.01.00.0);

    triangles[
6].vec3_a = verts[0]; triangles[6].vec2_aUV = new vec2(1.00.0);
    triangles[
6].vec3_b = verts[6]; triangles[6].vec2_bUV = new vec2(0.01.0);
    triangles[
6].vec3_c = verts[4]; triangles[6].vec2_cUV = new vec2(0.00.0);
    triangles[
6].vec3_n = new vec3(0.00.0-1.0);
    triangles[
7].vec3_a = verts[0]; triangles[7].vec2_aUV = new vec2(1.00.0);
    triangles[
7].vec3_b = verts[2]; triangles[7].vec2_bUV = new vec2(1.01.0);
    triangles[
7].vec3_c = verts[6]; triangles[7].vec2_cUV = new vec2(0.01.0);
    triangles[
7].vec3_n = new vec3(0.00.0-1.0);

    triangles[
8].vec3_a = verts[1]; triangles[8].vec2_aUV = new vec2(1.00.0);
    triangles[
8].vec3_b = verts[2]; triangles[8].vec2_bUV = new vec2(0.01.0);
    triangles[
8].vec3_c = verts[0]; triangles[8].vec2_cUV = new vec2(0.00.0);
    triangles[
8].vec3_n = new vec3(-1.00.00.0);
    triangles[
9].vec3_a = verts[1]; triangles[9].vec2_aUV = new vec2(1.00.0);
    triangles[
9].vec3_b = verts[3]; triangles[9].vec2_bUV = new vec2(1.01.0);
    triangles[
9].vec3_c = verts[2]; triangles[9].vec2_cUV = new vec2(0.01.0);
    triangles[
9].vec3_n = new vec3(-1.00.00.0);

    triangles[
10].vec3_a = verts[1]; triangles[10].vec2_aUV = new vec2(0.00.0);
    triangles[
10].vec3_b = verts[0]; triangles[10].vec2_bUV = new vec2(0.01.0);
    triangles[
10].vec3_c = verts[4]; triangles[10].vec2_cUV = new vec2(1.01.0);
    triangles[
10].vec3_n = new vec3(0.0-1.00.0);
    triangles[
11].vec3_a = verts[1]; triangles[11].vec2_aUV = new vec2(0.00.0);
    triangles[
11].vec3_b = verts[4]; triangles[11].vec2_bUV = new vec2(1.01.0);
    triangles[
11].vec3_c = verts[5]; triangles[11].vec2_cUV = new vec2(1.00.0);
    triangles[
11].vec3_n = new vec3(0.0-1.00.0);
}

function createFloor() {
    verts 
= new Array();

    verts[
0= new vec3(-3.0-1.0-3.0);
    verts[
1= new vec3(-3.0-1.03.0);
    verts[
2= new vec3(3.0-1.03.0);
    verts[
3= new vec3(3.0-1.0-3.0);

    triangles[
12].vec3_a = verts[0]; triangles[12].vec2_aUV = new vec2(0.00.0);
    triangles[
12].vec3_b = verts[1]; triangles[12].vec2_bUV = new vec2(0.03.0);
    triangles[
12].vec3_c = verts[3]; triangles[12].vec2_cUV = new vec2(3.00.0);
    triangles[
12].vec3_n = new vec3(0.01.00.0);
    triangles[
13].vec3_a = verts[1]; triangles[13].vec2_aUV = new vec2(0.03.0);
    triangles[
13].vec3_b = verts[2]; triangles[13].vec2_bUV = new vec2(3.03.0);
    triangles[
13].vec3_c = verts[3]; triangles[13].vec2_cUV = new vec2(3.00.0);
    triangles[
13].vec3_n = new vec3(0.01.00.0);
}


function RayIntersectTriangle(
    vec3_ro, vec3_rd,
    vec3_v0, vec3_v1, vec3_v2,
    vec3_result) {
    
var E1 = vec3_v1.Sub(vec3_v0);
    
var E2 = vec3_v2.Sub(vec3_v0);

    
var P = vec3_rd.Cross(E2);
    
var det = E1.Dot(P);

    
var T = vec3.zore;
    
if (det > 0.0)
        T 
= vec3_ro.Sub(vec3_v0);
    
else {
        T 
= vec3_v0.Sub(vec3_ro);
        det 
= -det;
    }

    
if (det < 0.001)
        
return false;

    
var u = T.Dot(P);
    
if (u < 0|| u > det)
        
return false;

    
var Q = T.Cross(E1);
    v 
= vec3_rd.Dot(Q);
    
if (v < 0|| u + v > det)
        
return false;

    vec3_result.x 
= E2.Dot(Q);

    
var fInvDet = 1/ det;
    vec3_result.x 
*= fInvDet;
    vec3_result.y 
*= fInvDet;
    vec3_result.z 
*= fInvDet;

    
return true;
}


var mdv;

var lig = new vec3(0.30.70.5).Normalize();

function SurfaceShader(vec3_nor, vec2_uv, float_z, vec3_wnor) {
    
var dif = clamp(vec3_nor.Dot(lig), 0.01.0);
    
var brdf = 0.5 + 0.8 * dif;
    brdf 
*= 4.0 * Math.exp(-0.7 * Math.abs(float_z));

    
return new Color(128.0 * brdf, 128.0 * brdf, 196.0 * brdf, 255);
}

function pixel_shader(x, y, w, h) {
    
var pix = new vec2(-1.0 + 2.0 * x / w, -1.0 + 2.0 * y / h);
    pix.x 
*= w / h;

    
var ro = new vec3(0.00.02.0);
    
var rd = new vec3(pix.x, pix.y, 0.0).Sub(ro).Normalize();
    
var color = Color.balck;

    
// clear zbuffer
    var mindist = -1000000.0;

    
for (var i = 0; i < 14; i++) {
        
// transform to eye space
        var ep0 = mdv.MulVec3(triangles[i].vec3_a);
        
var ep1 = mdv.MulVec3(triangles[i].vec3_b);
        
var ep2 = mdv.MulVec3(triangles[i].vec3_c);
        
var nor = mdv.MulNormal(triangles[i].vec3_n);

        
var result = vec3.zore;
        
if (RayIntersectTriangle(ro, rd, ep0, ep1, ep2, result)) {
            
// do uv linear interpolation.
            var uv = triangles[i].vec2_bUV.Sub(triangles[i].vec2_aUV).Mul(result.y) +
                triangles[i].vec2_cUV.Sub(triangles[i].vec2_aUV).Mul(result.z);

            
var z = ro.z + result.x * rd.z;

            
if (z > mindist) {
                mindist 
= z;

                
// perform lighting/shading
                color = SurfaceShader(nor, uv, z, triangles[i].n);
            }
        }
    }

    
return color;
}

function main() {
    
var d = new Date();
    iGlobalTime 
= (d.getTime() - iGlobalStartTime) / 1000;

    mdv 
= setTranslation(0.00.5-3.0).Mul(
        setRotation(
0.60.00.0).Mul(
            setRotation(
0.03.1 * sin(0.3 * iGlobalTime), 0.0)
        )
    );

    
var canvas = document.getElementById('nes_screen');
    
if (canvas && canvas.getContext) {
        
var ctx = canvas.getContext('2d');
        
var w = canvas.clientWidth, h = canvas.clientHeight;
        ctx.fillStyle 
= "rgb(0, 0, 0)";
        ctx.fillRect(
00, w, h);
        
var imgdata = ctx.getImageData(00, w, h);
        
var pixels = imgdata.data;
        
var i = 0;
        
for (var y = h - 1; y >= 0; y--)
            
for (var x = 0; x < w; x++) {
                
var data = pixel_shader(x, y, w, h);
                pixels[i
++= data.r;
                pixels[i
++= data.g;
                pixels[i
++= data.b;
                pixels[i
++= data.a;
            }
        ctx.putImageData(imgdata, 
00);
    }
    
//setTimeout(main,33);
    requestAnimationFrame(main);
}

try {
    
var d = new Date();
    iGlobalStartTime 
= d.getTime();
    createCube();
    createFloor();
    main();
}
catch (err) {
    alert(err.message);
}
</script>
posted on 2018-03-23 00:27 LSH 阅读(12) 评论(0)  编辑 收藏 引用