这叫什么以及如何实现!处理中的视觉效果

问题描述 投票:0回答:1

嘿,有人知道如何通过处理来达到这种效果,或称之为什么?

我一直在尝试在处理库中使用波梯度示例并实现Perlin噪声,但我无法接近gif的质量。

我知道艺术家使用了处理方式,但不知道如何处理!

waves animated gif

链接到gif:

https://giphy.com/gifs/processing-jodeus-QInYLzY33wMwM

processing
1个回答
0
投票

[效果是Op Art的幻觉(光学幻觉):我建议阅读/学习更多有关这种引人入胜的流派和类似的艺术家的信息:

Bridget Riley

Bridget Riley 1979

Bridget Riley, Intake, 1964

((Bridget Riley,Intake,1964)

Bridget Riley, Hesistate, 1964

([Bridget Riley, Hesistate, 1964, Copyright: (c) Bridget Riley 2018. All rights reserved. / Photo (c) Tate

Victor Vasarely

Zebra Couple

((Victor Vasarely,斑马夫妇)

Victor Vasarely, VegaII

((Victor Vasarely,VegaII)

Frank StellaFrank Stella, Untitled 1965(弗兰克·斯特拉(Frank Stella),《 1965年无题》,图片由Art Gallery NSW致谢)

以及更多

[您注意到这波浪潮让人想起/从布里奇特·赖利的作品中汲取了灵感。

我还建议签出San CharoenchaiBeach House - 7的相册可视化工具

Beach House - 7 album music video thumbnails

如我的评论中所述:您应该发表自己的尝试。波浪和贝林噪声可以肯定起作用。有很多方法可以实现相似的外观。

这里是Daniel Shiffman's Noise Wave example的调整版本:

int numWaves = 24;

float[] yoff = new float[numWaves];        // 2nd dimension of perlin noise
float[] yoffIncrements = new float[numWaves];

void setup() {
  size(640, 360);
  noStroke();

  for(int i = 0 ; i < numWaves; i++){
    yoffIncrements[i] = map(i, 0, numWaves - 1, 0.01, 0.03);
  }
}

void draw() {
  background(0);



  float waveHeight = height / numWaves;

  for(int i = 0 ; i < numWaves; i++){

    float waveY = i * waveHeight;

    fill(i % 2 == 0 ? color(255) : color(0));
    // We are going to draw a polygon out of the wave points
    beginShape(); 

    float xoff = 0;       // Option #1: 2D Noise
    // float xoff = yoff; // Option #2: 1D Noise

    // Iterate over horizontal pixels
    for (float x = 0; x <= width + 30; x += 20) {
      // Calculate a y value according to noise, map to 
      float y = map(noise(xoff, yoff[i]), 0, 1, waveY , waveY + (waveHeight * 3)); // Option #1: 2D Noise
      // float y = map(noise(xoff), 0, 1, 200,300);    // Option #2: 1D Noise

      // Set the vertex
      vertex(x, y); 
      // Increment x dimension for noise
      xoff += 0.05;
    }
    // increment y dimension for noise
    yoff[i] += yoffIncrements[i];
    vertex(width, height);
    vertex(0, height);
    endShape(CLOSE);
  }
}

Noise Wave modified Processing sketch

请注意,与您要模拟的图像相比,噪声波的质量:节奏是恒定的。对我来说,这暗示着它正在使用循环正弦波来改变相位和幅度(甚至可能将波加在一起)。

我已经为正弦波动画here撰写了广泛的答案Reuben Margolin's kinectic sculpture system demo(鲁本·马戈林的运动雕塑系统演示)

根据您的问题,听起来您会很喜欢实施正弦波动画。它有帮助,这是将两个波形加在一起的示例:

void setup(){
  size(600,600);
  noStroke();
}

void draw(){
  background(0);
  // how many waves per sketch height
  int heightDivisions = 30;
  // split the sketch height into equal height sections
  float heightDivisionSize = (float)height / heightDivisions;
  // for each height division
  for(int j = 0 ; j < heightDivisions; j++){
    // use % 2 to alternate between black and white
    // see https://processing.org/reference/modulo.html and
    //     https://processing.org/reference/conditional.html for more
    fill(j % 2 == 0 ? color(255) : color(0));
    // offset drawing on Y axis
    translate(0,(j * heightDivisionSize));
    // start a wave shape
    beginShape();
    // first vertex is at the top left corner
    vertex(0,height);
    // how many horizontal (per wave) divisions ?
    int widthDivisions = 12;
    // equally space the points on the wave horizontally
    float widthDivsionSize = (float)width / widthDivisions;
    // for each point on the wave 
    for(int i = 0; i <= widthDivisions; i++){
      // calculate different phases
      // play with arithmetic operators to make interesting wave additions
      float phase1 = (frameCount * 0.01) + ((i * j) * 0.025);
      float phase2 = (frameCount * 0.05) + ((i + j) * 0.25);
      // calculate vertex x position
      float x = widthDivsionSize * i;
      // multiple sine waves
      // (can use cos() and use other ratios too
      // 150 in this case is the wave amplitude (e.g. from -150 to + 150)
      float y = ((sin(phase1) * sin(phase2) * 150));
      // draw calculated vertex
      vertex(x,y);
    }
    // last vertex is at bottom right corner
    vertex(width,height);
    // finish the shape
    endShape();
  }
}

结果:Additive Waves shape

关于性能的小注释:可以使用PShape来更有效地实现,但是我建议您使用数学/几何来查找您想要的形式,然后最后一步是对其进行优化。

我的目的不是向您展示如何创建精确的副本,而是向我们展示Op Art除了效果以外,还希望激发您探索实现相似目标的其他方法,以期希望您发现自己的方法并结果:有趣的快乐事故带来的新事物和您自己的事物。

关于其他技术/探索途径:

  • [displacement mapsDisplacement maps SVG filter example
  • 在波浪形3D几何San Charoenchai Beach House 7 album video上使用交替的黑/白直条纹理
  • 使用着色器:shader toy hermite curve waves surface

着色器本身是一个巨大的话题,但值得注意:

  1. [非常好Processing Shader Tutorial
  2. 您可能可以在shadertoy上浏览帧着色器,在浏览器中调整代码,然后进行一些小的更改,以便可以在Processing中运行它们。

以下是一些快速示例:

https://www.shadertoy.com/view/Wts3DB

在“作为shader处理Wts3DB.frag中的处理中对黑/白波进行了调整

// https://www.shadertoy.com/view/Wts3DB

uniform vec2 iResolution;
uniform float iTime;

#define COUNT 6.
#define COL_BLACK vec3(23,32,38) / 255.0 

#define SF 1./min(iResolution.x,iResolution.y)
#define SS(l,s) smoothstep(SF,-SF,l-s)
#define hue(h) clamp( abs( fract(h + vec4(3,2,1,0)/3.) * 6. - 3.) -1. , 0., 1.)

// Original noise code from https://www.shadertoy.com/view/4sc3z2
#define MOD3 vec3(.1031,.11369,.13787)

vec3 hash33(vec3 p3)
{
    p3 = fract(p3 * MOD3);
    p3 += dot(p3, p3.yxz+19.19);
    return -1.0 + 2.0 * fract(vec3((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y, (p3.y+p3.z)*p3.x));
}

float simplex_noise(vec3 p)
{
    const float K1 = 0.333333333;
    const float K2 = 0.166666667;

    vec3 i = floor(p + (p.x + p.y + p.z) * K1);
    vec3 d0 = p - (i - (i.x + i.y + i.z) * K2);

    vec3 e = step(vec3(0.0), d0 - d0.yzx);
    vec3 i1 = e * (1.0 - e.zxy);
    vec3 i2 = 1.0 - e.zxy * (1.0 - e);

    vec3 d1 = d0 - (i1 - 1.0 * K2);
    vec3 d2 = d0 - (i2 - 2.0 * K2);
    vec3 d3 = d0 - (1.0 - 3.0 * K2);

    vec4 h = max(0.6 - vec4(dot(d0, d0), dot(d1, d1), dot(d2, d2), dot(d3, d3)), 0.0);
    vec4 n = h * h * h * h * vec4(dot(d0, hash33(i)), dot(d1, hash33(i + i1)), dot(d2, hash33(i + i2)), dot(d3, hash33(i + 1.0)));

    return dot(vec4(31.316), n);
}

void mainImage( vec4 fragColor, vec2 fragCoord )
{


}

void main(void) {
    //vec2 uv = vec2(gl_FragColor.x / iResolution.y, gl_FragColor.y / iResolution.y);
    vec2 uv = gl_FragCoord.xy / iResolution.y;
    float m = 0.;
    float t = iTime *.5;
    vec3 col;
    for(float i=COUNT; i>=0.; i-=1.){
        float edge = simplex_noise(vec3(uv * vec2(2., 0.) + vec2(0, t + i*.15), 3.))*.2 + (.95/COUNT)*i;
        float mi = SS(edge, uv.y) - SS(edge + .095, uv.y);        
        m += mi;        

        if(mi > 0.){
            col = vec3(1.0);
        }
    }           

    col = mix(COL_BLACK, col, m);

    gl_FragColor = vec4(col,1.0);

  // mainImage(gl_FragColor,gl_FragCoord);
}

在处理中加载为:

PShader shader;

void setup(){
  size(300,300,P2D);
  noStroke();
  shader = loadShader("shader-Wts3DB.frag");
  shader.set("iResolution",(float)width, float(height));
}

void draw(){
  background(0);
  shader.set("iTime",frameCount * 0.05);
  shader(shader);
  rect(0,0,width,height);
}

shadertoy Processing shader example 1

https://www.shadertoy.com/view/MtsXzl

已调整为shader-MtsXzl.frag

//https://www.shadertoy.com/view/MtsXzl
#define SHOW_GRID 1

const float c_scale = 0.5;
const float c_rate = 2.0;

#define FLT_MAX 3.402823466e+38

uniform vec3 iMouse;
uniform vec2 iResolution;
uniform float iTime;

//=======================================================================================
float CubicHermite (float A, float B, float C, float D, float t)
{
    float t2 = t*t;
    float t3 = t*t*t;
    float a = -A/2.0 + (3.0*B)/2.0 - (3.0*C)/2.0 + D/2.0;
    float b = A - (5.0*B)/2.0 + 2.0*C - D / 2.0;
    float c = -A/2.0 + C/2.0;
    float d = B;

    return a*t3 + b*t2 + c*t + d;
}

//=======================================================================================
float hash(float n) {
    return fract(sin(n) * 43758.5453123);
}

//=======================================================================================
float GetHeightAtTile(vec2 T)
{
    float rate = hash(hash(T.x) * hash(T.y))*0.5+0.5;

    return (sin(iTime*rate*c_rate) * 0.5 + 0.5) * c_scale;
}

//=======================================================================================
float HeightAtPos(vec2 P)
{
    vec2 tile = floor(P);

    P = fract(P);

    float CP0X = CubicHermite(
        GetHeightAtTile(tile + vec2(-1.0,-1.0)),
        GetHeightAtTile(tile + vec2(-1.0, 0.0)),
        GetHeightAtTile(tile + vec2(-1.0, 1.0)),
        GetHeightAtTile(tile + vec2(-1.0, 2.0)),
        P.y
    );

    float CP1X = CubicHermite(
        GetHeightAtTile(tile + vec2( 0.0,-1.0)),
        GetHeightAtTile(tile + vec2( 0.0, 0.0)),
        GetHeightAtTile(tile + vec2( 0.0, 1.0)),
        GetHeightAtTile(tile + vec2( 0.0, 2.0)),
        P.y
    );    

    float CP2X = CubicHermite(
        GetHeightAtTile(tile + vec2( 1.0,-1.0)),
        GetHeightAtTile(tile + vec2( 1.0, 0.0)),
        GetHeightAtTile(tile + vec2( 1.0, 1.0)),
        GetHeightAtTile(tile + vec2( 1.0, 2.0)),
        P.y
    );        

    float CP3X = CubicHermite(
        GetHeightAtTile(tile + vec2( 2.0,-1.0)),
        GetHeightAtTile(tile + vec2( 2.0, 0.0)),
        GetHeightAtTile(tile + vec2( 2.0, 1.0)),
        GetHeightAtTile(tile + vec2( 2.0, 2.0)),
        P.y
    );

    return CubicHermite(CP0X, CP1X, CP2X, CP3X, P.x);
}

//=======================================================================================
vec3 NormalAtPos( vec2 p )
{
    float eps = 0.01;
    vec3 n = vec3( HeightAtPos(vec2(p.x-eps,p.y)) - HeightAtPos(vec2(p.x+eps,p.y)),
                         2.0*eps,
                         HeightAtPos(vec2(p.x,p.y-eps)) - HeightAtPos(vec2(p.x,p.y+eps)));
    return normalize( n );
}

//=======================================================================================
float RayIntersectSphere (vec4 sphere, in vec3 rayPos, in vec3 rayDir)
{
    //get the vector from the center of this circle to where the ray begins.
    vec3 m = rayPos - sphere.xyz;

    //get the dot product of the above vector and the ray's vector
    float b = dot(m, rayDir);

    float c = dot(m, m) - sphere.w * sphere.w;

    //exit if r's origin outside s (c > 0) and r pointing away from s (b > 0)
    if(c > 0.0 && b > 0.0)
        return -1.0;

    //calculate discriminant
    float discr = b * b - c;

    //a negative discriminant corresponds to ray missing sphere
    if(discr < 0.0)
        return -1.0;

    //ray now found to intersect sphere, compute smallest t value of intersection
    float collisionTime = -b - sqrt(discr);

    //if t is negative, ray started inside sphere so clamp t to zero and remember that we hit from the inside
    if(collisionTime < 0.0)
        collisionTime = -b + sqrt(discr);

    return collisionTime;
}

//=======================================================================================
vec3 DiffuseColor (in vec3 pos)
{
    #if SHOW_GRID
    pos = mod(floor(pos),2.0);
    return vec3(mod(pos.x, 2.0) < 1.0 ? 1.0 : 0.0);
    #else
    return vec3(0.1, 0.8, 0.9);
    #endif
}

//=======================================================================================
vec3 ShadePoint (in vec3 pos, in vec3 rayDir, float time, bool fromUnderneath)
{
    vec3 diffuseColor = DiffuseColor(pos);
    vec3 reverseLightDir = normalize(vec3(1.0,1.0,-1.0));
    vec3 lightColor = vec3(1.0);    
    vec3 ambientColor = vec3(0.05);

    vec3 normal = NormalAtPos(pos.xz);
    normal *= fromUnderneath ? -1.0 : 1.0;

    // diffuse
    vec3 color = diffuseColor;
    float dp = dot(normal, reverseLightDir);
    if(dp > 0.0)
        color += (diffuseColor * lightColor);

    return color;
}

//=======================================================================================
vec3 HandleRay (in vec3 rayPos, in vec3 rayDir, in vec3 pixelColor, out float hitTime)
{
    float time = 0.0;
    float lastHeight = 0.0;
    float lastY = 0.0;
    float height;
    bool hitFound = false;
    hitTime = FLT_MAX;
    bool fromUnderneath = false;

    vec2 timeMinMax = vec2(0.0, 20.0);

    time = timeMinMax.x;

    const int c_numIters = 100;
    float deltaT = (timeMinMax.y - timeMinMax.x) / float(c_numIters);

    vec3 pos = rayPos + rayDir * time;
    float firstSign = sign(pos.y - HeightAtPos(pos.xz));

    for (int index = 0; index < c_numIters; ++index)
    {       
        pos = rayPos + rayDir * time;

        height = HeightAtPos(pos.xz);

        if (sign(pos.y - height) * firstSign < 0.0)
        {
            fromUnderneath = firstSign < 0.0; 
            hitFound = true;
            break;
        }

        time += deltaT;     
        lastHeight = height;
        lastY = pos.y;
    }


    if (hitFound) {
        time = time - deltaT + deltaT*(lastHeight-lastY)/(pos.y-lastY-height+lastHeight);
        pos = rayPos + rayDir * time;
        pixelColor = ShadePoint(pos, rayDir, time, fromUnderneath);
        hitTime = time;
    }

    return pixelColor;
}

//=======================================================================================
void main()
{      
    // scrolling camera
    vec3 cameraOffset = vec3(iTime, 0.5, iTime);

    //----- camera
    vec2 mouse = iMouse.xy / iResolution.xy;

    vec3 cameraAt   = vec3(0.5,0.5,0.5) + cameraOffset;

    float angleX = iMouse.z > 0.0 ? 6.28 * mouse.x : 3.14 + iTime * 0.25;
    float angleY = iMouse.z > 0.0 ? (mouse.y * 6.28) - 0.4 : 0.5;
    vec3 cameraPos  = (vec3(sin(angleX)*cos(angleY), sin(angleY), cos(angleX)*cos(angleY))) * 5.0;

 //    float angleX = 0.8;
 //    float angleY = 0.8;
 //    vec3 cameraPos = vec3(0.0,0.0,0.0);
    cameraPos += vec3(0.5,0.5,0.5) + cameraOffset;

    vec3 cameraFwd  = normalize(cameraAt - cameraPos);
    vec3 cameraLeft  = normalize(cross(normalize(cameraAt - cameraPos), vec3(0.0,sign(cos(angleY)),0.0)));
    vec3 cameraUp   = normalize(cross(cameraLeft, cameraFwd));

    float cameraViewWidth   = 6.0;
    float cameraViewHeight  = cameraViewWidth * iResolution.y / iResolution.x;
    float cameraDistance    = 6.0;  // intuitively backwards!


    // Objects
    vec2 rawPercent = (gl_FragCoord.xy / iResolution.xy);
    vec2 percent = rawPercent - vec2(0.5,0.5);

    vec3 rayTarget = (cameraFwd * vec3(cameraDistance,cameraDistance,cameraDistance))
                   - (cameraLeft * percent.x * cameraViewWidth)
                   + (cameraUp * percent.y * cameraViewHeight);
    vec3 rayDir = normalize(rayTarget);


    float hitTime = FLT_MAX;
    vec3 pixelColor = vec3(1.0, 1.0, 1.0);
    pixelColor = HandleRay(cameraPos, rayDir, pixelColor, hitTime);


    gl_FragColor = vec4(clamp(pixelColor,0.0,1.0), 1.0);
}

和鼠标交互式处理草图:

PShader shader;

void setup(){
  size(300,300,P2D);
  noStroke();
  shader = loadShader("shader-MtsXzl.frag");
  shader.set("iResolution",(float)width, float(height));
}

void draw(){
  background(0);
  shader.set("iTime",frameCount * 0.05);
  shader.set("iMouse",(float)mouseX , (float)mouseY, mousePressed ? 1.0 : 0.0);
  shader(shader);
  rect(0,0,width,height);
}

shadertoy Processing shader example 1

Shadertoy是玩/学习的好方法:玩得开心!

© www.soinside.com 2019 - 2024. All rights reserved.