简单的纹理生成方法

Texture Generation


A D V E R T I S E M E N T

The XOR Texture


Introduction


The XOR texture is a very easy to generate texture that looks fine. However, it's so overused that it's not a good choice to use in in a demo or intro release. It isn't useful for games either, unless you want some fancy floor tiles. What it's useful for, is for testing a texture mapper you just wrote, in case you want to quickly test out a pattern without having to load an image file or write more complex texture generation code.

This is an extremely small article, but the XOR Texture just couldn't be left out in a series of texture generation articles.
 

The XOR Texture


The XOR texture is simply generated by xor-ing the x and y coordinate of the current pixel. The '^' operator in C++ is the XOR operator.

 

int main(int argc, char *argv[]) 
{ 
    screen(256, 256, 0, "The XOR Texture"); 
   
    for(int x = 0; x < w; x++) 
    for(int y = 0; y < h; y++) 
    {    
         Uint8 c = x ^ y; 
         pset(x, y, ColorRGB(c, c, c)); 
    } 
   
    redraw(); 
    sleep(); 
    return 0; 
}

That's it, if you run it, you see the XOR texture:

The XOR Texture

There are 3 things you should keep in mind though:

1) The sizes of the texture should be a power of two, if they aren't, the texture doesn't look as good:



2)  Color component values range from 0 to 255. The maximum color value generated by the XOR operation is the same as the dimensions of the texture if it's size is a power of two. So if the size of your XOR pattern is smaller than 256, for example only 64, it'll be too dark (image on the left). Multiply the color with 4 to make it bright again (image on the right):

 

3) On the other hand, if the size is larger than 256, for example 512, you have to make sure the color is limited to a maximum value of 256. You can either modulo divide it through 256, but then it isn't a real XOR pattern anymore. Better is to divide it through 2. In any case, using a XOR texture larger than 256x256 doesn't increase the quality because there aren't enough distinct color values, unless you're using a color mode that allows more bits per channel. But who'd want to generate a 1024x1024 XOR texture anyway.

The XOR operator takes the binary values of both integers, and does a binary XOR on every two corresponding bits. XOR or eXclusive OR returns 1 if both bits are different, and returns 0 if both bits are the same: "Bit a is 1 OR bit 2 is 1, but  not both". In other words, it applies the following truth table to every two corresponding bits:

XOR
 
Bit_a
 
Bit_b
 
Result
 
0
 
0
 
0
 
0
 
1
 
1
 
1
 
0
 
1
 
1
 
1
 
0
 

This is done on every bit of the integer, creating the many possible resulting values.

For example, 5 XOR 13 = 8, because in binary 0101 XOR 1101 = 1000.

 

Colors


You can also try the XOR texture with different colors, by using different value for R, G and B. For example:

 

int main(int argc, char *argv[])
{
    screen(256, 256, 0, "The XOR Texture");
  
    ColorRGB color;
    
    for(int x = 0; x < w; x++)
    for(int y = 0; y < h; y++)
    {   
         Uint8 c = (x ^ y);
         color.r = 255 - c;
         color.g = c;
         color.b = c % 128;
         pset(x, y, color);
    }
      
    redraw();
    sleep();
    return 0;
}



You can even use the xor value as hue for the HSVtoRGB function...

 
int main(int argc, char *argv[])
{
    screen(256, 256, 0, "The XOR Texture");
  
    ColorRGB color; 
      
    for(int x = 0; x < w; x++)
    for(int y = 0; y < h; y++)
    {   
         Uint8 c = (x ^ y);
         color = HSVtoRGB(ColorHSV(c, 255, 255));
         pset(x, y, color);
    }
  
    redraw();
    sleep();
    return 0;
}



 

AND and OR


The AND and the OR operator also generate a similar texture.

The XOR operator returns 1 if both bits are different:

XOR
 
Bit_a
 
Bit_b
 
Result
 
0
 
0
 
0
 
0
 
1
 
1
 
1
 
0
 
1
 
1
 
1
 
0
 

The AND operator, only returns 1 if both bits are 1 (bit a AND bit b are true)

