public static shader_t parseShader(String name, ShaderTokenizer tokens) { string param; String brace = tokens.next(); if (brace != "{") { return(null); } shader_t shader = new shader_t(); shader.name = name; // Parse a shader while (!tokens.EOF()) { String token = tokens.next().ToLower(); if (token == "}") { break; } switch (token) { case "{": { stage_t stage = ShaderParser.parseStage(tokens); // I really really really don't like doing this, which basically just forces lightmaps to use the 'filter' blendmode // but if I don't a lot of textures end up looking too bright. I'm sure I'm jsut missing something, and this shouldn't // be needed. if (stage.isLightmap == true && (stage.hasBlendFunc == true)) { stage.blendSrc = "GL_DST_COLOR"; stage.blendDest = "GL_ZERO"; } // I'm having a ton of trouble getting lightingSpecular to work properly, // so this little hack gets it looking right till I can figure out the problem if (stage.alphaGen == "lightingspecular") { stage.blendSrc = "GL_ONE"; stage.blendDest = "GL_ZERO"; stage.hasBlendFunc = false; stage.depthWrite = true; shader.stages = new List <stage_t>(); } if (stage.hasBlendFunc == true) { shader.blend = true; } else { shader.opaque = true; } shader.stages.Add(stage); } break; case "cull": shader.cull = tokens.next(); break; case "deformvertexes": deform_t deform = new deform_t(); deform.type = tokens.next().ToLower(); switch (deform.type) { case "wave": deform.spread = 1.0 / double.Parse(tokens.next()); deform.waveform = ShaderParser.parseWaveform(tokens); break; default: deform = null; break; } if (deform != null) { shader.vertexDeforms.Add(deform); } break; case "sort": String sort = tokens.next().ToLower(); switch (sort) { case "portal": shader.sort = 1; break; case "sky": shader.sort = 2; break; case "opaque": shader.sort = 3; break; case "banner": shader.sort = 6; break; case "underwater": shader.sort = 8; break; case "additive": shader.sort = 9; break; case "nearest": shader.sort = 16; break; default: shader.sort = int.Parse(sort); break; } ; break; case "surfaceparm": param = tokens.next().ToLower(); switch (param) { case "sky": shader.sky = true; break; default: break; } break; case "skyparms": param = tokens.next().ToLower(); shader.sky_env_map = new sky_env_map_p(param);; break; default: break; } } if (shader.sort < 0 || shader.sort == 0) { shader.sort = (shader.opaque ? 3 : 9); } //if(!shader['sort']) { //shader['sort'] = (shader['opaque'] ? 3 : 9); //} return(shader); }
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); }