WebGL - 색상: 3D 그래픽에 생명을 더하는 초보자 가이드

안녕하세요, WebGL 열심히 공부하시는 분들! 이 이국적인 색의 여정에서 여러분의 안내자로서 기쁩니다. 컴퓨터 그래픽을 가르쳐온 10년 넘는 경험을 가진 사람으로서, 3D 시ーン에 색상을 추가하는 것은 흑백 사진에 생명을 불어넣는 것과 같다고 말할 수 있습니다. 마법 같은 일이고, 오늘 우리는 그 마법을 함께 풀어보겠습니다!

WebGL - Colors

WebGL에서 색상 이해하기

색상을 적용하기에 앞서, 잠시 WebGL의 맥락에서 색상이 무엇을 의미하는지 이해해 보겠습니다. 이 디지털 세계에서 색상은 RGB(적, 녹, 청) 색상 모델을 사용하여 표현됩니다. 각 색상은 이 세 가지 기본 색상의 조합으로, 값의 범위는 0.0에서 1.0까지입니다.

예를 들어:

  • 적: (1.0, 0.0, 0.0)
  • 녹: (0.0, 1.0, 0.0)
  • 청: (0.0, 0.0, 1.0)
  • 白: (1.0, 1.0, 1.0)
  • 黑: (0.0, 0.0, 0.0)

물감을 섞는 것처럼 생각하시면 됩니다. 하지만 이번에는 빛을 사용합니다. 무한한 팔레트를 손에 들고 있는 디지털 예술가처럼 생각하시면 됩니다!

WebGL에서 색상 적용하기

기본 개념을 이해했으므로, 이제 WebGL에서 색상을 적용하는 방법에 손을 댄다면 어떨까요?

색상 적용 단계

1.顶点着色器에서 색상 속성 정의하기 2. JavaScript 코드에서 색상 데이터 전달하기 3. 프래그먼트着色器에서 색상 사용하기

이 단계들을 코드 예제와 함께 설명해 보겠습니다.

Step 1: Define Color Attributes in Vertex Shader

먼저, 우리의顶点着色器가 색상을 처리할 수 있도록 설정해야 합니다. 다음과 같이 합니다:

attribute vec4 a_Position;
attribute vec4 a_Color;
varying vec4 v_Color;
void main() {
gl_Position = a_Position;
v_Color = a_Color;
}

이 코드에서 우리는 a_Color 속성을 정의하여 색상 데이터를 받고, v_Color 변하는 변수를 사용하여 색상을 프래그먼트着色器로 전달합니다. 이 것은 JavaScript 코드에서 색상 데이터를 픽셀로 전달하는 색상 파이프라인을 설정하는 것과 같습니다!

Step 2: Pass Color Data from JavaScript

이제 JavaScript 코드에서 색상 데이터를 셰이더로 전달하는 방법을 보겠습니다:

//顶点와 색상을 정의합니다
var vertices = new Float32Array([
0.0, 0.5, 1.0, 0.0, 0.0,  // Vertex 1: x, y, r, g, b
-0.5, -0.5, 0.0, 1.0, 0.0,  // Vertex 2: x, y, r, g, b
0.5, -0.5, 0.0, 0.0, 1.0   // Vertex 3: x, y, r, g, b
]);

// 버퍼를 생성하고 데이터를 보냅니다
var vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

// WebGL이 버퍼를 어떻게 읽을지 설정합니다
var FSIZE = vertices.BYTES_PER_ELEMENT;
var a_Position = gl.getAttribLocation(program, 'a_Position');
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 5, 0);
gl.enableVertexAttribArray(a_Position);

var a_Color = gl.getAttribLocation(program, 'a_Color');
gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 5, FSIZE * 2);
gl.enableVertexAttribArray(a_Color);

이 코드는 처음에는 복잡해 보일 수 있지만, 간단히 설명하면 다음과 같습니다:

  1. 우리는顶点和 색상을 단일 배열에 정의합니다. 각顶점은 5개의 값이 있습니다: x, y, r, g, b.
  2. 우리는 버퍼를 생성하고 데이터를 보냅니다.
  3. 우리는 WebGL이 이 버퍼를 어떻게 읽을지 설정합니다. 위치(처음 2개의 값)와 색상(마지막 3개의 값).

이것은 옷과 화장품을 짐에.pack하고, 친구에게 정확히 어떻게.open하는 방법을 알려주는 것과 같습니다!

Step 3: Use the Color in Fragment Shader

