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 -------->
@ -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) {
if(typeof canvas1.setShaders === "function")
canvas1.setShaders(vs, editor.getSession().getValue()); 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,7 +59,8 @@ 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);
@ -57,17 +70,20 @@ function loadTexture(gl, url) {
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);
// // Bind the texture to texture unit 0
// gl.bindTexture(gl.TEXTURE_2D, texture);
// // Tell the shader we bound the texture to texture unit 0
// textures[i] = i;
// }
loadTexture(gl, './1.jpg', 0); //Texture loading.
loadTexture(gl, './2.jpg', 1); //Texture loading.
gl.uniform1iv(gl.getUniformLocation(program, 'uSampler'), textures);
let texture = loadTexture(gl, './earthmap1k.jpg') //Texture loading.
// Tell WebGL we want to affect texture unit 0
gl.activeTexture(gl.TEXTURE0);
// Bind the texture to texture unit 0
gl.bindTexture(gl.TEXTURE_2D, texture);
// Tell the shader we bound the texture to texture unit 0
gl.uniform1i(gl.getUniformLocation(program, 'uSampler'), 0);
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