private RenderTarget CreateRenderTarget(Vector2i size, RenderTargetColorFormat colorFormat, TextureSampleParameters?sampleParameters = null, string name = null) { // Generate color attachment texture. var texture = new OGLHandle(GL.GenTexture()); GL.BindTexture(TextureTarget.Texture2D, texture.Handle); _applySampleParameters(sampleParameters); var internalFormat = colorFormat switch { RenderTargetColorFormat.Rgba8 => PixelInternalFormat.Rgba8, RenderTargetColorFormat.Rgba16F => PixelInternalFormat.Rgba16f, RenderTargetColorFormat.Rgba8Srgb => PixelInternalFormat.Srgb8Alpha8, RenderTargetColorFormat.R11FG11FB10F => PixelInternalFormat.R11fG11fB10f, _ => throw new ArgumentOutOfRangeException(nameof(colorFormat), colorFormat, null) }; var(width, height) = size; GL.TexImage2D(TextureTarget.Texture2D, 0, internalFormat, width, height, 0, PixelFormat.Red, PixelType.Byte, IntPtr.Zero); // Generate FBO. var fbo = new OGLHandle(GL.GenFramebuffer()); // Cache currently bound framebuffers // so if somebody creates a framebuffer while drawing it won't ruin everything. var boundDrawBuffer = GL.GetInteger(GetPName.DrawFramebufferBinding); var boundReadBuffer = GL.GetInteger(GetPName.ReadFramebufferBinding); // Bind color attachment to FBO. GL.BindFramebuffer(FramebufferTarget.Framebuffer, fbo.Handle); GL.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, texture.Handle, 0); // This should always pass but OpenGL makes it easy to check for once so let's. var status = GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer); DebugTools.Assert(status == FramebufferErrorCode.FramebufferComplete, $"new framebuffer has bad status {status}"); // Re-bind previous framebuffers. GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, boundDrawBuffer); GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, boundReadBuffer); var textureObject = _genTexture(texture, size, name); var handle = AllocRid(); var renderTarget = new RenderTarget(size, textureObject, fbo, this, handle); _renderTargets.Add(handle, renderTarget); return(renderTarget); }
public Texture LoadTextureFromImage <T>(Image <T> image, string name = null) where T : struct, IPixel <T> { DebugTools.Assert(_mainThread == Thread.CurrentThread); if (typeof(T) != typeof(Rgba32)) { throw new NotImplementedException("Cannot load images other than Rgba32"); } var texture = new OGLHandle(GL.GenTexture()); GL.BindTexture(TextureTarget.Texture2D, texture.Handle); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); var span = ((Image <Rgba32>)(object) image).GetPixelSpan(); unsafe { fixed(Rgba32 *ptr = &MemoryMarshal.GetReference(span)) { GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8, image.Width, image.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, (IntPtr)ptr); } } if (name != null) { _objectLabelMaybe(ObjectLabelIdentifier.Texture, texture, name); } var loaded = new LoadedTexture { OpenGLObject = texture, Width = image.Width, Height = image.Height, Name = name, }; var id = ++_nextTextureId; _loadedTextures.Add(id, loaded); return(new OpenGLTexture(id, image.Width, image.Height)); }
private ClydeTexture _genTexture(OGLHandle oglHandle, Vector2i size, string name) { if (name != null) { _objectLabelMaybe(ObjectLabelIdentifier.Texture, oglHandle, name); } var(width, height) = size; var loaded = new LoadedTexture { OpenGLObject = oglHandle, Width = width, Height = height, Name = name }; var id = ++_nextTextureId; _loadedTextures.Add(id, loaded); return(new ClydeTexture(id, size, this)); }
private void _objectLabelMaybe(ObjectLabelIdentifier identifier, OGLHandle name, string label) { _objectLabelMaybe(identifier, name.Handle, label); }
private void _initOpenGL() { _loadExtensions(); GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); var vendor = GL.GetString(StringName.Vendor); var renderer = GL.GetString(StringName.Renderer); var version = GL.GetString(StringName.Version); Logger.DebugS("ogl", "OpenGL Vendor: {0}", vendor); Logger.DebugS("ogl", "OpenGL Renderer: {0}", renderer); Logger.DebugS("ogl", "OpenGL Version: {0}", version); _loadVendorSettings(vendor, renderer, version); #if DEBUG _hijackDebugCallback(); #endif _loadStockTextures(); _loadStockShaders(); var quadVertices = new[] { new Vertex2D(1, 0, 1, 1), new Vertex2D(0, 0, 0, 1), new Vertex2D(1, 1, 1, 0), new Vertex2D(0, 1, 0, 0), }; QuadVBO = new Buffer <Vertex2D>(this, BufferTarget.ArrayBuffer, BufferUsageHint.StaticDraw, quadVertices, "QuadVBO"); QuadVAO = new OGLHandle(GL.GenVertexArray()); GL.BindVertexArray(QuadVAO.Handle); _objectLabelMaybe(ObjectLabelIdentifier.VertexArray, QuadVAO, "QuadVAO"); // Vertex Coords GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, Vertex2D.SizeOf, 0); GL.EnableVertexAttribArray(0); // Texture Coords. GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, Vertex2D.SizeOf, 2 * sizeof(float)); GL.EnableVertexAttribArray(1); // Texture Array Index. GL.VertexAttribPointer(2, 1, VertexAttribPointerType.Float, false, Vertex2D.SizeOf, 4 * sizeof(float)); GL.EnableVertexAttribArray(2); BatchVBO = new Buffer(this, BufferTarget.ArrayBuffer, BufferUsageHint.DynamicDraw, Vertex2D.SizeOf * BatchVertexData.Length, "BatchVBO"); BatchVAO = new OGLHandle(GL.GenVertexArray()); GL.BindVertexArray(BatchVAO.Handle); _objectLabelMaybe(ObjectLabelIdentifier.VertexArray, BatchVAO, "BatchVAO"); // Vertex Coords GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, Vertex2D.SizeOf, 0); GL.EnableVertexAttribArray(0); // Texture Coords. GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, Vertex2D.SizeOf, 2 * sizeof(float)); GL.EnableVertexAttribArray(1); BatchEBO = new Buffer(this, BufferTarget.ElementArrayBuffer, BufferUsageHint.DynamicDraw, sizeof(ushort) * BatchIndexData.Length, "BatchEBO"); ProjViewUBO = new Buffer(this, BufferTarget.UniformBuffer, BufferUsageHint.StreamDraw, "ProjViewUBO"); unsafe { ProjViewUBO.Reallocate(sizeof(ProjViewMatrices)); } GL.BindBufferBase(BufferRangeTarget.UniformBuffer, ProjViewBindingIndex, ProjViewUBO.Handle); UniformConstantsUBO = new Buffer(this, BufferTarget.UniformBuffer, BufferUsageHint.StreamDraw, nameof(UniformConstantsUBO)); unsafe { UniformConstantsUBO.Reallocate(sizeof(UniformConstants)); } GL.BindBufferBase(BufferRangeTarget.UniformBuffer, UniformConstantsBindingIndex, UniformConstantsUBO.Handle); LightFBO = new OGLHandle(GL.GenFramebuffer()); LightTexture = new OGLHandle(GL.GenTexture()); var(lightW, lightH) = _lightMapSize(); GL.BindTexture(TextureTarget.Texture2D, LightTexture.Handle); GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba16f, lightW, lightH, 0, PixelFormat.Rgba, PixelType.Float, IntPtr.Zero); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMagFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)OpenTK.Graphics.OpenGL.TextureWrapMode.ClampToEdge); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)OpenTK.Graphics.OpenGL.TextureWrapMode.ClampToEdge); GL.BindFramebuffer(FramebufferTarget.Framebuffer, LightFBO.Handle); _objectLabelMaybe(ObjectLabelIdentifier.Framebuffer, LightFBO, "LightFBO"); _objectLabelMaybe(ObjectLabelIdentifier.Texture, LightTexture, "LightTexture"); GL.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, LightTexture.Handle, 0); GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0); _drawingSplash = true; _renderHandle = new RenderHandle(this); GL.Viewport(0, 0, _window.Width, _window.Height); Render(null); }
public bool Equals(OGLHandle other) { return(Handle == other.Handle); }
private void _initOpenGL() { _loadExtensions(); GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); Logger.DebugS("ogl", "OpenGL Vendor: {0}", GL.GetString(StringName.Vendor)); Logger.DebugS("ogl", "OpenGL Version: {0}", GL.GetString(StringName.Version)); #if DEBUG _hijackDebugCallback(); #endif Vertex2DProgram = _compileProgram( new ResourcePath("/Shaders/Internal/sprite.vert"), new ResourcePath("/Shaders/Internal/sprite.frag")); _objectLabelMaybe(ObjectLabelIdentifier.Program, Vertex2DProgram, "Vertex2DProgram"); Vertex2DUniformModel = GL.GetUniformLocation(Vertex2DProgram.Handle, "modelMatrix"); Vertex2DUniformView = GL.GetUniformLocation(Vertex2DProgram.Handle, "viewMatrix"); Vertex2DUniformProjection = GL.GetUniformLocation(Vertex2DProgram.Handle, "projectionMatrix"); Vertex2DUniformModUV = GL.GetUniformLocation(Vertex2DProgram.Handle, "modifyUV"); Vertex2DUniformModulate = GL.GetUniformLocation(Vertex2DProgram.Handle, "modulate"); var quadVertices = new[] { new Vertex2D(1, 0, 1, 1), new Vertex2D(0, 0, 0, 1), new Vertex2D(1, 1, 1, 0), new Vertex2D(0, 1, 0, 0), }; QuadVBO = new OGLHandle(GL.GenBuffer()); GL.BindBuffer(BufferTarget.ArrayBuffer, QuadVBO.Handle); _objectLabelMaybe(ObjectLabelIdentifier.Buffer, QuadVBO, "QuadVBO"); GL.BufferData(BufferTarget.ArrayBuffer, quadVertices.Length * Vertex2D.SizeOf, quadVertices, BufferUsageHint.StaticDraw); QuadVAO = new OGLHandle(GL.GenVertexArray()); GL.BindVertexArray(QuadVAO.Handle); _objectLabelMaybe(ObjectLabelIdentifier.VertexArray, QuadVAO, "QuadVAO"); GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, Vertex2D.SizeOf, 0); GL.EnableVertexAttribArray(0); GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, Vertex2D.SizeOf, 2 * sizeof(float)); GL.EnableVertexAttribArray(1); BatchVBO = new OGLHandle(GL.GenBuffer()); GL.BindBuffer(BufferTarget.ArrayBuffer, BatchVBO.Handle); _objectLabelMaybe(ObjectLabelIdentifier.Buffer, BatchVBO, "BatchVBO"); GL.BufferData(BufferTarget.ArrayBuffer, Vertex2D.SizeOf * BatchVertexData.Length, IntPtr.Zero, BufferUsageHint.DynamicDraw); BatchVAO = new OGLHandle(GL.GenVertexArray()); GL.BindVertexArray(BatchVAO.Handle); _objectLabelMaybe(ObjectLabelIdentifier.VertexArray, BatchVAO, "BatchVAO"); GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, Vertex2D.SizeOf, 0); GL.EnableVertexAttribArray(0); GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, Vertex2D.SizeOf, 2 * sizeof(float)); GL.EnableVertexAttribArray(1); BatchEBO = new OGLHandle(GL.GenBuffer()); GL.BindBuffer(BufferTarget.ElementArrayBuffer, BatchEBO.Handle); _objectLabelMaybe(ObjectLabelIdentifier.Buffer, BatchEBO, "BatchEBO"); GL.BufferData(BufferTarget.ElementArrayBuffer, sizeof(ushort) * BatchIndexData.Length, IntPtr.Zero, BufferUsageHint.DynamicDraw); _drawingSplash = true; Render(null); }
private void InitOpenGL() { _loadExtensions(); _hijackDebugCallback(); var vendor = GL.GetString(StringName.Vendor); var renderer = GL.GetString(StringName.Renderer); var version = GL.GetString(StringName.Version); Logger.DebugS("clyde.ogl", "OpenGL Vendor: {0}", vendor); Logger.DebugS("clyde.ogl", "OpenGL Renderer: {0}", renderer); Logger.DebugS("clyde.ogl", "OpenGL Version: {0}", version); _loadVendorSettings(vendor, renderer, version); var major = GL.GetInteger(GetPName.MajorVersion); var minor = GL.GetInteger(GetPName.MinorVersion); DebugInfo = new ClydeDebugInfo(new Version(major, minor), MinimumOpenGLVersion, renderer, vendor, version); GL.Enable(EnableCap.Blend); GL.Enable(EnableCap.FramebufferSrgb); GL.Enable(EnableCap.PrimitiveRestart); GL.PrimitiveRestartIndex(ushort.MaxValue); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); _loadStockTextures(); _loadStockShaders(); // Quad drawing. { var quadVertices = new[] { new Vertex2D(1, 0, 1, 1), new Vertex2D(0, 0, 0, 1), new Vertex2D(1, 1, 1, 0), new Vertex2D(0, 1, 0, 0), }; QuadVBO = new Buffer <Vertex2D>(this, BufferTarget.ArrayBuffer, BufferUsageHint.StaticDraw, quadVertices, nameof(QuadVBO)); QuadVAO = new OGLHandle((uint)GL.GenVertexArray()); GL.BindVertexArray(QuadVAO.Handle); _objectLabelMaybe(ObjectLabelIdentifier.VertexArray, QuadVAO, "QuadVAO"); // Vertex Coords GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, Vertex2D.SizeOf, 0); GL.EnableVertexAttribArray(0); // Texture Coords. GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, Vertex2D.SizeOf, 2 * sizeof(float)); GL.EnableVertexAttribArray(1); } // Batch rendering { BatchVBO = new Buffer(this, BufferTarget.ArrayBuffer, BufferUsageHint.DynamicDraw, Vertex2D.SizeOf * BatchVertexData.Length, "BatchVBO"); BatchVAO = new OGLHandle(GL.GenVertexArray()); GL.BindVertexArray(BatchVAO.Handle); _objectLabelMaybe(ObjectLabelIdentifier.VertexArray, BatchVAO, "BatchVAO"); // Vertex Coords GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, Vertex2D.SizeOf, 0); GL.EnableVertexAttribArray(0); // Texture Coords. GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, Vertex2D.SizeOf, 2 * sizeof(float)); GL.EnableVertexAttribArray(1); BatchEBO = new Buffer(this, BufferTarget.ElementArrayBuffer, BufferUsageHint.DynamicDraw, sizeof(ushort) * BatchIndexData.Length, "BatchEBO"); } ProjViewUBO = new Buffer(this, BufferTarget.UniformBuffer, BufferUsageHint.StreamDraw, "ProjViewUBO"); unsafe { ProjViewUBO.Reallocate(sizeof(ProjViewMatrices)); } GL.BindBufferBase(BufferRangeTarget.UniformBuffer, ProjViewBindingIndex, ProjViewUBO.ObjectHandle); UniformConstantsUBO = new Buffer(this, BufferTarget.UniformBuffer, BufferUsageHint.StreamDraw, nameof(UniformConstantsUBO)); unsafe { UniformConstantsUBO.Reallocate(sizeof(UniformConstants)); } GL.BindBufferBase(BufferRangeTarget.UniformBuffer, UniformConstantsBindingIndex, UniformConstantsUBO.ObjectHandle); _regenerateLightRenderTarget(); EntityPostRenderTarget = CreateRenderTarget(Vector2i.One * 4 * EyeManager.PIXELSPERMETER, RenderTargetColorFormat.Rgba8Srgb, name: nameof(EntityPostRenderTarget)); _drawingSplash = true; _renderHandle = new RenderHandle(this); GL.Viewport(0, 0, ScreenSize.X, ScreenSize.Y); // Quickly do a render with _drawingSplash = true so the screen isn't blank. Render(); }
public Texture LoadTextureFromImage <T>(Image <T> image, string name = null, TextureLoadParameters?loadParams = null) where T : unmanaged, IPixel <T> { DebugTools.Assert(_mainThread == Thread.CurrentThread); var actualParams = loadParams ?? TextureLoadParameters.Default; var pixelType = typeof(T); var texture = new OGLHandle((uint)GL.GenTexture()); GL.BindTexture(TextureTarget.Texture2D, texture.Handle); _applySampleParameters(actualParams.SampleParameters); PixelInternalFormat internalFormat; PixelFormat pixelDataFormat; PixelType pixelDataType; if (pixelType == typeof(Rgba32)) { internalFormat = actualParams.Srgb ? PixelInternalFormat.Srgb8Alpha8 : PixelInternalFormat.Rgba8; pixelDataFormat = PixelFormat.Rgba; pixelDataType = PixelType.UnsignedByte; } else if (pixelType == typeof(Alpha8)) { if (image.Width % 4 != 0 || image.Height % 4 != 0) { throw new ArgumentException("Alpha8 images must have multiple of 4 sizes."); } internalFormat = PixelInternalFormat.R8; pixelDataFormat = PixelFormat.Red; pixelDataType = PixelType.UnsignedByte; // TODO: Does it make sense to default to 1 for RGB parameters? // It might make more sense to pass some options to change swizzling. var swizzle = new[] { (int)All.One, (int)All.One, (int)All.One, (int)All.Red }; GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleRgba, swizzle); } else if (pixelType == typeof(Gray8) && !actualParams.Srgb) { // Can only use R8 for Gray8 if sRGB is OFF. // Because OpenGL doesn't provide non-sRGB single/dual channel image formats. // Vulkan when? if (image.Width % 4 != 0 || image.Height % 4 != 0) { throw new ArgumentException("Gray8 non-sRGB images must have multiple of 4 sizes."); } internalFormat = PixelInternalFormat.R8; pixelDataFormat = PixelFormat.Red; pixelDataType = PixelType.UnsignedByte; var swizzle = new[] { (int)All.Red, (int)All.Red, (int)All.Red, (int)All.One }; GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleRgba, swizzle); } else { throw new NotImplementedException($"Unable to handle pixel type '{pixelType.Name}'"); } unsafe { var span = image.GetPixelSpan(); fixed(T *ptr = span) { GL.TexImage2D(TextureTarget.Texture2D, 0, internalFormat, image.Width, image.Height, 0, pixelDataFormat, pixelDataType, (IntPtr)ptr); } } return(_genTexture(texture, (image.Width, image.Height), name)); }
private void _initOpenGL() { _loadExtensions(); GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); var vendor = GL.GetString(StringName.Vendor); var renderer = GL.GetString(StringName.Renderer); var version = GL.GetString(StringName.Version); Logger.DebugS("ogl", "OpenGL Vendor: {0}", vendor); Logger.DebugS("ogl", "OpenGL Renderer: {0}", renderer); Logger.DebugS("ogl", "OpenGL Version: {0}", version); _loadVendorSettings(vendor, renderer, version); #if DEBUG _hijackDebugCallback(); #endif _loadStockTextures(); Vertex2DProgram = _compileProgram( new ResourcePath("/Shaders/Internal/sprite.vert"), new ResourcePath("/Shaders/Internal/sprite.frag"), "Vertex2DProgram"); Vertex2DProgram.BindBlock("projectionViewMatrices", ProjViewBindingIndex); Vertex2DArrayProgram = _compileProgram( new ResourcePath("/Shaders/Internal/sprite-arrayed.vert"), new ResourcePath("/Shaders/Internal/sprite-arrayed.frag"), "Vertex2DArrayProgram"); Vertex2DArrayProgram.BindBlock("projectionViewMatrices", ProjViewBindingIndex); var quadVertices = new[] { new Vertex2D(1, 0, 1, 1, 1), new Vertex2D(0, 0, 0, 1, 1), new Vertex2D(1, 1, 1, 0, 1), new Vertex2D(0, 1, 0, 0, 1), }; QuadVBO = new Buffer <Vertex2D>(this, BufferTarget.ArrayBuffer, BufferUsageHint.StaticDraw, quadVertices, "QuadVBO"); QuadVAO = new OGLHandle(GL.GenVertexArray()); GL.BindVertexArray(QuadVAO.Handle); _objectLabelMaybe(ObjectLabelIdentifier.VertexArray, QuadVAO, "QuadVAO"); // Vertex Coords GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, Vertex2D.SizeOf, 0); GL.EnableVertexAttribArray(0); // Texture Coords. GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, Vertex2D.SizeOf, 2 * sizeof(float)); GL.EnableVertexAttribArray(1); // Texture Array Index. GL.VertexAttribPointer(2, 1, VertexAttribPointerType.Float, false, Vertex2D.SizeOf, 4 * sizeof(float)); GL.EnableVertexAttribArray(2); BatchVBO = new Buffer(this, BufferTarget.ArrayBuffer, BufferUsageHint.DynamicDraw, Vertex2D.SizeOf * BatchVertexData.Length, "BatchVBO"); BatchVAO = new OGLHandle(GL.GenVertexArray()); GL.BindVertexArray(BatchVAO.Handle); _objectLabelMaybe(ObjectLabelIdentifier.VertexArray, BatchVAO, "BatchVAO"); // Vertex Coords GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, Vertex2D.SizeOf, 0); GL.EnableVertexAttribArray(0); // Texture Coords. GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, Vertex2D.SizeOf, 2 * sizeof(float)); GL.EnableVertexAttribArray(1); BatchEBO = new Buffer(this, BufferTarget.ElementArrayBuffer, BufferUsageHint.DynamicDraw, sizeof(ushort) * BatchIndexData.Length, "BatchEBO"); BatchArrayedVAO = new OGLHandle(GL.GenVertexArray()); BatchVBO.Use(); BatchEBO.Use(); GL.BindVertexArray(BatchArrayedVAO.Handle); _objectLabelMaybe(ObjectLabelIdentifier.VertexArray, BatchArrayedVAO, "BatchArrayedVAO"); // Vertex Coords GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, Vertex2D.SizeOf, 0); GL.EnableVertexAttribArray(0); // Texture Coords. GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, Vertex2D.SizeOf, 2 * sizeof(float)); GL.EnableVertexAttribArray(1); // Texture Array Index. GL.VertexAttribPointer(2, 1, VertexAttribPointerType.Float, false, Vertex2D.SizeOf, 4 * sizeof(float)); GL.EnableVertexAttribArray(2); ProjViewUBO = new Buffer(this, BufferTarget.UniformBuffer, BufferUsageHint.StreamDraw, "ProjViewUBO"); unsafe { ProjViewUBO.Reallocate(sizeof(ProjViewMatrices)); } GL.BindBufferBase(BufferRangeTarget.UniformBuffer, ProjViewBindingIndex, ProjViewUBO.Handle); _drawingSplash = true; _renderHandle = new RenderHandle(this); GL.Viewport(0, 0, _window.Width, _window.Height); Render(null); }
public Texture LoadTextureFromImage <T>(Image <T> image, string name = null, TextureLoadParameters?loadParams = null) where T : unmanaged, IPixel <T> { DebugTools.Assert(_mainThread == Thread.CurrentThread); var pixelType = typeof(T); var texture = new OGLHandle(GL.GenTexture()); GL.BindTexture(TextureTarget.Texture2D, texture.Handle); var actualParams = loadParams ?? TextureLoadParameters.Default; if (actualParams.SampleParameters.Filter) { GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); } else { GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); } switch (actualParams.SampleParameters.WrapMode) { case TextureWrapMode.None: GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)OGLTextureWrapMode.ClampToEdge); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)OGLTextureWrapMode.ClampToEdge); break; case TextureWrapMode.Repeat: GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)OGLTextureWrapMode.Repeat); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)OGLTextureWrapMode.Repeat); break; case TextureWrapMode.MirroredRepeat: GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)OGLTextureWrapMode.MirroredRepeat); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)OGLTextureWrapMode.MirroredRepeat); break; default: throw new ArgumentOutOfRangeException(); } PixelInternalFormat internalFormat; PixelFormat pixelDataFormat; PixelType pixelDataType; if (pixelType == typeof(Rgba32)) { internalFormat = PixelInternalFormat.Rgba8; pixelDataFormat = PixelFormat.Rgba; pixelDataType = PixelType.UnsignedByte; } else if (pixelType == typeof(Alpha8)) { internalFormat = PixelInternalFormat.R8; pixelDataFormat = PixelFormat.Red; pixelDataType = PixelType.UnsignedByte; // TODO: Does it make sense to default to 1 for RGB parameters? // It might make more sense to pass some options to change swizzling. var swizzle = new[] { (int)All.One, (int)All.One, (int)All.One, (int)All.Red }; GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleRgba, swizzle); } else { throw new NotImplementedException($"Unable to handle pixel type '{pixelType.Name}'"); } unsafe { var span = image.GetPixelSpan(); var length = span.Length; var val1 = span[0]; fixed(T *ptr = span) { GL.TexImage2D(TextureTarget.Texture2D, 0, internalFormat, image.Width, image.Height, 0, pixelDataFormat, pixelDataType, (IntPtr)ptr); } } if (name != null) { _objectLabelMaybe(ObjectLabelIdentifier.Texture, texture, name); } var loaded = new LoadedTexture { OpenGLObject = texture, Width = image.Width, Height = image.Height, Name = name, Type = LoadedTextureType.Texture2D }; var id = ++_nextTextureId; _loadedTextures.Add(id, loaded); return(new OpenGLTexture(id, image.Width, image.Height)); }
public TextureArray LoadArrayFromImages <T>(ICollection <Image <T> > images, string name = null, TextureLoadParameters?loadParams = null) where T : unmanaged, IPixel <T> { DebugTools.Assert(images.Count != 0); (int x, int y)? size = null; foreach (var image in images) { if (size == null) { size = (image.Width, image.Height); } if (size.Value.x != image.Width || size.Value.y != image.Height) { throw new ArgumentException("All images must be of the same dimensions.", nameof(images)); } } var textureId = ++_nextTextureId; var texture = new OGLHandle(GL.GenTexture()); GL.BindTexture(TextureTarget.Texture2DArray, texture.Handle); if (name != null) { _objectLabelMaybe(ObjectLabelIdentifier.Texture, texture, name); } DebugTools.Assert(size.HasValue); var(width, height) = size.Value; GL.TexImage3D(TextureTarget.Texture2DArray, 0, PixelInternalFormat.Rgba8, width, height, images.Count, 0, PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero); var actualParams = loadParams ?? TextureLoadParameters.Default; if (actualParams.SampleParameters.Filter) { GL.TexParameter(TextureTarget.Texture2DArray, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); GL.TexParameter(TextureTarget.Texture2DArray, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); } else { GL.TexParameter(TextureTarget.Texture2DArray, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); GL.TexParameter(TextureTarget.Texture2DArray, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); } switch (actualParams.SampleParameters.WrapMode) { case TextureWrapMode.None: GL.TexParameter(TextureTarget.Texture2DArray, TextureParameterName.TextureWrapS, (int)OGLTextureWrapMode.ClampToEdge); GL.TexParameter(TextureTarget.Texture2DArray, TextureParameterName.TextureWrapT, (int)OGLTextureWrapMode.ClampToEdge); break; case TextureWrapMode.Repeat: GL.TexParameter(TextureTarget.Texture2DArray, TextureParameterName.TextureWrapS, (int)OGLTextureWrapMode.Repeat); GL.TexParameter(TextureTarget.Texture2DArray, TextureParameterName.TextureWrapT, (int)OGLTextureWrapMode.Repeat); break; case TextureWrapMode.MirroredRepeat: GL.TexParameter(TextureTarget.Texture2DArray, TextureParameterName.TextureWrapS, (int)OGLTextureWrapMode.MirroredRepeat); GL.TexParameter(TextureTarget.Texture2DArray, TextureParameterName.TextureWrapT, (int)OGLTextureWrapMode.MirroredRepeat); break; default: throw new ArgumentOutOfRangeException(); } var index = 0; var refTextureList = new List <OpenGLTexture>(); foreach (var image in images) { var span = ((Image <Rgba32>)(object) image).GetPixelSpan(); unsafe { fixed(Rgba32 *ptr = span) { GL.TexSubImage3D(TextureTarget.Texture2DArray, 0, 0, 0, index, width, height, 1, PixelFormat.Rgba, PixelType.UnsignedByte, (IntPtr)ptr); } } index += 1; refTextureList.Add(new OpenGLTexture(textureId, width, height, index)); } var loaded = new LoadedTexture { OpenGLObject = texture, Width = width, Height = height, ArrayDepth = images.Count, Name = name, Type = LoadedTextureType.Array2D }; _loadedTextures.Add(textureId, loaded); return(new TextureArray(refTextureList.ToArray())); }