Román Cortés http://www.romancortes.com/blog Sat, 31 Mar 2012 22:15:05 +0000 http://wordpress.org/?v=2.3.3 en The Entry I Didn’t Submitted To Js1k http://www.romancortes.com/blog/the-entry-i-didnt-submitted-to-js1k/ http://www.romancortes.com/blog/the-entry-i-didnt-submitted-to-js1k/#comments Sat, 31 Mar 2012 22:15:05 +0000 Román Cortés http://www.romancortes.com/blog/the-entry-i-didnt-submitted-to-js1k/

If you are reading this post, you probably know about the love themed js1k competition. I tried to submit a new entry before the deadline on March 14th, but I failed to do it.

I was able to complete it on time, but I noticed a couple of problems during the last minute, so I told Kuvos, organizer of js1k to cancel its release.

The first and most notable problem was speed. I developed the thing on my recently bought high-end PC, and I had the error of not testing it on any older machine during development. In the new PC everything was fast and full framerate, but then I tested in my other machines, I noticed it was overkill, unacceptably slow and totally killing the visual effect.

So I’m publishing now 2 versions of the effect:

Clouds Low Res (recommended)

Clouds High Res (original version, only for high-end PCs)

Be warned that even the low res version might be too much for some old computers and for some browsers. And note it is a bit over 1kb, but it fits in less than 1kb after using JSCrush by aivopaas.

Ok, now I’m going to try to describe a bit what I did:

Making a texture

Perlin noise is specially well suited for clouds, as the own Ken Perlin explains in this presentation (a totally recommended read). Just to summarize how to go from Perlin noise to something resembling clouds:

The only problem with Perlin noise for js1k entries is that a perlin noise implementation is a bit too big for 1kb. It fits in 1kb, but it would not leave too much room for other code.

So I tried to make a texture similar to Perlin noise but by other method: a random walk. In the Wikipedia article about it you will find nice animations showing how it works. The only difference in my implementation, is that I don’t fill a full pixel at each position the walk traverses, but I just a bit, just like if I were using a non-full opacity brush, and this way it ends pretty similar to Perlin.

Random walk implementation details

The random walk needs a PRNG (pseudorandom number generator). As I wanted to create a cloud scene being always the same, I needed a PRNG with the ability to set its seed, and this way creating always on each run the same serie of (pseudo) random numbers.

Now a little problem was that Javascript’s Math.random doesn’t have the possibility to set the seed (not to mention each Math.random implementation would probably produce different results even with the same seed). So, I needed to implement my own PRNG, and to maintain it as little as possible… in js1k each byte counts.

This was my first implementation of the random walk with its own PRNG in 74 bytes:

m=Math.cos;for(x=y=n=9e4;n--;y+=m(x+=m(y*x)))a.fillRect(x%128,y%128,1,.1);

The result was this texture:

The problem with this implementation was that it was relying in Math.cos, and Math.cos doesn’t produce the same results across different browsers, as shown in the Ecmascript spec:

15.8.2.7 cos (x)

Returns an implementation-dependent approximation to the cosine of x.

So, the texture works the same on each run in the same browser, but in some browsers you get different results… so, next try:

for(x=y=l=i=9e4;i--;)l=l*i+i>>>1,x+=l%3-1,y+=1-(l>>4)%3,a.fillRect(x%128,y%128,1,.1);

It takes 11 bytes more up to 85, and we would not have set Math.cos in a single letter variable for posterior use as in the previous example, so in the end it is like occuping around 20 bytes more (a lot in js1k size terms). But it always renders this exact same result across all browsers:

Please note that the PRNG I created here is of extremely low quality, so while it is valid for my purpose it is not recommended for use in anything else. Search for high quality Javascript implementations of PRNGs with configurable seed - like Mersenne twister - if you need one for your own projects.

The Cloud Brush

Here I did the same as in my Christmas Tree from a previous js1k competition. First I create a cloud brush using the previously created texture:

Painting the brush multiple times:

Drawing the clouds scene

