Realizado por Prashant Jeswani Tejwani

Índice del contenido:

  1. Introducción
  2. Diseño
  3. Código implementado
  4. Descargar código en Processing
  5. Referencias

Introducción

Se implementa un shader de fragmentos:

  • Se describe el trabajo realizado argumentando las decisiones adoptadas para la solución propuesta
  • Se incluye las referencias y herramientas utilizadas
  • Se muestra el resultado con un gif animado

Diseño

El diseño ha sido el que se puede observar en la siguiente figura. Se representa un conjunto de colores en movimiento el cual se puede modificar la intensidad de color y velocidad del movimiento.

Código implementado

A continuación se describe el trabajo realizado. Se crean e inicializan las variables necesarias para la visualización de los colores en movimiento que se irán explicando a medida que se avance.

PShader shader;
float speed;
float color_intensity;
boolean help;


En la función setup() se inicializan las variables definidas anteriormente, y se carga el shader llamado ‘Abstract.glsl’.

void setup() {
  size(800, 600, P2D);
  speed = 1.0;
  color_intensity = 0.5;
  help = true;
  textAlign(CENTER, CENTER);
  shader = loadShader("Abstract.glsl");
}


En la función draw() se muestra u oculta el menú si el usuario ha hecho click con el ratón. Sino, se pasan las variables de resolución de pantalla, el tiempo desde que se ha cargado el shader, la velocidad del movimiento (rango 1.0 - Inf, un número más alto implica que el movimiento sea más lento) y la intensidad de color (rango 0.0 - 1.0). Luego, se carga el shader mediante la función shader(s).

void draw() {
  if (help) {
    background(0);
    fill(255);
    textSize(26);
    text("Shaders I", width/2, height/2 - 100);
    textSize(14);
    text("Press 'c' to change color intensity", width/2, height/2 - 60);
    text("Press 's' to slow down movement", width/2, height/2 - 40);
    text("Click to show/hide menu", width/2, height/2 - 20);
    text("Default values", width/2, height/2 + 20);
    text("Speed (Range: 1.0 to Inf): " + speed, width/2, height/2 + 40);
    text("Color intensity (Range: 0.0 to 1.0): " + color_intensity, width/2, height/2 + 60);
    text("© Prashant Jeswani Tejwani", 100, height - 20);
  } else {
    noStroke();
    shader.set("u_resolution", float(width), float(height));
    shader.set("u_time", millis() / 1000.0);
    shader.set("u_fluid_speed", speed);
    shader.set("u_color_intensity", color_intensity);
    shader(shader);
    rect(0, 0, width, height);
  }
}


Si la variable help es verdadera, se imprime un lienzo de ayuda de los controles que dispone el usuario:


Las funciones mousePressed() y keyPressed() detectan el click del ratón para mostrar u ocultar el menú y cuando el usuario presiona las teclas ‘c’ o ‘s’ para modificar la intensidad de color o aumentar la velocidad del movimiento.

void mousePressed() {
  help = !help;
}


void keyPressed() {
  if (key == 's') speed++;
  if (key == 'c') {
    if (color_intensity <= 1.0) { 
      color_intensity += 0.1;
    } else {
      color_intensity = 0.1;
    }
  }
}


El shader cargado es el siguiente. Los uniforms son definidos con sus correspondientes tipos, al principio del código, luego de definir la precisión del punto flotante: u_time (tiempo en segundos desde que shaders comenzó a correr), u_resolution (el tamaño de la ventana donde se está dibujando el shader), u_fluid_speed (velocidad del movimiento) y u_color_intensity (intensidad de los colores). La variable complexity define el número de puntos de colores que se ha establecido a 50.

#ifdef GL_ES
  precision mediump float;
#endif

uniform vec2 u_resolution; 
uniform float u_time; 
uniform float u_fluid_speed; // Higher number will make it slower
uniform float u_color_intensity = 0.5;

const int complexity = 50; // More points of color

void main() {
  vec2 p = (2.0 * gl_FragCoord.xy - u_resolution) / max(u_resolution.x, u_resolution.y);

  for (int i = 1; i < complexity; i++) {
    vec2 newp = p + u_time * 0.001;
    // + mouse.y / mouse_factor + mouse_offset
    newp.x += 0.6 / float(i) * sin(float(i) * p.y + u_time / u_fluid_speed + 20.3 * float(i)) + 0.5;
    // - mouse.x / mouse_factor + mouse_offset
    newp.y += 0.6 / float(i) * sin(float(i) * p.x + u_time / u_fluid_speed + 0.3 * float(i + 10)) - 0.5;
    p = newp;
  }

  vec3 color = vec3(u_color_intensity*sin(5.0*p.x) + u_color_intensity, u_color_intensity*sin(3.0*p.y) + 
                    u_color_intensity, u_color_intensity*sin(p.x+p.y) + u_color_intensity);
  gl_FragColor = vec4(color, 1.0);
}


A continuación, se muestra el resultado final mediante un gif animado:

Descargar código en Processing

Para la correcta ejecución en Processing, es necesario instalar el modo Shader. Esto se puede hacer de la siguiente manera:

Para descargar el código en Processing, acceda a: Descargar código en Processing o acceda a la carpeta del repositorio del proyecto en: Repositorio del proyecto


Referencias

Guión de prácticas

Página de Processing

Creación del enlace de descarga

The Book of Shaders