android - glGetAttribLocation 在我的一个属性上返回 -1
问题描述
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;
}
片段着色器:
#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 着色语言 1.00 规范;7.2 Fragment Shader 特殊变量;第 60 页:
片段着色器的输出由 OpenGL ES 管道后端的固定函数操作处理。片段着色器使用内置变量
gl_FragColor
和将值输出到 OpenGL ES 管道gl_FragData
,除非执行了 discard 关键字。
这意味着您必须在片段着色器中写入gl_FragColor
(而不是 varible outColor
):
gl_FragColor = texture2D(tex, Texcoord) * vec4(Color, 1.0);
在OpenGL ES Shading Language 3.00中,您可以将out
限定符用于片段着色器输出变量:
out vec4 outColor;
void main()
{
outColor = texture2D(tex, Texcoord) * vec4(Color, 1.0);
}
请注意,如果您不写入,则不使用gl_FragColor
可变变量(由编译器优化)。这会导致属性和未使用并且可能未激活。Color
Texcoord
color
texcoord
请参阅OpenGL ES 2 规范 - 2.10.4 着色器变量 - p。32:
如果编译器和链接器确定在执行着色器时可以访问该属性,则认为通用属性变量是活动的。在顶点着色器中声明但从未使用过的属性变量不被认为是活动的。在编译器和链接器无法做出决定性决定的情况下,属性将被视为活动的。
......
要确定程序使用的活动顶点属性集,并确定它们的类型,请使用以下命令:
void GetActiveAttrib( uint program, uint index, sizei bufSize, sizei *length, int *size, enum *type, char *name );
......
程序对象链接成功后,可以查询属性变量名到索引的绑定。命令
int GetAttribLocation( uint program, const char *name );
推荐阅读
- python - 在 C 和 Python 代码之间交换字符串
- datetime - python将日期列表作为字符串转换为日期列表
- jestjs - VSCode 无法识别开玩笑的自定义匹配器
- office-js - 登录到 Outlook 网页版上的共享邮箱时无法使用 Office.context.mailbox.item.addFileAttachmentAsync
- ruby - 如何使用 watir 上传文件
- spring - 应用程序启动失败spring boot
- css - 全屏背景图片 CSS
- java - 如何在调用 AdapterFragment 之前正确填充数组?爪哇
- javascript - 使用反应上下文时,预期的类型来自属性“值”
- oauth-2.0 - Keycloak 刷新令牌不是离线类型