Threejs光照

绘制流程。

使用是:
1.创建light
2light到场景。
2.调用render方法。

解析render方法对light处理过程。

this.render = function ( scene, camera, renderTarget, forceClear )
  1. 会将确定当前需要绘制scene和camera。从而确定当前需要渲染哪些。其中场景决定了哪些灯光需要参与渲染。
  2. render会调用renderState.setupLights(camera).
  3. setupLights调用webGLLights.setup(lights, shadows, camera)
  4. 重点是setup方法
function setup( lights, shadows, camera ) {

        var r = 0, g = 0, b = 0;

        var directionalLength = 0;
        var pointLength = 0;
        var spotLength = 0;
        var rectAreaLength = 0;
        var hemiLength = 0;

        var viewMatrix = camera.matrixWorldInverse;

        for ( var i = 0, l = lights.length; i < l; i ++ ) {

            var light = lights[ i ];

            var color = light.color;
            var intensity = light.intensity;
            var distance = light.distance;

            var shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null;

            if ( light.isAmbientLight ) {

                r += color.r * intensity;
                g += color.g * intensity;
                b += color.b * intensity;

            } else if ( light.isDirectionalLight ) {

                var uniforms = cache.get( light );

                uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
                uniforms.direction.setFromMatrixPosition( light.matrixWorld );
                vector3.setFromMatrixPosition( light.target.matrixWorld );
                uniforms.direction.sub( vector3 );
                uniforms.direction.transformDirection( viewMatrix );

                uniforms.shadow = light.castShadow;

                if ( light.castShadow ) {

                    var shadow = light.shadow;

                    uniforms.shadowBias = shadow.bias;
                    uniforms.shadowRadius = shadow.radius;
                    uniforms.shadowMapSize = shadow.mapSize;

                }

                state.directionalShadowMap[ directionalLength ] = shadowMap;
                state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
                state.directional[ directionalLength ] = uniforms;

                directionalLength ++;

            } else if ( light.isSpotLight ) {

                var uniforms = cache.get( light );

                uniforms.position.setFromMatrixPosition( light.matrixWorld );
                uniforms.position.applyMatrix4( viewMatrix );

                uniforms.color.copy( color ).multiplyScalar( intensity );
                uniforms.distance = distance;

                uniforms.direction.setFromMatrixPosition( light.matrixWorld );
                vector3.setFromMatrixPosition( light.target.matrixWorld );
                uniforms.direction.sub( vector3 );
                uniforms.direction.transformDirection( viewMatrix );

                uniforms.coneCos = Math.cos( light.angle );
                uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
                uniforms.decay = light.decay;

                uniforms.shadow = light.castShadow;

                if ( light.castShadow ) {

                    var shadow = light.shadow;

                    uniforms.shadowBias = shadow.bias;
                    uniforms.shadowRadius = shadow.radius;
                    uniforms.shadowMapSize = shadow.mapSize;

                }

                state.spotShadowMap[ spotLength ] = shadowMap;
                state.spotShadowMatrix[ spotLength ] = light.shadow.matrix;
                state.spot[ spotLength ] = uniforms;

                spotLength ++;

            } else if ( light.isRectAreaLight ) {

                var uniforms = cache.get( light );

                // (a) intensity is the total visible light emitted
                //uniforms.color.copy( color ).multiplyScalar( intensity / ( light.width * light.height * Math.PI ) );

                // (b) intensity is the brightness of the light
                uniforms.color.copy( color ).multiplyScalar( intensity );

                uniforms.position.setFromMatrixPosition( light.matrixWorld );
                uniforms.position.applyMatrix4( viewMatrix );

                // extract local rotation of light to derive width/height half vectors
                matrix42.identity();
                matrix4.copy( light.matrixWorld );
                matrix4.premultiply( viewMatrix );
                matrix42.extractRotation( matrix4 );

                uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
                uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );

                uniforms.halfWidth.applyMatrix4( matrix42 );
                uniforms.halfHeight.applyMatrix4( matrix42 );

                // TODO (abelnation): RectAreaLight distance?
                // uniforms.distance = distance;

                state.rectArea[ rectAreaLength ] = uniforms;

                rectAreaLength ++;

            } else if ( light.isPointLight ) {

                var uniforms = cache.get( light );

                uniforms.position.setFromMatrixPosition( light.matrixWorld );
                uniforms.position.applyMatrix4( viewMatrix );

                uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
                uniforms.distance = light.distance;
                uniforms.decay = light.decay;

                uniforms.shadow = light.castShadow;

                if ( light.castShadow ) {

                    var shadow = light.shadow;

                    uniforms.shadowBias = shadow.bias;
                    uniforms.shadowRadius = shadow.radius;
                    uniforms.shadowMapSize = shadow.mapSize;
                    uniforms.shadowCameraNear = shadow.camera.near;
                    uniforms.shadowCameraFar = shadow.camera.far;

                }

                state.pointShadowMap[ pointLength ] = shadowMap;
                state.pointShadowMatrix[ pointLength ] = light.shadow.matrix;
                state.point[ pointLength ] = uniforms;

                pointLength ++;

            } else if ( light.isHemisphereLight ) {

                var uniforms = cache.get( light );

                uniforms.direction.setFromMatrixPosition( light.matrixWorld );
                uniforms.direction.transformDirection( viewMatrix );
                uniforms.direction.normalize();

                uniforms.skyColor.copy( light.color ).multiplyScalar( intensity );
                uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );

                state.hemi[ hemiLength ] = uniforms;

                hemiLength ++;

            }

        }

        state.ambient[ 0 ] = r;
        state.ambient[ 1 ] = g;
        state.ambient[ 2 ] = b;

        state.directional.length = directionalLength;
        state.spot.length = spotLength;
        state.rectArea.length = rectAreaLength;
        state.point.length = pointLength;
        state.hemi.length = hemiLength;

        state.hash.stateID = state.id;
        state.hash.directionalLength = directionalLength;
        state.hash.pointLength = pointLength;
        state.hash.spotLength = spotLength;
        state.hash.rectAreaLength = rectAreaLength;
        state.hash.hemiLength = hemiLength;
        state.hash.shadowsLength = shadows.length;

    }

上面的代码是将灯光装换成uniforms数据,最终传递给GLSL。

  1. 上面的流程中并没有将灯光进行传递,接下来。回到render方法,设置了灯光之后,设置渲染目标,确定背景,接下来调用renderObjects去渲染场景下的所有网格。
  2. renderObjects通过循环调用renderObject
  3. renderobject通过判断是否需要即时渲染而调用renderObjectImmediate,或者使用renderBufferDirect。
  4. 最终 renderObjectImmediate和renderBufferDirect都会调用setProgram().
  5. 在setProgram()中会判断是否需要initMaterial();
  6. 在getParameters的时候,会将lights全部设置到属性中
var parameters = programCache.getParameters(
    material, 
    lights.state,
    shadowsArray,
    fog,
     _clipping.numPlanes,
    _clipping.numIntersection,
    object );

总结一下

  1. 当render的时候,threejs会先初始化renderState
  2. 为renderState添加sense中的lights,
  3. 在renderObject时,将材质中的lights合并到renderState中。
  4. 最后通过webGLPrograms.getParamesters(),将光照设置到Programs中。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,635评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,628评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,971评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,986评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,006评论 6 394
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,784评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,475评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,364评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,860评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,008评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,152评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,829评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,490评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,035评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,156评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,428评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,127评论 2 356

推荐阅读更多精彩内容