I'm using Python OpenGL, version '3.3.0 - Build 8.15.10.2725' on Win7 x64.
I'm using GL_LINES to draw 2D grids and XYZ axes in 3D space.
When I disable lighting the grid colors come out fine.
When I enable lighting and the light Z position is > 0, the grid colors come out fine.
However when I put the light Z position < 0, the grid colors are almost gray, even though the 3D portion of the model is rendering properly. Since lines are one dimensional, I don't think they have a surface; I'm not sure how OpenGL regards lines in the presence of lighting.
I can get colored lines with lighting Z position < 0 if I use a dumb fragment shader as follows:
# From http://bazaar.launchpad.net/~mcfletch/openglcontext/trunk/view/head:/tests/shader_2.py
self.color_fragmentshader = shaders.compileShader("""
varying vec4 vertex_color;
void main() {
gl_FragColor = vertex_color;
}
""", GL.GL_FRAGMENT_SHADER)
But if I leave the default shader (by not calling glUseProgram), or use some other shader I found, then the 2D lines come out gray.
My grid and axes functions are as follows:
def drawGrid(self, size, squares):
GL.glLineWidth(0.1)
GL.glColor((trolltechGreen.light().red()/255,
trolltechGreen.light().green()/255,
trolltechGreen.light().blue()/255))
GL.glBegin(GL.GL_LINES)
for x in np.linspace(-size, size, squares+1, True):
GL.glVertex2f(x, -size)
GL.glVertex2f(x, size)
for y in np.linspace(-size, size, squares+1, True):
GL.glVertex2f(-size, y)
GL.glVertex2f(size, y)
GL.glVertex2f(-size,-size)
GL.glVertex2f(size,-size)
GL.glVertex2f(size,size)
GL.glVertex2f(-size,size)
GL.glEnd()
def drawAxes(self, size):
GL.glLineWidth(5)
GL.glBegin(GL.GL_LINES)
GL.glColor(1,0,0,1)
GL.glVertex2f(0,0)
GL.glVertex2f(size,0)
GL.glColor(0,1,0,1)
GL.glVertex2f(0,0)
GL.glVertex2f(0,size)
GL.glColor(0,0,1,1)
GL.glVertex2f(0,0)
GL.glVertex3f(0,0,size)
GL.glEnd()
I can also get the line color to come out fine if I change the shader each time I render the lines, then change again to render the 3D objects, but I don't think this is the right solution.
Here is what the problem looks like. The lighting is "behind" the teapot in -Z. How can I force the lines to ignore the lighting, without constantly changing the shader? Thanks!
I'm not sure how OpenGL regards lines in the presence of lighting.
When you enable lighting in the fixed function pipeline, it will affec all primitives you draw - points, lights, triangles.
Lines might not define a mathematical surface, but you still have normal vectors defined for them. Remember that OpenGL is a state machine, so if you don't specify them with your line geometry, you still have some "current" normal vector which will be used.
When you use shaders, you yourself control the color which is generated. Shaders apply to all primitive types as well.
If you want the lines to be unaffected by the lighting, disable lighting when you draw the grid in the fixed-function pipeline, or use a color-only shader if you use the programmable pipeline.
You can of course set some material properties so that your lines will appear just in the color you whish while lighting is enabled. In fixed-function GL, this can be achieved by setting the "emissive" material coeffients to the desired color, and all others to 0, for example. If you use shaders, it will depend on how the shader work, of course.
Related
I am looking to create a repetitive pattern from a single shape (in the example below, the starting shape would be the smallest centre star) using Python. The pattern would look something like this:
To give context, I am working on a project that uses a camera to detect a shape on a rectangle of sand. The idea is that the ripple pattern is drawn out around the object using a pen plotter-type mechanism in the sand to create a zen garden-type feature.
Currently, I am running the Canny edge detection algorithm to create a png (in this example it would be the smallest star). I am able to convert this into an SVG using potrace, but am not sure how to create the ripple pattern (and at what stage, i.e. before converting to an SVG, or after).
Any help would be appreciated!
Here's how I did it:
In the end, I ran a vertex detection algorithm to calculate the shape's vertices.
Then, I sorted them in a clockwise order around the centroid coordinate. Using the svgwrite library, I recreated the shapes using lines.
I 'drew' a circle with a set radius around each vertex and calculated the intersection between the circle and a straight line from the centroid through the vertex.
This gave me two potential solutions (a +ve and a -ve). I chose the point furthest away from the centroid, iterated this method for each vertex and joined the points to create an outline of the shape.
Assing you are using turtle (very beginner friendly) you can use this:
import turtle, math
turtle.title("Stars!")
t = turtle.Turtle()
t.speed(900) # make it go fast
t.hideturtle() # hide turtle
t.width(1.5) # make lines nice & thick
def drawstar(size):
t.up() # make turtle not draw while repositioning
t.goto(0, size * math.sin(144)) # center star at 0, 0
t.setheading(216); # make star flat
t.down() # make turtle draw
for i in range(5): # draw 5 spikes
t.forward(size)
t.right(144)
t.forward(size)
t.right(288)
drawstar(250)
drawstar(200)
drawstar(150)
drawstar(100)
input() # stop turtle from exiting
which creates this:
I am using gluLookAt with a camera whose coordinates are xCam, yCam and zCam. The coordinates of the object the camera is looking at are xPos, yPos, and zPos. There are variables named mouseturnX and mouseturnY, which measure the deviation of the mouse from the middle of the screen in the x-axis and the y-axis. The variable camdist describes the distance between camera and the object it looks at.
The code of the cameraposition is this:
xCam = sin(mouseturnX)*camdist+xPos
yCam = mouseturnY+yPos
zCam = cos(mouseturnX)*camdist+zPos
I now made a polygon object, which I rotate with:
glRotatef(mouseturnX,0,1,0)
Usually it should only show me the backside of the object, it does not matter which position the camera has. But now it does not turn correctly. I tried it with other rotation-axises, there it works fine, but with the y-axis it just does not want to work. I tried changing the camdist from positive to negative, the mouseturnX in the glRotatef function from positive to negative and back to positive again. It just does not work. I used glPushMatrix before the rotation command and glPopMatrix after it. One line before the rotation command I used the translate function to set a fixpoint for the polygon.
Edit: The polygon actually spins, but not in the right amount. It seems like I have to multiply the rotation of the polygon with something.
I found the multiplicator by trying. It is 56.5. It is not perfect, but it works.
In TkInter, we can draw several shapes. But what if we just want to draw a pixel instead ?
After creating a Canvas object, you can draw a line that spans a single pixel.
your_canvas_widget.create_line(x, y, x + 1, y)
To create a single pixel with co-ordinates x, y on a canvas, you can use a rectangleobject:
canvas.create_rectangle( (x, y)*2 )
By default, the rectangle object has a one-pixel wide black border, which when one-pixel wide will just be black, regardless of the colour. To give the pixel your desired colour, you can use outline="", so you can then specify your fill colour.
I prefer this method as you only need to provide the x, y co-ordinates, no x+1 is needed.
This topic is already answered and quite old but I'd like to add a comment, maybe it is of interest:
your_canvas_widget.create_line(x, y, x + 1, y)
Is what I have also tried and it works for me. I used it for creating an image of a Mandelbrot-set. It works quite fine for small resoltions, e.g. 200 x 200 pixel. But for larger resolutions, the TK engine seems to have problems to render those many "micro lines". the calculation of the mandelbrot set is finished, but the Tk window seems to hang without rendering anything.
A better solution for drawing pixels, I have found in python-mandelbrot-fractal-with-tkinter. There the pixels are put one by one into a tkinter PhotoImage which is afterwards rendered all in one, very fast.
I'm using pygame for image editing (not displaying). (Yes, I know there are other options like PIL/pillow, but pygame should work for this.)
I want to draw and save an image where I'm individually setting the alpha values of each pixel according to a formula (I'm drawing a complicated RGBA profile). It seems that pixels_alpha is the right way to do this. But when I change pixels_alpha it's ignored, the image just stays transparent. Here's my code...
import pygame as pg
import os
def init_transparent(img_width, img_height):
"""
Create a new surface with width and height, starting with transparent
background. This part works!
"""
os.environ['SDL_VIDEODRIVER'] = 'dummy'
pg.init()
pg.display.init()
# next command enables alpha
# see http://stackoverflow.com/questions/14948711/
pg.display.set_mode((img_width, img_height), 0, 32)
# pg.SRCALPHA is a flag that turns on per-pixel alpha.
return pg.Surface((img_width, img_height), pg.SRCALPHA)
def make_semitransparent_image():
surf = init_transparent(20, 20)
# alphas should be a direct reference to the alpha data in surf
alphas = pg.surfarray.pixels_alpha(surf)
# alphas is a uint8-dtype numpy array. Right now it's all zeros.
for i in range(20):
for j in range(20):
# Since pixels_alpha gave me a uint8 array, I infer that
# alpha=255 means opaque. (Right?)
alphas[i,j] = 200
pg.image.save(surf, '/home/steve/Desktop/test.png')
make_semitransparent_image()
Again, it saves an image but the image looks completely transparent, no matter what value I set alphas to. What am I doing wrong here? (Using Python 2.7, pygame 1.9.1release.) (Thanks in advance!)
The Pygame docs say that pixels_array() locks the surface as long as the resulting array exists, and that locked surface may not be drawn correctly. It seems to be the case that they are not saved correctly, too. You need to throw away the alphas surfarray object before calling image.save(). This can be done by adding del alphas just before image.save().
(Note that this is more a workaround than a proper fix. Adding del alphas can only have a reliable effect only on CPython (and not PyPy, Jython, IronPython). Maybe you can really "close" a surfarray objects, the same way you can either close a file or merely forget about it?)
Simple question, but I've tried a few things and nothing seems to work.
I want to overlay some statistics onto a 3d VTK scene, using 2D vtkTextActors. This works fine, but the text is at times difficult to see, depending on what appears behind it in the 3D scene.
For this reason, I'd like to add a 2d, semi-transparent "box" behind my text actors to provide a darker background.
Which VTK object is appropriate for this? I've tried so far:
vtkLegendBoxActor: Not what I want, but I can use this with no text to display a semi-transparent box on screen. I cannot size it directly and I get warnings about not initialising some of the content.
vtkImageData: Tried manually creating image data and adding it to the scene; I believe it was placed within the 3d scene and not used as an overlay. If that's not the case then I couldn't get it to show at all.
vtkCornerAnnotation: Scales with window size, is fixed to a corner and the background opacity cannot be set AFAIK.
vtkTextActor: Cannot set a background color or opacity
Can anyone tell me how they might achieve what I'm after in VTK?
I've found a way to do this with vtkPolyMapper2D which seems to work okay. It seems to be a very stupid way to do this. If there is something more elegant, I'm all ears.
import vtk
extents = [[0,0],[620,0],[620,220],[0,220]]
polyPoints = vtk.vtkPoints()
for x, y in extents:
polyPoints.InsertNextPoint(x, y, 0)
num_corners = len(extents)
polyCells = vtk.vtkCellArray()
polyCells.InsertNextCell(num_corners + 1)
for i in range(0, num_corners):
polyCells.InsertCellPoint(i)
polyCells.InsertCellPoint(0) ## Rejoin at the end
poly_profile = vtk.vtkPolyData()
poly_profile.SetPoints(polyPoints)
poly_profile.SetPolys(polyCells) ## Goes solid
cut_triangles = vtk.vtkTriangleFilter()
cut_triangles.SetInput(poly_profile)
_poly_mapper = vtk.vtkPolyDataMapper2D()
_poly_mapper.SetInput(poly_profile)
_poly_mapper.SetInputConnection(cut_triangles.GetOutputPort())
_actor = vtk.vtkActor2D()
_actor.SetMapper(_poly_mapper)
_actor.GetProperty().SetColor([0.1,0.1,0.1])
_actor.GetProperty().SetOpacity(0.5)
#Add to renderer as normal
just use vtktexture, vtkimagedata & add your own image as texture background to the vtkrenderer by reducing the opacity like a watermark. thats it