├── README.md ├── docs ├── css │ └── page.css ├── favicons │ ├── apple-touch-icon-120x120-precomposed.png │ ├── apple-touch-icon-152x152-precomposed.png │ ├── favicon-16x16.png │ ├── favicon-180x180.png │ ├── favicon-192x192.png │ ├── favicon-32x32.png │ ├── favicon-48x48.png │ ├── favicon-60x60.png │ └── favicon-96x96.png ├── images │ ├── gear.svg │ ├── noise-dark.png │ ├── noise-light.png │ └── resize.svg ├── index.html ├── readme │ ├── css │ │ └── page.css │ ├── favicons │ │ ├── apple-touch-icon-120x120-precomposed.png │ │ ├── apple-touch-icon-152x152-precomposed.png │ │ ├── favicon-16x16.png │ │ ├── favicon-180x180.png │ │ ├── favicon-192x192.png │ │ ├── favicon-32x32.png │ │ ├── favicon-48x48.png │ │ ├── favicon-60x60.png │ │ └── favicon-96x96.png │ ├── images │ │ ├── noise-dark.png │ │ └── noise-light.png │ ├── index.html │ └── robots.txt ├── resources │ ├── models │ │ ├── cat.glb │ │ ├── chair.glb │ │ ├── chair_feet.glb │ │ ├── dice.glb │ │ ├── sphere.glb │ │ └── torus.glb │ └── textures │ │ ├── chair.png │ │ ├── dark.jpg │ │ ├── dice.png │ │ ├── giraffe.png │ │ ├── noise.png │ │ ├── torus.png │ │ └── white.png ├── robots.txt └── script │ ├── main.min.js │ ├── main.min.js.LICENSE.txt │ └── page.min.js └── src └── readme ├── chair.jpg └── sphere.jpg /README.md: -------------------------------------------------------------------------------- 1 | # fur-threejs 2 | 3 | ## Description 4 | This project is my take on real-time fur rendering. The result is quite good and flexible since it can adapt to any 3D model. A few properties are customizable, such as length, thickness, orientation and color patterns. 5 | 6 | Technically, I implemented the traditional shells and fins technique, adapted for WebGL (which lacks Geometry Shaders unfortunately). 7 | 8 | See it live [here](https://piellardj.github.io/fur-threejs/). 9 | 10 | [![Donate](https://raw.githubusercontent.com/piellardj/piellardj.github.io/master/images/readme/donate-paypal.svg)](https://www.paypal.com/donate/?hosted_button_id=AF7H7GEJTL95E) 11 | 12 | ## Preview 13 | 14 | ![A fur chair](src/readme/chair.jpg) 15 | 16 | ![A fur ball](src/readme/sphere.jpg) 17 | -------------------------------------------------------------------------------- /docs/css/page.css: -------------------------------------------------------------------------------- 1 | body{text-align:center}#error-messages{margin:32px 8px;color:red;font-weight:bold}.demo{display:flex;flex-flow:row wrap;align-items:flex-start;justify-content:center;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none} 2 | .logo{display:block;position:relative;width:64px;height:64px;margin:8px auto 16px;border-radius:50%;user-select:none;box-sizing:border-box}.logo,.logo:hover,.logo:focus,.logo:active{border-width:1px;border-style:solid;border-color:#009688;border-color:var(--var-color-control-accent, #009688)}.logo::before,.logo svg.logo-icon,.logo::after{position:absolute;top:-1px;left:-1px;width:64px;height:64px;border-radius:50%;pointer-events:none}.logo svg.logo-icon{stroke:#009688;stroke:var(--var-color-control-accent, #009688);fill:#009688;fill:var(--var-color-control-accent, #009688)}.logo::before{content:"";transform:scale(0);-webkit-transform:scale(0);-ms-transform:scale(0);transition:.1s ease;-webkit-transition:.1s ease}.logo.logo-animate-fill .logo::before{content:"";transform:scale(0);-webkit-transform:scale(0);-ms-transform:scale(0);transition:.1s ease;-webkit-transition:.1s ease}.logo:hover::before{transform:scale(1);-webkit-transform:scale(1);-ms-transform:scale(1)}.logo.logo-animate-fill{background:#eeeeee;background:var(--var-color-block-background, #eeeeee)}.logo.logo-animate-fill::before{background:#009688;background:var(--var-color-control-accent, #009688)}.logo.logo-animate-fill:hover svg.logo-icon{fill:#fff;stroke:#fff}.logo.logo-animate-empty{background:#009688;background:var(--var-color-control-accent, #009688)}.logo.logo-animate-empty::before{top:0;left:0;width:62px;height:62px;background:#eeeeee;background:var(--var-color-block-background, #eeeeee)} 3 | .intro{margin:auto;padding:16px;border-radius:8px;border:1px solid #c9c9c9;border:var(--var-color-block-border, 1px solid #c9c9c9);background:#eeeeee;background:var(--var-color-block-background, #eeeeee)}.intro h1{margin-top:0;text-align:center}@media only screen and (min-width: 560px){.intro{max-width:512px;border-width:1px}}.description{justify-content:center;line-height:125%;text-align:justify;text-indent:1em}.project-links{display:flex;flex-flow:row;justify-content:space-between;text-indent:0} 4 | a{color:#009688;color:var(--var-color-control-accent, #009688);font-weight:bold;text-decoration:none;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;border-width:0 0 2px;border-style:solid;border-color:rgba(0,0,0,0)}a:focus,a:hover{border-color:#009688;border-color:var(--var-color-control-accent, #009688)} 5 | .canvas-button{width:32px;height:32px;cursor:pointer}#canvas-container{position:relative;margin-bottom:16px;background:#000;overflow:hidden}@media only screen and (min-width: 540px){#canvas-container{margin:16px}}#canvas-container>canvas{width:100%;height:100%;z-index:10}#canvas-container>.loader{display:none}#indicators{display:flex;position:absolute;top:1px;left:1px;flex-direction:column;align-items:flex-start;color:#fff;font-family:"Lucida Console",Monaco,monospace;text-align:left;z-index:20}#indicators>div{flex:0 0 1em;margin:1px;padding:1px 4px;background:#000}#canvas-buttons-column{position:absolute;top:0;right:0;width:32px;z-index:30}#fullscreen-toggle-id{display:block;background-image:url("../images/resize.svg");background-position:0 0;background-size:200%}#fullscreen-toggle-id:hover{background-position-x:100%}#side-pane-toggle-id{display:none;background-image:url("../images/gear.svg");transition:transform .1s ease-in-out;-webkit-transition:transform .1s ease-in-out}#side-pane-toggle-id:hover{transform:rotate(-30deg);-webkit-transform:rotate(-30deg);-ms-transform:rotate(-30deg)}#side-pane-checkbox-id:checked+#canvas-container #side-pane-toggle-id:hover{transform:rotate(30deg);-webkit-transform:rotate(30deg);-ms-transform:rotate(30deg)}.hidden{display:none}#fullscreen-checkbox-id:checked+.demo{position:fixed;overflow:hidden}#fullscreen-checkbox-id:checked+.demo #canvas-container{position:fixed;top:0;left:0;width:100vw;height:100vh;margin:0;overflow:hidden;z-index:5}#fullscreen-checkbox-id:checked+.demo #canvas-container #canvas-buttons-column{transition:transform .2s ease-in-out;-webkit-transition:transform .2s ease-in-out}#fullscreen-checkbox-id:checked+.demo #canvas-container #fullscreen-toggle-id{background-position-y:100%}@media only screen and (min-width: 500px){#fullscreen-checkbox-id:checked+.demo #canvas-container #side-pane-toggle-id{display:block}}#fullscreen-checkbox-id:checked+.demo #side-pane-checkbox-id:checked+#canvas-container #canvas-buttons-column{transform:translateX(-400px)} 6 | .loader{position:absolute;top:0;right:0;bottom:0;left:0;width:120px;height:120px;margin:auto}.loader>span{color:#fff;font-size:32px;line-height:120px;text-shadow:1px 1px #000,-1px 1px #000,1px -1px #000,-1px -1px #000,1px 0 #000,-1px 0 #000,0 1px #000,0 -1px #000}.loader-animation{position:absolute;top:0;left:0;width:120px;height:120px;animation:spin 1.1s linear infinite}.loader-animation:before{position:absolute;top:-1px;left:-1px;width:122px;height:122px;border:6px solid rgba(0,0,0,0);border-top:6px solid #000;border-radius:50%;content:"";z-index:50;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.loader-animation:after{position:absolute;top:0;left:0;width:120px;height:120px;border:4px solid rgba(0,0,0,0);border-top:4px solid #fff;border-radius:50%;content:"";z-index:51;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}} 7 | .canvas-button{width:32px;height:32px;cursor:pointer}.controls-block{flex:1 0 0;max-width:36em;margin:16px 0;padding:12px 0;border-radius:8px;border:1px solid #c9c9c9;border:var(--var-color-block-border, 1px solid #c9c9c9);background:#eeeeee;background:var(--var-color-block-background, #eeeeee);z-index:0}@media only screen and (min-width: 540px){.controls-block{margin:16px}}.controls-block>hr{margin:12px 0;clear:both;border:none;border-top:1px solid #c9c9c9;border-top:var(--var-color-block-border, 1px solid #c9c9c9)}.controls-section{display:flex;flex-flow:row wrap;align-items:baseline;margin:0 16px}.controls-section>h2{width:7em;margin:0;font-size:medium;font-weight:bold;line-height:2em;text-align:left}.controls-section>.controls-list{display:flex;flex-direction:column;flex-grow:1}.controls-list>.control{display:flex;flex-flow:row wrap;align-items:center;min-width:300px;padding:3px 0}.control>label{min-width:8em;font-size:95%;line-height:95%;text-align:left}#fullscreen-checkbox-id:checked+.demo #side-pane-checkbox-id~.controls-block{position:fixed;top:0;left:100%;width:400px;max-height:calc(100% - 48px);margin:0;border-width:0 0 1px 1px;border-radius:0 0 0 8px;z-index:50;overflow-x:hidden;overflow-y:auto;transition:transform .2s ease-in-out;-webkit-transition:transform .2s ease-in-out}#fullscreen-checkbox-id:checked+.demo #side-pane-checkbox-id~.controls-block::-webkit-scrollbar{width:16px}#fullscreen-checkbox-id:checked+.demo #side-pane-checkbox-id~.controls-block::-webkit-scrollbar-track{border-radius:8px;background-color:#eeeeee;background-color:var(--var-color-block-background, #eeeeee)}#fullscreen-checkbox-id:checked+.demo #side-pane-checkbox-id~.controls-block::-webkit-scrollbar-thumb{border-width:3px 5px;border-style:solid;border-radius:8px;border-color:#eeeeee;border-color:var(--var-color-block-background, #eeeeee);background-color:#a5a5a5;background-color:var(--var-color-scrollbar, #a5a5a5)}#fullscreen-checkbox-id:checked+.demo #side-pane-checkbox-id~.controls-block::-webkit-scrollbar-thumb:focus,#fullscreen-checkbox-id:checked+.demo #side-pane-checkbox-id~.controls-block::-webkit-scrollbar-thumb:hover{background-color:#b2b2b2;background-color:var(--var-color-scrollbar-hover, #b2b2b2)}#fullscreen-checkbox-id:checked+.demo #side-pane-checkbox-id~.controls-block::-webkit-scrollbar-thumb:active{background-color:#959595;background-color:var(--var-color-scrollbar-active, #959595)}#fullscreen-checkbox-id:checked+.demo #side-pane-checkbox-id~.controls-block:hover::-webkit-scrollbar-thumb{border-width:3px}#fullscreen-checkbox-id:checked+.demo #side-pane-checkbox-id:checked~.controls-block{transform:translateX(-100%);-webkit-transform:translateX(-100%);-ms-transform:translateX(-100%)}#fullscreen-checkbox-id:checked+.demo #side-pane-checkbox-id:checked~.controls-block .tooltip{transform:translateX(-100vw) translateX(400px);-webkit-transform:translateX(-100vw) translateX(400px);-ms-transform:translateX(-100vw) translateX(400px)}#fullscreen-checkbox-id:checked+.demo #side-pane-checkbox-id:checked~.controls-block>#side-pane-close-toggle-id{display:block}#side-pane-close-toggle-id{display:none;position:absolute;top:0;right:0}#side-pane-close-toggle-id svg{stroke:#5e5e5e;stroke:var(--var-color-block-actionitem, #5e5e5e)}#side-pane-close-toggle-id svg:focus,#side-pane-close-toggle-id svg:hover{stroke:#7e7e7e;stroke:var(--var-color-block-actionitem-hover, #7e7e7e)}#side-pane-close-toggle-id svg:active{stroke:#535353;stroke:var(--var-color-block-actionitem-active, #535353)} 8 | .tabs{display:flex;position:relative;flex-flow:row wrap;flex-grow:1;width:auto;border-radius:4px;background:none;overflow:hidden}.tabs::after{position:absolute;top:0;left:0;width:100%;height:100%;border-width:2px;border-style:solid;border-color:#c9c9c9;border-color:var(--var-color-control-neutral, #c9c9c9);border-radius:4px;content:"";z-index:1;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.tabs.compact>input+label{padding:6px 14px;font-size:75%}.tabs>input{position:absolute;top:0;left:0;width:1px;height:1px;opacity:0}.tabs>input+label{flex:1;padding:8px 14px;font-size:87.5%;font-weight:bold;text-align:center;white-space:nowrap;cursor:pointer;z-index:2}.tabs>input:disabled+label,.tabs>input[type=radio]:checked+label{cursor:default}.tabs>input+label{background:none;color:#009688;color:var(--var-color-control-accent, #009688)}.tabs>input:checked+label{background:#009688;background:var(--var-color-control-accent, #009688);color:#fff}.tabs>input:disabled+label{background:none;color:#a5a5a5}.tabs>input:disabled:checked+label{background:#a5a5a5;color:#fff}.tabs>input[type=checkbox]:not(:disabled):hover+label,.tabs>input[type=checkbox]:not(:disabled):focus+label{background:rgba(0,150,136,.05)}.tabs>input[type=checkbox]:not(:disabled):hover:checked+label,.tabs>input[type=checkbox]:not(:disabled):focus:checked+label{background:#26a69a;background:var(--var-color-control-accent-hover, #26a69a)}.tabs>input[type=checkbox]:not(:disabled):active+label{background:rgba(0,150,136,.1)}.tabs>input[type=checkbox]:not(:disabled):active:checked+label{background:#00897b;background:var(--var-color-control-accent-active, #00897b)}.tabs>input[type=radio]:not(:disabled):not(:checked):hover+label,.tabs>input[type=radio]:not(:disabled):not(:checked):focus+label{background:rgba(0,150,136,.05)}.tabs>input[type=radio]:not(:disabled):not(:checked):active+label{background:rgba(0,150,136,.1)} 9 | .checkbox{display:block;position:relative;text-align:left;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.checkbox>input[type=checkbox]{width:1px;height:1px;opacity:0}.checkbox>input[type=checkbox]+label.checkmark,.checkbox>input[type=checkbox]+label.checkmark-line{margin-left:24px;line-height:26px;cursor:pointer}.checkbox>input[type=checkbox]:disabled+label.checkmark,.checkbox>input[type=checkbox]:disabled+label.checkmark-line{cursor:default}.checkbox>input[type=checkbox]+label.checkmark::before{position:absolute;top:calc(.5*(100% - 20px));left:0;width:20px;height:20px;border-width:2px;border-style:solid;border-radius:2px;background:none;content:"";box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.checkbox>input[type=checkbox]+label.checkmark::after{position:absolute;top:calc(.5*(100% - 20px) + .5*(20px - 14px));right:0;bottom:0;left:6.5px;width:7px;height:14px;border:solid #fff;border-width:0 3px 3px 0;background:none;content:"";box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;transform:translate(0, -1px) scale(0) rotate(45deg);-webkit-transform:translate(0, -1px) scale(0) rotate(45deg);-ms-transform:translate(0, -1px) scale(0) rotate(45deg)}.checkbox>input[type=checkbox]:checked+label.checkmark::after{transform:translate(0, -1px) scale(1) rotate(45deg);-webkit-transform:translate(0, -1px) scale(1) rotate(45deg);-ms-transform:translate(0, -1px) scale(1) rotate(45deg)}.checkbox>input[type=checkbox]+label.checkmark::before{border-color:#009688;border-color:var(--var-color-control-accent, #009688)}.checkbox>input[type=checkbox]:checked+label.checkmark::before{background:#009688;background:var(--var-color-control-accent, #009688)}.checkbox>input[type=checkbox]:hover+label.checkmark::before,.checkbox>input[type=checkbox]:focus+label.checkmark::before{border-color:#26a69a;border-color:var(--var-color-control-accent-hover, #26a69a)}.checkbox>input[type=checkbox]:hover:checked+label.checkmark::before,.checkbox>input[type=checkbox]:focus:checked+label.checkmark::before{background:#26a69a;background:var(--var-color-control-accent-hover, #26a69a)}.checkbox>input[type=checkbox]:active+label.checkmark::before{border-color:#00897b;border-color:var(--var-color-control-accent-active, #00897b)}.checkbox>input[type=checkbox]:active:checked+label.checkmark::before{background:#00897b;background:var(--var-color-control-accent-active, #00897b)}.checkbox>input[type=checkbox]:disabled+label.checkmark::before{border-color:#a5a5a5}.checkbox>input[type=checkbox]:disabled:checked+label.checkmark::before{background:#a5a5a5} 10 | .color-picker-container{position:relative}.color-picker{display:flex;flex-flow:row;align-items:center;cursor:pointer}.color-preview{width:32px;height:32px;margin-right:12px;border-width:2px;border-style:solid;border-color:#c9c9c9;border-color:var(--var-color-control-neutral, #c9c9c9);border-radius:50%;line-height:32px;box-sizing:border-box}.color-picker.compact .color-preview{width:26px;height:26px;line-height:26px}.color-picker:hover .color-preview,.color-picker:focus .color-preview{border-color:#26a69a;border-color:var(--var-color-control-accent-hover, #26a69a)}.color-picker:active .color-preview{border-color:#00897b;border-color:var(--var-color-control-accent-active, #00897b)}.color-value{text-transform:uppercase}.color-picker-popup{display:flex;position:absolute;top:0;left:0;flex-flow:column nowrap;min-width:275px;min-height:300px;text-align:left;white-space:nowrap;z-index:100}.color-picker-popup .picker .cursor{position:absolute;transform:translate(-50%, -50%);border:2px solid #fff;cursor:pointer}.color-picker-popup .value-saturation-picker{flex:1;min-height:180px}.color-picker-popup .value-saturation-picker .color-filter{position:absolute;top:0;left:0;width:100%;height:100%}.color-picker-popup .value-saturation-picker .cursor{top:0;left:0;width:16px;height:16px;border-radius:50%}.color-picker-popup .hue-picker{height:28px}.color-picker-popup .hue-picker .hue-bar{position:absolute;top:calc(50% - 5px);left:0;width:100%;height:10px;border-radius:5px;background:linear-gradient(to right, hsl(0, 100%, 50%), hsl(60, 100%, 50%), hsl(120, 100%, 50%), hsl(180, 100%, 50%), hsl(240, 100%, 50%), hsl(300, 100%, 50%), hsl(0, 100%, 50%))}.color-picker-popup .hue-picker .cursor{top:50%;left:0;width:10px;height:28px;border-radius:6px}.color-picker-popup .preview-block{display:flex;flex-flow:row nowrap}.color-picker-popup .preview-block .preview-color{flex:0 0 50px;width:50px;min-height:50px;background:green}.color-picker-popup .preview-block tr{height:28px}.color-picker-popup .preview-block input[type=text]{margin:0 0 0 4px;padding:3px 2px;border-width:1px;border-style:solid;border-radius:4px;background:none;color:inherit;font-size:inherit;border-color:#c9c9c9;border-color:var(--var-color-control-neutral, #c9c9c9)}.color-picker-popup .preview-block input[type=text]:invalid{border-color:red;outline:red solid}.color-picker-popup .outlined{border-width:1px;border-style:solid;border-color:#c9c9c9;border-color:var(--var-color-control-neutral, #c9c9c9);border-radius:4px}.popup{padding:7px;background:#fff;background:var(--var-color-theme, white);border:1px solid #c9c9c9;border:var(--var-color-block-border, 1px solid #c9c9c9);border-radius:8px;box-shadow:0 0 10px rgba(50,50,50,.6)}.popup .block{position:relative;margin:7px} 11 | .range-container{display:inline-block;position:relative;flex:1 1 0%;width:100%;min-width:15px;height:26px}.range-container input[type=range]{width:100%;min-width:128px;height:100%;margin:0;padding:0;opacity:0}.range-container input[type=range]:not(:disabled){cursor:pointer}.range-container .range-skin-container{display:flex;position:absolute;top:0;left:0;flex-flow:nowrap;width:100%;height:100%;pointer-events:none;user-select:none}.range-container .range-stub{position:relative;flex-grow:0;flex-shrink:0;width:7px}.range-container .range-progress{display:flex;flex:1;flex-flow:row nowrap}.range-container .range-progress-left{position:relative;flex-grow:0;flex-shrink:0;width:85%}.range-container .range-progress-right{position:relative;flex-grow:1}.range-container .range-bar{position:absolute;left:0;width:100%;z-index:0}.range-container .range-bar.range-bar-left{top:12px;height:3px}.range-container .range-bar.range-bar-right{top:12px;height:3px;background:#c9c9c9;background:var(--var-color-control-neutral, #c9c9c9)}.range-container .range-bar.range-stub-left{border-radius:3px 0 0 3px}.range-container .range-bar.range-stub-right{border-radius:0 3px 3px 0}.range-container .range-handle{position:absolute;top:5.5px;right:-7.5px;width:15px;height:15px;border-radius:50%;z-index:1}.range-container .range-bar-left,.range-container .range-handle{background:#009688;background:var(--var-color-control-accent, #009688)}.range-container input[type=range]:not(:disabled):hover+.range-skin-container .range-handle,.range-container input[type=range]:not(:disabled):focus+.range-skin-container .range-handle{background:#26a69a;background:var(--var-color-control-accent-hover, #26a69a)}.range-container input[type=range]:not(:disabled):active+.range-skin-container .range-handle{background:#00897b;background:var(--var-color-control-accent-active, #00897b)}.range-container input[type=range]:disabled+.range-skin-container .range-bar-left,.range-container input[type=range]:disabled+.range-skin-container .range-handle{background:#a5a5a5}.range-container .range-tooltip{position:absolute;top:-28px;right:0;min-width:24px;padding:4px;transform:translateX(50%);transition:opacity .1s ease-in-out;border-radius:4px;background:#535353;color:#eee;font-size:87.5%;text-align:center;opacity:0;z-index:2}.range-container input[type=range]:hover+.range-skin-container .range-tooltip,.range-container input[type=range]:active+.range-skin-container .range-tooltip,.range-container input[type=range]:focus+.range-skin-container .range-tooltip{opacity:1}.range-container .range-tooltip::after{position:absolute;top:100%;left:50%;width:0px;height:12px;margin-left:-6px;border-width:6px;border-style:solid;border-color:#535353 rgba(0,0,0,0) rgba(0,0,0,0);content:""} 12 | .select-container{display:inline-block;position:relative;text-align:left;user-select:none}.select-container .select-value,.select-container .select-current-value{padding:0 12px;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.select-container .select-current-value{padding-right:24px;border-width:2px;border-style:solid;border-color:#c9c9c9;border-color:var(--var-color-control-neutral, #c9c9c9);border-radius:4px;font-size:87.5%;font-weight:bold;line-height:28px}.select-container .select-current-value::after{position:absolute;top:13px;right:10px;width:0;height:0;border-width:7px;border-style:solid;border-color:rgba(0,0,0,0);content:"";border-top-color:#009688;border-top-color:var(--var-color-control-accent, #009688)}.select-container.expanded .select-current-value{border-radius:4px 4px 0 0;border-color:#26a69a;border-color:var(--var-color-control-accent-hover, #26a69a);border-bottom-color:#c9c9c9;border-bottom-color:var(--var-color-control-neutral, #c9c9c9)}.select-container.expanded .select-current-value::after{top:5px;border-color:rgba(0,0,0,0);border-bottom-color:#26a69a;border-bottom-color:var(--var-color-control-accent-hover, #26a69a)}.select-container.compact .select-current-value{font-size:75%;line-height:22px}.select-container.compact .select-current-value::after{top:10px}.select-container.compact.expanded .select-current-value::after{top:2px}.select-container:not(.expanded) .select-current-value{cursor:pointer}.select-container:not(.expanded):hover .select-current-value{border-color:#26a69a;border-color:var(--var-color-control-accent-hover, #26a69a)}.select-container:not(.expanded):hover .select-current-value::after{border-top-color:#26a69a;border-top-color:var(--var-color-control-accent-hover, #26a69a)}.select-container:not(.expanded):active .select-current-value{border-color:#00897b;border-color:var(--var-color-control-accent-active, #00897b)}.select-container:not(.expanded):active .select-current-value::after{border-top-color:#00897b;border-top-color:var(--var-color-control-accent-active, #00897b)}.select-container .select-values-list{display:none;position:absolute;top:100%;left:0;width:100%;border-width:0 2px 2px;border-style:solid;border-color:#26a69a;border-color:var(--var-color-control-accent-hover, #26a69a);border-radius:0 0 4px 4px;font-size:87.5%;line-height:32px;box-shadow:0 10px 16px rgba(0,0,0,.2);z-index:3;box-sizing:border-box;background:#fff;background:var(--var-color-theme, white)}.select-container .select-values-list::before{position:absolute;top:-4px;left:-2px;width:100%;height:6px;border-width:0 2px;border-style:solid;content:"";border-color:#26a69a;border-color:var(--var-color-control-accent-hover, #26a69a)}.select-container.expanded .select-values-list{display:block}.select-container.expanded .select-values-list .select-value{cursor:pointer}.select-container.expanded .select-values-list .select-value:hover{background:rgba(0,150,136,.1)} 13 | :root{--var-color-theme:white;--var-color-page-background:#ededed;--var-page-background-image:url("../images/noise-light.png");--var-color-block-background:#eeeeee;--var-color-block-border:1px solid #c9c9c9;--var-color-title:#535353;--var-color-text:#676767;--var-color-block-actionitem:#5e5e5e;--var-color-block-actionitem-hover:#7e7e7e;--var-color-block-actionitem-active:#535353;--var-color-scrollbar:#a5a5a5;--var-color-scrollbar-hover:#b2b2b2;--var-color-scrollbar-active:#959595;--var-color-control-neutral:#c9c9c9;--var-color-control-accent:#009688;--var-color-control-accent-hover:#26a69a;--var-color-control-accent-active:#00897b}@media(prefers-color-scheme: dark){:root{--var-color-theme:black;--var-color-page-background:#232323;--var-page-background-image:url("../images/noise-dark.png");--var-color-block-background:#202020;--var-color-block-border:1px solid #535353;--var-color-title:#eeeeee;--var-color-text:#dbdbdb;--var-color-block-actionitem:#dbdbdb;--var-color-block-actionitem-hover:#eeeeee;--var-color-block-actionitem-active:#c9c9c9;--var-color-scrollbar:#7e7e7e;--var-color-scrollbar-hover:#959595;--var-color-scrollbar-active:#676767;--var-color-control-neutral:#5e5e5e;--var-color-control-accent:#26a69a;--var-color-control-accent-hover:#4db6ac;--var-color-control-accent-active:#009688}}:root{color-scheme:light dark}html{display:flex;min-height:100%;font-family:Arial,Helvetica,sans-serif}body{display:flex;flex:1;flex-direction:column;min-height:100vh;margin:0px;background-attachment:fixed;background:#ededed;background:var(--var-color-page-background, #ededed);background-image:url("../images/noise-light.png");background-image:var(--var-page-background-image, url("../images/noise-light.png"));color:#676767;color:var(--var-color-text, #676767)}main{display:block;flex-grow:1;padding-bottom:32px}h1,h2,h3{color:#535353;color:var(--var-color-title, #535353)} 14 | .badge{width:32px;height:32px;margin:8px 12px;border:none}.badge>svg{width:32px;height:32px}.badge,.badge:hover,.badge:focus,.badge:active{border:none}.badge svg{fill:#5e5e5e;fill:var(--var-color-block-actionitem, #5e5e5e)}.badge svg:focus,.badge svg:hover{fill:#7e7e7e;fill:var(--var-color-block-actionitem-hover, #7e7e7e)}.badge svg:active{fill:#535353;fill:var(--var-color-block-actionitem-active, #535353)}.badge-shelf{display:flex;flex-flow:row;justify-content:center}footer{align-items:center;padding:8px;text-align:center;border-top:1px solid #c9c9c9;border-top:var(--var-color-block-border, 1px solid #c9c9c9);background:#eeeeee;background:var(--var-color-block-background, #eeeeee)} 15 | -------------------------------------------------------------------------------- /docs/favicons/apple-touch-icon-120x120-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/favicons/apple-touch-icon-120x120-precomposed.png -------------------------------------------------------------------------------- /docs/favicons/apple-touch-icon-152x152-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/favicons/apple-touch-icon-152x152-precomposed.png -------------------------------------------------------------------------------- /docs/favicons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/favicons/favicon-16x16.png -------------------------------------------------------------------------------- /docs/favicons/favicon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/favicons/favicon-180x180.png -------------------------------------------------------------------------------- /docs/favicons/favicon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/favicons/favicon-192x192.png -------------------------------------------------------------------------------- /docs/favicons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/favicons/favicon-32x32.png -------------------------------------------------------------------------------- /docs/favicons/favicon-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/favicons/favicon-48x48.png -------------------------------------------------------------------------------- /docs/favicons/favicon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/favicons/favicon-60x60.png -------------------------------------------------------------------------------- /docs/favicons/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/favicons/favicon-96x96.png -------------------------------------------------------------------------------- /docs/images/gear.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /docs/images/noise-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/images/noise-dark.png -------------------------------------------------------------------------------- /docs/images/noise-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/images/noise-light.png -------------------------------------------------------------------------------- /docs/images/resize.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Fur 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 31 |
32 |
33 |
34 |

