テクスチャマッピングについてメモします。
- OpenGL3.1(GLSL1.4)以上
テクスチャマッピング

平面に対して2x2のRGBAデータを貼り付け。
コード
- simple.vert
#version 140
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
in vec3 a_vertex;
in vec3 a_normal;
in vec2 a_texcoord;
out vec3 v_normal;
out vec2 v_texcoord;
void main(void)
{
mat4 modelViewMatrix = viewMatrix*modelMatrix;
v_normal = (viewMatrix*modelMatrix*vec4(a_normal, 0.0)).xyz;
v_texcoord = a_texcoord;
gl_Position = projectionMatrix*modelViewMatrix*vec4(a_vertex.xyz, 1.0);
}
- simple.frag
#version 140
uniform sampler2D texture0;
in vec3 v_normal;
in vec2 v_texcoord;
out vec4 fragColor;
void main(void)
{
float intensity;
intensity = max(dot(v_normal, vec3(0.0,0.0,1.0)),0.0);
fragColor = texture2D(texture0, v_texcoord) * intensity;
//fragColor = texture2D(texture0, v_texcoord);
}
- ソースコード
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <GL/glew.h>
#include <GL/glut.h>
#include "Transform.h"
GLuint programObject;
GLuint vertexShader;
GLuint fragmentShader;
GLint modelLocation;
GLint viewLocation;
GLint projectionLocation;
GLfloat viewMatrix[16];
GLfloat projectionMatrix[16];
class Plane
{
private:
GLuint vid[4]; // vertex, normal, texcoord, index
GLint vertexLocation;
GLint normalLocation;
GLint texCoordLocation;
GLuint texId[1];
GLint textureLocation;
GLuint numIndices;
GLfloat matrix[16];
public:
void setup(GLuint programObj)
{
// 平面作成
GLuint numVertices;
numVertices = 4;
numIndices = 6;
const GLfloat vertices[] = {
-1.0f, 0.0f, -1.0f,
+1.0f, 0.0f, -1.0f,
+1.0f, 0.0f, +1.0f,
-1.0f, 0.0f, +1.0f
};
const GLfloat normals[] = {
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f
};
const GLfloat texCoords[] = {
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f
};
const GLfloat indices[] = {
0, 2, 1,
0, 3, 2
};
////////////////////////////////////////////////////////////////
// in(attribute)変数への関連付け
vertexLocation = glGetAttribLocation(programObj, "a_vertex");
normalLocation = glGetAttribLocation(programObj, "a_normal");
texCoordLocation = glGetAttribLocation(programObj, "a_texcoord");
// uniform変数への関連付け
textureLocation = glGetUniformLocation(programObj, "texture0");
glGenBuffers(4, vid);
// 頂点データをGPUメモリ側へ転送
glBindBuffer(GL_ARRAY_BUFFER, vid[0]);
glBufferData(GL_ARRAY_BUFFER, 3*numVertices*sizeof(GLfloat), vertices, GL_STATIC_DRAW);
// 法線データをGPUメモリ側へ転送
glBindBuffer(GL_ARRAY_BUFFER, vid[1]);
glBufferData(GL_ARRAY_BUFFER, 3*numVertices*sizeof(GLfloat), normals, GL_STATIC_DRAW);
// テクスチャ座標データをGPUメモリ側へ転送
glBindBuffer(GL_ARRAY_BUFFER, vid[2]);
glBufferData(GL_ARRAY_BUFFER, 2*numVertices*sizeof(GLfloat), texCoords, GL_STATIC_DRAW);
// 頂点番号データをGPUメモリ側へ転送
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vid[3]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices*sizeof(GLuint), indices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
////////////////////////////////////////////////////////////////
// texture
const GLubyte imageData[] = { // RGBA
255, 0, 0, 255, // Red
0, 255, 0, 255, // Green
0, 0, 255, 255, // Blue
255, 255, 0, 255, // Yellow
};
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // 1データを1バイトごと
// テクスチャデータをGPUメモリ側へ転送
glGenTextures(1, texId);
glActiveTexture(GL_TEXTURE0); // テクスチャユニット番号 0
glBindTexture(GL_TEXTURE_2D, texId[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glBindTexture(GL_TEXTURE_2D, 0);
////////////////////////////////////////////////////////////////
angle = 0.0;
}
void render()
{
// vertex
glBindBuffer(GL_ARRAY_BUFFER, vid[0]);
glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(vertexLocation);
// normal
glBindBuffer(GL_ARRAY_BUFFER, vid[1]);
glVertexAttribPointer(normalLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(normalLocation);
// texcoord
glBindBuffer(GL_ARRAY_BUFFER, vid[2]);
glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(texCoordLocation);
// texture
glUniform1i(textureLocation, 0); // テクスチャユニット番号 0
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texId[0]);
// index
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vid[3]);
// draw
glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_INT, 0);
}
float angle;
void update() {
sl_LoadIdentityf(matrix);
sl_Scalef(matrix, 2.0f, 2.0f, 2.0f); // 2倍にする
//sl_Translatef(matrix, 0.0f, 0.0f, 0.0f);
//sl_Rotatef(matrix, angle, 1.0f, 0.0f, 0.0f);
//angle += 1.0f;
//if (angle > 360.0f) angle = 0.0f;
}
GLfloat* m() {
return matrix;
}
};
Plane plane;
// prototype
void display();
void reshape(int w, int h);
void timer(int t);
void init();
bool initGlsl();
void setupParams();
GLuint LoadShader(GLenum type, const char *fileName);
void display()
{
plane.update();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(programObject);
// transform
glUniformMatrix4fv(viewLocation, 1, GL_FALSE, viewMatrix);
glUniformMatrix4fv(projectionLocation, 1, GL_FALSE, projectionMatrix);
glUniformMatrix4fv(modelLocation, 1, GL_FALSE, plane.m());
plane.render();
glUseProgram(0);
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
sl_LoadIdentityf(projectionMatrix);
sl_Perspectivef(projectionMatrix, 30, (GLfloat)w/(GLfloat)h, 1.0f, 100.0f);
}
void timer(int t)
{
glutPostRedisplay();
glutTimerFunc(t, timer, 17);
}
void init()
{
glClearColor(0.5, 0.5, 0.5, 1.0);
glClearDepth(1.0f);
sl_LoadIdentityf(viewMatrix);
sl_LookAtf(viewMatrix, 3.0f, 4.0f, 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
}
bool initGlsl()
{
programObject = glCreateProgram();
if (programObject == 0) return false;
vertexShader = LoadShader(GL_VERTEX_SHADER, "simple.vert");
glAttachShader(programObject, vertexShader);
fragmentShader = LoadShader(GL_FRAGMENT_SHADER, "simple.frag");
glAttachShader(programObject, fragmentShader);
GLint linked;
glLinkProgram(programObject);
glGetProgramiv(programObject, GL_LINK_STATUS, &linked);
if (!linked) {
GLint infoLen = 0;
glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 1) {
char *infoLog = new char[sizeof(char)*infoLen];
glGetProgramInfoLog(programObject, infoLen, NULL, infoLog);
std::cerr << "Error linking program:\n" << infoLog << "\n";
delete [] infoLog;
}
glDeleteProgram(programObject);
return false;
}
return true;
}
void setupParams()
{
// Fragment data
glBindFragDataLocation(programObject, 0, "fragColor");
// Transform Matrix
modelLocation = glGetUniformLocation(programObject, "modelMatrix");
viewLocation = glGetUniformLocation(programObject, "viewMatrix");
projectionLocation = glGetUniformLocation(programObject, "projectionMatrix");
// objects
plane.setup(programObject);
}
GLuint LoadShader(GLenum type, const char *fileName)
{
GLuint shader;
GLint compiled;
std::fstream inputFile(fileName);
std::istreambuf_iterator<char> dataBegin(inputFile);
std::istreambuf_iterator<char> dataEnd;
std::string fileData(dataBegin, dataEnd);
const char *file = fileData.c_str();
shader = glCreateShader(type);
if (shader == 0) return 0;
glShaderSource(shader, 1, &file, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled) {
GLint infoLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 1) {
char* infoLog = new char[sizeof(char)*infoLen];
glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
std::cerr << "Error compiling shader: " << fileName << "\n" << infoLog << "\n";
delete [] infoLog;
}
glDeleteShader(shader);
return 0;
}
return shader;
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowSize(600, 400);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("test");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutTimerFunc(100, timer, 17);
GLenum err;
glewExperimental = GL_TRUE;
err = glewInit();
if (err != GLEW_OK) {
std::cerr << "GLEW error : " << glewGetErrorString(err) << "\n";
std::exit(1);
}
init();
initGlsl();
setupParams();
glutMainLoop();
return 0;
}
添付ファイル