Как преобразовать ядро ​​GLSL #version 330 в GLSL ES #version 100?

Я пытаюсь создать приложение, которое рисует изображение в Android Studio с помощью NDK и JNI для вызова кода C ++ с использованием OpenGL ES. Я изучил руководство, как это сделать в OpenGL, по адресу: https://learnopengl.com/#!Getting-started/Textures, использующие ядро ​​GLSL 330. Однако OpenGL ES 3.0 не поддерживается в эмуляторе Android (обратите внимание на эту ссылку: https://developer.android.com/ndk/guides/stable_apis.html).

Поэтому я должен использовать GLSL ES #version 100, который не поддерживает «layout», «in» и «out» в шейдерах ниже. Как мне отредактировать их, чтобы они могли работать в версии # 100, и есть ли какие-либо изменения в исходном коде, если я их отредактирую? Спасибо за внимание и помощь.

Обновление: после поиска я обнаружил, что могу использовать glGetAttributeLocation для получения местоположения переменной в вершинном шейдере вместо использования макета (location = 0). Однако в GLSL ES #version 100 нет VAO, поэтому я все еще не мог понять, как это работает без VAO.

Мой вершинный шейдер:

#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout (location = 2) in vec2 texCoord;

out vec3 ourColor;
out vec2 TexCoord;

void main()
{
    gl_Position = vec4(position, 1.0f);
    ourColor = color;
    // We swap the y-axis by substracing our coordinates from 1. This is done because most images have the top y-axis inversed with OpenGL's top y-axis.
    // TexCoord = texCoord;
    TexCoord = vec2(texCoord.x, 1.0 - texCoord.y);
}

фрагментный шейдер:

#version 330 core
in vec3 ourColor;
in vec2 TexCoord;

out vec4 color;

// Texture samplers
uniform sampler2D ourTexture1;
uniform sampler2D ourTexture2;

void main()
{
    // Linearly interpolate between both textures (second texture is only slightly combined)
    color = mix(texture(ourTexture1, TexCoord), texture(ourTexture2, TexCoord), 0.2);
}

Инициализировать VAO, VBO ,:

    // Set up vertex data (and buffer(s)) and attribute pointers
    GLfloat vertices[] = {
        // Positions          // Colors           // Texture Coords
         0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f, // Top Right
         0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f, // Bottom Right
        -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f, // Bottom Left
        -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f  // Top Left 
    };
    GLuint indices[] = {  // Note that we start from 0!
        0, 1, 3, // First Triangle
        1, 2, 3  // Second Triangle
    };
    GLuint VBO, VAO, ;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, );
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    // Position attribute
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);
    // Color attribute
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
    glEnableVertexAttribArray(1);
    // TexCoord attribute
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
    glEnableVertexAttribArray(2);

    glBindVertexArray(0); // Unbind VAO

Нарисуйте изображение:

        // Clear the colorbuffer
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        // Activate shader
        ourShader.Use();     

        // Bind Textures using texture units
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture1);
        glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture1"), 0);
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, texture2);
        glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture2"), 1);  

        // Draw container
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
        glBindVertexArray(0);

person Toan Tran    schedule 14.02.2017    source источник
comment
Создавайте отдельные шейдеры для разных версий и переключайтесь на нужный в коде C ++. Как вариант, используйте другой эмулятор, например bluestacks.   -  person Reaper    schedule 14.02.2017
comment
Спасибо за совет, я решил запустить его на своем телефоне, и теперь он работает. :)   -  person Toan Tran    schedule 16.02.2017


Ответы (1)


Наконец-то мне удается это решить. В GLSL ES 100 нет in out и layout(location=0), как я упоминал выше. Поэтому мне нужно их заменить:

in => attribute

out => varying

И полностью удалите layout(location=0), потому что, насколько мне известно, в GLSL ES 100 ничего подобного нет.

Из-за удаления layout(location=0) мы должны сообщить программе расположение данных нашей вершины, а именно: положение, цвет и textCoord в этом кейс. С layout(location=0) мы могли бы просто поместить 0 в

glVertexAttribPointer(0,3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);

Без него нам сначала нужно получить местоположение атрибута вершины с помощью:

GLint mPosition= glGetAttributeLocation(ourProgram,"position")

затем замените постоянное число 0,1 или 2 моим предопределенным mPosition:

glVertexAttribPointer(mPosition,3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(mPosition);;

То же на color и textCoord.

ниже мой отредактированный вершинный шейдер, фрагментный шейдер и то, как инициализировать VBO и передать наши данные:

Отредактировано vertex shader для GLSL ES 100:

auto gVertexShader =
"attribute vec3 position;\n"
"attribute vec3 color;\n"
"attribute  vec2 texCoord;\n"

"varying vec3 ourColor;\n"
"varying vec2 TexCoord;\n"

"void main()\n"
"{\n"
    "gl_Position = vec4(position,1.0); // Add the xOffset to the x position of the vertex position\n"
    "ourColor = color;\n"
    "TexCoord= vec2(texCoord.x,1.0-texCoord.y);\n"
"}\n";

Отредактировано fragment shader для GLSL ES 100:

static const char FRAGMENT_SHADER[] =
    "#version 100\n"
    "precision mediump float;\n"
    "varying vec4 vColor;\n"
    "void main() {\n"
    "    gl_FragColor = vColor;\n"
    "}\n";

моя InitBuffer функция:

// Set up vertex data (and buffer(s)) and attribute pointers
    GLfloat vertices[] = {
        // Positions          // Colors           // Texture Coords
         0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f, // Top Right
         0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f, // Bottom Right
        -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f, // Bottom Left
        -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f  // Top Left 
    };
    GLuint indices[] = {  // Note that we start from 0!
        0, 1, 3, // First Triangle
        1, 2, 3  // Second Triangle
    };
void initBuffers()
{
    GLint mPosition,mCorlor,mTextCoord;
    GLuint VBOs[2]; // Initialize an buffer to store all the verticles and transfer them to the GPU

    glGenBuffers(2, VBOs); // Generate VBO


    glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);//Bind verticles array for OpenGL to use
    glBufferData(GL_ARRAY_BUFFER, sizeof(recVertices), recVertices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VBOs[1]);//Bind the indices for information about drawing sequence
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    // 1. set the vertex attributes pointers
    // Position Attribute
    mPosition=glGetAttributeLocation(Program, "position");
    glVertexAttribPointer(mPosition, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(mPosition);
    // Color Attribute

    mColor=glGetAttributeLocation(Program, "color");
    glVertexAttribPointer(mColor, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
    glEnableVertexAttribArray(mColor);
    //Texture Coordinate Attribute

    mTextCoord=glGetAttributeLocation(Program, "textCoord")'
    glVertexAttribPointer(mTextCoord, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
    glEnableVertexAttribArray(mTextCoord);


}

Затем мы заменяем привязку VAO в нашей функции рисования на вызов функции initBuffer()

    // Clear the colorbuffer
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    // Activate shader
    ourShader.Use();     

    // Bind Textures using texture units
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture1);
    glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture1"), 0);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, texture2);
    glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture2"), 1);  

    // Draw container
    initBuffers();
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);

Надеюсь, это поможет тем, у кого такая же проблема со мной. Пожалуйста, не стесняйтесь спрашивать меня, если у вас есть вопросы :).

person Toan Tran    schedule 20.02.2017
comment
Куда делась униформа? - person Emmanuel Meric de Bellefon; 24.04.2021