Fur

35 | 36 |
37 |

This project is my take on real-time fur rendering. The result is flexible and can adapt to any 3D model. A few properties are customizable, such as length, thickness, orientation and color patterns.

38 |

Technically, I implemented the traditional shells and fins technique, adapted for WebGL.

39 | 40 |
41 | 42 | 45 |
46 |
47 |
48 | 51 |
52 | 53 | 54 |
55 | 56 |
57 | 58 |
59 | 60 |
61 |
62 |
63 |
64 | FPS: 65 |
66 |
67 |
68 | 69 | 70 |
71 |
72 |
73 | 79 |
80 |

Scene

81 | 82 |
83 |
84 | 85 |
86 | 87 | 88 | 89 | 90 |
91 |
92 |
93 | 94 |
95 | 96 | 97 |
98 |
99 |
100 |
101 |
102 |
103 |

Fur

104 | 105 |
106 |
107 | 108 |
109 | 110 | 111 | 112 | 113 |
114 |
115 |
116 | 117 | 118 |
119 |
120 |
 
121 | #FFFFFF 122 |
123 |
124 |
125 |
126 | 127 |
128 | 129 |
130 |
131 | 132 |
133 |
134 |
135 | 136 | 137 | 138 |
139 |
140 | 141 |
142 |
143 |
144 | 145 |
146 |
147 |
148 |
149 |
150 | 151 |
152 | 153 |
154 |
155 | 156 |
157 |
158 |
159 | 160 | 161 | 162 |
163 |
164 | 165 |
166 |
167 |
168 | 169 |
170 |
171 |
172 |
173 |
174 | 175 |
176 | 177 |
178 |
179 | 180 |
181 |
182 |
183 | 184 | 185 | 186 |
187 |
188 | 189 |
190 |
191 |
192 | 193 |
194 |
195 |
196 |
197 |
198 | 199 |
200 | 201 |
202 |
203 | 204 |
205 |
206 |
207 | 208 | 209 | 210 |
211 |
212 | 213 |
214 |
215 |
216 | 217 |
218 |
219 |
220 |
221 |
222 | 223 |
224 | 225 |
226 |
227 | 228 |
229 |
230 |
231 | 232 | 233 | 234 |
235 |
236 | 237 |
238 |
239 |
240 | 241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |

