简化版的窗体,js基础探寻七

// OpenGLBook.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

//变量声明
static GLfloat spin =0.0;
GLfloat zoom=-10.0f;
GLfloat angel=20.0f;
BOOL    light;                                    // 光源的开/关
BOOL    lp;                                    // L键按下了么?
BOOL    fp;                                    // F键按下了么?
GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0};
GLfloat mat_shininess[] = {50.0};
GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0};
GLfloat white_light[] = {1.0, 1.0, 1.0, 1.0};
GLfloat lmodel_ambient[] = {0.1, 0.1, 0.1, 1.0};
//函数声明
void init(void);
void display(void);
void spinDisplay(void);
void reshape(int w,int h);
void mouse(int button,int state,int x,int y);
void processNormalKeys(unsigned char key,int x,int y);
void processKeyUpDowm(int key,int x,int y);

/************************************************************************/
/*         函数实现                                                     */
/************************************************************************/

//初始化
void init(void){
    glClearColor(0.0f,0.0f,0.0f,0.0f);
     glShadeModel(GL_SMOOTH);


    glShadeModel(GL_SMOOTH);
    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
    glLightfv(GL_LIGHT0, GL_POSITION, light_position);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);
    glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);

    //glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_DEPTH_TEST);    
    ///////////////////////
    glShadeModel(GL_SMOOTH);                            // Enable Smooth Shading
    glClearColor(0.1f,0.1f, 0.1f, 0.9f);                // Black Background
    glClearDepth(1.0f);                                    // Depth Buffer Setup
    glEnable(GL_DEPTH_TEST);                            // Enables Depth Testing
    glDepthFunc(GL_LEQUAL);                                // The Type Of Depth Testing To Do
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);    // Really Nice Perspective Calculations
}

//图形绘画
void display(void){
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    // 清除屏幕及深度缓存
     // 重置模型观察矩阵

     glPushMatrix();
     //glLoadIdentity(); //等同于glPushMatrix();和glPopMatrix();配对重绘
     glTranslatef(0.0f,0.0f,zoom);
    glRotatef(spin,0.0f,1.0f,0.0f);
    glutSolidSphere(1.0, 20, 16);
    glPopMatrix();
    glutSwapBuffers(); //交换屏幕缓冲区与后台缓冲区
        angel+=5.0f;
    glutPostRedisplay(); //重绘
//     glPushMatrix();
}

void reshape(int w,int h){
    if (h==0)                                        // Prevent A Divide By Zero By
    {
        h=1;                                        // Making Height Equal One
    }

    glViewport(0,0,(GLsizei)w,(GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0f,(GLfloat)w/(GLfloat)h,0.1f,100.0f);//透视

    //glOrtho(-50.0,50.0,-50.0,50.0,-1.0,100.0); //平行修剪空间(离观察者远时,不会缩小)
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

//鼠标响应
void mouse(int button,int state,int x,int y)
{

    switch(state){
    case GLUT_DOWN:
        if (button==GLUT_LEFT_BUTTON)  //左键
        {

            break;
        }
        if (button==GLUT_RIGHT_BUTTON) //右键
        {

            break;
        }
    case GLUT_UP:
        if (button==GLUT_WHEEL_UP)
        {
            zoom-=1.0f;
            glutPostRedisplay();
            break;
        }
        else if (button==GLUT_WHEEL_DOWN)
        {
            zoom+=1.0f;
            glutPostRedisplay();
            break;
        }
    default:
        break;
    }

}
//按键响应
void processNormalKeys(unsigned char key,int x,int y)
{
    switch(key){
    case 27:
        exit(0);
        break;
    case 'l':
        if (!lp)
        {
            lp=TRUE;                // lp 设为 TRUE
            light=!light;                // 切换光源的 TRUE/FALSE
        }
        else{
            lp=FALSE;
            light=!light;    
        }
        if (!light)                // 如果没有光源
        {
            glDisable(GL_LIGHTING);        // 禁用光源
        }
        else                    // 否则
        {
            glEnable(GL_LIGHTING);        // 启用光源
        }
        break;
    case 'r':
        spin+=2.0f;
        if (spin>360.0f)
        {
            spin-=360.0f;
        }
        glutPostRedisplay();
        break;
    }

}

void processKeyUpDowm(int key,int x,int y){
    switch(key){
    case GLUT_KEY_UP:
            lp=TRUE;        
            break;
    case GLUT_KEY_DOWN:
        lp=false;
        break;
    default:
        break;
    }
}
//主函数
int _tmain(int argc, char**argv)
{
    glutInit(&argc,argv);
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); 
    glutInitWindowSize(640,480);
    glutInitWindowPosition(350,150);
    glutCreateWindow("this is my window");
    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMouseFunc(mouse);
    glutKeyboardFunc(processNormalKeys);
    glutMainLoop();
    return 0;
}

  材质(Material)是单身于物体顶点新闻之外的与渲染效果相关的特性。通过设置材质可以转移物体的水彩、纹理贴图、光照情势等。

ps:

  本篇将介绍中央材料以及两种基于光照模型的材料(Lamber与Phong)。

  镜面反射步骤:光源要安装镜面反射的特性、之后相应的实体要设置镜面反射的质量。还有自发光的质量emission,看起来就行物体在团结发光一样。

 

  尽量用glPushMatrix()和 
glPopMatrix()举办绘图,而glLoadIdentity()在先导化和重绘的时候用。

  MeshBasicMaterial:对光照无感,给几何体一种简易的颜色或浮现线框。

  暂时还没察觉回调函数中有捕获普通按键按下的函数,可是影响不是很大。长按一对一于接二连三按多次。

  MeshLambertMaterial:那种材料对光照有感应,用于成立暗淡的不发光的实体。

 

  MeshPhongMaterial:那种材质对光照也有感应,用于创制金属类明亮的实体。

 

1.焦点材料

  使用基本材料(BasicMaterial)的物体,渲染后物体的水彩始终为该材料的水彩,而不会由于光照暴发明暗、阴影效果。假若没有点名材质的颜色,则颜色是自由的。其构造函数是:

THREE.MeshLambertMaterial(opt)

  其中,opt可以缺省,或者为含有各属性的值。如新建一个不透明度为0.75的桃色材质:

new THREE.MeshBasicMaterial({

    color: 0xffff00,

    opacity: 0.75

});

  将其拔取于一个正方体(方法参见3.js-4,效果为:

图片 1

源码:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>3.js测试7.1</title>
    </head>
    <body onload="init()">
        <canvas id="mainCanvas" width="400px" height="300px" ></canvas>
    </body>
    <script type="text/javascript" src="js/three.min.js"></script>
    <script type="text/javascript">
        function init() {
            var renderer = new THREE.WebGLRenderer({
                canvas: document.getElementById('mainCanvas')
            });
            renderer.setClearColor(0x000000);
            var scene = new THREE.Scene();

            // camera
            var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 100);
            camera.position.set(25, 25, 25);
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);

            // light
            var light = new THREE.PointLight(0xffffff, 1, 100);
            light.position.set(10, 15, 5);
            scene.add(light);

            var material = new THREE.MeshBasicMaterial({
                color: 0xffff00,
                opacity: 0.75
            });

            var cube = new THREE.Mesh(new THREE.CubeGeometry(5, 5, 5), material);
            scene.add(cube);

            renderer.render(scene, camera);
        }
    </script>
