2017-02-14 23 views
1

Я пытаюсь сделать приложение, которое рисует изображение в 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 #version 330 в GLSL ES #version 100?

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

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

Моего Vertex шейдер:

#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); 
} 

фрагмент Shader:

#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); 
} 

Initialize ВАО, ВБ ,:

// 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); 
+1

Создайте отдельные шейдеры для разных версий и переключитесь на нужный код в C++. В качестве альтернативы используйте другой эмулятор, например, bluestacks. – Reaper

+0

Спасибо за ваш совет, я решил запустить его на своем телефоне, и теперь он работает. :) –

ответ

1

Наконец-то мне удалось решить эту проблему. В GLSL ES 100 нет inout и 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); 

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