I use the noise texture again to decide where to paint a cloud brush. If the texture at (x, y) is above a threshold level, I paint the brush at a position determined by x and y.

I consider y determine how far are the clouds. Further brushes are painted first so nearer are painted on top. To add a perspective sensation, further clouds are painted littler than nearer ones.

Finally, since I’m using only one brush, if it is repeated along a totally straight line it would be very noticeable the repetition causing visible linear patterns. What I do is to use again the noise texture to offset a bit the final positionto paint the brush, and this way I avoid those visual artifacts.

Parallax displacement

Drawing the clouds scene takes almost all the time in the precomputation process, several seconds in the high resolution version even in a high end computer, so it is not possible to render it realtime with canvas right now.

What I did was to pre-render it into several layers (multiple canvases). I used 22 in the high res version, 11 in the low res version. Each layer contains a big amount of brushes painted on it, grouped by the distance to the camera:

Moving the layers at different speeds, as I explained it in the CSS 3D Meninas post, cause the parallax 3d effect.

Heart-shaped rainbow

Could I have been more kitsch? Not sure, but it fits the love theme of the competition.

What I did was to draw multiple bezier curves, all with very few opacity and some displacement to cause the blurry effect common in rainbows and I used a canvas lighter composite operation to enhance its realism.

That’s it!

]]>
http://www.romancortes.com/blog/the-entry-i-didnt-submitted-to-js1k/feed/
1k Rose http://www.romancortes.com/blog/1k-rose/ http://www.romancortes.com/blog/1k-rose/#comments Sun, 05 Feb 2012 22:26:17 +0000 Román Cortés http://www.romancortes.com/blog/1k-rose/ Rose

I’ve participated in the love themed 4th edition of js1k. My submission is a static image, a procedurally generated 3d rose. You can take a look of it here.

It is made by Monte Carlo sampling of explicit piecewise 3d surfaces. I’m going to try to explain all a bit in this article.

A short note on Monte Carlo methods

Monte Carlo methods are incredible powerful tools. I use them all the time, for a lot of kinds of function optimization and sampling problems, and they are almost like magic when you have more CPU time than time for designing and coding algorithms. In the case of the rose, it was very useful for code size optimization.

If you don’t know much about Monte Carlo methods, you could read about them in this excellent Wikipedia article.

Explicit surfaces and sampling/drawing

To define the shape of the rose I’m using multiple explicit-defined surfaces. I use a total of 31 surfaces: 24 petals, 4 sepals (the thin leaves around the petals), 2 leaves and 1 for the rose stick.

So, how they work these explicit surfaces? It is easy, I’m going to provide a 2d example:

First I define the explicit surface function:

function surface(a, b) {  // I'm using a and b as parameters ranging from 0 to 1.
    return {
        x: a*50,
        y: b*50
    };
    // this surface will be a square of 50x50 units of size
}

Then, the code for drawing it:

var canvas = document.body.appendChild(document.createElement("canvas")),
    context = canvas.getContext("2d"),
    a, b, position;

// Now I'm going to sample the surface at .1 intervals for a and b parameters:

for (a = 0; a < 1; a += .1) {
    for (b = 0; b < 1; b += .1) {
        position = surface(a, b);
        context.fillRect(position.x, position.y, 1, 1);
    }
}

The result:

Now, lets try more dense sampling intervals (littler intervals = more dense sampling):

As you can see, as you sample more and more dense, points get closer and closer, up to the density when the distance from a point to their neighbours is littler than a pixel, and the surface is fully filled on screen (see 0.01). After that, making it more dense doesn’t cause much visual difference, as you will be just drawing on top of areas that are already filled (compare results of 0.01 and 0.001).

Ok, now lets redefine the surface function to draw a circle. There are multiple ways to do it, but I will use this formula: (x-x0)^2 + (y-y0)^2 < radius^2 where (x0, y0) is the center of the circle:

function surface(a, b) {
    var x = a * 100,
        y = b * 100,
        radius = 50,
        x0 = 50,
        y0 = 50;

    if ((x - x0) * (x - x0) + (y - y0) * (y - y0) < radius * radius) {
        // inside the circle
        return {
            x: x,
            y: y
        };
    } else {
        // outside the circle
        return null;
    }
}

As I’m rejecting the points outside the circle, I should add a conditional in the sampling:

if (position = surface(a, b)) {
    context.fillRect(position.x, position.y, 1, 1);
}

Result:

As I said, there are different ways to define a circle, and some of them doesn’t need rejection in the sampling. I’m going to show one way, but just as a note; I will not keep using it later in the article:

function surface(a, b) {
    // Circle using polar coordinates
    var angle = a * Math.PI * 2,
        radius = 50,
        x0 = 50,
        y0 = 50;

    return {
        x: Math.cos(angle) * radius * b + x0,
        y: Math.sin(angle) * radius * b + y0
    };
}

(this method requires a denser sampling to fill the circle than the previous one)

Ok, now lets deform the circle so it looks more like a petal:

function surface(a, b) {
    var x = a * 100,
        y = b * 100,
        radius = 50,
        x0 = 50,
        y0 = 50;

    if ((x - x0) * (x - x0) + (y - y0) * (y - y0) < radius * radius) {
        return {
            x: x,
            y: y * (1 + b) / 2 // deformation
        };
    } else {
        return null;
    }
}

Result:

Ok, now this looks much more like the shape of a petal of a rose. I suggest you to play a bit with deformations. You can use any imaginable math function you want, add, subtract, multiply, divide, sin, cos, pow… anything. Just experiment a bit modifying the function, and lots of shapes will appear (some more interesting, some less).

Now I want to add some color to it, so I’m going to add color data to the surface:

function surface(a, b) {
    var x = a * 100,
        y = b * 100,
        radius = 50,
        x0 = 50,
        y0 = 50;

    if ((x - x0) * (x - x0) + (y - y0) * (y - y0) < radius * radius) {
        return {
            x: x,
            y: y * (1 + b) / 2,
            r: 100 + Math.floor((1 - b) * 155), // this will add a gradient
            g: 50,
            b: 50
        };
    } else {
        return null;
    }
}

for (a = 0; a < 1; a += .01) {
    for (b = 0; b < 1; b += .001) {
        if (point = surface(a, b)) {
            context.fillStyle = "rgb(" + point.r + "," + point.g + "," + point.b + ")";
            context.fillRect(point.x, point.y, 1, 1);
        }
    }
}

Result:

And here it is, a petal with color!

3D surfaces and perspective projection

Defining 3d surfaces is straightforward: just add a z property to the surface function. As an example, I’m going to define a tube/cylinder:

function surface(a, b) {
    var angle = a * Math.PI * 2,
        radius = 100,
        length = 400;

    return {
        x: Math.cos(angle) * radius,
        y: Math.sin(angle) * radius,
        z: b * length - length / 2, // by subtracting length/2 I have centered the tube at (0, 0, 0)
        r: 0,
        g: Math.floor(b * 255),
        b: 0
    };
}

Now, to add perspective projection, first we have to define a camera:

I will place my camera at (0, 0, cameraZ), I will call “perspective” to the distance from the camera to the canvas. I will consider my canvas is in the x/y plane, centered at (0, 0, cameraZ + perspective). Now, each sampled point will be projected into the canvas:

var pX, pY,  // projected on canvas x and y coordinates
    perspective = 350,
    halfHeight = canvas.height / 2,
    halfWidth = canvas.width / 2,
    cameraZ = -700;

for (a = 0; a < 1; a += .001) {
    for (b = 0; b < 1; b += .01) {
        if (point = surface(a, b)) {
            pX = (point.x * perspective) / (point.z - cameraZ) + halfWidth;
            pY = (point.y * perspective) / (point.z - cameraZ) + halfHeight;
            context.fillStyle = "rgb(" + point.r + "," + point.g + "," + point.b + ")";
            context.fillRect(pX, pY, 1, 1);
        }
    }
}

This results in:

Z-buffer

