/// <summary> /// Read all shader structures /// </summary> private static List <shader_p> ReadShaders(bsp_header_lump_t lump, BinaryStreamReader src) { int count = (int)lump.length / 72; List <shader_p> elements = new List <shader_p>(); shader_p shader; src.Seek(lump.offset); for (var i = 0; i < count; ++i) { shader = new shader_p(); shader.shaderName = src.ReadString(0, 64); shader.flags = src.ReadInt32(); // ReadInt64 shader.contents = src.ReadInt32(); shader.shader = null; shader.faces = new List <Face>(); shader.indexOffset = 0; shader.elementCount = 0; shader.visible = true; elements.Add(shader); } return(elements); }
public static void render_model_surfaces(Matrix4 leftViewMat, Matrix4 leftProjMat, Viewport leftViewport, float time) { int i; // Setup State shader_gl shader = modelSurfaces[0].shader; glshading.setShader(shader); stage_gl stage = shader.stages[0]; shader_prog_t shaderProgram = glshading.setShaderStage(shader, stage, time); BspOpenglBinders.BindShaderAttribs(shaderProgram); GL.ActiveTexture(TextureUnit.Texture0); BspOpenglBinders.BindShaderMatrix(shaderProgram, leftViewMat, leftProjMat); setViewport(leftViewport); for (i = 0; i < modelSurfaces.Count; ++i) { shader_p surface = modelSurfaces[i]; stage_gl stage2 = surface.shader.stages[0]; GL.BindTexture(TextureTarget.Texture2D, stage2.texture); GL.DrawElements(BeginMode.Triangles, surface.elementCount, DrawElementsType.UnsignedShort, surface.indexOffset); } }
public static void render_default_surfaces(Matrix4 leftViewMat, Matrix4 leftProjMat, Viewport leftViewport, float time) { int i; // Map Geometry buffers GL.BindBuffer(BufferTarget.ElementArrayBuffer, indexBuffer); GL.BindBuffer(BufferTarget.ArrayBuffer, vertexBuffer); // Default shader surfaces (can bind shader once and draw all of them very quickly) if (defaultSurfaces.Count > 0 || unshadedSurfaces.Count > 0) { // Setup State shader_gl shader = glshading.defaultShader; glshading.setShader(shader); stage_gl stage = shader.stages[0]; shader_prog_t shaderProgram = glshading.setShaderStage(shader, stage, time); BspOpenglBinders.BindShaderAttribs(shaderProgram); GL.ActiveTexture(TextureUnit.Texture0); GL.BindTexture(TextureTarget.Texture2D, glshading.defaultTexture); BspOpenglBinders.BindShaderMatrix(shaderProgram, leftViewMat, leftProjMat); setViewport(leftViewport); for (i = 0; i < unshadedSurfaces.Count; ++i) { shader_p surface = unshadedSurfaces[i]; GL.DrawElements(BeginMode.Triangles, surface.elementCount, DrawElementsType.UnsignedShort, surface.indexOffset); } for (i = 0; i < defaultSurfaces.Count; ++i) { shader_p surface = defaultSurfaces[i]; //stage_gl stage2 = surface.shader.stages[0]; foreach (stage_gl stage2 in surface.shader.stages) { GL.ActiveTexture(TextureUnit.Texture0); GL.BindTexture(TextureTarget.Texture2D, stage2.texture); GL.DrawElements(BeginMode.Triangles, surface.elementCount, DrawElementsType.UnsignedShort, surface.indexOffset); } } } }
/// <summary> /// Compile the map into a stream of OpenGL-compatible data /// </summary> public static void CompileMap(List <Vertex> verts, List <Face> faces, List <int> meshVerts, List <lightmap_rect_t> lightmaps, List <shader_p> shaders, int tesselationLevel) { Vertex vert; BspCompiler.faces = faces; q3bsp.onMessage(new MessageParams() { type = "status", message = "Map geometry parsed, compiling shaders..." }); // Find associated shaders for all clusters // Per-face operations for (int i = 0; i < faces.Count; ++i) { Face face = faces[i]; if (face.type == 1 || face.type == 2 || face.type == 3) { // Add face to the appropriate texture face list shader_p shader = shaders[(int)face.shader]; shader.faces.Add(face); lightmap_rect_t lightmap = face.lightmap > 0 ? lightmaps[(int)face.lightmap] : null; if (lightmap == null) { lightmap = lightmaps[0]; } if (face.type == 1 || face.type == 3) { shader.geomType = face.type; // Transform lightmap coords to match position in combined texture for (int j = 0; j < face.meshVertCount; ++j) { vert = verts[(int)face.vertex + (int)meshVerts[(int)face.meshVert + j]]; vert.lmNewCoord.X = (vert.lmCoord.X * lightmap.xScale) + lightmap.x; vert.lmNewCoord.Y = (vert.lmCoord.Y * lightmap.yScale) + lightmap.y; } } else { q3bsp.onMessage(new MessageParams() { type = "status", message = "Tesselating face " + i.ToString() + " of " + faces.Count.ToString() }); // Build Bezier curve BspTess.Tesselate(face, verts, meshVerts, tesselationLevel); for (int j = 0; j < face.vertCount; ++j) { vert = verts[(int)face.vertex + j]; vert.lmNewCoord.X = (vert.lmCoord.X * lightmap.xScale) + lightmap.x; vert.lmNewCoord.Y = (vert.lmCoord.Y * lightmap.yScale) + lightmap.y; } } } } // Compile vert list INTERLEAVE float[] vertices; vertices = Interleave(verts); // Compile index list List <ushort> lst_indices = new List <ushort>(); for (int i = 0; i < shaders.Count; ++i) { shader_p shader = shaders[i]; if (shader.faces.Count > 0) { shader.indexOffset = lst_indices.Count * 2; // Offset is in bytes for (int j = 0; j < shader.faces.Count; ++j) { Face face = shader.faces[j]; face.indexOffset = lst_indices.Count * 2; for (int k = 0; k < face.meshVertCount; ++k) { lst_indices.Add((ushort)(face.vertex + meshVerts[face.meshVert + k])); } shader.elementCount += (int)face.meshVertCount; } } shader.faces = null; // Don't need to send this to the render thread. } ushort[] indices = lst_indices.ToArray(); // Send the compiled vertex/index data back to the render thread q3bsp.onMessage(new MessageParams() { type = "geometry", vertices = vertices, indices = indices, surfaces = shaders }); }
public static void traceNode(long nodeIdx, float startFraction, float endFraction, Vector3 start, Vector3 end, float radius, TraceOutput output) { if (nodeIdx < 0) { // Leaf node? Leaf leaf = BspCompiler.leaves[(int)-(nodeIdx + 1)]; for (int i = 0; i < leaf.leafBrushCount; i++) { Brush brush = BspCompiler.brushes[(int)BspCompiler.leafBrushes[(int)(leaf.leafBrush) + i]]; shader_p shader = BspCompiler.shaders[(int)brush.shader]; if (brush.brushSideCount > 0 && (shader.contents == 0)) // (shader['contents'] & 1)) { traceBrush(brush, start, end, radius, ref output); } } return; } // Tree node bsp_tree_node node = BspCompiler.nodes[(int)nodeIdx]; Plane plane = BspCompiler.planes[(int)node.plane]; float startDist = Vector3.Dot(plane.normal, start) - plane.distance; float endDist = Vector3.Dot(plane.normal, end) - plane.distance; if (startDist >= radius && endDist >= radius) { traceNode(node.children[0], startFraction, endFraction, start, end, radius, output); } else if (startDist < -radius && endDist < -radius) { traceNode(node.children[1], startFraction, endFraction, start, end, radius, output); } else { int side; float fraction1, fraction2, middleFraction; Vector3 middle = Vector3.Zero; if (startDist < endDist) { side = 1; // back var iDist = 1 / (startDist - endDist); fraction1 = (startDist - radius + 0.03125f) * iDist; fraction2 = (startDist + radius + 0.03125f) * iDist; } else if (startDist > endDist) { side = 0; // front var iDist = 1 / (startDist - endDist); fraction1 = (startDist + radius + 0.03125f) * iDist; fraction2 = (startDist - radius - 0.03125f) * iDist; } else { side = 0; // front fraction1 = 1.0f; fraction2 = 0.0f; } if (fraction1 < 0) { fraction1 = 0.0f; } else if (fraction1 > 1) { fraction1 = 1.0f; } if (fraction2 < 0) { fraction2 = 0.0f; } else if (fraction2 > 1) { fraction2 = 1.0f; } middleFraction = startFraction + (endFraction - startFraction) * fraction1; middle.X = start.X + fraction1 * (end.X - start.X); middle.Y = start.Y + fraction1 * (end.Y - start.Y); middle.Z = start.Z + fraction1 * (end.Z - start.Z); //for (var i = 0; i < 3; i++) //{ // middle[i] = start[i] + fraction1 * (end[i] - start[i]); //} traceNode(node.children[side], startFraction, middleFraction, start, middle, radius, output); middleFraction = startFraction + (endFraction - startFraction) * fraction2; middle.X = start.X + fraction2 * (end.X - start.X); middle.Y = start.Y + fraction2 * (end.Y - start.Y); middle.Z = start.Z + fraction2 * (end.Z - start.Z); //for (var i = 0; i < 3; i++) //{ // middle[i] = start[i] + fraction2 * (end[i] - start[i]); //} traceNode(node.children[side == 0 ? 1 : 0], middleFraction, endFraction, middle, end, radius, output); } }
public TraceOutput traceNode(long nodeIdx, float startFraction, float endFraction, Vector3 start, Vector3 end, float radius, TraceOutput output, SceneCamera camera) { if (nodeIdx < 0) // Leaf node? { Leaf leaf = this.bsp.leaves[(int)(-(nodeIdx + 1))]; for (var i = 0; i < leaf.leafBrushCount; i++) { Brush brush = this.bsp.brushes[(int)(this.bsp.leafBrushes[(leaf.leafBrush + i)])]; shader_p surface = this.bsp.surfaces[(int)brush.shader]; if (brush.brushSideCount > 0 && surface.contents != 0) // surface['contents'] & 1 { output = this.traceBrush(brush, start, end, radius, output); } } return(output); } // Tree node bsp_tree_node node = this.bsp.nodes[(int)nodeIdx]; Plane plane = this.bsp.planes[(int)node.plane]; float startDist = Vector3.Dot(plane.normal, start) - plane.distance; float endDist = Vector3.Dot(plane.normal, end) - plane.distance; if (startDist >= radius && endDist >= radius) { output = this.traceNode(node.children[0], startFraction, endFraction, start, end, radius, output, camera); } else if (startDist < -radius && endDist < -radius) { output = this.traceNode(node.children[1], startFraction, endFraction, start, end, radius, output, camera); } else { int side; float fraction1; float fraction2; float middleFraction; Vector3 middle = Vector3.Zero; if (startDist < endDist) { side = 1; // back var iDist = 1 / (startDist - endDist); fraction1 = (startDist - radius + Config.q3bsptree_trace_offset) * iDist; fraction2 = (startDist + radius + Config.q3bsptree_trace_offset) * iDist; } else if (startDist > endDist) { side = 0; // front var iDist = 1 / (startDist - endDist); fraction1 = (startDist + radius + Config.q3bsptree_trace_offset) * iDist; fraction2 = (startDist - radius - Config.q3bsptree_trace_offset) * iDist; } else { side = 0; // front fraction1 = 1.0f; fraction2 = 0.0f; } if (fraction1 < 0) { fraction1 = 0.0f; } else if (fraction1 > 1) { fraction1 = 1.0f; } if (fraction2 < 0) { fraction2 = 0.0f; } else if (fraction2 > 1) { fraction2 = 1.0f; } middleFraction = startFraction + (endFraction - startFraction) * fraction1; middle.X = start.X + fraction1 * (end.X - start.X); middle.Y = start.Y + fraction1 * (end.Y - start.Y); middle.Z = start.Z + fraction1 * (end.Z - start.Z); //for (var i = 0; i < 3; i++) //{ // middle[i] = start[i] + fraction1 * (end[i] - start[i]); //} output = this.traceNode(node.children[side], startFraction, middleFraction, start, middle, radius, output, camera); middleFraction = startFraction + (endFraction - startFraction) * fraction2; middle.X = start.X + fraction2 * (end.X - start.X); middle.Y = start.Y + fraction2 * (end.Y - start.Y); middle.Z = start.Z + fraction2 * (end.Z - start.Z); //for (var i = 0; i < 3; i++) //{ // middle[i] = start[i] + fraction2 * (end[i] - start[i]); //} output = this.traceNode(node.children[side == 0 ? 1 : 0], middleFraction, endFraction, middle, end, radius, output, camera); } return(output); }
public static void render_effect_surfaces(Matrix4 leftViewMat, Matrix4 leftProjMat, Viewport leftViewport, float time) { int i; int j; // Effect surfaces for (i = 0; i < effectSurfaces.Count; ++i) { shader_p surface = effectSurfaces[i]; if (surface.elementCount == 0 || surface.visible != true) { continue; } // Bind the surface shader shader_gl shader = surface.shader; if (highlighted != null && highlighted == surface.shaderName) { shader = glshading.defaultShader; } //shader = glshading.defaultShader; // test to show that effect shaders are buggy. Later remove this line to use the effect shader properly. if (shader.name == "textures/atcs/force_field_s") { //var tex = shader.stages[0].texture; //shader = glshading.defaultShader; //shader.stages[0].texture = tex; var tmp = shader; shader = glshading.defaultShader; shader.stages[0].texture = tmp.stages[0].texture; } if (!glshading.setShader(shader)) { continue; } for (j = 0; j < shader.stages.Count; ++j) { stage_gl stage = shader.stages[j]; shader_prog_t shaderProgram; //if (stage.shaderName == "textures/atcs/force_field_s") //{ // //shaderProgram = glshading.setShaderStage_EffectDEBUG(shader, stage, time); // shaderProgram = glshading.defaultProgram; // GL.UseProgram(shaderProgram.program); //} //else //{ // shaderProgram = glshading.setShaderStage(shader, stage, time); //} //shaderProgram = glshading.defaultProgram; //GL.UseProgram(shaderProgram.program); shaderProgram = glshading.setShaderStage(shader, stage, time); if (shaderProgram == null) { continue; } BspOpenglBinders.BindShaderAttribs(shaderProgram); BspOpenglBinders.BindShaderMatrix(shaderProgram, leftViewMat, leftProjMat); setViewport(leftViewport); // Draw all geometry that uses this textures GL.DrawElements(BeginMode.Triangles, surface.elementCount, DrawElementsType.UnsignedShort, surface.indexOffset); } } }