Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 20 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,34 @@ WebGL Clustered Deferred and Forward+ Shading

**University of Pennsylvania, CIS 565: GPU Programming and Architecture, Project 5**

* (TODO) YOUR NAME HERE
* Tested on: (TODO) **Google Chrome 222.2** on
Windows 22, i7-2222 @ 2.22GHz 22GB, GTX 222 222MB (Moore 2222 Lab)
* JuYang
* ### Tested on: Windows 7, i7-4710MQ @ 2.50GHz 8GB, GTX 870M 6870MB (Hasee Notebook K770E-i7)

### Live Online
Well after almost 2 weeks, I decided to give up on this project.

[![](img/thumb.png)](http://TODO.github.io/Project5B-WebGL-Deferred-Shading)
The only thing that has the right result is the forward+ glsl. Currently it can extract light clusters in a right way, and I added a "toon" shader which is not toon at all.

### Demo Video/GIF
![result](a.png)

[![](img/video.png)](TODO)
If you wanna see this feature, you can de-comment the "TEST GLSL" part in culster.js, line 193.

### (TODO: Your README)
Other from that, the cluster.js is where the problem is.

*DO NOT* leave the README to the last minute! It is a crucial part of the
project, and we will not be able to grade you without a good README.
What I think is to divide the space using angels instead of positions.

This assignment has a considerable amount of performance analysis compared
to implementation work. Complete the implementation early to leave time!
All positions are world based, and I can calculate which cluster the light is using angles*segments/(2*FOV);

![result](cluster.png)

Well, in javascript, I don't have something that's as accurate as int, float or vec3, vec4.

All I have is var or let, which is unstable and unperdictable.

I have to open the web page and debug each line to see if there's some trouble, for example, passing data from light.position(Float32 Array) into a vec3 or vec4.

Besides, in webgl, it is not real glsl, we don't have %, and not while (That's necessery for light looping, my way is to give a large int in for loop, and break when we met the condition). Even a basic goto would be better, I think.

After this bad experience using javascript and webgl, I'm not suprised if people tell me that they don't like webgl, nor do I like it.

### Credits

Expand Down
Binary file added a.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added cluster.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
217 changes: 209 additions & 8 deletions src/renderers/clustered.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { mat4, vec4, vec3 } from 'gl-matrix';
import { NUM_LIGHTS } from '../scene';
import TextureBuffer from './textureBuffer';
import {camera} from "../init";

export const MAX_LIGHTS_PER_CLUSTER = 100;

const pos=vec3.create();
const light_pos4=vec4.create();

