目录

  • 一、问题描述
  • 二、分析错误
  • 三、解决问题
  • 三、总结

一、问题描述

今天编写一个OpenGL ES的demo,发现没有任何图元输出。

android opengl 顶点着色器 顶点着色器编译失败_顶点着色器


查看日志,发现报了如下错误:

2021-11-15 15:09:07.406 26065-26107/opengles3.book.hello_Triangle E/ESShader: ERROR: 0:2: '
    ' : #version directive must occur on the first line of the shader 
    ERROR: 0:9: 'in' : storage qualifier supported in GLSL ES 3.00 only

android opengl 顶点着色器 顶点着色器编译失败_着色器_02


完整日志如下:

2021-11-15 15:09:07.393 26065-26107/opengles3.book.hello_Triangle I/System.out:   vertShaderSrc = // 表示OpenGL ES着色器语言V3.00
2021-11-15 15:09:07.395 26065-26107/opengles3.book.hello_Triangle I/System.out: #version 300 es
2021-11-15 15:09:07.395 26065-26107/opengles3.book.hello_Triangle I/System.out: // 使用in关键字,在顶点着色器中声明所有的输入顶点属性(Input Vertex Attribute)。
2021-11-15 15:09:07.395 26065-26107/opengles3.book.hello_Triangle I/System.out: // 声明一个输入属性数组:一个名为vPosition的4分量向量
2021-11-15 15:09:07.395 26065-26107/opengles3.book.hello_Triangle I/System.out: // 在图形编程中我们经常会使用向量这个数学概念,因为它简明地表达了任意空间中的位置和方向,并且它有非常有用的数学属性。
2021-11-15 15:09:07.395 26065-26107/opengles3.book.hello_Triangle I/System.out: // 在GLSL中一个向量有最多4个分量,每个分量值都代表空间中的一个坐标,它们可以通过vec.x、vec.y、vec.z和vec.w来获取。
2021-11-15 15:09:07.396 26065-26107/opengles3.book.hello_Triangle I/System.out: //注意vec.w分量不是用作表达空间中的位置的(我们处理的是3D不是4D),而是用在所谓透视除法(Perspective Division)上。
2021-11-15 15:09:07.396 26065-26107/opengles3.book.hello_Triangle I/System.out: in vec4 vPosition;
2021-11-15 15:09:07.396 26065-26107/opengles3.book.hello_Triangle I/System.out: void main()
2021-11-15 15:09:07.396 26065-26107/opengles3.book.hello_Triangle I/System.out: {
2021-11-15 15:09:07.396 26065-26107/opengles3.book.hello_Triangle I/System.out:     // 为了设置顶点着色器的输出,我们必须把位置数据赋值给预定义的gl_Position变量,它在幕后是vec4类型的。
2021-11-15 15:09:07.396 26065-26107/opengles3.book.hello_Triangle I/System.out:     // 将vPosition输入属性拷贝到名为gl_Position的特殊输出变量
2021-11-15 15:09:07.396 26065-26107/opengles3.book.hello_Triangle I/System.out:     // 每个顶点着色器必须在gl_Position变量中输出一个位置,这个位置传递到管线下一个阶段的位置
2021-11-15 15:09:07.396 26065-26107/opengles3.book.hello_Triangle I/System.out:     gl_Position = vPosition;
2021-11-15 15:09:07.396 26065-26107/opengles3.book.hello_Triangle I/System.out: }
2021-11-15 15:09:07.399 2068-2295/com.android.systemui D/EGL_emulation: eglMakeCurrent: 0xe79a8e20: ver 3 1 (tinfo 0xd3aaa1d0)
2021-11-15 15:09:07.400 26065-26107/opengles3.book.hello_Triangle I/System.out:   fragShaderSrc = // 表示OpenGL ES着色器语言V3.00
2021-11-15 15:09:07.400 26065-26107/opengles3.book.hello_Triangle I/System.out: #version 300 es
2021-11-15 15:09:07.400 26065-26107/opengles3.book.hello_Triangle I/System.out: // 声明着色器中浮点变量的默认精度
2021-11-15 15:09:07.400 26065-26107/opengles3.book.hello_Triangle I/System.out: precision mediump float;
2021-11-15 15:09:07.400 26065-26107/opengles3.book.hello_Triangle I/System.out: // 声明一个输出变量fragColor,这是一个4分量的向量,
2021-11-15 15:09:07.400 26065-26107/opengles3.book.hello_Triangle I/System.out: // 写入这个变量的值将被输出到颜色缓冲器
2021-11-15 15:09:07.400 26065-26107/opengles3.book.hello_Triangle I/System.out: out vec4 fragColor;
2021-11-15 15:09:07.401 26065-26107/opengles3.book.hello_Triangle I/System.out: void main()
2021-11-15 15:09:07.401 26065-26107/opengles3.book.hello_Triangle I/System.out: {
2021-11-15 15:09:07.401 26065-26107/opengles3.book.hello_Triangle I/System.out: 	// 所有片段的着色器输出都是红色( 1.0, 0.0, 0.0, 1.0 )
2021-11-15 15:09:07.401 26065-26107/opengles3.book.hello_Triangle I/System.out: 	fragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );
2021-11-15 15:09:07.401 26065-26107/opengles3.book.hello_Triangle I/System.out: 	// 会输出橘黄色
2021-11-15 15:09:07.401 26065-26107/opengles3.book.hello_Triangle I/System.out: 	// fragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
2021-11-15 15:09:07.402 26065-26107/opengles3.book.hello_Triangle I/System.out: }
2021-11-15 15:09:07.406 3713-26124/com.google.android.ims I/CarrierServices: [292] awt.doInBackground: New operation mode: 2
2021-11-15 15:09:07.406 26065-26107/opengles3.book.hello_Triangle E/ESShader: ERROR: 0:2: '
    ' : #version directive must occur on the first line of the shader 
    ERROR: 0:9: 'in' : storage qualifier supported in GLSL ES 3.00 only