</html>

 

  BasicMaterial的多少个相比常用的属性:

  ·
visible:是不是可知,默许为true

  ·
side:渲染面片正面或是反面,默许为正面THREE.FrontSide,可设置为反面THREE.BackSide,或双方THREE.DoubleSide

  ·
wireframe:是不是渲染线而非面,默许为false

  ·
color:十六进制RGB颜色,如黑色代表为0xff0000

  ·
map:使用纹理贴图

 

  对于基本材料,尽管改变风貌中的光源,使用该材料的实体也始终为颜色随处相同的效能。当然,那不是很富有真实感,因而,接下去大家将介绍更为真正的大同模型:Lambert光照模型以及Phong光照模型。

 

2.Lamber材质与Phong材质 

  兰伯特材质(MeshLambertMaterial)是符合兰伯特光照模型的质量。Lambert光照模型的显要特色是只考虑漫反射而不考虑镜面反射的职能,因此对于金属、镜子等需求镜面反射效率的实体就不适于,对于其余多数物体的漫反射效果都是适用的。

  其光照模型公式为:

Idiffuse = Kd * Id * cos(theta)

  其中,Idiffuse是漫反射光强,Kd是实体表面的漫反射属性,Id是光强,theta是光的入射角弧度。

  当然,对于使用Three.js的兰Bert材质,不要求领会以上公式就足以平昔动用。创设一个风骚的兰伯特材质的办法为:

new THREE.MeshLambertMaterial({

    color: 0xffff00

})

  在行使了光照之后,获得那样的成效:

图片 2

  color是用来显示材质对散射光的反光能力,也是最常用来设置材质颜色的特性。除此之外,仍是可以够用ambient和emissive控制材料的颜料。

  ambient表示对环境光的反光能力,唯有当设置了AmbientLight后,该值才是实用的,材质对环境光的反光能力与环境光强相乘后获取材质实际表现的颜色。

  emissive是材料的天生光颜色,可以用来表现光源的颜料,并不是一种光源,而是一种不受光照影响的颜色。单独行使藏紫色的自发光:

new THREE.MeshLambertMaterial({

    emissive: 0xff0000

})

  效果为:

图片 3

  即使同时使用黑色的自发光与色情的散射光:

new THREE.MeshLambertMaterial({

    color: 0xffff00,

    emissive: 0xff0000

})

  效果为:

图片 4

  球体的法力:

