public void textureInit(byte[] imageData, string _name) { DDSImage ddsImage; name = _name; ddsImage = new DDSImage(imageData); RenderStats.texturesNum += 1; //Accumulate settings Console.WriteLine("Sampler Name Path " + name + " Width {0} Height {1}", ddsImage.header.dwWidth, ddsImage.header.dwHeight); width = ddsImage.header.dwWidth; height = ddsImage.header.dwHeight; int blocksize = 16; switch (ddsImage.header.ddspf.dwFourCC) { //DXT1 case (0x31545844): pif = InternalFormat.CompressedSrgbAlphaS3tcDxt1Ext; blocksize = 8; break; case (0x35545844): pif = InternalFormat.CompressedSrgbAlphaS3tcDxt5Ext; break; case (0x32495441): //ATI2A2XY pif = InternalFormat.CompressedRgRgtc2; //Normal maps are probably never srgb break; //DXT10 HEADER case (0x30315844): { switch (ddsImage.header10.dxgiFormat) { case (DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM): pif = InternalFormat.CompressedSrgbAlphaBptcUnorm; break; default: throw new ApplicationException("Unimplemented DX10 Texture Pixel format"); } break; } default: throw new ApplicationException("Unimplemented Pixel format"); } //Temp Variables int w = width; int h = height; int mm_count = ddsImage.header.dwMipMapCount; int depth_count = Math.Max(1, ddsImage.header.dwDepth); //Fix the counter to 1 to fit the texture in a 3D container int temp_size = ddsImage.header.dwPitchOrLinearSize; //Generate PBO pboID = GL.GenBuffer(); GL.BindBuffer(BufferTarget.PixelUnpackBuffer, pboID); GL.BufferData(BufferTarget.PixelUnpackBuffer, ddsImage.bdata.Length, ddsImage.bdata, BufferUsageHint.StaticDraw); //GL.BufferSubData(BufferTarget.PixelUnpackBuffer, IntPtr.Zero, ddsImage.bdata.Length, ddsImage.bdata); //Upload to GPU texID = GL.GenTexture(); target = TextureTarget.Texture2DArray; GL.BindTexture(target, texID); //When manually loading mipmaps, levels should be loaded first GL.TexParameter(target, TextureParameterName.TextureBaseLevel, 0); //GL.TexParameter(target, TextureParameterName.TextureMaxLevel, mm_count - 1); int offset = 0; for (int i = 0; i < mm_count; i++) { GL.CompressedTexImage3D(target, i, pif, w, h, depth_count, 0, temp_size * depth_count, IntPtr.Zero + offset); offset += temp_size * depth_count; w = Math.Max(w >> 1, 1); h = Math.Max(h >> 1, 1); temp_size = Math.Max(1, (w + 3) / 4) * Math.Max(1, (h + 3) / 4) * blocksize; //This works only for square textures //temp_size = Math.Max(temp_size/4, blocksize); } //GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureLodBias, -0.2f); GL.TexParameter(target, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat); GL.TexParameter(target, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat); GL.TexParameter(target, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); GL.TexParameter(target, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear); //Console.WriteLine(GL.GetError()); //Use anisotropic filtering float af_amount = GL.GetFloat((GetPName)All.MaxTextureMaxAnisotropy); af_amount = (float)Math.Max(af_amount, 4.0f); //GL.TexParameter(TextureTarget.Texture2D, (TextureParameterName) 0x84FE, af_amount); int max_level = 0; GL.GetTexParameter(target, GetTextureParameter.TextureMaxLevel, out max_level); int base_level = 0; GL.GetTexParameter(target, GetTextureParameter.TextureBaseLevel, out base_level); int maxsize = Math.Max(height, width); int p = (int)Math.Floor(Math.Log(maxsize, 2)) + base_level; int q = Math.Min(p, max_level); #if (DEBUGNONO) //Get all mipmaps temp_size = ddsImage.header.dwPitchOrLinearSize; for (int i = 0; i < q; i++) { //Get lowest calculated mipmap byte[] pixels = new byte[temp_size]; //Save to disk GL.GetCompressedTexImage(TextureTarget.Texture2D, i, pixels); File.WriteAllBytes("Temp\\level" + i.ToString(), pixels); temp_size = Math.Max(temp_size / 4, 16); } #endif #if (DUMP_TEXTURESNONO) Sampler.dump_texture(name.Split('\\').Last().Split('/').Last(), width, height); #endif //avgColor = getAvgColor(pixels); ddsImage = null; GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0); //Unbind texture PBO }
public void init() { //Get MaterialFlags foreach (TkMaterialFlags f in Flags) { material_flags[(int)f.MaterialFlag] = 1.0f; } //Get Uniforms foreach (TkMaterialUniform un in Uniforms) { Uniform my_un = new Uniform("mpCustomPerMaterial.", un); CustomPerMaterialUniforms[my_un.Name] = my_un; } //Get Samplers foreach (TkMaterialSampler sm in Samplers) { Sampler s = new Sampler(sm); s.init(texMgr); PSamplers[s.PName] = s; } //Workaround for Procedurally Generated Samplers //I need to check if the diffuse sampler is procgen and then force the maps //on the other samplers with the appropriate names foreach (Sampler s in PSamplers.Values) { //Check if the first sampler is procgen if (s.isProcGen) { string name = s.Map; //Properly assemble the mask and the normal map names string[] split = name.Split('.'); string pre_ext_name = ""; for (int i = 0; i < split.Length - 1; i++) { pre_ext_name += split[i] + '.'; } if (PSamplers.ContainsKey("mpCustomPerMaterial.gMasksMap")) { string new_name = pre_ext_name + "MASKS.DDS"; PSamplers["mpCustomPerMaterial.gMasksMap"].PMap = new_name; PSamplers["mpCustomPerMaterial.gMasksMap"].tex = PSamplers["mpCustomPerMaterial.gMasksMap"].texMgr.getTexture(new_name); } if (PSamplers.ContainsKey("mpCustomPerMaterial.gNormalMap")) { string new_name = pre_ext_name + "NORMAL.DDS"; PSamplers["mpCustomPerMaterial.gNormalMap"].PMap = new_name; PSamplers["mpCustomPerMaterial.gNormalMap"].tex = PSamplers["mpCustomPerMaterial.gNormalMap"].texMgr.getTexture(new_name); } break; } } //Calculate material hash List <string> includes = new List <string>(); for (int i = 0; i < MaterialFlags.Count; i++) { if (supported_flags.Contains(MaterialFlags[i])) { includes.Add(MaterialFlags[i]); } } shaderHash = GLShaderHelper.calculateShaderHash(includes); if (!Common.RenderState.activeResMgr.shaderExistsForMaterial(this)) { try { compileMaterialShader(); } catch (Exception e) { Common.CallBacks.Log("Error during material shader compilation: " + e.Message); } } }