OpenGL/TK TexSubImage2D can't modify transparent pixel - c#

I have loaded in an image with this method:
public static int LoadTexture(string file)
{
Bitmap bitmap = new Bitmap(file);
int tex;
GL.GenTextures(1, out tex);
GL.BindTexture(TextureTarget.Texture2D, tex);
System.Drawing.Imaging.BitmapData data = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0,
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
bitmap.UnlockBits(data);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
Console.WriteLine("[ImageDisplay] Loaded image: " + file);
return tex;
}
I need to modify pixels within this image, so i have used this:
GL.TexSubImage2D(TextureTarget.Texture2D, 0, X, Y, 1, 1, OpenTK.Graphics.OpenGL.PixelFormat.Rgb, PixelType.UnsignedInt, new uint[] { 0xFFFF0000 });
My problem, is that only non-transparent pixels change to red, the transparent pixels do not change at all.
How could i fix this?

OpenTK.Graphics.OpenGL.PixelFormat.Rgb, PixelType.UnsignedInt, new uint[] { 0xFFFF0000 }
The pixel transfer format you state is GL_RGB. That means 3 components: red, green, and blue, in that order.
The pixel transfer type is GL_UNSIGNED_INT, which means that each component is an unsigned integer. Thus, you are expected to provide an array of 3 unsigned integers per pixel.
If you want each component to be an unsigned byte, then you should use that as your type. And your array should be an array of unsigned bytes.

Related

The data I am returning does not affect the inside of the void function protected override

I'm sending a bitmap frame to the "Load" function below. The LoadTexture function returns the data as "1" in GenTexture and sets it to texture. When I debug I see that texture returns "1". But it does not affect the data in the "OnRenderFrame" function. I have to use the OnRenderFrame with protected override.
public void Load(Bitmap bitmap)
{
texture = LoadTexture(bitmap);
}
public int LoadTexture(Bitmap file)
{
Bitmap bitmap = file;
int tex;
GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
GL.GenTextures(1, out tex);
GL.BindTexture(TextureTarget.Texture2D, tex);
BitmapData data = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Luminance, data.Width, data.Height, 0,
OpenTK.Graphics.OpenGL.PixelFormat.Luminance, PixelType.UnsignedByte, data.Scan0);
bitmap.UnlockBits(data);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
return tex;
}
protected override void OnRenderFrame(FrameEventArgs e)
{
Title = $"(Vsync: {VSync}) FPS: {1f / e.Time:0}";
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
DrawImage(texture);
Console.WriteLine(texture);
SwapBuffers();
}

what's the simplest framebuffer example for opengl?

im trying to add post processing to my game but i can't understand the framebuffer tutorial on learnopengl and opengl-tutorial i just need a simple framebuffer example with color and depth textures and how to use it and render it
im not sure how to implement a framebuffer
public class FrameBuffer
{
public int FBO,DBO;
public int Width, Height;
public int tex,depth;
public FrameBuffer(int width, int height)
{
this.Width = width;
this.Height = height;
FBO = GL.GenFramebuffer();
Bind();
tex = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, tex);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, Width, Height, 0, PixelFormat.Rgb, PixelType.UnsignedByte, (IntPtr)null);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2D, tex, 0);
}
public void Bind()
{
GL.BindFramebuffer(FramebufferTarget.Framebuffer, FBO);
}
public void Unbind()
{
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
}
Your code sets up a proper framebuffer with a color plane.
If the framebufer has to have a depth buffer, then you've to create a depth texture, with the format PixelFormat.DepthComponent and one of the internal formats PixelInternalFormat.DepthComponent16, PixelInternalFormat.DepthComponent24, PixelInternalFormat.DepthComponent32 or PixelInternalFormat.DepthComponent32f:
depth = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, depth);
GL.TexParameter(TextureTarget.Texture2D,
TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
GL.TexParameter(TextureTarget.Texture2D,
TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.DepthComponent24,
Width, Height, 0, PixelFormat.DepthComponent, PixelType.Float, (IntPtr)null);
Attach it to the framebuffer, to FramebufferAttachment.DepthAttachment
GL.FramebufferTexture2D(FramebufferTarget.Framebuffer,
FramebufferAttachment.DepthAttachment,
TextureTarget.Texture2D, depth, 0);
Note after you've attached the color buffer and the depth buffer you should validate the framebuffer completeness, which should return a status value of FramebufferErrorCode.FramebufferComplete.:
FramebufferErrorCode status = GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer);
Alternatively to a depth texture you can attach a (depth) renderbuffer:
depth = GL.GenRenderbuffer();
GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, depth);
GL.RenderbufferStorage(RenderbufferTarget.Renderbuffer,
RenderbufferStorage.DepthComponent24, Width, Height);
GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, 0);
GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer,
FramebufferAttachment.DepthAttachment,
RenderbufferTarget.Renderbuffer, depth);

