이전의 예제 004. WebGL - Prac03 - DrawPoints, DrawLines, DrawTriangles. 에서 단색의 삼각형을 렌더링하여 보았다. 이는 아래와 같이 Fragment Shader에서 붉은색으로만 색상값을 지정하고 있기 때문이다.
이제부터 단색이 아닌, 사용자가 직접 각 Vertex 마다 다른 색상을 지정해 보도록 하겠다.
우선 위와같이 작성되어 있던 Fragment Shader 코드를 아래와 같이 수정한다.
위의 코드에 사용된, 변수명 vColor의 값은 Vertex에서 지정할것이다.
두번째로, Vertex Shader 코드를 아래와 같이 수정한다.
이전에 작성했던 코드에 4~5라인 정도가 추가되었다. 위의 Vertex Shader 코드를 보면, Fragment Shader코드에서 사용하게될 vColor값을 설정하는 것을 볼 수 있다. Vertex/Fragment Shader 코드 모두 varying vec4 vColor;의 구문을 지니고 있음 기억해 둔다. vColor의 값을 aColor의 값을 그대로 복사하고 있는데, aColor이 선언 방식이 버텍스의 위치값으로 사용되었던 aPos와 동일함을 볼 수 있다. 이전에 aPos에 대해 수행했던 그대로, aColor역시 변수에 대한 핸들을 얻어와야 한다.
변수명 vertexColorAttribute는 자신의 프로그램 구조에 맞는 적당한 곳에 두면된다.
여기까지 코딩이 완료되었다면, Shader에게 Color 정보를 넘기기 위한 준비작업이 끝난것이다.
이제, Color 정보를 작성해 보도록 하자.
앞서 버턱스 좌표값을 위해 수행하였던 구문와 동일한 함수들을 사용한 것을 볼 수 있다. 1.버퍼를 만들고, 2.버퍼를바인딩하고, 3. 바인딩된 버퍼에 값을 쓰는 과정이 나타나 있다. 렌더링될 버텍스가 3개이므로 색상의 개수도 3개인 것에 유의한다. 만약 생상의 개수가 더 많으면 아무런 의미가 없고, 적다면 흰색으로 렌더링될 것이다.
여기까지의 코딩은, Shader에게 넘겨줄 Color 정보 채우기를 완료한 상태이다.
이제, Shader에게 Color 정보를 넘겨 보도록 하겠다.
앞서 생성하였던 색상 버퍼(triangleColorBuffer)를 vertexColorAttribute라는 핸들을 통해 Shader로 전담함을 볼 수 있다. Color 값은 RGBA의 4개의 채널을 갖고, 데이터 타입은 float형이다.
최종 결과는 아래와 같다.

