#c #qt #opengl #qml #shader
Вопрос:
Вот мой код: изменить из примера qt: ПримерыQt-5.14.2quickscenegraphopenglunderqml
void SquircleRenderer::init()
{
unsigned char* data = (unsigned char*)malloc(1200*4);
for(int i=0;i<600;i )
{
data[i*4] = 0;
data[i*4 1] = 255;
data[i*4 2] = 0;
data[i*4 3] = 255;
}
for(int i=600;i<1200;i )
{
data[i*4] = 0;
data[i*4 1] = 0;
data[i*4 2] = 255;
data[i*4 3] = 255;
}
if (!m_program) {
QSGRendererInterface *rif = m_window->rendererInterface();
Q_ASSERT(rif->graphicsApi() == QSGRendererInterface::OpenGL || rif->graphicsApi() == QSGRendererInterface::OpenGLRhi);
initializeOpenGLFunctions();
if (texs[0])
{
glDeleteTextures(1, texs);
}
glGenTextures(1, texs);
glBindTexture(GL_TEXTURE_2D, texs[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 30, 40, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
m_program = new QOpenGLShaderProgram();
m_program->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex,
"attribute highp vec4 vertices;"
"varying highp vec2 coords;"
"void main() {"
" gl_Position = vertices;"
" coords = vertices.xy;"
"}");
m_program->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment,
"varying highp vec2 coords;"
"uniform sampler2D inputImageTexture;"
"void main() {"
" gl_FragColor = texture2D(inputImageTexture, coords);"
"}");
m_program->bindAttributeLocation("vertices", 0);
m_program->link();
arrUni[0] = m_program->uniformLocation("inputImageTexture");
}
}
//! [4] //! [5]
void SquircleRenderer::paint()
{
// Play nice with the RHI. Not strictly needed when the scenegraph uses
// OpenGL directly.
m_window->beginExternalCommands();
m_program->bind();
m_program->enableAttributeArray(0);
float values[] = {
-1, 1,
1, 1,
-1, -1,
1, -1
};
// This example relies on (deprecated) client-side pointers for the vertex
// input. Therefore, we have to make sure no vertex buffer is bound.
glBindBuffer(GL_ARRAY_BUFFER, 0);
m_program->setAttributeArray(0, GL_FLOAT, values, 2);//values
//m_program->setUniformValue("t", (float) m_t);
qDebug()<<m_viewportSize.width()<<m_viewportSize.height()<<"n";
glViewport(0, 0, m_viewportSize.width(), m_viewportSize.height());
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texs[0]);
glUniform1i(arrUni[0], 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
m_program->disableAttributeArray(0);
m_program->release();
m_window->endExternalCommands();
}
Как вы можете видеть на картинке,она создает 4 одинаковых изображения,не могли бы вы сказать мне, как создать 1 изображение, заполняющее все окно?:
Я перепробовал так много методов, но это не сработало, я думаю, проблема существует в массиве значений или функции glTexImage2D.
Ответ №1:
Текстуры отображаются по [0, 1]
всему диапазону, а значения за пределами этого диапазона по модулю зацикливаются обратно в него, что создает повторяющийся шаблон. Интерпретация текстуры по [-1, 1]
диапазону приводит к тому, что вы видите, так как вы отображаете ровно в два раза ультрафиолетовый диапазон в обеих осях.
Есть несколько способов исправить это. Но я лично предпочитаю, чтобы при таком прохождении полного буфера кадров атрибут был нормализован, а затем преобразован в ожидаемый [-1, 1]
диапазон для координаты пространства клипов в шейдере вершин:
float values[] = {
0.f, 1.f,
1.f, 1.f,
0.f, 0.f,
1.f, 0.f
};
gl_Position = vertices * 2.0 - vec4(1.0, 1.0,0.0,1.0);
Другой распространенный метод-полностью отказаться от буфера атрибутов и использовать gl_VertexID
его для непосредственного создания как UV, так и координат.
Комментарии:
1. Спасибо! Это работает, gl_Position = вершины * 2.0 — vec4(1.0, 1.0,0.0,1.0);