Shells & Fins

250 | 251 |
252 |
253 | 254 |
255 |
Full
256 |
257 |
Full
258 |
Shells only
259 |
Fins only
260 |
Nothing
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 | 270 | 293 | 300 | 301 | 302 | 303 | 304 | -------------------------------------------------------------------------------- /docs/readme/css/page.css: -------------------------------------------------------------------------------- 1 | a{color:#009688;color:var(--var-color-control-accent, #009688);font-weight:bold;text-decoration:none;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;border-width:0 0 2px;border-style:solid;border-color:rgba(0,0,0,0)}a:focus,a:hover{border-color:#009688;border-color:var(--var-color-control-accent, #009688)}:root{--color-code: #e0e0e0}@media(prefers-color-scheme: dark){:root{--color-code: #343434}}body{max-width:100%}.contents{line-height:1.5em;max-width:900px;margin:auto;padding:16px 32px;border-radius:8px;border:1px solid #c9c9c9;border:var(--var-color-block-border, 1px solid #c9c9c9);background:#eeeeee;background:var(--var-color-block-background, #eeeeee)}h1{text-align:center;margin-bottom:1em}pre{overflow-x:auto;background:var(--color-code);padding:4px 16px;border-radius:8px;line-height:1.45}pre::-webkit-scrollbar{width:16px}pre::-webkit-scrollbar-track{background-color:rgba(0,0,0,0)}pre::-webkit-scrollbar-thumb{border-width:6px;border-style:solid;border-radius:8px;border-color:var(--color-code);background-color:#a5a5a5;background-color:var(--var-color-scrollbar, #a5a5a5)}pre::-webkit-scrollbar-thumb:focus,pre::-webkit-scrollbar-thumb:hover{background-color:#b2b2b2;background-color:var(--var-color-scrollbar-hover, #b2b2b2)}pre::-webkit-scrollbar-thumb:active{background-color:#959595;background-color:var(--var-color-scrollbar-active, #959595)}pre:hover::-webkit-scrollbar-thumb{border-width:5px}pre code{padding:0}code{background:var(--color-code);padding:2px 4px;border-radius:3px;font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;line-height:1.5em}video,img{max-width:100%;border-radius:8px} 2 | .logo{display:block;position:relative;width:64px;height:64px;margin:8px auto 16px;border-radius:50%;user-select:none;box-sizing:border-box}.logo,.logo:hover,.logo:focus,.logo:active{border-width:1px;border-style:solid;border-color:#009688;border-color:var(--var-color-control-accent, #009688)}.logo::before,.logo svg.logo-icon,.logo::after{position:absolute;top:-1px;left:-1px;width:64px;height:64px;border-radius:50%;pointer-events:none}.logo svg.logo-icon{stroke:#009688;stroke:var(--var-color-control-accent, #009688);fill:#009688;fill:var(--var-color-control-accent, #009688)}.logo::before{content:"";transform:scale(0);-webkit-transform:scale(0);-ms-transform:scale(0);transition:.1s ease;-webkit-transition:.1s ease}.logo.logo-animate-fill .logo::before{content:"";transform:scale(0);-webkit-transform:scale(0);-ms-transform:scale(0);transition:.1s ease;-webkit-transition:.1s ease}.logo:hover::before{transform:scale(1);-webkit-transform:scale(1);-ms-transform:scale(1)}.logo.logo-animate-fill{background:#eeeeee;background:var(--var-color-block-background, #eeeeee)}.logo.logo-animate-fill::before{background:#009688;background:var(--var-color-control-accent, #009688)}.logo.logo-animate-fill:hover svg.logo-icon{fill:#fff;stroke:#fff}.logo.logo-animate-empty{background:#009688;background:var(--var-color-control-accent, #009688)}.logo.logo-animate-empty::before{top:0;left:0;width:62px;height:62px;background:#eeeeee;background:var(--var-color-block-background, #eeeeee)} 3 | :root{--var-color-theme:white;--var-color-page-background:#ededed;--var-page-background-image:url("../images/noise-light.png");--var-color-block-background:#eeeeee;--var-color-block-border:1px solid #c9c9c9;--var-color-title:#535353;--var-color-text:#676767;--var-color-block-actionitem:#5e5e5e;--var-color-block-actionitem-hover:#7e7e7e;--var-color-block-actionitem-active:#535353;--var-color-scrollbar:#a5a5a5;--var-color-scrollbar-hover:#b2b2b2;--var-color-scrollbar-active:#959595;--var-color-control-neutral:#c9c9c9;--var-color-control-accent:#009688;--var-color-control-accent-hover:#26a69a;--var-color-control-accent-active:#00897b}@media(prefers-color-scheme: dark){:root{--var-color-theme:black;--var-color-page-background:#232323;--var-page-background-image:url("../images/noise-dark.png");--var-color-block-background:#202020;--var-color-block-border:1px solid #535353;--var-color-title:#eeeeee;--var-color-text:#dbdbdb;--var-color-block-actionitem:#dbdbdb;--var-color-block-actionitem-hover:#eeeeee;--var-color-block-actionitem-active:#c9c9c9;--var-color-scrollbar:#7e7e7e;--var-color-scrollbar-hover:#959595;--var-color-scrollbar-active:#676767;--var-color-control-neutral:#5e5e5e;--var-color-control-accent:#26a69a;--var-color-control-accent-hover:#4db6ac;--var-color-control-accent-active:#009688}}:root{color-scheme:light dark}html{display:flex;min-height:100%;font-family:Arial,Helvetica,sans-serif}body{display:flex;flex:1;flex-direction:column;min-height:100vh;margin:0px;background-attachment:fixed;background:#ededed;background:var(--var-color-page-background, #ededed);background-image:url("../images/noise-light.png");background-image:var(--var-page-background-image, url("../images/noise-light.png"));color:#676767;color:var(--var-color-text, #676767)}main{display:block;flex-grow:1;padding-bottom:32px}h1,h2,h3{color:#535353;color:var(--var-color-title, #535353)} 4 | .badge{width:32px;height:32px;margin:8px 12px;border:none}.badge>svg{width:32px;height:32px}.badge,.badge:hover,.badge:focus,.badge:active{border:none}.badge svg{fill:#5e5e5e;fill:var(--var-color-block-actionitem, #5e5e5e)}.badge svg:focus,.badge svg:hover{fill:#7e7e7e;fill:var(--var-color-block-actionitem-hover, #7e7e7e)}.badge svg:active{fill:#535353;fill:var(--var-color-block-actionitem-active, #535353)}.badge-shelf{display:flex;flex-flow:row;justify-content:center}footer{align-items:center;padding:8px;text-align:center;border-top:1px solid #c9c9c9;border-top:var(--var-color-block-border, 1px solid #c9c9c9);background:#eeeeee;background:var(--var-color-block-background, #eeeeee)} 5 | -------------------------------------------------------------------------------- /docs/readme/favicons/apple-touch-icon-120x120-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/readme/favicons/apple-touch-icon-120x120-precomposed.png -------------------------------------------------------------------------------- /docs/readme/favicons/apple-touch-icon-152x152-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/readme/favicons/apple-touch-icon-152x152-precomposed.png -------------------------------------------------------------------------------- /docs/readme/favicons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/readme/favicons/favicon-16x16.png -------------------------------------------------------------------------------- /docs/readme/favicons/favicon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/readme/favicons/favicon-180x180.png -------------------------------------------------------------------------------- /docs/readme/favicons/favicon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/readme/favicons/favicon-192x192.png -------------------------------------------------------------------------------- /docs/readme/favicons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/readme/favicons/favicon-32x32.png -------------------------------------------------------------------------------- /docs/readme/favicons/favicon-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/readme/favicons/favicon-48x48.png -------------------------------------------------------------------------------- /docs/readme/favicons/favicon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/readme/favicons/favicon-60x60.png -------------------------------------------------------------------------------- /docs/readme/favicons/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/readme/favicons/favicon-96x96.png -------------------------------------------------------------------------------- /docs/readme/images/noise-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/readme/images/noise-dark.png -------------------------------------------------------------------------------- /docs/readme/images/noise-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/readme/images/noise-light.png -------------------------------------------------------------------------------- /docs/readme/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Fur - Explanations 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 31 |
32 |
33 |
34 |

fur-threejs

35 |

Description

36 |

This project is my take on real-time fur rendering. The result is quite good and flexible since it can adapt to any 3D model. A few properties are customizable, such as length, thickness, orientation and color patterns.

37 |

Technically, I implemented the traditional shells and fins technique, adapted for WebGL (which lacks Geometry Shaders unfortunately).

38 |

See it live here.

39 |

Donate

40 |

Preview

41 |

A fur chair

42 |

A fur ball

43 |
44 |
45 | 46 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /docs/readme/robots.txt: -------------------------------------------------------------------------------- 1 | User-Agent: GPTBot 2 | Disallow: / -------------------------------------------------------------------------------- /docs/resources/models/cat.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/resources/models/cat.glb -------------------------------------------------------------------------------- /docs/resources/models/chair.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/resources/models/chair.glb -------------------------------------------------------------------------------- /docs/resources/models/chair_feet.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/resources/models/chair_feet.glb -------------------------------------------------------------------------------- /docs/resources/models/dice.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/resources/models/dice.glb -------------------------------------------------------------------------------- /docs/resources/models/sphere.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/resources/models/sphere.glb -------------------------------------------------------------------------------- /docs/resources/models/torus.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/resources/models/torus.glb -------------------------------------------------------------------------------- /docs/resources/textures/chair.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/resources/textures/chair.png -------------------------------------------------------------------------------- /docs/resources/textures/dark.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/resources/textures/dark.jpg -------------------------------------------------------------------------------- /docs/resources/textures/dice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/resources/textures/dice.png -------------------------------------------------------------------------------- /docs/resources/textures/giraffe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/resources/textures/giraffe.png -------------------------------------------------------------------------------- /docs/resources/textures/noise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/resources/textures/noise.png -------------------------------------------------------------------------------- /docs/resources/textures/torus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/resources/textures/torus.png -------------------------------------------------------------------------------- /docs/resources/textures/white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piellardj/fur-threejs/d7230990d10c333c044f617b99c2b845a6f15a9a/docs/resources/textures/white.png -------------------------------------------------------------------------------- /docs/robots.txt: -------------------------------------------------------------------------------- 1 | User-Agent: GPTBot 2 | Disallow: / -------------------------------------------------------------------------------- /docs/script/main.min.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2010-2024 Three.js Authors 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | -------------------------------------------------------------------------------- /docs/script/page.min.js: -------------------------------------------------------------------------------- 1 | var Page;!function(e){var e=e.Demopage||(e.Demopage={}),r="error-messages",t=document.getElementById(r);if(!t)throw new Error("Cannot find element '"+r+"'.");function a(e){return t?t.querySelector("span[id=error-message-"+e+"]"):null}e.setErrorMessage=function(e,r){var n;t&&((n=a(e))?n.innerHTML=r:((n=document.createElement("span")).id="error-message-"+e,n.innerText=r,t.appendChild(n),t.appendChild(document.createElement("br"))))},e.removeErrorMessage=function(e){var r;t&&(e=a(e))&&((r=e.nextElementSibling)&&t.removeChild(r),t.removeChild(e))}}(Page=Page||{}); 2 | var Page;!function(n){var e,t,i,a;function s(e){this.queryParameters={};var t=e.indexOf(s.queryDelimiter);if(t<0)this.baseUrl=e;else{this.baseUrl=e.substring(0,t);for(var r=0,n=e.substring(t+s.queryDelimiter.length).split(s.parameterDelimiter);re.length&&(i=this.queryParameters[a],t(a.substring(e.length),i))}},s.prototype.buildUrl=function(){for(var e=[],t=0,r=Object.keys(this.queryParameters);t input[type=checkbox][id]").map(function(e){return new r(e)})}),n=new e.Helpers.Storage("checkbox",function(e){return e.checked?"true":"false"},function(e,t){e=c.getByIdSafe(e);return!(!e||"true"!==t&&"false"!==t||(e.checked="true"===t,e.callObservers(),0))}),e.Helpers.Events.callAfterDOMLoaded(function(){c.load(),n.applyStoredState()}),t.addObserver=function(e,t){c.getById(e).observers.push(t)},t.setChecked=function(e,t){c.getById(e).checked=t},t.isChecked=function(e){return c.getById(e).checked},t.storeState=function(e){e=c.getById(e),n.storeState(e)},t.clearStoredState=function(e){e=c.getById(e),n.clearStoredState(e)}}(Page=Page||{}); 6 | var Page;!function(d){var a,e,t=d.ColorPicker||(d.ColorPicker={});function u(e,t,n){return Math.max(t,Math.min(n,e))}function l(e,t,n){return u(Math.round(e),t,n)}function s(e,t){return(e%t+t)%t}function n(e){e=e.toString(16).toUpperCase();return 2===e.length?e:"0"+e}(e=a=a||{}).parseHexa=function(e){return/^#[0-9a-fA-F]{6}$/.test(e)?e.toUpperCase():null},e.hsvToRgb=function(e){var t=e.h/60,n=e.s*e.v,r=n*(1-Math.abs(s(t,2)-1)),t=t<=1?{r:n,g:r,b:0}:t<=2?{r:r,g:n,b:0}:t<=3?{r:0,g:n,b:r}:t<=4?{r:0,g:r,b:n}:t<=5?{r:r,g:0,b:n}:{r:n,g:0,b:r},r=e.v-n;return t.r=l(255*(t.r+r),0,255),t.g=l(255*(t.g+r),0,255),t.b=l(255*(t.b+r),0,255),t},e.rgbToHsv=function(e){var t=e.r/255,n=e.g/255,e=e.b/255,r=Math.max(t,n,e),i=r-Math.min(t,n,e),o={h:0,s:0,v:r};return 0!=i&&(r===t?o.h=(n-e)/i%6*60:r===n?o.h=60*((e-t)/i+2):r===e&&(o.h=60*((t-n)/i+4))),0!==r&&(o.s=i/r),o.h=s(o.h,360),o},e.rgbToHex=function(e){return"#"+n(e.r)+n(e.g)+n(e.b)},e.hexToRgb=function(e){return{r:parseInt(e.substring(1,3),16),g:parseInt(e.substring(3,5),16),b:parseInt(e.substring(5,7),16)}},Object.defineProperty(i.prototype,"value",{get:function(){var e=this.element.dataset.currentColor;if(e)return e;throw new Error("No current color on ColorPicker '".concat(this.id,"'."))},set:function(e){if(this.value!==e){this.element.dataset.currentColor=e,this.updateVisiblePart();for(var t=a.hexToRgb(e),n=0,r=this.observers;n input[type='range']").map(function(e){e=e.parentElement;return new t(e)})}),s=new r.Helpers.Storage("range",function(e){return""+e.value},function(e,t){e=n.getByIdSafe(e);return!!e&&(e.value=+t,e.callObservers(),!0)}),r.Helpers.Events.callAfterDOMLoaded(function(){n.load(),s.applyStoredState()}),i=!!window.MSInputMethodContext&&!!document.documentMode,e.addObserver=function(e,t){e=n.getById(e),(i?e.onChangeObservers:e.onInputObservers).push(t)},e.addLazyObserver=function(e,t){n.getById(e).onChangeObservers.push(t)},e.getValue=function(e){return n.getById(e).value},e.setValue=function(e,t){n.getById(e).value=t},e.storeState=function(e){e=n.getById(e),s.storeState(e)},e.clearStoredState=function(e){e=n.getById(e),s.clearStoredState(e)}}(Page=Page||{}); 8 | var Page;!function(n){var e,t,l,i;function r(e){for(var a=this,t=(this.observers=[],this.id=e.id,this.containerElement=e,this.currentValueElement=n.Helpers.Utils.selector(e,".select-current-value"),this.valuesListElement=n.Helpers.Utils.selector(e,".select-values-list"),this.placeholder=this.valuesListElement.dataset.placeholder||"",this.currentValue=this.currentValueElement.dataset.value||null,this.valueElements=[],this.valuesListElement.querySelectorAll(".select-value[data-value]")),l=0;l