Opengl texturing weird rendering. Black and white, RGB separated, tiling [duplicate]

This question already has an answer here:
C# OpenTK - Textured Quad
(1 answer)
Closed 5 years ago.
So im trying to render a texture to a quad using OpenGL and im getting a really weird artifact and I think it being caused by my loading method but im not truly sure.
When you get close to the quad you can see that it is tring to render the red green and blue next to each other. kinda looks like what a pixel on a tv looks like
Rendered Quad
Close up of quad
Texture
LoadTexture
public static uint LoadTexture(string filePath)
{
Bitmap bitmap = new Bitmap("Res/" + filePath);
Gl.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
uint textureID = Gl.GenTexture();
Gl.BindTexture(TextureTarget.Texture2d, textureID);
BitmapData data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
Gl.TexImage2D(TextureTarget.Texture2d, 0, InternalFormat.Rgb8, data.Width, data.Height, 0, OpenGL.PixelFormat.Bgr, PixelType.UnsignedByte, data.Scan0);
bitmap.UnlockBits(data);
Gl.TexParameter(TextureTarget.Texture2d, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
Gl.TexParameter(TextureTarget.Texture2d, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
return textureID;
}
Rendering
public void Render(TexturedModel texturedModel, StaticShader shader)
{
RawModel model = texturedModel.model;
using (MemoryLock vertexPositions = new MemoryLock(model.vertexPositions))
using (MemoryLock texturePositions = new MemoryLock(texturedModel.textureCords))
{
Gl.VertexAttribPointer((uint)shader.locationPosition, model.dimension, VertexAttribType.Float, false, 0, vertexPositions.Address);
Gl.EnableVertexAttribArray((uint)shader.locationPosition);
Gl.VertexAttribPointer((uint)shader.locationTexturedCoords, 2, VertexAttribType.Float, false, 0, texturePositions.Address);
Gl.EnableVertexAttribArray((uint)shader.locationTexturedCoords);
Gl.PixelStore(PixelStoreParameter.UnpackAlignment, 0);
Gl.ActiveTexture(TextureUnit.Texture0);
Gl.BindTexture(TextureTarget.Texture2d, texturedModel.texture.TextureID);
Gl.Uniform1(shader.locationTextureSampler, 0);
Gl.UniformMatrix4(shader.locationProjectionMatrix, false, projectionMatrix.ToArray());
viewMatrix = Maths.CreateViewMatrix(camera);
Gl.UniformMatrix4(shader.locationViewMatrix, false, viewMatrix.ToArray());
Gl.UniformMatrix4(shader.locationTransformationMatrix, false, model.modelMatrix.ToArray());
//Gl.DrawArrays(PrimitiveType.Triangles, 0, model.vertexPositions.Length / model.dimension);
Gl.DrawElements(PrimitiveType.Triangles, model.indices.Length, DrawElementsType.UnsignedInt, model.indices);
}
}
Shader program
public class StaticShader : ShaderProgram
{
private static string VERTEX_FILE = #"Shader/VertexShader.txt";
private static string FRAGMENTSHADER = #"Shader/FragmentShader.txt";
public int locationPosition;
public int locationTexturedCoords;
public int locationTransformationMatrix;
public int locationProjectionMatrix;
public int locationViewMatrix;
public int locationTextureSampler;
public StaticShader() : base(VERTEX_FILE, FRAGMENTSHADER)
{
locationTransformationMatrix = this.GetUniformLocation("transformationMatrix");
locationProjectionMatrix = this.GetUniformLocation("projectionMatrix");
locationViewMatrix = this.GetUniformLocation("viewMatrix");
locationTexturedCoords = this.GetAttribLocation("textureCords");
locationPosition = this.GetAttribLocation("position");
locationTextureSampler = this.GetUniformLocation("textureSampler");
}
}
Fragment shader
varying vec2 outTextureCords;
uniform sampler2D textureSampler;
void main() {
gl_FragColor = texture(textureSampler, outTextureCords);
}
vertices
public float[] vertexPositions = new float[] {
-0.5f,0.5f,0, //V0
-0.5f,-0.5f,0, //V1
0.5f,-0.5f,0, //V2
0.5f,0.5f,0 //V3
};
public int[] indices = new int[] {
0,1,3, //Top left triangle (V0,V1,V3)
3,1,2 //Bottom right triangle (V3,V1,V2)
};
public float[] textureCords = {
0,0,
0,1,
1,1,
1,0
};
Change the opengl format in the TexImage2d to B and switch internalFormat to rgba
Gl.TexImage2D(TextureTarget.Texture2d, 0, InternalFormat.Rgba, data.Width, data.Height, 0, OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);

Read pixels from a rectangle in an OpenGL texture

I know the glGetTexImage OpenGL function allows reading the pixels from an entire texture. Is there an OpenGL function that does the same thing but allows passing a rectangle to restrict the pixels read?
Here is how I ended up doing it in OpenTK (should translate easily to C++ or other OpenGL / OpenGL ES enabled languages):
public Bitmap GetBitmap()
{
int fboId;
GL.Ext.GenFramebuffers(1, out fboId);
CheckGLError();
GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, fboId);
CheckGLError();
GL.Ext.FramebufferTexture2D(FramebufferTarget.FramebufferExt, FramebufferAttachment.ColorAttachment0Ext, TextureTarget.Texture2D, TextureId, 0);
CheckGLError();
Bitmap b = new Bitmap(Width, Height);
var bits = b.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.ReadPixels(Rect.Left, Rect.Top, Width, Height, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bits.Scan0);
GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0);
GL.Ext.DeleteFramebuffers(1, ref fboId);
b.UnlockBits(bits);
return b;
}

