shader从入门到放弃(3) 绘制函数
shader从入门到放弃(3) 绘制函数
绘制一个一次函数
点到直线的距离
d = \frac{Ax+By+C}{\sqrt{A^2+B^2}}
但是我们这个需要开平方,这个对程序很不友好,因此我们换个方法
换成向量的方法
点到直线的距离,向量法

\vec{AD} = \frac{\vec{AC} \cdot\vec{AB}}{\vec{AB}\cdot\vec{AB}}\cdot \vec{AB}$
采用上面的公式,我会可以很方便计算相关的值。,因此给出代码
代码
最初版本,没有segement采样
float lineFunction(float x,float a, float b){
return a * x + b;
}
//绘制坐标轴
vec3 drawAxis(vec2 uv){
vec3 color = vec3(1.0);
color = step(abs(uv.x),fwidth(uv.x)) * vec3(1,0,0) + step(abs(uv.y),fwidth(uv.y)) * vec3(0,1,0);
return color;
}
// 点到直线距离
float getDot2LineDisatance(vec2 targetPoint,vec2 lineA, vec2 lineB){
vec2 ab = lineB - lineA;
vec2 ac = targetPoint - lineA;
// 套公式
vec2 ad = (dot(ac,ab) / dot(ab,ab)) * ab;
return length(ac - ad);
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec3 color = vec3(1.0);
vec2 uv = (fragCoord.xy/ iResolution.xy - 0.5)*2.0;
color = drawAxis(uv);
//绘制直线
float y = lineFunction(uv.x,1.0,0.);
color = mix(color,vec3(0.0,0.0,1.0),step(getDot2LineDisatance(uv,vec2(0.,0.),vec2(1.0)),0.01));
fragColor = vec4(color,1.0);
}
float lineFunction(float x,float a, float b){
return a * x + b;
}
//绘制坐标轴
vec3 drawAxis(vec2 uv){
vec3 color = vec3(1.0);
color = step(abs(uv.x),fwidth(uv.x)) * vec3(1,0,0) + step(abs(uv.y),fwidth(uv.y)) * vec3(0,1,0);
return color;
}
// 点到直线距离
float getDot2LineDisatance(vec2 targetPoint,vec2 lineA, vec2 lineB){
vec2 ab = lineB - lineA;
vec2 ac = targetPoint - lineA;
// 套公式
vec2 ad = (dot(ac,ab) / dot(ab,ab)) * ab;
return length(ac - ad);
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec3 color = vec3(1.0);
vec2 uv = (fragCoord.xy/ iResolution.xy - 0.5)*2.0;
color = drawAxis(uv);
//绘制直线
float y = lineFunction(uv.x,1.0,0.);
color = mix(color,vec3(0.0,0.0,1.0),smoothstep(0.02,0.01,getDot2LineDisatance(uv,vec2(0.,0.),vec2(1.0))));
fragColor = vec4(color,1.0);
}
上面是绘制光滑直线
加入了Segement采样划分区间
const int SIZE = 100;
float func(float x){
return sin(x);
}
vec2 fixUV(vec2 uv){
return 3.0 *(uv.xy/ iResolution.xy - 0.5)*2.0;
}
//绘制坐标轴
vec3 drawAxis(vec2 uv){
vec3 color = vec3(1.0);
color = step(abs(uv.x),fwidth(uv.x)) * vec3(1,0,0) + step(abs(uv.y),fwidth(uv.y)) * vec3(0,1,0);
return color;
}
// 点到直线距离
float getDot2LineDisatance(vec2 targetPoint,vec2 lineA, vec2 lineB){
vec2 ab = lineB - lineA;
vec2 ac = targetPoint - lineA;
// 套公式
vec2 ad = clamp((dot(ac,ab) / dot(ab,ab)),0.0,1.0) * ab;
return length(ac - ad);
}
//划分区间
//整个定义域,划分一次,只要是UV都会划分
//例如
float plotFunc(vec2 uv){
float minDistance = 10000.0;
for (int i = 0; i < SIZE; i++){
// 当前 uv 的 X 可见范围为 -1 到 1。
float t0 = float(i) / float(SIZE);
float t1 = float(i+1) / float(SIZE);
float fx = fixUV(vec2(mix(0.0,iResolution.x,t0),0.0)).x;
float nfx = fixUV(vec2(mix(0.0,iResolution.x,t1),0.0)).x;
vec2 pa = vec2(fx,func(fx));
vec2 pb = vec2(nfx,func(nfx));
float distanceToSegment = getDot2LineDisatance(uv, pa, pb);
minDistance = min(minDistance, distanceToSegment);
}
return minDistance;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec3 color = vec3(1.0);
vec2 uv = fixUV(fragCoord);
color = drawAxis(uv);
//绘制直线
//float y = lineFunction(uv.x,1.0,0.);
//color = mix(color,vec3(0.0,0.0,1.0),smoothstep(0.01,0.03,plotFunc(uv)));
float curveMask = 1.0 - smoothstep(0.01, 0.03, plotFunc(uv));
color = mix(color, vec3(0.0, 0.0, 1.0), curveMask);
//color = vec3(smoothstep(0.3,0.01,plotFunc(uv)));
fragColor = vec4(color,1.0);
}
上面这个是,这个是绘制三角形,效果还行,迭代100次。这个是暴力算法
这个是自己理解后改进的
const int SIZE = 100;
float func(float x){
return sin(x);
}
vec2 fixUV(vec2 uv){
return 3.0 *(uv.xy/ iResolution.xy - 0.5)*2.0;
}
//绘制坐标轴
vec3 drawAxis(vec2 uv){
vec3 color = vec3(1.0);
color = step(abs(uv.x),fwidth(uv.x)) * vec3(1,0,0) + step(abs(uv.y),fwidth(uv.y)) * vec3(0,1,0);
return color;
}
// 点到直线距离
float getDot2LineDisatance(vec2 targetPoint,vec2 lineA, vec2 lineB){
vec2 ab = lineB - lineA;
vec2 ac = targetPoint - lineA;
// 套公式
vec2 ad = clamp((dot(ac,ab) / dot(ab,ab)),0.0,1.0) * ab;
return length(ac - ad);
}
//划分区间
//整个定义域,划分一次,只要是UV都会划分
//例如
float plotFunc(vec2 uv){
float minDistance = 10000.0;
for (int i = 0; i < SIZE; i++){
// 当前 uv 的 X 可见范围为 -1 到 1。
float t0 = float(i) / float(SIZE);
float t1 = float(i + 1) / float(SIZE);
float fx = uv.x + t0;
float nfx = uv.x + t1;
vec2 pa = vec2(fx,func(fx));
vec2 pb = vec2(nfx,func(nfx));
float distanceToSegment = getDot2LineDisatance(uv, pa, pb);
minDistance = min(minDistance, distanceToSegment);
}
return minDistance;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec3 color = vec3(1.0);
vec2 uv = fixUV(fragCoord);
color = drawAxis(uv);
//绘制直线
//float y = lineFunction(uv.x,1.0,0.);
//color = mix(color,vec3(0.0,0.0,1.0),smoothstep(0.01,0.03,plotFunc(uv)));
float curveMask = smoothstep(0.1, 0.003, plotFunc(uv));
color = mix(color, vec3(0.0, 0.0, 1.0), curveMask);
//color = vec3(smoothstep(0.3,0.01,plotFunc(uv)));
//float y = func(uv.x);
//float distance = getDot2LineDisatance()
fragColor = vec4(color,1.0);
}
针对函数这种单值的,可以不需要细分,直接计算就行了
我的优化版本
const int SIZE = 100;
float func(float x){
return sin(x) * sin(2.0*sin(3.0*x + 30.0));
}
vec2 fixUV(vec2 uv){
return 3.0 *(uv.xy/ iResolution.xy - 0.5)*2.0;
}
//绘制坐标轴
vec3 drawAxis(vec2 uv){
vec3 color = vec3(1.0);
color = step(abs(uv.x),fwidth(uv.x)) * vec3(1,0,0) + step(abs(uv.y),fwidth(uv.y)) * vec3(0,1,0);
return color;
}
// 点到直线距离
float getDot2LineDisatance(vec2 targetPoint,vec2 lineA, vec2 lineB){
vec2 ab = lineB - lineA;
vec2 ac = targetPoint - lineA;
// 套公式
vec2 ad = clamp((dot(ac,ab) / dot(ab,ab)),0.0,1.0) * ab;
return length(ac - ad);
}
// 返回曲线遮罩:1 为曲线,0 为背景。
float plotFunc(vec2 uv)
{
float field = uv.y - func(uv.x);
return 1.0 - smoothstep(0.0, fwidth(field) * 1.5, abs(field));
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec3 color = vec3(1.0);
vec2 uv = fixUV(fragCoord);
color = drawAxis(uv);
//绘制直线
//float y = lineFunction(uv.x,1.0,0.);
//color = mix(color,vec3(0.0,0.0,1.0),smoothstep(0.01,0.03,plotFunc(uv)));
//float curveMask = smoothstep(0.1, 0.003, plotFunc(uv));
//color = mix(color, vec3(0.0, 0.0, 1.0), curveMask);
float curveMask = plotFunc(uv);
color = mix(color, vec3(0.0, 0.0, 1.0), curveMask);
//color = vec3(smoothstep(0.3,0.01,plotFunc(uv)));
//float y = func(uv.x);
//float distance = getDot2LineDisatance()
fragColor = vec4(color,1.0);
}
最简单的方法