嗯,其实渲染球体,可以看做就是一个2d圆形图案+渲染光泽的函数。

定义球体结构——半径,球心坐标

struct Sphere {
vec3 center;
float radius;
};edzx-

定义光线——光源坐标,方向

struct Ray {
vec3 origin;
vec3 direction;
};

检测“光线”与“球体”是否相交,若未相交返回false,相交返回从光源到球面的距离

数学解释如下

图中红色线条即光线,重要线段已标注变量,光照方向记作向量Dir

首先,需要判断光线是否照射到球面,转化为数学问题,即光线所在直线是否与球相交。

在一个平面内,一条线与一个球形的关系有三种——相交相切相离

其中相切作为一个中间状态是很好判断的,当光线与球面相切,必然存在:

R = d

t1² = OC² - R²

如此,余下的两种状态也很好判断了。

假若线段t1的长度小于从光源出发到球形的切线段长,则光线必然与球形相交;反之,则与球形相离。

接下来,计算从光源到球面相交点的距离。

如图中所示,最终所求距离即线段t0长度:

                                  t1 = OC·Dir  (此处用到点乘)

d² = OC² - t1²

t3² = R² - d²

t0 = t1 - sqrt (t3)

代码表示如下:

float intersectSphere(in Ray ray, in Sphere sphere) {
vec3 co = ray.origin - sphere.center; float discriminant = dot(co, ray.direction) * dot(co, ray.direction)
- (dot(co, co) - sphere.radius * sphere.radius); if (discriminant >= 0.0) //相交或相切
return -dot(co, ray.direction)-sqrt(discriminant); //返回光源到球面距离
else //相离返回-1
return -.;

最后,是光照漫反射的方程,这里用到物理学上的兰伯特余弦定律Lambert Cosine's Law),即光照漫反射时的强度,遵循光线向量与法线向量间夹角余弦值的变化。

如下图,即随着光线向量与法线夹角增大,漫反射光的强度越弱。

漫反射代码如下:

vec4 diffuse(in vec3 surface, in vec3 center, in vec4 color, in vec3 litePos) {
// Surface normal
vec3 n = normalize(surface - center); // Light direction from surface
vec3 l = normalize(litePos - surface); // The diffuse equation
return color * max(0.0, dot(n, l));
}

最终返回反射光的颜色。

最终绘制阶段。

void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
float x = fragCoord.x / iResolution.x;
float y = fragCoord.y*. / iResolution.y;
vec4 m = iMouse / iResolution.xyxy; x = x * 3.0 ;
y = y * 3.0 - .; vec3 pixelPos = vec3(x, y, ); vec3 eyePos = vec3(, , -); vec3 rayDir = normalize(pixelPos - eyePos)*(.); Sphere sphere = Sphere(vec3(3.5, ., 5.0), 1.0); float eyeToSphere = intersectSphere(Ray(eyePos, rayDir), sphere); fragColor = vec4(0.1, 0.1, 0.1, ); if (eyeToSphere >= .)
{
//漫射颜色
vec4 diffuseColour = vec4(0.4,0.4,0.4,.); //周边颜色
vec4 ambientColour = vec4(0.8,0.1,0.1,.); //光亮位置
vec3 litePos = vec3(m.x*., m.y*., .); fragColor = ambientColour + diffuse(eyePos + eyeToSphere * rayDir, sphere.center, diffuseColour, litePos); }

→示例:https://www.shadertoy.com/view/MsffW4

【ShaderToy】画一个球体的更多相关文章

  1. Directx11教程(5) 画一个简单的三角形(1)

    原文:Directx11教程(5) 画一个简单的三角形(1)       在本篇教程中,我们将通过D3D11画一个简单的三角形.在D3D11中,GPU的渲染主要通过shader来操作(当然还有一些操作 ...

  2. Effective前端3:用CSS画一个三角形

    p { text-indent: 2em } .triangle-container p { text-indent: 0 } img { margin: 15px 0 } 三角形的场景很常见,打开一 ...

  3. canvas游戏小试:画一个按方向键移动的圆点

    canvas游戏小试:画一个按方向键移动的圆点   自己对canvas,但又有一颗做游戏的心TT.然后记录一下对canvas的学习吧,用一个按方向键控制的小圆点来做练习.(编程时用了一些es6的语法) ...

  4. PostScript的简单例子-用粗线画一个圆

    一 近期需要用到PostScript,查询资料学习PS的语法 简单的画一个圆的例子 %!PS-Adobe-3.0 /inch{72 mul} def 4.25 inch 5.5 inch 1.5 in ...

  5. 自己画一个ActivityIndicatorView-b

    苹果的UI控件中有一个UIActivityIndicatorView,俗称菊花.→_→现在我们仿照它来制作一个其它样式的指示器,如下: ActivityView.png 自定义指示器 首先画一个白色的 ...

  6. Android画一个随意拖动的圆形

    import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactor ...

  7. 用PS画一个齿轮

    以前只会画圆画方,这没技术含量.今天学了一个稍难一点的,画一个齿轮.图形有圆也有方.以下描述如何画出来的. 一.打开PS准备一画布,画一矩形并且填充颜色. 二.编辑->自由变换(CTRL+T), ...

  8. 深夜,用canvas画一个时钟

    深夜,用canvas画一个时钟 查看demo 这几天准备阿里巴巴的笔试,可以说已经是心力交瘁,自从阿里和蘑菇街的内推被刷掉之后,开始越来越怀疑起自己的能力来,虽然这点打击应该是微不足道的.毕竟校招在刚 ...

  9. Directx11学习笔记【十二】 画一个旋转的彩色立方体

    上一次我们学习了如何画一个2D三角形,现在让我们进一步学习如何画一个旋转的彩色立方体吧. 具体流程同画三角形类似,因此不再给出完整代码了,不同的部分会再说明. 由于我们要画彩色的立方体,所以顶点结构体 ...

随机推荐

  1. php分页数据最后一页继续追加第一页数据

    之前做数据分页遇到这样一个需求,就是数据到最后一页的时候不能中断,继续把第一页的数据追加到后面,无限显示下去. 原文地址:代码汇个人博客 http://www.codehui.net/info/23. ...

  2. windows server 几大实时同步软件比较

    需求: 从Windows Server 主机A 到 Windows Server 主机B 之间同步目录 方案一: 1. 使用bat脚本 + 计划任务的方式 1.1 bat脚本 功能: 把主机A的C:\ ...

  3. 简述同步IO、异步IO、阻塞IO、非阻塞IO之间的联系与区别

    POSIX 同步IO.异步IO.阻塞IO.非阻塞IO,这几个词常见于各种各样的与网络相关的文章之中,往往不同上下文中它们的意思是不一样的,以致于我在很长一段时间对此感到困惑,所以想写一篇文章整理一下. ...

  4. 面试中被问Spring循环依赖的三种方式!!!

    什么是循环依赖? 循环依赖其实就是循环引用,也就是两个或则两个以上的 Bean 互相持有对方,最终形成闭环.比如A依赖于B,B依赖于C,C又依赖于A.如下图: 如果在日常开发中我们用new 对象的方式 ...

  5. 使用原生 JS 复制文本兼容移动端 iOS & android

    注意事项 使用 JS 实现复制功能并不是很难,但是有几个需要注意的地方. 首先文本只有选中才可以复制,所以简单的做法就是创建一个隐藏的 input,然后绑定需要复制的文本. 另外如果将 input 设 ...

  6. ValueError: too many values to unpack

    Error msg: 执行: python manage,py makemigrations 报错:Value: too many values to unpack 问题: django第一次数据库迁 ...

  7. 【alpha阶段】第九次Scrum Meeting

    每日任务内容 队员 昨日完成任务 明日要完成的任务 牛宇航 #26 评价总览接口编写https://github.com/rRetr0Git/rateMyCourse/issues/26 #26 评价 ...

  8. array_map、array_walk、array_reduce

    不同情境下替换foreach,且效果更佳 array_map  遍历原数组,array_map()参数中有几个数组,自定义函数就接收几个参数, 在每个值上进行自定义函数处理,具有返回值,需要一个新数组 ...

  9. js获取元素宽高、位置相关知识汇总

    常见clientWidth.clientHeight.offsetWidth.offsetLeft,clientX.scrollTop等词语,比较混乱,现在总结下他们的区别. 1. clientWid ...

  10. 电脑突然使用不了复制粘贴快捷键,Ctrl+C和Ctrl+V没用

    今天不知道怎么回事,在复制代码的时候突然用不了Ctrl+C和Ctrl+V了 刚开始我还以为是eclipse出问题,然后我在idea中是可以复制 和 粘贴的,然后我又打开文本编辑器notepad++,发 ...