Bilgisayar Üretimi Dokulu Duvar Boyası


48

Odamda duvarlarda boya rastgele, neredeyse fraktal benzeri, 3 boyutlu bir dokuya sahiptir:

Resim A

Bu mücadelede, duvarlarımın bir parçası olacak gibi görünen rasgele görüntüler üreten bir program yazacaksınız.

Aşağıda duvarlarımda 10 farklı resim lekesi topladım. Hepsi kabaca aynı ışıklandırmaya sahipti ve kamera duvardan bir metre ötede kamerayla çekildi. Sınırlar, 2048'e 2048 piksel yapmak için düzgün bir şekilde kırpıldı, ardından 512'ye 512'ye ölçeklendi. Yukarıdaki resim A görüntüsüdür.

Bunlar sadece küçük resimler, tam boyutta görmek için resimlere tıklayın!

A: B: C: D: E:Resim A Görüntü B Görüntü C Görüntü D Görüntü E

F: G: H: I: J:Görüntü F Görüntü G Görüntü H Resim I Görüntü J

Senin görevin rastgele tohum olarak 1 ila 2 16 arasında pozitif bir tamsayı alan bir program yazmak ve her değer için duvarımın "onbirinci görüntüsü" olmuş gibi görünen farklı bir görüntü üretiyor. Eğer 10 resime bakıp biri, hanginiz sizin hangi bilgisayarların üretildiğini söyleyemiyorsa, o zaman çok iyi iş çıkardınız!

Lütfen oluşturduğunuz resimlerden birkaçını gösterin, böylece izleyiciler kod çalıştırmak zorunda kalmadan bunları görebilir.

Görüntülerimdeki ışığın, yoğunluk veya renk bakımından kusursuz bir şekilde eşit olmadığını fark ediyorum. Bunun için üzgünüm ama daha iyi aydınlatma ekipmanları olmadan yapabileceğim en iyisi. Resimlerinizin değişken bir aydınlatmaya sahip olmaları gerekmez (olsa da). Odaklanılacak en önemli şey doku.

ayrıntılar

  • Görüntü işleme araçlarını ve kitaplıklarını kullanabilirsiniz.
  • İstediğiniz herhangi bir şekilde girişi alın (komut satırı, stdin, belirgin değişken, vb.).
  • Çıktı görüntüsü, herhangi bir yaygın kayıpsız görüntü dosyası biçiminde olabilir veya sadece bir pencerede / yaylayıcıda görüntülenebilir.
  • 10 resmimi programlı olarak analiz edebilirsiniz, ancak kodunuzu çalıştıran herkesin bunlara erişimi olduğunu varsaymayın.
  • Görüntüleri programlı olarak oluşturmalısınız. Resimlerimden birinin veya başka bir hisse senedi resminin küçük bir değişkenini zor kodlayamazsınız. (İnsanlar zaten bunun için sana oy verirdi.)
  • Yerleşik yalancı sayı üreteçlerini kullanabilir ve sürenin 2 veya 16 olduğunu varsayabilirsin .

puanlama

Bu bir popülerlik yarışmasıdır, bu nedenle en yüksek oyu alan cevap kazanır.


PerlinNoise + truncation + gölgeleme
Ahtapot

21
Duvar resmi yapamıyorum, bunun yerine komik bir çizgi çizin !
Sp3000

8
@ Sp3000 Bu oldu böyle ya da az. Yukarı bakıyorum olmuşsa muhtemelen seçmiş razı olmama rağmen benim tavan yanı işe yarayabilir ...
Calvin'in Hobiler

Yanıtlar:


65

GLSL (+ JavaScript + WebGL)

görüntü tanımını buraya girin

Canlı demo | GitHub deposu

Nasıl kullanılır

Yeni bir rastgele resim için sayfayı yeniden yükleyin. Belirli bir tohumdan beslemek istiyorsanız, tarayıcınızın konsolunu açın ve arayın drawScreen(seed). Konsol, yükte kullanılan tohumu göstermelidir.

Bunu pek çok platformda test etmedim, bu yüzden sizin için işe yarayıp yaramadığını bana bildirin. Tabii ki, tarayıcınızın WebGL'yi desteklemesi gerekiyor. Hatalar soldaki sütunda veya tarayıcının konsolunda (hatanın türüne bağlı olarak) görüntülenir.

