【ShaderToy】画一个球体
嗯,其实渲染球体,可以看做就是一个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】画一个球体的更多相关文章
- Directx11教程(5) 画一个简单的三角形(1)
原文:Directx11教程(5) 画一个简单的三角形(1) 在本篇教程中,我们将通过D3D11画一个简单的三角形.在D3D11中,GPU的渲染主要通过shader来操作(当然还有一些操作 ...
- Effective前端3:用CSS画一个三角形
p { text-indent: 2em } .triangle-container p { text-indent: 0 } img { margin: 15px 0 } 三角形的场景很常见,打开一 ...
- canvas游戏小试:画一个按方向键移动的圆点
canvas游戏小试:画一个按方向键移动的圆点 自己对canvas,但又有一颗做游戏的心TT.然后记录一下对canvas的学习吧,用一个按方向键控制的小圆点来做练习.(编程时用了一些es6的语法) ...
- PostScript的简单例子-用粗线画一个圆
一 近期需要用到PostScript,查询资料学习PS的语法 简单的画一个圆的例子 %!PS-Adobe-3.0 /inch{72 mul} def 4.25 inch 5.5 inch 1.5 in ...
- 自己画一个ActivityIndicatorView-b
苹果的UI控件中有一个UIActivityIndicatorView,俗称菊花.→_→现在我们仿照它来制作一个其它样式的指示器,如下: ActivityView.png 自定义指示器 首先画一个白色的 ...
- Android画一个随意拖动的圆形
import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactor ...
- 用PS画一个齿轮
以前只会画圆画方,这没技术含量.今天学了一个稍难一点的,画一个齿轮.图形有圆也有方.以下描述如何画出来的. 一.打开PS准备一画布,画一矩形并且填充颜色. 二.编辑->自由变换(CTRL+T), ...
- 深夜,用canvas画一个时钟
深夜,用canvas画一个时钟 查看demo 这几天准备阿里巴巴的笔试,可以说已经是心力交瘁,自从阿里和蘑菇街的内推被刷掉之后,开始越来越怀疑起自己的能力来,虽然这点打击应该是微不足道的.毕竟校招在刚 ...
- Directx11学习笔记【十二】 画一个旋转的彩色立方体
上一次我们学习了如何画一个2D三角形,现在让我们进一步学习如何画一个旋转的彩色立方体吧. 具体流程同画三角形类似,因此不再给出完整代码了,不同的部分会再说明. 由于我们要画彩色的立方体,所以顶点结构体 ...
随机推荐
- RocketMQ知识整理与总结
1.架构 RocketMQ的master broker与master broker没有任何消息通讯,nameserver之间也同样没有消息通信 MQ历史 由数据结构队列发展而来 MQ使用场景 异 ...
- 服务消费者Feign和Ribbon的区别
1.Ribbon通过注解@EnableEurekaClient/@EnableDiscoveryClient向服务中心注册: PS:选用的注册中心是eureka,那么就推荐@EnableEure ...
- Codeforces #541 (Div2) - D. Gourmet choice(拓扑排序+并查集)
Problem Codeforces #541 (Div2) - D. Gourmet choice Time Limit: 2000 mSec Problem Description Input ...
- Python函数的装饰器修复技术(@wraps)
@wraps 函数的装饰器修复技术,可使被装饰的函数在增加了新功能的前提下,不改变原函数名称,还继续使用原函数的注释内容: 方便了上下文环境中不去更改原来使用的函数地方的函数名: 使用方法: from ...
- 如何改善SSH连接过慢(效率)
+++++++++++++++++++++++++++++++++++++++++问题:通过SSH链接远程Linux主机过慢.重点:学习如何通过调整ssh_config配置文件,提高SSH连接效率.时 ...
- 【MySQL 读书笔记】RR(REPEATABLE-READ)事务隔离详解
这篇我觉得有点难度,我会更慢的更详细的分析一些 case . MySQL 的默认事务隔离级别和其他几个主流数据库隔离级别不同,他的事务隔离级别是 RR(REPEATABLE-READ) 其他的主流数据 ...
- Activiti6-FormService(学习笔记)重要
设置流程定义文件: <?xml version="1.0" encoding="UTF-8"?> <definitions xmlns=&qu ...
- c提高第四课
1.一维数组的初始化 , , }; //3个元素 ] = { , , }; //a[3], a[4]自动初始化为0 ] = { }; //全部元素初始化为0 memset(c, , sizeof(c) ...
- windows编程 进程的创建销毁和分析
Windows程序设计:进程 进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动,在Windows编程环境下,主要由两大元素组成: • 一个是操作系统用来管理进程的内核对象.操作系统使用内 ...
- StringBuilder的常用方法
转自:https://www.cnblogs.com/jack-Leo/p/6684447.html 在程序开发过程中,我们常常碰到字符串连接的情况,方便和直接的方式是通过"+"符 ...