diff --git a/README.md b/README.md index 1410c30..f4c03a3 100644 --- a/README.md +++ b/README.md @@ -1,82 +1,89 @@ # [Project2: Toolbox Functions](https://github.com/CIS700-Procedural-Graphics/Project2-Toolbox-Functions) +Find the final product at: https://tabathah.github.io/Project2-Toolbox-Functions/ + ## Overview -The objective of this assignment is to procedurally model and animate a bird wing. Let's get creative! +I procedurally created an animated wing of a parrot. -Start by forking and then cloning [this repository](https://github.com/CIS700-Procedural-Graphics/Project2-Toolbox-Functions) +Here are some reference images I started out with: -## Modeling +![](./references/parrot01.jpg) -##### Reference images +![](./references/parrot02.jpg) -Search for three or more images of a bird wing (or any flying creature, really) in order to provide yourself reference material, as you're going to base your modeling and animation from these images. For the more artistic minds, feel free to sketch your own concept. +![](./references/parrot03.jpg) -##### Make wing curve +## Model -Begin with a 3D curve for your basic wing shape. Three.js provides classes to create many different types of curves, so you may use whatever type of curve you prefer. +I was given this basic model of a feather: -##### Distribute feathers +![](./progressShots/original-feather.PNG) -We have provided a simple feather model from which to begin. You are not required to use this model if you have others that you prefer. From this base, you must duplicate the feather to model a complete wing, and your wing should consist of at least thirty feathers. Distribute points along the curve you created previously; you will append the feather primitives to the curve at these points. Make sure that you modify the size, orientation, and color of your feathers depending on their location on the wing. +The first thing I did was create a curve that would outline the basic shape of the wing. Here is my curve displayed as a tube geometry so I could see and work on it: -Feel free to diversify your wings by using multiple base feather models. +![](./progressShots/curve.PNG) -## Animation +The next thing I did was evenly distribute feathers along the positions on the curve: -Add a wind force to your scene, and parameterize its direction and speed. You will use this wind force to animate the feathers of your wing by vibrating them slightly. Using Dat.GUI, allow the user to modify these wind parameters. Please note that we don't care about your feather motion being physically accurate, as long as it looks nice. +![](./progressShots/placed-feathers-on-curve.PNG) -Additionally, animate the control points of your wing curve to make the wing flap, and allow the user to control the speed of the wing flapping. +I then began scaling the feathers. To do this, I simply interpolated between the size I wanted the left most feather to have and the size I wanted the right most feather to have. To make this more realistic, I incorporated bias and gain to make the transition less linear. The bias on the scale favored the left feathers so that the left most feathers would be noticably larger than the rest. Also, the gain favored the middle of the feather distribution, so there would be many feathers of the same size in the middle. The result was the following: -## Interactivity +![](./progressShots/with-scale-distribution.PNG) + +After doing this, I realized I wanted three layers of feathers on my wing to provide added realism. I made two more layers of feathers, displacing there depth by a bit to separate them from other layers, with limited positions on the wing curve and different ranges of scale from the first layer. This gave the following result: + +![](./progressShots/layers-added.PNG) + +The last thing to do in the modeling was to interpolate rotation of the feathers. The left most feathers had a sharp angle to the left in comparison to the rest and the right most feathers had a slight angle to the right. I provided similar bias and gain in this interpolation to the scaling one because again I wanted the left-most feathers to stand out from the rest and I wanted the middle ones to be pretty uniform. This addition provided the following result: -Using Dat.GUI and the examples provided in the reference code, allow the user to adjust the following controls: +![](./progressShots/rotation-added.PNG) -1. The curvature of the wing's basic shape -2. Feather distribution -3. Feather size -4. Feather color -5. Feather orientation -6. Flapping speed -7. Flapping motion +Finally, I added color to the feathers. I created my own shaders which took into account the index of each feather for interpolating and deciding on color based on layer, as well as the light position in the scene and an integer indicating the color pallete. First I started with a flat shader, that merely chose color based on the layer the feather was on. -## For the Overachievers +![](./progressShots/color-added.PNG) -Suggestions: -- Make a pretty iridescent or otherwise feather appropriate shader. -- Otherwise, going the extra mile for this assignment is really in the polish! +I then added lamertian shading and iridescence, as well as changing the colors I was interpolating in order to make the colors more realistic. -## Submission +![](./progressShots/improved-color-with-lambert-and-iridescence.PNG) -- Create a folder called `references` to include your reference images. +## Animation + +I animated the wing so that it would flap at a certain speed and so that the feathers would be affected by a theoretical wind with a speed and a direction. + +The flapping part of the animation was simply a rotation about the x-axis that is linearly interpolated to create the continuous motion. -- Update `README.md` to contain a solid description of your project +I applied the wind by adding a rotation to each feather that was based on the angle of the wind direction and a simple pseudo-noise value based on the feather's index. This noise value was limited based on the speed of the wind, where low speed caused the noise to be very limited and high speed caused the noise to be unlimited. The following is a shot of the wing while high wind speed is on and feathers are being displaced. + +![](./progressShots/wind-displacement.PNG) + +## Interactivity -- Publish your project to gh-pages. `npm run deploy`. It should now be visible at http://username.github.io/repo-name +I added several sliders on the GUI to change the parameters of the wing for this project. Some pictures have been added for particularly interesting changes that can occur. -- Create a [pull request](https://help.github.com/articles/creating-a-pull-request/) to this repository, and in the comment, include a link to your published project. +The curvature one affects the y positions of the original curve the wing is based on, so that increasing curvature creates a bendy wing and decreasing it make the wing more flat. -- Submit the link to your pull request on Canvas. +![](./progressShots/high-curvature.PNG) -## Getting Started +![](./progressShots/low-curvature.PNG) -1. [Install Node.js](https://nodejs.org/en/download/). Node.js is a JavaScript runtime. It basically allows you to run JavaScript when not in a browser. For our purposes, this is not necessary. The important part is that with it comes `npm`, the Node Package Manager. This allows us to easily declare and install external dependencies such as [three.js](https://threejs.org/), [dat.GUI](https://workshop.chromeexperiments.com/examples/gui/#1--Basic-Usage), and [glMatrix](http://glmatrix.net/). Some other packages we'll be using make it significantly easier to develop your code and create modules for better code reuse and clarity. These tools make it _signficantly_ easier to write code in multiple `.js` files without globally defining everything. +The feather distribution one affects the bias of the position interpolation, so that the more it varies from 0.5, the more the featehrs shift to one side or the other. -2. Fork and clone your repository. +Feather size affects the scale of the feathers in a fairly straightforawrd way. -3. In the root directory of your project, run `npm install`. This will download all of those dependencies. +![](./progressShots/high-feather-size.PNG) -4. Do either of the following (but I highly recommend the first one for reasons I will explain later). +![](./progressShots/low-feather-size.PNG) - a. Run `npm start` and then go to `localhost:7000` in your web browser +Feather orientation affects the angle of the feathers, again in a pretty strightforward way. - b. Run `npm run build` and then go open `index.html` in your web browser +If the color slider is less than 1.5, the color palette is the default red, yellow, blue, whereas if its over 1.5, the color palette is a purple, blue, and turquoise palette. Below is the second color palette. - You should hopefully see the framework code with a 3D cube at the center of the screen! +![](./progressShots/second-color-palette.PNG) +Wind speed affects the amount of noise that can be placed on feathers during the wind animation, so higher speed creates a more violent wind displacement, and lower speed creates soft vibrations. -## Developing Your Code -All of the JavaScript code is living inside the `src` directory. The main file that gets executed when you load the page as you may have guessed is `main.js`. Here, you can make any changes you want, import functions from other files, etc. The reason that I highly suggest you build your project with `npm start` is that doing so will start a process that watches for any changes you make to your code. If it detects anything, it'll automagically rebuild your project and then refresh your browser window for you. Wow. That's cool. If you do it the other way, you'll need to run `npm build` and then refresh your page every time you want to test something. +Flap Speed affects the period of time during which one up and down motion of the wind occurs. -## Publishing Your Code -We highly suggest that you put your code on GitHub. One of the reasons we chose to make this course using JavaScript is that the Web is highly accessible and making your awesome work public and visible can be a huge benefit when you're looking to score a job or internship. To aid you in this process, running `npm run deploy` will automatically build your project and push it to `gh-pages` where it will be visible at `username.github.io/repo-name`. \ No newline at end of file +Finally, wind direction affects the angle on which the wind is blowing, where 0 is coming straight down onto the wing, 90 is blowing from the right side of the screen, and -90 is blowing from the left side of the screen. diff --git a/package.json b/package.json index c80e8a3..cde25c8 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "scripts": { "start": "webpack-dev-server --hot --inline", "build": "webpack", - "deploy": "rm -rf npm-debug.log && git checkout master && git commit -am 'update' && gh-pages-deploy" + "deploy": "gh-pages-deploy" }, "gh-pages-deploy": { "prep": [ diff --git a/progressShots/color-added.PNG b/progressShots/color-added.PNG new file mode 100644 index 0000000..0bc9a51 Binary files /dev/null and b/progressShots/color-added.PNG differ diff --git a/progressShots/curve.PNG b/progressShots/curve.PNG new file mode 100644 index 0000000..c951272 Binary files /dev/null and b/progressShots/curve.PNG differ diff --git a/progressShots/high-curvature.PNG b/progressShots/high-curvature.PNG new file mode 100644 index 0000000..315fa34 Binary files /dev/null and b/progressShots/high-curvature.PNG differ diff --git a/progressShots/high-feather-size.PNG b/progressShots/high-feather-size.PNG new file mode 100644 index 0000000..aafac24 Binary files /dev/null and b/progressShots/high-feather-size.PNG differ diff --git a/progressShots/improved-color-with-lambert-and-iridescence.PNG b/progressShots/improved-color-with-lambert-and-iridescence.PNG new file mode 100644 index 0000000..59c8184 Binary files /dev/null and b/progressShots/improved-color-with-lambert-and-iridescence.PNG differ diff --git a/progressShots/layers-added.PNG b/progressShots/layers-added.PNG new file mode 100644 index 0000000..4843deb Binary files /dev/null and b/progressShots/layers-added.PNG differ diff --git a/progressShots/low-curvature.PNG b/progressShots/low-curvature.PNG new file mode 100644 index 0000000..497c49e Binary files /dev/null and b/progressShots/low-curvature.PNG differ diff --git a/progressShots/low-feather-size.PNG b/progressShots/low-feather-size.PNG new file mode 100644 index 0000000..758c05c Binary files /dev/null and b/progressShots/low-feather-size.PNG differ diff --git a/progressShots/original-feather.PNG b/progressShots/original-feather.PNG new file mode 100644 index 0000000..66f14cd Binary files /dev/null and b/progressShots/original-feather.PNG differ diff --git a/progressShots/placed-feathers-on-curve.PNG b/progressShots/placed-feathers-on-curve.PNG new file mode 100644 index 0000000..7f50983 Binary files /dev/null and b/progressShots/placed-feathers-on-curve.PNG differ diff --git a/progressShots/rotation-added.PNG b/progressShots/rotation-added.PNG new file mode 100644 index 0000000..a61a12b Binary files /dev/null and b/progressShots/rotation-added.PNG differ diff --git a/progressShots/second-color-palette.PNG b/progressShots/second-color-palette.PNG new file mode 100644 index 0000000..8b7e353 Binary files /dev/null and b/progressShots/second-color-palette.PNG differ diff --git a/progressShots/wind-displacement.PNG b/progressShots/wind-displacement.PNG new file mode 100644 index 0000000..884797b Binary files /dev/null and b/progressShots/wind-displacement.PNG differ diff --git a/progressShots/with-scale-distribution.PNG b/progressShots/with-scale-distribution.PNG new file mode 100644 index 0000000..1177f11 Binary files /dev/null and b/progressShots/with-scale-distribution.PNG differ diff --git a/references/parrot01.jpg b/references/parrot01.jpg new file mode 100644 index 0000000..4af750b Binary files /dev/null and b/references/parrot01.jpg differ diff --git a/references/parrot02.jpg b/references/parrot02.jpg new file mode 100644 index 0000000..9a31e1f Binary files /dev/null and b/references/parrot02.jpg differ diff --git a/references/parrot03.jpg b/references/parrot03.jpg new file mode 100644 index 0000000..99971f6 Binary files /dev/null and b/references/parrot03.jpg differ diff --git a/src/distribution.js b/src/distribution.js new file mode 100644 index 0000000..0374b37 --- /dev/null +++ b/src/distribution.js @@ -0,0 +1,250 @@ +const THREE = require('three'); + +var curvature = 1.0; //controls y positions of feathers on curve, ranges from 0 to 4, higher curvature means more variation in y positions +var featherDistribution = 0.5; //controls bias of feather positions, ranges 0 to 1 +var featherSize = 1.0; //controls max scale values of feathers, ranges from 0 to 2 +var featherOrientation = 0.0; //controls an extra rotation about y, ranges from -1 to 1 +var windSpeed = 0.5; //speed of wind, ranges from 0 to 1, affects noise of feather displacement from sporadic to light +var flapSpeed = 1.0; //speed of wind, ranges from 0 to 5, affects speed of flap cycle +var windDirection = 45.0; //angle of wind parallel to y direction, goes from 0 to 360 degrees where 0 is straight down +var time = 0.0; //in order to animate with wind +var color = 1.0; //indicates the color palette, either 1 or 2 + +export function incTime() +{ + time++; +} + +export function changeColor() +{ + if(color == 1){ color = 2; } + else { color = 1; } +} + +export function updateCurve(newVal) +{ + curvature = newVal; +} + +export function updateDistrib(newVal) +{ + featherDistribution = newVal; +} + +export function updateSize(newVal) +{ + featherSize = newVal; +} + +export function updateOrient(newVal) +{ + featherOrientation = newVal; +} + +export function updateSpeed(newVal) +{ + windSpeed = newVal; +} + +export function updateFlapSpeed(newVal) +{ + flapSpeed = newVal; +} + +export function updateDir(newVal) +{ + windDirection = newVal; +} + +export function getPos(mesh, settings) +{ + var b = featherDistribution; + var g = 0.4; + + if(settings.num < settings.total1) + { + var t = gain(g, bias(b, settings.num/settings.total1)); + t = Math.round(t*100); + var pos = settings.curve.getPoints(100)[t]; + mesh.position.set(pos.x, pos.y*curvature, pos.z); + } + else if(settings.num < settings.total2) + { + var t = gain(g, bias(b, (settings.num-settings.total1)/(settings.total2-settings.total1))); + t = Math.round(t*70); + var pos = settings.curve.getPoints(100)[100-t]; + mesh.position.set(pos.x, pos.y*curvature, pos.z+0.05); + } + else + { + var t = gain(g, bias(b, (settings.num-settings.total2)/(settings.total3-settings.total2))); + t = Math.round(t*55); + var pos = settings.curve.getPoints(100)[100-t]; + mesh.position.set(pos.x, pos.y*curvature, pos.z+0.1); + } +} + +export function getRot(mesh, settings) +{ + var t; + var zmax; + var zmin; + var ymax; + var ymin; + + if(settings.num < settings.total1) + { + t = settings.num/settings.total1; + zmin = -3*Math.PI/7.0; + zmax = Math.PI/8.0; + ymin = -Math.PI/4.0; + ymax = 0; + } + else if(settings.num < settings.total2) + { + t = 1 - (settings.num-settings.total1)/(settings.total2-settings.total1); + zmin = -3*Math.PI/8.0; + zmax = Math.PI/16.0; + ymin = -Math.PI/8.0; + ymax = 0; + } + else + { + t = 1 - (settings.num-settings.total2)/(settings.total3-settings.total2); + zmin = -Math.PI/3.0; + zmax = 0; + ymin = -Math.PI/16.0; + ymax = 0; + } + + var zb = 0.2; + var zg = 0.3; + var yb = 0.1; + var yg = 0.3; + + var zt = gain(zg, bias(zb, t)); + var yt = gain(yg, bias(yb, t)); + + var extraZ = zmin*(1-zt) + zmax*(zt); + var extraY = ymin*(1-yt) + ymax*(yt); + + mesh.rotation.z = -Math.PI/2.0 + extraZ; + mesh.rotation.y = 3*Math.PI/4.0 + extraY + featherOrientation*Math.PI/2.0; + mesh.rotation.x = 0; + + var origyRot = mesh.rotation.y; + var origzRot = mesh.rotation.z; + var noise = findNoise(settings.num, time); + var jitterz = Math.PI/4.0; + var jittery = windSpeed*noise*Math.PI*windDirection/180; + if((flapSpeed*time)%120 < 60) + { + var timet = ((flapSpeed*time)%120)/60; + mesh.rotation.y = origyRot + jittery*timet; + mesh.rotation.z = origzRot + jitterz*timet; + } + else + { + var timet = ((flapSpeed*time)%120-60)/60; + mesh.rotation.y = origyRot + jittery*(1-timet); + mesh.rotation.z = origzRot + jitterz*(1-timet); + } +} + +export function getScale(mesh, settings) +{ + var t; + var yhighVal; + var ylowVal; + var zhighVal; + var zlowVal; + + if(settings.num < settings.total1) + { + t = 1 - (settings.num/settings.total1); + yhighVal = 1.5*featherSize; + ylowVal = 1; + zhighVal = 1.5*featherSize; + zlowVal = 1; + } + else if(settings.num < settings.total2) + { + t = (settings.num-settings.total1)/(settings.total2-settings.total1); + yhighVal = 1*featherSize; + ylowVal = 0.5; + zhighVal = 1*featherSize; + zlowVal = 0.5; + } + else + { + t = (settings.num-settings.total2)/(settings.total3-settings.total2); + yhighVal = 0.5*featherSize; + ylowVal = 0.2; + zhighVal = 0.5*featherSize; + zlowVal = 0.25; + } + + var zbias = 0.8; + var zgain = 0.8; + var ybias = 0.8; + var ygain = 0.8; + + var zt = gain(zgain, bias(zbias, t)); + var yt = gain(ygain, bias(ybias, t)); + + var scaleZ = zlowVal*(1-zt) + zhighVal*(zt); + var scaleY = ylowVal*(1-yt) + yhighVal*(yt); + + mesh.scale.z = scaleZ; + mesh.scale.x = scaleY; +} + +function bias(b, t) +{ + return Math.pow(t, Math.log(b) / Math.log(0.5)); +} + +function gain(g, t) +{ + if(t < 0.5) + { + return bias(1-g, 2*t) / 2; + } + else + { + return 1 - bias(1-g, 2 - 2*t) / 2; + } +} + +function findNoise(x, y) +{ + var bigNum = Math.sin(x*12.9898 + y*78.233)*43758.5453; + if(bigNum < 0.0){ return -1*(bigNum - Math.floor(bigNum)); } + else { return -1*(bigNum - Math.floor(bigNum)); } +} + +var funcs = { + updateCurve: updateCurve, + updateDistrib: updateDistrib, + updateSize: updateSize, + updateOrient: updateOrient, + updateSpeed: updateSpeed, + updateFlapSpeed: updateFlapSpeed, + updateDir: updateDir, + incTime: incTime, + changeColor: changeColor, + color: color, + getPos: getPos, + getRot: getRot, + getScale: getScale, + curvature: curvature, + featherDistribution: featherDistribution, + featherSize: featherSize, + featherOrientation: featherOrientation, + windSpeed: windSpeed, + flapSpeed: flapSpeed, + windDirection: windDirection +} + +export default funcs; + \ No newline at end of file diff --git a/src/main.js b/src/main.js index fd8fbd4..4574f77 100755 --- a/src/main.js +++ b/src/main.js @@ -3,6 +3,19 @@ const THREE = require('three'); // older modules are imported like this. You shouldn't have to worry about this much import Framework from './framework' +import Distribution from './distribution' + +//geometry of feather, will be created when obj loaded +var featherGeo; + +//curve that defines the shape of the wing, feather positions will start from here +var curve = new THREE.CatmullRomCurve3( [ + new THREE.Vector3( -2.5, -0.5, 1.15 ), + new THREE.Vector3( -2.25, 0.25, 1.25 ), + new THREE.Vector3( 0, 0, 0.25 ), + new THREE.Vector3( 1.5, -0.25, 0 ), + new THREE.Vector3( 2.5, 0.25, 0 ) +] ); // called after the scene loads function onLoad(framework) { @@ -23,7 +36,7 @@ function onLoad(framework) { // set skybox var loader = new THREE.CubeTextureLoader(); - var urlPrefix = '/images/skymap/'; + var urlPrefix = 'images/skymap/'; var skymap = new THREE.CubeTextureLoader().load([ urlPrefix + 'px.jpg', urlPrefix + 'nx.jpg', @@ -33,39 +46,127 @@ function onLoad(framework) { scene.background = skymap; - // load a simple obj mesh - var objLoader = new THREE.OBJLoader(); - objLoader.load('/geo/feather.obj', function(obj) { - - // LOOK: This function runs after the obj has finished loading - var featherGeo = obj.children[0].geometry; - - var featherMesh = new THREE.Mesh(featherGeo, lambertWhite); - featherMesh.name = "feather"; - scene.add(featherMesh); - }); - // set camera position camera.position.set(0, 1, 5); camera.lookAt(new THREE.Vector3(0,0,0)); - // scene.add(lambertCube); scene.add(directionalLight); + // load a simple obj mesh + var objLoader = new THREE.OBJLoader(); + objLoader.load('geo/feather.obj', function(obj) { + + // LOOK: This function runs after the obj has finished loading + featherGeo = obj.children[0].geometry; + + //create 100 feathers, deciding positions, rotations and scales using function from distribution.js + for(var i = 0.0; i < 100.0; i++) + { + var featherColor = new THREE.ShaderMaterial({ + uniforms: { + layer: { + value: i + }, + light: { + value: directionalLight.position + }, + colorType: { //will dictate what pallete of colors the wings will be + value: 1 + }, + }, + //using my own shaders to dictate color interpolation, lambert, iridescence + vertexShader: require('./shaders/feather-vert.glsl'), + fragmentShader: require('./shaders/feather-frag.glsl') + }); + + //creating a mesh object for this feather + var featherMesh = new THREE.Mesh(featherGeo, featherColor); + featherMesh.name = "feather" + i; //used in onUpdate + + //sent into distribution functions to get correct placement, orientation, and scale based on curve and number of feathers + var params = { + num: i, + total1: 45, + total2: 75, + total3: 100, + curve: curve + }; + + Distribution.getPos(featherMesh, params); + Distribution.getRot(featherMesh, params); + Distribution.getScale(featherMesh, params); + scene.add(featherMesh); + } +}); + // edit params and listen to changes like this // more information here: https://workshop.chromeexperiments.com/examples/gui/#1--Basic-Usage gui.add(camera, 'fov', 0, 180).onChange(function(newVal) { camera.updateProjectionMatrix(); }); + + gui.add(Distribution, 'curvature', 0.0, 4.0).onChange(function(newVal) { + Distribution.updateCurve(newVal); + }); + + gui.add(Distribution, 'featherDistribution', 0.0, 1.0).onChange(function(newVal) { + Distribution.updateDistrib(newVal); + }); + + gui.add(Distribution, 'featherSize', 0.0, 2.0).onChange(function(newVal) { + Distribution.updateSize(newVal); + }); + + gui.add(Distribution, 'featherOrientation', -1.0, 1.0).onChange(function(newVal) { + Distribution.updateOrient(newVal); + }); + + gui.add(Distribution, 'color', 1, 2).onChange(function(newVal) { + Distribution.changeColor(); + for(var i = 0.0; i < 100.0; i++) + { + var f = framework.scene.getObjectByName("feather" + i); + if(f !== undefined) + { + f.material.uniforms["colorType"].value = Distribution.color; + } + } + }); + + gui.add(Distribution, 'windSpeed', 0.0, 1.0).onChange(function(newVal) { + Distribution.updateSpeed(newVal); + }); + + gui.add(Distribution, 'flapSpeed', 0.0, 5.0).onChange(function(newVal) { + Distribution.updateFlapSpeed(newVal); + }); + + gui.add(Distribution, 'windDirection', -90.0, 90.0).onChange(function(newVal) { + Distribution.updateDir(newVal); + }); } // called on frame updates function onUpdate(framework) { - var feather = framework.scene.getObjectByName("feather"); - if (feather !== undefined) { - // Simply flap wing - var date = new Date(); - feather.rotateZ(Math.sin(date.getTime() / 100) * 2 * Math.PI / 180); + //increment time and recompute position, orientation, scale based on the new time + Distribution.incTime(); + for(var i = 0.0; i < 100.0; i++) + { + var f = framework.scene.getObjectByName("feather" + i); + if(f !== undefined) + { + var params = { + num: i, + total1: 45, + total2: 75, + total3: 100, + curve: curve + }; + + Distribution.getPos(f, params); + Distribution.getRot(f, params); + Distribution.getScale(f, params); + } } } diff --git a/src/shaders/feather-frag.glsl b/src/shaders/feather-frag.glsl new file mode 100644 index 0000000..c6042d5 --- /dev/null +++ b/src/shaders/feather-frag.glsl @@ -0,0 +1,81 @@ +uniform float layer; +uniform vec3 light; +uniform float colorType; +varying vec3 norm; +varying vec3 pos; + +void main() { + + vec3 basecolor; + + //need to round colorType up or down to 1 or 2 + int cType; + if(colorType < 1.5){ cType = 1; } + else{ cType = 2; } + + //all the colors that might be used in the wing + vec3 lightBlue = vec3((15.0/255.0), (132.0/255.0), 1.0); + vec3 darkBlue = vec3((37.0/255.0), (73.0/255.0), 1.0); + vec3 indigo = vec3((75.0/255.0), (25.0/255.0), (226.0/255.0)); + vec3 lightIndigo = vec3((79.0/255.0), (79.0/255.0), (222.0/255.0)); + vec3 yellow = vec3(1.0, (213.0/255.0), 0.0); + vec3 blueTurq = vec3((43.0/255.0), (187.0/255.0), (223.0/255.0)); + vec3 greenTurq = vec3((29.0/255.0), (223.0/255.0), (210.0/255.0)); + vec3 red = vec3((236.0/255.0), (67.0/255.0), (41.0/255.0)); + vec3 darkRed = vec3((202.0/255.0), (34.0/255.0), 0.0); + + //interpolating based on feather number, color pallete given, layer the feather is on + if(layer < 45.0) + { + float t = layer/45.0; + + if(cType == 1) + { + basecolor = (1.0-t)*darkBlue + t*lightBlue; + } + else + { + basecolor = (1.0-t)*indigo + t*lightIndigo; + } + + } + else if(layer < 75.0) + { + float t = (layer-45.0)/30.0; + + if(cType == 1) + { + basecolor = (1.0-t)*yellow + t*lightBlue; + } + else + { + basecolor = (1.0-t)*blueTurq + t*lightBlue; + } + } + else + { + float t = (layer-75.0)/25.0; + + if(cType == 1) + { + basecolor = (1.0-t)*darkRed + t*red; + } + else + { + basecolor = (1.0-t)*blueTurq + t*greenTurq; + } + } + + //lambertian shading calculation + vec3 lightDir = pos - vec3(0.0, 1.0, 0.0); + float lambert = clamp(dot(norm, normalize(lightDir)), 0.0, 1.0); + + //iridescence calculated as dot between z vector and camera position relative to this fragment + vec3 camDir = pos - cameraPosition; + float iridescence = 2.0*clamp(dot(vec3(0.0, 0.0, -1.0), normalize(camDir)), 0.5, 1.0); + + vec3 color = iridescence*lambert*basecolor; + + gl_FragColor = vec4( color.rgb, 1.0 ); + +} \ No newline at end of file diff --git a/src/shaders/feather-vert.glsl b/src/shaders/feather-vert.glsl new file mode 100644 index 0000000..d2b714b --- /dev/null +++ b/src/shaders/feather-vert.glsl @@ -0,0 +1,10 @@ +varying vec3 norm; +varying vec3 pos; + +void main() { + //to be used in fragment shader + norm = normal; + pos = position; + + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); +} \ No newline at end of file