私はこれに非常に困惑しています。後処理を実行できるように、画面外のテクスチャにレンダリングしようとしていますが、そのテクスチャを変更せずに画面に描画することさえできません。現在、iPhone シミュレーターで OpenGL ES 2.0 をターゲットにしています。
問題を vec4(0, 0, 0, 1) を返す GLSL の texture2D() 関数に絞り込みました。これは、その呼び出しを一定の色に置き換えると、画面が指定された色で塗りつぶされるためです。テクスチャが作成され、テクスチャ ユニット 0 にバインドされ、そのストレージが割り当てられ、その最小フィルタと最大フィルタが NEAREST に設定され、sampler2D ユニフォームが 0 に設定されます。
render-to-texture コードをすべて削除して、そのデータを明示的に初期化しようとしましたが、同じ結果が得られました。スクリーン フレームバッファを直接ターゲットにすると、期待どおりの画像が得られたので、テクスチャのデータがそれからサンプリングしようとする時間によってすべてが定義されます。
レンダリング中にテクスチャがどのテクスチャ ユニットにもバインドされていないことを確認しようとしましたが、違いはありませんでした。
glEnable(GL_TEXTURE_2D) も試しましたが、ES 2.0 には関係ないという印象を受けました。とにかく役に立ちませんでした。
私は実際に OpenGL ES 2.0 で独自のシン C++ ラッパー ライブラリを使用していますが、OpenGL ES 2.0 をよく知っていれば、このコードで何が起こっているかは明らかです。コードがプレーンな OpenGL ではないことをお詫びします。次のデバッグ手順は、ラッパー ライブラリを使用せずにコードを書き直すことです。とにかく飛び出す骨頭の間違いをしているのではないかと思っていました。
ただし、設定したすべての状態変数の最後の drawArrays 呼び出しの前に、プレーンな OpenGL glGet*() クエリを追加したところ、すべてが期待どおりに設定されました。
コードの唯一の明白でない部分は Smart<> オブジェクトです。それらは単に GL オブジェクト参照と参照配列をラップし、関連する glDelete*() をデストラクタで呼び出します。
#include <tsvl/vec.hpp>
using namespace tsvl;
#include <tsgl2/Context.hpp>
#include <tsgl2/Smart.hpp>
using namespace tsgl2;
#include <array>
#include <exception>
#include <string>
using namespace std;
#define SHADER_SOURCE(text) "#version 100\n" #text
namespace {
const AttributeLocation vertexPositionAttributeLocation(0);
const string vec2PassthroughVertexShaderSource = SHADER_SOURCE(
attribute vec2 vertexPosition;
void main() {
gl_Position = vec4(vertexPosition, 0, 1);
}
);
const string greenFragmentShaderSource = SHADER_SOURCE(
void main() {
gl_FragColor = vec4(0, 1, 0, 1);
}
);
const string combineTexturesFragmentShaderSource = SHADER_SOURCE(
precision highp float;
uniform vec2 screenSize;
uniform sampler2D samplers[1];
void main() {
vec2 texCoord = gl_FragCoord.xy / screenSize;
gl_FragColor = texture2D(samplers[0], texCoord);
}
);
const vec2 vertices[] = {
vec2(-0.9f, -0.9f),
vec2( 0.9f, -0.9f),
vec2( 0.0f, 0.9f),
};
const int vertexCount = sizeof(vertices) / sizeof(vertices[0]);
const vec2 screenCorners[] = {
vec2(-1.0f, -1.0f),
vec2( 1.0f, -1.0f),
vec2( 1.0f, 1.0f),
vec2(-1.0f, 1.0f),
};
const int screenCornerCount = sizeof(screenCorners) / sizeof(screenCorners[0]);
} // unnamed namespace
void drawDemoScene(int screenWidth, int screenHeight) {
FramebufferRef screenFramebuffer = Framebuffer::currentBinding();
//
Smart<array<TextureRef, 8>> renderTextures(Context::genTextures<8>());
Smart<array<FramebufferRef, 8>> renderFramebuffers(Context::genFramebuffers<8>());
Context::setActiveTextureUnit(TextureUnit(0)); // My wrapper translates this to GL_TEXTURE0
Texture2D::bind(renderTextures.get()[0]);
Texture2D::setStorage(TextureFormat::RGBA8, IntRect::Size(screenWidth, screenHeight));
Texture2D::setMinificationFilter(TextureMinificationFilter::NEAREST);
Texture2D::setMagnificationFilter(TextureMagnificationFilter::NEAREST);
Framebuffer::bind(renderFramebuffers.get()[0]);
Framebuffer::ColorAttachment::set(renderTextures.get()[0], FramebufferTextureTarget::TEXTURE_2D);
if (Framebuffer::status() != FramebufferStatus::COMPLETE)
throw exception();
//
vertexPositionAttributeLocation.enableAttributeArray();
Smart<ShaderRef> vec2PassthroughVertexShader(Context::createShader(ShaderType::VERTEX));
vec2PassthroughVertexShader->setSource(vec2PassthroughVertexShaderSource);
vec2PassthroughVertexShader->compile();
if (!vec2PassthroughVertexShader->compileWasSuccessful())
throw exception();
Smart<ShaderRef> greenFragmentShader(Context::createShader(ShaderType::FRAGMENT));
greenFragmentShader->setSource(greenFragmentShaderSource);
greenFragmentShader->compile();
if (!greenFragmentShader->compileWasSuccessful())
throw exception();
Smart<ShaderRef> combineTexturesFragmentShader(Context::createShader(ShaderType::FRAGMENT));
combineTexturesFragmentShader->setSource(combineTexturesFragmentShaderSource);
combineTexturesFragmentShader->compile();
if (!combineTexturesFragmentShader->compileWasSuccessful())
throw exception();
Smart<ProgramRef> vec2PassthroughGreenProgram(Context::createProgram());
vec2PassthroughGreenProgram->attach(*vec2PassthroughVertexShader);
vec2PassthroughGreenProgram->attach(*greenFragmentShader);
vec2PassthroughGreenProgram->bindAttributeToLocation(
"vertexPosition", vertexPositionAttributeLocation);
vec2PassthroughGreenProgram->link();
vec2PassthroughGreenProgram->validate();
if (!vec2PassthroughGreenProgram->validationWasSuccessful())
throw exception();
Smart<ProgramRef> combineTexturesProgram(Context::createProgram());
combineTexturesProgram->attach(*vec2PassthroughVertexShader);
combineTexturesProgram->attach(*combineTexturesFragmentShader);
combineTexturesProgram->bindAttributeToLocation(
"vertexPosition", vertexPositionAttributeLocation);
combineTexturesProgram->link();
combineTexturesProgram->validate();
if (!combineTexturesProgram->validationWasSuccessful())
throw exception();
UniformLocation screenSizeUniformLocation =
combineTexturesProgram->locationOfUniform("screenSize");
UniformLocation samplersUniformLocation =
combineTexturesProgram->locationOfUniform("samplers");
//
Context::setColorClearValue(0.0f, 0.0f, 0.0f, 0.0f);
Context::setLineWidth(2.0f);
Context::setViewport(IntRect(0, 0, screenWidth, screenHeight));
Context::useProgram(*vec2PassthroughGreenProgram);
Framebuffer::bind(renderFramebuffers.get()[0]);
vertexPositionAttributeLocation.setAttributeArrayPointerAndStride(
DONT_NORMALIZE, 2, AttributeLocation::ArrayDataType::FLOAT, vertices, 0);
Context::clear(CLEAR_COLOR_BUFFER);
Context::drawArrays(DrawMode::LINE_LOOP, 0, vertexCount);
//
Context::enableBlending();
Context::setBlendFuncs(SourceBlendFunc::SRC_ALPHA, DestBlendFunc::ONE_MINUS_SRC_ALPHA);
Context::setColorClearValue(1.0f, 1.0f, 1.0f, 1.0f);
Context::setViewport(IntRect(0, 0, screenWidth, screenHeight));
Context::useProgram(*combineTexturesProgram);
Framebuffer::bind(screenFramebuffer);
vertexPositionAttributeLocation.setAttributeArrayPointerAndStride(
DONT_NORMALIZE, 2, AttributeLocation::ArrayDataType::FLOAT, screenCorners, 0);
screenSizeUniformLocation.setUniformValue(vec2(screenWidth, screenHeight));
samplersUniformLocation.setUniformValue(TextureUnit(0)); // Even though setActiveTextureUnit()
// translated this to GL_TEXTURE0
// It stays plain int 0 here.
Context::clear(CLEAR_COLOR_BUFFER);
Context::drawArrays(DrawMode::TRIANGLE_FAN, 0, screenCornerCount);
}
私のラッパー ライブラリがどのように実装されているかは、https ://github.com/jbat-es/tsgl2 で確認できます。
編集:
さて、プレーンな OpenGL で非常に簡素化されたバージョンを作成しましたが、同じ問題があります。
void drawDemoScenePlainGL(int screenWidth, int screenHeight) {
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
int data[320][460];
memset(data, 0xFF, 320*460*sizeof(int));
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, screenWidth, screenHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
//
glEnableVertexAttribArray(0);
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
const char* source = vec2PassthroughVertexShaderSource.c_str();
int sourceLength = vec2PassthroughVertexShaderSource.length();
glShaderSource(vertexShader, 1, &source, &sourceLength);
glCompileShader(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
source = combineTexturesFragmentShaderSource.c_str();
sourceLength = combineTexturesFragmentShaderSource.length();
glShaderSource(fragmentShader, 1, &source, &sourceLength);
glCompileShader(fragmentShader);
GLuint program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glBindAttribLocation(program, 0, "vertexPosition");
glLinkProgram(program);
GLuint screenSizeUniformLocation = glGetUniformLocation(program, "screenSize");
GLuint samplersUniformLocation = glGetUniformLocation(program, "samplers");
//
glClearColor(1, 1, 1, 1);
glUseProgram(program);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, screenCorners);
glViewport(0, 0, screenWidth, screenHeight);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform2f(screenSizeUniformLocation, screenWidth, screenHeight);
glUniform1i(samplersUniformLocation, 0);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLE_FAN, 0, screenCornerCount);
}