图片 5

 

  统计拉姆er材质的故意属性:

  ambient:设置材质的环境色,和AmbientLight光源一起使用,那个颜色会与环境光的颜色相乘。即是对光源作出反应。

  emissive:设置材质发射的颜色,不是一种光源,而是一种不受光照影响的颜料。默许为粉红色。

 

  源码:

 

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>3.js测试7.2</title>
    </head>
    <body onload="init()">
        <canvas id="mainCanvas" width="400px" height="300px" ></canvas>
    </body>
    <script type="text/javascript" src="js/three.min.js"></script> 
    <script type="text/javascript">
        function init() {
            var renderer = new THREE.WebGLRenderer({
                canvas: document.getElementById('mainCanvas')
            });
            renderer.setClearColor(0x000000);
            var scene = new THREE.Scene();

            // camera
            var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 100);
            camera.position.set(25, 25, 25);
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);

            // light
            var light = new THREE.PointLight(0xffffff, 1, 100);
            light.position.set(10, 15, 5);
            scene.add(light);

            var material = new THREE.MeshLambertMaterial({
                color: 0xffff00,
                emissive: 0xff0000
            });

            var cube = new THREE.Mesh(new THREE.CubeGeometry(5, 5, 5), material);
            scene.add(cube);

//            var sphere = new THREE.Mesh(new THREE.SphereGeometry(3, 20, 8), material);
//            scene.add(sphere);

            renderer.render(scene, camera);
        }
    </script>
</html>

 

3.phong材质

  Phong材质(MeshPhongMaterial)是契合Phong光照模型的材质。和Lambert不一样的是,Phong模型考虑了镜面反射的机能,因而对此金属、镜面的展现越发适合。

  漫反射部分和兰Bert光照模型是一模一样的,镜面反射部分的模子为:

Ispecular = Ks * Is * (cos(alpha)) ^ n

  其中,Ispecular是镜面反射的光强,Ks是材料表面镜面反射周到,Is是光源强度,alpha是反射光与视线的夹角,n是高光指数,越大则高光光斑越小。

  由于漫反射部分与兰Bert模型是一模一样的,因而,如果不点名镜面反射周全,而只设定漫反射,其成效与Lambert是如出一辙的:

new THREE.MeshPhongMaterial({

    color: 0xffff00

});

图片 6

  同样地,可以指定emissive和ambient值,那里不再表达。下边就specular值指定镜面反射全面作表明。首先,我们只利用镜面反射,将高光设为粉色,应用于一个圆球:

var material = new THREE.MeshPhongMaterial({

    specular: 0xff0000

});

var sphere = new THREE.Mesh(new THREE.SphereGeometry(3, 20, 8), material);

  效果为:

图片 7

  可以经过shininess属性控制光照模型中的n值,当shininess值越大时,高光的光斑越小,默许值为30。我们将其设置为1000时:

new THREE.MeshPhongMaterial({

    specular: 0xff0000,

    shininess: 1000

});

  效果为:

图片 8

  使用藏黄色的镜面光,藏蓝色的散射光:

material = new THREE.MeshPhongMaterial({

    color: 0xff0000,

    specular: 0xffff00,

    shininess: 100

});

图片 9

  统计Phong材质的有意属性:

  ambient:设置材质的环境色,和AmbientLight光源一起使用,那些颜色会与环境光的颜色相乘。即是对光源作出反应。

  emissive:设置材质发射的水彩,不是一种光源,而是一种不受光照影响的颜料。默许为灰色

  specular:指定该材料的雨水程度及其高光部分的颜料,假若设置成和color属性相同的颜料,则会收获另一个更为接近金属的品质,假如设置成grey褐色,则看起来像塑料

  shininess:指定高光部分的亮度,默许值为30.

 

  源码:

 

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>3.js测试7.3</title>
    </head>
    <body onload="init()">
        <canvas id="mainCanvas" width="400px" height="300px" ></canvas>
    </body>
    <script type="text/javascript" src="js/three.min.js"></script>
    <script type="text/javascript">
        function init() {
            var renderer = new THREE.WebGLRenderer({
                canvas: document.getElementById('mainCanvas')
            });
            renderer.setClearColor(0x000000);
            var scene = new THREE.Scene();

            // camera
            var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 100);
            camera.position.set(25, 25, 25);
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);

            // light
            var light = new THREE.PointLight(0xffffff, 1, 200);
            light.position.set(10, 15, 25);
            scene.add(light);

            var material = new THREE.MeshPhongMaterial({
//              specular: 0xff0000,
                color: 0xff0000,
                specular: 0xffff00,
                shininess: 100
            });

//          var cube = new THREE.Mesh(new THREE.CubeGeometry(5, 5, 5), material);
//          scene.add(cube);

            var sphere = new THREE.Mesh(new THREE.SphereGeometry(3, 20, 8), material);
            scene.add(sphere);

            renderer.render(scene, camera);
        }
    </script>
</html>

 

 

 

  整理自张雯莉《Three.js入门指南》

  其余参考:THREE.JS中常用的3种材料