はじめに
oFでTextureMappingなどを行うときにofDisableArbTex
を呼ぶときと呼ばない場合があり,glsl内でも受け取り方が変わってくるのでそこら辺をまとめて行こうと思います.
結論
以下で説明を述べますが,結論から述べるsampler2D
型であるとuvは正規化されている必要があり,sampler2DRect
であるとuvは画像のテクセル数と対応させる必要があるといった感じです.
ofDisableArbTexを適応しなかった場合
ofDisableArbTex
を呼ばないと内部ではGL_TEXTURE_RECTANGLE_ARB
のモードでテクスチャが生成されます.そのためofApp.cppで見てわかる通りuv座標をmeshに対応させるのではなく,画像サイズをベースにしたテクセルの座標系を割り当てていることが特徴となります.
FragmentShader内部ではsampgler2DRect型でtextureを受け取ります.
#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;
};
#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()
}
#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);
}
#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;
}
ofDisableArbTexを適応した場合
ofDisableArbTex
を適応した場合,GL_TEXTURE_2D
モードでテクスチャが生成されます.
ofApp.cppではmeshにtextureのuv座標を割り当ててます.生openGLではこちらの方がメジャーだと思いますので,oFを使う際には注意が必要ですね..
またFragmentShader内部ではsampgler2D型でtextureを受け取ります.
(*下記に載せていない部分のコードは上のコードから変更はありません)
#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();
}
#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;
}
まとめ
oFでtextureを扱うのは奥が深いなぁと思いながらも色々試してみるのが楽しいのでこれからも色々やっていきたいと思います.textureMapping周りでまた何か発見があれば更新をかけたいと思います.