[openFrameworks]ofDisableArbTexの挙動，samper2Dとsampler2DRectの違い

#はじめに
oFでTextureMappingなどを行うときに`ofDisableArbTex`を呼ぶときと呼ばない場合があり，glsl内でも受け取り方が変わってくるのでそこら辺をまとめて行こうと思います．

#結論
以下で説明を述べますが，結論から述べる`sampler2D`型であるとuvは<font color="red">正規化</font>されている必要があり，`sampler2DRect`であるとuvは<font color="red">画像のテクセル数</font>と対応させる必要があるといった感じです．

#ofDisableArbTexを適応しなかった場合
`ofDisableArbTex`を呼ばないと内部では`GL_TEXTURE_RECTANGLE_ARB `のモードでテクスチャが生成されます．そのためofApp.cppで見てわかる通りuv座標をmeshに対応させるのではなく，画像サイズをベースにしたテクセルの座標系を割り当てていることが特徴となります．

FragmentShader内部ではsampgler2DRect型でtextureを受け取ります．


``` ofApp.h
#pragma once
#include "ofMain.h"
class ofApp : public ofBaseApp {
public:
    void setup();
    void update();
    void draw();

    ofEasyCam cam;
    ofShader shader;
    ofVboMesh vboMesh;
    ofImage img;
    ofVec3f pos;
};
```

```ofApp.cpp
#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup() {
    ofSetFrameRate(60);
    ofSetBackgroundColor(0);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);

    
    shader.load("shaders/shader");

    
    img.load("texture0.png");
    pos = ofVec3f(0.0, 0.0, 0.0);
    
    ofVec2f imgSize = ofVec2f(img.getWidth(), img.getHeight());
    vboMesh.addVertex(ofVec3f(-imgSize.x/2.0, -imgSize.y/2.0, 0.0));
    vboMesh.addVertex(ofVec3f(imgSize.x/2.0, -imgSize.y/2.0, 0.0));
    vboMesh.addVertex(ofVec3f(imgSize.x/2.0, imgSize.y/2.0, 0.0));
    vboMesh.addVertex(ofVec3f(-imgSize.x/2.0, imgSize.y/2.0, 0.0));
    
    vboMesh.addIndex(0);
    vboMesh.addIndex(1);
    vboMesh.addIndex(2);
    vboMesh.addIndex(2);
    vboMesh.addIndex(3);
    vboMesh.addIndex(0);
    
    //サンプリングする座標は画像サイズベース
    vboMesh.addTexCoord(ofVec2f(0.0, imgSize.y));
    vboMesh.addTexCoord(ofVec2f(imgSize.x, imgSize.y));
    vboMesh.addTexCoord(ofVec2f(imgSize.x, 0.0));
    vboMesh.addTexCoord(ofVec2f(0.0, 0.0));    
}

//--------------------------------------------------------------
void ofApp::update() {
    ofSetWindowTitle(ofToString(ofGetFrameRate()));
}

//--------------------------------------------------------------
void ofApp::draw() {
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClearDepth(1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    cam.begin();
    cam.lookAt(ofVec3f(0.0, 0.0, 0.0), ofVec3f(0.0, 1.0, 0.0));
    img.getTexture().bind();

    shader.begin();

    ofMatrix4x4 modelMatrix;
    ofMatrix4x4 viewMatrix;
    viewMatrix = ofGetCurrentViewMatrix();
    ofMatrix4x4 projectionMatrix;
    projectionMatrix = cam.getProjectionMatrix();
    ofMatrix4x4 mvpMatrix;
    mvpMatrix = modelMatrix * viewMatrix * projectionMatrix;

    shader.setUniformMatrix4f("model", modelMatrix);
    shader.setUniformMatrix4f("view", viewMatrix);
    shader.setUniformMatrix4f("projection", projectionMatrix);
    shader.setUniformMatrix4f("mvp", mvpMatrix);
    shader.setUniformTexture("tex0", img.getTexture(), 0);
    
    vboMesh.draw();
    shader.end();

    img.getTexture().unbind();
    cam.end()
}

```

```shader.vert
#version 150
precision mediump float;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform mat4 mvp;

in vec2 texcoord;
in vec3 position;
in vec4 color;

out vec2 vTextureCoord;
out vec4 vColor;

void main() {
    vTextureCoord = texcoord;
    vColor = color;
    //gl_Position = projection * view * model * vec4(position, 1.0);
    gl_Position = mvp * vec4(position, 1.0);
}

```

```shader.frag
#version 150
precision mediump float;
uniform sampler2DRect tex0;

in vec2 vTextureCoord;
in vec4 vColor;

out vec4 outputColor;

void main(){
    vec4 smpColor = texture(tex0, vTextureCoord);
    outputColor  = vColor * smpColor;
}

```