Yeni: Artık "hareketli ışık kaynağı" onay kutusunu işaretleyerek duvarları biraz canlandırın.

Bu büyücülük nedir?

Şimdi WebGL'de bazı 2D grafik öğelerini hızlıca prototiplemek için kullandığım GitHub hesabımın etrafında dönen bu WebGL kazan kodunu aldım . Bazı gölgelendirici sihriyle, biraz 3B görünmesini de sağlayabiliriz, bu yüzden bazı güzel efektlerin başlamasının en hızlı yolu olduğunu düşündüm. Kurulumun çoğu o kazan plakasından ve bu gönderi için bir kütüphane olduğunu ve bu yazıya dahil etmeyeceğini düşünüyorum. Eğer ilgileniyorsanız, bir göz main.js GitHub üzerinde (ve o klasördeki diğer dosyaların).

JavaScript'in yaptığı tek şey bir WebGL bağlamı oluşturmak, çekirdeği gölgelendirici için tek tip bir konumda saklamak ve ardından tüm bağlam boyunca tek bir dörtlü oluşturmaktır. Köşe gölgelendirici basit bir geçiş gölgelendiricisidir, böylece tüm sihir parça gölgelendiricisinde gerçekleşir. Bu yüzden bunu GLSL gönderimi olarak adlandırdım.

Kodun en büyük kısmı aslında GitHub'da bulduğum Simplex gürültüsünü oluşturmak . Bu yüzden, aşağıdaki kod listesindeki gibi atlıyorum. Önemli kısmı, snoise(vec2 coords)tek bir doku veya dizi araması kullanmadan tek yönlü gürültüyü döndüren bir işlevi tanımlamasıdır . Hiç ekilmemiş, bu nedenle farklı gürültü almanın püf noktası, aramanın nerede yapılacağının belirlenmesinde tohum kullanımıdır.

Yani işte gidiyor:

#ifdef GL_ES
precision mediump float;
#endif
#extension GL_OES_standard_derivatives : enable

uniform float uSeed;
uniform vec2 uLightPos;

varying vec4 vColor;
varying vec4 vPos;

/* ... functions to define snoise(vec2 v) ... */

float tanh(float x)
{
    return (exp(x)-exp(-x))/(exp(x)+exp(-x));
}

void main() {
    float seed = uSeed * 1.61803398875;
    // Light position based on seed passed in from JavaScript.
    vec3 light = vec3(uLightPos, 2.5);
    float x = vPos.x;
    float y = vPos.y;

    // Add a handful of octaves of simplex noise
    float noise = 0.0;
    for ( int i=4; i>0; i-- )
    {
        float oct = pow(2.0,float(i));
        noise += snoise(vec2(mod(seed,13.0)+x*oct,mod(seed*seed,11.0)+y*oct))/oct*4.0;
    }
    // Level off the noise with tanh
    noise = tanh(noise*noise)*2.0;
    // Add two smaller octaves to the top for extra graininess
    noise += sqrt(abs(noise))*snoise(vec2(mod(seed,13.0)+x*32.0,mod(seed*seed,11.0)+y*32.0))/32.0*3.0;
    noise += sqrt(abs(noise))*snoise(vec2(mod(seed,13.0)+x*64.0,mod(seed*seed,11.0)+y*64.0))/64.0*3.0;

    // And now, the lighting
    float dhdx = dFdx(noise);
    float dhdy = dFdy(noise);
    vec3 N = normalize(vec3(-dhdx, -dhdy, 1.0)); // surface normal
    vec3 L = normalize(light - vec3(vPos.x, vPos.y, 0.0)); // direction towards light source
    vec3 V = vec3(0.0, 0.0, 1.0); // direction towards viewpoint (straight up)
    float Rs = dot(2.0*N*dot(N,L) - L, V); // reflection coefficient of specular light, this is actually the dot product of V and and the direction of reflected light
    float k = 1.0; // specular exponent

    vec4 specularColor = vec4(0.4*pow(Rs,k));
    vec4 diffuseColor = vec4(0.508/4.0, 0.457/4.0, 0.417/4.0, 1.0)*dot(N,L);
    vec4 ambientColor = vec4(0.414/3.0, 0.379/3.0, 0.344/3.0, 1.0);

    gl_FragColor = specularColor + diffuseColor + ambientColor;
    gl_FragColor.a = 1.0;
}

