android - glGetAttribLocation 在我的一个属性上返回 -1

标签 android c++ opengl-es shader opengl-es-2.0

glGetAttribLocation 在我的 3 个属性(颜色)之一上返回 -1。检查错误、状态等,一切都会返回正数。在 Android 7 上使用 OpenGL ES2。只是找不到原因,颜色的设置方式对我来说与 texcoord 相同。

顶点着色器:

#version 100
attribute vec2 position;
attribute vec3 color;
attribute vec2 texcoord;

varying vec3 Color;
varying vec2 Texcoord;


void main()
   {
         Color = color;
         gl_Position = vec4(position, 0.0, 1.0);
         Texcoord = texcoord;
   }

fragment 着色器:

#version 100
precision mediump float;
varying vec3 Color;
varying vec2 Texcoord;

vec4 outColor;
uniform sampler2D tex;

void main()

{
   outColor = texture2D(tex, Texcoord) * vec4(Color, 1.0);
} 

代码:

GLuint GlHelper::loadShader(char* fragment, char* vertex)
{
off_t fLength;
const char *vertexSource = FileManager::ReadFile(vertex,fLength);


// Create vertex shader
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, NULL);
glCompileShader(vertexShader);


GLint status; GLint logLength;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
glGetShaderiv(vertexShader,GL_INFO_LOG_LENGTH,&logLength);


if (status != GL_TRUE)
{

    char buffer[logLength];
    glGetShaderInfoLog(vertexShader, logLength, NULL, buffer);

    __android_log_print(ANDROID_LOG_ERROR, QS_OPENGLTAG, "%s",buffer);

    return 0;
}

off_t fLength2;
const char *fragmentSource = FileManager::ReadFile(fragment,fLength2);

GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
glCompileShader(fragmentShader);

glGetShaderiv(fragmentShader,GL_COMPILE_STATUS, &status);
glGetShaderiv(fragmentShader,GL_INFO_LOG_LENGTH,&logLength);


if (status != GL_TRUE)
{

    char buffer[logLength];
    glGetShaderInfoLog(fragmentShader, logLength, NULL, buffer);

    __android_log_print(ANDROID_LOG_ERROR, QS_OPENGLTAG,"%s", buffer);
    return 0;
}

GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);

glLinkProgram(shaderProgram);

glGetProgramiv(shaderProgram,GL_LINK_STATUS,&status);
glGetProgramiv(shaderProgram,GL_INFO_LOG_LENGTH,&logLength);

if(status != GL_TRUE)
{
    char buffer[logLength];
    glGetProgramInfoLog(shaderProgram,logLength,NULL,buffer);
    __android_log_print(ANDROID_LOG_ERROR,QS_OPENGLTAG,"%s",buffer);
    return 0;
}

// Validate and error check.
glValidateProgram(shaderProgram);

glGetProgramiv(shaderProgram, GL_VALIDATE_STATUS, &status);
if(status != GL_TRUE)
{
    char buffer[512];
    glGetProgramInfoLog(shaderProgram,512,NULL,buffer);
    __android_log_print(ANDROID_LOG_ERROR,QS_OPENGLTAG,"%s",buffer);
    return 0;
}

glUseProgram(shaderProgram);

GLenum  err = glGetError();
if(err != GL_NO_ERROR)
{
    __android_log_print(ANDROID_LOG_ERROR,QS_OPENGLTAG,"%s","OpenGL error code: "); 
    return 0;
}


GLint posAttrib = glGetAttribLocation(shaderProgram, "position"); // works
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 7*sizeof(float), 0);

GLint colAttrib = glGetAttribLocation(shaderProgram, "color"); // returns -1
glEnableVertexAttribArray(colAttrib);
glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, 7*sizeof(float), (void*)(2*sizeof(float)));


GLint texAttrib = glGetAttribLocation(shaderProgram, "texcoord"); // works
glEnableVertexAttribArray(texAttrib);
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 7*sizeof(float), (void*)(5*sizeof(float)));

return shaderProgram;

这是我的 readfile 函数,以防它出错:

const char* FileManager::ReadFile(const char *path, off_t& length)
{
  AAsset* 
asset=AAssetManager_open(FileManager::assetManager,path,AASSET_MODE_BUFFER);

  char* buff = new char[AAsset_getLength(asset)];
  length = AAsset_getLength(asset);
  AAsset_read(asset,buff,(size_t)length);
  AAsset_close(asset);
  return buff;
}

最佳答案

参见 OpenGL ES Shading Language 1.00 Specification; 7.2 Fragment Shader Special Variables; page 60 :

The output of the fragment shader is processed by the fixed function operations at the back end of the OpenGL ES pipeline. Fragment shaders output values to the OpenGL ES pipeline using the built-in variables gl_FragColor and gl_FragData, unless the discard keyword is executed.

这意味着您必须在 fragment 着色器中写入 gl_FragColor(而不是变量 outColor):

gl_FragColor = texture2D(tex, Texcoord) * vec4(Color, 1.0);

OpenGL ES Shading Language 3.00您将能够对 fragment 着色器输出变量使用 out 限定符:

out vec4 outColor;

void main()
{
    outColor = texture2D(tex, Texcoord) * vec4(Color, 1.0);
} 


请注意,如果您不写入 gl_FragColor,则不会使用可变变量 ColorTexcoord(由编译器优化)。这会导致属性 colortexcoord 未被使用且可能未激活。

参见 OpenGL ES 2 Specifications - 2.10.4 Shader Variables - p. 32 :

A generic attribute variable is considered active if it is determined by the compiler and linker that the attribute may be accessed when the shader is executed. Attribute variables that are declared in a vertex shader but never used are not considered active. In cases where the compiler and linker cannot make a conclusive determination, an attribute will be considered active.

.....

To determine the set of active vertex attributes used by a program, and to determine their types, use the command:

void GetActiveAttrib( uint program, uint index, sizei bufSize, sizei *length, int *size, enum *type, char *name );

.....

After a program object has been linked successfully, the bindings of attribute variable names to indices can be queried. The command

int GetAttribLocation( uint program, const char *name );

关于android - glGetAttribLocation 在我的一个属性上返回 -1,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50252778/

相关文章:

android - 如何修复 "Execution failed for task ' :app:processDebugResources'. > Android 资源链接失败[Android/Flutter]

c++ - 迭代不同类型 vector 的索引类型

ios - 从 OpenGL 绘图创建 png UIImage

ios - 为 Star Ocean Second Story 和 Legend of Mana 等 2D 游戏存储游戏数据

java - 如何显示多个检索数据的项目 MySQL 和 Android

android - 检查 Android 中正在运行的语言环境

c++ - 从同一类中的另一个构造函数调用一个构造函数

java - OpenGL ES 中的纹理质量差

android - 使用自定义监听器扩充类时出错

c++ - 声明一个大小未知的多维数组