โ Shader
์
ฐ์ด๋๋ GPU์์ ๋์ํ๋ ์์ ํ๋ก๊ทธ๋จ์ผ๋ก ๊ฐ์ ๊ทธ๋ํฝ ํ์ดํ๋ผ์ธ์ ํน์ ๋ถ๋ถ์ ๋งก์ ์ํํ๋ค.
๊ธฐ๋ณธ์ ์ธ ์๋ฏธ์์ ์
ฐ์ด๋๋ ์
๋ ฅ๊ฐ์ ๋ฐ์ ๋ณํ์์ผ ์ถ๋ ฅ๊ฐ์ ๋ฐํํ๋ ํ๋ก๊ทธ๋จ์ด๋ค.
์
ฐ์ด๋๋ ๋
๋ฆฝ์ ์ธ ํ๋ก๊ทธ๋จ์ผ๋ก ์๋ก ์ํตํ ์ ์์ผ๋ฉฐ ์
๋ ฅ๊ฐ๊ณผ ์ถ๋ ฅ๊ฐ์ ํตํด์๋ง ์ํตํ ์ ์๋ค.
โ GLSL
์
ฐ์ด๋๋ C์ธ์ด์ ๋น์ทํ GLSL๋ก ์์ฑ๋๋ค.
์
ฐ์ด๋๋ ๋ฒ์ ์ ์ธ, ์
์ถ๋ ฅ ๋ณ์, uniform, main ํจ์๋ก ๊ตฌ์ฑ๋๋ค.
์
ฐ์ด๋์ ๋ํ์ ์ธ ๊ตฌ์กฐ
#version version_number
in type in_variable_name;
out type out_variable_name;
uniform type uniform_name;
void main()
{
// ์
๋ ฅ ๊ฐ์ ๋ฐ์ ๊ทธ๋ํฝ ์์
์ฒ๋ฆฌ๋ ๊ฒ์ ์ถ๋ ฅ ๋ณ์๋ก ์ถ๋ ฅ
out_variable_name = weird_stuff_we_processed;
}
- GLSL์ C์ธ์ด์ ๊ฐ์ด ๊ธฐ๋ณธ์ ์ธ ํ์
(int, float, double, uint, bool)์ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ GLSL์ ์ปจํ
์ด๋ ํ์
vector์ matrices๊ฐ ์๋ค.
โ Vector
vector๋ ๊ธฐ๋ณธ์ ์ธ ํ์
์ ์์๋ฅผ 1~4๊ฐ ๊ฐ์ง ์ปจํ
์ด๋์ด๋ค.
- vecn : n๊ฐ์ float ํ์
์์๋ฅผ ๊ฐ์ง๋ vector
- bvecn : n๊ฐ์ boolean ํ์
์์๋ฅผ ๊ฐ์ง๋ vector
- ivecn : n๊ฐ์ integer ํ์
์์๋ฅผ ๊ฐ์ง๋ vector
- uvecn : n๊ฐ์ unsigned integer ํ์
์์๋ฅผ ๊ฐ์ง๋ vector
- dvecn : n๊ฐ์ double ํ์
์์๋ฅผ ๊ฐ์ง๋ vector
ex) vec3 : 3๊ฐ์ float ํ์
์์๋ฅผ ๊ฐ์ง๋ vector
- Vector์ ์์๋ค์ '.' ์ ํตํด ์ ๊ทผํ ์ ์๋ค.
- ์ฒซ ๋ฒ์งธ, ๋ ๋ฒ์งธ, ์ธ ๋ฒ์งธ, ๋ค ๋ฒ์งธ ์์๋ค์ ๊ฐ๊ฐ ์ ๊ทผํ๊ธฐ ์ํด .x, .y, .z, .w๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
- GLSL์์ ์ปฌ๋ฌ๋ rgba๋ฅผ ์ฌ์ฉํ์ฌ ๋ํ๋ผ ์ ์๊ณ , ํ
์ค์ณ ์ขํ๋ stpq๋ฅผ ์ฌ์ฉํ์ฌ ๋ํ๋ผ ์ ์๋ค.
โ Swizzling
Swizzling์ ๋ฒกํฐ ํ์
์ ๋ณ์์์ ๊ตฌ์ฑ ์์๋ฅผ ์ ํํ๊ณ ์ฌ๋ฐฐ์นํ๋ ๊ธฐ๋ฅ์ผ๋ก ์ฝ๋์ ๊ฐ๊ฒฐ์ฑ์ ๋์ด๊ณ ๋ฒกํฐ ์ฐ์ฐ์ ์ง๊ด์ ์ผ๋ก ์ํํ ์ ์๊ฒ ๋์์ค๋ค.
vec4 v = vec4(1.0, 2.0, 3.0, 4.0);
// ์ ํ
float x = v.x;
// ์ฌ๋ฐฐ์น
vec2 xy = v.xy;
vec3 yzx = v.yzx;
// ์กฐํฉ
vec3 rgb = v.xyz;
* ๋์ผํ ๊ตฌ์ฑ ์์๋ฅผ ์ค๋ณตํด์ ์ ํํ ์๋ ์๋ค. (v.xx)
* ์ฝ๊ธฐ์ ์ฐ๊ธฐ๋ฅผ ๋์์ ํ ์๋ ์๋ค. (v.xy = v.zw ๊ฐ์ ์ฝ๋๋ ๋ถ๊ฐ๋ฅ)
โ ์ ๋ ฅ๊ณผ ์ถ๋ ฅ
์
ฐ์ด๋๋ ๊ฐ๊ฐ์ ์์ ํ๋ก๊ทธ๋จ์ด๊ธฐ ๋๋ฌธ์ ์ธ์ด๋๋ง๋ค ์
๋ ฅ๊ณผ ์ถ๋ ฅ์ด ํ์ํ๋ค.
GLSL์ 'in' ๊ณผ 'out' ํค์๋๋ก ์
๋ ฅ๊ณผ ์ถ๋ ฅ์ ์ ์ํ๊ณ ๋๊ธด๋ค.
- Vertex Shader
Vertex Shader์์ ๊ฐ๊ฐ์ ์
๋ ฅ ๋ณ์๋ Vertex Attribute๋ผ๊ณ ๋ถ๋ฅธ๋ค.
* ํ๋์จ์ด์ ์ํด Vertex Attribute๋ฅผ ์ ์ธํ ์ ์๋ ์ต๋ ๊ฐฏ์๊ฐ ์ ํด์ ธ ์๋ค.
layout (location = 0) in vec3 aPos;
out vec4 vertexColor;
- layout ํค์๋๋ก ๋ณ์์ ํน์ ์์ฑ์ ์ค์ ํ๋ฉฐ (location = 0) ๋ช
์๋ฅผ ํตํด ์ด ์
๋ ฅ ๋ณ์๊ฐ 0๋ฒ ์์น์ ๋งคํ๋์์์ ์๋ฏธํ๋ค.
- in ํค์๋๋ก ์ด ๋ณ์๊ฐ Vertex Shader์ ์
๋ ฅ์์ ๋ํ๋ธ๋ค.
- out ํค์๋๋ก Vertex Shader์ ์ถ๋ ฅ ๋ณ์์์ ๋ํ๋ด๊ณ Fragment Shader์ ์ ๋ฌํ ๋ฐ์ดํฐ๋ฅผ ๋ด๋๋ค. (์ฌ๊ธฐ์๋ vec4ํ์
์ผ๋ก ์์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅ)
- Fragment Shader
in vec4 vertexColor;
out vec4 FragColor;
- ํ์
๊ณผ ์ด๋ฆ์ด ๊ฐ๊ฒ ์ ์ธํ์ฌ vertexColor ๋ณ์๋ฅผ Vertex Shader์ ์ถ๋ ฅ ๋ณ์์ ์ฐ๊ฒฐ์ํจ๋ค.
โ Uniforms
uniform์ CPU์ ์์ฉ ํ๋ก๊ทธ๋จ์์ GPU์ ์
ฐ์ด๋๋ก ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๋ ๋ณ์ ํ์
์ด๋ค.
uniform ๋ณ์๋ CPU์์ ์ค์ ๋๊ณ GPU์์ ์ฝ๊ธฐ ์ ์ฉ์ผ๋ก ์ฌ์ฉ๋๋ค.
โ ํน์ง
- global : uniform ๋ณ์๋ ์
ฐ์ด๋ ํ๋ก๊ทธ๋จ ๊ฐ์ฒด๋ง๋ค ์ ๋ํฌํ๊ณ ์
ฐ์ด๋ ํ๋ก๊ทธ๋จ์ ๋ชจ๋ ๋จ๊ณ์ ์
ฐ์ด๋์์ ์ ๊ทผ์ด ๊ฐ๋ฅํ๋ค.
- readonly : uniform์ ๊ฐ์ ์ค์ ํ๋ฉด reset๋๊ฑฐ๋ update๋๊ธฐ ์ ๊น์ง ๊ทธ ๊ฐ์ ์ ์งํ๋ค.
โ ์ ์ธ
shader์ ํ์
, ์ด๋ฆ๊ณผ ํจ๊ป uniform ํค์๋๋ฅผ ์ถ๊ฐํ๋ค.
uniform vec4 ourColor;
* ์ฝ๋์์ ์ฌ์ฉ๋์ง ์๋ uniform์ ์ ์ธํ๋ค๋ฉด ์๋์ผ๋ก ํด๋น ๋ณ์๋ ์ปดํ์ผ๋ฌ์ ์ํด ์ปดํ์ผ ๋ ๋ฒ์ ์์๋ ์ญ์ ๋๋ฏ๋ก ์ฃผ์
โ ์ฌ์ฉ
๋จผ์ shader์์ uniform attribute์ index / location์ ์ฐพ์์ผ ํ๋ค. ์ฐพ์ ๋ค์ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์๋ค.
// color value๋ก ๋ณํ๋ ๊ฐ ์ง์ (0~1 ์ฌ์ด ์๋ณต)
float timeValue = glfwGetTime();
float greenValue = (sin(timeValue) / 2.0f) + 0.5f;
// ourColor์ location์ ํ์ธ
int vertexColorLocation = glGetUniformLocation(shaderProgram, "ourColor");
// ์ ๋ํผ ๋ณ์์ ๊ฐ์ ์ค์
glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f);
- glGetUniformLocation(์
ฐ์ด๋ ํ๋ก๊ทธ๋จ, uniform ์ด๋ฆ);
uniform ๋ณ์์ location์ ์ฐพ๋๋ค.
* ํจ์๊ฐ -1์ ๋ฐํํ๋ค๋ฉด location์ ์ฐพ์ง ๋ชปํ ๊ฒ
- glUniform4f(location, float๊ฐ 1, float๊ฐ 2, float๊ฐ 3, float๊ฐ 4);
uniform ๋ณ์์ 4๊ฐ์ float ๊ฐ์ ์ค์ ํ๋ค. (uniform ๋ณ์๋ฅผ ํตํด ์
ฐ์ด๋์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌ)
* ๊ฐ ์ ๋ฌ ์ ํด๋น uniform ๋ณ์๊ฐ ํฌํจ๋ ์
ฐ์ด๋ ํ๋ก๊ทธ๋จ์ด ํ์ฑํ ๋์ด ์์ด์ผ ํ๋ค. (glUseProgram ๋จผ์ ํธ์ถ ํ์)
* OpenGL์ ํ์
์ค๋ฒ๋ก๋ฉ์ ์ง์ํ์ง ์๊ธฐ ๋๋ฌธ์ ์ ๋ฏธ์ฌ๋ฅผ ๋ถ์ฌ ์ ํจ์๋ฅผ ์ ์ํ๋ค. (f, i, ui, 3f, fv...)
โ ์์ค ์ฝ๋
โ Attribute ์ถ๊ฐํ๊ธฐ
// ๊ธฐ์กด ์์น๋ฐ์ดํฐ์ ์ปฌ๋ฌ ๋ฐ์ดํฐ ์ถ๊ฐ
float vertices[] = {
// ์์น // ์ปฌ๋ฌ
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // ์ฐ์ธก ํ๋จ
-0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // ์ข์ธก ํ๋จ
0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f // ์
};
- Vertex Shader
#version 330 core
layout (location = 0) in vec3 aPos; // ์์น ๋ณ์๋ attribute position 0์ ๊ฐ์ง๋ค.
layout (location = 1) in vec3 aColor; // ์ปฌ๋ฌ ๋ณ์๋ attribute position 1์ ๊ฐ์ง๋ค.
out vec3 ourColor; // ์ปฌ๋ฌ๋ฅผ fragment shader๋ก ์ถ๋ ฅ
void main()
{
gl_Position = vec4(aPos, 1.0);
ourColor = aColor; // vertex data๋ก๋ถํฐ ๊ฐ์ ธ์จ ์
๋ ฅ๊ฐ์ ์ถ๋ ฅ ๋ณ์ ourColor์ ์ค์
}
- Fragment Shader
#version 330 core
in vec3 ourColor;
out vec4 FragColor;
void main()
{
FragColor = vec4(ourColor, 1.0);
}
- ๋ ์ด์์์ ์๊ธฐ ๋๋ฌธ์ glVertexAttribPointer ํจ์๋ฅผ ์ฌ์ฉํ์ฌ vertex ํ์์ ์์ ํ ์ ์๋ค.
// ์์น attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// ์ปฌ๋ฌ attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3* sizeof(float)));
glEnableVertexAttribArray(1);
* ๋งค๊ฐ๋ณ์ ์ค๋ช
1. location (์์น attribute๋ location 0, ์ปฌ๋ฌ attribute๋ location 1์ ์ค์ )
2. attribute ๊ตฌ์ฑ ์์์ ๊ฐ์ (3๊ฐ์ float x,y,z)
3. ๊ตฌ์ฑ ์์์ ๋ฐ์ดํฐ ํ์
(GL_FLOAT)
4. ์ ๊ทํ ์ฌ๋ถ (GL_FALSE)
5. stride ํฌ๊ธฐ : ๋ค์ attribute๊น์ง์ ๋ฐ์ดํธ ์ (์์น 3๊ฐ, ์ปฌ๋ฌ 3๊ฐ ์ด 6๊ฐ์ float = 6 * sizeof(float))
6. offset : VBO์ ์์ ์์น๋ก๋ถํฐ ํด๋น attribute๊ฐ ์์๋๋ ์์น (์์น attribute๋ ์์ ์์น๊ฐ 0, ์ปฌ๋ฌ attribute๋ ์์น attribute๊ฐ ๋๋ ๋ค์์ด๋ฏ๋ก ์์ ์์น๊ฐ 3 * sizeof(float))
โ ์์ค ์ฝ๋
https://learnopengl.com/code_viewer_gh.php?code=src/1.getting_started/3.2.shaders_interpolation/shaders_interpolation.cpp
- ์ด ๊ฒฐ๊ณผ๋ Fragment Shader์ Fragment Interpolation์ด๋ผ๊ณ ๋ถ๋ฆฐ๋ค. (์ ์ ์ฌ์ด์ ๋ชจ๋ ํ๋๊ทธ๋จผํธ์ ๋ํด ์์ฑ์ ๋ณด๊ฐํ์ฌ ๊ณ์ฐ)
โ Shader ํด๋์ค
Shader๋ค์ ์ฝ๊ณ ์ปดํ์ผํ๊ณ ์ฐ๊ฒฐํ ํ ์ค๋ฅ๋ฅผ ํ์ธํ๋ ํด๋์ค๋ฅผ ์์ฑํ๋ค.
์ดํ main์์ #include <Shader.h> ํ์ฌ ์ฌ์ฉ
#ifndef SHADER_H
#define SHADER_H
#include <glad/glad.h>
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
class Shader
{
public:
// Program ID
unsigned int ID;
// ์์ฑ์์์ Shader๋ฅผ ์ฝ๊ณ ์์ฑ
Shader(const char* vertexPath, const char* fragmentPath)
{
// 1. ํ์ผ ๊ฒฝ๋ก๋ฅผ ํตํด Vertex/Fragment Shader ์์ค ์ฝ๋๋ฅผ ๊ฒ์ํ๋ค.
std::string vertexCode;
std::string fragmentCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
// ์์ธ ์ฒ๋ฆฌ๋ฅผ ์ํ ifsteam ๊ฐ์ฒด
vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try
{
// ํ์ผ ์ด๊ธฐ
vShaderFile.open(vertexPath);
fShaderFile.open(fragmentPath);
std::stringstream vShaderStream, fShaderStream;
// ํ์ผ์ ๋ฒํผ ๋ด์ฉ์ ์ฝ์ด stream์ ์ ์ฅ
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
// ํ์ผ ํธ๋ค๋ฌ ๋ซ๊ธฐ
vShaderFile.close();
fShaderFile.close();
// stream์ string์ผ๋ก ๋ณํ
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
}
catch (std::ifstream::failure& e)
{
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ: " << e.what() << std::endl;
}
const char* vShaderCode = vertexCode.c_str();
const char* fShaderCode = fragmentCode.c_str();
// 2. Shader๋ฅผ ์ปดํ์ผํ๋ค.
unsigned int vertex, fragment;
// Vertex Shader
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, NULL);
glCompileShader(vertex);
checkCompileErrors(vertex, "VERTEX");
// Fragment Shader
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fShaderCode, NULL);
glCompileShader(fragment);
checkCompileErrors(fragment, "FRAGMENT");
// Shader Program
ID = glCreateProgram();
glAttachShader(ID, vertex);
glAttachShader(ID, fragment);
glLinkProgram(ID);
checkCompileErrors(ID, "PROGRAM");
// ํ๋ก๊ทธ๋จ์ ์ฐ๊ฒฐ๋์ด ํ์ ์์ด์ง Shader๋ค ์ ๊ฑฐ
glDeleteShader(vertex);
glDeleteShader(fragment);
}
void use()
{
glUseProgram(ID);
}
void setBool(const std::string& name, bool value) const
{
glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
}
void setInt(const std::string& name, int value) const
{
glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
}
void setFloat(const std::string& name, float value) const
{
glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
}
private:
// ์ปดํ์ผ, ์ฐ๊ฒฐ ์ค๋ฅ ์ฒดํฌ
void checkCompileErrors(unsigned int shader, std::string type)
{
int success;
char infoLog[1024];
if (type != "PROGRAM")
{
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(shader, 1024, NULL, infoLog);
std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
}
}
else
{
glGetProgramiv(shader, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(shader, 1024, NULL, infoLog);
std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
}
}
}
};
#endif
'๐จ Graphics > ๐ต OpenGL' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [OpenGL] Texture ์ ์ฉ (0) | 2024.07.28 |
|---|---|
| [OpenGL] Texture ๋ก๋ (0) | 2024.07.28 |
| [OpenGL] EBO (0) | 2024.07.18 |
| [OpenGL] ์ผ๊ฐํ ๊ทธ๋ฆฌ๊ธฐ (0) | 2024.07.17 |
| [OpenGL] ์๋์ฐ ์์ฑ ๋ฐ ๋ ๋๋ง (0) | 2024.07.17 |