I've got a problem with my render to texture process. When I render the scene with width = height = 512 it has nearly no errors but the smaller the texture and scene gets, the more errors it gets.
The error is that regions of the texture are black, what makes no sense.
Here are some screenshots
512*512: http://www.ld-host.de/uploads/images/d9452fa0ba28494830fd96f0f15b9eba.png
128*128: http://www.ld-host.de/uploads/images/a39c141282a622f086d4a96b070a56a3.png
Here is my code how I render to texture and use the texture later
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
gluLookAt(0,0,200,0,0,-1,0,1,0)
self.fbos = glGenFramebuffersEXT(1)
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, self.fbos)
self.depthbuffers = (glGenRenderbuffersEXT(1)
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, self.depthbuffers)
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height)
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, self.depthbuffers)
self.textures = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, self.textures)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, None);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, self.textures, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, self.fbos);
glEnable(GL_CLIP_PLANE0)
glEnable(GL_CLIP_PLANE1)
glClipPlane(GL_CLIP_PLANE0, (0,0,1,-1 * self.start + self.diff))
glClipPlane(GL_CLIP_PLANE1, (0,0,-1,self.start))
# render the mesh
glTranslatef(-64,-64,-64)
glEnableClientState(GL_VERTEX_ARRAY) # Enable something in OpenGL
glEnableClientState(GL_COLOR_ARRAY) # Enable something in OpenGL
glBindBuffer(GL_ARRAY_BUFFER,self.vbo[1])
glColorPointer(3,GL_FLOAT,0,None) # Tell OpenGL that it contains only ColorValues
#Now the vertex Buffer with positions
glBindBuffer(GL_ARRAY_BUFFER,self.vbo[0])
glVertexPointer(3,GL_FLOAT,0,None) # Tell OpenGL that it contains the Positions for each Points
glDrawArrays(GL_TRIANGLES,0,len(self.verts)+len(self.color)) # Merge both
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_CLIP_PLANE0)
glDisable(GL_CLIP_PLANE1)
glBindTexture(GL_TEXTURE_2D,0)
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
#Plane for showing texture
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
gluLookAt(0,0,1,0,0,0,0,1,0)
glClearColor(1,1,1,0)
glEnable(GL_TEXTURE_2D)
glBindTexture(GL_TEXTURE_2D, self.textures)
glBegin(GL_QUADS)
glNormal3f(0.0, 1.0, 0.0)
glTexCoord2f(0.0, 0.0)
glVertex3f(-1, 1, -1)
glTexCoord2f(1.0, 0.0)
glVertex3f(1, 1, -1)
glTexCoord2f(1.0, 1.0)
glVertex3f(1, -1, -1)
glTexCoord2f(0.0, 1.0)
glVertex3f(-1, -1, -1)
glEnd();
glDisable(GL_TEXTURE_2D)
pygame.display.flip()
How can I achieve a better quality for the smaller texture? The mesh has no holes but the texture sometimes has.
I don't know what exactly you're expecting to see. You're drawing triangles/cubes/etc that are clearly smaller than the size of a pixel/sample size. Therefore, not all of them are going to be visible.
This is a standard aliasing problem: triangles that don't cover the center of a pixel/sample will not be visible. That's the nature of rasterization. And the only way to fix aliasing is to increase the number of samples you use. You can render at a higher resolution and downscale, or you could use MSAA or another real aliasing technique.
Related
Am trying to render cube with tkinter frame opengl.
But I don't know where the problem lies the cube didn't show expect 2 lines.
Check my code
Pls can you help me write the code and do you have any PDF to teach me opengl I can't find much resources online
import tkinter as tk
from OpenGL.GL import *
from pyopengltk import
OpenGLFrame
cubeVertices =
((1,1,1),(1,1,-1),
(1,-1,-1),(1,-1,1),.
(-1,1,1),(-1,-1,-1),
(-1,-1,1),(-1,1,-1))
cubeEdges = ((0,1),.
(0,3),(0,4),(1,2),.
(1,7),(2,5),(2,3),.
(3,6),(4,6),(4,7),.
(5,6),(5,7))
classframe(OpenGLFrame):
def initgl(self):
glViewport(0,0,250,250)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0,self.width,self.height,0,-1,1)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
def redraw(self):
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
glPushMatrix()
glRotatef(90,0.0,1.0,0.0)
glBegin(GL_LINES)
glColor3f(0.0,1.0,0.0)
for cubeEdge in cubeEdges:
for cubeVertex in cubeEdge:
glVertex3fv(cubeVertices[cubeVertex])
glEnd()
glPopMatrix()
root = tk.Tk()
app = frame(root,width=900, height=600)
app.pack(
fill=tk.BOTH,expand=tk.YES)
app.mainloop()
You have to change the projection matrix. Since the cube has a dimension of 2x2x2 and the projection is an orthographic projection in window space, the cube will cover just 4 pixels in the window.
Change the view space and increase the distance to the near and far plane. Note, the geometry has to be in between the near and far plane, else the geometry will be clipped. For instance:
glOrtho(-10, 10, -10, 10, -10, 10)
Anyway I recommend to use Perspective projection. The projection matrix defines a 3 dimensional space (clip space) which is projected on the 2 dimensional viewport. At Perspective projection, this space is a frustum (Viewing frustum). The matrix can be set by gluPerspective. For instance:
classframe(OpenGLFrame):
def initgl(self):
glViewport(0,0,250,250)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
# glOrtho(-10, 10, -10, 10, -10, 10)
gluPerspective(90, self.width/self.height, 0.1, 10.0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
The value for the near plane and the far plane have to be greater than 0.0 and the far plane has to be greater then the near plane 0 < near < far. In the above example the near plane is 0.1 and the far plane 10. When you draw the geometry, the you have to ensure, that the geometry is in between then near and the far plane (in clip space respectively in the viewing volume), else the geometry is clipped.
Use gluLookAt to define a view matrix with a point of view (0, -3, 0) that has a certain distance to the origin of the world (0, 0, 0):
classframe(OpenGLFrame):
# [...]
def redraw(self):
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
# define view matrix
glLoadIdentity()
gluLookAt(0, -3, 0, 0, 0, 0, 0, 0, 1)
glPushMatrix()
glRotatef(90,0.0,1.0,0.0)
glBegin(GL_LINES)
glColor3f(0.0,1.0,0.0)
for cubeEdge in cubeEdges:
for cubeVertex in cubeEdge:
glVertex3fv(cubeVertices[cubeVertex])
glEnd()
glPopMatrix()
What exactly are eye space coordinates?
I'm trying to texturing a quad and to understand how this little sample works. My code is not original, it's mixed from various examples.
Texture: https://jamesmwake.files.wordpress.com/2015/10/uv_texture_map.jpg?w=660
My questions:
When I change GL_TEXTURE_MIN_FILTER to GL_TEXTURE_MAG_FILTER in
glTexParameteri the texture disappears. Why?
When I change GL_LINEAR to GL_NEAREST, nothing happens. The used
texture's resolution changed to 300x300px. Why is that?
How can I make mipmaps and then using them?
The loadImage() function make a texture. How knows PyOpenGL which
texture should be used in the makeQuad() function?
Code:
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
def loadImage():
img = pygame.image.load("checker_texture_downsized.jpg")
textureData = pygame.image.tostring(img, "RGB", 1)
width = img.get_width()
height = img.get_height()
bgImgGL = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, bgImgGL)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData)
glEnable(GL_TEXTURE_2D)
def makeQuad():
glBegin(GL_QUADS)
glTexCoord2f(0, 0)
glVertex2f(25, 25)
glTexCoord2f(0, 1)
glVertex2f(25, 775)
glTexCoord2f(1, 1)
glVertex2f(775, 775)
glTexCoord2f(1, 0)
glVertex2f(775, 25)
glEnd()
def main():
pygame.init()
display = (1280,800)
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
gluOrtho2D(0, 1280, 0, 800)
loadImage()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
makeQuad()
pygame.display.flip()
main()
Note, that drawing by glBegin/glEnd sequences, the fixed function pipeline matrix stack and fixed function pipeline per vertex light model, is deprecated since decades.
Read about Fixed Function Pipeline and see Vertex Specification and Shader for a state of the art way of rendering.
When I change GL_TEXTURE_MIN_FILTER to GL_TEXTURE_MAG_FILTER in glTexParameteri the texture disappears. Why?
The initial value of GL_TEXTURE_MIN_FILTER is GL_NEAREST_MIPMAP_LINEAR. If you don't change it and you don't create mipmaps, then the texture is not "complete" and will not be "shown". See glTexParameter.
See OpenGL 4.6 API Compatibility Profile Specification; 8.17 Texture Completeness; page 306
A texture is said to be complete if all the texture images and texture parameters required to utilize the texture for texture application are consistently defined.
... a texture is complete unless any of the following conditions hold true:
The minification filter requires a mipmap (is neither NEAREST nor LINEAR), and the texture is not mipmap complete.
When I change GL_LINEAR to GL_NEAREST, nothing happens. The used texture's resolution changed to 300x300px. Why is that?
If the texture is smaller than the region where the texture is wrapped to, the the minification filter has not effect, but the magnification would have an effect. If you set the value GL_NEAREST to the GL_TEXTURE_MAG_FILTER then the texels are not interpolated any more.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
How can I make mipmaps and then using them?
Mipmaps can be generated by glGenerateMipmap:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR)
glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData)
glGenerateMipmap(GL_TEXTURE_2D)
The loadImage() function make a texture. How knows PyOpenGL which texture should be used in the makeQuad() function?
OpenGL is a state engine. Each state is kept until you change it again, even beyond frames. Since you have bound the texture in loadImage
glBindTexture(GL_TEXTURE_2D, bgImgGL)
the currently named texture object, which is bound to texture unit 0 is bgImgGL. This texture is used for drawing.
I am trying to map a texture to a quad in pyglet using the opengl functions but the quad is just showing up as white.
My code looks like this:
import pyglet
from pyglet.gl import *
glEnable(GL_TEXTURE_2D)
image = pyglet.image.load("redbrick.png")
texture = image.get_texture()
and my draw function:
def on_draw():
window.clear()
glBindTexture (GL_TEXTURE_2D, 13)
glBegin (GL_QUADS);
glTexCoord2i (0, 0)
glVertex2i (0, 0)
glTexCoord2i (1, 0)
glVertex2i (100, 0)
glTexCoord2i (1, 1)
glVertex2i (100, 100)
glTexCoord2i (0, 1)
glVertex2i (0, 100)
glEnd ()
Is there something I am doing wrong or missing out for it to be drawn as a white quad?
I see a few things that may be wrong. It would be nice to have the full code in like a pastebin but I can't comment to ask so...
your texture needs to be made into an opengl texture. You need to first convert your image into a raw data format. When you load the image do image.get_data(), compressed into a single line below. This isn't the most efficient way but a simple example.
After Binding the texture set drawing parameters.
Then hand the data to the video card in glTexImage2D.
data=pyglet.image.load("redbrick.png").get_data()
texture_id = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texture_id)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (image_width), (image_height), 0, GL_RGBA, GL_UNSIGNED_BYTE, data)
After that you should be able to use this texture if you bind with texture_id. 13 could be nothing for all I can see. Provide all the code and I could probably revise.
My code draws a 3D world, with a 2D set of graphics on top of it. The 3D world is made out of textured quads and the textures are generated with the following code:
textures = []
image = pyglet.image.load(os.path.join(img_dir, "magic.png"))
textures.append(image.get_texture())
glEnable(textures[-1].target)
glBindTexture(textures[-1].target, textures[-1].id)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width, image.height,
0, GL_RGBA, GL_UNSIGNED_BYTE,
image.get_image_data().get_data('RGBA',
image.width * 4))
The quads are then drawn with (the other 2 just have different coords):
glBindTexture(texture.target, texture.id)
glBegin(GL_QUADS)
glTexCoord2f(0.0, 0.0); glVertex3f(4.0, -2.0, 100.0+self.clock)
glTexCoord2f(1.0, 0.0); glVertex3f(4.0, -2.0, -100.0+self.clock)
glTexCoord2f(1.0, 1.0); glVertex3f(-4.0, -2.0, -100.0+self.clock)
glTexCoord2f(0.0, 1.0); glVertex3f(-4.0, -2.0, 100.0+self.clock)
glEnd()
I have set up the correct parameters when drawing the 3D and 2D graphics, and when I draw a 2D triangle on top of the 3D quad (with the following code) everything works fine:
glBegin(GL_TRIANGLES)
glVertex3f(0.0, 10, 0.0)
glVertex3f(-10, -10, 0)
glVertex3f(10, -10, 0)
glEnd()
However, I then try to draw a sprite and the 3D quads lose their texture and are drawn as white.
self.spr=pyglet.sprite.Sprite(pyglet.image.load(os.path.join(img_dir, "largebullet.png")).get_texture())
...
self.spr.draw()
Note that there's some fog in the background
I found a solution to this, by running glDisable(texture.target) on the enabled textures after they were drawn. It's not ideal because they have to be reenabled again, but for now it works ok.
I ran into a similar problem to this, and I found that the pyglet Sprite class tends to disable everything in the OpenGL state that it sets. You must reset a lot of things each time any sprite is drawn.
I am working on a project that requires that I create a 2D interface rendered "on top" or a 3D world. On some other forums, I read that you could use "GluOrtho2D()" for the job, and switch back to GluPerspective() once you were done. The only thing is, my test code I wrote for it only displays the 3D world, not the 2D quad. When I disable the 3D rendering code, however, the quad appears where it was supposed to be.
I trimmed down the code to openGL only statements, which I wrote down below. The code is written in Python using the Pyglet library.
The scene initialization code:
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60.0, float(width)/height, .1, 10000.)
glMatrixMode(GL_MODELVIEW)
glClearDepth(1.0)
glShadeModel(GL_FLAT)
glEnable(GL_DEPTH_TEST)
glDepthFunc(GL_LEQUAL)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
The frame rendering code. The call to builder.buildMap() creates the 3D scene, and the glBegin-glEnd pair draws a 2D quad:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
stage.set3DMode(window.width, window.height)
builder.buildMap()
stage.set2DMode(window.width, window.height)
glBegin (GL_QUADS)
glVertex2i(0, 0)
glVertex2i(0, 200)
glVertex2i(200, 200)
glVertex2i(200, 0)
glEnd()
the stage.set3DMode function:
glDisable(GL_DEPTH_TEST)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluOrtho2D(0, width, 0, height)
glMatrixMode(GL_MODELVIEW)
and the stage.set3DMode function:
glEnable(GL_DEPTH_TEST)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60.0, float(width)/float(height), .1, 10000.)
glMatrixMode(GL_MODELVIEW)
I really hope someone can point out my mistake! And thank you for helping me :)
It looks like you don't call glLoadIdentity() after switching to GL_MODELVIEW. The simplest way to remember is to call it every time you change the projection matrix, switch to GL_MODELVIEW and call glLoadIdentity() (unless you really want to retain the old one).
A lot of people get it wrong how to use glViewport and the like. They always place it in the reshape callback which is simply wrong.
You always to the full setup in your rendering function, just before you need those settings. So your code should be (pesudocode):
render_scene():
// first clear the whole window
glViewport(0, 0, window.width, window.height)
glClearDepth(1.0)
glClearColor(1., 1., 1., 1.);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
glViewport(3Dstuff.x, 3Dstuff.y, 3Dstuff.w, 3Dstuff.h)
// maybe also set scissor to clip
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60.0, float(width)/height, .1, 10000.)
glMatrixMode(GL_MODELVIEW)
setup3DstuffModelview()
glDepthFunc(...)
glEnable(GL_DEPTH_TEST)
// other state stuff
render3Dstuff()
// now the 2D stuff
glViewport(2Dstuff.x, 2Dstuff.y, 2Dstuff.w, 2Dstuff.h)
// clear depth and stencil -- if you need parts of the 3D depth / stencil
// for some algorithm retain it or save and restore by FBO renderbuffers or
// glReadPixels, glDrawPixels
glClearDepth(1.0)
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(...)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
setup2DstuffModelview()
glDepthFunc(...)
glDisable(GL_DEPTH_TEST)
// other state stuff
render2Dstuff()
// repeat for all the layers you need
This is really important: OpenGL is a state machine. Unless you can prove that no undetermined state changes happen you always re-/set all the states you need prior to rendering a certain geometry.
I use the following matrices for 2d rendering:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, w, h, 0, 0, 1);
glViewport(0, 0, w, h);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.375f, 0.375f, 0);