OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2010, Google Inc. | 2 * Copyright 2010, Google Inc. |
3 * All rights reserved. | 3 * All rights reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions are | 6 * modification, are permitted provided that the following conditions are |
7 * met: | 7 * met: |
8 * | 8 * |
9 * * Redistributions of source code must retain the above copyright | 9 * * Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 o3d.EffectStreamInfo.prototype.semanticIndex = 0; | 117 o3d.EffectStreamInfo.prototype.semanticIndex = 0; |
118 | 118 |
119 | 119 |
120 /** | 120 /** |
121 * An Effect contains a vertex and pixel shader. | 121 * An Effect contains a vertex and pixel shader. |
122 * @constructor | 122 * @constructor |
123 */ | 123 */ |
124 o3d.Effect = function() { | 124 o3d.Effect = function() { |
125 o3d.ParamObject.call(this); | 125 o3d.ParamObject.call(this); |
126 this.program_ = null; | 126 this.program_ = null; |
| 127 this.uniforms_ = {}; |
| 128 this.attributes_ = {}; |
127 }; | 129 }; |
128 o3d.inherit('Effect', 'ParamObject'); | 130 o3d.inherit('Effect', 'ParamObject'); |
129 | 131 |
130 | 132 |
131 /** | 133 /** |
| 134 * An object mapping the names of uniform variables to objects containing |
| 135 * information about the variable. |
| 136 * @type {Object} |
| 137 * @private |
| 138 */ |
| 139 o3d.Effect.prototype.uniforms_ = {}; |
| 140 |
| 141 |
| 142 /** |
| 143 * An object mapping the names of attributes to objects containing |
| 144 * information about the attribute. |
| 145 * @type {Object} |
| 146 * @private |
| 147 */ |
| 148 o3d.Effect.prototype.attributes_ = {}; |
| 149 |
| 150 |
| 151 /** |
132 * Indicates whether the vertex shader has been loaded, so we can | 152 * Indicates whether the vertex shader has been loaded, so we can |
133 * postpone linking until both shaders are in. | 153 * postpone linking until both shaders are in. |
134 * | 154 * |
135 * @type {boolean} | 155 * @type {boolean} |
136 */ | 156 */ |
137 o3d.Effect.prototype.vertexShaderLoaded_ = false; | 157 o3d.Effect.prototype.vertexShaderLoaded_ = false; |
138 | 158 |
139 | 159 |
140 /** | 160 /** |
141 * Indicates whether the fragment shader has been loaded, so we can | 161 * Indicates whether the fragment shader has been loaded, so we can |
142 * postpone linking until both shaders are in. | 162 * postpone linking until both shaders are in. |
143 * | 163 * |
144 * @type {boolean} | 164 * @type {boolean} |
145 */ | 165 */ |
146 o3d.Effect.prototype.fragmentShaderLoaded_ = false; | 166 o3d.Effect.prototype.fragmentShaderLoaded_ = false; |
147 | 167 |
148 | 168 |
149 /** | 169 /** |
150 * Binds standard attribute locations for the shader. | 170 * Binds standard attribute locations for the shader. |
151 */ | 171 */ |
152 o3d.Effect.prototype.bindAttributesAndLinkIfReady = function() { | 172 o3d.Effect.prototype.bindAttributesAndLinkIfReady = function() { |
153 if (this.vertexShaderLoaded_ && this.fragmentShaderLoaded_) { | 173 if (this.vertexShaderLoaded_ && this.fragmentShaderLoaded_) { |
154 var attributes = ['position', 'normal', 'tangent', 'binormal', 'color', | 174 var attributes = ['position', 'normal', 'tangent', 'binormal', 'color', |
155 'texCoord0', 'texCoord1', 'texCoord2', 'texCoord3', | 175 'texCoord0', 'texCoord1', 'texCoord2', 'texCoord3', |
156 'texCoord4', 'texCoord5', 'texCoord6', 'texCoord7']; | 176 'texCoord4', 'texCoord5', 'texCoord6', 'texCoord7']; |
157 for (var i = 0; i < attributes.length; ++i) { | 177 for (var i = 0; i < attributes.length; ++i) { |
158 this.gl.bindAttribLocation(this.program_, i, attributes[i]); | 178 this.gl.bindAttribLocation(this.program_, i, attributes[i]); |
159 } | 179 } |
160 this.gl.linkProgram(this.program_); | 180 this.gl.linkProgram(this.program_); |
161 this.getAllUniforms(); | 181 this.getUniforms_(); |
| 182 this.getAttributes_(); |
162 } | 183 } |
163 }; | 184 }; |
164 | 185 |
165 | 186 |
166 /** | 187 /** |
167 * Helper function for loadVertexShaderFromString and | 188 * Helper function for loadVertexShaderFromString and |
168 * loadPixelShaderFromString that takes the type as an argument. | 189 * loadPixelShaderFromString that takes the type as an argument. |
169 * @param {string} shaderString The shader code. | 190 * @param {string} shaderString The shader code. |
170 * @param {number} type The type of the shader: either | 191 * @param {number} type The type of the shader: either |
171 * VERTEX_SHADER or FRAGMENT_SHADER. | 192 * VERTEX_SHADER or FRAGMENT_SHADER. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 */ | 227 */ |
207 o3d.Effect.prototype.loadPixelShaderFromString = | 228 o3d.Effect.prototype.loadPixelShaderFromString = |
208 function(shaderString) { | 229 function(shaderString) { |
209 this.loadShaderFromString(shaderString, this.gl.FRAGMENT_SHADER); | 230 this.loadShaderFromString(shaderString, this.gl.FRAGMENT_SHADER); |
210 this.fragmentShaderLoaded_ = true; | 231 this.fragmentShaderLoaded_ = true; |
211 this.bindAttributesAndLinkIfReady(); | 232 this.bindAttributesAndLinkIfReady(); |
212 }; | 233 }; |
213 | 234 |
214 | 235 |
215 /** | 236 /** |
| 237 * Loads a glsl vertex shader and pixel shader from one string. |
| 238 * Assumes the vertex shader and pixel shader are separated by |
| 239 * the text '// #o3d SplitMarker'. |
| 240 * @param {string} shaderString The string. |
| 241 */ |
| 242 o3d.Effect.prototype.loadFromFXString = |
| 243 function(shaderString) { |
| 244 var splitIndex = shaderString.indexOf('// #o3d SplitMarker'); |
| 245 this.loadVertexShaderFromString(shaderString.substr(0, splitIndex)); |
| 246 this.loadPixelShaderFromString(shaderString.substr(splitIndex)); |
| 247 }; |
| 248 |
| 249 |
| 250 /** |
216 * Iterates through the active uniforms of the program and gets the | 251 * Iterates through the active uniforms of the program and gets the |
217 * location of each one and stores them by name in the uniforms | 252 * location of each one and stores them by name in the uniforms |
218 * object. | 253 * object. |
| 254 * @private |
219 */ | 255 */ |
220 o3d.Effect.prototype.getAllUniforms = | 256 o3d.Effect.prototype.getUniforms_ = |
221 function() { | 257 function() { |
222 this.uniforms = {}; | 258 this.uniforms_ = {}; |
223 var numUniforms = this.gl.getProgramParameter( | 259 var numUniforms = this.gl.getProgramParameter( |
224 this.program_, this.gl.ACTIVE_UNIFORMS); | 260 this.program_, this.gl.ACTIVE_UNIFORMS); |
225 for (var i = 0; i < numUniforms; ++i) { | 261 for (var i = 0; i < numUniforms; ++i) { |
226 var info = this.gl.getActiveUniform(this.program_, i); | 262 var info = this.gl.getActiveUniform(this.program_, i); |
227 this.uniforms[info.name] = {info:info, | 263 this.uniforms_[info.name] = {info:info, |
| 264 location:this.gl.getUniformLocation(this.program_, info.name)}; |
| 265 } |
| 266 }; |
| 267 |
| 268 |
| 269 /** |
| 270 * Iterates through the active uniforms of the program and gets the |
| 271 * location of each one and stores them by name in the uniforms |
| 272 * object. |
| 273 * @private |
| 274 */ |
| 275 o3d.Effect.prototype.getAttributes_ = |
| 276 function() { |
| 277 this.attributes_ = {}; |
| 278 var numAttributes = this.gl.getProgramParameter( |
| 279 this.program_, this.gl.ACTIVE_ATTRIBUTES); |
| 280 for (var i = 0; i < numAttributes; ++i) { |
| 281 var info = this.gl.getActiveAttrib(this.program_, i); |
| 282 this.attributes_[info.name] = {info:info, |
228 location:this.gl.getUniformLocation(this.program_, info.name)}; | 283 location:this.gl.getUniformLocation(this.program_, info.name)}; |
229 } | 284 } |
230 }; | 285 }; |
231 | 286 |
232 | 287 |
233 /** | 288 /** |
234 * For each of the effect's uniform parameters, creates corresponding | 289 * For each of the effect's uniform parameters, creates corresponding |
235 * parameters on the given ParamObject. Skips SAS Parameters. | 290 * parameters on the given ParamObject. Skips SAS Parameters. |
236 * | 291 * |
237 * If a Param with the same name but the wrong type already exists on the | 292 * If a Param with the same name but the wrong type already exists on the |
(...skipping 27 matching lines...) Expand all Loading... |
265 'worldViewTranspose': true, | 320 'worldViewTranspose': true, |
266 'worldProjectionTranspose': true, | 321 'worldProjectionTranspose': true, |
267 'worldViewProjectionTranspose': true, | 322 'worldViewProjectionTranspose': true, |
268 'worldInverseTranspose': true, | 323 'worldInverseTranspose': true, |
269 'viewInverseTranspose': true, | 324 'viewInverseTranspose': true, |
270 'projectionInverseTranspose': true, | 325 'projectionInverseTranspose': true, |
271 'worldViewInverseTranspose': true, | 326 'worldViewInverseTranspose': true, |
272 'worldProjectionInverseTranspose': true, | 327 'worldProjectionInverseTranspose': true, |
273 'worldViewProjectionInverseTranspose': true}; | 328 'worldViewProjectionInverseTranspose': true}; |
274 | 329 |
275 for (name in this.uniforms) { | 330 for (name in this.uniforms_) { |
276 var info = this.uniforms[name].info; | 331 var info = this.uniforms_[name].info; |
277 | 332 |
278 if (sasNames[name]) | 333 if (sasNames[name]) |
279 continue; | 334 continue; |
280 | 335 |
281 var paramType = ''; | 336 var paramType = ''; |
282 switch (info.type) { | 337 switch (info.type) { |
283 case this.gl.FLOAT: | 338 case this.gl.FLOAT: |
284 paramType = 'ParamFloat'; | 339 paramType = 'ParamFloat'; |
285 break; | 340 break; |
286 case this.gl.FLOAT_VEC2: | 341 case this.gl.FLOAT_VEC2: |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 return []; | 401 return []; |
347 }; | 402 }; |
348 | 403 |
349 | 404 |
350 /** | 405 /** |
351 * Gets info about the streams this effect needs. | 406 * Gets info about the streams this effect needs. |
352 * @return {!Array.<!o3d.EffectStreamInfo>} an array of | 407 * @return {!Array.<!o3d.EffectStreamInfo>} an array of |
353 * EffectStreamInfo objects. | 408 * EffectStreamInfo objects. |
354 */ | 409 */ |
355 o3d.Effect.prototype.getStreamInfo = function() { | 410 o3d.Effect.prototype.getStreamInfo = function() { |
356 var r = []; | 411 var infoList = []; |
357 // TODO(petersont): This is a stub, will remove later and replace with | |
358 // something that actually gets its streams from the shader. | |
359 var standard_semantic_index_pairs = [ | |
360 {semantic: o3d.Stream.POSITION, index: 0}, | |
361 {semantic: o3d.Stream.NORMAL, index: 0}, | |
362 {semantic: o3d.Stream.COLOR, index: 0}, | |
363 {semantic: o3d.Stream.TEXCOORD, index: 0} | |
364 ]; | |
365 | 412 |
366 for (var i = 0; i < standard_semantic_index_pairs.length; ++i) { | 413 for (var name in this.attributes_) { |
367 var p = standard_semantic_index_pairs[i]; | 414 var attributes = { |
368 r.push(new o3d.EffectStreamInfo(p.semantic, p.index)); | 415 'position': {semantic: o3d.Stream.POSITION, index: 0}, |
| 416 'normal': {semantic: o3d.Stream.NORMAL, index: 0}, |
| 417 'tangent': {semantic: o3d.Stream.TANGENT, index: 0}, |
| 418 'binormal': {semantic: o3d.Stream.BINORMAL, index: 0}, |
| 419 'color': {semantic: o3d.Stream.COLOR, index: 0}, |
| 420 'texCoord0': {semantic: o3d.Stream.TEXCOORD, index: 0}, |
| 421 'texCoord1': {semantic: o3d.Stream.TEXCOORD, index: 1}, |
| 422 'texCoord2': {semantic: o3d.Stream.TEXCOORD, index: 2}, |
| 423 'texCoord3': {semantic: o3d.Stream.TEXCOORD, index: 3}, |
| 424 'texCoord4': {semantic: o3d.Stream.TEXCOORD, index: 4}, |
| 425 'texCoord5': {semantic: o3d.Stream.TEXCOORD, index: 5}, |
| 426 'texCoord6': {semantic: o3d.Stream.TEXCOORD, index: 6}, |
| 427 'texCoord7': {semantic: o3d.Stream.TEXCOORD, index: 7}}; |
| 428 var semantic_index_pair = attributes[name]; |
| 429 infoList.push(new o3d.EffectStreamInfo( |
| 430 semantic_index_pair.semantic, semantic_index_pair.index)); |
369 } | 431 } |
370 return r; | 432 return infoList; |
371 }; | 433 }; |
372 | 434 |
373 | 435 |
374 /** | 436 /** |
375 * Searches the objects in the given list for parameters to apply to the | 437 * Searches the objects in the given list for parameters to apply to the |
376 * uniforms defined on this effects program, and applies them, favoring | 438 * uniforms defined on this effects program, and applies them, favoring |
377 * the objects nearer the begining of the list. | 439 * the objects nearer the begining of the list. |
378 * | 440 * |
379 * @param {!Array.<!o3d.ParamObject>} object_list The param objects to search. | 441 * @param {!Array.<!o3d.ParamObject>} object_list The param objects to search. |
| 442 * @private |
380 */ | 443 */ |
381 o3d.Effect.prototype.searchForParams = function(object_list) { | 444 o3d.Effect.prototype.searchForParams_ = function(object_list) { |
382 var filled_map = {}; | 445 var filled_map = {}; |
383 for (name in this.uniforms) { | 446 for (name in this.uniforms_) { |
384 filled_map[name] = false; | 447 filled_map[name] = false; |
385 } | 448 } |
386 this.gl.useProgram(this.program_); | 449 this.gl.useProgram(this.program_); |
| 450 o3d.Param.texture_index_ = 0; |
387 for (var i = 0; i < object_list.length; ++i) { | 451 for (var i = 0; i < object_list.length; ++i) { |
388 var obj = object_list[i]; | 452 var obj = object_list[i]; |
389 for (name in this.uniforms) { | 453 for (name in this.uniforms_) { |
390 var uniformInfo = this.uniforms[name]; | 454 var uniformInfo = this.uniforms_[name]; |
391 if (filled_map[name]) { | 455 if (filled_map[name]) { |
392 continue; | 456 continue; |
393 } | 457 } |
394 var param = obj.getParam(name); | 458 var param = obj.getParam(name); |
395 if (param) { | 459 if (param) { |
396 param.applyToLocation(this.gl, uniformInfo.location); | 460 param.applyToLocation(this.gl, uniformInfo.location); |
397 filled_map[name] = true; | 461 filled_map[name] = true; |
398 } | 462 } |
399 } | 463 } |
400 } | 464 } |
401 | 465 |
402 for (name in this.uniforms) { | 466 for (name in this.uniforms_) { |
403 if (!filled_map[name]) { | 467 if (!filled_map[name]) { |
404 throw ('Uniform param not filled: '+name); | 468 throw ('Uniform param not filled: '+name); |
405 } | 469 } |
406 } | 470 } |
407 }; | 471 }; |
408 | 472 |
409 | 473 |
410 /** | 474 /** |
411 * @type {number} | 475 * @type {number} |
412 */ | 476 */ |
(...skipping 16 matching lines...) Expand all Loading... |
429 o3d.Effect.prototype.matrix_load_order_ = o3d.Effect.ROW_MAJOR; | 493 o3d.Effect.prototype.matrix_load_order_ = o3d.Effect.ROW_MAJOR; |
430 | 494 |
431 | 495 |
432 /** | 496 /** |
433 * The source for the shaders on this Effect. | 497 * The source for the shaders on this Effect. |
434 * @type {string} | 498 * @type {string} |
435 */ | 499 */ |
436 o3d.Effect.prototype.source_ = ''; | 500 o3d.Effect.prototype.source_ = ''; |
437 | 501 |
438 | 502 |
OLD | NEW |