Procedural texturing #
Una textura procedural es una textura creada utilizando una descripción matemática (es decir, un algoritmo) en lugar de datos almacenados directamente. La ventaja de este enfoque es el bajo costo de almacenamiento, la resolución ilimitada de texturas y el fácil mapeo de texturas. Este tipo de texturas se utilizan a menudo para modelar superficies o representaciones volumétricas de elementos naturales como madera, mármol, granito, metal, piedra y otros.
Por lo general, el aspecto natural del resultado renderizado se logra mediante el uso de funciones de turbulencia y ruido fractal. Estas funciones se utilizan como una representación numérica de la “aleatoriedad” que se encuentra en la naturaleza.
truchet_tiles.js
let pg;
let truchetShader;
function preload() {
truchetShader = readShader('/VisualComputing2022_2/sketches/Taller3/Procedural/truchet.frag',
{ matrices: Tree.NONE, varyings: Tree.NONE });
}
function setup() {
createCanvas(400, 400, WEBGL);
pg = createGraphics(400, 400, WEBGL);
textureMode(NORMAL);
noStroke();
pg.noStroke();
pg.textureMode(NORMAL);
pg.shader(truchetShader);
pg.emitResolution(truchetShader);
truchetShader.setUniform('u_zoom', 3);
pg.quad(-1, -1, 1, -1, 1, 1, -1, 1);
texture(pg);
}
function draw() {
background(33);
orbitControl();
cylinder(100, 200);
}
function mouseMoved() {
// https://p5js.org/reference/#/p5.Shader/setUniform
truchetShader.setUniform('u_zoom', int(map(mouseX, 0, width, 1, 30)));
// pg clip-space quad (i.e., both x and y vertex coordinates ∈ [-1..1])
pg.quad(-1, -1, 1, -1, 1, 1, -1, 1);
}
truchet.frag
// Author @patriciogv ( patriciogonzalezvivo.com ) - 2015
#ifdef GL_ES
precision mediump float;
#endif
#define PI 3.14159265358979323846
uniform vec2 u_resolution;
uniform float u_time;
uniform float u_zoom;
vec2 rotate2D (vec2 _st, float _angle) {
_st -= 0.5;
_st = mat2(cos(_angle),-sin(_angle),
sin(_angle),cos(_angle)) * _st;
_st += 0.5;
return _st;
}
vec2 tile (vec2 _st, float _zoom) {
_st *= _zoom;
return fract(_st);
}
vec2 rotateTilePattern(vec2 _st){
// Scale the coordinate system by 2x2
_st *= 2.0;
// Give each cell an index number
// according to its position
float index = 0.0;
index += step(1., mod(_st.x,2.0));
index += step(1., mod(_st.y,2.0))*2.0;
// |
// 2 | 3
// |
//--------------
// |
// 0 | 1
// |
// Make each cell between 0.0 - 1.0
_st = fract(_st);
// Rotate each cell according to the index
if(index == 1.0){
// Rotate cell 1 by 90 degrees
_st = rotate2D(_st,PI*0.5);
} else if(index == 2.0){
// Rotate cell 2 by -90 degrees
_st = rotate2D(_st,PI*-0.5);
} else if(index == 3.0){
// Rotate cell 3 by 180 degrees
_st = rotate2D(_st,PI);
}
return _st;
}
void main (void) {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st = tile(st,u_zoom);
st = rotateTilePattern(st);
// Make more interesting combinations
// st = tile(st,2.0);
// st = rotate2D(st,-PI*u_time*0.25);
// st = rotateTilePattern(st*2.);
// st = rotate2D(st,PI*u_time*0.25);
// step(st.x,st.y) just makes a b&w triangles
// but you can use whatever design you want.
gl_FragColor = vec4(vec3(step(st.x,st.y)),1.0);
}
Esfera con textura cambiante #
grill_sphere.js
let theShader;
let shaderTexture;
let theta = 0;
let x;
let y;
let outsideRadius = 200;
let insideRadius = 100;
function preload(){
// load the shader
theShader = loadShader('/VisualComputing2022_2/sketches/Taller3/Procedural/grill.vert','/VisualComputing2022_2/sketches/Taller3/Procedural/grill.frag');
}
function setup() {
// disables scaling for retina screens which can create inconsistent scaling between displays
//pixelDensity(1);
// shaders require WEBGL mode to work
createCanvas(710, 400, WEBGL);
noStroke();
// initialize the createGraphics layers
shaderTexture = createGraphics(710, 400, WEBGL);
// turn off the createGraphics layers stroke
shaderTexture.noStroke();
x = -50;
y = 0;
}
function draw() {
// instead of just setting the active shader we are passing it to the createGraphics layer
shaderTexture.shader(theShader);
// here we're using setUniform() to send our uniform values to the shader
theShader.setUniform("resolution", [width, height]);
theShader.setUniform("time", millis() / 1000.0);
theShader.setUniform("mouse", [mouseX, map(mouseY, 0, height, height, 0)]);
// passing the shaderTexture layer geometry to render on
shaderTexture.rect(0,0,width,height);
background(0);
//pass the shader as a texture
texture(shaderTexture);
translate(-150, 0, 0);
push();
rotateZ(theta * mouseX * 0.0001);
rotateX(theta * mouseX * 0.0001);
rotateY(theta * mouseX * 0.0001);
theta += 0.05;
sphere(125);
pop();
/* when you put a texture or shader on an ellipse it is rendered in 3d,
so a fifth parameter that controls the # vertices in it becomes necessary,
or else you'll have sharp corners. setting it to 100 is smooth. */
let ellipseFidelity = int(map(mouseX, 0, width, 8, 100));
ellipse(260, 0, 200, 200, ellipseFidelity);
}
grill.frag
#ifdef GL_ES
precision mediump float;
#endif
#define PI 3.14159265358979323846
uniform vec2 resolution;
uniform float time;
uniform vec2 mouse;
vec2 rotate2D (vec2 _st, float _angle) {
_st -= 0.5;
_st = mat2(cos(_angle),-sin(_angle),
sin(_angle),cos(_angle)) * _st;
_st += 0.5;
return _st;
}
vec2 tile (vec2 _st, float _zoom) {
_st *= _zoom;
return fract(_st);
}
vec2 rotateTilePattern(vec2 _st){
// Scale the coordinate system by 2x2
_st *= 2.0;
// Give each cell an index number
// according to its position
float index = 0.0;
index += step(1., mod(_st.x,2.0));
index += step(1., mod(_st.y,2.0))*2.0;
// |
// 2 | 3
// |
//--------------
// |
// 0 | 1
// |
// Make each cell between 0.0 - 1.0
_st = fract(_st);
// Rotate each cell according to the index
if(index == 1.0){
// Rotate cell 1 by 90 degrees
_st = rotate2D(_st,PI*0.5);
} else if(index == 2.0){
// Rotate cell 2 by -90 degrees
_st = rotate2D(_st,PI*-0.5);
} else if(index == 3.0){
// Rotate cell 3 by 180 degrees
_st = rotate2D(_st,PI);
}
return _st;
}
float concentricCircles(in vec2 st, in vec2 radius, in float res, in float scale) {
float dist = distance(st,radius);
float pct = floor(dist*res)/scale;
return pct;
}
void main (void) {
vec2 st = gl_FragCoord.xy/resolution.xy;
vec2 mst = gl_FragCoord.xy/mouse.xy;
float mdist= distance(vec2(1.0,1.0), mst);
float dist = distance(st,vec2(sin(time/10.0),cos(time/10.0)));
st = tile(st,10.0);
st = rotate2D(st,dist/(mdist/5.0)*PI*2.0);
gl_FragColor = vec4(vec3(concentricCircles(st, vec2(0.0,0.0), 5.0, 5.0),concentricCircles(st, vec2(0.0,0.0), 10.0, 10.0),concentricCircles(st, vec2(0.0,0.0), 20.0, 10.0)),1.0);
}