bambooflow Note

TextureMapping

最終更新:

bambooflow

- view
メンバー限定 登録/ログイン

テクスチャマッピングについてメモします。

  • 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;
}
 

タグ:

OpenGL GLSL
添付ファイル
記事メニュー
ウィキ募集バナー