Fork me on GitHub

API Documentation


Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_scene_glge_light.js.html, line: 145 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_scene_glge_light.js.html, line: 145 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_scene_glge_light.js.html, line: 479 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_scene_glge_light.js.html, line: 479 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_scene_glge_light.js.html, line: 498 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_scene_glge_light.js.html, line: 498 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
  1 /*
  2 GLGE WebGL Graphics Engine
  3 Copyright (c) 2010, Paul Brunt
  4 All rights reserved.
  5 
  6 Redistribution and use in source and binary forms, with or without
  7 modification, are permitted provided that the following conditions are met:
  8     * Redistributions of source code must retain the above copyright
  9       notice, this list of conditions and the following disclaimer.
 10     * Redistributions in binary form must reproduce the above copyright
 11       notice, this list of conditions and the following disclaimer in the
 12       documentation and/or other materials provided with the distribution.
 13     * Neither the name of GLGE nor the
 14       names of its contributors may be used to endorse or promote products
 15       derived from this software without specific prior written permission.
 16 
 17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 20 DISCLAIMED. IN NO EVENT SHALL PAUL BRUNT BE LIABLE FOR ANY
 21 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 24 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 27 */
 28 
 29 /**
 30  * @fileOverview
 31  * @name glge_light.js
 32  * @author me@paulbrunt.co.uk
 33  */
 34 
 35 
 36 (function(GLGE){
 37 
 38 
 39 
 40 /**
 41 * @class Creates a new light source to be added to a scene
 42 * @property {Boolean} diffuse Dose this light source effect diffuse shading
 43 * @property {Boolean} specular Dose this light source effect specular shading
 44 * @augments GLGE.Animatable
 45 * @augments GLGE.Placeable
 46 * @augments GLGE.QuickNotation
 47 * @augments GLGE.JSONLoader
 48 */
 49 GLGE.Light=function(uid){
 50 	this.color={r:1,g:1,b:1};
 51 	GLGE.Assets.registerAsset(this,uid);
 52 }
 53 GLGE.augment(GLGE.Placeable,GLGE.Light);
 54 GLGE.augment(GLGE.Animatable,GLGE.Light);
 55 GLGE.augment(GLGE.QuickNotation,GLGE.Light);
 56 GLGE.augment(GLGE.JSONLoader,GLGE.Light);
 57 GLGE.Light.prototype.className="Light";
 58 
 59 /**
 60  * @name GLGE.Light#shaderupdate
 61  * @event fires when a light has changed resulting in need to recompile shaders
 62  * @param {object} data
 63  */
 64 
 65 /**
 66 * @constant 
 67 * @description Enumeration for an point light source
 68 */
 69 GLGE.L_POINT=1;
 70 /**
 71 * @constant 
 72 * @description Enumeration for an directional light source
 73 */
 74 GLGE.L_DIR=2;
 75 /**
 76 * @constant 
 77 * @description Enumeration for an spot light source
 78 */
 79 GLGE.L_SPOT=3;
 80 /**
 81 * @constant 
 82 * @description Enumeration a light that is disabled
 83 */
 84 GLGE.L_OFF=4;
 85 
 86 GLGE.Light.prototype.constantAttenuation=1;
 87 GLGE.Light.prototype.linearAttenuation=0.002;
 88 GLGE.Light.prototype.quadraticAttenuation=0.0008;
 89 GLGE.Light.prototype.spotCosCutOff=0.95;
 90 GLGE.Light.prototype.spotCutOff=true;
 91 GLGE.Light.prototype.spotPMatrix=null;
 92 GLGE.Light.prototype.spotExponent=10;
 93 GLGE.Light.prototype.color=null; 
 94 GLGE.Light.prototype.diffuse=true; 
 95 GLGE.Light.prototype.specular=true; 
 96 GLGE.Light.prototype.samples=0; 
 97 GLGE.Light.prototype.softness=0.01; 
 98 GLGE.Light.prototype.type=GLGE.L_POINT;
 99 GLGE.Light.prototype.frameBuffer=null;
100 GLGE.Light.prototype.renderBuffer=null;
101 GLGE.Light.prototype.texture=null;
102 GLGE.Light.prototype.bufferHeight=256;
103 GLGE.Light.prototype.bufferWidth=256;
104 GLGE.Light.prototype.shadowBias=0.002;
105 GLGE.Light.prototype.castShadows=false;
106 GLGE.Light.prototype.cascadeLevels=3;
107 GLGE.Light.prototype.distance=500;
108 GLGE.Light.prototype.spotSoftness=0;
109 GLGE.Light.prototype.spotSoftnessDistance=0.3;
110 
111 
112 /**
113 * Gets the number of cascade levels to use for directional shadows
114 * @returns {number} the number of cascades
115 */
116 GLGE.Light.prototype.getCascadeLevels=function(){	
117 	return this.cascadeLevels;
118 }
119 /**
120 * Sets the number of cascade levels for directions shadows
121 * @param {number} cascadeLevels The number of cascade levels(higher slower better quailty)
122 */
123 GLGE.Light.prototype.setCascadeLevels=function(cascadeLevels){	
124 	this.cascadeLevels=+cascadeLevels;
125 	this.fireEvent("shaderupdate",{});
126 	return this;
127 }
128 
129 
130 /**
131 * Gets the spot lights projection matrix
132 * @returns the lights spot projection matrix
133 * @private
134 */
135 GLGE.Light.prototype.getPMatrix=function(cvp,invlight,projectedDistance,distance){
136 	if(!this.spotPMatrix){
137 		var far;
138 		if(this.scene && this.scene.camera) far=this.scene.camera.far;
139 			else far=1000;
140 		if(this.type==GLGE.L_SPOT){
141 			this.spotPMatrix=GLGE.makePerspective(Math.acos(this.spotCosCutOff)/3.14159*360, 1.0, 0.1, far);
142 		}
143 	}
144 	 if(this.type==GLGE.L_DIR){
145 		this.spotPMatrix=GLGE.getDirLightProjection(cvp,invlight,projectedDistance,distance);
146 	}
147 	return this.spotPMatrix;
148 }
149 
150 
151 
152 /**
153 * Sets the shadow casting flag
154 * @param {number} distance
155 */
156 GLGE.Light.prototype.setDistance=function(value){
157 	this.distance=value;
158 	this.fireEvent("shaderupdate",{});
159 	return this;
160 }
161 /**
162 * Gets the shadow casting distance
163 * @returns {number} distance
164 */
165 GLGE.Light.prototype.getDistance=function(){
166 	return this.distance;
167 }
168 
169 /**
170 * Sets negative shadow flag
171 * @param {boolean} negative shadow
172 */
173 GLGE.Light.prototype.setNegativeShadow=function(value){
174 	this.negativeShadow=value;
175 	this.fireEvent("shaderupdate",{});
176 	return this;
177 }
178 /**
179 * Gets negative shadow flag
180 * @param {boolean} negative shadow
181 */
182 GLGE.Light.prototype.getNegative=function(){
183 	return this.negativeShadow;
184 }
185 
186 /**
187 * Sets the shadow casting flag
188 * @param {number} value should cast shadows?
189 */
190 GLGE.Light.prototype.setCastShadows=function(value){
191 	this.castShadows=value;
192 	this.fireEvent("shaderupdate",{});
193 	return this;
194 }
195 /**
196 * Gets the shadow casting flag
197 * @returns {number} true if casts shadows
198 */
199 GLGE.Light.prototype.getCastShadows=function(){
200 	return this.castShadows;
201 	return this;
202 }
203 /**
204 * Sets the shadow bias
205 * @param {number} value The shadow bias
206 */
207 GLGE.Light.prototype.setShadowBias=function(value){
208 	this.shadowBias=value;
209 	return this;
210 }
211 /**
212 * Gets the shadow bias
213 * @returns {number} The shadow buffer bias
214 */
215 GLGE.Light.prototype.getShadowBias=function(){
216 	return this.shadowBias;
217 }
218 
219 /**
220 * Sets the number of samples for this shadow
221 * @param {number} value The number of samples to perform
222 */
223 GLGE.Light.prototype.setShadowSamples=function(value){
224 	this.samples=value;
225 	this.fireEvent("shaderupdate",{});
226 	return this;
227 }
228 /**
229 * Gets the number of samples for this shadow
230 * @returns {number} The number of samples
231 */
232 GLGE.Light.prototype.getShadowSamples=function(){
233 	return this.samples;
234 }
235 /**
236 * Sets the shadow softness
237 * @param {number} value The number of samples to perform
238 */
239 GLGE.Light.prototype.setShadowSoftness=function(value){
240 	this.softness=value;
241 	this.fireEvent("shaderupdate",{});
242 	return this;
243 }
244 /**
245 * Gets the shadow softness
246 * @returns {number} The softness of the shadows
247 */
248 GLGE.Light.prototype.getShadowSamples=function(){
249 	return this.softness;
250 }
251 /**
252 * Sets the shadow buffer width
253 * @param {number} value The shadow buffer width
254 */
255 GLGE.Light.prototype.setBufferWidth=function(value){
256 	this.bufferWidth=value;
257 	return this;
258 }
259 /**
260 * Gets the shadow buffer width
261 * @returns {number} The shadow buffer width
262 */
263 GLGE.Light.prototype.getBufferHeight=function(){
264 	return this.bufferHeight;
265 }
266 /**
267 * Sets the shadow buffer width
268 * @param {number} value The shadow buffer width
269 */
270 GLGE.Light.prototype.setBufferHeight=function(value){
271 	this.bufferHeight=value;
272 	return this;
273 }
274 /**
275 * Gets the shadow buffer width
276 * @returns {number} The shadow buffer width
277 */
278 GLGE.Light.prototype.getBufferWidth=function(){
279 	return this.bufferWidth;
280 }
281 /**
282 * Sets the spot light cut off
283 * @param {number} value The cos of the angle to limit
284 */
285 GLGE.Light.prototype.setSpotCosCutOff=function(value){
286 	this.spotPMatrix=null;
287 	this.spotCosCutOff=value;
288 	return this;
289 }
290 /**
291 * Gets the spot light cut off
292 * @returns {number} The cos of the limiting angle 
293 */
294 GLGE.Light.prototype.getSpotCosCutOff=function(){
295 	return this.spotCosCutOff;
296 }
297 
298 /**
299 * Sets the spot light cut off true results in circle spot light otherwise square
300 * @param {number} value The spot cutoff flag
301 */
302 GLGE.Light.prototype.setSpotCutOff=function(value){
303 	this.spotCutOff=value;
304 	this.fireEvent("shaderupdate",{});
305 	return this;
306 }
307 /**
308 * Gets the spot light cut off flag
309 * @returns {number} The spot cutoff flag
310 */
311 GLGE.Light.prototype.getSpotCutOff=function(){
312 	return this.spotCutOff;
313 }
314 
315 /**
316 * Sets the spot light exponent
317 * @param {number} value The spot lights exponent
318 */
319 GLGE.Light.prototype.setSpotExponent=function(value){
320 	this.spotExponent=value;
321 	return this;
322 }
323 /**
324 * Gets the spot light exponent
325 * @returns {number} The exponent of the spot light
326 */
327 GLGE.Light.prototype.getSpotExponent=function(){
328 	return this.spotExponent;
329 }
330 /**
331 * Sets the light sources Attenuation
332 * @returns {Object} The components of the light sources attenuation
333 */
334 GLGE.Light.prototype.getAttenuation=function(constant,linear,quadratic){
335 	var attenuation={};
336 	attenuation.constant=this.constantAttenuation;
337 	attenuation.linear=this.linearAttenuation;
338 	attenuation.quadratic=this.quadraticAttenuation;
339 	return attenuation;
340 }
341 /**
342 * Sets the light sources Attenuation
343 * @param {Number} constant The constant part of the attenuation
344 * @param {Number} linear The linear part of the attenuation
345 * @param {Number} quadratic The quadratic part of the attenuation
346 */
347 GLGE.Light.prototype.setAttenuation=function(constant,linear,quadratic){
348 	this.constantAttenuation=constant;
349 	this.linearAttenuation=linear;
350 	this.quadraticAttenuation=quadratic;
351 	return this;
352 }
353 /**
354 * Sets the light sources constant attenuation
355 * @param {Number} value The constant part of the attenuation
356 */
357 GLGE.Light.prototype.setAttenuationConstant=function(value){
358 	this.constantAttenuation=value;
359 	return this;
360 }
361 /**
362 * Sets the light sources linear attenuation
363 * @param {Number} value The linear part of the attenuation
364 */
365 GLGE.Light.prototype.setAttenuationLinear=function(value){
366 	this.linearAttenuation=value;
367 	return this;
368 }
369 /**
370 * Sets the light sources quadratic attenuation
371 * @param {Number} value The quadratic part of the attenuation
372 */
373 GLGE.Light.prototype.setAttenuationQuadratic=function(value){
374 	this.quadraticAttenuation=value;
375 	return this;
376 }
377 
378 /**
379 * Sets the color of the light source
380 * @param {string} color The color of the light
381 */
382 GLGE.Light.prototype.setColor=function(color){
383 	color=GLGE.colorParse(color);
384 	this.color={r:color.r,g:color.g,b:color.b};
385 	return this;
386 }
387 /**
388 * Sets the red color of the light source
389 * @param {Number} value The new red level 0-1
390 */
391 GLGE.Light.prototype.setColorR=function(value){
392 	this.color.r=value;
393 	return this;
394 }
395 /**
396 * Sets the green color of the light source
397 * @param {Number} value The new green level 0-1
398 */
399 GLGE.Light.prototype.setColorG=function(value){
400 	this.color.g=value;
401 	return this;
402 }
403 /**
404 * Sets the blue color of the light source
405 * @param {Number} value The new blue level 0-1
406 */
407 GLGE.Light.prototype.setColorB=function(value){
408 	this.color.b=value;
409 	return this;
410 }
411 /**
412 * Gets the current color of the light source
413 * @return {[r,g,b]} The current position
414 */
415 GLGE.Light.prototype.getColor=function(){
416 	return this.color;
417 }
418 /**
419 420 * Gets the type of the light
421 * @return {Number} The type of the light source eg GLGE.L_POINT
422 */
423 GLGE.Light.prototype.getType=function(){
424 	return this.type;
425 }
426 /**
427 * Sets the type of the light
428 * @param {Number} type The type of the light source eg GLGE.L_POINT
429 */
430 GLGE.Light.prototype.setType=function(type){
431 	this.type=type;
432 	this.fireEvent("shaderupdate",{});
433 	return this;
434 }
435 
436 /**
437 * Gets the softness of the spot shadow
438 * @return {Number} The type of the light source eg GLGE.L_POINT
439 */
440 GLGE.Light.prototype.getSpotSoftness=function(){
441 	return this.spotSoftness;
442 }
443 /**
444 * Sets the softness of the spot shadow
445 * @param {Number} spotSoftness The type of the light source eg GLGE.L_POINT
446 */
447 GLGE.Light.prototype.setSpotSoftness=function(spotSoftness){
448 	this.spotSoftness=+spotSoftness;
449 	if(this.gl) this.createSoftPrograms(this.gl);
450 	this.fireEvent("shaderupdate",{});
451 	return this;
452 }
453 
454 /**
455 * Gets the spotlights blur distance in pixels
456 * @return {Number} The blur distance for spot lights
457 */
458 GLGE.Light.prototype.getSpotSoftDistance=function(){
459 	return this.spotSoftnessDistance;
460 }
461 /**
462 * Sets the spotlights variance cutoff used to reduce light bleed
463 * @param {Number} spotSoftnessDistance the spotlights variance cutoff
464 */
465 GLGE.Light.prototype.setSpotSoftDistance=function(spotSoftnessDistance){
466 	this.spotSoftnessDistance=+spotSoftnessDistance;
467 	this.fireEvent("shaderupdate",{});
468 	return this;
469 }
470 
471 
472 GLGE.Light.prototype.enableLight=function(){
473     if (this.type == GLGE.L_OFF && this.old_type !== undefined) {
474         this.setType(this.old_type);
475         delete this.old_type;
476     }
477 };
478 
479 GLGE.Light.prototype.disableLight=function(){
480     if (this.type != GLGE.L_OFF) {
481         this.old_type=this.type;
482         this.setType(GLGE.L_OFF);
483     }
484 };
485 
486 /**
487 * init for the rendering
488 * @private
489 */
490 GLGE.Light.prototype.GLInit=function(gl){	
491 	this.gl=gl;
492 	if((this.type==GLGE.L_SPOT || this.type==GLGE.L_DIR) && !this.texture){
493 		this.createSpotBuffer(gl);
494 		this.createSoftBuffer(gl);
495 		this.createSoftPrograms(gl);
496 	}
497 }
498 /**
499 * Sets up the WebGL needed to render the depth map for this light source. Only used for spot lights which produce shadows
500 * @private
501 */
502 GLGE.Light.prototype.createSpotBuffer=function(gl){
503     this.frameBuffer = gl.createFramebuffer();
504     this.renderBuffer = gl.createRenderbuffer();
505     this.texture = gl.createTexture();
506     gl.bindTexture(gl.TEXTURE_2D, this.texture);
507 
508     try {
509         gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.bufferWidth, this.bufferHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
510     } catch (e) {
511         GLGE.error("incompatible texture creation method");
512         var width=parseFloat(this.bufferWidth);
513         var height=parseFloat(this.bufferHeight);
514         var tex = new Uint8Array(width * height * 4);
515         gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, tex);
516     }
517     
518     gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer);
519     gl.bindRenderbuffer(gl.RENDERBUFFER, this.renderBuffer);
520     gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, this.bufferWidth, this.bufferHeight);
521     
522     gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture, 0);
523     gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this.renderBuffer);
524     gl.bindFramebuffer(gl.FRAMEBUFFER, null);
525     gl.bindRenderbuffer(gl.RENDERBUFFER, null);
526     gl.bindTexture(gl.TEXTURE_2D, null);
527 }
528 
529 /**
530 * Sets up the buffers needed for the gaussian blured shadow buffer
531 * @private
532 */
533 GLGE.Light.prototype.createSoftBuffer=function(gl){
534     this.frameBufferSf = gl.createFramebuffer();
535     this.renderBufferSf = gl.createRenderbuffer();
536     this.textureSf = gl.createTexture();
537     gl.bindTexture(gl.TEXTURE_2D, this.textureSf);
538 
539     try {
540         gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.bufferWidth, this.bufferHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
541     } catch (e) {
542         GLGE.error("incompatible texture creation method");
543         var width=parseFloat(this.bufferWidth);
544         var height=parseFloat(this.bufferHeight);
545         var tex = new Uint8Array(width * height * 4);
546         gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, tex);
547     }
548     
549     gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBufferSf);
550     gl.bindRenderbuffer(gl.RENDERBUFFER, this.renderBufferSf);
551     gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, this.bufferWidth, this.bufferHeight);
552     
553     gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.textureSf, 0);
554     gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this.renderBufferSf);
555     gl.bindFramebuffer(gl.FRAMEBUFFER, null);
556     gl.bindRenderbuffer(gl.RENDERBUFFER, null);
557     gl.bindTexture(gl.TEXTURE_2D, null);
558     
559     //create the vertex positions
560 	if(!this.posBuffer) this.posBuffer = gl.createBuffer();
561 	gl.bindBuffer(gl.ARRAY_BUFFER, this.posBuffer);
562 	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1,1,0,-1,1,0,-1,-1,0,1,-1,0]), gl.STATIC_DRAW);
563 	this.posBuffer.itemSize = 3;
564 	this.posBuffer.numItems = 4;
565 	//create the vertex uv coords
566 	if(!this.uvBuffer) this.uvBuffer = gl.createBuffer();
567 	gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer);
568 	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1,1,0,1,0,0,1,0]), gl.STATIC_DRAW);
569 	this.uvBuffer.itemSize = 2;
570 	this.uvBuffer.numItems = 4;
571 	//create the faces
572 	if(!this.GLfaces) this.GLfaces = gl.createBuffer();
573 	gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.GLfaces);
574 	gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([2,1,0,0,3,2]), gl.STATIC_DRAW);
575 	this.GLfaces.itemSize = 1;
576 	this.GLfaces.numItems = 6;
577 }
578 
579 /**
580 * Sets up the programs require to do the soft shadows
581 * @private
582 */
583 GLGE.Light.prototype.createSoftPrograms=function(gl){
584 	if(this.GLShaderProgram) gl.deleteProgram(this.GLShaderProgram);
585 
586 	var vertexStr="";
587 	vertexStr+="attribute vec3 position;\n";
588 	vertexStr+="attribute vec2 uvcoord;\n";
589 	vertexStr+="varying vec2 texCoord;\n";
590 	vertexStr+="void main(void){\n";
591 	vertexStr+="texCoord=uvcoord;\n";    
592 	vertexStr+="gl_Position = vec4(position,1.0);\n";
593 	vertexStr+="}\n";
594 
595 	var SAMPLES=this.spotSoftness;
596 	
597 	var fragStr="precision mediump float;\n";
598 	fragStr=fragStr+"uniform sampler2D TEXTURE;\n";
599 	fragStr=fragStr+"varying vec2 texCoord;\n";
600 	fragStr=fragStr+"uniform bool xpass;\n";
601 	fragStr=fragStr+"float blurSize = "+(1/this.bufferWidth).toFixed(10)+";\n";
602 	fragStr=fragStr+"float unpack(sampler2D TEX, vec2 co){;";
603 	fragStr=fragStr+"float value = dot(texture2D(TEX, co), vec4(0.000000059604644775390625,0.0000152587890625,0.00390625,1.0));";
604 	fragStr=fragStr+"return value;";
605 	fragStr=fragStr+"}";
606 	fragStr=fragStr+"vec2 unpack2(sampler2D TEX, vec2 co){;";
607 	fragStr=fragStr+"vec4 color = texture2D(TEX, co);";
608 	fragStr=fragStr+"float value1 = dot(color.rg, vec2(0.00390625,1.0));";
609 	fragStr=fragStr+"float value2 = dot(color.ba, vec2(0.00390625,1.0));";
610 	fragStr=fragStr+"return vec2(value1,value2);";
611 	fragStr=fragStr+"}";
612 	fragStr=fragStr+"vec4 pack(float value){;";
613 	fragStr=fragStr+"vec4 rgba=fract(value * vec4(16777216.0, 65536.0, 256.0, 1.0));\n";
614 	fragStr=fragStr+"return rgba-rgba.rrgb*vec4(0.0,0.00390625,0.00390625,0.00390625);";
615 	fragStr=fragStr+"}";
616 	fragStr=fragStr+"vec2 pack2(float value){;";
617 	fragStr=fragStr+"vec2 rg=fract(value * vec2(256.0, 1.0));\n";
618 	fragStr=fragStr+"return rg-rg.rr*vec2(0.0,0.00390625);";
619 	fragStr=fragStr+"}";
620 	fragStr=fragStr+"void main(void){\n";
621 	fragStr=fragStr+"float value = 0.0;";
622 	fragStr=fragStr+"vec2 value2;";
623 	fragStr=fragStr+"float mean = 0.0;";
624 	fragStr=fragStr+"float mean2 = 0.0;";
625 	fragStr=fragStr+"float color = 0.0;";
626 	fragStr=fragStr+"if(xpass){";
627 	for(var i=-SAMPLES;i<SAMPLES;i++){
628 		fragStr=fragStr+"value = unpack(TEXTURE, vec2(texCoord.x - "+(i+0.5).toFixed(1)+"*blurSize, texCoord.y));";
629 		fragStr=fragStr+"mean += value;";
630 		fragStr=fragStr+"mean2 += value*value;";
631 	}
632 	fragStr=fragStr+"gl_FragColor = vec4(pack2(pow(mean2/"+(SAMPLES*2).toFixed(2)+",0.5)),pack2(mean/"+(SAMPLES*2).toFixed(2)+"));\n";
633 	fragStr=fragStr+"}else{";
634 	for(var i=-SAMPLES;i<SAMPLES;i++){
635 		fragStr=fragStr+"value2 = unpack2(TEXTURE, vec2(texCoord.x, texCoord.y - "+(i+0.5).toFixed(1)+"*blurSize));";
636 		fragStr=fragStr+"mean += value2.g;";
637 		fragStr=fragStr+"mean2 += pow(value2.r,2.0);";
638 	}
639 	fragStr=fragStr+"gl_FragColor = vec4(pack2(pow(mean2/"+(SAMPLES*2).toFixed(2)+",0.5)),pack2(mean/"+(SAMPLES*2).toFixed(2)+"));\n";
640 	fragStr=fragStr+"}";
641 	
642 	fragStr=fragStr+"}\n";
643 
644 	this.GLFragmentShader=gl.createShader(gl.FRAGMENT_SHADER);
645 	this.GLVertexShader=gl.createShader(gl.VERTEX_SHADER);
646 
647 	gl.shaderSource(this.GLFragmentShader, fragStr);
648 	gl.compileShader(this.GLFragmentShader);
649 	if (!gl.getShaderParameter(this.GLFragmentShader, gl.COMPILE_STATUS)) {
650 	      GLGE.error(gl.getShaderInfoLog(this.GLFragmentShader));
651 	      return;
652 	}
653 
654 	gl.shaderSource(this.GLVertexShader, vertexStr);
655 	gl.compileShader(this.GLVertexShader);
656 	if (!gl.getShaderParameter(this.GLVertexShader, gl.COMPILE_STATUS)) {
657 		GLGE.error(gl.getShaderInfoLog(this.GLVertexShader));
658 		return;
659 	}
660 
661 	this.GLShaderProgram = gl.createProgram();
662 	gl.attachShader(this.GLShaderProgram, this.GLVertexShader);
663 	gl.attachShader(this.GLShaderProgram, this.GLFragmentShader);
664 	gl.linkProgram(this.GLShaderProgram);	
665 }
666 
667 /**
668 * Renders the blured shadow
669 * @private
670 */
671 GLGE.Light.prototype.GLRenderSoft=function(gl){
672 	if(this.spotSoftness==0) return;
673 	
674 	if(!this.gl){
675 		this.GLInit(gl);
676 	}	
677 	
678 	gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBufferSf);
679 
680 	if(gl.program!=this.GLShaderProgram){
681 		gl.useProgram(this.GLShaderProgram);
682 		gl.program=this.GLShaderProgram;
683 	}
684 
685 	var attribslot;
686 	for(var i=0; i<8; i++) gl.disableVertexAttribArray(i);
687 	attribslot=GLGE.getAttribLocation(gl,this.GLShaderProgram, "position");
688 
689 	gl.bindBuffer(gl.ARRAY_BUFFER, this.posBuffer);
690 	gl.enableVertexAttribArray(attribslot);
691 	gl.vertexAttribPointer(attribslot, this.posBuffer.itemSize, gl.FLOAT, false, 0, 0);
692 
693 	attribslot=GLGE.getAttribLocation(gl,this.GLShaderProgram, "uvcoord");
694 	gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer);
695 	gl.enableVertexAttribArray(attribslot);
696 	gl.vertexAttribPointer(attribslot, this.uvBuffer.itemSize, gl.FLOAT, false, 0, 0);
697 
698 	gl.activeTexture(gl["TEXTURE0"]);
699 	gl.bindTexture(gl.TEXTURE_2D, this.texture);
700 	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
701 	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
702 	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
703 	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
704 	GLGE.setUniform(gl,"1i",GLGE.getUniformLocation(gl,this.GLShaderProgram, "TEXTURE"),0);
705 	GLGE.setUniform(gl,"1i",GLGE.getUniformLocation(gl,this.GLShaderProgram, "xpass"),1);
706 
707 	gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.GLfaces);
708 
709 	gl.clear(gl.DEPTH_BUFFER_BIT | gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
710 	gl.drawElements(gl.TRIANGLES, this.GLfaces.numItems, gl.UNSIGNED_SHORT, 0);
711 	
712 	//gl.disable(gl.BLEND);
713 	gl.activeTexture(gl["TEXTURE0"]);
714 	gl.bindTexture(gl.TEXTURE_2D, this.textureSf);
715 	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
716 	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
717 	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
718 	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
719 	GLGE.setUniform(gl,"1i",GLGE.getUniformLocation(gl,this.GLShaderProgram, "TEXTURE"),0);
720 	GLGE.setUniform(gl,"1i",GLGE.getUniformLocation(gl,this.GLShaderProgram, "xpass"),0);
721 
722 	gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer);
723 	
724 	gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.GLfaces);
725 	gl.drawElements(gl.TRIANGLES, this.GLfaces.numItems, gl.UNSIGNED_SHORT, 0);
726 	
727 	
728 	gl.bindTexture(gl.TEXTURE_2D, null);
729 	gl.bindFramebuffer(gl.FRAMEBUFFER, null);
730 }
731 
732 
733 })(GLGE);
734