I'm working on a little OpenTK based 2D graphics library and I'm trying to apply a shader to a Surface object:
public void ApplyTo(Surface surface)
{
using (Surface pong = new Surface())
{
pong.Create(surface.Width, surface.Height);
pong.Clear(0, 0, 0, 0);
GL.Viewport(0, 0, surface.Width, surface.Height);
GL.LoadIdentity();
GL.Ortho(0, 1.0, 1.0, 0.0, 0.0, 4.0);
GL.UseProgram(0);
surface.BindTexture();
pong.BindFramebuffer();
GL.Begin(PrimitiveType.Quads);
GL.TexCoord2(0.0f, 1.0f);
GL.Vertex3(0, 0, 0);
GL.TexCoord2(0.0f, 0.0f);
GL.Vertex3(0, 1, 0);
GL.TexCoord2(1.0f, 0.0f);
GL.Vertex3(1, 1, 0);
GL.TexCoord2(1.0f, 1.0f);
GL.Vertex3(1, 0, 0);
GL.End();
Use(); // calls GL.UseProgram()
pong.BindTexture();
surface.BindFramebuffer();
GL.Begin(PrimitiveType.Quads);
GL.TexCoord2(0.0f, 1.0f);
GL.Vertex3(0, 0, 0);
GL.TexCoord2(0.0f, 0.0f);
GL.Vertex3(0, 1, 0);
GL.TexCoord2(1.0f, 0.0f);
GL.Vertex3(1, 1, 0);
GL.TexCoord2(1.0f, 1.0f);
GL.Vertex3(1, 0, 0);
GL.End();
GL.BindTexture(TextureTarget.Texture2D, 0);
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
}
}
This somehow clears the surface instead of applying the shader. My suspicion is that I'm doing something wrong with the viewport / projection, but what? I hope the provided code is sufficient.
For full screen rendering on a quad, I use that projection:
OpenTK.Matrix4 ortho = OpenTK.Matrix4.CreateOrthographicOffCenter(-1, 1, -1, 1, 1, -1);
Theres a division by 0 somewhere when your vertices are exactly on the near plane, you may also move a bit further on the z axis.
Related
I'm trying to draw a cube in cabinet perspective. This is the cube in glOrtho:
Other faces:
Back - cyan, Left - magenta, down - blue
This is what I get
This is what I want to achieve
My code:
//init function
glClearColor(1, 1, 1, 1);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-10, 10, -10, 10, 4,6);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslated(0,0,-lat);//it doesn't show in the window without this.
DisplayAxis();
DisplayObject();
break;
//object initalization. I use glGenList and glCallList to draw it
void InitObject() {
glNewList(k, GL_COMPILE);
glColor3f(1, 0, 0);
glBegin(GL_QUADS);
glVertex3d(0, lat, lat);
glVertex3d(lat, lat, lat);
glVertex3d(lat, 0, lat);
glVertex3d(0, 0, lat);
glEnd();
glColor3f(1, 1, 0);
glBegin(GL_QUADS);
glVertex3d(lat, 0, 0);
glVertex3d(lat, 0, lat);
glVertex3d(lat, lat, lat);
glVertex3d(lat, lat, 0);
glEnd();
glColor3f(0, 1, 0);
glBegin(GL_QUADS);
glVertex3d(0, lat, lat);
glVertex3d(lat, lat, lat);
glVertex3d(lat, lat, 0);
glVertex3d(0, lat, 0);
glEnd();
glColor3f(0, 0, 1);
glBegin(GL_QUADS);
glVertex3d(0, 0, 0);
glVertex3d(lat, 0, 0);
glVertex3d(lat, 0, lat);
glVertex3d(0, 0, lat);
glEnd();
glColor3f(1, 0, 1);
glBegin(GL_QUADS);
glVertex3d(0, 0, lat);
glVertex3d(0, 0, 0);
glVertex3d(0, lat, 0);
glVertex3d(0, lat, lat);
glEnd();
glColor3f(0, 1, 1);
glBegin(GL_QUADS);
glVertex3d(0, lat, 0);
glVertex3d(lat, lat, 0);
glVertex3d(lat, 0, 0);
glVertex3d(0, 0, 0);
glEnd();
glEndList();
}
What am I doing wrong here? I tried some rotations on the object but I get some skewed results(I can post more images if needed).
The object is clipped by the near plane of the Viewing frustum.
Not you have to translate the object along the negativ z axis, to move the object in between the near and far plane of the viewing frustum:
glTranslated(0,0,-lat);//it doesn't show in the window without this.
Since the view space z axis points out out the viewport, you have to shift the object along the negative z axis.
The distance to the near plane is 4 and the distance to the far plane is 6:
glFrustum(-10, 10, -10, 10, 4,6);
The distance to the front of the cube is less than 4, thus it is clipped by the near plane.
Change the frustum, and keep the cube completely in the frustum to solve the issue:
glFrustum(-10, 10, -10, 10, 4,6);
glFrustum(-2.5, 2.5, -2.5, 2.5, 1, 10);
glTranslated(0,0,-lat);
glTranslated(0, 0, -6);
For a good perspective and look at the scene, use a projection matrix (frustum) with a smaller field of view:
glFrustum(-1, 1, -1, 1, 1, 12);
Alternatively you can define the frustum by gluPerspective and set the field of view angle in degrees:
gluPerspective(90, 1, 1, 12);
The view matrix defines the position and viewing direction of the observer (viewer) within the scene.
If you want a different look at the scene the you have to rotate the scene (glRotate):
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslated(0, 0, -8);
glRotatef(30, 1, 0, 0);
glRotatef(-45, 0, 1, 0);
Alternatively the look at the scene (view matrix) can be defined by gluLookAt . Arguments 1-3 are the position of the observer (x,y, z components of eye or camera position). The Arguments 4-6 are the target point (where the observer looks at). The arguments 7-9 are the upwards vector.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(5, 5, 7, 0, 0, 0, 0, 1, 0);
I have this code
glColor3f(1, 0, 0);// red quad
glBegin(GL_QUADS);
glVertex3f(-1, 0, -0.1);
glVertex3f(1, 0, -0.1);
glVertex3f(1, 1, -0.1);
glVertex3f(-1, 1, -0.1);
glEnd();
glColor3f(0, 1, 0); //green quad
glBegin(GL_QUADS);
glVertex3f(-1, 0, -0.2);
glVertex3f(1, 0, -0.2);
glVertex3f(1, 1, -0.2);
glVertex3f(-1, 1, -0.2);
glEnd();
glutSwapBuffers();
Using default projection matrix, the one that appears is my green quad.
If we're looking to negative z (from 1 to -1), shouldn't the green quad behind the red quad?
All matrices in compatibility mode OpenGL start off as identity matrices; they don't apply any transformations.
In Normalized Device Coordinates, +Z is into the window; you're looking at +Z. Matrices and shaders can, of course, change this.
Also make sure that depth testing is enabled and you create your window with a depth buffer.
If red quad is outside frustum's near and far plane then your red quad will not be visible because it gets clipped out. More information
I'm trying to make a Camera's View Matrix and make it zoomable, pannable and rotatable. The Matrix that I'd expect to work is.
Matrix.translateM(matrixView, 0, -camposition.X, -camposition.Y, 0);
Matrix.scaleM(matrixView, 0, zoom, zoom, 1.0f);
Matrix.rotateM(matrixView, 0, camrotation, 0, 0, 1.0f);
Matrix.translateM(matrixView, 0, screenwidth / 2, screenheight / 2, 0);
However it doesn't work this way. I would appreciate if somebody could point me in the right direction.
Here's how I did the model matrix which works:
Matrix.translateM(matrixModel, 0, position.X, position.Y, 0.0f);
Matrix.scaleM(matrixModel, 0, scale.X, scale.Y, 1.0f);
Matrix.rotateM(matrixModel, 0, rotation, 0, 0, 1.0f);
Matrix.translateM(matrixModel, 0, -origin.X, -origin.Y, 0.0f);
And here's the projection matrix aswell:
Matrix.orthoM(matrixProj, 0, 0f, screenWidth, screenHeight, 0, -1, 1);
I multiply them together in the vertex shader like so:
matrixProj * matrixView * matrixModel * vPosition;
I've found the correct order I'll leave it for future developers facing the same problem.
Matrix.translateM(matrixView, 0, screenWidth / 2, screenHeight / 2, 0);
Matrix.scaleM(matrixView, 0, camZoom, camZoom, 1.0f);
Matrix.rotateM(matrixView, 0, camRotation, 0, 0, 1.0f);
Matrix.translateM(matrixView, 0, -camPosition.X, -camPosition.Y, 0);
Keep in mind this is for the View Matrix. For the Model Matrix the above code works just fine.
I need to render an OpenGL scene to a texture in order to then manipulate that texture in a shader. I've solved this by using Framebuffer Objects, which I think I understand fairly well by now. At many points in my effect pipeline, I need to render a fullscreen quad and texture it with the dynamically rendered texture, which is where my problem is.
This is what my scene looks like: https://www.mathematik.uni-marburg.de/~thomak/planet.jpg
I render this to a texture and map that texture to a fullscreen quad. However, the resulting image is distorted in this way: https://www.mathematik.uni-marburg.de/~thomak/planettexture.jpg
Here is the code that renders the quad and sets the texture coordinates:
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glBegin(GL_QUADS);
glTexCoord2i(0, 0);
glVertex3i(-1, -1, -1);
glTexCoord2i(0, 1);
glVertex3i( 1, -1, -1);
glTexCoord2i(1, 1);
glVertex3i( 1, 1, -1);
glTexCoord2i(1, 0);
glVertex3i(-1, 1, -1);
glEnd();
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
And the shader code is here:
sampler2D BlitSamp = sampler_state
{
MinFilter = LINEAR;
MagFilter = LINEAR;
MipFilter = LINEAR;
AddressU = Clamp;
AddressV = Clamp;
};
float4 AlphaClearPS(float2 texcoords : TEXCOORD0) : COLOR
{
return float4(tex2D(BlitSamp, texcoords).rgb, 1.0f);
}
Where BlitSamp is the texture I rendered to and then passed to the shader. What could be going on here?
It's possible that your tex-coords are off. Your code, my comments:
glTexCoord2i(0, 0); //Bottom-Left
glVertex3i(-1, -1, -1); //Bottom-Left
glTexCoord2i(0, 1); //Top-Left
glVertex3i( 1, -1, -1); //Bottom-Right???
glTexCoord2i(1, 1); //Top-Right
glVertex3i( 1, 1, -1); //Top-Right
glTexCoord2i(1, 0); //Bottom-Right
glVertex3i(-1, 1, -1); //Bottom-Left??
Your code to render the quad looks fine so that would point to a mismatch in the size of the quad and the size of the viewport.
Could you have swapped the width and height when you created the render texture, by any chance ?
I want to rotate 2d texture in cocos2d-x(opengl es) as i searched i should use rotation matrix
as this :
(x = cos(deg) * x - sin(deg) * y y = sin(deg) * x + cos(deg) * y)
but when i want to implement this formula i fail may code is like(i want original x and y to be same ) :
i updated my code to this but still not working!
GLfloat coordinates[] = {
0.0f, text->getMaxS(),
text->getMaxS(),text->getMaxT(),
0.0f, 0.0f,
text->getMaxS(),0.0f };
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
GLfloat vertices[] = { rect.origin.x, rect.origin.y, 1.0f,
rect.origin.x + rect.size.width, rect.origin.y, 1.0f,
rect.origin.x, rect.origin.y + rect.size.height, 1.0f,
rect.origin.x + rect.size.width, rect.origin.y + rect.size.height, 1.0f };
glMultMatrixf(vertices);
glTranslatef(p1.x, p1.y, 0.0f);
glRotatef(a,0,0,1);
glBindTexture(GL_TEXTURE_2D, text->getName());
glVertexPointer(3, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
glColor4f( 0, 0, 250, 1);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glRotatef(-a, 0.0f, 0.0f, -1.0f);
glPopMatrix();
If you're using OpenGL in two dimensions, you can still use the various transformation functions. For glRotate(), you have to pass it an axis of (0,0,1):
glRotate(angle,0,0,1);
You seem to be confused about a few aspects of OpenGL. At the minute you have this:
glMultMatrixf(vertices);
glTranslatef(p1.x, p1.y, 0.0f);
glRotatef(a,0,0,1);
glBindTexture(GL_TEXTURE_2D, text->getName());
glVertexPointer(3, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
glColor4f( 0, 0, 250, 1);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glRotatef(-a, 0.0f, 0.0f, -1.0f);
glPopMatrix();
That would ostensibly:
// reinterpret your vertices as a matrix; multiply the
// current matrix by the one formed from your vertices
glMultMatrixf(vertices);
// rotate by a degrees, then translate to p1
glTranslatef(p1.x, p1.y, 0.0f);
glRotatef(a,0,0,1);
// bind the relevant texture, supply the vertices
// as vertices this time, supply texture coordinates
glBindTexture(GL_TEXTURE_2D, text->getName());
glVertexPointer(3, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
// set a colour of (0, 0, 1, 1) — probably you
// wanted glColor4ub to set a colour of (0, 0, 250/255, 1)?
glColor4f( 0, 0, 250, 1);
// draw some geometry
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// perform the same rotation as before a second time;
// giving either a and -1, or -a and 1 would have been
// the opposite rotation
glRotatef(-a, 0.0f, 0.0f, -1.0f);
// remove the current matrix from the stack
glPopMatrix();
What you probably want is:
// push the current matrix, so that the following
// transformations can be undone with a pop
glPushMatrix();
// rotate by a degrees, then translate to p1
glTranslatef(p1.x, p1.y, 0.0f);
glRotatef(a,0,0,1);
// bind the relevant texture, supply the vertices
// as vertices this time, supply texture coordinates
glBindTexture(GL_TEXTURE_2D, text->getName());
glVertexPointer(3, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
// set a colour of (0, 0, 250/255, 1)
glColor4ub( 0, 0, 250, 1);
// draw some geometry
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// remove the current matrix from the stack
glPopMatrix();
The current transform matrices are applied to all geometry. You don't flag up which geometry they apply to and which they don't. Pushes and pops should be paired, and are the way you affect transformations from being affected by prior transformations when that's what you want. So you don't manually perform the inverse rotation, and you need to push before you do all the stuff that changes the matrix. I've also switched you to glColor4ub for the reason given above — you appear to be using unsigned bytes to push colours in but OpenGL uses the range from 0.0 to 1.0 to represent a colour. glColor4ub will automatically map from the former to the latter.