AND
 
Bit_a
 
Bit_b
 
Result
 
0
 
0
 
0
 
0
 
1
 
0
 
1
 
0
 
0
 
1
 
1
 
1
 

The OR operator returns 1 if any or both of the bits are 1 (bit a OR bit b is true)

OR
 
Bit_a
 
Bit_b
 
Result
 
0
 
0
 
0
 
0
 
1
 
1
 
1
 
0
 
1
 
1
 
1
 
1
 

The AND operator is denoted '&' in C++, and the OR operator '|', replace the '^' operator with those to use the new operators. Here's the result of XOR, AND and OR respectively:

   

It makes sense that the AND texture is darker, because it returns 1 only in a single case. The OR texture is brighter, because it returns 1 very often. The sum of the XOR texture and the AND texture is the OR texture.
 

Conclusion


It was shown how easy it is to create a XOR texture, which makes the XOR texture useful to test if a texture renderer is working. However, it's not suitable for applications such as art or games.

Here, the XOR pattern was used as a 3D texture (x ^ y ^ z) to test if a planet texture renderer was working correctly:

### 程序化纹理生成技术概述 程序化纹理生成是一种通过算法而非手动绘制来创建视觉上复杂的图像的技术。这种方法广泛应用于计算机图形学、游戏开发以及电影制作等领域,因为它能够显著减少存储需求并提供高度可定制化的纹理效果。 #### 基本原理 程序化纹理的核心在于利用数学函数或过程性规则生成具有自然外观的图案[^1]。这些模式可以模拟诸如大理石、木纹、云层等自然界中的复杂结构。相比传统的基于位图的纹理映射方式,程序化方法提供了更高的灵活性和分辨率独立性。 #### 主要实现方法与算法 1. **噪声函数** - Perlin Noise 和 Simplex Noise 是两种最常用的噪声生成算法。它们能产生平滑过渡的随机值场,适用于模仿地形起伏或者水面波动的效果[^2]。 2. **分形构造** - 使用迭代函数系统(IFS) 或者多尺度叠加的方法构建细节丰富的表面特性。例如,通过累加不同频率和振幅的小波形成逼真的岩石裂缝或是树叶脉络[^3]。 3. **细胞自动机(Cellular Automata)** - 这种离散模型可以根据简单的局部交互规则演化出宏观层次上的有序形态,适合用来设计织物花样或者是晶体生长仿真[^4]。 4. **频谱合成(Spectral Synthesis)** - 将信号分解成若干正弦成分后再重新组合起来得到目标特征曲线。此技巧特别有利于再现周期性的条纹状装饰风格[^5]。 ```python import numpy as np from PIL import Image def perlin_noise(size, scale=10): def interpolate(a,b,x): ft = x * 3.1415927 f = (1-np.cos(ft))*.5 return a*(1-f)+b*f lin = np.linspace(0,size-1,num=size,dtype=int) xx,yy=np.meshgrid(lin,lin) p = np.random.rand(int(scale),int(scale)) int_x = xx.astype('float')/size*scale int_y = yy.astype('float')/size*scale x0 = int_x.astype('int') y0 = int_y.astype('int') x1 = (x0+1).clip(0,scale-1) y1 = (y0+1).clip(0,scale-1) dx = int_x-x0 dy = int_y-y0 n00 = p[x0,y0] n10 = p[x1,y0] ix0 = interpolate(n00,n10,dx) n01 = p[x0,y1] n11 = p[x1,y1] ix1 = interpolate(n01,n11,dx) value = interpolate(ix0,ix1,dy) img = Image.fromarray((value*255).astype(np.uint8),'L') return img perlin_image = perlin_noise(256, scale=10) perlin_image.show() ``` 上述代码片段展示了如何运用Perlin Noise生成一张灰度图片作为基础纹理素材的一部分[^6]。 ### 结论 综上所述,程序化纹理生成不仅限于单一技术路径的选择,而是多种手段综合应用的结果。每一种特定的应用场景都可能需要调整相应的参数设置甚至自定义全新的计算逻辑才能达到理想的艺术表现力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值