A z-buffer is a pretty common technique in computer graphics, useful to paint points closer to the camera on top of points that have been painted further to it. It works by maintaining an array with the closer z drawn per pixel of an image.

This is the visualized z-buffer of the rose, with black as far to the camera, white close to it.

The implementation:

var zBuffer = [],
    zBufferIndex;

for (a = 0; a < 1; a += .001) {
    for (b = 0; b < 1; b += .01) {
        if (point = surface(a, b)) {
            pX = Math.floor((point.x * perspective) / (point.z - cameraZ) + halfWidth);
            pY = Math.floor((point.y * perspective) / (point.z - cameraZ) + halfHeight);
            zBufferIndex = pY * canvas.width + pX;
            if ((typeof zBuffer[zBufferIndex] === "undefined") || (point.z < zBuffer[zBufferIndex])) {
                zBuffer[zBufferIndex] = point.z;
                context.fillStyle = "rgb(" + point.r + "," + point.g + "," + point.b + ")";
                context.fillRect(pX, pY, 1, 1);
            }
        }
    }
}

Let’s rotate the cylinder

You can use any vector rotation method. In the case of the rose I used Euler rotations. Let’s implement a rotation around the Y axis:

function surface(a, b) {
    var angle = a * Math.PI * 2,
        radius = 100,
        length = 400,
        x = Math.cos(angle) * radius,
        y = Math.sin(angle) * radius,
        z = b * length - length / 2,
        yAxisRotationAngle = -.4, // in radians!
        rotatedX = x * Math.cos(yAxisRotationAngle) + z * Math.sin(yAxisRotationAngle),
        rotatedZ = x * -Math.sin(yAxisRotationAngle) + z * Math.cos(yAxisRotationAngle);

    return {
        x: rotatedX,
        y: y,
        z: rotatedZ,
        r: 0,
        g: Math.floor(b * 255),
        b: 0
    };
}

Result:

Monte Carlo sampling

I’ve been using during the article interval based sampling. It requires the setting of a proper interval for each surface. If the interval is big, it render fast but it can end with holes in the surface that has not been filled. On the other hand, if the interval is too little, the time for rendering increments up to prohibitive quantities.

So, let’s switch to Monte Carlo sampling:

var i;

window.setInterval(function () {
    for (i = 0; i < 10000; i++) {
        if (point = surface(Math.random(), Math.random())) {
            pX = Math.floor((point.x * perspective) / (point.z - cameraZ) + halfWidth);
            pY = Math.floor((point.y * perspective) / (point.z - cameraZ) + halfHeight);
            zBufferIndex = pY * canvas.width + pX;
            if ((typeof zBuffer[zBufferIndex] === "undefined") || (point.z < zBuffer[zBufferIndex])) {
                zBuffer[zBufferIndex] = point.z;
                context.fillStyle = "rgb(" + point.r + "," + point.g + "," + point.b + ")";
                context.fillRect(pX, pY, 1, 1);
            }
        }
    }
}, 0);

Now, a and b parameters are set as 2 random values. Sampling enough points, the surface will be complete filled this way. I’m drawing 10,000 points each time and then letting the screen update thanks to the interval.

As a side note, the full filling of a surface is only ensured if the pseudorandom number generator is of good quality. In some browsers, Math.random is implemented with a linear congruential generator, and this may lead to problems with some surfaces. If you are in the need of a good PRNG for sampling, you can use high quality ones like Mersenne Twister (there are JS implementations for it), or the cryptographic random generators available in some browsers. It is also very advisable to use low-discrepancy sequences.

Final notes

To complete the rose, each part of the rose, each surface, is rendered at the same time. I added a third parameter for the function that selects the part of the rose to return a point from. Mathematically it is a piecewise function, where each piece represents a part of the rose. In the case of the petals, I used rotations and streching/deformation to create all the petals. Everything is done with by mixing the concepts exposed in the article.

