I have two VBOs. One of them has a texture and the other one doesn't. I have no success drawing them to the screen simultaneously. DrawQuad draws the untextured one and DrawQuadTex draws the textured one, both with code similar to the below:
// Enable/Disable GL_TEXTURE_2D depending on which I'm drawing
// Bind/Unbind the texture
GL.EnableClientState(ArrayCap.VertexArray);
GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferId);
GL.VertexPointer(2, VertexPointerType.Float, Vector2.SizeInBytes, IntPtr.Zero);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, _indexBufferId);
GL.DrawElements(BeginMode.Triangles, _indices.Length, DrawElementsType.UnsignedByte, 0);
Whichever of these two functions gets called first, that shape is then visible (i.e. if I call DrawQuad, then an untextured quad is visible).
I do set glDisable on GL_TEXTURE_2D and I tried turning off the TexCoordArray and I tried binding a texture to 0, nothing made any difference. Is there something I'm overlooking?
SSCCE
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using OpenTK;
using OpenTK.Graphics.OpenGL;
namespace E04
{
internal class Renderer
{
private readonly Int32 _vertexBufferId;
private readonly Int32 _textureBufferId;
private readonly Int32 _indexBufferId;
private readonly Int32 _colorBufferId;
private readonly Int32 _normalBufferId;
private readonly Vector2[] _vertices;
private readonly Vector2[] _textureCoordinates;
private readonly Byte[] _indices;
private readonly Vector4[] _colors;
private readonly Vector3[] _normals;
public Renderer()
{
// Create a vertex array
_vertices = new Vector2[4];
// Set the coordinate data
_textureCoordinates = new Vector2[4];
_textureCoordinates[0].X = 0.0f;
_textureCoordinates[0].Y = 0.0f;
_textureCoordinates[1].X = 1.0f;
_textureCoordinates[1].Y = 0.0f;
_textureCoordinates[2].X = 0.0f;
_textureCoordinates[2].Y = 1.0f;
_textureCoordinates[3].X = 1.0f;
_textureCoordinates[3].Y = 1.0f;
// Set the index data
_indices = new Byte[6];
_indices[0] = 0;
_indices[1] = 1;
_indices[2] = 3;
_indices[3] = 3;
_indices[4] = 2;
_indices[5] = 0;
// Set the color data
_colors = new Vector4[4];
_colors[0] = new Vector4(1.0f, 0.0f, 0.0f, 1.0f);
_colors[1] = new Vector4(1.0f, 1.0f, 0.0f, 1.0f);
_colors[2] = new Vector4(0.0f, 1.0f, 0.0f, 1.0f);
_colors[3] = new Vector4(0.0f, 0.0f, 1.0f, 1.0f);
// Set the normal data
_normals = new Vector3[4];
_normals[0] = new Vector3(0.0f, 0.0f, 1.0f);
_normals[1] = new Vector3(0.0f, 0.0f, 1.0f);
_normals[2] = new Vector3(0.0f, 0.0f, 1.0f);
_normals[3] = new Vector3(0.0f, 0.0f, 1.0f);
// Bind the texture array buffer
GL.GenBuffers(1, out _textureBufferId);
GL.BindBuffer(BufferTarget.ArrayBuffer, _textureBufferId);
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr) (_textureCoordinates.Length*Vector2.SizeInBytes),
_textureCoordinates, BufferUsageHint.DynamicDraw);
GL.TexCoordPointer(2, TexCoordPointerType.Float, 8, IntPtr.Zero);
GL.EnableClientState(ArrayCap.TextureCoordArray);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
// Bind the normal array buffer
GL.GenBuffers(1, out _normalBufferId);
GL.BindBuffer(BufferTarget.ArrayBuffer, _normalBufferId);
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr) (_normals.Length*Vector3.SizeInBytes), _normals,
BufferUsageHint.StaticDraw);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
// Bind the color array buffer
GL.GenBuffers(1, out _colorBufferId);
GL.BindBuffer(BufferTarget.ArrayBuffer, _colorBufferId);
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr) (_colors.Length*Vector4.SizeInBytes), _colors,
BufferUsageHint.StaticDraw);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
// Bind vertex array buffer
GL.GenBuffers(1, out _vertexBufferId);
GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferId);
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr) (_vertices.Length*Vector2.SizeInBytes), _vertices,
BufferUsageHint.StreamDraw);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
// Bind index array buffer
GL.GenBuffers(1, out _indexBufferId);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, _indexBufferId);
GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr) (_indices.Length*sizeof (Byte)), _indices,
BufferUsageHint.StaticDraw);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
}
public void DrawQuad(Int32 x, Int32 y, Int32 width, Int32 height)
{
UpdateQuadVertices(x, y, width, height);
GL.Disable(EnableCap.Texture2D);
GL.BindTexture(TextureTarget.Texture2D, 0);
GL.EnableClientState(ArrayCap.VertexArray);
GL.EnableClientState(ArrayCap.ColorArray);
GL.EnableClientState(ArrayCap.NormalArray);
GL.EnableClientState(ArrayCap.TextureCoordArray);
GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferId);
GL.VertexPointer(2, VertexPointerType.Float, 0, IntPtr.Zero);
GL.BindBuffer(BufferTarget.ArrayBuffer, _colorBufferId);
GL.ColorPointer(4, ColorPointerType.Float, 0, IntPtr.Zero);
GL.BindBuffer(BufferTarget.ArrayBuffer, _normalBufferId);
GL.NormalPointer(NormalPointerType.Float, 0, IntPtr.Zero);
GL.BindBuffer(BufferTarget.ArrayBuffer, _textureBufferId);
GL.TexCoordPointer(2, TexCoordPointerType.Float, 0, IntPtr.Zero);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, _indexBufferId);
GL.DrawElements(BeginMode.Triangles, _indices.Length, DrawElementsType.UnsignedByte, 0);
}
public void DrawQuadTex(Int32 x, Int32 y, Int32 width, Int32 height, Int32 textureId)
{
UpdateQuadVertices(x, y, width, height);
GL.Enable(EnableCap.Texture2D);
GL.BindTexture(TextureTarget.Texture2D, textureId);
GL.EnableClientState(ArrayCap.VertexArray);
GL.EnableClientState(ArrayCap.ColorArray);
GL.EnableClientState(ArrayCap.NormalArray);
GL.EnableClientState(ArrayCap.TextureCoordArray);
GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferId);
GL.VertexPointer(2, VertexPointerType.Float, 0, IntPtr.Zero);
GL.BindBuffer(BufferTarget.ArrayBuffer, _colorBufferId);
GL.ColorPointer(4, ColorPointerType.Float, 0, IntPtr.Zero);
GL.BindBuffer(BufferTarget.ArrayBuffer, _normalBufferId);
GL.NormalPointer(NormalPointerType.Float, 0, IntPtr.Zero);
GL.BindBuffer(BufferTarget.ArrayBuffer, _textureBufferId);
GL.TexCoordPointer(2, TexCoordPointerType.Float, 0, IntPtr.Zero);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, _indexBufferId);
GL.DrawElements(BeginMode.Triangles, _indices.Length, DrawElementsType.UnsignedByte, 0);
// Removing this has no effect
GL.DisableClientState(ArrayCap.TextureCoordArray);
}
internal void UpdateQuadVertices(Int32 x, Int32 y, Int32 width, Int32 height)
{
_vertices[0].X = x;
_vertices[0].Y = y;
_vertices[1].X = x + width;
_vertices[1].Y = y;
_vertices[2].X = x;
_vertices[2].Y = y + height;
_vertices[3].X = x + width;
_vertices[3].Y = y + height;
GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferId);
GL.BufferSubData(BufferTarget.ArrayBuffer, IntPtr.Zero, (IntPtr) (_vertices.Length*Vector2.SizeInBytes),
_vertices);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
}
public Int32 LoadSimpleTexture()
{
Int32 textureObjectId;
GL.GenTextures(1, out textureObjectId);
GL.BindTexture(TextureTarget.Texture2D, textureObjectId);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter,
(Int32) TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter,
(Int32)TextureMagFilter.Linear);
var bitmap = new Bitmap("simple.png");
BitmapData data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
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);
return textureObjectId;
}
}
class Program
{
static void Main()
{
Int32 textureObjectId = 0;
using (var gameWindow = new GameWindow(800, 600))
{
var renderer = new Renderer();
gameWindow.Load += (s, e) =>
{
GL.ClearColor(Color.CornflowerBlue);
GL.Enable(EnableCap.Blend);
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
GL.AlphaFunc(AlphaFunction.Greater, 1.0f);
textureObjectId = renderer.LoadSimpleTexture();
};
gameWindow.Resize += (s, e) =>
{
GL.Viewport(0, 0, 800, 600);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Ortho(0, 800, 600, 0, -1, 1);
};
gameWindow.RenderFrame += (s, e) =>
{
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
renderer.DrawQuad(0, 0, 128, 128);
renderer.DrawQuadTex(128, 0, 128, 128, textureObjectId);
gameWindow.SwapBuffers();
};
gameWindow.Run();
}
}
}
}
Update
When I said that whichever function gets called first that is the one who's shape is being shown is inaccurate, actually only the untextured supersedes the textured (i.e. when DrawQuad is present, only untextured is visible)
The sample code you posted, works just fine. Therefore I am unable to reproduce the issue that you described. Evidently from the picture both textured and non-textured quads are present. However the textured quad is in addition blended by the color which causes the rainbow look. To fix this disable the color-pointer or fill the color buffer with a white color.
If the results on your machine do not match the pictures I have posted below, it likely suggests that other forces are at play. A likely related example of this could be choice of video card (-drivers).
Related
I'm trying to render an image with a compute shader. For testing purposes, I try to render the gl_GlobalInvocationID to the image, but that only gives me a black screen. It does, however, work when I give the imageStore a predefined color. For example vec4(1, 0, 0, 1);. After some testing, it appears that the gl_GlobalInvocationID.xy doesn't get any further than [0,0]. What am I doing wrong?
I tested the values of gl_GlobalInvocationID by rendering a different color if the x or y coordinates got higher than 0, which they didn't.
Compute shader:
#version 440
layout (local_size_x = 1, local_size_y = 1) in;
layout(rgba32f, binding = 0) uniform image2D frameBuffer;
void main()
{
ivec2 pixel_coords = ivec2(gl_GlobalInvocationID.xy);
ivec2 size = ivec2(imageSize(frameBuffer));
vec4 pixel;
pixel = vec4(vec2(pixel_coords) / vec2(size.x, size.y),0, 1);
imageStore(frameBuffer, pixel_coords, pixel);
}
Framebuffer creation:
frameBuffer = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, frameBuffer);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba32f, Width, Height, 0, PixelFormat.Rgba, PixelType.Float, IntPtr.Zero);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMinFilter.Nearest);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba32f, Width, Height, 0, PixelFormat.Rgba, PixelType.Float, IntPtr.Zero);
GL.BindImageTexture(0, frameBuffer, 0, false, 0, TextureAccess.WriteOnly, SizedInternalFormat.Rgba32f);
Compute shader initialization
//Initialise compute shader in Onload()
cShader = new ComputeShader("../../RayTracer.glsl");
cShader.Use();
cShader.Dispatch(Width, Height, 1);
Compute shader class
class ComputeShader {
int handle;
//Initialize the compute shader given by the path
public ComputeShader(string path) {
handle = GL.CreateProgram();
int shader = GL.CreateShader(ShaderType.ComputeShader);
string source;
using (StreamReader sr = new StreamReader(path)) {
source = sr.ReadToEnd();
}
GL.ShaderSource(shader, source);
GL.CompileShader(shader);
string shaderError = GL.GetShaderInfoLog(shader);
if (shaderError.Length > 0) {
Console.WriteLine(shaderError);
}
GL.AttachShader(handle, shader);
GL.LinkProgram(handle);
GL.DetachShader(handle, shader);
GL.DeleteShader(shader);
}
//Sets a uniform 4x4 matrix in the compute shader
public void SetMatrix4x4(string name, Matrix4 matrix) {
int location = GL.GetUniformLocation(handle, name);
GL.UniformMatrix4(location, false, ref matrix);
}
//Sets a uniform float in the compute shader
public void SetUniformFloat(string name, float val) {
int location = GL.GetUniformLocation(handle, name);
GL.Uniform1(location, val);
}
//Use the compute shader
public void Use() {
GL.UseProgram(handle);
}
//Dispatch the compute shader
public void Dispatch(int xGroups, int yGroups, int zGroups) {
GL.DispatchCompute(xGroups, yGroups, zGroups);
}
}
OnRenderFrameMethod:
protected override void OnRenderFrame(FrameEventArgs e) {
//Launch computer shaders
cShader.Use();
cShader.Dispatch(Width, Height, 1);
//Make sure frame is finsihed before proceeding
GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit);
//Clear previous frame
GL.Clear(ClearBufferMask.ColorBufferBit);
//Bind VAO
GL.BindVertexArray(VertexArrayObject);
//Bind texture
GL.BindTexture(TextureTarget.Texture2D, frameBuffer); //Renders GPU
//Draw primitives
GL.DrawElements(PrimitiveType.Triangles, canvasIndices.Length, DrawElementsType.UnsignedInt, 0);
//Swap buffers
Context.SwapBuffers();
base.OnRenderFrame(e);
}
I'm completely new to openGL.
I have to show two images side by side using shader code.
It shows properly using below code. But throws an
out of memory
exception and the entire system gets hangs.
Can you please check my code to see what might be the cause?
I think the problem is that I'm not properly deallocating memory from openTK textures after I don't need them, so I'm generating massive amounts of images, but I don't know how to fix this.
public partial class Form7ImageOnly : Form
{
string file = "opentksquare.png";
string file1 = "img_smile.png";
int program;
int vertShader;
int fragShader;
int buffer;
int positionLocation;
int positionLocation1;
int positionLocation2;
int texture;
int texture1;
int ScreenWidth;
int ScreenHeight;
float[] vertices = {
// Left bottom triangle
-1f, -1f, 0f,
1f, -1f, 0f,
1f, 1f, 0f,
// Right top triangle
1f, 1f, 0f,
-1f, 1f, 0f,
-1f, -1f, 0f
};
public Form7ImageOnly()
{
InitializeComponent();
}
private void Form7ImageOnly_Load(object sender, EventArgs e)
{
glControl.Resize += new EventHandler(glControl_Resize);
glControl.Paint += new PaintEventHandler(glControl_Paint);
GL.Enable(EnableCap.DepthTest);
Application.Idle += Application_Idle;
glControl_Resize(glControl, EventArgs.Empty);
}
void Application_Idle(object sender, EventArgs e)
{
while (glControl.IsIdle)
{
Render();
}
}
private void Render()
{
ScreenWidth = Screen.PrimaryScreen.Bounds.Width;
ScreenHeight = Screen.PrimaryScreen.Bounds.Height;
glControl.Size = new System.Drawing.Size(ScreenWidth, ScreenHeight);//full screen
texture = LoadTexture(file);
texture1 = LoadTexture(file1);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
DrawImage(texture,texture1);
}
private void glControl_Paint(object sender, PaintEventArgs e)
{
Render();
}
private void glControl_Resize(object sender, EventArgs e)
{
Init();
}
private void Init()
{
CreateShaders();
CreateProgram();
InitBuffers();
}
public void DrawImage(int image,int image1)
{
GL.Viewport(new Rectangle(0, 0, ScreenWidth, ScreenHeight));
GL.MatrixMode(MatrixMode.Projection);
GL.PushMatrix();
GL.LoadIdentity();
GL.MatrixMode(MatrixMode.Modelview);
GL.PushMatrix();
GL.LoadIdentity();
GL.Disable(EnableCap.Lighting);
GL.Enable(EnableCap.Texture2D);
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, image);
GL.Uniform1(positionLocation1, 0);
GL.ActiveTexture(TextureUnit.Texture1);
GL.BindTexture(TextureTarget.Texture2D, image1);
GL.Uniform1(positionLocation2, 1);
RunShaders();
//GL.Begin(PrimitiveType.Quads);
//GL.TexCoord2(0, 1);
//GL.Vertex3(0, 0, 0);
//GL.TexCoord2(1, 1);
//GL.Vertex3(1920, 0, 0);
//GL.TexCoord2(1, 0);
//GL.Vertex3(1920, 1080, 0);
//GL.TexCoord2(0, 0);
//GL.Vertex3(0, 1080, 0);
//GL.End();
GL.Disable(EnableCap.Texture2D);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Projection);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Modelview);
ErrorCode ec = GL.GetError();
if (ec != 0)
System.Console.WriteLine(ec.ToString());
Console.Read();
glControl.SwapBuffers();
}
private void RunShaders()
{
GL.ClearColor(Color.Violet);
GL.UseProgram(program);
GL.DrawArrays(PrimitiveType.Triangles, 0, vertices.Length / 3);
ErrorCode ec = GL.GetError();
if (ec != 0)
System.Console.WriteLine(ec.ToString());
Console.Read();
}
private void CreateProgram()
{
program = GL.CreateProgram();
GL.AttachShader(program, vertShader);
GL.AttachShader(program, fragShader);
GL.LinkProgram(program);
}
private void CreateShaders()
{
/***********Vert Shader********************/
vertShader = GL.CreateShader(ShaderType.VertexShader);
GL.ShaderSource(vertShader, #"attribute vec3 a_position;
varying vec2 vTexCoord;
void main() {
vTexCoord = (a_position.xy + 1) / 2;
gl_Position = vec4(a_position, 1);
}");
GL.CompileShader(vertShader);
/***********Frag Shader ****************/
fragShader = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(fragShader, #"precision highp float;
uniform sampler2D sTexture;uniform sampler2D sTexture1;
uniform int screenwidth;
varying vec2 vTexCoord;
void main ()
{
if ( vTexCoord.x<0.5 )
gl_FragColor = texture2D (sTexture, vec2(vTexCoord.x*2.0, vTexCoord.y));
else
gl_FragColor = texture2D (sTexture1, vec2(1.0- (vTexCoord.x*2.0-1.0), vTexCoord.y));
}");
GL.CompileShader(fragShader);
}
private void InitBuffers()
{
buffer = GL.GenBuffer();
positionLocation = GL.GetAttribLocation(program, "a_position");
positionLocation1 = GL.GetUniformLocation(program, "sTexture");
positionLocation2 = GL.GetUniformLocation(program, "sTexture1");
GL.EnableVertexAttribArray(positionLocation);
GL.BindBuffer(BufferTarget.ArrayBuffer, buffer);
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * sizeof(float)), vertices, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, 0,0);
}
public int LoadTexture(string file)
{
Bitmap bitmap = new Bitmap(file);
int tex = -1;
if (bitmap != null)
{
GL.DeleteTextures(1, ref tex);
GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
GL.GenTextures(1, out tex);
GL.BindTexture(TextureTarget.Texture2D, tex);
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
BitmapData data = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
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.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
}
return tex;
}
}
I've been trying to figure out how to get this to work. I'm using OpenTK for C# to modify images. Right now I'm able to load an image successfully, but when I try to modify the image with shaders is where I begin to have problems. I have 3 basic methods:
1) LoadTexture (sets the texture to GL)
2) DrawImage (actually draws the texture)
3) AddShaders (this method is called inside DrawImage.It applies the
shaders)
So here are the 2 problems I'm having:
1) I'm trying to create 2 triangles that span the entire texture.
This is because I want my fragment shader to do work over the entire
texture. What I'm actually getting is a large triangle that covers
the left side of the screen, and a rectangle on the right side of the
screen. EDIT: Made some progress! But still looking weird...Shader scripts updated..EDIT2: Newer progress pic uploaded
2) The shapes are showing up green, when I want them to use the
colors from the texture but red channel modified. What's important to
know is that I need to be able to analyze each pixel. Changing the
red channel of every pixel is JUST a proof of concept for what I want
to actually do (using color distance formulas, hue shifting, etc. but
I need to start simpler first)
This is the image I've successfully loaded as a texture:Loaded Texture
Here's the code for LoadTexture:
public int LoadTexture(string file)
{
Bitmap bitmap = new 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.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);
return tex;
}
Here's the code for DrawImage:
public static void DrawImage(int image)
{
GL.MatrixMode(MatrixMode.Projection);
GL.PushMatrix();
GL.LoadIdentity();
GL.Ortho(0, 1920, 0, 1080, -1, 1);
GL.MatrixMode(MatrixMode.Modelview);
GL.PushMatrix();
GL.LoadIdentity();
GL.Disable(EnableCap.Lighting);
GL.Enable(EnableCap.Texture2D);
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, image);
GL.Begin(PrimitiveType.Quads);
GL.TexCoord2(0,1);
GL.Vertex3(0, 0, 0);
GL.TexCoord2(1, 1);
GL.Vertex3(1920, 0, 0);
GL.TexCoord2(1, 0);
GL.Vertex3(1920, 1080, 0);
GL.TexCoord2(0, 0);
GL.Vertex3(0, 1080, 0);
GL.End();
AddShaders();
GL.Disable(EnableCap.Texture2D);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Projection);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Modelview);
ErrorCode ec = GL.GetError();
if (ec != 0)
System.Console.WriteLine(ec.ToString());
Console.Read();
}
And here's the code for AddShaders:
private static void AddShaders()
{
/***********Vert Shader********************/
var vertShader = GL.CreateShader(ShaderType.VertexShader);
GL.ShaderSource(vertShader, #"attribute vec3 a_position;
varying vec2 vTexCoord;
void main() {
vTexCoord = a_position.xy;
gl_Position = vec4(a_position, 1);
}");
GL.CompileShader(vertShader);
/***********Frag Shader ****************/
var fragShader = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(fragShader, #"uniform sampler2D sTexture;
varying vec2 vTexCoord;
void main ()
{
vec4 color = texture2D (sTexture, vTexCoord);
color.r = 0.5;
// Save the result
gl_FragColor = color;
}");
GL.CompileShader(fragShader);
var program = GL.CreateProgram();
GL.AttachShader(program, vertShader);
GL.AttachShader(program, fragShader);
GL.LinkProgram(program);
GL.ClearColor(Color.AliceBlue);
// OpenGL expects vertices to be defined counter clockwise by default
float[] vertices = {
// Left bottom triangle
-1f, 1f, 0f,
-1f, -1f, 0f,
1f, -1, 0f,
// Right top triangle
1f, -1f, 0f,
1f, 1f, 0f,
-1f, 1f, 0f
};
var buffer = GL.GenBuffer();
var positionLocation = GL.GetAttribLocation(program, "a_position");
GL.EnableVertexAttribArray(positionLocation);
GL.BindBuffer(BufferTarget.ArrayBuffer, buffer);
GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float,false,0,0);
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * sizeof(ushort)), vertices, BufferUsageHint.StaticDraw);
GL.DrawArrays(PrimitiveType.Triangles, 0, vertices.Length);
GL.UseProgram(program);
}
I've researched this for a few days and I'm just completely stuck. Thanks to anyone who can see what I'm doing wrong. It HAS to be something small and dumb on my part!
EDIT: When I remove ALL vertex related code in AddShaders, I get the output I want, except its 1/4 the size and flipped in the top right of the screen. So, somehow my shaders don't even care about the vertices. Why is it being scaled down to 1/4 size and flipped?
EDIT2: Ok so thanks to Robert Rouhani, I've ALMOST got this working! Progress It looks like the triangle vertices might be messed up??
Here's my new code. I refactored functionality into methods, stopped creating programs / buffers every frame, etc. Now I have class level variables to hold the GL specific data, methods to create the GL program for the app, create the shaders, create the buffers, etc. Also I know that the 1920x1080 hardcode is, well, hardcoded. That is on my plate to make dynamic.
string file = "lambo2.png";
int program;
int vertShader;
int fragShader;
int buffer;
int positionLocation;
int texture;
float[] vertices = {
// Left bottom triangle
-1f, -1f, 0f,
1f, -1f, 0f,
1f, 1f, 0f,
// Right top triangle
1f, 1f, 0f,
-1f, 1f, 0f,
-1f, -1f, 0f
};
private void CreateProgram()
{
program = GL.CreateProgram();
GL.AttachShader(program, vertShader);
GL.AttachShader(program, fragShader);
GL.LinkProgram(program);
}
private void CreateShaders()
{
/***********Vert Shader********************/
vertShader = GL.CreateShader(ShaderType.VertexShader);
GL.ShaderSource(vertShader, #"attribute vec3 a_position;
varying vec2 vTexCoord;
void main() {
vTexCoord = (a_position.xy + 1) / 2;
gl_Position = vec4(a_position, 1);
}");
GL.CompileShader(vertShader);
/***********Frag Shader ****************/
fragShader = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(fragShader, #"precision highp float;
uniform sampler2D sTexture;
varying vec2 vTexCoord;
void main ()
{
vec4 color = texture2D (sTexture, vTexCoord);
if(color.r < 0.3){color.r = 1.0;}
// Save the result
gl_FragColor = color;
}");
// GL.ShaderSource(fragShader, System.IO.File.ReadAllText(#"C:\Users\Matt\Desktop\hue-shader-backup.ps"));
GL.CompileShader(fragShader);
}
private void InitBuffers()
{
buffer = GL.GenBuffer();
positionLocation = GL.GetAttribLocation(program, "a_position");
GL.EnableVertexAttribArray(positionLocation);
GL.BindBuffer(BufferTarget.ArrayBuffer, buffer);
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * sizeof(ushort)), vertices, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, 0, 0);
}
private void Init()
{
texture = LoadTexture(file);
CreateShaders();
CreateProgram();
InitBuffers();
}
public int LoadTexture(string file)
{
Bitmap bitmap = new Bitmap(file);
int tex;
GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
GL.GenTextures(1, out tex);
GL.BindTexture(TextureTarget.Texture2D, tex);
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
BitmapData data = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
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.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
return tex;
}
public void DrawImage(int image)
{
GL.Viewport(new Rectangle(0, 0, 1920, 1080));
GL.MatrixMode(MatrixMode.Projection);
GL.PushMatrix();
GL.LoadIdentity();
GL.Ortho(0, 1920, 0, 1080, 0, 1);
GL.MatrixMode(MatrixMode.Modelview);
GL.PushMatrix();
GL.LoadIdentity();
GL.Disable(EnableCap.Lighting);
GL.Enable(EnableCap.Texture2D);
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, image);
GL.Begin(PrimitiveType.Quads);
GL.TexCoord2(0, 1);
GL.Vertex3(0, 0, 0);
GL.TexCoord2(1, 1);
GL.Vertex3(1920, 0, 0);
GL.TexCoord2(1, 0);
GL.Vertex3(1920, 1080, 0);
GL.TexCoord2(0, 0);
GL.Vertex3(0, 1080, 0);
GL.End();
RunShaders();
GL.Disable(EnableCap.Texture2D);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Projection);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Modelview);
ErrorCode ec = GL.GetError();
if (ec != 0)
System.Console.WriteLine(ec.ToString());
Console.Read();
}
private void RunShaders()
{
GL.ClearColor(Color.AliceBlue);
GL.UseProgram(program);
GL.DrawArrays(PrimitiveType.Triangles, 0, vertices.Length / 3);
ErrorCode ec = GL.GetError();
if (ec != 0)
System.Console.WriteLine(ec.ToString());
Console.Read();
}
Going to start an answer instead of continuing the comments. You've still got a few minor issues that are compounding. You should comment out everything between and including GL.Begin and GL.End as the RunShaders function should do draw everything you need to the screen. Also comment out the GL.Ortho line, you don't need it if you're working with the vertices in the [-1, 1] range.
Second, your issue is that you're only uploading half your vertex buffer to the GPU. In InitBuffers on the GL.BufferData line, change sizeof(ushort) to sizeof(float), since your vertices are floats (4 bytes long) and not ushorts (2 bytes long).
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * sizeof(float)), vertices, BufferUsageHint.StaticDraw);
Together this should get your program working.
I working with C# and OpenTK.
Currently I only want to map a texture on a triangle.
It seems to be working but on nearest texture filter, the whole triangle is only colored with the upper left pixel color of the bmp image and if I set the texture filter to linear the triangle shows still only one color, but it seems whether it is now mixed with the other pixels.
Can someone find the error in the code ?
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
GL.Enable(EnableCap.Texture2D);
GL.ClearColor(0.5F, 0.5F, 0.5F, 1.0F);
int vertexShaderHandle = GL.CreateShader(ShaderType.VertexShader);
int fragmentShaderHandle = GL.CreateShader(ShaderType.FragmentShader);
string vertexShaderSource = #"#version 400
layout(location = 0) in vec3 position;
layout(location = 1) in vec2 uv;
out vec2 texture_uv;
void main()
{
gl_Position = vec4(inPosition.xyz, 1);
texture_uv = uv;
}";
string fragmentShaderSource = #"#version 400
in vec2 texture_uv;
out vec3 outColor;
uniform sampler2D uniSampler;
void main()
{
outColor = texture( uniSampler, texture_uv ).rgb;
}";
GL.ShaderSource(vertexShaderHandle, vertexShaderSource);
GL.ShaderSource(fragmentShaderHandle, fragmentShaderSource);
GL.CompileShader(vertexShaderHandle);
GL.CompileShader(fragmentShaderHandle);
prgHandle = GL.CreateProgram();
GL.AttachShader(prgHandle, vertexShaderHandle);
GL.AttachShader(prgHandle, fragmentShaderHandle);
GL.LinkProgram(prgHandle);
GL.DetachShader(prgHandle, vertexShaderHandle);
GL.DetachShader(prgHandle, fragmentShaderHandle);
GL.DeleteShader(vertexShaderHandle);
GL.DeleteShader(fragmentShaderHandle);
uniSamplerLoc = GL.GetUniformLocation(prgHandle, "uniSampler");
texHandle = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, texHandle);
Bitmap bmp = new Bitmap("C:/Users/Michael/Desktop/Test.bmp");
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bmpData.Width, bmpData.Height, 0,
OpenTK.Graphics.OpenGL4.PixelFormat.Bgra, PixelType.UnsignedByte, bmpData.Scan0);
bmp.UnlockBits(bmpData);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
vaoHandle = GL.GenVertexArray();
GL.BindVertexArray(vaoHandle);
vboHandle = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, vboHandle);
float[] bufferData = { 0.5F, 1, 0, 1, 1,
0, 0, 0, 0, 0,
1, 0, 0, 1, 0 };
GL.BufferData<float>(BufferTarget.ArrayBuffer, (IntPtr) (15 * sizeof(float)), bufferData, BufferUsageHint.StaticDraw);
GL.EnableVertexAttribArray(0);
GL.EnableVertexAttribArray(1);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 5 * sizeof(float), 0);
GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float));
}
protected override void OnUnload(EventArgs e)
{
base.OnUnload(e);
GL.DeleteTexture(texHandle);
GL.DeleteProgram(prgHandle);
GL.DeleteBuffer(vboHandle);
GL.DeleteVertexArray(vaoHandle);
}
protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(e);
GL.Clear(ClearBufferMask.ColorBufferBit);
GL.UseProgram(prgHandle);
GL.Uniform1(uniSamplerLoc, texHandle);
GL.BindVertexArray(vaoHandle);
GL.DrawArrays(PrimitiveType.Triangles, 0, 3);
SwapBuffers();
}
EDIT:
I tried this:
protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(e);
GL.Clear(ClearBufferMask.ColorBufferBit);
GL.UseProgram(prgHandle);
GL.BindVertexArray(vaoHandle);
GL.ActiveTexture(TextureUnit.Texture3);
GL.BindTexture(TextureTarget.Texture2D, texHandle);
GL.Uniform1(uniSamplerLoc, 3);
GL.DrawArrays(PrimitiveType.Triangles, 0, 3);
SwapBuffers();
}
But nothing changed :(
The value of a sampler uniform variable needs to be the texture unit it should sample from. In your code, it is set to the texture name (aka texture id, aka texture handle) instead:
GL.Uniform1(uniSamplerLoc, texHandle);
The texture unit can be set with ActiveTexture(). When glBindTexture() is called, the value of the currently active texture unit determines which unit the texture is bound to. The default for the active texture unit is 0. So if you never called ActiveTexture(), the uniform should be set as:
GL.Uniform1(uniSamplerLoc, 0);
Just as a heads-up, another related source of errors is that the value of the uniform is a 0-based index of the texture unit, while the glActiveTexture() call takes an enum starting with GL_TEXTURE0. For example with the C bindings (not sure how exactly this looks with C# and OpenTK, but it should be similar enough), this would bind a texture to texture unit 3, and set a uniform sampler variable to use it:
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, texId);
glUniform1i(texUniformLoc, 3);
Note how GL_TEXTURE3 is used in the argument for glActiveTexture(), but a plain 3 in glUniform1i().
I have a following picture:
Window displays two textures, the left texture is generated by binding it to a FBO and rendering to FBO, 50 random triangles.
The right texture is generated by glTexImage2D with full-color image of Mona Lisa, but as you can see the image is lacking red colors, I think the problem is in OpenGL part, since I've investigated bytes that are passed to glTexImage2D and they do contain Red...
Here is C#/Mono/OpenTK source
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Platform;
using OpenTK.Platform.X11;
using OpenTK.Input;
using ManOCL;
namespace GlTest
{
public class MainClass: GameWindow
{
public MainClass()
: base(800, 600, new GraphicsMode(new ColorFormat(0, 0, 0, 0), 32, 0))
{
this.VSync = VSyncMode.Off;
}
public uint fbo;
public uint textureA;
public uint textureB;
public int textureAWidth = 1024;
public int textureAHeight = 1024;
public int textureBWidth;
public int textureBHeight;
Random rand = new Random();
protected override void OnLoad(EventArgs e)
{
GL.Enable(EnableCap.Blend);
GL.ShadeModel(ShadingModel.Smooth);
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
GL.Disable(EnableCap.DepthTest);
GL.Disable(EnableCap.CullFace);
// GL.PolygonMode(MaterialFace.Back, PolygonMode.Line);
// Create Color Tex
GL.GenTextures(1, out textureA);
GL.BindTexture(TextureTarget.Texture2D, textureA);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8, textureAWidth, textureAHeight, 0, OpenTK.Graphics.OpenGL.PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero);
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.ClampToBorder);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int) TextureWrapMode.ClampToBorder);
GL.GenTextures(1, out textureB);
GL.BindTexture(TextureTarget.Texture2D, textureB);
Bitmap bmp = new Bitmap("/Projects/MonaLisa/MonaLisa.bmp");
Console.WriteLine(textureBWidth = bmp.Width);
Console.WriteLine(textureBHeight = bmp.Height);
//get the data out of the bitmap
System.Drawing.Imaging.BitmapData bmpBits = bmp.LockBits
(
new System.Drawing.Rectangle(0,0,textureBWidth, textureBHeight),
System.Drawing.Imaging.ImageLockMode.ReadOnly,
System.Drawing.Imaging.PixelFormat.Format32bppRgb
);
for (int row = 0; row < 1; row++)
{
for (int col = 0; col < 32; col++)
{
Console.WriteLine
(
"{0}, {1}, {2}, {3}",
Marshal.ReadByte(bmpBits.Scan0, (row * textureBWidth + col) * 4 + 0),
Marshal.ReadByte(bmpBits.Scan0, (row * textureBWidth + col) * 4 + 1),
Marshal.ReadByte(bmpBits.Scan0, (row * textureBWidth + col) * 4 + 2),
Marshal.ReadByte(bmpBits.Scan0, (row * textureBWidth + col) * 4 + 3)
);
}
}
Console.WriteLine(bmpBits.Width);
Console.WriteLine(bmpBits.Height);
GL.TexImage2D
(
TextureTarget.Texture2D,
0,
PixelInternalFormat.Rgba,
textureBWidth,
textureBHeight,
0,
OpenTK.Graphics.OpenGL.PixelFormat.Rgba,
PixelType.UnsignedByte,
bmpBits.Scan0
);
// GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8, textureBWidth, textureBHeight, 0, OpenTK.Graphics.OpenGL.PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero);
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.ClampToBorder);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int) TextureWrapMode.ClampToBorder);
//free the bitmap data (we dont need it anymore because it has been passed to the OpenGL driver
bmp.UnlockBits(bmpBits);
// Create a FBO and attach the textures
GL.Ext.GenFramebuffers(1, out fbo);
GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, fbo);
GL.Ext.FramebufferTexture2D(FramebufferTarget.FramebufferExt, FramebufferAttachment.ColorAttachment0Ext, TextureTarget.Texture2D, textureA, 0);
#region Test for Error
switch (GL.Ext.CheckFramebufferStatus(FramebufferTarget.FramebufferExt))
{
case FramebufferErrorCode.FramebufferCompleteExt:
{
Console.WriteLine("FBO: The framebuffer is complete and valid for rendering.");
break;
}
case FramebufferErrorCode.FramebufferIncompleteAttachmentExt:
{
Console.WriteLine("FBO: One or more attachment points are not framebuffer attachment complete. This could mean there’s no texture attached or the format isn’t renderable. For color textures this means the base format must be RGB or RGBA and for depth textures it must be a DEPTH_COMPONENT format. Other causes of this error are that the width or height is zero or the z-offset is out of range in case of render to volume.");
break;
}
case FramebufferErrorCode.FramebufferIncompleteMissingAttachmentExt:
{
Console.WriteLine("FBO: There are no attachments.");
break;
}
/* case FramebufferErrorCode.GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
{
Console.WriteLine("FBO: An object has been attached to more than one attachment point.");
break;
}*/
case FramebufferErrorCode.FramebufferIncompleteDimensionsExt:
{
Console.WriteLine("FBO: Attachments are of different size. All attachments must have the same width and height.");
break;
}
case FramebufferErrorCode.FramebufferIncompleteFormatsExt:
{
Console.WriteLine("FBO: The color attachments have different format. All color attachments must have the same format.");
break;
}
case FramebufferErrorCode.FramebufferIncompleteDrawBufferExt:
{
Console.WriteLine("FBO: An attachment point referenced by GL.DrawBuffers() doesn’t have an attachment.");
break;
}
case FramebufferErrorCode.FramebufferIncompleteReadBufferExt:
{
Console.WriteLine("FBO: The attachment point referenced by GL.ReadBuffers() doesn’t have an attachment.");
break;
}
case FramebufferErrorCode.FramebufferUnsupportedExt:
{
Console.WriteLine("FBO: This particular FBO configuration is not supported by the implementation.");
break;
}
default:
{
Console.WriteLine("FBO: Status unknown. (yes, this is really bad.)");
break;
}
}
// using FBO might have changed states, e.g. the FBO might not support stereoscopic views or double buffering
int[] queryinfo = new int[6];
GL.GetInteger(GetPName.MaxColorAttachmentsExt, out queryinfo[0]);
GL.GetInteger(GetPName.AuxBuffers, out queryinfo[1]);
GL.GetInteger(GetPName.MaxDrawBuffers, out queryinfo[2]);
GL.GetInteger(GetPName.Stereo, out queryinfo[3]);
GL.GetInteger(GetPName.Samples, out queryinfo[4]);
GL.GetInteger(GetPName.Doublebuffer, out queryinfo[5]);
Console.WriteLine("max. ColorBuffers: " + queryinfo[0] + " max. AuxBuffers: " + queryinfo[1] + " max. DrawBuffers: " + queryinfo[2] +
"\nStereo: " + queryinfo[3] + " Samples: " + queryinfo[4] + " DoubleBuffer: " + queryinfo[5]);
Console.WriteLine("Last GL Error: " + GL.GetError());
#endregion Test for Error
GL.PushAttrib(AttribMask.ViewportBit);
{
GL.Viewport(0, 0, textureAWidth, textureAHeight);
OpenTK.Matrix4 orthogonal = OpenTK.Matrix4.CreateOrthographicOffCenter(0, 1, 0, 1, -3, 3);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadMatrix(ref orthogonal);
Matrix4 lookat = Matrix4.LookAt(0, 0, 1, 0, 0, 0, 0, 1, 0);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadMatrix(ref lookat);
// clear the screen in red, to make it very obvious what the clear affected. only the FBO, not the real framebuffer
GL.ClearColor(0f, 0f, 0f, 0f);
GL.Clear(ClearBufferMask.ColorBufferBit);
// smack 50 random triangles into the FBO's textures
GL.Begin(BeginMode.Triangles);
{
for (int i = 0; i < 50; i++)
{
GL.Color4(((float)(rand.NextDouble())), ((float)(rand.NextDouble())), ((float)(rand.NextDouble())), ((float)(rand.NextDouble())));
GL.Vertex3(((float)(rand.NextDouble())), ((float)(rand.NextDouble())), 0);
GL.Color4(((float)(rand.NextDouble())), ((float)(rand.NextDouble())), ((float)(rand.NextDouble())), ((float)(rand.NextDouble())));
GL.Vertex3(((float)(rand.NextDouble())), ((float)(rand.NextDouble())), 0);
GL.Color4(((float)(rand.NextDouble())), ((float)(rand.NextDouble())), ((float)(rand.NextDouble())), ((float)(rand.NextDouble())));
GL.Vertex3(((float)(rand.NextDouble())), ((float)(rand.NextDouble())), 0);
}
}
GL.End();
}
GL.PopAttrib();
GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0); // disable rendering into the FBO
GL.ClearColor(1f, 1f, 1f, 0.0f);
GL.Color3(1f, 1f, 1f);
GL.Enable(EnableCap.Texture2D); // enable Texture Mapping
GL.BindTexture(TextureTarget.Texture2D, 0); // bind default texture
// IntPtr cglContext = Monobjc.OpenGL.CGL.GetCurrentContext();
//
// IntPtr cglShareGroup = Monobjc.OpenGL.CGL.GetShareGroup(cglContext);
//
// ManOCL.Context.ShareWithCGL(cglShareGroup);
//
// Kernel kernel = ManOCL.Kernel.Create
// (
// "kernel1",
// #"__kernel void kernel1(__global int *srcimg, __global int * output, __global int *smp)
// {
// }",
// new Argument[]
// {
// DeviceGlobalMemory.CreateFromArray(new int[1]),
// DeviceGlobalMemory.CreateFromArray(new int[2]),
// DeviceGlobalMemory.CreateFromArray(new int[1])
// }
// );
// Console.WriteLine("Success!");
// Console.WriteLine(kernel);
}
protected override void OnUnload(EventArgs e)
{
// Clean up what we allocated before exiting
GL.DeleteTextures(1, ref textureA);
GL.DeleteTextures(1, ref textureB);
GL.Ext.DeleteFramebuffers(1, ref fbo);
base.OnUnload(e);
}
protected override void OnResize (EventArgs e)
{
GL.Viewport(0, 0, Width, Height);
double aspect_ratio = Width / (double)Height;
OpenTK.Matrix4 perspective = OpenTK.Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4 * 3 / 2, (float)aspect_ratio, 1, 64);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadMatrix(ref perspective);
Matrix4 lookat = Matrix4.LookAt(0, 0, 3, 0, 0, 0, 0, 1, 0);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadMatrix(ref lookat);
base.OnResize(e);
}
protected override void OnUpdateFrame (FrameEventArgs e)
{
base.OnUpdateFrame(e);
if (Keyboard[Key.Escape])
{
this.Exit();
}
}
protected override void OnRenderFrame(FrameEventArgs e)
{
this.Title = "Frames per Second: " + (1.0 / e.Time);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.PushMatrix();
{
// Draw the Color Texture
GL.Translate(-1f, 0f, 0f);
GL.BindTexture(TextureTarget.Texture2D, textureA);
GL.Begin(BeginMode.Quads);
{
GL.TexCoord2(0f, 1f);
GL.Vertex2(-1.0f, 1.0f);
GL.TexCoord2(0.0f, 0.0f);
GL.Vertex2(-1.0f, -1.0f);
GL.TexCoord2(1.0f, 0.0f);
GL.Vertex2(1.0f, -1.0f);
GL.TexCoord2(1.0f, 1.0f);
GL.Vertex2(1.0f, 1.0f);
}
GL.End();
GL.Translate(2f, 0f, 0f);
GL.BindTexture(TextureTarget.Texture2D, textureB);
GL.Begin(BeginMode.Quads);
{
GL.TexCoord2(0f, 0f);
GL.Vertex2(-1.0f, 1.0f);
GL.TexCoord2(0.0f, 1.0f);
GL.Vertex2(-1.0f, -1.0f);
GL.TexCoord2(1.0f, 1.0f);
GL.Vertex2(1.0f, -1.0f);
GL.TexCoord2(1.0f, 0.0f);
GL.Vertex2(1.0f, 1.0f);
}
GL.End();
GL.Translate(0f, 0f, 0f);
}
GL.PopMatrix();
this.SwapBuffers();
}
#region public static void Main()
/// <summary>
/// Entry point of this example.
/// </summary>
[STAThread]
public static void Main()
{
using (MainClass example = new MainClass())
{
example.Title = "FrameBufferObjects";
example.Run(1.0, 0.0);
}
}
#endregion
}
}
In the bit of code where you set your texture data:
GL.TexImage2D
(
TextureTarget.Texture2D,
0,
PixelInternalFormat.Rgba,
textureBWidth,
textureBHeight,
0,
OpenTK.Graphics.OpenGL.PixelFormat.Rgba,
PixelType.UnsignedByte,
bmpBits.Scan0
);
Change your pixel format to
OpenTK.Graphics.OpenGL.PixelFormat.Bgra;
Windows bitmaps and opengl have a different endianess on pixels i.e. the bytes are reversed.