Bu kadar. Yarın biraz daha açıklama ekleyebilirim, ancak temel fikir şudur:

  • Rasgele bir ışık konumu seçin.
  • Fraktal paterni oluşturmak için birkaç oktav gürültü ekleyiniz.
  • Alt kaba tutmak için gürültü kare.
  • tanhÜst seviyeden seviyeye çıkarmak için gürültüyü besleyin .
  • Üst katmanda biraz daha fazla doku için iki oktav ekleyin.
  • Elde edilen yüzeyin normlarını hesaplayın.
  • Speküler ve dağınık ışıklarla, yüzeye basit bir Phong gölgeleme uygulayın. Renkler, ilk örnek görüntüden topladığım bazı rasgele renklere göre seçiliyor.

17
Bu duvarın kendisinden daha gerçekçi: o
Quentin

1
Bazı “damarlar” / “yılanlar” / “solucanlar” bu resmi “duvar” için daha uygun hale getirir. Ama yine de iyi.
Nova

33

Mathematica Spackling

Aşağıdaki uygulama, rastgele bir görüntü için benekli uygulanır. "Yeni düzeltme ekini" tıklamak, çalışmak için yeni bir rasgele görüntü oluşturur ve ardından efektleri geçerli ayarlara göre uygular. Etkileri yağlıboya resim, Gaussian filtresi, posterleme ve kabartmadır. Her efekt bağımsız olarak tweaked edilebilir. Rasgele sayı üreteci için tohum 1 ila 2 ^ 16 arasında herhangi bir tam sayı olabilir.

Güncelleme : Kenarları yumuşatan Gaussian filtre, şimdi uygulanan son görüntü efekti. Bu değişiklikle, posterleştirme etkisine artık ihtiyaç duyulmadı ve bu nedenle kaldırıldı.

Manipulate[
 GaussianFilter[ImageEffect[ImageEffect[r, {"OilPainting", o}], {"Embossing", e, 1.8}], g],
 Button["new patch", (SeedRandom[seed] r = RandomImage[1, {400, 400}])], 
 {{o, 15, "oil painting"}, 1, 20, 1, ContinuousAction -> False, Appearance -> "Labeled"}, 
 {{e, 1.64, "embossing"}, 0, 5, ContinuousAction -> False, Appearance -> "Labeled"},
 {{g, 5, "Gaussian filter"}, 1, 12, 1, ContinuousAction -> False, Appearance -> "Labeled"},
 {{seed, 1}, 1, 2^16, 1, ContinuousAction -> False, Appearance -> "Labeled"}, 
 Initialization :> (SeedRandom[seed]; r = RandomImage[1, {400, 400}])]

sonuç


açıklama

Açıklama, posterlemenin kullanıldığı ve GaussianFilterdaha önce uygulandığı , biraz farklı bir sürüme dayanıyor . Ancak yine de, her görüntünün etkisinin bir görüntüyü nasıl değiştirdiğini netleştirmeye hizmet eder. Sonuç, keskin kenarlı bir boya dokusudur. Gaussian filtre yalnızca sonunda uygulandığında, yukarıdaki resimde gösterildiği gibi sonuç daha yumuşak olacaktır.

Her seferinde bir tane olmak üzere bazı görüntü efektlerine bakalım.

Bir başlangıç ​​resmi oluşturun.

 r = RandomImage[1, {200, 200}]

Rastgele görüntü


Lena bize her görüntünün nasıl bir canlı fotoğrafa dönüştüğünü gösterecek.

Lena = ExampleData[{"TestImage", "Lena"}]

Lena


Lena'ya bir yağlı boya efekti uygulandı.

ImageEffect[Lena, {"OilPainting", 8}]

lena yağı

Rastgele imajımıza uygulanan bir yağlı boya efekti. Etki yoğunlaştırıldı (8 yerine 16).

 r1 = ImageEffect[r, {"OilPainting", 16}]