While sampling explicit surfaces by sampling is a very well known method, and one of the oldest methods for 3d graphics, my approach of piecewise/Monte Carlo/z-buffer has been probably very few times used for artistical purposes the way I did. Not exactly very innovative, and not useful in real life scenarios, but it fits very good in the context of js1k where simplicity and minimal size are desirable.

With this article I really hope to inspire readers interested in computer graphics to experiment and have fun with different rendering methods. There is a whole world in graphics, and it is amazing to research and play on it.

]]>
http://www.romancortes.com/blog/1k-rose/feed/
This blog is for sale http://www.romancortes.com/blog/this-blog-is-for-sale/ http://www.romancortes.com/blog/this-blog-is-for-sale/#comments Fri, 01 Apr 2011 07:35:36 +0000 Román Cortés http://www.romancortes.com/blog/this-blog-is-for-sale/ I’ve decided to sell this blog, domain and content. It is a very personal blog, as it contains my surnames (Roman Cortes), but it is already popular and it would be perfect for SEO purposes. I’ve PR5 and PR6 blog posts, and a good amount of visitors per day.Since it is so personal, I’m selling also, as a pack, my Twitter account, my Gmail account, Facebook account, my Spanish ID and my passport.The starting price is $1 USD. If you are interested, please write a comment here and/or send me a message to my contact form. I could sell you also some of my clothes and anything you would need to assume my personality.

]]>
http://www.romancortes.com/blog/this-blog-is-for-sale/feed/
Trabajar para Motorola http://www.romancortes.com/blog/trabajar-para-motorola/ http://www.romancortes.com/blog/trabajar-para-motorola/#comments Thu, 10 Feb 2011 07:59:17 +0000 Román Cortés http://www.romancortes.com/blog/trabajar-para-motorola/ Hoy se cumple mi primer mes trabajando para Motorola Mobility. Uno de los equipos de desarrollo/ingeniería del Silicon Valley me contactó hace unos 3 meses con la propuesta y me pareció un proyecto tan interesante que no pude evitar aceptarla.

Esta semana próxima, desde el 14 al 17 de febrero, se celebra en Barcelona, España, el Mobile World Congress, al que varios de los equipos de ingeniería Motorola Mobility asistirán. Dichos equipos están en plena expansión y en busca de desarrolladores con talento, y me han pedido que transmita este mensaje:

Several of Motorola Mobility engineering teams will be at the Mobile World Congress in Barcelona from February 14 to 17 for a recruiting event.  We are looking for passionate and very high profile web developers.  Send CV to TalentAcquisition@Motorola.com for consideration.

Me gustaría invitaros a intentarlo, yo la verdad es que estoy encantado con el trabajo. El proyecto en el que trabajo es interesantísimo. Los compañeros de trabajo que he conocido hasta ahora son personas muy agradables y de gran talento. Las condiciones de trabajo son excelentes. Básicamente todo lo que puedo decir del trabajo es positivo, y por ello no puedo más que recomendarlo.

Yo estaré algunos de esos días por Barcelona también, para los que estéis interesados es posible que nos conozcamos allá.

¡Mucha suerte a todos los interesados!

]]>
http://www.romancortes.com/blog/trabajar-para-motorola/feed/
I don’t want a chrome anymore http://www.romancortes.com/blog/i-dont-want-a-chrome-anymore/ http://www.romancortes.com/blog/i-dont-want-a-chrome-anymore/#comments Sun, 19 Dec 2010 06:37:10 +0000 Román Cortés http://www.romancortes.com/blog/i-dont-want-a-chrome-anymore/ EDIT: After some commentaries, I’ve found that the idea exposed in this post was already developed. Being ashamed by futility and stupidity of the post, I’m now changing it and publishing something else: one of the very first drawings I’ve saved from my childhood:

ZX Spectrum

I did it when I was 3 years old, and I was definitely and completely obsessed with the tiny home computer. It was drawn at school, and it made my teacher to ask my mother what it was - in 1984 computers were not a very common thing.

Ok, let’s try to add something more to distract from the fact the previous content of this post was ridiculous:

Rey azul

