I tried to draw a triangle with OCaml using glfw-ocaml and lablgl libraries. The program only shows a black window and I didn't manage to draw something in.
I've tried to use shader and the result is the same. I succeed to draw a simple triangle with GLUT. But how to do it with GLFW?
Here's my code (without shader):
let of_float_array_static arr ~kind =
let raw = Raw.create_static kind ~len:(Array.length arr) in
Raw.sets_float raw ~pos:0 arr;
raw
let () =
(* Initialize the library *)
GLFW.init ();
GLFW.windowHint ~hint:Samples ~value:(Some 4);
GLFW.windowHint ~hint:ContextVersionMajor ~value:3;
GLFW.windowHint ~hint:ContextVersionMinor ~value:3;
GLFW.windowHint ~hint:OpenGLForwardCompat ~value:true;
GLFW.windowHint ~hint:OpenGLProfile ~value:CoreProfile;
(* Create a windowed mode window and its OpenGL context *)
let window = GLFW.createWindow ~width:1024 ~height:768 ~title:"Triangle" () in
(* Make the window's context current *)
GLFW.makeContextCurrent ~window:(Some window);
(* Ensure we can capture the escape key being pressed below *)
GLFW.setInputMode ~window:window ~mode:StickyKeys ~value:true;
(* Dark blue background *)
GlClear.color (0., 0., 0.4);
let raw = of_float_array_static [|-1.; -1.; 0.; 1.; -1.; 0.; 0.; 1.; 0.|] ~kind:`float in
GlArray.vertex `three raw;
while (not ((GLFW.getKey ~window:window ~key:Escape) || (GLFW.windowShouldClose ~window:window))) do
(* Render here *)
(* Clear the screen *)
GlClear.clear [`color; `depth];
(* Draw triangle... *)
GlArray.enable `vertex;
GlArray.draw_arrays `triangles ~first:0 ~count:3;
GlArray.disable `vertex;
(* Swap front and back buffers *)
GLFW.swapBuffers ~window:window;
(* Poll for and process events *)
GLFW.pollEvents ()
done;
GLFW.terminate ()
I suppose I didn't succeed to draw in the right buffer, but I didn't find any function allowing to draw in a specific buffer. Moreover, the program (except the shaders) works when I use glut.
Related
A Project I am working on involves me using glScissor, in some cases i need to perform a scissor on an area twice (or more), with the goal of only rendering what is within both scissor boxes.
The issue im running into is that the second scissor box just overrides the previous one, meaning only the last box set is used instead of both.
I have tried existing solutions such as setting scissor1, push matrix, enable scissor_test, set scissor2, disable scissor_test, popmatrix, disable scissor_test. As proposed here: glScissor() call inside another glScissor()
I could not get these to produce any difference, I had also tried glPushAttrib instead of matrix but still no difference.
Here is an example program I wrote for scissor testing, its compiled by g++ and uses freeglut, the scissoring takes place in display():
/*
Compile: g++ .\scissor.cpp -lglu32 -lfreeglut -lopengl32
*/
#include <GL/gl.h>//standard from mingw, already in glut.h - header library
#include <GL/glu.h>//standard from mingw, already in glut.h - utility library
#include <GL/glut.h>//glut/freeglut - more utilities, utility tool kit
void display();
void reshape(int, int);
void timer(int);
void init(){
glClearColor(0, 0, 0, 1);
}
int main(int argc, char **argv){
glutInit(&argc, argv);//init glut
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);//init display mode, add double buffer mode
//init window
glutInitWindowPosition(200, 100);//if not specified, it will display in a random spot
glutInitWindowSize(500, 500);//size
//create window
glutCreateWindow("Window 1");
//give glut a function pointer so it can call that function later
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutTimerFunc(0, timer, 0);//call certain function after a specified amount of time
init();
glutMainLoop();//once this loop runs your program has started running, when the loop ends the program terminates
}
float xPos = -10;
int state = 1;//1 = right, -1 = left
//our rendering happens here
void display(){
//clear previous frame
glClear(GL_COLOR_BUFFER_BIT);//pass in flag of frame buffer
//draw next frame below
glLoadIdentity();//reset rotations, transformations, ect. (resets coordinate system)
//we are using a model view matrix by default
//TEST
glEnable(GL_SCISSOR_TEST);
glScissor(0, 0, 100, 1000);
glPushMatrix();
glEnable(GL_SCISSOR_TEST);
glScissor(50, 0, 1000, 1000);
//assuming both scissors intersect, we should only see the square between 50 and 100 pixels
//draw
glBegin(GL_QUADS);//every set of 3 verticies is a triangle
//GL_TRIANGLES = 3 points
//GL_QUADS = 4 points
//GL_POLYGON = any amount of points
glVertex2f(xPos, 1);//the 2 is the amount of args we pass in, the f means theyr floats
glVertex2f(xPos, -1);
glVertex2f(xPos+2, -1);
glVertex2f(xPos+2, 1);
glEnd();//tell opengl your done drawing verticies
glDisable(GL_SCISSOR_TEST);
glPopMatrix();
glDisable(GL_SCISSOR_TEST);
//display frame buffer on screen
//glFlush();
glutSwapBuffers();//if double buffering, call swap buffers instead of flush
}
//gets called when window is reshaped
void reshape(int width, int hight){
//set viewport and projection
//viewport is a rectangle where everything is drawn, like its the window
glViewport(0, 0, width, hight);
//matrix modes: there is model view and projection, projection has depth
glMatrixMode(GL_PROJECTION);
glLoadIdentity();//reset current matrix after changing matrix mode
gluOrtho2D(-10, 10, -10, 10);//specify 2d projection, set opengl's coordinate system
glMatrixMode(GL_MODELVIEW);//change back to model view
}
//this like makes a loop
void timer(int a){
glutPostRedisplay();//opengl will call the display function the next time it gets the chance
glutTimerFunc(1000/60, timer, 0);
//update positions and stuff
//this can be done here or in the display function
switch(state){
case 1:
if(xPos < 8)
xPos += 0.15;
else
state = -1;
break;
case -1:
if(xPos > -10)
xPos -= 0.15;
else
state = 1;
break;
}
}
I tried following example solutions, such as push/pop matrix/attrib, but couldnt get anything to work
There is no first or second scissor box. There is just the scissor box. You can change the scissor box and that change will affect subsequent rendering. But at any one time, there is only one.
What you want is to use the stencil buffer to discard fragments outside of an area defined by rendering certain values into the stencil buffer.
I have an interesting bug that has been "bugging" me for a few days now.
I am currently using OpenGL to draw text on a screen. I am utilizing the OGLFT library to assist the drawing. This library actually uses the freetype2 library. I am actually not doing anything special with the text. I am only looking for monochromatic text.
Anyways, after implementing the library, I noticed that the text is only drawn correct when I have glStipple enabled. I believe that there is some interference issue between the OGLFT library and what I am enabling.
I was wondering if there is anyone out there with some experience on using the OGLFT library. I am posting a minimalist example of my code to demonstrate what is going on:
(Please note that there are some variables that are used to st the zoom factor of my glCanvas and the position of the camera and that this is only for 2D)
double _zoomX = 1.0;
double _zoomY = 1.0;
double _cameraX = 0;
double _cameraY = 0;
/* This function gets called everytime a draw routine is needed */
void modelDefinition::onPaintCanvas(wxPaintEvent &event)
{
wxGLCanvas::SetCurrent(*_geometryContext);// This will make sure the the openGL commands are routed to the wxGLCanvas object
wxPaintDC dc(this);// This is required for drawing
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT);
updateProjection();
OGLFT::Monochrome *testface = new OGLFT::Monochrome( "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", 8);
testface->draw(0, 0, "test");
glEnable(GL_LINE_STIPPLE);// WHen I comment out this line, the text is unable to be drawn
glLineStipple(1, 0b0001100011000110);
glBegin(GL_LINES);
glVertex2d(_startPoint.x, _startPoint.y);
glVertex2d(_endPoint.x, _endPoint.y);
glEnd();
glDisable(GL_LINE_STIPPLE);
SwapBuffers();
}
void modelDefinition::updateProjection()
{
// First, load the projection matrix and reset the view to a default view
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-_zoomX, _zoomX, -_zoomY, _zoomY, -1.0, 1.0);
//Reset to modelview matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0, 0, (double)this->GetSize().GetWidth(), (double)this->GetSize().GetHeight());
/* This section will handle the translation (panning) and scaled (zooming).
* Needs to be called each time a draw occurs in order to update the placement of all the components */
if(_zoomX < 1e-9 || _zoomY < 1e-9)
{
_zoomX = 1e-9;
_zoomY = _zoomX;
}
if(_zoomX > 1e6 || _zoomY > 1e6)
{
_zoomX = 1e6;
_zoomY = _zoomX;
}
glTranslated(-_cameraX, -_cameraY, 0.0);
}
Also one thing to note is that the code below the glEnable(GL_LINE_STIPPLE); is required. It is as if the glStipple needs to be drawn correctly for the text to be displayed correctly.
Looking through your code, I believe that your intention is to render it as a greyscale? If so, then you can simply use the OGLFT::Grayscale *testface = new OGLFT::Grayscale( "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", 8);
This will get what you need without having to worry about the issue that you posted. In fact, I recommend doing it this way too.
In my code I cannot draw a String at precise coordinates. Its upper left corner does not start at the given coordinates but somewhere else. However if I draw a rectangle from the same given coordinates it is well placed. How on earth can this behaviour be possible ?
Here is my code I call in the beforeShow() method :
Image photoBase = fetchResourceFile().getImage("Voiture_4_3.jpg");
Image watermark = fetchResourceFile().getImage("Watermark.png");
f.setLayout(new LayeredLayout());
final Label drawing = new Label();
f.addComponent(drawing);
// Image mutable dans laquelle on va dessiner (fond blancpar défaut)
Image mutableImage = Image.createImage(photoBase.getWidth(), photoBase.getHeight());
// Paint all the stuff
paintAll(mutableImage.getGraphics(), photoBase, watermark, photoBase.getWidth(), photoBase.getHeight());
drawing.getUnselectedStyle().setBgImage(mutableImage);
drawing.getUnselectedStyle().setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FIT);
// Save the graphics
// Save the image with the ImageIO class
long time = new Date().getTime();
OutputStream os;
try {
os = Storage.getInstance().createOutputStream("screenshot_" + Long.toString(time) + ".png");
ImageIO.getImageIO().save(mutableImage, os, ImageIO.FORMAT_PNG, 1.0f);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
And the paintAll method
public void paintAll(Graphics g, Image background, Image watermark, int width, int height) {
// Full quality
float saveQuality = 1.0f;
// Create image as buffer
Image imageBuffer = Image.createImage(width, height, 0xffffff);
// Create graphics out of image object
Graphics imageGraphics = imageBuffer.getGraphics();
// Do your drawing operations on the graphics from the image
imageGraphics.drawImage(background, 0, 0);
imageGraphics.drawImage(watermark, 0, 0);
imageGraphics.setColor(0xFF0000);
// Upper left corner
imageGraphics.fillRect(0, 0, 10, 10);
// Lower right corner
imageGraphics.setColor(0x00FF00);
imageGraphics.fillRect(width - 10, height - 10, 10, 10);
imageGraphics.setColor(0xFF0000);
Font f = Font.createTrueTypeFont("Geometos", "Geometos.ttf").derive(220, Font.STYLE_BOLD);
imageGraphics.setFont(f);
// Draw a string right below the M from Mercedes on the car windscreen (measured in Gimp)
int w = 0, h = 0;
imageGraphics.drawString("HelloWorld", w, h);
// Coin haut droit de la string
imageGraphics.setColor(0x0000FF);
imageGraphics.fillRect(w, h, 20, 20);
// Draw the complete image on your Graphics object g (the screen I guess)
g.drawImage(imageBuffer, 0, 0);
}
Result for w = 0, h = 0 (no apparent offset) :
Result for w = 841 , h = 610 (offset appears on both axis : there is an offset between the blue point near Mercedes M on the windscreen and the Hello World String)
EDIT1:
I also read this SO question for Android where it is advised to convert the dpi into pixel. Does it also applies in Codename One ? If so how can I do that ? I tried
Display.getInstance().convertToPixel(measureInMillimeterFromGimp)
without success (I used mm because the javadoc tells that dpi is roughly 1 mm)
Any help would be appreciated,
Cheers
Both g and imageGraphics are the same graphics created twice which might have some implications (not really sure)...
You also set the mutable image to the background of a style before you finished drawing it. I don't know if this will be the reason for the oddities you are seeing but I would suspect that code.
Inspired from Gabriel Hass' answer I finally made it work using another intermediate Image to only write the String at (0 ; 0) and then drawing this image on the the imageBuffer Image now at the right coordinates. It works but to my mind drawString(Image, Coordinates) should directly draw at the given coordinates, shouldn't it #Shai ?
Here is the method paintAll I used to solve my problem (beforeShow code hasn't changed) :
// Full quality
float saveQuality = 1.0f;
String mess = "HelloWorld";
// Create image as buffer
Image imageBuffer = Image.createImage(width, height, 0xffffff);
// Create graphics out of image object
Graphics imageGraphics = imageBuffer.getGraphics();
// Do your drawing operations on the graphics from the image
imageGraphics.drawImage(background, 0, 0);
imageGraphics.drawImage(watermark, 0, 0);
imageGraphics.setColor(0xFF0000);
// Upper left corner
imageGraphics.fillRect(0, 0, 10, 10);
// Lower right corner
imageGraphics.setColor(0x00FF00);
imageGraphics.fillRect(width - 10, height - 10, 10, 10);
// Create an intermediate image just with the message string (will be moved to the right coordinates later)
Font f = Font.createTrueTypeFont("Geometos", "Geometos.ttf").derive(150, Font.STYLE_BOLD);
// Get the message dimensions
int messWidth = f.stringWidth(mess);
int messHeight = f.getHeight();
Image messageImageBuffer = Image.createImage(messWidth, messHeight, 0xffffff);
Graphics messageImageGraphics = messageImageBuffer.getGraphics();
messageImageGraphics.setColor(0xFF0000);
messageImageGraphics.setFont(f);
// Write the string at (0; 0)
messageImageGraphics.drawString(mess, 0, 0);
// Move the string to its final location right below the M from Mercedes on the car windscreen (measured in Gimp)
int w = 841, h = 610;
imageGraphics.drawImage(messageImageBuffer, w, h);
// This "point" is expected to be on the lower left corner of the M letter from Mercedes and on the upper left corner of the message string
imageGraphics.setColor(0x0000FF);
imageGraphics.fillRect(w, h, 20, 20);
// Draw the complete image on your Graphics object g
g.drawImage(imageBuffer, 0, 0);
I have a mesh model (.ply file) and I have rendered it with VTK and changed the camera viewpoint.
From the new camera viewpoint how can I render an RGB and a depth image? I think this might be raytracing, but not sure
EDIT
I want to generate a real depth map, as opposed to just a visualization of the depth. The visualization can be achieved by using values in Z buffer and scaling between 0-255 but this does not provide real depth information.
To get the real world depth from the camera I have done the following:
double z = render_win->GetZbufferDataAtPoint(x,y);
worldPicker->Pick(x, y, z, renderer);
worldPicker->GetPickPosition(coords);
double euclidean_distance = sqrt(pow((coords[0] - cam_pos[0]), 2) + pow(coords[1] - cam_pos[1], 2) + pow(coords[2] - cam_pos[2], 2));
where cam_pos is the camera position in real world coordinates. This seems to do the trick
Here is a short few lines if you already have the application set up and rendering, this has to be after the mesh has rendered at least once
// Screenshot
vtkSmartPointer<vtkWindowToImageFilter> windowToImageFilter =
vtkSmartPointer<vtkWindowToImageFilter>::New();
windowToImageFilter->SetInput(renderWindow);
windowToImageFilter->SetMagnification(3); //set the resolution of the output image (3 times the current resolution of vtk render window)
windowToImageFilter->SetInputBufferTypeToRGBA(); //also record the alpha (transparency) channel
windowToImageFilter->Update();
vtkSmartPointer<vtkPNGWriter> writer =
vtkSmartPointer<vtkPNGWriter>::New();
writer->SetFileName("screenshot2.png");
writer->SetInputConnection(windowToImageFilter->GetOutputPort());
writer->Write();
This is from the VTK Public Wiki
To retrieve RGB image you can use vtkWindowToImageFilter class, allowing to read data from the vtkWindow.
For the Depth Image, i tried a solution which is to modify color on the mesh using vtkDepthSortPolyData , and again, read from the window.
See the example above :
# define VTK_CREATE(type, nom) vtkSmartPointer<type> nom = vtkSmartPointer<type>::New()
int main ()
{
VTK_CREATE(vtkPLYReader, reader);
reader->SetFileName ("mesh.ply");
reader->Update ();
// create depth sort algo
VTK_CREATE(vtkDepthSortPolyData, sort);
sort->SetInput(reader->GetOutput ());
// init stuff for rendering
VTK_CREATE(vtkPolyDataMapper, mapper);
VTK_CREATE(vtkActor, actor);
VTK_CREATE(vtkRenderer, rend);
VTK_CREATE(vtkRenderWindow, rw);
VTK_CREATE(vtkRenderWindowInteractor, inte);
VTK_CREATE(vtkCamera, cam);
sort->SetDirectionToBackToFront (); // camera direction
sort->SetCamera (cam); // set camera or runtime warning
sort->SortScalarsOn ();
sort->Update ();
mapper->SetScalarVisibility(true);
// limit max scalar (nb Color)
mapper->SetScalarRange (0, sort->GetOutput ()->GetNumberOfCells ());
mapper->SetInputConnection(sort->GetOutputPort ());
mapper->Update ();
actor->SetMapper(mapper);
actor->RotateY (59); // transform with a rotation to see depth
actor->GetProperty()->SetColor(1, 0, 0);
sort->SetProp3D (actor); // set the actor to the algo
rend->SetActiveCamera (cam);
rw->AddRenderer(rend);
rend->AddActor(actor);
inte->SetRenderWindow (rw);
inte->Initialize ();
// read depth image from vtk Window
VTK_CREATE (vtkWindowToImageFilter, screen);
screen->SetInput (rw);
screen->Update ();
// start rendering for visualization
rw->Render ();
// save the depth img as a png
VTK_CREATE(vtkPNGWriter, writer);
writer->SetFileName ("output.png");
writer->SetInputConnection (screen->GetOutputPort ());
writer->Write ();
inte->Start ();
return 0;
}
Tested on VTK 5.10.
I'm writing a program using OpenGl and Haskell that should draw a rectangle when and where the mouse is clicked. However, the program closes as soon as I click and before the rectangle is drawn.
import Graphics.Rendering.OpenGL
import Graphics.UI.GLUT
import Graphics.UI.GLUT.Callbacks.Window
main = do
(progname, _) <- getArgsAndInitialize
createWindow progname
keyboardMouseCallback $= Just myKeyboardMouseCallback
displayCallback $= display
mainLoop
myKeyboardMouseCallback key keyState modifiers (Position x y) =
case (key, keyState) of
(MouseButton LeftButton, Down) -> do
clear[ColorBuffer]
let x = x :: GLfloat
let y = y :: GLfloat
renderPrimitive Quads $ do
color $ (Color3 (1.0::GLfloat) 0 0)
vertex $ (Vertex3 (x::GLfloat) y 0)
vertex $ (Vertex3 (x::GLfloat) (y+0.2) 0)
vertex $ (Vertex3 ((x+0.2)::GLfloat) (y+0.2) 0)
vertex $ (Vertex3 ((x+0.2)::GLfloat) y 0)
flush
_ -> return ()
display = do
clear [ColorBuffer]
renderPrimitive Lines $ do
flush
Is there something causing the program to terminate early in one of the methods, or is this just the the computers way of telling me I can't do this?
You can't do what you are trying to do. In an OpenGL program, you are only allowed to issue draw commands in the OpenGL context. This context is always bound to a specific thread, and is only active in the body of the displayCallback in GLUT, because the other callbacks might potentially run from different threads.
However, you might say: On many/most platforms, a separate thread isn't used for input in GLUT, which means that you theoretically could issue drawing commands there. There are, however, many other things that play a role in where and when you can issue drawing commands; for example when the environment requires you to use double-buffered output where the buffers have to be flushed in very specific ways (e.g. when using EGL or GLX for X11).
In short: you should not issue drawing commands outside of the displayCallback. The whole reason for its existence is so that you can let GLUT handle the platform-specific stuff related to native frame buffer management, and it expects you to keep your code in the right places for it to work.
What you want to do instead is to create a mutable variable (Hey, you're using OpenGL; mutable state shouldn't be a worry to you) that indicates whether to draw the rectangle and where. Something like (Using Data.IORef):
main = do
-- ...
-- Create a mutable variable that stores a Bool and a pair of floats
mouseStateRef <- newIORef (False, (0, 0))
-- Pass a reference to the mutable variable to the callbacks
keyboardMouseCallback $= Just (myKeyboardMouseCallback mouseStateRef)
displayCallback $= (display mouseStateRef)
myKeyboardMouseCallback mouseStateRef key keyState modifiers (Position x y) =
case key of
MouseButton LeftButton -> do
-- Store the current mouse pressed state and coords in the reference
writeIORef mouseStateRef (keyState == Pressed, (x, y))
_ -> return ()
display mouseStateRef = do
clear [ColorBuffer]
-- Read the state stored in the mutable reference
(pressed, (x, y)) <- readIORef mouseStateRef
-- Draw the quad if the mouse button is pressed
when pressed . renderPrimitive Quads $ do
color $ (Color3 (1.0::GLfloat) 0 0)
vertex $ (Vertex3 (x::GLfloat) y 0)
vertex $ (Vertex3 (x::GLfloat) (y+0.2) 0)
vertex $ (Vertex3 ((x+0.2)::GLfloat) (y+0.2) 0)
vertex $ (Vertex3 ((x+0.2)::GLfloat) y 0)
flush