OpenTK Texture showing up full black

Allright so I've taken some code that works fine on other programs, I've copied it into a new program I'm working on and it doesn't seem to work, as far as I know I've got all the needed lines in there, but the areas where a texture is suppost to appear just display black squares.
I think I'm missing a line but I've got no idea what it is. I'm quite puzzled to say the least.
Here is my opengl setup:
GL.ClearColor(Color.Black);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Viewport(0, 0, glControl1.Width, glControl1.Height);
GL.Ortho(0, 800, 600, 0, -30, 30);
This is the method that loads the textures and returns the texture id, I store that in my variable. (the file.writeallbytes is just a test, I could open that no problem in photoshop)
private int loadTexture(String path)
{
GL.Enable(EnableCap.Texture2D);
byte[] ddsBytes = Media.GetFile("\\"+path.Replace("\\\\","\\")).Skip(20).ToArray();
File.WriteAllBytes("Derp.dds", ddsBytes);
int texId = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, texId);
Bitmap image = null;
DDSReader.DDSImage ddsImg = new DDSReader.DDSImage(ddsBytes);
image = ddsImg.BitmapImage;
ddsImg = null;
BitmapData bmpData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bmpData.Width, bmpData.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bmpData.Scan0);
image.UnlockBits(bmpData);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)All.Modulate);
return texId;
}
And my drawing method looks like this:
public void Draw()
{
if (TexID == -1)
{
GL.Color4(Color[0], Color[1], Color[2], (byte)100);
}
else
{
GL.Color3((byte)255,(byte)255,(byte)255);
GL.Enable(EnableCap.Texture2D);
GL.BindTexture(TextureTarget.Texture2D, TexID);
}
GL.Begin(BeginMode.TriangleStrip);
GL.TexCoord2(0, 0);
GL.Vertex2(X, Y + Height);
GL.TexCoord2(0, 1);
GL.Vertex2(X, Y);
GL.TexCoord2(1, 0);
GL.Vertex2(X + Width, Y + Height);
GL.TexCoord2(1, 1);
GL.Vertex2(X +Width, Y);
GL.End();
GL.Disable(EnableCap.Texture2D);
}
EDIT: The texture does show up, but the texture is full black, even when I set another color value (which usually changes the hue of the texture)

Categories