Look at this beatiful Magi King! At Spain, it is not only Santa Claus who brings gifts to good children, but mostly the Three Kings. They take a bit more to reach children houses (January 6th), and I suppose it is mostly because their camel based ground way of transport.

]]>
http://www.romancortes.com/blog/i-dont-want-a-chrome-anymore/feed/
How I did the 1kb Christmas Tree http://www.romancortes.com/blog/how-i-did-the-1kb-christmas-tree/ http://www.romancortes.com/blog/how-i-did-the-1kb-christmas-tree/#comments Wed, 15 Dec 2010 18:06:29 +0000 Román Cortés http://www.romancortes.com/blog/how-i-did-the-1kb-christmas-tree/ Christmas Tree

JS1k is a really nice contest for coding tiny 1 kb Javascript programs and try to do something nice in that few available space. In its second edition, all the entries must be Christmas themed.

My contribution to the contest has been a 3D Christmas tree (note it doesn’t work in IE, and works slow in any current browser except in Chrome). I’m really lazy to write articles explaining how I do my visual effects, but in this case a lot of people are asking me to do it, so let’s try it in a visual way:

------

Finally, some size optimization tricks

I used several tricks to make the code fit in 1 kb. The most of them are the usual tricks for reducing Javascript code size, like renaming variables to single character names, removing white spaces, unnecesary semi-colons and so on.

It is also very common  to assign functions you use more than one time to variables to avoid the repetition. For example, if I do r=Math.random;, I can call r() each time I need a random number.

I used some few math tricks, like using cos(angle+11) to approximate sin(angle) and modular arithmetic.

Finally, I’ve used some other tricks like reusing functions. A function does different things depending on if it received parameters or not. This saves some few bytes from writing again “function”.

Writing code for limited size competitions is mostly like a puzzle or logical game. In the most of the cases there is not a common rule to do it, but just thinking and trying different ways to achieve the same goal in less space. It is usually possible to fit 5 or 6 kb of normal code in 1 kb if you try it and don’t give up.

]]>
http://www.romancortes.com/blog/how-i-did-the-1kb-christmas-tree/feed/
Relighting Sylvia http://www.romancortes.com/blog/relighting-sylvia/ http://www.romancortes.com/blog/relighting-sylvia/#comments Mon, 28 Jun 2010 18:07:47 +0000 Román Cortés http://www.romancortes.com/blog/relighting-sylvia/ Relighting Sylvia

Inspired by the research of Paul Debevec on photographic relighting, I’ve created this Flash experiment showing a real-time relighted scene of my girlfriend with her netbook. Watch it here. Please note it requires a fast computer to run at full framerate.

The scene has been captured without any special hardware, just a common reflex camera (Nikon D70) with its remote, a tripod and the netbook as the only light source. The time for shooting all the photos required for the relighting process was about 3-4 minutes, where Silvia — the Spanish for Sylvia — stayed amazingly static for the purpose.

I’ve really enjoyed the development of this experiment because it mixes the most of my hobbies: photography, art, coding, technology, and also it has been a great opportunity to involve my girlfriend in any of my experiments.

]]>
http://www.romancortes.com/blog/relighting-sylvia/feed/
My Trip To Germany http://www.romancortes.com/blog/my-trip-to-germany/ http://www.romancortes.com/blog/my-trip-to-germany/#comments Sun, 20 Jun 2010 12:28:43 +0000 Román Cortés http://www.romancortes.com/blog/my-trip-to-germany/ Few months ago I was invited to Merz Akademy by Olia Lialina to teach a CSS3 workshop for a week in June. I accepted, and it has been not only my first time visiting Germany but an amazing experience.

The Workshop at Merz

Classroom photo by Olia Lialina

First I have to say that Merz Akademy installations are excellent. The best place to study I’ve ever seen. During a week each semester, they invite 8 to 10 expert guests in different fields — music, film, graphic design… — to teach workshops to their students. The students are free to choose in which workshop they want to participate.

My workshop was about web coding with standars and an overview of CSS3. There were 17 students, all of them really nice people, it was a pleasure to work with them. A message to them: Hello! Come to visit me at Málaga, you have a free room here!

