hi
i'm trying to load a texture (.bmp image) ...
with debugging i see it has been loaded ... but on the screen nothing appear!
here is my code :
int front_ID = Terrain.LoadGLTextures(#"C:\Users\Ruba\Desktop\our project graphic2\our project graphic\images\top.bmp");
int back_ID = Terrain.LoadGLTextures(#"C:\Users\Ruba\Desktop\our project graphic2\our project graphic\images\top.bmp");
int right_ID = Terrain.LoadGLTextures(#"C:\Users\Ruba\Desktop\our project graphic2\our project graphic\images\top.bmp");
int left_ID = Terrain.LoadGLTextures(#"C:\Users\Ruba\Desktop\our project graphic2\our project graphic\images\top.bmp");
int top_ID = Terrain.LoadGLTextures(#"C:\Users\Ruba\Desktop\our project graphic2\our project graphic\images\top.bmp");
int down_ID = Terrain.LoadGLTextures(#"C:\Users\Ruba\Desktop\our project graphic2\our project graphic\images\top.bmp");
Terrain.draw_skybox(520, front_ID, back_ID, right_ID, left_ID, top_ID, down_ID);
and the method (draw_skybox) :
public static void draw_skybox(float size, int front, int back, int right, int left, int up, int bottom)
{
float scale = 1; // important
Gl.glPushMatrix();
Gl.glScalef(size, size, size);
//Front Face
//Gl.glEnable(Gl.GL_CULL_FACE);
Gl.glCullFace(Gl.GL_BACK);
Gl.glBindTexture(Gl.GL_TEXTURE_2D, front);
Gl.glBegin(Gl.GL_QUADS);
Gl.glNormal3f(0, 0, 1);
Gl.glTexCoord2d(0, 0); Gl.glVertex3f(-0.5f, -0.5f, -0.5f);
Gl.glTexCoord2d(1, 0); Gl.glVertex3f(0.5f, -0.5f, -0.5f);
Gl.glTexCoord2d(1, 1); Gl.glVertex3f(0.5f, 0.5f, -0.5f);
Gl.glTexCoord2d(0, 1); Gl.glVertex3f(-0.5f, 0.5f, -0.5f);
Gl.glEnd();
//Gl.glCullFace(Gl.GL_BACK);
// Gl.glDisable(Gl.GL_CULL_FACE);
//Back Face
Gl.glBindTexture(Gl.GL_TEXTURE_2D, back);
Gl.glBegin(Gl.GL_QUADS);
Gl.glNormal3f(0, 0, -1);
Gl.glTexCoord2d(1, 0); Gl.glVertex3f(-0.5f, -0.5f, 0.5f);
Gl.glTexCoord2d(0, 0); Gl.glVertex3f(0.5f, -0.5f, 0.5f);
Gl.glTexCoord2d(0, 1); Gl.glVertex3f(0.5f, 0.5f, 0.5f);
Gl.glTexCoord2d(1, 1); Gl.glVertex3f(-0.5f, 0.5f, 0.5f);
Gl.glEnd();
//right face
Gl.glBindTexture(Gl.GL_TEXTURE_2D, right);
Gl.glBegin(Gl.GL_QUADS);
Gl.glNormal3f(1, 0, 0);
Gl.glTexCoord2d(0, 0); Gl.glVertex3f(0.5f, -0.5f, -0.5f);
Gl.glTexCoord2d(0, 1); Gl.glVertex3f(0.5f, 0.5f, -0.5f);
Gl.glTexCoord2d(1, 1); Gl.glVertex3f(0.5f, 0.5f, 0.5f);
Gl.glTexCoord2d(1, 0); Gl.glVertex3f(0.5f, -0.5f, 0.5f);
Gl.glEnd();
//Left Face
Gl.glBindTexture(Gl.GL_TEXTURE_2D, left);
Gl.glBegin(Gl.GL_QUADS);
Gl.glNormal3f(-1, 0, 0);
Gl.glTexCoord2d(1, 0); Gl.glVertex3f(-0.5f, -0.5f, -0.5f);
Gl.glTexCoord2d(1, 1); Gl.glVertex3f(-0.5f, 0.5f, -0.5f);
Gl.glTexCoord2d(0, 1); Gl.glVertex3f(-0.5f, 0.5f, 0.5f);
Gl.glTexCoord2d(0, 0); Gl.glVertex3f(-0.5f, -0.5f, 0.5f);
Gl.glEnd();
//Top Face
Gl.glBindTexture(Gl.GL_TEXTURE_2D, up);
Gl.glBegin(Gl.GL_QUADS);
Gl.glNormal3f(0, 1, 0);
Gl.glTexCoord2d(0, 0); Gl.glVertex3f(-0.5f, 0.5f, -0.5f);
Gl.glTexCoord2d(1, 0); Gl.glVertex3f(0.5f, 0.5f, -0.5f);
Gl.glTexCoord2d(1, 1); Gl.glVertex3f(0.5f, 0.5f, 0.5f);
Gl.glTexCoord2d(0, 1); Gl.glVertex3f(-0.5f, 0.5f, 0.5f);
Gl.glEnd();
//Bottom Face
Gl.glBindTexture(Gl.GL_TEXTURE_2D, bottom);
Gl.glBegin(Gl.GL_QUADS);
Gl.glNormal3f(0, -1, 0);
Gl.glTexCoord2d(0, 0); Gl.glVertex3f(-0.5f, -0.5f, -0.5f);
Gl.glTexCoord2d(1, 0); Gl.glVertex3f(0.5f, -0.5f, -0.5f);
Gl.glTexCoord2d(1, 1); Gl.glVertex3f(0.5f, -0.5f, 0.5f);
Gl.glTexCoord2d(0, 1); Gl.glVertex3f(-0.5f, -0.5f, 0.5f);
Gl.glEnd();
Gl.glPopMatrix();
}
public static void draw_skybox(float size, int front, int back, int right, int left, int up, int bottom)
{
float scale = 1; // important
Gl.glPushMatrix();
Gl.glScalef(size, size, size);
//Front Face
//Gl.glEnable(Gl.GL_CULL_FACE);
//Gl.glCullFace(Gl.GL_BACK);
Gl.glBindTexture(Gl.GL_TEXTURE_2D, front);
Gl.glBegin(Gl.GL_QUADS);
Gl.glNormal3f(0, 0, 1);
Gl.glTexCoord2d(0, 0); Gl.glVertex3f(-0.5f, -0.5f, -0.5f);
Gl.glTexCoord2d(1, 0); Gl.glVertex3f(0.5f, -0.5f, -0.5f);
Gl.glTexCoord2d(1, 1); Gl.glVertex3f(0.5f, 0.5f, -0.5f);
Gl.glTexCoord2d(0, 1); Gl.glVertex3f(-0.5f, 0.5f, -0.5f);
Gl.glEnd();
//Gl.glCullFace(Gl.GL_BACK);
// Gl.glDisable(Gl.GL_CULL_FACE);
//Back Face
Gl.glBindTexture(Gl.GL_TEXTURE_2D, back);
Gl.glBegin(Gl.GL_QUADS);
Gl.glNormal3f(0, 0, -1);
Gl.glTexCoord2d(1, 0); Gl.glVertex3f(-0.5f, -0.5f, 0.5f);
Gl.glTexCoord2d(0, 0); Gl.glVertex3f(0.5f, -0.5f, 0.5f);
Gl.glTexCoord2d(0, 1); Gl.glVertex3f(0.5f, 0.5f, 0.5f);
Gl.glTexCoord2d(1, 1); Gl.glVertex3f(-0.5f, 0.5f, 0.5f);
Gl.glEnd();
//right face
Gl.glBindTexture(Gl.GL_TEXTURE_2D, right);
Gl.glBegin(Gl.GL_QUADS);
Gl.glNormal3f(1, 0, 0);
Gl.glTexCoord2d(0, 0); Gl.glVertex3f(0.5f, -0.5f, -0.5f);
Gl.glTexCoord2d(0, 1); Gl.glVertex3f(0.5f, 0.5f, -0.5f);
Gl.glTexCoord2d(1, 1); Gl.glVertex3f(0.5f, 0.5f, 0.5f);
Gl.glTexCoord2d(1, 0); Gl.glVertex3f(0.5f, -0.5f, 0.5f);
Gl.glEnd();
//Left Face
Gl.glBindTexture(Gl.GL_TEXTURE_2D, left);
Gl.glBegin(Gl.GL_QUADS);
Gl.glNormal3f(-1, 0, 0);
Gl.glTexCoord2d(1, 0); Gl.glVertex3f(-0.5f, -0.5f, -0.5f);
Gl.glTexCoord2d(1, 1); Gl.glVertex3f(-0.5f, 0.5f, -0.5f);
Gl.glTexCoord2d(0, 1); Gl.glVertex3f(-0.5f, 0.5f, 0.5f);
Gl.glTexCoord2d(0, 0); Gl.glVertex3f(-0.5f, -0.5f, 0.5f);
Gl.glEnd();
//Top Face
Gl.glBindTexture(Gl.GL_TEXTURE_2D, up);
Gl.glBegin(Gl.GL_QUADS);
Gl.glNormal3f(0, 1, 0);
Gl.glTexCoord2d(0, 0); Gl.glVertex3f(-0.5f, 0.5f, -0.5f);
Gl.glTexCoord2d(1, 0); Gl.glVertex3f(0.5f, 0.5f, -0.5f);
Gl.glTexCoord2d(1, 1); Gl.glVertex3f(0.5f, 0.5f, 0.5f);
Gl.glTexCoord2d(0, 1); Gl.glVertex3f(-0.5f, 0.5f, 0.5f);
Gl.glEnd();
//Bottom Face
Gl.glBindTexture(Gl.GL_TEXTURE_2D, bottom);
Gl.glBegin(Gl.GL_QUADS);
Gl.glNormal3f(0, -1, 0);
Gl.glTexCoord2d(0, 0); Gl.glVertex3f(-0.5f, -0.5f, -0.5f);
Gl.glTexCoord2d(1, 0); Gl.glVertex3f(0.5f, -0.5f, -0.5f);
Gl.glTexCoord2d(1, 1); Gl.glVertex3f(0.5f, -0.5f, 0.5f);
Gl.glTexCoord2d(0, 1); Gl.glVertex3f(-0.5f, -0.5f, 0.5f);
Gl.glEnd();
Gl.glPopMatrix();
}
please help me
A few things you should check.
Is Texturing enabled?
Gl.glEnable(Gl.GL_TEXTURE_2D);
Are you calling Gl.glGenTextures(...) and Gl.glTexImage2D(...) inside Terrain.LoadGLTextures(...); ?
The winding order of the back, right & bottom quads is wrong. The winding must be counter clock wise. Since you're enabling culling, those quads won't be seen from inside the cube volume. Just swap the first & second vertices, and the third & fourth.
Make sure you're viewing the scene from inside the volume.
Do you really want to use the Tao Framework? The Tao Framework hasn't been updated since may 2008 and is effectivaly defunct since july 2010. Perhaps you should take a look at the OpenTK Framework: http://www.opentk.com/
Related
I am trying to draw a wire cube (edges only) using ElementBufferObject. I have set the coordinates of the eight vertices of the cube and an array of indices. Next, I initialize VAO, VBO and EBO for the future cube. Then I try to draw it, but I don't see any result.
Cube vertices and indices:
private readonly float[] _cubeVertices =
{
// Bottom side
-0.5f, -0.5f, 0.0f, // [0] Front-left
0.5f, -0.5f, 0.0f, // [1] Front-right
-0.5f, -0.5f, -1.0f, // [2] Rear-left
0.5f, -0.5f, -1.0f, // [3] Rear-right
// Upper side
-0.5f, 0.5f, 0.0f, // [4] Front-left
0.5f, 0.5f, 0.0f, // [5] Front-right
-0.5f, 0.5f, -1.0f, // [6] Rear-left
0.5f, 0.5f, -1.0f // [7] Rear-right
};
//indices
private readonly uint[] _cubeEdges =
{
0, 1,
0, 2,
0, 4,
3, 2,
3, 1,
3, 7,
5, 6,
5, 4,
5, 1,
6, 7,
6, 4,
6, 2
};
onLoad():
_cubeShader = new Shader("../../../Shaders/cubeShader.vert", "../../../Shaders/shader.frag");
_cubeShader.Use();
_vboCube = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, _vboCube);
GL.BufferData(BufferTarget.ArrayBuffer, _cubeVertices.Length * sizeof(float), _cubeVertices, BufferUsageHint.StaticDraw);
_vaoCube = GL.GenVertexArray();
GL.BindVertexArray(_vaoCube);
var vertexLocation = _cubeShader.GetAttribLocation("aPosition");
GL.VertexAttribPointer(vertexLocation, 3, VertexAttribPointerType.Float, false, 3 * sizeof(float), 0);
_eboCube = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ElementArrayBuffer, _eboCube);
GL.BufferData(BufferTarget.ElementArrayBuffer, _cubeEdges.Length * sizeof(uint), _cubeEdges, BufferUsageHint.StaticDraw);
Actual drawing:
_cubeShader.Use();
GL.BindVertexArray(_vaoCube);
//GL.LineWidth(2.0f);
GL.DrawElements(PrimitiveType.Lines, _cubeEdges.Length, DrawElementsType.UnsignedInt, 0);
cubeShader.vert:
#version 330 core
in vec3 aPosition;
void main(void)
{
gl_Position = vec4(aPosition, 1.0);
}
shader.frag:
#version 330 core
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0);
}
Shader.cs code you can find here GitHub.
Actually, all my code based on LearnOpenTK repo
This is my first introduction to OpenGL, so most likely I'm missing something important in the process. Is it even possible to draw lines using EBO? I have already tried the same thing with triangles and everything worked out.
I figured it out. I forgot the line
GL.EnableVertexAttribArray(vertex Location);
after calling
GL.vertexAttribPointer()
My app is displaying an image in full screen by using OpenGL shader code as shown below. The vertex shader I used here is copied from somewhere. Can anyone explain why here used vTexCoord = (a_position.xy+1)/2;? When I'm trying with vTexCoord = a_position.xy, my OpenGL output is split into four rectangles and only it's top right portion is showing the image. Other three sides are seem as blurred. What change should I do to work it with vTexCoord = a_position.xy ?
Some important functions used in the project are shown below. Please check and help to correct.
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 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);
gl_FragColor =color;
}");
GL.CompileShader(fragShader);
}
private void InitBuffers()
{
buffer = GL.GenBuffer();
positionLocation = GL.GetAttribLocation(program, "a_position");
positionLocation1 = GL.GetUniformLocation(program, "sTexture");
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 void DrawImage(int image)
{
GL.Viewport(new Rectangle(0, 0, ScreenWidth, ScreenHeight));
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.Uniform1(positionLocation1, 0);
GL.Begin(PrimitiveType.Quads);
GL.TexCoord2(0, 1);
GL.Vertex3(0, 0, 0);
GL.TexCoord2(0, 0);
GL.Vertex3(1920, 0, 0);
GL.TexCoord2(1, 1);
GL.Vertex3(1920, 1080, 0);
GL.TexCoord2(1, 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);
glControl1.SwapBuffers();
}
private void RunShaders()
{
GL.UseProgram(program);
GL.DrawArrays(PrimitiveType.Triangles, 0, vertices.Length / 3);
}
Can anyone explain why here used vTexCoord = (a_position.xy+1)/2;?
The vertex coordinates in you example are in range [-1, 1], for the x and component. This matches to the normalized device space. The normalized device space is a cube from the left-lower-front (-1, -1, -1), to the right-top-back (1, 1, 1), this is the area wich is "visible". This area is mapped to the viewport.
This causes that the vertex coordinates, in your example, form a rectangle, which covers the entire viewport.
If the texture coordinates should wrap the entire texture to the quad, then the texture coordinates (u, v) have to be in range [0, 1]. (0, 0) is the lower left of the texture and (1, 1) the upper right.
See also How do OpenGL texture coordinates work?
So the x and y component of a_position have to be mapped form the range [-1, 1], to the range [0, 1], to be used as uv coordinates for the texture lookup:
u = (a_position.x + 1) / 2
v = (a_position.y + 1) / 2
What change should I do to work it with vTexCoord = a_position.xy?
This is not possible, but you can generate a separate texture coordinate attribute, which is common:
attribute vec3 a_position;
attribute vec2 a_texture;
varying vec2 vTexCoord;
void main() {
vTexCoord = a_texture;
gl_Position = vec4(a_position, 1);
}
float[] vertices = {
// x y z u v
// Left bottom triangle
-1f, -1f, 0f, 0f, 0f
1f, -1f, 0f, 1f, 0f
1f, 1f, 0f, 1f, 1f
// Right top triangle
1f, 1f, 0f, 1f, 1f
-1f, 1f, 0f, 0f, 1f
-1f, -1f, 0f 0f, 0f
};
buffer = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, buffer);
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * sizeof(float)), vertices, BufferUsageHint.StaticDraw);
positionLocation = GL.GetAttribLocation(program, "a_position");
tetureLocation = GL.GetAttribLocation(program, "a_texture");
GL.EnableVertexAttribArray(positionLocation);
GL.EnableVertexAttribArray(tetureLocation);
int stride = sizeof(float) * 5; // 5 because of (x, y, z, u, v)
int offsetUV = sizeof(float) * 3; // 3 because the u and v coordinates are the 4th and 5th coordinate
GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, stride, 0);
GL.VertexAttribPointer(tetureLocation, 2, VertexAttribPointerType.Float, false, stride, (IntPtr)(offsetUV));
I'm going crazy trying to draw some text over an OpenGL window using OpenTK!
I followed some of the tutorials around but I can't make it work, when I enable the texture where the text is drawn, then I just have a white window and the QUAD I'm drawing for test just disappears.
If someone has the time to check the code, it is below. I can also send my test program to check it out faster. Thanks in advance for any help on this.
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using OpenTK.Graphics.OpenGL;
using System.Diagnostics;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
Bitmap textBmp;
int textTexture = -1;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
if (!glControl1.Context.IsCurrent)
{
glControl1.MakeCurrent();
}
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Ortho(0, glControl1.Width, 0, glControl1.Height, -1000, 1000);
GL.Scale(1, 1, 1);
GL.Viewport(0, 0, glControl1.Width, glControl1.Height);
GL.ClearColor(Color.White);
// Better point and line drawing
GL.Hint(HintTarget.PointSmoothHint, HintMode.Nicest);
GL.Hint(HintTarget.LineSmoothHint, HintMode.Nicest);
GL.BlendFunc(BlendingFactorSrc.One, BlendingFactorDest.OneMinusSrcAlpha);
GL.Enable(EnableCap.PointSmooth);
GL.Enable(EnableCap.LineSmooth);
GL.Enable(EnableCap.Blend);
// Hide stuff behind in 3D
GL.Enable(EnableCap.DepthTest);
// Enable the texture
GL.Enable(EnableCap.Texture2D);
// Create Bitmap and OpenGL texture
textBmp = new Bitmap((int)glControl1.Width, (int)glControl1.Height);
textTexture = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, textTexture);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, textBmp.Width, textBmp.Height, 0,
OpenTK.Graphics.OpenGL.PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero);
ErrorCode errorCode = GL.GetError();
Debug.Assert(errorCode == ErrorCode.NoError, "OpenTK error!");
}
private void glControl1_Paint(object sender, PaintEventArgs e)
{
ErrorCode errorCode;
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit);
GL.PushMatrix();
GL.Color3(Color.Black);
GL.Begin(PrimitiveType.Quads);
GL.Vertex3(10, 10, 10);
GL.Vertex3(40, 10, 10);
GL.Vertex3(40, 50, 10);
GL.Vertex3(10, 50, 10);
GL.End();
if (textBmp != null)
{
using (Graphics gfx = Graphics.FromImage(textBmp))
{
gfx.Clear(Color.Transparent);
gfx.DrawString("text", new Font("Arial", 10), Brushes.Black, new PointF(textBmp.Width / 2, textBmp.Height));
}
BitmapData data = textBmp.LockBits(new Rectangle(0, 0, textBmp.Width, textBmp.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, (int)glControl1.Width, (int)glControl1.Height, 0,
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
textBmp.UnlockBits(data);
errorCode = GL.GetError();
Debug.Assert(errorCode == ErrorCode.NoError, "OpenTK error!");
GL.Begin(PrimitiveType.Quads);
GL.TexCoord2(0f, 1f); GL.Vertex2(0f, 0f);
GL.TexCoord2(1f, 1f); GL.Vertex2(1f, 0f);
GL.TexCoord2(1f, 0f); GL.Vertex2(1f, 1f);
GL.TexCoord2(0f, 0f); GL.Vertex2(0f, 1f);
GL.End();
}
errorCode = GL.GetError();
Debug.Assert(errorCode == ErrorCode.NoError, "OpenTK error!");
glControl1.SwapBuffers();
}
}
}
Ok, I finally managed to make it work.
On initialization I just did:
if (!control.Context.IsCurrent)
{
control.MakeCurrent();
}
GL.Ortho(0, controlWidth, 0, controlHeight, -1000, 1000);
GL.Scale(1, -1, 1); // I work with a top/left image and openGL is bottom/left
GL.Viewport(0, 0, controlWidth, controlHeight);
GL.ClearColor(Color.White);
GL.Hint(HintTarget.PointSmoothHint, HintMode.Nicest);
GL.Hint(HintTarget.LineSmoothHint, HintMode.Nicest);
GL.BlendFunc(BlendingFactorSrc.One, BlendingFactorDest.OneMinusSrcAlpha);
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
GL.PolygonMode(MaterialFace.Front, PolygonMode.Line);
GL.Enable(EnableCap.PointSmooth);
GL.Enable(EnableCap.LineSmooth);
GL.Enable(EnableCap.Blend);
GL.Enable(EnableCap.DepthTest);
GL.ShadeModel(ShadingModel.Smooth);
GL.Enable(EnableCap.AutoNormal);
bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
gfx = Graphics.FromImage(bmp);
gfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
texture = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, texture);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bmp.Width, bmp.Height, 0,
OpenTK.Graphics.OpenGL.PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero);
Then to write text in the bitmap:
gfx.DrawString(text, font, brush, new PointF(x, y));
And to render:
if (!control.Context.IsCurrent)
{
control.MakeCurrent();
}
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.MatrixMode(MatrixMode.Modelview);
GL.Enable(EnableCap.Texture2D);
GL.BindTexture(TextureTarget.Texture2D, Texture);
GL.Begin(PrimitiveType.Quads);
GL.TexCoord3(0.0f, 0.0f, 0f); GL.Vertex3(0f, 0f, 0f);
GL.TexCoord3(1.0f, 0.0f, 0f); GL.Vertex3(realWidth, 0f, 0f);
GL.TexCoord3(1.0f, 1.0f, 0f); GL.Vertex3(realWidth, realHeight, 0f);
GL.TexCoord3(0.0f, 1.0f, 0f); GL.Vertex3(0f, realHeight, 0f);
GL.End();
GL.Disable(EnableCap.Texture2D);
control.SwapBuffers();
That did the trick.
Very important (at least I think it is):
- the GL.Enable(EnableCap.Texture2D) just before rendering the quad with the texture and GL.Disable(EnableCap.Texture2D) afterwords.
- the GL.BindTexture(TextureTarget.Texture2D, Texture) after enabling GL.Enable(EnableCap.Texture2D).
Hope this helps someone. If I manage to have some time I'll make a C# class with it and post it here.
I am having issues drawing a texture onto my quad but it remains white. I have looked through a number of guides and I don't seem to be doing anything different from them.
To load the texture:
Bitmap bitmap = new Bitmap("Textures/Sprite_Can.png");
GL.GenTextures(1, out textureID);
GL.BindTexture(TextureTarget.Texture2D, textureID);
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);
Setup and apply an orthographic projection:
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Ortho(0, control.Width, 0, control.Height, -1, 1);
GL.Viewport(0, 0, control.Width, control.Height);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadIdentity();
GL.ClearColor(Color4.CornflowerBlue);
And finally the draw:
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.LoadIdentity();
GL.Translate(30, 30, 0);
GL.BindTexture(TextureTarget.Texture2D, textureID);
GL.Begin(BeginMode.Quads);
GL.TexCoord2(0, 0);
GL.Vertex2(-1 * width / 2, 1 * height / 2);
GL.TexCoord2(1, 0);
GL.Vertex2(1 * width / 2, 1 * height / 2);
GL.TexCoord2(1, 1);
GL.Vertex2(1 * width / 2, -1 * height / 2);
GL.TexCoord2(0, 1);
GL.Vertex2(-1 * width / 2, -1 * height / 2);
GL.End();
GL.Flush();
control.SwapBuffers();
So basically, the quad draws just fine. However, the texture is not rendered. As a result, all I have is just a white square.
In the fixed-function OpenGL pipeline, you must also Enable texture units before a texture bound to one will be applied to anything you draw.
The normal OpenGL API binding for this is glEnable (GL_TEXTURE_2D). The OpenTK equivalent would be: GL.Enable (EnableCap.Texture2D).
i am using C# (visual studio 2008) to develop a slot machine,
using OpenTK for using openGL in my project
we have done the basic functionality but the we cant get a code to draw a cube that can rotate.
THe cude needs to rotate for some time, but i cant figure out how to do it.
we have tried this Cube
but this we want to draw it on a form
OpenTK provides a Windows Forms control called GLControl. It has no built-in main loop, but getting continuous rendering to work on the control isn't that hard if you follow this GLControl tutorial.
Once you have continuous rendering working, you can move over the code to render a cube and it will be continuously rotating on a form.
Here is an example of a rotating cube in C# using OpenTK:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;
// adapted from : dreamstatecoding.blogspot.com
namespace RotatingCube
{
public struct Vertex
{
public const int Size = (4 + 4) * 4; // size of struct in bytes
private readonly Vector4 _position;
private readonly Color4 _color;
public Vertex(Vector4 position, Color4 color)
{
_position = position;
_color = color;
}
}
public sealed class MainWindow : GameWindow
{
private readonly string _title;
private int _width;
private int _height;
private int _program;
private double _time;
private bool _initialized;
private int _vertexArray;
private int _buffer;
private int _verticeCount;
private Matrix4 _model;
private Matrix4 _view;
private Matrix4 _projection;
private float _FOV = 45.0f;
private float _lastTimestamp = Stopwatch.GetTimestamp();
private float _freq = Stopwatch.Frequency;
private float _angle;
public MainWindow()
: base(750, // initial width
500, // initial height
GraphicsMode.Default,
"", // initial title
GameWindowFlags.Default,
DisplayDevice.Default,
3, // OpenGL major version
3, // OpenGL minor version
GraphicsContextFlags.ForwardCompatible)
{
_width = 750;
_height = 500;
_title += "Spinning Cube, OpenGL Version: " + GL.GetString(StringName.Version);
}
protected override void OnLoad(EventArgs e)
{
_model = Matrix4.Identity;
Vertex[] vertices =
{
new Vertex(new Vector4(-0.5f, -0.5f, -0.5f, 1.0f), Color4.Blue),
new Vertex(new Vector4( 0.5f, -0.5f, -0.5f, 1.0f), Color4.Blue),
new Vertex(new Vector4( 0.5f, 0.5f, -0.5f, 1.0f), Color4.Blue),
new Vertex(new Vector4( 0.5f, 0.5f, -0.5f, 1.0f), Color4.Blue),
new Vertex(new Vector4(-0.5f, 0.5f, -0.5f, 1.0f), Color4.Blue),
new Vertex(new Vector4(-0.5f, -0.5f, -0.5f, 1.0f), Color4.Blue),
new Vertex(new Vector4(-0.5f, -0.5f, 0.5f, 1.0f), Color4.Blue),
new Vertex(new Vector4( 0.5f, -0.5f, 0.5f, 1.0f), Color4.Blue),
new Vertex(new Vector4( 0.5f, 0.5f, 0.5f, 1.0f), Color4.Blue),
new Vertex(new Vector4( 0.5f, 0.5f, 0.5f, 1.0f), Color4.Blue),
new Vertex(new Vector4(-0.5f, 0.5f, 0.5f, 1.0f), Color4.Blue),
new Vertex(new Vector4(-0.5f, -0.5f, 0.5f, 1.0f), Color4.Blue),
new Vertex(new Vector4(-0.5f, 0.5f, 0.5f, 1.0f), Color4.Red),
new Vertex(new Vector4(-0.5f, 0.5f, -0.5f, 1.0f), Color4.Red),
new Vertex(new Vector4(-0.5f, -0.5f, -0.5f, 1.0f), Color4.Red),
new Vertex(new Vector4(-0.5f, -0.5f, -0.5f, 1.0f), Color4.Red),
new Vertex(new Vector4(-0.5f, -0.5f, 0.5f, 1.0f), Color4.Red),
new Vertex(new Vector4(-0.5f, 0.5f, 0.5f, 1.0f), Color4.Red),
new Vertex(new Vector4( 0.5f, 0.5f, 0.5f, 1.0f), Color4.Red),
new Vertex(new Vector4( 0.5f, 0.5f, -0.5f, 1.0f), Color4.Red),
new Vertex(new Vector4( 0.5f, -0.5f, -0.5f, 1.0f), Color4.Red),
new Vertex(new Vector4( 0.5f, -0.5f, -0.5f, 1.0f), Color4.Red),
new Vertex(new Vector4( 0.5f, -0.5f, 0.5f, 1.0f), Color4.Red),
new Vertex(new Vector4( 0.5f, 0.5f, 0.5f, 1.0f), Color4.Red),
new Vertex(new Vector4(-0.5f, -0.5f, -0.5f, 1.0f), Color4.Green),
new Vertex(new Vector4( 0.5f, -0.5f, -0.5f, 1.0f), Color4.Green),
new Vertex(new Vector4( 0.5f, -0.5f, 0.5f, 1.0f), Color4.Green),
new Vertex(new Vector4( 0.5f, -0.5f, 0.5f, 1.0f), Color4.Green),
new Vertex(new Vector4(-0.5f, -0.5f, 0.5f, 1.0f), Color4.Green),
new Vertex(new Vector4(-0.5f, -0.5f, -0.5f, 1.0f), Color4.Green),
new Vertex(new Vector4(-0.5f, 0.5f, -0.5f, 1.0f), Color4.Green),
new Vertex(new Vector4( 0.5f, 0.5f, -0.5f, 1.0f), Color4.Green),
new Vertex(new Vector4( 0.5f, 0.5f, 0.5f, 1.0f), Color4.Green),
new Vertex(new Vector4( 0.5f, 0.5f, 0.5f, 1.0f), Color4.Green),
new Vertex(new Vector4(-0.5f, 0.5f, 0.5f, 1.0f), Color4.Green),
new Vertex(new Vector4(-0.5f, 0.5f, -0.5f, 1.0f), Color4.Green),
};
_verticeCount = vertices.Length;
_vertexArray = GL.GenVertexArray();
_buffer = GL.GenBuffer();
GL.BindVertexArray(_vertexArray);
GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexArray);
// create first buffer: vertex
GL.NamedBufferStorage(
_buffer,
Vertex.Size*vertices.Length, // the size needed by this buffer
vertices, // data to initialize with
BufferStorageFlags.MapWriteBit); // at this point we will only write to the buffer
GL.VertexArrayAttribBinding(_vertexArray, 0, 0);
GL.EnableVertexArrayAttrib(_vertexArray, 0);
GL.VertexArrayAttribFormat(
_vertexArray,
0, // attribute index, from the shader location = 0
4, // size of attribute, vec4
VertexAttribType.Float, // contains floats
false, // does not need to be normalized as it is already, floats ignore this flag anyway
0); // relative offset, first item
GL.VertexArrayAttribBinding(_vertexArray, 1, 0);
GL.EnableVertexArrayAttrib(_vertexArray, 1);
GL.VertexArrayAttribFormat(
_vertexArray,
1, // attribute index, from the shader location = 1
4, // size of attribute, vec4
VertexAttribType.Float, // contains floats
false, // does not need to be normalized as it is already, floats ignore this flag anyway
16); // relative offset after a vec4
// link the vertex array and buffer and provide the stride as size of Vertex
GL.VertexArrayVertexBuffer(_vertexArray, 0, _buffer, IntPtr.Zero, Vertex.Size);
_initialized = true;
CursorVisible = true;
try
{
_program = GL.CreateProgram();
var shaders = new List<int>();
ShaderType type = ShaderType.VertexShader;
var shader = GL.CreateShader(type);
string src = #"#version 330 core
layout (location = 0) in vec4 position;
layout(location = 1) in vec4 color;
out vec4 vs_color;
out vec3 original_normal;
out vec3 transformed_normal;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main(void)
{
gl_Position = projection * view * model * position;
vs_color = color;
original_normal = vec3(color);
mat3 normal_matrix = transpose(inverse(mat3(view * model)));
transformed_normal = normal_matrix * original_normal;
}";
GL.ShaderSource(shader, src);
GL.CompileShader(shader);
var info = GL.GetShaderInfoLog(shader);
if (!string.IsNullOrWhiteSpace(info))
throw new Exception($"CompileShader {type} had errors: {info}");
shaders.Add(shader);
type = ShaderType.FragmentShader;
shader = GL.CreateShader(type);
src = #"#version 330 core
in vec4 vs_color;
in vec3 original_normal;
in vec3 transformed_normal;
out vec4 color;
void main(void)
{
float lighting = abs(dot(transformed_normal, vec3(0,0,-1)));
color = vs_color * lighting;
}";
GL.ShaderSource(shader, src);
GL.CompileShader(shader);
info = GL.GetShaderInfoLog(shader);
if (!string.IsNullOrWhiteSpace(info))
throw new Exception($"CompileShader {type} had errors: {info}");
shaders.Add(shader);
foreach (var shader_ in shaders)
GL.AttachShader(_program, shader_);
GL.LinkProgram(_program);
var info_ = GL.GetProgramInfoLog(_program);
if (!string.IsNullOrWhiteSpace(info_))
throw new Exception($"CompileShaders ProgramLinking had errors: {info}");
foreach (var shader_ in shaders)
{
GL.DetachShader(_program, shader_);
GL.DeleteShader(shader_);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
throw;
}
GL.Enable(EnableCap.DepthTest);
GL.PolygonMode(MaterialFace.Front, PolygonMode.Fill);
GL.PatchParameter(PatchParameterInt.PatchVertices, 3);
Closed += OnClosed;
}
private void OnClosed(object sender, EventArgs eventArgs)
{
Exit();
}
public override void Exit()
{
Debug.WriteLine("Exit called");
GL.DeleteVertexArray(_vertexArray);
GL.DeleteBuffer(_buffer);
GL.DeleteProgram(_program);
base.Exit();
}
protected override void OnResize(EventArgs e)
{
// Resize the viewport to match the window size.
GL.Viewport(0, 0, Width, Height);
base.OnResize(e);
}
private float[] Matrix4ToArray(Matrix4 matrix)
{
float[] data = new float[16];
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
data[i*4+j] = matrix[i, j];
}
}
return data;
}
private void PrintMatrix(Matrix4 matrix)
{
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
Console.WriteLine(matrix[i,j]);
}
}
}
protected override void OnRenderFrame(FrameEventArgs e)
{
var timeStamp = Stopwatch.GetTimestamp();
_angle += (float)((timeStamp - _lastTimestamp) / (double)_freq);
_lastTimestamp = timeStamp;
GL.ClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// Clear the color buffer.
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
// Bind the VBO
GL.BindBuffer(BufferTarget.ArrayBuffer, _buffer);
// Bind the VAO
GL.BindVertexArray(_vertexArray);
// Use/Bind the program
GL.UseProgram(_program);
_model = Matrix4.CreateFromAxisAngle(new Vector3(1.0f, 0.0f, 1.0f), _angle);
_view = Matrix4.LookAt(new Vector3(0.0f,0.0f,5.0f), new Vector3(0.0f,0.0f,0.0f), Vector3.UnitY);
_projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI * (_FOV/180f), _width / (float)_height, 0.2f, 256.0f);
int location = GL.GetUniformLocation(_program, "model");
GL.UniformMatrix4(location, 1, false, Matrix4ToArray(_model));
location = GL.GetUniformLocation(_program, "view");
GL.UniformMatrix4(location, 1, false, Matrix4ToArray(_view));
location = GL.GetUniformLocation(_program, "projection");
GL.UniformMatrix4(location, 1, false, Matrix4ToArray(_projection));
// This draws the triangle.
GL.DrawArrays(PrimitiveType.Triangles, 0, _verticeCount);
// Swap the front/back buffers so what we just rendered to the back buffer is displayed in the window.
Context.SwapBuffers();
base.OnRenderFrame(e);
}
[STAThread]
static void Main()
{
new MainWindow().Run(60);
}
}
}
Result: