Skip to content
Snippets Groups Projects
Commit 220139b5 authored by Hwanyong Lee's avatar Hwanyong Lee
Browse files

Re-arrange

parent 848a9f14
No related branches found
No related tags found
No related merge requests found
Showing
with 9412 additions and 2 deletions
Final_Project @ e2181506
Subproject commit e21815064c18d90d4dafcec5abdf71e95a5f2589
Hidden Surface Removal이란?
우리는 눈에서 가까운 물체 뒤에 있는 물체를 볼 수 없다.
예를 들어 어떠한 상자가 존재할 때, 우리가 상자의 앞면을 보고 있다면,
동시에 뒷면을 볼 수 없다. 사실적인 이미지 화면을 얻기 위해서는 물체의 숨겨진 면을 제거해야 한다.
이러한 숨겨진 면을 식별하고 제거하는 것을 Hidden Surface Removal이라고 한다.
WebGL의 경우 Hidden Surface Removal을 구현하기 위해 Z-buffering을 사용한다.
Z-Buffering이란 3차원 이미지를 화면에 그릴 때,
Z-Buffer에 저장된 각 픽셀의 깊이 정보를 비교하여,
어떤 물체를 그려야 할 지, 어떤 물체를 그리지 말아야 할 지 결정하는 알고리즘이다.
이때 주의해야 할 점은, Z-buffer는 각 오브젝트별로 z 값을 저장하는 것이 아니라, 픽셀별로 z 값을 저장한다.
처음 물체가 그려질 때에는 해당 물체가 차지하는 픽셀에, 각 필셀 마다 물체의 Z값을 Z버퍼에 저장하고, 물체를 그린다.
이후에 또 다른 물체가 그려 져야할 상황이 생기면,
그 물체가 차지하는 각 픽셀에 해당하는 Z버퍼값과 새로 그려 져야할 물체의 해당 픽셀의 Z값과 비교한 후,
사용자와 더 가까이 있는 물체를 그리고 그 값을 Z버퍼에 저장한다.
만약 사각형과 삼각형의 Z값이 모두 평행을 이룬다면, 사각형과 삼각형이 교차할 때,
아래와 같이 삼각형과 사각형의 위아래가 한순간에 뒤바뀐다.
![image01](./image/image01.jpeg)
하지만 해당 페이지의 경우, 삼각형의 한 쪽 꼭지점을 사용자로부터 멀리 떨어뜨려 놓았기 때문에,
삼각형과 사각형이 교차할 때, 아래와 같이 사용자로부터 멀리 떨어진 지점의 픽셀부터 서서히 감추어 지는 것을 볼 수 있다.
![image02](./image/image02.jpeg)
이는 Z-Buffer가 z값을 저장할 때, 오브젝트 전체의 z값을 저장하는 것이 아니라,
오브젝트가 차지하는 각 픽셀마다 z값을 저장하고 비교한다는 것을 의미한다.
주제 선정 이유: 필자가 처음 Hidden Surface Removal을 공부할 때에는, Z-buffer가 픽셀이 아니라,
오브젝트마다 z값을 저장하여 비교한다고 생각해서 매우 혼란을 겪었다.
처음 WebGL을 공부하는 사람들이 나와 같은 실수를 범하지 않았으면 하는 마음에서 이와 같은 주제를 선정하였다.
해당 페이지의 기능: 삼각형과 정사각형의 z값을 변경하여 두 오브젝트가 교차할 때 어떤 반응이 일어나는 지를 보여준다.
삼각형의 한 쪽 모서리의 z값을 사용자로부터 멀리 떨어뜨려 놓았기 때문에,
삼각형과 정사각형이 교차할 때 이 부분부터 점차적으로 사라지는 모습을 보여줌으로써,
z-buffer에 z값이 저장될 때에는 object가 아닌 픽셀 별로 데이터가 저장된다는 것을 직관적으로 보여준다.
또한 Depth test 기능을 on/off 할 수 있는 버튼을 추가하여, Depth Test기능을 사용하지 않으면,
그리지 말아야 할 부분도 그리게 되어 사용자에게 혼란을 가져다 줄 수 있다는 점을 보여주고 싶었다.
File added
This diff is collapsed.
<!--(CC-NC-BY)LEEDONGHEON2019-->
<html>
<head>
<title>Ajou-CG</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="gl-matrix.js"></script>
<script type="text/javascript" src="trCube
.js">
</script>
<style>
#test_btn1{
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
margin-right:-4px;
}
#test_btn2{
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
margin-left:-3px;
}
#btn_group button{
border: 1px solid skyblue;
background-color: rgba(0,0,0,0);
color: skyblue;
padding: 5px;
}
#btn_group button:hover{
color:white;
background-color: skyblue;
}
</style>
</head>
<body onload="main()">
<p style="font-size:30px";>
Hidden Surface Removal - Z Buffer
</p><br>
<canvas id="helloapicanvas" style="border: none;" width="400" height="400"></canvas>
<br>
Z-buffer stores Z-values per pixel, not an object.<br>
Thus, when the triangle and square intersect,<Br>
the pixel of triangle which is farther from User is hidden faster<br><br>
<div id="btn_group">
<!-Increase square's z-value by 0.1 -->
<button onclick="sq_trZinc()" style="width: 150px; height: 30px;">Square Z + 0.1</button>
<!-Decrease square's z-value by 0.1 -->
<button onclick="sq_trZdec()" style="width: 150px; height: 30px;">Sqaure Z - 0.1</button><br>
<!-Increase Triangle's z-value by 0.1 -->
<button onclick="tri_trZinc()" style="width: 150px; height: 30px;">Triangle Z + 0.1</button>
<!-Decrease square's z-value by 0.1 -->
<button onclick="tri_trZdec()" style="width: 150px; height: 30px;">Triangle Z - 0.1</button><br>
<!-Toggle Depth test method-->
<button onclick="toggle_depthtest()" style="width: 150px; height: 30px;">ON/OFF Depth test</button>
</div>
</body>
</html>
//(CC-NC-BY)LEEDONGHEON2019
var gl;
function testGLError(functionLastCalled) {
var lastError = gl.getError();
if (lastError != gl.NO_ERROR) {
alert(functionLastCalled + " failed (" + lastError + ")");
return false;
}
return true;
}
function initialiseGL(canvas) {
try {
// Try to grab the standard context. If it fails, fallback to experimental
gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
gl.viewport(0, 0, canvas.width, canvas.height);
}
catch (e) {
}
if (!gl) {
alert("Unable to initialise WebGL. Your browser may not support it");
return false;
}
return true;
}
var shaderProgram;
function initialiseBuffer() {
var vertexData = [
//Initialize the vertex of square
-0.5, -0.5, 0.3, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0,//3
0.5, -0.5, 0.3, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,//1
-0.5, 0.5, 0.3, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,//2
-0.5, 0.5, 0.3, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0,//3
0.5, -0.5, 0.3, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,//2
0.5, 0.5, 0.3, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0,//4
//Initiallize the vertex of Triangle
-0.6, -0.3, 0.6, 0.3, 0.0, 0.2, 0.1, 0.0, 1.0,//3
0.6, -0.3, 0.6, 0.3, 0.0, 0.2, 0.1, 1.0, 1.0,//1
0.0, 0.6, 0.3, 0.3, 0.0, 0.2, 0.1, 1.0, 1.0,//2
];
// Generate a buffer object
gl.vertexBuffer = gl.createBuffer();
// Bind buffer as a vertex buffer so we can fill it with data
gl.bindBuffer(gl.ARRAY_BUFFER, gl.vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexData), gl.STATIC_DRAW);
return testGLError("initialiseBuffers");
}
function initialiseShaders() {
var fragmentShaderSource = '\
varying mediump vec4 color; \
void main(void) \
{ \
gl_FragColor = 1.0 * color;\
}';
gl.fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(gl.fragShader, fragmentShaderSource);
gl.compileShader(gl.fragShader);
if (!gl.getShaderParameter(gl.fragShader, gl.COMPILE_STATUS)) {
alert("Failed to compile the fragment shader.\n" + gl.getShaderInfoLog(gl.fragShader));
return false;
}
var vertexShaderSource = '\
attribute highp vec3 myVertex; \
attribute highp vec4 myColor; \
attribute highp vec2 myUV; \
uniform mediump mat4 Pmatrix; \
uniform mediump mat4 Vmatrix; \
uniform mediump mat4 Mmatrix; \
varying mediump vec4 color; \
varying mediump vec2 texCoord;\
void main(void) \
{ \
gl_Position = Pmatrix*Vmatrix*Mmatrix*vec4(myVertex, 1.0);\
color = myColor;\
texCoord = myUV; \
}';
gl.vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(gl.vertexShader, vertexShaderSource);
gl.compileShader(gl.vertexShader);
if (!gl.getShaderParameter(gl.vertexShader, gl.COMPILE_STATUS)) {
alert("Failed to compile the vertex shader.\n" + gl.getShaderInfoLog(gl.vertexShader));
return false;
}
gl.programObject = gl.createProgram();
// Attach the fragment and vertex shaders to it
gl.attachShader(gl.programObject, gl.fragShader);
gl.attachShader(gl.programObject, gl.vertexShader);
// Bind the custom vertex attribute "myVertex" to location 0
gl.bindAttribLocation(gl.programObject, 0, "myVertex");
gl.bindAttribLocation(gl.programObject, 1, "myColor");
gl.bindAttribLocation(gl.programObject, 2, "myUV");
// Link the program
gl.linkProgram(gl.programObject);
if (!gl.getProgramParameter(gl.programObject, gl.LINK_STATUS)) {
alert("Failed to link the program.\n" + gl.getProgramInfoLog(gl.programObject));
return false;
}
gl.useProgram(gl.programObject);
return testGLError("initialiseShaders");
}
// FOV, Aspect Ratio, Near, Far
function get_projection(angle, a, zMin, zMax) {
var ang = Math.tan((angle*.5)*Math.PI/180);//angle*.5
return [
0.5/ang, 0 , 0, 0,
0, 0.5*a/ang, 0, 0,
0, 0, -(zMax+zMin)/(zMax-zMin), -1,
0, 0, (-2*zMax*zMin)/(zMax-zMin), 0 ];
}
var proj_matrix = get_projection(30, 1.0, 1, 5.0);
var mov_matrix = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1];
var view_matrix = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1];
// translating z
view_matrix[14] = view_matrix[14]-2;//zoom
function identity$3(out) {
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = 1;
out[6] = 0;
out[7] = 0;
out[8] = 0;
out[9] = 0;
out[10] = 1;
out[11] = 0;
out[12] = 0;
out[13] = 0;
out[14] = 0;
out[15] = 1;
return out;
}
function fromTranslation$2(out, v) {
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = 1;
out[6] = 0;
out[7] = 0;
out[8] = 0;
out[9] = 0;
out[10] = 1;
out[11] = 0;
out[12] = v[0];
out[13] = v[1];
out[14] = v[2];
out[15] = 1;
return out;
}
function translate$2(out, a, v) {
var x = v[0],
y = v[1],
z = v[2];
var a00, a01, a02, a03;
var a10, a11, a12, a13;
var a20, a21, a22, a23;
if (a === out) {
out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
} else {
a00 = a[0];
a01 = a[1];
a02 = a[2];
a03 = a[3];
a10 = a[4];
a11 = a[5];
a12 = a[6];
a13 = a[7];
a20 = a[8];
a21 = a[9];
a22 = a[10];
a23 = a[11];
out[0] = a00;
out[1] = a01;
out[2] = a02;
out[3] = a03;
out[4] = a10;
out[5] = a11;
out[6] = a12;
out[7] = a13;
out[8] = a20;
out[9] = a21;
out[10] = a22;
out[11] = a23;
out[12] = a00 * x + a10 * y + a20 * z + a[12];
out[13] = a01 * x + a11 * y + a21 * z + a[13];
out[14] = a02 * x + a12 * y + a22 * z + a[14];
out[15] = a03 * x + a13 * y + a23 * z + a[15];
}
return out;
}
toggle=2; //Initialize the value of 'toggle' which used in 'toggle_depthtest()'
//Variables for used in Translation.
sq_transX = 0.0;
sq_transZ= 0.0;
sq_transY=0.0;
tri_transX=0.0;
tri_transY=0.0;
tri_transZ=0.0;
frames = 1;
//Vector variables for used in Transalation.
var trans_sq_vec;
var trans_tri_vec;
//method for toggle the variable-'toggle' to use 'ON/OFF DEPTH_TEST' button.
function toggle_depthtest(){
if(toggle==1){
toggle=0;
return;
}
else {
toggle=1;
return;
}
}
function sq_trZinc(){
sq_transZ+=0.01;
}
function sq_trZdec(){
sq_transZ-=0.01;
}
function tri_trZinc(){
tri_transZ+=0.01;
}
function tri_trZdec(){
tri_transZ-=0.01;
}
function renderScene() {
//console.log("Frame "+frames+"\n");
frames += 1 ;
rotAxis = [1,1,0];
var Pmatrix = gl.getUniformLocation(gl.programObject, "Pmatrix");
var Vmatrix = gl.getUniformLocation(gl.programObject, "Vmatrix");
var Mmatrix = gl.getUniformLocation(gl.programObject, "Mmatrix");
gl.uniformMatrix4fv(Pmatrix, false, proj_matrix);
gl.uniformMatrix4fv(Vmatrix, false, view_matrix);
if (!testGLError("gl.uniformMatrix4fv")) {
return false;
}
gl.enableVertexAttribArray(0);
gl.vertexAttribPointer(0, 3, gl.FLOAT, gl.FALSE, 36, 0);
gl.enableVertexAttribArray(1);
gl.vertexAttribPointer(1, 4, gl.FLOAT, gl.FALSE, 36, 12);
gl.enableVertexAttribArray(2);
gl.vertexAttribPointer(2, 2, gl.FLOAT, gl.FALSE, 36, 28);
if (!testGLError("gl.vertexAttribPointer")) {
return false;
}
if(toggle==2){
gl.enable(gl.DEPTH_TEST);
toggle=1;
}
else if(toggle==1){
gl.enable(gl.DEPTH_TEST);
}
else if(!toggle){
gl.disable(gl.DEPTH_TEST);
}
gl.depthFunc(gl.LEQUAL);
// gl.enable(gl.CULL_FACE);
// gl.enable(gl.BLEND);
gl.clearColor(1.0, 0.8, 0.8, 1.0);
gl.clearDepth(1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
//DrawSquare
identity$3(mov_matrix);
trans_sq_vec=[sq_transX,sq_transY,sq_transZ];
fromTranslation$2(mov_matrix,trans_sq_vec);
gl.uniformMatrix4fv(Mmatrix, false, mov_matrix);
gl.drawArrays(gl.TRIANGLES, 0, 6);
mov_matrix_child=mov_matrix.slice();
//DrawTriangle
trans_tri_vec=[tri_transX,tri_transY,tri_transZ];
fromTranslation$2(mov_matrix,trans_tri_vec);
gl.uniformMatrix4fv(Mmatrix, false, mov_matrix);
gl.drawArrays(gl.TRIANGLES, 6, 3);
if (!testGLError("gl.drawArrays")) {
return false;
}
return true;
}
function main() {
var canvas = document.getElementById("helloapicanvas");
console.log("Start");
if (!initialiseGL(canvas)) {
return;
}
if (!initialiseBuffer()) {
return;
}
if (!initialiseShaders()) {
return;
}
// Render loop
requestAnimFrame = (
function () {
// return window.requestAnimationFrame || window.webkitRequestAnimationFrame
// || window.mozRequestAnimationFrame ||
return function (callback) {
// console.log("Callback is"+callback);
window.setTimeout(callback, 10, 10); };
})();
(function renderLoop(param) {
if (renderScene()) {
// Everything was successful, request that we redraw our scene again in the future
requestAnimFrame(renderLoop);
}
})();
}
<!--
WebGL 1.0 Tutorial - Phong Shading
CC-NC-BY SeongHeon Kim (201421109)
@author SeongHeon Kim
@date 2019-06-22
@WebGL applet by Prof. Thorsten Thormahlen. Modified by SeongHeon Kim for educational purpose
@http://www.mathematik.uni-marburg.de/~thormae/lectures/graphics1/code/WebGLShaderLightMat/ShaderLightMat.html
-->
<html>
<head>
<title>201421109_CGproject</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<script type="text/javascript" src="201421109_phong_shading.js"> </script>
<!-- change mode script -->
<script type="text/javascript">
function modeChanged() {
var mode = document.getElementById("select_mode").value;
modeVal = mode;
}
</script>
<!-- slider style -->
<style>
.slidecontainer {
width: 100%;
}
.slider {
-webkit-appearance: none;
width: 100%;
height: 25px;
background: #d3d3d3;
outline: none;
opacity: 0.7;
-webkit-transition: .2s;
transition: opacity .2s;
}
.slider:hover {
opacity: 1;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 25px;
height: 25px;
background: #4CAF50;
cursor: pointer;
}
.slider::-moz-range-thumb {
width: 25px;
height: 25px;
background: #4CAF50;
cursor: pointer;
}
</style>
<!-- tab style -->
<style>
body {font-family: Arial;}
/* Style the tab */
.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f1f1f1;
}
/* Style the buttons inside the tab */
.tab button {
background-color: inherit;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 14px 16px;
transition: 0.3s;
font-size: 17px;
}
/* Change background color of buttons on hover */
.tab button:hover {
background-color: #ddd;
}
/* Create an active/current tablink class */
.tab button.active {
background-color: #ccc;
}
/* Style the tab content */
.tabcontent {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
</style>
</head>
<body onload="main()">
<h1>WebGL Project: Phong Shading tutorial</h1>
<div style="max-width: 550px;">
<p>
This project is webGL shading tutorial.<br>
You can learn about phong shading by selecting each component.
</p>
</div>
<h3>Functions</h3>
<p>Click and check function which tutorial provide:</p>
<!-- tab -->
<div class="tab">
<button class="tablinks" onclick="openCity(event, 'Animation')">Animation</button>
<button class="tablinks" onclick="openCity(event, 'Mode')">Mode</button>
<button class="tablinks" onclick="openCity(event, 'Coefficient')">Coefficient</button>
<button class="tablinks" onclick="openCity(event, 'Code')">Code</button>
</div>
<div id="Animation" class="tabcontent">
<h3>Animation</h3>
<p>To start or stop rotating using 'Animation Rotate' and 'Stop Rotate' button. </p>
</div>
<div id="Mode" class="tabcontent">
<h3>Mode</h3>
<p>To chage mode. Phong, Ambient only, Diffuse Only, Specular Only, NormalColor mode are provided.</p>
<p>NormalColor mode use normal vector as ambient and diffuse color.
</div>
<div id="Coefficient" class="tabcontent">
<h3>Coefficient</h3>
<p>To chage Coefficient. You can learn aobut particular reflection's role in phong shading.</p>
</div>
<div id="Code" class="tabcontent">
<h3>Code</h3>
<p>Using provided shder code. You can implement your own phong shading.</p>
<p>Editing and Renadering code are not provided.</p>
</div>
<script>
function openCity(evt, cityName) {
var i, tabcontent, tablinks;
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
tablinks = document.getElementsByClassName("tablinks");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
document.getElementById(cityName).style.display = "block";
evt.currentTarget.className += " active";
}
</script>
<!-- canvas for WebGL -->
<p>
<canvas id="helloapicanvas" style="border: none;" width="400" height="400"></canvas>
<!-- rotation button -->
<p>
<button onclick="animRotate()">Animation Rotate</button>
<button onclick="stopRotate()">Stop Rotate</button>
<!-- mode change menue -->
<p>
<select onchange="modeChanged()" id="select_mode">
<option value="1">normal mode</option>
<option value="2">ambient only</option>
<option value="3">diffuse only</option>
<option value="4">specular only</option>
<option value="5">NormalColor mode</option>
</select>
<!-- coefficient slider -->
<p>
<div class="slidecontainer1">
<p>Ambient reflection coefficient (Ka): <span id="Ka"></span></p>
<input type="range" min="0" max="100" value="100" id="KaSlider">
</div>
<script>
var slider = document.getElementById("KaSlider");
var output = document.getElementById("Ka");
slider.oninput = function() {
KaVal = document.getElementById("KaSlider").value / 100;
}
</script>
<div class="slidecontainer2">
<p>Diffuse reflection coefficient (Kd): <span id="Kd"></span></p>
<input type="range" min="0" max="100" value="100" id="KdSlider">
</div>
<script>
var slider = document.getElementById("KdSlider");
var output = document.getElementById("Kd");
slider.oninput = function() {
KdVal = document.getElementById("KdSlider").value / 100;
}
</script>
<div class="slidecontainer3">
<p>Specular reflection coefficient (Ks): <span id="Ks"></span></p>
<input type="range" min="0" max="100" value="100" id="KsSlider">
</div>
<script>
var slider = document.getElementById("KsSlider");
var output = document.getElementById("Ks");
slider.oninput = function() {
KsVal = document.getElementById("KsSlider").value / 100;
}
</script>
<!-- shader code viewer-->
<P>
<table border="0" class="maintable" cellpadding="3px" cellspacing="3px">
<tr style="vertical-align: top;">
<!-- vertex shader code -->
<td>Vertex shader: <br>
<textarea cols="80" rows="30" class="code_input_vert" id="code_vert">
attribute highp vec3 myVertex;
attribute highp vec4 myColor;
attribute highp vec2 myUV;
attribute highp vec3 myNormal;
attribute vec2 inputTexCoord;
uniform mediump mat4 Pmatrix;
uniform mediump mat4 Vmatrix;
uniform mediump mat4 Mmatrix;
uniform mediump mat4 Nmatrix;
varying mediump vec4 color;
varying mediump vec2 texCoord;
varying mediump vec3 normalInterp;
varying vec3 vertPos;
void main(void)
{
vec4 vertPos4 = Vmatrix*vec4(myVertex, 1.0);
vertPos = vec3(vertPos4) / vertPos4.w;
normalInterp = vec3(Mmatrix * vec4(myNormal, 0.0));
gl_Position = Pmatrix*Vmatrix*Mmatrix*vec4(myVertex, 1.0);
};
</textarea>
<p id="code_vert_error" style="width: 300px;"></p>
</td>
<!-- fragment shader code -->
<td>Fragment shader: <br>
<textarea cols="80" rows="30" class="code_input" id="code_frag">
precision mediump float;
varying vec3 normalInterp;
varying vec3 vertPos;
uniform int mode;
uniform float Ka;
uniform float Kd;
uniform float Ks;
const vec3 lightPos = vec3(5.0,1.0,1.0);
const vec3 ambientColor = vec3(0.3, 0.0, 0.0);
const vec3 diffuseColor = vec3(0.7, 0.0, 0.0);
const vec3 specColor = vec3(1.0, 1.0, 1.0);
void main()
{
vec3 normal = normalize(normalInterp);
vec3 lightDir = normalize(lightPos - vertPos);
vec3 reflectDir = reflect(-lightDir, normal);
vec3 viewDir = normalize(-vertPos);
float lambertian = max(dot(normal, lightDir), 0.0);
float specular = 0.0;
if(lambertian > 0.0)
{
float specAngle = max(dot(reflectDir, viewDir), 0.0);
specular = pow(specAngle, 4.0);
}
gl_FragColor = vec4(Ka*ambientColor + Kd*lambertian*diffuseColor + Ks*specular*specColor, 1.0);
if(mode == 2) gl_FragColor = vec4(Ka*ambientColor, 1.0);
if(mode == 3) gl_FragColor = vec4(Kd*lambertian*diffuseColor, 1.0);
if(mode == 4) gl_FragColor = vec4(Ks*specular*specColor, 1.0);
}
</textarea>
<p id="code_frag_error" style="width: 300px;"></p>
</td>
</tr>
</table>
</body>
</html>
This diff is collapsed.
# CG_Project : Phong Shading tutorial
CC-NC-BY SeongHeon Kim
This Porject is WebGL shading tutorial
You can learn aobut 'Phong Shading 'by selecting ambient, diffuse and specular
or control coefficient of each of them.
You can also animate object and change color.
But,
select color (ambient, diffuse, specular)
change vertex or fragment shader and re render scene are not provided.
However,
Copy vertex and fragment shader code are provided.
You can easily implement your own Phong Shading Object !
This program are tested in google chrome invironment only.
other web browser would not support WebGL
# Features
- Animation
> To start or stop rotating using 'Animation Rotate' and 'Stop Rotate' button.
> Also, you can speed up rotation of cube clicking button repetedly
- Change Mode
> Phong shading
> Ambient Only
> Diffuse Only
> Specular Only
> Normal Color Mode (use normal vector as ambient and diffuse color)
- Control Coefficient
> control coefficient of Ambient, Diffuse, Specular
> You can change intensity of each color
- Shader Code
> You can copy shader code which tutorial used
> Also, you can easily know about Phong shading's implementaion
# What is Phong shading
![Phong](./image/phong.png)
The Phong reflection model (also called Phong illumination or Phong lighting) is an empirical model of the local illumination of points on a surface.
In 3D computer graphics, it is sometimes referred to as "Phong shading", in particular if the model is used with the interpolation method of the same name and in the context of pixel shaders or other places where a lighting calculation can be referred to as “shading”.
Phong interpolation is not a part of this tutorial.
# Implementation of Phong shading
## vertex shader
* vertes shader source code
* phong shading calculate light and color in fragment shader
* So vertex shader only have goal that calculate position of vertex
* and assign value for varying using attribute
```
attribute highp vec3 myVertex;
attribute highp vec4 myColor;
attribute highp vec2 myUV;
attribute highp vec3 myNormal;
attribute vec2 inputTexCoord;
uniform mediump mat4 Pmatrix;
uniform mediump mat4 Vmatrix;
uniform mediump mat4 Mmatrix;
uniform mediump mat4 Nmatrix;
varying mediump vec4 color;
varying mediump vec2 texCoord;
varying mediump vec3 normalInterp;
varying vec3 vertPos;
void main(void)
{
vec4 vertPos4 = Vmatrix*vec4(myVertex, 1.0);
vertPos = vec3(vertPos4) / vertPos4.w;
normalInterp = vec3(Mmatrix * vec4(myNormal, 0.0));
gl_Position = Pmatrix*Vmatrix*Mmatrix*vec4(myVertex, 1.0);
}
```
## fragment shader
* varying comes form vertex shader
* normalInterp was Surfce normal vector
* vertPos was a Vertex Position
* uniform was set as global variable and it will be changed by HTML
* const vec3 for light position, ambientColor, diffuseColor, specularColor
* normal vector was normalize to use
* lightDir was Light direction from obj
* reflectDir was reflected light vector
* viewDir was vector to viewer
* Phong shading use labercian suface which is perfectly diffuse reflector
So we use Labert's cosine Law to calculate specular
* Phong Shading = Ambient + Diffuse + Specular
Ka, Kd, Ks was coefficient for tutorial study
```
precision mediump float;
varying vec3 normalInterp;
varying vec3 vertPos;
uniform int mode;
uniform float Ka;
uniform float Kd;
uniform float Ks;
const vec3 lightPos = vec3(5.0,1.0,1.0);
const vec3 ambientColor = vec3(0.3, 0.0, 0.0);
const vec3 diffuseColor = vec3(0.7, 0.0, 0.0);
const vec3 specColor = vec3(1.0, 1.0, 1.0);
void main()
{
vec3 normal = normalize(normalInterp);
vec3 lightDir = normalize(lightPos - vertPos);
vec3 reflectDir = reflect(-lightDir, normal);
vec3 viewDir = normalize(-vertPos);
float lambertian = max(dot(normal, lightDir), 0.0);
float specular = 0.0;
if(lambertian > 0.0)
{
float specAngle = max(dot(reflectDir, viewDir), 0.0);
specular = pow(specAngle, 4.0);
}
gl_FragColor = vec4(Ka*ambientColor + Kd*lambertian*diffuseColor + Ks*specular*specColor, 1.0);
if(mode == 2) gl_FragColor = vec4(Ka*ambientColor, 1.0);
if(mode == 3) gl_FragColor = vec4(Kd*lambertian*diffuseColor, 1.0);
if(mode == 4) gl_FragColor = vec4(Ks*specular*specColor, 1.0);
}
```
# result
## Phong
![result_phong](./image/result_phong.png)
## Ambient Only
![result_ambient](./image/result_ambient.png)
## Diffuse Only
![result_diffuse](./image/result_diffuse.png)
## Specular Only
![result_specular](./image/result_specular.png)
## Normal Color
![result_normalColor](./image/result_normalColor.png)
# reference
WebGL applet by Prof. Thorsten Thormahlen. Modified by SeongHeon Kim for educational purpose
\ No newline at end of file
cg_project @ c71eb4c9
Subproject commit c71eb4c9d1f6781035246a9d47045d4977f63bac
student2019/201421109/image/phong.png

60.8 KiB

student2019/201421109/image/result_ambient.png

6.99 KiB

student2019/201421109/image/result_diffuse.png

10.5 KiB

student2019/201421109/image/result_normalColor.png

21.9 KiB

student2019/201421109/image/result_phong.png

17.4 KiB

student2019/201421109/image/result_specular.png

15.8 KiB

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment