diff --git a/LandblockExtraction/LandBlockExtractor/LandBlockExtrator.cs b/LandblockExtraction/LandBlockExtractor/LandBlockExtrator.cs index cf65fac..a9f41a5 100644 --- a/LandblockExtraction/LandBlockExtractor/LandBlockExtrator.cs +++ b/LandblockExtraction/LandBlockExtractor/LandBlockExtrator.cs @@ -42,11 +42,12 @@ namespace LandblockExtraction.LandBlockExtractor { blockStruct.verticesStruct.color[indice] = GenerateVertexColor(blockData.cellInfos[indice]); blockStruct.verticesStruct.farcolor[indice] = GenerateVertexFarColor(blockData.cellInfos[indice]); blockStruct.verticesStruct.terraintype[indice] = GenerateVertexTerrainType(blockData.cellInfos[indice]); - blockStruct.verticesStruct.texturecoord[indice] = GenerateBasicUV(x, y); + blockStruct.verticesStruct.texturecoord[indice] = GenerateUVForSubTile(x, y); blockStruct.indices = GenerateBasicIndices(); } } + //blockStruct.verticesStruct.texturecoord = GenerateBasicUVTest(blockStruct); blockStruct.verticesStruct.normal = GenerateBasicNormal(blockStruct); //DoubleEdgeVertices(blockStruct); @@ -69,7 +70,37 @@ namespace LandblockExtraction.LandBlockExtractor { return new Vector2(u, v); } + private Vector2 GenerateUVForSubTile(int x, int y) { + // Taille d'une "mini-tuile" en termes de coordonnées UV + float miniTileSize = 1f / BlockSize - 1; // Comme la sous-grille est 5x5 + // Calcul des coordonnées UV basées sur la position (x, y) dans la sous-grille + float u = x * miniTileSize; + float v = y * miniTileSize; + + return new Vector2(u, v); + } + private Vector2[] GenerateBasicUVTest(BlockStruct blockStruct) { + Vector2[] uvs = new Vector2[blockStruct.verticesStruct.position.Length]; + + for (int i = 0; i < uvs.Length; i++) { + uvs[i] = new Vector2(0, 0); + } + + for (int i = 0; i < blockStruct.indices.Length; i += 6) { + int index1 = blockStruct.indices[i]; + int index2 = blockStruct.indices[i + 1]; + int index3 = blockStruct.indices[i + 2]; + int index4 = blockStruct.indices[i + 5]; + + uvs[index1] = new(0, 0); + uvs[index2] = new(0, 1); + uvs[index3] = new(1, 0); + uvs[index4] = new(1, 1); + } + + return uvs; + } private Vector3[] GenerateBasicNormal(BlockStruct blockStruct) { Vector3[] normals = new Vector3[blockStruct.verticesStruct.position.Length]; diff --git a/Map3DRendering/Common/Texture.cs b/Map3DRendering/Common/Texture.cs index 2032c28..96e397c 100644 --- a/Map3DRendering/Common/Texture.cs +++ b/Map3DRendering/Common/Texture.cs @@ -68,6 +68,42 @@ namespace Map3DRendering { return new Texture(handle); } + public static Texture LoadFromArray(string[] paths) { + // Générer un identifiant de texture + int handle = GL.GenTexture(); + + // Activer la texture + GL.ActiveTexture(TextureUnit.Texture0); + GL.BindTexture(TextureTarget.Texture2DArray, handle); + + // Ici, nous supposons que toutes les images ont les mêmes dimensions et le même format + // Charger la première image pour obtenir les dimensions + ImageResult firstImage = ImageResult.FromStream(File.OpenRead(paths[0]), ColorComponents.RedGreenBlueAlpha); + int width = firstImage.Width; + int height = firstImage.Height; + + // Initialiser la texture 2D array sans lui passer de données pour l'instant + GL.TexImage3D(TextureTarget.Texture2DArray, 0, PixelInternalFormat.Rgba, width, height, paths.Length, 0, PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero); + + // Charger chaque texture dans l'array + for (int i = 0; i < paths.Length; i++) { + using (Stream stream = File.OpenRead(paths[i])) { + ImageResult image = ImageResult.FromStream(stream, ColorComponents.RedGreenBlueAlpha); + GL.TexSubImage3D(TextureTarget.Texture2DArray, 0, 0, 0, i, width, height, 1, PixelFormat.Rgba, PixelType.UnsignedByte, image.Data); + } + } + + // Paramètres de texture + GL.TexParameter(TextureTarget.Texture2DArray, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); + GL.TexParameter(TextureTarget.Texture2DArray, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); + GL.TexParameter(TextureTarget.Texture2DArray, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge); + GL.TexParameter(TextureTarget.Texture2DArray, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge); + + // Générer des mipmaps pour la texture array + GL.GenerateMipmap(GenerateMipmapTarget.Texture2DArray); + + return new Texture(handle); + } public Texture(int glHandle) { Handle = glHandle; @@ -81,5 +117,9 @@ namespace Map3DRendering { GL.ActiveTexture(unit); GL.BindTexture(TextureTarget.Texture2D, Handle); } + public void UseArray(TextureUnit unit) { + GL.ActiveTexture(unit); + GL.BindTexture(TextureTarget.Texture2DArray, Handle); + } } } \ No newline at end of file diff --git a/Map3DRendering/Shaders/shader.frag b/Map3DRendering/Shaders/shader.frag index 8de05a0..a559a77 100644 --- a/Map3DRendering/Shaders/shader.frag +++ b/Map3DRendering/Shaders/shader.frag @@ -2,8 +2,7 @@ out vec4 outputColor; -uniform sampler2D texture0; -uniform sampler2D texture1; +uniform sampler2DArray texture0; uniform vec3 viewPos; uniform vec3 lightPos; @@ -19,14 +18,11 @@ in float RealType; void main() { - vec4 color0 = texture(texture0, TexCoord); - vec4 color1 = texture(texture1, TexCoord); + vec4 color0 = texture(texture0, vec3(TexCoord, TexType.x)); vec3 norm = normalize(Normal); - float inclineFactor = abs(norm.y); - - vec4 finalColor = mix(color0, color1, norm.y); + vec4 finalColor = color0; //mix(color0, color1, norm.y); vec3 lightDir = normalize(lightPos - FragPos); float diff = max(dot(norm, lightDir), 0.0); diff --git a/Map3DRendering/Window.cs b/Map3DRendering/Window.cs index 8040ec4..8958671 100644 --- a/Map3DRendering/Window.cs +++ b/Map3DRendering/Window.cs @@ -16,7 +16,6 @@ namespace Map3DRendering { private Shader _shader; private Texture _texture; - private Texture _texture2; private Camera _camera; @@ -55,20 +54,13 @@ namespace Map3DRendering { mapRender.OnLoad(_shader); - _texture = Texture.LoadFromFile("terrains/0.jpg"); + var file = Directory.EnumerateFiles(@"./terrains"); + + _texture = Texture.LoadFromArray(file.ToArray()); // Texture units are explained in Texture.cs, at the Use function. // First texture goes in texture unit 0. - _texture.Use(TextureUnit.Texture0); + _texture.UseArray(TextureUnit.Texture0); - // This is helpful because System.Drawing reads the pixels differently than OpenGL expects. - _texture2 = Texture.LoadFromFile("terrains/1.jpg"); - // Then, the second goes in texture unit 1. - _texture2.Use(TextureUnit.Texture1); - - // Next, we must setup the samplers in the shaders to use the right textures. - // The int we send to the uniform indicates which texture unit the sampler should use. - _shader.SetInt("texture0", 0); - _shader.SetInt("texture1", 1); axesGizmo = new AxesGizmo(); @@ -87,8 +79,7 @@ namespace Map3DRendering { GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); - _texture.Use(TextureUnit.Texture0); - _texture2.Use(TextureUnit.Texture1); + _texture.UseArray(TextureUnit.Texture0); _shader.Use(); _shader.SetMatrix4("view", _camera.GetViewMatrix());