export default class ClusteredRenderer {
constructor(xSlices, ySlices, zSlices) {
// Create a texture to store cluster data. Each cluster stores the number of lights followed by the light indices
Expand All @@ -17,16 +21,213 @@ export default class ClusteredRenderer {
// TODO: Update the cluster texture with the count and indices of the lights in each cluster
// This will take some time. The math is nontrivial...

for (let z = 0; z < this._zSlices; ++z) {
for (let y = 0; y < this._ySlices; ++y) {
for (let x = 0; x < this._xSlices; ++x) {
let i = x + y * this._xSlices + z * this._xSlices * this._ySlices;
// Reset the light count to 0 for every cluster
this._clusterTexture.buffer[this._clusterTexture.bufferIndex(i, 0)] = 0;
}
for (let z = 0; z < this._zSlices; ++z) {
for (let y = 0; y < this._ySlices; ++y) {
for (let x = 0; x < this._xSlices; ++x) {
let index = x + y * this._xSlices + z * this._xSlices * this._ySlices;
// Reset the light count to 0 for every cluster
this._clusterTexture.buffer[this._clusterTexture.bufferIndex(index, 0)] = 0;}}}

// WHY LOOP CLUSTERS?????

//Get camera angles in X,Y axis
let yFOV=camera.fov;
let xFOV=camera.aspect*yFOV;
//Get degrees for each segment
let ysegment=yFOV*2.0/this._ySlices;
let xsegment=xFOV*2.0/this._xSlices;

let totallights=0;
let lightnumtotalinscene=scene.lights.length;
//Camera position
let cam_pos=camera.position;
//Get camera direction XY
/*
let cam_dir_x=vec3.create();
let cam_q=vec4.create();
cam_q[0]=camera.quaternion.w;
cam_q[1]=camera.quaternion.x;
cam_q[2]=0;
cam_q[3]=0;
vec3.transformQuat(cam_dir_x,vec3.fromValues(0,0,1),cam_q);

let cam_dir_y=vec3.create();
cam_q[0]=camera.quaternion.w;
cam_q[1]=0;
cam_q[2]=camera.quaternion.y;
cam_q[3]=0;
vec3.transformQuat(cam_dir_y,vec3.fromValues(0,0,1),cam_q);
*/
let cam_dir_x=vec3.fromValues(0,0,1);
//vec3.rotateY(cam_dir_x,cam_dir_x,vec3.create(),camera.rotation.y*180.0/Math.PI);

let cam_dir_y=vec3.fromValues(0,0,1);
//vec3.rotateX(cam_dir_y,cam_dir_y,vec3.create(),camera.rotation.x*180.0/Math.PI);



//Loop Lights
for(let L=0;L<lightnumtotalinscene;L++)
{

//Light Position
vec3.set(pos,scene.lights[L].position[0], scene.lights[L].position[1], scene.lights[L].position[2]);
//Light-Camera Distance
let dis=vec3.create();
dis[0]=pos[0]-cam_pos.x;
dis[1]=pos[1]-cam_pos.y;
dis[2]=pos[2]-cam_pos.z;
//X,Y angles
var dis2;
dis2=dis;
dis2[0]=0;
let yangle=(vec3.angle(vec3.fromValues(0,0,1),dis2)-camera.rotation.y)*180/Math.PI;
dis2[0]=dis[0];
dis2[1]=0;
let xangle=(vec3.angle(vec3.fromValues(0,0,1),dis2)-camera.rotation.x)*180/Math.PI;
//which segment is it in?
let xint=Math.round(xangle/xsegment);
let yint=Math.round(yangle/ysegment);
let zint=Math.round( dis[2] / ((camera.far-camera.near)/this._zSlices) );

//Radius of Light
let r=scene.lights[L].radius;
//Get Bounding BOX
let xmin=vec3.fromValues(dis[0]-r, dis[1], dis[2]);
let xmax=vec3.fromValues(dis[0]+r, dis[1], dis[2]);
let ymin=vec3.fromValues(dis[0], dis[1]-r, dis[2]);
let ymax=vec3.fromValues(dis[0], dis[1]+r, dis[2]);
let zmin=vec3.fromValues(dis[0], dis[1], dis[2]-r);
let zmax=vec3.fromValues(dis[0], dis[1], dis[2]+r);
//Rotate Camera direction to left most
let direction=vec3.fromValues(0,0,1);
vec3.rotateX(direction,cam_dir_x,vec3.fromValues(0,0,0),-xFOV);
//Get x range for all clusters that contains this light ball
let xmin_int=this.get_pos(xmin,direction,xsegment) *this._xSlices;
let xmax_int=this.get_pos(xmax,direction,xsegment) *this._xSlices;
//Rotate Camera direction to down most
direction=vec3.fromValues(0,0,1);
vec3.rotateY(direction,cam_dir_y,vec3.fromValues(0,0,0),-yFOV);
//Get y range for all clusters that contains this light ball
let ymin_int=this.get_pos(ymin,direction,ysegment) *this._ySlices;
let ymax_int=this.get_pos(ymax,direction,ysegment) *this._ySlices;
//Get z range for all clusters that contains this light ball
let zmin_int=Math.round(zmin[2]);
let zmax_int=Math.round(zmax[2]);



/*
vec3.set(pos,scene.lights[L].position[0], scene.lights[L].position[1], scene.lights[L].position[2]);
vec4.set(light_pos4,
scene.lights[L].position[0],
scene.lights[L].position[1],
scene.lights[L].position[2],
1);

vec4.transformMat4(light_pos4,light_pos4,viewMatrix);

light_pos4[0] /=light_pos4[3];
light_pos4[1] /=light_pos4[3];
light_pos4[2] /=light_pos4[3];

let xint=Math.round((1+light_pos4[0])*this._xSlices/2);
let yint=Math.round((2-light_pos4[1])*this._ySlices/2);
let zint=Math.round(light_pos4[2]*this._zSlices);
*/


//Loop all clusters within bounding box
for(let i=xmin_int;i<=xmax_int;i++)
{
for(let j=ymin_int;j<=ymax_int;j++)
{
for(let k=zmin_int;k<=zmax_int;k++)
{
//Which Cluster
let index1= i + j * this._xSlices + k * this._xSlices * this._ySlices;
//how many lights are there already in the cluster
let light_num=this._clusterTexture.buffer[this._clusterTexture.bufferIndex(index1, 0)];

if(light_num<MAX_LIGHTS_PER_CLUSTER)
{
//add one more light
light_num+=1;
this._clusterTexture.buffer[this._clusterTexture.bufferIndex(index1, 0)]=light_num;
//which texel in cluster
let clusterTexel = Math.floor(light_num/4.0);
//which position in the 4 slots of a texel
let reminder = light_num % 4;
//put the light index into buffer
this._clusterTexture.buffer[this._clusterTexture.bufferIndex(index1, clusterTexel+reminder)] = L;
totallights++;
}
}
}
}



let index2= xint + yint * this._xSlices + zint * this._xSlices * this._ySlices;
//how many lights are there already in the cluster
let light_num2=this._clusterTexture.buffer[this._clusterTexture.bufferIndex(index2, 0)];

if(light_num2<MAX_LIGHTS_PER_CLUSTER)
{
//add one more light
light_num2=light_num2+1;
this._clusterTexture.buffer[this._clusterTexture.bufferIndex(index2, 0)]=light_num2;
//which texel in cluster
let clusterTexel2 = Math.floor(light_num2/4.0);
//which position in the 4 slots of a texel
let reminder2 = light_num2 % 4;
//put the light index into buffer
this._clusterTexture.buffer[this._clusterTexture.bufferIndex(index2, clusterTexel2+reminder2)] = L;
totallights++;
}



}
}

//TEST GLSL
/*
for (let z = 0; z < this._zSlices; ++z) {
for (let y = 0; y < this._ySlices; ++y) {
for (let x = 0; x < this._xSlices; ++x) {

let index = x + y * this._xSlices + z * this._xSlices * this._ySlices;

for(let iii=1;iii<lightnumtotalinscene;iii++)
{
this._clusterTexture.buffer[this._clusterTexture.bufferIndex(index, 0)]=iii;

var LightTexel = Math.floor(iii * 0.25);
var LightTexelIndex = this._clusterTexture.bufferIndex(index, LightTexel);
var reminder = iii - LightTexel * 4;

this._clusterTexture.buffer[LightTexelIndex + reminder] = iii;

}}}}
*/


console.log("Lights total= "+totallights);

this._clusterTexture.update();
}





get_pos(dis , cam , segment)
{
//let angle=Math.acos( vec3.dot(vec3.normalize(dis,dis),cam)) * 180.0/Math.PI;
let angle=vec3.angle(cam,dis);
let seg=Math.round(0.5+(angle/segment));

return seg;
}

}
14 changes: 12 additions & 2 deletions src/renderers/clusteredForwardPlus.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { NUM_LIGHTS } from '../scene';
import vsSource from '../shaders/clusteredForward.vert.glsl';
import fsSource from '../shaders/clusteredForward.frag.glsl.js';
import TextureBuffer from './textureBuffer';
import ClusteredRenderer from './clustered';
import ClusteredRenderer, {MAX_LIGHTS_PER_CLUSTER} from './clustered';

export default class ClusteredForwardPlusRenderer extends ClusteredRenderer {
constructor(xSlices, ySlices, zSlices) {
Expand All @@ -15,7 +15,17 @@ export default class ClusteredForwardPlusRenderer extends ClusteredRenderer {
this._lightTexture = new TextureBuffer(NUM_LIGHTS, 8);

this._shaderProgram = loadShaderProgram(vsSource, fsSource({
numLights: NUM_LIGHTS,

numLights: NUM_LIGHTS, //草泥马在这传的值啊
Xsegment: xSlices,
Ysegment: ySlices,
Zsegment: zSlices,
MAXLIGHTSPERCLUSTER: MAX_LIGHTS_PER_CLUSTER,
PIXELSPERELEMENT: this._clusterTexture._pixelsPerElement,
SCREENWIDTH: screen.width,
SCREENHEIGHT: screen.height,


}), {
uniforms: ['u_viewProjectionMatrix', 'u_colmap', 'u_normap', 'u_lightbuffer', 'u_clusterbuffer'],
attribs: ['a_position', 'a_normal', 'a_uv'],
Expand Down
2 changes: 1 addition & 1 deletion src/scene.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const LIGHT_RADIUS = 5.0;
export const LIGHT_DT = -0.03;

// TODO: This controls the number of lights
export const NUM_LIGHTS = 100;
export const NUM_LIGHTS = 50;

class Scene {
constructor() {
Expand Down
Loading