Beispiel #1
0
        /// <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);
        }
Beispiel #2
0
        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);
            }
        }
Beispiel #3
0
        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);
                    }
                }
            }
        }
Beispiel #4
0
        /// <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);
            }
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        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);
                }
            }
        }