From 35b8b254ded1001e6d37ecec255104acaa23941d Mon Sep 17 00:00:00 2001 From: "hngmo.kim" <hngmo.kim@gmail.com> Date: Sun, 26 Jun 2022 23:19:34 +0900 Subject: [PATCH] final? commit --- img/0.png | Bin 0 -> 31423 bytes index.html | 69 +++++++++++++++++++ pointlightshadow0.js | 25 +++++++ pointlightshadow1.js | 82 +++++++++++++++++++++++ pointlightshadow2.js | 74 +++++++++++++++++++++ pointlightshadow3.js | 68 +++++++++++++++++++ pointlightshadow4.js | 74 +++++++++++++++++++++ pointlightshadow5.js | 54 +++++++++++++++ pointlightshadow6.js | 54 +++++++++++++++ pointlightshadow7.js | 55 ++++++++++++++++ pointlightshadow8.js | 55 ++++++++++++++++ pointlightshadowelse.js | 104 +++++++++++++++++++++++++++++ second.html | 143 ++++++++++++++++++++++++++++++++++++++++ 13 files changed, 857 insertions(+) create mode 100644 img/0.png create mode 100644 index.html create mode 100644 pointlightshadow0.js create mode 100644 pointlightshadow1.js create mode 100644 pointlightshadow2.js create mode 100644 pointlightshadow3.js create mode 100644 pointlightshadow4.js create mode 100644 pointlightshadow5.js create mode 100644 pointlightshadow6.js create mode 100644 pointlightshadow7.js create mode 100644 pointlightshadow8.js create mode 100644 pointlightshadowelse.js create mode 100644 second.html diff --git a/img/0.png b/img/0.png new file mode 100644 index 0000000000000000000000000000000000000000..4eb78f1ae5928af55dbd614a0ddba142fa1e99b2 GIT binary patch literal 31423 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 O7(8A5T-G@yGywpi^e@x^ literal 0 HcmV?d00001 diff --git a/index.html b/index.html new file mode 100644 index 0000000..f46c786 --- /dev/null +++ b/index.html @@ -0,0 +1,69 @@ +<html> + <head> + <meta charset="utf-8"> + <title>PointLight Shadow - Hngmo.Kim</title> + <style>body { margin: 0; }</style> + </head> + <body> + <div> + <script src="js/three.js"></script> + <p> + <h2> + 본 문서는 그래픽스 조명의 종류중 PointLight에 의해 + 발생하는 그림자(PointLight Shadow)에 대해 three.js에서 어떻게 활용할 + 것인지 학습하는 것을 목표로 한다. + </h2> + <h3> + 대부분의 예제 케이스에 대하여 git에 함께 첨부된 js파일 순서에 + 맞추어 확인해 보는 것으로 학습에 도움이 될것이다. + </h3> + </p> + <p> + <img src="img/0.png"> + </p> + <p> + 우선 PointLight에 대해 간단히 되짚어 보고자 한다. + PointLight는 한국어로 pointlight이라고도 불린다. + </p> + <p> + 빛을 발하는 근원이 기하학적으로 차원이 없는 한 점으로 되어있는 광원을 의미한다. + </p> + <p> + 위의 그림과 같이 점을 중심으로 빛이 뻗어 나가게 되는 형태이다. + </p> + <p> + <canvas id="HelloCanvas0"></canvas> + <script src="pointlightshadow0.js"></script> + </p> + <p> + 위의 렌더링 결과를 보아라. 중심 좌표에 PointLight를 두었을 때, 뒷편의 면에 빛이 어떻게 도달하는지를 나타낸다. + 중심부는 밝지만 주변부로 갈수록 어두워진다. + 이는 pointlight으로 부터 나온 빛이 면에 도달할 때, 면의 주변부로 갈수록 단위면적당 빛의 수가 감소하기 때문이다. + </p> + <p> + <canvas id="HelloCanvas1"></canvas> + <script src="pointlightshadow1.js"></script> + </p> + <p> + 위는 중앙의 pointlight을 두고, 주위로 8개의 물체를 두었을 때 이다. + </p> + <h2> + 그럼 지금부터 threejs.org의 document에 작성된 LightShadow중 쉽게, 눈에띄게 활용할 수 있는 요소에 대하여 pointlight의 관점에서 살펴보도록 하겠다. + </h2> + <h3> + 예제코드의 이해를 위해서는 geometry, transform, camera, pointlight에 대한 three.js 코드 이해가 선행되어야 한다. + </h3> + <p> + 각각의 기능에 대해 값을 수정해 가며 그 기능을 어떻게 활용할 수 있는지를 중심으로 보겠다. + </p> + <h1> + <a href="second.html" target = "_self">다음으로</a> + </h1> + <h3> + <p> + three.js : PointLightShadow - Kim Hyeongmo + </p> + </h3> + </div> + </body> +</html> diff --git a/pointlightshadow0.js b/pointlightshadow0.js new file mode 100644 index 0000000..9b7577b --- /dev/null +++ b/pointlightshadow0.js @@ -0,0 +1,25 @@ +const function_0 = function(){ +const h_scr2 = window.innerWidth; +const v_scr2 = window.innerHeight; +const scene2 = new THREE.Scene(); +const camera2 = new THREE.PerspectiveCamera(120, h_scr2/v_scr2, 0.1, 1000); +camera2.position.z = 10; // (0,0,z)에서 (0,0,0)을 보고있는 것 + +const renderer2 = new THREE.WebGLRenderer({canvas: HelloCanvas0}); +renderer2.setSize( h_scr2, v_scr2 ); +renderer2.shadowMap.enabled = true; +renderer2.shadowMap.type = THREE.PCFSoftShadowMap; // default THREE.PCFShadowMap + +const light2 = new THREE.PointLight( 0xffffff, 1, 100 ); +light2.position.set( 0, 0, 0 ); +scene2.add( light2 ); + +const planeGeometry2 = new THREE.PlaneGeometry( 60, 60, 32, 32 ); +const planeMaterial2 = new THREE.MeshStandardMaterial( { color: 0xffffff } ) +const plane2 = new THREE.Mesh( planeGeometry2, planeMaterial2 ); +plane2.position.z = -30; +scene2.add( plane2 ); + +renderer2.render( scene2, camera2 ); +} +function_0(); \ No newline at end of file diff --git a/pointlightshadow1.js b/pointlightshadow1.js new file mode 100644 index 0000000..c50cb5f --- /dev/null +++ b/pointlightshadow1.js @@ -0,0 +1,82 @@ +const function_1 = function(){ + const h_scr2 = window.innerWidth; + const v_scr2 = window.innerHeight; + const scene2 = new THREE.Scene(); + const camera2 = new THREE.PerspectiveCamera(120, h_scr2/v_scr2, 0.1, 1000); + camera2.position.z = 10; // (0,0,z)에서 (0,0,0)을 보고있는 것 + + const renderer2 = new THREE.WebGLRenderer({canvas: HelloCanvas1}); + renderer2.setSize( h_scr2, v_scr2 ); + + const light2 = new THREE.PointLight( 0xffffff, 1, 100 ); + light2.position.set( 0, 0, 0 ); + scene2.add( light2 ); + + + const sphereGeometry = new THREE.SphereGeometry( 2, 32, 32 ); + const sphereMaterial = new THREE.MeshPhongMaterial( { + color: 0xffff00, shininess : 90.0 }); + const sphere = new THREE.Mesh( sphereGeometry, sphereMaterial ); + sphere.position.set(0,8,0); + scene2.add( sphere ); + + const sphereGeometry2 = new THREE.SphereGeometry( 2, 32, 32 ); + const sphereMaterial2 = new THREE.MeshPhongMaterial( { + color: 0xffff00, shininess : 90.0 }); + const sphere2 = new THREE.Mesh( sphereGeometry2, sphereMaterial2 ); + sphere2.position.set(-8,8,0); + scene2.add( sphere2 ); + + const sphereGeometry3 = new THREE.SphereGeometry( 2, 32, 32 ); + const sphereMaterial3 = new THREE.MeshPhongMaterial( { + color: 0xffff00, shininess : 90.0 }); + const sphere3 = new THREE.Mesh( sphereGeometry3, sphereMaterial3 ); + sphere3.position.set(-8,0,0); + scene2.add( sphere3 ); + + const sphereGeometry4 = new THREE.SphereGeometry( 2, 32, 32 ); + const sphereMaterial4 = new THREE.MeshPhongMaterial( { + color: 0xffff00, shininess : 90.0 }); + const sphere4 = new THREE.Mesh( sphereGeometry4, sphereMaterial4 ); + sphere4.position.set(-8,-8,0); + scene2.add( sphere4 ); + + const sphereGeometry5 = new THREE.SphereGeometry( 2, 32, 32 ); + const sphereMaterial5 = new THREE.MeshPhongMaterial( { + color: 0xffff00, shininess : 90.0 }); + const sphere5 = new THREE.Mesh( sphereGeometry5, sphereMaterial5 ); + sphere5.position.set(0,-8,0); + scene2.add( sphere5 ); + + const sphereGeometry6 = new THREE.SphereGeometry( 2, 32, 32 ); + const sphereMaterial6 = new THREE.MeshPhongMaterial( { + color: 0xffff00, shininess : 90.0 }); + const sphere6 = new THREE.Mesh( sphereGeometry6, sphereMaterial6 ); + sphere6.position.set(8,-8,0); + scene2.add( sphere6 ); + + const sphereGeometry7 = new THREE.SphereGeometry( 2, 32, 32 ); + const sphereMaterial7 = new THREE.MeshPhongMaterial( { + color: 0xffff00, shininess : 90.0 }); + const sphere7 = new THREE.Mesh( sphereGeometry7, sphereMaterial7 ); + sphere7.position.set(8,0,0); + scene2.add( sphere7 ); + + const sphereGeometry8 = new THREE.SphereGeometry( 2, 32, 32 ); + const sphereMaterial8 = new THREE.MeshPhongMaterial( { + color: 0xffff00, shininess : 90.0 }); + const sphere8 = new THREE.Mesh( sphereGeometry8, sphereMaterial8 ); + sphere8.position.set(8,8,0); + scene2.add( sphere8 ); + + + const planeGeometry2 = new THREE.PlaneGeometry( 60, 60, 32, 32 ); + const planeMaterial2 = new THREE.MeshStandardMaterial( { color: 0xffffff } ) + const plane2 = new THREE.Mesh( planeGeometry2, planeMaterial2 ); + plane2.position.z = -30; + scene2.add( plane2 ); + + + renderer2.render( scene2, camera2 ); + } + function_1(); \ No newline at end of file diff --git a/pointlightshadow2.js b/pointlightshadow2.js new file mode 100644 index 0000000..1faebf4 --- /dev/null +++ b/pointlightshadow2.js @@ -0,0 +1,74 @@ +const function0 = function(){ +const h_scr2 = window.innerWidth; +const v_scr2 = window.innerHeight; +const scene2 = new THREE.Scene(); +const camera2 = new THREE.PerspectiveCamera(120, h_scr2/v_scr2, 0.1, 1000); +camera2.position.y = 15; +camera2.lookAt(0,0,0); + +//Create a WebGLRenderer and turn on shadows in the renderer +const renderer2 = new THREE.WebGLRenderer({canvas: HelloCanvas}); +renderer2.setSize( h_scr2, v_scr2 ); +renderer2.shadowMap.enabled = true; +const light2 = new THREE.PointLight( 0xffffff, 1, 100 ); +//const light2 = new THREE.DirectionalLight( 0xffffff, 1); +//light2.position.set( 0, 0, 1 ); +//directioanl은 항상 위에서 온다. +//light2.rotaion.x = 90; +light2.castShadow = true; // default false +//light2.autoUpdate = false; +scene2.add( light2 ); + +//Set up shadow properties for the light +//light2.shadow.mapSize.width = 128; // default +//light2.shadow.mapSize.height = 128; // default +//light2.shadow.camera.near = 0.5; // default +//light2.shadow.camera.far = 500; // default + +//Create a sphere that cast shadows (but does not receive them) +const sphereGeometry = new THREE.SphereGeometry( 5, 32, 32 ); +const sphereMaterial = new THREE.MeshPhongMaterial( { + color: 0xffff00, shininess : 90.0 }); +const sphere = new THREE.Mesh( sphereGeometry, sphereMaterial ); +sphere.castShadow = true; //default is false +sphere.receiveShadow = false; //default +scene2.add( sphere ); + +//Create a plane that receives shadows (but does not cast them) +const planeGeometry = new THREE.PlaneGeometry( 60, 60, 32, 32 ); +const planeMaterial = new THREE.MeshStandardMaterial( { color: 0xffffff } ) +const plane = new THREE.Mesh( planeGeometry, planeMaterial ); +plane.receiveShadow = true; +plane.rotation.x = -1.57; +plane.position.set(0,-5,0); +scene2.add( plane ); + +//Create a helper for the shadow camera (optional) +const helper = new THREE.CameraHelper( light2.shadow.camera ); +scene2.add( helper ); + + +var x = -12; +var x_trans = 0; +const animate = function () { + requestAnimationFrame( animate ); + + if(x>=12) + { + x_trans = -0.1; + } + else if(x<=-12) + { + x_trans = +0.1; + } + + x += x_trans; + + + light2.position.set( x, 10, 0 ); + + renderer2.render( scene2, camera2 ); +}; +animate(); +} +function0(); \ No newline at end of file diff --git a/pointlightshadow3.js b/pointlightshadow3.js new file mode 100644 index 0000000..97a317d --- /dev/null +++ b/pointlightshadow3.js @@ -0,0 +1,68 @@ +const function1 = function(){ +const h_scr2 = window.innerWidth; +const v_scr2 = window.innerHeight; +const scene2 = new THREE.Scene(); +const camera2 = new THREE.PerspectiveCamera(120, h_scr2/v_scr2, 0.1, 1000); +camera2.position.y = 15; +camera2.lookAt(0,0,0); + +//Create a WebGLRenderer and turn on shadows in the renderer +const renderer2 = new THREE.WebGLRenderer({canvas: HelloCanvas2}); +renderer2.setSize( h_scr2, v_scr2 ); +renderer2.shadowMap.enabled = true; +const light2 = new THREE.PointLight( 0xffffff, 1, 100 ); +//const light2 = new THREE.DirectionalLight( 0xffffff, 1); +//light2.position.set( 0, 0, 1 ); +//directioanl은 항상 위에서 온다. +//light2.rotaion.x = 90; +light2.castShadow = true; // default false +light2.position.set(0,5,0); +//light2.autoUpdate = false; +scene2.add( light2 ); + +//Set up shadow properties for the light +//light2.shadow.mapSize.width = 128; // default +//light2.shadow.mapSize.height = 128; // default +//light2.shadow.camera.near = 0.5; // default +//light2.shadow.camera.far = 500; // default + +//Create a sphere that cast shadows (but does not receive them) +const sphereGeometry = new THREE.SphereGeometry( 5, 32, 32 ); +const sphereMaterial = new THREE.MeshPhongMaterial( { + color: 0xffff00, shininess : 90.0 }); +const sphere = new THREE.Mesh( sphereGeometry, sphereMaterial ); +sphere.castShadow = true; //default is false +sphere.receiveShadow = false; //default +scene2.add( sphere ); + +//Create a plane that receives shadows (but does not cast them) +const planeGeometry = new THREE.PlaneGeometry( 60, 60, 32, 32 ); +const planeMaterial = new THREE.MeshStandardMaterial( { color: 0xffffff } ) +const plane = new THREE.Mesh( planeGeometry, planeMaterial ); +plane.receiveShadow = true; +plane.rotation.x = -1.57; +plane.position.set(0,-5,0); +scene2.add( plane ); + + + + +var x = -12; +var x_trans = 0; +const animate = function () { + requestAnimationFrame( animate ); + if(light2.position.y <= 10) + { + light2.position.y += 0.01; + } + else + { + light2.position.y = 5; + } + + + renderer2.render( scene2, camera2 ); +}; +animate(); +} +function1(); \ No newline at end of file diff --git a/pointlightshadow4.js b/pointlightshadow4.js new file mode 100644 index 0000000..f665704 --- /dev/null +++ b/pointlightshadow4.js @@ -0,0 +1,74 @@ +const function4 = function(){ +const h_scr2 = window.innerWidth; +const v_scr2 = window.innerHeight; +const scene2 = new THREE.Scene(); +const camera2 = new THREE.PerspectiveCamera(120, h_scr2/v_scr2, 0.1, 1000); +camera2.position.y = 15; +camera2.lookAt(0,0,0); + +//Create a WebGLRenderer and turn on shadows in the renderer +const renderer2 = new THREE.WebGLRenderer({canvas: HelloCanvas4}); +renderer2.setSize( h_scr2, v_scr2 ); +renderer2.shadowMap.enabled = true; +const light2 = new THREE.PointLight( 0xffffff, 1, 100 ); +//const light2 = new THREE.DirectionalLight( 0xffffff, 1); +//light2.position.set( 0, 0, 1 ); +//directioanl은 항상 위에서 온다. +//light2.rotaion.x = 90; +light2.castShadow = true; // default false +//light2.autoUpdate = false; +scene2.add( light2 ); + +//Set up shadow properties for the light +//light2.shadow.mapSize.width = 128; // default +//light2.shadow.mapSize.height = 128; // default +light2.shadow.camera.near = 20; +//light2.shadow.camera.far = 500; // default + +//Create a sphere that cast shadows (but does not receive them) +const sphereGeometry = new THREE.SphereGeometry( 5, 32, 32 ); +const sphereMaterial = new THREE.MeshPhongMaterial( { + color: 0xffff00, shininess : 90.0 }); +const sphere = new THREE.Mesh( sphereGeometry, sphereMaterial ); +sphere.castShadow = true; //default is false +sphere.receiveShadow = false; //default +scene2.add( sphere ); + +//Create a plane that receives shadows (but does not cast them) +const planeGeometry = new THREE.PlaneGeometry( 60, 60, 32, 32 ); +const planeMaterial = new THREE.MeshStandardMaterial( { color: 0xffffff } ) +const plane = new THREE.Mesh( planeGeometry, planeMaterial ); +plane.receiveShadow = true; +plane.rotation.x = -1.57; +plane.position.set(0,-5,0); +scene2.add( plane ); + +//Create a helper for the shadow camera (optional) +const helper = new THREE.CameraHelper( light2.shadow.camera ); +scene2.add( helper ); + + +var x = -12; +var x_trans = 0; +const animate = function () { + requestAnimationFrame( animate ); + + if(x>=12) + { + x_trans = -0.1; + } + else if(x<=-12) + { + x_trans = +0.1; + } + + x += x_trans; + + + light2.position.set( x, 10, 0 ); + + renderer2.render( scene2, camera2 ); +}; +animate(); +} +function4(); \ No newline at end of file diff --git a/pointlightshadow5.js b/pointlightshadow5.js new file mode 100644 index 0000000..f0e9735 --- /dev/null +++ b/pointlightshadow5.js @@ -0,0 +1,54 @@ +const function5 = function(){ +const h_scr2 = window.innerWidth; +const v_scr2 = window.innerHeight; +const scene2 = new THREE.Scene(); +const camera2 = new THREE.PerspectiveCamera(120, h_scr2/v_scr2, 0.1, 1000); +camera2.position.y = 15; +camera2.lookAt(0,0,0); + +//Create a WebGLRenderer and turn on shadows in the renderer +const renderer2 = new THREE.WebGLRenderer({canvas: HelloCanvas5}); +renderer2.setSize( h_scr2, v_scr2 ); +renderer2.shadowMap.enabled = true; +const light2 = new THREE.PointLight( 0xffffff, 1, 100 ); +//const light2 = new THREE.DirectionalLight( 0xffffff, 1); +//light2.position.set( 0, 0, 1 ); +//directioanl은 항상 위에서 온다. +//light2.rotaion.x = 90; +light2.castShadow = true; // default false +scene2.add( light2 ); + + +//Set up shadow properties for the light +light2.shadow.mapSize.width = 128; // default +light2.shadow.mapSize.height = 128; // default +//light2.shadow.camera.near = 0.5; // default +//light2.shadow.camera.far = 500; // default + +//Create a sphere that cast shadows (but does not receive them) +const sphereGeometry = new THREE.SphereGeometry( 5, 32, 32 ); +const sphereMaterial = new THREE.MeshPhongMaterial( { + color: 0xffff00, shininess : 90.0 }); +const sphere = new THREE.Mesh( sphereGeometry, sphereMaterial ); +sphere.castShadow = true; //default is false +sphere.receiveShadow = false; //default +scene2.add( sphere ); + +//Create a plane that receives shadows (but does not cast them) +const planeGeometry = new THREE.PlaneGeometry( 60, 60, 32, 32 ); +const planeMaterial = new THREE.MeshStandardMaterial( { color: 0xffffff } ) +const plane = new THREE.Mesh( planeGeometry, planeMaterial ); +plane.receiveShadow = true; +plane.rotation.x = -1.57; +plane.position.set(0,-5,0); +scene2.add( plane ); + + +var x = -12; +light2.position.set( x, 10, 0 ); + + + + renderer2.render( scene2, camera2 ); +} +function5(); \ No newline at end of file diff --git a/pointlightshadow6.js b/pointlightshadow6.js new file mode 100644 index 0000000..b5079e6 --- /dev/null +++ b/pointlightshadow6.js @@ -0,0 +1,54 @@ +const function6 = function(){ +const h_scr2 = window.innerWidth; +const v_scr2 = window.innerHeight; +const scene2 = new THREE.Scene(); +const camera2 = new THREE.PerspectiveCamera(120, h_scr2/v_scr2, 0.1, 1000); +camera2.position.y = 15; +camera2.lookAt(0,0,0); + +//Create a WebGLRenderer and turn on shadows in the renderer +const renderer2 = new THREE.WebGLRenderer({canvas: HelloCanvas6}); +renderer2.setSize( h_scr2, v_scr2 ); +renderer2.shadowMap.enabled = true; +const light2 = new THREE.PointLight( 0xffffff, 1, 100 ); +//const light2 = new THREE.DirectionalLight( 0xffffff, 1); +//light2.position.set( 0, 0, 1 ); +//directioanl은 항상 위에서 온다. +//light2.rotaion.x = 90; +light2.castShadow = true; // default false +scene2.add( light2 ); + + +//Set up shadow properties for the light +light2.shadow.mapSize.width = 1024; // default +light2.shadow.mapSize.height = 1024; // default +//light2.shadow.camera.near = 0.5; // default +//light2.shadow.camera.far = 500; // default + +//Create a sphere that cast shadows (but does not receive them) +const sphereGeometry = new THREE.SphereGeometry( 5, 32, 32 ); +const sphereMaterial = new THREE.MeshPhongMaterial( { + color: 0xffff00, shininess : 90.0 }); +const sphere = new THREE.Mesh( sphereGeometry, sphereMaterial ); +sphere.castShadow = true; //default is false +sphere.receiveShadow = false; //default +scene2.add( sphere ); + +//Create a plane that receives shadows (but does not cast them) +const planeGeometry = new THREE.PlaneGeometry( 60, 60, 32, 32 ); +const planeMaterial = new THREE.MeshStandardMaterial( { color: 0xffffff } ) +const plane = new THREE.Mesh( planeGeometry, planeMaterial ); +plane.receiveShadow = true; +plane.rotation.x = -1.57; +plane.position.set(0,-5,0); +scene2.add( plane ); + + +var x = -12; +light2.position.set( x, 10, 0 ); + + + + renderer2.render( scene2, camera2 ); +} +function6(); \ No newline at end of file diff --git a/pointlightshadow7.js b/pointlightshadow7.js new file mode 100644 index 0000000..918af98 --- /dev/null +++ b/pointlightshadow7.js @@ -0,0 +1,55 @@ +const function7 = function(){ +const h_scr2 = window.innerWidth; +const v_scr2 = window.innerHeight; +const scene2 = new THREE.Scene(); +const camera2 = new THREE.PerspectiveCamera(120, h_scr2/v_scr2, 0.1, 1000); +camera2.position.y = 15; +camera2.lookAt(0,0,0); + +//Create a WebGLRenderer and turn on shadows in the renderer +const renderer2 = new THREE.WebGLRenderer({canvas: HelloCanvas7}); +renderer2.setSize( h_scr2, v_scr2 ); +renderer2.shadowMap.enabled = true; +const light2 = new THREE.PointLight( 0xffffff, 1, 100 ); +//const light2 = new THREE.DirectionalLight( 0xffffff, 1); +//light2.position.set( 0, 0, 1 ); +//directioanl은 항상 위에서 온다. +//light2.rotaion.x = 90; +light2.castShadow = true; // default false +scene2.add( light2 ); + + +//Set up shadow properties for the light +light2.shadow.mapSize.width = 1024; // default +light2.shadow.mapSize.height = 1024; // default +light2.shadow.radius = 20; +//light2.shadow.camera.near = 0.5; // default +//light2.shadow.camera.far = 500; // default + +//Create a sphere that cast shadows (but does not receive them) +const sphereGeometry = new THREE.SphereGeometry( 5, 32, 32 ); +const sphereMaterial = new THREE.MeshPhongMaterial( { + color: 0xffff00, shininess : 90.0 }); +const sphere = new THREE.Mesh( sphereGeometry, sphereMaterial ); +sphere.castShadow = true; //default is false +sphere.receiveShadow = false; //default +scene2.add( sphere ); + +//Create a plane that receives shadows (but does not cast them) +const planeGeometry = new THREE.PlaneGeometry( 60, 60, 32, 32 ); +const planeMaterial = new THREE.MeshStandardMaterial( { color: 0xffffff } ) +const plane = new THREE.Mesh( planeGeometry, planeMaterial ); +plane.receiveShadow = true; +plane.rotation.x = -1.57; +plane.position.set(0,-5,0); +scene2.add( plane ); + + +var x = -12; +light2.position.set( x, 10, 0 ); + + + + renderer2.render( scene2, camera2 ); +} +function7(); \ No newline at end of file diff --git a/pointlightshadow8.js b/pointlightshadow8.js new file mode 100644 index 0000000..8a746e8 --- /dev/null +++ b/pointlightshadow8.js @@ -0,0 +1,55 @@ +const function8 = function(){ +const h_scr2 = window.innerWidth; +const v_scr2 = window.innerHeight; +const scene2 = new THREE.Scene(); +const camera2 = new THREE.PerspectiveCamera(120, h_scr2/v_scr2, 0.1, 1000); +camera2.position.y = 15; +camera2.lookAt(0,0,0); + +//Create a WebGLRenderer and turn on shadows in the renderer +const renderer2 = new THREE.WebGLRenderer({canvas: HelloCanvas8}); +renderer2.setSize( h_scr2, v_scr2 ); +renderer2.shadowMap.enabled = true; +const light2 = new THREE.PointLight( 0xffffff, 1, 100 ); +//const light2 = new THREE.DirectionalLight( 0xffffff, 1); +//light2.position.set( 0, 0, 1 ); +//directioanl은 항상 위에서 온다. +//light2.rotaion.x = 90; +light2.castShadow = true; // default false +scene2.add( light2 ); + + +//Set up shadow properties for the light +light2.shadow.mapSize.width = 1024; // default +light2.shadow.mapSize.height = 1024; // default +light2.shadow.radius = 100; +//light2.shadow.camera.near = 0.5; // default +//light2.shadow.camera.far = 500; // default + +//Create a sphere that cast shadows (but does not receive them) +const sphereGeometry = new THREE.SphereGeometry( 5, 32, 32 ); +const sphereMaterial = new THREE.MeshPhongMaterial( { + color: 0xff0000, shininess : 90.0 }); +const sphere = new THREE.Mesh( sphereGeometry, sphereMaterial ); +sphere.castShadow = true; //default is false +sphere.receiveShadow = false; //default +scene2.add( sphere ); + +//Create a plane that receives shadows (but does not cast them) +const planeGeometry = new THREE.PlaneGeometry( 60, 60, 32, 32 ); +const planeMaterial = new THREE.MeshStandardMaterial( { color: 0xffffff } ) +const plane = new THREE.Mesh( planeGeometry, planeMaterial ); +plane.receiveShadow = true; +plane.rotation.x = -1.57; +plane.position.set(0,-5,0); +scene2.add( plane ); + + +var x = -12; +light2.position.set( x, 10, 0 ); + + + + renderer2.render( scene2, camera2 ); +} +function8(); \ No newline at end of file diff --git a/pointlightshadowelse.js b/pointlightshadowelse.js new file mode 100644 index 0000000..d798c8a --- /dev/null +++ b/pointlightshadowelse.js @@ -0,0 +1,104 @@ +const function1 = function(){ +//그림자옵션이 꺼질 때의 점광원 테스트 +//그 테스트는 구에서 시행할 것 +//그림자로 인해 도형이 어두워지는 것과 그냥 빛을 받지않아 도형이 어두워진 것을 표현하는 것과의 차이를 분석할 것. +//그렇게 점광원과 점광원 그림자에 대한 테스트를 진행한 후 점광원 그림자 관련 함수들을 사용해보면서 변화를 설명할 것. +//변수명의 뒤에는 종류와 무관하게 파일 번호를 입력할 것. +const h_scr2 = window.innerWidth; +const v_scr2 = window.innerHeight; +//const h_scr = 800; +//const v_scr = 750; +const scene2 = new THREE.Scene(); +const camera2 = new THREE.PerspectiveCamera(120, h_scr2/v_scr2, 0.1, 1000); +camera2.position.z = 10; // (0,0,z)에서 (0,0,0)을 보고있는 것 +camera2.position.x = 30; + +//Create a WebGLRenderer and turn on shadows in the renderer +const renderer2 = new THREE.WebGLRenderer({canvas: HelloCanvas2}); +renderer2.setSize( h_scr2, v_scr2 ); +renderer2.shadowMap.enabled = true; +renderer2.shadowMap.type = THREE.PCFSoftShadowMap; // default THREE.PCFShadowMap + +//Create a PointLight and turn on shadows for the light +const light2 = new THREE.PointLight( 0xffffff, 1, 100 ); +//const light2 = new THREE.DirectionalLight( 0xffffff, 1); +light2.position.set( 0, 0, 0 ); +//light2.position.set( 0, 0, 1 ); +//directioanl은 항상 위에서 온다. +//light2.rotaion.x = 90; +light2.castShadow = true; // default false +scene2.add( light2 ); + +//Set up shadow properties for the light +light2.shadow.mapSize.width = 512; // default +light2.shadow.mapSize.height = 512; // default +light2.shadow.camera.near = 0.5; // default +light2.shadow.camera.far = 500; // default + +//Create a sphere that cast shadows (but does not receive them) +const sphereGeometry2 = new THREE.SphereGeometry( 1, 32, 32 ); +const sphereMaterial2 = new THREE.MeshPhongMaterial( { + color: 0xffff00, shininess : 90.0 }); +const sphere2 = new THREE.Mesh( sphereGeometry2, sphereMaterial2 ); +sphere2.castShadow = true; //default is false +sphere2.receiveShadow = true; //default +sphere2.position.z = -5 +//sphere2.position.z = -5 +scene2.add( sphere2 ); + +//Create a sphere that cast shadows (but does not receive them) +const sphereGeometry2_1 = new THREE.SphereGeometry( 5, 32, 32 ); +const sphereMaterial2_1 = new THREE.MeshPhongMaterial( { + color: 0xffff00, shininess : 90.0 }); +const sphere2_1 = new THREE.Mesh( sphereGeometry2_1, sphereMaterial2_1 ); +sphere2_1.castShadow = true; //default is false +sphere2_1.receiveShadow = true; //default +sphere2_1.position.z = -15 +//sphere2_1.position.z = -15 +scene2.add( sphere2_1 ); + + + +//Create a plane that receives shadows (but does not cast them) +const planeGeometry2 = new THREE.PlaneGeometry( 60, 60, 32, 32 ); +const planeMaterial2 = new THREE.MeshStandardMaterial( { color: 0xffffff } ) +const plane2 = new THREE.Mesh( planeGeometry2, planeMaterial2 ); +plane2.receiveShadow = true; +plane2.position.z = -30; +scene2.add( plane2 ); + +//Create a helper for the shadow camera (optional) +const helper2 = new THREE.CameraHelper( light2.shadow.camera ); +scene2.add( helper2 ); + + +var x2 = -8; +var z2 = 0; +var x_trans2 = 0; + +const animate2 = function () { + requestAnimationFrame( animate2 ); +/* + if(x2>=8) + { + x_trans2 = -0.1; + } + else if(x2<=-8) + { + x_trans2 = +0.1; + } + + x2 += x_trans2; + + + light2.position.set( x, 0, 0 ); + plane2.position.z = -30; + */ + plane2.position.z -= 0.05; + + renderer2.render( scene2, camera2 ); +}; +//animate2(); +renderer2.render( scene2, camera2 ); +} +function1(); \ No newline at end of file diff --git a/second.html b/second.html new file mode 100644 index 0000000..1d2e1e4 --- /dev/null +++ b/second.html @@ -0,0 +1,143 @@ +<html> + <head> + <meta charset="utf-8"> + <title>PointLight Shadow - Hngmo.Kim</title> + <style>body { margin: 0; }</style> + </head> + <body> + <div> + <h4> + 우선 그림자를 드리우기 위한 기본 작업이 필요하다. 각각의 변수명은 절대적인 것이 아니다. 자신이 만든 변수 이름을 사용하면 된다. + </h4> + <p> + renderer에서 shadow의 사용을 활성화 해주는 코드 + </p> + <p> + <code>renderer.shadowMap.enabled = true;</code> + </p> + <p> + 그림자를 발생시키는 빛에 대해 castShadow를 활성화 시켜야 한다. + </p> + <p> + <code>light.castShadow = true;</code> + </p> + <p> + 그림자를 발생시키는 물체에 대해 castShadow를 활성화 시켜야 한다. + </p> + <p> + <code>object.castShadow = true;</code> + </p> + <p> + 발생한 그림자를 받아 표현될 물체에 대해 receiveShadow를 활성화 시켜야 한다. + </p> + <p> + <code>object.receiveShadow = true;</code> + </p> + <p> + </p> + <h4> + 각각은 default값이 false이기 때문에 true로 값을 바꿔주어야 한다. + </h4> + <p> + <script src="js/three.js"></script> + <canvas id="HelloCanvas"></canvas> + <script src="pointlightshadow2.js"></script> + </p> + <p> + 위의 렌더링에서는 광원의 위치만 변경하고 있다. 광원의 위치에 따라 그림자가 생성되는 것을 확인할 수 있다. + 그런데 자세히 보면 빛이 중앙으로 올 때, 구체의 크기보다 그림자가 큰 것을 확인할 수 있다. + 이것은 광원이 pointlight이기 때문이며, 물체와 광원과의 거리에 따라 그림자의 크기가 달라질 것이다. + 한번 광원의 위치를 점차 구체로 부터 멀어지게 해볼까? + </p> + <p> + <canvas id="HelloCanvas2"></canvas> + <script src="pointlightshadow3.js"></script> + </p> + <h2> + property 첫번째 : camera + </h2> + <p> + 처음 렌더링 예제에서 perspective camera와 비슷한 것이 움직이는 것을 보지 않았는가? + 그렇다. three.js에서 pointlight은 그림자를 드리울 떄 마치 perspective camera인 것 처럼 드리운다. + 즉 near, far 값을 조정하여 그림자를 표현할 범위를 지정할 수 있다 + 중요한 것은 그림자다! 그림자를 표현할 범위이다. + 그러면 near값을 키워 그림자를 없애보도록 하겠다. + </p> + <p> + <canvas id="HelloCanvas4"></canvas> + <script src="pointlightshadow4.js"></script> + </p> + <p> + default값은 near : 0.5, far : 500 이다. + </p> + <p> + <code>light2.shadow.camera.near = 20;</code> + </p> + <p> + near를 뒷면 너머로 보냈더니 그림자가 드리워지지 않는다. 하지만 빛은 정상적으로 구체를 비치며, 명암이 형성된다. + 코드에서도 추측할 수 있듯이 그림자에 대한 적용이다. + </p> + <p> + <code>const helper = new THREE.CameraHelper( light2.shadow.camera ); + scene2.add( helper ); + </code> + </p> + <p> + 이상의 코드를 적용시키면 그림자에 대한 perspective camera 를 띄울 수 있게된다. + </p> + <h2> + property 두번째 : mapSize + </h2> + <p> + 렌더링된 그림자들의 테두리를 잘 보면 매끄럽지 않다는 것을 확인할 수 있다. + 이 때 mapsize값을 수정시킴으로써 매끈한 상태, 혹은 더욱 매끄럽지 않은 상태를 만들 수 있다. + 섬세할 수록 연산 속도는 느려지니 적절히 사용하도록 하자. + </p> + <p> + default값은 width,height : 512 이다. + </p> + <p> + <code>light2.shadow.mapSize.width = </code> + </p> + <p> + <code>light2.shadow.mapSize.height = </code> + </p> + <h4>128</h4> + <p> + <canvas id="HelloCanvas5"></canvas> + <script src="pointlightshadow5.js"></script> + </p> + <h4>1024</h4> + <p> + <canvas id="HelloCanvas6"></canvas> + <script src="pointlightshadow6.js"></script> + </p> + <h2> + property 세번째 : radius + </h2> + <p> + 그림자에 blur처리를 할 수 있게된다. blur처리를 통해 원래는 pointlight 특성상 그림자의 경계가 진하게, 뚜렷하게 나타나 어색한 느낌을 받기도 하는데, + 그 느낌을 지워줄 수 있다. + </p> + <p> + default값은 radius : 1이며, 1 이상의 값을 통해 작동한다. + </p> + <p> + <code>light2.shadow.radius = </code> + </p> + <h4> + 20 + </h4> + <p> + <canvas id="HelloCanvas7"></canvas> + <script src="pointlightshadow7.js"></script> + </p> + <h4> + 값을 키워주면 그림자를 통해 생동감을 줄 수 있다. 100으로 값을 바꿔보자 | 색깔은 열정의 색 빨강으로 바꿔보자 :) + </h4> + <p> + <canvas id="HelloCanvas8"></canvas> + <script src="pointlightshadow8.js"></script> + </p> + </body> +</html> -- GitLab