二、分析错误

shaders\fragmentShader.frag

// 表示OpenGL ES着色器语言V3.00
#version 300 es
// 声明着色器中浮点变量的默认精度
precision mediump float;
// 声明一个输出变量fragColor,这是一个4分量的向量,
// 写入这个变量的值将被输出到颜色缓冲器
out vec4 fragColor;
void main()
{
	// 所有片段的着色器输出都是红色( 1.0, 0.0, 0.0, 1.0 )
	fragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );

	// 会输出橘黄色
	// fragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}

android opengl 顶点着色器 顶点着色器编译失败_着色器_03

shaders\vertexShader.vert

// 表示OpenGL ES着色器语言V3.00
#version 300 es

// 使用in关键字,在顶点着色器中声明所有的输入顶点属性(Input Vertex Attribute)。
// 声明一个输入属性数组:一个名为vPosition的4分量向量
// 在图形编程中我们经常会使用向量这个数学概念,因为它简明地表达了任意空间中的位置和方向,并且它有非常有用的数学属性。
// 在GLSL中一个向量有最多4个分量,每个分量值都代表空间中的一个坐标,它们可以通过vec.x、vec.y、vec.z和vec.w来获取。
//注意vec.w分量不是用作表达空间中的位置的(我们处理的是3D不是4D),而是用在所谓透视除法(Perspective Division)上。
in vec4 vPosition;
void main()
{
    // 为了设置顶点着色器的输出,我们必须把位置数据赋值给预定义的gl_Position变量,它在幕后是vec4类型的。
    // 将vPosition输入属性拷贝到名为gl_Position的特殊输出变量
    // 每个顶点着色器必须在gl_Position变量中输出一个位置,这个位置传递到管线下一个阶段的位置
    gl_Position = vPosition;
}

android opengl 顶点着色器 顶点着色器编译失败_System_04


通过报错信息

2021-11-15 15:09:07.406 26065-26107/opengles3.book.hello_Triangle E/ESShader: ERROR: 0:2: '
    ' : #version directive must occur on the first line of the shader 
    ERROR: 0:9: 'in' : storage qualifier supported in GLSL ES 3.00 only

我们发现,#version 300 es这行代码确实不是第一行,第一行是一行注释

三、解决问题

我们将#version 300 es写在第一行,注释写第二行,重新修改下,如下所示:

shaders\fragmentShader.frag

#version 300 es
// 表示OpenGL ES着色器语言V3.00

// 声明着色器中浮点变量的默认精度
precision mediump float;
// 声明一个输出变量fragColor,这是一个4分量的向量,
// 写入这个变量的值将被输出到颜色缓冲器
out vec4 fragColor;
void main()
{
	// 所有片段的着色器输出都是红色( 1.0, 0.0, 0.0, 1.0 )
	fragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );

	// 会输出橘黄色
	// fragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}

android opengl 顶点着色器 顶点着色器编译失败_System_05


shaders\vertexShader.vert

#version 300 es
// 表示OpenGL ES着色器语言V3.00

// 使用in关键字,在顶点着色器中声明所有的输入顶点属性(Input Vertex Attribute)。
// 声明一个输入属性数组:一个名为vPosition的4分量向量
// 在图形编程中我们经常会使用向量这个数学概念,因为它简明地表达了任意空间中的位置和方向,并且它有非常有用的数学属性。
// 在GLSL中一个向量有最多4个分量,每个分量值都代表空间中的一个坐标,它们可以通过vec.x、vec.y、vec.z和vec.w来获取。
//注意vec.w分量不是用作表达空间中的位置的(我们处理的是3D不是4D),而是用在所谓透视除法(Perspective Division)上。
in vec4 vPosition;
void main()
{
    // 为了设置顶点着色器的输出,我们必须把位置数据赋值给预定义的gl_Position变量,它在幕后是vec4类型的。
    // 将vPosition输入属性拷贝到名为gl_Position的特殊输出变量
    // 每个顶点着色器必须在gl_Position变量中输出一个位置,这个位置传递到管线下一个阶段的位置
    gl_Position = vPosition;
}

android opengl 顶点着色器 顶点着色器编译失败_System_06

重新编译一下,三角形出来了,如下所示:

android opengl 顶点着色器 顶点着色器编译失败_着色器_07

三、总结

在OpenGL ES的着色器语言的第一行,一定是#version 300 es,不要写其他的内容,否则着色器语言会编译失败,无法显示图元。