コード例 #1
0
        public static void AddFaceToVao(WorldServer world, Vector3i blockPos, int x, int y, int z, Block block, BlockFace face, BlockModel.FaceData data, VertexArrayObject vao, Matrix4 transform)
        {
            var faceId        = (int)face - 1;
            var indicesOffset = vao.VertexCount;

            //var transform = Matrix4.CreateScale()//Matrix4.Identity;//block.GetTransform(world, blockPos, face);
            var texture = data.LoadedTexture;    //block.GetTexture(world, blockPos, face);
            //var overlayTexture = block.GetOverlayTexture(world, blockPos, face);
            var texCoords = data.GetTexCoords(); //block.GetTexCoords(world, blockPos, face) ?? FaceTexCoords;
            //var overlayTexCoords = block.GetOverlayTexCoords(world, blockPos, face) ?? FaceTexCoords;
            var color  = data.TintIndex == -1 ? new Vector4(1) : block.GetTintColor(world, blockPos, data.TintIndex).ToVector4();
            var normal = face.GetNormal();

            if (texCoords.Length != 4)
            {
                throw new Exception($"\"{block}\" invalid texture coords array length!");
            }


            var vPositions        = new Vector3[4];
            var vTexCoords        = new Vector4[4];
            var vOverlayTexCoords = new Vector4[4]; //TODO: Remove
            var vBrightness       = new Vector3[4];

            for (var j = 0; j < 4; j++)
            {
                var vertexPosition = FacePositions[faceId * 4 + j];
                var position       = (new Vector4(vertexPosition, 1) * transform).Xyz + new Vector3(x, y, z);

                //tex coords are -1 if texture is null
                var texCoord = texture == null ? new Vector4(-1) : new Vector4(texCoords[j])
                {
                    //texCoord z = texId, w = textureArrayId
                    Z = texture.TextureId,
                    W = texture.ArrayId
                };



                //per vertex light value interpolation (smooth lighting + free ambient occlusion)
                var brightness = CalculateBrightness(world, block, blockPos, face, vertexPosition);

                //TODO: transform normals

                vPositions[j]        = position;
                vTexCoords[j]        = texCoord;
                vOverlayTexCoords[j] = new Vector4(-1);
                vBrightness[j]       = brightness;
            }

            //Flip faces to fix ambient occlusion anisotrophy
            //https://0fps.net/2013/07/03/ambient-occlusion-for-minecraft-like-worlds/

            for (var j = 0; j < 4; j++)
            {
                vao.Add(vPositions[j], vTexCoords[j], new Vector4(normal), color.Xyz, vBrightness[j]);
            }

            var newIndices = new uint[FaceIndices.Length];

            if ((vBrightness[0] + vBrightness[3]).LengthSquared > (vBrightness[1] + vBrightness[2]).LengthSquared)
            {
                for (var j = 0; j < newIndices.Length; j++)
                {
                    newIndices[j] = (uint)(FlippedFaceIndices[j] + indicesOffset);
                }
            }
            else
            {
                for (var j = 0; j < newIndices.Length; j++)
                {
                    newIndices[j] = (uint)(FaceIndices[j] + indicesOffset);
                }
            }

            //Calculate face middle for transparency sorting
            var faceMiddle = Vector3.Zero;

            if (vao is SortedVertexArrayObject)
            {
                faceMiddle = vPositions.Aggregate(faceMiddle, (current, pos) => current + pos);
                faceMiddle = faceMiddle / vPositions.Length + blockPos.ToVector3() - new Vector3(x, y, z);
            }

            vao.AddFace(newIndices, faceMiddle);
        }