merged hw2 w/ my changes

Added more textures
Work on editor
master
bill 4 years ago
parent db81299aef
commit 107bbb23cd

BIN
1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 803 KiB

Before

Width:  |  Height:  |  Size: 336 KiB

After

Width:  |  Height:  |  Size: 336 KiB

@ -1,4 +1,4 @@
<script src=lib1.js></script> <script src=lib2.js></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js"crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js"crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ext-language_tools.js" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ext-language_tools.js" crossorigin="anonymous"></script>
<style> <style>
@ -40,181 +40,7 @@
<!!-------- FRAGMENT SHADER: THIS IS WHERE YOU WILL DO YOUR WORK --------> <!!-------- FRAGMENT SHADER: THIS IS WHERE YOU WILL DO YOUR WORK -------->
<script id='my_fragment_shader' type='x-shader/x-fragment'> <script src="shader.frag" id='my_fragment_shader' type='x-shader/x-fragment'> </script>
uniform float uTime; // TIME, IN SECONDS
uniform int flags;
varying vec3 vPos; // -1 < vPos.x < +1
// -1 < vPos.y < +1
// vPos.z == 0
uniform sampler2D uSampler;
// YOU MUST DEFINE A main() FUNCTION.
void main() {
////////////////////////////////////////////////
//
// HERE, FOR YOUR HOMEWORK, YOU CAN WRITE ANY
// CODE YOU LIKE
//DEFINE A COLOR FOR THIS FRAGMENT.
// LIGHT DIRECTION AND COLOR
vec3 LDir = vec3(1, 1, 1);
vec3 LCol = vec3(1.,.98,.9);
vec3 VDir = vec3(0., 0., 1.);
float R = 0.5 + 0.3*sin(uTime/10.);
// vPos IS THE 3D LOCATION OF THIS FRAGMENT.
// SURFACE REFLECTANCE PROPERTIES
vec3 diffuse = vec3(.7,.7,.6);
vec3 ambient = vec3(.1,.1,.09);
vec3 specular = vec3(.35,.35,.3);
// CREATE A WACKY BACKGROUND PATTERN.
vec3 color = vec3(.5 + .5 * sin(20. * vPos.x + sin(10. * vPos.y + 5. * uTime)),
.5,
.5 + .5 * sin(20. * vPos.y + sin(10. * vPos.x + 5. * uTime)));
vec3 specularlight; //specular light should disregard object color.
float x = vPos.x;
float y = vPos.y;
// CREATE BOUNCING ANIMATION.
y += .5 - 2. * abs(.5 * sin(uTime));
// FIGURE OUT WHETHER THIS PIXEL IS ON THE SPHERE.
float rr = x * x + y * y;
// IF SO, THEN SHADE THE SPHERE.
if (rr < R*R) {
// COMPUTE THE z AND NORMAL OF THE SPHERE.
float z = R * sqrt(1. - rr/(R*R));
vec3 N = vec3(x,y,z) / R;
// APPLY SHADING AND LIGHTING.
vec3 realVPos = vec3(vPos.x, vPos.y, z);
//*DIRECTIONS ARE NORMALIZED TO GET THE CORRECT PHONG LIGHTING
LDir = normalize(LDir - realVPos);
VDir = normalize(VDir - realVPos);
vec3 lcolor = ambient;
lcolor += diffuse * max(0., dot(N, LDir)) * LCol;
//*SPECULAR LIGHTS ARE ADDED
specularlight = specular *
pow(max(0.,dot(2.*dot(N, LDir) * N - LDir, VDir)),3.) * LCol;
// ROTATE THE TEXTURE OVER TIME.
float angle = 0.4 * uTime;
float px = cos(angle) * N.x + sin(angle) * N.z;
float pz = -sin(angle) * N.x + cos(angle) * N.z;
vec3 P = vec3(px, N.y, pz);
// APPLY PROCEDURAL NOISE TEXTURE.
float cloud = min(0.85, max(-0.05, 2. * noise(1.1 * P)));
//const float rspeed = 10.;
//*CALCULATING THE TEXTURE COORDINATE.
const float pi = 3.14159265359;
float tex_x = acos(abs(x)/sqrt(R*R-y*y));
if(x > 0.)
tex_x = pi - tex_x;
tex_x = R * tex_x;
tex_x *= 1.5708;//*Correct aspect ratio of texture 2:1 -> 2pir:2r
tex_x = tex_x + float(uTime)*R;
float _2pir = 2. * pi * R;
float quo = float(int(tex_x/_2pir));
tex_x = (tex_x - quo * _2pir) / _2pir;
//*TEXTURE MAPPING
vec3 texture_color;
if(flags /*& 0x1*/ == 0)
texture_color = texture2D(uSampler, vec2(tex_x, ((R - y)/(2.*R)))).xyz;
else
texture_color = vec3(.0841, .5329, .9604);
color = lcolor *
(cloud + texture_color) + specularlight;
}
//*CALCULATING LIGHTING AND SHADOWS FOR THE BACKGROUND
else{
vec3 realVPos = vec3(vPos.x, vPos.y, -1.);
vec3 N = vec3(0., 0., 1.);
vec3 C = vec3(0., vPos.y - y, 0.);
// APPLY SHADING AND LIGHTING.
vec3 lcolor = 6.*ambient;
//*CALCULATING DISTANCE BETWEEN SPHERE CENTER TO THE RAY
//BETWEEN THE POINT TO LIGHT SOURCE
vec3 LV = realVPos - LDir;
vec3 LC = C - LDir;
vec3 VC = C - realVPos;
float lLV = dot(LV, LV);
float lLC = dot(LC, LC);
float lVC = dot(VC, VC);
float RR = R*R;
float d_VCVL = -dot(VC, LV);
float dist = min(lLC, lVC);
if (d_VCVL > 0.)
dist = min(dist, lVC - d_VCVL*d_VCVL/lLV);
//*CALCULATE DISTANCE BETWEEN SPHERE CENTER TO THE RAY BETWEEN POINT TO CAMERA
vec3 EV = realVPos - VDir;
vec3 EC = C - VDir;
float lEV = dot(EV, EV);
float lEC = dot(EC, EC);
float d_VCVE = -dot(VC, EV);
float dist2 = min(lEC, lVC);
if (d_VCVE > 0.)
dist2 = min(dist2, lVC - d_VCVE*d_VCVE/lEV);
//*AMBIENT LIGHT WILL DECAY WHEN BACKGROUND POINT IS CLOSER TO THE SPHERE
//*FIRST THE DISTANCE IS NORMALIZED, THEN I CURVED IT WITH LOGISTIC FUNCTION
float aratio0 = 1./(1.+pow(2.71828,15.*(.2-(sqrt(lVC) - R - .4806)/1.381)));
lcolor *= aratio0;
diffuse *= pow(aratio0, 0.3);
//*TEST IF CAMERA CAN SEE THE POINT
if(dist2 < RR)
{
specular *= 0.;
float d = sqrt(dist2);
float ratio = pow(2., sqrt(dist2)/R) - 1.;
diffuse *= ratio;
}
//*TEST IF THE LIGHT CAN REACH THE BACKGROUND POINT DIRECTLY
if(dist < RR)
{
specular *= 0.;
float ratio = pow(2.7, sqrt(dist)/R) - 1.7;
float aratio = pow(2., sqrt(dist)/R) - 1.;
if(ratio < 0.)
ratio = 0.;
diffuse *= ratio;
lcolor *= aratio;
}
LDir = normalize(LDir - realVPos);
VDir = normalize(VDir - realVPos);
lcolor += 1.2*diffuse * max(0., dot(N, LDir)) * LCol;
specularlight = 0.3*specular *
pow(max(0., dot(2.*dot(N, LDir) * N - LDir, VDir)),32.) * LCol;
color = color * lcolor + specularlight;
}
// APPLY GAMMA CORRECTION AND SET THE PIXEL COLOR.
gl_FragColor = vec4(sqrt(color), 1.0);
}
</script>
<!!-------- CREATE A PROPERLY DESCRIPTIVE TITLE BELOW --------> <!!-------- CREATE A PROPERLY DESCRIPTIVE TITLE BELOW -------->
@ -245,7 +71,7 @@ that you are seeing now.</p>
<ul> <ul>
<li>The Ambient lights and diffusion lights are reduced with respect to the distance between the background point and the sphere.</li> <li>The Ambient lights and diffusion lights are reduced with respect to the distance between the background point and the sphere.</li>
<li>The specular light of the background wall is eliminated and the diffusion factor is reduced when the ray shooting from the background point <li>The specular light of the background wall is eliminated and the diffusion factor is reduced when the ray shooting from the background point
towards the light source or from the background point towards the camera position intersect with the sphere.</li> towards the light source or from the background point towards the camera position intersect with the sphere.</li>
</ul> </ul>
<li>I added basic interactions such as press ctrl + 't' key to hide/show texture, click on the above canvas to pause/unpause animations. <li>I added basic interactions such as press ctrl + 't' key to hide/show texture, click on the above canvas to pause/unpause animations.
Just a proof of concept.</li> Just a proof of concept.</li>
@ -266,10 +92,16 @@ that you are seeing now.</p>
// CREATE THE HTML DOCUMENT // CREATE THE HTML DOCUMENT
let flags = 0x0; let flags = 0x0;
let vs = my_vertex_shader.innerHTML, let vs = my_vertex_shader.innerHTML;
fs = my_fragment_shader.innerHTML; var client = new XMLHttpRequest();
fs = fs.substring(1, fs.length); client.open('GET', './shader.frag');
client.onloadend = function() {
fs = (client.responseText);
// START EVERYTHING.
gl_start(canvas1, vs, fs);
editor.getSession().setValue(fs);
}
client.send();
document.body.innerHTML = ['' document.body.innerHTML = [''
,'<font size=7 color=#909090>' + my_title.innerHTML ,'<font size=7 color=#909090>' + my_title.innerHTML
,'<TABLE cellspacing=0 cellpadding=0><TR>' ,'<TABLE cellspacing=0 cellpadding=0><TR>'
@ -285,10 +117,6 @@ document.body.innerHTML = [''
].join(''); ].join('');
// SET UP THE EDITABLE TEXT AREA ON THE LEFT SIDE. // SET UP THE EDITABLE TEXT AREA ON THE LEFT SIDE.
let text = fs.split('\n'), cols = 0;
for (let i = 0 ; i < text.length ; i++)
cols = Math.max(cols, text[i].length);
ace.require("ace/ext/language_tools"); ace.require("ace/ext/language_tools");
var editor = ace.edit("ace", { var editor = ace.edit("ace", {
mode:"ace/mode/glsl", mode:"ace/mode/glsl",
@ -305,11 +133,10 @@ editor.setOptions({
showPrintMargin: false, showPrintMargin: false,
}); });
editor.setAutoScrollEditorIntoView(true); editor.setAutoScrollEditorIntoView(true);
editor.getSession().setValue(fs);
// REPARSE THE SHADER PROGRAM AFTER EVERY KEYSTROKE. // REPARSE THE SHADER PROGRAM AFTER EVERY KEYSTROKE.
editor.session.on('change', function(delta) { editor.session.on('change', function(delta) {
canvas1.setShaders(vs, editor.getSession().getValue()); if(typeof canvas1.setShaders === "function")
canvas1.setShaders(vs, editor.getSession().getValue());
}); });
let lastTime = Date.now(); let lastTime = Date.now();
let animating = true; let animating = true;
@ -322,17 +149,23 @@ canvas1.addEventListener('click',function(ev){
animating = !animating; animating = !animating;
}); });
document.addEventListener('keydown',(e)=>{ document.addEventListener('keydown',(e)=>{
if(e.code.startsWith('Control'))
if(e.code.startsWith('Control')) {
{ ctrl = true;
ctrl = true; }
} else if(ctrl && e.code == 'KeyT')
else if(ctrl && e.code == 'KeyT')
{ {
mask = 0x1; mask = 0x1;
flags = flags&!mask | (!(flags&mask)*mask); flags = flags&!mask | (!(flags&mask)?0:mask);
setUniform('1i', 'flags', flags); setUniform('1i', 'flags', flags);
} }
else if (ctrl && e.code == 'KeyS')
{
let a = document.createElement('a');
a.href = "data:text/plain,"+encodeURIComponent(editor.getSession().getValue());
a.download = 'shader.frag';
a.click();
}
}); });
document.addEventListener('keyup',(e)=>{ document.addEventListener('keyup',(e)=>{
@ -353,8 +186,6 @@ function animate(gl) {
} }
// START EVERYTHING.
gl_start(canvas1, vs, fs);
</script> </script>

@ -24,10 +24,22 @@ let errorMsg = '';
// Initialize a texture and load an image. // Initialize a texture and load an image.
// When the image finished loading copy it into the texture. // When the image finished loading copy it into the texture.
// //
function loadTexture(gl, url) { function getBlob(data) {
const texture = gl.createTexture(); let bytes = new Array(data.length);
gl.bindTexture(gl.TEXTURE_2D, texture); for (let i = 0; i < data.length; i++) {
bytes[i] = data.charCodeAt(i);
}
return new Blob([new Uint8Array(bytes)]);
}
let texture = [], gl, program;
let textures = [0, 1];
function loadTexture(gl, url, i) {
if (texture[i] == null)
{
texture[i] = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture[i]);
}
// Because images have to be downloaded over the internet // Because images have to be downloaded over the internet
// they might take a moment until they are ready. // they might take a moment until they are ready.
// Until then put a single pixel in the texture so we can // Until then put a single pixel in the texture so we can
@ -47,27 +59,31 @@ function loadTexture(gl, url) {
const image = new Image(); const image = new Image();
image.onload = function () { image.onload = function () {
gl.bindTexture(gl.TEXTURE_2D, texture); errorMessage.innerHTML += image.src + i;
gl.bindTexture(gl.TEXTURE_2D, texture[i]);
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
srcFormat, srcType, image); srcFormat, srcType, image);
// WebGL1 has different requirements for power of 2 images // WebGL1 has different requirements for power of 2 images
// vs non power of 2 images so check if the image is a // vs non power of 2 images so check if the image is a
// power of 2 in both dimensions. // power of 2 in both dimensions.
if (isPowerOf2(image.width) && isPowerOf2(image.height)) { if (isPowerOf2(image.width) && isPowerOf2(image.height)) {
// Yes, it's a power of 2. Generate mips. // Yes, it's a power of 2. Generate mips.
gl.generateMipmap(gl.TEXTURE_2D); gl.generateMipmap(gl.TEXTURE_2D);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
} else { } else {
// No, it's not a power of 2. Turn off mips and set // No, it's not a power of 2. Turn off mips and set
// wrapping to clamp to edge // wrapping to clamp to edge
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.activeTexture(gl.TEXTURE0+i);
gl.bindTexture(gl.TEXTURE_2D, texture[i]);
} }
}; };
image.src = url; image.src = url;
gl.activeTexture(gl.TEXTURE0+i);
return texture; gl.bindTexture(gl.TEXTURE_2D, texture[i]);
} }
function isPowerOf2(value) { function isPowerOf2(value) {
@ -82,7 +98,8 @@ function gl_start(canvas, vertexShader, fragmentShader) { // START WEB
canvas.setShaders = function (vertexShader, fragmentShader) { // Add the vertex and fragment shaders: canvas.setShaders = function (vertexShader, fragmentShader) { // Add the vertex and fragment shaders:
let gl = this.gl, program = gl.createProgram(); // Create the WebGL program. gl = this.gl;
program = gl.createProgram(); // Create the WebGL program.
function addshader(type, src) { // Create and attach a WebGL shader. function addshader(type, src) { // Create and attach a WebGL shader.
function spacer(color, width, height) { function spacer(color, width, height) {
@ -131,14 +148,29 @@ function gl_start(canvas, vertexShader, fragmentShader) { // START WEB
console.log('Could not link the shader program!'); console.log('Could not link the shader program!');
gl.useProgram(program); gl.useProgram(program);
gl.program = program; gl.program = program;
const ns = 2;
errorMessage.innerHTML += gl.TEXTURE0 + ' ';
errorMessage.innerHTML += gl.TEXTURE1;
// for(let i = 0; i < 2; ++i){
// let texture = loadTexture(gl, './'+(i+1)+'.jpg') //Texture loading.
// // Tell WebGL we want to affect texture unit 0
// if( i == 0 )
// gl.activeTexture(gl.TEXTURE0);
// else
// gl.activeTexture(gl.TEXTURE1);
let texture = loadTexture(gl, './earthmap1k.jpg') //Texture loading. // // Bind the texture to texture unit 0
// Tell WebGL we want to affect texture unit 0 // gl.bindTexture(gl.TEXTURE_2D, texture);
gl.activeTexture(gl.TEXTURE0); // // Tell the shader we bound the texture to texture unit 0
// Bind the texture to texture unit 0 // textures[i] = i;
gl.bindTexture(gl.TEXTURE_2D, texture); // }
// Tell the shader we bound the texture to texture unit 0 loadTexture(gl, './1.jpg', 0); //Texture loading.
gl.uniform1i(gl.getUniformLocation(program, 'uSampler'), 0); loadTexture(gl, './2.jpg', 1); //Texture loading.
gl.uniform1iv(gl.getUniformLocation(program, 'uSampler'), textures);
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer()); // Create a square as a triangle strip gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer()); // Create a square as a triangle strip
@ -151,7 +183,6 @@ function gl_start(canvas, vertexShader, fragmentShader) { // START WEB
} }
canvas.setShaders(vertexShader, fragmentShader); // Initialize everything, canvas.setShaders(vertexShader, fragmentShader); // Initialize everything,
setInterval(function () { // Start the animation loop. setInterval(function () { // Start the animation loop.
gl = canvas.gl; gl = canvas.gl;
if (gl.startTime === undefined) // First time through, if (gl.startTime === undefined) // First time through,
@ -167,7 +198,6 @@ function gl_start(canvas, vertexShader, fragmentShader) { // START WEB
function animate() { } function animate() { }
let gl;
function setUniform(type, name, a, b, c, d, e, f) { function setUniform(type, name, a, b, c, d, e, f) {
let loc = gl.getUniformLocation(gl.program, name); let loc = gl.getUniformLocation(gl.program, name);
(gl['uniform' + type])(loc, a, b, c, d, e, f); (gl['uniform' + type])(loc, a, b, c, d, e, f);

@ -0,0 +1,130 @@
uniform float uTime; // TIME, IN SECONDS
uniform int flags;
varying vec3 vPos; // -1 < vPos.x < +1
// -1 < vPos.y < +1
// vPos.z == 0
float fl = 3.0;
const float pi = 3.14159265359;
const int ns = 2;
vec4 Sph[ns];
uniform sampler2D uSampler[ns];
vec3 Ambient [ns];
vec3 Diffuse [ns];
vec4 Specular[ns];
// YOU MUST DEFINE A main() FUNCTION.
bool getflag(int flag, int bit){
float shifted = float(flag) - pow(2., float(bit));
return fract(shifted / 2.) > 0.;
}
float clampv(float val, float l, float h){
return val < l? l:val > h? h:val;
}
void main() {
////////////////////////////////////////////////
//
// HERE, FOR YOUR HOMEWORK, YOU CAN WRITE ANY
// CODE YOU LIKDEFINE A COLOR FOR THIS FRAGMENT.
// LIGHT DIRECTION AND COLOR
vec3 LDir = vec3(.5,.5,.5);
vec3 LCol = vec3(1.,1.,1.);
// SPHERE
Sph[0] = vec4(.5*sin(uTime),0.,.5*cos(uTime), 0.2);
Sph[1] = vec4(0.,0.,0., 0.2);
// SURFACE REFLECTANCE PROPERTIES
Ambient [0] = vec3(.1,.05,.05); // r,g,b
Diffuse [0] = vec3(1.,.5,.5); // r,g,b
Specular[0] = vec4(1.,.5,.5, 10.); // r,g,b,power
Ambient [1] = vec3(.05,.05,.1); // r,g,b
Diffuse [1] = vec3(.5,.5,1.); // r,g,b
Specular[1] = vec4(1.,.5,.5, 20.); // r,g,b,power
// INITIALIZE TO A BACKGROUND COLOR
vec3 color = vec3(.2, .3, .5);
// COMPUTE THE RAY ORIGIN AND DIRECTION
float x = vPos.x;
float y = vPos.y;
vec3 V = vec3(0.,0.,fl);
vec3 W = normalize(vec3(x, y, -fl));
// RAY TRACE TO ALL OBJECTS IN THE SCENE
float tMin = 10000.0;
for (int i = 0 ; i < ns ; i++) {
// SHIFT COORDINATES, SO THAT SPHERE IS AT (0,0,0)
vec3 Vp = V - Sph[i].xyz;
// SOLVE FOR QUADRATIC EQUATION IN t
float B = dot(W, Vp);
float C = dot(Vp, Vp) - Sph[i].w * Sph[i].w;
float D = B*B - C;
if (D > 0.) {
float t = -B - sqrt(D);
// IF RAY HITS SPHERE
if (t > 0. && t < tMin) {
float t = -B - sqrt(D);
// IF RAY HITS SPHERE
vec3 S = V + t * W;
if (t > 0. && t < tMin) {
vec3 tex_sph = S - Sph[i].xyz;
// FIND SURFACE POINT AND NORMAL, DO SHADING
float R = Sph[i].w;
float tex_x = acos(abs(tex_sph.x)/sqrt(R*R-tex_sph.y*tex_sph.y));
if(tex_sph.x > 0.)
tex_x = pi - tex_x;
tex_x = R * tex_x;
tex_x *= 1.5708;//*Correct aspect ratio of texture 2:1 -> 2pir:2r
tex_x = tex_x + float(uTime)*R;
float _2pir = 2. * pi * R;
float quo = float(int(tex_x/_2pir));
tex_x = clampv((tex_x - quo * _2pir), 0., _2pir) / _2pir;
//*TEXTURE MAPPING
vec3 texture_color;
if(getflag(flags, 0))
texture_color = texture2D(uSampler[i], vec2(tex_x, ((R - tex_sph.y)/(2.*R)))).xyz;
vec3 N = normalize(S - Sph[i].xyz);
vec3 VDir = normalize(Vp);
//*DIRECTIONS ARE NORMALIZED TO GET THE CORRECT PHONG LIGHTING
vec3 realLDir = normalize(LDir - S);
color = (Ambient[i]
+ Diffuse[i] * max(0.,dot(N,LDir)) * LCol) * texture_color
// + SPECULAR COMPONENT GOES HERE
+ Specular[i].xyz*pow(max(0., dot(2.*dot(N, LDir)*N - LDir, VDir)), Specular[i].w)
;
tMin = t;
}
}
}
// APPLY GAMMA CORRECTION AND SET THE PIXEL COLOR.
gl_FragColor = vec4(sqrt(color), 1.0);
}
}
Loading…
Cancel
Save