Back on creating textures. First, I finished the first version of that new renderer. Might still have some bug, but in general, it's done.
One of the objectives that we had with this new tool that we created was to create some smoke. A bit similar to this one:
The picture above is called Smoke Art, so creating images using smoke. This one is not generated by any computer. Other Smoke Art are listed there: http://www.bablotech.com/2008/12/14/20-amazing-smoke-art-pictures/, and some of them are really amazing.
With our new method, we try to reproduce such piece of art, but completely random. We don't try to recreate a scene or anything. Just create random smoke effects.
There's many ways to do such images, the most popular is probably with particles. You use thousands or millions of points and let them behave like smoke. But this approach is heavy to run and it's mostly for animation. For static images like ours, it's not very interesting to manage that amount of points to finally find the right image.
Our method still consists of placing points and some information of associated with points on the plane to partition it. We are still using the layers to create the effects and it works really well with smoke. So here's some of my favorite that I created today:
We still have some work to do to really control that new technique. And also some experimentation to be sure that the behavior is more stable. One thing that we might try is adding a bit of color to it instead of working in gray. But not drastic colors like red or green. Little variation from gray, but enough to see that there's more.
Please leave any comment or question that you have about these textures.
I use this blog to share (presentable) results from my research as a PhD student in computer science.
2011/10/04
smoke textures
2011/09/30
Changed my profil logo...
... just for the fun of doing it.
I had an idea last night about a simple drawing:
But hey... it's very simple and it includes a bit my passion for mathematics without being that obvious... but I don't think it's very complicated to understand! And more important... it's better than just my nickname written in green :)
I had an idea last night about a simple drawing:
But hey... it's very simple and it includes a bit my passion for mathematics without being that obvious... but I don't think it's very complicated to understand! And more important... it's better than just my nickname written in green :)
research news
I don't have new stuff to show right now, but I've been busy in the last week. I'm currently implementing a more dynamic version of my renderer. CUDA is very nice, but when you need to add quickly new modules or do some rapid tweaks, it's not the best solution. So, for now the plan is to render to have a slower renderer that would be easier to change and adapt. When we're sure of the features that we really want to keep and we'll know the full limitation of our system, an implementation in CUDA would be possible.
One of the reason to change the renderer is that I needed some C++ features like virtual functions, which is very useful for designing rapidly a new system. I think there's some language that allows to create virtual function in CUDA or OpenCL by simply adding some hidden piece of code.
If it doesn't exist, here's how I'd do it:
First, in CUDA, there's no function pointers. But if we take a look at how polymorphism works, it's really just a way to disguise procedural code. Actually, the whole object oriented programming scheme is just a way to disguise procedural code by hiding some information to the programmer so (s)he doesn't have to worry about it. Just like many other languages do (Java is the most popular about that one because it hides a lot of security features like buffer overflows done during the execution to avoid major problems).
So, if we have:
But, without any function pointers, we need to recreate that illusion. So, one way that can be done in CUDA/OpenCL, is to add a unique ID for each class. And each instance of that class will have that ID assigned in the constructor. So:
I think that such compilers exist already, but I never used one of them. But it's probably using a method similar to the one above to emulate the virtual tables.
And for those of you who didn't know how polymorphism worked, now you have a better idea of the process the compiler has to do to convert classes and their virtual functions in machine bytecode. So, I hoped that post helps a bit for that. Otherwise, there's a couple of resources available on the web that would clearly describe that process.
If any of you know a (free if possible) compiler that convert basic C++ code in CUDA or OpenCL, but also has integrated some of the features of those languages like the synchronization between threads of the same bloc and atomic operations, I'd really like to see that and use it eventually. It must work on Linux!
One of the reason to change the renderer is that I needed some C++ features like virtual functions, which is very useful for designing rapidly a new system. I think there's some language that allows to create virtual function in CUDA or OpenCL by simply adding some hidden piece of code.
If it doesn't exist, here's how I'd do it:
First, in CUDA, there's no function pointers. But if we take a look at how polymorphism works, it's really just a way to disguise procedural code. Actually, the whole object oriented programming scheme is just a way to disguise procedural code by hiding some information to the programmer so (s)he doesn't have to worry about it. Just like many other languages do (Java is the most popular about that one because it hides a lot of security features like buffer overflows done during the execution to avoid major problems).
So, if we have:
class AThen this piece of code is actually converted into something that look basically like this:
{
private:
int value;
public:
A(void);
virtual ~A(void);
virtual void test(T param1, U param2);
};
// prototypesAnd then, with a subclass B, we have:
struct class_A;
void __class_A_constructor(struct class_A *this);
void __class_A_destructor(struct class_A *this);
void __class_A_test(struct class_A *this, T param1, U param2);
struct class_A_virtual_table
{
void (*class_A_destructor)(struct class_A *this);
void (*class_A_test)(struct class_A *this, T param1, U param2);
};
// create a single instance of the virtual table and assign the values for the function pointersstruct class_A_virtual_table class_A_virtual_table_only_instance_needed =
{
__class_A_destructor,
__class_A_test
};
struct class_A
{
class_A_virtual_table *VT;
int value;
};
void __class_A_constructor(struct class_A *this)
{
this->value = 0; // or some other default value
this->VT = &class_A_virtual_table_only_instance_needed;
}
void __class_A_destructor(struct class_A *this)
{
// stuff to destroy
}
void __class_A_test(struct class_A *this, T param1, U param2)
{
// stuff to test
}
// virtual functions
void virtual_class_A_destructor(struct class_A *this)
{
this->VT.class_A_destructor(this);
}
void virtual_class_A_test(struct class_A*this, T param1, U param2)
{
this->VT.class_A_test(this, param1, param2);
}
class B: public A
{
private:
double value;
public:
B(void);
~B(void);
void test(T param1, U param2); // version of test but for class B
void function_in_B(void);
};
int main(void)Then, all of this become:
{
B b;
A *a = &b;
a->test(1, 2); // let way that type T and U are integers...
b.function_in_B();
}
struct class_BSo, as you can see, polymorphism is using function pointers to create the illusion that the right function is called each time.
{
struct class_A super;
double value;
};
// prototypes for class B
void __class_B_constructor(struct class_B *this);
void __class_B_destructor(struct class_B *this);
void __class_B_test(struct class_B *this, T param1, U param2);
void __class_B_function_in_B(struct class_B *this);
// virtual table for B, with the virtual functions for B
struct class_A_virtual_table class_B_virtual_table_only_instance_needed =
{
__class_B_destructor,
__class_B_test
};
void __class_B_constructor(struct class_B *this)
{
__class_B_constructor(&(this->super));
this->VT = &class_B_virtual_table_only_instance_needed; // replace the virtual table
this->value = 0.0; // or some other default value
}
void __class_B_destructor(struct class_B *this)
{
// stuff to destroy in B
__class_A_destructor(&(this->super)); // then, destroy the stuff in the parent
}
void __class_B_test(struct class_B *this, T param1, U param2)
{
// stuff to test, but for B
}
void __class_B_function_in_B(struct class_B *this)
{
// whatever that function does!
}
int main(void)
{
struct class_B b;
__class_B_constructor(&b);
struct class_A *a = &(b.super); // the address of the parent in struct class_B
virtual_class_A_test(a, 1, 2);
__class_B_function_in_B(&b);
__class_B_destructor(&b);
}
But, without any function pointers, we need to recreate that illusion. So, one way that can be done in CUDA/OpenCL, is to add a unique ID for each class. And each instance of that class will have that ID assigned in the constructor. So:
enum CLASS_IDS { CLASS_A_ID, CLASS_B_ID, ..., CLASS_X_ID };Finally, write the virtual functions like this:
struct class_A
{
int ID;
int value;
};
void __class_A_constructor(struct class_A *this)
{
this->ID = CLASS_A_ID;
this->value = 0; // or some other default value
}
struct class_B
{
struct class_A super;
double value;
};
void __class_B_constructor(struct class_B *this)
{
__class_A_constructor(&(this->super)); // always call the parent constructor first!
this->ID = CLASS_B_ID; // overwrite the ID
this->value = 0.0; // or some other default value
}
void virtual_class_A_destructor(struct class_A *this)So, with a switch statement, it's possible to replace the virtual table. So, a compiler that would be able to take C++ code and convert it in CUDA/OpenCL would be able to do polymorphism with that approach. It's much more slower than a function pointer, but the result of the computation would be the same.
{
switch(this->ID)
{
case CLASS_A_ID:
__class_A_destructor(this);
break;
case CLASS_B_ID:
__class_B_destructor((class_B*)this);
break;
// ...
case CLASS_X_ID:
__class_X_destructor((class_X*)this);
break;
};
}
I think that such compilers exist already, but I never used one of them. But it's probably using a method similar to the one above to emulate the virtual tables.
And for those of you who didn't know how polymorphism worked, now you have a better idea of the process the compiler has to do to convert classes and their virtual functions in machine bytecode. So, I hoped that post helps a bit for that. Otherwise, there's a couple of resources available on the web that would clearly describe that process.
If any of you know a (free if possible) compiler that convert basic C++ code in CUDA or OpenCL, but also has integrated some of the features of those languages like the synchronization between threads of the same bloc and atomic operations, I'd really like to see that and use it eventually. It must work on Linux!
Labels:
C++,
C++ to CUDA,
C++ to OpenCL,
classes,
cuda,
function pointers,
GPGPU,
GPU,
inheritance,
Khronos,
new renderer,
nvidia,
OpenCL,
polymorphism,
programming,
switch statement,
virtual functions
2011/08/25
first pattern
So, yesterday I mentioned two steps that we need to work on to finish the hierarchy project. And one of them is to work on patterns or structures to show what is possible to do with that product.
Today, I managed to to a first structure, a flower. Very simple to do. Just needed some adjustment first, but I got that result in few minutes. So here it is:
Naturally, I just showed the final product. I had other images created before I managed to do the right effect that I wanted. I think that this is a nice preview of what that product can do.
Let me know what you think about that output!
Today, I managed to to a first structure, a flower. Very simple to do. Just needed some adjustment first, but I got that result in few minutes. So here it is:
Naturally, I just showed the final product. I had other images created before I managed to do the right effect that I wanted. I think that this is a nice preview of what that product can do.
Let me know what you think about that output!
Labels:
cuda,
flower,
hierarchy,
pattern,
procedural texturing,
rendering,
texture,
voronoi diagram
2011/08/24
Hierarchy textures
So, it's been a while. I was so busy at SIGGRAPH that I never had the time to share anything.
In this post, I'm showing you some of the last textures I've been working on. These are build as a hierarchy. We use again our variation of the Voronoi diagram to create weird shapes. But this time, instead of using simply one level, we introduce many levels.
On the first level, again, the Voronoi cells are computed and once we know in which cell we are, if that cell has a sub-level, we can then continue the visit in the structure into that sub-level. Each level has can have a small or big influence on the final color of the pixel.
So, here's some outputs:
One of the first output made. It has two cells on the first level. One is the circle-like shape in the middle and then the rest. In the "rest", there's a sub level with a simple small division of the plane in two.
Exactly as the previous one, but here, there's a sub-level in the circle-like shape. As you can see, the fact that there's a new sub-level only affects the part where that sub-level is.
The actual first output that I got with the hierarchy.
In the next images, I start playing with colors inside the cells. Naturally, all of these images where made from random point distribution.
Finally, there's two big step to do before we consider that project finished. First, we want to investigate various patterns. So, how can we do a particular shape for a cell. For this part, we don't need the hierarchy because we know it works. When we are able to control properly the patterns, we will be able to used them at various level.
Second, we want to be more dynamic for the color. Right now, each cell use a function f:[0;1]->[0;1] to control its value that will influence all the other levels. But those functions are a bit static. I can add more, but it will never be enough. So we turn to use something like the shaders in OpenGL. Literally, each cell could have its own function (coded in CUDA-C) and that function would be used to control the contribution of that cell and its sub-level to the final color of the pixel.
In this post, I'm showing you some of the last textures I've been working on. These are build as a hierarchy. We use again our variation of the Voronoi diagram to create weird shapes. But this time, instead of using simply one level, we introduce many levels.
On the first level, again, the Voronoi cells are computed and once we know in which cell we are, if that cell has a sub-level, we can then continue the visit in the structure into that sub-level. Each level has can have a small or big influence on the final color of the pixel.
So, here's some outputs:
One of the first output made. It has two cells on the first level. One is the circle-like shape in the middle and then the rest. In the "rest", there's a sub level with a simple small division of the plane in two.
Exactly as the previous one, but here, there's a sub-level in the circle-like shape. As you can see, the fact that there's a new sub-level only affects the part where that sub-level is.
The actual first output that I got with the hierarchy.
In the next images, I start playing with colors inside the cells. Naturally, all of these images where made from random point distribution.
In these images, I simply played with the hierarchy. Each cell has a random chance to get a sub-level and so on. Until a maximal depth was reached. In some of them, I played also with the feature that at each level, you can influence the final color by accumulating a value.
Finally, there's two big step to do before we consider that project finished. First, we want to investigate various patterns. So, how can we do a particular shape for a cell. For this part, we don't need the hierarchy because we know it works. When we are able to control properly the patterns, we will be able to used them at various level.
Second, we want to be more dynamic for the color. Right now, each cell use a function f:[0;1]->[0;1] to control its value that will influence all the other levels. But those functions are a bit static. I can add more, but it will never be enough. So we turn to use something like the shaders in OpenGL. Literally, each cell could have its own function (coded in CUDA-C) and that function would be used to control the contribution of that cell and its sub-level to the final color of the pixel.
Labels:
cuda,
cuda-c,
GPU,
hierarchy,
opengl,
procedural texturing,
shader,
SIGGRAPH,
texture,
voronoi diagram
2011/08/05
SIGGRAPH
This week, I will be at SIGGRAPH in Vancouver. I will try to share some of the stuff I will see on the blog. I hope to be able to talk about the last stuffs in procedural texturing and rendering.
2011/08/04
Twin Pictures DEMO
I decided to put a demo on the market of Twin Pictures. In that free version, the only difference with the paid version is that you cannot change the pictures. But all the other effects are there.
Here's the link: https://market.android.com/details?id=com.blogspot.widgg_research.twin_demo
If you like it, you will definitely like the full version where you can change the images!
Here's the link: https://market.android.com/details?id=com.blogspot.widgg_research.twin_demo
If you like it, you will definitely like the full version where you can change the images!
Labels:
Android,
demo,
live-wallpaper,
market,
trial,
twin pictures
Subscribe to:
Posts (Atom)