• 沒有找到結果。

to model such spatial variations.

N/A
N/A
Protected

Academic year: 2022

Share "to model such spatial variations."

Copied!
24
0
0

加載中.... (立即查看全文)

全文

(1)

Texture

Digital Image Synthesis g g y Yung-Yu Chuang

with slides by Pat Hanrahan and Mario Costa Sousa

Texture

• Recall that materials requires parameters to describe their characteristics These parameters describe their characteristics. These parameters are often spatially varying and textures are used to model such spatial variations

to model such spatial variations.

• Textures is a function that maps points in some

d i t l i th d i

domain to values in some other domain.

• core/texture.* mipmap.h texture/* (currently 12 plug-ins in total)

• In pbrt, pattern generation is separated from p , p g p material implementation so that it is more flexible.

Texture maps

• How is a texture mapped to the surface?

Di i lit 1D 2D 3D – Dimensionality: 1D, 2D, 3D – Texture coordinates (s,t)

S f t ( )

• Surface parameters (u,v)

• Projection: spherical, cylindrical, planar

• ReparameterizationReparameterization

• What can a texture control?

Surface color and transparency – Surface color and transparency

– Illumination: environment maps, shadow maps Reflection function: reflectance maps

– Reflection function: reflectance maps – Geometry: displacement and bump maps

Texture mapping

scene scene (u,v) mapping

p

pp g

(s,t)

T(s,t)

footprint

screen texture T

p

(2)

Texture History

• 1974 basic idea (Catmull/Williams) 1976 fl i (Bli /N ll)

• 1976 reflection maps (Blinn/Newell)

• 1978 bump mapping (Blinn)

• 1983 mipmap (Williams)

• 1984 illumination (Miller/Hoffman)

• 1984 illumination (Miller/Hoffman)

• 1985 solid texture (Perlin)

Texture maps Reflection maps

(3)

Environment maps Bump/displacement maps

Illumination maps Illumination maps

(4)

Solid textures Sampling and antialiasing

• A source of high-frequency variation in the final image Aliasing could be reduced by sampling image. Aliasing could be reduced by sampling, but it is more efficient if a good approximation can be provided

can be provided.

Sampling and antialiasing

• Antialiasing for textures is not as hopeless as we have seen in chapter 7 because there are we have seen in chapter 7 because there are either analytical forms or ways to avoid adding high frequency

high frequency

• Two problems that must be addressed

1. Compute the sampling rate in texture space 2. Apply sampling theory to guide texture

i computation

Finding the texture sampling rate

scene p

p scene

p

x

p

y

screen texture

(5)

Differential geometry

• DifferentialGeometry : a self-contained representation for a particular point on a representation for a particular point on a surface so that all the other operations in pbrt can be executed without referring to the

can be executed without referring to the original shape. It contains

P iti

• Position

• Surface normal

• Parameterization

• Parametric derivatives

• Parametric derivatives

• Derivatives of normals P i t t h

• Pointer to shape

DifferentialGeometry

struct DifferentialGeometry { ...

// DifferentialGeometry Public Data Point p;

Normal nn;

float u, v;

const Shape *shape;

const Shape *shape;

Vector dpdu, dpdv;

Normal dndu, dndv; ,

mutable Vector dpdx, dpdy;

mutable float dudx, dvdx, dudy, dvdy;

} };

Intersection:GetBSDF() calls

DifferentialGeometry::ComputeDifferentials() DifferentialGeometry::ComputeDifferentials() to calculate these values.

ComputeDifferentials

scene n

p

p scene

p

x

p

y

n x n p = 0 n

x - n

p = 0

d n

o n p n

  t

screen n d

ComputeDifferentials(RayDifferential&)

float d = -Dot(nn, Vector(p.x, p.y, p.z));

Vector rxv(ray.rx.o.x, ray.rx.o.y, ray.rx.o.z);

Vector rxv(ray.rx.o.x, ray.rx.o.y, ray.rx.o.z);

float tx = -(Dot(nn, rxv) + d) / Dot(nn, ray.rx.d); y Point px = ray.rx.o + tx * ray.rx.d;

Vector ryv(ray.ry.o.x, ray.ry.o.y, ray.ry.o.z);

float ty = -(Dot(nn, ryv) + d)

/ D t( d)

/ Dot(nn, ray.ry.d);

Point py = ray.ry.o + ty * ray.ry.d;

dpdx = px - p;

dpdy = py - p; n d

o n p n    t

dpdy = py p; nd

(6)

ComputeDifferentials

scene

x

v

p

p scene

v p

v

x

p

x

u p

u

x u

p

y u

p p  

 

' v

p u

p p

p

u v

 

 

 ' 

 

 

 

 

 

 

v u

p

v

p u p p

p'

screen   

v

ComputeDifferentials

float A[2][2], Bx[2], By[2], x[2];

// we only need 2 equations; select two axes int axes[2];

if (fabsf(nn.x) > fabsf(nn.y)

&& fabsf(nn.x) > fabsf(nn.z)) { axes[0] = 1; axes[1] = 2;

axes[0] = 1; axes[1] = 2;

}

else if (fabsf(nn.y) > fabsf(nn.z)) { y axes[0] = 0; axes[1] = 2;

}

l {

else {

axes[0] = 0; axes[1] = 1;

} }

ComputeDifferentials

// matrices for chosen projection plane A[0][0] = dpdu[axes[0]]; [ ][ ] p [ [ ]]

A[0][1] = dpdv[axes[0]];

A[1][0] = dpdu[axes[1]];

A[1][1] = dpdv[axes[1]];

Bx[0] = px[axes[0]] - p[axes[0]];

Bx[1] = px[axes[1]] - p[axes[1]];

Bx[1] = px[axes[1]] - p[axes[1]];

By[0] = py[axes[0]] - p[axes[0]];

By[1] = py[axes[1]] - p[axes[1]]; y py p

ComputeDifferentials

if (SolveLinearSystem2x2(A, Bx, x)) { dudx = x[0]; dvdx = x[1]; [ ] [ ]

}

else {

dudx = 1.; dvdx = 0.;

}

if (SolveLinearSystem2x2(A, By, x)) { dudy = x[0]; dvdy = x[1]; y y

}

else {

d d 0 d d 1

dudy = 0.; dvdy = 1.;

}

(7)

Texture coordinate generation

• We use (s,t) for texture coordinate and (u,v) for parametric coordinate

parametric coordinate.

• Creating smooth parameterization of complex h ith l di t ti i till ti meshes with low distortion is still an active research area in graphics.

• Two classes, TextureMapping2D and

TextureMapping3D , provide an interface for computing these 2D or 3D texture coordinates.

Texture coordinate generation

class TextureMapping2D {

virtual ~ TextureMapping2D() { }

virtual void Map(const DifferentialGeometry &dg, float *s, float *t, float *dsdx, float *dtdx, float *dsdy, float *dtdy) const = 0;

};

(u,v) spherical cylindrical planar

(u.v)-mapping

class UVMapping2D : public TextureMapping2D { UVMapping2D(float su = 1, float sv = 1,pp g ( , ,

scale

float du = 0, float dv = 0);

...

offset d

u s

s   ts vd

}

void UVMapping2D::Map(const DifferentialGeometry &dg, float *s float *t float *dsdx float *dtdx

u

u

u d

s

st s

v

vd

v

float *s, float *t, float *dsdx, float *dtdx, float *dsdy, float *dtdy) const

{ {

*s = su * dg.u + du; *t = sv * dg.v + dv;

s u v s u s

s        

x is a function of u v

*dsdx = su * dg.dudx; *dtdx = sv * dg.dvdx;

*dsdy = su * dg dudy; *dtdy = sv * dg dvdy;

s x x v x u

x

u

 

 

x is a function of u,v

*dsdy = su * dg.dudy; *dtdy = sv * dg.dvdy;

}

Spherical mapping

class SphericalMapping2D : public TextureMapping2D { ...

SphericalMapping2D(const Transform &toSph) : WorldToTexture(toSph) { } };

(8)

Spherical mapping

void sphere(Point &p, float *s, float *t) {

Vector v=Normalize(WorldToTexture(p)-Point(0 0 0));

Vector v Normalize(WorldToTexture(p) Point(0,0,0));

float theta = SphericalTheta(v);

float phi = SphericalPhi(v);

*s = theta * INV_PI;

*t = phi * INV_TWOPI;

}

 

s f

s

( p p x ) f

s

( p )

 

x

Spherical mapping

void SphericalMapping2D::Map(...) {

sphere(dg.p, s, t);

float sx, tx, sy, ty;

const float delta = 1f;

const float delta = .1f;

sphere(dg.p + delta * dg.dpdx, &sx, &tx);

*dsdx = (sx - *s) / delta;

*dtdx = (tx - *t) / delta;

if (*dtdx > .5) *dtdx = 1.f - *dtdx;

else if (*dtdx < -.5f) *dtdx = -(*dtdx + 1);

avoid seam at t=1

else if ( dtdx < .5f) dtdx ( dtdx + 1);

sphere(dg.p + delta * dg.dpdy, &sy, &ty);

*dsdy = (sy - *s) / delta;

*d d ( * ) / d l

*dtdy = (ty - *t) / delta;

if (*dtdy > .5) *dtdy = 1.f - *dtdy;

else if (*dtdy < -.5f) *dtdy = -(*dtdy + 1);( y ) y ( y );

}

Spherical mapping Cylindrical mapping

t

void cylinder(const Point &p, float *s, float *t) { Vector v=Normalize(WorldToTexture(p)-Point(0 0 0));

s

Vector v=Normalize(WorldToTexture(p) Point(0,0,0));

*s = (M_PI + atan2f(v.y, v.x)) / (2.f * M_PI);

*t = v.z;

}

How to calculate differentials?

}

How to calculate differentials?

(9)

Cylindrical mapping Planar mapping

void PlanarMapping2D::Map(DifferentialGeometry &dg, float *s, float *t, float *dsdx, float *dtdx,, , , , float *dsdy, float *dtdy) const {

Vector vec = dg.p - Point(0,0,0);

*s = ds + Dot(vec, vs);

*t = dt + Dot(vec, vt);

*dsdx = Dot(dg dpdx vs);

*dsdx = Dot(dg.dpdx, vs);

*dtdx = Dot(dg.dpdx, vt);

*dsdy = Dot(dg.dpdy, vs);

v

t

y ( g p y, )

v

*dtdy = Dot(dg.dpdy, vt);

}

v

s

d

s,

d

t

Example, for z=0 plane, v =(1 0 0) v =(0 1 0) d =d =0 v

s

=(1,0,0), v

t

=(0,1,0), d

s

=d

t

=0

Planar mapping 3D mapping

class TextureMapping3D { public:

virtual ~TextureMapping3D() { }

virtual Point Map(const DifferentialGeometry &dg, Vector *dpdx Vector *dpdy) const = 0;

Vector *dpdx, Vector *dpdy) const = 0;

};

Point IdentityMapping3D::Map(

const DifferentialGeometry &dg, Vector *dpdx, Vector *dpdy) const Vector dpdx, Vector dpdy) const {

*dpdx = WorldToTexture(dg.dpdx);

*dpdy = WorldToTexture(dg.dpdy);

return WorldToTexture(dg.p);

} }

(10)

Texture

template <class T> class Texture { public:

p

virtual T Evaluate(DifferentialGeometry &) = 0;

virtual ~Texture() { } };

pbrt currently uses only fl t and S t textures pbrt currently uses only float and Spectrum textures.

ConstantTexture

template <class T>

class ConstantTexture : public Texture<T> { public:

ConstantTexture(const T &v) { value = v; }

T Evaluate(const DifferentialGeometry &) const { T Evaluate(const DifferentialGeometry &) const {

return value;

} private:

T value;

};

};

It can be accurately reconstructed from any sampling rate and therefore needs no antialiasing

and therefore needs no antialiasing.

ScaleTexture

template <class T1, class T2>

class ScaleTexture : public Texture<T2> { public:

// ScaleTexture Public Methods

ScaleTexture(Reference<Texture<T1> > t1 ScaleTexture(Reference<Texture<T1> > t1,

Reference<Texture<T2> > t2) {

tex1 = t1; tex2 = t2;

}

T2 Evaluate(const DifferentialGeometry &dg) const T2 Evaluate(const DifferentialGeometry &dg) const

{

return tex1->Evaluate(dg) * tex2->Evaluate(dg);

} Leave antialiasing to tex1 and tex2; ignore antialiasing of }

private:

Reference<Texture<T1> > tex1;

Leave antialiasing to tex1 and tex2; ignore antialiasing of the product, it is generally fine

Reference<Texture<T2> > tex2;

};

MixTexture

template <class T>

class MixTexture : public Texture<T> { public:

MixTexture(Reference<Texture<T> > t1, Reference<Texture<T> > t2,

Reference<Texture<float> > amt) {

tex1 = t1; tex2 = t2; amount = amt;; ; ; }

T Evaluate(const DifferentialGeometry &dg) const { T t1=tex1->Evaluate(dg) t2=tex2->Evaluate(dg);

T t1=tex1 >Evaluate(dg), t2=tex2 >Evaluate(dg);

float amt = amount->Evaluate(dg);

return (1.f - amt) * t1 + amt * t2;

} i i ti li i i h

} private:

Reference<Texture<T> > tex1, tex2;

f fl

again, ignore antialiasing issue here Reference<Texture<float> > amount;

};

(11)

BilerpTexture

BilerpTexture::BilerpTexture(TextureMapping2D *m, const T &t00, const T &t01, const T &t10, const T &t11) {

mapping = m;

v00 = t00;

v01 = t01;

v10 = t10;

v00 s v10

; v11 = t11;

} t (s,t)

T Evaluate(... &dg) {

fl

float s, t, ...;

mapping->Map(dg, &s, &t,...);

...

}

v01 v11

Image texture

class ImageTexture : public Texture<T> { public:

ImageTexture(TextureMapping2D *m, string &filename, bool doTri, float maxAniso, ImageWrap wm);

T Evaluate(const DifferentialGeometry &);

only one copy even

~ImageTexture();

private:

static MIPMap<T>

• only one copy even if it is used multiple times

C t d t t T p

*GetTexture(

string &filename, bool doTrilinear

• Converted to type T

• Failed-> 1-image bool doTrilinear,

float maxAniso, ImageWrap wm);

...

MIPMap<T> *mipmap;

TextureMapping2D *mapping;

} };

Mip maps

• It is more efficient to do antialiasing for textures because

textures because

1. Less expensive to get samples

2 W l filt i i th t t 2. We can apply pre-filtering since the texture

function is fully defined

However the sampling

• However, the sampling rate is spatially varying, need to filter over

need to filter over arbitrary regions efficiently

efficiently

• A mipmap takes at most 1/3 more memory

1/3 more memory

Mipmaps

• Resize by resampling if the original resolution is not power of 2 Apply a box filter to do

not power of 2. Apply a box filter to do downsampling.

typedef enum { TEXTURE_REPEAT, TEXTURE_BLACK, TEXTURE_CLAMP } ImageWrap;

• Use 4 points and Lanczos reconstruction filter

• Implemented as a BlockedArray to improve performance

performance

(12)

Access texel at a level

const T &MIPMap<T>::texel(int level, int s, int t) { const BlockedArray<T> &l = *pyramid[level];

switch (wrapMode) { case TEXTURE_REPEAT:

s = Mod(s, l.uSize());

t = Mod(t, l.vSize()); break;

case TEXTURE_CLAMP:

s = Clamp(s, 0, l.uSize() - 1);p( , , () );

t = Clamp(t, 0, l.vSize() - 1); break;

case TEXTURE_BLACK: {

static const T black = 0 f;

static const T black = 0.f;

if (s < 0 || s >= l.uSize() ||

t < 0 || t >= l.vSize()) return black; break;

return black; break;

} }

l( )

return l(s, t);

}

Mipmap lookup

• Return the texel value for a given (s, t)

T h d

• Two methods:

– Triangle filter – EWA filter

Mipmap lookup

• Trilinear filtering: level Res.

Lookup(float s, float t, float width)

l n

 2

1

1 ln  1 log w

0 2

n-1

1

w 2 ln 1 log w

choose the level to

: :

l 2

n-1-l

choose the level to

cover four texels : :

n-1 1

Trilinear filtering

(13)

Trilinear filtering

T Lookup(float s, float t, float width){

float level = nLevels - 1 + Log2(max(width, g ( ( , 1e-8f));

if (level < 0) if (level < 0)

return triangle(0, s, t);

else if (level >= nLevels - 1) else if (level > nLevels 1)

return texel(nLevels-1, 0, 0);

else {

int iLevel = Floor2Int(level);

float delta = level - iLevel;

return (1 delta)*triangle(iLevel s t) return (1-delta)*triangle(iLevel, s, t)

+ delta * triangle(iLevel+1, s, t);

} } }

Trilinear filtering

T triangle(int level, float s, float t) {

{

level = Clamp(level, 0, nLevels-1);

s = s * pyramid[level] >uSize() 0 5f;

s = s * pyramid[level]->uSize() - 0.5f;

t = t * pyramid[level]->vSize() - 0.5f;

int s0 Floor2Int(s) t0 Floor2Int(t);

int s0 = Floor2Int(s), t0 = Floor2Int(t);

float ds = s - s0, dt = t - t0;

t (1 d )*(1 f dt)*t l(l l 0 t0) return (1-ds)*(1.f-dt)*texel(level,s0,t0)

+(1-ds)*dt * texel(level, s0, t0+1) d *(1 dt) * t l(l l 0 1 t0) +ds*(1-dt) * texel(level, s0+1, t0) +ds*dt * texel(level, s0+1, t0+1);

}

Mipmap lookup

• Elliptically weighted average filtering

Mipmaps

trilinear EWA

(14)

Solid and procedural texturing

• Solid texture: textures defined over 3D domains;

often requiring a large amount of storage often requiring a large amount of storage

• Procedural texture: short programs are used to

t t t l ( i )

generate texture values (e.g. sine waves)

– Less storage

– Better details (evaluate accurate values when needed; resolution independent)

H d l

– Harder to control

– More difficult to do antialising

UV texture

Convert (s, t) into first 2 components of spectrum, mostly for debugging.

UV texture

Spectrum Evaluate(const DifferentialGeometry &dg) { float s, t, dsdx, dtdx, dsdy, dtdy;, , , , y, y;

mapping->Map(dg, &s, &t, &dsdx,&dtdx,&dsdy,&dtdy);

float cs[COLOR_SAMPLES];

memset(cs, 0, COLOR_SAMPLES * sizeof(float));

cs[0] = s - Floor2Int(s);

cs[1] = t Floor2Int(t);

cs[1] = t - Floor2Int(t);

return Spectrum(cs);

} }

Checkboard

(15)

Checkerboard2D

class Checkerboard2D : public Texture<T> { Checkerboard2D(TextureMapping2D *m,

Reference<Texture<T>> c1, Reference<Texture<T>> c2, const string &aa);

...

T Evaluate(const DifferentialGeometry &dg) const { float s, t, dsdx, dtdx, dsdy, dtdy;

mapping->Map(dg, &s, &t,&dsdx,&dtdx,&dsdy,&dtdy);

if (aaMethod==CLOSEFORM) {...}

else if (aaMethod==SUPERSAMPLE) { } else if (aaMethod SUPERSAMPLE) {...}

else { // no antialiasing

if ((Floor2Int(s) + Floor2Int(t)) % 2 == 0) return tex1->Evaluate(dg);

return tex2->Evaluate(dg);

} } }

Close-form

float ds = max(fabsf(dsdx), fabsf(dsdy));

float dt = max(fabsf(dtdx), fabsf(dtdy));

float s0 = s - ds, s1 = s + ds;

float t0 = t - dt, t1 = t + dt;

if (Floor2Int(s0) == Floor2Int(s1) &&( ( ) ( ) Floor2Int(t0) == Floor2Int(t1)) {

if ((Floor2Int(s) + Floor2Int(t)) % 2 == 0) return tex1->Evaluate(dg);

point sampling

) ,

( t

s t s  

return tex1 >Evaluate(dg);

return tex2->Evaluate(dg);

}

point sampling

t

 ) , ( yy )

,

( x

t t x s s





) ,

( ts ( , )

x t t x s s





Close-form

#define BUMPINT(x) \

(Floor2Int((x)/2) + \

( (( )/ ) \

2.f * max((x/2)-Floor2Int(x/2) - .5f, 0.f)) float sint = (BUMPINT(s1) - BUMPINT(s0)) / (2.f*ds);

float tint = (BUMPINT(t1) - BUMPINT(t0)) / (2.f*dt);

float area2 = sint + tint - 2.f * sint * tint;

if (ds > 1 f || dt > 1 f) area2 = 5f;

if (ds > 1.f || dt > 1.f) area2 = .5f;

return (1.f - area2) * tex1->Evaluate(dg) + area2 * tex2->Evaluate(dg);( g)

  

x x xx1 

( ) 2 2max 2 2 21,0

0

x x dx x

x c

Close-form

(16)

Supersampling

• Takes a fixed number of stratified samples and applies a Gaussian filter for reconstruction applies a Gaussian filter for reconstruction

#define SQRT SAMPLES 4

#define SQRT_SAMPLES 4

#define N_SAMPLES (SQRT_SAMPLES * SQRT_SAMPLES) float samples[2*N_SAMPLES];

StratifiedSample2D(samples,SQRT_SAMPLES,SQRT_SAMPLES);

T value = 0.;

fl t filt S 0 float filterSum = 0.;

Supersampling

for (int i = 0; i < N_SAMPLES; ++i) { float dx = samples[2*i] - 0.5f;

float dy = samples[2*i+1] - 0.5f;

DifferentialGeometry dgs = dg;

dgs p += dx * dgs dpdx + dy * dgs dpdy;

dgs.p += dx dgs.dpdx + dy dgs.dpdy;

dgs.u += dx * dgs.dudx + dy * dgs.dudy;

dgs.v += dx * dgs.dvdx + dy * dgs.dvdy;

...

float ss, ts, dsdxs, dtdxs, dsdys, dtdys;

mapping->Map(dgs,&ss,&ts,&dsdxs,&dtdxs,&dsdys,&dtdys);pp g p( g , , , , , y , y );

float wt = expf(-2.f * (dx*dx + dy*dy));

filterSum += wt;

if ((Fl 2I t( ) + Fl 2I t(t )) % 2 0) if ((Floor2Int(ss) + Floor2Int(ts)) % 2 == 0)

value += wt * tex1->Evaluate(dgs);

else value += wt * tex2->Evaluate(dgs);

}

return value / filterSum;

Comparisons

no antialiasing

closed-form

l li i

less aliasing but blurring

supersampling supersampling less blurring susceptible to p aliasing

Solid checkboard

Checkerboard3D(TextureMapping3D *m,

Reference<Texture<T>> c1, Reference<Texture<T>> c2) , ) {

mapping = m;

tex1 = c1;

tex2 = c2;

} }

if ((Floor2Int(P.x)+Floor2Int(P.y)+ Floor2Int(P.z)) (( ( ) ( y) ( ))

% 2 == 0)

value += wt * tex1->Evaluate(dgs);

else

value += wt * tex2->Evaluate(dgs);

for supersampling

(17)

Solid checkboard Some other procedure textures

• Stripe

R d i

• Ramp and sine

• Rings

• Wood

Stripes on teapot

• Find the integer part of the x-, y-, or z-value of each point of the object

point of the object.

• If resulting value is even

• If resulting value is even,

– then choose red;

– else choose white.

Ramp and Sine Functions

• A nice ramp: mod(x,a)/a

• This ramp function has a range of zero to one as does

• This ramp function has a range of zero to one, as does (sin(x)+1)/2.

Magenta to value of zero; and yellow to the value one

(18)

Rings on teapot

• Use the x- and y-components to compute the distance of a point from the object’s center, and truncate the p j , result.

• If the resulting value is even,

– then we choose red;

– else we choose white.

Wood grain

• r=x

2

+y

2

i ( ) (i ( )) % 2

• ring(r) = (int (r)) % 2

• Wobble(r) = ring( r/M + k*sin(θ/N)) z

Noise

• Real-world objects have both regularity and irregularity in nature

irregularity in nature.

Perlin noise

• For example, we might want to add “noise” to the stripe function One possibility would be to the stripe function. One possibility would be to add random numbers to the stripe function.

This won’t look good because it looks just like This won t look good because it looks just like white noise in TV.

W t t k it th ith t l i

• We want to make it smoother without losing the random quality.

• Another option is to take a random value at

every lattice point and interpolate them. This

often makes the lattice too obvious.

(19)

Smooth out randomness (1D) Perlin noise

• Developed by Ken Perlin for TRON (1982) TRON i h fi 3D h d d hi i

• TRON is the first 3D shaded graphics in a Hollywood film

• Perlin used some tricks to improve the basic to improve the basic lattice approach to achieve “determined achieve determined and coherent

randomness”

randomness

• float Noise(float x, float y, float z) in pbrt

Perlin noise

• Hermite interpolation

Random vectors instead of random values;

• Random vectors instead of random values;

values are derived using inner product Hashing for randomness

• Hashing for randomness

 

 

 

  

1 1 1

( , , )

) , , (

x y z

ijk

x i y j z k

z y x n

 

 

  

 

) , , ( )

, , (

x

i j y k z

ijk

y j

y

)) , , ( )(

( ) ( ) ( ) , ,

( u v w u v w

ijk

u v w

ijk

  

   

1 t 0 1 t 3 t 2 )

( t

3

2

  

)))) ( ( (

( i j k

G   

ijk

G (  ( i   ( j   ( k ))))

]

% [ )

( iP i n

Pis an array of length n containing a permutation of 0 n-1; n=256 in practice

of 0..n 1; n 256 in practice Gis a precomputed array of n random unit vectors

Perlin noise (2D illustration)

ijij

j i 1) (

(i1)j

) 1 (

i j

) 1 )(

1 (

(ii1)(jj1)

(20)

Improving Perlin noise (Perlin 2002)

• Two deficiencies:

I t l ti f ti ’ 2 d d i ti i t 12t-6 t – Interpolation function’s 2nd derivative is not zero at either t=0 or t=1, creating 2nd order discontinuities.

Gradient in G are distributed uniformly over a – Gradient in G are distributed uniformly over a

sphere; but, cubic grid has directional biases

Improving Perlin noise (Perlin 2002)

•  ( t )  6 t

5

 15 t

4

 10 t

3

0  t  1 30t

4

-60t

3

+30t

2

120t

3

-180t

2

+60t

• Use only 12 vectors, defined by the directions

120t 180t +60t

from the center of a cube to its edges. It is not necessary for G to be random since P provides plenty of randomness.

Improving Perlin noise (Perlin 2002)

3 4

5

1 10

6 ) 1 (

t 3 t 2 )

( t

3

2

  ( t ) 6 t

5

15 t

4

10 t

3

Improving Perlin noise (Perlin 2002)

uniformly sampled from a sphere use only 12 vectors;

uniformly sampled from a sphere use only 12 vectors;

also faster

(21)

Random Polka dots

• Divide texture space into regular cells; each cell has a 50% chance of having a dot inside it cell has a 50% chance of having a dot inside it.

DotsTexture(TextureMapping2D *m,

Reference<Texture<T>> c1, Reference<Texture<T>> c2) { mapping = m;

{ pp g ;

outsideDot = c1;

insideDot = c2;

} }

Random Polka dots

T Evaluate(const DifferentialGeometry &dg) const { float s, t, dsdx, dtdx, dsdy, dtdy;

mapping->Map(dg,&s,&t,&dsdx,&dtdx,&dsdy,&dtdy);

int sCell = Floor2Int(s + .5f), tCell = Floor2Int(t + .5f);

if (Noise(sCell+.5f, tCell+.5f) > 0) { float radius = .35f;

float maxShift = 0.5f - radius;

It is deterministic so that it makes consistent decision for pixels.

; float sCenter = sCell + maxShift *

Noise(sCell + 1.5f, tCell + 2.8f);

float tCenter = tCell + maxShift * float tCenter = tCell + maxShift

Noise(sCell + 4.5f, tCell + 9.8f);

float ds = s - sCenter, dt = t - tCenter;

if (ds*ds + dt*dt < radius*radius) if (ds*ds + dt*dt < radius*radius) return insideDot->Evaluate(dg);

}

id l (d )

return outsideDot->Evaluate(dg);

}

Random Polka dots Multiple-scale Perlin noise

• Many applications would like to have variation over multiple scales

over multiple scales.

i i

s

x w f s x

f ( )  ( )

i

2

1

i

i

s

1

s 2 1

i

i

w

w

• Application of this to Perlin noise leads to

“Fractional Brownian motion” (FBm)

2

Fractional Brownian motion (FBm)

• Turblence

f

f ( )  ( )

i

i i

s

x w f s x

f ( ) ( )

(22)

(1-D) Perlin Noise Function :

• Get lots of such smooth functions, with various frequencies and amplitudes

(1-D) Perlin Noise Function :

• Get lots of such smooth functions, with various frequencies and amplitudes

• Add them all together to create a nice noisy functiong y

+ + +

+ + =

(2-D) Perlin Noise Function (2-D) Perlin Noise Function

+ + +

+ + =

(23)

Bumpy and wrinkled textures

• FBmTexture uses FBm to compute offset and WrinkledTexture uses Turbulence to do so WrinkledTexture uses Turbulence to do so.

FBmTexture WrinkledTexture

FBmTexture

FBmTexture(int oct, float roughness, TextureMapping3D *map) { TextureMapping3D *map) { omega = roughness;

octaves = oct;

octaves = oct;

mapping = map;

} }

T E l t ( t Diff ti lG t &d ){

T Evaluate(const DifferentialGeometry &dg){

Vector dpdx, dpdy;

P i t P i M (d d d d d )

Point P = mapping->Map(dg, &dpdx, &dpdy);

return FBm(P, dpdx, dpdy, omega, octaves);

}

Windy waves

T WindyTexture:Evaluate(DifferentialGeometry &dg) { Vector dpdx, dpdy;p , p y;

Point P = mapping->Map(dg, &dpdx, &dpdy);

float windStrength = low frequency for local wind strength FBm(.1f * P, .1f * dpdx, .1f * dpdy, .5f, 3);

float waveHeight =

FBm(P dpdx dpdy 5f 6);

amplitude of wave independent of wind FBm(P, dpdx, dpdy, .5f, 6);

return fabsf(windStrength) * waveHeight;

} }

Windy waves

(24)

Marble

• Perturb texture coordinates before using another texture or lookup table

another texture or lookup table

Texture Generation using 3D Perlin Noise

Standard 3 dimensional Perlin noise 4 octaves, persistence 0.25 and 0.5

Texture Generation using 3D Perlin Noise

A marble texture can be made by using a Perlin function as an offset using a Perlin function as an offset to a cosine function.

texture = cosine( x + perlin(x,y,z) )

Texture Generation using 3D Perlin Noise

• Very nice wood textures can be defined.

• The grain is defined with a low

• The grain is defined with a low persistence function like this:

li ( ) * 20 g = perlin(x,y,z) * 20 grain = g - int(g)

• The very fine bumps you can see on the wood are high frequency noise that has g q y been stretched in one dimension.

bumps = perlin(x*50,y*50,z*20) bu ps pe ( 50,y 50, 0) if bumps < .5

then bumps = 0 else bumps = 1t else bumps = 1t

參考文獻

相關文件

The third step is to express the proper rational function R(x)/Q(x) (from Equation 1) as a sum of partial fractions of the

With the proposed model equations, accurate results can be obtained on a mapped grid using a standard method, such as the high-resolution wave- propagation algorithm for a

(In Section 7.5 we will be able to use Newton's Law of Cooling to find an equation for T as a function of time.) By measuring the slope of the tangent, estimate the rate of change

An additional senior teacher post, to be offset by a post in the rank of CM or Assistant Primary School Master/Mistress (APSM) as appropriate, is provided to each primary

An additional senior teacher post, to be offset by a post in the rank of Certificated Master/Mistress or Assistant Primary School Master/ Mistress as appropriate, is provided

An additional senior teacher post, to be offset by a post in the rank of CM or Assistant Primary School Master/Mistress (APSM) as appropriate, is provided to each primary

An additional senior teacher post, to be offset by a post in the rank of CM or Assistant Primary School Master/Mistress (APSM) as appropriate, is provided to each primary

An additional senior teacher post, to be offset by a post in the rank of Certificated Master/Mistress or Assistant Primary School Master/Mistress as appropriate, is provided to