protected virtual void RenderBlock(Block block, float x, float y, float scale) { var model = JsonModelLoader.GetModelForBlock(block.UnlocalizedName); if (model == null) { return; } ModelBlockRaw mbr = (ModelBlockRaw)model.RawModel; List <float> uvs = new List <float>(8); mbr.AppendUvsForSide(FaceSides.South, uvs); Vector2 UVmin = new Vector2(uvs[0], uvs[1]); Vector2 UVmax = new Vector2(uvs[4], uvs[5]); Vector2 unit = new Vector2(1f / SharpCraft.Instance.ClientSize.Width, 1f / SharpCraft.Instance.ClientSize.Height); float width = 16; float height = 16; float scaledWidth = 16 * scale; float scaledHeight = 16 * scale; float posX = x + scaledWidth / 2; float posY = -y - scaledHeight / 2; Vector2 pos = new Vector2(posX, posY).Ceiling() * unit; Matrix4 mat = MatrixHelper.CreateTransformationMatrix(pos * 2 - Vector2.UnitX + Vector2.UnitY, scale * new Vector2(width, height) * unit); _item.Bind(); Shader.Bind(); Shader.UpdateGlobalUniforms(); Shader.UpdateModelUniforms(); Shader.UpdateInstanceUniforms(mat, UVmin, UVmax); GL.BindTexture(TextureTarget.Texture2D, JsonModelLoader.TEXTURE_BLOCKS); _item.RawModel.Render(PrimitiveType.Quads); _item.Unbind(); }
public void BuildChunkModelNow() { if (ModelBuilding || !QueuedForModelBuild) { return; } ModelBuilding = true; //ConcurrentDictionary<Shader<ModelBlock>, List<RawQuad>> modelRaw = new ConcurrentDictionary<Shader<ModelBlock>, List<RawQuad>>(); //List<RawQuad> quads; Stopwatch sw = Stopwatch.StartNew(); //this is just a debug thing.... var air = BlockRegistry.GetBlock <BlockAir>(); var vertexes = new List <float>(); var normals = new List <float>(); var uvs = new List <float>(); object locker = new object(); //generate the model - fill MODEL_RAW Enumerable.Range(0, ChunkHeight).AsParallel().ForAll(y => { for (int x = 0; x < ChunkSize; x++) { for (int z = 0; z < ChunkSize; z++) { BlockPos worldPos = new BlockPos(x + Pos.WorldSpaceX(), y, z + Pos.WorldSpaceZ()); BlockState state = World.GetBlockState(worldPos); if (state.Block == air) { continue; } BlockPos localPos = new BlockPos(x, y, z); ModelBlockRaw mbr = (ModelBlockRaw)state.Model?.RawModel; if (mbr == null) { continue; } if (!state.Block.IsFullCube) { lock (locker) mbr.AppendAllVertexData(vertexes, normals, uvs, localPos); continue; } for (var index = 0; index < FaceSides.AllSides.Count; index++) { FaceSides dir = FaceSides.AllSides[index]; BlockPos worldPosO = worldPos.Offset(dir); BlockState stateO = World.GetBlockState(worldPosO); if (!(stateO.Block == air || stateO.Block.HasTransparency && !state.Block.HasTransparency) && stateO.Block.IsFullCube) { continue; } lock (locker) { mbr.AppendVertexDataForSide(dir, vertexes, normals, uvs, localPos); //mbr.AppendNormalsForSide(dir, normals); //mbr.AppendUvsForSide(dir, uvs); } } } } }); sw.Stop(); Console.WriteLine($"DEBUG: built chunk model [{sw.Elapsed.TotalMilliseconds:F}ms]"); float[] vtx = vertexes.ToArray(); //this is here because this takes time and I don't want it to slow down the main thread by running it in GlContext float[] nrm = normals.ToArray(); float[] uv = uvs.ToArray(); SharpCraft.Instance.RunGlContext(() => { if (_model == null) { _model = new ModelChunk(vtx, nrm, uv, Block.DefaultShader); } else { _model.OverrideData(vtx, nrm, uv); } ModelBuilding = false; }); QueuedForModelBuild = false; }