Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Processing 2 Creative Coding Hotshot.pdf
Скачиваний:
10
Добавлен:
17.03.2016
Размер:
5.28 Mб
Скачать

Project 7

Objective Complete - Mini Debriefing

In our third task, we turned the sphere that we smoothened and lit in the second task into a globe using a texture. In step 2, we added a texture image and created a PImage object to store it. We extended our makeSphere() method to take a texture image as a parameter and then used the image as the texture for our sphere. To make sure the texture was mapped to our mesh, we needed to use an extended version of the vertex() method that also allowed us to specify which part of the texture we want to use for each vertex.

Since we already used two loops to iterate over the angles of the polar coordinates, we used the same coordinates as a basis for our texture coordinates. We simply needed to map them to the height and width of our texture image.

Finally, we added a callback function that handles key press events and used it to switch between the texture images. We added two satellite images from NASA's Visible Earth project. The blue marble image is a satellite image that has been processed to show no clouds on the planet, and the earth-by-night image shows the globe by night. We switched the textures of our shape using the setTexture() method of the PShape class that replaces the current texture.

From globe to neon globe

For our final task of this mission, we will be converting the globe we just created into a glowing neon globe. We will create a globe that would fit into an 80s movie like WarGames or Tron. We will create this glow effect by applying two filters to our globe. The first one is an edge detection filter, which strips away every filled area of the image and only leaves the outlines of the continents. The second filter will add a glow effect to our lines. We will implement these filters in the OpenGL Shading Language (GLSL). These GLSL filters will be executed by our graphics card; they don't need CPU resources.

We will only apply our filters if the simple texture showing the continents is active, and we will deactivate them when the satellite images from NASA's Visible Earth project are active.

Engage Thrusters

Let's create our filters:

1.First, we need to change the colors of our world map texture to make the sea appear black and the continents green. Open the sketch that we created in the third task and add the following code to our setup() method:

void setup() { size(400,400,P3D); frameRate(25);

179

The Neon Globe

PGraphics g = createGraphics( 700,349); g.beginDraw();

PImage tmp = loadImage( "world.png" ); tmp.filter(INVERT);

g.tint(100,255,0); g.image( tmp,0,0 ); g.endDraw();

world = createGraphics( 700, 349 ); world = g.get(0,0,700,349);

bluemarble = loadImage( "bluemarble.jpg" ); night = loadImage( "night.jpg" );

sphere = makeSphere( 150, 5, world);

}

2.We want our globe drawn with a blue grid for the ocean, so we will set the stroke color to blue and the stroke weight to 2 in our makeSphere() method.

