GLSL 레이마칭 연구_거리 함수에 대해 공부해 보았다 16(Heart의 함수를 만들어 보았다_그 2)
사실 더 좋은 기사가 있었다.
너무 아름다운 하트 수식
이 기사의 수식은 GLSL로 그릴 수 있도록 떨어졌습니다.
수식
(x^2+\frac{9}{4}y^2+z^2)^3 - (x^2+\frac{9}{80}y^2)z^3 = 0
코드에 떨어뜨리는 방법
이번에는 인수 분해로,
a^3 - b^3 = (a-b)(a^2+ab+b^2)
사용하십시오.
\begin{align}
&(x^2+\frac{9}{4}y^2+z^2)^3 - (x^2+\frac{9}{80}y^2)z^3 = 0 \\
&((x^2+\frac{9}{4}y^2+z^2) - (x^2+\frac{9}{80}y^2)^\frac{1}{3}z)((x^2+\frac{9}{4}y^2+z^2)^2 + (x^2+\frac{9}{4}y^2+z^2)(x^2+\frac{9}{80}y^2)^\frac{1}{3}z+((x^2+\frac{9}{80}y^2)^\frac{1}{3}z)^2) = 0 \\
&ここで,((x^2+\frac{9}{4}y^2+z^2) - (x^2+\frac{9}{80}y^2)^\frac{1}{3}z) = 0 の方のみを採用して考え行く \\
&((x^2+\frac{9}{4}y^2+z^2) - (x^2+\frac{9}{80}y^2)^\frac{1}{3}z) = 0
\end{align}
코드에 떨어 뜨려 (C++로 다시 작성)
return sqrt(p.x*p.x+p.y*p.y+2.25*p.z*p.z+pow(p.x*p.x+0.1125*p.z*p.z, 0.33)*p.y)-1.0;
그리면,
length
를 사용하여 다시 작성하면
vec3 q = vec3(p.x, p.y, 1.5*p.z);
return sqrt(length(q)*length(q) + pow(p.x*p.x+0.1125*p.z*p.z, 0.33)*p.y)- 1.0;
그 후, 회전을 가하여 완성
glslandbox
코드
// ============================================================================
// Heart02
// ============================================================================
precision mediump float;
uniform vec2 resolution; // resolution (512.0, 512.0)
uniform vec2 mouse; // mouse (-1.0 ~ 1.0)
uniform float time; // time (1second == 1.0)
uniform sampler2D prevScene; // previous scene texture
// Heartの距離関数
float sdHeart(vec3 p)
{
// 回転
// mat3 m_y = mat3(cos(time),0,-sin(time),0,1,0,sin(time),0,cos(time));
// p = m_y * p;
mat3 m_z = mat3(cos(3.14),-sin(3.14),0,sin(3.14),cos(3.14),0,0,0,1);
p = m_z * p;
/* Heart距離関数 */
// return sqrt(p.x*p.x+p.y*p.y+2.25*p.z*p.z+pow(p.x*p.x+0.1125*p.z*p.z, 0.33)*p.y)-1.0;
/* Heart距離関数(lengthあり) */
vec3 q = vec3(p.x, p.y, 1.5*p.z);
return sqrt(length(q)*length(q) + pow(p.x*p.x+0.1125*p.z*p.z, 0.33)*p.y)- 1.0;
}
// 距離関数を呼び出すハブ関数
float distanceHub(vec3 p){
return sdHeart(p);
}
// 法線を生成する
vec3 genNormal(vec3 p){
float d = 0.001;
return normalize(vec3(
distanceHub(p + vec3( d, 0.0, 0.0)) - distanceHub(p + vec3( -d, 0.0, 0.0)),
distanceHub(p + vec3(0.0, d, 0.0)) - distanceHub(p + vec3(0.0, -d, 0.0)),
distanceHub(p + vec3(0.0, 0.0, d)) - distanceHub(p + vec3(0.0, 0.0, -d))
));
}
void main(){
// スクリーンスペースを考慮して座標を正規化する
vec2 p = (gl_FragCoord.xy * 2.0 - resolution) / min(resolution.x, resolution.y);
// カメラを定義する
vec3 cPos = vec3(0.0, 0.0, 2.5); // カメラの位置
vec3 cDir = vec3(0.0, 0.0, -1.0); // カメラの向き(視線)
vec3 cUp = vec3(0.0, 1.0, 0.0); // カメラの上方向
vec3 cSide = cross(cDir, cUp); // 外積を使って横方向を算出
float targetDepth = 1.0; // フォーカスする深度
// カメラの情報からレイを定義する
vec3 ray = normalize(cSide * p.x + cUp * p.y + cDir * targetDepth);
// マーチングループを組む
float dist = 0.0; // レイとオブジェクト間の最短距離
float rLen = 0.0; // レイに継ぎ足す長さ
vec3 rPos = cPos; // レイの先端位置(初期位置)
for(int i = 0; i < 32; ++i){
dist = distanceHub(rPos);
rLen += dist;
rPos = cPos + ray * rLen;
}
// レイとオブジェクトの距離を確認
if(abs(dist) < 0.001){
// 法線を算出
vec3 normal = genNormal(rPos);
// ライトベクトルの定義
vec3 light = normalize(vec3(1.0, 1.0, 1.0));
// ライトベクトルとの内積を取る
float diff = max(dot(normal, light), 0.1);
// gl_FragColor = vec4(vec3(diff, diff, diff), 1.0);
gl_FragColor = vec4(vec3(diff*240.0/255.0, diff*128.0/255.0, diff*128.0/255.0), 1.0);
}else{
// 衝突しなかった場合はそのまま黒
gl_FragColor = vec4(vec3(0.0, 0.0, 0.0), 1.0);
}
}
덧붙여서, 하트 만들고 있는데는 어른의 사정이 있어, 비교적 괴롭습니다…
Reference
이 문제에 관하여(GLSL 레이마칭 연구_거리 함수에 대해 공부해 보았다 16(Heart의 함수를 만들어 보았다_그 2)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/muripo_life/items/f24408ca1d06eb0658e3
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
(x^2+\frac{9}{4}y^2+z^2)^3 - (x^2+\frac{9}{80}y^2)z^3 = 0
코드에 떨어뜨리는 방법
이번에는 인수 분해로,
a^3 - b^3 = (a-b)(a^2+ab+b^2)
사용하십시오.
\begin{align}
&(x^2+\frac{9}{4}y^2+z^2)^3 - (x^2+\frac{9}{80}y^2)z^3 = 0 \\
&((x^2+\frac{9}{4}y^2+z^2) - (x^2+\frac{9}{80}y^2)^\frac{1}{3}z)((x^2+\frac{9}{4}y^2+z^2)^2 + (x^2+\frac{9}{4}y^2+z^2)(x^2+\frac{9}{80}y^2)^\frac{1}{3}z+((x^2+\frac{9}{80}y^2)^\frac{1}{3}z)^2) = 0 \\
&ここで,((x^2+\frac{9}{4}y^2+z^2) - (x^2+\frac{9}{80}y^2)^\frac{1}{3}z) = 0 の方のみを採用して考え行く \\
&((x^2+\frac{9}{4}y^2+z^2) - (x^2+\frac{9}{80}y^2)^\frac{1}{3}z) = 0
\end{align}
코드에 떨어 뜨려 (C++로 다시 작성)
return sqrt(p.x*p.x+p.y*p.y+2.25*p.z*p.z+pow(p.x*p.x+0.1125*p.z*p.z, 0.33)*p.y)-1.0;
그리면,
length
를 사용하여 다시 작성하면vec3 q = vec3(p.x, p.y, 1.5*p.z);
return sqrt(length(q)*length(q) + pow(p.x*p.x+0.1125*p.z*p.z, 0.33)*p.y)- 1.0;
그 후, 회전을 가하여 완성
glslandbox
코드
// ============================================================================
// Heart02
// ============================================================================
precision mediump float;
uniform vec2 resolution; // resolution (512.0, 512.0)
uniform vec2 mouse; // mouse (-1.0 ~ 1.0)
uniform float time; // time (1second == 1.0)
uniform sampler2D prevScene; // previous scene texture
// Heartの距離関数
float sdHeart(vec3 p)
{
// 回転
// mat3 m_y = mat3(cos(time),0,-sin(time),0,1,0,sin(time),0,cos(time));
// p = m_y * p;
mat3 m_z = mat3(cos(3.14),-sin(3.14),0,sin(3.14),cos(3.14),0,0,0,1);
p = m_z * p;
/* Heart距離関数 */
// return sqrt(p.x*p.x+p.y*p.y+2.25*p.z*p.z+pow(p.x*p.x+0.1125*p.z*p.z, 0.33)*p.y)-1.0;
/* Heart距離関数(lengthあり) */
vec3 q = vec3(p.x, p.y, 1.5*p.z);
return sqrt(length(q)*length(q) + pow(p.x*p.x+0.1125*p.z*p.z, 0.33)*p.y)- 1.0;
}
// 距離関数を呼び出すハブ関数
float distanceHub(vec3 p){
return sdHeart(p);
}
// 法線を生成する
vec3 genNormal(vec3 p){
float d = 0.001;
return normalize(vec3(
distanceHub(p + vec3( d, 0.0, 0.0)) - distanceHub(p + vec3( -d, 0.0, 0.0)),
distanceHub(p + vec3(0.0, d, 0.0)) - distanceHub(p + vec3(0.0, -d, 0.0)),
distanceHub(p + vec3(0.0, 0.0, d)) - distanceHub(p + vec3(0.0, 0.0, -d))
));
}
void main(){
// スクリーンスペースを考慮して座標を正規化する
vec2 p = (gl_FragCoord.xy * 2.0 - resolution) / min(resolution.x, resolution.y);
// カメラを定義する
vec3 cPos = vec3(0.0, 0.0, 2.5); // カメラの位置
vec3 cDir = vec3(0.0, 0.0, -1.0); // カメラの向き(視線)
vec3 cUp = vec3(0.0, 1.0, 0.0); // カメラの上方向
vec3 cSide = cross(cDir, cUp); // 外積を使って横方向を算出
float targetDepth = 1.0; // フォーカスする深度
// カメラの情報からレイを定義する
vec3 ray = normalize(cSide * p.x + cUp * p.y + cDir * targetDepth);
// マーチングループを組む
float dist = 0.0; // レイとオブジェクト間の最短距離
float rLen = 0.0; // レイに継ぎ足す長さ
vec3 rPos = cPos; // レイの先端位置(初期位置)
for(int i = 0; i < 32; ++i){
dist = distanceHub(rPos);
rLen += dist;
rPos = cPos + ray * rLen;
}
// レイとオブジェクトの距離を確認
if(abs(dist) < 0.001){
// 法線を算出
vec3 normal = genNormal(rPos);
// ライトベクトルの定義
vec3 light = normalize(vec3(1.0, 1.0, 1.0));
// ライトベクトルとの内積を取る
float diff = max(dot(normal, light), 0.1);
// gl_FragColor = vec4(vec3(diff, diff, diff), 1.0);
gl_FragColor = vec4(vec3(diff*240.0/255.0, diff*128.0/255.0, diff*128.0/255.0), 1.0);
}else{
// 衝突しなかった場合はそのまま黒
gl_FragColor = vec4(vec3(0.0, 0.0, 0.0), 1.0);
}
}
덧붙여서, 하트 만들고 있는데는 어른의 사정이 있어, 비교적 괴롭습니다…
Reference
이 문제에 관하여(GLSL 레이마칭 연구_거리 함수에 대해 공부해 보았다 16(Heart의 함수를 만들어 보았다_그 2)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/muripo_life/items/f24408ca1d06eb0658e3
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
// ============================================================================
// Heart02
// ============================================================================
precision mediump float;
uniform vec2 resolution; // resolution (512.0, 512.0)
uniform vec2 mouse; // mouse (-1.0 ~ 1.0)
uniform float time; // time (1second == 1.0)
uniform sampler2D prevScene; // previous scene texture
// Heartの距離関数
float sdHeart(vec3 p)
{
// 回転
// mat3 m_y = mat3(cos(time),0,-sin(time),0,1,0,sin(time),0,cos(time));
// p = m_y * p;
mat3 m_z = mat3(cos(3.14),-sin(3.14),0,sin(3.14),cos(3.14),0,0,0,1);
p = m_z * p;
/* Heart距離関数 */
// return sqrt(p.x*p.x+p.y*p.y+2.25*p.z*p.z+pow(p.x*p.x+0.1125*p.z*p.z, 0.33)*p.y)-1.0;
/* Heart距離関数(lengthあり) */
vec3 q = vec3(p.x, p.y, 1.5*p.z);
return sqrt(length(q)*length(q) + pow(p.x*p.x+0.1125*p.z*p.z, 0.33)*p.y)- 1.0;
}
// 距離関数を呼び出すハブ関数
float distanceHub(vec3 p){
return sdHeart(p);
}
// 法線を生成する
vec3 genNormal(vec3 p){
float d = 0.001;
return normalize(vec3(
distanceHub(p + vec3( d, 0.0, 0.0)) - distanceHub(p + vec3( -d, 0.0, 0.0)),
distanceHub(p + vec3(0.0, d, 0.0)) - distanceHub(p + vec3(0.0, -d, 0.0)),
distanceHub(p + vec3(0.0, 0.0, d)) - distanceHub(p + vec3(0.0, 0.0, -d))
));
}
void main(){
// スクリーンスペースを考慮して座標を正規化する
vec2 p = (gl_FragCoord.xy * 2.0 - resolution) / min(resolution.x, resolution.y);
// カメラを定義する
vec3 cPos = vec3(0.0, 0.0, 2.5); // カメラの位置
vec3 cDir = vec3(0.0, 0.0, -1.0); // カメラの向き(視線)
vec3 cUp = vec3(0.0, 1.0, 0.0); // カメラの上方向
vec3 cSide = cross(cDir, cUp); // 外積を使って横方向を算出
float targetDepth = 1.0; // フォーカスする深度
// カメラの情報からレイを定義する
vec3 ray = normalize(cSide * p.x + cUp * p.y + cDir * targetDepth);
// マーチングループを組む
float dist = 0.0; // レイとオブジェクト間の最短距離
float rLen = 0.0; // レイに継ぎ足す長さ
vec3 rPos = cPos; // レイの先端位置(初期位置)
for(int i = 0; i < 32; ++i){
dist = distanceHub(rPos);
rLen += dist;
rPos = cPos + ray * rLen;
}
// レイとオブジェクトの距離を確認
if(abs(dist) < 0.001){
// 法線を算出
vec3 normal = genNormal(rPos);
// ライトベクトルの定義
vec3 light = normalize(vec3(1.0, 1.0, 1.0));
// ライトベクトルとの内積を取る
float diff = max(dot(normal, light), 0.1);
// gl_FragColor = vec4(vec3(diff, diff, diff), 1.0);
gl_FragColor = vec4(vec3(diff*240.0/255.0, diff*128.0/255.0, diff*128.0/255.0), 1.0);
}else{
// 衝突しなかった場合はそのまま黒
gl_FragColor = vec4(vec3(0.0, 0.0, 0.0), 1.0);
}
}
Reference
이 문제에 관하여(GLSL 레이마칭 연구_거리 함수에 대해 공부해 보았다 16(Heart의 함수를 만들어 보았다_그 2)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/muripo_life/items/f24408ca1d06eb0658e3텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)