Skip to content

Commit

Permalink
Apply @extension specification
Browse files Browse the repository at this point in the history
  • Loading branch information
kyasbal committed Dec 24, 2017
1 parent 45d975c commit dc550a3
Show file tree
Hide file tree
Showing 9 changed files with 46 additions and 19 deletions.
2 changes: 0 additions & 2 deletions src/Components/MaterialComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ export default class MaterialComponent extends MaterialContainerBase {

public ready: boolean;

public materialArgs: { [key: string]: any } = {};

protected $mount(): void {
const typeName = this.getAttribute("type");
if (typeName && typeof typeName === "string") {
Expand Down
3 changes: 0 additions & 3 deletions src/Components/MaterialContainerComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,6 @@ export default class MaterialContainer extends MaterialContainerBase {

public material: Material;

public materialArgs: { [key: string]: any; } = {};

public materialReady = false;

public useMaterial = false;
Expand Down Expand Up @@ -123,7 +121,6 @@ export default class MaterialContainer extends MaterialContainerBase {
private async _prepareExternalMaterial(materialPromise: Promise<Material>): Promise<void> {
const material = await materialPromise; // waiting for material load completion
this.material = material;
this.materialArgs = this._materialComponent.materialArgs;
this.materialReady = true;
}

Expand Down
3 changes: 2 additions & 1 deletion src/Material/Pass.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import IPassRecipe from "./Schema/IPassRecipe";
import Technique from "./Technique";
import UniformResolverContainer from "./UniformResolverContainer";
import UniformResolverRegistry from "./UniformResolverRegistry";
import GLExtRequestor from "../Resource/GLExtRequestor";
/**
* Pass provides single draw call for a geometry.
* Containing arguments of uniform variables and gl state configruations for each drawing call.
Expand Down Expand Up @@ -60,7 +61,7 @@ export default class Pass {
const factory = MaterialFactory.get(this._gl);
const macroRegister = factory.macro;
this._dynamicStateResolver = GLStateConfigurator.getDynamicStateResolver(this);
this.program = new PassProgram(this._gl, passRecipe.vertex, passRecipe.fragment);
this.program = new PassProgram(this._gl, passRecipe.vertex, passRecipe.fragment, passRecipe.extensions);
// register macro
for (const key in passRecipe.macros) {
const macro = passRecipe.macros[key];
Expand Down
29 changes: 18 additions & 11 deletions src/Material/PassProgram.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Geometry from "../Geometry/Geometry";
import ManagedProgram from "../Resource/ManagedProgram";
import ManagedShader from "../Resource/ManagedShader";
import ShaderMixer from "./ShaderMixer";
import GLExtRequestor from "../Resource/GLExtRequestor";
/**
* Container of shader program used for Pass.
* Pass needs to care which geometry will be drawn by a material.
Expand All @@ -13,11 +14,11 @@ export default class PassProgram {
* macros registered dynamically of this programs
* @return {[type]} [description]
*/
public get macros(): {[key: string]: any} {
public get macros(): { [key: string]: any } {
return this._macros;
}

public set macros(val: {[key: string]: any}) {
public set macros(val: { [key: string]: any }) {
this._macros = val;
this.dispose();
}
Expand All @@ -37,22 +38,28 @@ export default class PassProgram {
* @param {string} source [description]
* @return {[type]} [description]
*/
public set fragmentShader(source: string){
public set fragmentShader(source: string) {
this._fsSource = source;
this.dispose();
}

public set vertexShader(source: string){
public set vertexShader(source: string) {
this._vsSource = source;
this.dispose();
}

private _programs: {[hash: number]: ManagedProgram} = {};
public supportedExtensions: string[];

private _programs: { [hash: number]: ManagedProgram } = {};

private _shaders: ManagedShader[] = [];

constructor(private _gl: WebGLRenderingContext, private _vsSource: string, private _fsSource: string, private _macros: {[key: string]: any} = {}) {

constructor(private _gl: WebGLRenderingContext, private _vsSource: string, private _fsSource: string, public extensions: string[], private _macros: { [key: string]: any } = {}) {
this.supportedExtensions = this.extensions.filter((ext) => {
GLExtRequestor.request(ext);
return GLExtRequestor.supported(ext);
})
}
/**
* Fetch a program instance with specified geometry
Expand All @@ -62,7 +69,7 @@ export default class PassProgram {
public getProgram(geometry: Geometry): ManagedProgram {
if (this._programs[geometry.accessorHash]) {
return this._programs[geometry.accessorHash];
}else {
} else {
return this._constructProgram(geometry);
}
}
Expand All @@ -72,11 +79,11 @@ export default class PassProgram {
* @param {string} macroName [description]
* @param {string|boolean} value [description]
*/
public setMacro(macroName: string, value?: string|boolean): void {
public setMacro(macroName: string, value?: string | boolean): void {
if (this._macros[macroName] !== value) {
if (typeof value === "boolean") {
this._macros[macroName] = value ? "" : undefined;
}else {
} else {
this._macros[macroName] = value;
}
this.dispose();
Expand All @@ -96,8 +103,8 @@ export default class PassProgram {
}

private _constructProgram(geometry: Geometry): ManagedProgram {
const fs = ManagedShader.getShader(this._gl, WebGLRenderingContext.FRAGMENT_SHADER, ShaderMixer.generate(WebGLRenderingContext.FRAGMENT_SHADER, this._macros, this._fsSource, geometry));
const vs = ManagedShader.getShader(this._gl, WebGLRenderingContext.VERTEX_SHADER, ShaderMixer.generate(WebGLRenderingContext.VERTEX_SHADER, this._macros, this._vsSource, geometry));
const fs = ManagedShader.getShader(this._gl, WebGLRenderingContext.FRAGMENT_SHADER, ShaderMixer.generate(WebGLRenderingContext.FRAGMENT_SHADER, this._macros, this._fsSource, geometry, this.extensions, this.supportedExtensions));
const vs = ManagedShader.getShader(this._gl, WebGLRenderingContext.VERTEX_SHADER, ShaderMixer.generate(WebGLRenderingContext.VERTEX_SHADER, this._macros, this._vsSource, geometry, this.extensions, this.supportedExtensions));
const program = ManagedProgram.getProgram(this._gl, [vs, fs]);
this._shaders.push(fs);
this._shaders.push(vs);
Expand Down
1 change: 1 addition & 0 deletions src/Material/Schema/IPassRecipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import IMacro from "./IMacro";
import IState from "./IState";
import IVariableInfo from "./IVariableInfo";
interface IPassRecipe {
extensions: string[];
fragment: string;
vertex: string;
uniforms: {
Expand Down
12 changes: 10 additions & 2 deletions src/Material/ShaderMixer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ export default class ShaderMixer {
* @param {string} code shader body(Raw glsl)
* @return {string} generated shader code
*/
public static generate(type: number, macros: { [key: string]: string }, code: string, geometry: Geometry): string {
public static generate(type: number, macros: { [key: string]: string }, code: string, geometry: Geometry, extensions: string[], supportedExtensions: string[]): string {
let shaderTypeMacro;
if (type === WebGLRenderingContext.VERTEX_SHADER) {
shaderTypeMacro = "#define VS\n";
} else {
shaderTypeMacro = "#define FS\n";
}
return `${shaderTypeMacro}${this._precisionCode(geometry.gl)}${ShaderMixer._geometryToAttributeUsedFlags(geometry)}${ShaderMixer._macroCode(macros)}${header}\n/*****BEGINNING OF USER CODE******/\n${code}`;
return `${this._getExtensionCode(extensions, supportedExtensions)}${shaderTypeMacro}${this._precisionCode(geometry.gl)}${ShaderMixer._geometryToAttributeUsedFlags(geometry)}${ShaderMixer._macroCode(macros)}${header}\n/*****BEGINNING OF USER CODE******/\n${code}`;
}

private static _macroCode(macros: { [key: string]: string }): string {
Expand All @@ -31,6 +31,14 @@ export default class ShaderMixer {
return macroCode;
}

private static _getExtensionCode(extensions: string[], supportedExtensions: string[]): string {
let result = "";
extensions.forEach(e => result += `#extension GL_${e} : enable\n`);
supportedExtensions.forEach(e => result += `#define ${e}_ENABLED\n`);
return result;
}


private static _geometryToAttributeUsedFlags(geometry: Geometry): string {
let macroCode = "";
for (const attribName in geometry.accessors) {
Expand Down
2 changes: 2 additions & 0 deletions src/Sort/Parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,13 @@ class SortParser {

private static _parsePassSource(passSource: string): IPassRecipe {
const shaderSource = SortTransformUtility.removePreferences(passSource);
const extensions = SortTransformUtility.parseExtensions(passSource);
const attributes = SortTransformUtility.parseVariables(passSource, "attribute");
const uniforms = SortTransformUtility.parseVariables(passSource, "uniform");
const macros = SortTransformUtility.parseMacros(passSource);
const states = SortTransformUtility.parsePreferences(passSource);
return {
extensions,
fragment: shaderSource,
vertex: shaderSource,
attributes,
Expand Down
3 changes: 3 additions & 0 deletions src/Sort/Preferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ export default {
ReferMacro() {
return;
},
Extension() {
return;
},
DynamicState(state: IState, args: string[]) {
if (!args.length) {
throw new Error("DynamicState require at least 1 argument for specifying state resolver");
Expand Down
10 changes: 10 additions & 0 deletions src/Sort/SortTransformUtility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,16 @@ export default class SortTransformUtility {
return result;
}

public static parseExtensions(source: string): string[] {
const regex = /@Extension\(([\sa-zA-Z_0-9]*)\)/g;
let regexResult;
const result = [];
while ((regexResult = regex.exec(source))) {
result.push(regexResult[1].trim());
}
return result;
}

public static asValidJSON(json: string): string {
const regex = /([\{,]\s*)([a-zA-Z0-9_]+)(\s*\:)/gm;
const result = json.replace(regex, '$1"$2"$3');
Expand Down

0 comments on commit dc550a3

Please sign in to comment.