PShape makeSphere( int r, int step, PImage tex) {

PShape s = createShape();

s.beginShape(QUAD_STRIP); s.texture( tex ); s.stroke(0,0,255); s.strokeWeight( 2 );

for( int i = 0; i < 180; i+=step ) { float sini = sin( radians( i )); float cosi = cos( radians( i ));

float sinip = sin( radians( i + step )); float cosip = cos( radians( i + step ));

3. Run the sketch now. The globe should look like this screenshot:

180

Project 7

4.Now we are going to add our edge detection filter. Add a PShape variable to the sketch; in the setup() method, load a file named edge.glsl (which we are going to create in a minute).

PShape sphere;

PImage world;

PShader edge;

void setup() { size(400,400,P3D); frameRate(25);

PGraphics g = createGraphics( 700,349); g.beginDraw();

PImage tmp = loadImage( "world.png" ); tmp.filter(INVERT);

g.tint(100,255,0); g.image( tmp,0,0 ); g.endDraw();

world = createGraphics( 700, 349 ); world = g.get(0,0,700,349);

sphere = makeSphere( 150, 5, world);

edge = loadShader("edge.glsl");

}

5. Now open a text editor, create a file namededge.glsl, and enter the following code:

#ifdef GL_ES

precision mediump float; precision mediump int; #endif

#define PROCESSING_TEXTURE_SHADER

uniform sampler2D texture; uniform vec2 texOffset;

varying vec4 vertColor; varying vec4 vertTexCoord;

void main(void) {

181

The Neon Globe

// calculate the coordinates of the neighboring points

vec2 tc0 = vertTexCoord.st + vec2(-texOffset.s, -texOffset.t); vec2 tc1 = vertTexCoord.st + vec2( 0.0, -texOffset.t);

vec2 tc2 = vertTexCoord.st + vec2(+texOffset.s, -texOffset.t); vec2 tc3 = vertTexCoord.st + vec2(-texOffset.s, 0.0);

vec2 tc4 = vertTexCoord.st + vec2( 0.0, 0.0);

vec2 tc5 = vertTexCoord.st + vec2(+texOffset.s, 0.0);

vec2 tc6 = vertTexCoord.st + vec2(-texOffset.s, +texOffset.t); vec2 tc7 = vertTexCoord.st + vec2( 0.0, +texOffset.t);

vec2 tc8 = vertTexCoord.st + vec2(+texOffset.s, +texOffset.t); // get the color values from the image for each coordinate vec4 col0 = texture2D(texture, tc0);

vec4 col1 = texture2D(texture, tc1); vec4 col2 = texture2D(texture, tc2); vec4 col3 = texture2D(texture, tc3); vec4 col4 = texture2D(texture, tc4); vec4 col5 = texture2D(texture, tc5); vec4 col6 = texture2D(texture, tc6); vec4 col7 = texture2D(texture, tc7); vec4 col8 = texture2D(texture, tc8);

vec4 sum = 8.0 * col4 - (col0 + col1 + col2 + col3 + col5 + col6 + col7 + col8);

float f = sum.r + sum.g + sum.b; gl_FragColor = vec4(f,f,f,1.0)*col4;

}

6.We need to add the edge.glsl file we just created to our sketch by dragging the file onto the sketch window or by going to Sketch | Add File....

7.To use the shader we just created as a filter, we need to add a call to the filter() method in our draw() method after our globe has been drawn and add the shader variable that we initialized in our setup() method as a parameter.

void draw() { background(0);

translate( width/2, height/2 );

lights();

pushMatrix();

rotateX( radians(-30)); rotateY( a );

a+= 0.01; shape(sphere);

182

Project 7

popMatrix();

filter(edge);

}

8. Now run the sketch. The globe should look like this screenshot:

9.Our second filter will add a glow effect to the lines that our edge detection filter created to make it look like the image of an old CRT monitor. Create a file named blur.glsl using a text editor and insert the following code:

#ifdef GL_ES

precision mediump float; precision mediump int; #endif

#define PROCESSING_TEXTURE_SHADER

uniform sampler2D texture; uniform vec2 texOffset; varying vec4 vertTexCoord;

void main(void) { int i = 0;

int j= 0;

vec4 sum = vec4(0.0);

for( i=-5;i<5;i++) { for( j=-5;j<5;j++) {

183

The Neon Globe

sum += texture2D( texture, vertTexCoord.st + vec2(j,i)*texOffset.st)*0.025;

}

}

gl_FragColor = sum*sum+ vec4(texture2D( texture, vertTexCoord. st).rgb, 1.0);

}

10.We will now add the file to our sketch by dragging it on to the sketch window or by going to Sketch | Add File....

11.Now add another PShader variable and load the shader into our setup() method.

PShape sphere;

PImage world;

PShader blur;

PShader edge;

void setup() { size(400,400,P3D); frameRate(25);

PGraphics g = createGraphics( 700,349); g.beginDraw();

PImage tmp = loadImage( "world.png" ); tmp.filter(INVERT);

g.tint(100,255,0); g.image( tmp,0,0 ); g.endDraw();

world = createGraphics( 700, 349 ); world = g.get(0,0,700,349);

sphere = makeSphere( 150, 5, world);

edge = loadShader("edge.glsl"); blur = loadShader("blur.glsl");

}

12.In our draw() method, we will add a second call to filter() using the blur shader as a parameter.

void draw() { background(0);

184

Project 7

translate( width/2, height/2 );

lights();

pushMatrix();

rotateX( radians(-30)); rotateY( a );

a+= 0.01; shape(sphere);

popMatrix();

filter(edge);

filter(blur);

}

13. Now run the sketch. The globe should look like the following screenshot:

14.Currently, the filters and grid lines are active at the same time that the satellite images are active, which looks strange. So, we will now add a Boolean variable named satelite and set it to true whenever a satellite image gets selected in our keyPressed() method.

boolean satelite = false; void keyPressed() {

if( key == '1' ) { sphere.setTexture( world ); satelite = false;

} else if ( key == '2' ) {

185

The Neon Globe

sphere.setTexture( bluemarble ); satelite = true;

}else if ( key == '3' ) { sphere.setTexture( night );

satelite = true;

}

}

15.In our draw()method, we will now deactivate the filters when a satellite image is selected.

void draw() { background(0);

translate( width/2, height/2 );

lights();

pushMatrix();

rotateX( radians(-30)); rotateY( a );

a+= 0.01;

shape(sphere);

popMatrix();

if ( !satelite ) { filter(edge); filter(blur);

}

}

16.The filters are deactivated now, but we still have the lines of our blue grid over the satellite images, which looks kind of weird. So, we will now set the stroke to false if a satellite image is active. Unfortunately, you can't reactivate the stroke lines when the neon map is activated, so we will recreate our original shape using the makeSphere() command.

void keyPressed() { if( key == '1' ) { satelite = false;

sphere = makeSphere( 150, 5, world);

}else if ( key == '2' ) { sphere.setTexture( bluemarble ); sphere.setStroke(false); satelite = true;

186

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]