We spent the first two days on learning a bit of semantic html, a review of CSS1/2 positioning, CSS sprites… The next two days were spent in experimenting with CSS3 and making something artistical with it.

The last day, projection and presentation of the projects from all the workshops.

Our workshop: CSS3 Guernica by Picasso

In my opinion, one of the better ways to learn is by free playing an experimenting, so after the first days of good coding practices and real life web design examples, we started to play in an artistical and free way with CSS3 — just the same as I usually do with my blog CSS experiments. So, our project was not meant to be useful or applicable to real world web design, but an artistical experiment.

We cutted the painting Guernica in parts, one for each student, and we animated it with CSS3 transitions. You can see the result here:

http://id.merz-akademie.de/guernica/
* Note: it is for webkit browsers only, watch it from Safari or Chrome.

Visiting Smashing Magazine office

Vitaly Friedman and Román Cortés at the Smashing Magazine officeIf you are a common reader of this blog, I suppose there is no need to explain that Smashing Magazine is one of the most important web magazines on web design and development. Since it was at only 2-3 hours by car from Merz Akademy, I went to visit their office with one of the students (Hello Candogan!).

We met Vitaly Friedman, editor-in-chief of Smashing Magazine. He is a really nice person and it was a pleasure to meet him and talk to him in person.

Vitaly gave us signed copies of the Smashing Book (Vitaly, thanks again for the book!). I’ve fully read it right now, and I’ve to say that it is really a good book. If you are into web design/development and you are searching for a good book, I can’t recommend you anything better than this. It is easy to read, well designed in its content, structure and visually, and very complete. I would have like to have a book like this when I was learning web development, it took me years to achieve all the knowledge that is condensed in this single book.

Conclusion

It has been an amazing and intense trip and experience. I would like to thank everybody I’ve met and Merz Akademy for making it possible.

]]>
http://www.romancortes.com/blog/my-trip-to-germany/feed/
Dancing Typography http://www.romancortes.com/blog/dancing-typography/ http://www.romancortes.com/blog/dancing-typography/#comments Sat, 29 May 2010 03:11:36 +0000 Román Cortés http://www.romancortes.com/blog/dancing-typography/ Dancing Typography screenshots

In this experiment/new visual effect, the letters from a lyric of a popular song – Never Gonna Give You Up — are repositioned to compose the images of its singer — Rick Astley — dancing in fluid motion. Take a look of it here.

It is an evolution of an experiment I did a month ago where text compose a static image. In this case, I modified the algorithm to achieve the smooth motion by making the  letters move the less as possible to be adapted to the next frame in the video.

As the previous experiment, this was thought to be done with Javascript/CSS, but I’ve finally had to recode it in Flash because the Javascript version was too slow rendering. This is why it is done with Arial font, so a big sorry to typography purists about it.

I’ve included an slider to morph from the lyrics to the video and two checkboxes, one for a interesting slow motion video where it is possible to see in detail how the letters move to create the different frames and a cinematic motion blur that also helps to see the motion, but that unfortunately requires a very fast computer to render at full speed. I hope you enjoy it!

]]>
http://www.romancortes.com/blog/dancing-typography/feed/
Pure CSS3 Page Flip Effect http://www.romancortes.com/blog/pure-css3-page-flip-effect/ http://www.romancortes.com/blog/pure-css3-page-flip-effect/#comments Mon, 17 May 2010 03:17:03 +0000 Román Cortés http://www.romancortes.com/blog/pure-css3-page-flip-effect/ CSS3 Page Flip

By using CSS3 gradients, transitions, 2d transforms and clipping, I’ve achieved this pure CSS3 — without Javascript — page flipping effect.  By adding some Javascript it would be possible to do a full catalog viewer just like the existent ones done in Flash, but I wanted to try if it was possible to do it without Javascript… and it is!

It works in Webkit based browsers (Safari and Chrome) only. Take a look of it here.

]]>
http://www.romancortes.com/blog/pure-css3-page-flip-effect/feed/