Roman Cortes는 JavaScript 스크립트로 작성된 빨간 장미를 가져 왔습니다. 코드로 만든 로즈는 멋진 프로그래머가 여자 친구에게 제공하는 최고의 발렌타인 데이 선물입니다! (팁 :보기 효과와 속도는 다른 브라우저에서 매우 다릅니다)
이미지는 코드별로 생성되며 사용자는 페이지를 새로 고치고 장미 시청의 프리젠 테이션 프로세스를 반복 할 수 있습니다.
3D Rose의 구현 코드는 다음과 같습니다.
코드 사본은 다음과 같습니다 P (a, b, c) {if (c> 60) 반환 [s (a*7)*(13+5/(. 2+p (b*4,4))-s (b)*50, b*f+50,625+c (a*7)*(13+ 5/(. 2+p (b*4,4))+b*400, a*1-b/2, a]; a = a*2-1; b = b*2-1; if (a*a+b*b <1) {if (c> 37) {n = (j = c & 1) ? 6 : 4; o = .5/(a+.01)+c (b*125)*3-a*300; w = b*h; return [o*c (n)+w*s (n)+j*610-390, o*s (n) -w*c (N)+550-J*350,1180+C (B+A)*99-J*300, .4-A*.1+P (1-B*B, -H*6)*. 15-A*B*.4+C (A+B)/5+P (C (C) o*(a+1)+(b> 0? w : -w)/25), 30)*. 1*(1-b*b), o/1e3+.7-o*w*3e-6]} if (c> 32) {c = c*1.16-.15; o = a*45-20; w = b*b*h; z = o*s (c)+w*c (c) +620; 반환 [o*c (c) -w*s (c), 28+c (b*.5)*99-b*b*b*60-z/ 2-h, z, (b*b*.3+p ((1- (a*a)), 7)*. 15+.3)*b, b*.7]} o = a*(2-b)*(80-c*2); w = 99-C (A)*120-C (B)*(-HC*4.9)+C (P (1-B, 7))*50+C*2; Z = O*S (C)+W*C (C) +700; 반환 [o*c (c) -w*s (c), b*99-c (p (b, 7))*50-c/3-z/1.35+450, z, (1-b/1.2)*. 9+a*.1, p (1-b), 20) /4+.05]}} setInterval ( 'for (i = 0; i <1e4; i ++) if (s = p (r (), r (), i%46/.74) {z = s [2]; x = ~~ (s [0]*f/zh); y = ~~ (s [1]*f/zh); (!
물론 관심있는 사람들은 다음과 같은 구현 프로세스와 관련 이론을 이해할 수 있습니다.
이 3 차원 코드 Rose의 프리젠 테이션 효과는 Monte Carlo 방법을 사용하며 제작자는 Monte Carlo 방법을 높이 평가했습니다. 그는 Monte Carlo 방법은 기능적 최적화 및 샘플링 측면에서 "엄청나게 강력한 도구"라고 말했다. Monte Carlo 메소드의 경우 Monte Carlo Method를 참조하십시오.
특정 작업 :
외관 샘플링 렌더링 효과 도면
이 코드 상승을 형성하기 위해 여러 가지 다른 모양 다이어그램을 사용했습니다. 총 31 개의 모양이 사용되었습니다 : 24 개의 꽃잎, 4 개의 잎, 2 개의 잎 및 1 개의 꽃 줄기, 각 모양 다이어그램이 코드에 표시되었습니다.
먼저 샘플링 범위를 정의하십시오.
함수 표면 (a, b) {// 매개 변수로 A와 B를 사용하고 있습니다.그런 다음 모양 묘사 코드를 작성하십시오.
var canvas = document.body.appendChild (document.createElement ( "canvas")), context = cantxt = canvas.getContext ( "2d"), a, b, 위치; // 이제 a와 b 매개 변수의 .1 간격으로 표면을 샘플링하려고합니다. b); context.fillRect (position.x, position.y, 1, 1);}}
이제 더 조밀 한 샘플링 간격을 시도하십시오.
보시다시피, 샘플링 간격이 더 밀도가 높아지고 가면, 점수가 가장 높은 밀도에 가까워지고, 인접한 지점 사이의 거리는 하나의 픽셀보다 작으며, 육안으로는 간격을 볼 수 없습니다 (0.01 참조). 시각적 차이가 너무 많지 않기 위해 샘플링 간격이 더 줄어 듭니다. 현재 드로잉 영역이 채워졌습니다 (비교 결과는 0.01 및 0.001).
다음으로, 나는이 공식을 사용하여 원을 그립니다.
함수 표면 (a, b) {var x = a * 100, y = b * 100, 반지름 = 50, x0 = 50, y0 = 50; if ((x -x0) * (x -x0) * (x -x0) + (y -y0) * (y -y0) <Radius * Radius) {// circlereturn {x : x, y : y}; null;}}오버플로를 방지하려면 샘플링 조건을 추가해야합니다.
if (position = surface (a, b)) {context.fillRect (position.x, position.y, 1, 1);}원을 정의하는 방법에는 여러 가지가 있으며, 그 중 일부는 샘플링을 거부 할 필요가 없습니다. 원을 정의하기 위해 어느 것을 사용할 필요가 없으므로 다른 방법을 사용하여 원을 정의합니다.
함수 표면 (a, b) {// 극지 좌표를 사용한 원형 원형 angle = a * math.pi * 2, radius = 50, x0 = 50, y0 = 50; return {x : math.cos (각도) * Radius * b + x0, y : math.sin (angle) * radius * b + y0};}}}}}(이 방법은 이전 방법에 비해 충전을 위해 밀도가 높은 샘플링이 필요합니다.)
자, 이제 원이 꽃잎처럼 보이도록 변형되도록하십시오.
함수 표면 (a, b) {var x = a * 100, y = b * 100, 반경 = 50, x0 = 50, y0 = 50; if ((x -x0) * (x -x0) * (x -x0) * (x -x0) * (x -x0) * (x -x0) + (y -y0) * (y -y0) <반경 * Radius) {return {x : x, y : y * (1 + b) / 2 // deformation};이것은 장미 꽃잎처럼 보입니다. 여기서는 일부 기능 값을 수정하려고 시도 할 수 있으며 많은 흥미로운 모양이 나타납니다.
다음으로 색상을 추가하십시오.
함수 표면 (a, b) {var x = a * 100, y = b * 100, 반경 = 50, x0 = 50, y0 = 50; if ((x -x0) * (x -x0) * (x -x0) * (x -x0) * (x -x0) + (y -y0) * (y -y0) <RADIUS * RADIUS) {return {x : x, y : y * (1 + b) / 2, r : 100 + Math. a gradientg : 50, b : 50};} else {return null;}} for (a = 0; a <1; a + = .01) {for (b = 0; b <1; b + = .001) {if (point = surface (a, b)) {context.fillstyle = "rgb (" + point.r + "," + point.b " + point.b. ")"; context.fillRect (point.x, point.y, 1, 1);}}}유색 꽃잎이 나타납니다.
3D 표면 및 관점 투영
예를 들어 관형 물체를 정의하는 것과 같이 3 차원 표면을 정의하는 것은 간단합니다.
함수 표면 (a, b) {var angle = a * math.pi * 2, 반경 = 100, 길이 = 400; return {x : math.cos (각도) * 반경, y : math.sin (각도) * 반경, z : b * 길이 / 2, // 2, i 2, g : g : g : g : g : g : g : g : g : b. 0};}그런 다음 투영 관점을 추가하십시오. 먼저 카메라를 정의해야합니다.
위에서 볼 수 있듯이 카메라를 (0, 0, z) 위치에, 캔버스를 x/y 평면에 놓습니다. 캔버스에 투사 된 샘플링 지점은 다음과 같습니다.
var px, py, // canvas x 및 y codernatesperspective = 350, halfheight = canvas.height / 2, alfwidth = canvas.width / 2, cameraz = -700; for (a = 0; a <1; a += .001) {(b = 0; b += .01) {if (b +=) {. {px = (point.x * perspective) / (point.z -cameraz) + halfwidth; py = (point.y * perspective) / (point.z -z -z -z -z -z -z -z -keraz) + alfheight; context.fillstyle = "rgb (" + point.r + "," + point.g + "," + point.b + "); 1);}}}효과는 다음과 같습니다.
z- 버퍼
Z-Buffer는 컴퓨터 그래픽에서 매우 일반적인 기술입니다. 객체를 음영 할 때, "숨겨진 표면 제거"작업이 수행되어 숨겨진 물체 뒤의 부분이 표시되지 않습니다.
위의 그림은 Z- 버퍼 기술로 처리 된 장미입니다. (이미 3 차원이 있음을 알 수 있습니다)
코드는 다음과 같습니다.
var zbuffer = [], zbufferindex; for (a = 0; a <1; a += .001) {for (b = 0; b <1; b <1; b <1; b <1; b <1; b += .01) {if (point = surfact (a, b)) {px = math.floor ((point.x * perspective) / (point.z -cameraz) +alfwidth); (point.z -cameraz) + halfheight); zbufferindex = py * canvas.width + px; if ((zbuffer [zbufferindex] === "undefined") || (point.z <zbuffer [zbufferindex])) {zbuffer [Zbuffer [zbuffer willx] = " point.r + "," + point.g + "," + point.b + ")"; context.fillRect (px, py, 1, 1);}}}회전
벡터 회전 방법을 사용할 수 있습니다. 코드 상승의 생성에서 나는 오일러 회전을 사용합니다. 이제 이전에 쓰여진 관상 객체를 회전시켜 Y 축을 중심으로 회전합니다.
함수 표면 (a, b) {var angle = a * math.pi * 2, 반경 = 100, 길이 = 400, x = math.cos (각도) * 반경, y = math.sin (각도) * 반경, z = b * 길이 - 길이 / 2, yaxisrotationangle = -.4, // radians! Math.sin (yaxisrotangle), rotatedz = x * -math.sin (yaxisrotationangle) + z * math.cos (yaxisrotationangle); return {x : rotatedx, y : y, z : rotatedz, r : 0, g : math.floor (b * 255), b : 0};};효과:
몬테 카를로 방법
샘플링 시간과 관련하여 너무 크고 너무 작 으면 시각적 경험이 극도로 저하되므로 합리적인 샘플링 간격을 설정해야하며 Monte Carlo 방법이 여기에서 사용됩니다.
var i; window.setInterVal (fort (i = 0; i = 0; i <10000; i ++) {if (point = surface (math.random (), math.random ()) {px = math.floor ((point.x * perspective)) / (point.z -z -cameraz) +halfwidth); py = math.) HalfHeight); zbufferindex = py * canvas.width + px; if ((Zbuffer [Zbufferindex] === "undefined") || (point.z <zbuffer [zbufferindex]))) {zbuffer [zbufferindex] = point.z; rgb ( " +" + " +" + " +" point.g + "," + point.b + ")"; context.fillRect (px, py, 1, 1);}}}, 0);A와 B를 랜덤 파라미터로 설정하고 충분한 샘플링으로 완전한 표면 충전. 매번 10000 포인트를 그리고 화면이 업데이트를 완료 할 때까지 기다립니다.
또한 임의의 숫자가 올바르지 않으면 표면 충전 효과가 올바르지 않습니다. 일부 브라우저에서는 Math.random의 실행이 선형으로 표면 충전 효과의 오류로 이어질 수 있습니다. 현재 Mersenne Twister (임의의 숫자 알고리즘)와 같은 것을 사용하여 오류를 피하기 위해 고품질 PRNG 샘플링을 수행해야합니다.
마치다
장미의 각 부분이 동시에 완료되고 렌더링 되려면 동기화 값을 반환하기 위해 각 부품의 매개 변수를 설정하려면 기능을 추가해야합니다. 그리고 세그먼트 함수를 사용하여 장미의 다양한 부분을 나타냅니다. 예를 들어, 꽃잎 부분에서는 회전과 변형을 사용하여이를 생성합니다.
표면 샘플링 방법은 3 차원 그래픽을 생성하는 가장 유명하고 오래된 방법 중 하나이지만 몬테 카를로와 Z- 버퍼를 표면 샘플링에 추가하는이 방법은 일반적이지 않습니다. 이것은 실제 시나리오 제작에는 그다지 창의적이지 않을 수 있지만 간단한 코드 구현과 작은 크기는 여전히 만족 스럽습니다.
이 기사가 컴퓨터 그래픽 애호가들이 다른 프레젠테이션 방법을 시도하고 재미있게 즐기도록 영감을 줄 것입니다. (로마 코르테스)
위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.