![](/img/trans.png)
[英]How to render part of the texture inside the quad in opengl es using shaders
[英]OpenGL ES 2 How To Render to Texture and Extract Data for GPGPU Test
我試圖提交一個小浮點數組作為OpenGL ES 2.0紋理並讀回來以更好地理解GPGPU。 我試圖在TI OMAP3 ARM SoC上的SGX 530 GPU上執行此操作。
我一直在關注本指南: 在此處輸入鏈接說明
我的代碼當前創建並填充2個浮點數組,然后像這樣創建“傳遞”着色器:
void GLWidget::initializeGL()
{
// Max texture size in each direction
int maxSize;
glGetIntegerv(GL_MAX_TEXTURE_SIZE,&maxSize);
texSize = sqrt(maxSize);
texSize = 2;
qDebug() << "GL_MAX_TEXTURE_SIZE " << maxSize << " SQRT " << texSize;
// Define input and output arrays of RGBA format with each channel being u8
m_Format = 4;
dataX = (quint8*)malloc(m_Format*texSize*texSize*sizeof(quint8));
dataY = (quint8*)malloc(m_Format*texSize*texSize*sizeof(quint8));
// Setup some dummy data
int arraySize = m_Format*texSize*texSize;
qDebug() << "Array Size: " << arraySize;
for (int i = 0; i < arraySize ; i++) {
dataX[i] = i;
}
for (int i = 0; i < arraySize ; i++) {
dataY[i] = 0;
}
QGLShader *vshader = new QGLShader(QGLShader::Vertex);
const char *vsrc =
"attribute highp vec4 vertex;\n"
"attribute highp vec4 texCoord;\n"
"varying vec2 texc;\n"
"void main(void)\n"
"{\n"
" gl_Position = vertex;\n"
" texc = texCoord.xy;\n"
"}\n";
vshader->compileSourceCode(vsrc);
QGLShader *fshader = new QGLShader(QGLShader::Fragment);
const char *fsrc =
"varying highp vec2 texc;\n"
"uniform sampler2D tex;\n"
"void main(void)\n"
"{\n"
" gl_FragColor = texture2D(tex, texc);\n"
"}\n";
fshader->compileSourceCode(fsrc);
program.addShader(vshader);
program.addShader(fshader);
program.link();
vertexAttr = program.attributeLocation("vertex");
texCoordAttr = program.attributeLocation("texCoord");
textureUniform = program.uniformLocation("tex");
}
然后我嘗試將紋理提交到GPU,將其渲染到幀緩沖區,然后將其讀回:
void GLWidget::renderToScene()
{
// Bind and configure a texture
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &m_hTexture);
glBindTexture(GL_TEXTURE_2D, m_hTexture);
glUniform1i(textureUniform, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texSize, texSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, dataX); // Allocate buffer to hold RGBA with 8 bytes each
// Generate handles for Frame Buffer Object
glGenFramebuffers(1, &m_hFBO);
// Switch the render target to the current FBO to update the texture map
glBindFramebuffer(GL_FRAMEBUFFER, m_hFBO);
qDebug() << "Data before roundtrip:";
int arraySize = m_Format*texSize*texSize;
for (int i = 0 ; i < arraySize ; i++)
qDebug() << dataX[i];
// FBO attachment is complete?
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
{
qDebug() << "Frame buffer is present...";
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_hTexture, 0);
//glTexSubImage2D(GL_TEXTURE_2D,0,0,0,texSize,texSize, GL_RGBA,GL_UNSIGNED_BYTE,dataX); // pixel data is RGBA and each channel u8
static const GLfloat squareVertices[] = {
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f,
};
static const GLfloat textureVertices[] = {
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
0.0f, 0.0f,
};
// ensure no VBOs or IBOs are bound
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
// Set pointers to the arrays
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_TEXTUREPOSITON, 2, GL_FLOAT, 0, 0, textureVertices);
glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITON);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableVertexAttribArray(ATTRIB_VERTEX);
glDisableVertexAttribArray(ATTRIB_TEXTUREPOSITON);
}
qDebug() << "Zero data:";
for (int i = 0; i < arraySize ; i++)
qDebug() << dataY[i];
// GPGPU Extract
glReadPixels(0, 0, texSize, texSize, GL_RGBA,GL_UNSIGNED_BYTE,dataY);
// print out results
qDebug() << "Data after roundtrip:";
for (int i = 0; i < arraySize ; i++)
qDebug() << dataY[i];
// Unbind the FBO so rendering will return to the main buffer.
glBindFramebuffer(GL_FRAMEBUFFER, 0);
qDebug() << "Done...";
sleep(60000);
}
繪制調用如下所示:
void GLWidget::draw() {
glClearColor(0.1f, 0.1f, 0.2f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glFrontFace(GL_CW);
glCullFace(GL_FRONT);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
// Draw
program.bind();
renderToScene();
program.release();
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
swapBuffers();
}
一切都編譯並運行,但我的數據輸出如下所示:
Found SGX/MBX driver, enabling FullClearOnEveryFrame
Found v1.4 driver, enabling brokenTexSubImage
Found non-Nokia v1.4 driver, enabling brokenFBOReadBack
GL_MAX_TEXTURE_SIZE 2048 SQRT 2
Array Size: 16
Data before roundtrip:
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Zero data:
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
Data after roundtrip:
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
Done...
如何正確提交和回讀我的文本? 謝謝!
您對此代碼有很多問題。 主要的一個是ES 2.0不支持浮動紋理。 特別:
GL_FLOAT
無效作為glTexImage2D()
和glTexSubImage2D()
的類型參數。 這需要是GL_UNSIGNED_BYTE
,或者是各種GL_UNSIGNED_SHORT_*
選項之一。 glReadPixels()
的唯一格式 / 類型組合是GL_RGBA
/ GL_UNSIGNED_BYTE
。 您可以查詢第二個與實現相關的組合。 我強烈建議您在盲目嘗試傳遞可能對API調用有效或可能無效的參數之前檢查一些文檔。 手冊頁是一個好的開始。 另外,使用glGetError()
,如果進行無效調用,它將返回錯誤代碼。
實現可以支持擴展,以增加對您正在尋找的某些功能的支持。 例如, OES_texture_float添加了對浮動紋理的支持。 但是在嘗試使用這些擴展之前,您需要檢查這些擴展是否存在。
顯示的代碼沒有使用紋理和渲染到默認顏色緩沖區的繪制調用(像glDrawElements這樣的調用)。 glReadPixels從默認的Framebuffer中讀取。 可以使用GL_COLOR_ATTACHMENT0在OpenGLES2中更改它,而不是GL_COLOR_ATTACHMENT0_EXT
對於支持幀緩沖支持/ nullw的絕大多數TI器件,您可以使用下面鏈接中的分析代碼。 下面的代碼測試了一些GPGPU場景,包括邊緣檢測,顏色轉換和使用FBO。 請參閱測試11,17的調用
https://github.com/prabindh/sgxperf/blob/master/sgxperf_gles20_vg.cpp
順便說一下,OMAP3生產的芯片組有SGX530 GPU而不是SGX540。 SGX540 /變體用於OMAP4芯片組。 如果您使用SGX540生產OMAP3變體,那將非常幸運。您可以在bootlogs中或使用PVR驅動程序的調試版本進行確認。
還要提一下正在使用的板/平台。
然后我嘗試將紋理提交到GPU並像這樣讀回來
[...]
所以很明顯我沒有從OpenGL“獲取”緩沖區。 我希望它包含1.5,因為我正在使用glReadPixels將紋理讀回到我的dataY數組中。
為什么它顯然不是你正在讀回的后台緩沖區?
您永遠不會將紋理渲染到顏色緩沖區,因此從顏色緩沖區讀回將永遠不會返回紋理數據。
原始代碼使用framebuffer對象來訪問紋理作為顏色緩沖區,在這種情況下它將具有完全不同的語義(盡管如此,它仍然是一個無用的基准)。 請注意,大多數真實世界的ES2設備也支持GL_OES_framebuffer_object
擴展 ,因此您可以從概念上移植它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.