sıvı yağ


Lena'ya uygulanan bir Gauss filtre efekti (Lena'nın yağlı boya efekti sürümüne değil). Yarıçapı 10 pikseldir. (Son sürümde, bu girişin başında, GaussianFilter son efekt olarak uygulanır.)

 GaussianFilter[Lena, 10]

Lena Gaussian.


R1'e biraz daha hafif bir Gauss filtre etkisi uygulandı. Yarıçapı 5 pikseldir.

 r2 = GaussianFilter[r1, 5]

gaus


Lena'ya uygulanan yoğun bir posterizasyon etkisi. (Uygulamanın son sürümünde, posterleştirmeyi kaldırdım. Fakat analizdeki örnekler posterlemeyle daha eski bir sürüme dayandığından, bunu analizde bırakacağız.)

 ImageEffect[Lena, {"Posterization", 2}]

Lena Posterize


R2'ye uygulanan bir posterizasyon efekti.

r3 = ImageEffect[r2, {"Posterization", 4}]

posterize


Kabartma Lena

 ImageEffect[Lena, {"Embossing", 1.2, 1.8}]

lena kabartma


Kabartma r3, görüntü işlemeyi tamamlar. Bu OP'nin tavanı gibi bir şeye benzemek içindir.

 ceilingSample = ImageEffect[r3, {"Embossing", 1.2, 1.8}]

kabartma yapmak


Meraklı için, burada aynı görüntü efektleri uygulanmış olan Lena.

lena4


... Lena imajını elde etmek için bir yerleşik var mı? LOL.
kullanıcı253751,

7
Evet. Mathematica'da görüntü işleme testleri için kullanılan yaklaşık 30 adet yerleşik resim var.
DavidC

Hafif bir değişiklikle, RandomIntegerbir tohum beslenebilir ve böylece belirli bir çıktı garanti edilir. Yoksa, etkilerin uygulandığı, Rastgele olmayan bir görüntü gibi, başka bir şey mi demek istiyorsunuz?
DavidC

1
Şimdi 1 ila 2 ^ 16 arasında bir tohum kabul eder.
DavidC

1
+1 çünkü Lena will show us how each image effect transforms a life-like picturebeni LOL yaptı. Asıl garip olan, son Lena imgesinin bir Aztek veya İnka'nın sola dönük, bir başlık takmış ve bir sanki silahmış gibi bir dal yapması gibi görünüyor.
Seviye Nehri St

13

POV-Ray

Çok sayıda golf oynama potansiyeli var povray /RENDER wall.pov -h512 -w512 -K234543 görüntü tanımını buraya girin

İlk önce rastgele bir doku oluşturur, ancak orada durmak yerine, dokuyu 3D yükseklik alanına dönüştürür ve kameradan gelen radyal gölgeleri daha gerçekçi bir şekilde parlatır. Ve iyi bir ölçü için, üstüne küçük tümsekler başka bir doku ekler.
Rastgele tohumun kodlamasının dışında tek yolu clock, animasyonlar için kullanılan değişkeni kullanmaktır , bu -K{number}bayrakla geçirilir

#default{ finish{ ambient 0.1 diffuse 0.9 }} 

camera {location y look_at 0 right x}
light_source {5*y color 1}

#declare R1 = seed (clock); // <= change this

#declare HF_Function  =
 function{
   pigment{
     crackle turbulence 0.6
     color_map{
       [0.00, color 0.01]
       [0.10, color 0.05]
       [0.30, color 0.20]
       [0.50, color 0.31]
       [0.70, color 0.28]
       [1.00, color 0.26]
     }// end color_map
    scale <0.25,0.005,0.25>*0.7 
    translate <500*rand(R1),0,500*rand(R1)>
   } // end pigment
 } // end function

height_field{
  function  512, 512
  { HF_Function(x,0,y).gray * .04 }
  smooth 
  texture { pigment{ color rgb<0.6,0.55,0.5>}
            normal { bumps 0.1 scale 0.005}
            finish { phong .1 phong_size 400}
          } // end of texture  
  translate< -0.5,0.0,-0.5>
}

Bunu hiç golf oynamaya gerek yok. Güzel sonuçlar! :)
Martin Ender,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.