마지막으로, 프래그먼트着色器에서 색상을 사용합니다:

precision mediump float;
varying vec4 v_Color;
void main() {
gl_FragColor = v_Color;
}

이 간단한 셰이더는顶点着色器에서 전달된 색상을 픽셀에 적용합니다. 이것은 색상이 화면에서 빛나는 최종 단계입니다!

색상 적용 예제

이제 모든 것을 한데 모아 색상이 있는 삼각형을 만들어 보겠습니다.

<!DOCTYPE html>
<html>
<head>
<title>Colorful WebGL Triangle</title>
</head>
<body>
<canvas id="glCanvas" width="640" height="480"></canvas>
<script>
// Vertex shader program
const vsSource = `
attribute vec4 a_Position;
attribute vec4 a_Color;
varying vec4 v_Color;
void main() {
gl_Position = a_Position;
v_Color = a_Color;
}
`;

// Fragment shader program
const fsSource = `
precision mediump float;
varying vec4 v_Color;
void main() {
gl_FragColor = v_Color;
}
`;

function main() {
const canvas = document.querySelector("#glCanvas");
const gl = canvas.getContext("webgl");

if (!gl) {
alert("Unable to initialize WebGL. Your browser or machine may not support it.");
return;
}

// Initialize a shader program
const shaderProgram = initShaderProgram(gl, vsSource, fsSource);

// Get the attribute locations
const programInfo = {
program: shaderProgram,
attribLocations: {
vertexPosition: gl.getAttribLocation(shaderProgram, 'a_Position'),
vertexColor: gl.getAttribLocation(shaderProgram, 'a_Color'),
},
};

// Create the buffer
const buffers = initBuffers(gl);

// Draw the scene
drawScene(gl, programInfo, buffers);
}

function initBuffers(gl) {
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

const positions = [
0.0,  0.5,  1.0, 0.0, 0.0,
-0.5, -0.5,  0.0, 1.0, 0.0,
0.5, -0.5,  0.0, 0.0, 1.0,
];

gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

return {
position: positionBuffer,
};
}

function drawScene(gl, programInfo, buffers) {
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);

gl.useProgram(programInfo.program);

{
const numComponents = 2;  // pull out 2 values per iteration
const type = gl.FLOAT;    // the data in the buffer is 32bit floats
const normalize = false;  // don't normalize
const stride = 20;        // how many bytes to get from one set of values to the next
const offset = 0;         // how many bytes inside the buffer to start from
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position);
gl.vertexAttribPointer(
programInfo.attribLocations.vertexPosition,
numComponents,
type,
normalize,
stride,
offset);
gl.enableVertexAttribArray(
programInfo.attribLocations.vertexPosition);
}

{
const numComponents = 3;
const type = gl.FLOAT;
const normalize = false;
const stride = 20;
const offset = 8;
gl.vertexAttribPointer(
programInfo.attribLocations.vertexColor,
numComponents,
type,
normalize,
stride,
offset);
gl.enableVertexAttribArray(
programInfo.attribLocations.vertexColor);
}

gl.drawArrays(gl.TRIANGLES, 0, 3);
}

function initShaderProgram(gl, vsSource, fsSource) {
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);

const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);

if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram));
return null;
}

return shaderProgram;
}

function loadShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);

if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}

return shader;
}

window.onload = main;
</script>
</body>
</html>

이 코드를 실행하면 적, 녹, 청의顶점을 가진 아름다운 삼각형이 보입니다. 빛의 무지개가 화면에서 살아나는 것처럼 보입니다!

결론

이제 여러분은 WebGL의 색상 세계를 통해 여행을 마친 것입니다. 색상이 무엇인지 이해하고, 3D 그래픽에 어떻게 적용하는지 배웠습니다. 이 기본적인 내용을 배운 것은 시작에 불과합니다. 이제 여러분은 아름답고 생생한 3D 그래픽을 만드는 길에 한 걸음 더 나아갔습니다.

우리 수업을 마치면서, 한 학생이曾经说过, WebGL 색상을 배우는 것은 빛으로 그림을 그리는 것과 같다고 했습니다. 그녀는 정말로 옳았습니다. 그러므로, 내 사랑하는 학생들이여, 디지털 캔버스에 바람의 모든 색상으로 그림을 그리세요!

행복하게 코딩하시고, 여러분의 WebGL 여정이 항상 색상이 가득하길 바랍니다!

Credits: Image by storyset