百科问答小站 logo
百科问答小站 font logo



怎样用c语言画一个"三维的球体"? 第1页

  

user avatar   miloyip 网友的相关建议: 
      

我们用 81x40 个 ASCII 字符,向 -Z 轴方向渲染一个单位球 :

       #include <math.h> #include <stdio.h>  int main() {     float x, y;     for (y = 1; y >= -1; y -= 0.05f, putchar('
'))         for (x = -1; x <= 1; x += 0.025f)             putchar(x * x + y * y > 1 ? 'M' : "@@%#*+=;:. "[(int)(                 ((x + y + sqrt(1 - (x * x + y * y))) * 0.5773502692f + 1)                 * 5.0f + 0.5f)]); }     

编译运行结果:

解释一下,这个单位球是投影在 平面上,所以 y 从上至下、x 从左至右迭代;而一般半角文字的显示长宽比是 2:1, y 轴用 1 / 20 = 0.05 增量,x 轴用 1 / 40 = 0.025。

我们知道单位球投影在 平面后,会在单位圆的范围,即 ,在这范围内渲染单位球的表面,范围以外填上背景('M' 字符)。

为了表示立体感,需要按球体表面的法线着色。单位球的表面法线等同于表面位置,表面位置/法线可以从单位球的方程解出:

因为面向我们的一面球面是向 +z 方向的,z 值取正号便可。

然后,通常着色的 Lambert 项是:

当中 为光源方向, 为法线。需要 max 是因为两者夹角超过 90 度是不会获得光照。但这里采用了一个名为 Half Lambert 的方案(最先用于《Half Life》游戏),把着色的过渡从 0 至 90 度,扩展至 0 至 180 度,使整个球体表面都有过渡着色(这种非物理正确的方法可用于模拟 SSS 或卡通化的效果):

(左为 Lambert 项,右为 Half Lambert 项)

为简单起见,我们采用 作为光源方向,那么着色就变成:

最后,我们把亮度结果映射至 10 个字符。

相关答案和文章




  

相关话题

  C 语言如何不用 goto、多处 return 进行错误处理? 
  为什么C++中,含有函数声明的头文件应该被包含在定义函数的源文件中? 
  大学c语言学习的考题中,故意用相同变量名来命名形参实参,局部变量和全局变量让学生区分,有实际意义吗? 
  网游服务器逻辑和传输如何分层/解耦? 
  如果加班是自愿的,你们会为了钱加班吗? 
  计算机存储浮点数的时候,为什么不使用十进制来存储呢? 
  C/C++中的数组为什么必须定义之后在一行内立刻赋值,而不能定义数组之后换一行再赋值? 
  在C++中,“?:”这个符号叫什么名字? 
  c++如此繁琐,为什么大学不直接开展python课程? 
  有多少人知道汉诺塔其实应该叫河内塔? 

前一个讨论
如何看待京东销量前十蔻驰包存在假货的现象?
下一个讨论
如何用鸡蛋做出最简单却好吃的美食?





© 2025-04-20 - tinynew.org. All Rights Reserved.
© 2025-04-20 - tinynew.org. 保留所有权利