전체 코드는 아래와 같다.
<script id="FragmentShader" type="x-shader/x-vertex">
void main(){
gl_FragColor= vec4(1.0, 0.0, 0.0, 1.0);
}
</script>
이제부터 단색이 아닌, 사용자가 직접 각 Vertex 마다 다른 색상을 지정해 보도록 하겠다.
우선 위와같이 작성되어 있던 Fragment Shader 코드를 아래와 같이 수정한다.
<script id="FragmentShader" type="x-shader/x-vertex">
precision mediump vec4;
varying vec4 vColor;
void main(){
gl_FragColor= vColor;
}
</script>
위의 코드에 사용된, 변수명 vColor의 값은 Vertex에서 지정할것이다.
두번째로, Vertex Shader 코드를 아래와 같이 수정한다.
<script id="VertexShader" type="x-shader/x-vertex">
attribute vec3 aPos;
attribute vec4 aColor;
varying vec4 vColor;
void main(){
gl_Position= vec4(aPos, 1.0);
vColor= aColor;
}
</script>
이전에 작성했던 코드에 4~5라인 정도가 추가되었다. 위의 Vertex Shader 코드를 보면, Fragment Shader코드에서 사용하게될 vColor값을 설정하는 것을 볼 수 있다. Vertex/Fragment Shader 코드 모두 varying vec4 vColor;의 구문을 지니고 있음 기억해 둔다. vColor의 값을 aColor의 값을 그대로 복사하고 있는데, aColor이 선언 방식이 버텍스의 위치값으로 사용되었던 aPos와 동일함을 볼 수 있다. 이전에 aPos에 대해 수행했던 그대로, aColor역시 변수에 대한 핸들을 얻어와야 한다.
vertexColorAttribute= gl.getAttribLocation(shaderProgram, "aColor");
if( vertexColorAttribute==-1 ){
alert("Unable to find Vertex Color Attribute Location.");
return false;
}
gl.enableVertexAttribArray(vertexColorAttribute);
변수명 vertexColorAttribute는 자신의 프로그램 구조에 맞는 적당한 곳에 두면된다.
여기까지 코딩이 완료되었다면, Shader에게 Color 정보를 넘기기 위한 준비작업이 끝난것이다.
이제, Color 정보를 작성해 보도록 하자.
var colorAry= [
1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0
];
var triangleColorBuffer= gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, triangleColorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colorAry), gl.STATIC_DRAW);
앞서 버턱스 좌표값을 위해 수행하였던 구문와 동일한 함수들을 사용한 것을 볼 수 있다. 1.버퍼를 만들고, 2.버퍼를바인딩하고, 3. 바인딩된 버퍼에 값을 쓰는 과정이 나타나 있다. 렌더링될 버텍스가 3개이므로 색상의 개수도 3개인 것에 유의한다. 만약 생상의 개수가 더 많으면 아무런 의미가 없고, 적다면 흰색으로 렌더링될 것이다.
여기까지의 코딩은, Shader에게 넘겨줄 Color 정보 채우기를 완료한 상태이다.
이제, Shader에게 Color 정보를 넘겨 보도록 하겠다.
gl.bindBuffer(gl.ARRAY_BUFFER, triangleColorBuffer);
gl.vertexAttribPointer(vertexColorAttribute, 4, gl.FLOAT, false, 0, 0);
앞서 생성하였던 색상 버퍼(triangleColorBuffer)를 vertexColorAttribute라는 핸들을 통해 Shader로 전담함을 볼 수 있다. Color 값은 RGBA의 4개의 채널을 갖고, 데이터 타입은 float형이다.
최종 결과는 아래와 같다.
전체 코드는 아래와 같다.
<html>
<head>
<title>WebGL - Prac05 - DrawTriangleWithColor</title>
<script type="text/javascript">
var gl;
var vertexPositionAttribute;
var vertexColorAttribute;
function start(){
if( !initWebGL() ){
return;
}
if( !initShader() ){
return;
}
var verAry= [
0.0, 0.0, 0.0,
0.5, 0.0, 0.0,
0.0, 1.0, 0.0
];
var colorAry= [
1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0
];
var triangleVertBuffer= gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verAry), gl.STATIC_DRAW);
//색상 버퍼 생성
var triangleColorBuffer= gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, triangleColorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colorAry), gl.STATIC_DRAW);
gl.clearColor(0.4, 0.5, 0.6, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertBuffer);
gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
//색상 버퍼를 Shder에 넘김
gl.bindBuffer(gl.ARRAY_BUFFER, triangleColorBuffer);
gl.vertexAttribPointer(vertexColorAttribute, 4, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, 3);
alert("finish!");
}
function initWebGL(){
var canvas= document.getElementById("WebGL-Canvas");
if( !canvas ){
alert("Can't find WebGL-Canvas.");
return false;
}
try{
gl= canvas.getContext("experimental-webgl");
}catch(e){
}
if( !gl ){
alert("Unable to initialize WebGL. Your browser may not support it.");
return false;
}
return true;
}
function initShader(){
var vertexShaderDesc= getShader("VertexShader");
var vertexShader= gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderDesc);
gl.compileShader(vertexShader);
if( !gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS) ){
alert("Error(VertexShader): " + gl.getShaderInfoLog(vertexShader));
return false;
}
var fragmentShaderDesc= getShader("FragmentShader");
var fragmentShader= gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderDesc);
gl.compileShader(fragmentShader);
if( !gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS) ){
alert("Error(PixelShader): " + gl.getShaderInfoLog(fragmentShader));
return false;
}
var shaderProgram= gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if( !gl.getProgramParameter(shaderProgram, gl.LINK_STATUS) ){
alert("Unagle to initialize the shader program.");
return false;
}
gl.useProgram(shaderProgram);
vertexPositionAttribute= gl.getAttribLocation(shaderProgram, "aPos");
if( vertexPositionAttribute==-1 ){
alert("Unable to find Vertex Attribute Location.");
return false;
}
gl.enableVertexAttribArray(vertexPositionAttribute);
//색상 값을 전달할, GLSL에서의 변수명 "aColor"에 대한 핸들을 얻어온다.
vertexColorAttribute= gl.getAttribLocation(shaderProgram, "aColor");
if( vertexColorAttribute==-1 ){
alert("Unable to find Vertex Color Attribute Location.");
return false;
}
gl.enableVertexAttribArray(vertexColorAttribute);
return true;
}
function getShader(id){
var shaderScript= document.getElementById(id);
if( !shaderScript ){
alert("Unable to get shader script. id='" + id + "'");
return null;
}
var shaderDesc= "";
var currentChild= shaderScript.firstChild;
while( currentChild ){
if( currentChild.nodeType==3 ){
shaderDesc+= currentChild.textContent;
}
currentChild= currentChild.nextSibling;
}
return shaderDesc;
}
</script>
<script id="VertexShader" type="x-shader/x-vertex">
attribute vec3 aPos;
attribute vec4 aColor;
varying vec4 vColor;
void main(){
gl_Position= vec4(aPos, 1.0);
vColor= aColor;
}
</script>
<script id="FragmentShader" type="x-shader/x-vertex">
precision mediump vec4;
varying vec4 vColor;
void main(){
gl_FragColor= vColor;
}
</script>
</head>
<body onload="start()">
<canvas id="WebGL-Canvas" style="border: 1px solid green" width="400" height="300">
Your browser doesn't appear to support the HTML5 <canvas> element.
</canvas>
</body>
</html>