macOS에서 OpenGL 프로그래밍 (2-5. 다중 텍스처 결합)
소개
지난번은 단일 텍스처를 읽고 표시하는 프로그램을 작성했습니다.
이번에는 두 장의 텍스처를 동시에 사용하여 시간에 따라 어느 텍스처를 크게 표시할지를 전환하면서 애니메이션을 만들고 싶습니다.
1. ShaderProgram 클래스 개선
우선은 ShaderProgram 클래스에, float 형의 uniform 변수의 값을 세트 할 수 있도록 SetUniform()
함수의 오버로드 함수를 추가합니다. 또한 이전에 작성한 SetUniform()
함수와 동일한 작업을 수행하는 부분이 최소화되도록 uniform 변수의 위치를 얻기 위해 GetUniformLocation()
함수를 별도로 추가합니다.
Shader.hpp(일부)class ShaderProgram
{
/* 一部省略 */
public:
GLint GetUniformLocation(const std::string& name);
void SetUniform(const std::string& name, float value);
void SetUniform(const std::string& name, int value);
void Use();
};
이러한 함수를 구현하는 코드를 ShaderProgram.cpp에 씁니다. 대부분의 행 수는 uniform 변수의 위치를 쿼리하기 위한 코드이므로, GetUniformLocation()
함수를 준비한 것으로, 2개의 SetUniform()
함수의 구현은 2행씩으로 끝나게 되었습니다.
Shader.cpp(일부)GLint ShaderProgram::GetUniformLocation(const std::string& name)
{
GLint location;
if (uniformLocationMap.find(name) == uniformLocationMap.end()) {
location = glGetUniformLocation(program, name.c_str());
if (location < 0) {
throw GameError("ShaderProgram::SetUniform() Cannot locate a uniform value: %s", name.c_str());
}
uniformLocationMap[name] = location;
} else {
location = uniformLocationMap[name];
}
return location;
}
void ShaderProgram::SetUniform(const std::string& name, float value)
{
GLint location = GetUniformLocation(name);
glUniform1f(location, value);
}
void ShaderProgram::SetUniform(const std::string& name, int value)
{
GLint location = GetUniformLocation(name);
glUniform1i(location, value);
}
2. Game 클래스에 변수 추가
Game.hpp를 편집하여 새 텍스처 변수tex2
와 시간이 지남에 따라 값을 변경하는 변수t
를 추가합니다.
Game.hpp(일부)class Game
{
/* ここまで省略 */
Texture *tex;
Texture *tex2;
float t;
/* 以下、省略 */
};
Game.cpp를 편집하여 생성자에서 새 텍스처를 새로 만드는 코드와 첫 번째 텍스처를 바인딩하는 코드를 추가합니다 (이전에는 0 번째 텍스처를 바인딩하고 사용했습니다). 또한 변수t
를 0.0f로 초기화합니다.
Game.cpp(생성자)Game::Game()
{
/* 前半省略 */
tex = new Texture("photo.jpg");
tex2 = new Texture("photo2.jpg");
glActiveTexture(GL_TEXTURE0);
tex->Bind();
glActiveTexture(GL_TEXTURE1);
tex2->Bind();
program->Use();
program->SetUniform("tex", 0);
program->SetUniform("tex2", 1);
t = 0.5f;
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
}
이용할 수 있는 텍스처의 수는, 2개 뿐만이 아니라, GL_TEXTURE0, GL_TEXTURE1, GL_TEXTURE2, ...라고 정수가 준비되어 있으므로, 3개에서도 4개에서도 동시에 이용할 수 있습니다.
Game 클래스의 소멸자에는 추가한 텍스처를 삭제하기 위한 코드를 잊지 않고 써 둡니다.
Game 클래스의 소멸자Game::~Game()
{
delete program;
delete tex;
delete tex2;
...
}
그런 다음 Game::Render()
함수 구현입니다. 키보드의 왼쪽 및 오른쪽 화살표 키를 사용하여 변수t
의 값을 0.0에서 1.0으로 변경합니다.
Game.cpp(Render() 함수)void Game::Render()
{
if (Input::GetKey(KeyCode::LeftArrow)) {
t -= 0.5f * Time::deltaTime;
}
if (Input::GetKey(KeyCode::RightArrow)) {
t += 0.5f * Time::deltaTime;
}
if (t < 0.0f) {
t = 0.0f;
} else if (t > 1.0f) {
t = 1.0f;
}
program->Use();
program->SetUniform("t", t);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void *)0);
}
텍스처의 번호를 나타내는 sampler2D형의 변수 2개와 달리, 변수 t
의 값은 계속 변화하기 때문에, Render() 함수의 선두로 매 프레임 세트 재차 합니다.
3. 프래그먼트 셰이더 재작성
이번에는 정점 쉐이더의 변경은 필요 없기 때문에, 단편 쉐이더만을, 다음과 같이 재기록합니다.
myshader.fsh#version 410
in vec4 color;
in vec2 uv;
uniform sampler2D tex;
uniform sampler2D tex2;
uniform float t;
layout (location=0) out vec4 frag_color;
void main()
{
vec4 c1 = texture(tex, uv);
vec4 c2 = texture(tex2, uv);
frag_color = (uv.x < t? c1: c2);
}
sampler2D 형의 uniform 변수 tex
를 1 개 늘려, float 형의 값을 받기위한 uniform 변수 t
도 추가했습니다.
그런 다음 tex
변수를 사용하여 0 번째 텍스처 이미지에서 tex2
변수를 사용하여 첫 번째 텍스처 이미지에서 UV 좌표에 해당하는 색상 값을 가져옵니다 c1
및 c2
에 저장합니다. 마지막으로 3항 연산자를 사용해, UV 좌표의 X 좌표가 0.0~1.0의 t
의 값보다 작으면 c1
의 값을, 그렇지 않으면 c2
의 값을 사용하도록(듯이) frag_color
변수에 할당 명령을 씁니다.
4. 텍스처 이미지 추가
마지막으로 이전과 마찬가지로 새 이미지를 프로젝트에 추가합니다. "photo2.jpg"라는 이미지 파일을 추가했습니다.
5. 정리
어플리케이션을 실행하면, 좌우의 화살표 키의 조작에 따라서, X축 방향으로 2매의 텍스처 화상이 크기를 바꾸면서 표시되게 된 것을 알 수 있습니다.
지금까지 프로젝트: MyGL은 _s로 p2-5. 지 p
다음 문서: macOS에서 OpenGL 프로그래밍 (2-6. 정점 데이터에 GLKit 구조체 사용)
Reference
이 문제에 관하여(macOS에서 OpenGL 프로그래밍 (2-5. 다중 텍스처 결합)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/sazameki/items/8529169d355df667bed6
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
우선은 ShaderProgram 클래스에, float 형의 uniform 변수의 값을 세트 할 수 있도록
SetUniform()
함수의 오버로드 함수를 추가합니다. 또한 이전에 작성한 SetUniform()
함수와 동일한 작업을 수행하는 부분이 최소화되도록 uniform 변수의 위치를 얻기 위해 GetUniformLocation()
함수를 별도로 추가합니다.Shader.hpp(일부)
class ShaderProgram
{
/* 一部省略 */
public:
GLint GetUniformLocation(const std::string& name);
void SetUniform(const std::string& name, float value);
void SetUniform(const std::string& name, int value);
void Use();
};
이러한 함수를 구현하는 코드를 ShaderProgram.cpp에 씁니다. 대부분의 행 수는 uniform 변수의 위치를 쿼리하기 위한 코드이므로,
GetUniformLocation()
함수를 준비한 것으로, 2개의 SetUniform()
함수의 구현은 2행씩으로 끝나게 되었습니다.Shader.cpp(일부)
GLint ShaderProgram::GetUniformLocation(const std::string& name)
{
GLint location;
if (uniformLocationMap.find(name) == uniformLocationMap.end()) {
location = glGetUniformLocation(program, name.c_str());
if (location < 0) {
throw GameError("ShaderProgram::SetUniform() Cannot locate a uniform value: %s", name.c_str());
}
uniformLocationMap[name] = location;
} else {
location = uniformLocationMap[name];
}
return location;
}
void ShaderProgram::SetUniform(const std::string& name, float value)
{
GLint location = GetUniformLocation(name);
glUniform1f(location, value);
}
void ShaderProgram::SetUniform(const std::string& name, int value)
{
GLint location = GetUniformLocation(name);
glUniform1i(location, value);
}
2. Game 클래스에 변수 추가
Game.hpp를 편집하여 새 텍스처 변수tex2
와 시간이 지남에 따라 값을 변경하는 변수t
를 추가합니다.
Game.hpp(일부)class Game
{
/* ここまで省略 */
Texture *tex;
Texture *tex2;
float t;
/* 以下、省略 */
};
Game.cpp를 편집하여 생성자에서 새 텍스처를 새로 만드는 코드와 첫 번째 텍스처를 바인딩하는 코드를 추가합니다 (이전에는 0 번째 텍스처를 바인딩하고 사용했습니다). 또한 변수t
를 0.0f로 초기화합니다.
Game.cpp(생성자)Game::Game()
{
/* 前半省略 */
tex = new Texture("photo.jpg");
tex2 = new Texture("photo2.jpg");
glActiveTexture(GL_TEXTURE0);
tex->Bind();
glActiveTexture(GL_TEXTURE1);
tex2->Bind();
program->Use();
program->SetUniform("tex", 0);
program->SetUniform("tex2", 1);
t = 0.5f;
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
}
이용할 수 있는 텍스처의 수는, 2개 뿐만이 아니라, GL_TEXTURE0, GL_TEXTURE1, GL_TEXTURE2, ...라고 정수가 준비되어 있으므로, 3개에서도 4개에서도 동시에 이용할 수 있습니다.
Game 클래스의 소멸자에는 추가한 텍스처를 삭제하기 위한 코드를 잊지 않고 써 둡니다.
Game 클래스의 소멸자Game::~Game()
{
delete program;
delete tex;
delete tex2;
...
}
그런 다음 Game::Render()
함수 구현입니다. 키보드의 왼쪽 및 오른쪽 화살표 키를 사용하여 변수t
의 값을 0.0에서 1.0으로 변경합니다.
Game.cpp(Render() 함수)void Game::Render()
{
if (Input::GetKey(KeyCode::LeftArrow)) {
t -= 0.5f * Time::deltaTime;
}
if (Input::GetKey(KeyCode::RightArrow)) {
t += 0.5f * Time::deltaTime;
}
if (t < 0.0f) {
t = 0.0f;
} else if (t > 1.0f) {
t = 1.0f;
}
program->Use();
program->SetUniform("t", t);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void *)0);
}
텍스처의 번호를 나타내는 sampler2D형의 변수 2개와 달리, 변수 t
의 값은 계속 변화하기 때문에, Render() 함수의 선두로 매 프레임 세트 재차 합니다.
3. 프래그먼트 셰이더 재작성
이번에는 정점 쉐이더의 변경은 필요 없기 때문에, 단편 쉐이더만을, 다음과 같이 재기록합니다.
myshader.fsh#version 410
in vec4 color;
in vec2 uv;
uniform sampler2D tex;
uniform sampler2D tex2;
uniform float t;
layout (location=0) out vec4 frag_color;
void main()
{
vec4 c1 = texture(tex, uv);
vec4 c2 = texture(tex2, uv);
frag_color = (uv.x < t? c1: c2);
}
sampler2D 형의 uniform 변수 tex
를 1 개 늘려, float 형의 값을 받기위한 uniform 변수 t
도 추가했습니다.
그런 다음 tex
변수를 사용하여 0 번째 텍스처 이미지에서 tex2
변수를 사용하여 첫 번째 텍스처 이미지에서 UV 좌표에 해당하는 색상 값을 가져옵니다 c1
및 c2
에 저장합니다. 마지막으로 3항 연산자를 사용해, UV 좌표의 X 좌표가 0.0~1.0의 t
의 값보다 작으면 c1
의 값을, 그렇지 않으면 c2
의 값을 사용하도록(듯이) frag_color
변수에 할당 명령을 씁니다.
4. 텍스처 이미지 추가
마지막으로 이전과 마찬가지로 새 이미지를 프로젝트에 추가합니다. "photo2.jpg"라는 이미지 파일을 추가했습니다.
5. 정리
어플리케이션을 실행하면, 좌우의 화살표 키의 조작에 따라서, X축 방향으로 2매의 텍스처 화상이 크기를 바꾸면서 표시되게 된 것을 알 수 있습니다.
지금까지 프로젝트: MyGL은 _s로 p2-5. 지 p
다음 문서: macOS에서 OpenGL 프로그래밍 (2-6. 정점 데이터에 GLKit 구조체 사용)
Reference
이 문제에 관하여(macOS에서 OpenGL 프로그래밍 (2-5. 다중 텍스처 결합)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/sazameki/items/8529169d355df667bed6
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
class Game
{
/* ここまで省略 */
Texture *tex;
Texture *tex2;
float t;
/* 以下、省略 */
};
Game::Game()
{
/* 前半省略 */
tex = new Texture("photo.jpg");
tex2 = new Texture("photo2.jpg");
glActiveTexture(GL_TEXTURE0);
tex->Bind();
glActiveTexture(GL_TEXTURE1);
tex2->Bind();
program->Use();
program->SetUniform("tex", 0);
program->SetUniform("tex2", 1);
t = 0.5f;
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
}
Game::~Game()
{
delete program;
delete tex;
delete tex2;
...
}
void Game::Render()
{
if (Input::GetKey(KeyCode::LeftArrow)) {
t -= 0.5f * Time::deltaTime;
}
if (Input::GetKey(KeyCode::RightArrow)) {
t += 0.5f * Time::deltaTime;
}
if (t < 0.0f) {
t = 0.0f;
} else if (t > 1.0f) {
t = 1.0f;
}
program->Use();
program->SetUniform("t", t);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void *)0);
}
이번에는 정점 쉐이더의 변경은 필요 없기 때문에, 단편 쉐이더만을, 다음과 같이 재기록합니다.
myshader.fsh
#version 410
in vec4 color;
in vec2 uv;
uniform sampler2D tex;
uniform sampler2D tex2;
uniform float t;
layout (location=0) out vec4 frag_color;
void main()
{
vec4 c1 = texture(tex, uv);
vec4 c2 = texture(tex2, uv);
frag_color = (uv.x < t? c1: c2);
}
sampler2D 형의 uniform 변수
tex
를 1 개 늘려, float 형의 값을 받기위한 uniform 변수 t
도 추가했습니다.그런 다음
tex
변수를 사용하여 0 번째 텍스처 이미지에서 tex2
변수를 사용하여 첫 번째 텍스처 이미지에서 UV 좌표에 해당하는 색상 값을 가져옵니다 c1
및 c2
에 저장합니다. 마지막으로 3항 연산자를 사용해, UV 좌표의 X 좌표가 0.0~1.0의 t
의 값보다 작으면 c1
의 값을, 그렇지 않으면 c2
의 값을 사용하도록(듯이) frag_color
변수에 할당 명령을 씁니다.4. 텍스처 이미지 추가
마지막으로 이전과 마찬가지로 새 이미지를 프로젝트에 추가합니다. "photo2.jpg"라는 이미지 파일을 추가했습니다.
5. 정리
어플리케이션을 실행하면, 좌우의 화살표 키의 조작에 따라서, X축 방향으로 2매의 텍스처 화상이 크기를 바꾸면서 표시되게 된 것을 알 수 있습니다.
지금까지 프로젝트: MyGL은 _s로 p2-5. 지 p
다음 문서: macOS에서 OpenGL 프로그래밍 (2-6. 정점 데이터에 GLKit 구조체 사용)
Reference
이 문제에 관하여(macOS에서 OpenGL 프로그래밍 (2-5. 다중 텍스처 결합)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/sazameki/items/8529169d355df667bed6
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
어플리케이션을 실행하면, 좌우의 화살표 키의 조작에 따라서, X축 방향으로 2매의 텍스처 화상이 크기를 바꾸면서 표시되게 된 것을 알 수 있습니다.
지금까지 프로젝트: MyGL은 _s로 p2-5. 지 p
다음 문서: macOS에서 OpenGL 프로그래밍 (2-6. 정점 데이터에 GLKit 구조체 사용)
Reference
이 문제에 관하여(macOS에서 OpenGL 프로그래밍 (2-5. 다중 텍스처 결합)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/sazameki/items/8529169d355df667bed6텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)