본문 바로가기

셰이더 (Shader)/The Book of Shaders (완)14

[GLSL] 13 - Fractal Brownian Motion 노이즈의 근본인, 파동(wave)과 파동의 성질을 살펴보자. 파동의 두 가지 중요한 특성은 진폭과 주파수이다. 간단한 선형(1차원) 파동의 방정식은 다음과 같다. float amplitude = 1.; float frequency = 1.; y = amplitude * sin(x * frequency); 파동의 또 다른 특성은 합산할 수 있다는 것이다. ( 두 개 이상의 파동을 합침) 이는 공식적으로 superposition(중첩)이라고 불린다. // 위 이미지 참고링크 https://www.acs.psu.edu/drussell/demos/superposition/superposition.html // 예제 진폭과 주파수가 다른 파동을 더하면 모양이 어떻게 되는지 주목하라. float amplitude .. 2023. 5. 4.
[GLSL] 12 - Cellular Noise 펄린의 노이즈가 나온 지 16년 후이자, 심플렉스 노이즈가 나오기 5년 전인 1996년, 스티븐 월리는 "셀룰러 텍스처 베이스 함수"라는 논문을 썼다. 이 기법의 원리를 이해하려면 반복문에 대해 알아야한다. GLSL에서 for 루프에는 단점이 있다. 조건식의 숫자가 상수(const)여야 한다는 점이다. 따라서 동적 루프는 사용할 수 없다. 반복 횟수를 고정해야한다. 예제를 보자. Points for a distance field 셀룰러 노이즈는 거리 필드 기반으로 계산한다. 특정한 점으로부터의 가장 가까운 지점까지의 거리를 사용하는 것이다. 예를 들어, 4개의 점으로 구성된 거리 필드를 만들어보자. 각 픽셀이 가장 가까운 점까지의 거리를 계산해야한다. 즉, 점 개수만큼 반복하여 현재 픽셀까지의 거리를 계.. 2023. 5. 3.
[GLSL] 11 - Noise 현실 세계 무작위성을 가지고 있지만, 랜덤과는 다르다. 이 다양성을 어떻게 표현할까? 1980년대 초 영화 "트론"을 위해 보다 사실적인 텍스처를 생성해 달라는 의뢰를 받은 켄 펄린은 이 문제를 해결했다. 이에 대한 해답으로 노이즈 알고리즘을 고안해냈다. 다음은 고전적인 펄린 노이즈 알고리즘은 아니지만, 노이즈 생성 방법을 이해하기 위한 기초 예제이다. float i = floor(x); // integer float f = fract(x); // fraction y = rand(i); //rand() is described in the previous chapter y = mix(rand(i), rand(i + 1.0), f); // 선형 보간법 y = mix(rand(i), rand(i + 1.0),.. 2023. 4. 26.
[GLSL] 10 - Random 랜덤은 엔트로피의 최대 표현이다. 코드에서 어떻게 랜덤을 생성할 수 있을까? 다음 함수를 분석해보자. y = fract(sin(x)*1.0); sin 값은 -1.0과 1.0 사이에서 변동한다. 소수점 뒤를 잘라서 0.0과 1.0 사이의 모든 양수 값으로 만들었다. 이를 사용하면, 사인파를 잘게 쪼개서 랜덤 값을 얻을 수 있다. sin(x)의 뒤에 큰 숫자를 곱하는 것이다. 100000.0만큼 곱하면 더 이상 사인파를 식별할 수 없게 된다. Controlling chaos 랜덤 사용시 주의할 점이 있다. 충분히 무작위적이지 않을 수 있다. 자세히 살펴보면 -1.5707과 1.5707에서 sin() 형태가 보인다. 이 지점은 사인파의 최대값과 최소값이 발생하는 지점이기 때문이다. 또한 분포가 가장자리에 비해.. 2023. 4. 25.
[GLSL] 9 - Patterns 정규화된 좌표계를 3으로 늘린다. 여기에 fract 함수를 적용한다. 0-1값에서 생성된 실수값, 1-2 값에서 생성된 실수값, 2-3 값에서 생성된 실수값. 3x3 셀을 얻을 수 있다. float circle(in vec2 _st, in float _radius){ vec2 l = _st-vec2(0.5); return 1.-smoothstep(_radius-(_radius*0.01), _radius+(_radius*0.01), dot(l,l)*4.0); } void main() { vec2 st = gl_FragCoord.xy/u_resolution; vec3 color = vec3(0.0); st *= 3.0; // Scale up the space by 3 st = fract(st); // Wra.. 2023. 4. 20.
[GLSL] 8 - 2D Matrices Translate 도형을 이동하는 방법은 좌표계 자체를 이동하는 것이다. st 변수에 각 도형의 위치 벡터를 더한다. 이러면 전체 공간 좌표계가 움직인다. 코드 예제를 보자. float box(in vec2 _st, in vec2 _size){ _size = vec2(0.5) - _size*0.5; vec2 uv = smoothstep(_size, _size+vec2(0.001), _st); uv *= smoothstep(_size, _size+vec2(0.001), vec2(1.0)-_st); return uv.x*uv.y; } float cross(in vec2 _st, float _size){ return box(_st, vec2(_size,_size/4.)) + box(_st, vec2(_size.. 2023. 4. 20.
[GLSL] 7 - Shapes 간단한 도형을 병렬적인 절차에 따라 그리는 방법을 배운다. Rectangle 정사각형을 그리기 if 문 사용 if ( (X GREATER THAN 1) AND (Y GREATER THAN 1) ) paint white else paint black if 문을 step()으로 변경 uniform vec2 u_resolution; void main(){ vec2 st = gl_FragCoord.xy/u_resolution.xy; vec3 color = vec3(0.0); float left = step(0.1,st.x); float bottom = step(0.1,st.y); color = vec3( left * bottom ); gl_FragColor = vec4(color,1.0); } 코드를 줄여보자... 2023. 4. 19.
[GLSL] 6 - Colors 벡터 내부의 데이터에 C언어의 구조체처럼 접근한다. vec3 red = vec3(1.0,0.0,0.0); red.x = 1.0; red.y = 0.0; red.z = 0.0; 색상을 x, y, z 표기법으로 정의하면 혼란스러울 수 있다. 그래서 다른 접근법도 있다. s,t,p는 일반적으로 텍스처의 공간 좌표에 사용된다. vector[0] = vector.r = vector.x = vector.s; vector[1] = vector.g = vector.y = vector.t; vector[2] = vector.b = vector.z = vector.p; vector[3] = vector.a = vector.w = vector.q; GLSL 벡터의 또 다른 특징은 프로퍼티를 원하는 순서대로 결합할 수 있다... 2023. 4. 18.
[GLSL] 5 - Shaping functions // 개요 1차원 함수를 만드는 방법을 알아본다. 이를 알아야 기초가 튼튼해진다. 데이터를 검은색에서 흰색으로의 그라데이션으로 시각화한다. 또한 녹색 선도 그려서 시각화한다. plot 함수 기능에 의문 가지지 말아야한다. 나중에 알아볼 것이다. // 직선 #ifdef GL_ES precision mediump float; #endif uniform vec2 u_resolution; uniform vec2 u_mouse; uniform float u_time; // Plot a line on Y using a value between 0.0-1.0 float plot(vec2 st) { return smoothstep(0.02, 0.0, abs(st.y - st.x)); } void main() { vec.. 2023. 4. 17.