public static vertex_shader_src_t buildVertexShader(shader_t stageShader, stage_t stage) { ShaderBuilder shader; Dictionary <string, string> attribs, varyings, uniforms; List <string> statements; shader = new ShaderBuilder(); attribs = new Dictionary <string, string>(); varyings = new Dictionary <string, string>(); uniforms = new Dictionary <string, string>(); statements = new List <string>(); shader.addAttribs("position", "vec3"); shader.addAttribs("normal", "vec3"); shader.addAttribs("color", "vec4"); shader.addVaryings("vTexCoord", "vec2"); shader.addVaryings("vColor", "vec4"); shader.addUniforms("modelViewMat", "mat4"); shader.addUniforms("projectionMat", "mat4"); shader.addUniforms("time", "float"); if (stage.isLightmap == true) { shader.addAttribs("lightCoord", "vec2"); } else { shader.addAttribs("texCoord", "vec2"); } shader.addLines("vec3 defPosition = position;"); //shader.addAttribs(attribs); //shader.addVaryings(varyings); //shader.addUniforms(uniforms); //shader.addLines(statements); for (int i = 0; i < stageShader.vertexDeforms.Count; ++i) { deform_t deform = stageShader.vertexDeforms[i]; switch (deform.type) { case "wave": String name = "deform" + i.ToString(); String offName = "deformOff" + i.ToString(); shader.addLine("float " + offName + " = (position.x + position.y + position.z) * " + ShaderBuilder.toStringAsFixed(deform.spread, 4) + ";"); var phase = deform.waveform.phase; deform.waveform.phase = ShaderBuilder.toStringAsFixed((double)phase, 4) + " + " + offName; shader.addWaveform(name, deform.waveform, null); deform.waveform.phase = phase; shader.addLine("defPosition += normal * " + name + ";"); break; default: break; } } shader.addLine("vec4 worldPosition = modelViewMat * vec4(defPosition, 1.0);"); shader.addLine("vColor = color;"); if (stage.tcGen == "environment") { shader.addLines( "vec3 viewer = normalize(-worldPosition.xyz);", "float d = dot(normal, viewer);", "vec3 reflected = normal*2.0*d - viewer;", "vTexCoord = vec2(0.5, 0.5) + reflected.xy * 0.5;" ); } else { // Standard texturing if (stage.isLightmap == true) { shader.addLines("vTexCoord = lightCoord;"); } else { shader.addLines("vTexCoord = texCoord;"); } } // tcMods for (int i = 0; i < stage.tcMods.Count; ++i) { tcMod_t tcMod = stage.tcMods[i]; switch (tcMod.type) { case "rotate": shader.addLines( string.Format("float r = {0} * time;", ShaderBuilder.toStringAsFixed(tcMod.angle, 4)), "vTexCoord -= vec2(0.5, 0.5);", "vTexCoord = vec2(vTexCoord.s * cos(r) - vTexCoord.t * sin(r), vTexCoord.t * cos(r) + vTexCoord.s * sin(r));", "vTexCoord += vec2(0.5, 0.5);" ); break; case "scroll": double sSpeed = tcMod.sSpeed; // was tcMod['sSpeed'].toFixed(4) double tSpeed = tcMod.tSpeed; shader.addLines(string.Format("vTexCoord += vec2({0} * time, {1} * time); ", ShaderBuilder.toStringAsFixed(sSpeed, 4), ShaderBuilder.toStringAsFixed(tSpeed, 4))); break; case "scale": double scaleX = tcMod.scaleX; double scaleY = tcMod.scaleY; shader.addLines("vTexCoord *= vec2(" + ShaderBuilder.toStringAsFixed(scaleX, 4) + ", " + ShaderBuilder.toStringAsFixed(scaleY, 4) + ");"); break; case "stretch": shader.addWaveform("stretchWave", tcMod.waveform, null); shader.addLines( "stretchWave = 1.0 / stretchWave;", "vTexCoord *= stretchWave;", "vTexCoord += vec2(0.5 - (0.5 * stretchWave), 0.5 - (0.5 * stretchWave));" ); break; case "turb": String tName = "turbTime" + i.ToString(); shader.addLines( "float " + tName + " = " + ShaderBuilder.toStringAsFixed(tcMod.turbulance.phase, 4) + " + time * " + ShaderBuilder.toStringAsFixed(tcMod.turbulance.freq, 4) + ";", "vTexCoord.s += sin( ( ( position.x + position.z )* 1.0/128.0 * 0.125 + " + tName + " ) * 6.283) * " + ShaderBuilder.toStringAsFixed(tcMod.turbulance.amp, 4) + ';', "vTexCoord.t += sin( ( position.y * 1.0/128.0 * 0.125 + " + tName + " ) * 6.283) * " + ShaderBuilder.toStringAsFixed(tcMod.turbulance.amp, 4) + ";" ); break; default: break; } } switch (stage.alphaGen) { case "lightingspecular": shader.addAttribs("lightCoord", "vec2"); shader.addVaryings("vLightCoord", "vec2"); shader.addLines("vLightCoord = lightCoord;"); break; default: break; } shader.addLines("gl_Position = projectionMat * worldPosition;"); vertex_shader_src_t vertex_shader = new vertex_shader_src_t(); vertex_shader.source_code = shader.getSource(); return(vertex_shader); }
public static stage_t parseStage(ShaderTokenizer tokens) { stage_t stage = new stage_t(); String map; // Parse a shader while (!tokens.EOF()) { String token = tokens.next(); if (token == "}") { break; } switch (token.ToLower()) { case "clampmap": stage.clamp = true; break; case "map": map = tokens.next(); if (!Config.preserve_tga_images) { //Regex r; //r = new Regex("(\\.jpg|\\.tga)"); map = map.Replace(".tga", ".jpg"); //map = r.Replace(map, ".jpg"); //map = map.replaceAll(new RegExp(r'(\.jpg|\.tga)'), '.jpg'); } stage.map = map; //stage.map = tokens.next().replaceAll(/(\.jpg|\.tga)/, '.jpg'); break; case "animmap": stage.map = "anim"; stage.animFreq = double.Parse(tokens.next()); String nextMap = tokens.next(); while (nextMap.Contains(".tga") || nextMap.Contains(".jpg")) //while(nextMap.match(/(\.jpg|\.tga)/)) { map = nextMap; if (!Config.preserve_tga_images) { map = map.Replace(".tga", ".jpg"); //map = nextMap.replaceAll(new RegExp(r'(\.jpg|\.tga)'), '.jpg'); } // stage.animMaps.Add(map); //stage.animMaps.push(nextMap.replace(/(\.jpg|\.tga)/, '.jpg')); nextMap = tokens.next(); } tokens.prev(); break; case "rgbgen": stage.rgbGen = tokens.next().ToLower();; switch (stage.rgbGen) { case "wave": stage.rgbWaveform = ShaderParser.parseWaveform(tokens); if (stage.rgbWaveform == null) { stage.rgbGen = "identity"; } break; } ; break; case "alphagen": stage.alphaGen = tokens.next().ToLower(); switch (stage.alphaGen) { case "wave": stage.alphaWaveform = ShaderParser.parseWaveform(tokens); if (stage.alphaWaveform == null) { stage.alphaGen = "1.0"; } break; default: break; } ; break; case "alphafunc": stage.alphaFunc = tokens.next().ToUpper(); break; case "blendfunc": stage.blendSrc = tokens.next(); stage.hasBlendFunc = true; if (stage.depthWriteOverride == false) { stage.depthWrite = false; } switch (stage.blendSrc) { case "add": stage.blendSrc = "GL_ONE"; stage.blendDest = "GL_ONE"; break; case "blend": stage.blendSrc = "GL_SRC_ALPHA"; stage.blendDest = "GL_ONE_MINUS_SRC_ALPHA"; break; case "filter": stage.blendSrc = "GL_DST_COLOR"; stage.blendDest = "GL_ZERO"; break; default: stage.blendDest = tokens.next(); break; } break; case "depthfunc": stage.depthFunc = tokens.next().ToLower(); break; case "depthwrite": stage.depthWrite = true; stage.depthWriteOverride = true; break; case "tcmod": tcMod_t tcMod = new tcMod_t(); tcMod.type = tokens.next().ToLower(); switch (tcMod.type) { case "rotate": tcMod.angle = double.Parse(tokens.next()) * (Math.PI / 180); break; case "scale": tcMod.scaleX = double.Parse(tokens.next()); tcMod.scaleY = double.Parse(tokens.next()); break; case "scroll": tcMod.sSpeed = double.Parse(tokens.next()); tcMod.tSpeed = double.Parse(tokens.next()); break; case "stretch": tcMod.waveform = ShaderParser.parseWaveform(tokens); if (tcMod.waveform == null) { tcMod.type = null; } break; case "turb": tcMod.turbulance = new turbulance_t(); tcMod.turbulance.@base = double.Parse(tokens.next()); tcMod.turbulance.amp = double.Parse(tokens.next()); tcMod.turbulance.phase = double.Parse(tokens.next()); tcMod.turbulance.freq = double.Parse(tokens.next()); break; default: tcMod.type = null; break; } if (tcMod.type != null) { stage.tcMods.Add(tcMod); } break; case "tcgen": stage.tcGen = tokens.next(); break; default: break; } } if (stage.blendSrc == "GL_ONE" && stage.blendDest == "GL_ZERO") { stage.hasBlendFunc = false; stage.depthWrite = true; } stage.isLightmap = stage.map == "\\$lightmap"; return(stage); }