From 5873f1264373c035c7469e51575af22319912f1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20L=C3=BCbe=C3=9F?= Date: Wed, 24 Mar 2021 14:44:02 +0100 Subject: [PATCH] Added textures for Blocks --- Sandbox/content/Textures/Dirt.png | Bin 0 -> 533 bytes Sandbox/content/Textures/GrassSide.png | Bin 0 -> 565 bytes Sandbox/content/Textures/GrassTop.png | Bin 0 -> 482 bytes Sandbox/content/Textures/Stone.png | Bin 0 -> 332 bytes Sandbox/src/VoxelFun/BlockModel.bf | 95 ++++++++++---- Sandbox/src/VoxelFun/BlockTexture.bf | 28 +++++ Sandbox/src/VoxelFun/BlockTextures.bf | 163 +++++++++++++++++++++++++ Sandbox/src/VoxelFun/ChunkManager.bf | 3 +- Sandbox/src/VoxelFun/Models.bf | 6 +- Sandbox/src/VoxelFun/VoxelTestLayer.bf | 5 +- 10 files changed, 269 insertions(+), 31 deletions(-) create mode 100644 Sandbox/content/Textures/Dirt.png create mode 100644 Sandbox/content/Textures/GrassSide.png create mode 100644 Sandbox/content/Textures/GrassTop.png create mode 100644 Sandbox/content/Textures/Stone.png create mode 100644 Sandbox/src/VoxelFun/BlockTexture.bf create mode 100644 Sandbox/src/VoxelFun/BlockTextures.bf diff --git a/Sandbox/content/Textures/Dirt.png b/Sandbox/content/Textures/Dirt.png new file mode 100644 index 0000000000000000000000000000000000000000..db0c9ae1da194eb4955c5d261ba2e4714085fe58 GIT binary patch literal 533 zcmV+w0_y#VP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!2kdb!2!6DYwZ940jfzvK~y+TC6a4y z+%OP>si(cWX$$m6f#eDY8erHAHI zqiK2dbN?%y3Q@O3$5ZKN(L9w`g{09nlN42wLeQLw(J!GZC3UGC98Lv^r;_rbT$L87 zO2xzzC?_C>&ck2gx~SevA9lr|KzCCq0s<>{NLewdWUp9Z8tU&l(Q}%n@xHmtHC^Y> z1XC4@V2?B%o6U`Qt*JqGi1F5R?ivKp)q$Zf;40$7efi@6KJV|E)xM|%WZVTnc@!SL zsXP>#wedr-O*T!qZb~nX=yMGUdevB+ARCJFLkY!jH}jELoX(2+wtJ;tH}9DUim_;~ zh@l?Eghs3wIBcwMCW_>Byn8c2EV(rOvZrae7!kZSr5 XSp3b-Z9-|P00000NkvXXu0mjf?o#R& literal 0 HcmV?d00001 diff --git a/Sandbox/content/Textures/GrassSide.png b/Sandbox/content/Textures/GrassSide.png new file mode 100644 index 0000000000000000000000000000000000000000..c2c31c47073fd3a02a960369f585940a08f8230f GIT binary patch literal 565 zcmV-50?Pe~P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGizW@LZzX3P}QzQTY0m?~4K~y+TEs{-c zR51{Q%l7-3%nU?A3Sz^KLvRc>5eiFIoPbphg2V+P1w|YUiDYKpd;Z}oi;?B$9#^-k zsylqR*Z5lbSuIP0LXe8;)(=T-)p(;ct30bL3Q;j#tGuY5rC?CKs1=3LAqV#I*ZHkq zfsEpFQJ8f1+X=%_Y6?xa4;l{o{G_;ZPB|$gX;k?BPU)b>JAHXj+w}Miyl#JbugRG# zZK_SbzUtEth5Pp^aE%(O+2`uJp(&1PJ8J+>ZSPGfE26cWRW_B_S5rYW*CbGQF`1H; zfmJJs5#e0p3FxefP~yGX)LEej_24>yr=n&}*BTEBn2n9C7osCA`uR7(FBBJ#JzD}B6jyq?ThSpiv)As@yxBwJ`+EiBV3c*Ugk#X(t} zkg%d##Q!8vn0IKfuRvGC5OmRru8mfCxu{m35i`IRhFvbW%c&=zO*2Oq<0$nJ)Vd6Lad~b8Mw(wSI?}1=C<1lDCdSIEEaj*H6c5j@Y7m9h` zkcWDlM&y|~T^7)3@^oM#B}9W4X=fVrW;?m%Ahqcq8rI-pI^I^Z00000NkvXXu0mjf DBr^75 literal 0 HcmV?d00001 diff --git a/Sandbox/content/Textures/GrassTop.png b/Sandbox/content/Textures/GrassTop.png new file mode 100644 index 0000000000000000000000000000000000000000..53509c7cb896ca063395fa734821256797b22660 GIT binary patch literal 482 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6T`Z5GB1G~mUKs7M+SzC z{oH>NS%Lg%0X`wFD%A|ir3@Nf4B8VJG+G%{>loA;7*uK)G`kp7su)!27*y*SRBITN z%NbNE7?gpij6t=QL9>TJy^TS=n?bFfL8X#Gy_rG1l|i|RLA9Deqn$ww$ZcUz2Qr!% zR2vvHIv7+N8I&s-G&&hHfV!F()H@h7I~mj(8MG%cr~pmtV9=hxpw-8q+0CHZ#Gq2o zV9nO-0CXW|fk$L90|Vb-5N14{zaj-Fc-7OzF+?Mn_iSSLAq5e(2iGT^o?y5~sF~%6 zWxBHV>;M0E{`oiOGsEoZ*ViiCkEPMD#PyU7k{~wrFRq&DlA7UQ9hGb$!t-^&5WE zi^9cX-Qza!KbW~sBdlV%x7WwppDs*mV!6Dx8U^OlQhNY{15i2lZ4w#cIoT^ PdXT}>)z4*}Q$iB}*vF-O literal 0 HcmV?d00001 diff --git a/Sandbox/content/Textures/Stone.png b/Sandbox/content/Textures/Stone.png new file mode 100644 index 0000000000000000000000000000000000000000..999fd97aee4a9bd7848d6432567f9dfac4e132d7 GIT binary patch literal 332 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6T`Z5GB1G~mUKs7M+SzC z{oH>NS%G}Z0G|-o`uh5cii+~`^0KnB%F4>>>gw9s+N!Fmnwpxry1IsjhNh;b_V)I+ zwzig*mgeT>j*gDT#>Udp(p2l*Dxe{p1s;*b3=DjSK$uZf!>a)(ILFh)F+?L+w4Ymu zMS;UFSL8WXi|IFCf8yD=HhGQVpRGHX9`h$< Wvg}Qt#(om$P6kg`KbLh*2~7a!cY$yK literal 0 HcmV?d00001 diff --git a/Sandbox/src/VoxelFun/BlockModel.bf b/Sandbox/src/VoxelFun/BlockModel.bf index 4920205..6714da5 100644 --- a/Sandbox/src/VoxelFun/BlockModel.bf +++ b/Sandbox/src/VoxelFun/BlockModel.bf @@ -27,69 +27,116 @@ namespace Sandbox.VoxelFun { Color _color; + BlockTexture _textureTop; + BlockTexture _textureSide; + BlockTexture _textureBottom; + + public this(Color color) { _color = color; + + bottomCoords = sideCoords = topCoords = (.Zero, .UnitX, .UnitY, .One); + } + + public this(Color color, BlockTexture texture) : this(color, texture, texture, texture) + { + } + + public this(Color color, BlockTexture topTexture, BlockTexture sideTexture, BlockTexture bottomTexture) + { + _color = color; + _textureTop = topTexture; + _textureSide = sideTexture; + _textureBottom = bottomTexture; + + CalculateTexCoords(); + } + + typealias TexCoords = (Vector2 Zero, Vector2 UnitX, Vector2 UnitY, Vector2 One); + + TexCoords topCoords; + TexCoords sideCoords; + TexCoords bottomCoords; + + private void CalculateTexCoords() + { + topCoords = GetQuadCoords(_textureTop); + sideCoords = GetQuadCoords(_textureSide); + bottomCoords = GetQuadCoords(_textureBottom); + } + + private TexCoords GetQuadCoords(BlockTexture texture) + { + TexCoords coords; + + coords.UnitX = texture.TransformTexCoords(.UnitX); + coords.UnitY = texture.TransformTexCoords(.UnitY); + coords.Zero = texture.TransformTexCoords(.Zero); + coords.One = texture.TransformTexCoords(.One); + + return coords; } public override void GenerateGeometry(Block block, Vector3 blockPosition, BlockFace visibleFaces, List vertices, List indices, ref uint32 lastIndex) { + if(visibleFaces.HasFlag(.Back)) { - vertices.Add(VertexColorTexture(blockPosition + .(0, 0, 0), _color, .UnitY)); - vertices.Add(VertexColorTexture(blockPosition + .(1, 0, 0), _color, .One)); - vertices.Add(VertexColorTexture(blockPosition + .(1, 1, 0), _color, .UnitX)); - vertices.Add(VertexColorTexture(blockPosition + .(0, 1, 0), _color, .Zero)); + vertices.Add(VertexColorTexture(blockPosition + .(0, 0, 0), _color, sideCoords.UnitY)); + vertices.Add(VertexColorTexture(blockPosition + .(1, 0, 0), _color, sideCoords.One)); + vertices.Add(VertexColorTexture(blockPosition + .(1, 1, 0), _color, sideCoords.UnitX)); + vertices.Add(VertexColorTexture(blockPosition + .(0, 1, 0), _color, sideCoords.Zero)); AddQuadIndices(ref lastIndex, indices); } if(visibleFaces.HasFlag(.Top)) { - vertices.Add(VertexColorTexture(blockPosition + .(0, 1, 0), _color, .UnitY)); - vertices.Add(VertexColorTexture(blockPosition + .(1, 1, 0), _color, .One)); - vertices.Add(VertexColorTexture(blockPosition + .(1, 1, 1), _color, .UnitX)); - vertices.Add(VertexColorTexture(blockPosition + .(0, 1, 1), _color, .Zero)); + vertices.Add(VertexColorTexture(blockPosition + .(0, 1, 0), _color, topCoords.UnitY)); + vertices.Add(VertexColorTexture(blockPosition + .(1, 1, 0), _color, topCoords.One)); + vertices.Add(VertexColorTexture(blockPosition + .(1, 1, 1), _color, topCoords.UnitX)); + vertices.Add(VertexColorTexture(blockPosition + .(0, 1, 1), _color, topCoords.Zero)); AddQuadIndices(ref lastIndex, indices); } if(visibleFaces.HasFlag(.Bottom)) { - vertices.Add(VertexColorTexture(blockPosition + .(0, 0, 1), _color, .UnitY)); - vertices.Add(VertexColorTexture(blockPosition + .(1, 0, 1), _color, .One)); - vertices.Add(VertexColorTexture(blockPosition + .(1, 0, 0), _color, .UnitX)); - vertices.Add(VertexColorTexture(blockPosition + .(0, 0, 0), _color, .Zero)); + vertices.Add(VertexColorTexture(blockPosition + .(0, 0, 1), _color, bottomCoords.UnitY)); + vertices.Add(VertexColorTexture(blockPosition + .(1, 0, 1), _color, bottomCoords.One)); + vertices.Add(VertexColorTexture(blockPosition + .(1, 0, 0), _color, bottomCoords.UnitX)); + vertices.Add(VertexColorTexture(blockPosition + .(0, 0, 0), _color, bottomCoords.Zero)); AddQuadIndices(ref lastIndex, indices); } if(visibleFaces.HasFlag(.Front)) { - vertices.Add(VertexColorTexture(blockPosition + .(1, 0, 1), _color, .UnitY)); - vertices.Add(VertexColorTexture(blockPosition + .(0, 0, 1), _color, .One)); - vertices.Add(VertexColorTexture(blockPosition + .(0, 1, 1), _color, .UnitX)); - vertices.Add(VertexColorTexture(blockPosition + .(1, 1, 1), _color, .Zero)); + vertices.Add(VertexColorTexture(blockPosition + .(1, 0, 1), _color, sideCoords.UnitY)); + vertices.Add(VertexColorTexture(blockPosition + .(0, 0, 1), _color, sideCoords.One)); + vertices.Add(VertexColorTexture(blockPosition + .(0, 1, 1), _color, sideCoords.UnitX)); + vertices.Add(VertexColorTexture(blockPosition + .(1, 1, 1), _color, sideCoords.Zero)); AddQuadIndices(ref lastIndex, indices); } if(visibleFaces.HasFlag(.Right)) { - vertices.Add(VertexColorTexture(blockPosition + .(1, 0, 0), _color, .UnitY)); - vertices.Add(VertexColorTexture(blockPosition + .(1, 0, 1), _color, .One)); - vertices.Add(VertexColorTexture(blockPosition + .(1, 1, 1), _color, .UnitX)); - vertices.Add(VertexColorTexture(blockPosition + .(1, 1, 0), _color, .Zero)); + vertices.Add(VertexColorTexture(blockPosition + .(1, 0, 0), _color, sideCoords.UnitY)); + vertices.Add(VertexColorTexture(blockPosition + .(1, 0, 1), _color, sideCoords.One)); + vertices.Add(VertexColorTexture(blockPosition + .(1, 1, 1), _color, sideCoords.UnitX)); + vertices.Add(VertexColorTexture(blockPosition + .(1, 1, 0), _color, sideCoords.Zero)); AddQuadIndices(ref lastIndex, indices); } if(visibleFaces.HasFlag(.Left)) { - vertices.Add(VertexColorTexture(blockPosition + .(0, 0, 1), _color, .UnitY)); - vertices.Add(VertexColorTexture(blockPosition + .(0, 0, 0), _color, .One)); - vertices.Add(VertexColorTexture(blockPosition + .(0, 1, 0), _color, .UnitX)); - vertices.Add(VertexColorTexture(blockPosition + .(0, 1, 1), _color, .Zero)); + vertices.Add(VertexColorTexture(blockPosition + .(0, 0, 1), _color, sideCoords.UnitY)); + vertices.Add(VertexColorTexture(blockPosition + .(0, 0, 0), _color, sideCoords.One)); + vertices.Add(VertexColorTexture(blockPosition + .(0, 1, 0), _color, sideCoords.UnitX)); + vertices.Add(VertexColorTexture(blockPosition + .(0, 1, 1), _color, sideCoords.Zero)); AddQuadIndices(ref lastIndex, indices); } diff --git a/Sandbox/src/VoxelFun/BlockTexture.bf b/Sandbox/src/VoxelFun/BlockTexture.bf new file mode 100644 index 0000000..d47b347 --- /dev/null +++ b/Sandbox/src/VoxelFun/BlockTexture.bf @@ -0,0 +1,28 @@ +using System; +using GlitchyEngine.Math; + +namespace Sandbox.VoxelFun +{ + class BlockTexture + { + private String _fileName; + + public String FileName => _fileName; + + private Vector2 _atlasStart; + private Vector2 _atlasSize; + + [AllowAppend] + public this(String fileName) + { + String str = append String(fileName); + + _fileName = str; + } + + public Vector2 TransformTexCoords(Vector2 texCoords) + { + return _atlasStart + texCoords * _atlasSize; + } + } +} diff --git a/Sandbox/src/VoxelFun/BlockTextures.bf b/Sandbox/src/VoxelFun/BlockTextures.bf new file mode 100644 index 0000000..8310edd --- /dev/null +++ b/Sandbox/src/VoxelFun/BlockTextures.bf @@ -0,0 +1,163 @@ +using System.Collections; +using GlitchyEngine.Renderer; +using System.Collections; +using GlitchyEngine.Renderer; +using GlitchyEngine.Math; +using GlitchyEngine; +using DirectX.D3D11; +using System; +namespace Sandbox.VoxelFun +{ + class BlockTextures + { + static List _textures = new List() ~ DeleteContainerAndItems!(_); + + static TextureAtlas _atlas ~ _?.ReleaseRef(); + + public static BlockTexture Stone; + public static BlockTexture Dirt; + public static BlockTexture GrassTop; + public static BlockTexture GrassSide; + + public static TextureAtlas Atlas => _atlas; + + public static void Init(GraphicsContext context) + { + Stone = RegisterTexture(.. new BlockTexture("Content\\Textures\\Stone.png")); + Dirt = RegisterTexture(.. new BlockTexture("Content\\Textures\\Dirt.png")); + GrassTop = RegisterTexture(.. new BlockTexture("Content\\Textures\\GrassTop.png")); + GrassSide = RegisterTexture(.. new BlockTexture("Content\\Textures\\GrassSide.png")); + + GenerateAtlas(context); + } + + private static void RegisterTexture(BlockTexture texture) + { + _textures.Add(texture); + } + + static void GenerateAtlas(GraphicsContext context) + { + _atlas = new TextureAtlas(context, _textures); + + GlitchyEngine.Renderer.SamplerStateDescription desc = .(); + desc.MagFilter = .Point; + desc.MinFilter = .Point; + desc.MipFilter = .Point; + desc.MipMaxLOD = 0; + desc.MipMinLOD = 0; + desc.MaxAnisotropy = 0; + + _atlas.SamplerState = new SamplerState(context, desc)..ReleaseRefNoDelete(); + } + } + + class TextureAtlas : Texture + { + // TODO: native code + private ID3D11Texture2D* nativeTexture ~ _?.Release(); + + public override extern uint32 Width {get;} + public override extern uint32 Height {get;} + public override uint32 Depth => 1; + public override extern uint32 ArraySize {get;} + public override extern uint32 MipLevels {get;} + + public this(GraphicsContext context, List textures) : base(context) + { + // Todo: rewrite this garbage algorithm + + List<(Color* data, uint32 width, uint32 height, BlockTexture blockTex)> textureDatas = new .(textures.Count); + defer + { + for(let item in textureDatas) + { + LodePng.LodePng.Free(item.data); + } + + delete textureDatas; + } + + uint32 maxWidth = 0; + uint32 maxHeight = 0; + + for(let texture in textures) + { + (Color* data, uint32 width, uint32 height, BlockTexture blockTex) tex; + tex.blockTex = texture; + + let error = LodePng.LodePng.Decode32File(out tex.data, out tex.width, out tex.height, texture.FileName); + + if(error != 0) + Log.ClientLogger.Error($"Failed to load texture \"{texture.FileName}\". ({error}) \"{StringView(LodePng.LodePng.ErrorText(error))}\""); + + if(tex.width > maxWidth) + maxWidth = tex.width; + + if(tex.height > maxHeight) + maxHeight = tex.height; + + textureDatas.Add(tex); + } + + uint32 texturesX = (.)System.Math.Ceiling(System.Math.Sqrt(textureDatas.Count)); + uint32 texturesY = (.)System.Math.Ceiling((float)textureDatas.Count / (float)texturesX); + + uint32 textureWidth = texturesX * maxWidth; + uint32 textureHeight = texturesY * maxHeight; + + Color[] atlasColors = new DirectX.Color[textureWidth * textureHeight]; + defer delete atlasColors; + + uint32 currentX = 0; + uint32 currentY = 0; + + for(let texture in textureDatas) + { + texture.blockTex.[Friend]_atlasStart = .((float)currentX / (float)textureWidth, (float)currentY / (float)textureHeight); + texture.blockTex.[Friend]_atlasSize = .((float)texture.width / (float)textureWidth, (float)texture.height / (float)textureHeight); + + for(uint32 penY = currentY, uint32 y = 0; y < texture.height; penY++, y++) + for(uint32 penX = currentX, uint32 x = 0; x < texture.width; penX++, x++) + { + atlasColors[penX + penY * textureWidth] = texture.data[x + y * texture.width]; + } + + currentX += maxWidth; + if(currentX >= textureWidth) + { + currentX = 0; + currentY += maxHeight; + } + } + + Texture2DDescription desc; + desc.Width = textureWidth; + desc.Height = textureHeight; + desc.ArraySize = 1; + desc.MipLevels = 1; + desc.SampleDesc = .(1, 0); + desc.Usage = .Immutable; + desc.MiscFlags = .None; + desc.BindFlags = .ShaderResource; + desc.CpuAccessFlags = .None; + desc.Format = .R8G8B8A8_UNorm; + + //SubresourceData data = .(atlasColors.CArray(), textureWidth, textureWidth * textureHeight); + SubresourceData data = .(atlasColors.CArray(), textureWidth * sizeof(Color), 0); + + // TODO: this is bad platform dependant code... + var result = _context.[Friend]nativeDevice.CreateTexture2D(ref desc, &data, &nativeTexture); + + //LodePng.LodePng.Encode32File("testout.png", textureD) + + if(result.Failed) + Log.ClientLogger.Error($"Failed to create atlas texture. Error ({result.Underlying}): {result}"); + + result = _context.[Friend]nativeDevice.CreateShaderResourceView(nativeTexture, null, &nativeView); + + if(result.Failed) + Log.ClientLogger.Error($"Failed to create atlas texture. Error ({result.Underlying}): {result}"); + } + } +} diff --git a/Sandbox/src/VoxelFun/ChunkManager.bf b/Sandbox/src/VoxelFun/ChunkManager.bf index f606e2b..a32ac18 100644 --- a/Sandbox/src/VoxelFun/ChunkManager.bf +++ b/Sandbox/src/VoxelFun/ChunkManager.bf @@ -84,7 +84,6 @@ namespace Sandbox.VoxelFun private HashSet _generatingChunks = new .() ~ delete _; private Monitor _generatingChunksLock = new .() ~ delete _; - public Texture2D Texture ~ _?.ReleaseRef(); public Effect TextureEffect ~ _?.ReleaseRef(); VoxelGeometryGenerator voxelGeoGen = new VoxelGeometryGenerator() ~ delete _; @@ -618,7 +617,7 @@ namespace Sandbox.VoxelFun chunkGeo.AddRef(); - Texture.Bind(); + BlockTextures.Atlas.Bind(); Renderer.Submit(chunk.Geometry, TextureEffect, chunk.Transform); chunkGeo.ReleaseRef(); diff --git a/Sandbox/src/VoxelFun/Models.bf b/Sandbox/src/VoxelFun/Models.bf index b9a36f8..dd5febf 100644 --- a/Sandbox/src/VoxelFun/Models.bf +++ b/Sandbox/src/VoxelFun/Models.bf @@ -13,9 +13,9 @@ namespace Sandbox.VoxelFun public static void Init() { - Stone = RegisterModel(Blocks.Stone, .. new BlockModel(.Gray)); - Grass = RegisterModel(Blocks.Grass, .. new BlockModel(.Green)); - Dirt = RegisterModel(Blocks.Dirt, .. new BlockModel(.Brown)); + Stone = RegisterModel(Blocks.Stone, .. new BlockModel(.White, BlockTextures.Stone)); + Grass = RegisterModel(Blocks.Grass, .. new BlockModel(.White, BlockTextures.GrassTop, BlockTextures.GrassSide, BlockTextures.Dirt)); + Dirt = RegisterModel(Blocks.Dirt, .. new BlockModel(.White, BlockTextures.Dirt)); } public static void RegisterModel(Block block, Model model) diff --git a/Sandbox/src/VoxelFun/VoxelTestLayer.bf b/Sandbox/src/VoxelFun/VoxelTestLayer.bf index fedff46..e230d6e 100644 --- a/Sandbox/src/VoxelFun/VoxelTestLayer.bf +++ b/Sandbox/src/VoxelFun/VoxelTestLayer.bf @@ -88,9 +88,11 @@ namespace Sandbox.VoxelFun public this() : base("VoxelTest") { Blocks.Init(); - Models.Init(); _context = Application.Get().Window.Context..AddRef(); + + BlockTextures.Init(_context); + Models.Init(); _effectLibrary = new EffectLibrary(_context); @@ -255,7 +257,6 @@ namespace Sandbox.VoxelFun } _world.ChunkManager = new ChunkManager(_context, _vertexLayout, _world); - _world.ChunkManager.Texture = _texture..AddRef(); _world.ChunkManager.TextureEffect = _textureEffect..AddRef(); }