![bandicam 2019-04-30 18-57-24-344.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184790/bbb0682a-2051-0ced-11cc-f25b22f940fc.jpeg)


#ofDisableArbTexを適応した場合
`ofDisableArbTex`を適応した場合,`GL_TEXTURE_2D`モードでテクスチャが生成されます．
ofApp.cppではmeshにtextureのuv座標を割り当ててます．生openGLではこちらの方がメジャーだと思いますので，oFを使う際には注意が必要ですね．．
またFragmentShader内部ではsampgler2D型でtextureを受け取ります．
(*下記に載せていない部分のコードは上のコードから変更はありません)


```ofApp.cpp
#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup() {
    ofSetFrameRate(60);
    ofSetBackgroundColor(0);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);

    // shader setings
    shader.load("shaders/shader");

 
    // load image
    ofDisableArbTex();
    img.load("texture0.png");
    pos = ofVec3f(0.0, 0.0, 0.0);
    
    ofVec2f imgSize = ofVec2f(img.getWidth(), img.getHeight());
    
    vboMesh.addVertex(ofVec3f(-imgSize.x/2.0, -imgSize.y/2.0, 0.0));
    vboMesh.addVertex(ofVec3f(imgSize.x/2.0, -imgSize.y/2.0, 0.0));
    vboMesh.addVertex(ofVec3f(imgSize.x/2.0, imgSize.y/2.0, 0.0));
    vboMesh.addVertex(ofVec3f(-imgSize.x/2.0, imgSize.y/2.0, 0.0));
    
    vboMesh.addIndex(0);
    vboMesh.addIndex(1);
    vboMesh.addIndex(2);
    vboMesh.addIndex(2);
    vboMesh.addIndex(3);
    vboMesh.addIndex(0);
    
    //ofDisableArbTex()の場合
    //サンプリングする座標はuv座標系ベース
    vboMesh.addTexCoord(ofVec2f(0.0, 1.0));
    vboMesh.addTexCoord(ofVec2f(1.0, 1.0));
    vboMesh.addTexCoord(ofVec2f(1.0, 0.0));
    vboMesh.addTexCoord(ofVec2f(0.0, 0.0));
}

//--------------------------------------------------------------
void ofApp::update() {
    ofSetWindowTitle(ofToString(ofGetFrameRate()));
}

//--------------------------------------------------------------
void ofApp::draw() {
    glEnable(GL_TEXTURE_2D);
 
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClearDepth(1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    cam.begin();
    cam.lookAt(ofVec3f(0.0, 0.0, 0.0), ofVec3f(0.0, 1.0, 0.0));
    img.getTexture().bind();


    shader.begin();

    ofMatrix4x4 modelMatrix;
    ofMatrix4x4 viewMatrix;
    viewMatrix = ofGetCurrentViewMatrix();
    ofMatrix4x4 projectionMatrix;
    projectionMatrix = cam.getProjectionMatrix();
    ofMatrix4x4 mvpMatrix;
    mvpMatrix = modelMatrix * viewMatrix * projectionMatrix;

    shader.setUniformMatrix4f("model", modelMatrix);
    shader.setUniformMatrix4f("view", viewMatrix);
    shader.setUniformMatrix4f("projection", projectionMatrix);
    shader.setUniformMatrix4f("mvp", mvpMatrix);
    shader.setUniformTexture("tex0", img.getTexture(), 0);

    for (int j = 0; j<vboMesh.getVertices().size(); j++) {
        vboMesh.addColor(ofFloatColor(1.0, 1.0, 1.0, 1.0));
    }
    
    vboMesh.draw();
    shader.end();

    img.getTexture().unbind();
    cam.end();
}

```

```shader.frag
#version 150
precision mediump float;

// this is how we receive the texture
uniform sampler2D tex0;

in vec2 vTextureCoord;
in vec4 vColor;

out vec4 outputColor;

void main(){
    vec4 smpColor = texture(tex0, vTextureCoord);
    outputColor  = vColor * smpColor;
}

```

![bandicam 2019-04-30 18-57-24-344.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184790/3d9e32cd-92a1-0c96-0b13-7b9e5d4571c7.jpeg)



# まとめ
oFでtextureを扱うのは奥が深いなぁと思いながらも色々試してみるのが楽しいのでこれからも色々やっていきたいと思います．textureMapping周りでまた何か発見があれば更新をかけたいと思います．

# 参考
- https://forum.openframeworks.cc/t/sampler2d-instead-of-sampler2drect/23401